1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#include <common.h>
37#include <asm/cpm_8260.h>
38#include <linux/ctype.h>
39#include <malloc.h>
40#include <post.h>
41#include <net.h>
42
43#if defined(CONFIG_SPI)
44
45
46
47
48
49
50
51#undef DEBUG
52
53#define SPI_EEPROM_WREN 0x06
54#define SPI_EEPROM_RDSR 0x05
55#define SPI_EEPROM_READ 0x03
56#define SPI_EEPROM_WRITE 0x02
57
58
59
60
61
62
63
64
65
66#ifndef CONFIG_SYS_SPI_INIT_OFFSET
67#define CONFIG_SYS_SPI_INIT_OFFSET 0x2000
68#endif
69
70#define CPM_SPI_BASE 0x100
71
72#ifdef DEBUG
73
74#define DPRINT(a) printf a;
75
76
77
78static const char * const hex_digit = "0123456789ABCDEF";
79
80static char quickhex (int i)
81{
82 return hex_digit[i];
83}
84
85static void memdump (void *pv, int num)
86{
87 int i;
88 unsigned char *pc = (unsigned char *) pv;
89
90 for (i = 0; i < num; i++)
91 printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
92 printf ("\t");
93 for (i = 0; i < num; i++)
94 printf ("%c", isprint (pc[i]) ? pc[i] : '.');
95 printf ("\n");
96}
97#else
98
99#define DPRINT(a)
100
101#endif
102
103
104
105
106void spi_init (void);
107
108ssize_t spi_read (uchar *, int, uchar *, int);
109ssize_t spi_write (uchar *, int, uchar *, int);
110ssize_t spi_xfer (size_t);
111
112
113
114
115
116#define MAX_BUFFER 0x104
117
118
119
120
121static uchar *rxbuf =
122 (uchar *)&((immap_t *)CONFIG_SYS_IMMR)->im_dprambase
123 [CONFIG_SYS_SPI_INIT_OFFSET];
124static uchar *txbuf =
125 (uchar *)&((immap_t *)CONFIG_SYS_IMMR)->im_dprambase
126 [CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER];
127
128
129
130
131
132
133
134
135
136
137void spi_init_f (void)
138{
139 unsigned int dpaddr;
140
141 volatile spi_t *spi;
142 volatile immap_t *immr;
143 volatile cpm8260_t *cp;
144 volatile cbd_t *tbdf, *rbdf;
145
146 immr = (immap_t *) CONFIG_SYS_IMMR;
147 cp = (cpm8260_t *) &immr->im_cpm;
148
149 *(ushort *)(&immr->im_dprambase[PROFF_SPI_BASE]) = PROFF_SPI;
150 spi = (spi_t *)&immr->im_dprambase[PROFF_SPI];
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 immr->im_ioport.iop_ppard |= 0x0000E000;
166 immr->im_ioport.iop_ppard &= ~0x00080000;
167
168
169
170
171
172
173
174
175 immr->im_ioport.iop_pdird &= ~0x0000E000;
176 immr->im_ioport.iop_pdird |= 0x00080000;
177
178
179
180
181
182
183
184 immr->im_ioport.iop_psord |= 0x0000E000;
185
186
187
188
189 spi->spi_rstate = 0;
190 spi->spi_rdp = 0;
191 spi->spi_rbptr = 0;
192 spi->spi_rbc = 0;
193 spi->spi_rxtmp = 0;
194 spi->spi_tstate = 0;
195 spi->spi_tdp = 0;
196 spi->spi_tbptr = 0;
197 spi->spi_tbc = 0;
198 spi->spi_txtmp = 0;
199
200
201
202
203#ifdef CONFIG_SYS_ALLOC_DPRAM
204 dpaddr = m8260_cpm_dpalloc (sizeof(cbd_t)*2, 8);
205#else
206 dpaddr = CPM_SPI_BASE;
207#endif
208
209
210
211 spi->spi_rbase = dpaddr;
212 spi->spi_tbase = dpaddr + sizeof (cbd_t);
213
214
215
216
217
218
219
220
221
222
223 spi->spi_rbptr = spi->spi_rbase;
224 spi->spi_tbptr = spi->spi_tbase;
225
226
227
228 while (cp->cp_cpcr & CPM_CR_FLG)
229 ;
230 cp->cp_cpcr = mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK,
231 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
232 while (cp->cp_cpcr & CPM_CR_FLG)
233 ;
234
235
236
237 spi->spi_tfcr = CPMFCR_EB;
238 spi->spi_rfcr = CPMFCR_EB;
239
240
241
242 spi->spi_mrblr = MAX_BUFFER;
243
244
245
246 tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
247 rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
248
249 tbdf->cbd_sc &= ~BD_SC_READY;
250 rbdf->cbd_sc &= ~BD_SC_EMPTY;
251
252
253 rbdf->cbd_bufaddr = (ulong) rxbuf;
254 tbdf->cbd_bufaddr = (ulong) txbuf;
255
256
257 immr->im_spi.spi_spie = SPI_EMASK;
258 immr->im_spi.spi_spim = 0x00;
259
260
261 return;
262}
263
264
265
266
267
268
269
270
271
272
273
274
275void spi_init_r (void)
276{
277 volatile spi_t *spi;
278 volatile immap_t *immr;
279 volatile cpm8260_t *cp;
280 volatile cbd_t *tbdf, *rbdf;
281
282 immr = (immap_t *) CONFIG_SYS_IMMR;
283 cp = (cpm8260_t *) &immr->im_cpm;
284
285 spi = (spi_t *)&immr->im_dprambase[PROFF_SPI];
286
287
288 tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
289 rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
290
291
292 rxbuf = (uchar *) malloc (MAX_BUFFER);
293 txbuf = (uchar *) malloc (MAX_BUFFER);
294
295 rbdf->cbd_bufaddr = (ulong) rxbuf;
296 tbdf->cbd_bufaddr = (ulong) txbuf;
297
298 return;
299}
300
301
302
303
304ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
305{
306 int i;
307
308 memset(rxbuf, 0, MAX_BUFFER);
309 memset(txbuf, 0, MAX_BUFFER);
310 *txbuf = SPI_EEPROM_WREN;
311 spi_xfer(1);
312 memcpy(txbuf, addr, alen);
313 *txbuf = SPI_EEPROM_WRITE;
314 memcpy(alen + txbuf, buffer, len);
315 spi_xfer(alen + len);
316
317 for (i = 0; i < 1000; i++) {
318 *txbuf = SPI_EEPROM_RDSR;
319 txbuf[1] = 0;
320 spi_xfer(2);
321 if (!(rxbuf[1] & 1)) {
322 break;
323 }
324 udelay(1000);
325 }
326 if (i >= 1000) {
327 printf ("*** spi_write: Time out while writing!\n");
328 }
329
330 return len;
331}
332
333
334
335
336ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
337{
338 memset(rxbuf, 0, MAX_BUFFER);
339 memset(txbuf, 0, MAX_BUFFER);
340 memcpy(txbuf, addr, alen);
341 *txbuf = SPI_EEPROM_READ;
342
343
344
345
346
347
348
349 spi_xfer(alen + len + 1);
350 memcpy(buffer, alen + rxbuf, len);
351
352 return len;
353}
354
355
356
357
358ssize_t spi_xfer (size_t count)
359{
360 volatile immap_t *immr;
361 volatile cpm8260_t *cp;
362 volatile spi_t *spi;
363 cbd_t *tbdf, *rbdf;
364 int tm;
365
366 DPRINT (("*** spi_xfer entered ***\n"));
367
368 immr = (immap_t *) CONFIG_SYS_IMMR;
369 cp = (cpm8260_t *) &immr->im_cpm;
370
371 spi = (spi_t *)&immr->im_dprambase[PROFF_SPI];
372
373 tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
374 rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
375
376
377 immr->im_ioport.iop_pdatd &= ~0x00080000;
378
379
380 tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP;
381 tbdf->cbd_datlen = count;
382
383 DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n",
384 tbdf->cbd_datlen));
385
386
387 rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
388 rbdf->cbd_datlen = 0;
389
390 immr->im_spi.spi_spmode = SPMODE_REV |
391 SPMODE_MSTR |
392 SPMODE_EN |
393 SPMODE_LEN(8) |
394 SPMODE_PM(0x8) ;
395 immr->im_spi.spi_spie = SPI_EMASK;
396 immr->im_spi.spi_spim = 0x00;
397
398
399 DPRINT (("*** spi_xfer: Performing transfer ...\n"));
400 immr->im_spi.spi_spcom |= SPI_STR;
401
402
403
404
405
406 for (tm=0; tm<1000; ++tm) {
407 if (immr->im_spi.spi_spie & SPI_TXB) {
408 DPRINT (("*** spi_xfer: Tx buffer empty\n"));
409 break;
410 }
411 if ((tbdf->cbd_sc & BD_SC_READY) == 0) {
412 DPRINT (("*** spi_xfer: Tx BD done\n"));
413 break;
414 }
415 udelay (1000);
416 }
417 if (tm >= 1000) {
418 printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
419 }
420 DPRINT (("*** spi_xfer: ... transfer ended\n"));
421
422#ifdef DEBUG
423 printf ("\nspi_xfer: txbuf after xfer\n");
424 memdump ((void *) txbuf, 16);
425 printf ("spi_xfer: rxbuf after xfer\n");
426 memdump ((void *) rxbuf, 16);
427 printf ("\n");
428#endif
429
430
431 immr->im_ioport.iop_pdatd |= 0x00080000;
432
433 return count;
434}
435#endif
436