cs35l41-lib.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // cs35l41-lib.c -- CS35L41 Common functions for HDA and ASoC Audio drivers
  4. //
  5. // Copyright 2017-2021 Cirrus Logic, Inc.
  6. //
  7. // Author: David Rhodes <[email protected]>
  8. // Author: Lucas Tanure <[email protected]>
  9. #include <linux/dev_printk.h>
  10. #include <linux/module.h>
  11. #include <linux/regmap.h>
  12. #include <linux/regulator/consumer.h>
  13. #include <linux/slab.h>
  14. #include <linux/firmware/cirrus/wmfw.h>
  15. #include <sound/cs35l41.h>
  16. static const struct reg_default cs35l41_reg[] = {
  17. { CS35L41_PWR_CTRL1, 0x00000000 },
  18. { CS35L41_PWR_CTRL2, 0x00000000 },
  19. { CS35L41_PWR_CTRL3, 0x01000010 },
  20. { CS35L41_GPIO_PAD_CONTROL, 0x00000000 },
  21. { CS35L41_GLOBAL_CLK_CTRL, 0x00000003 },
  22. { CS35L41_TST_FS_MON0, 0x00020016 },
  23. { CS35L41_BSTCVRT_COEFF, 0x00002424 },
  24. { CS35L41_BSTCVRT_SLOPE_LBST, 0x00007500 },
  25. { CS35L41_BSTCVRT_PEAK_CUR, 0x0000004A },
  26. { CS35L41_SP_ENABLES, 0x00000000 },
  27. { CS35L41_SP_RATE_CTRL, 0x00000028 },
  28. { CS35L41_SP_FORMAT, 0x18180200 },
  29. { CS35L41_SP_HIZ_CTRL, 0x00000002 },
  30. { CS35L41_SP_FRAME_TX_SLOT, 0x03020100 },
  31. { CS35L41_SP_FRAME_RX_SLOT, 0x00000100 },
  32. { CS35L41_SP_TX_WL, 0x00000018 },
  33. { CS35L41_SP_RX_WL, 0x00000018 },
  34. { CS35L41_DAC_PCM1_SRC, 0x00000008 },
  35. { CS35L41_ASP_TX1_SRC, 0x00000018 },
  36. { CS35L41_ASP_TX2_SRC, 0x00000019 },
  37. { CS35L41_ASP_TX3_SRC, 0x00000000 },
  38. { CS35L41_ASP_TX4_SRC, 0x00000000 },
  39. { CS35L41_DSP1_RX1_SRC, 0x00000008 },
  40. { CS35L41_DSP1_RX2_SRC, 0x00000009 },
  41. { CS35L41_DSP1_RX3_SRC, 0x00000018 },
  42. { CS35L41_DSP1_RX4_SRC, 0x00000019 },
  43. { CS35L41_DSP1_RX5_SRC, 0x00000020 },
  44. { CS35L41_DSP1_RX6_SRC, 0x00000021 },
  45. { CS35L41_DSP1_RX7_SRC, 0x0000003A },
  46. { CS35L41_DSP1_RX8_SRC, 0x0000003B },
  47. { CS35L41_NGATE1_SRC, 0x00000008 },
  48. { CS35L41_NGATE2_SRC, 0x00000009 },
  49. { CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 },
  50. { CS35L41_CLASSH_CFG, 0x000B0405 },
  51. { CS35L41_WKFET_CFG, 0x00000111 },
  52. { CS35L41_NG_CFG, 0x00000033 },
  53. { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
  54. { CS35L41_IRQ1_MASK1, 0xFFFFFFFF },
  55. { CS35L41_IRQ1_MASK2, 0xFFFFFFFF },
  56. { CS35L41_IRQ1_MASK3, 0xFFFF87FF },
  57. { CS35L41_IRQ1_MASK4, 0xFEFFFFFF },
  58. { CS35L41_GPIO1_CTRL1, 0x81000001 },
  59. { CS35L41_GPIO2_CTRL1, 0x81000001 },
  60. { CS35L41_MIXER_NGATE_CFG, 0x00000000 },
  61. { CS35L41_MIXER_NGATE_CH1_CFG, 0x00000303 },
  62. { CS35L41_MIXER_NGATE_CH2_CFG, 0x00000303 },
  63. { CS35L41_DSP1_CCM_CORE_CTRL, 0x00000101 },
  64. };
  65. static bool cs35l41_readable_reg(struct device *dev, unsigned int reg)
  66. {
  67. switch (reg) {
  68. case CS35L41_DEVID:
  69. case CS35L41_REVID:
  70. case CS35L41_FABID:
  71. case CS35L41_RELID:
  72. case CS35L41_OTPID:
  73. case CS35L41_TEST_KEY_CTL:
  74. case CS35L41_USER_KEY_CTL:
  75. case CS35L41_OTP_CTRL0:
  76. case CS35L41_OTP_CTRL3:
  77. case CS35L41_OTP_CTRL4:
  78. case CS35L41_OTP_CTRL5:
  79. case CS35L41_OTP_CTRL6:
  80. case CS35L41_OTP_CTRL7:
  81. case CS35L41_OTP_CTRL8:
  82. case CS35L41_PWR_CTRL1:
  83. case CS35L41_PWR_CTRL2:
  84. case CS35L41_PWR_CTRL3:
  85. case CS35L41_CTRL_OVRRIDE:
  86. case CS35L41_AMP_OUT_MUTE:
  87. case CS35L41_PROTECT_REL_ERR_IGN:
  88. case CS35L41_GPIO_PAD_CONTROL:
  89. case CS35L41_JTAG_CONTROL:
  90. case CS35L41_PWRMGT_CTL:
  91. case CS35L41_WAKESRC_CTL:
  92. case CS35L41_PWRMGT_STS:
  93. case CS35L41_PLL_CLK_CTRL:
  94. case CS35L41_DSP_CLK_CTRL:
  95. case CS35L41_GLOBAL_CLK_CTRL:
  96. case CS35L41_DATA_FS_SEL:
  97. case CS35L41_TST_FS_MON0:
  98. case CS35L41_MDSYNC_EN:
  99. case CS35L41_MDSYNC_TX_ID:
  100. case CS35L41_MDSYNC_PWR_CTRL:
  101. case CS35L41_MDSYNC_DATA_TX:
  102. case CS35L41_MDSYNC_TX_STATUS:
  103. case CS35L41_MDSYNC_DATA_RX:
  104. case CS35L41_MDSYNC_RX_STATUS:
  105. case CS35L41_MDSYNC_ERR_STATUS:
  106. case CS35L41_MDSYNC_SYNC_PTE2:
  107. case CS35L41_MDSYNC_SYNC_PTE3:
  108. case CS35L41_MDSYNC_SYNC_MSM_STATUS:
  109. case CS35L41_BSTCVRT_VCTRL1:
  110. case CS35L41_BSTCVRT_VCTRL2:
  111. case CS35L41_BSTCVRT_PEAK_CUR:
  112. case CS35L41_BSTCVRT_SFT_RAMP:
  113. case CS35L41_BSTCVRT_COEFF:
  114. case CS35L41_BSTCVRT_SLOPE_LBST:
  115. case CS35L41_BSTCVRT_SW_FREQ:
  116. case CS35L41_BSTCVRT_DCM_CTRL:
  117. case CS35L41_BSTCVRT_DCM_MODE_FORCE:
  118. case CS35L41_BSTCVRT_OVERVOLT_CTRL:
  119. case CS35L41_VI_VOL_POL:
  120. case CS35L41_DTEMP_WARN_THLD:
  121. case CS35L41_DTEMP_CFG:
  122. case CS35L41_DTEMP_EN:
  123. case CS35L41_VPVBST_FS_SEL:
  124. case CS35L41_SP_ENABLES:
  125. case CS35L41_SP_RATE_CTRL:
  126. case CS35L41_SP_FORMAT:
  127. case CS35L41_SP_HIZ_CTRL:
  128. case CS35L41_SP_FRAME_TX_SLOT:
  129. case CS35L41_SP_FRAME_RX_SLOT:
  130. case CS35L41_SP_TX_WL:
  131. case CS35L41_SP_RX_WL:
  132. case CS35L41_DAC_PCM1_SRC:
  133. case CS35L41_ASP_TX1_SRC:
  134. case CS35L41_ASP_TX2_SRC:
  135. case CS35L41_ASP_TX3_SRC:
  136. case CS35L41_ASP_TX4_SRC:
  137. case CS35L41_DSP1_RX1_SRC:
  138. case CS35L41_DSP1_RX2_SRC:
  139. case CS35L41_DSP1_RX3_SRC:
  140. case CS35L41_DSP1_RX4_SRC:
  141. case CS35L41_DSP1_RX5_SRC:
  142. case CS35L41_DSP1_RX6_SRC:
  143. case CS35L41_DSP1_RX7_SRC:
  144. case CS35L41_DSP1_RX8_SRC:
  145. case CS35L41_NGATE1_SRC:
  146. case CS35L41_NGATE2_SRC:
  147. case CS35L41_AMP_DIG_VOL_CTRL:
  148. case CS35L41_VPBR_CFG:
  149. case CS35L41_VBBR_CFG:
  150. case CS35L41_VPBR_STATUS:
  151. case CS35L41_VBBR_STATUS:
  152. case CS35L41_OVERTEMP_CFG:
  153. case CS35L41_AMP_ERR_VOL:
  154. case CS35L41_VOL_STATUS_TO_DSP:
  155. case CS35L41_CLASSH_CFG:
  156. case CS35L41_WKFET_CFG:
  157. case CS35L41_NG_CFG:
  158. case CS35L41_AMP_GAIN_CTRL:
  159. case CS35L41_DAC_MSM_CFG:
  160. case CS35L41_IRQ1_CFG:
  161. case CS35L41_IRQ1_STATUS:
  162. case CS35L41_IRQ1_STATUS1:
  163. case CS35L41_IRQ1_STATUS2:
  164. case CS35L41_IRQ1_STATUS3:
  165. case CS35L41_IRQ1_STATUS4:
  166. case CS35L41_IRQ1_RAW_STATUS1:
  167. case CS35L41_IRQ1_RAW_STATUS2:
  168. case CS35L41_IRQ1_RAW_STATUS3:
  169. case CS35L41_IRQ1_RAW_STATUS4:
  170. case CS35L41_IRQ1_MASK1:
  171. case CS35L41_IRQ1_MASK2:
  172. case CS35L41_IRQ1_MASK3:
  173. case CS35L41_IRQ1_MASK4:
  174. case CS35L41_IRQ1_FRC1:
  175. case CS35L41_IRQ1_FRC2:
  176. case CS35L41_IRQ1_FRC3:
  177. case CS35L41_IRQ1_FRC4:
  178. case CS35L41_IRQ1_EDGE1:
  179. case CS35L41_IRQ1_EDGE4:
  180. case CS35L41_IRQ1_POL1:
  181. case CS35L41_IRQ1_POL2:
  182. case CS35L41_IRQ1_POL3:
  183. case CS35L41_IRQ1_POL4:
  184. case CS35L41_IRQ1_DB3:
  185. case CS35L41_IRQ2_CFG:
  186. case CS35L41_IRQ2_STATUS:
  187. case CS35L41_IRQ2_STATUS1:
  188. case CS35L41_IRQ2_STATUS2:
  189. case CS35L41_IRQ2_STATUS3:
  190. case CS35L41_IRQ2_STATUS4:
  191. case CS35L41_IRQ2_RAW_STATUS1:
  192. case CS35L41_IRQ2_RAW_STATUS2:
  193. case CS35L41_IRQ2_RAW_STATUS3:
  194. case CS35L41_IRQ2_RAW_STATUS4:
  195. case CS35L41_IRQ2_MASK1:
  196. case CS35L41_IRQ2_MASK2:
  197. case CS35L41_IRQ2_MASK3:
  198. case CS35L41_IRQ2_MASK4:
  199. case CS35L41_IRQ2_FRC1:
  200. case CS35L41_IRQ2_FRC2:
  201. case CS35L41_IRQ2_FRC3:
  202. case CS35L41_IRQ2_FRC4:
  203. case CS35L41_IRQ2_EDGE1:
  204. case CS35L41_IRQ2_EDGE4:
  205. case CS35L41_IRQ2_POL1:
  206. case CS35L41_IRQ2_POL2:
  207. case CS35L41_IRQ2_POL3:
  208. case CS35L41_IRQ2_POL4:
  209. case CS35L41_IRQ2_DB3:
  210. case CS35L41_GPIO_STATUS1:
  211. case CS35L41_GPIO1_CTRL1:
  212. case CS35L41_GPIO2_CTRL1:
  213. case CS35L41_MIXER_NGATE_CFG:
  214. case CS35L41_MIXER_NGATE_CH1_CFG:
  215. case CS35L41_MIXER_NGATE_CH2_CFG:
  216. case CS35L41_DSP_MBOX_1 ... CS35L41_DSP_VIRT2_MBOX_8:
  217. case CS35L41_CLOCK_DETECT_1:
  218. case CS35L41_DIE_STS1:
  219. case CS35L41_DIE_STS2:
  220. case CS35L41_TEMP_CAL1:
  221. case CS35L41_TEMP_CAL2:
  222. case CS35L41_DSP1_TIMESTAMP_COUNT:
  223. case CS35L41_DSP1_SYS_ID:
  224. case CS35L41_DSP1_SYS_VERSION:
  225. case CS35L41_DSP1_SYS_CORE_ID:
  226. case CS35L41_DSP1_SYS_AHB_ADDR:
  227. case CS35L41_DSP1_SYS_XSRAM_SIZE:
  228. case CS35L41_DSP1_SYS_YSRAM_SIZE:
  229. case CS35L41_DSP1_SYS_PSRAM_SIZE:
  230. case CS35L41_DSP1_SYS_PM_BOOT_SIZE:
  231. case CS35L41_DSP1_SYS_FEATURES:
  232. case CS35L41_DSP1_SYS_FIR_FILTERS:
  233. case CS35L41_DSP1_SYS_LMS_FILTERS:
  234. case CS35L41_DSP1_SYS_XM_BANK_SIZE:
  235. case CS35L41_DSP1_SYS_YM_BANK_SIZE:
  236. case CS35L41_DSP1_SYS_PM_BANK_SIZE:
  237. case CS35L41_DSP1_RX1_RATE:
  238. case CS35L41_DSP1_RX2_RATE:
  239. case CS35L41_DSP1_RX3_RATE:
  240. case CS35L41_DSP1_RX4_RATE:
  241. case CS35L41_DSP1_RX5_RATE:
  242. case CS35L41_DSP1_RX6_RATE:
  243. case CS35L41_DSP1_RX7_RATE:
  244. case CS35L41_DSP1_RX8_RATE:
  245. case CS35L41_DSP1_TX1_RATE:
  246. case CS35L41_DSP1_TX2_RATE:
  247. case CS35L41_DSP1_TX3_RATE:
  248. case CS35L41_DSP1_TX4_RATE:
  249. case CS35L41_DSP1_TX5_RATE:
  250. case CS35L41_DSP1_TX6_RATE:
  251. case CS35L41_DSP1_TX7_RATE:
  252. case CS35L41_DSP1_TX8_RATE:
  253. case CS35L41_DSP1_SCRATCH1:
  254. case CS35L41_DSP1_SCRATCH2:
  255. case CS35L41_DSP1_SCRATCH3:
  256. case CS35L41_DSP1_SCRATCH4:
  257. case CS35L41_DSP1_CCM_CORE_CTRL:
  258. case CS35L41_DSP1_CCM_CLK_OVERRIDE:
  259. case CS35L41_DSP1_XM_MSTR_EN:
  260. case CS35L41_DSP1_XM_CORE_PRI:
  261. case CS35L41_DSP1_XM_AHB_PACK_PL_PRI:
  262. case CS35L41_DSP1_XM_AHB_UP_PL_PRI:
  263. case CS35L41_DSP1_XM_ACCEL_PL0_PRI:
  264. case CS35L41_DSP1_XM_NPL0_PRI:
  265. case CS35L41_DSP1_YM_MSTR_EN:
  266. case CS35L41_DSP1_YM_CORE_PRI:
  267. case CS35L41_DSP1_YM_AHB_PACK_PL_PRI:
  268. case CS35L41_DSP1_YM_AHB_UP_PL_PRI:
  269. case CS35L41_DSP1_YM_ACCEL_PL0_PRI:
  270. case CS35L41_DSP1_YM_NPL0_PRI:
  271. case CS35L41_DSP1_MPU_XM_ACCESS0:
  272. case CS35L41_DSP1_MPU_YM_ACCESS0:
  273. case CS35L41_DSP1_MPU_WNDW_ACCESS0:
  274. case CS35L41_DSP1_MPU_XREG_ACCESS0:
  275. case CS35L41_DSP1_MPU_YREG_ACCESS0:
  276. case CS35L41_DSP1_MPU_XM_ACCESS1:
  277. case CS35L41_DSP1_MPU_YM_ACCESS1:
  278. case CS35L41_DSP1_MPU_WNDW_ACCESS1:
  279. case CS35L41_DSP1_MPU_XREG_ACCESS1:
  280. case CS35L41_DSP1_MPU_YREG_ACCESS1:
  281. case CS35L41_DSP1_MPU_XM_ACCESS2:
  282. case CS35L41_DSP1_MPU_YM_ACCESS2:
  283. case CS35L41_DSP1_MPU_WNDW_ACCESS2:
  284. case CS35L41_DSP1_MPU_XREG_ACCESS2:
  285. case CS35L41_DSP1_MPU_YREG_ACCESS2:
  286. case CS35L41_DSP1_MPU_XM_ACCESS3:
  287. case CS35L41_DSP1_MPU_YM_ACCESS3:
  288. case CS35L41_DSP1_MPU_WNDW_ACCESS3:
  289. case CS35L41_DSP1_MPU_XREG_ACCESS3:
  290. case CS35L41_DSP1_MPU_YREG_ACCESS3:
  291. case CS35L41_DSP1_MPU_XM_VIO_ADDR:
  292. case CS35L41_DSP1_MPU_XM_VIO_STATUS:
  293. case CS35L41_DSP1_MPU_YM_VIO_ADDR:
  294. case CS35L41_DSP1_MPU_YM_VIO_STATUS:
  295. case CS35L41_DSP1_MPU_PM_VIO_ADDR:
  296. case CS35L41_DSP1_MPU_PM_VIO_STATUS:
  297. case CS35L41_DSP1_MPU_LOCK_CONFIG:
  298. case CS35L41_DSP1_MPU_WDT_RST_CTRL:
  299. case CS35L41_OTP_TRIM_1:
  300. case CS35L41_OTP_TRIM_2:
  301. case CS35L41_OTP_TRIM_3:
  302. case CS35L41_OTP_TRIM_4:
  303. case CS35L41_OTP_TRIM_5:
  304. case CS35L41_OTP_TRIM_6:
  305. case CS35L41_OTP_TRIM_7:
  306. case CS35L41_OTP_TRIM_8:
  307. case CS35L41_OTP_TRIM_9:
  308. case CS35L41_OTP_TRIM_10:
  309. case CS35L41_OTP_TRIM_11:
  310. case CS35L41_OTP_TRIM_12:
  311. case CS35L41_OTP_TRIM_13:
  312. case CS35L41_OTP_TRIM_14:
  313. case CS35L41_OTP_TRIM_15:
  314. case CS35L41_OTP_TRIM_16:
  315. case CS35L41_OTP_TRIM_17:
  316. case CS35L41_OTP_TRIM_18:
  317. case CS35L41_OTP_TRIM_19:
  318. case CS35L41_OTP_TRIM_20:
  319. case CS35L41_OTP_TRIM_21:
  320. case CS35L41_OTP_TRIM_22:
  321. case CS35L41_OTP_TRIM_23:
  322. case CS35L41_OTP_TRIM_24:
  323. case CS35L41_OTP_TRIM_25:
  324. case CS35L41_OTP_TRIM_26:
  325. case CS35L41_OTP_TRIM_27:
  326. case CS35L41_OTP_TRIM_28:
  327. case CS35L41_OTP_TRIM_29:
  328. case CS35L41_OTP_TRIM_30:
  329. case CS35L41_OTP_TRIM_31:
  330. case CS35L41_OTP_TRIM_32:
  331. case CS35L41_OTP_TRIM_33:
  332. case CS35L41_OTP_TRIM_34:
  333. case CS35L41_OTP_TRIM_35:
  334. case CS35L41_OTP_TRIM_36:
  335. case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
  336. case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068:
  337. case CS35L41_DSP1_XMEM_UNPACK32_0 ... CS35L41_DSP1_XMEM_UNPACK32_2046:
  338. case CS35L41_DSP1_XMEM_UNPACK24_0 ... CS35L41_DSP1_XMEM_UNPACK24_4093:
  339. case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532:
  340. case CS35L41_DSP1_YMEM_UNPACK32_0 ... CS35L41_DSP1_YMEM_UNPACK32_1022:
  341. case CS35L41_DSP1_YMEM_UNPACK24_0 ... CS35L41_DSP1_YMEM_UNPACK24_2045:
  342. case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114:
  343. /*test regs*/
  344. case CS35L41_PLL_OVR:
  345. case CS35L41_BST_TEST_DUTY:
  346. case CS35L41_DIGPWM_IOCTRL:
  347. return true;
  348. default:
  349. return false;
  350. }
  351. }
  352. static bool cs35l41_precious_reg(struct device *dev, unsigned int reg)
  353. {
  354. switch (reg) {
  355. case CS35L41_TEST_KEY_CTL:
  356. case CS35L41_USER_KEY_CTL:
  357. case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
  358. case CS35L41_TST_FS_MON0:
  359. case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068:
  360. case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532:
  361. case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114:
  362. return true;
  363. default:
  364. return false;
  365. }
  366. }
  367. static bool cs35l41_volatile_reg(struct device *dev, unsigned int reg)
  368. {
  369. switch (reg) {
  370. case CS35L41_DEVID:
  371. case CS35L41_SFT_RESET:
  372. case CS35L41_FABID:
  373. case CS35L41_REVID:
  374. case CS35L41_OTPID:
  375. case CS35L41_TEST_KEY_CTL:
  376. case CS35L41_USER_KEY_CTL:
  377. case CS35L41_PWRMGT_CTL:
  378. case CS35L41_WAKESRC_CTL:
  379. case CS35L41_PWRMGT_STS:
  380. case CS35L41_DTEMP_EN:
  381. case CS35L41_IRQ1_STATUS:
  382. case CS35L41_IRQ1_STATUS1:
  383. case CS35L41_IRQ1_STATUS2:
  384. case CS35L41_IRQ1_STATUS3:
  385. case CS35L41_IRQ1_STATUS4:
  386. case CS35L41_IRQ1_RAW_STATUS1:
  387. case CS35L41_IRQ1_RAW_STATUS2:
  388. case CS35L41_IRQ1_RAW_STATUS3:
  389. case CS35L41_IRQ1_RAW_STATUS4:
  390. case CS35L41_IRQ2_STATUS:
  391. case CS35L41_IRQ2_STATUS1:
  392. case CS35L41_IRQ2_STATUS2:
  393. case CS35L41_IRQ2_STATUS3:
  394. case CS35L41_IRQ2_STATUS4:
  395. case CS35L41_IRQ2_RAW_STATUS1:
  396. case CS35L41_IRQ2_RAW_STATUS2:
  397. case CS35L41_IRQ2_RAW_STATUS3:
  398. case CS35L41_IRQ2_RAW_STATUS4:
  399. case CS35L41_GPIO_STATUS1:
  400. case CS35L41_DSP_MBOX_1 ... CS35L41_DSP_VIRT2_MBOX_8:
  401. case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068:
  402. case CS35L41_DSP1_XMEM_UNPACK32_0 ... CS35L41_DSP1_XMEM_UNPACK32_2046:
  403. case CS35L41_DSP1_XMEM_UNPACK24_0 ... CS35L41_DSP1_XMEM_UNPACK24_4093:
  404. case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532:
  405. case CS35L41_DSP1_YMEM_UNPACK32_0 ... CS35L41_DSP1_YMEM_UNPACK32_1022:
  406. case CS35L41_DSP1_YMEM_UNPACK24_0 ... CS35L41_DSP1_YMEM_UNPACK24_2045:
  407. case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114:
  408. case CS35L41_DSP1_SCRATCH1:
  409. case CS35L41_DSP1_SCRATCH2:
  410. case CS35L41_DSP1_SCRATCH3:
  411. case CS35L41_DSP1_SCRATCH4:
  412. case CS35L41_DSP1_CCM_CLK_OVERRIDE ... CS35L41_DSP1_WDT_STATUS:
  413. case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
  414. return true;
  415. default:
  416. return false;
  417. }
  418. }
  419. static const struct cs35l41_otp_packed_element_t otp_map_1[] = {
  420. /* addr shift size */
  421. { 0x00002030, 0, 4 }, /*TRIM_OSC_FREQ_TRIM*/
  422. { 0x00002030, 7, 1 }, /*TRIM_OSC_TRIM_DONE*/
  423. { 0x0000208c, 24, 6 }, /*TST_DIGREG_VREF_TRIM*/
  424. { 0x00002090, 14, 4 }, /*TST_REF_TRIM*/
  425. { 0x00002090, 10, 4 }, /*TST_REF_TEMPCO_TRIM*/
  426. { 0x0000300C, 11, 4 }, /*PLL_LDOA_TST_VREF_TRIM*/
  427. { 0x0000394C, 23, 2 }, /*BST_ATEST_CM_VOFF*/
  428. { 0x00003950, 0, 7 }, /*BST_ATRIM_IADC_OFFSET*/
  429. { 0x00003950, 8, 7 }, /*BST_ATRIM_IADC_GAIN1*/
  430. { 0x00003950, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET1*/
  431. { 0x00003950, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN1*/
  432. { 0x00003954, 0, 7 }, /*BST_ATRIM_IADC_OFFSET2*/
  433. { 0x00003954, 8, 7 }, /*BST_ATRIM_IADC_GAIN2*/
  434. { 0x00003954, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET2*/
  435. { 0x00003954, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN2*/
  436. { 0x00003958, 0, 7 }, /*BST_ATRIM_IADC_OFFSET3*/
  437. { 0x00003958, 8, 7 }, /*BST_ATRIM_IADC_GAIN3*/
  438. { 0x00003958, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET3*/
  439. { 0x00003958, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN3*/
  440. { 0x0000395C, 0, 7 }, /*BST_ATRIM_IADC_OFFSET4*/
  441. { 0x0000395C, 8, 7 }, /*BST_ATRIM_IADC_GAIN4*/
  442. { 0x0000395C, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET4*/
  443. { 0x0000395C, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN4*/
  444. { 0x0000416C, 0, 8 }, /*VMON_GAIN_OTP_VAL*/
  445. { 0x00004160, 0, 7 }, /*VMON_OFFSET_OTP_VAL*/
  446. { 0x0000416C, 8, 8 }, /*IMON_GAIN_OTP_VAL*/
  447. { 0x00004160, 16, 10 }, /*IMON_OFFSET_OTP_VAL*/
  448. { 0x0000416C, 16, 12 }, /*VMON_CM_GAIN_OTP_VAL*/
  449. { 0x0000416C, 28, 1 }, /*VMON_CM_GAIN_SIGN_OTP_VAL*/
  450. { 0x00004170, 0, 6 }, /*IMON_CAL_TEMPCO_OTP_VAL*/
  451. { 0x00004170, 6, 1 }, /*IMON_CAL_TEMPCO_SIGN_OTP*/
  452. { 0x00004170, 8, 6 }, /*IMON_CAL_TEMPCO2_OTP_VAL*/
  453. { 0x00004170, 14, 1 }, /*IMON_CAL_TEMPCO2_DN_UPB_OTP_VAL*/
  454. { 0x00004170, 16, 9 }, /*IMON_CAL_TEMPCO_TBASE_OTP_VAL*/
  455. { 0x00004360, 0, 5 }, /*TEMP_GAIN_OTP_VAL*/
  456. { 0x00004360, 6, 9 }, /*TEMP_OFFSET_OTP_VAL*/
  457. { 0x00004448, 0, 8 }, /*VP_SARADC_OFFSET*/
  458. { 0x00004448, 8, 8 }, /*VP_GAIN_INDEX*/
  459. { 0x00004448, 16, 8 }, /*VBST_SARADC_OFFSET*/
  460. { 0x00004448, 24, 8 }, /*VBST_GAIN_INDEX*/
  461. { 0x0000444C, 0, 3 }, /*ANA_SELINVREF*/
  462. { 0x00006E30, 0, 5 }, /*GAIN_ERR_COEFF_0*/
  463. { 0x00006E30, 8, 5 }, /*GAIN_ERR_COEFF_1*/
  464. { 0x00006E30, 16, 5 }, /*GAIN_ERR_COEFF_2*/
  465. { 0x00006E30, 24, 5 }, /*GAIN_ERR_COEFF_3*/
  466. { 0x00006E34, 0, 5 }, /*GAIN_ERR_COEFF_4*/
  467. { 0x00006E34, 8, 5 }, /*GAIN_ERR_COEFF_5*/
  468. { 0x00006E34, 16, 5 }, /*GAIN_ERR_COEFF_6*/
  469. { 0x00006E34, 24, 5 }, /*GAIN_ERR_COEFF_7*/
  470. { 0x00006E38, 0, 5 }, /*GAIN_ERR_COEFF_8*/
  471. { 0x00006E38, 8, 5 }, /*GAIN_ERR_COEFF_9*/
  472. { 0x00006E38, 16, 5 }, /*GAIN_ERR_COEFF_10*/
  473. { 0x00006E38, 24, 5 }, /*GAIN_ERR_COEFF_11*/
  474. { 0x00006E3C, 0, 5 }, /*GAIN_ERR_COEFF_12*/
  475. { 0x00006E3C, 8, 5 }, /*GAIN_ERR_COEFF_13*/
  476. { 0x00006E3C, 16, 5 }, /*GAIN_ERR_COEFF_14*/
  477. { 0x00006E3C, 24, 5 }, /*GAIN_ERR_COEFF_15*/
  478. { 0x00006E40, 0, 5 }, /*GAIN_ERR_COEFF_16*/
  479. { 0x00006E40, 8, 5 }, /*GAIN_ERR_COEFF_17*/
  480. { 0x00006E40, 16, 5 }, /*GAIN_ERR_COEFF_18*/
  481. { 0x00006E40, 24, 5 }, /*GAIN_ERR_COEFF_19*/
  482. { 0x00006E44, 0, 5 }, /*GAIN_ERR_COEFF_20*/
  483. { 0x00006E48, 0, 10 }, /*VOFF_GAIN_0*/
  484. { 0x00006E48, 10, 10 }, /*VOFF_GAIN_1*/
  485. { 0x00006E48, 20, 10 }, /*VOFF_GAIN_2*/
  486. { 0x00006E4C, 0, 10 }, /*VOFF_GAIN_3*/
  487. { 0x00006E4C, 10, 10 }, /*VOFF_GAIN_4*/
  488. { 0x00006E4C, 20, 10 }, /*VOFF_GAIN_5*/
  489. { 0x00006E50, 0, 10 }, /*VOFF_GAIN_6*/
  490. { 0x00006E50, 10, 10 }, /*VOFF_GAIN_7*/
  491. { 0x00006E50, 20, 10 }, /*VOFF_GAIN_8*/
  492. { 0x00006E54, 0, 10 }, /*VOFF_GAIN_9*/
  493. { 0x00006E54, 10, 10 }, /*VOFF_GAIN_10*/
  494. { 0x00006E54, 20, 10 }, /*VOFF_GAIN_11*/
  495. { 0x00006E58, 0, 10 }, /*VOFF_GAIN_12*/
  496. { 0x00006E58, 10, 10 }, /*VOFF_GAIN_13*/
  497. { 0x00006E58, 20, 10 }, /*VOFF_GAIN_14*/
  498. { 0x00006E5C, 0, 10 }, /*VOFF_GAIN_15*/
  499. { 0x00006E5C, 10, 10 }, /*VOFF_GAIN_16*/
  500. { 0x00006E5C, 20, 10 }, /*VOFF_GAIN_17*/
  501. { 0x00006E60, 0, 10 }, /*VOFF_GAIN_18*/
  502. { 0x00006E60, 10, 10 }, /*VOFF_GAIN_19*/
  503. { 0x00006E60, 20, 10 }, /*VOFF_GAIN_20*/
  504. { 0x00006E64, 0, 10 }, /*VOFF_INT1*/
  505. { 0x00007418, 7, 5 }, /*DS_SPK_INT1_CAP_TRIM*/
  506. { 0x0000741C, 0, 5 }, /*DS_SPK_INT2_CAP_TRIM*/
  507. { 0x0000741C, 11, 4 }, /*DS_SPK_LPF_CAP_TRIM*/
  508. { 0x0000741C, 19, 4 }, /*DS_SPK_QUAN_CAP_TRIM*/
  509. { 0x00007434, 17, 1 }, /*FORCE_CAL*/
  510. { 0x00007434, 18, 7 }, /*CAL_OVERRIDE*/
  511. { 0x00007068, 0, 9 }, /*MODIX*/
  512. { 0x0000410C, 7, 1 }, /*VIMON_DLY_NOT_COMB*/
  513. { 0x0000400C, 0, 7 }, /*VIMON_DLY*/
  514. { 0x00000000, 0, 1 }, /*extra bit*/
  515. { 0x00017040, 0, 8 }, /*X_COORDINATE*/
  516. { 0x00017040, 8, 8 }, /*Y_COORDINATE*/
  517. { 0x00017040, 16, 8 }, /*WAFER_ID*/
  518. { 0x00017040, 24, 8 }, /*DVS*/
  519. { 0x00017044, 0, 24 }, /*LOT_NUMBER*/
  520. };
  521. static const struct cs35l41_otp_packed_element_t otp_map_2[] = {
  522. /* addr shift size */
  523. { 0x00002030, 0, 4 }, /*TRIM_OSC_FREQ_TRIM*/
  524. { 0x00002030, 7, 1 }, /*TRIM_OSC_TRIM_DONE*/
  525. { 0x0000208c, 24, 6 }, /*TST_DIGREG_VREF_TRIM*/
  526. { 0x00002090, 14, 4 }, /*TST_REF_TRIM*/
  527. { 0x00002090, 10, 4 }, /*TST_REF_TEMPCO_TRIM*/
  528. { 0x0000300C, 11, 4 }, /*PLL_LDOA_TST_VREF_TRIM*/
  529. { 0x0000394C, 23, 2 }, /*BST_ATEST_CM_VOFF*/
  530. { 0x00003950, 0, 7 }, /*BST_ATRIM_IADC_OFFSET*/
  531. { 0x00003950, 8, 7 }, /*BST_ATRIM_IADC_GAIN1*/
  532. { 0x00003950, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET1*/
  533. { 0x00003950, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN1*/
  534. { 0x00003954, 0, 7 }, /*BST_ATRIM_IADC_OFFSET2*/
  535. { 0x00003954, 8, 7 }, /*BST_ATRIM_IADC_GAIN2*/
  536. { 0x00003954, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET2*/
  537. { 0x00003954, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN2*/
  538. { 0x00003958, 0, 7 }, /*BST_ATRIM_IADC_OFFSET3*/
  539. { 0x00003958, 8, 7 }, /*BST_ATRIM_IADC_GAIN3*/
  540. { 0x00003958, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET3*/
  541. { 0x00003958, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN3*/
  542. { 0x0000395C, 0, 7 }, /*BST_ATRIM_IADC_OFFSET4*/
  543. { 0x0000395C, 8, 7 }, /*BST_ATRIM_IADC_GAIN4*/
  544. { 0x0000395C, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET4*/
  545. { 0x0000395C, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN4*/
  546. { 0x0000416C, 0, 8 }, /*VMON_GAIN_OTP_VAL*/
  547. { 0x00004160, 0, 7 }, /*VMON_OFFSET_OTP_VAL*/
  548. { 0x0000416C, 8, 8 }, /*IMON_GAIN_OTP_VAL*/
  549. { 0x00004160, 16, 10 }, /*IMON_OFFSET_OTP_VAL*/
  550. { 0x0000416C, 16, 12 }, /*VMON_CM_GAIN_OTP_VAL*/
  551. { 0x0000416C, 28, 1 }, /*VMON_CM_GAIN_SIGN_OTP_VAL*/
  552. { 0x00004170, 0, 6 }, /*IMON_CAL_TEMPCO_OTP_VAL*/
  553. { 0x00004170, 6, 1 }, /*IMON_CAL_TEMPCO_SIGN_OTP*/
  554. { 0x00004170, 8, 6 }, /*IMON_CAL_TEMPCO2_OTP_VAL*/
  555. { 0x00004170, 14, 1 }, /*IMON_CAL_TEMPCO2_DN_UPB_OTP_VAL*/
  556. { 0x00004170, 16, 9 }, /*IMON_CAL_TEMPCO_TBASE_OTP_VAL*/
  557. { 0x00004360, 0, 5 }, /*TEMP_GAIN_OTP_VAL*/
  558. { 0x00004360, 6, 9 }, /*TEMP_OFFSET_OTP_VAL*/
  559. { 0x00004448, 0, 8 }, /*VP_SARADC_OFFSET*/
  560. { 0x00004448, 8, 8 }, /*VP_GAIN_INDEX*/
  561. { 0x00004448, 16, 8 }, /*VBST_SARADC_OFFSET*/
  562. { 0x00004448, 24, 8 }, /*VBST_GAIN_INDEX*/
  563. { 0x0000444C, 0, 3 }, /*ANA_SELINVREF*/
  564. { 0x00006E30, 0, 5 }, /*GAIN_ERR_COEFF_0*/
  565. { 0x00006E30, 8, 5 }, /*GAIN_ERR_COEFF_1*/
  566. { 0x00006E30, 16, 5 }, /*GAIN_ERR_COEFF_2*/
  567. { 0x00006E30, 24, 5 }, /*GAIN_ERR_COEFF_3*/
  568. { 0x00006E34, 0, 5 }, /*GAIN_ERR_COEFF_4*/
  569. { 0x00006E34, 8, 5 }, /*GAIN_ERR_COEFF_5*/
  570. { 0x00006E34, 16, 5 }, /*GAIN_ERR_COEFF_6*/
  571. { 0x00006E34, 24, 5 }, /*GAIN_ERR_COEFF_7*/
  572. { 0x00006E38, 0, 5 }, /*GAIN_ERR_COEFF_8*/
  573. { 0x00006E38, 8, 5 }, /*GAIN_ERR_COEFF_9*/
  574. { 0x00006E38, 16, 5 }, /*GAIN_ERR_COEFF_10*/
  575. { 0x00006E38, 24, 5 }, /*GAIN_ERR_COEFF_11*/
  576. { 0x00006E3C, 0, 5 }, /*GAIN_ERR_COEFF_12*/
  577. { 0x00006E3C, 8, 5 }, /*GAIN_ERR_COEFF_13*/
  578. { 0x00006E3C, 16, 5 }, /*GAIN_ERR_COEFF_14*/
  579. { 0x00006E3C, 24, 5 }, /*GAIN_ERR_COEFF_15*/
  580. { 0x00006E40, 0, 5 }, /*GAIN_ERR_COEFF_16*/
  581. { 0x00006E40, 8, 5 }, /*GAIN_ERR_COEFF_17*/
  582. { 0x00006E40, 16, 5 }, /*GAIN_ERR_COEFF_18*/
  583. { 0x00006E40, 24, 5 }, /*GAIN_ERR_COEFF_19*/
  584. { 0x00006E44, 0, 5 }, /*GAIN_ERR_COEFF_20*/
  585. { 0x00006E48, 0, 10 }, /*VOFF_GAIN_0*/
  586. { 0x00006E48, 10, 10 }, /*VOFF_GAIN_1*/
  587. { 0x00006E48, 20, 10 }, /*VOFF_GAIN_2*/
  588. { 0x00006E4C, 0, 10 }, /*VOFF_GAIN_3*/
  589. { 0x00006E4C, 10, 10 }, /*VOFF_GAIN_4*/
  590. { 0x00006E4C, 20, 10 }, /*VOFF_GAIN_5*/
  591. { 0x00006E50, 0, 10 }, /*VOFF_GAIN_6*/
  592. { 0x00006E50, 10, 10 }, /*VOFF_GAIN_7*/
  593. { 0x00006E50, 20, 10 }, /*VOFF_GAIN_8*/
  594. { 0x00006E54, 0, 10 }, /*VOFF_GAIN_9*/
  595. { 0x00006E54, 10, 10 }, /*VOFF_GAIN_10*/
  596. { 0x00006E54, 20, 10 }, /*VOFF_GAIN_11*/
  597. { 0x00006E58, 0, 10 }, /*VOFF_GAIN_12*/
  598. { 0x00006E58, 10, 10 }, /*VOFF_GAIN_13*/
  599. { 0x00006E58, 20, 10 }, /*VOFF_GAIN_14*/
  600. { 0x00006E5C, 0, 10 }, /*VOFF_GAIN_15*/
  601. { 0x00006E5C, 10, 10 }, /*VOFF_GAIN_16*/
  602. { 0x00006E5C, 20, 10 }, /*VOFF_GAIN_17*/
  603. { 0x00006E60, 0, 10 }, /*VOFF_GAIN_18*/
  604. { 0x00006E60, 10, 10 }, /*VOFF_GAIN_19*/
  605. { 0x00006E60, 20, 10 }, /*VOFF_GAIN_20*/
  606. { 0x00006E64, 0, 10 }, /*VOFF_INT1*/
  607. { 0x00007418, 7, 5 }, /*DS_SPK_INT1_CAP_TRIM*/
  608. { 0x0000741C, 0, 5 }, /*DS_SPK_INT2_CAP_TRIM*/
  609. { 0x0000741C, 11, 4 }, /*DS_SPK_LPF_CAP_TRIM*/
  610. { 0x0000741C, 19, 4 }, /*DS_SPK_QUAN_CAP_TRIM*/
  611. { 0x00007434, 17, 1 }, /*FORCE_CAL*/
  612. { 0x00007434, 18, 7 }, /*CAL_OVERRIDE*/
  613. { 0x00007068, 0, 9 }, /*MODIX*/
  614. { 0x0000410C, 7, 1 }, /*VIMON_DLY_NOT_COMB*/
  615. { 0x0000400C, 0, 7 }, /*VIMON_DLY*/
  616. { 0x00004000, 11, 1 }, /*VMON_POL*/
  617. { 0x00017040, 0, 8 }, /*X_COORDINATE*/
  618. { 0x00017040, 8, 8 }, /*Y_COORDINATE*/
  619. { 0x00017040, 16, 8 }, /*WAFER_ID*/
  620. { 0x00017040, 24, 8 }, /*DVS*/
  621. { 0x00017044, 0, 24 }, /*LOT_NUMBER*/
  622. };
  623. static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
  624. { 0x00003854, 0x05180240 },
  625. { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 },
  626. { 0x00004310, 0x00000000 },
  627. { CS35L41_VPVBST_FS_SEL, 0x00000000 },
  628. { CS35L41_OTP_TRIM_30, 0x9091A1C8 },
  629. { 0x00003014, 0x0200EE0E },
  630. { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 },
  631. { 0x00000054, 0x00000004 },
  632. { CS35L41_IRQ1_DB3, 0x00000000 },
  633. { CS35L41_IRQ2_DB3, 0x00000000 },
  634. { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
  635. { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
  636. { CS35L41_PWR_CTRL2, 0x00000000 },
  637. { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
  638. { CS35L41_ASP_TX3_SRC, 0x00000000 },
  639. { CS35L41_ASP_TX4_SRC, 0x00000000 },
  640. };
  641. static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
  642. { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 },
  643. { 0x00004310, 0x00000000 },
  644. { CS35L41_VPVBST_FS_SEL, 0x00000000 },
  645. { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 },
  646. { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
  647. { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
  648. { CS35L41_PWR_CTRL2, 0x00000000 },
  649. { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
  650. { CS35L41_ASP_TX3_SRC, 0x00000000 },
  651. { CS35L41_ASP_TX4_SRC, 0x00000000 },
  652. };
  653. static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
  654. { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 },
  655. { 0x00004310, 0x00000000 },
  656. { CS35L41_VPVBST_FS_SEL, 0x00000000 },
  657. { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 },
  658. { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
  659. { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
  660. { CS35L41_PWR_CTRL2, 0x00000000 },
  661. { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
  662. { CS35L41_ASP_TX3_SRC, 0x00000000 },
  663. { CS35L41_ASP_TX4_SRC, 0x00000000 },
  664. };
  665. static const struct reg_sequence cs35l41_fs_errata_patch[] = {
  666. { CS35L41_DSP1_RX1_RATE, 0x00000001 },
  667. { CS35L41_DSP1_RX2_RATE, 0x00000001 },
  668. { CS35L41_DSP1_RX3_RATE, 0x00000001 },
  669. { CS35L41_DSP1_RX4_RATE, 0x00000001 },
  670. { CS35L41_DSP1_RX5_RATE, 0x00000001 },
  671. { CS35L41_DSP1_RX6_RATE, 0x00000001 },
  672. { CS35L41_DSP1_RX7_RATE, 0x00000001 },
  673. { CS35L41_DSP1_RX8_RATE, 0x00000001 },
  674. { CS35L41_DSP1_TX1_RATE, 0x00000001 },
  675. { CS35L41_DSP1_TX2_RATE, 0x00000001 },
  676. { CS35L41_DSP1_TX3_RATE, 0x00000001 },
  677. { CS35L41_DSP1_TX4_RATE, 0x00000001 },
  678. { CS35L41_DSP1_TX5_RATE, 0x00000001 },
  679. { CS35L41_DSP1_TX6_RATE, 0x00000001 },
  680. { CS35L41_DSP1_TX7_RATE, 0x00000001 },
  681. { CS35L41_DSP1_TX8_RATE, 0x00000001 },
  682. };
  683. static const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[] = {
  684. {
  685. .id = 0x01,
  686. .map = otp_map_1,
  687. .num_elements = ARRAY_SIZE(otp_map_1),
  688. .bit_offset = 16,
  689. .word_offset = 2,
  690. },
  691. {
  692. .id = 0x02,
  693. .map = otp_map_2,
  694. .num_elements = ARRAY_SIZE(otp_map_2),
  695. .bit_offset = 16,
  696. .word_offset = 2,
  697. },
  698. {
  699. .id = 0x03,
  700. .map = otp_map_2,
  701. .num_elements = ARRAY_SIZE(otp_map_2),
  702. .bit_offset = 16,
  703. .word_offset = 2,
  704. },
  705. {
  706. .id = 0x06,
  707. .map = otp_map_2,
  708. .num_elements = ARRAY_SIZE(otp_map_2),
  709. .bit_offset = 16,
  710. .word_offset = 2,
  711. },
  712. {
  713. .id = 0x08,
  714. .map = otp_map_1,
  715. .num_elements = ARRAY_SIZE(otp_map_1),
  716. .bit_offset = 16,
  717. .word_offset = 2,
  718. },
  719. };
  720. struct regmap_config cs35l41_regmap_i2c = {
  721. .reg_bits = 32,
  722. .val_bits = 32,
  723. .reg_stride = CS35L41_REGSTRIDE,
  724. .reg_format_endian = REGMAP_ENDIAN_BIG,
  725. .val_format_endian = REGMAP_ENDIAN_BIG,
  726. .max_register = CS35L41_LASTREG,
  727. .reg_defaults = cs35l41_reg,
  728. .num_reg_defaults = ARRAY_SIZE(cs35l41_reg),
  729. .volatile_reg = cs35l41_volatile_reg,
  730. .readable_reg = cs35l41_readable_reg,
  731. .precious_reg = cs35l41_precious_reg,
  732. .cache_type = REGCACHE_RBTREE,
  733. };
  734. EXPORT_SYMBOL_GPL(cs35l41_regmap_i2c);
  735. struct regmap_config cs35l41_regmap_spi = {
  736. .reg_bits = 32,
  737. .val_bits = 32,
  738. .pad_bits = 16,
  739. .reg_stride = CS35L41_REGSTRIDE,
  740. .reg_format_endian = REGMAP_ENDIAN_BIG,
  741. .val_format_endian = REGMAP_ENDIAN_BIG,
  742. .max_register = CS35L41_LASTREG,
  743. .reg_defaults = cs35l41_reg,
  744. .num_reg_defaults = ARRAY_SIZE(cs35l41_reg),
  745. .volatile_reg = cs35l41_volatile_reg,
  746. .readable_reg = cs35l41_readable_reg,
  747. .precious_reg = cs35l41_precious_reg,
  748. .cache_type = REGCACHE_RBTREE,
  749. };
  750. EXPORT_SYMBOL_GPL(cs35l41_regmap_spi);
  751. static const struct cs35l41_otp_map_element_t *cs35l41_find_otp_map(u32 otp_id)
  752. {
  753. int i;
  754. for (i = 0; i < ARRAY_SIZE(cs35l41_otp_map_map); i++) {
  755. if (cs35l41_otp_map_map[i].id == otp_id)
  756. return &cs35l41_otp_map_map[i];
  757. }
  758. return NULL;
  759. }
  760. int cs35l41_test_key_unlock(struct device *dev, struct regmap *regmap)
  761. {
  762. static const struct reg_sequence unlock[] = {
  763. { CS35L41_TEST_KEY_CTL, 0x00000055 },
  764. { CS35L41_TEST_KEY_CTL, 0x000000AA },
  765. };
  766. int ret;
  767. ret = regmap_multi_reg_write(regmap, unlock, ARRAY_SIZE(unlock));
  768. if (ret)
  769. dev_err(dev, "Failed to unlock test key: %d\n", ret);
  770. return ret;
  771. }
  772. EXPORT_SYMBOL_GPL(cs35l41_test_key_unlock);
  773. int cs35l41_test_key_lock(struct device *dev, struct regmap *regmap)
  774. {
  775. static const struct reg_sequence unlock[] = {
  776. { CS35L41_TEST_KEY_CTL, 0x000000CC },
  777. { CS35L41_TEST_KEY_CTL, 0x00000033 },
  778. };
  779. int ret;
  780. ret = regmap_multi_reg_write(regmap, unlock, ARRAY_SIZE(unlock));
  781. if (ret)
  782. dev_err(dev, "Failed to lock test key: %d\n", ret);
  783. return ret;
  784. }
  785. EXPORT_SYMBOL_GPL(cs35l41_test_key_lock);
  786. /* Must be called with the TEST_KEY unlocked */
  787. int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap)
  788. {
  789. const struct cs35l41_otp_map_element_t *otp_map_match;
  790. const struct cs35l41_otp_packed_element_t *otp_map;
  791. int bit_offset, word_offset, ret, i;
  792. unsigned int bit_sum = 8;
  793. u32 otp_val, otp_id_reg;
  794. u32 *otp_mem;
  795. otp_mem = kmalloc_array(CS35L41_OTP_SIZE_WORDS, sizeof(*otp_mem), GFP_KERNEL);
  796. if (!otp_mem)
  797. return -ENOMEM;
  798. ret = regmap_read(regmap, CS35L41_OTPID, &otp_id_reg);
  799. if (ret) {
  800. dev_err(dev, "Read OTP ID failed: %d\n", ret);
  801. goto err_otp_unpack;
  802. }
  803. otp_map_match = cs35l41_find_otp_map(otp_id_reg);
  804. if (!otp_map_match) {
  805. dev_err(dev, "OTP Map matching ID %d not found\n", otp_id_reg);
  806. ret = -EINVAL;
  807. goto err_otp_unpack;
  808. }
  809. ret = regmap_bulk_read(regmap, CS35L41_OTP_MEM0, otp_mem, CS35L41_OTP_SIZE_WORDS);
  810. if (ret) {
  811. dev_err(dev, "Read OTP Mem failed: %d\n", ret);
  812. goto err_otp_unpack;
  813. }
  814. otp_map = otp_map_match->map;
  815. bit_offset = otp_map_match->bit_offset;
  816. word_offset = otp_map_match->word_offset;
  817. for (i = 0; i < otp_map_match->num_elements; i++) {
  818. dev_dbg(dev, "bitoffset= %d, word_offset=%d, bit_sum mod 32=%d, otp_map[i].size = %u\n",
  819. bit_offset, word_offset, bit_sum % 32, otp_map[i].size);
  820. if (bit_offset + otp_map[i].size - 1 >= 32) {
  821. otp_val = (otp_mem[word_offset] &
  822. GENMASK(31, bit_offset)) >> bit_offset;
  823. otp_val |= (otp_mem[++word_offset] &
  824. GENMASK(bit_offset + otp_map[i].size - 33, 0)) <<
  825. (32 - bit_offset);
  826. bit_offset += otp_map[i].size - 32;
  827. } else if (bit_offset + otp_map[i].size - 1 >= 0) {
  828. otp_val = (otp_mem[word_offset] &
  829. GENMASK(bit_offset + otp_map[i].size - 1, bit_offset)
  830. ) >> bit_offset;
  831. bit_offset += otp_map[i].size;
  832. } else /* both bit_offset and otp_map[i].size are 0 */
  833. otp_val = 0;
  834. bit_sum += otp_map[i].size;
  835. if (bit_offset == 32) {
  836. bit_offset = 0;
  837. word_offset++;
  838. }
  839. if (otp_map[i].reg != 0) {
  840. ret = regmap_update_bits(regmap, otp_map[i].reg,
  841. GENMASK(otp_map[i].shift + otp_map[i].size - 1,
  842. otp_map[i].shift),
  843. otp_val << otp_map[i].shift);
  844. if (ret < 0) {
  845. dev_err(dev, "Write OTP val failed: %d\n", ret);
  846. goto err_otp_unpack;
  847. }
  848. }
  849. }
  850. ret = 0;
  851. err_otp_unpack:
  852. kfree(otp_mem);
  853. return ret;
  854. }
  855. EXPORT_SYMBOL_GPL(cs35l41_otp_unpack);
  856. /* Must be called with the TEST_KEY unlocked */
  857. int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid)
  858. {
  859. char *rev;
  860. int ret;
  861. switch (reg_revid) {
  862. case CS35L41_REVID_A0:
  863. ret = regmap_register_patch(reg, cs35l41_reva0_errata_patch,
  864. ARRAY_SIZE(cs35l41_reva0_errata_patch));
  865. rev = "A0";
  866. break;
  867. case CS35L41_REVID_B0:
  868. ret = regmap_register_patch(reg, cs35l41_revb0_errata_patch,
  869. ARRAY_SIZE(cs35l41_revb0_errata_patch));
  870. rev = "B0";
  871. break;
  872. case CS35L41_REVID_B2:
  873. ret = regmap_register_patch(reg, cs35l41_revb2_errata_patch,
  874. ARRAY_SIZE(cs35l41_revb2_errata_patch));
  875. rev = "B2";
  876. break;
  877. default:
  878. ret = -EINVAL;
  879. rev = "XX";
  880. break;
  881. }
  882. if (ret)
  883. dev_err(dev, "Failed to apply %s errata patch: %d\n", rev, ret);
  884. ret = regmap_write(reg, CS35L41_DSP1_CCM_CORE_CTRL, 0);
  885. if (ret < 0)
  886. dev_err(dev, "Write CCM_CORE_CTRL failed: %d\n", ret);
  887. return ret;
  888. }
  889. EXPORT_SYMBOL_GPL(cs35l41_register_errata_patch);
  890. int cs35l41_set_channels(struct device *dev, struct regmap *reg,
  891. unsigned int tx_num, unsigned int *tx_slot,
  892. unsigned int rx_num, unsigned int *rx_slot)
  893. {
  894. unsigned int val, mask;
  895. int i;
  896. if (tx_num > 4 || rx_num > 2)
  897. return -EINVAL;
  898. val = 0;
  899. mask = 0;
  900. for (i = 0; i < rx_num; i++) {
  901. dev_dbg(dev, "rx slot %d position = %d\n", i, rx_slot[i]);
  902. val |= rx_slot[i] << (i * 8);
  903. mask |= 0x3F << (i * 8);
  904. }
  905. regmap_update_bits(reg, CS35L41_SP_FRAME_RX_SLOT, mask, val);
  906. val = 0;
  907. mask = 0;
  908. for (i = 0; i < tx_num; i++) {
  909. dev_dbg(dev, "tx slot %d position = %d\n", i, tx_slot[i]);
  910. val |= tx_slot[i] << (i * 8);
  911. mask |= 0x3F << (i * 8);
  912. }
  913. regmap_update_bits(reg, CS35L41_SP_FRAME_TX_SLOT, mask, val);
  914. return 0;
  915. }
  916. EXPORT_SYMBOL_GPL(cs35l41_set_channels);
  917. static const unsigned char cs35l41_bst_k1_table[4][5] = {
  918. { 0x24, 0x32, 0x32, 0x4F, 0x57 },
  919. { 0x24, 0x32, 0x32, 0x4F, 0x57 },
  920. { 0x40, 0x32, 0x32, 0x4F, 0x57 },
  921. { 0x40, 0x32, 0x32, 0x4F, 0x57 }
  922. };
  923. static const unsigned char cs35l41_bst_k2_table[4][5] = {
  924. { 0x24, 0x49, 0x66, 0xA3, 0xEA },
  925. { 0x24, 0x49, 0x66, 0xA3, 0xEA },
  926. { 0x48, 0x49, 0x66, 0xA3, 0xEA },
  927. { 0x48, 0x49, 0x66, 0xA3, 0xEA }
  928. };
  929. static const unsigned char cs35l41_bst_slope_table[4] = {
  930. 0x75, 0x6B, 0x3B, 0x28
  931. };
  932. static int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind,
  933. int boost_cap, int boost_ipk)
  934. {
  935. unsigned char bst_lbst_val, bst_cbst_range, bst_ipk_scaled;
  936. int ret;
  937. switch (boost_ind) {
  938. case 1000: /* 1.0 uH */
  939. bst_lbst_val = 0;
  940. break;
  941. case 1200: /* 1.2 uH */
  942. bst_lbst_val = 1;
  943. break;
  944. case 1500: /* 1.5 uH */
  945. bst_lbst_val = 2;
  946. break;
  947. case 2200: /* 2.2 uH */
  948. bst_lbst_val = 3;
  949. break;
  950. default:
  951. dev_err(dev, "Invalid boost inductor value: %d nH\n", boost_ind);
  952. return -EINVAL;
  953. }
  954. switch (boost_cap) {
  955. case 0 ... 19:
  956. bst_cbst_range = 0;
  957. break;
  958. case 20 ... 50:
  959. bst_cbst_range = 1;
  960. break;
  961. case 51 ... 100:
  962. bst_cbst_range = 2;
  963. break;
  964. case 101 ... 200:
  965. bst_cbst_range = 3;
  966. break;
  967. default:
  968. if (boost_cap < 0) {
  969. dev_err(dev, "Invalid boost capacitor value: %d nH\n", boost_cap);
  970. return -EINVAL;
  971. }
  972. /* 201 uF and greater */
  973. bst_cbst_range = 4;
  974. }
  975. if (boost_ipk < 1600 || boost_ipk > 4500) {
  976. dev_err(dev, "Invalid boost inductor peak current: %d mA\n", boost_ipk);
  977. return -EINVAL;
  978. }
  979. ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_COEFF,
  980. CS35L41_BST_K1_MASK | CS35L41_BST_K2_MASK,
  981. cs35l41_bst_k1_table[bst_lbst_val][bst_cbst_range]
  982. << CS35L41_BST_K1_SHIFT |
  983. cs35l41_bst_k2_table[bst_lbst_val][bst_cbst_range]
  984. << CS35L41_BST_K2_SHIFT);
  985. if (ret) {
  986. dev_err(dev, "Failed to write boost coefficients: %d\n", ret);
  987. return ret;
  988. }
  989. ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_SLOPE_LBST,
  990. CS35L41_BST_SLOPE_MASK | CS35L41_BST_LBST_VAL_MASK,
  991. cs35l41_bst_slope_table[bst_lbst_val]
  992. << CS35L41_BST_SLOPE_SHIFT |
  993. bst_lbst_val << CS35L41_BST_LBST_VAL_SHIFT);
  994. if (ret) {
  995. dev_err(dev, "Failed to write boost slope/inductor value: %d\n", ret);
  996. return ret;
  997. }
  998. bst_ipk_scaled = ((boost_ipk - 1600) / 50) + 0x10;
  999. ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_PEAK_CUR, CS35L41_BST_IPK_MASK,
  1000. bst_ipk_scaled << CS35L41_BST_IPK_SHIFT);
  1001. if (ret) {
  1002. dev_err(dev, "Failed to write boost inductor peak current: %d\n", ret);
  1003. return ret;
  1004. }
  1005. regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK,
  1006. CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT);
  1007. return 0;
  1008. }
  1009. static const struct reg_sequence cs35l41_safe_to_reset[] = {
  1010. { 0x00000040, 0x00000055 },
  1011. { 0x00000040, 0x000000AA },
  1012. { 0x0000393C, 0x000000C0, 6000},
  1013. { 0x0000393C, 0x00000000 },
  1014. { 0x00007414, 0x00C82222 },
  1015. { 0x0000742C, 0x00000000 },
  1016. { 0x00000040, 0x000000CC },
  1017. { 0x00000040, 0x00000033 },
  1018. };
  1019. static const struct reg_sequence cs35l41_active_to_safe[] = {
  1020. { 0x00000040, 0x00000055 },
  1021. { 0x00000040, 0x000000AA },
  1022. { 0x00007438, 0x00585941 },
  1023. { CS35L41_PWR_CTRL1, 0x00000000 },
  1024. { 0x0000742C, 0x00000009, 3000 },
  1025. { 0x00007438, 0x00580941 },
  1026. { 0x00000040, 0x000000CC },
  1027. { 0x00000040, 0x00000033 },
  1028. };
  1029. static const struct reg_sequence cs35l41_safe_to_active[] = {
  1030. { 0x00000040, 0x00000055 },
  1031. { 0x00000040, 0x000000AA },
  1032. { 0x0000742C, 0x0000000F },
  1033. { 0x0000742C, 0x00000079 },
  1034. { 0x00007438, 0x00585941 },
  1035. { CS35L41_PWR_CTRL1, 0x00000001, 3000 }, // GLOBAL_EN = 1
  1036. { 0x0000742C, 0x000000F9 },
  1037. { 0x00007438, 0x00580941 },
  1038. { 0x00000040, 0x000000CC },
  1039. { 0x00000040, 0x00000033 },
  1040. };
  1041. static const struct reg_sequence cs35l41_reset_to_safe[] = {
  1042. { 0x00000040, 0x00000055 },
  1043. { 0x00000040, 0x000000AA },
  1044. { 0x00007438, 0x00585941 },
  1045. { 0x00007414, 0x08C82222 },
  1046. { 0x0000742C, 0x00000009 },
  1047. { 0x00000040, 0x000000CC },
  1048. { 0x00000040, 0x00000033 },
  1049. };
  1050. int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
  1051. struct cs35l41_hw_cfg *hw_cfg)
  1052. {
  1053. int ret;
  1054. switch (hw_cfg->bst_type) {
  1055. case CS35L41_INT_BOOST:
  1056. ret = cs35l41_boost_config(dev, regmap, hw_cfg->bst_ind,
  1057. hw_cfg->bst_cap, hw_cfg->bst_ipk);
  1058. if (ret)
  1059. dev_err(dev, "Error in Boost DT config: %d\n", ret);
  1060. break;
  1061. case CS35L41_EXT_BOOST:
  1062. case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
  1063. /* Only CLSA0100 doesn't use GPIO as VSPK switch, but even on that laptop we can
  1064. * toggle GPIO1 as is not connected to anything.
  1065. * There will be no other device without VSPK switch.
  1066. */
  1067. regmap_write(regmap, CS35L41_GPIO1_CTRL1, 0x00000001);
  1068. regmap_multi_reg_write(regmap, cs35l41_reset_to_safe,
  1069. ARRAY_SIZE(cs35l41_reset_to_safe));
  1070. ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK,
  1071. CS35L41_BST_DIS_FET_OFF << CS35L41_BST_EN_SHIFT);
  1072. break;
  1073. default:
  1074. dev_err(dev, "Boost type %d not supported\n", hw_cfg->bst_type);
  1075. ret = -EINVAL;
  1076. break;
  1077. }
  1078. return ret;
  1079. }
  1080. EXPORT_SYMBOL_GPL(cs35l41_init_boost);
  1081. bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type)
  1082. {
  1083. switch (b_type) {
  1084. /* There is only one laptop that doesn't have VSPK switch. */
  1085. case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
  1086. return false;
  1087. case CS35L41_EXT_BOOST:
  1088. regmap_write(regmap, CS35L41_GPIO1_CTRL1, 0x00000001);
  1089. regmap_multi_reg_write(regmap, cs35l41_safe_to_reset,
  1090. ARRAY_SIZE(cs35l41_safe_to_reset));
  1091. return true;
  1092. default:
  1093. return true;
  1094. }
  1095. }
  1096. EXPORT_SYMBOL_GPL(cs35l41_safe_reset);
  1097. int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable)
  1098. {
  1099. int ret;
  1100. switch (b_type) {
  1101. case CS35L41_INT_BOOST:
  1102. ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK,
  1103. enable << CS35L41_GLOBAL_EN_SHIFT);
  1104. usleep_range(3000, 3100);
  1105. break;
  1106. case CS35L41_EXT_BOOST:
  1107. case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
  1108. if (enable)
  1109. ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active,
  1110. ARRAY_SIZE(cs35l41_safe_to_active));
  1111. else
  1112. ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe,
  1113. ARRAY_SIZE(cs35l41_active_to_safe));
  1114. break;
  1115. default:
  1116. ret = -EINVAL;
  1117. break;
  1118. }
  1119. return ret;
  1120. }
  1121. EXPORT_SYMBOL_GPL(cs35l41_global_enable);
  1122. int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg)
  1123. {
  1124. struct cs35l41_gpio_cfg *gpio1 = &hw_cfg->gpio1;
  1125. struct cs35l41_gpio_cfg *gpio2 = &hw_cfg->gpio2;
  1126. int irq_pol = IRQF_TRIGGER_NONE;
  1127. regmap_update_bits(regmap, CS35L41_GPIO1_CTRL1,
  1128. CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
  1129. gpio1->pol_inv << CS35L41_GPIO_POL_SHIFT |
  1130. !gpio1->out_en << CS35L41_GPIO_DIR_SHIFT);
  1131. regmap_update_bits(regmap, CS35L41_GPIO2_CTRL1,
  1132. CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
  1133. gpio2->pol_inv << CS35L41_GPIO_POL_SHIFT |
  1134. !gpio2->out_en << CS35L41_GPIO_DIR_SHIFT);
  1135. if (gpio1->valid)
  1136. regmap_update_bits(regmap, CS35L41_GPIO_PAD_CONTROL, CS35L41_GPIO1_CTRL_MASK,
  1137. gpio1->func << CS35L41_GPIO1_CTRL_SHIFT);
  1138. if (gpio2->valid) {
  1139. regmap_update_bits(regmap, CS35L41_GPIO_PAD_CONTROL, CS35L41_GPIO2_CTRL_MASK,
  1140. gpio2->func << CS35L41_GPIO2_CTRL_SHIFT);
  1141. switch (gpio2->func) {
  1142. case CS35L41_GPIO2_INT_PUSH_PULL_LOW:
  1143. case CS35L41_GPIO2_INT_OPEN_DRAIN:
  1144. irq_pol = IRQF_TRIGGER_LOW;
  1145. break;
  1146. case CS35L41_GPIO2_INT_PUSH_PULL_HIGH:
  1147. irq_pol = IRQF_TRIGGER_HIGH;
  1148. break;
  1149. default:
  1150. break;
  1151. }
  1152. }
  1153. return irq_pol;
  1154. }
  1155. EXPORT_SYMBOL_GPL(cs35l41_gpio_config);
  1156. static const struct cs_dsp_region cs35l41_dsp1_regions[] = {
  1157. { .type = WMFW_HALO_PM_PACKED, .base = CS35L41_DSP1_PMEM_0 },
  1158. { .type = WMFW_HALO_XM_PACKED, .base = CS35L41_DSP1_XMEM_PACK_0 },
  1159. { .type = WMFW_HALO_YM_PACKED, .base = CS35L41_DSP1_YMEM_PACK_0 },
  1160. {. type = WMFW_ADSP2_XM, .base = CS35L41_DSP1_XMEM_UNPACK24_0},
  1161. {. type = WMFW_ADSP2_YM, .base = CS35L41_DSP1_YMEM_UNPACK24_0},
  1162. };
  1163. void cs35l41_configure_cs_dsp(struct device *dev, struct regmap *reg, struct cs_dsp *dsp)
  1164. {
  1165. dsp->num = 1;
  1166. dsp->type = WMFW_HALO;
  1167. dsp->rev = 0;
  1168. dsp->dev = dev;
  1169. dsp->regmap = reg;
  1170. dsp->base = CS35L41_DSP1_CTRL_BASE;
  1171. dsp->base_sysinfo = CS35L41_DSP1_SYS_ID;
  1172. dsp->mem = cs35l41_dsp1_regions;
  1173. dsp->num_mems = ARRAY_SIZE(cs35l41_dsp1_regions);
  1174. dsp->lock_regions = 0xFFFFFFFF;
  1175. }
  1176. EXPORT_SYMBOL_GPL(cs35l41_configure_cs_dsp);
  1177. static bool cs35l41_check_cspl_mbox_sts(enum cs35l41_cspl_mbox_cmd cmd,
  1178. enum cs35l41_cspl_mbox_status sts)
  1179. {
  1180. switch (cmd) {
  1181. case CSPL_MBOX_CMD_NONE:
  1182. case CSPL_MBOX_CMD_UNKNOWN_CMD:
  1183. return true;
  1184. case CSPL_MBOX_CMD_PAUSE:
  1185. case CSPL_MBOX_CMD_OUT_OF_HIBERNATE:
  1186. return (sts == CSPL_MBOX_STS_PAUSED);
  1187. case CSPL_MBOX_CMD_RESUME:
  1188. return (sts == CSPL_MBOX_STS_RUNNING);
  1189. case CSPL_MBOX_CMD_REINIT:
  1190. return (sts == CSPL_MBOX_STS_RUNNING);
  1191. case CSPL_MBOX_CMD_STOP_PRE_REINIT:
  1192. return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT);
  1193. default:
  1194. return false;
  1195. }
  1196. }
  1197. int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap,
  1198. enum cs35l41_cspl_mbox_cmd cmd)
  1199. {
  1200. unsigned int sts = 0, i;
  1201. int ret;
  1202. // Set mailbox cmd
  1203. ret = regmap_write(regmap, CS35L41_DSP_VIRT1_MBOX_1, cmd);
  1204. if (ret < 0) {
  1205. if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE)
  1206. dev_err(dev, "Failed to write MBOX: %d\n", ret);
  1207. return ret;
  1208. }
  1209. // Read mailbox status and verify it is appropriate for the given cmd
  1210. for (i = 0; i < 5; i++) {
  1211. usleep_range(1000, 1100);
  1212. ret = regmap_read(regmap, CS35L41_DSP_MBOX_2, &sts);
  1213. if (ret < 0) {
  1214. dev_err(dev, "Failed to read MBOX STS: %d\n", ret);
  1215. continue;
  1216. }
  1217. if (!cs35l41_check_cspl_mbox_sts(cmd, sts))
  1218. dev_dbg(dev, "[%u] cmd %u returned invalid sts %u", i, cmd, sts);
  1219. else
  1220. return 0;
  1221. }
  1222. if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE)
  1223. dev_err(dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts);
  1224. return -ENOMSG;
  1225. }
  1226. EXPORT_SYMBOL_GPL(cs35l41_set_cspl_mbox_cmd);
  1227. int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap)
  1228. {
  1229. int ret;
  1230. ret = regmap_multi_reg_write(regmap, cs35l41_fs_errata_patch,
  1231. ARRAY_SIZE(cs35l41_fs_errata_patch));
  1232. if (ret < 0)
  1233. dev_err(dev, "Failed to write fs errata: %d\n", ret);
  1234. return ret;
  1235. }
  1236. EXPORT_SYMBOL_GPL(cs35l41_write_fs_errata);
  1237. int cs35l41_enter_hibernate(struct device *dev, struct regmap *regmap,
  1238. enum cs35l41_boost_type b_type)
  1239. {
  1240. if (!cs35l41_safe_reset(regmap, b_type)) {
  1241. dev_dbg(dev, "System does not support Suspend\n");
  1242. return -EINVAL;
  1243. }
  1244. dev_dbg(dev, "Enter hibernate\n");
  1245. regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0088);
  1246. regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0188);
  1247. // Don't wait for ACK since bus activity would wake the device
  1248. regmap_write(regmap, CS35L41_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE);
  1249. return 0;
  1250. }
  1251. EXPORT_SYMBOL_GPL(cs35l41_enter_hibernate);
  1252. static void cs35l41_wait_for_pwrmgt_sts(struct device *dev, struct regmap *regmap)
  1253. {
  1254. const int pwrmgt_retries = 10;
  1255. unsigned int sts;
  1256. int i, ret;
  1257. for (i = 0; i < pwrmgt_retries; i++) {
  1258. ret = regmap_read(regmap, CS35L41_PWRMGT_STS, &sts);
  1259. if (ret)
  1260. dev_err(dev, "Failed to read PWRMGT_STS: %d\n", ret);
  1261. else if (!(sts & CS35L41_WR_PEND_STS_MASK))
  1262. return;
  1263. udelay(20);
  1264. }
  1265. dev_err(dev, "Timed out reading PWRMGT_STS\n");
  1266. }
  1267. int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap)
  1268. {
  1269. const int wake_retries = 20;
  1270. const int sleep_retries = 5;
  1271. int ret, i, j;
  1272. for (i = 0; i < sleep_retries; i++) {
  1273. dev_dbg(dev, "Exit hibernate\n");
  1274. for (j = 0; j < wake_retries; j++) {
  1275. ret = cs35l41_set_cspl_mbox_cmd(dev, regmap,
  1276. CSPL_MBOX_CMD_OUT_OF_HIBERNATE);
  1277. if (!ret)
  1278. break;
  1279. usleep_range(100, 200);
  1280. }
  1281. if (j < wake_retries) {
  1282. dev_dbg(dev, "Wake success at cycle: %d\n", j);
  1283. return 0;
  1284. }
  1285. dev_err(dev, "Wake failed, re-enter hibernate: %d\n", ret);
  1286. cs35l41_wait_for_pwrmgt_sts(dev, regmap);
  1287. regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0088);
  1288. cs35l41_wait_for_pwrmgt_sts(dev, regmap);
  1289. regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0188);
  1290. cs35l41_wait_for_pwrmgt_sts(dev, regmap);
  1291. regmap_write(regmap, CS35L41_PWRMGT_CTL, 0x3);
  1292. }
  1293. dev_err(dev, "Timed out waking device\n");
  1294. return -ETIMEDOUT;
  1295. }
  1296. EXPORT_SYMBOL_GPL(cs35l41_exit_hibernate);
  1297. MODULE_DESCRIPTION("CS35L41 library");
  1298. MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <[email protected]>");
  1299. MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <[email protected]>");
  1300. MODULE_LICENSE("GPL");