Home | History | Annotate | Download | only in cmd
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2009 Reinhard Arlt, reinhard.arlt (at) esd-electronics.com
      4  *
      5  * base on universe.h by
      6  *
      7  * (C) Copyright 2003 Stefan Roese, stefan.roese (at) 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