xref: /rk3399_rockchip-uboot/drivers/spi/omap3_spi.c (revision 4c0620bf42172325ea0c6afa0fdd362bb264e31b)
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  * See file CREDITS for list of people who contributed to this
15  * project.
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License as
19  * published by the Free Software Foundation; either version 2 of
20  * the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30  * MA 02111-1307 USA
31  *
32  */
33 
34 #include <common.h>
35 #include <spi.h>
36 #include <malloc.h>
37 #include <asm/io.h>
38 #include "omap3_spi.h"
39 
40 #define WORD_LEN	8
41 #define SPI_WAIT_TIMEOUT 3000000;
42 
43 static void spi_reset(struct omap3_spi_slave *ds)
44 {
45 	unsigned int tmp;
46 
47 	writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &ds->regs->sysconfig);
48 	do {
49 		tmp = readl(&ds->regs->sysstatus);
50 	} while (!(tmp & OMAP3_MCSPI_SYSSTATUS_RESETDONE));
51 
52 	writel(OMAP3_MCSPI_SYSCONFIG_AUTOIDLE |
53 				 OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP |
54 				 OMAP3_MCSPI_SYSCONFIG_SMARTIDLE,
55 				 &ds->regs->sysconfig);
56 
57 	writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &ds->regs->wakeupenable);
58 }
59 
60 void spi_init()
61 {
62 	/* do nothing */
63 }
64 
65 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
66 				  unsigned int max_hz, unsigned int mode)
67 {
68 	struct omap3_spi_slave	*ds;
69 
70 	ds = malloc(sizeof(struct omap3_spi_slave));
71 	if (!ds) {
72 		printf("SPI error: malloc of SPI structure failed\n");
73 		return NULL;
74 	}
75 
76 	/*
77 	 * OMAP3 McSPI (MultiChannel SPI) has 4 busses (modules)
78 	 * with different number of chip selects (CS, channels):
79 	 * McSPI1 has 4 CS (bus 0, cs 0 - 3)
80 	 * McSPI2 has 2 CS (bus 1, cs 0 - 1)
81 	 * McSPI3 has 2 CS (bus 2, cs 0 - 1)
82 	 * McSPI4 has 1 CS (bus 3, cs 0)
83 	 */
84 
85 	switch (bus) {
86 	case 0:
87 		ds->regs = (struct mcspi *)OMAP3_MCSPI1_BASE;
88 		break;
89 #ifdef OMAP3_MCSPI2_BASE
90 	case 1:
91 		ds->regs = (struct mcspi *)OMAP3_MCSPI2_BASE;
92 		break;
93 #endif
94 #ifdef OMAP3_MCSPI3_BASE
95 	case 2:
96 		ds->regs = (struct mcspi *)OMAP3_MCSPI3_BASE;
97 		break;
98 #endif
99 #ifdef OMAP3_MCSPI4_BASE
100 	case 3:
101 		ds->regs = (struct mcspi *)OMAP3_MCSPI4_BASE;
102 		break;
103 #endif
104 	default:
105 		printf("SPI error: unsupported bus %i. \
106 			Supported busses 0 - 3\n", bus);
107 		return NULL;
108 	}
109 	ds->slave.bus = bus;
110 
111 	if (((bus == 0) && (cs > 3)) ||
112 			((bus == 1) && (cs > 1)) ||
113 			((bus == 2) && (cs > 1)) ||
114 			((bus == 3) && (cs > 0))) {
115 		printf("SPI error: unsupported chip select %i \
116 			on bus %i\n", cs, bus);
117 		return NULL;
118 	}
119 	ds->slave.cs = cs;
120 
121 	if (max_hz > OMAP3_MCSPI_MAX_FREQ) {
122 		printf("SPI error: unsupported frequency %i Hz. \
123 			Max frequency is 48 Mhz\n", max_hz);
124 		return NULL;
125 	}
126 	ds->freq = max_hz;
127 
128 	if (mode > SPI_MODE_3) {
129 		printf("SPI error: unsupported SPI mode %i\n", mode);
130 		return NULL;
131 	}
132 	ds->mode = mode;
133 
134 	return &ds->slave;
135 }
136 
137 void spi_free_slave(struct spi_slave *slave)
138 {
139 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
140 
141 	free(ds);
142 }
143 
144 int spi_claim_bus(struct spi_slave *slave)
145 {
146 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
147 	unsigned int conf, div = 0;
148 
149 	/* McSPI global module configuration */
150 
151 	/*
152 	 * setup when switching from (reset default) slave mode
153 	 * to single-channel master mode
154 	 */
155 	spi_reset(ds);
156 	conf = readl(&ds->regs->modulctrl);
157 	conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS);
158 	conf |= OMAP3_MCSPI_MODULCTRL_SINGLE;
159 	writel(conf, &ds->regs->modulctrl);
160 
161 	/* McSPI individual channel configuration */
162 
163 	/* Calculate clock divisor. Valid range: 0x0 - 0xC ( /1 - /4096 ) */
164 	if (ds->freq) {
165 		while (div <= 0xC && (OMAP3_MCSPI_MAX_FREQ / (1 << div))
166 					 > ds->freq)
167 			div++;
168 	} else
169 		div = 0xC;
170 
171 	conf = readl(&ds->regs->channel[ds->slave.cs].chconf);
172 
173 	/* standard 4-wire master mode:	SCK, MOSI/out, MISO/in, nCS
174 	 * REVISIT: this controller could support SPI_3WIRE mode.
175 	 */
176 	conf &= ~(OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1);
177 	conf |= OMAP3_MCSPI_CHCONF_DPE0;
178 
179 	/* wordlength */
180 	conf &= ~OMAP3_MCSPI_CHCONF_WL_MASK;
181 	conf |= (WORD_LEN - 1) << 7;
182 
183 	/* set chipselect polarity; manage with FORCE */
184 	if (!(ds->mode & SPI_CS_HIGH))
185 		conf |= OMAP3_MCSPI_CHCONF_EPOL; /* active-low; normal */
186 	else
187 		conf &= ~OMAP3_MCSPI_CHCONF_EPOL;
188 
189 	/* set clock divisor */
190 	conf &= ~OMAP3_MCSPI_CHCONF_CLKD_MASK;
191 	conf |= div << 2;
192 
193 	/* set SPI mode 0..3 */
194 	if (ds->mode & SPI_CPOL)
195 		conf |= OMAP3_MCSPI_CHCONF_POL;
196 	else
197 		conf &= ~OMAP3_MCSPI_CHCONF_POL;
198 	if (ds->mode & SPI_CPHA)
199 		conf |= OMAP3_MCSPI_CHCONF_PHA;
200 	else
201 		conf &= ~OMAP3_MCSPI_CHCONF_PHA;
202 
203 	/* Transmit & receive mode */
204 	conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
205 
206 	writel(conf, &ds->regs->channel[ds->slave.cs].chconf);
207 
208 	return 0;
209 }
210 
211 void spi_release_bus(struct spi_slave *slave)
212 {
213 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
214 
215 	/* Reset the SPI hardware */
216 	spi_reset(ds);
217 }
218 
219 int omap3_spi_write(struct spi_slave *slave, unsigned int len, const u8 *txp,
220 		    unsigned long flags)
221 {
222 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
223 	int i;
224 	int timeout = SPI_WAIT_TIMEOUT;
225 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
226 
227 	if (flags & SPI_XFER_BEGIN)
228 		writel(OMAP3_MCSPI_CHCTRL_EN,
229 		       &ds->regs->channel[ds->slave.cs].chctrl);
230 
231 	chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
232 	chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
233 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
234 	writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
235 
236 	for (i = 0; i < len; i++) {
237 		/* wait till TX register is empty (TXS == 1) */
238 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
239 			 OMAP3_MCSPI_CHSTAT_TXS)) {
240 			if (--timeout <= 0) {
241 				printf("SPI TXS timed out, status=0x%08x\n",
242 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
243 				return -1;
244 			}
245 		}
246 		/* Write the data */
247 		writel(txp[i], &ds->regs->channel[ds->slave.cs].tx);
248 	}
249 
250 	if (flags & SPI_XFER_END) {
251 		/* wait to finish of transfer */
252 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
253 			 OMAP3_MCSPI_CHSTAT_EOT));
254 
255 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
256 		writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
257 
258 		writel(0, &ds->regs->channel[ds->slave.cs].chctrl);
259 	}
260 	return 0;
261 }
262 
263 int omap3_spi_read(struct spi_slave *slave, unsigned int len, u8 *rxp,
264 		   unsigned long flags)
265 {
266 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
267 	int i;
268 	int timeout = SPI_WAIT_TIMEOUT;
269 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
270 
271 	if (flags & SPI_XFER_BEGIN)
272 		writel(OMAP3_MCSPI_CHCTRL_EN,
273 		       &ds->regs->channel[ds->slave.cs].chctrl);
274 
275 	chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
276 	chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
277 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
278 	writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
279 
280 	writel(0, &ds->regs->channel[ds->slave.cs].tx);
281 
282 	for (i = 0; i < len; i++) {
283 		/* Wait till RX register contains data (RXS == 1) */
284 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
285 			 OMAP3_MCSPI_CHSTAT_RXS)) {
286 			if (--timeout <= 0) {
287 				printf("SPI RXS timed out, status=0x%08x\n",
288 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
289 				return -1;
290 			}
291 		}
292 		/* Read the data */
293 		rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx);
294 	}
295 
296 	if (flags & SPI_XFER_END) {
297 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
298 		writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
299 
300 		writel(0, &ds->regs->channel[ds->slave.cs].chctrl);
301 	}
302 
303 	return 0;
304 }
305 
306 /*McSPI Transmit Receive Mode*/
307 int omap3_spi_txrx(struct spi_slave *slave,
308 		unsigned int len, const u8 *txp, u8 *rxp, unsigned long flags)
309 {
310 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
311 	int timeout = SPI_WAIT_TIMEOUT;
312 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
313 	int irqstatus = readl(&ds->regs->irqstatus);
314 	int i=0;
315 
316 	/*Enable SPI channel*/
317 	if (flags & SPI_XFER_BEGIN)
318 		writel(OMAP3_MCSPI_CHCTRL_EN,
319 		       &ds->regs->channel[ds->slave.cs].chctrl);
320 
321 	/*set TRANSMIT-RECEIVE Mode*/
322 	chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
323 	chconf |= OMAP3_MCSPI_CHCONF_FORCE;
324 	writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
325 
326 	/*Shift in and out 1 byte at time*/
327 	for (i=0; i < len; i++){
328 		/* Write: wait for TX empty (TXS == 1)*/
329 		irqstatus |= (1<< (4*(ds->slave.bus)));
330 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
331 			 OMAP3_MCSPI_CHSTAT_TXS)) {
332 			if (--timeout <= 0) {
333 				printf("SPI TXS timed out, status=0x%08x\n",
334 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
335 				return -1;
336 			}
337 		}
338 		/* Write the data */
339 		writel(txp[i], &ds->regs->channel[ds->slave.cs].tx);
340 
341 		/*Read: wait for RX containing data (RXS == 1)*/
342 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
343 			 OMAP3_MCSPI_CHSTAT_RXS)) {
344 			if (--timeout <= 0) {
345 				printf("SPI RXS timed out, status=0x%08x\n",
346 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
347 				return -1;
348 			}
349 		}
350 		/* Read the data */
351 		rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx);
352 	}
353 
354 	/*if transfer must be terminated disable the channel*/
355 	if (flags & SPI_XFER_END) {
356 		chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
357 		writel(chconf, &ds->regs->channel[ds->slave.cs].chconf);
358 
359 		writel(0, &ds->regs->channel[ds->slave.cs].chctrl);
360 	}
361 
362 	return 0;
363 }
364 
365 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
366 	     const void *dout, void *din, unsigned long flags)
367 {
368 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
369 	unsigned int	len;
370 	const u8	*txp = dout;
371 	u8		*rxp = din;
372 	int ret = -1;
373 
374 	if (bitlen % 8)
375 		return -1;
376 
377 	len = bitlen / 8;
378 
379 	if (bitlen == 0) {	 /* only change CS */
380 		int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
381 
382 		if (flags & SPI_XFER_BEGIN) {
383 			writel(OMAP3_MCSPI_CHCTRL_EN,
384 			       &ds->regs->channel[ds->slave.cs].chctrl);
385 			chconf |= OMAP3_MCSPI_CHCONF_FORCE;
386 			writel(chconf,
387 			       &ds->regs->channel[ds->slave.cs].chconf);
388 		}
389 		if (flags & SPI_XFER_END) {
390 			chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
391 			writel(chconf,
392 			       &ds->regs->channel[ds->slave.cs].chconf);
393 			writel(0, &ds->regs->channel[ds->slave.cs].chctrl);
394 		}
395 		ret = 0;
396 	} else {
397 		if (dout != NULL && din != NULL)
398 			ret = omap3_spi_txrx(slave, len, txp, rxp, flags);
399 		else if (dout != NULL)
400 			ret = omap3_spi_write(slave, len, txp, flags);
401 		else if (din != NULL)
402 			ret = omap3_spi_read(slave, len, rxp, flags);
403 	}
404 	return ret;
405 }
406 
407 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
408 {
409 	return 1;
410 }
411 
412 void spi_cs_activate(struct spi_slave *slave)
413 {
414 }
415 
416 void spi_cs_deactivate(struct spi_slave *slave)
417 {
418 }
419