xref: /openbmc/u-boot/drivers/spi/omap3_spi.c (revision e5c5301f)
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));
265 
266 	/* Disable the channel otherwise the next immediate RX will get affected */
267 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
268 
269 	if (flags & SPI_XFER_END) {
270 
271 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
272 		omap3_spi_write_chconf(ds,chconf);
273 	}
274 	return 0;
275 }
276 
277 int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp,
278 		   unsigned long flags)
279 {
280 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
281 	int i;
282 	int timeout = SPI_WAIT_TIMEOUT;
283 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
284 
285 	/* Enable the channel */
286 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
287 
288 	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
289 	chconf |= (ds->slave.wordlen - 1) << 7;
290 	chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
291 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
292 	omap3_spi_write_chconf(ds,chconf);
293 
294 	writel(0, &ds->regs->channel[ds->slave.cs].tx);
295 
296 	for (i = 0; i < len; i++) {
297 		/* Wait till RX register contains data (RXS == 1) */
298 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
299 			 OMAP3_MCSPI_CHSTAT_RXS)) {
300 			if (--timeout <= 0) {
301 				printf("SPI RXS timed out, status=0x%08x\n",
302 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
303 				return -1;
304 			}
305 		}
306 
307 		/* Disable the channel to prevent furher receiving */
308 		if(i == (len - 1))
309 			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
310 
311 		/* Read the data */
312 		unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
313 		if (ds->slave.wordlen > 16)
314 			((u32 *)rxp)[i] = readl(rx);
315 		else if (ds->slave.wordlen > 8)
316 			((u16 *)rxp)[i] = (u16)readl(rx);
317 		else
318 			((u8 *)rxp)[i] = (u8)readl(rx);
319 	}
320 
321 	if (flags & SPI_XFER_END) {
322 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
323 		omap3_spi_write_chconf(ds,chconf);
324 	}
325 
326 	return 0;
327 }
328 
329 /*McSPI Transmit Receive Mode*/
330 int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
331 		   const void *txp, void *rxp, unsigned long flags)
332 {
333 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
334 	int timeout = SPI_WAIT_TIMEOUT;
335 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
336 	int irqstatus = readl(&ds->regs->irqstatus);
337 	int i=0;
338 
339 	/*Enable SPI channel*/
340 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
341 
342 	/*set TRANSMIT-RECEIVE Mode*/
343 	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
344 	chconf |= (ds->slave.wordlen - 1) << 7;
345 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
346 	omap3_spi_write_chconf(ds,chconf);
347 
348 	/*Shift in and out 1 byte at time*/
349 	for (i=0; i < len; i++){
350 		/* Write: wait for TX empty (TXS == 1)*/
351 		irqstatus |= (1<< (4*(ds->slave.bus)));
352 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
353 			 OMAP3_MCSPI_CHSTAT_TXS)) {
354 			if (--timeout <= 0) {
355 				printf("SPI TXS timed out, status=0x%08x\n",
356 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
357 				return -1;
358 			}
359 		}
360 		/* Write the data */
361 		unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx;
362 		if (ds->slave.wordlen > 16)
363 			writel(((u32 *)txp)[i], tx);
364 		else if (ds->slave.wordlen > 8)
365 			writel(((u16 *)txp)[i], tx);
366 		else
367 			writel(((u8 *)txp)[i], tx);
368 
369 		/*Read: wait for RX containing data (RXS == 1)*/
370 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
371 			 OMAP3_MCSPI_CHSTAT_RXS)) {
372 			if (--timeout <= 0) {
373 				printf("SPI RXS timed out, status=0x%08x\n",
374 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
375 				return -1;
376 			}
377 		}
378 		/* Read the data */
379 		unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
380 		if (ds->slave.wordlen > 16)
381 			((u32 *)rxp)[i] = readl(rx);
382 		else if (ds->slave.wordlen > 8)
383 			((u16 *)rxp)[i] = (u16)readl(rx);
384 		else
385 			((u8 *)rxp)[i] = (u8)readl(rx);
386 	}
387 	/* Disable the channel */
388 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
389 
390 	/*if transfer must be terminated disable the channel*/
391 	if (flags & SPI_XFER_END) {
392 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
393 		omap3_spi_write_chconf(ds,chconf);
394 	}
395 
396 	return 0;
397 }
398 
399 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
400 	     const void *dout, void *din, unsigned long flags)
401 {
402 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
403 	unsigned int	len;
404 	int ret = -1;
405 
406 	if (ds->slave.wordlen < 4 || ds->slave.wordlen > 32) {
407 		printf("omap3_spi: invalid wordlen %d\n", ds->slave.wordlen);
408 		return -1;
409 	}
410 
411 	if (bitlen % ds->slave.wordlen)
412 		return -1;
413 
414 	len = bitlen / ds->slave.wordlen;
415 
416 	if (bitlen == 0) {	 /* only change CS */
417 		int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
418 
419 		if (flags & SPI_XFER_BEGIN) {
420 			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
421 			chconf |= OMAP3_MCSPI_CHCONF_FORCE;
422 			omap3_spi_write_chconf(ds,chconf);
423 		}
424 		if (flags & SPI_XFER_END) {
425 			chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
426 			omap3_spi_write_chconf(ds,chconf);
427 			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
428 		}
429 		ret = 0;
430 	} else {
431 		if (dout != NULL && din != NULL)
432 			ret = omap3_spi_txrx(slave, len, dout, din, flags);
433 		else if (dout != NULL)
434 			ret = omap3_spi_write(slave, len, dout, flags);
435 		else if (din != NULL)
436 			ret = omap3_spi_read(slave, len, din, flags);
437 	}
438 	return ret;
439 }
440 
441 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
442 {
443 	return 1;
444 }
445 
446 void spi_cs_activate(struct spi_slave *slave)
447 {
448 }
449 
450 void spi_cs_deactivate(struct spi_slave *slave)
451 {
452 }
453