1ff1da6fbSAllen Martin /* 26b3a03e1SAllen Martin * Copyright (c) 2010-2013 NVIDIA Corporation 3ff1da6fbSAllen Martin * With help from the mpc8xxx SPI driver 4ff1da6fbSAllen Martin * With more help from omap3_spi SPI driver 5ff1da6fbSAllen Martin * 61a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 7ff1da6fbSAllen Martin */ 8ff1da6fbSAllen Martin 9ff1da6fbSAllen Martin #include <common.h> 10fda6fac3SSimon Glass #include <dm.h> 11fda6fac3SSimon Glass #include <errno.h> 12ff1da6fbSAllen Martin #include <asm/io.h> 13ff1da6fbSAllen Martin #include <asm/gpio.h> 14ff1da6fbSAllen Martin #include <asm/arch/clock.h> 15ff1da6fbSAllen Martin #include <asm/arch/pinmux.h> 16ff1da6fbSAllen Martin #include <asm/arch-tegra/clk_rst.h> 17ff1da6fbSAllen Martin #include <spi.h> 18ff1da6fbSAllen Martin #include <fdtdec.h> 19fda6fac3SSimon Glass #include "tegra_spi.h" 20ff1da6fbSAllen Martin 21ff1da6fbSAllen Martin DECLARE_GLOBAL_DATA_PTR; 22ff1da6fbSAllen Martin 237a49ba6eSAllen Martin #define SPI_CMD_GO (1 << 30) 247a49ba6eSAllen Martin #define SPI_CMD_ACTIVE_SCLK_SHIFT 26 257a49ba6eSAllen Martin #define SPI_CMD_ACTIVE_SCLK_MASK (3 << SPI_CMD_ACTIVE_SCLK_SHIFT) 267a49ba6eSAllen Martin #define SPI_CMD_CK_SDA (1 << 21) 277a49ba6eSAllen Martin #define SPI_CMD_ACTIVE_SDA_SHIFT 18 287a49ba6eSAllen Martin #define SPI_CMD_ACTIVE_SDA_MASK (3 << SPI_CMD_ACTIVE_SDA_SHIFT) 297a49ba6eSAllen Martin #define SPI_CMD_CS_POL (1 << 16) 307a49ba6eSAllen Martin #define SPI_CMD_TXEN (1 << 15) 317a49ba6eSAllen Martin #define SPI_CMD_RXEN (1 << 14) 327a49ba6eSAllen Martin #define SPI_CMD_CS_VAL (1 << 13) 337a49ba6eSAllen Martin #define SPI_CMD_CS_SOFT (1 << 12) 347a49ba6eSAllen Martin #define SPI_CMD_CS_DELAY (1 << 9) 357a49ba6eSAllen Martin #define SPI_CMD_CS3_EN (1 << 8) 367a49ba6eSAllen Martin #define SPI_CMD_CS2_EN (1 << 7) 377a49ba6eSAllen Martin #define SPI_CMD_CS1_EN (1 << 6) 387a49ba6eSAllen Martin #define SPI_CMD_CS0_EN (1 << 5) 397a49ba6eSAllen Martin #define SPI_CMD_BIT_LENGTH (1 << 4) 407a49ba6eSAllen Martin #define SPI_CMD_BIT_LENGTH_MASK 0x0000001F 417a49ba6eSAllen Martin 427a49ba6eSAllen Martin #define SPI_STAT_BSY (1 << 31) 437a49ba6eSAllen Martin #define SPI_STAT_RDY (1 << 30) 447a49ba6eSAllen Martin #define SPI_STAT_RXF_FLUSH (1 << 29) 457a49ba6eSAllen Martin #define SPI_STAT_TXF_FLUSH (1 << 28) 467a49ba6eSAllen Martin #define SPI_STAT_RXF_UNR (1 << 27) 477a49ba6eSAllen Martin #define SPI_STAT_TXF_OVF (1 << 26) 487a49ba6eSAllen Martin #define SPI_STAT_RXF_EMPTY (1 << 25) 497a49ba6eSAllen Martin #define SPI_STAT_RXF_FULL (1 << 24) 507a49ba6eSAllen Martin #define SPI_STAT_TXF_EMPTY (1 << 23) 517a49ba6eSAllen Martin #define SPI_STAT_TXF_FULL (1 << 22) 527a49ba6eSAllen Martin #define SPI_STAT_SEL_TXRX_N (1 << 16) 537a49ba6eSAllen Martin #define SPI_STAT_CUR_BLKCNT (1 << 15) 547a49ba6eSAllen Martin 557a49ba6eSAllen Martin #define SPI_TIMEOUT 1000 567a49ba6eSAllen Martin #define TEGRA_SPI_MAX_FREQ 52000000 577a49ba6eSAllen Martin 587a49ba6eSAllen Martin struct spi_regs { 597a49ba6eSAllen Martin u32 command; /* SPI_COMMAND_0 register */ 607a49ba6eSAllen Martin u32 status; /* SPI_STATUS_0 register */ 617a49ba6eSAllen Martin u32 rx_cmp; /* SPI_RX_CMP_0 register */ 627a49ba6eSAllen Martin u32 dma_ctl; /* SPI_DMA_CTL_0 register */ 637a49ba6eSAllen Martin u32 tx_fifo; /* SPI_TX_FIFO_0 register */ 647a49ba6eSAllen Martin u32 rsvd[3]; /* offsets 0x14 to 0x1F reserved */ 657a49ba6eSAllen Martin u32 rx_fifo; /* SPI_RX_FIFO_0 register */ 667a49ba6eSAllen Martin }; 677a49ba6eSAllen Martin 68fda6fac3SSimon Glass struct tegra20_sflash_priv { 697a49ba6eSAllen Martin struct spi_regs *regs; 70ff1da6fbSAllen Martin unsigned int freq; 71ff1da6fbSAllen Martin unsigned int mode; 72ff1da6fbSAllen Martin int periph_id; 736b3a03e1SAllen Martin int valid; 74fda6fac3SSimon Glass int last_transaction_us; 75ff1da6fbSAllen Martin }; 76ff1da6fbSAllen Martin 77fda6fac3SSimon Glass int tegra20_sflash_cs_info(struct udevice *bus, unsigned int cs, 78fda6fac3SSimon Glass struct spi_cs_info *info) 79ff1da6fbSAllen Martin { 80ff1da6fbSAllen Martin /* Tegra20 SPI-Flash - only 1 device ('bus/cs') */ 81fda6fac3SSimon Glass if (cs != 0) 82fda6fac3SSimon Glass return -ENODEV; 83ff1da6fbSAllen Martin else 84fda6fac3SSimon Glass return 0; 85ff1da6fbSAllen Martin } 86ff1da6fbSAllen Martin 87fda6fac3SSimon Glass static int tegra20_sflash_ofdata_to_platdata(struct udevice *bus) 88ff1da6fbSAllen Martin { 89fda6fac3SSimon Glass struct tegra_spi_platdata *plat = bus->platdata; 90fda6fac3SSimon Glass const void *blob = gd->fdt_blob; 91fda6fac3SSimon Glass int node = bus->of_offset; 92ff1da6fbSAllen Martin 93fda6fac3SSimon Glass plat->base = fdtdec_get_addr(blob, node, "reg"); 94fda6fac3SSimon Glass plat->periph_id = clock_decode_periph_id(blob, node); 95fda6fac3SSimon Glass 96fda6fac3SSimon Glass if (plat->periph_id == PERIPH_ID_NONE) { 97fda6fac3SSimon Glass debug("%s: could not decode periph id %d\n", __func__, 98fda6fac3SSimon Glass plat->periph_id); 99fda6fac3SSimon Glass return -FDT_ERR_NOTFOUND; 100ff1da6fbSAllen Martin } 101ff1da6fbSAllen Martin 102fda6fac3SSimon Glass /* Use 500KHz as a suitable default */ 103fda6fac3SSimon Glass plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", 104fda6fac3SSimon Glass 500000); 105fda6fac3SSimon Glass plat->deactivate_delay_us = fdtdec_get_int(blob, node, 106fda6fac3SSimon Glass "spi-deactivate-delay", 0); 107fda6fac3SSimon Glass debug("%s: base=%#08lx, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n", 108fda6fac3SSimon Glass __func__, plat->base, plat->periph_id, plat->frequency, 109fda6fac3SSimon Glass plat->deactivate_delay_us); 110fda6fac3SSimon Glass 111fda6fac3SSimon Glass return 0; 112ff1da6fbSAllen Martin } 113ff1da6fbSAllen Martin 114fda6fac3SSimon Glass static int tegra20_sflash_probe(struct udevice *bus) 115ff1da6fbSAllen Martin { 116fda6fac3SSimon Glass struct tegra_spi_platdata *plat = dev_get_platdata(bus); 117fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus); 118ff1da6fbSAllen Martin 119fda6fac3SSimon Glass priv->regs = (struct spi_regs *)plat->base; 120fda6fac3SSimon Glass 121fda6fac3SSimon Glass priv->last_transaction_us = timer_get_us(); 122fda6fac3SSimon Glass priv->freq = plat->frequency; 123fda6fac3SSimon Glass priv->periph_id = plat->periph_id; 124fda6fac3SSimon Glass 125fda6fac3SSimon Glass return 0; 126ff1da6fbSAllen Martin } 127ff1da6fbSAllen Martin 128*9694b724SSimon Glass static int tegra20_sflash_claim_bus(struct udevice *dev) 129ff1da6fbSAllen Martin { 130*9694b724SSimon Glass struct udevice *bus = dev->parent; 131fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus); 132fda6fac3SSimon Glass struct spi_regs *regs = priv->regs; 133ff1da6fbSAllen Martin u32 reg; 134ff1da6fbSAllen Martin 135ff1da6fbSAllen Martin /* Change SPI clock to correct frequency, PLLP_OUT0 source */ 136fda6fac3SSimon Glass clock_start_periph_pll(priv->periph_id, CLOCK_ID_PERIPH, 137fda6fac3SSimon Glass priv->freq); 138ff1da6fbSAllen Martin 139ff1da6fbSAllen Martin /* Clear stale status here */ 140ff1da6fbSAllen Martin reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \ 141ff1da6fbSAllen Martin SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF; 142ff1da6fbSAllen Martin writel(reg, ®s->status); 14378f47b73SAllen Martin debug("%s: STATUS = %08x\n", __func__, readl(®s->status)); 144ff1da6fbSAllen Martin 145ff1da6fbSAllen Martin /* 146ff1da6fbSAllen Martin * Use sw-controlled CS, so we can clock in data after ReadID, etc. 147ff1da6fbSAllen Martin */ 148fda6fac3SSimon Glass reg = (priv->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT; 149fda6fac3SSimon Glass if (priv->mode & 2) 150ff1da6fbSAllen Martin reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT; 151ff1da6fbSAllen Martin clrsetbits_le32(®s->command, SPI_CMD_ACTIVE_SCLK_MASK | 152ff1da6fbSAllen Martin SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg); 15378f47b73SAllen Martin debug("%s: COMMAND = %08x\n", __func__, readl(®s->command)); 154ff1da6fbSAllen Martin 155ff1da6fbSAllen Martin /* 156ff1da6fbSAllen Martin * SPI pins on Tegra20 are muxed - change pinmux later due to UART 157ff1da6fbSAllen Martin * issue. 158ff1da6fbSAllen Martin */ 15970ad375eSStephen Warren pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH); 16070ad375eSStephen Warren pinmux_tristate_disable(PMUX_PINGRP_LSPI); 16170ad375eSStephen Warren pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH); 162ff1da6fbSAllen Martin 163ff1da6fbSAllen Martin return 0; 164ff1da6fbSAllen Martin } 165ff1da6fbSAllen Martin 166fda6fac3SSimon Glass static void spi_cs_activate(struct udevice *dev) 167ff1da6fbSAllen Martin { 168fda6fac3SSimon Glass struct udevice *bus = dev->parent; 169fda6fac3SSimon Glass struct tegra_spi_platdata *pdata = dev_get_platdata(bus); 170fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus); 171fda6fac3SSimon Glass 172fda6fac3SSimon Glass /* If it's too soon to do another transaction, wait */ 173fda6fac3SSimon Glass if (pdata->deactivate_delay_us && 174fda6fac3SSimon Glass priv->last_transaction_us) { 175fda6fac3SSimon Glass ulong delay_us; /* The delay completed so far */ 176fda6fac3SSimon Glass delay_us = timer_get_us() - priv->last_transaction_us; 177fda6fac3SSimon Glass if (delay_us < pdata->deactivate_delay_us) 178fda6fac3SSimon Glass udelay(pdata->deactivate_delay_us - delay_us); 179fda6fac3SSimon Glass } 180ff1da6fbSAllen Martin 181ff1da6fbSAllen Martin /* CS is negated on Tegra, so drive a 1 to get a 0 */ 182fda6fac3SSimon Glass setbits_le32(&priv->regs->command, SPI_CMD_CS_VAL); 183ff1da6fbSAllen Martin } 184ff1da6fbSAllen Martin 185fda6fac3SSimon Glass static void spi_cs_deactivate(struct udevice *dev) 186ff1da6fbSAllen Martin { 187fda6fac3SSimon Glass struct udevice *bus = dev->parent; 188fda6fac3SSimon Glass struct tegra_spi_platdata *pdata = dev_get_platdata(bus); 189fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus); 190ff1da6fbSAllen Martin 191ff1da6fbSAllen Martin /* CS is negated on Tegra, so drive a 0 to get a 1 */ 192fda6fac3SSimon Glass clrbits_le32(&priv->regs->command, SPI_CMD_CS_VAL); 193fda6fac3SSimon Glass 194fda6fac3SSimon Glass /* Remember time of this transaction so we can honour the bus delay */ 195fda6fac3SSimon Glass if (pdata->deactivate_delay_us) 196fda6fac3SSimon Glass priv->last_transaction_us = timer_get_us(); 197ff1da6fbSAllen Martin } 198ff1da6fbSAllen Martin 199fda6fac3SSimon Glass static int tegra20_sflash_xfer(struct udevice *dev, unsigned int bitlen, 200fda6fac3SSimon Glass const void *data_out, void *data_in, 201fda6fac3SSimon Glass unsigned long flags) 202ff1da6fbSAllen Martin { 203fda6fac3SSimon Glass struct udevice *bus = dev->parent; 204fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus); 205fda6fac3SSimon Glass struct spi_regs *regs = priv->regs; 206ff1da6fbSAllen Martin u32 reg, tmpdout, tmpdin = 0; 207ff1da6fbSAllen Martin const u8 *dout = data_out; 208ff1da6fbSAllen Martin u8 *din = data_in; 209ff1da6fbSAllen Martin int num_bytes; 210ff1da6fbSAllen Martin int ret; 211ff1da6fbSAllen Martin 212fda6fac3SSimon Glass debug("%s: slave %u:%u dout %p din %p bitlen %u\n", 213fda6fac3SSimon Glass __func__, bus->seq, spi_chip_select(dev), dout, din, bitlen); 214ff1da6fbSAllen Martin if (bitlen % 8) 215ff1da6fbSAllen Martin return -1; 216ff1da6fbSAllen Martin num_bytes = bitlen / 8; 217ff1da6fbSAllen Martin 218ff1da6fbSAllen Martin ret = 0; 219ff1da6fbSAllen Martin 220ff1da6fbSAllen Martin reg = readl(®s->status); 221ff1da6fbSAllen Martin writel(reg, ®s->status); /* Clear all SPI events via R/W */ 222ff1da6fbSAllen Martin debug("spi_xfer entry: STATUS = %08x\n", reg); 223ff1da6fbSAllen Martin 224ff1da6fbSAllen Martin reg = readl(®s->command); 225ff1da6fbSAllen Martin reg |= SPI_CMD_TXEN | SPI_CMD_RXEN; 226ff1da6fbSAllen Martin writel(reg, ®s->command); 227ff1da6fbSAllen Martin debug("spi_xfer: COMMAND = %08x\n", readl(®s->command)); 228ff1da6fbSAllen Martin 229ff1da6fbSAllen Martin if (flags & SPI_XFER_BEGIN) 230fda6fac3SSimon Glass spi_cs_activate(dev); 231ff1da6fbSAllen Martin 232ff1da6fbSAllen Martin /* handle data in 32-bit chunks */ 233ff1da6fbSAllen Martin while (num_bytes > 0) { 234ff1da6fbSAllen Martin int bytes; 235ff1da6fbSAllen Martin int is_read = 0; 236ff1da6fbSAllen Martin int tm, i; 237ff1da6fbSAllen Martin 238ff1da6fbSAllen Martin tmpdout = 0; 239ff1da6fbSAllen Martin bytes = (num_bytes > 4) ? 4 : num_bytes; 240ff1da6fbSAllen Martin 241ff1da6fbSAllen Martin if (dout != NULL) { 242ff1da6fbSAllen Martin for (i = 0; i < bytes; ++i) 243ff1da6fbSAllen Martin tmpdout = (tmpdout << 8) | dout[i]; 244ff1da6fbSAllen Martin } 245ff1da6fbSAllen Martin 246ff1da6fbSAllen Martin num_bytes -= bytes; 247ff1da6fbSAllen Martin if (dout) 248ff1da6fbSAllen Martin dout += bytes; 249ff1da6fbSAllen Martin 250ff1da6fbSAllen Martin clrsetbits_le32(®s->command, SPI_CMD_BIT_LENGTH_MASK, 251ff1da6fbSAllen Martin bytes * 8 - 1); 252ff1da6fbSAllen Martin writel(tmpdout, ®s->tx_fifo); 253ff1da6fbSAllen Martin setbits_le32(®s->command, SPI_CMD_GO); 254ff1da6fbSAllen Martin 255ff1da6fbSAllen Martin /* 256ff1da6fbSAllen Martin * Wait for SPI transmit FIFO to empty, or to time out. 257ff1da6fbSAllen Martin * The RX FIFO status will be read and cleared last 258ff1da6fbSAllen Martin */ 259ff1da6fbSAllen Martin for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) { 260ff1da6fbSAllen Martin u32 status; 261ff1da6fbSAllen Martin 262ff1da6fbSAllen Martin status = readl(®s->status); 263ff1da6fbSAllen Martin 264ff1da6fbSAllen Martin /* We can exit when we've had both RX and TX activity */ 265ff1da6fbSAllen Martin if (is_read && (status & SPI_STAT_TXF_EMPTY)) 266ff1da6fbSAllen Martin break; 267ff1da6fbSAllen Martin 268ff1da6fbSAllen Martin if ((status & (SPI_STAT_BSY | SPI_STAT_RDY)) != 269ff1da6fbSAllen Martin SPI_STAT_RDY) 270ff1da6fbSAllen Martin tm++; 271ff1da6fbSAllen Martin 272ff1da6fbSAllen Martin else if (!(status & SPI_STAT_RXF_EMPTY)) { 273ff1da6fbSAllen Martin tmpdin = readl(®s->rx_fifo); 274ff1da6fbSAllen Martin is_read = 1; 275ff1da6fbSAllen Martin 276ff1da6fbSAllen Martin /* swap bytes read in */ 277ff1da6fbSAllen Martin if (din != NULL) { 278ff1da6fbSAllen Martin for (i = bytes - 1; i >= 0; --i) { 279ff1da6fbSAllen Martin din[i] = tmpdin & 0xff; 280ff1da6fbSAllen Martin tmpdin >>= 8; 281ff1da6fbSAllen Martin } 282ff1da6fbSAllen Martin din += bytes; 283ff1da6fbSAllen Martin } 284ff1da6fbSAllen Martin } 285ff1da6fbSAllen Martin } 286ff1da6fbSAllen Martin 287ff1da6fbSAllen Martin if (tm >= SPI_TIMEOUT) 288ff1da6fbSAllen Martin ret = tm; 289ff1da6fbSAllen Martin 290ff1da6fbSAllen Martin /* clear ACK RDY, etc. bits */ 291ff1da6fbSAllen Martin writel(readl(®s->status), ®s->status); 292ff1da6fbSAllen Martin } 293ff1da6fbSAllen Martin 294ff1da6fbSAllen Martin if (flags & SPI_XFER_END) 295fda6fac3SSimon Glass spi_cs_deactivate(dev); 296ff1da6fbSAllen Martin 297ff1da6fbSAllen Martin debug("spi_xfer: transfer ended. Value=%08x, status = %08x\n", 298ff1da6fbSAllen Martin tmpdin, readl(®s->status)); 299ff1da6fbSAllen Martin 300ff1da6fbSAllen Martin if (ret) { 301ff1da6fbSAllen Martin printf("spi_xfer: timeout during SPI transfer, tm %d\n", ret); 302ff1da6fbSAllen Martin return -1; 303ff1da6fbSAllen Martin } 304ff1da6fbSAllen Martin 305ff1da6fbSAllen Martin return 0; 306ff1da6fbSAllen Martin } 307fda6fac3SSimon Glass 308fda6fac3SSimon Glass static int tegra20_sflash_set_speed(struct udevice *bus, uint speed) 309fda6fac3SSimon Glass { 310fda6fac3SSimon Glass struct tegra_spi_platdata *plat = bus->platdata; 311fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus); 312fda6fac3SSimon Glass 313fda6fac3SSimon Glass if (speed > plat->frequency) 314fda6fac3SSimon Glass speed = plat->frequency; 315fda6fac3SSimon Glass priv->freq = speed; 316fda6fac3SSimon Glass debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq); 317fda6fac3SSimon Glass 318fda6fac3SSimon Glass return 0; 319fda6fac3SSimon Glass } 320fda6fac3SSimon Glass 321fda6fac3SSimon Glass static int tegra20_sflash_set_mode(struct udevice *bus, uint mode) 322fda6fac3SSimon Glass { 323fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus); 324fda6fac3SSimon Glass 325fda6fac3SSimon Glass priv->mode = mode; 326fda6fac3SSimon Glass debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode); 327fda6fac3SSimon Glass 328fda6fac3SSimon Glass return 0; 329fda6fac3SSimon Glass } 330fda6fac3SSimon Glass 331fda6fac3SSimon Glass static const struct dm_spi_ops tegra20_sflash_ops = { 332fda6fac3SSimon Glass .claim_bus = tegra20_sflash_claim_bus, 333fda6fac3SSimon Glass .xfer = tegra20_sflash_xfer, 334fda6fac3SSimon Glass .set_speed = tegra20_sflash_set_speed, 335fda6fac3SSimon Glass .set_mode = tegra20_sflash_set_mode, 336fda6fac3SSimon Glass .cs_info = tegra20_sflash_cs_info, 337fda6fac3SSimon Glass }; 338fda6fac3SSimon Glass 339fda6fac3SSimon Glass static const struct udevice_id tegra20_sflash_ids[] = { 340fda6fac3SSimon Glass { .compatible = "nvidia,tegra20-sflash" }, 341fda6fac3SSimon Glass { } 342fda6fac3SSimon Glass }; 343fda6fac3SSimon Glass 344fda6fac3SSimon Glass U_BOOT_DRIVER(tegra20_sflash) = { 345fda6fac3SSimon Glass .name = "tegra20_sflash", 346fda6fac3SSimon Glass .id = UCLASS_SPI, 347fda6fac3SSimon Glass .of_match = tegra20_sflash_ids, 348fda6fac3SSimon Glass .ops = &tegra20_sflash_ops, 349fda6fac3SSimon Glass .ofdata_to_platdata = tegra20_sflash_ofdata_to_platdata, 350fda6fac3SSimon Glass .platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata), 351fda6fac3SSimon Glass .priv_auto_alloc_size = sizeof(struct tegra20_sflash_priv), 352fda6fac3SSimon Glass .probe = tegra20_sflash_probe, 353fda6fac3SSimon Glass }; 354