xref: /OK3568_Linux_fs/u-boot/drivers/spi/kirkwood_spi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2009
3*4882a593Smuzhiyun  * Marvell Semiconductor <www.marvell.com>
4*4882a593Smuzhiyun  * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Derived from drivers/spi/mpc8xxx_spi.c
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <dm.h>
13*4882a593Smuzhiyun #include <malloc.h>
14*4882a593Smuzhiyun #include <spi.h>
15*4882a593Smuzhiyun #include <asm/io.h>
16*4882a593Smuzhiyun #include <asm/arch/soc.h>
17*4882a593Smuzhiyun #ifdef CONFIG_KIRKWOOD
18*4882a593Smuzhiyun #include <asm/arch/mpp.h>
19*4882a593Smuzhiyun #endif
20*4882a593Smuzhiyun #include <asm/arch-mvebu/spi.h>
21*4882a593Smuzhiyun 
_spi_cs_activate(struct kwspi_registers * reg)22*4882a593Smuzhiyun static void _spi_cs_activate(struct kwspi_registers *reg)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun 	setbits_le32(&reg->ctrl, KWSPI_CSN_ACT);
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun 
_spi_cs_deactivate(struct kwspi_registers * reg)27*4882a593Smuzhiyun static void _spi_cs_deactivate(struct kwspi_registers *reg)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	clrbits_le32(&reg->ctrl, KWSPI_CSN_ACT);
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun 
_spi_xfer(struct kwspi_registers * reg,unsigned int bitlen,const void * dout,void * din,unsigned long flags)32*4882a593Smuzhiyun static int _spi_xfer(struct kwspi_registers *reg, unsigned int bitlen,
33*4882a593Smuzhiyun 		     const void *dout, void *din, unsigned long flags)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	unsigned int tmpdout, tmpdin;
36*4882a593Smuzhiyun 	int tm, isread = 0;
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	debug("spi_xfer: dout %p din %p bitlen %u\n", dout, din, bitlen);
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	if (flags & SPI_XFER_BEGIN)
41*4882a593Smuzhiyun 		_spi_cs_activate(reg);
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	/*
44*4882a593Smuzhiyun 	 * handle data in 8-bit chunks
45*4882a593Smuzhiyun 	 * TBD: 2byte xfer mode to be enabled
46*4882a593Smuzhiyun 	 */
47*4882a593Smuzhiyun 	clrsetbits_le32(&reg->cfg, KWSPI_XFERLEN_MASK, KWSPI_XFERLEN_1BYTE);
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	while (bitlen > 4) {
50*4882a593Smuzhiyun 		debug("loopstart bitlen %d\n", bitlen);
51*4882a593Smuzhiyun 		tmpdout = 0;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 		/* Shift data so it's msb-justified */
54*4882a593Smuzhiyun 		if (dout)
55*4882a593Smuzhiyun 			tmpdout = *(u32 *)dout & 0xff;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 		clrbits_le32(&reg->irq_cause, KWSPI_SMEMRDIRQ);
58*4882a593Smuzhiyun 		writel(tmpdout, &reg->dout);	/* Write the data out */
59*4882a593Smuzhiyun 		debug("*** spi_xfer: ... %08x written, bitlen %d\n",
60*4882a593Smuzhiyun 		      tmpdout, bitlen);
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 		/*
63*4882a593Smuzhiyun 		 * Wait for SPI transmit to get out
64*4882a593Smuzhiyun 		 * or time out (1 second = 1000 ms)
65*4882a593Smuzhiyun 		 * The NE event must be read and cleared first
66*4882a593Smuzhiyun 		 */
67*4882a593Smuzhiyun 		for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) {
68*4882a593Smuzhiyun 			if (readl(&reg->irq_cause) & KWSPI_SMEMRDIRQ) {
69*4882a593Smuzhiyun 				isread = 1;
70*4882a593Smuzhiyun 				tmpdin = readl(&reg->din);
71*4882a593Smuzhiyun 				debug("spi_xfer: din %p..%08x read\n",
72*4882a593Smuzhiyun 				      din, tmpdin);
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 				if (din) {
75*4882a593Smuzhiyun 					*((u8 *)din) = (u8)tmpdin;
76*4882a593Smuzhiyun 					din += 1;
77*4882a593Smuzhiyun 				}
78*4882a593Smuzhiyun 				if (dout)
79*4882a593Smuzhiyun 					dout += 1;
80*4882a593Smuzhiyun 				bitlen -= 8;
81*4882a593Smuzhiyun 			}
82*4882a593Smuzhiyun 			if (isread)
83*4882a593Smuzhiyun 				break;
84*4882a593Smuzhiyun 		}
85*4882a593Smuzhiyun 		if (tm >= KWSPI_TIMEOUT)
86*4882a593Smuzhiyun 			printf("*** spi_xfer: Time out during SPI transfer\n");
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 		debug("loopend bitlen %d\n", bitlen);
89*4882a593Smuzhiyun 	}
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	if (flags & SPI_XFER_END)
92*4882a593Smuzhiyun 		_spi_cs_deactivate(reg);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	return 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun #ifndef CONFIG_DM_SPI
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun static struct kwspi_registers *spireg =
100*4882a593Smuzhiyun 	(struct kwspi_registers *)MVEBU_SPI_BASE;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun #ifdef CONFIG_KIRKWOOD
103*4882a593Smuzhiyun static u32 cs_spi_mpp_back[2];
104*4882a593Smuzhiyun #endif
105*4882a593Smuzhiyun 
spi_setup_slave(unsigned int bus,unsigned int cs,unsigned int max_hz,unsigned int mode)106*4882a593Smuzhiyun struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
107*4882a593Smuzhiyun 				unsigned int max_hz, unsigned int mode)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	struct spi_slave *slave;
110*4882a593Smuzhiyun 	u32 data;
111*4882a593Smuzhiyun #ifdef CONFIG_KIRKWOOD
112*4882a593Smuzhiyun 	static const u32 kwspi_mpp_config[2][2] = {
113*4882a593Smuzhiyun 		{ MPP0_SPI_SCn, 0 }, /* if cs == 0 */
114*4882a593Smuzhiyun 		{ MPP7_SPI_SCn, 0 } /* if cs != 0 */
115*4882a593Smuzhiyun 	};
116*4882a593Smuzhiyun #endif
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	if (!spi_cs_is_valid(bus, cs))
119*4882a593Smuzhiyun 		return NULL;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	slave = spi_alloc_slave_base(bus, cs);
122*4882a593Smuzhiyun 	if (!slave)
123*4882a593Smuzhiyun 		return NULL;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	writel(KWSPI_SMEMRDY, &spireg->ctrl);
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	/* calculate spi clock prescaller using max_hz */
128*4882a593Smuzhiyun 	data = ((CONFIG_SYS_TCLK / 2) / max_hz) + 0x10;
129*4882a593Smuzhiyun 	data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data;
130*4882a593Smuzhiyun 	data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	/* program spi clock prescaller using max_hz */
133*4882a593Smuzhiyun 	writel(KWSPI_ADRLEN_3BYTE | data, &spireg->cfg);
134*4882a593Smuzhiyun 	debug("data = 0x%08x\n", data);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	writel(KWSPI_SMEMRDIRQ, &spireg->irq_cause);
137*4882a593Smuzhiyun 	writel(KWSPI_IRQMASK, &spireg->irq_mask);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun #ifdef CONFIG_KIRKWOOD
140*4882a593Smuzhiyun 	/* program mpp registers to select  SPI_CSn */
141*4882a593Smuzhiyun 	kirkwood_mpp_conf(kwspi_mpp_config[cs ? 1 : 0], cs_spi_mpp_back);
142*4882a593Smuzhiyun #endif
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	return slave;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
spi_free_slave(struct spi_slave * slave)147*4882a593Smuzhiyun void spi_free_slave(struct spi_slave *slave)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun #ifdef CONFIG_KIRKWOOD
150*4882a593Smuzhiyun 	kirkwood_mpp_conf(cs_spi_mpp_back, NULL);
151*4882a593Smuzhiyun #endif
152*4882a593Smuzhiyun 	free(slave);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun #if defined(CONFIG_SYS_KW_SPI_MPP)
156*4882a593Smuzhiyun u32 spi_mpp_backup[4];
157*4882a593Smuzhiyun #endif
158*4882a593Smuzhiyun 
board_spi_claim_bus(struct spi_slave * slave)159*4882a593Smuzhiyun __attribute__((weak)) int board_spi_claim_bus(struct spi_slave *slave)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
spi_claim_bus(struct spi_slave * slave)164*4882a593Smuzhiyun int spi_claim_bus(struct spi_slave *slave)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun #if defined(CONFIG_SYS_KW_SPI_MPP)
167*4882a593Smuzhiyun 	u32 config;
168*4882a593Smuzhiyun 	u32 spi_mpp_config[4];
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	config = CONFIG_SYS_KW_SPI_MPP;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	if (config & MOSI_MPP6)
173*4882a593Smuzhiyun 		spi_mpp_config[0] = MPP6_SPI_MOSI;
174*4882a593Smuzhiyun 	else
175*4882a593Smuzhiyun 		spi_mpp_config[0] = MPP1_SPI_MOSI;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	if (config & SCK_MPP10)
178*4882a593Smuzhiyun 		spi_mpp_config[1] = MPP10_SPI_SCK;
179*4882a593Smuzhiyun 	else
180*4882a593Smuzhiyun 		spi_mpp_config[1] = MPP2_SPI_SCK;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	if (config & MISO_MPP11)
183*4882a593Smuzhiyun 		spi_mpp_config[2] = MPP11_SPI_MISO;
184*4882a593Smuzhiyun 	else
185*4882a593Smuzhiyun 		spi_mpp_config[2] = MPP3_SPI_MISO;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	spi_mpp_config[3] = 0;
188*4882a593Smuzhiyun 	spi_mpp_backup[3] = 0;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	/* set new spi mpp and save current mpp config */
191*4882a593Smuzhiyun 	kirkwood_mpp_conf(spi_mpp_config, spi_mpp_backup);
192*4882a593Smuzhiyun #endif
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	return board_spi_claim_bus(slave);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
board_spi_release_bus(struct spi_slave * slave)197*4882a593Smuzhiyun __attribute__((weak)) void board_spi_release_bus(struct spi_slave *slave)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun 
spi_release_bus(struct spi_slave * slave)201*4882a593Smuzhiyun void spi_release_bus(struct spi_slave *slave)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun #if defined(CONFIG_SYS_KW_SPI_MPP)
204*4882a593Smuzhiyun 	kirkwood_mpp_conf(spi_mpp_backup, NULL);
205*4882a593Smuzhiyun #endif
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	board_spi_release_bus(slave);
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun #ifndef CONFIG_SPI_CS_IS_VALID
211*4882a593Smuzhiyun /*
212*4882a593Smuzhiyun  * you can define this function board specific
213*4882a593Smuzhiyun  * define above CONFIG in board specific config file and
214*4882a593Smuzhiyun  * provide the function in board specific src file
215*4882a593Smuzhiyun  */
spi_cs_is_valid(unsigned int bus,unsigned int cs)216*4882a593Smuzhiyun int spi_cs_is_valid(unsigned int bus, unsigned int cs)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	return bus == 0 && (cs == 0 || cs == 1);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun #endif
221*4882a593Smuzhiyun 
spi_init(void)222*4882a593Smuzhiyun void spi_init(void)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun 
spi_cs_activate(struct spi_slave * slave)226*4882a593Smuzhiyun void spi_cs_activate(struct spi_slave *slave)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun 	_spi_cs_activate(spireg);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun 
spi_cs_deactivate(struct spi_slave * slave)231*4882a593Smuzhiyun void spi_cs_deactivate(struct spi_slave *slave)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	_spi_cs_deactivate(spireg);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
spi_xfer(struct spi_slave * slave,unsigned int bitlen,const void * dout,void * din,unsigned long flags)236*4882a593Smuzhiyun int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
237*4882a593Smuzhiyun 	     const void *dout, void *din, unsigned long flags)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun 	return _spi_xfer(spireg, bitlen, dout, din, flags);
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun #else
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun /* Here now the DM part */
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun struct mvebu_spi_dev {
247*4882a593Smuzhiyun 	bool			is_errata_50mhz_ac;
248*4882a593Smuzhiyun };
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun struct mvebu_spi_platdata {
251*4882a593Smuzhiyun 	struct kwspi_registers *spireg;
252*4882a593Smuzhiyun };
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun struct mvebu_spi_priv {
255*4882a593Smuzhiyun 	struct kwspi_registers *spireg;
256*4882a593Smuzhiyun };
257*4882a593Smuzhiyun 
mvebu_spi_set_speed(struct udevice * bus,uint hz)258*4882a593Smuzhiyun static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun 	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
261*4882a593Smuzhiyun 	struct kwspi_registers *reg = plat->spireg;
262*4882a593Smuzhiyun 	u32 data;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	/* calculate spi clock prescaller using max_hz */
265*4882a593Smuzhiyun 	data = ((CONFIG_SYS_TCLK / 2) / hz) + 0x10;
266*4882a593Smuzhiyun 	data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data;
267*4882a593Smuzhiyun 	data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	/* program spi clock prescaler using max_hz */
270*4882a593Smuzhiyun 	writel(KWSPI_ADRLEN_3BYTE | data, &reg->cfg);
271*4882a593Smuzhiyun 	debug("data = 0x%08x\n", data);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	return 0;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
mvebu_spi_50mhz_ac_timing_erratum(struct udevice * bus,uint mode)276*4882a593Smuzhiyun static void mvebu_spi_50mhz_ac_timing_erratum(struct udevice *bus, uint mode)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
279*4882a593Smuzhiyun 	struct kwspi_registers *reg = plat->spireg;
280*4882a593Smuzhiyun 	u32 data;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	/*
283*4882a593Smuzhiyun 	 * Erratum description: (Erratum NO. FE-9144572) The device
284*4882a593Smuzhiyun 	 * SPI interface supports frequencies of up to 50 MHz.
285*4882a593Smuzhiyun 	 * However, due to this erratum, when the device core clock is
286*4882a593Smuzhiyun 	 * 250 MHz and the SPI interfaces is configured for 50MHz SPI
287*4882a593Smuzhiyun 	 * clock and CPOL=CPHA=1 there might occur data corruption on
288*4882a593Smuzhiyun 	 * reads from the SPI device.
289*4882a593Smuzhiyun 	 * Erratum Workaround:
290*4882a593Smuzhiyun 	 * Work in one of the following configurations:
291*4882a593Smuzhiyun 	 * 1. Set CPOL=CPHA=0 in "SPI Interface Configuration
292*4882a593Smuzhiyun 	 * Register".
293*4882a593Smuzhiyun 	 * 2. Set TMISO_SAMPLE value to 0x2 in "SPI Timing Parameters 1
294*4882a593Smuzhiyun 	 * Register" before setting the interface.
295*4882a593Smuzhiyun 	 */
296*4882a593Smuzhiyun 	data = readl(&reg->timing1);
297*4882a593Smuzhiyun 	data &= ~KW_SPI_TMISO_SAMPLE_MASK;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	if (CONFIG_SYS_TCLK == 250000000 &&
300*4882a593Smuzhiyun 	    mode & SPI_CPOL &&
301*4882a593Smuzhiyun 	    mode & SPI_CPHA)
302*4882a593Smuzhiyun 		data |= KW_SPI_TMISO_SAMPLE_2;
303*4882a593Smuzhiyun 	else
304*4882a593Smuzhiyun 		data |= KW_SPI_TMISO_SAMPLE_1;
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	writel(data, &reg->timing1);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun 
mvebu_spi_set_mode(struct udevice * bus,uint mode)309*4882a593Smuzhiyun static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun 	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
312*4882a593Smuzhiyun 	struct kwspi_registers *reg = plat->spireg;
313*4882a593Smuzhiyun 	const struct mvebu_spi_dev *drvdata;
314*4882a593Smuzhiyun 	u32 data = readl(&reg->cfg);
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	data &= ~(KWSPI_CPHA | KWSPI_CPOL | KWSPI_RXLSBF | KWSPI_TXLSBF);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	if (mode & SPI_CPHA)
319*4882a593Smuzhiyun 		data |= KWSPI_CPHA;
320*4882a593Smuzhiyun 	if (mode & SPI_CPOL)
321*4882a593Smuzhiyun 		data |= KWSPI_CPOL;
322*4882a593Smuzhiyun 	if (mode & SPI_LSB_FIRST)
323*4882a593Smuzhiyun 		data |= (KWSPI_RXLSBF | KWSPI_TXLSBF);
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	writel(data, &reg->cfg);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	drvdata = (struct mvebu_spi_dev *)dev_get_driver_data(bus);
328*4882a593Smuzhiyun 	if (drvdata->is_errata_50mhz_ac)
329*4882a593Smuzhiyun 		mvebu_spi_50mhz_ac_timing_erratum(bus, mode);
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	return 0;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun 
mvebu_spi_xfer(struct udevice * dev,unsigned int bitlen,const void * dout,void * din,unsigned long flags)334*4882a593Smuzhiyun static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
335*4882a593Smuzhiyun 			  const void *dout, void *din, unsigned long flags)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	struct udevice *bus = dev->parent;
338*4882a593Smuzhiyun 	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	return _spi_xfer(plat->spireg, bitlen, dout, din, flags);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun 
mvebu_spi_claim_bus(struct udevice * dev)343*4882a593Smuzhiyun static int mvebu_spi_claim_bus(struct udevice *dev)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun 	struct udevice *bus = dev->parent;
346*4882a593Smuzhiyun 	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	/* Configure the chip-select in the CTRL register */
349*4882a593Smuzhiyun 	clrsetbits_le32(&plat->spireg->ctrl,
350*4882a593Smuzhiyun 			KWSPI_CS_MASK << KWSPI_CS_SHIFT,
351*4882a593Smuzhiyun 			spi_chip_select(dev) << KWSPI_CS_SHIFT);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	return 0;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun 
mvebu_spi_probe(struct udevice * bus)356*4882a593Smuzhiyun static int mvebu_spi_probe(struct udevice *bus)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
359*4882a593Smuzhiyun 	struct kwspi_registers *reg = plat->spireg;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	writel(KWSPI_SMEMRDY, &reg->ctrl);
362*4882a593Smuzhiyun 	writel(KWSPI_SMEMRDIRQ, &reg->irq_cause);
363*4882a593Smuzhiyun 	writel(KWSPI_IRQMASK, &reg->irq_mask);
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	return 0;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
mvebu_spi_ofdata_to_platdata(struct udevice * bus)368*4882a593Smuzhiyun static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun 	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	plat->spireg = (struct kwspi_registers *)devfdt_get_addr(bus);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	return 0;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun static const struct dm_spi_ops mvebu_spi_ops = {
378*4882a593Smuzhiyun 	.claim_bus	= mvebu_spi_claim_bus,
379*4882a593Smuzhiyun 	.xfer		= mvebu_spi_xfer,
380*4882a593Smuzhiyun 	.set_speed	= mvebu_spi_set_speed,
381*4882a593Smuzhiyun 	.set_mode	= mvebu_spi_set_mode,
382*4882a593Smuzhiyun 	/*
383*4882a593Smuzhiyun 	 * cs_info is not needed, since we require all chip selects to be
384*4882a593Smuzhiyun 	 * in the device tree explicitly
385*4882a593Smuzhiyun 	 */
386*4882a593Smuzhiyun };
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun static const struct mvebu_spi_dev armada_xp_spi_dev_data = {
389*4882a593Smuzhiyun 	.is_errata_50mhz_ac = false,
390*4882a593Smuzhiyun };
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun static const struct mvebu_spi_dev armada_375_spi_dev_data = {
393*4882a593Smuzhiyun 	.is_errata_50mhz_ac = false,
394*4882a593Smuzhiyun };
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun static const struct mvebu_spi_dev armada_380_spi_dev_data = {
397*4882a593Smuzhiyun 	.is_errata_50mhz_ac = true,
398*4882a593Smuzhiyun };
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun static const struct udevice_id mvebu_spi_ids[] = {
401*4882a593Smuzhiyun 	{
402*4882a593Smuzhiyun 		.compatible = "marvell,armada-375-spi",
403*4882a593Smuzhiyun 		.data = (ulong)&armada_375_spi_dev_data
404*4882a593Smuzhiyun 	},
405*4882a593Smuzhiyun 	{
406*4882a593Smuzhiyun 		.compatible = "marvell,armada-380-spi",
407*4882a593Smuzhiyun 		.data = (ulong)&armada_380_spi_dev_data
408*4882a593Smuzhiyun 	},
409*4882a593Smuzhiyun 	{
410*4882a593Smuzhiyun 		.compatible = "marvell,armada-xp-spi",
411*4882a593Smuzhiyun 		.data = (ulong)&armada_xp_spi_dev_data
412*4882a593Smuzhiyun 	},
413*4882a593Smuzhiyun 	{ }
414*4882a593Smuzhiyun };
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun U_BOOT_DRIVER(mvebu_spi) = {
417*4882a593Smuzhiyun 	.name = "mvebu_spi",
418*4882a593Smuzhiyun 	.id = UCLASS_SPI,
419*4882a593Smuzhiyun 	.of_match = mvebu_spi_ids,
420*4882a593Smuzhiyun 	.ops = &mvebu_spi_ops,
421*4882a593Smuzhiyun 	.ofdata_to_platdata = mvebu_spi_ofdata_to_platdata,
422*4882a593Smuzhiyun 	.platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata),
423*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct mvebu_spi_priv),
424*4882a593Smuzhiyun 	.probe = mvebu_spi_probe,
425*4882a593Smuzhiyun };
426*4882a593Smuzhiyun #endif
427