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