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