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