]>
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 | #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 | { | |
e4119560 | 49 | int j, result; |
256e4be8 SR |
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: | |
dcb2f95a | 129 | return result; |
256e4be8 SR |
130 | } |
131 | ||
132 | ||
133 | /* | |
134 | * Create pci slave window (access: pci -> vme) | |
135 | */ | |
136 | int universe_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr, int size, int vam, int pms, int vdw) | |
137 | { | |
138 | int result, i; | |
139 | unsigned int ctl = 0; | |
140 | ||
141 | if (NULL == dev) { | |
142 | result = -1; | |
143 | goto exit_10; | |
144 | } | |
145 | ||
146 | for (i = 0; i < 4; i++) { | |
147 | if (0x00800000 == readl(&dev->uregs->lsi[i].ctl)) | |
148 | break; | |
149 | } | |
150 | ||
151 | if (i == 4) { | |
e2ffd59b | 152 | printf ("universe: No Image available\n"); |
256e4be8 SR |
153 | result = -1; |
154 | goto exit_10; | |
155 | } | |
156 | ||
e2ffd59b | 157 | debug ("universe: Using image %d\n", i); |
256e4be8 SR |
158 | |
159 | writel(pciAddr , &dev->uregs->lsi[i].bs); | |
160 | writel((pciAddr + size), &dev->uregs->lsi[i].bd); | |
161 | writel((vmeAddr - pciAddr), &dev->uregs->lsi[i].to); | |
162 | ||
163 | switch (vam & VME_AM_Axx) { | |
164 | case VME_AM_A16: | |
165 | ctl = 0x00000000; | |
166 | break; | |
167 | case VME_AM_A24: | |
168 | ctl = 0x00010000; | |
169 | break; | |
170 | case VME_AM_A32: | |
171 | ctl = 0x00020000; | |
172 | break; | |
173 | } | |
174 | ||
175 | switch (vam & VME_AM_Mxx) { | |
176 | case VME_AM_DATA: | |
177 | ctl |= 0x00000000; | |
178 | break; | |
179 | case VME_AM_PROG: | |
180 | ctl |= 0x00008000; | |
181 | break; | |
182 | } | |
183 | ||
184 | if (vam & VME_AM_SUP) { | |
185 | ctl |= 0x00001000; | |
186 | ||
187 | } | |
188 | ||
189 | switch (vdw & VME_FLAG_Dxx) { | |
190 | case VME_FLAG_D8: | |
191 | ctl |= 0x00000000; | |
192 | break; | |
193 | case VME_FLAG_D16: | |
194 | ctl |= 0x00400000; | |
195 | break; | |
196 | case VME_FLAG_D32: | |
197 | ctl |= 0x00800000; | |
198 | break; | |
199 | } | |
200 | ||
201 | switch (pms & PCI_MS_Mxx) { | |
202 | case PCI_MS_MEM: | |
dcb2f95a | 203 | ctl |= 0x00000000; |
256e4be8 SR |
204 | break; |
205 | case PCI_MS_IO: | |
dcb2f95a | 206 | ctl |= 0x00000001; |
256e4be8 SR |
207 | break; |
208 | case PCI_MS_CONFIG: | |
dcb2f95a | 209 | ctl |= 0x00000002; |
256e4be8 SR |
210 | break; |
211 | } | |
212 | ||
213 | ctl |= 0x80000000; /* enable */ | |
214 | ||
215 | writel(ctl, &dev->uregs->lsi[i].ctl); | |
216 | ||
e2ffd59b WD |
217 | debug ("universe: window-addr=%p\n", &dev->uregs->lsi[i].ctl); |
218 | debug ("universe: pci slave window[%d] ctl=%08x\n", i, readl(&dev->uregs->lsi[i].ctl)); | |
219 | debug ("universe: pci slave window[%d] bs=%08x\n", i, readl(&dev->uregs->lsi[i].bs)); | |
220 | debug ("universe: pci slave window[%d] bd=%08x\n", i, readl(&dev->uregs->lsi[i].bd)); | |
221 | debug ("universe: pci slave window[%d] to=%08x\n", i, readl(&dev->uregs->lsi[i].to)); | |
256e4be8 SR |
222 | |
223 | return 0; | |
224 | ||
225 | exit_10: | |
226 | return -result; | |
227 | } | |
228 | ||
229 | ||
230 | /* | |
231 | * Create vme slave window (access: vme -> pci) | |
232 | */ | |
233 | int universe_vme_slave_window(unsigned int vmeAddr, unsigned int pciAddr, int size, int vam, int pms) | |
234 | { | |
235 | int result, i; | |
236 | unsigned int ctl = 0; | |
237 | ||
238 | if (NULL == dev) { | |
239 | result = -1; | |
240 | goto exit_10; | |
241 | } | |
242 | ||
243 | for (i = 0; i < 4; i++) { | |
244 | if (0x00800000 == readl(&dev->uregs->vsi[i].ctl)) | |
245 | break; | |
246 | } | |
247 | ||
248 | if (i == 4) { | |
e2ffd59b | 249 | printf ("universe: No Image available\n"); |
256e4be8 SR |
250 | result = -1; |
251 | goto exit_10; | |
252 | } | |
253 | ||
e2ffd59b | 254 | debug ("universe: Using image %d\n", i); |
256e4be8 SR |
255 | |
256 | writel(vmeAddr , &dev->uregs->vsi[i].bs); | |
257 | writel((vmeAddr + size), &dev->uregs->vsi[i].bd); | |
258 | writel((pciAddr - vmeAddr), &dev->uregs->vsi[i].to); | |
259 | ||
260 | switch (vam & VME_AM_Axx) { | |
261 | case VME_AM_A16: | |
262 | ctl = 0x00000000; | |
263 | break; | |
264 | case VME_AM_A24: | |
265 | ctl = 0x00010000; | |
266 | break; | |
267 | case VME_AM_A32: | |
268 | ctl = 0x00020000; | |
269 | break; | |
270 | } | |
271 | ||
272 | switch (vam & VME_AM_Mxx) { | |
273 | case VME_AM_DATA: | |
274 | ctl |= 0x00000000; | |
275 | break; | |
276 | case VME_AM_PROG: | |
277 | ctl |= 0x00800000; | |
278 | break; | |
279 | } | |
280 | ||
281 | if (vam & VME_AM_SUP) { | |
282 | ctl |= 0x00100000; | |
283 | ||
284 | } | |
285 | ||
286 | switch (pms & PCI_MS_Mxx) { | |
287 | case PCI_MS_MEM: | |
dcb2f95a | 288 | ctl |= 0x00000000; |
256e4be8 SR |
289 | break; |
290 | case PCI_MS_IO: | |
dcb2f95a | 291 | ctl |= 0x00000001; |
256e4be8 SR |
292 | break; |
293 | case PCI_MS_CONFIG: | |
dcb2f95a | 294 | ctl |= 0x00000002; |
256e4be8 SR |
295 | break; |
296 | } | |
297 | ||
298 | ctl |= 0x80f00000; /* enable */ | |
299 | ||
300 | writel(ctl, &dev->uregs->vsi[i].ctl); | |
301 | ||
e2ffd59b WD |
302 | debug ("universe: window-addr=%p\n", &dev->uregs->vsi[i].ctl); |
303 | debug ("universe: vme slave window[%d] ctl=%08x\n", i, readl(&dev->uregs->vsi[i].ctl)); | |
304 | debug ("universe: vme slave window[%d] bs=%08x\n", i, readl(&dev->uregs->vsi[i].bs)); | |
305 | debug ("universe: vme slave window[%d] bd=%08x\n", i, readl(&dev->uregs->vsi[i].bd)); | |
306 | debug ("universe: vme slave window[%d] to=%08x\n", i, readl(&dev->uregs->vsi[i].to)); | |
256e4be8 SR |
307 | |
308 | return 0; | |
309 | ||
310 | exit_10: | |
311 | return -result; | |
312 | } | |
313 | ||
314 | ||
315 | /* | |
316 | * Tundra Universe configuration | |
317 | */ | |
54841ab5 | 318 | int do_universe(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
256e4be8 SR |
319 | { |
320 | ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, pms = 0, vdw = 0; | |
321 | char cmd = 'x'; | |
322 | ||
323 | /* get parameter */ | |
324 | if (argc > 1) | |
325 | cmd = argv[1][0]; | |
326 | if (argc > 2) | |
327 | addr1 = simple_strtoul(argv[2], NULL, 16); | |
328 | if (argc > 3) | |
329 | addr2 = simple_strtoul(argv[3], NULL, 16); | |
330 | if (argc > 4) | |
331 | size = simple_strtoul(argv[4], NULL, 16); | |
332 | if (argc > 5) | |
333 | vam = simple_strtoul(argv[5], NULL, 16); | |
334 | if (argc > 6) | |
335 | pms = simple_strtoul(argv[6], NULL, 16); | |
336 | if (argc > 7) | |
337 | vdw = simple_strtoul(argv[7], NULL, 16); | |
338 | ||
339 | switch (cmd) { | |
340 | case 'i': /* init */ | |
341 | universe_init(); | |
342 | break; | |
343 | case 'v': /* vme */ | |
344 | printf("Configuring Universe VME Slave Window (VME->PCI):\n"); | |
345 | printf(" vme=%08lx pci=%08lx size=%08lx vam=%02lx pms=%02lx\n", | |
346 | addr1, addr2, size, vam, pms); | |
347 | universe_vme_slave_window(addr1, addr2, size, vam, pms); | |
348 | break; | |
349 | case 'p': /* pci */ | |
350 | printf("Configuring Universe PCI Slave Window (PCI->VME):\n"); | |
351 | printf(" pci=%08lx vme=%08lx size=%08lx vam=%02lx pms=%02lx vdw=%02lx\n", | |
352 | addr1, addr2, size, vam, pms, vdw); | |
353 | universe_pci_slave_window(addr1, addr2, size, vam, pms, vdw); | |
354 | break; | |
355 | default: | |
356 | printf("Universe command %s not supported!\n", argv[1]); | |
357 | } | |
358 | ||
359 | return 0; | |
360 | } | |
361 | ||
362 | ||
363 | U_BOOT_CMD( | |
364 | universe, 8, 1, do_universe, | |
2fb2604d | 365 | "initialize and configure Turndra Universe", |
256e4be8 SR |
366 | "init\n" |
367 | " - initialize universe\n" | |
368 | "universe vme [vme_addr] [pci_addr] [size] [vam] [pms]\n" | |
369 | " - create vme slave window (access: vme->pci)\n" | |
370 | "universe pci [pci_addr] [vme_addr] [size] [vam] [pms] [vdw]\n" | |
371 | " - create pci slave window (access: pci->vme)\n" | |
372 | " [vam] = VMEbus Address-Modifier: 01 -> A16 Address Space\n" | |
373 | " 02 -> A24 Address Space\n" | |
374 | " 03 -> A32 Address Space\n" | |
375 | " 04 -> Supervisor AM Code\n" | |
376 | " 10 -> Data AM Code\n" | |
377 | " 20 -> Program AM Code\n" | |
378 | " [pms] = PCI Memory Space: 01 -> Memory Space\n" | |
379 | " 02 -> I/O Space\n" | |
380 | " 03 -> Configuration Space\n" | |
381 | " [vdw] = VMEbus Maximum Datawidth: 01 -> D8 Data Width\n" | |
382 | " 02 -> D16 Data Width\n" | |
a89c33db | 383 | " 03 -> D32 Data Width" |
256e4be8 | 384 | ); |