]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_tsi148.c
Merge branch 'master' of git://git.denx.de/u-boot-blackfin
[karo-tx-uboot.git] / common / cmd_tsi148.c
1 /*
2  * (C) Copyright 2009 Reinhard Arlt, reinhard.arlt@esd-electronics.com
3  *
4  * base on universe.h by
5  *
6  * (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com
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 #define DEBUG
28
29 #include <common.h>
30 #include <command.h>
31 #include <malloc.h>
32 #include <asm/io.h>
33 #include <pci.h>
34
35 #include <tsi148.h>
36
37 #define PCI_VENDOR PCI_VENDOR_ID_TUNDRA
38 #define PCI_DEVICE PCI_DEVICE_ID_TUNDRA_TSI148
39
40 typedef struct _TSI148_DEV TSI148_DEV;
41
42 struct _TSI148_DEV {
43         int            bus;
44         pci_dev_t      busdevfn;
45         TSI148        *uregs;
46         unsigned int   pci_bs;
47 };
48
49 static TSI148_DEV *dev;
50
51 /*
52  * Most of the TSI148 register are BIGENDIAN
53  * This is the reason for the __raw_writel(htonl(x), x) usage!
54  */
55
56 int tsi148_init(void)
57 {
58         int j, result, lastError = 0;
59         pci_dev_t busdevfn;
60         unsigned int val;
61
62         busdevfn = pci_find_device(PCI_VENDOR, PCI_DEVICE, 0);
63         if (busdevfn == -1) {
64                 puts("Tsi148: No Tundra Tsi148 found!\n");
65                 return -1;
66         }
67
68         /* Lets turn Latency off */
69         pci_write_config_dword(busdevfn, 0x0c, 0);
70
71         dev = malloc(sizeof(*dev));
72         if (NULL == dev) {
73                 puts("Tsi148: No memory!\n");
74                 result = -1;
75                 goto break_20;
76         }
77
78         memset(dev, 0, sizeof(*dev));
79         dev->busdevfn = busdevfn;
80
81         pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_0, &val);
82         val &= ~0xf;
83         dev->uregs = (TSI148 *)val;
84
85         debug("Tsi148: Base    : %p\n", dev->uregs);
86
87         /* check mapping  */
88         debug("Tsi148: Read via mapping, PCI_ID = %08X\n", readl(&dev->uregs->pci_id));
89         if (((PCI_DEVICE << 16) | PCI_VENDOR) !=  readl(&dev->uregs->pci_id)) {
90                 printf("Tsi148: Cannot read PCI-ID via Mapping: %08x\n",
91                         readl(&dev->uregs->pci_id));
92                 result = -1;
93                 goto break_30;
94         }
95
96         debug("Tsi148: PCI_BS = %08X\n", readl(&dev->uregs->pci_mbarl));
97
98         dev->pci_bs = readl(&dev->uregs->pci_mbarl);
99
100         /* turn off windows */
101         for (j = 0; j < 8; j++) {
102                 __raw_writel(htonl(0x00000000), &dev->uregs->outbound[j].otat);
103                 __raw_writel(htonl(0x00000000), &dev->uregs->inbound[j].itat);
104         }
105
106         /* Tsi148 VME timeout etc */
107         __raw_writel(htonl(0x00000084), &dev->uregs->vctrl);
108
109         if ((__raw_readl(&dev->uregs->vstat) & 0x00000100) != 0)
110                 debug("Tsi148: System Controller!\n");
111         else
112                 debug("Tsi148: Not System Controller!\n");
113
114         /*
115          * Lets turn off interrupts
116          */
117         /* Disable interrupts in Tsi148 first */
118         __raw_writel(htonl(0x00000000), &dev->uregs->inten);
119         /* Disable interrupt out */
120         __raw_writel(htonl(0x00000000), &dev->uregs->inteo);
121         eieio();
122         /* Reset all IRQ's */
123         __raw_writel(htonl(0x03ff3f00), &dev->uregs->intc);
124         /* Map all ints to 0 */
125         __raw_writel(htonl(0x00000000), &dev->uregs->intm1);
126         __raw_writel(htonl(0x00000000), &dev->uregs->intm2);
127         eieio();
128
129         val  = __raw_readl(&dev->uregs->vstat);
130         val &= ~(0x00004000);
131         __raw_writel(val, &dev->uregs->vstat);
132         eieio();
133
134         debug("Tsi148: register struct size %08x\n", sizeof(TSI148));
135
136         return 0;
137
138  break_30:
139         free(dev);
140         dev = NULL;
141  break_20:
142         lastError = result;
143
144         return result;
145 }
146
147 /*
148  * Create pci slave window (access: pci -> vme)
149  */
150 int tsi148_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr, int size, int vam, int vdw)
151 {
152         int result, i;
153         unsigned int ctl = 0;
154
155         if (NULL == dev) {
156                 result = -1;
157                 goto exit_10;
158         }
159
160         for (i = 0; i < 8; i++) {
161                 if (0x00000000 == readl(&dev->uregs->outbound[i].otat))
162                         break;
163         }
164
165         if (i > 7) {
166                 printf("Tsi148: No Image available\n");
167                 result = -1;
168                 goto exit_10;
169         }
170
171         debug("Tsi148: Using image %d\n", i);
172
173         printf("Tsi148: Pci addr %08x\n", pciAddr);
174
175
176         __raw_writel(htonl(pciAddr) , &dev->uregs->outbound[i].otsal);
177         __raw_writel(0x00000000 , &dev->uregs->outbound[i].otsau);
178         __raw_writel(htonl(pciAddr + size), &dev->uregs->outbound[i].oteal);
179         __raw_writel(0x00000000 , &dev->uregs->outbound[i].oteau);
180         __raw_writel(htonl(vmeAddr - pciAddr), &dev->uregs->outbound[i].otofl);
181         __raw_writel(0x00000000 , &dev->uregs->outbound[i].otofu);
182
183         switch (vam & VME_AM_Axx) {
184         case VME_AM_A16:
185                 ctl = 0x00000000;
186                 break;
187         case VME_AM_A24:
188                 ctl = 0x00000001;
189                 break;
190         case VME_AM_A32:
191                 ctl = 0x00000002;
192                 break;
193         }
194
195         switch (vam & VME_AM_Mxx) {
196         case VME_AM_DATA:
197                 ctl |= 0x00000000;
198                 break;
199         case VME_AM_PROG:
200                 ctl |= 0x00000010;
201                 break;
202         }
203
204         if (vam & VME_AM_SUP)
205                 ctl |= 0x00000020;
206
207         switch (vdw & VME_FLAG_Dxx) {
208         case VME_FLAG_D16:
209                 ctl |= 0x00000000;
210                 break;
211         case VME_FLAG_D32:
212                 ctl |= 0x00000040;
213                 break;
214         }
215
216         ctl |= 0x80040000;    /* enable, no prefetch */
217
218         __raw_writel(htonl(ctl), &dev->uregs->outbound[i].otat);
219
220         debug("Tsi148: window-addr                =%p\n",
221               &dev->uregs->outbound[i].otsau);
222         debug("Tsi148: pci slave window[%d] attr  =%08x\n",
223               i, ntohl(__raw_readl(&dev->uregs->outbound[i].otat)));
224         debug("Tsi148: pci slave window[%d] start =%08x\n",
225               i, ntohl(__raw_readl(&dev->uregs->outbound[i].otsal)));
226         debug("Tsi148: pci slave window[%d] end   =%08x\n",
227               i, ntohl(__raw_readl(&dev->uregs->outbound[i].oteal)));
228         debug("Tsi148: pci slave window[%d] offset=%08x\n",
229               i, ntohl(__raw_readl(&dev->uregs->outbound[i].otofl)));
230
231         return 0;
232
233  exit_10:
234         return -result;
235 }
236
237 unsigned int tsi148_eval_vam(int vam)
238 {
239         unsigned int ctl = 0;
240
241         switch (vam & VME_AM_Axx) {
242         case VME_AM_A16:
243                 ctl = 0x00000000;
244                 break;
245         case VME_AM_A24:
246                 ctl = 0x00000010;
247                 break;
248         case VME_AM_A32:
249                 ctl = 0x00000020;
250                 break;
251         }
252         switch (vam & VME_AM_Mxx) {
253         case VME_AM_DATA:
254                 ctl |= 0x00000001;
255                 break;
256         case VME_AM_PROG:
257                 ctl |= 0x00000002;
258                 break;
259         case (VME_AM_PROG | VME_AM_DATA):
260                 ctl |= 0x00000003;
261                 break;
262         }
263
264         if (vam & VME_AM_SUP)
265                 ctl |= 0x00000008;
266         if (vam & VME_AM_USR)
267                 ctl |= 0x00000004;
268
269         return ctl;
270 }
271
272 /*
273  * Create vme slave window (access: vme -> pci)
274  */
275 int tsi148_vme_slave_window(unsigned int vmeAddr, unsigned int pciAddr, int size, int vam)
276 {
277         int result, i;
278         unsigned int ctl = 0;
279
280         if (NULL == dev) {
281                 result = -1;
282                 goto exit_10;
283         }
284
285         for (i = 0; i < 8; i++) {
286                 if (0x00000000 == readl(&dev->uregs->inbound[i].itat))
287                         break;
288         }
289
290         if (i > 7) {
291                 printf("Tsi148: No Image available\n");
292                 result = -1;
293                 goto exit_10;
294         }
295
296         debug("Tsi148: Using image %d\n", i);
297
298         __raw_writel(htonl(vmeAddr), &dev->uregs->inbound[i].itsal);
299         __raw_writel(0x00000000, &dev->uregs->inbound[i].itsau);
300         __raw_writel(htonl(vmeAddr + size), &dev->uregs->inbound[i].iteal);
301         __raw_writel(0x00000000, &dev->uregs->inbound[i].iteau);
302         __raw_writel(htonl(pciAddr - vmeAddr), &dev->uregs->inbound[i].itofl);
303         if (vmeAddr > pciAddr)
304                 __raw_writel(0xffffffff, &dev->uregs->inbound[i].itofu);
305         else
306                 __raw_writel(0x00000000, &dev->uregs->inbound[i].itofu);
307
308         ctl = tsi148_eval_vam(vam);
309         ctl |= 0x80000000;    /* enable */
310         __raw_writel(htonl(ctl), &dev->uregs->inbound[i].itat);
311
312         debug("Tsi148: window-addr                =%p\n",
313               &dev->uregs->inbound[i].itsau);
314         debug("Tsi148: vme slave window[%d] attr  =%08x\n",
315               i, ntohl(__raw_readl(&dev->uregs->inbound[i].itat))) ;
316         debug("Tsi148: vme slave window[%d] start =%08x\n",
317               i, ntohl(__raw_readl(&dev->uregs->inbound[i].itsal)));
318         debug("Tsi148: vme slave window[%d] end   =%08x\n",
319               i, ntohl(__raw_readl(&dev->uregs->inbound[i].iteal)));
320         debug("Tsi148: vme slave window[%d] offset=%08x\n",
321               i, ntohl(__raw_readl(&dev->uregs->inbound[i].itofl)));
322
323         return 0;
324
325  exit_10:
326         return -result;
327 }
328
329 /*
330  * Create vme slave window (access: vme -> gcsr)
331  */
332 int tsi148_vme_gcsr_window(unsigned int vmeAddr, int vam)
333 {
334         int result;
335         unsigned int ctl;
336
337         result = 0;
338
339         if (NULL == dev) {
340                 result = 1;
341         } else {
342                __raw_writel(htonl(vmeAddr), &dev->uregs->gbal);
343                __raw_writel(0x00000000, &dev->uregs->gbau);
344
345                ctl = tsi148_eval_vam(vam);
346                ctl |= 0x00000080;    /* enable */
347                __raw_writel(htonl(ctl), &dev->uregs->gcsrat);
348         }
349
350         return result;
351 }
352
353 /*
354  * Create vme slave window (access: vme -> crcsr)
355  */
356 int tsi148_vme_crcsr_window(unsigned int vmeAddr)
357 {
358         int result;
359         unsigned int ctl;
360
361         result = 0;
362
363         if (NULL == dev) {
364                 result = 1;
365         } else {
366                __raw_writel(htonl(vmeAddr), &dev->uregs->crol);
367                __raw_writel(0x00000000, &dev->uregs->crou);
368
369                ctl = 0x00000080;    /* enable */
370                __raw_writel(htonl(ctl), &dev->uregs->crat);
371         }
372
373         return result;
374 }
375
376
377 /*
378  * Create vme slave window (access: vme -> crg)
379  */
380 int tsi148_vme_crg_window(unsigned int vmeAddr, int vam)
381 {
382         int result;
383         unsigned int ctl;
384
385         result = 0;
386
387         if (NULL == dev) {
388                 result = 1;
389         } else {
390                __raw_writel(htonl(vmeAddr), &dev->uregs->cbal);
391                __raw_writel(0x00000000, &dev->uregs->cbau);
392
393                ctl = tsi148_eval_vam(vam);
394                ctl |= 0x00000080;    /* enable */
395                __raw_writel(htonl(ctl), &dev->uregs->crgat);
396         }
397
398         return result;
399 }
400
401 /*
402  * Tundra Tsi148 configuration
403  */
404 int do_tsi148(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
405 {
406         ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, vdw = 0;
407         char cmd = 'x';
408
409         /* get parameter */
410         if (argc > 1)
411                 cmd = argv[1][0];
412         if (argc > 2)
413                 addr1 = simple_strtoul(argv[2], NULL, 16);
414         if (argc > 3)
415                 addr2 = simple_strtoul(argv[3], NULL, 16);
416         if (argc > 4)
417                 size = simple_strtoul(argv[4], NULL, 16);
418         if (argc > 5)
419                 vam = simple_strtoul(argv[5], NULL, 16);
420         if (argc > 6)
421                 vdw = simple_strtoul(argv[7], NULL, 16);
422
423         switch (cmd) {
424         case 'c':
425                 if (strcmp(argv[1], "crg") == 0) {
426                         vam = addr2;
427                         printf("Tsi148: Configuring VME CRG Window (VME->CRG):\n");
428                         printf("  vme=%08lx vam=%02lx\n", addr1, vam);
429                         tsi148_vme_crg_window(addr1, vam);
430                 } else {
431                         printf("Tsi148: Configuring VME CR/CSR Window (VME->CR/CSR):\n");
432                         printf("  pci=%08lx\n", addr1);
433                         tsi148_vme_crcsr_window(addr1);
434                 }
435                 break;
436         case 'i':               /* init */
437                 tsi148_init();
438                 break;
439         case 'g':
440                 vam = addr2;
441                 printf("Tsi148: Configuring VME GCSR Window (VME->GCSR):\n");
442                 printf("  vme=%08lx vam=%02lx\n", addr1, vam);
443                 tsi148_vme_gcsr_window(addr1, vam);
444                 break;
445         case 'v':               /* vme */
446                 printf("Tsi148: Configuring VME Slave Window (VME->PCI):\n");
447                 printf("  vme=%08lx pci=%08lx size=%08lx vam=%02lx\n",
448                        addr1, addr2, size, vam);
449                 tsi148_vme_slave_window(addr1, addr2, size, vam);
450                 break;
451         case 'p':               /* pci */
452                 printf("Tsi148: Configuring PCI Slave Window (PCI->VME):\n");
453                 printf("  pci=%08lx vme=%08lx size=%08lx vam=%02lx vdw=%02lx\n",
454                        addr1, addr2, size, vam, vdw);
455                 tsi148_pci_slave_window(addr1, addr2, size, vam, vdw);
456                 break;
457         default:
458                 printf("Tsi148: Command %s not supported!\n", argv[1]);
459         }
460
461         return 0;
462 }
463
464 U_BOOT_CMD(
465         tsi148, 8,      1,      do_tsi148,
466         "tsi148  - initialize and configure Turndra Tsi148\n",
467         "init\n"
468         "    - initialize tsi148\n"
469         "tsi148 vme   [vme_addr] [pci_addr] [size] [vam]\n"
470         "    - create vme slave window (access: vme->pci)\n"
471         "tsi148 pci   [pci_addr] [vme_addr] [size] [vam] [vdw]\n"
472         "    - create pci slave window (access: pci->vme)\n"
473         "tsi148 crg   [vme_addr] [vam]\n"
474         "    - create vme slave window: (access vme->CRG\n"
475         "tsi148 crcsr [pci_addr]\n"
476         "    - create vme slave window: (access vme->CR/CSR\n"
477         "tsi148 gcsr  [vme_addr] [vam]\n"
478         "    - create vme slave window: (access vme->GCSR\n"
479         "    [vam] = VMEbus Address-Modifier:  01 -> A16 Address Space\n"
480         "                                      02 -> A24 Address Space\n"
481         "                                      03 -> A32 Address Space\n"
482         "                                      04 -> Usr        AM Code\n"
483         "                                      08 -> Supervisor AM Code\n"
484         "                                      10 -> Data AM Code\n"
485         "                                      20 -> Program AM Code\n"
486         "    [vdw] = VMEbus Maximum Datawidth: 02 -> D16 Data Width\n"
487         "                                      03 -> D32 Data Width\n"
488 );