cmd_pati.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /*
  2. * (C) Copyright 2001
  3. * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. *
  7. * Adapted for PATI
  8. */
  9. #include <common.h>
  10. #include <command.h>
  11. #define PLX9056_LOC
  12. #include "plx9056.h"
  13. #include "pati.h"
  14. #include "pci_eeprom.h"
  15. extern void show_pld_regs(void);
  16. extern int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
  17. extern void user_led0(int led_on);
  18. extern void user_led1(int led_on);
  19. /* ------------------------------------------------------------------------- */
  20. #if defined(CONFIG_SYS_PCI_CON_DEVICE)
  21. extern void pci_con_disc(void);
  22. extern void pci_con_connect(void);
  23. #endif
  24. /******************************************************************************
  25. * Eeprom Support
  26. ******************************************************************************/
  27. unsigned long get32(unsigned long addr)
  28. {
  29. unsigned long *p=(unsigned long *)addr;
  30. return *p;
  31. }
  32. void set32(unsigned long addr,unsigned long data)
  33. {
  34. unsigned long *p=(unsigned long *)addr;
  35. *p=data;
  36. }
  37. #define PCICFG_GET_REG(x) (get32((x) + PCI_CONFIG_BASE))
  38. #define PCICFG_SET_REG(x,y) (set32((x) + PCI_CONFIG_BASE,(y)))
  39. /******************************************************************************
  40. * reload_pci_eeprom
  41. ******************************************************************************/
  42. static void reload_pci_eeprom(void)
  43. {
  44. unsigned long reg;
  45. /* Set Bit 29 and clear it again */
  46. reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
  47. udelay(1);
  48. /* set it*/
  49. reg|=(1<<29);
  50. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
  51. /* EECLK @ 33MHz = 125kHz
  52. * -> extra long load = 32 * 16bit = 512Bit @ 125kHz = 4.1msec
  53. * use 20msec
  54. */
  55. udelay(20000); /* wait 20ms */
  56. reg &= ~(1<<29); /* set it low */
  57. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
  58. udelay(1); /* wait some time */
  59. }
  60. /******************************************************************************
  61. * clock_pci_eeprom
  62. ******************************************************************************/
  63. static void clock_pci_eeprom(void)
  64. {
  65. unsigned long reg;
  66. /* clock is low, data is valid */
  67. reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
  68. udelay(1);
  69. /* set clck high */
  70. reg|=(1<<24);
  71. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
  72. udelay(1); /* wait some time */
  73. reg &= ~(1<<24); /* set clock low */
  74. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
  75. udelay(1); /* wait some time */
  76. }
  77. /******************************************************************************
  78. * send_pci_eeprom_cmd
  79. ******************************************************************************/
  80. static void send_pci_eeprom_cmd(unsigned long cmd, unsigned char len)
  81. {
  82. unsigned long reg;
  83. int i;
  84. reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
  85. /* Clear all EEPROM bits */
  86. reg &= ~(0xF << 24);
  87. /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
  88. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
  89. udelay(1); /* wait some time */
  90. /* Enable EEPROM Chip Select */
  91. reg |= (1 << 25);
  92. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
  93. /* Send EEPROM command - one bit at a time */
  94. for (i = (int)(len-1); i >= 0; i--) {
  95. /* Check if current bit is 0 or 1 */
  96. if (cmd & (1 << i))
  97. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,(reg | (1<<26)));
  98. else
  99. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
  100. clock_pci_eeprom();
  101. }
  102. }
  103. /******************************************************************************
  104. * write_pci_eeprom_offs
  105. ******************************************************************************/
  106. static void write_pci_eeprom_offs(unsigned short offset, unsigned short value)
  107. {
  108. unsigned long reg;
  109. int bitpos, cmdshft, cmdlen, timeout;
  110. /* we're using the Eeprom 93CS66 */
  111. cmdshft = 2;
  112. cmdlen = EE66_CMD_LEN;
  113. /* Send Write_Enable command to EEPROM */
  114. send_pci_eeprom_cmd((EE_WREN << cmdshft),cmdlen);
  115. /* Send EEPROM Write command and offset to EEPROM */
  116. send_pci_eeprom_cmd((EE_WRITE << cmdshft) | (offset / 2),cmdlen);
  117. reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
  118. /* Clear all EEPROM bits */
  119. reg &= ~(0xF << 24);
  120. /* Make sure EEDO Input is disabled for some PLX chips */
  121. reg &= ~(1 << 31);
  122. /* Enable EEPROM Chip Select */
  123. reg |= (1 << 25);
  124. /* Write 16-bit value to EEPROM - one bit at a time */
  125. for (bitpos = 15; bitpos >= 0; bitpos--) {
  126. /* Get bit value and shift into result */
  127. if (value & (1 << bitpos))
  128. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,(reg | (1<<26)));
  129. else
  130. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg );
  131. clock_pci_eeprom();
  132. } /* for */
  133. /* Deselect Chip */
  134. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg & ~(1 << 25));
  135. /* Re-select Chip */
  136. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg | (1 << 25));
  137. /* A small delay is needed to let EEPROM complete */
  138. timeout = 0;
  139. do {
  140. udelay(10);
  141. reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
  142. timeout++;
  143. } while (((reg & (1 << 27)) == 0) && timeout < 20000);
  144. /* Send Write_Disable command to EEPROM */
  145. send_pci_eeprom_cmd((EE_WDS << cmdshft),cmdlen);
  146. /* Clear Chip Select and all other EEPROM bits */
  147. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg & ~(0xF << 24));
  148. }
  149. /******************************************************************************
  150. * read_pci_eeprom_offs
  151. ******************************************************************************/
  152. static void read_pci_eeprom_offs(unsigned short offset, unsigned short *pvalue)
  153. {
  154. unsigned long reg;
  155. int bitpos, cmdshft, cmdlen;
  156. /* we're using the Eeprom 93CS66 */
  157. cmdshft = 2;
  158. cmdlen = EE66_CMD_LEN;
  159. /* Send EEPROM read command and offset to EEPROM */
  160. send_pci_eeprom_cmd((EE_READ << cmdshft) | (offset / 2),cmdlen);
  161. /* Set EEPROM write output bit */
  162. reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
  163. /* Set EEDO Input enable */
  164. reg |= (1 << 31);
  165. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg | (1 << 26));
  166. /* Get 16-bit value from EEPROM - one bit at a time */
  167. for (bitpos = 0; bitpos < 16; bitpos++) {
  168. clock_pci_eeprom();
  169. udelay(10);
  170. reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
  171. /* Get bit value and shift into result */
  172. if (reg & (1 << 27))
  173. *pvalue = (unsigned short)((*pvalue << 1) | 1);
  174. else
  175. *pvalue = (unsigned short)(*pvalue << 1);
  176. }
  177. /* Clear EEDO Input enable */
  178. reg &= ~(1 << 31);
  179. /* Clear Chip Select and all other EEPROM bits */
  180. PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg & ~(0xF << 24));
  181. }
  182. /******************************************************************************
  183. * EEPROM read/writes
  184. ******************************************************************************/
  185. #undef EEPROM_DBG
  186. static int pati_pci_eeprom_erase(void)
  187. {
  188. int i;
  189. printf("Erasing EEPROM ");
  190. for( i=0; i < PATI_EEPROM_LAST_OFFSET; i+=2) {
  191. write_pci_eeprom_offs(i,0xffff);
  192. if((i%0x10))
  193. printf(".");
  194. }
  195. printf("\nDone\n");
  196. return 0;
  197. }
  198. static int pati_pci_eeprom_prg(void)
  199. {
  200. int i;
  201. i=0;
  202. printf("Programming EEPROM ");
  203. while(pati_eeprom[i].offset<0xffff) {
  204. write_pci_eeprom_offs(pati_eeprom[i].offset,pati_eeprom[i].value);
  205. #ifdef EEPROM_DBG
  206. printf("0x%04X: 0x%04X\n",pati_eeprom[i].offset, pati_eeprom[i].value);
  207. #else
  208. if((i%0x10))
  209. printf(".");
  210. #endif
  211. i++;
  212. }
  213. printf("\nDone\n");
  214. return 0;
  215. }
  216. static int pati_pci_eeprom_write(unsigned short offset, unsigned long addr, unsigned short size)
  217. {
  218. int i;
  219. unsigned short value;
  220. unsigned short *buffer =(unsigned short *)addr;
  221. if((offset + size) > PATI_EEPROM_LAST_OFFSET) {
  222. size = PATI_EEPROM_LAST_OFFSET - offset;
  223. }
  224. printf("Write To EEPROM from 0x%lX to 0x%X 0x%X words\n", addr, offset, size/2);
  225. for( i = offset; i< (offset + size); i+=2) {
  226. value = *buffer++;
  227. write_pci_eeprom_offs(i,value);
  228. #ifdef EEPROM_DBG
  229. printf("0x%04X: 0x%04X\n",i, value);
  230. #else
  231. if((i%0x10))
  232. printf(".");
  233. #endif
  234. }
  235. printf("\nDone\n");
  236. return 0;
  237. }
  238. static int pati_pci_eeprom_read(unsigned short offset, unsigned long addr, unsigned short size)
  239. {
  240. int i;
  241. unsigned short value = 0;
  242. unsigned short *buffer =(unsigned short *)addr;
  243. if((offset + size) > PATI_EEPROM_LAST_OFFSET) {
  244. size = PATI_EEPROM_LAST_OFFSET - offset;
  245. }
  246. printf("Read from EEPROM from 0x%X to 0x%lX 0x%X words\n", offset, addr, size/2);
  247. for( i = offset; i< (offset + size); i+=2) {
  248. read_pci_eeprom_offs(i,&value);
  249. *buffer++=value;
  250. #ifdef EEPROM_DBG
  251. printf("0x%04X: 0x%04X\n",i, value);
  252. #else
  253. if((i%0x10))
  254. printf(".");
  255. #endif
  256. }
  257. printf("\nDone\n");
  258. return 0;
  259. }
  260. /******************************************************************************
  261. * PCI Bridge Registers Dump
  262. *******************************************************************************/
  263. static void display_pci_regs(void)
  264. {
  265. printf(" PCI9056_SPACE0_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_SPACE0_RANGE));
  266. printf(" PCI9056_SPACE0_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_SPACE0_REMAP));
  267. printf(" PCI9056_LOCAL_DMA_ARBIT %08lX\n",PCICFG_GET_REG(PCI9056_LOCAL_DMA_ARBIT));
  268. printf(" PCI9056_ENDIAN_DESC %08lX\n",PCICFG_GET_REG(PCI9056_ENDIAN_DESC));
  269. printf(" PCI9056_EXP_ROM_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_EXP_ROM_RANGE));
  270. printf(" PCI9056_EXP_ROM_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_EXP_ROM_REMAP));
  271. printf(" PCI9056_SPACE0_ROM_DESC %08lX\n",PCICFG_GET_REG(PCI9056_SPACE0_ROM_DESC));
  272. printf(" PCI9056_DM_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_DM_RANGE));
  273. printf(" PCI9056_DM_MEM_BASE %08lX\n",PCICFG_GET_REG(PCI9056_DM_MEM_BASE));
  274. printf(" PCI9056_DM_IO_BASE %08lX\n",PCICFG_GET_REG(PCI9056_DM_IO_BASE));
  275. printf(" PCI9056_DM_PCI_MEM_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_DM_PCI_MEM_REMAP));
  276. printf(" PCI9056_DM_PCI_IO_CONFIG %08lX\n",PCICFG_GET_REG(PCI9056_DM_PCI_IO_CONFIG));
  277. printf(" PCI9056_SPACE1_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_SPACE1_RANGE));
  278. printf(" PCI9056_SPACE1_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_SPACE1_REMAP));
  279. printf(" PCI9056_SPACE1_DESC %08lX\n",PCICFG_GET_REG(PCI9056_SPACE1_DESC));
  280. printf(" PCI9056_DM_DAC %08lX\n",PCICFG_GET_REG(PCI9056_DM_DAC));
  281. printf(" PCI9056_MAILBOX0 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX0));
  282. printf(" PCI9056_MAILBOX1 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX1));
  283. printf(" PCI9056_MAILBOX2 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX2));
  284. printf(" PCI9056_MAILBOX3 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX3));
  285. printf(" PCI9056_MAILBOX4 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX4));
  286. printf(" PCI9056_MAILBOX5 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX5));
  287. printf(" PCI9056_MAILBOX6 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX6));
  288. printf(" PCI9056_MAILBOX7 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX7));
  289. printf(" PCI9056_PCI_TO_LOC_DBELL %08lX\n",PCICFG_GET_REG(PCI9056_PCI_TO_LOC_DBELL));
  290. printf(" PCI9056_LOC_TO_PCI_DBELL %08lX\n",PCICFG_GET_REG(PCI9056_LOC_TO_PCI_DBELL));
  291. printf(" PCI9056_INT_CTRL_STAT %08lX\n",PCICFG_GET_REG(PCI9056_INT_CTRL_STAT));
  292. printf(" PCI9056_EEPROM_CTRL_STAT %08lX\n",PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT));
  293. printf(" PCI9056_PERM_VENDOR_ID %08lX\n",PCICFG_GET_REG(PCI9056_PERM_VENDOR_ID));
  294. printf(" PCI9056_REVISION_ID %08lX\n",PCICFG_GET_REG(PCI9056_REVISION_ID));
  295. printf(" \n");
  296. printf(" PCI9056_VENDOR_ID %08lX\n",PCICFG_GET_REG(PCI9056_VENDOR_ID));
  297. printf(" PCI9056_COMMAND %08lX\n",PCICFG_GET_REG(PCI9056_COMMAND));
  298. printf(" PCI9056_REVISION %08lX\n",PCICFG_GET_REG(PCI9056_REVISION));
  299. printf(" PCI9056_CACHE_SIZE %08lX\n",PCICFG_GET_REG(PCI9056_CACHE_SIZE));
  300. printf(" PCI9056_RTR_BASE %08lX\n",PCICFG_GET_REG(PCI9056_RTR_BASE));
  301. printf(" PCI9056_RTR_IO_BASE %08lX\n",PCICFG_GET_REG(PCI9056_RTR_IO_BASE));
  302. printf(" PCI9056_LOCAL_BASE0 %08lX\n",PCICFG_GET_REG(PCI9056_LOCAL_BASE0));
  303. printf(" PCI9056_LOCAL_BASE1 %08lX\n",PCICFG_GET_REG(PCI9056_LOCAL_BASE1));
  304. printf(" PCI9056_UNUSED_BASE1 %08lX\n",PCICFG_GET_REG(PCI9056_UNUSED_BASE1));
  305. printf(" PCI9056_UNUSED_BASE2 %08lX\n",PCICFG_GET_REG(PCI9056_UNUSED_BASE2));
  306. printf(" PCI9056_CIS_PTR %08lX\n",PCICFG_GET_REG(PCI9056_CIS_PTR));
  307. printf(" PCI9056_SUB_ID %08lX\n",PCICFG_GET_REG(PCI9056_SUB_ID));
  308. printf(" PCI9056_EXP_ROM_BASE %08lX\n",PCICFG_GET_REG(PCI9056_EXP_ROM_BASE));
  309. printf(" PCI9056_CAP_PTR %08lX\n",PCICFG_GET_REG(PCI9056_CAP_PTR));
  310. printf(" PCI9056_INT_LINE %08lX\n",PCICFG_GET_REG(PCI9056_INT_LINE));
  311. printf(" PCI9056_PM_CAP_ID %08lX\n",PCICFG_GET_REG(PCI9056_PM_CAP_ID));
  312. printf(" PCI9056_PM_CSR %08lX\n",PCICFG_GET_REG(PCI9056_PM_CSR));
  313. printf(" PCI9056_HS_CAP_ID %08lX\n",PCICFG_GET_REG(PCI9056_HS_CAP_ID));
  314. printf(" PCI9056_VPD_CAP_ID %08lX\n",PCICFG_GET_REG(PCI9056_VPD_CAP_ID));
  315. printf(" PCI9056_VPD_DATA %08lX\n",PCICFG_GET_REG(PCI9056_VPD_DATA));
  316. }
  317. int do_pati(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  318. {
  319. if (strcmp(argv[1], "info") == 0)
  320. {
  321. show_pld_regs();
  322. return 0;
  323. }
  324. if (strcmp(argv[1], "pci") == 0)
  325. {
  326. display_pci_regs();
  327. return 0;
  328. }
  329. if (strcmp(argv[1], "led") == 0)
  330. {
  331. int led_nr,led_on;
  332. led_nr = (int)simple_strtoul(argv[2], NULL, 10);
  333. led_on = (int)simple_strtoul(argv[3], NULL, 10);
  334. if(!led_nr)
  335. user_led0(led_on);
  336. else
  337. user_led1(led_on);
  338. return 0;
  339. }
  340. #if defined(CONFIG_SYS_PCI_CON_DEVICE)
  341. if (strcmp(argv[1], "con") == 0) {
  342. pci_con_connect();
  343. return 0;
  344. }
  345. if (strcmp(argv[1], "disc") == 0) {
  346. pci_con_disc();
  347. return 0;
  348. }
  349. #endif
  350. if (strcmp(argv[1], "eeprom") == 0) {
  351. unsigned long addr;
  352. int size, offset;
  353. offset = 0;
  354. size = PATI_EEPROM_LAST_OFFSET;
  355. if(argc>2) {
  356. if(argc>3) {
  357. addr = simple_strtoul(argv[3], NULL, 16);
  358. if(argc>4)
  359. offset = (int) simple_strtoul(argv[4], NULL, 16);
  360. if(argc>5)
  361. size = (int) simple_strtoul(argv[5], NULL, 16);
  362. if (strcmp(argv[2], "read") == 0) {
  363. return (pati_pci_eeprom_read(offset, addr, size));
  364. }
  365. if (strcmp(argv[2], "write") == 0) {
  366. return (pati_pci_eeprom_write(offset, addr, size));
  367. }
  368. }
  369. if (strcmp(argv[2], "prg") == 0) {
  370. return (pati_pci_eeprom_prg());
  371. }
  372. if (strcmp(argv[2], "era") == 0) {
  373. return (pati_pci_eeprom_erase());
  374. }
  375. if (strcmp(argv[2], "reload") == 0) {
  376. reload_pci_eeprom();
  377. return 0;
  378. }
  379. }
  380. }
  381. return (do_mplcommon(cmdtp, flag, argc, argv));
  382. }
  383. U_BOOT_CMD(
  384. pati, 8, 1, do_pati,
  385. "PATI specific Cmds",
  386. "info - displays board information\n"
  387. "pati pci - displays PCI registers\n"
  388. "pati led <nr> <on> \n"
  389. " - switch LED <nr> <on>\n"
  390. "pati flash mem [SrcAddr]\n"
  391. " - updates U-Boot with image in memory\n"
  392. "pati eeprom <cmd> - PCI EEPROM sub-system\n"
  393. " read <addr> <offset> <size>\n"
  394. " - read PCI EEPROM to <addr> from <offset> <size> words\n"
  395. " write <addr> <offset> <size>\n"
  396. " - write PCI EEPROM from <addr> to <offset> <size> words\n"
  397. " prg - programm PCI EEPROM with default values\n"
  398. " era - erase PCI EEPROM (write all word to 0xffff)\n"
  399. " reload- Reload PCI Bridge with EEPROM Values\n"
  400. " NOTE: <addr> must start on word boundary\n"
  401. " <offset> and <size> must be even byte values"
  402. );
  403. /* ------------------------------------------------------------------------- */