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