cmd_tsi148.c 12 KB

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