tsi148.c 11 KB

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