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