odroid: remove CONFIG_DM_I2C_COMPAT config
[platform/kernel/u-boot.git] / arch / powerpc / cpu / mpc8260 / 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-2003 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 /*
12  * MPC8260 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  */
19
20 #include <common.h>
21 #include <asm/cpm_8260.h>
22 #include <linux/ctype.h>
23 #include <malloc.h>
24 #include <post.h>
25 #include <net.h>
26
27 #if defined(CONFIG_SPI)
28
29 /* Warning:
30  * You cannot enable DEBUG for early system initalization, i. e. when
31  * this driver is used to read environment parameters like "baudrate"
32  * from EEPROM which are used to initialize the serial port which is
33  * needed to print the debug messages...
34  */
35 #undef  DEBUG
36
37 #define SPI_EEPROM_WREN         0x06
38 #define SPI_EEPROM_RDSR         0x05
39 #define SPI_EEPROM_READ         0x03
40 #define SPI_EEPROM_WRITE        0x02
41
42 /* ---------------------------------------------------------------
43  * Offset for initial SPI buffers in DPRAM:
44  * We need a 520 byte scratch DPRAM area to use at an early stage.
45  * It is used between the two initialization calls (spi_init_f()
46  * and spi_init_r()).
47  * The value 0x2000 makes it far enough from the start of the data
48  * area (as well as from the stack pointer).
49  * --------------------------------------------------------------- */
50 #ifndef CONFIG_SYS_SPI_INIT_OFFSET
51 #define CONFIG_SYS_SPI_INIT_OFFSET      0x2000
52 #endif
53
54 #define CPM_SPI_BASE 0x100
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
64 static char quickhex (int i)
65 {
66         return hex_digit[i];
67 }
68
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  * Variables
98  * ------------------- */
99
100 #define MAX_BUFFER      0x104
101
102 /* ----------------------------------------------------------------------
103  * Initially we place the RX and TX buffers at a fixed location in DPRAM!
104  * ---------------------------------------------------------------------- */
105 static uchar *rxbuf =
106   (uchar *)&((immap_t *)CONFIG_SYS_IMMR)->im_dprambase
107                         [CONFIG_SYS_SPI_INIT_OFFSET];
108 static uchar *txbuf =
109   (uchar *)&((immap_t *)CONFIG_SYS_IMMR)->im_dprambase
110                         [CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER];
111
112 /* **************************************************************************
113  *
114  *  Function:    spi_init_f
115  *
116  *  Description: Init SPI-Controller (ROM part)
117  *
118  *  return:      ---
119  *
120  * *********************************************************************** */
121 void spi_init_f (void)
122 {
123         unsigned int dpaddr;
124
125         volatile spi_t *spi;
126         volatile immap_t *immr;
127         volatile cpm8260_t *cp;
128         volatile cbd_t *tbdf, *rbdf;
129
130         immr = (immap_t *)  CONFIG_SYS_IMMR;
131         cp   = (cpm8260_t *) &immr->im_cpm;
132
133         immr->im_dprambase16[PROFF_SPI_BASE / sizeof(u16)] = PROFF_SPI;
134         spi  = (spi_t *)&immr->im_dprambase[PROFF_SPI];
135
136 /* 1 */
137         /* ------------------------------------------------
138          * Initialize Port D SPI pins
139          * (we are only in Master Mode !)
140          * ------------------------------------------------ */
141
142         /* --------------------------------------------
143          * GPIO or per. Function
144          * PPARD[16] = 1 [0x00008000] (SPIMISO)
145          * PPARD[17] = 1 [0x00004000] (SPIMOSI)
146          * PPARD[18] = 1 [0x00002000] (SPICLK)
147          * PPARD[12] = 0 [0x00080000] -> GPIO: (CS for ATC EEPROM)
148          * -------------------------------------------- */
149         immr->im_ioport.iop_ppard |=  0x0000E000;       /* set  bits    */
150         immr->im_ioport.iop_ppard &= ~0x00080000;       /* reset bit    */
151
152         /* ----------------------------------------------
153          * In/Out or per. Function 0/1
154          * PDIRD[16] = 0 [0x00008000] -> PERI1: SPIMISO
155          * PDIRD[17] = 0 [0x00004000] -> PERI1: SPIMOSI
156          * PDIRD[18] = 0 [0x00002000] -> PERI1: SPICLK
157          * PDIRD[12] = 1 [0x00080000] -> GPIO OUT: CS for ATC EEPROM
158          * ---------------------------------------------- */
159         immr->im_ioport.iop_pdird &= ~0x0000E000;
160         immr->im_ioport.iop_pdird |= 0x00080000;
161
162         /* ----------------------------------------------
163          * special option reg.
164          * PSORD[16] = 1 [0x00008000] -> SPIMISO
165          * PSORD[17] = 1 [0x00004000] -> SPIMOSI
166          * PSORD[18] = 1 [0x00002000] -> SPICLK
167          * ---------------------------------------------- */
168         immr->im_ioport.iop_psord |= 0x0000E000;
169
170         /* Initialize the parameter ram.
171          * We need to make sure many things are initialized to zero
172          */
173         spi->spi_rstate = 0;
174         spi->spi_rdp    = 0;
175         spi->spi_rbptr  = 0;
176         spi->spi_rbc    = 0;
177         spi->spi_rxtmp  = 0;
178         spi->spi_tstate = 0;
179         spi->spi_tdp    = 0;
180         spi->spi_tbptr  = 0;
181         spi->spi_tbc    = 0;
182         spi->spi_txtmp  = 0;
183
184         dpaddr = CPM_SPI_BASE;
185
186 /* 3 */
187         /* Set up the SPI parameters in the parameter ram */
188         spi->spi_rbase = dpaddr;
189         spi->spi_tbase = dpaddr + sizeof (cbd_t);
190
191         /***********IMPORTANT******************/
192
193         /*
194          * Setting transmit and receive buffer descriptor pointers
195          * initially to rbase and tbase. Only the microcode patches
196          * documentation talks about initializing this pointer. This
197          * is missing from the sample I2C driver. If you dont
198          * initialize these pointers, the kernel hangs.
199          */
200         spi->spi_rbptr = spi->spi_rbase;
201         spi->spi_tbptr = spi->spi_tbase;
202
203 /* 4 */
204         /* Init SPI Tx + Rx Parameters */
205         while (cp->cp_cpcr & CPM_CR_FLG)
206                 ;
207         cp->cp_cpcr = mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK,
208                                                         0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
209         while (cp->cp_cpcr & CPM_CR_FLG)
210                 ;
211
212 /* 6 */
213         /* Set to big endian. */
214         spi->spi_tfcr = CPMFCR_EB;
215         spi->spi_rfcr = CPMFCR_EB;
216
217 /* 7 */
218         /* Set maximum receive size. */
219         spi->spi_mrblr = MAX_BUFFER;
220
221 /* 8 + 9 */
222         /* tx and rx buffer descriptors */
223         tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
224         rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
225
226         tbdf->cbd_sc &= ~BD_SC_READY;
227         rbdf->cbd_sc &= ~BD_SC_EMPTY;
228
229         /* Set the bd's rx and tx buffer address pointers */
230         rbdf->cbd_bufaddr = (ulong) rxbuf;
231         tbdf->cbd_bufaddr = (ulong) txbuf;
232
233 /* 10 + 11 */
234         immr->im_spi.spi_spie = SPI_EMASK;              /* Clear all SPI events */
235         immr->im_spi.spi_spim = 0x00;                   /* Mask  all SPI events */
236
237
238         return;
239 }
240
241 /* **************************************************************************
242  *
243  *  Function:    spi_init_r
244  *
245  *  Description: Init SPI-Controller (RAM part) -
246  *               The malloc engine is ready and we can move our buffers to
247  *               normal RAM
248  *
249  *  return:      ---
250  *
251  * *********************************************************************** */
252 void spi_init_r (void)
253 {
254         volatile spi_t *spi;
255         volatile immap_t *immr;
256         volatile cbd_t *tbdf, *rbdf;
257
258         immr = (immap_t *)  CONFIG_SYS_IMMR;
259
260         spi  = (spi_t *)&immr->im_dprambase[PROFF_SPI];
261
262         /* tx and rx buffer descriptors */
263         tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
264         rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
265
266         /* Allocate memory for RX and TX buffers */
267         rxbuf = (uchar *) malloc (MAX_BUFFER);
268         txbuf = (uchar *) malloc (MAX_BUFFER);
269
270         rbdf->cbd_bufaddr = (ulong) rxbuf;
271         tbdf->cbd_bufaddr = (ulong) txbuf;
272
273         return;
274 }
275
276 /****************************************************************************
277  *  Function:    spi_write
278  **************************************************************************** */
279 ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
280 {
281         int i;
282
283         memset(rxbuf, 0, MAX_BUFFER);
284         memset(txbuf, 0, MAX_BUFFER);
285         *txbuf = SPI_EEPROM_WREN;               /* write enable         */
286         spi_xfer(1);
287         memcpy(txbuf, addr, alen);
288         *txbuf = SPI_EEPROM_WRITE;              /* WRITE memory array   */
289         memcpy(alen + txbuf, buffer, len);
290         spi_xfer(alen + len);
291                                                 /* ignore received data */
292         for (i = 0; i < 1000; i++) {
293                 *txbuf = SPI_EEPROM_RDSR;       /* read status          */
294                 txbuf[1] = 0;
295                 spi_xfer(2);
296                 if (!(rxbuf[1] & 1)) {
297                         break;
298                 }
299                 udelay(1000);
300         }
301         if (i >= 1000) {
302                 printf ("*** spi_write: Time out while writing!\n");
303         }
304
305         return len;
306 }
307
308 /****************************************************************************
309  *  Function:    spi_read
310  **************************************************************************** */
311 ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
312 {
313         memset(rxbuf, 0, MAX_BUFFER);
314         memset(txbuf, 0, MAX_BUFFER);
315         memcpy(txbuf, addr, alen);
316         *txbuf = SPI_EEPROM_READ;               /* READ memory array    */
317
318         /*
319          * There is a bug in 860T (?) that cuts the last byte of input
320          * if we're reading into DPRAM. The solution we choose here is
321          * to always read len+1 bytes (we have one extra byte at the
322          * end of the buffer).
323          */
324         spi_xfer(alen + len + 1);
325         memcpy(buffer, alen + rxbuf, len);
326
327         return len;
328 }
329
330 /****************************************************************************
331  *  Function:    spi_xfer
332  **************************************************************************** */
333 ssize_t spi_xfer (size_t count)
334 {
335         volatile immap_t *immr;
336         volatile spi_t *spi;
337         cbd_t *tbdf, *rbdf;
338         int tm;
339
340         DPRINT (("*** spi_xfer entered ***\n"));
341
342         immr = (immap_t *) CONFIG_SYS_IMMR;
343
344         spi  = (spi_t *)&immr->im_dprambase[PROFF_SPI];
345
346         tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
347         rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
348
349         /* Board-specific: Set CS for device (ATC EEPROM) */
350         immr->im_ioport.iop_pdatd &= ~0x00080000;
351
352         /* Setting tx bd status and data length */
353         tbdf->cbd_sc  = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP;
354         tbdf->cbd_datlen = count;
355
356         DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n",
357                                                         tbdf->cbd_datlen));
358
359         /* Setting rx bd status and data length */
360         rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
361         rbdf->cbd_datlen = 0;    /* rx length has no significance */
362
363         immr->im_spi.spi_spmode = SPMODE_REV    |
364                         SPMODE_MSTR     |
365                         SPMODE_EN       |
366                         SPMODE_LEN(8)   |       /* 8 Bits per char */
367                         SPMODE_PM(0x8) ;        /* medium speed */
368         immr->im_spi.spi_spie = SPI_EMASK;              /* Clear all SPI events */
369         immr->im_spi.spi_spim = 0x00;                   /* Mask  all SPI events */
370
371         /* start spi transfer */
372         DPRINT (("*** spi_xfer: Performing transfer ...\n"));
373         immr->im_spi.spi_spcom |= SPI_STR;              /* Start transmit */
374
375         /* --------------------------------
376          * Wait for SPI transmit to get out
377          * or time out (1 second = 1000 ms)
378          * -------------------------------- */
379         for (tm=0; tm<1000; ++tm) {
380                 if (immr->im_spi.spi_spie & SPI_TXB) {  /* Tx Buffer Empty */
381                         DPRINT (("*** spi_xfer: Tx buffer empty\n"));
382                         break;
383                 }
384                 if ((tbdf->cbd_sc & BD_SC_READY) == 0) {
385                         DPRINT (("*** spi_xfer: Tx BD done\n"));
386                         break;
387                 }
388                 udelay (1000);
389         }
390         if (tm >= 1000) {
391                 printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
392         }
393         DPRINT (("*** spi_xfer: ... transfer ended\n"));
394
395 #ifdef  DEBUG
396         printf ("\nspi_xfer: txbuf after xfer\n");
397         memdump ((void *) txbuf, 16);   /* dump of txbuf before transmit */
398         printf ("spi_xfer: rxbuf after xfer\n");
399         memdump ((void *) rxbuf, 16);   /* dump of rxbuf after transmit */
400         printf ("\n");
401 #endif
402
403         /* Clear CS for device */
404         immr->im_ioport.iop_pdatd |= 0x00080000;
405
406         return count;
407 }
408 #endif  /* CONFIG_SPI */