tsi148.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2009 Reinhard Arlt, reinhard.arlt@esd-electronics.com
  4. *
  5. * base on universe.h by
  6. *
  7. * (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com
  8. */
  9. #include <common.h>
  10. #include <command.h>
  11. #include <malloc.h>
  12. #include <asm/io.h>
  13. #include <pci.h>
  14. #include <tsi148.h>
  15. #define LPCI_VENDOR PCI_VENDOR_ID_TUNDRA
  16. #define LPCI_DEVICE PCI_DEVICE_ID_TUNDRA_TSI148
  17. typedef struct _TSI148_DEV TSI148_DEV;
  18. struct _TSI148_DEV {
  19. int bus;
  20. pci_dev_t busdevfn;
  21. TSI148 *uregs;
  22. unsigned int pci_bs;
  23. };
  24. static TSI148_DEV *dev;
  25. /*
  26. * Most of the TSI148 register are BIGENDIAN
  27. * This is the reason for the __raw_writel(htonl(x), x) usage!
  28. */
  29. int tsi148_init(void)
  30. {
  31. int j, result;
  32. pci_dev_t busdevfn;
  33. unsigned int val;
  34. busdevfn = pci_find_device(LPCI_VENDOR, LPCI_DEVICE, 0);
  35. if (busdevfn == -1) {
  36. puts("Tsi148: No Tundra Tsi148 found!\n");
  37. return -1;
  38. }
  39. /* Lets turn Latency off */
  40. pci_write_config_dword(busdevfn, 0x0c, 0);
  41. dev = malloc(sizeof(*dev));
  42. if (NULL == dev) {
  43. puts("Tsi148: No memory!\n");
  44. return -1;
  45. }
  46. memset(dev, 0, sizeof(*dev));
  47. dev->busdevfn = busdevfn;
  48. pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_0, &val);
  49. val &= ~0xf;
  50. dev->uregs = (TSI148 *)val;
  51. debug("Tsi148: Base : %p\n", dev->uregs);
  52. /* check mapping */
  53. debug("Tsi148: Read via mapping, PCI_ID = %08X\n",
  54. readl(&dev->uregs->pci_id));
  55. if (((LPCI_DEVICE << 16) | LPCI_VENDOR) != readl(&dev->uregs->pci_id)) {
  56. printf("Tsi148: Cannot read PCI-ID via Mapping: %08x\n",
  57. readl(&dev->uregs->pci_id));
  58. result = -1;
  59. goto break_30;
  60. }
  61. debug("Tsi148: PCI_BS = %08X\n", readl(&dev->uregs->pci_mbarl));
  62. dev->pci_bs = readl(&dev->uregs->pci_mbarl);
  63. /* turn off windows */
  64. for (j = 0; j < 8; j++) {
  65. __raw_writel(htonl(0x00000000), &dev->uregs->outbound[j].otat);
  66. __raw_writel(htonl(0x00000000), &dev->uregs->inbound[j].itat);
  67. }
  68. /* Tsi148 VME timeout etc */
  69. __raw_writel(htonl(0x00000084), &dev->uregs->vctrl);
  70. #ifdef DEBUG
  71. if ((__raw_readl(&dev->uregs->vstat) & 0x00000100) != 0)
  72. printf("Tsi148: System Controller!\n");
  73. else
  74. printf("Tsi148: Not System Controller!\n");
  75. #endif
  76. /*
  77. * Lets turn off interrupts
  78. */
  79. /* Disable interrupts in Tsi148 first */
  80. __raw_writel(htonl(0x00000000), &dev->uregs->inten);
  81. /* Disable interrupt out */
  82. __raw_writel(htonl(0x00000000), &dev->uregs->inteo);
  83. eieio();
  84. /* Reset all IRQ's */
  85. __raw_writel(htonl(0x03ff3f00), &dev->uregs->intc);
  86. /* Map all ints to 0 */
  87. __raw_writel(htonl(0x00000000), &dev->uregs->intm1);
  88. __raw_writel(htonl(0x00000000), &dev->uregs->intm2);
  89. eieio();
  90. val = __raw_readl(&dev->uregs->vstat);
  91. val &= ~(0x00004000);
  92. __raw_writel(val, &dev->uregs->vstat);
  93. eieio();
  94. debug("Tsi148: register struct size %08x\n", sizeof(TSI148));
  95. return 0;
  96. break_30:
  97. free(dev);
  98. dev = NULL;
  99. return result;
  100. }
  101. /*
  102. * Create pci slave window (access: pci -> vme)
  103. */
  104. int tsi148_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr,
  105. int size, int vam, int vdw)
  106. {
  107. int result, i;
  108. unsigned int ctl = 0;
  109. if (NULL == dev) {
  110. result = -1;
  111. goto exit_10;
  112. }
  113. for (i = 0; i < 8; i++) {
  114. if (0x00000000 == readl(&dev->uregs->outbound[i].otat))
  115. break;
  116. }
  117. if (i > 7) {
  118. printf("Tsi148: No Image available\n");
  119. result = -1;
  120. goto exit_10;
  121. }
  122. debug("Tsi148: Using image %d\n", i);
  123. printf("Tsi148: Pci addr %08x\n", pciAddr);
  124. __raw_writel(htonl(pciAddr), &dev->uregs->outbound[i].otsal);
  125. __raw_writel(0x00000000, &dev->uregs->outbound[i].otsau);
  126. __raw_writel(htonl(pciAddr + size), &dev->uregs->outbound[i].oteal);
  127. __raw_writel(0x00000000, &dev->uregs->outbound[i].oteau);
  128. __raw_writel(htonl(vmeAddr - pciAddr), &dev->uregs->outbound[i].otofl);
  129. __raw_writel(0x00000000, &dev->uregs->outbound[i].otofu);
  130. switch (vam & VME_AM_Axx) {
  131. case VME_AM_A16:
  132. ctl = 0x00000000;
  133. break;
  134. case VME_AM_A24:
  135. ctl = 0x00000001;
  136. break;
  137. case VME_AM_A32:
  138. ctl = 0x00000002;
  139. break;
  140. }
  141. switch (vam & VME_AM_Mxx) {
  142. case VME_AM_DATA:
  143. ctl |= 0x00000000;
  144. break;
  145. case VME_AM_PROG:
  146. ctl |= 0x00000010;
  147. break;
  148. }
  149. if (vam & VME_AM_SUP)
  150. ctl |= 0x00000020;
  151. switch (vdw & VME_FLAG_Dxx) {
  152. case VME_FLAG_D16:
  153. ctl |= 0x00000000;
  154. break;
  155. case VME_FLAG_D32:
  156. ctl |= 0x00000040;
  157. break;
  158. }
  159. ctl |= 0x80040000; /* enable, no prefetch */
  160. __raw_writel(htonl(ctl), &dev->uregs->outbound[i].otat);
  161. debug("Tsi148: window-addr =%p\n",
  162. &dev->uregs->outbound[i].otsau);
  163. debug("Tsi148: pci slave window[%d] attr =%08x\n",
  164. i, ntohl(__raw_readl(&dev->uregs->outbound[i].otat)));
  165. debug("Tsi148: pci slave window[%d] start =%08x\n",
  166. i, ntohl(__raw_readl(&dev->uregs->outbound[i].otsal)));
  167. debug("Tsi148: pci slave window[%d] end =%08x\n",
  168. i, ntohl(__raw_readl(&dev->uregs->outbound[i].oteal)));
  169. debug("Tsi148: pci slave window[%d] offset=%08x\n",
  170. i, ntohl(__raw_readl(&dev->uregs->outbound[i].otofl)));
  171. return 0;
  172. exit_10:
  173. return -result;
  174. }
  175. unsigned int tsi148_eval_vam(int vam)
  176. {
  177. unsigned int ctl = 0;
  178. switch (vam & VME_AM_Axx) {
  179. case VME_AM_A16:
  180. ctl = 0x00000000;
  181. break;
  182. case VME_AM_A24:
  183. ctl = 0x00000010;
  184. break;
  185. case VME_AM_A32:
  186. ctl = 0x00000020;
  187. break;
  188. }
  189. switch (vam & VME_AM_Mxx) {
  190. case VME_AM_DATA:
  191. ctl |= 0x00000001;
  192. break;
  193. case VME_AM_PROG:
  194. ctl |= 0x00000002;
  195. break;
  196. case (VME_AM_PROG | VME_AM_DATA):
  197. ctl |= 0x00000003;
  198. break;
  199. }
  200. if (vam & VME_AM_SUP)
  201. ctl |= 0x00000008;
  202. if (vam & VME_AM_USR)
  203. ctl |= 0x00000004;
  204. return ctl;
  205. }
  206. /*
  207. * Create vme slave window (access: vme -> pci)
  208. */
  209. int tsi148_vme_slave_window(unsigned int vmeAddr, unsigned int pciAddr,
  210. int size, int vam)
  211. {
  212. int result, i;
  213. unsigned int ctl = 0;
  214. if (NULL == dev) {
  215. result = -1;
  216. goto exit_10;
  217. }
  218. for (i = 0; i < 8; i++) {
  219. if (0x00000000 == readl(&dev->uregs->inbound[i].itat))
  220. break;
  221. }
  222. if (i > 7) {
  223. printf("Tsi148: No Image available\n");
  224. result = -1;
  225. goto exit_10;
  226. }
  227. debug("Tsi148: Using image %d\n", i);
  228. __raw_writel(htonl(vmeAddr), &dev->uregs->inbound[i].itsal);
  229. __raw_writel(0x00000000, &dev->uregs->inbound[i].itsau);
  230. __raw_writel(htonl(vmeAddr + size), &dev->uregs->inbound[i].iteal);
  231. __raw_writel(0x00000000, &dev->uregs->inbound[i].iteau);
  232. __raw_writel(htonl(pciAddr - vmeAddr), &dev->uregs->inbound[i].itofl);
  233. if (vmeAddr > pciAddr)
  234. __raw_writel(0xffffffff, &dev->uregs->inbound[i].itofu);
  235. else
  236. __raw_writel(0x00000000, &dev->uregs->inbound[i].itofu);
  237. ctl = tsi148_eval_vam(vam);
  238. ctl |= 0x80000000; /* enable */
  239. __raw_writel(htonl(ctl), &dev->uregs->inbound[i].itat);
  240. debug("Tsi148: window-addr =%p\n",
  241. &dev->uregs->inbound[i].itsau);
  242. debug("Tsi148: vme slave window[%d] attr =%08x\n",
  243. i, ntohl(__raw_readl(&dev->uregs->inbound[i].itat)));
  244. debug("Tsi148: vme slave window[%d] start =%08x\n",
  245. i, ntohl(__raw_readl(&dev->uregs->inbound[i].itsal)));
  246. debug("Tsi148: vme slave window[%d] end =%08x\n",
  247. i, ntohl(__raw_readl(&dev->uregs->inbound[i].iteal)));
  248. debug("Tsi148: vme slave window[%d] offset=%08x\n",
  249. i, ntohl(__raw_readl(&dev->uregs->inbound[i].itofl)));
  250. return 0;
  251. exit_10:
  252. return -result;
  253. }
  254. /*
  255. * Create vme slave window (access: vme -> gcsr)
  256. */
  257. int tsi148_vme_gcsr_window(unsigned int vmeAddr, int vam)
  258. {
  259. int result;
  260. unsigned int ctl;
  261. result = 0;
  262. if (NULL == dev) {
  263. result = 1;
  264. } else {
  265. __raw_writel(htonl(vmeAddr), &dev->uregs->gbal);
  266. __raw_writel(0x00000000, &dev->uregs->gbau);
  267. ctl = tsi148_eval_vam(vam);
  268. ctl |= 0x00000080; /* enable */
  269. __raw_writel(htonl(ctl), &dev->uregs->gcsrat);
  270. }
  271. return result;
  272. }
  273. /*
  274. * Create vme slave window (access: vme -> crcsr)
  275. */
  276. int tsi148_vme_crcsr_window(unsigned int vmeAddr)
  277. {
  278. int result;
  279. unsigned int ctl;
  280. result = 0;
  281. if (NULL == dev) {
  282. result = 1;
  283. } else {
  284. __raw_writel(htonl(vmeAddr), &dev->uregs->crol);
  285. __raw_writel(0x00000000, &dev->uregs->crou);
  286. ctl = 0x00000080; /* enable */
  287. __raw_writel(htonl(ctl), &dev->uregs->crat);
  288. }
  289. return result;
  290. }
  291. /*
  292. * Create vme slave window (access: vme -> crg)
  293. */
  294. int tsi148_vme_crg_window(unsigned int vmeAddr, int vam)
  295. {
  296. int result;
  297. unsigned int ctl;
  298. result = 0;
  299. if (NULL == dev) {
  300. result = 1;
  301. } else {
  302. __raw_writel(htonl(vmeAddr), &dev->uregs->cbal);
  303. __raw_writel(0x00000000, &dev->uregs->cbau);
  304. ctl = tsi148_eval_vam(vam);
  305. ctl |= 0x00000080; /* enable */
  306. __raw_writel(htonl(ctl), &dev->uregs->crgat);
  307. }
  308. return result;
  309. }
  310. /*
  311. * Tundra Tsi148 configuration
  312. */
  313. int do_tsi148(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  314. {
  315. ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, vdw = 0;
  316. char cmd = 'x';
  317. /* get parameter */
  318. if (argc > 1)
  319. cmd = argv[1][0];
  320. if (argc > 2)
  321. addr1 = simple_strtoul(argv[2], NULL, 16);
  322. if (argc > 3)
  323. addr2 = simple_strtoul(argv[3], NULL, 16);
  324. if (argc > 4)
  325. size = simple_strtoul(argv[4], NULL, 16);
  326. if (argc > 5)
  327. vam = simple_strtoul(argv[5], NULL, 16);
  328. if (argc > 6)
  329. vdw = simple_strtoul(argv[6], NULL, 16);
  330. switch (cmd) {
  331. case 'c':
  332. if (strcmp(argv[1], "crg") == 0) {
  333. vam = addr2;
  334. printf("Tsi148: Configuring VME CRG Window "
  335. "(VME->CRG):\n");
  336. printf(" vme=%08lx vam=%02lx\n", addr1, vam);
  337. tsi148_vme_crg_window(addr1, vam);
  338. } else {
  339. printf("Tsi148: Configuring VME CR/CSR Window "
  340. "(VME->CR/CSR):\n");
  341. printf(" pci=%08lx\n", addr1);
  342. tsi148_vme_crcsr_window(addr1);
  343. }
  344. break;
  345. case 'i': /* init */
  346. tsi148_init();
  347. break;
  348. case 'g':
  349. vam = addr2;
  350. printf("Tsi148: Configuring VME GCSR Window (VME->GCSR):\n");
  351. printf(" vme=%08lx vam=%02lx\n", addr1, vam);
  352. tsi148_vme_gcsr_window(addr1, vam);
  353. break;
  354. case 'v': /* vme */
  355. printf("Tsi148: Configuring VME Slave Window (VME->PCI):\n");
  356. printf(" vme=%08lx pci=%08lx size=%08lx vam=%02lx\n",
  357. addr1, addr2, size, vam);
  358. tsi148_vme_slave_window(addr1, addr2, size, vam);
  359. break;
  360. case 'p': /* pci */
  361. printf("Tsi148: Configuring PCI Slave Window (PCI->VME):\n");
  362. printf(" pci=%08lx vme=%08lx size=%08lx vam=%02lx vdw=%02lx\n",
  363. addr1, addr2, size, vam, vdw);
  364. tsi148_pci_slave_window(addr1, addr2, size, vam, vdw);
  365. break;
  366. default:
  367. printf("Tsi148: Command %s not supported!\n", argv[1]);
  368. }
  369. return 0;
  370. }
  371. U_BOOT_CMD(
  372. tsi148, 7, 1, do_tsi148,
  373. "initialize and configure Turndra Tsi148\n",
  374. "init\n"
  375. " - initialize tsi148\n"
  376. "tsi148 vme [vme_addr] [pci_addr] [size] [vam]\n"
  377. " - create vme slave window (access: vme->pci)\n"
  378. "tsi148 pci [pci_addr] [vme_addr] [size] [vam] [vdw]\n"
  379. " - create pci slave window (access: pci->vme)\n"
  380. "tsi148 crg [vme_addr] [vam]\n"
  381. " - create vme slave window: (access vme->CRG\n"
  382. "tsi148 crcsr [pci_addr]\n"
  383. " - create vme slave window: (access vme->CR/CSR\n"
  384. "tsi148 gcsr [vme_addr] [vam]\n"
  385. " - create vme slave window: (access vme->GCSR\n"
  386. " [vam] = VMEbus Address-Modifier: 01 -> A16 Address Space\n"
  387. " 02 -> A24 Address Space\n"
  388. " 03 -> A32 Address Space\n"
  389. " 04 -> Usr AM Code\n"
  390. " 08 -> Supervisor AM Code\n"
  391. " 10 -> Data AM Code\n"
  392. " 20 -> Program AM Code\n"
  393. " [vdw] = VMEbus Maximum Datawidth: 02 -> D16 Data Width\n"
  394. " 03 -> D32 Data Width\n"
  395. );