cmd_tsi148.c 12 KB

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