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