5ff47dde4fbed9686c90e24b18a9eb9eec145e29
[platform/kernel/u-boot.git] / cmd / universe.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com
4  */
5
6 #include <common.h>
7 #include <command.h>
8 #include <malloc.h>
9 #include <asm/io.h>
10 #include <pci.h>
11
12 #include <universe.h>
13
14 #define PCI_VENDOR PCI_VENDOR_ID_TUNDRA
15 #define PCI_DEVICE PCI_DEVICE_ID_TUNDRA_CA91C042
16
17
18 typedef struct _UNI_DEV UNI_DEV;
19
20 struct _UNI_DEV {
21         int            bus;
22         pci_dev_t      busdevfn;
23         UNIVERSE       *uregs;
24         unsigned int   pci_bs;
25 };
26
27 static UNI_DEV   *dev;
28
29
30 int universe_init(void)
31 {
32         int j, result;
33         pci_dev_t busdevfn;
34         unsigned int val;
35
36         busdevfn = pci_find_device(PCI_VENDOR, PCI_DEVICE, 0);
37         if (busdevfn == -1) {
38                 puts("No Tundra Universe found!\n");
39                 return -1;
40         }
41
42         /* Lets turn Latency off */
43         pci_write_config_dword(busdevfn, 0x0c, 0);
44
45         dev = malloc(sizeof(*dev));
46         if (NULL == dev) {
47                 puts("UNIVERSE: No memory!\n");
48                 result = -1;
49                 goto break_20;
50         }
51
52         memset(dev, 0, sizeof(*dev));
53         dev->busdevfn = busdevfn;
54
55         pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_1, &val);
56         if (val & 1) {
57                 pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_0, &val);
58         }
59         val &= ~0xf;
60         dev->uregs = (UNIVERSE *)val;
61
62         debug ("UNIVERSE-Base    : %p\n", dev->uregs);
63
64         /* check mapping  */
65         debug (" Read via mapping, PCI_ID = %08X\n", readl(&dev->uregs->pci_id));
66         if (((PCI_DEVICE <<16) | PCI_VENDOR) !=  readl(&dev->uregs->pci_id)) {
67                 printf ("UNIVERSE: Cannot read PCI-ID via Mapping: %08x\n",
68                         readl(&dev->uregs->pci_id));
69                 result = -1;
70                 goto break_30;
71         }
72
73         debug ("PCI_BS = %08X\n", readl(&dev->uregs->pci_bs));
74
75         dev->pci_bs = readl(&dev->uregs->pci_bs);
76
77         /* turn off windows */
78         for (j=0; j <4; j ++) {
79                 writel(0x00800000, &dev->uregs->lsi[j].ctl);
80                 writel(0x00800000, &dev->uregs->vsi[j].ctl);
81         }
82
83         /*
84          * Write to Misc Register
85          * Set VME Bus Time-out
86          *   Arbitration Mode
87          *   DTACK Enable
88          */
89         writel(0x15040000 | (readl(&dev->uregs->misc_ctl) & 0x00020000), &dev->uregs->misc_ctl);
90
91         if (readl(&dev->uregs->misc_ctl) & 0x00020000) {
92                 debug ("System Controller!\n"); /* test-only */
93         } else {
94                 debug ("Not System Controller!\n"); /* test-only */
95         }
96
97         /*
98          * Lets turn off interrupts
99          */
100         writel(0x00000000,&dev->uregs->lint_en);   /* Disable interrupts in the Universe first */
101         writel(0x0000FFFF,&dev->uregs->lint_stat); /* Clear Any Pending Interrupts */
102         eieio();
103         writel(0x0000, &dev->uregs->lint_map0);  /* Map all ints to 0 */
104         writel(0x0000, &dev->uregs->lint_map1);  /* Map all ints to 0 */
105         eieio();
106
107         return 0;
108
109  break_30:
110         free(dev);
111  break_20:
112         return result;
113 }
114
115
116 /*
117  * Create pci slave window (access: pci -> vme)
118  */
119 int universe_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr, int size, int vam, int pms, int vdw)
120 {
121         int result, i;
122         unsigned int ctl = 0;
123
124         if (NULL == dev) {
125                 result = -1;
126                 goto exit_10;
127         }
128
129         for (i = 0; i < 4; i++) {
130                 if (0x00800000 == readl(&dev->uregs->lsi[i].ctl))
131                         break;
132         }
133
134         if (i == 4) {
135                 printf ("universe: No Image available\n");
136                 result = -1;
137                 goto exit_10;
138         }
139
140         debug ("universe: Using image %d\n", i);
141
142         writel(pciAddr , &dev->uregs->lsi[i].bs);
143         writel((pciAddr + size), &dev->uregs->lsi[i].bd);
144         writel((vmeAddr - pciAddr), &dev->uregs->lsi[i].to);
145
146         switch (vam & VME_AM_Axx) {
147         case VME_AM_A16:
148                 ctl = 0x00000000;
149                 break;
150         case VME_AM_A24:
151                 ctl = 0x00010000;
152                 break;
153         case VME_AM_A32:
154                 ctl = 0x00020000;
155                 break;
156         }
157
158         switch (vam & VME_AM_Mxx) {
159         case VME_AM_DATA:
160                 ctl |= 0x00000000;
161                 break;
162         case VME_AM_PROG:
163                 ctl |= 0x00008000;
164                 break;
165         }
166
167         if (vam & VME_AM_SUP) {
168                 ctl |= 0x00001000;
169
170         }
171
172         switch (vdw & VME_FLAG_Dxx) {
173         case VME_FLAG_D8:
174                 ctl |= 0x00000000;
175                 break;
176         case VME_FLAG_D16:
177                 ctl |= 0x00400000;
178                 break;
179         case VME_FLAG_D32:
180                 ctl |= 0x00800000;
181                 break;
182         }
183
184         switch (pms & PCI_MS_Mxx) {
185         case PCI_MS_MEM:
186                 ctl |= 0x00000000;
187                 break;
188         case PCI_MS_IO:
189                 ctl |= 0x00000001;
190                 break;
191         case PCI_MS_CONFIG:
192                 ctl |= 0x00000002;
193                 break;
194         }
195
196         ctl |= 0x80000000;    /* enable */
197
198         writel(ctl, &dev->uregs->lsi[i].ctl);
199
200         debug ("universe: window-addr=%p\n", &dev->uregs->lsi[i].ctl);
201         debug ("universe: pci slave window[%d] ctl=%08x\n", i, readl(&dev->uregs->lsi[i].ctl));
202         debug ("universe: pci slave window[%d] bs=%08x\n", i, readl(&dev->uregs->lsi[i].bs));
203         debug ("universe: pci slave window[%d] bd=%08x\n", i, readl(&dev->uregs->lsi[i].bd));
204         debug ("universe: pci slave window[%d] to=%08x\n", i, readl(&dev->uregs->lsi[i].to));
205
206         return 0;
207
208  exit_10:
209         return -result;
210 }
211
212
213 /*
214  * Create vme slave window (access: vme -> pci)
215  */
216 int universe_vme_slave_window(unsigned int vmeAddr, unsigned int pciAddr, int size, int vam, int pms)
217 {
218         int result, i;
219         unsigned int ctl = 0;
220
221         if (NULL == dev) {
222                 result = -1;
223                 goto exit_10;
224         }
225
226         for (i = 0; i < 4; i++) {
227                 if (0x00800000 == readl(&dev->uregs->vsi[i].ctl))
228                         break;
229         }
230
231         if (i == 4) {
232                 printf ("universe: No Image available\n");
233                 result = -1;
234                 goto exit_10;
235         }
236
237         debug ("universe: Using image %d\n", i);
238
239         writel(vmeAddr , &dev->uregs->vsi[i].bs);
240         writel((vmeAddr + size), &dev->uregs->vsi[i].bd);
241         writel((pciAddr - vmeAddr), &dev->uregs->vsi[i].to);
242
243         switch (vam & VME_AM_Axx) {
244         case VME_AM_A16:
245                 ctl = 0x00000000;
246                 break;
247         case VME_AM_A24:
248                 ctl = 0x00010000;
249                 break;
250         case VME_AM_A32:
251                 ctl = 0x00020000;
252                 break;
253         }
254
255         switch (vam & VME_AM_Mxx) {
256         case VME_AM_DATA:
257                 ctl |= 0x00000000;
258                 break;
259         case VME_AM_PROG:
260                 ctl |= 0x00800000;
261                 break;
262         }
263
264         if (vam & VME_AM_SUP) {
265                 ctl |= 0x00100000;
266
267         }
268
269         switch (pms & PCI_MS_Mxx) {
270         case PCI_MS_MEM:
271                 ctl |= 0x00000000;
272                 break;
273         case PCI_MS_IO:
274                 ctl |= 0x00000001;
275                 break;
276         case PCI_MS_CONFIG:
277                 ctl |= 0x00000002;
278                 break;
279         }
280
281         ctl |= 0x80f00000;    /* enable */
282
283         writel(ctl, &dev->uregs->vsi[i].ctl);
284
285         debug ("universe: window-addr=%p\n", &dev->uregs->vsi[i].ctl);
286         debug ("universe: vme slave window[%d] ctl=%08x\n", i, readl(&dev->uregs->vsi[i].ctl));
287         debug ("universe: vme slave window[%d] bs=%08x\n", i, readl(&dev->uregs->vsi[i].bs));
288         debug ("universe: vme slave window[%d] bd=%08x\n", i, readl(&dev->uregs->vsi[i].bd));
289         debug ("universe: vme slave window[%d] to=%08x\n", i, readl(&dev->uregs->vsi[i].to));
290
291         return 0;
292
293  exit_10:
294         return -result;
295 }
296
297
298 /*
299  * Tundra Universe configuration
300  */
301 int do_universe(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
302 {
303         ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, pms = 0, vdw = 0;
304         char cmd = 'x';
305
306         /* get parameter */
307         if (argc > 1)
308                 cmd = argv[1][0];
309         if (argc > 2)
310                 addr1 = simple_strtoul(argv[2], NULL, 16);
311         if (argc > 3)
312                 addr2 = simple_strtoul(argv[3], NULL, 16);
313         if (argc > 4)
314                 size = simple_strtoul(argv[4], NULL, 16);
315         if (argc > 5)
316                 vam = simple_strtoul(argv[5], NULL, 16);
317         if (argc > 6)
318                 pms = simple_strtoul(argv[6], NULL, 16);
319         if (argc > 7)
320                 vdw = simple_strtoul(argv[7], NULL, 16);
321
322         switch (cmd) {
323         case 'i':               /* init */
324                 universe_init();
325                 break;
326         case 'v':               /* vme */
327                 printf("Configuring Universe VME Slave Window (VME->PCI):\n");
328                 printf("  vme=%08lx pci=%08lx size=%08lx vam=%02lx pms=%02lx\n",
329                        addr1, addr2, size, vam, pms);
330                 universe_vme_slave_window(addr1, addr2, size, vam, pms);
331                 break;
332         case 'p':               /* pci */
333                 printf("Configuring Universe PCI Slave Window (PCI->VME):\n");
334                 printf("  pci=%08lx vme=%08lx size=%08lx vam=%02lx pms=%02lx vdw=%02lx\n",
335                        addr1, addr2, size, vam, pms, vdw);
336                 universe_pci_slave_window(addr1, addr2, size, vam, pms, vdw);
337                 break;
338         default:
339                 printf("Universe command %s not supported!\n", argv[1]);
340         }
341
342         return 0;
343 }
344
345
346 U_BOOT_CMD(
347         universe,       8,      1,      do_universe,
348         "initialize and configure Turndra Universe",
349         "init\n"
350         "    - initialize universe\n"
351         "universe vme [vme_addr] [pci_addr] [size] [vam] [pms]\n"
352         "    - create vme slave window (access: vme->pci)\n"
353         "universe pci [pci_addr] [vme_addr] [size] [vam] [pms] [vdw]\n"
354         "    - create pci slave window (access: pci->vme)\n"
355         "    [vam] = VMEbus Address-Modifier:  01 -> A16 Address Space\n"
356         "                                      02 -> A24 Address Space\n"
357         "                                      03 -> A32 Address Space\n"
358         "                                      04 -> Supervisor AM Code\n"
359         "                                      10 -> Data AM Code\n"
360         "                                      20 -> Program AM Code\n"
361         "    [pms] = PCI Memory Space:         01 -> Memory Space\n"
362         "                                      02 -> I/O Space\n"
363         "                                      03 -> Configuration Space\n"
364         "    [vdw] = VMEbus Maximum Datawidth: 01 -> D8 Data Width\n"
365         "                                      02 -> D16 Data Width\n"
366         "                                      03 -> D32 Data Width"
367 );