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