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. #define DEBUG
  27. #include <common.h>
  28. #include <command.h>
  29. #include <malloc.h>
  30. #include <asm/io.h>
  31. #include <pci.h>
  32. #include <tsi148.h>
  33. #define PCI_VENDOR PCI_VENDOR_ID_TUNDRA
  34. #define PCI_DEVICE PCI_DEVICE_ID_TUNDRA_TSI148
  35. typedef struct _TSI148_DEV TSI148_DEV;
  36. struct _TSI148_DEV {
  37. int bus;
  38. pci_dev_t busdevfn;
  39. TSI148 *uregs;
  40. unsigned int pci_bs;
  41. };
  42. static TSI148_DEV *dev;
  43. /*
  44. * Most of the TSI148 register are BIGENDIAN
  45. * This is the reason for the __raw_writel(htonl(x), x) usage!
  46. */
  47. int tsi148_init(void)
  48. {
  49. int j, result, lastError = 0;
  50. pci_dev_t busdevfn;
  51. unsigned int val;
  52. busdevfn = pci_find_device(PCI_VENDOR, PCI_DEVICE, 0);
  53. if (busdevfn == -1) {
  54. puts("Tsi148: No Tundra Tsi148 found!\n");
  55. return -1;
  56. }
  57. /* Lets turn Latency off */
  58. pci_write_config_dword(busdevfn, 0x0c, 0);
  59. dev = malloc(sizeof(*dev));
  60. if (NULL == dev) {
  61. puts("Tsi148: No memory!\n");
  62. result = -1;
  63. goto break_20;
  64. }
  65. memset(dev, 0, sizeof(*dev));
  66. dev->busdevfn = busdevfn;
  67. pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_0, &val);
  68. val &= ~0xf;
  69. dev->uregs = (TSI148 *)val;
  70. debug("Tsi148: Base : %p\n", dev->uregs);
  71. /* check mapping */
  72. debug("Tsi148: Read via mapping, PCI_ID = %08X\n", 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. if ((__raw_readl(&dev->uregs->vstat) & 0x00000100) != 0)
  89. debug("Tsi148: System Controller!\n");
  90. else
  91. debug("Tsi148: Not System Controller!\n");
  92. /*
  93. * Lets turn off interrupts
  94. */
  95. /* Disable interrupts in Tsi148 first */
  96. __raw_writel(htonl(0x00000000), &dev->uregs->inten);
  97. /* Disable interrupt out */
  98. __raw_writel(htonl(0x00000000), &dev->uregs->inteo);
  99. eieio();
  100. /* Reset all IRQ's */
  101. __raw_writel(htonl(0x03ff3f00), &dev->uregs->intc);
  102. /* Map all ints to 0 */
  103. __raw_writel(htonl(0x00000000), &dev->uregs->intm1);
  104. __raw_writel(htonl(0x00000000), &dev->uregs->intm2);
  105. eieio();
  106. val = __raw_readl(&dev->uregs->vstat);
  107. val &= ~(0x00004000);
  108. __raw_writel(val, &dev->uregs->vstat);
  109. eieio();
  110. debug("Tsi148: register struct size %08x\n", sizeof(TSI148));
  111. return 0;
  112. break_30:
  113. free(dev);
  114. dev = NULL;
  115. break_20:
  116. lastError = result;
  117. return result;
  118. }
  119. /*
  120. * Create pci slave window (access: pci -> vme)
  121. */
  122. int tsi148_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr, 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, int size, int vam)
  227. {
  228. int result, i;
  229. unsigned int ctl = 0;
  230. if (NULL == dev) {
  231. result = -1;
  232. goto exit_10;
  233. }
  234. for (i = 0; i < 8; i++) {
  235. if (0x00000000 == readl(&dev->uregs->inbound[i].itat))
  236. break;
  237. }
  238. if (i > 7) {
  239. printf("Tsi148: No Image available\n");
  240. result = -1;
  241. goto exit_10;
  242. }
  243. debug("Tsi148: Using image %d\n", i);
  244. __raw_writel(htonl(vmeAddr), &dev->uregs->inbound[i].itsal);
  245. __raw_writel(0x00000000, &dev->uregs->inbound[i].itsau);
  246. __raw_writel(htonl(vmeAddr + size), &dev->uregs->inbound[i].iteal);
  247. __raw_writel(0x00000000, &dev->uregs->inbound[i].iteau);
  248. __raw_writel(htonl(pciAddr - vmeAddr), &dev->uregs->inbound[i].itofl);
  249. if (vmeAddr > pciAddr)
  250. __raw_writel(0xffffffff, &dev->uregs->inbound[i].itofu);
  251. else
  252. __raw_writel(0x00000000, &dev->uregs->inbound[i].itofu);
  253. ctl = tsi148_eval_vam(vam);
  254. ctl |= 0x80000000; /* enable */
  255. __raw_writel(htonl(ctl), &dev->uregs->inbound[i].itat);
  256. debug("Tsi148: window-addr =%p\n",
  257. &dev->uregs->inbound[i].itsau);
  258. debug("Tsi148: vme slave window[%d] attr =%08x\n",
  259. i, ntohl(__raw_readl(&dev->uregs->inbound[i].itat))) ;
  260. debug("Tsi148: vme slave window[%d] start =%08x\n",
  261. i, ntohl(__raw_readl(&dev->uregs->inbound[i].itsal)));
  262. debug("Tsi148: vme slave window[%d] end =%08x\n",
  263. i, ntohl(__raw_readl(&dev->uregs->inbound[i].iteal)));
  264. debug("Tsi148: vme slave window[%d] offset=%08x\n",
  265. i, ntohl(__raw_readl(&dev->uregs->inbound[i].itofl)));
  266. return 0;
  267. exit_10:
  268. return -result;
  269. }
  270. /*
  271. * Create vme slave window (access: vme -> gcsr)
  272. */
  273. int tsi148_vme_gcsr_window(unsigned int vmeAddr, int vam)
  274. {
  275. int result;
  276. unsigned int ctl;
  277. result = 0;
  278. if (NULL == dev) {
  279. result = 1;
  280. } else {
  281. __raw_writel(htonl(vmeAddr), &dev->uregs->gbal);
  282. __raw_writel(0x00000000, &dev->uregs->gbau);
  283. ctl = tsi148_eval_vam(vam);
  284. ctl |= 0x00000080; /* enable */
  285. __raw_writel(htonl(ctl), &dev->uregs->gcsrat);
  286. }
  287. return result;
  288. }
  289. /*
  290. * Create vme slave window (access: vme -> crcsr)
  291. */
  292. int tsi148_vme_crcsr_window(unsigned int vmeAddr)
  293. {
  294. int result;
  295. unsigned int ctl;
  296. result = 0;
  297. if (NULL == dev) {
  298. result = 1;
  299. } else {
  300. __raw_writel(htonl(vmeAddr), &dev->uregs->crol);
  301. __raw_writel(0x00000000, &dev->uregs->crou);
  302. ctl = 0x00000080; /* enable */
  303. __raw_writel(htonl(ctl), &dev->uregs->crat);
  304. }
  305. return result;
  306. }
  307. /*
  308. * Create vme slave window (access: vme -> crg)
  309. */
  310. int tsi148_vme_crg_window(unsigned int vmeAddr, int vam)
  311. {
  312. int result;
  313. unsigned int ctl;
  314. result = 0;
  315. if (NULL == dev) {
  316. result = 1;
  317. } else {
  318. __raw_writel(htonl(vmeAddr), &dev->uregs->cbal);
  319. __raw_writel(0x00000000, &dev->uregs->cbau);
  320. ctl = tsi148_eval_vam(vam);
  321. ctl |= 0x00000080; /* enable */
  322. __raw_writel(htonl(ctl), &dev->uregs->crgat);
  323. }
  324. return result;
  325. }
  326. /*
  327. * Tundra Tsi148 configuration
  328. */
  329. int do_tsi148(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  330. {
  331. ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, vdw = 0;
  332. char cmd = 'x';
  333. /* get parameter */
  334. if (argc > 1)
  335. cmd = argv[1][0];
  336. if (argc > 2)
  337. addr1 = simple_strtoul(argv[2], NULL, 16);
  338. if (argc > 3)
  339. addr2 = simple_strtoul(argv[3], NULL, 16);
  340. if (argc > 4)
  341. size = simple_strtoul(argv[4], NULL, 16);
  342. if (argc > 5)
  343. vam = simple_strtoul(argv[5], NULL, 16);
  344. if (argc > 6)
  345. vdw = simple_strtoul(argv[7], NULL, 16);
  346. switch (cmd) {
  347. case 'c':
  348. if (strcmp(argv[1], "crg") == 0) {
  349. vam = addr2;
  350. printf("Tsi148: Configuring VME CRG Window (VME->CRG):\n");
  351. printf(" vme=%08lx vam=%02lx\n", addr1, vam);
  352. tsi148_vme_crg_window(addr1, vam);
  353. } else {
  354. printf("Tsi148: Configuring VME CR/CSR Window (VME->CR/CSR):\n");
  355. printf(" pci=%08lx\n", addr1);
  356. tsi148_vme_crcsr_window(addr1);
  357. }
  358. break;
  359. case 'i': /* init */
  360. tsi148_init();
  361. break;
  362. case 'g':
  363. vam = addr2;
  364. printf("Tsi148: Configuring VME GCSR Window (VME->GCSR):\n");
  365. printf(" vme=%08lx vam=%02lx\n", addr1, vam);
  366. tsi148_vme_gcsr_window(addr1, vam);
  367. break;
  368. case 'v': /* vme */
  369. printf("Tsi148: Configuring VME Slave Window (VME->PCI):\n");
  370. printf(" vme=%08lx pci=%08lx size=%08lx vam=%02lx\n",
  371. addr1, addr2, size, vam);
  372. tsi148_vme_slave_window(addr1, addr2, size, vam);
  373. break;
  374. case 'p': /* pci */
  375. printf("Tsi148: Configuring PCI Slave Window (PCI->VME):\n");
  376. printf(" pci=%08lx vme=%08lx size=%08lx vam=%02lx vdw=%02lx\n",
  377. addr1, addr2, size, vam, vdw);
  378. tsi148_pci_slave_window(addr1, addr2, size, vam, vdw);
  379. break;
  380. default:
  381. printf("Tsi148: Command %s not supported!\n", argv[1]);
  382. }
  383. return 0;
  384. }
  385. U_BOOT_CMD(
  386. tsi148, 8, 1, do_tsi148,
  387. "tsi148 - initialize and configure Turndra Tsi148\n",
  388. "init\n"
  389. " - initialize tsi148\n"
  390. "tsi148 vme [vme_addr] [pci_addr] [size] [vam]\n"
  391. " - create vme slave window (access: vme->pci)\n"
  392. "tsi148 pci [pci_addr] [vme_addr] [size] [vam] [vdw]\n"
  393. " - create pci slave window (access: pci->vme)\n"
  394. "tsi148 crg [vme_addr] [vam]\n"
  395. " - create vme slave window: (access vme->CRG\n"
  396. "tsi148 crcsr [pci_addr]\n"
  397. " - create vme slave window: (access vme->CR/CSR\n"
  398. "tsi148 gcsr [vme_addr] [vam]\n"
  399. " - create vme slave window: (access vme->GCSR\n"
  400. " [vam] = VMEbus Address-Modifier: 01 -> A16 Address Space\n"
  401. " 02 -> A24 Address Space\n"
  402. " 03 -> A32 Address Space\n"
  403. " 04 -> Usr AM Code\n"
  404. " 08 -> Supervisor AM Code\n"
  405. " 10 -> Data AM Code\n"
  406. " 20 -> Program AM Code\n"
  407. " [vdw] = VMEbus Maximum Datawidth: 02 -> D16 Data Width\n"
  408. " 03 -> D32 Data Width\n"
  409. );