wcd934x-dsp-cntl.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/slab.h>
  6. #include <linux/delay.h>
  7. #include <linux/component.h>
  8. #include <linux/debugfs.h>
  9. #include <sound/soc.h>
  10. #include <sound/wcd-dsp-mgr.h>
  11. #include <asoc/wcd934x_registers.h>
  12. #include "wcd934x.h"
  13. #include "wcd934x-dsp-cntl.h"
  14. #include "../wcd9xxx-irq.h"
  15. #include "../core.h"
  16. #define WCD_CNTL_DIR_NAME_LEN_MAX 32
  17. #define WCD_CPE_FLL_MAX_RETRIES 5
  18. #define WCD_MEM_ENABLE_MAX_RETRIES 20
  19. #define WCD_DSP_BOOT_TIMEOUT_MS 3000
  20. #define WCD_SYSFS_ENTRY_MAX_LEN 8
  21. #define WCD_PROCFS_ENTRY_MAX_LEN 16
  22. #define WCD_934X_RAMDUMP_START_ADDR 0x20100000
  23. #define WCD_934X_RAMDUMP_SIZE ((1024 * 1024) - 128)
  24. #define WCD_MISCDEV_CMD_MAX_LEN 11
  25. #define WCD_CNTL_MUTEX_LOCK(codec, lock) \
  26. { \
  27. dev_dbg(codec->dev, "%s: mutex_lock(%s)\n", \
  28. __func__, __stringify_1(lock)); \
  29. mutex_lock(&lock); \
  30. }
  31. #define WCD_CNTL_MUTEX_UNLOCK(codec, lock) \
  32. { \
  33. dev_dbg(codec->dev, "%s: mutex_unlock(%s)\n", \
  34. __func__, __stringify_1(lock)); \
  35. mutex_unlock(&lock); \
  36. }
  37. enum wcd_mem_type {
  38. WCD_MEM_TYPE_ALWAYS_ON,
  39. WCD_MEM_TYPE_SWITCHABLE,
  40. };
  41. struct wcd_cntl_attribute {
  42. struct attribute attr;
  43. ssize_t (*show)(struct wcd_dsp_cntl *cntl, char *buf);
  44. ssize_t (*store)(struct wcd_dsp_cntl *cntl, const char *buf,
  45. ssize_t count);
  46. };
  47. #define WCD_CNTL_ATTR(_name, _mode, _show, _store) \
  48. static struct wcd_cntl_attribute cntl_attr_##_name = { \
  49. .attr = {.name = __stringify(_name), .mode = _mode}, \
  50. .show = _show, \
  51. .store = _store, \
  52. }
  53. #define to_wcd_cntl_attr(a) \
  54. container_of((a), struct wcd_cntl_attribute, attr)
  55. #define to_wcd_cntl(kobj) \
  56. container_of((kobj), struct wcd_dsp_cntl, wcd_kobj)
  57. static u8 mem_enable_values[] = {
  58. 0xFE, 0xFC, 0xF8, 0xF0,
  59. 0xE0, 0xC0, 0x80, 0x00,
  60. };
  61. #ifdef CONFIG_DEBUG_FS
  62. #define WCD_CNTL_SET_ERR_IRQ_FLAG(cntl)\
  63. atomic_cmpxchg(&cntl->err_irq_flag, 0, 1)
  64. #define WCD_CNTL_CLR_ERR_IRQ_FLAG(cntl)\
  65. atomic_set(&cntl->err_irq_flag, 0)
  66. static u16 wdsp_reg_for_debug_dump[] = {
  67. WCD934X_CPE_SS_CPE_CTL,
  68. WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0,
  69. WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_1,
  70. WCD934X_CPE_SS_PWR_CPEFLL_CTL,
  71. WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0,
  72. WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1,
  73. WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_OVERRIDE,
  74. WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0,
  75. WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1,
  76. WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2,
  77. WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3,
  78. WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_4,
  79. WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_5,
  80. WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN,
  81. WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
  82. WCD934X_CPE_SS_MAD_CTL,
  83. WCD934X_CPE_SS_CPAR_CTL,
  84. WCD934X_CPE_SS_CPAR_CFG,
  85. WCD934X_CPE_SS_WDOG_CFG,
  86. WCD934X_CPE_SS_STATUS,
  87. WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A,
  88. WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B,
  89. WCD934X_CPE_SS_SS_ERROR_INT_MASK_1A,
  90. WCD934X_CPE_SS_SS_ERROR_INT_MASK_1B,
  91. WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0A,
  92. WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0B,
  93. WCD934X_CPE_SS_SS_ERROR_INT_STATUS_1A,
  94. WCD934X_CPE_SS_SS_ERROR_INT_STATUS_1B,
  95. };
  96. static void wcd_cntl_collect_debug_dumps(struct wcd_dsp_cntl *cntl,
  97. bool internal)
  98. {
  99. struct snd_soc_codec *codec = cntl->codec;
  100. struct wdsp_err_signal_arg arg;
  101. enum wdsp_signal signal;
  102. int i;
  103. u8 val;
  104. /* If WDSP SSR happens, skip collecting debug dumps */
  105. if (WCD_CNTL_SET_ERR_IRQ_FLAG(cntl) != 0)
  106. return;
  107. /* Mask all error interrupts */
  108. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A,
  109. 0xFF);
  110. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B,
  111. 0xFF);
  112. /* Collect important WDSP registers dump for debug use */
  113. pr_err("%s: Dump the WDSP registers for debug use\n", __func__);
  114. for (i = 0; i < sizeof(wdsp_reg_for_debug_dump)/sizeof(u16); i++) {
  115. val = snd_soc_read(codec, wdsp_reg_for_debug_dump[i]);
  116. pr_err("%s: reg = 0x%x, val = 0x%x\n", __func__,
  117. wdsp_reg_for_debug_dump[i], val);
  118. }
  119. /* Trigger NMI in WDSP to sync and update the memory */
  120. snd_soc_write(codec, WCD934X_CPE_SS_BACKUP_INT, 0x02);
  121. /* Collect WDSP ramdump for debug use */
  122. if (cntl->m_dev && cntl->m_ops && cntl->m_ops->signal_handler) {
  123. arg.mem_dumps_enabled = cntl->ramdump_enable;
  124. arg.remote_start_addr = WCD_934X_RAMDUMP_START_ADDR;
  125. arg.dump_size = WCD_934X_RAMDUMP_SIZE;
  126. signal = internal ? WDSP_DEBUG_DUMP_INTERNAL : WDSP_DEBUG_DUMP;
  127. cntl->m_ops->signal_handler(cntl->m_dev, signal, &arg);
  128. }
  129. /* Unmask the fatal irqs */
  130. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A,
  131. ~(cntl->irqs.fatal_irqs & 0xFF));
  132. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B,
  133. ~((cntl->irqs.fatal_irqs >> 8) & 0xFF));
  134. WCD_CNTL_CLR_ERR_IRQ_FLAG(cntl);
  135. }
  136. #else
  137. #define WCD_CNTL_SET_ERR_IRQ_FLAG(cntl) 0
  138. #define WCD_CNTL_CLR_ERR_IRQ_FLAG(cntl) do {} while (0)
  139. static void wcd_cntl_collect_debug_dumps(struct wcd_dsp_cntl *cntl,
  140. bool internal)
  141. {
  142. }
  143. #endif
  144. static ssize_t wdsp_boot_show(struct wcd_dsp_cntl *cntl, char *buf)
  145. {
  146. return snprintf(buf, WCD_SYSFS_ENTRY_MAX_LEN,
  147. "%u", cntl->boot_reqs);
  148. }
  149. static ssize_t wdsp_boot_store(struct wcd_dsp_cntl *cntl,
  150. const char *buf, ssize_t count)
  151. {
  152. u32 val;
  153. bool vote;
  154. int ret;
  155. ret = kstrtou32(buf, 10, &val);
  156. if (ret) {
  157. dev_err(cntl->codec->dev,
  158. "%s: Invalid entry, ret = %d\n", __func__, ret);
  159. return -EINVAL;
  160. }
  161. if (val > 0) {
  162. cntl->boot_reqs++;
  163. vote = true;
  164. } else {
  165. cntl->boot_reqs--;
  166. vote = false;
  167. }
  168. if (cntl->m_dev && cntl->m_ops &&
  169. cntl->m_ops->vote_for_dsp)
  170. ret = cntl->m_ops->vote_for_dsp(cntl->m_dev, vote);
  171. else
  172. ret = -EINVAL;
  173. if (ret < 0)
  174. dev_err(cntl->codec->dev,
  175. "%s: failed to %s dsp\n", __func__,
  176. vote ? "enable" : "disable");
  177. return count;
  178. }
  179. WCD_CNTL_ATTR(boot, 0660, wdsp_boot_show, wdsp_boot_store);
  180. static ssize_t wcd_cntl_sysfs_show(struct kobject *kobj,
  181. struct attribute *attr, char *buf)
  182. {
  183. struct wcd_cntl_attribute *wcd_attr = to_wcd_cntl_attr(attr);
  184. struct wcd_dsp_cntl *cntl = to_wcd_cntl(kobj);
  185. ssize_t ret = -EINVAL;
  186. if (cntl && wcd_attr->show)
  187. ret = wcd_attr->show(cntl, buf);
  188. return ret;
  189. }
  190. static ssize_t wcd_cntl_sysfs_store(struct kobject *kobj,
  191. struct attribute *attr, const char *buf,
  192. size_t count)
  193. {
  194. struct wcd_cntl_attribute *wcd_attr = to_wcd_cntl_attr(attr);
  195. struct wcd_dsp_cntl *cntl = to_wcd_cntl(kobj);
  196. ssize_t ret = -EINVAL;
  197. if (cntl && wcd_attr->store)
  198. ret = wcd_attr->store(cntl, buf, count);
  199. return ret;
  200. }
  201. static const struct sysfs_ops wcd_cntl_sysfs_ops = {
  202. .show = wcd_cntl_sysfs_show,
  203. .store = wcd_cntl_sysfs_store,
  204. };
  205. static struct kobj_type wcd_cntl_ktype = {
  206. .sysfs_ops = &wcd_cntl_sysfs_ops,
  207. };
  208. static void wcd_cntl_change_online_state(struct wcd_dsp_cntl *cntl,
  209. u8 online)
  210. {
  211. struct wdsp_ssr_entry *ssr_entry = &cntl->ssr_entry;
  212. unsigned long ret;
  213. WCD_CNTL_MUTEX_LOCK(cntl->codec, cntl->ssr_mutex);
  214. ssr_entry->offline = !online;
  215. /* Make sure the write is complete */
  216. wmb();
  217. ret = xchg(&ssr_entry->offline_change, 1);
  218. wake_up_interruptible(&ssr_entry->offline_poll_wait);
  219. dev_dbg(cntl->codec->dev,
  220. "%s: requested %u, offline %u offline_change %u, ret = %ldn",
  221. __func__, online, ssr_entry->offline,
  222. ssr_entry->offline_change, ret);
  223. WCD_CNTL_MUTEX_UNLOCK(cntl->codec, cntl->ssr_mutex);
  224. }
  225. static ssize_t wdsp_ssr_entry_read(struct snd_info_entry *entry,
  226. void *file_priv_data, struct file *file,
  227. char __user *buf, size_t count, loff_t pos)
  228. {
  229. int len = 0;
  230. char buffer[WCD_PROCFS_ENTRY_MAX_LEN];
  231. struct wcd_dsp_cntl *cntl;
  232. struct wdsp_ssr_entry *ssr_entry;
  233. ssize_t ret;
  234. u8 offline;
  235. cntl = (struct wcd_dsp_cntl *) entry->private_data;
  236. if (!cntl) {
  237. pr_err("%s: Invalid private data for SSR procfs entry\n",
  238. __func__);
  239. return -EINVAL;
  240. }
  241. ssr_entry = &cntl->ssr_entry;
  242. WCD_CNTL_MUTEX_LOCK(cntl->codec, cntl->ssr_mutex);
  243. offline = ssr_entry->offline;
  244. /* Make sure the read is complete */
  245. rmb();
  246. dev_dbg(cntl->codec->dev, "%s: offline = %s\n", __func__,
  247. offline ? "true" : "false");
  248. len = snprintf(buffer, sizeof(buffer), "%s\n",
  249. offline ? "OFFLINE" : "ONLINE");
  250. ret = simple_read_from_buffer(buf, count, &pos, buffer, len);
  251. WCD_CNTL_MUTEX_UNLOCK(cntl->codec, cntl->ssr_mutex);
  252. return ret;
  253. }
  254. static unsigned int wdsp_ssr_entry_poll(struct snd_info_entry *entry,
  255. void *private_data, struct file *file,
  256. poll_table *wait)
  257. {
  258. struct wcd_dsp_cntl *cntl;
  259. struct wdsp_ssr_entry *ssr_entry;
  260. unsigned int ret = 0;
  261. if (!entry || !entry->private_data) {
  262. pr_err("%s: %s is NULL\n", __func__,
  263. (!entry) ? "entry" : "private_data");
  264. return -EINVAL;
  265. }
  266. cntl = (struct wcd_dsp_cntl *) entry->private_data;
  267. ssr_entry = &cntl->ssr_entry;
  268. dev_dbg(cntl->codec->dev, "%s: Poll wait, offline = %u\n",
  269. __func__, ssr_entry->offline);
  270. poll_wait(file, &ssr_entry->offline_poll_wait, wait);
  271. dev_dbg(cntl->codec->dev, "%s: Woken up Poll wait, offline = %u\n",
  272. __func__, ssr_entry->offline);
  273. WCD_CNTL_MUTEX_LOCK(cntl->codec, cntl->ssr_mutex);
  274. if (xchg(&ssr_entry->offline_change, 0))
  275. ret = POLLIN | POLLPRI | POLLRDNORM;
  276. dev_dbg(cntl->codec->dev, "%s: ret (%d) from poll_wait\n",
  277. __func__, ret);
  278. WCD_CNTL_MUTEX_UNLOCK(cntl->codec, cntl->ssr_mutex);
  279. return ret;
  280. }
  281. static struct snd_info_entry_ops wdsp_ssr_entry_ops = {
  282. .read = wdsp_ssr_entry_read,
  283. .poll = wdsp_ssr_entry_poll,
  284. };
  285. static int wcd_cntl_cpe_fll_calibrate(struct wcd_dsp_cntl *cntl)
  286. {
  287. struct snd_soc_codec *codec = cntl->codec;
  288. int ret = 0, retry = 0;
  289. u8 cal_lsb, cal_msb;
  290. u8 lock_det;
  291. /* Make sure clocks are gated */
  292. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPE_CTL,
  293. 0x05, 0x00);
  294. /* Enable CPE FLL reference clock */
  295. snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
  296. 0x80, 0x80);
  297. snd_soc_update_bits(codec, WCD934X_CPE_FLL_USER_CTL_5,
  298. 0xF3, 0x13);
  299. snd_soc_write(codec, WCD934X_CPE_FLL_L_VAL_CTL_0, 0x50);
  300. /* Disable CPAR reset and Enable CPAR clk */
  301. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CTL,
  302. 0x02, 0x02);
  303. /* Write calibration l-value based on cdc clk rate */
  304. if (cntl->clk_rate == 9600000) {
  305. cal_lsb = 0x6d;
  306. cal_msb = 0x00;
  307. } else {
  308. cal_lsb = 0x56;
  309. cal_msb = 0x00;
  310. }
  311. snd_soc_write(codec, WCD934X_CPE_FLL_USER_CTL_6, cal_lsb);
  312. snd_soc_write(codec, WCD934X_CPE_FLL_USER_CTL_7, cal_msb);
  313. /* FLL mode to follow power up sequence */
  314. snd_soc_update_bits(codec, WCD934X_CPE_FLL_FLL_MODE,
  315. 0x60, 0x00);
  316. /* HW controlled CPE FLL */
  317. snd_soc_update_bits(codec, WCD934X_CPE_FLL_FLL_MODE,
  318. 0x80, 0x80);
  319. /* Force on CPE FLL */
  320. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CFG,
  321. 0x04, 0x04);
  322. do {
  323. /* Time for FLL calibration to complete */
  324. usleep_range(1000, 1100);
  325. lock_det = snd_soc_read(codec, WCD934X_CPE_FLL_STATUS_3);
  326. retry++;
  327. } while (!(lock_det & 0x01) &&
  328. retry <= WCD_CPE_FLL_MAX_RETRIES);
  329. if (!(lock_det & 0x01)) {
  330. dev_err(codec->dev, "%s: lock detect not set, 0x%02x\n",
  331. __func__, lock_det);
  332. ret = -EIO;
  333. goto err_lock_det;
  334. }
  335. snd_soc_update_bits(codec, WCD934X_CPE_FLL_FLL_MODE,
  336. 0x60, 0x20);
  337. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CFG,
  338. 0x04, 0x00);
  339. return ret;
  340. err_lock_det:
  341. /* Undo the register settings */
  342. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CFG,
  343. 0x04, 0x00);
  344. snd_soc_update_bits(codec, WCD934X_CPE_FLL_FLL_MODE,
  345. 0x80, 0x00);
  346. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CTL,
  347. 0x02, 0x00);
  348. return ret;
  349. }
  350. static void wcd_cntl_config_cpar(struct wcd_dsp_cntl *cntl)
  351. {
  352. struct snd_soc_codec *codec = cntl->codec;
  353. u8 nom_lo, nom_hi, svs2_lo, svs2_hi;
  354. /* Configure CPAR */
  355. nom_hi = svs2_hi = 0;
  356. if (cntl->clk_rate == 9600000) {
  357. nom_lo = 0x90;
  358. svs2_lo = 0x50;
  359. } else {
  360. nom_lo = 0x70;
  361. svs2_lo = 0x3e;
  362. }
  363. snd_soc_write(codec, WCD934X_TEST_DEBUG_LVAL_NOM_LOW, nom_lo);
  364. snd_soc_write(codec, WCD934X_TEST_DEBUG_LVAL_NOM_HIGH, nom_hi);
  365. snd_soc_write(codec, WCD934X_TEST_DEBUG_LVAL_SVS_SVS2_LOW, svs2_lo);
  366. snd_soc_write(codec, WCD934X_TEST_DEBUG_LVAL_SVS_SVS2_HIGH, svs2_hi);
  367. snd_soc_update_bits(codec, WCD934X_CPE_SS_PWR_CPEFLL_CTL,
  368. 0x03, 0x03);
  369. }
  370. static int wcd_cntl_cpe_fll_ctrl(struct wcd_dsp_cntl *cntl,
  371. bool enable)
  372. {
  373. struct snd_soc_codec *codec = cntl->codec;
  374. int ret = 0;
  375. if (enable) {
  376. ret = wcd_cntl_cpe_fll_calibrate(cntl);
  377. if (ret < 0) {
  378. dev_err(codec->dev,
  379. "%s: cpe_fll_cal failed, err = %d\n",
  380. __func__, ret);
  381. goto done;
  382. }
  383. wcd_cntl_config_cpar(cntl);
  384. /* Enable AHB CLK and CPE CLK*/
  385. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPE_CTL,
  386. 0x05, 0x05);
  387. } else {
  388. /* Disable AHB CLK and CPE CLK */
  389. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPE_CTL,
  390. 0x05, 0x00);
  391. /* Reset the CPAR mode for CPE FLL */
  392. snd_soc_write(codec, WCD934X_CPE_FLL_FLL_MODE, 0x20);
  393. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CFG,
  394. 0x04, 0x00);
  395. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CTL,
  396. 0x02, 0x00);
  397. }
  398. done:
  399. return ret;
  400. }
  401. static int wcd_cntl_clocks_enable(struct wcd_dsp_cntl *cntl)
  402. {
  403. struct snd_soc_codec *codec = cntl->codec;
  404. int ret;
  405. WCD_CNTL_MUTEX_LOCK(codec, cntl->clk_mutex);
  406. /* Enable codec clock */
  407. if (cntl->cdc_cb && cntl->cdc_cb->cdc_clk_en)
  408. ret = cntl->cdc_cb->cdc_clk_en(codec, true);
  409. else
  410. ret = -EINVAL;
  411. if (ret < 0) {
  412. dev_err(codec->dev,
  413. "%s: Failed to enable cdc clk, err = %d\n",
  414. __func__, ret);
  415. goto done;
  416. }
  417. /* Pull CPAR out of reset */
  418. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CTL, 0x04, 0x00);
  419. /* Configure and Enable CPE FLL clock */
  420. ret = wcd_cntl_cpe_fll_ctrl(cntl, true);
  421. if (ret < 0) {
  422. dev_err(codec->dev,
  423. "%s: Failed to enable cpe clk, err = %d\n",
  424. __func__, ret);
  425. goto err_cpe_clk;
  426. }
  427. cntl->is_clk_enabled = true;
  428. /* Ungate the CPR clock */
  429. snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_GATE, 0x10, 0x00);
  430. done:
  431. WCD_CNTL_MUTEX_UNLOCK(codec, cntl->clk_mutex);
  432. return ret;
  433. err_cpe_clk:
  434. if (cntl->cdc_cb && cntl->cdc_cb->cdc_clk_en)
  435. cntl->cdc_cb->cdc_clk_en(codec, false);
  436. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CTL, 0x04, 0x04);
  437. WCD_CNTL_MUTEX_UNLOCK(codec, cntl->clk_mutex);
  438. return ret;
  439. }
  440. static int wcd_cntl_clocks_disable(struct wcd_dsp_cntl *cntl)
  441. {
  442. struct snd_soc_codec *codec = cntl->codec;
  443. int ret = 0;
  444. WCD_CNTL_MUTEX_LOCK(codec, cntl->clk_mutex);
  445. if (!cntl->is_clk_enabled) {
  446. dev_info(codec->dev, "%s: clocks already disabled\n",
  447. __func__);
  448. goto done;
  449. }
  450. /* Gate the CPR clock */
  451. snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_GATE, 0x10, 0x10);
  452. /* Disable CPE FLL clock */
  453. ret = wcd_cntl_cpe_fll_ctrl(cntl, false);
  454. if (ret < 0)
  455. dev_err(codec->dev,
  456. "%s: Failed to disable cpe clk, err = %d\n",
  457. __func__, ret);
  458. /*
  459. * Even if CPE FLL disable failed, go ahead and disable
  460. * the codec clock
  461. */
  462. if (cntl->cdc_cb && cntl->cdc_cb->cdc_clk_en)
  463. ret = cntl->cdc_cb->cdc_clk_en(codec, false);
  464. else
  465. ret = -EINVAL;
  466. cntl->is_clk_enabled = false;
  467. /* Put CPAR in reset */
  468. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CTL, 0x04, 0x04);
  469. done:
  470. WCD_CNTL_MUTEX_UNLOCK(codec, cntl->clk_mutex);
  471. return ret;
  472. }
  473. static void wcd_cntl_cpar_ctrl(struct wcd_dsp_cntl *cntl,
  474. bool enable)
  475. {
  476. struct snd_soc_codec *codec = cntl->codec;
  477. if (enable)
  478. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CTL, 0x03, 0x03);
  479. else
  480. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPAR_CTL, 0x03, 0x00);
  481. }
  482. static int wcd_cntl_enable_memory(struct wcd_dsp_cntl *cntl,
  483. enum wcd_mem_type mem_type)
  484. {
  485. struct snd_soc_codec *codec = cntl->codec;
  486. struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
  487. int loop_cnt = 0;
  488. u8 status;
  489. int ret = 0;
  490. switch (mem_type) {
  491. case WCD_MEM_TYPE_ALWAYS_ON:
  492. /* 512KB of always on region */
  493. wcd9xxx_slim_write_repeat(wcd9xxx,
  494. WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0,
  495. ARRAY_SIZE(mem_enable_values),
  496. mem_enable_values);
  497. wcd9xxx_slim_write_repeat(wcd9xxx,
  498. WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1,
  499. ARRAY_SIZE(mem_enable_values),
  500. mem_enable_values);
  501. break;
  502. case WCD_MEM_TYPE_SWITCHABLE:
  503. snd_soc_update_bits(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
  504. 0x04, 0x00);
  505. snd_soc_update_bits(codec, WCD934X_TEST_DEBUG_MEM_CTRL,
  506. 0x80, 0x80);
  507. snd_soc_update_bits(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
  508. 0x01, 0x01);
  509. do {
  510. loop_cnt++;
  511. /* Time to enable the power domain for memory */
  512. usleep_range(100, 150);
  513. status = snd_soc_read(codec,
  514. WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL);
  515. } while ((status & 0x02) != 0x02 &&
  516. loop_cnt != WCD_MEM_ENABLE_MAX_RETRIES);
  517. if ((status & 0x02) != 0x02) {
  518. dev_err(cntl->codec->dev,
  519. "%s: power domain not enabled, status = 0x%02x\n",
  520. __func__, status);
  521. ret = -EIO;
  522. goto done;
  523. }
  524. /* Rest of the memory */
  525. wcd9xxx_slim_write_repeat(wcd9xxx,
  526. WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2,
  527. ARRAY_SIZE(mem_enable_values),
  528. mem_enable_values);
  529. wcd9xxx_slim_write_repeat(wcd9xxx,
  530. WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3,
  531. ARRAY_SIZE(mem_enable_values),
  532. mem_enable_values);
  533. snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN,
  534. 0x05);
  535. break;
  536. default:
  537. dev_err(cntl->codec->dev, "%s: Invalid mem_type %d\n",
  538. __func__, mem_type);
  539. ret = -EINVAL;
  540. break;
  541. }
  542. done:
  543. /* Make sure Deep sleep of memories is enabled for all banks */
  544. snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0, 0xFF);
  545. snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1, 0x0F);
  546. return ret;
  547. }
  548. static void wcd_cntl_disable_memory(struct wcd_dsp_cntl *cntl,
  549. enum wcd_mem_type mem_type)
  550. {
  551. struct snd_soc_codec *codec = cntl->codec;
  552. u8 val;
  553. switch (mem_type) {
  554. case WCD_MEM_TYPE_ALWAYS_ON:
  555. snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1,
  556. 0xFF);
  557. snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0,
  558. 0xFF);
  559. break;
  560. case WCD_MEM_TYPE_SWITCHABLE:
  561. snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3,
  562. 0xFF);
  563. snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2,
  564. 0xFF);
  565. snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN,
  566. 0x07);
  567. snd_soc_update_bits(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
  568. 0x01, 0x00);
  569. val = snd_soc_read(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL);
  570. if (val & 0x02)
  571. dev_err(codec->dev,
  572. "%s: Disable switchable failed, val = 0x%02x",
  573. __func__, val);
  574. snd_soc_update_bits(codec, WCD934X_TEST_DEBUG_MEM_CTRL,
  575. 0x80, 0x00);
  576. break;
  577. default:
  578. dev_err(cntl->codec->dev, "%s: Invalid mem_type %d\n",
  579. __func__, mem_type);
  580. break;
  581. }
  582. snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0, 0xFF);
  583. snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1, 0x0F);
  584. }
  585. static void wcd_cntl_do_shutdown(struct wcd_dsp_cntl *cntl)
  586. {
  587. struct snd_soc_codec *codec = cntl->codec;
  588. /* Disable WDOG */
  589. snd_soc_update_bits(codec, WCD934X_CPE_SS_WDOG_CFG,
  590. 0x3F, 0x01);
  591. /* Put WDSP in reset state */
  592. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPE_CTL,
  593. 0x02, 0x00);
  594. /* If DSP transitions from boot to shutdown, then vote for SVS */
  595. if (cntl->is_wdsp_booted)
  596. cntl->cdc_cb->cdc_vote_svs(codec, true);
  597. cntl->is_wdsp_booted = false;
  598. }
  599. static int wcd_cntl_do_boot(struct wcd_dsp_cntl *cntl)
  600. {
  601. struct snd_soc_codec *codec = cntl->codec;
  602. int ret = 0;
  603. /*
  604. * Debug mode is set from debugfs file node. If debug_mode
  605. * is set, then do not configure the watchdog timer. This
  606. * will be required for debugging the DSP firmware.
  607. */
  608. if (cntl->debug_mode) {
  609. snd_soc_update_bits(codec, WCD934X_CPE_SS_WDOG_CFG,
  610. 0x3F, 0x01);
  611. } else {
  612. snd_soc_update_bits(codec, WCD934X_CPE_SS_WDOG_CFG,
  613. 0x3F, 0x21);
  614. }
  615. /* Make sure all the error interrupts are cleared */
  616. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_0A, 0xFF);
  617. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_CLEAR_0B, 0xFF);
  618. reinit_completion(&cntl->boot_complete);
  619. /* Remove WDSP out of reset */
  620. snd_soc_update_bits(codec, WCD934X_CPE_SS_CPE_CTL,
  621. 0x02, 0x02);
  622. /*
  623. * In debug mode, DSP may not boot up normally,
  624. * wait indefinitely for DSP to boot.
  625. */
  626. if (cntl->debug_mode) {
  627. wait_for_completion(&cntl->boot_complete);
  628. dev_dbg(codec->dev, "%s: WDSP booted in dbg mode\n", __func__);
  629. cntl->is_wdsp_booted = true;
  630. goto done;
  631. }
  632. /* Boot in normal mode */
  633. ret = wait_for_completion_timeout(&cntl->boot_complete,
  634. msecs_to_jiffies(WCD_DSP_BOOT_TIMEOUT_MS));
  635. if (!ret) {
  636. dev_err(codec->dev, "%s: WDSP boot timed out\n",
  637. __func__);
  638. if (cntl->dbg_dmp_enable)
  639. wcd_cntl_collect_debug_dumps(cntl, true);
  640. ret = -ETIMEDOUT;
  641. goto err_boot;
  642. } else {
  643. /*
  644. * Re-initialize the return code to 0, as in success case,
  645. * it will hold the remaining time for completion timeout
  646. */
  647. ret = 0;
  648. }
  649. dev_dbg(codec->dev, "%s: WDSP booted in normal mode\n", __func__);
  650. cntl->is_wdsp_booted = true;
  651. /* Enable WDOG */
  652. snd_soc_update_bits(codec, WCD934X_CPE_SS_WDOG_CFG,
  653. 0x10, 0x10);
  654. done:
  655. /* If dsp booted up, then remove vote on SVS */
  656. if (cntl->is_wdsp_booted)
  657. cntl->cdc_cb->cdc_vote_svs(codec, false);
  658. return ret;
  659. err_boot:
  660. /* call shutdown to perform cleanup */
  661. wcd_cntl_do_shutdown(cntl);
  662. return ret;
  663. }
  664. static irqreturn_t wcd_cntl_ipc_irq(int irq, void *data)
  665. {
  666. struct wcd_dsp_cntl *cntl = data;
  667. int ret;
  668. complete(&cntl->boot_complete);
  669. if (cntl->m_dev && cntl->m_ops &&
  670. cntl->m_ops->signal_handler)
  671. ret = cntl->m_ops->signal_handler(cntl->m_dev, WDSP_IPC1_INTR,
  672. NULL);
  673. else
  674. ret = -EINVAL;
  675. if (ret < 0)
  676. dev_err(cntl->codec->dev,
  677. "%s: Failed to handle irq %d\n", __func__, irq);
  678. return IRQ_HANDLED;
  679. }
  680. static irqreturn_t wcd_cntl_err_irq(int irq, void *data)
  681. {
  682. struct wcd_dsp_cntl *cntl = data;
  683. struct snd_soc_codec *codec = cntl->codec;
  684. struct wdsp_err_signal_arg arg;
  685. u16 status = 0;
  686. u8 reg_val;
  687. int rc, ret = 0;
  688. reg_val = snd_soc_read(codec, WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0A);
  689. status = status | reg_val;
  690. reg_val = snd_soc_read(codec, WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0B);
  691. status = status | (reg_val << 8);
  692. dev_info(codec->dev, "%s: error interrupt status = 0x%x\n",
  693. __func__, status);
  694. if ((status & cntl->irqs.fatal_irqs) &&
  695. (cntl->m_dev && cntl->m_ops && cntl->m_ops->signal_handler)) {
  696. /*
  697. * If WDSP SSR happens, skip collecting debug dumps.
  698. * If debug dumps collecting happens first, WDSP_ERR_INTR
  699. * will be blocked in signal_handler and get processed later.
  700. */
  701. rc = WCD_CNTL_SET_ERR_IRQ_FLAG(cntl);
  702. arg.mem_dumps_enabled = cntl->ramdump_enable;
  703. arg.remote_start_addr = WCD_934X_RAMDUMP_START_ADDR;
  704. arg.dump_size = WCD_934X_RAMDUMP_SIZE;
  705. ret = cntl->m_ops->signal_handler(cntl->m_dev, WDSP_ERR_INTR,
  706. &arg);
  707. if (ret < 0)
  708. dev_err(cntl->codec->dev,
  709. "%s: Failed to handle fatal irq 0x%x\n",
  710. __func__, status & cntl->irqs.fatal_irqs);
  711. wcd_cntl_change_online_state(cntl, 0);
  712. if (rc == 0)
  713. WCD_CNTL_CLR_ERR_IRQ_FLAG(cntl);
  714. } else {
  715. dev_err(cntl->codec->dev, "%s: Invalid signal_handler\n",
  716. __func__);
  717. }
  718. return IRQ_HANDLED;
  719. }
  720. static int wcd_control_handler(struct device *dev, void *priv_data,
  721. enum wdsp_event_type event, void *data)
  722. {
  723. struct wcd_dsp_cntl *cntl = priv_data;
  724. struct snd_soc_codec *codec = cntl->codec;
  725. int ret = 0;
  726. switch (event) {
  727. case WDSP_EVENT_POST_INIT:
  728. case WDSP_EVENT_POST_DLOAD_CODE:
  729. case WDSP_EVENT_DLOAD_FAILED:
  730. case WDSP_EVENT_POST_SHUTDOWN:
  731. /* Disable CPAR */
  732. wcd_cntl_cpar_ctrl(cntl, false);
  733. /* Disable all the clocks */
  734. ret = wcd_cntl_clocks_disable(cntl);
  735. if (ret < 0)
  736. dev_err(codec->dev,
  737. "%s: Failed to disable clocks, err = %d\n",
  738. __func__, ret);
  739. if (event == WDSP_EVENT_POST_DLOAD_CODE)
  740. /* Mark DSP online since code download is complete */
  741. wcd_cntl_change_online_state(cntl, 1);
  742. break;
  743. case WDSP_EVENT_PRE_DLOAD_DATA:
  744. case WDSP_EVENT_PRE_DLOAD_CODE:
  745. /* Enable all the clocks */
  746. ret = wcd_cntl_clocks_enable(cntl);
  747. if (ret < 0) {
  748. dev_err(codec->dev,
  749. "%s: Failed to enable clocks, err = %d\n",
  750. __func__, ret);
  751. goto done;
  752. }
  753. /* Enable CPAR */
  754. wcd_cntl_cpar_ctrl(cntl, true);
  755. if (event == WDSP_EVENT_PRE_DLOAD_CODE)
  756. wcd_cntl_enable_memory(cntl, WCD_MEM_TYPE_ALWAYS_ON);
  757. else if (event == WDSP_EVENT_PRE_DLOAD_DATA)
  758. wcd_cntl_enable_memory(cntl, WCD_MEM_TYPE_SWITCHABLE);
  759. break;
  760. case WDSP_EVENT_DO_BOOT:
  761. ret = wcd_cntl_do_boot(cntl);
  762. if (ret < 0)
  763. dev_err(codec->dev,
  764. "%s: WDSP boot failed, err = %d\n",
  765. __func__, ret);
  766. break;
  767. case WDSP_EVENT_DO_SHUTDOWN:
  768. wcd_cntl_do_shutdown(cntl);
  769. wcd_cntl_disable_memory(cntl, WCD_MEM_TYPE_SWITCHABLE);
  770. break;
  771. default:
  772. dev_dbg(codec->dev, "%s: unhandled event %d\n",
  773. __func__, event);
  774. }
  775. done:
  776. return ret;
  777. }
  778. static int wcd_cntl_sysfs_init(char *dir, struct wcd_dsp_cntl *cntl)
  779. {
  780. struct snd_soc_codec *codec = cntl->codec;
  781. int ret = 0;
  782. ret = kobject_init_and_add(&cntl->wcd_kobj, &wcd_cntl_ktype,
  783. kernel_kobj, dir);
  784. if (ret < 0) {
  785. dev_err(codec->dev,
  786. "%s: Failed to add kobject %s, err = %d\n",
  787. __func__, dir, ret);
  788. goto done;
  789. }
  790. ret = sysfs_create_file(&cntl->wcd_kobj, &cntl_attr_boot.attr);
  791. if (ret < 0) {
  792. dev_err(codec->dev,
  793. "%s: Failed to add wdsp_boot sysfs entry to %s\n",
  794. __func__, dir);
  795. goto fail_create_file;
  796. }
  797. return ret;
  798. fail_create_file:
  799. kobject_put(&cntl->wcd_kobj);
  800. done:
  801. return ret;
  802. }
  803. static void wcd_cntl_sysfs_remove(struct wcd_dsp_cntl *cntl)
  804. {
  805. sysfs_remove_file(&cntl->wcd_kobj, &cntl_attr_boot.attr);
  806. kobject_put(&cntl->wcd_kobj);
  807. }
  808. static void wcd_cntl_debugfs_init(char *dir, struct wcd_dsp_cntl *cntl)
  809. {
  810. struct snd_soc_codec *codec = cntl->codec;
  811. cntl->entry = debugfs_create_dir(dir, NULL);
  812. if (IS_ERR_OR_NULL(dir)) {
  813. dev_err(codec->dev, "%s debugfs_create_dir failed for %s\n",
  814. __func__, dir);
  815. goto done;
  816. }
  817. debugfs_create_u32("debug_mode", 0644,
  818. cntl->entry, &cntl->debug_mode);
  819. debugfs_create_bool("ramdump_enable", 0644,
  820. cntl->entry, &cntl->ramdump_enable);
  821. debugfs_create_bool("debug_dump_enable", 0644,
  822. cntl->entry, &cntl->dbg_dmp_enable);
  823. done:
  824. return;
  825. }
  826. static void wcd_cntl_debugfs_remove(struct wcd_dsp_cntl *cntl)
  827. {
  828. if (cntl)
  829. debugfs_remove(cntl->entry);
  830. }
  831. static int wcd_miscdev_release(struct inode *inode, struct file *filep)
  832. {
  833. struct wcd_dsp_cntl *cntl = container_of(filep->private_data,
  834. struct wcd_dsp_cntl, miscdev);
  835. if (!cntl->m_dev || !cntl->m_ops ||
  836. !cntl->m_ops->vote_for_dsp) {
  837. dev_err(cntl->codec->dev,
  838. "%s: DSP not ready to boot\n", __func__);
  839. return -EINVAL;
  840. }
  841. /* Make sure the DSP users goes to zero upon closing dev node */
  842. while (cntl->boot_reqs > 0) {
  843. cntl->m_ops->vote_for_dsp(cntl->m_dev, false);
  844. cntl->boot_reqs--;
  845. }
  846. return 0;
  847. }
  848. static ssize_t wcd_miscdev_write(struct file *filep, const char __user *ubuf,
  849. size_t count, loff_t *pos)
  850. {
  851. struct wcd_dsp_cntl *cntl = container_of(filep->private_data,
  852. struct wcd_dsp_cntl, miscdev);
  853. char val[WCD_MISCDEV_CMD_MAX_LEN + 1];
  854. bool vote;
  855. int ret = 0;
  856. memset(val, 0, WCD_MISCDEV_CMD_MAX_LEN + 1);
  857. if (count == 0 || count > WCD_MISCDEV_CMD_MAX_LEN) {
  858. pr_err("%s: Invalid count = %zd\n", __func__, count);
  859. ret = -EINVAL;
  860. goto done;
  861. }
  862. ret = copy_from_user(val, ubuf, count);
  863. if (ret < 0) {
  864. dev_err(cntl->codec->dev,
  865. "%s: copy_from_user failed, err = %d\n",
  866. __func__, ret);
  867. ret = -EFAULT;
  868. goto done;
  869. }
  870. if (val[0] == '1') {
  871. cntl->boot_reqs++;
  872. vote = true;
  873. } else if (val[0] == '0') {
  874. if (cntl->boot_reqs == 0) {
  875. dev_err(cntl->codec->dev,
  876. "%s: WDSP already disabled\n",
  877. __func__);
  878. ret = -EINVAL;
  879. goto done;
  880. }
  881. cntl->boot_reqs--;
  882. vote = false;
  883. } else if (!strcmp(val, "DEBUG_DUMP")) {
  884. if (cntl->dbg_dmp_enable) {
  885. dev_dbg(cntl->codec->dev,
  886. "%s: Collect dumps for debug use\n", __func__);
  887. wcd_cntl_collect_debug_dumps(cntl, false);
  888. }
  889. /*
  890. * simply ignore the request from userspace
  891. * if dbg_dump_enable is not set from debugfs
  892. */
  893. goto done;
  894. } else {
  895. dev_err(cntl->codec->dev, "%s: Invalid value %s\n",
  896. __func__, val);
  897. ret = -EINVAL;
  898. goto done;
  899. }
  900. dev_dbg(cntl->codec->dev,
  901. "%s: booted = %s, ref_cnt = %d, vote = %s\n",
  902. __func__, cntl->is_wdsp_booted ? "true" : "false",
  903. cntl->boot_reqs, vote ? "true" : "false");
  904. if (cntl->m_dev && cntl->m_ops &&
  905. cntl->m_ops->vote_for_dsp)
  906. ret = cntl->m_ops->vote_for_dsp(cntl->m_dev, vote);
  907. else
  908. ret = -EINVAL;
  909. done:
  910. if (ret)
  911. return ret;
  912. else
  913. return count;
  914. }
  915. static const struct file_operations wcd_miscdev_fops = {
  916. .write = wcd_miscdev_write,
  917. .release = wcd_miscdev_release,
  918. };
  919. static int wcd_cntl_miscdev_create(struct wcd_dsp_cntl *cntl)
  920. {
  921. snprintf(cntl->miscdev_name, ARRAY_SIZE(cntl->miscdev_name),
  922. "wcd_dsp%u_control", cntl->dsp_instance);
  923. cntl->miscdev.minor = MISC_DYNAMIC_MINOR;
  924. cntl->miscdev.name = cntl->miscdev_name;
  925. cntl->miscdev.fops = &wcd_miscdev_fops;
  926. cntl->miscdev.parent = cntl->codec->dev;
  927. return misc_register(&cntl->miscdev);
  928. }
  929. static void wcd_cntl_miscdev_destroy(struct wcd_dsp_cntl *cntl)
  930. {
  931. misc_deregister(&cntl->miscdev);
  932. }
  933. static int wcd_control_init(struct device *dev, void *priv_data)
  934. {
  935. struct wcd_dsp_cntl *cntl = priv_data;
  936. struct snd_soc_codec *codec = cntl->codec;
  937. struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
  938. struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
  939. int ret;
  940. bool err_irq_requested = false;
  941. ret = wcd9xxx_request_irq(core_res,
  942. cntl->irqs.cpe_ipc1_irq,
  943. wcd_cntl_ipc_irq, "CPE IPC1",
  944. cntl);
  945. if (ret < 0) {
  946. dev_err(codec->dev,
  947. "%s: Failed to request cpe ipc irq, err = %d\n",
  948. __func__, ret);
  949. goto done;
  950. }
  951. /* Unmask the fatal irqs */
  952. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A,
  953. ~(cntl->irqs.fatal_irqs & 0xFF));
  954. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B,
  955. ~((cntl->irqs.fatal_irqs >> 8) & 0xFF));
  956. /*
  957. * CPE ERR irq is used only for error reporting from WCD DSP,
  958. * even if this request fails, DSP can be function normally.
  959. * Continuing with init even if the CPE ERR irq request fails.
  960. */
  961. if (wcd9xxx_request_irq(core_res, cntl->irqs.cpe_err_irq,
  962. wcd_cntl_err_irq, "CPE ERR", cntl))
  963. dev_info(codec->dev, "%s: Failed request_irq(cpe_err_irq)",
  964. __func__);
  965. else
  966. err_irq_requested = true;
  967. /* Enable all the clocks */
  968. ret = wcd_cntl_clocks_enable(cntl);
  969. if (ret < 0) {
  970. dev_err(codec->dev, "%s: Failed to enable clocks, err = %d\n",
  971. __func__, ret);
  972. goto err_clk_enable;
  973. }
  974. wcd_cntl_cpar_ctrl(cntl, true);
  975. return 0;
  976. err_clk_enable:
  977. /* Mask all error interrupts */
  978. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A, 0xFF);
  979. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B, 0xFF);
  980. /* Free the irq's requested */
  981. wcd9xxx_free_irq(core_res, cntl->irqs.cpe_ipc1_irq, cntl);
  982. if (err_irq_requested)
  983. wcd9xxx_free_irq(core_res, cntl->irqs.cpe_err_irq, cntl);
  984. done:
  985. return ret;
  986. }
  987. static int wcd_control_deinit(struct device *dev, void *priv_data)
  988. {
  989. struct wcd_dsp_cntl *cntl = priv_data;
  990. struct snd_soc_codec *codec = cntl->codec;
  991. struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
  992. struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
  993. wcd_cntl_clocks_disable(cntl);
  994. wcd_cntl_cpar_ctrl(cntl, false);
  995. /* Mask all error interrupts */
  996. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A, 0xFF);
  997. snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B, 0xFF);
  998. /* Free the irq's requested */
  999. wcd9xxx_free_irq(core_res, cntl->irqs.cpe_err_irq, cntl);
  1000. wcd9xxx_free_irq(core_res, cntl->irqs.cpe_ipc1_irq, cntl);
  1001. return 0;
  1002. }
  1003. static struct wdsp_cmpnt_ops control_ops = {
  1004. .init = wcd_control_init,
  1005. .deinit = wcd_control_deinit,
  1006. .event_handler = wcd_control_handler,
  1007. };
  1008. static int wcd_ctrl_component_bind(struct device *dev,
  1009. struct device *master,
  1010. void *data)
  1011. {
  1012. struct wcd_dsp_cntl *cntl;
  1013. struct snd_soc_codec *codec;
  1014. struct snd_card *card;
  1015. struct snd_info_entry *entry;
  1016. char proc_name[WCD_PROCFS_ENTRY_MAX_LEN];
  1017. char wcd_cntl_dir_name[WCD_CNTL_DIR_NAME_LEN_MAX];
  1018. int ret = 0;
  1019. if (!dev || !master || !data) {
  1020. pr_err("%s: Invalid parameters\n", __func__);
  1021. return -EINVAL;
  1022. }
  1023. cntl = tavil_get_wcd_dsp_cntl(dev);
  1024. if (!cntl) {
  1025. dev_err(dev, "%s: Failed to get cntl reference\n",
  1026. __func__);
  1027. return -EINVAL;
  1028. }
  1029. cntl->m_dev = master;
  1030. cntl->m_ops = data;
  1031. if (!cntl->m_ops->register_cmpnt_ops) {
  1032. dev_err(dev, "%s: invalid master callback register_cmpnt_ops\n",
  1033. __func__);
  1034. ret = -EINVAL;
  1035. goto done;
  1036. }
  1037. ret = cntl->m_ops->register_cmpnt_ops(master, dev, cntl, &control_ops);
  1038. if (ret) {
  1039. dev_err(dev, "%s: register_cmpnt_ops failed, err = %d\n",
  1040. __func__, ret);
  1041. goto done;
  1042. }
  1043. ret = wcd_cntl_miscdev_create(cntl);
  1044. if (ret < 0) {
  1045. dev_err(dev, "%s: misc dev register failed, err = %d\n",
  1046. __func__, ret);
  1047. goto done;
  1048. }
  1049. snprintf(wcd_cntl_dir_name, WCD_CNTL_DIR_NAME_LEN_MAX,
  1050. "%s%d", "wdsp", cntl->dsp_instance);
  1051. ret = wcd_cntl_sysfs_init(wcd_cntl_dir_name, cntl);
  1052. if (ret < 0) {
  1053. dev_err(dev, "%s: sysfs_init failed, err = %d\n",
  1054. __func__, ret);
  1055. goto err_sysfs_init;
  1056. }
  1057. wcd_cntl_debugfs_init(wcd_cntl_dir_name, cntl);
  1058. codec = cntl->codec;
  1059. card = codec->component.card->snd_card;
  1060. snprintf(proc_name, WCD_PROCFS_ENTRY_MAX_LEN, "%s%d%s", "cpe",
  1061. cntl->dsp_instance, "_state");
  1062. entry = snd_info_create_card_entry(card, proc_name, card->proc_root);
  1063. if (!entry) {
  1064. /* Do not treat this as Fatal error */
  1065. dev_err(dev, "%s: Failed to create procfs entry %s\n",
  1066. __func__, proc_name);
  1067. goto err_sysfs_init;
  1068. }
  1069. cntl->ssr_entry.entry = entry;
  1070. cntl->ssr_entry.offline = 1;
  1071. entry->size = WCD_PROCFS_ENTRY_MAX_LEN;
  1072. entry->content = SNDRV_INFO_CONTENT_DATA;
  1073. entry->c.ops = &wdsp_ssr_entry_ops;
  1074. entry->private_data = cntl;
  1075. ret = snd_info_register(entry);
  1076. if (ret < 0) {
  1077. dev_err(dev, "%s: Failed to register entry %s, err = %d\n",
  1078. __func__, proc_name, ret);
  1079. snd_info_free_entry(entry);
  1080. /* Let bind still happen even if creating the entry failed */
  1081. ret = 0;
  1082. }
  1083. done:
  1084. return ret;
  1085. err_sysfs_init:
  1086. wcd_cntl_miscdev_destroy(cntl);
  1087. return ret;
  1088. }
  1089. static void wcd_ctrl_component_unbind(struct device *dev,
  1090. struct device *master,
  1091. void *data)
  1092. {
  1093. struct wcd_dsp_cntl *cntl;
  1094. if (!dev) {
  1095. pr_err("%s: Invalid device\n", __func__);
  1096. return;
  1097. }
  1098. cntl = tavil_get_wcd_dsp_cntl(dev);
  1099. if (!cntl) {
  1100. dev_err(dev, "%s: Failed to get cntl reference\n",
  1101. __func__);
  1102. return;
  1103. }
  1104. cntl->m_dev = NULL;
  1105. cntl->m_ops = NULL;
  1106. /* Remove the sysfs entries */
  1107. wcd_cntl_sysfs_remove(cntl);
  1108. /* Remove the debugfs entries */
  1109. wcd_cntl_debugfs_remove(cntl);
  1110. /* Remove the misc device */
  1111. wcd_cntl_miscdev_destroy(cntl);
  1112. }
  1113. static const struct component_ops wcd_ctrl_component_ops = {
  1114. .bind = wcd_ctrl_component_bind,
  1115. .unbind = wcd_ctrl_component_unbind,
  1116. };
  1117. /*
  1118. * wcd_dsp_ssr_event: handle the SSR event raised by caller.
  1119. * @cntl: Handle to the wcd_dsp_cntl structure
  1120. * @event: The SSR event to be handled
  1121. *
  1122. * Notifies the manager driver about the SSR event.
  1123. * Returns 0 on success and negative error code on error.
  1124. */
  1125. int wcd_dsp_ssr_event(struct wcd_dsp_cntl *cntl, enum cdc_ssr_event event)
  1126. {
  1127. int ret = 0;
  1128. if (!cntl) {
  1129. pr_err("%s: Invalid handle to control\n", __func__);
  1130. return -EINVAL;
  1131. }
  1132. if (!cntl->m_dev || !cntl->m_ops || !cntl->m_ops->signal_handler) {
  1133. dev_err(cntl->codec->dev,
  1134. "%s: Invalid signal_handler callback\n", __func__);
  1135. return -EINVAL;
  1136. }
  1137. switch (event) {
  1138. case WCD_CDC_DOWN_EVENT:
  1139. ret = cntl->m_ops->signal_handler(cntl->m_dev,
  1140. WDSP_CDC_DOWN_SIGNAL,
  1141. NULL);
  1142. if (ret < 0)
  1143. dev_err(cntl->codec->dev,
  1144. "%s: WDSP_CDC_DOWN_SIGNAL failed, err = %d\n",
  1145. __func__, ret);
  1146. wcd_cntl_change_online_state(cntl, 0);
  1147. break;
  1148. case WCD_CDC_UP_EVENT:
  1149. ret = cntl->m_ops->signal_handler(cntl->m_dev,
  1150. WDSP_CDC_UP_SIGNAL,
  1151. NULL);
  1152. if (ret < 0)
  1153. dev_err(cntl->codec->dev,
  1154. "%s: WDSP_CDC_UP_SIGNAL failed, err = %d\n",
  1155. __func__, ret);
  1156. break;
  1157. default:
  1158. dev_err(cntl->codec->dev, "%s: Invalid event %d\n",
  1159. __func__, event);
  1160. ret = -EINVAL;
  1161. break;
  1162. }
  1163. return ret;
  1164. }
  1165. EXPORT_SYMBOL(wcd_dsp_ssr_event);
  1166. /*
  1167. * wcd_dsp_cntl_init: Initialize the wcd-dsp control
  1168. * @codec: pointer to the codec handle
  1169. * @params: Parameters required to initialize wcd-dsp control
  1170. *
  1171. * This API is expected to be invoked by the codec driver and
  1172. * provide information essential for the wcd dsp control to
  1173. * configure and initialize the dsp
  1174. */
  1175. void wcd_dsp_cntl_init(struct snd_soc_codec *codec,
  1176. struct wcd_dsp_params *params,
  1177. struct wcd_dsp_cntl **cntl)
  1178. {
  1179. struct wcd_dsp_cntl *control;
  1180. int ret;
  1181. if (!codec || !params) {
  1182. pr_err("%s: Invalid handle to %s\n", __func__,
  1183. (!codec) ? "codec" : "params");
  1184. *cntl = NULL;
  1185. return;
  1186. }
  1187. if (*cntl) {
  1188. pr_err("%s: cntl is non NULL, maybe already initialized ?\n",
  1189. __func__);
  1190. return;
  1191. }
  1192. if (!params->cb || !params->cb->cdc_clk_en ||
  1193. !params->cb->cdc_vote_svs) {
  1194. dev_err(codec->dev,
  1195. "%s: clk_en and vote_svs callbacks must be provided\n",
  1196. __func__);
  1197. return;
  1198. }
  1199. control = kzalloc(sizeof(*control), GFP_KERNEL);
  1200. if (!(control))
  1201. return;
  1202. control->codec = codec;
  1203. control->clk_rate = params->clk_rate;
  1204. control->cdc_cb = params->cb;
  1205. control->dsp_instance = params->dsp_instance;
  1206. memcpy(&control->irqs, &params->irqs, sizeof(control->irqs));
  1207. init_completion(&control->boot_complete);
  1208. mutex_init(&control->clk_mutex);
  1209. mutex_init(&control->ssr_mutex);
  1210. init_waitqueue_head(&control->ssr_entry.offline_poll_wait);
  1211. WCD_CNTL_CLR_ERR_IRQ_FLAG(control);
  1212. /*
  1213. * The default state of WDSP is in SVS mode.
  1214. * Vote for SVS now, the vote will be removed only
  1215. * after DSP is booted up.
  1216. */
  1217. control->cdc_cb->cdc_vote_svs(codec, true);
  1218. /*
  1219. * If this is the last component needed by master to be ready,
  1220. * then component_bind will be called within the component_add.
  1221. * Hence, the data pointer should be assigned before component_add,
  1222. * so that we can access it during this component's bind call.
  1223. */
  1224. *cntl = control;
  1225. ret = component_add(codec->dev, &wcd_ctrl_component_ops);
  1226. if (ret) {
  1227. dev_err(codec->dev, "%s: component_add failed, err = %d\n",
  1228. __func__, ret);
  1229. kfree(*cntl);
  1230. *cntl = NULL;
  1231. }
  1232. }
  1233. EXPORT_SYMBOL(wcd_dsp_cntl_init);
  1234. /*
  1235. * wcd_dsp_cntl_deinit: De-initialize the wcd-dsp control
  1236. * @cntl: The struct wcd_dsp_cntl to de-initialize
  1237. *
  1238. * This API is intended to be invoked by the codec driver
  1239. * to de-initialize the wcd dsp control
  1240. */
  1241. void wcd_dsp_cntl_deinit(struct wcd_dsp_cntl **cntl)
  1242. {
  1243. struct wcd_dsp_cntl *control = *cntl;
  1244. struct snd_soc_codec *codec;
  1245. /* If control is NULL, there is nothing to de-initialize */
  1246. if (!control)
  1247. return;
  1248. codec = control->codec;
  1249. /*
  1250. * Calling shutdown will cleanup all register states,
  1251. * irrespective of DSP was booted up or not.
  1252. */
  1253. wcd_cntl_do_shutdown(control);
  1254. wcd_cntl_disable_memory(control, WCD_MEM_TYPE_SWITCHABLE);
  1255. wcd_cntl_disable_memory(control, WCD_MEM_TYPE_ALWAYS_ON);
  1256. component_del(codec->dev, &wcd_ctrl_component_ops);
  1257. mutex_destroy(&control->clk_mutex);
  1258. mutex_destroy(&control->ssr_mutex);
  1259. kfree(*cntl);
  1260. *cntl = NULL;
  1261. }
  1262. EXPORT_SYMBOL(wcd_dsp_cntl_deinit);