]>
Commit | Line | Data |
---|---|---|
256e4be8 SR |
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 | ||
256e4be8 SR |
31 | #if (CONFIG_COMMANDS & CFG_CMD_UNIVERSE) |
32 | ||
256e4be8 SR |
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); | |
dcb2f95a SR |
75 | if (val & 1) { |
76 | pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_0, &val); | |
77 | } | |
256e4be8 SR |
78 | val &= ~0xf; |
79 | dev->uregs = (UNIVERSE *)val; | |
80 | ||
e2ffd59b | 81 | debug ("UNIVERSE-Base : %p\n", dev->uregs); |
256e4be8 SR |
82 | |
83 | /* check mapping */ | |
e2ffd59b | 84 | debug (" Read via mapping, PCI_ID = %08X\n", readl(&dev->uregs->pci_id)); |
256e4be8 | 85 | if (((PCI_DEVICE <<16) | PCI_VENDOR) != readl(&dev->uregs->pci_id)) { |
e2ffd59b WD |
86 | printf ("UNIVERSE: Cannot read PCI-ID via Mapping: %08x\n", |
87 | readl(&dev->uregs->pci_id)); | |
256e4be8 SR |
88 | result = -1; |
89 | goto break_30; | |
90 | } | |
91 | ||
e2ffd59b | 92 | debug ("PCI_BS = %08X\n", readl(&dev->uregs->pci_bs)); |
256e4be8 SR |
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 | */ | |
dcb2f95a SR |
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 | } | |
256e4be8 SR |
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 | ||
dcb2f95a SR |
126 | return 0; |
127 | ||
256e4be8 SR |
128 | break_30: |
129 | free(dev); | |
130 | break_20: | |
131 | lastError = result; | |
132 | ||
dcb2f95a | 133 | return result; |
256e4be8 SR |
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) { | |
e2ffd59b | 156 | printf ("universe: No Image available\n"); |
256e4be8 SR |
157 | result = -1; |
158 | goto exit_10; | |
159 | } | |
160 | ||
e2ffd59b | 161 | debug ("universe: Using image %d\n", i); |
256e4be8 SR |
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: | |
dcb2f95a | 207 | ctl |= 0x00000000; |
256e4be8 SR |
208 | break; |
209 | case PCI_MS_IO: | |
dcb2f95a | 210 | ctl |= 0x00000001; |
256e4be8 SR |
211 | break; |
212 | case PCI_MS_CONFIG: | |
dcb2f95a | 213 | ctl |= 0x00000002; |
256e4be8 SR |
214 | break; |
215 | } | |
216 | ||
217 | ctl |= 0x80000000; /* enable */ | |
218 | ||
219 | writel(ctl, &dev->uregs->lsi[i].ctl); | |
220 | ||
e2ffd59b WD |
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)); | |
256e4be8 SR |
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) { | |
e2ffd59b | 253 | printf ("universe: No Image available\n"); |
256e4be8 SR |
254 | result = -1; |
255 | goto exit_10; | |
256 | } | |
257 | ||
e2ffd59b | 258 | debug ("universe: Using image %d\n", i); |
256e4be8 SR |
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: | |
dcb2f95a | 292 | ctl |= 0x00000000; |
256e4be8 SR |
293 | break; |
294 | case PCI_MS_IO: | |
dcb2f95a | 295 | ctl |= 0x00000001; |
256e4be8 SR |
296 | break; |
297 | case PCI_MS_CONFIG: | |
dcb2f95a | 298 | ctl |= 0x00000002; |
256e4be8 SR |
299 | break; |
300 | } | |
301 | ||
302 | ctl |= 0x80f00000; /* enable */ | |
303 | ||
304 | writel(ctl, &dev->uregs->vsi[i].ctl); | |
305 | ||
e2ffd59b WD |
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)); | |
256e4be8 SR |
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) */ |