otp.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /*
  2. * Copyright (c) 2010 Broadcom Corporation
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <linux/io.h>
  17. #include <linux/errno.h>
  18. #include <linux/string.h>
  19. #include <brcm_hw_ids.h>
  20. #include <chipcommon.h>
  21. #include "aiutils.h"
  22. #include "otp.h"
  23. #define OTPS_GUP_MASK 0x00000f00
  24. #define OTPS_GUP_SHIFT 8
  25. /* h/w subregion is programmed */
  26. #define OTPS_GUP_HW 0x00000100
  27. /* s/w subregion is programmed */
  28. #define OTPS_GUP_SW 0x00000200
  29. /* chipid/pkgopt subregion is programmed */
  30. #define OTPS_GUP_CI 0x00000400
  31. /* fuse subregion is programmed */
  32. #define OTPS_GUP_FUSE 0x00000800
  33. /* Fields in otpprog in rev >= 21 */
  34. #define OTPP_COL_MASK 0x000000ff
  35. #define OTPP_COL_SHIFT 0
  36. #define OTPP_ROW_MASK 0x0000ff00
  37. #define OTPP_ROW_SHIFT 8
  38. #define OTPP_OC_MASK 0x0f000000
  39. #define OTPP_OC_SHIFT 24
  40. #define OTPP_READERR 0x10000000
  41. #define OTPP_VALUE_MASK 0x20000000
  42. #define OTPP_VALUE_SHIFT 29
  43. #define OTPP_START_BUSY 0x80000000
  44. #define OTPP_READ 0x40000000
  45. /* Opcodes for OTPP_OC field */
  46. #define OTPPOC_READ 0
  47. #define OTPPOC_BIT_PROG 1
  48. #define OTPPOC_VERIFY 3
  49. #define OTPPOC_INIT 4
  50. #define OTPPOC_SET 5
  51. #define OTPPOC_RESET 6
  52. #define OTPPOC_OCST 7
  53. #define OTPPOC_ROW_LOCK 8
  54. #define OTPPOC_PRESCN_TEST 9
  55. #define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23)
  56. #define OTPP_TRIES 10000000 /* # of tries for OTPP */
  57. #define MAXNUMRDES 9 /* Maximum OTP redundancy entries */
  58. /* Fixed size subregions sizes in words */
  59. #define OTPGU_CI_SZ 2
  60. struct otpinfo;
  61. /* OTP function struct */
  62. struct otp_fn_s {
  63. int (*init)(struct si_pub *sih, struct otpinfo *oi);
  64. int (*read_region)(struct otpinfo *oi, int region, u16 *data,
  65. uint *wlen);
  66. };
  67. struct otpinfo {
  68. uint ccrev; /* chipc revision */
  69. const struct otp_fn_s *fn; /* OTP functions */
  70. struct si_pub *sih; /* Saved sb handle */
  71. /* IPX OTP section */
  72. u16 wsize; /* Size of otp in words */
  73. u16 rows; /* Geometry */
  74. u16 cols; /* Geometry */
  75. u32 status; /* Flag bits (lock/prog/rv).
  76. * (Reflected only when OTP is power cycled)
  77. */
  78. u16 hwbase; /* hardware subregion offset */
  79. u16 hwlim; /* hardware subregion boundary */
  80. u16 swbase; /* software subregion offset */
  81. u16 swlim; /* software subregion boundary */
  82. u16 fbase; /* fuse subregion offset */
  83. u16 flim; /* fuse subregion boundary */
  84. int otpgu_base; /* offset to General Use Region */
  85. };
  86. /* OTP layout */
  87. /* CC revs 21, 24 and 27 OTP General Use Region word offset */
  88. #define REVA4_OTPGU_BASE 12
  89. /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
  90. #define REVB8_OTPGU_BASE 20
  91. /* CC rev 36 OTP General Use Region word offset */
  92. #define REV36_OTPGU_BASE 12
  93. /* Subregion word offsets in General Use region */
  94. #define OTPGU_HSB_OFF 0
  95. #define OTPGU_SFB_OFF 1
  96. #define OTPGU_CI_OFF 2
  97. #define OTPGU_P_OFF 3
  98. #define OTPGU_SROM_OFF 4
  99. /* Flag bit offsets in General Use region */
  100. #define OTPGU_HWP_OFF 60
  101. #define OTPGU_SWP_OFF 61
  102. #define OTPGU_CIP_OFF 62
  103. #define OTPGU_FUSEP_OFF 63
  104. #define OTPGU_CIP_MSK 0x4000
  105. #define OTPGU_P_MSK 0xf000
  106. #define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16)
  107. /* OTP Size */
  108. #define OTP_SZ_FU_324 ((roundup(324, 8))/8) /* 324 bits */
  109. #define OTP_SZ_FU_288 (288/8) /* 288 bits */
  110. #define OTP_SZ_FU_216 (216/8) /* 216 bits */
  111. #define OTP_SZ_FU_72 (72/8) /* 72 bits */
  112. #define OTP_SZ_CHECKSUM (16/8) /* 16 bits */
  113. #define OTP4315_SWREG_SZ 178 /* 178 bytes */
  114. #define OTP_SZ_FU_144 (144/8) /* 144 bits */
  115. static u16
  116. ipxotp_otpr(struct otpinfo *oi, struct chipcregs __iomem *cc, uint wn)
  117. {
  118. return R_REG(&cc->sromotp[wn]);
  119. }
  120. /*
  121. * Calculate max HW/SW region byte size by subtracting fuse region
  122. * and checksum size, osizew is oi->wsize (OTP size - GU size) in words
  123. */
  124. static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
  125. {
  126. int ret = 0;
  127. switch (sih->chip) {
  128. case BCM43224_CHIP_ID:
  129. case BCM43225_CHIP_ID:
  130. ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
  131. break;
  132. case BCM4313_CHIP_ID:
  133. ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
  134. break;
  135. default:
  136. break; /* Don't know about this chip */
  137. }
  138. return ret;
  139. }
  140. static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
  141. {
  142. uint k;
  143. u32 otpp, st;
  144. /*
  145. * record word offset of General Use Region
  146. * for various chipcommon revs
  147. */
  148. if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
  149. || oi->sih->ccrev == 27) {
  150. oi->otpgu_base = REVA4_OTPGU_BASE;
  151. } else if (oi->sih->ccrev == 36) {
  152. /*
  153. * OTP size greater than equal to 2KB (128 words),
  154. * otpgu_base is similar to rev23
  155. */
  156. if (oi->wsize >= 128)
  157. oi->otpgu_base = REVB8_OTPGU_BASE;
  158. else
  159. oi->otpgu_base = REV36_OTPGU_BASE;
  160. } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
  161. oi->otpgu_base = REVB8_OTPGU_BASE;
  162. }
  163. /* First issue an init command so the status is up to date */
  164. otpp =
  165. OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
  166. W_REG(&cc->otpprog, otpp);
  167. for (k = 0;
  168. ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
  169. && (k < OTPP_TRIES); k++)
  170. ;
  171. if (k >= OTPP_TRIES)
  172. return;
  173. /* Read OTP lock bits and subregion programmed indication bits */
  174. oi->status = R_REG(&cc->otpstatus);
  175. if ((oi->sih->chip == BCM43224_CHIP_ID)
  176. || (oi->sih->chip == BCM43225_CHIP_ID)) {
  177. u32 p_bits;
  178. p_bits =
  179. (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
  180. OTPGU_P_MSK)
  181. >> OTPGU_P_SHIFT;
  182. oi->status |= (p_bits << OTPS_GUP_SHIFT);
  183. }
  184. /*
  185. * h/w region base and fuse region limit are fixed to
  186. * the top and the bottom of the general use region.
  187. * Everything else can be flexible.
  188. */
  189. oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
  190. oi->hwlim = oi->wsize;
  191. if (oi->status & OTPS_GUP_HW) {
  192. oi->hwlim =
  193. ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
  194. oi->swbase = oi->hwlim;
  195. } else
  196. oi->swbase = oi->hwbase;
  197. /* subtract fuse and checksum from beginning */
  198. oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
  199. if (oi->status & OTPS_GUP_SW) {
  200. oi->swlim =
  201. ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
  202. oi->fbase = oi->swlim;
  203. } else
  204. oi->fbase = oi->swbase;
  205. oi->flim = oi->wsize;
  206. }
  207. static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
  208. {
  209. uint idx;
  210. struct chipcregs __iomem *cc;
  211. /* Make sure we're running IPX OTP */
  212. if (!OTPTYPE_IPX(sih->ccrev))
  213. return -EBADE;
  214. /* Make sure OTP is not disabled */
  215. if (ai_is_otp_disabled(sih))
  216. return -EBADE;
  217. /* Check for otp size */
  218. switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
  219. case 0:
  220. /* Nothing there */
  221. return -EBADE;
  222. case 1: /* 32x64 */
  223. oi->rows = 32;
  224. oi->cols = 64;
  225. oi->wsize = 128;
  226. break;
  227. case 2: /* 64x64 */
  228. oi->rows = 64;
  229. oi->cols = 64;
  230. oi->wsize = 256;
  231. break;
  232. case 5: /* 96x64 */
  233. oi->rows = 96;
  234. oi->cols = 64;
  235. oi->wsize = 384;
  236. break;
  237. case 7: /* 16x64 *//* 1024 bits */
  238. oi->rows = 16;
  239. oi->cols = 64;
  240. oi->wsize = 64;
  241. break;
  242. default:
  243. /* Don't know the geometry */
  244. return -EBADE;
  245. }
  246. /* Retrieve OTP region info */
  247. idx = ai_coreidx(sih);
  248. cc = ai_setcoreidx(sih, SI_CC_IDX);
  249. _ipxotp_init(oi, cc);
  250. ai_setcoreidx(sih, idx);
  251. return 0;
  252. }
  253. static int
  254. ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
  255. {
  256. uint idx;
  257. struct chipcregs __iomem *cc;
  258. uint base, i, sz;
  259. /* Validate region selection */
  260. switch (region) {
  261. case OTP_HW_RGN:
  262. sz = (uint) oi->hwlim - oi->hwbase;
  263. if (!(oi->status & OTPS_GUP_HW)) {
  264. *wlen = sz;
  265. return -ENODATA;
  266. }
  267. if (*wlen < sz) {
  268. *wlen = sz;
  269. return -EOVERFLOW;
  270. }
  271. base = oi->hwbase;
  272. break;
  273. case OTP_SW_RGN:
  274. sz = ((uint) oi->swlim - oi->swbase);
  275. if (!(oi->status & OTPS_GUP_SW)) {
  276. *wlen = sz;
  277. return -ENODATA;
  278. }
  279. if (*wlen < sz) {
  280. *wlen = sz;
  281. return -EOVERFLOW;
  282. }
  283. base = oi->swbase;
  284. break;
  285. case OTP_CI_RGN:
  286. sz = OTPGU_CI_SZ;
  287. if (!(oi->status & OTPS_GUP_CI)) {
  288. *wlen = sz;
  289. return -ENODATA;
  290. }
  291. if (*wlen < sz) {
  292. *wlen = sz;
  293. return -EOVERFLOW;
  294. }
  295. base = oi->otpgu_base + OTPGU_CI_OFF;
  296. break;
  297. case OTP_FUSE_RGN:
  298. sz = (uint) oi->flim - oi->fbase;
  299. if (!(oi->status & OTPS_GUP_FUSE)) {
  300. *wlen = sz;
  301. return -ENODATA;
  302. }
  303. if (*wlen < sz) {
  304. *wlen = sz;
  305. return -EOVERFLOW;
  306. }
  307. base = oi->fbase;
  308. break;
  309. case OTP_ALL_RGN:
  310. sz = ((uint) oi->flim - oi->hwbase);
  311. if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
  312. *wlen = sz;
  313. return -ENODATA;
  314. }
  315. if (*wlen < sz) {
  316. *wlen = sz;
  317. return -EOVERFLOW;
  318. }
  319. base = oi->hwbase;
  320. break;
  321. default:
  322. return -EINVAL;
  323. }
  324. idx = ai_coreidx(oi->sih);
  325. cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
  326. /* Read the data */
  327. for (i = 0; i < sz; i++)
  328. data[i] = ipxotp_otpr(oi, cc, base + i);
  329. ai_setcoreidx(oi->sih, idx);
  330. *wlen = sz;
  331. return 0;
  332. }
  333. static const struct otp_fn_s ipxotp_fn = {
  334. (int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init,
  335. (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region,
  336. };
  337. static int otp_init(struct si_pub *sih, struct otpinfo *oi)
  338. {
  339. int ret;
  340. memset(oi, 0, sizeof(struct otpinfo));
  341. oi->ccrev = sih->ccrev;
  342. if (OTPTYPE_IPX(oi->ccrev))
  343. oi->fn = &ipxotp_fn;
  344. if (oi->fn == NULL)
  345. return -EBADE;
  346. oi->sih = sih;
  347. ret = (oi->fn->init) (sih, oi);
  348. return ret;
  349. }
  350. int
  351. otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) {
  352. struct otpinfo otpinfo;
  353. struct otpinfo *oi = &otpinfo;
  354. int err = 0;
  355. if (ai_is_otp_disabled(sih)) {
  356. err = -EPERM;
  357. goto out;
  358. }
  359. err = otp_init(sih, oi);
  360. if (err)
  361. goto out;
  362. err = ((oi)->fn->read_region)(oi, region, data, wlen);
  363. out:
  364. return err;
  365. }