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