srom.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299
  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/kernel.h>
  17. #include <linux/string.h>
  18. #include <linux/io.h>
  19. #include <linux/etherdevice.h>
  20. #include <linux/crc8.h>
  21. #include <stdarg.h>
  22. #include <chipcommon.h>
  23. #include <brcmu_utils.h>
  24. #include "pub.h"
  25. #include "nicpci.h"
  26. #include "aiutils.h"
  27. #include "otp.h"
  28. #include "srom.h"
  29. #include "soc.h"
  30. /*
  31. * SROM CRC8 polynomial value:
  32. *
  33. * x^8 + x^7 +x^6 + x^4 + x^2 + 1
  34. */
  35. #define SROM_CRC8_POLY 0xAB
  36. /* Maximum srom: 6 Kilobits == 768 bytes */
  37. #define SROM_MAX 768
  38. /* PCI fields */
  39. #define PCI_F0DEVID 48
  40. #define SROM_WORDS 64
  41. #define SROM_SSID 2
  42. #define SROM_WL1LHMAXP 29
  43. #define SROM_WL1LPAB0 30
  44. #define SROM_WL1LPAB1 31
  45. #define SROM_WL1LPAB2 32
  46. #define SROM_WL1HPAB0 33
  47. #define SROM_WL1HPAB1 34
  48. #define SROM_WL1HPAB2 35
  49. #define SROM_MACHI_IL0 36
  50. #define SROM_MACMID_IL0 37
  51. #define SROM_MACLO_IL0 38
  52. #define SROM_MACHI_ET1 42
  53. #define SROM_MACMID_ET1 43
  54. #define SROM_MACLO_ET1 44
  55. #define SROM3_MACHI 37
  56. #define SROM3_MACMID 38
  57. #define SROM3_MACLO 39
  58. #define SROM_BXARSSI2G 40
  59. #define SROM_BXARSSI5G 41
  60. #define SROM_TRI52G 42
  61. #define SROM_TRI5GHL 43
  62. #define SROM_RXPO52G 45
  63. #define SROM_AABREV 46
  64. /* Fields in AABREV */
  65. #define SROM_BR_MASK 0x00ff
  66. #define SROM_CC_MASK 0x0f00
  67. #define SROM_CC_SHIFT 8
  68. #define SROM_AA0_MASK 0x3000
  69. #define SROM_AA0_SHIFT 12
  70. #define SROM_AA1_MASK 0xc000
  71. #define SROM_AA1_SHIFT 14
  72. #define SROM_WL0PAB0 47
  73. #define SROM_WL0PAB1 48
  74. #define SROM_WL0PAB2 49
  75. #define SROM_LEDBH10 50
  76. #define SROM_LEDBH32 51
  77. #define SROM_WL10MAXP 52
  78. #define SROM_WL1PAB0 53
  79. #define SROM_WL1PAB1 54
  80. #define SROM_WL1PAB2 55
  81. #define SROM_ITT 56
  82. #define SROM_BFL 57
  83. #define SROM_BFL2 28
  84. #define SROM3_BFL2 61
  85. #define SROM_AG10 58
  86. #define SROM_CCODE 59
  87. #define SROM_OPO 60
  88. #define SROM3_LEDDC 62
  89. #define SROM_CRCREV 63
  90. /* SROM Rev 4: Reallocate the software part of the srom to accommodate
  91. * MIMO features. It assumes up to two PCIE functions and 440 bytes
  92. * of usable srom i.e. the usable storage in chips with OTP that
  93. * implements hardware redundancy.
  94. */
  95. #define SROM4_WORDS 220
  96. #define SROM4_SIGN 32
  97. #define SROM4_SIGNATURE 0x5372
  98. #define SROM4_BREV 33
  99. #define SROM4_BFL0 34
  100. #define SROM4_BFL1 35
  101. #define SROM4_BFL2 36
  102. #define SROM4_BFL3 37
  103. #define SROM5_BFL0 37
  104. #define SROM5_BFL1 38
  105. #define SROM5_BFL2 39
  106. #define SROM5_BFL3 40
  107. #define SROM4_MACHI 38
  108. #define SROM4_MACMID 39
  109. #define SROM4_MACLO 40
  110. #define SROM5_MACHI 41
  111. #define SROM5_MACMID 42
  112. #define SROM5_MACLO 43
  113. #define SROM4_CCODE 41
  114. #define SROM4_REGREV 42
  115. #define SROM5_CCODE 34
  116. #define SROM5_REGREV 35
  117. #define SROM4_LEDBH10 43
  118. #define SROM4_LEDBH32 44
  119. #define SROM5_LEDBH10 59
  120. #define SROM5_LEDBH32 60
  121. #define SROM4_LEDDC 45
  122. #define SROM5_LEDDC 45
  123. #define SROM4_AA 46
  124. #define SROM4_AG10 47
  125. #define SROM4_AG32 48
  126. #define SROM4_TXPID2G 49
  127. #define SROM4_TXPID5G 51
  128. #define SROM4_TXPID5GL 53
  129. #define SROM4_TXPID5GH 55
  130. #define SROM4_TXRXC 61
  131. #define SROM4_TXCHAIN_MASK 0x000f
  132. #define SROM4_TXCHAIN_SHIFT 0
  133. #define SROM4_RXCHAIN_MASK 0x00f0
  134. #define SROM4_RXCHAIN_SHIFT 4
  135. #define SROM4_SWITCH_MASK 0xff00
  136. #define SROM4_SWITCH_SHIFT 8
  137. /* Per-path fields */
  138. #define MAX_PATH_SROM 4
  139. #define SROM4_PATH0 64
  140. #define SROM4_PATH1 87
  141. #define SROM4_PATH2 110
  142. #define SROM4_PATH3 133
  143. #define SROM4_2G_ITT_MAXP 0
  144. #define SROM4_2G_PA 1
  145. #define SROM4_5G_ITT_MAXP 5
  146. #define SROM4_5GLH_MAXP 6
  147. #define SROM4_5G_PA 7
  148. #define SROM4_5GL_PA 11
  149. #define SROM4_5GH_PA 15
  150. /* All the miriad power offsets */
  151. #define SROM4_2G_CCKPO 156
  152. #define SROM4_2G_OFDMPO 157
  153. #define SROM4_5G_OFDMPO 159
  154. #define SROM4_5GL_OFDMPO 161
  155. #define SROM4_5GH_OFDMPO 163
  156. #define SROM4_2G_MCSPO 165
  157. #define SROM4_5G_MCSPO 173
  158. #define SROM4_5GL_MCSPO 181
  159. #define SROM4_5GH_MCSPO 189
  160. #define SROM4_CDDPO 197
  161. #define SROM4_STBCPO 198
  162. #define SROM4_BW40PO 199
  163. #define SROM4_BWDUPPO 200
  164. #define SROM4_CRCREV 219
  165. /* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
  166. * This is acombined srom for both MIMO and SISO boards, usable in
  167. * the .130 4Kilobit OTP with hardware redundancy.
  168. */
  169. #define SROM8_BREV 65
  170. #define SROM8_BFL0 66
  171. #define SROM8_BFL1 67
  172. #define SROM8_BFL2 68
  173. #define SROM8_BFL3 69
  174. #define SROM8_MACHI 70
  175. #define SROM8_MACMID 71
  176. #define SROM8_MACLO 72
  177. #define SROM8_CCODE 73
  178. #define SROM8_REGREV 74
  179. #define SROM8_LEDBH10 75
  180. #define SROM8_LEDBH32 76
  181. #define SROM8_LEDDC 77
  182. #define SROM8_AA 78
  183. #define SROM8_AG10 79
  184. #define SROM8_AG32 80
  185. #define SROM8_TXRXC 81
  186. #define SROM8_BXARSSI2G 82
  187. #define SROM8_BXARSSI5G 83
  188. #define SROM8_TRI52G 84
  189. #define SROM8_TRI5GHL 85
  190. #define SROM8_RXPO52G 86
  191. #define SROM8_FEM2G 87
  192. #define SROM8_FEM5G 88
  193. #define SROM8_FEM_ANTSWLUT_MASK 0xf800
  194. #define SROM8_FEM_ANTSWLUT_SHIFT 11
  195. #define SROM8_FEM_TR_ISO_MASK 0x0700
  196. #define SROM8_FEM_TR_ISO_SHIFT 8
  197. #define SROM8_FEM_PDET_RANGE_MASK 0x00f8
  198. #define SROM8_FEM_PDET_RANGE_SHIFT 3
  199. #define SROM8_FEM_EXTPA_GAIN_MASK 0x0006
  200. #define SROM8_FEM_EXTPA_GAIN_SHIFT 1
  201. #define SROM8_FEM_TSSIPOS_MASK 0x0001
  202. #define SROM8_FEM_TSSIPOS_SHIFT 0
  203. #define SROM8_THERMAL 89
  204. /* Temp sense related entries */
  205. #define SROM8_MPWR_RAWTS 90
  206. #define SROM8_TS_SLP_OPT_CORRX 91
  207. /* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable,
  208. * IQSWP: IQ CAL swap disable */
  209. #define SROM8_FOC_HWIQ_IQSWP 92
  210. /* Temperature delta for PHY calibration */
  211. #define SROM8_PHYCAL_TEMPDELTA 93
  212. /* Per-path offsets & fields */
  213. #define SROM8_PATH0 96
  214. #define SROM8_PATH1 112
  215. #define SROM8_PATH2 128
  216. #define SROM8_PATH3 144
  217. #define SROM8_2G_ITT_MAXP 0
  218. #define SROM8_2G_PA 1
  219. #define SROM8_5G_ITT_MAXP 4
  220. #define SROM8_5GLH_MAXP 5
  221. #define SROM8_5G_PA 6
  222. #define SROM8_5GL_PA 9
  223. #define SROM8_5GH_PA 12
  224. /* All the miriad power offsets */
  225. #define SROM8_2G_CCKPO 160
  226. #define SROM8_2G_OFDMPO 161
  227. #define SROM8_5G_OFDMPO 163
  228. #define SROM8_5GL_OFDMPO 165
  229. #define SROM8_5GH_OFDMPO 167
  230. #define SROM8_2G_MCSPO 169
  231. #define SROM8_5G_MCSPO 177
  232. #define SROM8_5GL_MCSPO 185
  233. #define SROM8_5GH_MCSPO 193
  234. #define SROM8_CDDPO 201
  235. #define SROM8_STBCPO 202
  236. #define SROM8_BW40PO 203
  237. #define SROM8_BWDUPPO 204
  238. /* SISO PA parameters are in the path0 spaces */
  239. #define SROM8_SISO 96
  240. /* Legacy names for SISO PA paramters */
  241. #define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP)
  242. #define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA)
  243. #define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1)
  244. #define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2)
  245. #define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP)
  246. #define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP)
  247. #define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA)
  248. #define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1)
  249. #define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2)
  250. #define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA)
  251. #define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1)
  252. #define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2)
  253. #define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA)
  254. #define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1)
  255. #define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2)
  256. /* SROM REV 9 */
  257. #define SROM9_2GPO_CCKBW20 160
  258. #define SROM9_2GPO_CCKBW20UL 161
  259. #define SROM9_2GPO_LOFDMBW20 162
  260. #define SROM9_2GPO_LOFDMBW20UL 164
  261. #define SROM9_5GLPO_LOFDMBW20 166
  262. #define SROM9_5GLPO_LOFDMBW20UL 168
  263. #define SROM9_5GMPO_LOFDMBW20 170
  264. #define SROM9_5GMPO_LOFDMBW20UL 172
  265. #define SROM9_5GHPO_LOFDMBW20 174
  266. #define SROM9_5GHPO_LOFDMBW20UL 176
  267. #define SROM9_2GPO_MCSBW20 178
  268. #define SROM9_2GPO_MCSBW20UL 180
  269. #define SROM9_2GPO_MCSBW40 182
  270. #define SROM9_5GLPO_MCSBW20 184
  271. #define SROM9_5GLPO_MCSBW20UL 186
  272. #define SROM9_5GLPO_MCSBW40 188
  273. #define SROM9_5GMPO_MCSBW20 190
  274. #define SROM9_5GMPO_MCSBW20UL 192
  275. #define SROM9_5GMPO_MCSBW40 194
  276. #define SROM9_5GHPO_MCSBW20 196
  277. #define SROM9_5GHPO_MCSBW20UL 198
  278. #define SROM9_5GHPO_MCSBW40 200
  279. #define SROM9_PO_MCS32 202
  280. #define SROM9_PO_LOFDM40DUP 203
  281. /* SROM flags (see sromvar_t) */
  282. /* value continues as described by the next entry */
  283. #define SRFL_MORE 1
  284. #define SRFL_NOFFS 2 /* value bits can't be all one's */
  285. #define SRFL_PRHEX 4 /* value is in hexdecimal format */
  286. #define SRFL_PRSIGN 8 /* value is in signed decimal format */
  287. #define SRFL_CCODE 0x10 /* value is in country code format */
  288. #define SRFL_ETHADDR 0x20 /* value is an Ethernet address */
  289. #define SRFL_LEDDC 0x40 /* value is an LED duty cycle */
  290. /* do not generate a nvram param, entry is for mfgc */
  291. #define SRFL_NOVAR 0x80
  292. /* Max. nvram variable table size */
  293. #define MAXSZ_NVRAM_VARS 4096
  294. /*
  295. * indicates type of value.
  296. */
  297. enum brcms_srom_var_type {
  298. BRCMS_SROM_STRING,
  299. BRCMS_SROM_SNUMBER,
  300. BRCMS_SROM_UNUMBER
  301. };
  302. /*
  303. * storage type for srom variable.
  304. *
  305. * var_list: for linked list operations.
  306. * varid: identifier of the variable.
  307. * var_type: type of variable.
  308. * buf: variable value when var_type == BRCMS_SROM_STRING.
  309. * uval: unsigned variable value when var_type == BRCMS_SROM_UNUMBER.
  310. * sval: signed variable value when var_type == BRCMS_SROM_SNUMBER.
  311. */
  312. struct brcms_srom_list_head {
  313. struct list_head var_list;
  314. enum brcms_srom_id varid;
  315. enum brcms_srom_var_type var_type;
  316. union {
  317. char buf[0];
  318. u32 uval;
  319. s32 sval;
  320. };
  321. };
  322. struct brcms_sromvar {
  323. enum brcms_srom_id varid;
  324. u32 revmask;
  325. u32 flags;
  326. u16 off;
  327. u16 mask;
  328. };
  329. struct brcms_varbuf {
  330. char *base; /* pointer to buffer base */
  331. char *buf; /* pointer to current position */
  332. unsigned int size; /* current (residual) size in bytes */
  333. };
  334. /*
  335. * Assumptions:
  336. * - Ethernet address spans across 3 consecutive words
  337. *
  338. * Table rules:
  339. * - Add multiple entries next to each other if a value spans across multiple
  340. * words (even multiple fields in the same word) with each entry except the
  341. * last having it's SRFL_MORE bit set.
  342. * - Ethernet address entry does not follow above rule and must not have
  343. * SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
  344. * - The last entry's name field must be NULL to indicate the end of the table.
  345. * Other entries must have non-NULL name.
  346. */
  347. static const struct brcms_sromvar pci_sromvars[] = {
  348. {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID,
  349. 0xffff},
  350. {BRCMS_SROM_BOARDREV, 0x0000000e, SRFL_PRHEX, SROM_AABREV,
  351. SROM_BR_MASK},
  352. {BRCMS_SROM_BOARDREV, 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
  353. {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
  354. {BRCMS_SROM_BOARDFLAGS, 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
  355. {BRCMS_SROM_BOARDFLAGS, 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL,
  356. 0xffff},
  357. {BRCMS_SROM_CONT, 0, 0, SROM_BFL2, 0xffff},
  358. {BRCMS_SROM_BOARDFLAGS, 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL,
  359. 0xffff},
  360. {BRCMS_SROM_CONT, 0, 0, SROM3_BFL2, 0xffff},
  361. {BRCMS_SROM_BOARDFLAGS, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0,
  362. 0xffff},
  363. {BRCMS_SROM_CONT, 0, 0, SROM4_BFL1, 0xffff},
  364. {BRCMS_SROM_BOARDFLAGS, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0,
  365. 0xffff},
  366. {BRCMS_SROM_CONT, 0, 0, SROM5_BFL1, 0xffff},
  367. {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0,
  368. 0xffff},
  369. {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff},
  370. {BRCMS_SROM_BOARDFLAGS2, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2,
  371. 0xffff},
  372. {BRCMS_SROM_CONT, 0, 0, SROM4_BFL3, 0xffff},
  373. {BRCMS_SROM_BOARDFLAGS2, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2,
  374. 0xffff},
  375. {BRCMS_SROM_CONT, 0, 0, SROM5_BFL3, 0xffff},
  376. {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2,
  377. 0xffff},
  378. {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff},
  379. {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
  380. {BRCMS_SROM_BOARDNUM, 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
  381. {BRCMS_SROM_BOARDNUM, 0x00000008, 0, SROM3_MACLO, 0xffff},
  382. {BRCMS_SROM_BOARDNUM, 0x00000010, 0, SROM4_MACLO, 0xffff},
  383. {BRCMS_SROM_BOARDNUM, 0x000000e0, 0, SROM5_MACLO, 0xffff},
  384. {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff},
  385. {BRCMS_SROM_CC, 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
  386. {BRCMS_SROM_REGREV, 0x00000008, 0, SROM_OPO, 0xff00},
  387. {BRCMS_SROM_REGREV, 0x00000010, 0, SROM4_REGREV, 0x00ff},
  388. {BRCMS_SROM_REGREV, 0x000000e0, 0, SROM5_REGREV, 0x00ff},
  389. {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff},
  390. {BRCMS_SROM_LEDBH0, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
  391. {BRCMS_SROM_LEDBH1, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
  392. {BRCMS_SROM_LEDBH2, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
  393. {BRCMS_SROM_LEDBH3, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
  394. {BRCMS_SROM_LEDBH0, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
  395. {BRCMS_SROM_LEDBH1, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
  396. {BRCMS_SROM_LEDBH2, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
  397. {BRCMS_SROM_LEDBH3, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
  398. {BRCMS_SROM_LEDBH0, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
  399. {BRCMS_SROM_LEDBH1, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
  400. {BRCMS_SROM_LEDBH2, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
  401. {BRCMS_SROM_LEDBH3, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
  402. {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
  403. {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
  404. {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
  405. {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
  406. {BRCMS_SROM_PA0B0, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
  407. {BRCMS_SROM_PA0B1, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
  408. {BRCMS_SROM_PA0B2, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
  409. {BRCMS_SROM_PA0ITSSIT, 0x0000000e, 0, SROM_ITT, 0x00ff},
  410. {BRCMS_SROM_PA0MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
  411. {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
  412. {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
  413. {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
  414. {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
  415. {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
  416. {BRCMS_SROM_OPO, 0x0000000c, 0, SROM_OPO, 0x00ff},
  417. {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
  418. {BRCMS_SROM_AA2G, 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
  419. {BRCMS_SROM_AA2G, 0x000000f0, 0, SROM4_AA, 0x00ff},
  420. {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff},
  421. {BRCMS_SROM_AA5G, 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
  422. {BRCMS_SROM_AA5G, 0x000000f0, 0, SROM4_AA, 0xff00},
  423. {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00},
  424. {BRCMS_SROM_AG0, 0x0000000e, 0, SROM_AG10, 0x00ff},
  425. {BRCMS_SROM_AG1, 0x0000000e, 0, SROM_AG10, 0xff00},
  426. {BRCMS_SROM_AG0, 0x000000f0, 0, SROM4_AG10, 0x00ff},
  427. {BRCMS_SROM_AG1, 0x000000f0, 0, SROM4_AG10, 0xff00},
  428. {BRCMS_SROM_AG2, 0x000000f0, 0, SROM4_AG32, 0x00ff},
  429. {BRCMS_SROM_AG3, 0x000000f0, 0, SROM4_AG32, 0xff00},
  430. {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff},
  431. {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00},
  432. {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff},
  433. {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00},
  434. {BRCMS_SROM_PA1B0, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
  435. {BRCMS_SROM_PA1B1, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
  436. {BRCMS_SROM_PA1B2, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
  437. {BRCMS_SROM_PA1LOB0, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
  438. {BRCMS_SROM_PA1LOB1, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
  439. {BRCMS_SROM_PA1LOB2, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
  440. {BRCMS_SROM_PA1HIB0, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
  441. {BRCMS_SROM_PA1HIB1, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
  442. {BRCMS_SROM_PA1HIB2, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
  443. {BRCMS_SROM_PA1ITSSIT, 0x0000000e, 0, SROM_ITT, 0xff00},
  444. {BRCMS_SROM_PA1MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
  445. {BRCMS_SROM_PA1LOMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
  446. {BRCMS_SROM_PA1HIMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
  447. {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
  448. {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
  449. {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
  450. {BRCMS_SROM_PA1LOB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
  451. {BRCMS_SROM_PA1LOB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
  452. {BRCMS_SROM_PA1LOB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
  453. {BRCMS_SROM_PA1HIB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
  454. {BRCMS_SROM_PA1HIB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
  455. {BRCMS_SROM_PA1HIB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
  456. {BRCMS_SROM_PA1ITSSIT, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
  457. {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
  458. {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
  459. {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
  460. {BRCMS_SROM_BXA2G, 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
  461. {BRCMS_SROM_RSSISAV2G, 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
  462. {BRCMS_SROM_RSSISMC2G, 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
  463. {BRCMS_SROM_RSSISMF2G, 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
  464. {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
  465. {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
  466. {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
  467. {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
  468. {BRCMS_SROM_BXA5G, 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
  469. {BRCMS_SROM_RSSISAV5G, 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
  470. {BRCMS_SROM_RSSISMC5G, 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
  471. {BRCMS_SROM_RSSISMF5G, 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
  472. {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
  473. {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
  474. {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
  475. {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
  476. {BRCMS_SROM_TRI2G, 0x00000008, 0, SROM_TRI52G, 0x00ff},
  477. {BRCMS_SROM_TRI5G, 0x00000008, 0, SROM_TRI52G, 0xff00},
  478. {BRCMS_SROM_TRI5GL, 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
  479. {BRCMS_SROM_TRI5GH, 0x00000008, 0, SROM_TRI5GHL, 0xff00},
  480. {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
  481. {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00},
  482. {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
  483. {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
  484. {BRCMS_SROM_RXPO2G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
  485. {BRCMS_SROM_RXPO5G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
  486. {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
  487. {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
  488. {BRCMS_SROM_TXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
  489. SROM4_TXCHAIN_MASK},
  490. {BRCMS_SROM_RXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
  491. SROM4_RXCHAIN_MASK},
  492. {BRCMS_SROM_ANTSWITCH, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
  493. SROM4_SWITCH_MASK},
  494. {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
  495. SROM4_TXCHAIN_MASK},
  496. {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
  497. SROM4_RXCHAIN_MASK},
  498. {BRCMS_SROM_ANTSWITCH, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
  499. SROM4_SWITCH_MASK},
  500. {BRCMS_SROM_TSSIPOS2G, 0xffffff00, 0, SROM8_FEM2G,
  501. SROM8_FEM_TSSIPOS_MASK},
  502. {BRCMS_SROM_EXTPAGAIN2G, 0xffffff00, 0, SROM8_FEM2G,
  503. SROM8_FEM_EXTPA_GAIN_MASK},
  504. {BRCMS_SROM_PDETRANGE2G, 0xffffff00, 0, SROM8_FEM2G,
  505. SROM8_FEM_PDET_RANGE_MASK},
  506. {BRCMS_SROM_TRISO2G, 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
  507. {BRCMS_SROM_ANTSWCTL2G, 0xffffff00, 0, SROM8_FEM2G,
  508. SROM8_FEM_ANTSWLUT_MASK},
  509. {BRCMS_SROM_TSSIPOS5G, 0xffffff00, 0, SROM8_FEM5G,
  510. SROM8_FEM_TSSIPOS_MASK},
  511. {BRCMS_SROM_EXTPAGAIN5G, 0xffffff00, 0, SROM8_FEM5G,
  512. SROM8_FEM_EXTPA_GAIN_MASK},
  513. {BRCMS_SROM_PDETRANGE5G, 0xffffff00, 0, SROM8_FEM5G,
  514. SROM8_FEM_PDET_RANGE_MASK},
  515. {BRCMS_SROM_TRISO5G, 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
  516. {BRCMS_SROM_ANTSWCTL5G, 0xffffff00, 0, SROM8_FEM5G,
  517. SROM8_FEM_ANTSWLUT_MASK},
  518. {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00},
  519. {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
  520. {BRCMS_SROM_TXPID2GA0, 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
  521. {BRCMS_SROM_TXPID2GA1, 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
  522. {BRCMS_SROM_TXPID2GA2, 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
  523. {BRCMS_SROM_TXPID2GA3, 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
  524. {BRCMS_SROM_TXPID5GA0, 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
  525. {BRCMS_SROM_TXPID5GA1, 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
  526. {BRCMS_SROM_TXPID5GA2, 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
  527. {BRCMS_SROM_TXPID5GA3, 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
  528. {BRCMS_SROM_TXPID5GLA0, 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
  529. {BRCMS_SROM_TXPID5GLA1, 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
  530. {BRCMS_SROM_TXPID5GLA2, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
  531. {BRCMS_SROM_TXPID5GLA3, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
  532. {BRCMS_SROM_TXPID5GHA0, 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
  533. {BRCMS_SROM_TXPID5GHA1, 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
  534. {BRCMS_SROM_TXPID5GHA2, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
  535. {BRCMS_SROM_TXPID5GHA3, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
  536. {BRCMS_SROM_CCODE, 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
  537. {BRCMS_SROM_CCODE, 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
  538. {BRCMS_SROM_CCODE, 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
  539. {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
  540. {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
  541. {BRCMS_SROM_MACADDR, 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
  542. {BRCMS_SROM_MACADDR, 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
  543. {BRCMS_SROM_MACADDR, 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
  544. {BRCMS_SROM_IL0MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0,
  545. 0xffff},
  546. {BRCMS_SROM_ET1MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1,
  547. 0xffff},
  548. {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC,
  549. 0xffff},
  550. {BRCMS_SROM_LEDDC, 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC,
  551. 0xffff},
  552. {BRCMS_SROM_LEDDC, 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC,
  553. 0xffff},
  554. {BRCMS_SROM_LEDDC, 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC,
  555. 0xffff},
  556. {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
  557. 0x01ff},
  558. {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
  559. 0xfe00},
  560. {BRCMS_SROM_TEMPSENSE_SLOPE, 0xffffff00, SRFL_PRHEX,
  561. SROM8_TS_SLP_OPT_CORRX, 0x00ff},
  562. {BRCMS_SROM_TEMPCORRX, 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
  563. 0xfc00},
  564. {BRCMS_SROM_TEMPSENSE_OPTION, 0xffffff00, SRFL_PRHEX,
  565. SROM8_TS_SLP_OPT_CORRX, 0x0300},
  566. {BRCMS_SROM_FREQOFFSET_CORR, 0xffffff00, SRFL_PRHEX,
  567. SROM8_FOC_HWIQ_IQSWP, 0x000f},
  568. {BRCMS_SROM_IQCAL_SWP_DIS, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
  569. 0x0010},
  570. {BRCMS_SROM_HW_IQCAL_EN, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
  571. 0x0020},
  572. {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA,
  573. 0x00ff},
  574. {BRCMS_SROM_CCK2GPO, 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
  575. {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
  576. {BRCMS_SROM_OFDM2GPO, 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
  577. {BRCMS_SROM_CONT, 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
  578. {BRCMS_SROM_OFDM5GPO, 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
  579. {BRCMS_SROM_CONT, 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
  580. {BRCMS_SROM_OFDM5GLPO, 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
  581. {BRCMS_SROM_CONT, 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
  582. {BRCMS_SROM_OFDM5GHPO, 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
  583. {BRCMS_SROM_CONT, 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
  584. {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
  585. {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
  586. {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
  587. {BRCMS_SROM_CONT, 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
  588. {BRCMS_SROM_OFDM5GLPO, 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
  589. {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
  590. {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
  591. {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
  592. {BRCMS_SROM_MCS2GPO0, 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
  593. {BRCMS_SROM_MCS2GPO1, 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
  594. {BRCMS_SROM_MCS2GPO2, 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
  595. {BRCMS_SROM_MCS2GPO3, 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
  596. {BRCMS_SROM_MCS2GPO4, 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
  597. {BRCMS_SROM_MCS2GPO5, 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
  598. {BRCMS_SROM_MCS2GPO6, 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
  599. {BRCMS_SROM_MCS2GPO7, 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
  600. {BRCMS_SROM_MCS5GPO0, 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
  601. {BRCMS_SROM_MCS5GPO1, 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
  602. {BRCMS_SROM_MCS5GPO2, 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
  603. {BRCMS_SROM_MCS5GPO3, 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
  604. {BRCMS_SROM_MCS5GPO4, 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
  605. {BRCMS_SROM_MCS5GPO5, 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
  606. {BRCMS_SROM_MCS5GPO6, 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
  607. {BRCMS_SROM_MCS5GPO7, 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
  608. {BRCMS_SROM_MCS5GLPO0, 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
  609. {BRCMS_SROM_MCS5GLPO1, 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
  610. {BRCMS_SROM_MCS5GLPO2, 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
  611. {BRCMS_SROM_MCS5GLPO3, 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
  612. {BRCMS_SROM_MCS5GLPO4, 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
  613. {BRCMS_SROM_MCS5GLPO5, 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
  614. {BRCMS_SROM_MCS5GLPO6, 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
  615. {BRCMS_SROM_MCS5GLPO7, 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
  616. {BRCMS_SROM_MCS5GHPO0, 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
  617. {BRCMS_SROM_MCS5GHPO1, 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
  618. {BRCMS_SROM_MCS5GHPO2, 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
  619. {BRCMS_SROM_MCS5GHPO3, 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
  620. {BRCMS_SROM_MCS5GHPO4, 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
  621. {BRCMS_SROM_MCS5GHPO5, 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
  622. {BRCMS_SROM_MCS5GHPO6, 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
  623. {BRCMS_SROM_MCS5GHPO7, 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
  624. {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
  625. {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
  626. {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
  627. {BRCMS_SROM_MCS2GPO3, 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
  628. {BRCMS_SROM_MCS2GPO4, 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
  629. {BRCMS_SROM_MCS2GPO5, 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
  630. {BRCMS_SROM_MCS2GPO6, 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
  631. {BRCMS_SROM_MCS2GPO7, 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
  632. {BRCMS_SROM_MCS5GPO0, 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
  633. {BRCMS_SROM_MCS5GPO1, 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
  634. {BRCMS_SROM_MCS5GPO2, 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
  635. {BRCMS_SROM_MCS5GPO3, 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
  636. {BRCMS_SROM_MCS5GPO4, 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
  637. {BRCMS_SROM_MCS5GPO5, 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
  638. {BRCMS_SROM_MCS5GPO6, 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
  639. {BRCMS_SROM_MCS5GPO7, 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
  640. {BRCMS_SROM_MCS5GLPO0, 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
  641. {BRCMS_SROM_MCS5GLPO1, 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
  642. {BRCMS_SROM_MCS5GLPO2, 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
  643. {BRCMS_SROM_MCS5GLPO3, 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
  644. {BRCMS_SROM_MCS5GLPO4, 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
  645. {BRCMS_SROM_MCS5GLPO5, 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
  646. {BRCMS_SROM_MCS5GLPO6, 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
  647. {BRCMS_SROM_MCS5GLPO7, 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
  648. {BRCMS_SROM_MCS5GHPO0, 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
  649. {BRCMS_SROM_MCS5GHPO1, 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
  650. {BRCMS_SROM_MCS5GHPO2, 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
  651. {BRCMS_SROM_MCS5GHPO3, 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
  652. {BRCMS_SROM_MCS5GHPO4, 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
  653. {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
  654. {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
  655. {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
  656. {BRCMS_SROM_CDDPO, 0x000000f0, 0, SROM4_CDDPO, 0xffff},
  657. {BRCMS_SROM_STBCPO, 0x000000f0, 0, SROM4_STBCPO, 0xffff},
  658. {BRCMS_SROM_BW40PO, 0x000000f0, 0, SROM4_BW40PO, 0xffff},
  659. {BRCMS_SROM_BWDUPPO, 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
  660. {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff},
  661. {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff},
  662. {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff},
  663. {BRCMS_SROM_BWDUPPO, 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
  664. /* power per rate from sromrev 9 */
  665. {BRCMS_SROM_CCKBW202GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
  666. {BRCMS_SROM_CCKBW20UL2GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
  667. {BRCMS_SROM_LEGOFDMBW202GPO, 0xfffffe00, SRFL_MORE,
  668. SROM9_2GPO_LOFDMBW20, 0xffff},
  669. {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
  670. {BRCMS_SROM_LEGOFDMBW20UL2GPO, 0xfffffe00, SRFL_MORE,
  671. SROM9_2GPO_LOFDMBW20UL, 0xffff},
  672. {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
  673. {BRCMS_SROM_LEGOFDMBW205GLPO, 0xfffffe00, SRFL_MORE,
  674. SROM9_5GLPO_LOFDMBW20, 0xffff},
  675. {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
  676. {BRCMS_SROM_LEGOFDMBW20UL5GLPO, 0xfffffe00, SRFL_MORE,
  677. SROM9_5GLPO_LOFDMBW20UL, 0xffff},
  678. {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
  679. {BRCMS_SROM_LEGOFDMBW205GMPO, 0xfffffe00, SRFL_MORE,
  680. SROM9_5GMPO_LOFDMBW20, 0xffff},
  681. {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
  682. {BRCMS_SROM_LEGOFDMBW20UL5GMPO, 0xfffffe00, SRFL_MORE,
  683. SROM9_5GMPO_LOFDMBW20UL, 0xffff},
  684. {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
  685. {BRCMS_SROM_LEGOFDMBW205GHPO, 0xfffffe00, SRFL_MORE,
  686. SROM9_5GHPO_LOFDMBW20, 0xffff},
  687. {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
  688. {BRCMS_SROM_LEGOFDMBW20UL5GHPO, 0xfffffe00, SRFL_MORE,
  689. SROM9_5GHPO_LOFDMBW20UL, 0xffff},
  690. {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
  691. {BRCMS_SROM_MCSBW202GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20,
  692. 0xffff},
  693. {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
  694. {BRCMS_SROM_MCSBW20UL2GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL,
  695. 0xffff},
  696. {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
  697. {BRCMS_SROM_MCSBW402GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40,
  698. 0xffff},
  699. {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
  700. {BRCMS_SROM_MCSBW205GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20,
  701. 0xffff},
  702. {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
  703. {BRCMS_SROM_MCSBW20UL5GLPO, 0xfffffe00, SRFL_MORE,
  704. SROM9_5GLPO_MCSBW20UL, 0xffff},
  705. {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
  706. {BRCMS_SROM_MCSBW405GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40,
  707. 0xffff},
  708. {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
  709. {BRCMS_SROM_MCSBW205GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20,
  710. 0xffff},
  711. {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
  712. {BRCMS_SROM_MCSBW20UL5GMPO, 0xfffffe00, SRFL_MORE,
  713. SROM9_5GMPO_MCSBW20UL, 0xffff},
  714. {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
  715. {BRCMS_SROM_MCSBW405GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40,
  716. 0xffff},
  717. {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
  718. {BRCMS_SROM_MCSBW205GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20,
  719. 0xffff},
  720. {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
  721. {BRCMS_SROM_MCSBW20UL5GHPO, 0xfffffe00, SRFL_MORE,
  722. SROM9_5GHPO_MCSBW20UL, 0xffff},
  723. {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
  724. {BRCMS_SROM_MCSBW405GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40,
  725. 0xffff},
  726. {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
  727. {BRCMS_SROM_MCS32PO, 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
  728. {BRCMS_SROM_LEGOFDM40DUPPO, 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
  729. {BRCMS_SROM_NULL, 0, 0, 0, 0}
  730. };
  731. static const struct brcms_sromvar perpath_pci_sromvars[] = {
  732. {BRCMS_SROM_MAXP2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
  733. {BRCMS_SROM_ITT2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
  734. {BRCMS_SROM_ITT5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
  735. {BRCMS_SROM_PA2GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
  736. {BRCMS_SROM_PA2GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
  737. {BRCMS_SROM_PA2GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
  738. {BRCMS_SROM_PA2GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
  739. {BRCMS_SROM_MAXP5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
  740. {BRCMS_SROM_MAXP5GHA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
  741. {BRCMS_SROM_MAXP5GLA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
  742. {BRCMS_SROM_PA5GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
  743. {BRCMS_SROM_PA5GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
  744. {BRCMS_SROM_PA5GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
  745. {BRCMS_SROM_PA5GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
  746. {BRCMS_SROM_PA5GLW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
  747. {BRCMS_SROM_PA5GLW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1,
  748. 0xffff},
  749. {BRCMS_SROM_PA5GLW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2,
  750. 0xffff},
  751. {BRCMS_SROM_PA5GLW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3,
  752. 0xffff},
  753. {BRCMS_SROM_PA5GHW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
  754. {BRCMS_SROM_PA5GHW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1,
  755. 0xffff},
  756. {BRCMS_SROM_PA5GHW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2,
  757. 0xffff},
  758. {BRCMS_SROM_PA5GHW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3,
  759. 0xffff},
  760. {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
  761. {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
  762. {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
  763. {BRCMS_SROM_PA2GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
  764. {BRCMS_SROM_PA2GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
  765. {BRCMS_SROM_PA2GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
  766. {BRCMS_SROM_MAXP5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
  767. {BRCMS_SROM_MAXP5GHA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
  768. {BRCMS_SROM_MAXP5GLA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
  769. {BRCMS_SROM_PA5GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
  770. {BRCMS_SROM_PA5GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
  771. {BRCMS_SROM_PA5GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
  772. {BRCMS_SROM_PA5GLW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
  773. {BRCMS_SROM_PA5GLW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1,
  774. 0xffff},
  775. {BRCMS_SROM_PA5GLW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2,
  776. 0xffff},
  777. {BRCMS_SROM_PA5GHW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
  778. {BRCMS_SROM_PA5GHW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1,
  779. 0xffff},
  780. {BRCMS_SROM_PA5GHW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2,
  781. 0xffff},
  782. {BRCMS_SROM_NULL, 0, 0, 0, 0}
  783. };
  784. /* crc table has the same contents for every device instance, so it can be
  785. * shared between devices. */
  786. static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE];
  787. static u16 __iomem *
  788. srom_window_address(struct si_pub *sih, u8 __iomem *curmap)
  789. {
  790. if (sih->ccrev < 32)
  791. return (u16 __iomem *)(curmap + PCI_BAR0_SPROM_OFFSET);
  792. if (sih->cccaps & CC_CAP_SROM)
  793. return (u16 __iomem *)
  794. (curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP);
  795. return NULL;
  796. }
  797. /* Parse SROM and create name=value pairs. 'srom' points to
  798. * the SROM word array. 'off' specifies the offset of the
  799. * first word 'srom' points to, which should be either 0 or
  800. * SROM3_SWRG_OFF (full SROM or software region).
  801. */
  802. static uint mask_shift(u16 mask)
  803. {
  804. uint i;
  805. for (i = 0; i < (sizeof(mask) << 3); i++) {
  806. if (mask & (1 << i))
  807. return i;
  808. }
  809. return 0;
  810. }
  811. static uint mask_width(u16 mask)
  812. {
  813. int i;
  814. for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
  815. if (mask & (1 << i))
  816. return (uint) (i - mask_shift(mask) + 1);
  817. }
  818. return 0;
  819. }
  820. static inline void ltoh16_buf(u16 *buf, unsigned int size)
  821. {
  822. size /= 2;
  823. while (size--)
  824. *(buf + size) = le16_to_cpu(*(__le16 *)(buf + size));
  825. }
  826. static inline void htol16_buf(u16 *buf, unsigned int size)
  827. {
  828. size /= 2;
  829. while (size--)
  830. *(__le16 *)(buf + size) = cpu_to_le16(*(buf + size));
  831. }
  832. /*
  833. * convert binary srom data into linked list of srom variable items.
  834. */
  835. static void
  836. _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
  837. {
  838. struct brcms_srom_list_head *entry;
  839. enum brcms_srom_id id;
  840. u16 w;
  841. u32 val;
  842. const struct brcms_sromvar *srv;
  843. uint width;
  844. uint flags;
  845. u32 sr = (1 << sromrev);
  846. /* first store the srom revision */
  847. entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL);
  848. entry->varid = BRCMS_SROM_REV;
  849. entry->var_type = BRCMS_SROM_UNUMBER;
  850. entry->uval = sromrev;
  851. list_add(&entry->var_list, var_list);
  852. for (srv = pci_sromvars; srv->varid != BRCMS_SROM_NULL; srv++) {
  853. enum brcms_srom_var_type type;
  854. u8 ea[ETH_ALEN];
  855. u8 extra_space = 0;
  856. if ((srv->revmask & sr) == 0)
  857. continue;
  858. flags = srv->flags;
  859. id = srv->varid;
  860. /* This entry is for mfgc only. Don't generate param for it, */
  861. if (flags & SRFL_NOVAR)
  862. continue;
  863. if (flags & SRFL_ETHADDR) {
  864. /*
  865. * stored in string format XX:XX:XX:XX:XX:XX (17 chars)
  866. */
  867. ea[0] = (srom[srv->off] >> 8) & 0xff;
  868. ea[1] = srom[srv->off] & 0xff;
  869. ea[2] = (srom[srv->off + 1] >> 8) & 0xff;
  870. ea[3] = srom[srv->off + 1] & 0xff;
  871. ea[4] = (srom[srv->off + 2] >> 8) & 0xff;
  872. ea[5] = srom[srv->off + 2] & 0xff;
  873. /* 17 characters + string terminator - union size */
  874. extra_space = 18 - sizeof(s32);
  875. type = BRCMS_SROM_STRING;
  876. } else {
  877. w = srom[srv->off];
  878. val = (w & srv->mask) >> mask_shift(srv->mask);
  879. width = mask_width(srv->mask);
  880. while (srv->flags & SRFL_MORE) {
  881. srv++;
  882. if (srv->off == 0)
  883. continue;
  884. w = srom[srv->off];
  885. val +=
  886. ((w & srv->mask) >> mask_shift(srv->
  887. mask)) <<
  888. width;
  889. width += mask_width(srv->mask);
  890. }
  891. if ((flags & SRFL_NOFFS)
  892. && ((int)val == (1 << width) - 1))
  893. continue;
  894. if (flags & SRFL_CCODE) {
  895. type = BRCMS_SROM_STRING;
  896. } else if (flags & SRFL_LEDDC) {
  897. /* LED Powersave duty cycle has to be scaled:
  898. *(oncount >> 24) (offcount >> 8)
  899. */
  900. u32 w32 = /* oncount */
  901. (((val >> 8) & 0xff) << 24) |
  902. /* offcount */
  903. (((val & 0xff)) << 8);
  904. type = BRCMS_SROM_UNUMBER;
  905. val = w32;
  906. } else if ((flags & SRFL_PRSIGN)
  907. && (val & (1 << (width - 1)))) {
  908. type = BRCMS_SROM_SNUMBER;
  909. val |= ~0 << width;
  910. } else
  911. type = BRCMS_SROM_UNUMBER;
  912. }
  913. entry = kzalloc(sizeof(struct brcms_srom_list_head) +
  914. extra_space, GFP_KERNEL);
  915. entry->varid = id;
  916. entry->var_type = type;
  917. if (flags & SRFL_ETHADDR) {
  918. snprintf(entry->buf, 18, "%pM", ea);
  919. } else if (flags & SRFL_CCODE) {
  920. if (val == 0)
  921. entry->buf[0] = '\0';
  922. else
  923. snprintf(entry->buf, 3, "%c%c",
  924. (val >> 8), (val & 0xff));
  925. } else {
  926. entry->uval = val;
  927. }
  928. list_add(&entry->var_list, var_list);
  929. }
  930. if (sromrev >= 4) {
  931. /* Do per-path variables */
  932. uint p, pb, psz;
  933. if (sromrev >= 8) {
  934. pb = SROM8_PATH0;
  935. psz = SROM8_PATH1 - SROM8_PATH0;
  936. } else {
  937. pb = SROM4_PATH0;
  938. psz = SROM4_PATH1 - SROM4_PATH0;
  939. }
  940. for (p = 0; p < MAX_PATH_SROM; p++) {
  941. for (srv = perpath_pci_sromvars;
  942. srv->varid != BRCMS_SROM_NULL; srv++) {
  943. if ((srv->revmask & sr) == 0)
  944. continue;
  945. if (srv->flags & SRFL_NOVAR)
  946. continue;
  947. w = srom[pb + srv->off];
  948. val = (w & srv->mask) >> mask_shift(srv->mask);
  949. width = mask_width(srv->mask);
  950. /* Cheating: no per-path var is more than
  951. * 1 word */
  952. if ((srv->flags & SRFL_NOFFS)
  953. && ((int)val == (1 << width) - 1))
  954. continue;
  955. entry =
  956. kzalloc(sizeof(struct brcms_srom_list_head),
  957. GFP_KERNEL);
  958. entry->varid = srv->varid+p;
  959. entry->var_type = BRCMS_SROM_UNUMBER;
  960. entry->uval = val;
  961. list_add(&entry->var_list, var_list);
  962. }
  963. pb += psz;
  964. }
  965. }
  966. }
  967. /*
  968. * Read in and validate sprom.
  969. * Return 0 on success, nonzero on error.
  970. */
  971. static int
  972. sprom_read_pci(struct si_pub *sih, u16 __iomem *sprom, uint wordoff,
  973. u16 *buf, uint nwords, bool check_crc)
  974. {
  975. int err = 0;
  976. uint i;
  977. /* read the sprom */
  978. for (i = 0; i < nwords; i++)
  979. buf[i] = R_REG(&sprom[wordoff + i]);
  980. if (check_crc) {
  981. if (buf[0] == 0xffff)
  982. /*
  983. * The hardware thinks that an srom that starts with
  984. * 0xffff is blank, regardless of the rest of the
  985. * content, so declare it bad.
  986. */
  987. return -ENODATA;
  988. /* fixup the endianness so crc8 will pass */
  989. htol16_buf(buf, nwords * 2);
  990. if (crc8(brcms_srom_crc8_table, (u8 *) buf, nwords * 2,
  991. CRC8_INIT_VALUE) !=
  992. CRC8_GOOD_VALUE(brcms_srom_crc8_table))
  993. /* DBG only pci always read srom4 first, then srom8/9 */
  994. err = -EIO;
  995. /* now correct the endianness of the byte array */
  996. ltoh16_buf(buf, nwords * 2);
  997. }
  998. return err;
  999. }
  1000. static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
  1001. {
  1002. u8 *otp;
  1003. uint sz = OTP_SZ_MAX / 2; /* size in words */
  1004. int err = 0;
  1005. otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
  1006. if (otp == NULL)
  1007. return -ENOMEM;
  1008. err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
  1009. memcpy(buf, otp, bufsz);
  1010. kfree(otp);
  1011. /* Check CRC */
  1012. if (buf[0] == 0xffff)
  1013. /* The hardware thinks that an srom that starts with 0xffff
  1014. * is blank, regardless of the rest of the content, so declare
  1015. * it bad.
  1016. */
  1017. return -ENODATA;
  1018. /* fixup the endianness so crc8 will pass */
  1019. htol16_buf(buf, bufsz);
  1020. if (crc8(brcms_srom_crc8_table, (u8 *) buf, SROM4_WORDS * 2,
  1021. CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table))
  1022. err = -EIO;
  1023. /* now correct the endianness of the byte array */
  1024. ltoh16_buf(buf, bufsz);
  1025. return err;
  1026. }
  1027. /*
  1028. * Initialize nonvolatile variable table from sprom.
  1029. * Return 0 on success, nonzero on error.
  1030. */
  1031. static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
  1032. {
  1033. u16 *srom;
  1034. u16 __iomem *sromwindow;
  1035. u8 sromrev = 0;
  1036. u32 sr;
  1037. int err = 0;
  1038. /*
  1039. * Apply CRC over SROM content regardless SROM is present or not.
  1040. */
  1041. srom = kmalloc(SROM_MAX, GFP_ATOMIC);
  1042. if (!srom)
  1043. return -ENOMEM;
  1044. sromwindow = srom_window_address(sih, curmap);
  1045. crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY);
  1046. if (ai_is_sprom_available(sih)) {
  1047. err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
  1048. true);
  1049. if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
  1050. (((sih->buscoretype == PCIE_CORE_ID)
  1051. && (sih->buscorerev >= 6))
  1052. || ((sih->buscoretype == PCI_CORE_ID)
  1053. && (sih->buscorerev >= 0xe)))) {
  1054. /* sromrev >= 4, read more */
  1055. err = sprom_read_pci(sih, sromwindow, 0, srom,
  1056. SROM4_WORDS, true);
  1057. sromrev = srom[SROM4_CRCREV] & 0xff;
  1058. } else if (err == 0) {
  1059. /* srom is good and is rev < 4 */
  1060. /* top word of sprom contains version and crc8 */
  1061. sromrev = srom[SROM_CRCREV] & 0xff;
  1062. /* bcm4401 sroms misprogrammed */
  1063. if (sromrev == 0x10)
  1064. sromrev = 1;
  1065. }
  1066. } else {
  1067. /* Use OTP if SPROM not available */
  1068. err = otp_read_pci(sih, srom, SROM_MAX);
  1069. if (err == 0)
  1070. /* OTP only contain SROM rev8/rev9 for now */
  1071. sromrev = srom[SROM4_CRCREV] & 0xff;
  1072. }
  1073. if (!err) {
  1074. struct si_info *sii = (struct si_info *)sih;
  1075. /* Bitmask for the sromrev */
  1076. sr = 1 << sromrev;
  1077. /*
  1078. * srom version check: Current valid versions: 1, 2, 3, 4, 5, 8,
  1079. * 9
  1080. */
  1081. if ((sr & 0x33e) == 0) {
  1082. err = -EINVAL;
  1083. goto errout;
  1084. }
  1085. INIT_LIST_HEAD(&sii->var_list);
  1086. /* parse SROM into name=value pairs. */
  1087. _initvars_srom_pci(sromrev, srom, &sii->var_list);
  1088. }
  1089. errout:
  1090. kfree(srom);
  1091. return err;
  1092. }
  1093. void srom_free_vars(struct si_pub *sih)
  1094. {
  1095. struct si_info *sii;
  1096. struct brcms_srom_list_head *entry, *next;
  1097. sii = (struct si_info *)sih;
  1098. list_for_each_entry_safe(entry, next, &sii->var_list, var_list) {
  1099. list_del(&entry->var_list);
  1100. kfree(entry);
  1101. }
  1102. }
  1103. /*
  1104. * Initialize local vars from the right source for this platform.
  1105. * Return 0 on success, nonzero on error.
  1106. */
  1107. int srom_var_init(struct si_pub *sih, void __iomem *curmap)
  1108. {
  1109. uint len;
  1110. len = 0;
  1111. if (curmap != NULL)
  1112. return initvars_srom_pci(sih, curmap);
  1113. return -EINVAL;
  1114. }
  1115. /*
  1116. * Search the name=value vars for a specific one and return its value.
  1117. * Returns NULL if not found.
  1118. */
  1119. char *getvar(struct si_pub *sih, enum brcms_srom_id id)
  1120. {
  1121. struct si_info *sii;
  1122. struct brcms_srom_list_head *entry;
  1123. sii = (struct si_info *)sih;
  1124. list_for_each_entry(entry, &sii->var_list, var_list)
  1125. if (entry->varid == id)
  1126. return &entry->buf[0];
  1127. /* nothing found */
  1128. return NULL;
  1129. }
  1130. /*
  1131. * Search the vars for a specific one and return its value as
  1132. * an integer. Returns 0 if not found.-
  1133. */
  1134. int getintvar(struct si_pub *sih, enum brcms_srom_id id)
  1135. {
  1136. struct si_info *sii;
  1137. struct brcms_srom_list_head *entry;
  1138. unsigned long res;
  1139. sii = (struct si_info *)sih;
  1140. list_for_each_entry(entry, &sii->var_list, var_list)
  1141. if (entry->varid == id) {
  1142. if (entry->var_type == BRCMS_SROM_SNUMBER ||
  1143. entry->var_type == BRCMS_SROM_UNUMBER)
  1144. return (int)entry->sval;
  1145. else if (!kstrtoul(&entry->buf[0], 0, &res))
  1146. return (int)res;
  1147. }
  1148. return 0;
  1149. }