PageRenderTime 60ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/board/esd/pmc440/cmd_pmc440.c

https://github.com/zhanggf/U-boot-2009.11_tekkaman
C | 557 lines | 418 code | 71 blank | 68 comment | 72 complexity | 6a153fe9e4150bbd5d14a4261fb9e847 MD5 | raw file
  1. /*
  2. * (C) Copyright 2007-2008
  3. * Matthias Fuchs, esd Gmbh, matthias.fuchs@esd-electronics.com.
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. *
  23. */
  24. #include <common.h>
  25. #include <command.h>
  26. #include <asm/io.h>
  27. #include <asm/cache.h>
  28. #include <asm/processor.h>
  29. #if defined(CONFIG_LOGBUFFER)
  30. #include <logbuff.h>
  31. #endif
  32. #include "pmc440.h"
  33. int is_monarch(void);
  34. int bootstrap_eeprom_write(unsigned dev_addr, unsigned offset,
  35. uchar *buffer, unsigned cnt);
  36. int eeprom_write_enable(unsigned dev_addr, int state);
  37. DECLARE_GLOBAL_DATA_PTR;
  38. #if defined(CONFIG_CMD_BSP)
  39. static int got_fifoirq;
  40. static int got_hcirq;
  41. int fpga_interrupt(u32 arg)
  42. {
  43. pmc440_fpga_t *fpga = (pmc440_fpga_t *)arg;
  44. int rc = -1; /* not for us */
  45. u32 status = FPGA_IN32(&fpga->status);
  46. /* check for interrupt from fifo module */
  47. if (status & STATUS_FIFO_ISF) {
  48. /* disable this int source */
  49. FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_FIFOIE_GATE);
  50. rc = 0;
  51. got_fifoirq = 1; /* trigger backend */
  52. }
  53. if (status & STATUS_HOST_ISF) {
  54. FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_HCINT_GATE);
  55. rc = 0;
  56. got_hcirq = 1;
  57. }
  58. return rc;
  59. }
  60. int do_waithci(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  61. {
  62. pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
  63. got_hcirq = 0;
  64. FPGA_CLRBITS(&fpga->ctrla, CTRL_HOST_IE);
  65. FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_HCINT_GATE);
  66. irq_install_handler(IRQ0_FPGA,
  67. (interrupt_handler_t *)fpga_interrupt,
  68. fpga);
  69. FPGA_SETBITS(&fpga->ctrla, CTRL_HOST_IE);
  70. while (!got_hcirq) {
  71. /* Abort if ctrl-c was pressed */
  72. if (ctrlc()) {
  73. puts("\nAbort\n");
  74. break;
  75. }
  76. }
  77. if (got_hcirq)
  78. printf("Got interrupt!\n");
  79. FPGA_CLRBITS(&fpga->ctrla, CTRL_HOST_IE);
  80. irq_free_handler(IRQ0_FPGA);
  81. return 0;
  82. }
  83. U_BOOT_CMD(
  84. waithci, 1, 1, do_waithci,
  85. "Wait for host control interrupt",
  86. ""
  87. );
  88. void dump_fifo(pmc440_fpga_t *fpga, int f, int *n)
  89. {
  90. u32 ctrl;
  91. while (!((ctrl = FPGA_IN32(&fpga->fifo[f].ctrl)) & FIFO_EMPTY)) {
  92. printf("%5d %d %3d %08x",
  93. (*n)++, f, ctrl & (FIFO_LEVEL_MASK | FIFO_FULL),
  94. FPGA_IN32(&fpga->fifo[f].data));
  95. if (ctrl & FIFO_OVERFLOW) {
  96. printf(" OVERFLOW\n");
  97. FPGA_CLRBITS(&fpga->fifo[f].ctrl, FIFO_OVERFLOW);
  98. } else
  99. printf("\n");
  100. }
  101. }
  102. int do_fifo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  103. {
  104. pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
  105. int i;
  106. int n = 0;
  107. u32 ctrl, data, f;
  108. char str[] = "\\|/-";
  109. int abort = 0;
  110. int count = 0;
  111. int count2 = 0;
  112. switch (argc) {
  113. case 1:
  114. /* print all fifos status information */
  115. printf("fifo level status\n");
  116. printf("______________________________\n");
  117. for (i=0; i<FIFO_COUNT; i++) {
  118. ctrl = FPGA_IN32(&fpga->fifo[i].ctrl);
  119. printf(" %d %3d %s%s%s %s\n",
  120. i, ctrl & (FIFO_LEVEL_MASK | FIFO_FULL),
  121. ctrl & FIFO_FULL ? "FULL " : "",
  122. ctrl & FIFO_EMPTY ? "EMPTY " : "",
  123. ctrl & (FIFO_FULL|FIFO_EMPTY) ? "" : "NOT EMPTY",
  124. ctrl & FIFO_OVERFLOW ? "OVERFLOW" : "");
  125. }
  126. break;
  127. case 2:
  128. /* completely read out fifo 'n' */
  129. if (!strcmp(argv[1],"read")) {
  130. printf(" # fifo level data\n");
  131. printf("______________________________\n");
  132. for (i=0; i<FIFO_COUNT; i++)
  133. dump_fifo(fpga, i, &n);
  134. } else if (!strcmp(argv[1],"wait")) {
  135. got_fifoirq = 0;
  136. irq_install_handler(IRQ0_FPGA,
  137. (interrupt_handler_t *)fpga_interrupt,
  138. fpga);
  139. printf(" # fifo level data\n");
  140. printf("______________________________\n");
  141. /* enable all fifo interrupts */
  142. FPGA_OUT32(&fpga->hostctrl,
  143. HOSTCTRL_FIFOIE_GATE | HOSTCTRL_FIFOIE_FLAG);
  144. for (i=0; i<FIFO_COUNT; i++) {
  145. /* enable interrupts from all fifos */
  146. FPGA_SETBITS(&fpga->fifo[i].ctrl, FIFO_IE);
  147. }
  148. while (1) {
  149. /* wait loop */
  150. while (!got_fifoirq) {
  151. count++;
  152. if (!(count % 100)) {
  153. count2++;
  154. putc(0x08); /* backspace */
  155. putc(str[count2 % 4]);
  156. }
  157. /* Abort if ctrl-c was pressed */
  158. if ((abort = ctrlc())) {
  159. puts("\nAbort\n");
  160. break;
  161. }
  162. udelay(1000);
  163. }
  164. if (abort)
  165. break;
  166. /* simple fifo backend */
  167. if (got_fifoirq) {
  168. for (i=0; i<FIFO_COUNT; i++)
  169. dump_fifo(fpga, i, &n);
  170. got_fifoirq = 0;
  171. /* unmask global fifo irq */
  172. FPGA_OUT32(&fpga->hostctrl,
  173. HOSTCTRL_FIFOIE_GATE |
  174. HOSTCTRL_FIFOIE_FLAG);
  175. }
  176. }
  177. /* disable all fifo interrupts */
  178. FPGA_OUT32(&fpga->hostctrl, HOSTCTRL_FIFOIE_GATE);
  179. for (i=0; i<FIFO_COUNT; i++)
  180. FPGA_CLRBITS(&fpga->fifo[i].ctrl, FIFO_IE);
  181. irq_free_handler(IRQ0_FPGA);
  182. } else {
  183. printf("Usage:\nfifo %s\n", cmdtp->help);
  184. return 1;
  185. }
  186. break;
  187. case 4:
  188. case 5:
  189. if (!strcmp(argv[1],"write")) {
  190. /* get fifo number or fifo address */
  191. f = simple_strtoul(argv[2], NULL, 16);
  192. /* data paramter */
  193. data = simple_strtoul(argv[3], NULL, 16);
  194. /* get optional count parameter */
  195. n = 1;
  196. if (argc >= 5)
  197. n = (int)simple_strtoul(argv[4], NULL, 10);
  198. if (f < FIFO_COUNT) {
  199. printf("writing %d x %08x to fifo %d\n",
  200. n, data, f);
  201. for (i=0; i<n; i++)
  202. FPGA_OUT32(&fpga->fifo[f].data, data);
  203. } else {
  204. printf("writing %d x %08x to fifo port at "
  205. "address %08x\n",
  206. n, data, f);
  207. for (i=0; i<n; i++)
  208. out_be32((void *)f, data);
  209. }
  210. } else {
  211. printf("Usage:\nfifo %s\n", cmdtp->help);
  212. return 1;
  213. }
  214. break;
  215. default:
  216. printf("Usage:\nfifo %s\n", cmdtp->help);
  217. return 1;
  218. }
  219. return 0;
  220. }
  221. U_BOOT_CMD(
  222. fifo, 5, 1, do_fifo,
  223. "Fifo module operations",
  224. "wait\nfifo read\n"
  225. "fifo write fifo(0..3) data [cnt=1]\n"
  226. "fifo write address(>=4) data [cnt=1]\n"
  227. " - without arguments: print all fifo's status\n"
  228. " - with 'wait' argument: interrupt driven read from all fifos\n"
  229. " - with 'read' argument: read current contents from all fifos\n"
  230. " - with 'write' argument: write 'data' 'cnt' times to "
  231. "'fifo' or 'address'"
  232. );
  233. int do_setup_bootstrap_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  234. {
  235. ulong sdsdp[5];
  236. ulong delay;
  237. int count=16;
  238. if (argc < 2) {
  239. printf("Usage:\nsbe %s\n", cmdtp->help);
  240. return -1;
  241. }
  242. if (argc > 1) {
  243. if (!strcmp(argv[1], "400")) {
  244. /* PLB=133MHz, PLB/PCI=3 */
  245. printf("Bootstrapping for 400MHz\n");
  246. sdsdp[0]=0x8678624e;
  247. sdsdp[1]=0x095fa030;
  248. sdsdp[2]=0x40082350;
  249. sdsdp[3]=0x0d050000;
  250. } else if (!strcmp(argv[1], "533")) {
  251. /* PLB=133MHz, PLB/PCI=3 */
  252. printf("Bootstrapping for 533MHz\n");
  253. sdsdp[0]=0x87788252;
  254. sdsdp[1]=0x095fa030;
  255. sdsdp[2]=0x40082350;
  256. sdsdp[3]=0x0d050000;
  257. } else if (!strcmp(argv[1], "667")) {
  258. /* PLB=133MHz, PLB/PCI=3 */
  259. printf("Bootstrapping for 667MHz\n");
  260. sdsdp[0]=0x8778a256;
  261. sdsdp[1]=0x095fa030;
  262. sdsdp[2]=0x40082350;
  263. sdsdp[3]=0x0d050000;
  264. } else {
  265. printf("Usage:\nsbe %s\n", cmdtp->help);
  266. return -1;
  267. }
  268. }
  269. if (argc > 2) {
  270. sdsdp[4] = 0;
  271. if (argv[2][0]=='1')
  272. sdsdp[4]=0x19750100;
  273. else if (argv[2][0]=='0')
  274. sdsdp[4]=0x19750000;
  275. if (sdsdp[4])
  276. count += 4;
  277. }
  278. if (argc > 3) {
  279. delay = simple_strtoul(argv[3], NULL, 10);
  280. if (delay > 20)
  281. delay = 20;
  282. sdsdp[4] |= delay;
  283. }
  284. printf("Writing boot EEPROM ...\n");
  285. if (bootstrap_eeprom_write(CONFIG_SYS_I2C_BOOT_EEPROM_ADDR,
  286. 0, (uchar*)sdsdp, count) != 0)
  287. printf("bootstrap_eeprom_write failed\n");
  288. else
  289. printf("done (dump via 'i2c md 52 0.1 14')\n");
  290. return 0;
  291. }
  292. U_BOOT_CMD(
  293. sbe, 4, 0, do_setup_bootstrap_eeprom,
  294. "setup bootstrap eeprom",
  295. "<cpufreq:400|533|667> [<console-uart:0|1> [<bringup delay (0..20s)>]]"
  296. );
  297. #if defined(CONFIG_PRAM)
  298. #include <environment.h>
  299. extern env_t *env_ptr;
  300. int do_painit(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  301. {
  302. u32 pram, nextbase, base;
  303. char *v;
  304. u32 param;
  305. ulong *lptr;
  306. v = getenv("pram");
  307. if (v)
  308. pram = simple_strtoul(v, NULL, 10);
  309. else {
  310. printf("Error: pram undefined. Please define pram in KiB\n");
  311. return 1;
  312. }
  313. base = gd->bd->bi_memsize;
  314. #if defined(CONFIG_LOGBUFFER)
  315. base -= LOGBUFF_LEN + LOGBUFF_OVERHEAD;
  316. #endif
  317. /*
  318. * gd->bd->bi_memsize == physical ram size - CONFIG_SYS_MEM_TOP_HIDE
  319. */
  320. param = base - (pram << 10);
  321. printf("PARAM: @%08x\n", param);
  322. debug("memsize=0x%08x, base=0x%08x\n", gd->bd->bi_memsize, base);
  323. /* clear entire PA ram */
  324. memset((void*)param, 0, (pram << 10));
  325. /* reserve 4k for pointer field */
  326. nextbase = base - 4096;
  327. lptr = (ulong*)(base);
  328. /*
  329. * *(--lptr) = item_size;
  330. * *(--lptr) = base - item_base = distance from field top;
  331. */
  332. /* env is first (4k aligned) */
  333. nextbase -= ((CONFIG_ENV_SIZE + 4096 - 1) & ~(4096 - 1));
  334. memcpy((void*)nextbase, env_ptr, CONFIG_ENV_SIZE);
  335. *(--lptr) = CONFIG_ENV_SIZE; /* size */
  336. *(--lptr) = base - nextbase; /* offset | type=0 */
  337. /* free section */
  338. *(--lptr) = nextbase - param; /* size */
  339. *(--lptr) = (base - param) | 126; /* offset | type=126 */
  340. /* terminate pointer field */
  341. *(--lptr) = crc32(0, (void*)(base - 0x10), 0x10);
  342. *(--lptr) = 0; /* offset=0 -> terminator */
  343. return 0;
  344. }
  345. U_BOOT_CMD(
  346. painit, 1, 1, do_painit,
  347. "prepare PciAccess system",
  348. ""
  349. );
  350. #endif /* CONFIG_PRAM */
  351. int do_selfreset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  352. {
  353. in_be32((void*)CONFIG_SYS_RESET_BASE);
  354. return 0;
  355. }
  356. U_BOOT_CMD(
  357. selfreset, 1, 1, do_selfreset,
  358. "assert self-reset# signal",
  359. ""
  360. );
  361. int do_resetout(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  362. {
  363. pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
  364. /* requiers bootet FPGA and PLD_IOEN_N active */
  365. if (in_be32((void*)GPIO1_OR) & GPIO1_IOEN_N) {
  366. printf("Error: resetout requires a bootet FPGA\n");
  367. return -1;
  368. }
  369. if (argc > 1) {
  370. if (argv[1][0] == '0') {
  371. /* assert */
  372. printf("PMC-RESETOUT# asserted\n");
  373. FPGA_OUT32(&fpga->hostctrl,
  374. HOSTCTRL_PMCRSTOUT_GATE);
  375. } else {
  376. /* deassert */
  377. printf("PMC-RESETOUT# deasserted\n");
  378. FPGA_OUT32(&fpga->hostctrl,
  379. HOSTCTRL_PMCRSTOUT_GATE |
  380. HOSTCTRL_PMCRSTOUT_FLAG);
  381. }
  382. } else {
  383. printf("PMC-RESETOUT# is %s\n",
  384. FPGA_IN32(&fpga->hostctrl) & HOSTCTRL_PMCRSTOUT_FLAG ?
  385. "inactive" : "active");
  386. }
  387. return 0;
  388. }
  389. U_BOOT_CMD(
  390. resetout, 2, 1, do_resetout,
  391. "assert PMC-RESETOUT# signal",
  392. ""
  393. );
  394. int do_inta(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  395. {
  396. if (is_monarch()) {
  397. printf("This command is only supported in non-monarch mode\n");
  398. return -1;
  399. }
  400. if (argc > 1) {
  401. if (argv[1][0] == '0') {
  402. /* assert */
  403. printf("inta# asserted\n");
  404. out_be32((void*)GPIO1_TCR,
  405. in_be32((void*)GPIO1_TCR) | GPIO1_INTA_FAKE);
  406. } else {
  407. /* deassert */
  408. printf("inta# deasserted\n");
  409. out_be32((void*)GPIO1_TCR,
  410. in_be32((void*)GPIO1_TCR) & ~GPIO1_INTA_FAKE);
  411. }
  412. } else {
  413. printf("inta# is %s\n",
  414. in_be32((void*)GPIO1_TCR) & GPIO1_INTA_FAKE ?
  415. "active" : "inactive");
  416. }
  417. return 0;
  418. }
  419. U_BOOT_CMD(
  420. inta, 2, 1, do_inta,
  421. "Assert/Deassert or query INTA# state in non-monarch mode",
  422. ""
  423. );
  424. /* test-only */
  425. int do_pmm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  426. {
  427. ulong pciaddr;
  428. if (argc > 1) {
  429. pciaddr = simple_strtoul(argv[1], NULL, 16);
  430. pciaddr &= 0xf0000000;
  431. /* map PCI address at 0xc0000000 in PLB space */
  432. /* PMM1 Mask/Attribute - disabled b4 setting */
  433. out32r(PCIL0_PMM1MA, 0x00000000);
  434. /* PMM1 Local Address */
  435. out32r(PCIL0_PMM1LA, 0xc0000000);
  436. /* PMM1 PCI Low Address */
  437. out32r(PCIL0_PMM1PCILA, pciaddr);
  438. /* PMM1 PCI High Address */
  439. out32r(PCIL0_PMM1PCIHA, 0x00000000);
  440. /* 256MB + No prefetching, and enable region */
  441. out32r(PCIL0_PMM1MA, 0xf0000001);
  442. } else {
  443. printf("Usage:\npmm %s\n", cmdtp->help);
  444. }
  445. return 0;
  446. }
  447. U_BOOT_CMD(
  448. pmm, 2, 1, do_pmm,
  449. "Setup pmm[1] registers",
  450. "<pciaddr> (pciaddr will be aligned to 256MB)"
  451. );
  452. #if defined(CONFIG_SYS_EEPROM_WREN)
  453. int do_eep_wren(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  454. {
  455. int query = argc == 1;
  456. int state = 0;
  457. if (query) {
  458. /* Query write access state. */
  459. state = eeprom_write_enable(CONFIG_SYS_I2C_EEPROM_ADDR, -1);
  460. if (state < 0) {
  461. puts("Query of write access state failed.\n");
  462. } else {
  463. printf("Write access for device 0x%0x is %sabled.\n",
  464. CONFIG_SYS_I2C_EEPROM_ADDR, state ? "en" : "dis");
  465. state = 0;
  466. }
  467. } else {
  468. if ('0' == argv[1][0]) {
  469. /* Disable write access. */
  470. state = eeprom_write_enable(CONFIG_SYS_I2C_EEPROM_ADDR, 0);
  471. } else {
  472. /* Enable write access. */
  473. state = eeprom_write_enable(CONFIG_SYS_I2C_EEPROM_ADDR, 1);
  474. }
  475. if (state < 0) {
  476. puts("Setup of write access state failed.\n");
  477. }
  478. }
  479. return state;
  480. }
  481. U_BOOT_CMD(eepwren, 2, 0, do_eep_wren,
  482. "Enable / disable / query EEPROM write access",
  483. ""
  484. );
  485. #endif /* #if defined(CONFIG_SYS_EEPROM_WREN) */
  486. #endif /* CONFIG_CMD_BSP */