1 /*
2  * Copyright (c) 2001 Navin Boppuri / Prashant Patel
3  *	<nboppuri@trinetcommunication.com>,
4  *	<pmpatel@trinetcommunication.com>
5  * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de>
6  * Copyright (c) 2001 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26 
27 /*
28  * MPC5xx CPM SPI interface.
29  *
30  * Parts of this code are probably not portable and/or specific to
31  * the board which I used for the tests. Please send fixes/complaints
32  * to wd@denx.de
33  *
34  * Ported to MPC5xx
35  * Copyright (c) 2003 Denis Peter, MPL AG Switzerland, d.petr@mpl.ch.
36  */
37 
38 #include <common.h>
39 #include <mpc5xx.h>
40 #include <asm/5xx_immap.h>
41 #include <linux/ctype.h>
42 #include <malloc.h>
43 #include <post.h>
44 #include <net.h>
45 
46 #if defined(CONFIG_SPI)
47 
48 #undef	DEBUG
49 
50 #define SPI_EEPROM_WREN		0x06
51 #define SPI_EEPROM_RDSR		0x05
52 #define SPI_EEPROM_READ		0x03
53 #define SPI_EEPROM_WRITE	0x02
54 
55 
56 #ifdef	DEBUG
57 
58 #define	DPRINT(a)	printf a;
59 /* -----------------------------------------------
60  * Helper functions to peek into tx and rx buffers
61  * ----------------------------------------------- */
62 static const char * const hex_digit = "0123456789ABCDEF";
63 
quickhex(int i)64 static char quickhex (int i)
65 {
66 	return hex_digit[i];
67 }
68 
memdump(void * pv,int num)69 static void memdump (void *pv, int num)
70 {
71 	int i;
72 	unsigned char *pc = (unsigned char *) pv;
73 
74 	for (i = 0; i < num; i++)
75 		printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
76 	printf ("\t");
77 	for (i = 0; i < num; i++)
78 		printf ("%c", isprint (pc[i]) ? pc[i] : '.');
79 	printf ("\n");
80 }
81 #else	/* !DEBUG */
82 
83 #define	DPRINT(a)
84 
85 #endif	/* DEBUG */
86 
87 /* -------------------
88  * Function prototypes
89  * ------------------- */
90 void spi_init (void);
91 
92 ssize_t spi_read (uchar *, int, uchar *, int);
93 ssize_t spi_write (uchar *, int, uchar *, int);
94 ssize_t spi_xfer (size_t);
95 
96 
97 /* **************************************************************************
98  *
99  *  Function:    spi_init_f
100  *
101  *  Description: Init SPI-Controller (ROM part)
102  *
103  *  return:      ---
104  *
105  * *********************************************************************** */
106 
spi_init_f(void)107 void spi_init_f (void)
108 {
109 	int i;
110 
111 	volatile immap_t *immr;
112 	volatile qsmcm5xx_t *qsmcm;
113 
114 	immr = (immap_t *)  CONFIG_SYS_IMMR;
115 	qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
116 
117 	qsmcm->qsmcm_qsmcr = 0; /* all accesses enabled */
118 	qsmcm->qsmcm_qspi_il = 0; /* lowest IRQ */
119 
120 	/* --------------------------------------------
121 	 * GPIO or per. Function
122 	 * PQSPAR[00] = 0 reserved
123 	 * PQSPAR[01] = 1 [0x4000] -> PERI: (SPICS3)
124 	 * PQSPAR[02] = 0 [0x0000] -> GPIO
125 	 * PQSPAR[03] = 0 [0x0000] -> GPIO
126 	 * PQSPAR[04] = 1 [0x0800] -> PERI: (SPICS0)
127 	 * PQSPAR[05] = 0 reseved
128 	 * PQSPAR[06] = 1 [0x0200] -> PERI: (SPIMOSI)
129 	 * PQSPAR[07] = 1 [0x0100] -> PERI: (SPIMISO)
130 	 * -------------------------------------------- */
131 	qsmcm->qsmcm_pqspar =  0x3 | (CONFIG_SYS_SPI_CS_USED << 3);
132 
133 	 /* --------------------------------------------
134 	 * DDRQS[00] = 0 reserved
135 	 * DDRQS[01] = 1 [0x0040] -> SPICS3 Output
136 	 * DDRQS[02] = 0 [0x0000] -> GPIO Output
137 	 * DDRQS[03] = 0 [0x0000] -> GPIO Output
138 	 * DDRQS[04] = 1 [0x0008] -> SPICS0 Output
139 	 * DDRQS[05] = 1 [0x0004] -> SPICLK Output
140 	 * DDRQS[06] = 1 [0x0002] -> SPIMOSI Output
141 	 * DDRQS[07] = 0 [0x0001] -> SPIMISO Input
142 	 * -------------------------------------------- */
143 	qsmcm->qsmcm_ddrqs = 0x7E;
144 	 /* --------------------------------------------
145 	 * Base state for used SPI CS pins, if base = 0 active must be 1
146 	 * PORTQS[00] = 0 reserved
147 	 * PORTQS[01] = 0 reserved
148 	 * PORTQS[02] = 0 reserved
149 	 * PORTQS[03] = 0 reserved
150 	 * PORTQS[04] = 0 [0x0000] RxD2
151 	 * PORTQS[05] = 1 [0x0400] TxD2
152 	 * PORTQS[06] = 0 [0x0000] RxD1
153 	 * PORTQS[07] = 1 [0x0100] TxD1
154 	 * PORTQS[08] = 0 reserved
155 	 * PORTQS[09] = 0 [0x0000] -> SPICS3 Base Output
156 	 * PORTQS[10] = 0 [0x0000] -> SPICS2 Base Output
157 	 * PORTQS[11] = 0 [0x0000] -> SPICS1 Base Output
158 	 * PORTQS[12] = 0 [0x0000] -> SPICS0 Base Output
159 	 * PORTQS[13] = 0 [0x0004] -> SPICLK Output
160 	 * PORTQS[14] = 0 [0x0002] -> SPIMOSI Output
161 	 * PORTQS[15] = 0 [0x0001] -> SPIMISO Input
162 	 * -------------------------------------------- */
163 	qsmcm->qsmcm_portqs |= (CONFIG_SYS_SPI_CS_BASE << 3);
164 	/* --------------------------------------------
165 	 * Controll Register 0
166 	 * SPCR0[00] = 1 (0x8000) Master
167 	 * SPCR0[01] = 0 (0x0000) Wired-Or
168 	 * SPCR0[2..5] = (0x2000) Bits per transfer (default 8)
169 	 * SPCR0[06] = 0 (0x0000) Normal polarity
170 	 * SPCR0[07] = 0 (0x0000) Normal Clock Phase
171 	 * SPCR0[08..15] = 14 1.4MHz
172 	 */
173 	qsmcm->qsmcm_spcr0=0xA00E;
174 	/* --------------------------------------------
175 	 * Controll Register 1
176 	 * SPCR1[00] = 0 (0x0000) QSPI enabled
177 	 * SPCR1[1..7] =  (0x7F00) Delay before Transfer
178 	 * SPCR1[8..15] = (0x0000) Delay After transfer (204.8usec@40MHz)
179 	 */
180 	qsmcm->qsmcm_spcr1=0x7F00;
181 	/* --------------------------------------------
182 	 * Controll Register 2
183 	 * SPCR2[00] = 0 (0x0000) SPI IRQs Disabeld
184 	 * SPCR2[01] = 0 (0x0000) No Wrap around
185 	 * SPCR2[02] = 0 (0x0000) Wrap to 0
186 	 * SPCR2[3..7] = (0x0000) End Queue pointer = 0
187 	 * SPCR2[8..10] = 0 (0x0000) reserved
188 	 * SPCR2[11..15] = 0 (0x0000) NewQueue Address = 0
189 	 */
190 	qsmcm->qsmcm_spcr2=0x0000;
191 	/* --------------------------------------------
192 	 * Controll Register 3
193 	 * SPCR3[00..04] = 0 (0x0000) reserved
194 	 * SPCR3[05] = 0 (0x0000) Feedback disabled
195 	 * SPCR3[06] = 0 (0x0000) IRQ on HALTA & MODF disabled
196 	 * SPCR3[07] = 0 (0x0000) Not halted
197 	 */
198 	qsmcm->qsmcm_spcr3=0x00;
199 	/* --------------------------------------------
200 	 * SPSR (Controll Register 3) Read only/ reset Flags 08,09,10
201 	 * SPCR3[08] = 1 (0x80) QSPI finished
202 	 * SPCR3[09] = 1 (0x40) Mode Fault Flag
203 	 * SPCR3[10] = 1 (0x20) HALTA
204 	 * SPCR3[11..15] = 0 (0x0000) Last executed command
205 	 */
206 	qsmcm->qsmcm_spsr=0xE0;
207 	/*-------------------------------------------
208 	 * Setup RAM
209 	 */
210 	for(i=0;i<32;i++) {
211 		 qsmcm->qsmcm_recram[i]=0x0000;
212 		 qsmcm->qsmcm_tranram[i]=0x0000;
213 		 qsmcm->qsmcm_comdram[i]=0x00;
214 	}
215 	return;
216 }
217 
218 /* **************************************************************************
219  *
220  *  Function:    spi_init_r
221  *  Dummy, all initializations have been done in spi_init_r
222  * *********************************************************************** */
spi_init_r(void)223 void spi_init_r (void)
224 {
225 	return;
226 
227 }
228 
229 /****************************************************************************
230  *  Function:    spi_write
231  **************************************************************************** */
short_spi_write(uchar * addr,int alen,uchar * buffer,int len)232 ssize_t short_spi_write (uchar *addr, int alen, uchar *buffer, int len)
233 {
234 	int i,dlen;
235 	volatile immap_t *immr;
236 	volatile qsmcm5xx_t *qsmcm;
237 
238 	immr = (immap_t *)  CONFIG_SYS_IMMR;
239 	qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
240 	for(i=0;i<32;i++) {
241 		 qsmcm->qsmcm_recram[i]=0x0000;
242 		 qsmcm->qsmcm_tranram[i]=0x0000;
243 		 qsmcm->qsmcm_comdram[i]=0x00;
244 	}
245 	qsmcm->qsmcm_tranram[0] =  SPI_EEPROM_WREN; /* write enable */
246 	spi_xfer(1);
247 	i=0;
248 	qsmcm->qsmcm_tranram[i++] =  SPI_EEPROM_WRITE; /* WRITE memory array */
249 	qsmcm->qsmcm_tranram[i++] =  addr[0];
250 	qsmcm->qsmcm_tranram[i++] =  addr[1];
251 
252 	for(dlen=0;dlen<len;dlen++) {
253 		qsmcm->qsmcm_tranram[i+dlen] = buffer[dlen]; /* WRITE memory array */
254 	}
255 	/* transmit it */
256 	spi_xfer(i+dlen);
257 	/* ignore received data	*/
258 	for (i = 0; i < 1000; i++) {
259 		qsmcm->qsmcm_tranram[0] =  SPI_EEPROM_RDSR; /* read status */
260 		qsmcm->qsmcm_tranram[1] = 0;
261 		spi_xfer(2);
262 		if (!(qsmcm->qsmcm_recram[1] & 1)) {
263 			break;
264 		}
265 		udelay(1000);
266 	}
267 	if (i >= 1000) {
268 		printf ("*** spi_write: Time out while writing!\n");
269 	}
270 	return len;
271 }
272 
273 #define TRANSFER_LEN 16
274 
spi_write(uchar * addr,int alen,uchar * buffer,int len)275 ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
276 {
277 	int index,i,newlen;
278 	uchar newaddr[2];
279 	int curraddr;
280 
281 	curraddr=(addr[alen-2]<<8)+addr[alen-1];
282 	i=len;
283 	index=0;
284 	do {
285 		newaddr[1]=(curraddr & 0xff);
286 		newaddr[0]=((curraddr>>8) & 0xff);
287 		if(i>TRANSFER_LEN) {
288 			newlen=TRANSFER_LEN;
289 			i-=TRANSFER_LEN;
290 		}
291 		else {
292 			newlen=i;
293 			i=0;
294 		}
295 		short_spi_write (newaddr, 2, &buffer[index], newlen);
296 		index+=newlen;
297 		curraddr+=newlen;
298 	}while(i);
299 	return (len);
300 }
301 
302 /****************************************************************************
303  *  Function:    spi_read
304  **************************************************************************** */
short_spi_read(uchar * addr,int alen,uchar * buffer,int len)305 ssize_t short_spi_read (uchar *addr, int alen, uchar *buffer, int len)
306 {
307 	int i;
308 	volatile immap_t *immr;
309 	volatile qsmcm5xx_t *qsmcm;
310 
311 	immr = (immap_t *)  CONFIG_SYS_IMMR;
312 	qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
313 
314 	for(i=0;i<32;i++) {
315 		 qsmcm->qsmcm_recram[i]=0x0000;
316 		 qsmcm->qsmcm_tranram[i]=0x0000;
317 		 qsmcm->qsmcm_comdram[i]=0x00;
318 	}
319 	i=0;
320 	qsmcm->qsmcm_tranram[i++] = (SPI_EEPROM_READ); /* READ memory array */
321 	qsmcm->qsmcm_tranram[i++] = addr[0] & 0xff;
322 	qsmcm->qsmcm_tranram[i++] = addr[1] & 0xff;
323 	spi_xfer(3 + len);
324 	for(i=0;i<len;i++) {
325 		*buffer++=(char)qsmcm->qsmcm_recram[i+3];
326 	}
327 	return len;
328 }
329 
spi_read(uchar * addr,int alen,uchar * buffer,int len)330 ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
331 {
332 	int index,i,newlen;
333 	uchar newaddr[2];
334 	int curraddr;
335 
336 	curraddr=(addr[alen-2]<<8)+addr[alen-1];
337 	i=len;
338 	index=0;
339 	do {
340 		newaddr[1]=(curraddr & 0xff);
341 		newaddr[0]=((curraddr>>8) & 0xff);
342 		if(i>TRANSFER_LEN) {
343 			newlen=TRANSFER_LEN;
344 			i-=TRANSFER_LEN;
345 		}
346 		else {
347 			newlen=i;
348 			i=0;
349 		}
350 		short_spi_read (newaddr, 2, &buffer[index], newlen);
351 		index+=newlen;
352 		curraddr+=newlen;
353 	}while(i);
354 	return (len);
355 }
356 
357 /****************************************************************************
358  *  Function:    spi_xfer
359  **************************************************************************** */
spi_xfer(size_t count)360 ssize_t spi_xfer (size_t count)
361 {
362 	volatile immap_t *immr;
363 	volatile qsmcm5xx_t *qsmcm;
364 	int i;
365 	int tm;
366 	ushort status;
367 	immr = (immap_t *)  CONFIG_SYS_IMMR;
368 	qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
369 	DPRINT (("*** spi_xfer entered count %d***\n",count));
370 
371 	/* Set CS for device */
372 	for(i=0;i<(count-1);i++)
373 		qsmcm->qsmcm_comdram[i] = 0x80 | CONFIG_SYS_SPI_CS_ACT;  /* CS3 is connected to the SPI EEPROM */
374 
375 	qsmcm->qsmcm_comdram[i] = CONFIG_SYS_SPI_CS_ACT; /* CS3 is connected to the SPI EEPROM */
376 	qsmcm->qsmcm_spcr2=((count-1)&0x1F)<<8;
377 
378 	DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n", count));
379 
380 	qsmcm->qsmcm_spsr=0xE0; /* clear all flags */
381 
382 	/* start spi transfer */
383 	DPRINT (("*** spi_xfer: Performing transfer ...\n"));
384 	qsmcm->qsmcm_spcr1 |= 0x8000;		/* Start transmit */
385 
386 	/* --------------------------------
387 	 * Wait for SPI transmit to get out
388 	 * or time out (1 second = 1000 ms)
389 	 * -------------------------------- */
390 	for (tm=0; tm<1000; ++tm) {
391 		status=qsmcm->qsmcm_spcr1;
392 		if((status & 0x8000)==0)
393 			break;
394 		udelay (1000);
395 	}
396 	if (tm >= 1000) {
397 		printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
398 	}
399 #ifdef	DEBUG
400 	printf ("\nspi_xfer: txbuf after xfer\n");
401 	memdump ((void *) qsmcm->qsmcm_tranram, 32);	/* dump of txbuf before transmit */
402 	printf ("spi_xfer: rxbuf after xfer\n");
403 	memdump ((void *) qsmcm->qsmcm_recram, 32);	/* dump of rxbuf after transmit */
404 	printf ("\nspi_xfer: commbuf after xfer\n");
405 	memdump ((void *) qsmcm->qsmcm_comdram, 32);	/* dump of txbuf before transmit */
406 	printf ("\n");
407 #endif
408 
409 	return count;
410 }
411 
412 #endif	/* CONFIG_SPI  */
413