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