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