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