xref: /openbmc/u-boot/cmd/tsi148.c (revision 407b5b956a2e0facf6668fc8b295f4be9205c83e)
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