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