xref: /openbmc/u-boot/drivers/spi/omap3_spi.c (revision 2f6ed3b8)
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 i=0;
340 
341 	/*Enable SPI channel*/
342 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
343 
344 	/*set TRANSMIT-RECEIVE Mode*/
345 	chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
346 	chconf |= (ds->slave.wordlen - 1) << 7;
347 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
348 	omap3_spi_write_chconf(ds,chconf);
349 
350 	/*Shift in and out 1 byte at time*/
351 	for (i=0; i < len; i++){
352 		/* Write: wait for TX empty (TXS == 1)*/
353 		start = get_timer(0);
354 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
355 			 OMAP3_MCSPI_CHSTAT_TXS)) {
356 			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
357 				printf("SPI TXS timed out, status=0x%08x\n",
358 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
359 				return -1;
360 			}
361 		}
362 		/* Write the data */
363 		unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx;
364 		if (ds->slave.wordlen > 16)
365 			writel(((u32 *)txp)[i], tx);
366 		else if (ds->slave.wordlen > 8)
367 			writel(((u16 *)txp)[i], tx);
368 		else
369 			writel(((u8 *)txp)[i], tx);
370 
371 		/*Read: wait for RX containing data (RXS == 1)*/
372 		start = get_timer(0);
373 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
374 			 OMAP3_MCSPI_CHSTAT_RXS)) {
375 			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
376 				printf("SPI RXS timed out, status=0x%08x\n",
377 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
378 				return -1;
379 			}
380 		}
381 		/* Read the data */
382 		unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
383 		if (ds->slave.wordlen > 16)
384 			((u32 *)rxp)[i] = readl(rx);
385 		else if (ds->slave.wordlen > 8)
386 			((u16 *)rxp)[i] = (u16)readl(rx);
387 		else
388 			((u8 *)rxp)[i] = (u8)readl(rx);
389 	}
390 	/* Disable the channel */
391 	omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
392 
393 	/*if transfer must be terminated disable the channel*/
394 	if (flags & SPI_XFER_END) {
395 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
396 		omap3_spi_write_chconf(ds,chconf);
397 	}
398 
399 	return 0;
400 }
401 
402 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
403 	     const void *dout, void *din, unsigned long flags)
404 {
405 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
406 	unsigned int	len;
407 	int ret = -1;
408 
409 	if (ds->slave.wordlen < 4 || ds->slave.wordlen > 32) {
410 		printf("omap3_spi: invalid wordlen %d\n", ds->slave.wordlen);
411 		return -1;
412 	}
413 
414 	if (bitlen % ds->slave.wordlen)
415 		return -1;
416 
417 	len = bitlen / ds->slave.wordlen;
418 
419 	if (bitlen == 0) {	 /* only change CS */
420 		int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
421 
422 		if (flags & SPI_XFER_BEGIN) {
423 			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
424 			chconf |= OMAP3_MCSPI_CHCONF_FORCE;
425 			omap3_spi_write_chconf(ds,chconf);
426 		}
427 		if (flags & SPI_XFER_END) {
428 			chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
429 			omap3_spi_write_chconf(ds,chconf);
430 			omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
431 		}
432 		ret = 0;
433 	} else {
434 		if (dout != NULL && din != NULL)
435 			ret = omap3_spi_txrx(slave, len, dout, din, flags);
436 		else if (dout != NULL)
437 			ret = omap3_spi_write(slave, len, dout, flags);
438 		else if (din != NULL)
439 			ret = omap3_spi_read(slave, len, din, flags);
440 	}
441 	return ret;
442 }
443 
444 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
445 {
446 	return 1;
447 }
448 
449 void spi_cs_activate(struct spi_slave *slave)
450 {
451 }
452 
453 void spi_cs_deactivate(struct spi_slave *slave)
454 {
455 }
456