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