uboot/drivers/spi/spi-sunxi.c
<<
>>
Prefs
   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
  40DECLARE_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 */
  88enum 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 */
 102enum 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
 118struct 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
 126struct sun4i_spi_plat {
 127        struct sun4i_spi_variant *variant;
 128        u32 base;
 129        u32 max_hz;
 130};
 131
 132struct 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
 144static 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
 155static 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
 165static 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
 183static 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 = sunxi_name_to_gpio(pin_name);
 249                        if (pin < 0)
 250                                break;
 251
 252                        if (IS_ENABLED(CONFIG_MACH_SUN50I) ||
 253                            IS_ENABLED(CONFIG_SUN50I_GEN_H6))
 254                                sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
 255                        else
 256                                sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
 257                        sunxi_gpio_set_drv(pin, drive);
 258                        sunxi_gpio_set_pull(pin, pull);
 259                }
 260        }
 261        return 0;
 262}
 263
 264static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
 265{
 266        struct sun4i_spi_priv *priv = dev_get_priv(dev);
 267        int ret;
 268
 269        if (!enable) {
 270                clk_disable(&priv->clk_ahb);
 271                clk_disable(&priv->clk_mod);
 272                if (reset_valid(&priv->reset))
 273                        reset_assert(&priv->reset);
 274                return 0;
 275        }
 276
 277        ret = clk_enable(&priv->clk_ahb);
 278        if (ret) {
 279                dev_err(dev, "failed to enable ahb clock (ret=%d)\n", ret);
 280                return ret;
 281        }
 282
 283        ret = clk_enable(&priv->clk_mod);
 284        if (ret) {
 285                dev_err(dev, "failed to enable mod clock (ret=%d)\n", ret);
 286                goto err_ahb;
 287        }
 288
 289        if (reset_valid(&priv->reset)) {
 290                ret = reset_deassert(&priv->reset);
 291                if (ret) {
 292                        dev_err(dev, "failed to deassert reset\n");
 293                        goto err_mod;
 294                }
 295        }
 296
 297        return 0;
 298
 299err_mod:
 300        clk_disable(&priv->clk_mod);
 301err_ahb:
 302        clk_disable(&priv->clk_ahb);
 303        return ret;
 304}
 305
 306static int sun4i_spi_claim_bus(struct udevice *dev)
 307{
 308        struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
 309        int ret;
 310
 311        ret = sun4i_spi_set_clock(dev->parent, true);
 312        if (ret)
 313                return ret;
 314
 315        setbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE |
 316                     SUN4I_CTL_MASTER | SPI_BIT(priv, SPI_GCR_TP));
 317
 318        if (priv->variant->has_soft_reset)
 319                setbits_le32(SPI_REG(priv, SPI_GCR),
 320                             SPI_BIT(priv, SPI_GCR_SRST));
 321
 322        setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) |
 323                     SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW));
 324
 325        return 0;
 326}
 327
 328static int sun4i_spi_release_bus(struct udevice *dev)
 329{
 330        struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
 331
 332        clrbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE);
 333
 334        sun4i_spi_set_clock(dev->parent, false);
 335
 336        return 0;
 337}
 338
 339static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
 340                          const void *dout, void *din, unsigned long flags)
 341{
 342        struct udevice *bus = dev->parent;
 343        struct sun4i_spi_priv *priv = dev_get_priv(bus);
 344        struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev);
 345
 346        u32 len = bitlen / 8;
 347        u32 rx_fifocnt;
 348        u8 nbytes;
 349        int ret;
 350
 351        priv->tx_buf = dout;
 352        priv->rx_buf = din;
 353
 354        if (bitlen % 8) {
 355                debug("%s: non byte-aligned SPI transfer.\n", __func__);
 356                return -ENAVAIL;
 357        }
 358
 359        if (flags & SPI_XFER_BEGIN)
 360                sun4i_spi_set_cs(bus, slave_plat->cs, true);
 361
 362        /* Reset FIFOs */
 363        setbits_le32(SPI_REG(priv, SPI_FCR), SPI_BIT(priv, SPI_FCR_RF_RST) |
 364                     SPI_BIT(priv, SPI_FCR_TF_RST));
 365
 366        while (len) {
 367                /* Setup the transfer now... */
 368                nbytes = min(len, (priv->variant->fifo_depth - 1));
 369
 370                /* Setup the counters */
 371                writel(SUN4I_BURST_CNT(nbytes), SPI_REG(priv, SPI_BC));
 372                writel(SUN4I_XMIT_CNT(nbytes), SPI_REG(priv, SPI_TC));
 373
 374                if (priv->variant->has_burst_ctl)
 375                        writel(SUN4I_BURST_CNT(nbytes),
 376                               SPI_REG(priv, SPI_BCTL));
 377
 378                /* Fill the TX FIFO */
 379                sun4i_spi_fill_fifo(priv, nbytes);
 380
 381                /* Start the transfer */
 382                setbits_le32(SPI_REG(priv, SPI_TCR),
 383                             SPI_BIT(priv, SPI_TCR_XCH));
 384
 385                /* Wait till RX FIFO to be empty */
 386                ret = readl_poll_timeout(SPI_REG(priv, SPI_FSR),
 387                                         rx_fifocnt,
 388                                         (((rx_fifocnt &
 389                                         SPI_BIT(priv, SPI_FSR_RF_CNT_MASK)) >>
 390                                         SUN4I_FIFO_STA_RF_CNT_BITS) >= nbytes),
 391                                         SUN4I_SPI_TIMEOUT_US);
 392                if (ret < 0) {
 393                        printf("ERROR: sun4i_spi: Timeout transferring data\n");
 394                        sun4i_spi_set_cs(bus, slave_plat->cs, false);
 395                        return ret;
 396                }
 397
 398                /* Drain the RX FIFO */
 399                sun4i_spi_drain_fifo(priv, nbytes);
 400
 401                len -= nbytes;
 402        }
 403
 404        if (flags & SPI_XFER_END)
 405                sun4i_spi_set_cs(bus, slave_plat->cs, false);
 406
 407        return 0;
 408}
 409
 410static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
 411{
 412        struct sun4i_spi_plat *plat = dev_get_plat(dev);
 413        struct sun4i_spi_priv *priv = dev_get_priv(dev);
 414        unsigned int div;
 415        u32 reg;
 416
 417        if (speed > plat->max_hz)
 418                speed = plat->max_hz;
 419
 420        if (speed < SUN4I_SPI_MIN_RATE)
 421                speed = SUN4I_SPI_MIN_RATE;
 422        /*
 423         * Setup clock divider.
 424         *
 425         * We have two choices there. Either we can use the clock
 426         * divide rate 1, which is calculated thanks to this formula:
 427         * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
 428         * Or we can use CDR2, which is calculated with the formula:
 429         * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
 430         * Whether we use the former or the latter is set through the
 431         * DRS bit.
 432         *
 433         * First try CDR2, and if we can't reach the expected
 434         * frequency, fall back to CDR1.
 435         */
 436
 437        div = SUN4I_SPI_MAX_RATE / (2 * speed);
 438        reg = readl(SPI_REG(priv, SPI_CCR));
 439
 440        if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
 441                if (div > 0)
 442                        div--;
 443
 444                reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS);
 445                reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
 446        } else {
 447                div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(speed);
 448                reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS);
 449                reg |= SUN4I_CLK_CTL_CDR1(div);
 450        }
 451
 452        priv->freq = speed;
 453        writel(reg, SPI_REG(priv, SPI_CCR));
 454
 455        return 0;
 456}
 457
 458static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
 459{
 460        struct sun4i_spi_priv *priv = dev_get_priv(dev);
 461        u32 reg;
 462
 463        reg = readl(SPI_REG(priv, SPI_TCR));
 464        reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA));
 465
 466        if (mode & SPI_CPOL)
 467                reg |= SPI_BIT(priv, SPI_TCR_CPOL);
 468
 469        if (mode & SPI_CPHA)
 470                reg |= SPI_BIT(priv, SPI_TCR_CPHA);
 471
 472        priv->mode = mode;
 473        writel(reg, SPI_REG(priv, SPI_TCR));
 474
 475        return 0;
 476}
 477
 478static const struct dm_spi_ops sun4i_spi_ops = {
 479        .claim_bus              = sun4i_spi_claim_bus,
 480        .release_bus            = sun4i_spi_release_bus,
 481        .xfer                   = sun4i_spi_xfer,
 482        .set_speed              = sun4i_spi_set_speed,
 483        .set_mode               = sun4i_spi_set_mode,
 484};
 485
 486static int sun4i_spi_probe(struct udevice *bus)
 487{
 488        struct sun4i_spi_plat *plat = dev_get_plat(bus);
 489        struct sun4i_spi_priv *priv = dev_get_priv(bus);
 490        int ret;
 491
 492        ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
 493        if (ret) {
 494                dev_err(bus, "failed to get ahb clock\n");
 495                return ret;
 496        }
 497
 498        ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
 499        if (ret) {
 500                dev_err(bus, "failed to get mod clock\n");
 501                return ret;
 502        }
 503
 504        ret = reset_get_by_index(bus, 0, &priv->reset);
 505        if (ret && ret != -ENOENT) {
 506                dev_err(bus, "failed to get reset\n");
 507                return ret;
 508        }
 509
 510        sun4i_spi_parse_pins(bus);
 511
 512        priv->variant = plat->variant;
 513        priv->base = plat->base;
 514        priv->freq = plat->max_hz;
 515
 516        return 0;
 517}
 518
 519static int sun4i_spi_of_to_plat(struct udevice *bus)
 520{
 521        struct sun4i_spi_plat *plat = dev_get_plat(bus);
 522        int node = dev_of_offset(bus);
 523
 524        plat->base = dev_read_addr(bus);
 525        plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
 526        plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
 527                                      "spi-max-frequency",
 528                                      SUN4I_SPI_DEFAULT_RATE);
 529
 530        if (plat->max_hz > SUN4I_SPI_MAX_RATE)
 531                plat->max_hz = SUN4I_SPI_MAX_RATE;
 532
 533        return 0;
 534}
 535
 536static const unsigned long sun4i_spi_regs[] = {
 537        [SPI_GCR]               = SUN4I_CTL_REG,
 538        [SPI_TCR]               = SUN4I_CTL_REG,
 539        [SPI_FCR]               = SUN4I_CTL_REG,
 540        [SPI_FSR]               = SUN4I_FIFO_STA_REG,
 541        [SPI_CCR]               = SUN4I_CLK_CTL_REG,
 542        [SPI_BC]                = SUN4I_BURST_CNT_REG,
 543        [SPI_TC]                = SUN4I_XMIT_CNT_REG,
 544        [SPI_TXD]               = SUN4I_TXDATA_REG,
 545        [SPI_RXD]               = SUN4I_RXDATA_REG,
 546};
 547
 548static const u32 sun4i_spi_bits[] = {
 549        [SPI_GCR_TP]            = BIT(18),
 550        [SPI_TCR_CPHA]          = BIT(2),
 551        [SPI_TCR_CPOL]          = BIT(3),
 552        [SPI_TCR_CS_ACTIVE_LOW] = BIT(4),
 553        [SPI_TCR_XCH]           = BIT(10),
 554        [SPI_TCR_CS_SEL]        = 12,
 555        [SPI_TCR_CS_MASK]       = 0x3000,
 556        [SPI_TCR_CS_MANUAL]     = BIT(16),
 557        [SPI_TCR_CS_LEVEL]      = BIT(17),
 558        [SPI_FCR_TF_RST]        = BIT(8),
 559        [SPI_FCR_RF_RST]        = BIT(9),
 560        [SPI_FSR_RF_CNT_MASK]   = GENMASK(6, 0),
 561};
 562
 563static const unsigned long sun6i_spi_regs[] = {
 564        [SPI_GCR]               = SUN6I_GBL_CTL_REG,
 565        [SPI_TCR]               = SUN6I_TFR_CTL_REG,
 566        [SPI_FCR]               = SUN6I_FIFO_CTL_REG,
 567        [SPI_FSR]               = SUN6I_FIFO_STA_REG,
 568        [SPI_CCR]               = SUN6I_CLK_CTL_REG,
 569        [SPI_BC]                = SUN6I_BURST_CNT_REG,
 570        [SPI_TC]                = SUN6I_XMIT_CNT_REG,
 571        [SPI_BCTL]              = SUN6I_BURST_CTL_REG,
 572        [SPI_TXD]               = SUN6I_TXDATA_REG,
 573        [SPI_RXD]               = SUN6I_RXDATA_REG,
 574};
 575
 576static const u32 sun6i_spi_bits[] = {
 577        [SPI_GCR_TP]            = BIT(7),
 578        [SPI_GCR_SRST]          = BIT(31),
 579        [SPI_TCR_CPHA]          = BIT(0),
 580        [SPI_TCR_CPOL]          = BIT(1),
 581        [SPI_TCR_CS_ACTIVE_LOW] = BIT(2),
 582        [SPI_TCR_CS_SEL]        = 4,
 583        [SPI_TCR_CS_MASK]       = 0x30,
 584        [SPI_TCR_CS_MANUAL]     = BIT(6),
 585        [SPI_TCR_CS_LEVEL]      = BIT(7),
 586        [SPI_TCR_XCH]           = BIT(31),
 587        [SPI_FCR_RF_RST]        = BIT(15),
 588        [SPI_FCR_TF_RST]        = BIT(31),
 589        [SPI_FSR_RF_CNT_MASK]   = GENMASK(7, 0),
 590};
 591
 592static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
 593        .regs                   = sun4i_spi_regs,
 594        .bits                   = sun4i_spi_bits,
 595        .fifo_depth             = 64,
 596};
 597
 598static const struct sun4i_spi_variant sun6i_a31_spi_variant = {
 599        .regs                   = sun6i_spi_regs,
 600        .bits                   = sun6i_spi_bits,
 601        .fifo_depth             = 128,
 602        .has_soft_reset         = true,
 603        .has_burst_ctl          = true,
 604};
 605
 606static const struct sun4i_spi_variant sun8i_h3_spi_variant = {
 607        .regs                   = sun6i_spi_regs,
 608        .bits                   = sun6i_spi_bits,
 609        .fifo_depth             = 64,
 610        .has_soft_reset         = true,
 611        .has_burst_ctl          = true,
 612};
 613
 614static const struct udevice_id sun4i_spi_ids[] = {
 615        {
 616          .compatible = "allwinner,sun4i-a10-spi",
 617          .data = (ulong)&sun4i_a10_spi_variant,
 618        },
 619        {
 620          .compatible = "allwinner,sun6i-a31-spi",
 621          .data = (ulong)&sun6i_a31_spi_variant,
 622        },
 623        {
 624          .compatible = "allwinner,sun8i-h3-spi",
 625          .data = (ulong)&sun8i_h3_spi_variant,
 626        },
 627        { /* sentinel */ }
 628};
 629
 630U_BOOT_DRIVER(sun4i_spi) = {
 631        .name   = "sun4i_spi",
 632        .id     = UCLASS_SPI,
 633        .of_match       = sun4i_spi_ids,
 634        .ops    = &sun4i_spi_ops,
 635        .of_to_plat     = sun4i_spi_of_to_plat,
 636        .plat_auto      = sizeof(struct sun4i_spi_plat),
 637        .priv_auto      = sizeof(struct sun4i_spi_priv),
 638        .probe  = sun4i_spi_probe,
 639};
 640