xref: /openbmc/u-boot/drivers/spi/omap3_spi.c (revision dfe6f4d6)
1 /*
2  * Copyright (C) 2010 Dirk Behme <dirk.behme@googlemail.com>
3  *
4  * Driver for McSPI controller on OMAP3. Based on davinci_spi.c
5  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
6  *
7  * Copyright (C) 2007 Atmel Corporation
8  *
9  * Parts taken from linux/drivers/spi/omap2_mcspi.c
10  * Copyright (C) 2005, 2006 Nokia Corporation
11  *
12  * Modified by Ruslan Araslanov <ruslan.araslanov@vitecmm.com>
13  *
14  * SPDX-License-Identifier:	GPL-2.0+
15  */
16 
17 #include <common.h>
18 #include <spi.h>
19 #include <malloc.h>
20 #include <asm/io.h>
21 #include "omap3_spi.h"
22 
23 #define SPI_WAIT_TIMEOUT 3000000
24 
25 static void spi_reset(struct omap3_spi_slave *ds)
26 {
27 	unsigned int tmp;
28 
29 	writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &ds->regs->sysconfig);
30 	do {
31 		tmp = readl(&ds->regs->sysstatus);
32 	} while (!(tmp & OMAP3_MCSPI_SYSSTATUS_RESETDONE));
33 
34 	writel(OMAP3_MCSPI_SYSCONFIG_AUTOIDLE |
35 				 OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP |
36 				 OMAP3_MCSPI_SYSCONFIG_SMARTIDLE,
37 				 &ds->regs->sysconfig);
38 
39 	writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &ds->regs->wakeupenable);
40 }
41 
42 static void omap3_spi_write_chconf(struct omap3_spi_slave *ds, int val)
43 {
44 	writel(val, &ds->regs->channel[ds->slave.cs].chconf);
45 	/* Flash post writes to make immediate effect */
46 	readl(&ds->regs->channel[ds->slave.cs].chconf);
47 }
48 
49 static void omap3_spi_set_enable(struct omap3_spi_slave *ds, int enable)
50 {
51 	writel(enable, &ds->regs->channel[ds->slave.cs].chctrl);
52 	/* Flash post writes to make immediate effect */
53 	readl(&ds->regs->channel[ds->slave.cs].chctrl);
54 }
55 
56 void spi_init()
57 {
58 	/* do nothing */
59 }
60 
61 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
62 				  unsigned int max_hz, unsigned int mode)
63 {
64 	struct omap3_spi_slave	*ds;
65 	struct mcspi *regs;
66 
67 	/*
68 	 * OMAP3 McSPI (MultiChannel SPI) has 4 busses (modules)
69 	 * with different number of chip selects (CS, channels):
70 	 * McSPI1 has 4 CS (bus 0, cs 0 - 3)
71 	 * McSPI2 has 2 CS (bus 1, cs 0 - 1)
72 	 * McSPI3 has 2 CS (bus 2, cs 0 - 1)
73 	 * McSPI4 has 1 CS (bus 3, cs 0)
74 	 */
75 
76 	switch (bus) {
77 	case 0:
78 		regs = (struct mcspi *)OMAP3_MCSPI1_BASE;
79 		break;
80 #ifdef OMAP3_MCSPI2_BASE
81 	case 1:
82 		regs = (struct mcspi *)OMAP3_MCSPI2_BASE;
83 		break;
84 #endif
85 #ifdef OMAP3_MCSPI3_BASE
86 	case 2:
87 		regs = (struct mcspi *)OMAP3_MCSPI3_BASE;
88 		break;
89 #endif
90 #ifdef OMAP3_MCSPI4_BASE
91 	case 3:
92 		regs = (struct mcspi *)OMAP3_MCSPI4_BASE;
93 		break;
94 #endif
95 	default:
96 		printf("SPI error: unsupported bus %i. \
97 			Supported busses 0 - 3\n", bus);
98 		return NULL;
99 	}
100 
101 	if (((bus == 0) && (cs > 3)) ||
102 			((bus == 1) && (cs > 1)) ||
103 			((bus == 2) && (cs > 1)) ||
104 			((bus == 3) && (cs > 0))) {
105 		printf("SPI error: unsupported chip select %i \
106 			on bus %i\n", cs, bus);
107 		return NULL;
108 	}
109 
110 	if (max_hz > OMAP3_MCSPI_MAX_FREQ) {
111 		printf("SPI error: unsupported frequency %i Hz. \
112 			Max frequency is 48 Mhz\n", max_hz);
113 		return NULL;
114 	}
115 
116 	if (mode > SPI_MODE_3) {
117 		printf("SPI error: unsupported SPI mode %i\n", mode);
118 		return NULL;
119 	}
120 
121 	ds = spi_alloc_slave(struct omap3_spi_slave, bus, cs);
122 	if (!ds) {
123 		printf("SPI error: malloc of SPI structure failed\n");
124 		return NULL;
125 	}
126 
127 	ds->regs = regs;
128 	ds->freq = max_hz;
129 	ds->mode = mode;
130 
131 	return &ds->slave;
132 }
133 
134 void spi_free_slave(struct spi_slave *slave)
135 {
136 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
137 
138 	free(ds);
139 }
140 
141 int spi_claim_bus(struct spi_slave *slave)
142 {
143 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
144 	unsigned int conf, div = 0;
145 
146 	/* McSPI global module configuration */
147 
148 	/*
149 	 * setup when switching from (reset default) slave mode
150 	 * to single-channel master mode
151 	 */
152 	spi_reset(ds);
153 	conf = readl(&ds->regs->modulctrl);
154 	conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS);
155 	conf |= OMAP3_MCSPI_MODULCTRL_SINGLE;
156 	writel(conf, &ds->regs->modulctrl);
157 
158 	/* McSPI individual channel configuration */
159 
160 	/* Calculate clock divisor. Valid range: 0x0 - 0xC ( /1 - /4096 ) */
161 	if (ds->freq) {
162 		while (div <= 0xC && (OMAP3_MCSPI_MAX_FREQ / (1 << div))
163 					 > ds->freq)
164 			div++;
165 	} else
166 		div = 0xC;
167 
168 	conf = readl(&ds->regs->channel[ds->slave.cs].chconf);
169 
170 	/* standard 4-wire master mode:	SCK, MOSI/out, MISO/in, nCS
171 	 * REVISIT: this controller could support SPI_3WIRE mode.
172 	 */
173 #ifdef CONFIG_OMAP3_SPI_D0_D1_SWAPPED
174 	/*
175 	 * Some boards have D0 wired as MOSI / D1 as MISO instead of
176 	 * The normal D0 as MISO / D1 as MOSI.
177 	 */
178 	conf &= ~OMAP3_MCSPI_CHCONF_DPE0;
179 	conf |= OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1;
180 #else
181 	conf &= ~(OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1);
182 	conf |= OMAP3_MCSPI_CHCONF_DPE0;
183 #endif
184 
185 	/* wordlength */
186 	conf &= ~OMAP3_MCSPI_CHCONF_WL_MASK;
187 	conf |= (ds->slave.wordlen - 1) << 7;
188 
189 	/* set chipselect polarity; manage with FORCE */
190 	if (!(ds->mode & SPI_CS_HIGH))
191 		conf |= OMAP3_MCSPI_CHCONF_EPOL; /* active-low; normal */
192 	else
193 		conf &= ~OMAP3_MCSPI_CHCONF_EPOL;
194 
195 	/* set clock divisor */
196 	conf &= ~OMAP3_MCSPI_CHCONF_CLKD_MASK;
197 	conf |= div << 2;
198 
199 	/* set SPI mode 0..3 */
200 	if (ds->mode & SPI_CPOL)
201 		conf |= OMAP3_MCSPI_CHCONF_POL;
202 	else
203 		conf &= ~OMAP3_MCSPI_CHCONF_POL;
204 	if (ds->mode & SPI_CPHA)
205 		conf |= OMAP3_MCSPI_CHCONF_PHA;
206 	else
207 		conf &= ~OMAP3_MCSPI_CHCONF_PHA;
208 
209 	/* Transmit & receive mode */
210 	conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
211 
212 	omap3_spi_write_chconf(ds,conf);
213 
214 	return 0;
215 }
216 
217 void spi_release_bus(struct spi_slave *slave)
218 {
219 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
220 
221 	/* Reset the SPI hardware */
222 	spi_reset(ds);
223 }
224 
225 int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp,
226 		    unsigned long flags)
227 {
228 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
229 	int i;
230 	int timeout = SPI_WAIT_TIMEOUT;
231 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
232 
233 	/* Enable the channel */
234 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
235 
236 	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
237 	chconf |= (ds->slave.wordlen - 1) << 7;
238 	chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
239 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
240 	omap3_spi_write_chconf(ds,chconf);
241 
242 	for (i = 0; i < len; i++) {
243 		/* wait till TX register is empty (TXS == 1) */
244 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
245 			 OMAP3_MCSPI_CHSTAT_TXS)) {
246 			if (--timeout <= 0) {
247 				printf("SPI TXS timed out, status=0x%08x\n",
248 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
249 				return -1;
250 			}
251 		}
252 		/* Write the data */
253 		unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx;
254 		if (ds->slave.wordlen > 16)
255 			writel(((u32 *)txp)[i], tx);
256 		else if (ds->slave.wordlen > 8)
257 			writel(((u16 *)txp)[i], tx);
258 		else
259 			writel(((u8 *)txp)[i], tx);
260 	}
261 
262 	/* wait to finish of transfer */
263 	while ((readl(&ds->regs->channel[ds->slave.cs].chstat) &
264 			 (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS)) !=
265 			 (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS));
266 
267 	/* Disable the channel otherwise the next immediate RX will get affected */
268 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
269 
270 	if (flags & SPI_XFER_END) {
271 
272 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
273 		omap3_spi_write_chconf(ds,chconf);
274 	}
275 	return 0;
276 }
277 
278 int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp,
279 		   unsigned long flags)
280 {
281 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
282 	int i;
283 	int timeout = SPI_WAIT_TIMEOUT;
284 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
285 
286 	/* Enable the channel */
287 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
288 
289 	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
290 	chconf |= (ds->slave.wordlen - 1) << 7;
291 	chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
292 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
293 	omap3_spi_write_chconf(ds,chconf);
294 
295 	writel(0, &ds->regs->channel[ds->slave.cs].tx);
296 
297 	for (i = 0; i < len; i++) {
298 		/* Wait till RX register contains data (RXS == 1) */
299 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
300 			 OMAP3_MCSPI_CHSTAT_RXS)) {
301 			if (--timeout <= 0) {
302 				printf("SPI RXS timed out, status=0x%08x\n",
303 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
304 				return -1;
305 			}
306 		}
307 
308 		/* Disable the channel to prevent furher receiving */
309 		if(i == (len - 1))
310 			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
311 
312 		/* Read the data */
313 		unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
314 		if (ds->slave.wordlen > 16)
315 			((u32 *)rxp)[i] = readl(rx);
316 		else if (ds->slave.wordlen > 8)
317 			((u16 *)rxp)[i] = (u16)readl(rx);
318 		else
319 			((u8 *)rxp)[i] = (u8)readl(rx);
320 	}
321 
322 	if (flags & SPI_XFER_END) {
323 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
324 		omap3_spi_write_chconf(ds,chconf);
325 	}
326 
327 	return 0;
328 }
329 
330 /*McSPI Transmit Receive Mode*/
331 int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
332 		   const void *txp, void *rxp, unsigned long flags)
333 {
334 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
335 	int timeout = SPI_WAIT_TIMEOUT;
336 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
337 	int irqstatus = readl(&ds->regs->irqstatus);
338 	int i=0;
339 
340 	/*Enable SPI channel*/
341 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
342 
343 	/*set TRANSMIT-RECEIVE Mode*/
344 	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
345 	chconf |= (ds->slave.wordlen - 1) << 7;
346 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
347 	omap3_spi_write_chconf(ds,chconf);
348 
349 	/*Shift in and out 1 byte at time*/
350 	for (i=0; i < len; i++){
351 		/* Write: wait for TX empty (TXS == 1)*/
352 		irqstatus |= (1<< (4*(ds->slave.bus)));
353 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
354 			 OMAP3_MCSPI_CHSTAT_TXS)) {
355 			if (--timeout <= 0) {
356 				printf("SPI TXS timed out, status=0x%08x\n",
357 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
358 				return -1;
359 			}
360 		}
361 		/* Write the data */
362 		unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx;
363 		if (ds->slave.wordlen > 16)
364 			writel(((u32 *)txp)[i], tx);
365 		else if (ds->slave.wordlen > 8)
366 			writel(((u16 *)txp)[i], tx);
367 		else
368 			writel(((u8 *)txp)[i], tx);
369 
370 		/*Read: wait for RX containing data (RXS == 1)*/
371 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
372 			 OMAP3_MCSPI_CHSTAT_RXS)) {
373 			if (--timeout <= 0) {
374 				printf("SPI RXS timed out, status=0x%08x\n",
375 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
376 				return -1;
377 			}
378 		}
379 		/* Read the data */
380 		unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
381 		if (ds->slave.wordlen > 16)
382 			((u32 *)rxp)[i] = readl(rx);
383 		else if (ds->slave.wordlen > 8)
384 			((u16 *)rxp)[i] = (u16)readl(rx);
385 		else
386 			((u8 *)rxp)[i] = (u8)readl(rx);
387 	}
388 	/* Disable the channel */
389 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
390 
391 	/*if transfer must be terminated disable the channel*/
392 	if (flags & SPI_XFER_END) {
393 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
394 		omap3_spi_write_chconf(ds,chconf);
395 	}
396 
397 	return 0;
398 }
399 
400 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
401 	     const void *dout, void *din, unsigned long flags)
402 {
403 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
404 	unsigned int	len;
405 	int ret = -1;
406 
407 	if (ds->slave.wordlen < 4 || ds->slave.wordlen > 32) {
408 		printf("omap3_spi: invalid wordlen %d\n", ds->slave.wordlen);
409 		return -1;
410 	}
411 
412 	if (bitlen % ds->slave.wordlen)
413 		return -1;
414 
415 	len = bitlen / ds->slave.wordlen;
416 
417 	if (bitlen == 0) {	 /* only change CS */
418 		int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
419 
420 		if (flags & SPI_XFER_BEGIN) {
421 			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
422 			chconf |= OMAP3_MCSPI_CHCONF_FORCE;
423 			omap3_spi_write_chconf(ds,chconf);
424 		}
425 		if (flags & SPI_XFER_END) {
426 			chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
427 			omap3_spi_write_chconf(ds,chconf);
428 			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
429 		}
430 		ret = 0;
431 	} else {
432 		if (dout != NULL && din != NULL)
433 			ret = omap3_spi_txrx(slave, len, dout, din, flags);
434 		else if (dout != NULL)
435 			ret = omap3_spi_write(slave, len, dout, flags);
436 		else if (din != NULL)
437 			ret = omap3_spi_read(slave, len, din, flags);
438 	}
439 	return ret;
440 }
441 
442 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
443 {
444 	return 1;
445 }
446 
447 void spi_cs_activate(struct spi_slave *slave)
448 {
449 }
450 
451 void spi_cs_deactivate(struct spi_slave *slave)
452 {
453 }
454