]> git.sur5r.net Git - u-boot/blob - board/spc1920/hpi.c
687c170a85084bafa2018f0cc44479c85180b757
[u-boot] / board / spc1920 / hpi.c
1 /*
2  * (C) Copyright 2006
3  * Markus Klotzbuecher, DENX Software Engineering, mk@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * Host Port Interface (HPI)
26  */
27
28 /* debug levels:
29  *  0 : errors
30  *  1 : usefull info
31  *  2 : lots of info
32  *  3 : noisy
33  */
34
35 #define DEBUG 0
36
37 #include <config.h>
38 #include <common.h>
39 #include <mpc8xx.h>
40
41 #include "pld.h"
42 #include "hpi.h"
43 #include "spc1920.h" /* led function */
44
45 #define _NOT_USED_      0xFFFFFFFF
46
47 /* original table:
48  * - inserted loops to achieve long CS low and high Periods (~217ns)
49  * - move cs high 2/4 to the right
50  */
51 const uint dsp_table_slow[] =
52 {
53         /* single read   (offset  0x00 in upm ram) */
54         0x8fffdc04, 0x0fffdc84, 0x0fffdc84, 0x0fffdc00,
55         0x3fffdc04, 0xffffdc84, 0xffffdc84, 0xffffdc05,
56
57         /* burst read    (offset 0x08 in upm ram) */
58         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
59         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
60         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
61         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
62
63         /* single write  (offset 0x18 in upm ram) */
64         0x8fffd004, 0x0fffd084, 0x0fffd084, 0x3fffd000,
65         0xffffd084, 0xffffd084, 0xffffd005, _NOT_USED_,
66
67         /* burst write   (offset 0x20 in upm ram) */
68         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
69         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
70         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
71         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
72         /* refresh       (offset 0x30 in upm ram) */
73         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
74         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
75         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
76         /* exception     (offset 0x3C in upm ram) */
77         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
78 };
79
80 /* dsp hpi upm ram table
81  * works fine for noninc access, failes on incremental.
82  * - removed first word
83  */
84 const uint dsp_table_fast[] =
85 {
86         /* single read   (offset  0x00 in upm ram) */
87         0x8fffdc04, 0x0fffdc04, 0x0fffdc00, 0x3fffdc04,
88         0xffffdc05, _NOT_USED_, _NOT_USED_, _NOT_USED_,
89
90         /* burst read    (offset 0x08 in upm ram) */
91         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
92         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
93         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
94         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
95
96         /* single write  (offset 0x18 in upm ram) */
97         0x8fffd004, 0x0fffd004, 0x3fffd000, 0xffffd005,
98         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
99
100         /* burst write   (offset 0x20 in upm ram) */
101         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
102         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
103         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
104         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
105         /* refresh       (offset 0x30 in upm ram) */
106         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
107         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
108         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
109         /* exception     (offset 0x3C in upm ram) */
110         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
111 };
112
113
114 #ifdef CONFIG_SPC1920_HPI_TEST
115 #undef HPI_TEST_OSZI
116
117 #define HPI_TEST_CHUNKSIZE      0x1000
118 #define HPI_TEST_PATTERN        0x00000000
119 #define HPI_TEST_START          0x0
120 #define HPI_TEST_END            0x30000
121
122 #define TINY_AUTOINC_DATA_SIZE 16 /* 32bit words */
123 #define TINY_AUTOINC_BASE_ADDR 0x0
124
125 static int hpi_activate(void);
126 static void hpi_inactivate(void);
127 static void dsp_reset(void);
128
129 static int hpi_write_inc(u32 addr, u32 *data, u32 count);
130 static int hpi_read_inc(u32 addr, u32 *buf, u32 count);
131 static int hpi_write_noinc(u32 addr, u32 data);
132 static u32 hpi_read_noinc(u32 addr);
133
134 int hpi_test(void);
135 static int hpi_write_addr_test(u32 addr);
136 static int hpi_read_write_test(u32 addr, u32 data);
137 static int hpi_tiny_autoinc_test(void);
138 #endif /* CONFIG_SPC1920_HPI_TEST */
139
140
141 /* init the host port interface on UPMA */
142 int hpi_init(void)
143 {
144         volatile immap_t *immr = (immap_t *) CFG_IMMR;
145         volatile memctl8xx_t *memctl = &immr->im_memctl;
146         volatile spc1920_pld_t *pld = (spc1920_pld_t *) CFG_SPC1920_PLD_BASE;
147
148         upmconfig(UPMA, (uint *)dsp_table_slow, sizeof(dsp_table_slow)/sizeof(uint));
149         udelay(100);
150
151         memctl->memc_mamr = CFG_MAMR;
152         memctl->memc_or3 = CFG_OR3_PRELIM;
153         memctl->memc_br3 = CFG_BR3_PRELIM;
154
155         /* reset dsp */
156         dsp_reset();
157
158         /* activate hpi switch*/
159         pld->dsp_hpi_on = 0x1;
160
161         udelay(100);
162
163         return 0;
164 }
165
166 #ifdef CONFIG_SPC1920_HPI_TEST
167 /* activate the Host Port interface */
168 static int hpi_activate(void)
169 {
170         volatile spc1920_pld_t *pld = (spc1920_pld_t *) CFG_SPC1920_PLD_BASE;
171
172         /* turn on hpi */
173         pld->dsp_hpi_on = 0x1;
174
175         udelay(5);
176
177         /* turn on the power EN_DSP_POWER high*/
178         /* currently always on TBD */
179
180         /* setup hpi control register */
181         HPI_HPIC_1 = (u16) 0x0008;
182         HPI_HPIC_2 = (u16) 0x0008;
183
184         udelay(100);
185
186         return 0;
187 }
188
189 /* turn off the host port interface */
190 static void hpi_inactivate(void)
191 {
192         volatile spc1920_pld_t *pld = (spc1920_pld_t *) CFG_SPC1920_PLD_BASE;
193
194         /* deactivate hpi */
195         pld->dsp_hpi_on = 0x0;
196
197         /* reset the dsp */
198         /* pld->dsp_reset = 0x0; */
199
200         /* turn off the power EN_DSP_POWER# high*/
201         /* currently always on TBD */
202
203 }
204
205 /* reset the DSP */
206 static void dsp_reset(void)
207 {
208         volatile spc1920_pld_t *pld = (spc1920_pld_t *) CFG_SPC1920_PLD_BASE;
209         pld->dsp_reset = 0x1;
210         pld->dsp_hpi_on = 0x0;
211
212         udelay(300000);
213
214         pld->dsp_reset = 0x0;
215         pld->dsp_hpi_on = 0x1;
216 }
217
218
219 /* write using autoinc (count is number of 32bit words) */
220 static int hpi_write_inc(u32 addr, u32 *data, u32 count)
221 {
222         int i;
223         u16 addr1, addr2;
224
225         addr1 = (u16) ((addr >> 16) & 0xffff); /* First HW is most significant */
226         addr2 = (u16) (addr & 0xffff);
227
228         /* write address */
229         HPI_HPIA_1 = addr1;
230         HPI_HPIA_2 = addr2;
231
232         debugX(4, "writing from data=0x%x to 0x%x\n", data, (data+count));
233
234         for(i=0; i<count; i++) {
235                 HPI_HPID_INC_1 = (u16) ((data[i] >> 16) & 0xffff);
236                 HPI_HPID_INC_2 = (u16) (data[i] & 0xffff);
237                 debugX(4, "hpi_write_inc: data1=0x%x, data2=0x%x\n",
238                        (u16) ((data[i] >> 16) & 0xffff),
239                        (u16) (data[i] & 0xffff));
240         }
241 #if 0
242         while(data_ptr < (u16*) (data + count)) {
243                 HPI_HPID_INC_1 = *(data_ptr++);
244                 HPI_HPID_INC_2 = *(data_ptr++);
245         }
246 #endif
247
248         /* return number of bytes written */
249         return count;
250 }
251
252 /*
253  * read using autoinc (count is number of 32bit words)
254  */
255 static int hpi_read_inc(u32 addr, u32 *buf, u32 count)
256 {
257         int i;
258         u16 addr1, addr2, data1, data2;
259
260         addr1 = (u16) ((addr >> 16) & 0xffff); /* First HW is most significant */
261         addr2 = (u16) (addr & 0xffff);
262
263         /* write address */
264         HPI_HPIA_1 = addr1;
265         HPI_HPIA_2 = addr2;
266
267         for(i=0; i<count; i++) {
268                 data1 = HPI_HPID_INC_1;
269                 data2 = HPI_HPID_INC_2;
270                 debugX(4, "hpi_read_inc: data1=0x%x, data2=0x%x\n", data1, data2);
271                 buf[i] = (((u32) data1) << 16) | (data2 & 0xffff);
272         }
273
274 #if 0
275         while(buf_ptr < (u16*) (buf + count)) {
276                 *(buf_ptr++) = HPI_HPID_INC_1;
277                 *(buf_ptr++) = HPI_HPID_INC_2;
278         }
279 #endif
280
281         /* return number of bytes read */
282         return count;
283 }
284
285
286 /* write to non- auto inc regs */
287 static int hpi_write_noinc(u32 addr, u32 data)
288 {
289
290         u16 addr1, addr2, data1, data2;
291
292         addr1 = (u16) ((addr >> 16) & 0xffff); /* First HW is most significant */
293         addr2 = (u16) (addr & 0xffff);
294
295         /* printf("hpi_write_noinc: addr1=0x%x, addr2=0x%x\n", addr1, addr2); */
296
297         HPI_HPIA_1 = addr1;
298         HPI_HPIA_2 = addr2;
299
300         data1 = (u16) ((data >> 16) & 0xffff);
301         data2 = (u16) (data & 0xffff);
302
303         /* printf("hpi_write_noinc: data1=0x%x, data2=0x%x\n", data1, data2); */
304
305         HPI_HPID_NOINC_1 = data1;
306         HPI_HPID_NOINC_2 = data2;
307
308         return 0;
309 }
310
311 /* read from non- auto inc regs */
312 static u32 hpi_read_noinc(u32 addr)
313 {
314         u16 addr1, addr2, data1, data2;
315         u32 ret;
316
317         addr1 = (u16) ((addr >> 16) & 0xffff); /* First HW is most significant */
318         addr2 = (u16) (addr & 0xffff);
319
320         HPI_HPIA_1 = addr1;
321         HPI_HPIA_2 = addr2;
322
323         /* printf("hpi_read_noinc: addr1=0x%x, addr2=0x%x\n", addr1, addr2); */
324
325         data1 = HPI_HPID_NOINC_1;
326         data2 = HPI_HPID_NOINC_2;
327
328         /* printf("hpi_read_noinc: data1=0x%x, data2=0x%x\n", data1, data2); */
329
330         ret = (((u32) data1) << 16) | (data2 & 0xffff);
331         return ret;
332
333 }
334
335 /*
336  * Host Port Interface Tests
337  */
338
339 #ifndef HPI_TEST_OSZI
340 /* main test function */
341 int hpi_test(void)
342 {
343         int err = 0;
344         u32 i, ii, pattern, tmp;
345
346         pattern = HPI_TEST_PATTERN;
347
348         u32 test_data[HPI_TEST_CHUNKSIZE];
349         u32 read_data[HPI_TEST_CHUNKSIZE];
350
351         debugX(2, "hpi_test: activating hpi...");
352         hpi_activate();
353         debugX(2, "OK.\n");
354
355 #if 0
356         /* Dump the first 1024 bytes
357          *
358          */
359         for(i=0; i<1024; i+=4) {
360                 if(i%16==0)
361                         printf("\n0x%08x: ", i);
362                 printf("0x%08x ", hpi_read_noinc(i));
363         }
364 #endif
365
366         /* HPIA read-write test
367          *
368          */
369         debugX(1, "hpi_test: starting HPIA read-write tests...\n");
370         err |= hpi_write_addr_test(0xdeadc0de);
371         err |= hpi_write_addr_test(0xbeefd00d);
372         err |= hpi_write_addr_test(0xabcd1234);
373         err |= hpi_write_addr_test(0xaaaaaaaa);
374         if(err) {
375                 debugX(1, "hpi_test: HPIA read-write tests: *** FAILED ***\n");
376                 return -1;
377         }
378         debugX(1, "hpi_test: HPIA read-write tests: OK\n");
379
380
381         /* read write test using nonincremental data regs
382          *
383          */
384         debugX(1, "hpi_test: starting nonincremental tests...\n");
385         for(i=HPI_TEST_START; i<HPI_TEST_END; i+=4) {
386                 err |= hpi_read_write_test(i, pattern);
387
388                 /* stolen from cmd_mem.c */
389                 if(pattern & 0x80000000) {
390                         pattern = -pattern;     /* complement & increment */
391                 } else {
392                         pattern = ~pattern;
393                 }
394                 err |= hpi_read_write_test(i, pattern);
395
396                 if(err) {
397                         debugX(1, "hpi_test: nonincremental tests *** FAILED ***\n");
398                         return -1;
399                 }
400         }
401         debugX(1, "hpi_test: nonincremental test OK\n");
402
403         /* read write a chunk of data using nonincremental data regs
404          *
405          */
406         debugX(1, "hpi_test: starting nonincremental chunk tests...\n");
407         pattern = HPI_TEST_PATTERN;
408         for(i=HPI_TEST_START; i<HPI_TEST_END; i+=4) {
409                 hpi_write_noinc(i, pattern);
410
411                 /* stolen from cmd_mem.c */
412                 if(pattern & 0x80000000) {
413                         pattern = -pattern;     /* complement & increment */
414                 } else {
415                         pattern = ~pattern;
416                 }
417         }
418         pattern = HPI_TEST_PATTERN;
419         for(i=HPI_TEST_START; i<HPI_TEST_END; i+=4) {
420                 tmp = hpi_read_noinc(i);
421
422                 if(tmp != pattern) {
423                         debugX(1, "hpi_test: noninc chunk test *** FAILED *** @ 0x%x, written=0x%x, read=0x%x\n", i, pattern, tmp);
424                         err = -1;
425                 }
426                 /* stolen from cmd_mem.c */
427                 if(pattern & 0x80000000) {
428                         pattern = -pattern;     /* complement & increment */
429                 } else {
430                         pattern = ~pattern;
431                 }
432         }
433         if(err)
434                 return -1;
435         debugX(1, "hpi_test: nonincremental chunk test OK\n");
436
437
438 #ifdef DO_TINY_TEST
439         /* small verbose test using autoinc and nonautoinc to compare
440          *
441          */
442         debugX(1, "hpi_test: tiny_autoinc_test...\n");
443         hpi_tiny_autoinc_test();
444         debugX(1, "hpi_test: tiny_autoinc_test done\n");
445 #endif /* DO_TINY_TEST */
446
447
448         /* $%& write a chunk of data using the autoincremental regs
449          *
450          */
451         debugX(1, "hpi_test: starting autoinc test %d chunks with 0x%x bytes...\n",
452                ((HPI_TEST_END - HPI_TEST_START) / HPI_TEST_CHUNKSIZE),
453                HPI_TEST_CHUNKSIZE);
454
455         for(i=HPI_TEST_START;
456             i < ((HPI_TEST_END - HPI_TEST_START) / HPI_TEST_CHUNKSIZE);
457             i++) {
458                 /* generate the pattern data */
459                 debugX(3, "generating pattern data: ");
460                 for(ii = 0; ii < HPI_TEST_CHUNKSIZE; ii++) {
461                         debugX(3, "0x%x ", pattern);
462
463                         test_data[ii] = pattern;
464                         read_data[ii] = 0x0; /* zero to be sure */
465
466                         /* stolen from cmd_mem.c */
467                         if(pattern & 0x80000000) {
468                                 pattern = -pattern;     /* complement & increment */
469                         } else {
470                                 pattern = ~pattern;
471                         }
472                 }
473                 debugX(3, "done\n");
474
475                 debugX(2, "Writing autoinc data @ 0x%x\n", i);
476                 hpi_write_inc(i, test_data, HPI_TEST_CHUNKSIZE);
477
478                 debugX(2, "Reading autoinc data @ 0x%x\n", i);
479                 hpi_read_inc(i, read_data, HPI_TEST_CHUNKSIZE);
480
481                 /* compare */
482                 for(ii = 0; ii < HPI_TEST_CHUNKSIZE; ii++) {
483                         debugX(3, "hpi_test_autoinc: @ 0x%x, written=0x%x, read=0x%x", i+ii, test_data[ii], read_data[ii]);
484                         if(read_data[ii] != test_data[ii]) {
485                                 debugX(0, "hpi_test: autoinc test @ 0x%x, written=0x%x, read=0x%x *** FAILED ***\n", i+ii, test_data[ii], read_data[ii]);
486                                 return -1;
487                         }
488                 }
489         }
490         debugX(1, "hpi_test: autoinc test OK\n");
491
492         return 0;
493 }
494 #else /* HPI_TEST_OSZI */
495 int hpi_test(void)
496 {
497         int i;
498         u32 read_data[TINY_AUTOINC_DATA_SIZE];
499
500         unsigned int dummy_data[TINY_AUTOINC_DATA_SIZE] = {
501                 0x11112222, 0x33334444, 0x55556666, 0x77778888,
502                 0x9999aaaa, 0xbbbbcccc, 0xddddeeee, 0xffff1111,
503                 0x00010002, 0x00030004, 0x00050006, 0x00070008,
504                 0x0009000a, 0x000b000c, 0x000d000e, 0x000f0001
505         };
506
507         debugX(0, "hpi_test: activating hpi...");
508         hpi_activate();
509         debugX(0, "OK.\n");
510
511         while(1) {
512                 led9(1);
513                 debugX(0, " writing to autoinc...\n");
514                 hpi_write_inc(TINY_AUTOINC_BASE_ADDR,
515                               dummy_data, TINY_AUTOINC_DATA_SIZE);
516
517                 debugX(0, " reading from autoinc...\n");
518                 hpi_read_inc(TINY_AUTOINC_BASE_ADDR,
519                              read_data, TINY_AUTOINC_DATA_SIZE);
520
521                 for(i=0; i < (TINY_AUTOINC_DATA_SIZE); i++) {
522                         debugX(0, " written=0x%x, read(inc)=0x%x\n",
523                                dummy_data[i], read_data[i]);
524                 }
525                 led9(0);
526                 udelay(2000000);
527         }
528         return 0;
529 }
530 #endif
531
532 /* test if Host Port Address Register can be written correctly */
533 static int hpi_write_addr_test(u32 addr)
534 {
535         u32 read_back;
536         /* write address */
537         HPI_HPIA_1 = ((u16) (addr >> 16)); /* First HW is most significant */
538         HPI_HPIA_2 = ((u16) addr);
539
540         read_back = (((u32) HPI_HPIA_1)<<16) | ((u32) HPI_HPIA_2);
541
542         if(read_back == addr) {
543                 debugX(2, " hpi_write_addr_test OK: written=0x%x, read=0x%x\n",
544                        addr, read_back);
545                 return 0;
546         } else {
547                 debugX(0, " hpi_write_addr_test *** FAILED ***: written=0x%x, read=0x%x\n",
548                       addr, read_back);
549                 return -1;
550         }
551
552         return 0;
553 }
554
555 /* test if a simple read/write sequence succeeds */
556 static int hpi_read_write_test(u32 addr, u32 data)
557 {
558         u32 read_back;
559
560         hpi_write_noinc(addr, data);
561         read_back = hpi_read_noinc(addr);
562
563         if(read_back == data) {
564                 debugX(2, " hpi_read_write_test: OK, addr=0x%x written=0x%x, read=0x%x\n", addr, data, read_back);
565                 return 0;
566         } else {
567                 debugX(0, " hpi_read_write_test: *** FAILED ***, addr=0x%x written=0x%x, read=0x%x\n", addr, data, read_back);
568                 return -1;
569         }
570
571         return 0;
572 }
573
574 static int hpi_tiny_autoinc_test(void)
575 {
576         int i;
577         u32 read_data[TINY_AUTOINC_DATA_SIZE];
578         u32 read_data_noinc[TINY_AUTOINC_DATA_SIZE];
579
580         unsigned int dummy_data[TINY_AUTOINC_DATA_SIZE] = {
581                 0x11112222, 0x33334444, 0x55556666, 0x77778888,
582                 0x9999aaaa, 0xbbbbcccc, 0xddddeeee, 0xffff1111,
583                 0x00010002, 0x00030004, 0x00050006, 0x00070008,
584                 0x0009000a, 0x000b000c, 0x000d000e, 0x000f0001
585         };
586
587         printf(" writing to autoinc...\n");
588         hpi_write_inc(TINY_AUTOINC_BASE_ADDR, dummy_data, TINY_AUTOINC_DATA_SIZE);
589
590         printf(" reading from autoinc...\n");
591         hpi_read_inc(TINY_AUTOINC_BASE_ADDR, read_data, TINY_AUTOINC_DATA_SIZE);
592
593         printf(" reading from noinc for comparison...\n");
594         for(i=0; i < (TINY_AUTOINC_DATA_SIZE); i++)
595                 read_data_noinc[i] = hpi_read_noinc(TINY_AUTOINC_BASE_ADDR+i*4);
596
597         for(i=0; i < (TINY_AUTOINC_DATA_SIZE); i++) {
598                 printf(" written=0x%x, read(inc)=0x%x, read(noinc)=0x%x\n",
599                        dummy_data[i], read_data[i], read_data_noinc[i]);
600         }
601         return 0;
602 }
603
604 #endif /* CONFIG_SPC1920_HPI_TEST */