]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc8xx/spi.c
db34852d60577e7c15f10c497dd25474dd62ce91
[karo-tx-uboot.git] / arch / powerpc / cpu / mpc8xx / 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  * 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  * MPC8xx 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  */
35
36 #include <common.h>
37 #include <mpc8xx.h>
38 #include <commproc.h>
39 #include <linux/ctype.h>
40 #include <malloc.h>
41 #include <post.h>
42 #include <serial.h>
43
44 #if (defined(CONFIG_SPI)) || (CONFIG_POST & CONFIG_SYS_POST_SPI)
45
46 /* Warning:
47  * You cannot enable DEBUG for early system initalization, i. e. when
48  * this driver is used to read environment parameters like "baudrate"
49  * from EEPROM which are used to initialize the serial port which is
50  * needed to print the debug messages...
51  */
52 #undef  DEBUG
53
54 #define SPI_EEPROM_WREN         0x06
55 #define SPI_EEPROM_RDSR         0x05
56 #define SPI_EEPROM_READ         0x03
57 #define SPI_EEPROM_WRITE        0x02
58
59 /* ---------------------------------------------------------------
60  * Offset for initial SPI buffers in DPRAM:
61  * We need a 520 byte scratch DPRAM area to use at an early stage.
62  * It is used between the two initialization calls (spi_init_f()
63  * and spi_init_r()).
64  * The value 0xb00 makes it far enough from the start of the data
65  * area (as well as from the stack pointer).
66  * --------------------------------------------------------------- */
67 #ifndef CONFIG_SYS_SPI_INIT_OFFSET
68 #define CONFIG_SYS_SPI_INIT_OFFSET      0xB00
69 #endif
70
71 #ifdef  DEBUG
72
73 #define DPRINT(a)       printf a;
74 /* -----------------------------------------------
75  * Helper functions to peek into tx and rx buffers
76  * ----------------------------------------------- */
77 static const char * const hex_digit = "0123456789ABCDEF";
78
79 static char quickhex (int i)
80 {
81         return hex_digit[i];
82 }
83
84 static void memdump (void *pv, int num)
85 {
86         int i;
87         unsigned char *pc = (unsigned char *) pv;
88
89         for (i = 0; i < num; i++)
90                 printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
91         printf ("\t");
92         for (i = 0; i < num; i++)
93                 printf ("%c", isprint (pc[i]) ? pc[i] : '.');
94         printf ("\n");
95 }
96 #else   /* !DEBUG */
97
98 #define DPRINT(a)
99
100 #endif  /* DEBUG */
101
102 /* -------------------
103  * Function prototypes
104  * ------------------- */
105 void spi_init (void);
106
107 ssize_t spi_read (uchar *, int, uchar *, int);
108 ssize_t spi_write (uchar *, int, uchar *, int);
109 ssize_t spi_xfer (size_t);
110
111 /* -------------------
112  * Variables
113  * ------------------- */
114
115 #define MAX_BUFFER      0x104
116
117 /* ----------------------------------------------------------------------
118  * Initially we place the RX and TX buffers at a fixed location in DPRAM!
119  * ---------------------------------------------------------------------- */
120 static uchar *rxbuf =
121   (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem
122                         [CONFIG_SYS_SPI_INIT_OFFSET];
123 static uchar *txbuf =
124   (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem
125                         [CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER];
126
127 /* **************************************************************************
128  *
129  *  Function:    spi_init_f
130  *
131  *  Description: Init SPI-Controller (ROM part)
132  *
133  *  return:      ---
134  *
135  * *********************************************************************** */
136 void spi_init_f (void)
137 {
138         unsigned int dpaddr;
139
140         volatile spi_t *spi;
141         volatile immap_t *immr;
142         volatile cpm8xx_t *cp;
143         volatile cbd_t *tbdf, *rbdf;
144
145         immr = (immap_t *)  CONFIG_SYS_IMMR;
146         cp   = (cpm8xx_t *) &immr->im_cpm;
147
148 #ifdef CONFIG_SYS_SPI_UCODE_PATCH
149         spi  = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
150 #else
151         spi  = (spi_t *)&cp->cp_dparam[PROFF_SPI];
152         /* Disable relocation */
153         spi->spi_rpbase = 0;
154 #endif
155
156 /* 1 */
157         /* ------------------------------------------------
158          * Initialize Port B SPI pins -> page 34-8 MPC860UM
159          * (we are only in Master Mode !)
160          * ------------------------------------------------ */
161
162         /* --------------------------------------------
163          * GPIO or per. Function
164          * PBPAR[28] = 1 [0x00000008] -> PERI: (SPIMISO)
165          * PBPAR[29] = 1 [0x00000004] -> PERI: (SPIMOSI)
166          * PBPAR[30] = 1 [0x00000002] -> PERI: (SPICLK)
167          * PBPAR[31] = 0 [0x00000001] -> GPIO: (CS for PCUE/CCM-EEPROM)
168          * -------------------------------------------- */
169         cp->cp_pbpar |=  0x0000000E;    /* set  bits    */
170         cp->cp_pbpar &= ~0x00000001;    /* reset bit    */
171
172         /* ----------------------------------------------
173          * In/Out or per. Function 0/1
174          * PBDIR[28] = 1 [0x00000008] -> PERI1: SPIMISO
175          * PBDIR[29] = 1 [0x00000004] -> PERI1: SPIMOSI
176          * PBDIR[30] = 1 [0x00000002] -> PERI1: SPICLK
177          * PBDIR[31] = 1 [0x00000001] -> GPIO OUT: CS for PCUE/CCM-EEPROM
178          * ---------------------------------------------- */
179         cp->cp_pbdir |= 0x0000000F;
180
181         /* ----------------------------------------------
182          * open drain or active output
183          * PBODR[28] = 1 [0x00000008] -> open drain: SPIMISO
184          * PBODR[29] = 0 [0x00000004] -> active output SPIMOSI
185          * PBODR[30] = 0 [0x00000002] -> active output: SPICLK
186          * PBODR[31] = 0 [0x00000001] -> active output: GPIO OUT: CS for PCUE/CCM
187          * ---------------------------------------------- */
188
189         cp->cp_pbodr |=  0x00000008;
190         cp->cp_pbodr &= ~0x00000007;
191
192         /* Initialize the parameter ram.
193          * We need to make sure many things are initialized to zero
194          */
195         spi->spi_rstate = 0;
196         spi->spi_rdp    = 0;
197         spi->spi_rbptr  = 0;
198         spi->spi_rbc    = 0;
199         spi->spi_rxtmp  = 0;
200         spi->spi_tstate = 0;
201         spi->spi_tdp    = 0;
202         spi->spi_tbptr  = 0;
203         spi->spi_tbc    = 0;
204         spi->spi_txtmp  = 0;
205
206         /* Allocate space for one transmit and one receive buffer
207          * descriptor in the DP ram
208          */
209 #ifdef CONFIG_SYS_ALLOC_DPRAM
210         dpaddr = dpram_alloc_align (sizeof(cbd_t)*2, 8);
211 #else
212         dpaddr = CPM_SPI_BASE;
213 #endif
214
215 /* 3 */
216         /* Set up the SPI parameters in the parameter ram */
217         spi->spi_rbase = dpaddr;
218         spi->spi_tbase = dpaddr + sizeof (cbd_t);
219
220         /***********IMPORTANT******************/
221
222         /*
223          * Setting transmit and receive buffer descriptor pointers
224          * initially to rbase and tbase. Only the microcode patches
225          * documentation talks about initializing this pointer. This
226          * is missing from the sample I2C driver. If you dont
227          * initialize these pointers, the kernel hangs.
228          */
229         spi->spi_rbptr = spi->spi_rbase;
230         spi->spi_tbptr = spi->spi_tbase;
231
232 /* 4 */
233 #ifdef CONFIG_SYS_SPI_UCODE_PATCH
234         /*
235          *  Initialize required parameters if using microcode patch.
236          */
237         spi->spi_rstate = 0;
238         spi->spi_tstate = 0;
239 #else
240         /* Init SPI Tx + Rx Parameters */
241         while (cp->cp_cpcr & CPM_CR_FLG)
242                 ;
243         cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SPI, CPM_CR_INIT_TRX) | CPM_CR_FLG;
244         while (cp->cp_cpcr & CPM_CR_FLG)
245                 ;
246 #endif  /* CONFIG_SYS_SPI_UCODE_PATCH */
247
248 /* 5 */
249         /* Set SDMA configuration register */
250         immr->im_siu_conf.sc_sdcr = 0x0001;
251
252 /* 6 */
253         /* Set to big endian. */
254         spi->spi_tfcr = SMC_EB;
255         spi->spi_rfcr = SMC_EB;
256
257 /* 7 */
258         /* Set maximum receive size. */
259         spi->spi_mrblr = MAX_BUFFER;
260
261 /* 8 + 9 */
262         /* tx and rx buffer descriptors */
263         tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
264         rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
265
266         tbdf->cbd_sc &= ~BD_SC_READY;
267         rbdf->cbd_sc &= ~BD_SC_EMPTY;
268
269         /* Set the bd's rx and tx buffer address pointers */
270         rbdf->cbd_bufaddr = (ulong) rxbuf;
271         tbdf->cbd_bufaddr = (ulong) txbuf;
272
273 /* 10 + 11 */
274         cp->cp_spim = 0;                        /* Mask  all SPI events */
275         cp->cp_spie = SPI_EMASK;                /* Clear all SPI events */
276
277         return;
278 }
279
280 /* **************************************************************************
281  *
282  *  Function:    spi_init_r
283  *
284  *  Description: Init SPI-Controller (RAM part) -
285  *               The malloc engine is ready and we can move our buffers to
286  *               normal RAM
287  *
288  *  return:      ---
289  *
290  * *********************************************************************** */
291 void spi_init_r (void)
292 {
293         volatile cpm8xx_t *cp;
294         volatile spi_t *spi;
295         volatile immap_t *immr;
296         volatile cbd_t *tbdf, *rbdf;
297
298         immr = (immap_t *)  CONFIG_SYS_IMMR;
299         cp   = (cpm8xx_t *) &immr->im_cpm;
300
301 #ifdef CONFIG_SYS_SPI_UCODE_PATCH
302         spi  = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
303 #else
304         spi  = (spi_t *)&cp->cp_dparam[PROFF_SPI];
305         /* Disable relocation */
306         spi->spi_rpbase = 0;
307 #endif
308
309         /* tx and rx buffer descriptors */
310         tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
311         rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
312
313         /* Allocate memory for RX and TX buffers */
314         rxbuf = (uchar *) malloc (MAX_BUFFER);
315         txbuf = (uchar *) malloc (MAX_BUFFER);
316
317         rbdf->cbd_bufaddr = (ulong) rxbuf;
318         tbdf->cbd_bufaddr = (ulong) txbuf;
319
320         return;
321 }
322
323 /****************************************************************************
324  *  Function:    spi_write
325  **************************************************************************** */
326 ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
327 {
328         int i;
329
330         memset(rxbuf, 0, MAX_BUFFER);
331         memset(txbuf, 0, MAX_BUFFER);
332         *txbuf = SPI_EEPROM_WREN;               /* write enable         */
333         spi_xfer(1);
334         memcpy(txbuf, addr, alen);
335         *txbuf = SPI_EEPROM_WRITE;              /* WRITE memory array   */
336         memcpy(alen + txbuf, buffer, len);
337         spi_xfer(alen + len);
338                                                 /* ignore received data */
339         for (i = 0; i < 1000; i++) {
340                 *txbuf = SPI_EEPROM_RDSR;       /* read status          */
341                 txbuf[1] = 0;
342                 spi_xfer(2);
343                 if (!(rxbuf[1] & 1)) {
344                         break;
345                 }
346                 udelay(1000);
347         }
348         if (i >= 1000) {
349                 printf ("*** spi_write: Time out while writing!\n");
350         }
351
352         return len;
353 }
354
355 /****************************************************************************
356  *  Function:    spi_read
357  **************************************************************************** */
358 ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
359 {
360         memset(rxbuf, 0, MAX_BUFFER);
361         memset(txbuf, 0, MAX_BUFFER);
362         memcpy(txbuf, addr, alen);
363         *txbuf = SPI_EEPROM_READ;               /* READ memory array    */
364
365         /*
366          * There is a bug in 860T (?) that cuts the last byte of input
367          * if we're reading into DPRAM. The solution we choose here is
368          * to always read len+1 bytes (we have one extra byte at the
369          * end of the buffer).
370          */
371         spi_xfer(alen + len + 1);
372         memcpy(buffer, alen + rxbuf, len);
373
374         return len;
375 }
376
377 /****************************************************************************
378  *  Function:    spi_xfer
379  **************************************************************************** */
380 ssize_t spi_xfer (size_t count)
381 {
382         volatile immap_t *immr;
383         volatile cpm8xx_t *cp;
384         volatile spi_t *spi;
385         cbd_t *tbdf, *rbdf;
386         ushort loop;
387         int tm;
388
389         DPRINT (("*** spi_xfer entered ***\n"));
390
391         immr = (immap_t *) CONFIG_SYS_IMMR;
392         cp   = (cpm8xx_t *) &immr->im_cpm;
393
394 #ifdef CONFIG_SYS_SPI_UCODE_PATCH
395         spi  = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
396 #else
397         spi  = (spi_t *)&cp->cp_dparam[PROFF_SPI];
398         /* Disable relocation */
399         spi->spi_rpbase = 0;
400 #endif
401
402         tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
403         rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
404
405         /* Set CS for device */
406         cp->cp_pbdat &= ~0x0001;
407
408         /* Setting tx bd status and data length */
409         tbdf->cbd_sc  = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP;
410         tbdf->cbd_datlen = count;
411
412         DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n",
413                                                         tbdf->cbd_datlen));
414
415         /* Setting rx bd status and data length */
416         rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
417         rbdf->cbd_datlen = 0;    /* rx length has no significance */
418
419         loop = cp->cp_spmode & SPMODE_LOOP;
420         cp->cp_spmode = /*SPMODE_DIV16  |*/     /* BRG/16 mode not used here */
421                         loop            |
422                         SPMODE_REV      |
423                         SPMODE_MSTR     |
424                         SPMODE_EN       |
425                         SPMODE_LEN(8)   |       /* 8 Bits per char */
426                         SPMODE_PM(0x8) ;        /* medium speed */
427         cp->cp_spim = 0;                        /* Mask  all SPI events */
428         cp->cp_spie = SPI_EMASK;                /* Clear all SPI events */
429
430         /* start spi transfer */
431         DPRINT (("*** spi_xfer: Performing transfer ...\n"));
432         cp->cp_spcom |= SPI_STR;                /* Start transmit */
433
434         /* --------------------------------
435          * Wait for SPI transmit to get out
436          * or time out (1 second = 1000 ms)
437          * -------------------------------- */
438         for (tm=0; tm<1000; ++tm) {
439                 if (cp->cp_spie & SPI_TXB) {    /* Tx Buffer Empty */
440                         DPRINT (("*** spi_xfer: Tx buffer empty\n"));
441                         break;
442                 }
443                 if ((tbdf->cbd_sc & BD_SC_READY) == 0) {
444                         DPRINT (("*** spi_xfer: Tx BD done\n"));
445                         break;
446                 }
447                 udelay (1000);
448         }
449         if (tm >= 1000) {
450                 printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
451         }
452         DPRINT (("*** spi_xfer: ... transfer ended\n"));
453
454 #ifdef  DEBUG
455         printf ("\nspi_xfer: txbuf after xfer\n");
456         memdump ((void *) txbuf, 16);   /* dump of txbuf before transmit */
457         printf ("spi_xfer: rxbuf after xfer\n");
458         memdump ((void *) rxbuf, 16);   /* dump of rxbuf after transmit */
459         printf ("\n");
460 #endif
461
462         /* Clear CS for device */
463         cp->cp_pbdat |= 0x0001;
464
465         return count;
466 }
467 #endif  /* CONFIG_SPI || (CONFIG_POST & CONFIG_SYS_POST_SPI) */
468
469 /*
470  * SPI test
471  *
472  * The Serial Peripheral Interface (SPI) is tested in the local loopback mode.
473  * The interface is configured accordingly and several packets
474  * are transfered. The configurable test parameters are:
475  *   TEST_MIN_LENGTH - minimum size of packet to transfer
476  *   TEST_MAX_LENGTH - maximum size of packet to transfer
477  *   TEST_NUM - number of tests
478  */
479
480 #if CONFIG_POST & CONFIG_SYS_POST_SPI
481
482 #define TEST_MIN_LENGTH         1
483 #define TEST_MAX_LENGTH         MAX_BUFFER
484 #define TEST_NUM                1
485
486 static void packet_fill (char * packet, int length)
487 {
488         char c = (char) length;
489         int i;
490
491         for (i = 0; i < length; i++)
492         {
493             packet[i] = c++;
494         }
495 }
496
497 static int packet_check (char * packet, int length)
498 {
499         char c = (char) length;
500         int i;
501
502         for (i = 0; i < length; i++) {
503             if (packet[i] != c++) return -1;
504         }
505
506         return 0;
507 }
508
509 int spi_post_test (int flags)
510 {
511         int res = -1;
512         volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
513         volatile cpm8xx_t *cp = (cpm8xx_t *) & immr->im_cpm;
514         int i;
515         int l;
516
517         spi_init_f ();
518         spi_init_r ();
519
520         cp->cp_spmode |= SPMODE_LOOP;
521
522         for (i = 0; i < TEST_NUM; i++) {
523                 for (l = TEST_MIN_LENGTH; l <= TEST_MAX_LENGTH; l += 8) {
524                         packet_fill ((char *)txbuf, l);
525
526                         spi_xfer (l);
527
528                         if (packet_check ((char *)rxbuf, l) < 0) {
529                                 goto Done;
530                         }
531                 }
532         }
533
534         res = 0;
535
536       Done:
537
538         cp->cp_spmode &= ~SPMODE_LOOP;
539
540         /*
541          * SCC2 parameter RAM space overlaps
542          * the SPI parameter RAM space. So we need to restore
543          * the SCC2 configuration if it is used by UART.
544          */
545
546 #if !defined(CONFIG_8xx_CONS_NONE)
547         serial_reinit_all ();
548 #endif
549
550         if (res != 0) {
551                 post_log ("SPI test failed\n");
552         }
553
554         return res;
555 }
556 #endif  /* CONFIG_POST & CONFIG_SYS_POST_SPI */