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