15710de45SPrafulla Wadaskar /*
25710de45SPrafulla Wadaskar * (C) Copyright 2009
35710de45SPrafulla Wadaskar * Marvell Semiconductor <www.marvell.com>
45710de45SPrafulla Wadaskar * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
55710de45SPrafulla Wadaskar *
65710de45SPrafulla Wadaskar * Derived from drivers/spi/mpc8xxx_spi.c
75710de45SPrafulla Wadaskar *
81a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
95710de45SPrafulla Wadaskar */
105710de45SPrafulla Wadaskar
115710de45SPrafulla Wadaskar #include <common.h>
129985bdb1SStefan Roese #include <dm.h>
135710de45SPrafulla Wadaskar #include <malloc.h>
145710de45SPrafulla Wadaskar #include <spi.h>
15a7efd719SLei Wen #include <asm/io.h>
163dc23f78SStefan Roese #include <asm/arch/soc.h>
174aceea20SStefan Roese #ifdef CONFIG_KIRKWOOD
185710de45SPrafulla Wadaskar #include <asm/arch/mpp.h>
194aceea20SStefan Roese #endif
203e972cb9SStefan Roese #include <asm/arch-mvebu/spi.h>
215710de45SPrafulla Wadaskar
_spi_cs_activate(struct kwspi_registers * reg)229985bdb1SStefan Roese static void _spi_cs_activate(struct kwspi_registers *reg)
239985bdb1SStefan Roese {
249985bdb1SStefan Roese setbits_le32(®->ctrl, KWSPI_CSN_ACT);
259985bdb1SStefan Roese }
269985bdb1SStefan Roese
_spi_cs_deactivate(struct kwspi_registers * reg)279985bdb1SStefan Roese static void _spi_cs_deactivate(struct kwspi_registers *reg)
289985bdb1SStefan Roese {
299985bdb1SStefan Roese clrbits_le32(®->ctrl, KWSPI_CSN_ACT);
309985bdb1SStefan Roese }
319985bdb1SStefan Roese
_spi_xfer(struct kwspi_registers * reg,unsigned int bitlen,const void * dout,void * din,unsigned long flags)329985bdb1SStefan Roese static int _spi_xfer(struct kwspi_registers *reg, unsigned int bitlen,
339985bdb1SStefan Roese const void *dout, void *din, unsigned long flags)
349985bdb1SStefan Roese {
359985bdb1SStefan Roese unsigned int tmpdout, tmpdin;
369985bdb1SStefan Roese int tm, isread = 0;
379985bdb1SStefan Roese
389985bdb1SStefan Roese debug("spi_xfer: dout %p din %p bitlen %u\n", dout, din, bitlen);
399985bdb1SStefan Roese
409985bdb1SStefan Roese if (flags & SPI_XFER_BEGIN)
419985bdb1SStefan Roese _spi_cs_activate(reg);
429985bdb1SStefan Roese
439985bdb1SStefan Roese /*
449985bdb1SStefan Roese * handle data in 8-bit chunks
459985bdb1SStefan Roese * TBD: 2byte xfer mode to be enabled
469985bdb1SStefan Roese */
479985bdb1SStefan Roese clrsetbits_le32(®->cfg, KWSPI_XFERLEN_MASK, KWSPI_XFERLEN_1BYTE);
489985bdb1SStefan Roese
499985bdb1SStefan Roese while (bitlen > 4) {
509985bdb1SStefan Roese debug("loopstart bitlen %d\n", bitlen);
519985bdb1SStefan Roese tmpdout = 0;
529985bdb1SStefan Roese
539985bdb1SStefan Roese /* Shift data so it's msb-justified */
549985bdb1SStefan Roese if (dout)
559985bdb1SStefan Roese tmpdout = *(u32 *)dout & 0xff;
569985bdb1SStefan Roese
579985bdb1SStefan Roese clrbits_le32(®->irq_cause, KWSPI_SMEMRDIRQ);
589985bdb1SStefan Roese writel(tmpdout, ®->dout); /* Write the data out */
599985bdb1SStefan Roese debug("*** spi_xfer: ... %08x written, bitlen %d\n",
609985bdb1SStefan Roese tmpdout, bitlen);
619985bdb1SStefan Roese
629985bdb1SStefan Roese /*
639985bdb1SStefan Roese * Wait for SPI transmit to get out
649985bdb1SStefan Roese * or time out (1 second = 1000 ms)
659985bdb1SStefan Roese * The NE event must be read and cleared first
669985bdb1SStefan Roese */
679985bdb1SStefan Roese for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) {
689985bdb1SStefan Roese if (readl(®->irq_cause) & KWSPI_SMEMRDIRQ) {
699985bdb1SStefan Roese isread = 1;
709985bdb1SStefan Roese tmpdin = readl(®->din);
719985bdb1SStefan Roese debug("spi_xfer: din %p..%08x read\n",
729985bdb1SStefan Roese din, tmpdin);
739985bdb1SStefan Roese
749985bdb1SStefan Roese if (din) {
759985bdb1SStefan Roese *((u8 *)din) = (u8)tmpdin;
769985bdb1SStefan Roese din += 1;
779985bdb1SStefan Roese }
789985bdb1SStefan Roese if (dout)
799985bdb1SStefan Roese dout += 1;
809985bdb1SStefan Roese bitlen -= 8;
819985bdb1SStefan Roese }
829985bdb1SStefan Roese if (isread)
839985bdb1SStefan Roese break;
849985bdb1SStefan Roese }
859985bdb1SStefan Roese if (tm >= KWSPI_TIMEOUT)
869985bdb1SStefan Roese printf("*** spi_xfer: Time out during SPI transfer\n");
879985bdb1SStefan Roese
889985bdb1SStefan Roese debug("loopend bitlen %d\n", bitlen);
899985bdb1SStefan Roese }
909985bdb1SStefan Roese
919985bdb1SStefan Roese if (flags & SPI_XFER_END)
929985bdb1SStefan Roese _spi_cs_deactivate(reg);
939985bdb1SStefan Roese
949985bdb1SStefan Roese return 0;
959985bdb1SStefan Roese }
969985bdb1SStefan Roese
979985bdb1SStefan Roese #ifndef CONFIG_DM_SPI
989985bdb1SStefan Roese
994fd7717eSStefan Roese static struct kwspi_registers *spireg =
1004fd7717eSStefan Roese (struct kwspi_registers *)MVEBU_SPI_BASE;
1015710de45SPrafulla Wadaskar
1024aceea20SStefan Roese #ifdef CONFIG_KIRKWOOD
1030299046eSStefan Roese static u32 cs_spi_mpp_back[2];
1044aceea20SStefan Roese #endif
105ca880679SValentin Longchamp
spi_setup_slave(unsigned int bus,unsigned int cs,unsigned int max_hz,unsigned int mode)1065710de45SPrafulla Wadaskar struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
1075710de45SPrafulla Wadaskar unsigned int max_hz, unsigned int mode)
1085710de45SPrafulla Wadaskar {
1095710de45SPrafulla Wadaskar struct spi_slave *slave;
1105710de45SPrafulla Wadaskar u32 data;
1114aceea20SStefan Roese #ifdef CONFIG_KIRKWOOD
1129d86f0c3SAlbert ARIBAUD static const u32 kwspi_mpp_config[2][2] = {
1139d86f0c3SAlbert ARIBAUD { MPP0_SPI_SCn, 0 }, /* if cs == 0 */
1149d86f0c3SAlbert ARIBAUD { MPP7_SPI_SCn, 0 } /* if cs != 0 */
1159d86f0c3SAlbert ARIBAUD };
1164aceea20SStefan Roese #endif
1175710de45SPrafulla Wadaskar
1185710de45SPrafulla Wadaskar if (!spi_cs_is_valid(bus, cs))
1195710de45SPrafulla Wadaskar return NULL;
1205710de45SPrafulla Wadaskar
121d3504feeSSimon Glass slave = spi_alloc_slave_base(bus, cs);
1225710de45SPrafulla Wadaskar if (!slave)
1235710de45SPrafulla Wadaskar return NULL;
1245710de45SPrafulla Wadaskar
125c032174fSStefan Roese writel(KWSPI_SMEMRDY, &spireg->ctrl);
1265710de45SPrafulla Wadaskar
1275710de45SPrafulla Wadaskar /* calculate spi clock prescaller using max_hz */
1288203b201SValentin Longchamp data = ((CONFIG_SYS_TCLK / 2) / max_hz) + 0x10;
1298203b201SValentin Longchamp data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data;
1308203b201SValentin Longchamp data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data;
1315710de45SPrafulla Wadaskar
1325710de45SPrafulla Wadaskar /* program spi clock prescaller using max_hz */
1335710de45SPrafulla Wadaskar writel(KWSPI_ADRLEN_3BYTE | data, &spireg->cfg);
1345710de45SPrafulla Wadaskar debug("data = 0x%08x\n", data);
1355710de45SPrafulla Wadaskar
1365710de45SPrafulla Wadaskar writel(KWSPI_SMEMRDIRQ, &spireg->irq_cause);
1373f843551SIan Campbell writel(KWSPI_IRQMASK, &spireg->irq_mask);
1385710de45SPrafulla Wadaskar
1394aceea20SStefan Roese #ifdef CONFIG_KIRKWOOD
1405710de45SPrafulla Wadaskar /* program mpp registers to select SPI_CSn */
1419d86f0c3SAlbert ARIBAUD kirkwood_mpp_conf(kwspi_mpp_config[cs ? 1 : 0], cs_spi_mpp_back);
1424aceea20SStefan Roese #endif
1435710de45SPrafulla Wadaskar
1445710de45SPrafulla Wadaskar return slave;
1455710de45SPrafulla Wadaskar }
1465710de45SPrafulla Wadaskar
spi_free_slave(struct spi_slave * slave)1475710de45SPrafulla Wadaskar void spi_free_slave(struct spi_slave *slave)
1485710de45SPrafulla Wadaskar {
1494aceea20SStefan Roese #ifdef CONFIG_KIRKWOOD
150ca880679SValentin Longchamp kirkwood_mpp_conf(cs_spi_mpp_back, NULL);
1514aceea20SStefan Roese #endif
1525710de45SPrafulla Wadaskar free(slave);
1535710de45SPrafulla Wadaskar }
1545710de45SPrafulla Wadaskar
155ac486e3bSValentin Longchamp #if defined(CONFIG_SYS_KW_SPI_MPP)
156ac486e3bSValentin Longchamp u32 spi_mpp_backup[4];
157ac486e3bSValentin Longchamp #endif
158ac486e3bSValentin Longchamp
board_spi_claim_bus(struct spi_slave * slave)15924934feaSValentin Longchamp __attribute__((weak)) int board_spi_claim_bus(struct spi_slave *slave)
16024934feaSValentin Longchamp {
16124934feaSValentin Longchamp return 0;
16224934feaSValentin Longchamp }
16324934feaSValentin Longchamp
spi_claim_bus(struct spi_slave * slave)1645710de45SPrafulla Wadaskar int spi_claim_bus(struct spi_slave *slave)
1655710de45SPrafulla Wadaskar {
166ac486e3bSValentin Longchamp #if defined(CONFIG_SYS_KW_SPI_MPP)
167ac486e3bSValentin Longchamp u32 config;
168ac486e3bSValentin Longchamp u32 spi_mpp_config[4];
169ac486e3bSValentin Longchamp
170ac486e3bSValentin Longchamp config = CONFIG_SYS_KW_SPI_MPP;
171ac486e3bSValentin Longchamp
172ac486e3bSValentin Longchamp if (config & MOSI_MPP6)
173ac486e3bSValentin Longchamp spi_mpp_config[0] = MPP6_SPI_MOSI;
174ac486e3bSValentin Longchamp else
175ac486e3bSValentin Longchamp spi_mpp_config[0] = MPP1_SPI_MOSI;
176ac486e3bSValentin Longchamp
177ac486e3bSValentin Longchamp if (config & SCK_MPP10)
178ac486e3bSValentin Longchamp spi_mpp_config[1] = MPP10_SPI_SCK;
179ac486e3bSValentin Longchamp else
180ac486e3bSValentin Longchamp spi_mpp_config[1] = MPP2_SPI_SCK;
181ac486e3bSValentin Longchamp
182ac486e3bSValentin Longchamp if (config & MISO_MPP11)
183ac486e3bSValentin Longchamp spi_mpp_config[2] = MPP11_SPI_MISO;
184ac486e3bSValentin Longchamp else
185ac486e3bSValentin Longchamp spi_mpp_config[2] = MPP3_SPI_MISO;
186ac486e3bSValentin Longchamp
187ac486e3bSValentin Longchamp spi_mpp_config[3] = 0;
188ac486e3bSValentin Longchamp spi_mpp_backup[3] = 0;
189ac486e3bSValentin Longchamp
190ac486e3bSValentin Longchamp /* set new spi mpp and save current mpp config */
191ac486e3bSValentin Longchamp kirkwood_mpp_conf(spi_mpp_config, spi_mpp_backup);
192ac486e3bSValentin Longchamp #endif
193ac486e3bSValentin Longchamp
19424934feaSValentin Longchamp return board_spi_claim_bus(slave);
19524934feaSValentin Longchamp }
19624934feaSValentin Longchamp
board_spi_release_bus(struct spi_slave * slave)19724934feaSValentin Longchamp __attribute__((weak)) void board_spi_release_bus(struct spi_slave *slave)
19824934feaSValentin Longchamp {
1995710de45SPrafulla Wadaskar }
2005710de45SPrafulla Wadaskar
spi_release_bus(struct spi_slave * slave)2015710de45SPrafulla Wadaskar void spi_release_bus(struct spi_slave *slave)
2025710de45SPrafulla Wadaskar {
203ac486e3bSValentin Longchamp #if defined(CONFIG_SYS_KW_SPI_MPP)
204ac486e3bSValentin Longchamp kirkwood_mpp_conf(spi_mpp_backup, NULL);
205ac486e3bSValentin Longchamp #endif
20624934feaSValentin Longchamp
20724934feaSValentin Longchamp board_spi_release_bus(slave);
2085710de45SPrafulla Wadaskar }
2095710de45SPrafulla Wadaskar
2105710de45SPrafulla Wadaskar #ifndef CONFIG_SPI_CS_IS_VALID
2115710de45SPrafulla Wadaskar /*
2125710de45SPrafulla Wadaskar * you can define this function board specific
2135710de45SPrafulla Wadaskar * define above CONFIG in board specific config file and
2145710de45SPrafulla Wadaskar * provide the function in board specific src file
2155710de45SPrafulla Wadaskar */
spi_cs_is_valid(unsigned int bus,unsigned int cs)2165710de45SPrafulla Wadaskar int spi_cs_is_valid(unsigned int bus, unsigned int cs)
2175710de45SPrafulla Wadaskar {
218bf9b86dcSStefan Roese return bus == 0 && (cs == 0 || cs == 1);
2195710de45SPrafulla Wadaskar }
2205710de45SPrafulla Wadaskar #endif
2215710de45SPrafulla Wadaskar
spi_init(void)222efa4e43aSMichael Walle void spi_init(void)
223efa4e43aSMichael Walle {
224efa4e43aSMichael Walle }
225efa4e43aSMichael Walle
spi_cs_activate(struct spi_slave * slave)2265710de45SPrafulla Wadaskar void spi_cs_activate(struct spi_slave *slave)
2275710de45SPrafulla Wadaskar {
22818dd3b22SStefan Roese _spi_cs_activate(spireg);
2295710de45SPrafulla Wadaskar }
2305710de45SPrafulla Wadaskar
spi_cs_deactivate(struct spi_slave * slave)2315710de45SPrafulla Wadaskar void spi_cs_deactivate(struct spi_slave *slave)
2325710de45SPrafulla Wadaskar {
23318dd3b22SStefan Roese _spi_cs_deactivate(spireg);
2345710de45SPrafulla Wadaskar }
2355710de45SPrafulla Wadaskar
spi_xfer(struct spi_slave * slave,unsigned int bitlen,const void * dout,void * din,unsigned long flags)23618dd3b22SStefan Roese int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
23718dd3b22SStefan Roese const void *dout, void *din, unsigned long flags)
23818dd3b22SStefan Roese {
23918dd3b22SStefan Roese return _spi_xfer(spireg, bitlen, dout, din, flags);
24018dd3b22SStefan Roese }
2419985bdb1SStefan Roese
2429985bdb1SStefan Roese #else
2439985bdb1SStefan Roese
2449985bdb1SStefan Roese /* Here now the DM part */
2459985bdb1SStefan Roese
246*ab86434dSChris Packham struct mvebu_spi_dev {
247*ab86434dSChris Packham bool is_errata_50mhz_ac;
248*ab86434dSChris Packham };
249*ab86434dSChris Packham
2509985bdb1SStefan Roese struct mvebu_spi_platdata {
2519985bdb1SStefan Roese struct kwspi_registers *spireg;
2529985bdb1SStefan Roese };
2539985bdb1SStefan Roese
2549985bdb1SStefan Roese struct mvebu_spi_priv {
2559985bdb1SStefan Roese struct kwspi_registers *spireg;
2569985bdb1SStefan Roese };
2579985bdb1SStefan Roese
mvebu_spi_set_speed(struct udevice * bus,uint hz)2589985bdb1SStefan Roese static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
2599985bdb1SStefan Roese {
2609985bdb1SStefan Roese struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
2619985bdb1SStefan Roese struct kwspi_registers *reg = plat->spireg;
2629985bdb1SStefan Roese u32 data;
2639985bdb1SStefan Roese
2649985bdb1SStefan Roese /* calculate spi clock prescaller using max_hz */
2659985bdb1SStefan Roese data = ((CONFIG_SYS_TCLK / 2) / hz) + 0x10;
2669985bdb1SStefan Roese data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data;
2679985bdb1SStefan Roese data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data;
2689985bdb1SStefan Roese
2699985bdb1SStefan Roese /* program spi clock prescaler using max_hz */
2709985bdb1SStefan Roese writel(KWSPI_ADRLEN_3BYTE | data, ®->cfg);
2719985bdb1SStefan Roese debug("data = 0x%08x\n", data);
2729985bdb1SStefan Roese
2739985bdb1SStefan Roese return 0;
2749985bdb1SStefan Roese }
2759985bdb1SStefan Roese
mvebu_spi_50mhz_ac_timing_erratum(struct udevice * bus,uint mode)276*ab86434dSChris Packham static void mvebu_spi_50mhz_ac_timing_erratum(struct udevice *bus, uint mode)
277*ab86434dSChris Packham {
278*ab86434dSChris Packham struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
279*ab86434dSChris Packham struct kwspi_registers *reg = plat->spireg;
280*ab86434dSChris Packham u32 data;
281*ab86434dSChris Packham
282*ab86434dSChris Packham /*
283*ab86434dSChris Packham * Erratum description: (Erratum NO. FE-9144572) The device
284*ab86434dSChris Packham * SPI interface supports frequencies of up to 50 MHz.
285*ab86434dSChris Packham * However, due to this erratum, when the device core clock is
286*ab86434dSChris Packham * 250 MHz and the SPI interfaces is configured for 50MHz SPI
287*ab86434dSChris Packham * clock and CPOL=CPHA=1 there might occur data corruption on
288*ab86434dSChris Packham * reads from the SPI device.
289*ab86434dSChris Packham * Erratum Workaround:
290*ab86434dSChris Packham * Work in one of the following configurations:
291*ab86434dSChris Packham * 1. Set CPOL=CPHA=0 in "SPI Interface Configuration
292*ab86434dSChris Packham * Register".
293*ab86434dSChris Packham * 2. Set TMISO_SAMPLE value to 0x2 in "SPI Timing Parameters 1
294*ab86434dSChris Packham * Register" before setting the interface.
295*ab86434dSChris Packham */
296*ab86434dSChris Packham data = readl(®->timing1);
297*ab86434dSChris Packham data &= ~KW_SPI_TMISO_SAMPLE_MASK;
298*ab86434dSChris Packham
299*ab86434dSChris Packham if (CONFIG_SYS_TCLK == 250000000 &&
300*ab86434dSChris Packham mode & SPI_CPOL &&
301*ab86434dSChris Packham mode & SPI_CPHA)
302*ab86434dSChris Packham data |= KW_SPI_TMISO_SAMPLE_2;
303*ab86434dSChris Packham else
304*ab86434dSChris Packham data |= KW_SPI_TMISO_SAMPLE_1;
305*ab86434dSChris Packham
306*ab86434dSChris Packham writel(data, ®->timing1);
307*ab86434dSChris Packham }
308*ab86434dSChris Packham
mvebu_spi_set_mode(struct udevice * bus,uint mode)3099985bdb1SStefan Roese static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
3109985bdb1SStefan Roese {
311ebfa18cbSChris Packham struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
312ebfa18cbSChris Packham struct kwspi_registers *reg = plat->spireg;
313*ab86434dSChris Packham const struct mvebu_spi_dev *drvdata;
314ebfa18cbSChris Packham u32 data = readl(®->cfg);
315ebfa18cbSChris Packham
316ebfa18cbSChris Packham data &= ~(KWSPI_CPHA | KWSPI_CPOL | KWSPI_RXLSBF | KWSPI_TXLSBF);
317ebfa18cbSChris Packham
318ebfa18cbSChris Packham if (mode & SPI_CPHA)
319ebfa18cbSChris Packham data |= KWSPI_CPHA;
320ebfa18cbSChris Packham if (mode & SPI_CPOL)
321ebfa18cbSChris Packham data |= KWSPI_CPOL;
322ebfa18cbSChris Packham if (mode & SPI_LSB_FIRST)
323ebfa18cbSChris Packham data |= (KWSPI_RXLSBF | KWSPI_TXLSBF);
324ebfa18cbSChris Packham
325ebfa18cbSChris Packham writel(data, ®->cfg);
326ebfa18cbSChris Packham
327*ab86434dSChris Packham drvdata = (struct mvebu_spi_dev *)dev_get_driver_data(bus);
328*ab86434dSChris Packham if (drvdata->is_errata_50mhz_ac)
329*ab86434dSChris Packham mvebu_spi_50mhz_ac_timing_erratum(bus, mode);
330*ab86434dSChris Packham
3319985bdb1SStefan Roese return 0;
3329985bdb1SStefan Roese }
3339985bdb1SStefan Roese
mvebu_spi_xfer(struct udevice * dev,unsigned int bitlen,const void * dout,void * din,unsigned long flags)3349985bdb1SStefan Roese static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
3359985bdb1SStefan Roese const void *dout, void *din, unsigned long flags)
3369985bdb1SStefan Roese {
3379985bdb1SStefan Roese struct udevice *bus = dev->parent;
3389985bdb1SStefan Roese struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
3399985bdb1SStefan Roese
3409985bdb1SStefan Roese return _spi_xfer(plat->spireg, bitlen, dout, din, flags);
3419985bdb1SStefan Roese }
3429985bdb1SStefan Roese
mvebu_spi_claim_bus(struct udevice * dev)3439fc56631SStefan Roese static int mvebu_spi_claim_bus(struct udevice *dev)
3449fc56631SStefan Roese {
3459fc56631SStefan Roese struct udevice *bus = dev->parent;
3469fc56631SStefan Roese struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
3479fc56631SStefan Roese
3489fc56631SStefan Roese /* Configure the chip-select in the CTRL register */
3499fc56631SStefan Roese clrsetbits_le32(&plat->spireg->ctrl,
3509fc56631SStefan Roese KWSPI_CS_MASK << KWSPI_CS_SHIFT,
3519fc56631SStefan Roese spi_chip_select(dev) << KWSPI_CS_SHIFT);
3529fc56631SStefan Roese
3539fc56631SStefan Roese return 0;
3549fc56631SStefan Roese }
3559fc56631SStefan Roese
mvebu_spi_probe(struct udevice * bus)3569985bdb1SStefan Roese static int mvebu_spi_probe(struct udevice *bus)
3579985bdb1SStefan Roese {
3589985bdb1SStefan Roese struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
3599985bdb1SStefan Roese struct kwspi_registers *reg = plat->spireg;
3609985bdb1SStefan Roese
3619985bdb1SStefan Roese writel(KWSPI_SMEMRDY, ®->ctrl);
3629985bdb1SStefan Roese writel(KWSPI_SMEMRDIRQ, ®->irq_cause);
3639985bdb1SStefan Roese writel(KWSPI_IRQMASK, ®->irq_mask);
3649985bdb1SStefan Roese
3659985bdb1SStefan Roese return 0;
3669985bdb1SStefan Roese }
3679985bdb1SStefan Roese
mvebu_spi_ofdata_to_platdata(struct udevice * bus)3689985bdb1SStefan Roese static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
3699985bdb1SStefan Roese {
3709985bdb1SStefan Roese struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
3719985bdb1SStefan Roese
372a821c4afSSimon Glass plat->spireg = (struct kwspi_registers *)devfdt_get_addr(bus);
3739985bdb1SStefan Roese
3749985bdb1SStefan Roese return 0;
3759985bdb1SStefan Roese }
3769985bdb1SStefan Roese
3779985bdb1SStefan Roese static const struct dm_spi_ops mvebu_spi_ops = {
3789fc56631SStefan Roese .claim_bus = mvebu_spi_claim_bus,
3799985bdb1SStefan Roese .xfer = mvebu_spi_xfer,
3809985bdb1SStefan Roese .set_speed = mvebu_spi_set_speed,
3819985bdb1SStefan Roese .set_mode = mvebu_spi_set_mode,
3829985bdb1SStefan Roese /*
3839985bdb1SStefan Roese * cs_info is not needed, since we require all chip selects to be
3849985bdb1SStefan Roese * in the device tree explicitly
3859985bdb1SStefan Roese */
3869985bdb1SStefan Roese };
3879985bdb1SStefan Roese
388*ab86434dSChris Packham static const struct mvebu_spi_dev armada_xp_spi_dev_data = {
389*ab86434dSChris Packham .is_errata_50mhz_ac = false,
390*ab86434dSChris Packham };
391*ab86434dSChris Packham
392*ab86434dSChris Packham static const struct mvebu_spi_dev armada_375_spi_dev_data = {
393*ab86434dSChris Packham .is_errata_50mhz_ac = false,
394*ab86434dSChris Packham };
395*ab86434dSChris Packham
396*ab86434dSChris Packham static const struct mvebu_spi_dev armada_380_spi_dev_data = {
397*ab86434dSChris Packham .is_errata_50mhz_ac = true,
398*ab86434dSChris Packham };
399*ab86434dSChris Packham
4009985bdb1SStefan Roese static const struct udevice_id mvebu_spi_ids[] = {
401*ab86434dSChris Packham {
402*ab86434dSChris Packham .compatible = "marvell,armada-375-spi",
403*ab86434dSChris Packham .data = (ulong)&armada_375_spi_dev_data
404*ab86434dSChris Packham },
405*ab86434dSChris Packham {
406*ab86434dSChris Packham .compatible = "marvell,armada-380-spi",
407*ab86434dSChris Packham .data = (ulong)&armada_380_spi_dev_data
408*ab86434dSChris Packham },
409*ab86434dSChris Packham {
410*ab86434dSChris Packham .compatible = "marvell,armada-xp-spi",
411*ab86434dSChris Packham .data = (ulong)&armada_xp_spi_dev_data
412*ab86434dSChris Packham },
4139985bdb1SStefan Roese { }
4149985bdb1SStefan Roese };
4159985bdb1SStefan Roese
4169985bdb1SStefan Roese U_BOOT_DRIVER(mvebu_spi) = {
4179985bdb1SStefan Roese .name = "mvebu_spi",
4189985bdb1SStefan Roese .id = UCLASS_SPI,
4199985bdb1SStefan Roese .of_match = mvebu_spi_ids,
4209985bdb1SStefan Roese .ops = &mvebu_spi_ops,
4219985bdb1SStefan Roese .ofdata_to_platdata = mvebu_spi_ofdata_to_platdata,
4229985bdb1SStefan Roese .platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata),
4239985bdb1SStefan Roese .priv_auto_alloc_size = sizeof(struct mvebu_spi_priv),
4249985bdb1SStefan Roese .probe = mvebu_spi_probe,
4259985bdb1SStefan Roese };
4269985bdb1SStefan Roese #endif
427