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