16b239db4SRick Chen /*
2*ab1460f2SRick Chen * Andestech ATCSPI200 SPI controller driver.
36b239db4SRick Chen *
46b239db4SRick Chen * Copyright 2017 Andes Technology, Inc.
56b239db4SRick Chen * Author: Rick Chen (rick@andestech.com)
66b239db4SRick Chen *
76b239db4SRick Chen * SPDX-License-Identifier: GPL-2.0+
86b239db4SRick Chen */
96b239db4SRick Chen
106b239db4SRick Chen #include <clk.h>
116b239db4SRick Chen #include <common.h>
126b239db4SRick Chen #include <malloc.h>
136b239db4SRick Chen #include <spi.h>
146b239db4SRick Chen #include <asm/io.h>
156b239db4SRick Chen #include <dm.h>
166b239db4SRick Chen
176b239db4SRick Chen DECLARE_GLOBAL_DATA_PTR;
186b239db4SRick Chen
196b239db4SRick Chen #define MAX_TRANSFER_LEN 512
206b239db4SRick Chen #define CHUNK_SIZE 1
216b239db4SRick Chen #define SPI_TIMEOUT 0x100000
226b239db4SRick Chen #define SPI0_BUS 0
236b239db4SRick Chen #define SPI1_BUS 1
246b239db4SRick Chen #define SPI0_BASE 0xf0b00000
256b239db4SRick Chen #define SPI1_BASE 0xf0f00000
266b239db4SRick Chen #define NSPI_MAX_CS_NUM 1
276b239db4SRick Chen
28*ab1460f2SRick Chen struct atcspi200_spi_regs {
296b239db4SRick Chen u32 rev;
306b239db4SRick Chen u32 reserve1[3];
316b239db4SRick Chen u32 format; /* 0x10 */
326b239db4SRick Chen #define DATA_LENGTH(x) ((x-1)<<8)
336b239db4SRick Chen u32 pio;
346b239db4SRick Chen u32 reserve2[2];
356b239db4SRick Chen u32 tctrl; /* 0x20 */
366b239db4SRick Chen #define TRAMODE_OFFSET 24
376b239db4SRick Chen #define TRAMODE_MASK (0x0F<<TRAMODE_OFFSET)
386b239db4SRick Chen #define TRAMODE_WR_SYNC (0<<TRAMODE_OFFSET)
396b239db4SRick Chen #define TRAMODE_WO (1<<TRAMODE_OFFSET)
406b239db4SRick Chen #define TRAMODE_RO (2<<TRAMODE_OFFSET)
416b239db4SRick Chen #define TRAMODE_WR (3<<TRAMODE_OFFSET)
426b239db4SRick Chen #define TRAMODE_RW (4<<TRAMODE_OFFSET)
436b239db4SRick Chen #define TRAMODE_WDR (5<<TRAMODE_OFFSET)
446b239db4SRick Chen #define TRAMODE_RDW (6<<TRAMODE_OFFSET)
456b239db4SRick Chen #define TRAMODE_NONE (7<<TRAMODE_OFFSET)
466b239db4SRick Chen #define TRAMODE_DW (8<<TRAMODE_OFFSET)
476b239db4SRick Chen #define TRAMODE_DR (9<<TRAMODE_OFFSET)
486b239db4SRick Chen #define WCNT_OFFSET 12
496b239db4SRick Chen #define WCNT_MASK (0x1FF<<WCNT_OFFSET)
506b239db4SRick Chen #define RCNT_OFFSET 0
516b239db4SRick Chen #define RCNT_MASK (0x1FF<<RCNT_OFFSET)
526b239db4SRick Chen u32 cmd;
536b239db4SRick Chen u32 addr;
546b239db4SRick Chen u32 data;
556b239db4SRick Chen u32 ctrl; /* 0x30 */
566b239db4SRick Chen #define TXFTH_OFFSET 16
576b239db4SRick Chen #define RXFTH_OFFSET 8
586b239db4SRick Chen #define TXDMAEN (1<<4)
596b239db4SRick Chen #define RXDMAEN (1<<3)
606b239db4SRick Chen #define TXFRST (1<<2)
616b239db4SRick Chen #define RXFRST (1<<1)
626b239db4SRick Chen #define SPIRST (1<<0)
636b239db4SRick Chen u32 status;
646b239db4SRick Chen #define TXFFL (1<<23)
656b239db4SRick Chen #define TXEPTY (1<<22)
666b239db4SRick Chen #define TXFVE_MASK (0x1F<<16)
676b239db4SRick Chen #define RXFEM (1<<14)
686b239db4SRick Chen #define RXFVE_OFFSET (8)
696b239db4SRick Chen #define RXFVE_MASK (0x1F<<RXFVE_OFFSET)
706b239db4SRick Chen #define SPIBSY (1<<0)
716b239db4SRick Chen u32 inten;
726b239db4SRick Chen u32 intsta;
736b239db4SRick Chen u32 timing; /* 0x40 */
746b239db4SRick Chen #define SCLK_DIV_MASK 0xFF
756b239db4SRick Chen };
766b239db4SRick Chen
776b239db4SRick Chen struct nds_spi_slave {
78*ab1460f2SRick Chen volatile struct atcspi200_spi_regs *regs;
796b239db4SRick Chen int to;
806b239db4SRick Chen unsigned int freq;
816b239db4SRick Chen ulong clock;
826b239db4SRick Chen unsigned int mode;
836b239db4SRick Chen u8 num_cs;
846b239db4SRick Chen unsigned int mtiming;
856b239db4SRick Chen size_t cmd_len;
866b239db4SRick Chen u8 cmd_buf[16];
876b239db4SRick Chen size_t data_len;
886b239db4SRick Chen size_t tran_len;
896b239db4SRick Chen u8 *din;
906b239db4SRick Chen u8 *dout;
916b239db4SRick Chen unsigned int max_transfer_length;
926b239db4SRick Chen };
936b239db4SRick Chen
__atcspi200_spi_set_speed(struct nds_spi_slave * ns)94*ab1460f2SRick Chen static int __atcspi200_spi_set_speed(struct nds_spi_slave *ns)
956b239db4SRick Chen {
966b239db4SRick Chen u32 tm;
976b239db4SRick Chen u8 div;
986b239db4SRick Chen tm = ns->regs->timing;
996b239db4SRick Chen tm &= ~SCLK_DIV_MASK;
1006b239db4SRick Chen
1016b239db4SRick Chen if(ns->freq >= ns->clock)
1026b239db4SRick Chen div =0xff;
1036b239db4SRick Chen else{
1046b239db4SRick Chen for (div = 0; div < 0xff; div++) {
1056b239db4SRick Chen if (ns->freq >= ns->clock / (2 * (div + 1)))
1066b239db4SRick Chen break;
1076b239db4SRick Chen }
1086b239db4SRick Chen }
1096b239db4SRick Chen
1106b239db4SRick Chen tm |= div;
1116b239db4SRick Chen ns->regs->timing = tm;
1126b239db4SRick Chen
1136b239db4SRick Chen return 0;
1146b239db4SRick Chen
1156b239db4SRick Chen }
1166b239db4SRick Chen
__atcspi200_spi_claim_bus(struct nds_spi_slave * ns)117*ab1460f2SRick Chen static int __atcspi200_spi_claim_bus(struct nds_spi_slave *ns)
1186b239db4SRick Chen {
1196b239db4SRick Chen unsigned int format=0;
1206b239db4SRick Chen ns->regs->ctrl |= (TXFRST|RXFRST|SPIRST);
1216b239db4SRick Chen while((ns->regs->ctrl &(TXFRST|RXFRST|SPIRST))&&(ns->to--))
1226b239db4SRick Chen if(!ns->to)
1236b239db4SRick Chen return -EINVAL;
1246b239db4SRick Chen
1256b239db4SRick Chen ns->cmd_len = 0;
1266b239db4SRick Chen format = ns->mode|DATA_LENGTH(8);
1276b239db4SRick Chen ns->regs->format = format;
128*ab1460f2SRick Chen __atcspi200_spi_set_speed(ns);
1296b239db4SRick Chen
1306b239db4SRick Chen return 0;
1316b239db4SRick Chen }
1326b239db4SRick Chen
__atcspi200_spi_release_bus(struct nds_spi_slave * ns)133*ab1460f2SRick Chen static int __atcspi200_spi_release_bus(struct nds_spi_slave *ns)
1346b239db4SRick Chen {
1356b239db4SRick Chen /* do nothing */
1366b239db4SRick Chen return 0;
1376b239db4SRick Chen }
1386b239db4SRick Chen
__atcspi200_spi_start(struct nds_spi_slave * ns)139*ab1460f2SRick Chen static int __atcspi200_spi_start(struct nds_spi_slave *ns)
1406b239db4SRick Chen {
1416b239db4SRick Chen int i,olen=0;
1426b239db4SRick Chen int tc = ns->regs->tctrl;
1436b239db4SRick Chen
1446b239db4SRick Chen tc &= ~(WCNT_MASK|RCNT_MASK|TRAMODE_MASK);
1456b239db4SRick Chen if ((ns->din)&&(ns->cmd_len))
1466b239db4SRick Chen tc |= TRAMODE_WR;
1476b239db4SRick Chen else if (ns->din)
1486b239db4SRick Chen tc |= TRAMODE_RO;
1496b239db4SRick Chen else
1506b239db4SRick Chen tc |= TRAMODE_WO;
1516b239db4SRick Chen
1526b239db4SRick Chen if(ns->dout)
1536b239db4SRick Chen olen = ns->tran_len;
1546b239db4SRick Chen tc |= (ns->cmd_len+olen-1) << WCNT_OFFSET;
1556b239db4SRick Chen
1566b239db4SRick Chen if(ns->din)
1576b239db4SRick Chen tc |= (ns->tran_len-1) << RCNT_OFFSET;
1586b239db4SRick Chen
1596b239db4SRick Chen ns->regs->tctrl = tc;
1606b239db4SRick Chen ns->regs->cmd = 1;
1616b239db4SRick Chen
1626b239db4SRick Chen for (i=0;i<ns->cmd_len;i++)
1636b239db4SRick Chen ns->regs->data = ns->cmd_buf[i];
1646b239db4SRick Chen
1656b239db4SRick Chen return 0;
1666b239db4SRick Chen }
1676b239db4SRick Chen
__atcspi200_spi_stop(struct nds_spi_slave * ns)168*ab1460f2SRick Chen static int __atcspi200_spi_stop(struct nds_spi_slave *ns)
1696b239db4SRick Chen {
1706b239db4SRick Chen ns->regs->timing = ns->mtiming;
1716b239db4SRick Chen while ((ns->regs->status & SPIBSY)&&(ns->to--))
1726b239db4SRick Chen if (!ns->to)
1736b239db4SRick Chen return -EINVAL;
1746b239db4SRick Chen
1756b239db4SRick Chen return 0;
1766b239db4SRick Chen }
1776b239db4SRick Chen
__nspi_espi_tx(struct nds_spi_slave * ns,const void * dout)1786b239db4SRick Chen static void __nspi_espi_tx(struct nds_spi_slave *ns, const void *dout)
1796b239db4SRick Chen {
1806b239db4SRick Chen ns->regs->data = *(u8 *)dout;
1816b239db4SRick Chen }
1826b239db4SRick Chen
__nspi_espi_rx(struct nds_spi_slave * ns,void * din,unsigned int bytes)1836b239db4SRick Chen static int __nspi_espi_rx(struct nds_spi_slave *ns, void *din, unsigned int bytes)
1846b239db4SRick Chen {
1856b239db4SRick Chen *(u8 *)din = ns->regs->data;
1866b239db4SRick Chen return bytes;
1876b239db4SRick Chen }
1886b239db4SRick Chen
1896b239db4SRick Chen
__atcspi200_spi_xfer(struct nds_spi_slave * ns,unsigned int bitlen,const void * data_out,void * data_in,unsigned long flags)190*ab1460f2SRick Chen static int __atcspi200_spi_xfer(struct nds_spi_slave *ns,
1916b239db4SRick Chen unsigned int bitlen, const void *data_out, void *data_in,
1926b239db4SRick Chen unsigned long flags)
1936b239db4SRick Chen {
1946b239db4SRick Chen unsigned int event, rx_bytes;
1956b239db4SRick Chen const void *dout = NULL;
1966b239db4SRick Chen void *din = NULL;
1976b239db4SRick Chen int num_blks, num_chunks, max_tran_len, tran_len;
1986b239db4SRick Chen int num_bytes;
1996b239db4SRick Chen u8 *cmd_buf = ns->cmd_buf;
2006b239db4SRick Chen size_t cmd_len = ns->cmd_len;
2016b239db4SRick Chen size_t data_len = bitlen / 8;
2026b239db4SRick Chen int rf_cnt;
2036b239db4SRick Chen int ret = 0;
2046b239db4SRick Chen
2056b239db4SRick Chen max_tran_len = ns->max_transfer_length;
2066b239db4SRick Chen switch (flags) {
2076b239db4SRick Chen case SPI_XFER_BEGIN:
2086b239db4SRick Chen cmd_len = ns->cmd_len = data_len;
2096b239db4SRick Chen memcpy(cmd_buf, data_out, cmd_len);
2106b239db4SRick Chen return 0;
2116b239db4SRick Chen
2126b239db4SRick Chen case 0:
2136b239db4SRick Chen case SPI_XFER_END:
2146b239db4SRick Chen if (bitlen == 0) {
2156b239db4SRick Chen return 0;
2166b239db4SRick Chen }
2176b239db4SRick Chen ns->data_len = data_len;
2186b239db4SRick Chen ns->din = (u8 *)data_in;
2196b239db4SRick Chen ns->dout = (u8 *)data_out;
2206b239db4SRick Chen break;
2216b239db4SRick Chen
2226b239db4SRick Chen case SPI_XFER_BEGIN | SPI_XFER_END:
2236b239db4SRick Chen ns->data_len = 0;
2246b239db4SRick Chen ns->din = 0;
2256b239db4SRick Chen ns->dout = 0;
2266b239db4SRick Chen cmd_len = ns->cmd_len = data_len;
2276b239db4SRick Chen memcpy(cmd_buf, data_out, cmd_len);
2286b239db4SRick Chen data_out = 0;
2296b239db4SRick Chen data_len = 0;
230*ab1460f2SRick Chen __atcspi200_spi_start(ns);
2316b239db4SRick Chen break;
2326b239db4SRick Chen }
2336b239db4SRick Chen debug("spi_xfer: data_out %08X(%p) data_in %08X(%p) data_len %u\n",
2346b239db4SRick Chen *(uint *)data_out, data_out, *(uint *)data_in, data_in, data_len);
2356b239db4SRick Chen num_chunks = DIV_ROUND_UP(data_len, max_tran_len);
2366b239db4SRick Chen din = data_in;
2376b239db4SRick Chen dout = data_out;
2386b239db4SRick Chen while (num_chunks--) {
2396b239db4SRick Chen tran_len = min(data_len, (size_t)max_tran_len);
2406b239db4SRick Chen ns->tran_len = tran_len;
2416b239db4SRick Chen num_blks = DIV_ROUND_UP(tran_len , CHUNK_SIZE);
2426b239db4SRick Chen num_bytes = (tran_len) % CHUNK_SIZE;
2436b239db4SRick Chen if(num_bytes == 0)
2446b239db4SRick Chen num_bytes = CHUNK_SIZE;
245*ab1460f2SRick Chen __atcspi200_spi_start(ns);
2466b239db4SRick Chen
2476b239db4SRick Chen while (num_blks) {
2486b239db4SRick Chen event = in_le32(&ns->regs->status);
2496b239db4SRick Chen if ((event & TXEPTY) && (data_out)) {
2506b239db4SRick Chen __nspi_espi_tx(ns, dout);
2516b239db4SRick Chen num_blks -= CHUNK_SIZE;
2526b239db4SRick Chen dout += CHUNK_SIZE;
2536b239db4SRick Chen }
2546b239db4SRick Chen
2556b239db4SRick Chen if ((event & RXFVE_MASK) && (data_in)) {
2566b239db4SRick Chen rf_cnt = ((event & RXFVE_MASK)>> RXFVE_OFFSET);
2576b239db4SRick Chen if (rf_cnt >= CHUNK_SIZE)
2586b239db4SRick Chen rx_bytes = CHUNK_SIZE;
2596b239db4SRick Chen else if (num_blks == 1 && rf_cnt == num_bytes)
2606b239db4SRick Chen rx_bytes = num_bytes;
2616b239db4SRick Chen else
2626b239db4SRick Chen continue;
2636b239db4SRick Chen
2646b239db4SRick Chen if (__nspi_espi_rx(ns, din, rx_bytes) == rx_bytes) {
2656b239db4SRick Chen num_blks -= CHUNK_SIZE;
2666b239db4SRick Chen din = (unsigned char *)din + rx_bytes;
2676b239db4SRick Chen }
2686b239db4SRick Chen }
2696b239db4SRick Chen }
2706b239db4SRick Chen
2716b239db4SRick Chen data_len -= tran_len;
2726b239db4SRick Chen if(data_len)
2736b239db4SRick Chen {
2746b239db4SRick Chen ns->cmd_buf[1] += ((tran_len>>16)&0xff);
2756b239db4SRick Chen ns->cmd_buf[2] += ((tran_len>>8)&0xff);
2766b239db4SRick Chen ns->cmd_buf[3] += ((tran_len)&0xff);
2776b239db4SRick Chen ns->data_len = data_len;
2786b239db4SRick Chen }
279*ab1460f2SRick Chen ret = __atcspi200_spi_stop(ns);
2806b239db4SRick Chen }
281*ab1460f2SRick Chen ret = __atcspi200_spi_stop(ns);
2826b239db4SRick Chen
2836b239db4SRick Chen return ret;
2846b239db4SRick Chen }
2856b239db4SRick Chen
atcspi200_spi_set_speed(struct udevice * bus,uint max_hz)286*ab1460f2SRick Chen static int atcspi200_spi_set_speed(struct udevice *bus, uint max_hz)
2876b239db4SRick Chen {
2886b239db4SRick Chen struct nds_spi_slave *ns = dev_get_priv(bus);
2896b239db4SRick Chen
2906b239db4SRick Chen debug("%s speed %u\n", __func__, max_hz);
2916b239db4SRick Chen
2926b239db4SRick Chen ns->freq = max_hz;
293*ab1460f2SRick Chen __atcspi200_spi_set_speed(ns);
2946b239db4SRick Chen
2956b239db4SRick Chen return 0;
2966b239db4SRick Chen }
2976b239db4SRick Chen
atcspi200_spi_set_mode(struct udevice * bus,uint mode)298*ab1460f2SRick Chen static int atcspi200_spi_set_mode(struct udevice *bus, uint mode)
2996b239db4SRick Chen {
3006b239db4SRick Chen struct nds_spi_slave *ns = dev_get_priv(bus);
3016b239db4SRick Chen
3026b239db4SRick Chen debug("%s mode %u\n", __func__, mode);
3036b239db4SRick Chen ns->mode = mode;
3046b239db4SRick Chen
3056b239db4SRick Chen return 0;
3066b239db4SRick Chen }
3076b239db4SRick Chen
atcspi200_spi_claim_bus(struct udevice * dev)308*ab1460f2SRick Chen static int atcspi200_spi_claim_bus(struct udevice *dev)
3096b239db4SRick Chen {
3106b239db4SRick Chen struct dm_spi_slave_platdata *slave_plat =
3116b239db4SRick Chen dev_get_parent_platdata(dev);
3126b239db4SRick Chen struct udevice *bus = dev->parent;
3136b239db4SRick Chen struct nds_spi_slave *ns = dev_get_priv(bus);
3146b239db4SRick Chen
3156b239db4SRick Chen if (slave_plat->cs >= ns->num_cs) {
3166b239db4SRick Chen printf("Invalid SPI chipselect\n");
3176b239db4SRick Chen return -EINVAL;
3186b239db4SRick Chen }
3196b239db4SRick Chen
320*ab1460f2SRick Chen return __atcspi200_spi_claim_bus(ns);
3216b239db4SRick Chen }
3226b239db4SRick Chen
atcspi200_spi_release_bus(struct udevice * dev)323*ab1460f2SRick Chen static int atcspi200_spi_release_bus(struct udevice *dev)
3246b239db4SRick Chen {
3256b239db4SRick Chen struct nds_spi_slave *ns = dev_get_priv(dev->parent);
3266b239db4SRick Chen
327*ab1460f2SRick Chen return __atcspi200_spi_release_bus(ns);
3286b239db4SRick Chen }
3296b239db4SRick Chen
atcspi200_spi_xfer(struct udevice * dev,unsigned int bitlen,const void * dout,void * din,unsigned long flags)330*ab1460f2SRick Chen static int atcspi200_spi_xfer(struct udevice *dev, unsigned int bitlen,
3316b239db4SRick Chen const void *dout, void *din,
3326b239db4SRick Chen unsigned long flags)
3336b239db4SRick Chen {
3346b239db4SRick Chen struct udevice *bus = dev->parent;
3356b239db4SRick Chen struct nds_spi_slave *ns = dev_get_priv(bus);
3366b239db4SRick Chen
337*ab1460f2SRick Chen return __atcspi200_spi_xfer(ns, bitlen, dout, din, flags);
3386b239db4SRick Chen }
3396b239db4SRick Chen
atcspi200_spi_get_clk(struct udevice * bus)340*ab1460f2SRick Chen static int atcspi200_spi_get_clk(struct udevice *bus)
3416b239db4SRick Chen {
3426b239db4SRick Chen struct nds_spi_slave *ns = dev_get_priv(bus);
3436b239db4SRick Chen struct clk clk;
3446b239db4SRick Chen ulong clk_rate;
3456b239db4SRick Chen int ret;
3466b239db4SRick Chen
3476b239db4SRick Chen ret = clk_get_by_index(bus, 0, &clk);
3486b239db4SRick Chen if (ret)
3496b239db4SRick Chen return -EINVAL;
3506b239db4SRick Chen
3516b239db4SRick Chen clk_rate = clk_get_rate(&clk);
3526b239db4SRick Chen if (!clk_rate)
3536b239db4SRick Chen return -EINVAL;
3546b239db4SRick Chen
3556b239db4SRick Chen ns->clock = clk_rate;
3566b239db4SRick Chen clk_free(&clk);
3576b239db4SRick Chen
3586b239db4SRick Chen return 0;
3596b239db4SRick Chen }
3606b239db4SRick Chen
atcspi200_spi_probe(struct udevice * bus)361*ab1460f2SRick Chen static int atcspi200_spi_probe(struct udevice *bus)
3626b239db4SRick Chen {
3636b239db4SRick Chen struct nds_spi_slave *ns = dev_get_priv(bus);
3646b239db4SRick Chen
3656b239db4SRick Chen ns->to = SPI_TIMEOUT;
3666b239db4SRick Chen ns->max_transfer_length = MAX_TRANSFER_LEN;
3676b239db4SRick Chen ns->mtiming = ns->regs->timing;
368*ab1460f2SRick Chen atcspi200_spi_get_clk(bus);
3696b239db4SRick Chen
3706b239db4SRick Chen return 0;
3716b239db4SRick Chen }
3726b239db4SRick Chen
atcspi200_ofdata_to_platadata(struct udevice * bus)373*ab1460f2SRick Chen static int atcspi200_ofdata_to_platadata(struct udevice *bus)
3746b239db4SRick Chen {
3756b239db4SRick Chen struct nds_spi_slave *ns = dev_get_priv(bus);
3766b239db4SRick Chen const void *blob = gd->fdt_blob;
3776b239db4SRick Chen int node = dev_of_offset(bus);
3786b239db4SRick Chen
3796b239db4SRick Chen ns->regs = map_physmem(devfdt_get_addr(bus),
380*ab1460f2SRick Chen sizeof(struct atcspi200_spi_regs),
3816b239db4SRick Chen MAP_NOCACHE);
3826b239db4SRick Chen if (!ns->regs) {
3836b239db4SRick Chen printf("%s: could not map device address\n", __func__);
3846b239db4SRick Chen return -EINVAL;
3856b239db4SRick Chen }
3866b239db4SRick Chen ns->num_cs = fdtdec_get_int(blob, node, "num-cs", 4);
3876b239db4SRick Chen
3886b239db4SRick Chen return 0;
3896b239db4SRick Chen }
3906b239db4SRick Chen
391*ab1460f2SRick Chen static const struct dm_spi_ops atcspi200_spi_ops = {
392*ab1460f2SRick Chen .claim_bus = atcspi200_spi_claim_bus,
393*ab1460f2SRick Chen .release_bus = atcspi200_spi_release_bus,
394*ab1460f2SRick Chen .xfer = atcspi200_spi_xfer,
395*ab1460f2SRick Chen .set_speed = atcspi200_spi_set_speed,
396*ab1460f2SRick Chen .set_mode = atcspi200_spi_set_mode,
3976b239db4SRick Chen };
3986b239db4SRick Chen
399*ab1460f2SRick Chen static const struct udevice_id atcspi200_spi_ids[] = {
4006b239db4SRick Chen { .compatible = "andestech,atcspi200" },
4016b239db4SRick Chen { }
4026b239db4SRick Chen };
4036b239db4SRick Chen
404*ab1460f2SRick Chen U_BOOT_DRIVER(atcspi200_spi) = {
405*ab1460f2SRick Chen .name = "atcspi200_spi",
4066b239db4SRick Chen .id = UCLASS_SPI,
407*ab1460f2SRick Chen .of_match = atcspi200_spi_ids,
408*ab1460f2SRick Chen .ops = &atcspi200_spi_ops,
409*ab1460f2SRick Chen .ofdata_to_platdata = atcspi200_ofdata_to_platadata,
4106b239db4SRick Chen .priv_auto_alloc_size = sizeof(struct nds_spi_slave),
411*ab1460f2SRick Chen .probe = atcspi200_spi_probe,
4126b239db4SRick Chen };
413