1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <common.h>
28#include <command.h>
29#include <malloc.h>
30#include <asm/io.h>
31#include <pci.h>
32
33#include <tsi148.h>
34
35#define PCI_VENDOR PCI_VENDOR_ID_TUNDRA
36#define PCI_DEVICE PCI_DEVICE_ID_TUNDRA_TSI148
37
38typedef struct _TSI148_DEV TSI148_DEV;
39
40struct _TSI148_DEV {
41 int bus;
42 pci_dev_t busdevfn;
43 TSI148 *uregs;
44 unsigned int pci_bs;
45};
46
47static TSI148_DEV *dev;
48
49
50
51
52
53
54int tsi148_init(void)
55{
56 int j, result, lastError = 0;
57 pci_dev_t busdevfn;
58 unsigned int val;
59
60 busdevfn = pci_find_device(PCI_VENDOR, PCI_DEVICE, 0);
61 if (busdevfn == -1) {
62 puts("Tsi148: No Tundra Tsi148 found!\n");
63 return -1;
64 }
65
66
67 pci_write_config_dword(busdevfn, 0x0c, 0);
68
69 dev = malloc(sizeof(*dev));
70 if (NULL == dev) {
71 puts("Tsi148: No memory!\n");
72 result = -1;
73 goto break_20;
74 }
75
76 memset(dev, 0, sizeof(*dev));
77 dev->busdevfn = busdevfn;
78
79 pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_0, &val);
80 val &= ~0xf;
81 dev->uregs = (TSI148 *)val;
82
83 debug("Tsi148: Base : %p\n", dev->uregs);
84
85
86 debug("Tsi148: Read via mapping, PCI_ID = %08X\n",
87 readl(&dev->uregs->pci_id));
88 if (((PCI_DEVICE << 16) | PCI_VENDOR) != readl(&dev->uregs->pci_id)) {
89 printf("Tsi148: Cannot read PCI-ID via Mapping: %08x\n",
90 readl(&dev->uregs->pci_id));
91 result = -1;
92 goto break_30;
93 }
94
95 debug("Tsi148: PCI_BS = %08X\n", readl(&dev->uregs->pci_mbarl));
96
97 dev->pci_bs = readl(&dev->uregs->pci_mbarl);
98
99
100 for (j = 0; j < 8; j++) {
101 __raw_writel(htonl(0x00000000), &dev->uregs->outbound[j].otat);
102 __raw_writel(htonl(0x00000000), &dev->uregs->inbound[j].itat);
103 }
104
105
106 __raw_writel(htonl(0x00000084), &dev->uregs->vctrl);
107
108#ifdef DEBUG
109 if ((__raw_readl(&dev->uregs->vstat) & 0x00000100) != 0)
110 printf("Tsi148: System Controller!\n");
111 else
112 printf("Tsi148: Not System Controller!\n");
113#endif
114
115
116
117
118
119 __raw_writel(htonl(0x00000000), &dev->uregs->inten);
120
121 __raw_writel(htonl(0x00000000), &dev->uregs->inteo);
122 eieio();
123
124 __raw_writel(htonl(0x03ff3f00), &dev->uregs->intc);
125
126 __raw_writel(htonl(0x00000000), &dev->uregs->intm1);
127 __raw_writel(htonl(0x00000000), &dev->uregs->intm2);
128 eieio();
129
130 val = __raw_readl(&dev->uregs->vstat);
131 val &= ~(0x00004000);
132 __raw_writel(val, &dev->uregs->vstat);
133 eieio();
134
135 debug("Tsi148: register struct size %08x\n", sizeof(TSI148));
136
137 return 0;
138
139 break_30:
140 free(dev);
141 dev = NULL;
142 break_20:
143 lastError = result;
144
145 return result;
146}
147
148
149
150
151int tsi148_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr,
152 int size, int vam, int vdw)
153{
154 int result, i;
155 unsigned int ctl = 0;
156
157 if (NULL == dev) {
158 result = -1;
159 goto exit_10;
160 }
161
162 for (i = 0; i < 8; i++) {
163 if (0x00000000 == readl(&dev->uregs->outbound[i].otat))
164 break;
165 }
166
167 if (i > 7) {
168 printf("Tsi148: No Image available\n");
169 result = -1;
170 goto exit_10;
171 }
172
173 debug("Tsi148: Using image %d\n", i);
174
175 printf("Tsi148: Pci addr %08x\n", pciAddr);
176
177 __raw_writel(htonl(pciAddr), &dev->uregs->outbound[i].otsal);
178 __raw_writel(0x00000000, &dev->uregs->outbound[i].otsau);
179 __raw_writel(htonl(pciAddr + size), &dev->uregs->outbound[i].oteal);
180 __raw_writel(0x00000000, &dev->uregs->outbound[i].oteau);
181 __raw_writel(htonl(vmeAddr - pciAddr), &dev->uregs->outbound[i].otofl);
182 __raw_writel(0x00000000, &dev->uregs->outbound[i].otofu);
183
184 switch (vam & VME_AM_Axx) {
185 case VME_AM_A16:
186 ctl = 0x00000000;
187 break;
188 case VME_AM_A24:
189 ctl = 0x00000001;
190 break;
191 case VME_AM_A32:
192 ctl = 0x00000002;
193 break;
194 }
195
196 switch (vam & VME_AM_Mxx) {
197 case VME_AM_DATA:
198 ctl |= 0x00000000;
199 break;
200 case VME_AM_PROG:
201 ctl |= 0x00000010;
202 break;
203 }
204
205 if (vam & VME_AM_SUP)
206 ctl |= 0x00000020;
207
208 switch (vdw & VME_FLAG_Dxx) {
209 case VME_FLAG_D16:
210 ctl |= 0x00000000;
211 break;
212 case VME_FLAG_D32:
213 ctl |= 0x00000040;
214 break;
215 }
216
217 ctl |= 0x80040000;
218
219 __raw_writel(htonl(ctl), &dev->uregs->outbound[i].otat);
220
221 debug("Tsi148: window-addr =%p\n",
222 &dev->uregs->outbound[i].otsau);
223 debug("Tsi148: pci slave window[%d] attr =%08x\n",
224 i, ntohl(__raw_readl(&dev->uregs->outbound[i].otat)));
225 debug("Tsi148: pci slave window[%d] start =%08x\n",
226 i, ntohl(__raw_readl(&dev->uregs->outbound[i].otsal)));
227 debug("Tsi148: pci slave window[%d] end =%08x\n",
228 i, ntohl(__raw_readl(&dev->uregs->outbound[i].oteal)));
229 debug("Tsi148: pci slave window[%d] offset=%08x\n",
230 i, ntohl(__raw_readl(&dev->uregs->outbound[i].otofl)));
231
232 return 0;
233
234 exit_10:
235 return -result;
236}
237
238unsigned int tsi148_eval_vam(int vam)
239{
240 unsigned int ctl = 0;
241
242 switch (vam & VME_AM_Axx) {
243 case VME_AM_A16:
244 ctl = 0x00000000;
245 break;
246 case VME_AM_A24:
247 ctl = 0x00000010;
248 break;
249 case VME_AM_A32:
250 ctl = 0x00000020;
251 break;
252 }
253 switch (vam & VME_AM_Mxx) {
254 case VME_AM_DATA:
255 ctl |= 0x00000001;
256 break;
257 case VME_AM_PROG:
258 ctl |= 0x00000002;
259 break;
260 case (VME_AM_PROG | VME_AM_DATA):
261 ctl |= 0x00000003;
262 break;
263 }
264
265 if (vam & VME_AM_SUP)
266 ctl |= 0x00000008;
267 if (vam & VME_AM_USR)
268 ctl |= 0x00000004;
269
270 return ctl;
271}
272
273
274
275
276int tsi148_vme_slave_window(unsigned int vmeAddr, unsigned int pciAddr,
277 int size, int vam)
278{
279 int result, i;
280 unsigned int ctl = 0;
281
282 if (NULL == dev) {
283 result = -1;
284 goto exit_10;
285 }
286
287 for (i = 0; i < 8; i++) {
288 if (0x00000000 == readl(&dev->uregs->inbound[i].itat))
289 break;
290 }
291
292 if (i > 7) {
293 printf("Tsi148: No Image available\n");
294 result = -1;
295 goto exit_10;
296 }
297
298 debug("Tsi148: Using image %d\n", i);
299
300 __raw_writel(htonl(vmeAddr), &dev->uregs->inbound[i].itsal);
301 __raw_writel(0x00000000, &dev->uregs->inbound[i].itsau);
302 __raw_writel(htonl(vmeAddr + size), &dev->uregs->inbound[i].iteal);
303 __raw_writel(0x00000000, &dev->uregs->inbound[i].iteau);
304 __raw_writel(htonl(pciAddr - vmeAddr), &dev->uregs->inbound[i].itofl);
305 if (vmeAddr > pciAddr)
306 __raw_writel(0xffffffff, &dev->uregs->inbound[i].itofu);
307 else
308 __raw_writel(0x00000000, &dev->uregs->inbound[i].itofu);
309
310 ctl = tsi148_eval_vam(vam);
311 ctl |= 0x80000000;
312 __raw_writel(htonl(ctl), &dev->uregs->inbound[i].itat);
313
314 debug("Tsi148: window-addr =%p\n",
315 &dev->uregs->inbound[i].itsau);
316 debug("Tsi148: vme slave window[%d] attr =%08x\n",
317 i, ntohl(__raw_readl(&dev->uregs->inbound[i].itat)));
318 debug("Tsi148: vme slave window[%d] start =%08x\n",
319 i, ntohl(__raw_readl(&dev->uregs->inbound[i].itsal)));
320 debug("Tsi148: vme slave window[%d] end =%08x\n",
321 i, ntohl(__raw_readl(&dev->uregs->inbound[i].iteal)));
322 debug("Tsi148: vme slave window[%d] offset=%08x\n",
323 i, ntohl(__raw_readl(&dev->uregs->inbound[i].itofl)));
324
325 return 0;
326
327 exit_10:
328 return -result;
329}
330
331
332
333
334int tsi148_vme_gcsr_window(unsigned int vmeAddr, int vam)
335{
336 int result;
337 unsigned int ctl;
338
339 result = 0;
340
341 if (NULL == dev) {
342 result = 1;
343 } else {
344 __raw_writel(htonl(vmeAddr), &dev->uregs->gbal);
345 __raw_writel(0x00000000, &dev->uregs->gbau);
346
347 ctl = tsi148_eval_vam(vam);
348 ctl |= 0x00000080;
349 __raw_writel(htonl(ctl), &dev->uregs->gcsrat);
350 }
351
352 return result;
353}
354
355
356
357
358int tsi148_vme_crcsr_window(unsigned int vmeAddr)
359{
360 int result;
361 unsigned int ctl;
362
363 result = 0;
364
365 if (NULL == dev) {
366 result = 1;
367 } else {
368 __raw_writel(htonl(vmeAddr), &dev->uregs->crol);
369 __raw_writel(0x00000000, &dev->uregs->crou);
370
371 ctl = 0x00000080;
372 __raw_writel(htonl(ctl), &dev->uregs->crat);
373 }
374
375 return result;
376}
377
378
379
380
381int tsi148_vme_crg_window(unsigned int vmeAddr, int vam)
382{
383 int result;
384 unsigned int ctl;
385
386 result = 0;
387
388 if (NULL == dev) {
389 result = 1;
390 } else {
391 __raw_writel(htonl(vmeAddr), &dev->uregs->cbal);
392 __raw_writel(0x00000000, &dev->uregs->cbau);
393
394 ctl = tsi148_eval_vam(vam);
395 ctl |= 0x00000080;
396 __raw_writel(htonl(ctl), &dev->uregs->crgat);
397 }
398
399 return result;
400}
401
402
403
404
405int do_tsi148(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
406{
407 ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, vdw = 0;
408 char cmd = 'x';
409
410
411 if (argc > 1)
412 cmd = argv[1][0];
413 if (argc > 2)
414 addr1 = simple_strtoul(argv[2], NULL, 16);
415 if (argc > 3)
416 addr2 = simple_strtoul(argv[3], NULL, 16);
417 if (argc > 4)
418 size = simple_strtoul(argv[4], NULL, 16);
419 if (argc > 5)
420 vam = simple_strtoul(argv[5], NULL, 16);
421 if (argc > 6)
422 vdw = simple_strtoul(argv[7], NULL, 16);
423
424 switch (cmd) {
425 case 'c':
426 if (strcmp(argv[1], "crg") == 0) {
427 vam = addr2;
428 printf("Tsi148: Configuring VME CRG Window "
429 "(VME->CRG):\n");
430 printf(" vme=%08lx vam=%02lx\n", addr1, vam);
431 tsi148_vme_crg_window(addr1, vam);
432 } else {
433 printf("Tsi148: Configuring VME CR/CSR Window "
434 "(VME->CR/CSR):\n");
435 printf(" pci=%08lx\n", addr1);
436 tsi148_vme_crcsr_window(addr1);
437 }
438 break;
439 case 'i':
440 tsi148_init();
441 break;
442 case 'g':
443 vam = addr2;
444 printf("Tsi148: Configuring VME GCSR Window (VME->GCSR):\n");
445 printf(" vme=%08lx vam=%02lx\n", addr1, vam);
446 tsi148_vme_gcsr_window(addr1, vam);
447 break;
448 case 'v':
449 printf("Tsi148: Configuring VME Slave Window (VME->PCI):\n");
450 printf(" vme=%08lx pci=%08lx size=%08lx vam=%02lx\n",
451 addr1, addr2, size, vam);
452 tsi148_vme_slave_window(addr1, addr2, size, vam);
453 break;
454 case 'p':
455 printf("Tsi148: Configuring PCI Slave Window (PCI->VME):\n");
456 printf(" pci=%08lx vme=%08lx size=%08lx vam=%02lx vdw=%02lx\n",
457 addr1, addr2, size, vam, vdw);
458 tsi148_pci_slave_window(addr1, addr2, size, vam, vdw);
459 break;
460 default:
461 printf("Tsi148: Command %s not supported!\n", argv[1]);
462 }
463
464 return 0;
465}
466
467U_BOOT_CMD(
468 tsi148, 8, 1, do_tsi148,
469 "initialize and configure Turndra Tsi148\n",
470 "init\n"
471 " - initialize tsi148\n"
472 "tsi148 vme [vme_addr] [pci_addr] [size] [vam]\n"
473 " - create vme slave window (access: vme->pci)\n"
474 "tsi148 pci [pci_addr] [vme_addr] [size] [vam] [vdw]\n"
475 " - create pci slave window (access: pci->vme)\n"
476 "tsi148 crg [vme_addr] [vam]\n"
477 " - create vme slave window: (access vme->CRG\n"
478 "tsi148 crcsr [pci_addr]\n"
479 " - create vme slave window: (access vme->CR/CSR\n"
480 "tsi148 gcsr [vme_addr] [vam]\n"
481 " - create vme slave window: (access vme->GCSR\n"
482 " [vam] = VMEbus Address-Modifier: 01 -> A16 Address Space\n"
483 " 02 -> A24 Address Space\n"
484 " 03 -> A32 Address Space\n"
485 " 04 -> Usr AM Code\n"
486 " 08 -> Supervisor AM Code\n"
487 " 10 -> Data AM Code\n"
488 " 20 -> Program AM Code\n"
489 " [vdw] = VMEbus Maximum Datawidth: 02 -> D16 Data Width\n"
490 " 03 -> D32 Data Width\n"
491);
492