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