1 /*
2  * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V.
3  * S.J.R. van Schaik <stephan@whiteboxsystems.nl>
4  * M.B.W. Wajer <merlijn@whiteboxsystems.nl>
5  *
6  * (C) Copyright 2017 Olimex Ltd..
7  * Stefan Mavrodiev <stefan@olimex.com>
8  *
9  * Based on linux spi driver. Original copyright follows:
10  * linux/drivers/spi/spi-sun4i.c
11  *
12  * Copyright (C) 2012 - 2014 Allwinner Tech
13  * Pan Nan <pannan@allwinnertech.com>
14  *
15  * Copyright (C) 2014 Maxime Ripard
16  * Maxime Ripard <maxime.ripard@free-electrons.com>
17  *
18  * SPDX-License-Identifier:	GPL-2.0+
19  */
20 
21 #include <common.h>
22 #include <clk.h>
23 #include <dm.h>
24 #include <log.h>
25 #include <spi.h>
26 #include <errno.h>
27 #include <fdt_support.h>
28 #include <reset.h>
29 #include <wait_bit.h>
30 #include <asm/global_data.h>
31 #include <dm/device_compat.h>
32 #include <linux/bitops.h>
33 
34 #include <asm/bitops.h>
35 #include <asm/gpio.h>
36 #include <asm/io.h>
37 
38 #include <linux/iopoll.h>
39 
40 DECLARE_GLOBAL_DATA_PTR;
41 
42 /* sun4i spi registers */
43 #define SUN4I_RXDATA_REG		0x00
44 #define SUN4I_TXDATA_REG		0x04
45 #define SUN4I_CTL_REG			0x08
46 #define SUN4I_CLK_CTL_REG		0x1c
47 #define SUN4I_BURST_CNT_REG		0x20
48 #define SUN4I_XMIT_CNT_REG		0x24
49 #define SUN4I_FIFO_STA_REG		0x28
50 
51 /* sun6i spi registers */
52 #define SUN6I_GBL_CTL_REG		0x04
53 #define SUN6I_TFR_CTL_REG		0x08
54 #define SUN6I_FIFO_CTL_REG		0x18
55 #define SUN6I_FIFO_STA_REG		0x1c
56 #define SUN6I_CLK_CTL_REG		0x24
57 #define SUN6I_BURST_CNT_REG		0x30
58 #define SUN6I_XMIT_CNT_REG		0x34
59 #define SUN6I_BURST_CTL_REG		0x38
60 #define SUN6I_TXDATA_REG		0x200
61 #define SUN6I_RXDATA_REG		0x300
62 
63 /* sun spi bits */
64 #define SUN4I_CTL_ENABLE		BIT(0)
65 #define SUN4I_CTL_MASTER		BIT(1)
66 #define SUN4I_CLK_CTL_CDR2_MASK		0xff
67 #define SUN4I_CLK_CTL_CDR2(div)		((div) & SUN4I_CLK_CTL_CDR2_MASK)
68 #define SUN4I_CLK_CTL_CDR1_MASK		0xf
69 #define SUN4I_CLK_CTL_CDR1(div)		(((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
70 #define SUN4I_CLK_CTL_DRS		BIT(12)
71 #define SUN4I_MAX_XFER_SIZE		0xffffff
72 #define SUN4I_BURST_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
73 #define SUN4I_XMIT_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
74 #define SUN4I_FIFO_STA_RF_CNT_BITS	0
75 
76 #define SUN4I_SPI_MAX_RATE		24000000
77 #define SUN4I_SPI_MIN_RATE		3000
78 #define SUN4I_SPI_DEFAULT_RATE		1000000
79 #define SUN4I_SPI_TIMEOUT_US		1000000
80 
81 #define SPI_REG(priv, reg)		((priv)->base + \
82 					(priv)->variant->regs[reg])
83 #define SPI_BIT(priv, bit)		((priv)->variant->bits[bit])
84 #define SPI_CS(priv, cs)		(((cs) << SPI_BIT(priv, SPI_TCR_CS_SEL)) & \
85 					SPI_BIT(priv, SPI_TCR_CS_MASK))
86 
87 /* sun spi register set */
88 enum sun4i_spi_regs {
89 	SPI_GCR,
90 	SPI_TCR,
91 	SPI_FCR,
92 	SPI_FSR,
93 	SPI_CCR,
94 	SPI_BC,
95 	SPI_TC,
96 	SPI_BCTL,
97 	SPI_TXD,
98 	SPI_RXD,
99 };
100 
101 /* sun spi register bits */
102 enum sun4i_spi_bits {
103 	SPI_GCR_TP,
104 	SPI_GCR_SRST,
105 	SPI_TCR_CPHA,
106 	SPI_TCR_CPOL,
107 	SPI_TCR_CS_ACTIVE_LOW,
108 	SPI_TCR_CS_SEL,
109 	SPI_TCR_CS_MASK,
110 	SPI_TCR_XCH,
111 	SPI_TCR_CS_MANUAL,
112 	SPI_TCR_CS_LEVEL,
113 	SPI_FCR_TF_RST,
114 	SPI_FCR_RF_RST,
115 	SPI_FSR_RF_CNT_MASK,
116 };
117 
118 struct sun4i_spi_variant {
119 	const unsigned long *regs;
120 	const u32 *bits;
121 	u32 fifo_depth;
122 	bool has_soft_reset;
123 	bool has_burst_ctl;
124 };
125 
126 struct sun4i_spi_plat {
127 	struct sun4i_spi_variant *variant;
128 	u32 base;
129 	u32 max_hz;
130 };
131 
132 struct sun4i_spi_priv {
133 	struct sun4i_spi_variant *variant;
134 	struct clk clk_ahb, clk_mod;
135 	struct reset_ctl reset;
136 	u32 base;
137 	u32 freq;
138 	u32 mode;
139 
140 	const u8 *tx_buf;
141 	u8 *rx_buf;
142 };
143 
sun4i_spi_drain_fifo(struct sun4i_spi_priv * priv,int len)144 static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
145 {
146 	u8 byte;
147 
148 	while (len--) {
149 		byte = readb(SPI_REG(priv, SPI_RXD));
150 		if (priv->rx_buf)
151 			*priv->rx_buf++ = byte;
152 	}
153 }
154 
sun4i_spi_fill_fifo(struct sun4i_spi_priv * priv,int len)155 static inline void sun4i_spi_fill_fifo(struct sun4i_spi_priv *priv, int len)
156 {
157 	u8 byte;
158 
159 	while (len--) {
160 		byte = priv->tx_buf ? *priv->tx_buf++ : 0;
161 		writeb(byte, SPI_REG(priv, SPI_TXD));
162 	}
163 }
164 
sun4i_spi_set_cs(struct udevice * bus,u8 cs,bool enable)165 static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
166 {
167 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
168 	u32 reg;
169 
170 	reg = readl(SPI_REG(priv, SPI_TCR));
171 
172 	reg &= ~SPI_BIT(priv, SPI_TCR_CS_MASK);
173 	reg |= SPI_CS(priv, cs);
174 
175 	if (enable)
176 		reg &= ~SPI_BIT(priv, SPI_TCR_CS_LEVEL);
177 	else
178 		reg |= SPI_BIT(priv, SPI_TCR_CS_LEVEL);
179 
180 	writel(reg, SPI_REG(priv, SPI_TCR));
181 }
182 
sun4i_spi_parse_pins(struct udevice * dev)183 static int sun4i_spi_parse_pins(struct udevice *dev)
184 {
185 	const void *fdt = gd->fdt_blob;
186 	const char *pin_name;
187 	const fdt32_t *list;
188 	u32 phandle;
189 	int drive, pull = 0, pin, i;
190 	int offset;
191 	int size;
192 
193 	list = fdt_getprop(fdt, dev_of_offset(dev), "pinctrl-0", &size);
194 	if (!list) {
195 		printf("WARNING: sun4i_spi: cannot find pinctrl-0 node\n");
196 		return -EINVAL;
197 	}
198 
199 	while (size) {
200 		phandle = fdt32_to_cpu(*list++);
201 		size -= sizeof(*list);
202 
203 		offset = fdt_node_offset_by_phandle(fdt, phandle);
204 		if (offset < 0)
205 			return offset;
206 
207 		drive = fdt_getprop_u32_default_node(fdt, offset, 0,
208 						     "drive-strength", 0);
209 		if (drive) {
210 			if (drive <= 10)
211 				drive = 0;
212 			else if (drive <= 20)
213 				drive = 1;
214 			else if (drive <= 30)
215 				drive = 2;
216 			else
217 				drive = 3;
218 		} else {
219 			drive = fdt_getprop_u32_default_node(fdt, offset, 0,
220 							     "allwinner,drive",
221 							      0);
222 			drive = min(drive, 3);
223 		}
224 
225 		if (fdt_get_property(fdt, offset, "bias-disable", NULL))
226 			pull = 0;
227 		else if (fdt_get_property(fdt, offset, "bias-pull-up", NULL))
228 			pull = 1;
229 		else if (fdt_get_property(fdt, offset, "bias-pull-down", NULL))
230 			pull = 2;
231 		else
232 			pull = fdt_getprop_u32_default_node(fdt, offset, 0,
233 							    "allwinner,pull",
234 							     0);
235 		pull = min(pull, 2);
236 
237 		for (i = 0; ; i++) {
238 			pin_name = fdt_stringlist_get(fdt, offset,
239 						      "pins", i, NULL);
240 			if (!pin_name) {
241 				pin_name = fdt_stringlist_get(fdt, offset,
242 							      "allwinner,pins",
243 							       i, NULL);
244 				if (!pin_name)
245 					break;
246 			}
247 
248 			pin = name_to_gpio(pin_name);
249 			if (pin < 0)
250 				break;
251 
252 			if (IS_ENABLED(CONFIG_MACH_SUN50I))
253 				sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
254 			else
255 				sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
256 			sunxi_gpio_set_drv(pin, drive);
257 			sunxi_gpio_set_pull(pin, pull);
258 		}
259 	}
260 	return 0;
261 }
262 
sun4i_spi_set_clock(struct udevice * dev,bool enable)263 static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
264 {
265 	struct sun4i_spi_priv *priv = dev_get_priv(dev);
266 	int ret;
267 
268 	if (!enable) {
269 		clk_disable(&priv->clk_ahb);
270 		clk_disable(&priv->clk_mod);
271 		if (reset_valid(&priv->reset))
272 			reset_assert(&priv->reset);
273 		return 0;
274 	}
275 
276 	ret = clk_enable(&priv->clk_ahb);
277 	if (ret) {
278 		dev_err(dev, "failed to enable ahb clock (ret=%d)\n", ret);
279 		return ret;
280 	}
281 
282 	ret = clk_enable(&priv->clk_mod);
283 	if (ret) {
284 		dev_err(dev, "failed to enable mod clock (ret=%d)\n", ret);
285 		goto err_ahb;
286 	}
287 
288 	if (reset_valid(&priv->reset)) {
289 		ret = reset_deassert(&priv->reset);
290 		if (ret) {
291 			dev_err(dev, "failed to deassert reset\n");
292 			goto err_mod;
293 		}
294 	}
295 
296 	return 0;
297 
298 err_mod:
299 	clk_disable(&priv->clk_mod);
300 err_ahb:
301 	clk_disable(&priv->clk_ahb);
302 	return ret;
303 }
304 
sun4i_spi_claim_bus(struct udevice * dev)305 static int sun4i_spi_claim_bus(struct udevice *dev)
306 {
307 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
308 	int ret;
309 
310 	ret = sun4i_spi_set_clock(dev->parent, true);
311 	if (ret)
312 		return ret;
313 
314 	setbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE |
315 		     SUN4I_CTL_MASTER | SPI_BIT(priv, SPI_GCR_TP));
316 
317 	if (priv->variant->has_soft_reset)
318 		setbits_le32(SPI_REG(priv, SPI_GCR),
319 			     SPI_BIT(priv, SPI_GCR_SRST));
320 
321 	setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) |
322 		     SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW));
323 
324 	return 0;
325 }
326 
sun4i_spi_release_bus(struct udevice * dev)327 static int sun4i_spi_release_bus(struct udevice *dev)
328 {
329 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
330 
331 	clrbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE);
332 
333 	sun4i_spi_set_clock(dev->parent, false);
334 
335 	return 0;
336 }
337 
sun4i_spi_xfer(struct udevice * dev,unsigned int bitlen,const void * dout,void * din,unsigned long flags)338 static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
339 			  const void *dout, void *din, unsigned long flags)
340 {
341 	struct udevice *bus = dev->parent;
342 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
343 	struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev);
344 
345 	u32 len = bitlen / 8;
346 	u32 rx_fifocnt;
347 	u8 nbytes;
348 	int ret;
349 
350 	priv->tx_buf = dout;
351 	priv->rx_buf = din;
352 
353 	if (bitlen % 8) {
354 		debug("%s: non byte-aligned SPI transfer.\n", __func__);
355 		return -ENAVAIL;
356 	}
357 
358 	if (flags & SPI_XFER_BEGIN)
359 		sun4i_spi_set_cs(bus, slave_plat->cs, true);
360 
361 	/* Reset FIFOs */
362 	setbits_le32(SPI_REG(priv, SPI_FCR), SPI_BIT(priv, SPI_FCR_RF_RST) |
363 		     SPI_BIT(priv, SPI_FCR_TF_RST));
364 
365 	while (len) {
366 		/* Setup the transfer now... */
367 		nbytes = min(len, (priv->variant->fifo_depth - 1));
368 
369 		/* Setup the counters */
370 		writel(SUN4I_BURST_CNT(nbytes), SPI_REG(priv, SPI_BC));
371 		writel(SUN4I_XMIT_CNT(nbytes), SPI_REG(priv, SPI_TC));
372 
373 		if (priv->variant->has_burst_ctl)
374 			writel(SUN4I_BURST_CNT(nbytes),
375 			       SPI_REG(priv, SPI_BCTL));
376 
377 		/* Fill the TX FIFO */
378 		sun4i_spi_fill_fifo(priv, nbytes);
379 
380 		/* Start the transfer */
381 		setbits_le32(SPI_REG(priv, SPI_TCR),
382 			     SPI_BIT(priv, SPI_TCR_XCH));
383 
384 		/* Wait till RX FIFO to be empty */
385 		ret = readl_poll_timeout(SPI_REG(priv, SPI_FSR),
386 					 rx_fifocnt,
387 					 (((rx_fifocnt &
388 					 SPI_BIT(priv, SPI_FSR_RF_CNT_MASK)) >>
389 					 SUN4I_FIFO_STA_RF_CNT_BITS) >= nbytes),
390 					 SUN4I_SPI_TIMEOUT_US);
391 		if (ret < 0) {
392 			printf("ERROR: sun4i_spi: Timeout transferring data\n");
393 			sun4i_spi_set_cs(bus, slave_plat->cs, false);
394 			return ret;
395 		}
396 
397 		/* Drain the RX FIFO */
398 		sun4i_spi_drain_fifo(priv, nbytes);
399 
400 		len -= nbytes;
401 	}
402 
403 	if (flags & SPI_XFER_END)
404 		sun4i_spi_set_cs(bus, slave_plat->cs, false);
405 
406 	return 0;
407 }
408 
sun4i_spi_set_speed(struct udevice * dev,uint speed)409 static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
410 {
411 	struct sun4i_spi_plat *plat = dev_get_plat(dev);
412 	struct sun4i_spi_priv *priv = dev_get_priv(dev);
413 	unsigned int div;
414 	u32 reg;
415 
416 	if (speed > plat->max_hz)
417 		speed = plat->max_hz;
418 
419 	if (speed < SUN4I_SPI_MIN_RATE)
420 		speed = SUN4I_SPI_MIN_RATE;
421 	/*
422 	 * Setup clock divider.
423 	 *
424 	 * We have two choices there. Either we can use the clock
425 	 * divide rate 1, which is calculated thanks to this formula:
426 	 * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
427 	 * Or we can use CDR2, which is calculated with the formula:
428 	 * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
429 	 * Whether we use the former or the latter is set through the
430 	 * DRS bit.
431 	 *
432 	 * First try CDR2, and if we can't reach the expected
433 	 * frequency, fall back to CDR1.
434 	 */
435 
436 	div = SUN4I_SPI_MAX_RATE / (2 * speed);
437 	reg = readl(SPI_REG(priv, SPI_CCR));
438 
439 	if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
440 		if (div > 0)
441 			div--;
442 
443 		reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS);
444 		reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
445 	} else {
446 		div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(speed);
447 		reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS);
448 		reg |= SUN4I_CLK_CTL_CDR1(div);
449 	}
450 
451 	priv->freq = speed;
452 	writel(reg, SPI_REG(priv, SPI_CCR));
453 
454 	return 0;
455 }
456 
sun4i_spi_set_mode(struct udevice * dev,uint mode)457 static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
458 {
459 	struct sun4i_spi_priv *priv = dev_get_priv(dev);
460 	u32 reg;
461 
462 	reg = readl(SPI_REG(priv, SPI_TCR));
463 	reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA));
464 
465 	if (mode & SPI_CPOL)
466 		reg |= SPI_BIT(priv, SPI_TCR_CPOL);
467 
468 	if (mode & SPI_CPHA)
469 		reg |= SPI_BIT(priv, SPI_TCR_CPHA);
470 
471 	priv->mode = mode;
472 	writel(reg, SPI_REG(priv, SPI_TCR));
473 
474 	return 0;
475 }
476 
477 static const struct dm_spi_ops sun4i_spi_ops = {
478 	.claim_bus		= sun4i_spi_claim_bus,
479 	.release_bus		= sun4i_spi_release_bus,
480 	.xfer			= sun4i_spi_xfer,
481 	.set_speed		= sun4i_spi_set_speed,
482 	.set_mode		= sun4i_spi_set_mode,
483 };
484 
sun4i_spi_probe(struct udevice * bus)485 static int sun4i_spi_probe(struct udevice *bus)
486 {
487 	struct sun4i_spi_plat *plat = dev_get_plat(bus);
488 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
489 	int ret;
490 
491 	ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
492 	if (ret) {
493 		dev_err(bus, "failed to get ahb clock\n");
494 		return ret;
495 	}
496 
497 	ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
498 	if (ret) {
499 		dev_err(bus, "failed to get mod clock\n");
500 		return ret;
501 	}
502 
503 	ret = reset_get_by_index(bus, 0, &priv->reset);
504 	if (ret && ret != -ENOENT) {
505 		dev_err(bus, "failed to get reset\n");
506 		return ret;
507 	}
508 
509 	sun4i_spi_parse_pins(bus);
510 
511 	priv->variant = plat->variant;
512 	priv->base = plat->base;
513 	priv->freq = plat->max_hz;
514 
515 	return 0;
516 }
517 
sun4i_spi_of_to_plat(struct udevice * bus)518 static int sun4i_spi_of_to_plat(struct udevice *bus)
519 {
520 	struct sun4i_spi_plat *plat = dev_get_plat(bus);
521 	int node = dev_of_offset(bus);
522 
523 	plat->base = dev_read_addr(bus);
524 	plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
525 	plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
526 				      "spi-max-frequency",
527 				      SUN4I_SPI_DEFAULT_RATE);
528 
529 	if (plat->max_hz > SUN4I_SPI_MAX_RATE)
530 		plat->max_hz = SUN4I_SPI_MAX_RATE;
531 
532 	return 0;
533 }
534 
535 static const unsigned long sun4i_spi_regs[] = {
536 	[SPI_GCR]		= SUN4I_CTL_REG,
537 	[SPI_TCR]		= SUN4I_CTL_REG,
538 	[SPI_FCR]		= SUN4I_CTL_REG,
539 	[SPI_FSR]		= SUN4I_FIFO_STA_REG,
540 	[SPI_CCR]		= SUN4I_CLK_CTL_REG,
541 	[SPI_BC]		= SUN4I_BURST_CNT_REG,
542 	[SPI_TC]		= SUN4I_XMIT_CNT_REG,
543 	[SPI_TXD]		= SUN4I_TXDATA_REG,
544 	[SPI_RXD]		= SUN4I_RXDATA_REG,
545 };
546 
547 static const u32 sun4i_spi_bits[] = {
548 	[SPI_GCR_TP]		= BIT(18),
549 	[SPI_TCR_CPHA]		= BIT(2),
550 	[SPI_TCR_CPOL]		= BIT(3),
551 	[SPI_TCR_CS_ACTIVE_LOW] = BIT(4),
552 	[SPI_TCR_XCH]		= BIT(10),
553 	[SPI_TCR_CS_SEL]	= 12,
554 	[SPI_TCR_CS_MASK]	= 0x3000,
555 	[SPI_TCR_CS_MANUAL]	= BIT(16),
556 	[SPI_TCR_CS_LEVEL]	= BIT(17),
557 	[SPI_FCR_TF_RST]	= BIT(8),
558 	[SPI_FCR_RF_RST]	= BIT(9),
559 	[SPI_FSR_RF_CNT_MASK]	= GENMASK(6, 0),
560 };
561 
562 static const unsigned long sun6i_spi_regs[] = {
563 	[SPI_GCR]		= SUN6I_GBL_CTL_REG,
564 	[SPI_TCR]		= SUN6I_TFR_CTL_REG,
565 	[SPI_FCR]		= SUN6I_FIFO_CTL_REG,
566 	[SPI_FSR]		= SUN6I_FIFO_STA_REG,
567 	[SPI_CCR]		= SUN6I_CLK_CTL_REG,
568 	[SPI_BC]		= SUN6I_BURST_CNT_REG,
569 	[SPI_TC]		= SUN6I_XMIT_CNT_REG,
570 	[SPI_BCTL]		= SUN6I_BURST_CTL_REG,
571 	[SPI_TXD]		= SUN6I_TXDATA_REG,
572 	[SPI_RXD]		= SUN6I_RXDATA_REG,
573 };
574 
575 static const u32 sun6i_spi_bits[] = {
576 	[SPI_GCR_TP]		= BIT(7),
577 	[SPI_GCR_SRST]		= BIT(31),
578 	[SPI_TCR_CPHA]		= BIT(0),
579 	[SPI_TCR_CPOL]		= BIT(1),
580 	[SPI_TCR_CS_ACTIVE_LOW] = BIT(2),
581 	[SPI_TCR_CS_SEL]	= 4,
582 	[SPI_TCR_CS_MASK]	= 0x30,
583 	[SPI_TCR_CS_MANUAL]	= BIT(6),
584 	[SPI_TCR_CS_LEVEL]	= BIT(7),
585 	[SPI_TCR_XCH]		= BIT(31),
586 	[SPI_FCR_RF_RST]	= BIT(15),
587 	[SPI_FCR_TF_RST]	= BIT(31),
588 	[SPI_FSR_RF_CNT_MASK]	= GENMASK(7, 0),
589 };
590 
591 static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
592 	.regs			= sun4i_spi_regs,
593 	.bits			= sun4i_spi_bits,
594 	.fifo_depth		= 64,
595 };
596 
597 static const struct sun4i_spi_variant sun6i_a31_spi_variant = {
598 	.regs			= sun6i_spi_regs,
599 	.bits			= sun6i_spi_bits,
600 	.fifo_depth		= 128,
601 	.has_soft_reset		= true,
602 	.has_burst_ctl		= true,
603 };
604 
605 static const struct sun4i_spi_variant sun8i_h3_spi_variant = {
606 	.regs			= sun6i_spi_regs,
607 	.bits			= sun6i_spi_bits,
608 	.fifo_depth		= 64,
609 	.has_soft_reset		= true,
610 	.has_burst_ctl		= true,
611 };
612 
613 static const struct udevice_id sun4i_spi_ids[] = {
614 	{
615 	  .compatible = "allwinner,sun4i-a10-spi",
616 	  .data = (ulong)&sun4i_a10_spi_variant,
617 	},
618 	{
619 	  .compatible = "allwinner,sun6i-a31-spi",
620 	  .data = (ulong)&sun6i_a31_spi_variant,
621 	},
622 	{
623 	  .compatible = "allwinner,sun8i-h3-spi",
624 	  .data = (ulong)&sun8i_h3_spi_variant,
625 	},
626 	{ /* sentinel */ }
627 };
628 
629 U_BOOT_DRIVER(sun4i_spi) = {
630 	.name	= "sun4i_spi",
631 	.id	= UCLASS_SPI,
632 	.of_match	= sun4i_spi_ids,
633 	.ops	= &sun4i_spi_ops,
634 	.of_to_plat	= sun4i_spi_of_to_plat,
635 	.plat_auto	= sizeof(struct sun4i_spi_plat),
636 	.priv_auto	= sizeof(struct sun4i_spi_priv),
637 	.probe	= sun4i_spi_probe,
638 };
639