1
2
3
4
5
6
7#include <common.h>
8#include <dm.h>
9#include <malloc.h>
10#include <spi.h>
11#include <asm/io.h>
12#include <linux/iopoll.h>
13#include <linux/ioport.h>
14
15
16struct mtk_qspi_regs {
17 u32 cmd;
18 u32 cnt;
19 u32 rdsr;
20 u32 rdata;
21 u32 radr[3];
22 u32 wdata;
23 u32 prgdata[6];
24 u32 shreg[10];
25 u32 cfg[2];
26 u32 shreg10;
27 u32 mode_mon;
28 u32 status[4];
29 u32 flash_time;
30 u32 flash_cfg;
31 u32 reserved_0[3];
32 u32 sf_time;
33 u32 pp_dw_data;
34 u32 reserved_1;
35 u32 delsel_0[2];
36 u32 intrstus;
37 u32 intren;
38 u32 reserved_2;
39 u32 cfg3;
40 u32 reserved_3;
41 u32 chksum;
42 u32 aaicmd;
43 u32 wrprot;
44 u32 radr3;
45 u32 dual;
46 u32 delsel_1[3];
47};
48
49struct mtk_qspi_platdata {
50 fdt_addr_t reg_base;
51 fdt_addr_t mem_base;
52};
53
54struct mtk_qspi_priv {
55 struct mtk_qspi_regs *regs;
56 unsigned long *mem_base;
57 u8 op;
58 u8 tx[3];
59 u32 txlen;
60 u8 *rx;
61 u32 rxlen;
62};
63
64#define MTK_QSPI_CMD_POLLINGREG_US 500000
65#define MTK_QSPI_WRBUF_SIZE 256
66#define MTK_QSPI_COMMAND_ENABLE 0x30
67
68
69#define MTK_QSPI_RD_TRIGGER BIT(0)
70#define MTK_QSPI_READSTATUS BIT(1)
71#define MTK_QSPI_PRG_CMD BIT(2)
72#define MTK_QSPI_WR_TRIGGER BIT(4)
73#define MTK_QSPI_WRITESTATUS BIT(5)
74#define MTK_QSPI_AUTOINC BIT(7)
75
76#define MTK_QSPI_MAX_RX_TX_SHIFT 0x6
77#define MTK_QSPI_MAX_SHIFT 0x8
78
79#define MTK_QSPI_WR_BUF_ENABLE 0x1
80#define MTK_QSPI_WR_BUF_DISABLE 0x0
81
82static int mtk_qspi_execute_cmd(struct mtk_qspi_priv *priv, u8 cmd)
83{
84 u8 tmp;
85 u8 val = cmd & ~MTK_QSPI_AUTOINC;
86
87 writeb(cmd, &priv->regs->cmd);
88
89 return readb_poll_timeout(&priv->regs->cmd, tmp, !(val & tmp),
90 MTK_QSPI_CMD_POLLINGREG_US);
91}
92
93static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
94{
95 int len = 1 + priv->txlen + priv->rxlen;
96 int i, ret, idx;
97
98 if (len > MTK_QSPI_MAX_SHIFT)
99 return -ERR_INVAL;
100
101 writeb(len * 8, &priv->regs->cnt);
102
103
104 idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
105
106
107 writeb(priv->op, &priv->regs->prgdata[idx]);
108 idx--;
109
110
111 for (i = 0; i < priv->txlen; i++, idx--)
112 writeb(priv->tx[i], &priv->regs->prgdata[idx]);
113
114
115 while (idx >= 0) {
116 writeb(0, &priv->regs->prgdata[idx]);
117 idx--;
118 }
119
120 ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);
121 if (ret)
122 return ret;
123
124
125 idx = priv->rxlen - 1;
126
127
128 for (i = 0; i < priv->rxlen; i++, idx--)
129 priv->rx[i] = readb(&priv->regs->shreg[idx]);
130
131 return 0;
132}
133
134static int mtk_qspi_read(struct mtk_qspi_priv *priv,
135 u32 addr, u8 *buf, u32 len)
136{
137 memcpy(buf, (u8 *)priv->mem_base + addr, len);
138 return 0;
139}
140
141static void mtk_qspi_set_addr(struct mtk_qspi_priv *priv, u32 addr)
142{
143 int i;
144
145 for (i = 0; i < 3; i++) {
146 writeb(addr & 0xff, &priv->regs->radr[i]);
147 addr >>= 8;
148 }
149}
150
151static int mtk_qspi_write_single_byte(struct mtk_qspi_priv *priv,
152 u32 addr, u32 length, const u8 *data)
153{
154 int i, ret;
155
156 mtk_qspi_set_addr(priv, addr);
157
158 for (i = 0; i < length; i++) {
159 writeb(*data++, &priv->regs->wdata);
160 ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_WR_TRIGGER);
161 if (ret < 0)
162 return ret;
163 }
164 return 0;
165}
166
167static int mtk_qspi_write_buffer(struct mtk_qspi_priv *priv, u32 addr,
168 const u8 *buf)
169{
170 int i, data;
171
172 mtk_qspi_set_addr(priv, addr);
173
174 for (i = 0; i < MTK_QSPI_WRBUF_SIZE; i += 4) {
175 data = buf[i + 3] << 24 | buf[i + 2] << 16 |
176 buf[i + 1] << 8 | buf[i];
177 writel(data, &priv->regs->pp_dw_data);
178 }
179
180 return mtk_qspi_execute_cmd(priv, MTK_QSPI_WR_TRIGGER);
181}
182
183static int mtk_qspi_write(struct mtk_qspi_priv *priv,
184 u32 addr, const u8 *buf, u32 len)
185{
186 int ret;
187
188
189 writel(MTK_QSPI_WR_BUF_ENABLE, &priv->regs->cfg[1]);
190 while (len >= MTK_QSPI_WRBUF_SIZE) {
191 ret = mtk_qspi_write_buffer(priv, addr, buf);
192 if (ret < 0)
193 return ret;
194
195 len -= MTK_QSPI_WRBUF_SIZE;
196 addr += MTK_QSPI_WRBUF_SIZE;
197 buf += MTK_QSPI_WRBUF_SIZE;
198 }
199
200 writel(MTK_QSPI_WR_BUF_DISABLE, &priv->regs->cfg[1]);
201
202 if (len)
203 return mtk_qspi_write_single_byte(priv, addr, len, buf);
204
205 return 0;
206}
207
208static int mtk_qspi_claim_bus(struct udevice *dev)
209{
210
211 return 0;
212}
213
214static int mtk_qspi_release_bus(struct udevice *dev)
215{
216
217 return 0;
218}
219
220static int mtk_qspi_transfer(struct mtk_qspi_priv *priv, unsigned int bitlen,
221 const void *dout, void *din, unsigned long flags)
222{
223 u32 bytes = DIV_ROUND_UP(bitlen, 8);
224 u32 addr;
225
226 if (!bytes)
227 return -ERR_INVAL;
228
229 if (dout) {
230 if (flags & SPI_XFER_BEGIN) {
231
232 priv->op = *(u8 *)dout;
233 if (bytes > 1)
234 memcpy(priv->tx, (u8 *)dout + 1,
235 bytes <= 4 ? bytes - 1 : 3);
236 priv->txlen = bytes - 1;
237 }
238
239 if (flags == SPI_XFER_ONCE) {
240
241
242
243
244 priv->rx = NULL;
245 priv->rxlen = 0;
246 return mtk_qspi_tx_rx(priv);
247 }
248
249 if (flags & SPI_XFER_END) {
250
251
252
253 addr = priv->tx[0] << 16 | priv->tx[1] << 8 |
254 priv->tx[2];
255 return mtk_qspi_write(priv, addr, (u8 *)dout, bytes);
256 }
257 }
258
259 if (din) {
260 if (priv->txlen >= 3) {
261
262
263
264
265 addr = priv->tx[0] << 16 | priv->tx[1] << 8 |
266 priv->tx[2];
267 return mtk_qspi_read(priv, addr, (u8 *)din, bytes);
268 }
269
270
271 priv->rx = (u8 *)din;
272 priv->rxlen = bytes;
273 return mtk_qspi_tx_rx(priv);
274 }
275
276 return 0;
277}
278
279static int mtk_qspi_xfer(struct udevice *dev, unsigned int bitlen,
280 const void *dout, void *din, unsigned long flags)
281{
282 struct udevice *bus = dev->parent;
283 struct mtk_qspi_priv *priv = dev_get_priv(bus);
284
285 return mtk_qspi_transfer(priv, bitlen, dout, din, flags);
286}
287
288static int mtk_qspi_set_speed(struct udevice *bus, uint speed)
289{
290
291 return 0;
292}
293
294static int mtk_qspi_set_mode(struct udevice *bus, uint mode)
295{
296
297 return 0;
298}
299
300static int mtk_qspi_ofdata_to_platdata(struct udevice *bus)
301{
302 struct resource res_reg, res_mem;
303 struct mtk_qspi_platdata *plat = bus->platdata;
304 int ret;
305
306 ret = dev_read_resource_byname(bus, "reg_base", &res_reg);
307 if (ret) {
308 debug("can't get reg_base resource(ret = %d)\n", ret);
309 return -ENOMEM;
310 }
311
312 ret = dev_read_resource_byname(bus, "mem_base", &res_mem);
313 if (ret) {
314 debug("can't get map_base resource(ret = %d)\n", ret);
315 return -ENOMEM;
316 }
317
318 plat->mem_base = res_mem.start;
319 plat->reg_base = res_reg.start;
320
321 return 0;
322}
323
324static int mtk_qspi_probe(struct udevice *bus)
325{
326 struct mtk_qspi_platdata *plat = dev_get_platdata(bus);
327 struct mtk_qspi_priv *priv = dev_get_priv(bus);
328
329 priv->regs = (struct mtk_qspi_regs *)plat->reg_base;
330 priv->mem_base = (unsigned long *)plat->mem_base;
331
332 writel(MTK_QSPI_COMMAND_ENABLE, &priv->regs->wrprot);
333
334 return 0;
335}
336
337static const struct dm_spi_ops mtk_qspi_ops = {
338 .claim_bus = mtk_qspi_claim_bus,
339 .release_bus = mtk_qspi_release_bus,
340 .xfer = mtk_qspi_xfer,
341 .set_speed = mtk_qspi_set_speed,
342 .set_mode = mtk_qspi_set_mode,
343};
344
345static const struct udevice_id mtk_qspi_ids[] = {
346 { .compatible = "mediatek,mt7629-qspi" },
347 { }
348};
349
350U_BOOT_DRIVER(mtk_qspi) = {
351 .name = "mtk_qspi",
352 .id = UCLASS_SPI,
353 .of_match = mtk_qspi_ids,
354 .ops = &mtk_qspi_ops,
355 .ofdata_to_platdata = mtk_qspi_ofdata_to_platdata,
356 .platdata_auto_alloc_size = sizeof(struct mtk_qspi_platdata),
357 .priv_auto_alloc_size = sizeof(struct mtk_qspi_priv),
358 .probe = mtk_qspi_probe,
359};
360