cmd_pati.c 15 KB

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