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
23f692248fSJagan Teki #define SPI_CMD_GO BIT(30)
247a49ba6eSAllen Martin #define SPI_CMD_ACTIVE_SCLK_SHIFT 26
257a49ba6eSAllen Martin #define SPI_CMD_ACTIVE_SCLK_MASK (3 << SPI_CMD_ACTIVE_SCLK_SHIFT)
26f692248fSJagan Teki #define SPI_CMD_CK_SDA BIT(21)
277a49ba6eSAllen Martin #define SPI_CMD_ACTIVE_SDA_SHIFT 18
287a49ba6eSAllen Martin #define SPI_CMD_ACTIVE_SDA_MASK (3 << SPI_CMD_ACTIVE_SDA_SHIFT)
29f692248fSJagan Teki #define SPI_CMD_CS_POL BIT(16)
30f692248fSJagan Teki #define SPI_CMD_TXEN BIT(15)
31f692248fSJagan Teki #define SPI_CMD_RXEN BIT(14)
32f692248fSJagan Teki #define SPI_CMD_CS_VAL BIT(13)
33f692248fSJagan Teki #define SPI_CMD_CS_SOFT BIT(12)
34f692248fSJagan Teki #define SPI_CMD_CS_DELAY BIT(9)
35f692248fSJagan Teki #define SPI_CMD_CS3_EN BIT(8)
36f692248fSJagan Teki #define SPI_CMD_CS2_EN BIT(7)
37f692248fSJagan Teki #define SPI_CMD_CS1_EN BIT(6)
38f692248fSJagan Teki #define SPI_CMD_CS0_EN BIT(5)
39f692248fSJagan Teki #define SPI_CMD_BIT_LENGTH BIT(4)
4076538ec6SJagan Teki #define SPI_CMD_BIT_LENGTH_MASK GENMASK(4, 0)
417a49ba6eSAllen Martin
42f692248fSJagan Teki #define SPI_STAT_BSY BIT(31)
43f692248fSJagan Teki #define SPI_STAT_RDY BIT(30)
44f692248fSJagan Teki #define SPI_STAT_RXF_FLUSH BIT(29)
45f692248fSJagan Teki #define SPI_STAT_TXF_FLUSH BIT(28)
46f692248fSJagan Teki #define SPI_STAT_RXF_UNR BIT(27)
47f692248fSJagan Teki #define SPI_STAT_TXF_OVF BIT(26)
48f692248fSJagan Teki #define SPI_STAT_RXF_EMPTY BIT(25)
49f692248fSJagan Teki #define SPI_STAT_RXF_FULL BIT(24)
50f692248fSJagan Teki #define SPI_STAT_TXF_EMPTY BIT(23)
51f692248fSJagan Teki #define SPI_STAT_TXF_FULL BIT(22)
52f692248fSJagan Teki #define SPI_STAT_SEL_TXRX_N BIT(16)
53f692248fSJagan Teki #define SPI_STAT_CUR_BLKCNT BIT(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
tegra20_sflash_cs_info(struct udevice * bus,unsigned int cs,struct spi_cs_info * info)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
tegra20_sflash_ofdata_to_platdata(struct udevice * bus)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;
91e160f7d4SSimon Glass int node = dev_of_offset(bus);
92ff1da6fbSAllen Martin
93a821c4afSSimon Glass plat->base = devfdt_get_addr(bus);
94*000f15faSSimon Glass plat->periph_id = clock_decode_periph_id(bus);
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
tegra20_sflash_probe(struct udevice * bus)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
1254832c7f5SStephen Warren /* Change SPI clock to correct frequency, PLLP_OUT0 source */
1264832c7f5SStephen Warren clock_start_periph_pll(priv->periph_id, CLOCK_ID_PERIPH,
1274832c7f5SStephen Warren priv->freq);
1284832c7f5SStephen Warren
129fda6fac3SSimon Glass return 0;
130ff1da6fbSAllen Martin }
131ff1da6fbSAllen Martin
tegra20_sflash_claim_bus(struct udevice * dev)1329694b724SSimon Glass static int tegra20_sflash_claim_bus(struct udevice *dev)
133ff1da6fbSAllen Martin {
1349694b724SSimon Glass struct udevice *bus = dev->parent;
135fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus);
136fda6fac3SSimon Glass struct spi_regs *regs = priv->regs;
137ff1da6fbSAllen Martin u32 reg;
138ff1da6fbSAllen Martin
139ff1da6fbSAllen Martin /* Change SPI clock to correct frequency, PLLP_OUT0 source */
140fda6fac3SSimon Glass clock_start_periph_pll(priv->periph_id, CLOCK_ID_PERIPH,
141fda6fac3SSimon Glass priv->freq);
142ff1da6fbSAllen Martin
143ff1da6fbSAllen Martin /* Clear stale status here */
144ff1da6fbSAllen Martin reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \
145ff1da6fbSAllen Martin SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF;
146ff1da6fbSAllen Martin writel(reg, ®s->status);
14778f47b73SAllen Martin debug("%s: STATUS = %08x\n", __func__, readl(®s->status));
148ff1da6fbSAllen Martin
149ff1da6fbSAllen Martin /*
150ff1da6fbSAllen Martin * Use sw-controlled CS, so we can clock in data after ReadID, etc.
151ff1da6fbSAllen Martin */
152fda6fac3SSimon Glass reg = (priv->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT;
153fda6fac3SSimon Glass if (priv->mode & 2)
154ff1da6fbSAllen Martin reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT;
155ff1da6fbSAllen Martin clrsetbits_le32(®s->command, SPI_CMD_ACTIVE_SCLK_MASK |
156ff1da6fbSAllen Martin SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg);
15778f47b73SAllen Martin debug("%s: COMMAND = %08x\n", __func__, readl(®s->command));
158ff1da6fbSAllen Martin
159ff1da6fbSAllen Martin /*
160ff1da6fbSAllen Martin * SPI pins on Tegra20 are muxed - change pinmux later due to UART
161ff1da6fbSAllen Martin * issue.
162ff1da6fbSAllen Martin */
16370ad375eSStephen Warren pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
16470ad375eSStephen Warren pinmux_tristate_disable(PMUX_PINGRP_LSPI);
16570ad375eSStephen Warren pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);
166ff1da6fbSAllen Martin
167ff1da6fbSAllen Martin return 0;
168ff1da6fbSAllen Martin }
169ff1da6fbSAllen Martin
spi_cs_activate(struct udevice * dev)170fda6fac3SSimon Glass static void spi_cs_activate(struct udevice *dev)
171ff1da6fbSAllen Martin {
172fda6fac3SSimon Glass struct udevice *bus = dev->parent;
173fda6fac3SSimon Glass struct tegra_spi_platdata *pdata = dev_get_platdata(bus);
174fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus);
175fda6fac3SSimon Glass
176fda6fac3SSimon Glass /* If it's too soon to do another transaction, wait */
177fda6fac3SSimon Glass if (pdata->deactivate_delay_us &&
178fda6fac3SSimon Glass priv->last_transaction_us) {
179fda6fac3SSimon Glass ulong delay_us; /* The delay completed so far */
180fda6fac3SSimon Glass delay_us = timer_get_us() - priv->last_transaction_us;
181fda6fac3SSimon Glass if (delay_us < pdata->deactivate_delay_us)
182fda6fac3SSimon Glass udelay(pdata->deactivate_delay_us - delay_us);
183fda6fac3SSimon Glass }
184ff1da6fbSAllen Martin
185ff1da6fbSAllen Martin /* CS is negated on Tegra, so drive a 1 to get a 0 */
186fda6fac3SSimon Glass setbits_le32(&priv->regs->command, SPI_CMD_CS_VAL);
187ff1da6fbSAllen Martin }
188ff1da6fbSAllen Martin
spi_cs_deactivate(struct udevice * dev)189fda6fac3SSimon Glass static void spi_cs_deactivate(struct udevice *dev)
190ff1da6fbSAllen Martin {
191fda6fac3SSimon Glass struct udevice *bus = dev->parent;
192fda6fac3SSimon Glass struct tegra_spi_platdata *pdata = dev_get_platdata(bus);
193fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus);
194ff1da6fbSAllen Martin
195ff1da6fbSAllen Martin /* CS is negated on Tegra, so drive a 0 to get a 1 */
196fda6fac3SSimon Glass clrbits_le32(&priv->regs->command, SPI_CMD_CS_VAL);
197fda6fac3SSimon Glass
198fda6fac3SSimon Glass /* Remember time of this transaction so we can honour the bus delay */
199fda6fac3SSimon Glass if (pdata->deactivate_delay_us)
200fda6fac3SSimon Glass priv->last_transaction_us = timer_get_us();
201ff1da6fbSAllen Martin }
202ff1da6fbSAllen Martin
tegra20_sflash_xfer(struct udevice * dev,unsigned int bitlen,const void * data_out,void * data_in,unsigned long flags)203fda6fac3SSimon Glass static int tegra20_sflash_xfer(struct udevice *dev, unsigned int bitlen,
204fda6fac3SSimon Glass const void *data_out, void *data_in,
205fda6fac3SSimon Glass unsigned long flags)
206ff1da6fbSAllen Martin {
207fda6fac3SSimon Glass struct udevice *bus = dev->parent;
208fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus);
209fda6fac3SSimon Glass struct spi_regs *regs = priv->regs;
210ff1da6fbSAllen Martin u32 reg, tmpdout, tmpdin = 0;
211ff1da6fbSAllen Martin const u8 *dout = data_out;
212ff1da6fbSAllen Martin u8 *din = data_in;
213ff1da6fbSAllen Martin int num_bytes;
214ff1da6fbSAllen Martin int ret;
215ff1da6fbSAllen Martin
216fda6fac3SSimon Glass debug("%s: slave %u:%u dout %p din %p bitlen %u\n",
217fda6fac3SSimon Glass __func__, bus->seq, spi_chip_select(dev), dout, din, bitlen);
218ff1da6fbSAllen Martin if (bitlen % 8)
219ff1da6fbSAllen Martin return -1;
220ff1da6fbSAllen Martin num_bytes = bitlen / 8;
221ff1da6fbSAllen Martin
222ff1da6fbSAllen Martin ret = 0;
223ff1da6fbSAllen Martin
224ff1da6fbSAllen Martin reg = readl(®s->status);
225ff1da6fbSAllen Martin writel(reg, ®s->status); /* Clear all SPI events via R/W */
226ff1da6fbSAllen Martin debug("spi_xfer entry: STATUS = %08x\n", reg);
227ff1da6fbSAllen Martin
228ff1da6fbSAllen Martin reg = readl(®s->command);
229ff1da6fbSAllen Martin reg |= SPI_CMD_TXEN | SPI_CMD_RXEN;
230ff1da6fbSAllen Martin writel(reg, ®s->command);
231ff1da6fbSAllen Martin debug("spi_xfer: COMMAND = %08x\n", readl(®s->command));
232ff1da6fbSAllen Martin
233ff1da6fbSAllen Martin if (flags & SPI_XFER_BEGIN)
234fda6fac3SSimon Glass spi_cs_activate(dev);
235ff1da6fbSAllen Martin
236ff1da6fbSAllen Martin /* handle data in 32-bit chunks */
237ff1da6fbSAllen Martin while (num_bytes > 0) {
238ff1da6fbSAllen Martin int bytes;
239ff1da6fbSAllen Martin int is_read = 0;
240ff1da6fbSAllen Martin int tm, i;
241ff1da6fbSAllen Martin
242ff1da6fbSAllen Martin tmpdout = 0;
243ff1da6fbSAllen Martin bytes = (num_bytes > 4) ? 4 : num_bytes;
244ff1da6fbSAllen Martin
245ff1da6fbSAllen Martin if (dout != NULL) {
246ff1da6fbSAllen Martin for (i = 0; i < bytes; ++i)
247ff1da6fbSAllen Martin tmpdout = (tmpdout << 8) | dout[i];
248ff1da6fbSAllen Martin }
249ff1da6fbSAllen Martin
250ff1da6fbSAllen Martin num_bytes -= bytes;
251ff1da6fbSAllen Martin if (dout)
252ff1da6fbSAllen Martin dout += bytes;
253ff1da6fbSAllen Martin
254ff1da6fbSAllen Martin clrsetbits_le32(®s->command, SPI_CMD_BIT_LENGTH_MASK,
255ff1da6fbSAllen Martin bytes * 8 - 1);
256ff1da6fbSAllen Martin writel(tmpdout, ®s->tx_fifo);
257ff1da6fbSAllen Martin setbits_le32(®s->command, SPI_CMD_GO);
258ff1da6fbSAllen Martin
259ff1da6fbSAllen Martin /*
260ff1da6fbSAllen Martin * Wait for SPI transmit FIFO to empty, or to time out.
261ff1da6fbSAllen Martin * The RX FIFO status will be read and cleared last
262ff1da6fbSAllen Martin */
263ff1da6fbSAllen Martin for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) {
264ff1da6fbSAllen Martin u32 status;
265ff1da6fbSAllen Martin
266ff1da6fbSAllen Martin status = readl(®s->status);
267ff1da6fbSAllen Martin
268ff1da6fbSAllen Martin /* We can exit when we've had both RX and TX activity */
269ff1da6fbSAllen Martin if (is_read && (status & SPI_STAT_TXF_EMPTY))
270ff1da6fbSAllen Martin break;
271ff1da6fbSAllen Martin
272ff1da6fbSAllen Martin if ((status & (SPI_STAT_BSY | SPI_STAT_RDY)) !=
273ff1da6fbSAllen Martin SPI_STAT_RDY)
274ff1da6fbSAllen Martin tm++;
275ff1da6fbSAllen Martin
276ff1da6fbSAllen Martin else if (!(status & SPI_STAT_RXF_EMPTY)) {
277ff1da6fbSAllen Martin tmpdin = readl(®s->rx_fifo);
278ff1da6fbSAllen Martin is_read = 1;
279ff1da6fbSAllen Martin
280ff1da6fbSAllen Martin /* swap bytes read in */
281ff1da6fbSAllen Martin if (din != NULL) {
282ff1da6fbSAllen Martin for (i = bytes - 1; i >= 0; --i) {
283ff1da6fbSAllen Martin din[i] = tmpdin & 0xff;
284ff1da6fbSAllen Martin tmpdin >>= 8;
285ff1da6fbSAllen Martin }
286ff1da6fbSAllen Martin din += bytes;
287ff1da6fbSAllen Martin }
288ff1da6fbSAllen Martin }
289ff1da6fbSAllen Martin }
290ff1da6fbSAllen Martin
291ff1da6fbSAllen Martin if (tm >= SPI_TIMEOUT)
292ff1da6fbSAllen Martin ret = tm;
293ff1da6fbSAllen Martin
294ff1da6fbSAllen Martin /* clear ACK RDY, etc. bits */
295ff1da6fbSAllen Martin writel(readl(®s->status), ®s->status);
296ff1da6fbSAllen Martin }
297ff1da6fbSAllen Martin
298ff1da6fbSAllen Martin if (flags & SPI_XFER_END)
299fda6fac3SSimon Glass spi_cs_deactivate(dev);
300ff1da6fbSAllen Martin
301ff1da6fbSAllen Martin debug("spi_xfer: transfer ended. Value=%08x, status = %08x\n",
302ff1da6fbSAllen Martin tmpdin, readl(®s->status));
303ff1da6fbSAllen Martin
304ff1da6fbSAllen Martin if (ret) {
305ff1da6fbSAllen Martin printf("spi_xfer: timeout during SPI transfer, tm %d\n", ret);
306ff1da6fbSAllen Martin return -1;
307ff1da6fbSAllen Martin }
308ff1da6fbSAllen Martin
309ff1da6fbSAllen Martin return 0;
310ff1da6fbSAllen Martin }
311fda6fac3SSimon Glass
tegra20_sflash_set_speed(struct udevice * bus,uint speed)312fda6fac3SSimon Glass static int tegra20_sflash_set_speed(struct udevice *bus, uint speed)
313fda6fac3SSimon Glass {
314fda6fac3SSimon Glass struct tegra_spi_platdata *plat = bus->platdata;
315fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus);
316fda6fac3SSimon Glass
317fda6fac3SSimon Glass if (speed > plat->frequency)
318fda6fac3SSimon Glass speed = plat->frequency;
319fda6fac3SSimon Glass priv->freq = speed;
320fda6fac3SSimon Glass debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
321fda6fac3SSimon Glass
322fda6fac3SSimon Glass return 0;
323fda6fac3SSimon Glass }
324fda6fac3SSimon Glass
tegra20_sflash_set_mode(struct udevice * bus,uint mode)325fda6fac3SSimon Glass static int tegra20_sflash_set_mode(struct udevice *bus, uint mode)
326fda6fac3SSimon Glass {
327fda6fac3SSimon Glass struct tegra20_sflash_priv *priv = dev_get_priv(bus);
328fda6fac3SSimon Glass
329fda6fac3SSimon Glass priv->mode = mode;
330fda6fac3SSimon Glass debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
331fda6fac3SSimon Glass
332fda6fac3SSimon Glass return 0;
333fda6fac3SSimon Glass }
334fda6fac3SSimon Glass
335fda6fac3SSimon Glass static const struct dm_spi_ops tegra20_sflash_ops = {
336fda6fac3SSimon Glass .claim_bus = tegra20_sflash_claim_bus,
337fda6fac3SSimon Glass .xfer = tegra20_sflash_xfer,
338fda6fac3SSimon Glass .set_speed = tegra20_sflash_set_speed,
339fda6fac3SSimon Glass .set_mode = tegra20_sflash_set_mode,
340fda6fac3SSimon Glass .cs_info = tegra20_sflash_cs_info,
341fda6fac3SSimon Glass };
342fda6fac3SSimon Glass
343fda6fac3SSimon Glass static const struct udevice_id tegra20_sflash_ids[] = {
344fda6fac3SSimon Glass { .compatible = "nvidia,tegra20-sflash" },
345fda6fac3SSimon Glass { }
346fda6fac3SSimon Glass };
347fda6fac3SSimon Glass
348fda6fac3SSimon Glass U_BOOT_DRIVER(tegra20_sflash) = {
349fda6fac3SSimon Glass .name = "tegra20_sflash",
350fda6fac3SSimon Glass .id = UCLASS_SPI,
351fda6fac3SSimon Glass .of_match = tegra20_sflash_ids,
352fda6fac3SSimon Glass .ops = &tegra20_sflash_ops,
353fda6fac3SSimon Glass .ofdata_to_platdata = tegra20_sflash_ofdata_to_platdata,
354fda6fac3SSimon Glass .platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata),
355fda6fac3SSimon Glass .priv_auto_alloc_size = sizeof(struct tegra20_sflash_priv),
356fda6fac3SSimon Glass .probe = tegra20_sflash_probe,
357fda6fac3SSimon Glass };
358