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 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 */ 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 */ 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 */ 301 int do_universe(cmd_tbl_t *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