iim.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /*
  2. * Copyright 2008 Silicon Turnkey Express, Inc.
  3. * Martha Marx <mmarx@silicontkx.com>
  4. *
  5. * ADS5121 IIM (Fusebox) Interface
  6. *
  7. * See file CREDITS for list of people who contributed to this
  8. * project.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23. * MA 02111-1307 USA
  24. */
  25. #include <common.h>
  26. #include <command.h>
  27. #include <asm/io.h>
  28. #ifdef CONFIG_CMD_FUSE
  29. DECLARE_GLOBAL_DATA_PTR;
  30. static char cur_bank = '1';
  31. char *iim_err_msg(u32 err)
  32. {
  33. static char *IIM_errs[] = {
  34. "Parity Error in cache",
  35. "Explicit Sense Cycle Error",
  36. "Write to Locked Register Error",
  37. "Read Protect Error",
  38. "Override Protect Error",
  39. "Write Protect Error"};
  40. int i;
  41. if (!err)
  42. return "";
  43. for (i = 1; i < 8; i++)
  44. if (err & (1 << i))
  45. printf("IIM - %s\n", IIM_errs[i-1]);
  46. return "";
  47. }
  48. int in_range(int n, int min, int max, char *err, char *usg)
  49. {
  50. if (n > max || n < min) {
  51. printf(err);
  52. printf("Usage:\n%s\n", usg);
  53. return 0;
  54. }
  55. return 1;
  56. }
  57. int ads5121_fuse_read(int bank, int fstart, int num)
  58. {
  59. iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
  60. u32 *iim_fb, dummy;
  61. int f, ctr;
  62. out_be32(&iim->err, in_be32(&iim->err));
  63. if (bank == 0)
  64. iim_fb = (u32 *)&(iim->fbac0);
  65. else
  66. iim_fb = (u32 *)&(iim->fbac1);
  67. /* try a read to see if Read Protect is set */
  68. dummy = in_be32(&iim_fb[0]);
  69. if (in_be32(&iim->err) & IIM_ERR_RPE) {
  70. printf("\tRead protect fuse is set\n");
  71. out_be32(&iim->err, IIM_ERR_RPE);
  72. return 0;
  73. }
  74. printf("Reading Bank %d cache\n", bank);
  75. for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) {
  76. if (ctr % 4 == 0)
  77. printf("F%2d:", f);
  78. printf("\t%#04x", (u8)(iim_fb[f]));
  79. if (ctr % 4 == 3)
  80. printf("\n");
  81. }
  82. if (ctr % 4 != 0)
  83. printf("\n");
  84. }
  85. int ads5121_fuse_override(int bank, int f, u8 val)
  86. {
  87. iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
  88. u32 *iim_fb;
  89. u32 iim_stat;
  90. int i;
  91. out_be32(&iim->err, in_be32(&iim->err));
  92. if (bank == 0)
  93. iim_fb = (u32 *)&(iim->fbac0);
  94. else
  95. iim_fb = (u32 *)&(iim->fbac1);
  96. /* try a read to see if Read Protect is set */
  97. iim_stat = in_be32(&iim_fb[0]);
  98. if (in_be32(&iim->err) & IIM_ERR_RPE) {
  99. printf("Read protect fuse is set on bank %d;"
  100. "Override protect may also be set\n", bank);
  101. printf("An attempt will be made to override\n");
  102. out_be32(&iim->err, IIM_ERR_RPE);
  103. }
  104. if (iim_stat & IIM_FBAC_FBOP) {
  105. printf("Override protect fuse is set on bank %d\n", bank);
  106. return 1;
  107. }
  108. if (f > IIM_FMAX) /* reset the entire bank */
  109. for (i = 0; i < IIM_FMAX + 1; i++)
  110. out_be32(&iim_fb[i], 0);
  111. else
  112. out_be32(&iim_fb[f], val);
  113. return 0;
  114. }
  115. int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno)
  116. {
  117. iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
  118. int f, i, bitno;
  119. u32 stat, err;
  120. f = simple_strtol(fuseno_bitno, NULL, 10);
  121. if (f == 0 && fuseno_bitno[0] != '0')
  122. f = -1;
  123. if (!in_range(f, 0, IIM_FMAX,
  124. "<frow> must be between 0-31\n\n", cmdtp->usage))
  125. return 1;
  126. bitno = -1;
  127. for (i = 0; i < 6; i++) {
  128. if (fuseno_bitno[i] == '_') {
  129. bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10);
  130. if (bitno == 0 && fuseno_bitno[i+1] != '0')
  131. bitno = -1;
  132. break;
  133. }
  134. }
  135. if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n"
  136. "Example of <frow_bitno>: \"18_4\" sets bit 4 of row 18\n",
  137. cmdtp->usage))
  138. return 1;
  139. out_be32(&iim->err, in_be32(&iim->err));
  140. out_be32(&iim->prg_p, IIM_PRG_P_SET);
  141. out_be32(&iim->ua, IIM_SET_UA(bank, f));
  142. out_be32(&iim->la, IIM_SET_LA(f, bitno));
  143. #ifdef DEBUG
  144. printf("Programming disabled with DEBUG defined \n");
  145. printf(""Set up to pro
  146. printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la);
  147. #else
  148. out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG);
  149. do
  150. udelay(20);
  151. while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
  152. out_be32(&iim->prg_p, 0);
  153. err = in_be32(&iim->err);
  154. if (stat & IIM_STAT_PRGD) {
  155. if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) {
  156. printf("Fuse is successfully set");
  157. if (err)
  158. printf(" - however there are other errors");
  159. printf("\n");
  160. }
  161. iim->stat = 0;
  162. }
  163. if (err) {
  164. iim_err_msg(err);
  165. out_be32(&iim->err, in_be32(&iim->err));
  166. }
  167. #endif
  168. }
  169. int ads5121_fuse_sense(int bank, int fstart, int num)
  170. {
  171. iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
  172. u32 iim_fbac;
  173. u32 stat, err, err_hold = 0;
  174. int f, ctr;
  175. out_be32(&iim->err, in_be32(&iim->err));
  176. if (bank == 0)
  177. iim_fbac = in_be32(&iim->fbac0);
  178. else
  179. iim_fbac = in_be32(&iim->fbac1);
  180. if (iim_fbac & IIM_FBAC_FBESP) {
  181. printf("\tSense Protect disallows this operation\n");
  182. out_be32(&iim->err, IIM_FBAC_FBESP);
  183. return 1;
  184. }
  185. err = in_be32(&iim->err);
  186. if (err) {
  187. iim_err_msg(err);
  188. err_hold |= err;
  189. }
  190. if (err & IIM_ERR_RPE)
  191. printf("\tRead protect fuse is set; "
  192. "Sense Protect may be set but will be attempted\n");
  193. if (err)
  194. out_be32(&iim->err, err);
  195. printf("Sensing fuse(s) on Bank %d\n", bank);
  196. for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) {
  197. out_be32(&iim->ua, IIM_SET_UA(bank, f));
  198. out_be32(&iim->la, IIM_SET_LA(f, 0));
  199. out_be32(&iim->fctl, IIM_FCTL_ESNS_N);
  200. do
  201. udelay(20);
  202. while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
  203. err = in_be32(&iim->err);
  204. if (err & IIM_ERR_SNSE) {
  205. iim_err_msg(err);
  206. out_be32(&iim->err, IIM_ERR_SNSE);
  207. return 1;
  208. }
  209. if (stat & IIM_STAT_SNSD) {
  210. out_be32(&iim->stat, 0);
  211. if (ctr % 4 == 0)
  212. printf("F%2d:", f);
  213. printf("\t%#04x", (u8)iim->sdat);
  214. if (ctr % 4 == 3)
  215. printf("\n");
  216. }
  217. if (err) {
  218. err_hold |= err;
  219. out_be32(&iim->err, err);
  220. }
  221. }
  222. if (ctr % 4 != 0)
  223. printf("\n");
  224. if (err_hold)
  225. iim_err_msg(err_hold);
  226. return 0;
  227. }
  228. int ads5121_fuse_stat(int bank)
  229. {
  230. iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
  231. u32 iim_fbac;
  232. u32 err;
  233. out_be32(&iim->err, in_be32(&iim->err));
  234. if (bank == 0)
  235. iim_fbac = in_be32(&iim->fbac0);
  236. else
  237. iim_fbac = in_be32(&iim->fbac1);
  238. err = in_be32(&iim->err);
  239. if (err)
  240. iim_err_msg(err);
  241. if (err & IIM_ERR_RPE || iim_fbac & IIM_FBAC_FBRP) {
  242. if (iim_fbac == 0)
  243. printf("Since protection settings can't be read - "
  244. "try sensing fuse row 0;\n");
  245. return 0;
  246. }
  247. if (iim_fbac & IIM_PROTECTION)
  248. printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac);
  249. else if (!(err & IIM_ERR_RPE))
  250. printf("No Protection fuses are set\n");
  251. if (iim_fbac & IIM_FBAC_FBWP)
  252. printf("\tWrite Protect fuse is set\n");
  253. if (iim_fbac & IIM_FBAC_FBOP)
  254. printf("\tOverride Protect fuse is set\n");
  255. if (iim_fbac & IIM_FBAC_FBESP)
  256. printf("\tSense Protect Fuse is set\n");
  257. out_be32(&iim->err, in_be32(&iim->err));
  258. return 0;
  259. }
  260. int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  261. {
  262. int frow, n, v, bank;
  263. if (cur_bank == '0')
  264. bank = 0;
  265. else
  266. bank = 1;
  267. switch (argc) {
  268. case 0:
  269. case 1:
  270. printf("Usage:\n%s\n", cmdtp->usage);
  271. return 1;
  272. case 2:
  273. if (strncmp(argv[1], "stat", 4) == 0)
  274. return ads5121_fuse_stat(bank);
  275. if (strncmp(argv[1], "read", 4) == 0)
  276. return ads5121_fuse_read(bank, 0, IIM_FMAX + 1);
  277. if (strncmp(argv[1], "sense", 5) == 0)
  278. return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1);
  279. if (strncmp(argv[1], "ovride", 6) == 0)
  280. return ads5121_fuse_override(bank, IIM_FMAX + 1, 0);
  281. if (strncmp(argv[1], "bank", 4) == 0) {
  282. printf("Active Fuse Bank is %c\n", cur_bank);
  283. return 0;
  284. }
  285. printf("Usage:\n%s\n", cmdtp->usage);
  286. return 1;
  287. case 3:
  288. if (strncmp(argv[1], "bank", 4) == 0) {
  289. if (argv[2][0] == '0')
  290. cur_bank = '0';
  291. else if (argv[2][0] == '1')
  292. cur_bank = '1';
  293. else {
  294. printf("Usage:\n%s\n", cmdtp->usage);
  295. return 1;
  296. }
  297. printf("Setting Active Fuse Bank to %c\n", cur_bank);
  298. return 0;
  299. }
  300. if (strncmp(argv[1], "prog", 4) == 0)
  301. return ads5121_fuse_prog(cmdtp, bank, argv[2]);
  302. frow = (int)simple_strtol(argv[2], NULL, 10);
  303. if (frow == 0 && argv[2][0] != '0')
  304. frow = -1;
  305. if (!in_range(frow, 0, IIM_FMAX,
  306. "<frow> must be between 0-31\n\n", cmdtp->usage))
  307. return 1;
  308. if (strncmp(argv[1], "read", 4) == 0)
  309. return ads5121_fuse_read(bank, frow, 1);
  310. if (strncmp(argv[1], "ovride", 6) == 0)
  311. return ads5121_fuse_override(bank, frow, 0);
  312. if (strncmp(argv[1], "sense", 5) == 0)
  313. return ads5121_fuse_sense(bank, frow, 1);
  314. printf("Usage:\n%s\n", cmdtp->usage);
  315. return 1;
  316. case 4:
  317. frow = (int)simple_strtol(argv[2], NULL, 10);
  318. if (frow == 0 && argv[2][0] != '0')
  319. frow = -1;
  320. if (!in_range(frow, 0, IIM_FMAX,
  321. "<frow> must be between 0-31\n\n", cmdtp->usage))
  322. return 1;
  323. if (strncmp(argv[1], "read", 4) == 0) {
  324. n = (int)simple_strtol(argv[3], NULL, 10);
  325. if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
  326. "<frow>+<n> must be between 1-32\n\n",
  327. cmdtp->usage))
  328. return 1;
  329. return ads5121_fuse_read(bank, frow, n);
  330. }
  331. if (strncmp(argv[1], "ovride", 6) == 0) {
  332. v = (int)simple_strtol(argv[3], NULL, 10);
  333. return ads5121_fuse_override(bank, frow, v);
  334. }
  335. if (strncmp(argv[1], "sense", 5) == 0) {
  336. n = (int)simple_strtol(argv[3], NULL, 10);
  337. if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
  338. "<frow>+<n> must be between 1-32\n\n",
  339. cmdtp->usage))
  340. return 1;
  341. return ads5121_fuse_sense(bank, frow, n);
  342. }
  343. printf("Usage:\n%s\n", cmdtp->usage);
  344. return 1;
  345. default: /* at least 5 args */
  346. printf("Usage:\n%s\n", cmdtp->usage);
  347. return 1;
  348. }
  349. }
  350. U_BOOT_CMD(
  351. fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse,
  352. " - Read, Sense, Override or Program Fuses\n",
  353. "bank <n> - sets active Fuse Bank to 0 or 1\n"
  354. " no args shows current active bank\n"
  355. "fuse stat - print active fuse bank's protection status\n"
  356. "fuse read [<frow> [<n>]] - print <n> fuse rows starting at <frow>\n"
  357. " no args to print entire bank's fuses\n"
  358. "fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n"
  359. " no <v> defaults to 0 for the row\n"
  360. " no args resets entire bank to 0\n"
  361. " NOTE - settings persist until hard reset\n"
  362. "fuse sense [<frow>] - senses current fuse at <frow>\n"
  363. " no args for entire bank\n"
  364. "fuse prog <frow_bit> - program fuse at row <frow>, bit <_bit>\n"
  365. " <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n"
  366. " WARNING - this is permanent\n"
  367. );
  368. #endif /* CONFIG_CMD_FUSE */