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