wcd-dsp-mgr.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/module.h>
  6. #include <linux/platform_device.h>
  7. #include <linux/slab.h>
  8. #include <linux/stringify.h>
  9. #include <linux/of.h>
  10. #include <linux/debugfs.h>
  11. #include <linux/component.h>
  12. #include <linux/dma-mapping.h>
  13. #include <soc/qcom/ramdump.h>
  14. #include <sound/wcd-dsp-mgr.h>
  15. #include "wcd-dsp-utils.h"
  16. /* Forward declarations */
  17. static char *wdsp_get_cmpnt_type_string(enum wdsp_cmpnt_type);
  18. /* Component related macros */
  19. #define WDSP_GET_COMPONENT(wdsp, x) ((x >= WDSP_CMPNT_TYPE_MAX || x < 0) ? \
  20. NULL : (&(wdsp->cmpnts[x])))
  21. #define WDSP_GET_CMPNT_TYPE_STR(x) wdsp_get_cmpnt_type_string(x)
  22. /*
  23. * These #defines indicate the bit number in status field
  24. * for each of the status. If bit is set, it indicates
  25. * the status as done, else if bit is not set, it indicates
  26. * the status is either failed or not done.
  27. */
  28. #define WDSP_STATUS_INITIALIZED BIT(0)
  29. #define WDSP_STATUS_CODE_DLOADED BIT(1)
  30. #define WDSP_STATUS_DATA_DLOADED BIT(2)
  31. #define WDSP_STATUS_BOOTED BIT(3)
  32. /* Helper macros for printing wdsp messages */
  33. #define WDSP_ERR(wdsp, fmt, ...) \
  34. dev_err(wdsp->mdev, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
  35. #define WDSP_DBG(wdsp, fmt, ...) \
  36. dev_dbg(wdsp->mdev, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
  37. /* Helper macros for locking */
  38. #define WDSP_MGR_MUTEX_LOCK(wdsp, lock) \
  39. { \
  40. WDSP_DBG(wdsp, "mutex_lock(%s)", \
  41. __stringify_1(lock)); \
  42. mutex_lock(&lock); \
  43. }
  44. #define WDSP_MGR_MUTEX_UNLOCK(wdsp, lock) \
  45. { \
  46. WDSP_DBG(wdsp, "mutex_unlock(%s)", \
  47. __stringify_1(lock)); \
  48. mutex_unlock(&lock); \
  49. }
  50. /* Helper macros for using status mask */
  51. #define WDSP_SET_STATUS(wdsp, state) \
  52. { \
  53. wdsp->status |= state; \
  54. WDSP_DBG(wdsp, "set 0x%lx, new_state = 0x%x", \
  55. state, wdsp->status); \
  56. }
  57. #define WDSP_CLEAR_STATUS(wdsp, state) \
  58. { \
  59. wdsp->status &= (~state); \
  60. WDSP_DBG(wdsp, "clear 0x%lx, new_state = 0x%x", \
  61. state, wdsp->status); \
  62. }
  63. #define WDSP_STATUS_IS_SET(wdsp, state) (wdsp->status & state)
  64. /* SSR relate status macros */
  65. #define WDSP_SSR_STATUS_WDSP_READY BIT(0)
  66. #define WDSP_SSR_STATUS_CDC_READY BIT(1)
  67. #define WDSP_SSR_STATUS_READY \
  68. (WDSP_SSR_STATUS_WDSP_READY | WDSP_SSR_STATUS_CDC_READY)
  69. #define WDSP_SSR_READY_WAIT_TIMEOUT (10 * HZ)
  70. enum wdsp_ssr_type {
  71. /* Init value, indicates there is no SSR in progress */
  72. WDSP_SSR_TYPE_NO_SSR = 0,
  73. /*
  74. * Indicates WDSP crashed. The manager driver internally
  75. * decides when to perform WDSP restart based on the
  76. * users of wdsp. Hence there is no explicit WDSP_UP.
  77. */
  78. WDSP_SSR_TYPE_WDSP_DOWN,
  79. /* Indicates codec hardware is down */
  80. WDSP_SSR_TYPE_CDC_DOWN,
  81. /* Indicates codec hardware is up, trigger to restart WDSP */
  82. WDSP_SSR_TYPE_CDC_UP,
  83. };
  84. struct wdsp_cmpnt {
  85. /* OF node of the phandle */
  86. struct device_node *np;
  87. /*
  88. * Child component's dev_name, should be set in DT for the child's
  89. * phandle if child's dev->of_node does not match the phandle->of_node
  90. */
  91. const char *cdev_name;
  92. /* Child component's device node */
  93. struct device *cdev;
  94. /* Private data that component may want back on callbacks */
  95. void *priv_data;
  96. /* Child ops */
  97. struct wdsp_cmpnt_ops *ops;
  98. };
  99. struct wdsp_ramdump_data {
  100. /* Ramdump device */
  101. void *rd_dev;
  102. /* DMA address of the dump */
  103. dma_addr_t rd_addr;
  104. /* Virtual address of the dump */
  105. void *rd_v_addr;
  106. /* Data provided through error interrupt */
  107. struct wdsp_err_signal_arg err_data;
  108. };
  109. struct wdsp_mgr_priv {
  110. /* Manager driver's struct device pointer */
  111. struct device *mdev;
  112. /* Match struct for component framework */
  113. struct component_match *match;
  114. /* Manager's ops/function callbacks */
  115. struct wdsp_mgr_ops *ops;
  116. /* Array to store information for all expected components */
  117. struct wdsp_cmpnt cmpnts[WDSP_CMPNT_TYPE_MAX];
  118. /* The filename of image to be downloaded */
  119. const char *img_fname;
  120. /* Keeps track of current state of manager driver */
  121. u32 status;
  122. /* Work to load the firmware image after component binding */
  123. struct work_struct load_fw_work;
  124. /* List of segments in image to be downloaded */
  125. struct list_head *seg_list;
  126. /* Base address of the image in memory */
  127. u32 base_addr;
  128. /* Instances using dsp */
  129. int dsp_users;
  130. /* Lock for serializing ops called by components */
  131. struct mutex api_mutex;
  132. struct wdsp_ramdump_data dump_data;
  133. /* SSR related */
  134. enum wdsp_ssr_type ssr_type;
  135. struct mutex ssr_mutex;
  136. struct work_struct ssr_work;
  137. u16 ready_status;
  138. struct completion ready_compl;
  139. /* Debugfs related */
  140. struct dentry *entry;
  141. bool panic_on_error;
  142. };
  143. static char *wdsp_get_ssr_type_string(enum wdsp_ssr_type type)
  144. {
  145. switch (type) {
  146. case WDSP_SSR_TYPE_NO_SSR:
  147. return "NO_SSR";
  148. case WDSP_SSR_TYPE_WDSP_DOWN:
  149. return "WDSP_DOWN";
  150. case WDSP_SSR_TYPE_CDC_DOWN:
  151. return "CDC_DOWN";
  152. case WDSP_SSR_TYPE_CDC_UP:
  153. return "CDC_UP";
  154. default:
  155. pr_err("%s: Invalid ssr_type %d\n",
  156. __func__, type);
  157. return "Invalid";
  158. }
  159. }
  160. static char *wdsp_get_cmpnt_type_string(enum wdsp_cmpnt_type type)
  161. {
  162. switch (type) {
  163. case WDSP_CMPNT_CONTROL:
  164. return "control";
  165. case WDSP_CMPNT_IPC:
  166. return "ipc";
  167. case WDSP_CMPNT_TRANSPORT:
  168. return "transport";
  169. default:
  170. pr_err("%s: Invalid component type %d\n",
  171. __func__, type);
  172. return "Invalid";
  173. }
  174. }
  175. static void __wdsp_clr_ready_locked(struct wdsp_mgr_priv *wdsp,
  176. u16 value)
  177. {
  178. wdsp->ready_status &= ~(value);
  179. WDSP_DBG(wdsp, "ready_status = 0x%x", wdsp->ready_status);
  180. }
  181. static void __wdsp_set_ready_locked(struct wdsp_mgr_priv *wdsp,
  182. u16 value, bool mark_complete)
  183. {
  184. wdsp->ready_status |= value;
  185. WDSP_DBG(wdsp, "ready_status = 0x%x", wdsp->ready_status);
  186. if (mark_complete &&
  187. wdsp->ready_status == WDSP_SSR_STATUS_READY) {
  188. WDSP_DBG(wdsp, "marking ready completion");
  189. complete(&wdsp->ready_compl);
  190. }
  191. }
  192. static void wdsp_broadcast_event_upseq(struct wdsp_mgr_priv *wdsp,
  193. enum wdsp_event_type event,
  194. void *data)
  195. {
  196. struct wdsp_cmpnt *cmpnt;
  197. int i;
  198. for (i = 0; i < WDSP_CMPNT_TYPE_MAX; i++) {
  199. cmpnt = WDSP_GET_COMPONENT(wdsp, i);
  200. if (cmpnt && cmpnt->ops && cmpnt->ops->event_handler)
  201. cmpnt->ops->event_handler(cmpnt->cdev, cmpnt->priv_data,
  202. event, data);
  203. }
  204. }
  205. static void wdsp_broadcast_event_downseq(struct wdsp_mgr_priv *wdsp,
  206. enum wdsp_event_type event,
  207. void *data)
  208. {
  209. struct wdsp_cmpnt *cmpnt;
  210. int i;
  211. for (i = WDSP_CMPNT_TYPE_MAX - 1; i >= 0; i--) {
  212. cmpnt = WDSP_GET_COMPONENT(wdsp, i);
  213. if (cmpnt && cmpnt->ops && cmpnt->ops->event_handler)
  214. cmpnt->ops->event_handler(cmpnt->cdev, cmpnt->priv_data,
  215. event, data);
  216. }
  217. }
  218. static int wdsp_unicast_event(struct wdsp_mgr_priv *wdsp,
  219. enum wdsp_cmpnt_type type,
  220. enum wdsp_event_type event,
  221. void *data)
  222. {
  223. struct wdsp_cmpnt *cmpnt;
  224. int ret;
  225. cmpnt = WDSP_GET_COMPONENT(wdsp, type);
  226. if (cmpnt && cmpnt->ops && cmpnt->ops->event_handler) {
  227. ret = cmpnt->ops->event_handler(cmpnt->cdev, cmpnt->priv_data,
  228. event, data);
  229. } else {
  230. WDSP_ERR(wdsp, "not valid event_handler for %s",
  231. WDSP_GET_CMPNT_TYPE_STR(type));
  232. ret = -EINVAL;
  233. }
  234. return ret;
  235. }
  236. static void wdsp_deinit_components(struct wdsp_mgr_priv *wdsp)
  237. {
  238. struct wdsp_cmpnt *cmpnt;
  239. int i;
  240. for (i = WDSP_CMPNT_TYPE_MAX - 1; i >= 0; i--) {
  241. cmpnt = WDSP_GET_COMPONENT(wdsp, i);
  242. if (cmpnt && cmpnt->ops && cmpnt->ops->deinit)
  243. cmpnt->ops->deinit(cmpnt->cdev, cmpnt->priv_data);
  244. }
  245. }
  246. static int wdsp_init_components(struct wdsp_mgr_priv *wdsp)
  247. {
  248. struct wdsp_cmpnt *cmpnt;
  249. int fail_idx = WDSP_CMPNT_TYPE_MAX;
  250. int i, ret = 0;
  251. for (i = 0; i < WDSP_CMPNT_TYPE_MAX; i++) {
  252. cmpnt = WDSP_GET_COMPONENT(wdsp, i);
  253. /* Init is allowed to be NULL */
  254. if (!cmpnt->ops || !cmpnt->ops->init)
  255. continue;
  256. ret = cmpnt->ops->init(cmpnt->cdev, cmpnt->priv_data);
  257. if (ret) {
  258. WDSP_ERR(wdsp, "Init failed (%d) for component %s",
  259. ret, WDSP_GET_CMPNT_TYPE_STR(i));
  260. fail_idx = i;
  261. break;
  262. }
  263. }
  264. if (fail_idx < WDSP_CMPNT_TYPE_MAX) {
  265. /* Undo init for already initialized components */
  266. for (i = fail_idx - 1; i >= 0; i--) {
  267. struct wdsp_cmpnt *cmpnt = WDSP_GET_COMPONENT(wdsp, i);
  268. if (cmpnt->ops && cmpnt->ops->deinit)
  269. cmpnt->ops->deinit(cmpnt->cdev,
  270. cmpnt->priv_data);
  271. }
  272. } else {
  273. wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_INIT, NULL);
  274. }
  275. return ret;
  276. }
  277. static int wdsp_load_each_segment(struct wdsp_mgr_priv *wdsp,
  278. struct wdsp_img_segment *seg)
  279. {
  280. struct wdsp_img_section img_section;
  281. int ret;
  282. WDSP_DBG(wdsp,
  283. "base_addr 0x%x, split_fname %s, load_addr 0x%x, size 0x%zx",
  284. wdsp->base_addr, seg->split_fname, seg->load_addr, seg->size);
  285. if (seg->load_addr < wdsp->base_addr) {
  286. WDSP_ERR(wdsp, "Invalid addr 0x%x, base_addr = 0x%x",
  287. seg->load_addr, wdsp->base_addr);
  288. return -EINVAL;
  289. }
  290. img_section.addr = seg->load_addr - wdsp->base_addr;
  291. img_section.size = seg->size;
  292. img_section.data = seg->data;
  293. ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_TRANSPORT,
  294. WDSP_EVENT_DLOAD_SECTION,
  295. &img_section);
  296. if (ret < 0)
  297. WDSP_ERR(wdsp,
  298. "Failed, err = %d for base_addr = 0x%x split_fname = %s, load_addr = 0x%x, size = 0x%zx",
  299. ret, wdsp->base_addr, seg->split_fname,
  300. seg->load_addr, seg->size);
  301. return ret;
  302. }
  303. static int wdsp_download_segments(struct wdsp_mgr_priv *wdsp,
  304. unsigned int type)
  305. {
  306. struct wdsp_cmpnt *ctl;
  307. struct wdsp_img_segment *seg = NULL;
  308. enum wdsp_event_type pre, post;
  309. long status;
  310. int ret;
  311. ctl = WDSP_GET_COMPONENT(wdsp, WDSP_CMPNT_CONTROL);
  312. if (type == WDSP_ELF_FLAG_RE) {
  313. pre = WDSP_EVENT_PRE_DLOAD_CODE;
  314. post = WDSP_EVENT_POST_DLOAD_CODE;
  315. status = WDSP_STATUS_CODE_DLOADED;
  316. } else if (type == WDSP_ELF_FLAG_WRITE) {
  317. pre = WDSP_EVENT_PRE_DLOAD_DATA;
  318. post = WDSP_EVENT_POST_DLOAD_DATA;
  319. status = WDSP_STATUS_DATA_DLOADED;
  320. } else {
  321. WDSP_ERR(wdsp, "Invalid type %u", type);
  322. return -EINVAL;
  323. }
  324. ret = wdsp_get_segment_list(ctl->cdev, wdsp->img_fname,
  325. type, wdsp->seg_list, &wdsp->base_addr);
  326. if (ret < 0 ||
  327. list_empty(wdsp->seg_list)) {
  328. WDSP_ERR(wdsp, "Error %d to get image segments for type %d",
  329. ret, type);
  330. wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_DLOAD_FAILED,
  331. NULL);
  332. goto done;
  333. }
  334. /* Notify all components that image is about to be downloaded */
  335. wdsp_broadcast_event_upseq(wdsp, pre, NULL);
  336. /* Go through the list of segments and download one by one */
  337. list_for_each_entry(seg, wdsp->seg_list, list) {
  338. ret = wdsp_load_each_segment(wdsp, seg);
  339. if (ret)
  340. goto dload_error;
  341. }
  342. /* Flush the list before setting status and notifying components */
  343. wdsp_flush_segment_list(wdsp->seg_list);
  344. WDSP_SET_STATUS(wdsp, status);
  345. /* Notify all components that image is downloaded */
  346. wdsp_broadcast_event_downseq(wdsp, post, NULL);
  347. done:
  348. return ret;
  349. dload_error:
  350. wdsp_flush_segment_list(wdsp->seg_list);
  351. wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_DLOAD_FAILED, NULL);
  352. return ret;
  353. }
  354. static int wdsp_init_and_dload_code_sections(struct wdsp_mgr_priv *wdsp)
  355. {
  356. int ret;
  357. bool is_initialized;
  358. is_initialized = WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_INITIALIZED);
  359. if (!is_initialized) {
  360. /* Components are not initialized yet, initialize them */
  361. ret = wdsp_init_components(wdsp);
  362. if (ret < 0) {
  363. WDSP_ERR(wdsp, "INIT failed, err = %d", ret);
  364. goto done;
  365. }
  366. WDSP_SET_STATUS(wdsp, WDSP_STATUS_INITIALIZED);
  367. }
  368. /* Download the read-execute sections of image */
  369. ret = wdsp_download_segments(wdsp, WDSP_ELF_FLAG_RE);
  370. if (ret < 0) {
  371. WDSP_ERR(wdsp, "Error %d to download code sections", ret);
  372. goto done;
  373. }
  374. done:
  375. return ret;
  376. }
  377. static void wdsp_load_fw_image(struct work_struct *work)
  378. {
  379. struct wdsp_mgr_priv *wdsp;
  380. int ret;
  381. wdsp = container_of(work, struct wdsp_mgr_priv, load_fw_work);
  382. if (!wdsp) {
  383. pr_err("%s: Invalid private_data\n", __func__);
  384. return;
  385. }
  386. ret = wdsp_init_and_dload_code_sections(wdsp);
  387. if (ret < 0)
  388. WDSP_ERR(wdsp, "dload code sections failed, err = %d", ret);
  389. }
  390. static int wdsp_enable_dsp(struct wdsp_mgr_priv *wdsp)
  391. {
  392. int ret;
  393. /* Make sure wdsp is in good state */
  394. if (!WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_CODE_DLOADED)) {
  395. WDSP_ERR(wdsp, "WDSP in invalid state 0x%x", wdsp->status);
  396. return -EINVAL;
  397. }
  398. /*
  399. * Acquire SSR mutex lock to make sure enablement of DSP
  400. * does not race with SSR handling.
  401. */
  402. WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
  403. /* Download the read-write sections of image */
  404. ret = wdsp_download_segments(wdsp, WDSP_ELF_FLAG_WRITE);
  405. if (ret < 0) {
  406. WDSP_ERR(wdsp, "Data section download failed, err = %d", ret);
  407. goto done;
  408. }
  409. wdsp_broadcast_event_upseq(wdsp, WDSP_EVENT_PRE_BOOTUP, NULL);
  410. ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_CONTROL,
  411. WDSP_EVENT_DO_BOOT, NULL);
  412. if (ret < 0) {
  413. WDSP_ERR(wdsp, "Failed to boot dsp, err = %d", ret);
  414. WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_DATA_DLOADED);
  415. goto done;
  416. }
  417. wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_BOOTUP, NULL);
  418. WDSP_SET_STATUS(wdsp, WDSP_STATUS_BOOTED);
  419. done:
  420. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
  421. return ret;
  422. }
  423. static int wdsp_disable_dsp(struct wdsp_mgr_priv *wdsp)
  424. {
  425. int ret;
  426. WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
  427. /*
  428. * If Disable happened while SSR is in progress, then set the SSR
  429. * ready status indicating WDSP is now ready. Ignore the disable
  430. * event here and let the SSR handler go through shutdown.
  431. */
  432. if (wdsp->ssr_type != WDSP_SSR_TYPE_NO_SSR) {
  433. __wdsp_set_ready_locked(wdsp, WDSP_SSR_STATUS_WDSP_READY, true);
  434. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
  435. return 0;
  436. }
  437. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
  438. /* Make sure wdsp is in good state */
  439. if (!WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_BOOTED)) {
  440. WDSP_ERR(wdsp, "wdsp in invalid state 0x%x", wdsp->status);
  441. ret = -EINVAL;
  442. goto done;
  443. }
  444. wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_PRE_SHUTDOWN, NULL);
  445. ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_CONTROL,
  446. WDSP_EVENT_DO_SHUTDOWN, NULL);
  447. if (ret < 0) {
  448. WDSP_ERR(wdsp, "Failed to shutdown dsp, err = %d", ret);
  449. goto done;
  450. }
  451. wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_SHUTDOWN, NULL);
  452. WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_BOOTED);
  453. /* Data sections are to be downloaded per boot */
  454. WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_DATA_DLOADED);
  455. done:
  456. return ret;
  457. }
  458. static int wdsp_register_cmpnt_ops(struct device *wdsp_dev,
  459. struct device *cdev,
  460. void *priv_data,
  461. struct wdsp_cmpnt_ops *ops)
  462. {
  463. struct wdsp_mgr_priv *wdsp;
  464. struct wdsp_cmpnt *cmpnt;
  465. int i, ret;
  466. if (!wdsp_dev || !cdev || !ops)
  467. return -EINVAL;
  468. wdsp = dev_get_drvdata(wdsp_dev);
  469. WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->api_mutex);
  470. for (i = 0; i < WDSP_CMPNT_TYPE_MAX; i++) {
  471. cmpnt = WDSP_GET_COMPONENT(wdsp, i);
  472. if ((cdev->of_node && cdev->of_node == cmpnt->np) ||
  473. (cmpnt->cdev_name &&
  474. !strcmp(dev_name(cdev), cmpnt->cdev_name))) {
  475. break;
  476. }
  477. }
  478. if (i == WDSP_CMPNT_TYPE_MAX) {
  479. WDSP_ERR(wdsp, "Failed to register component dev %s",
  480. dev_name(cdev));
  481. ret = -EINVAL;
  482. goto done;
  483. }
  484. cmpnt->cdev = cdev;
  485. cmpnt->ops = ops;
  486. cmpnt->priv_data = priv_data;
  487. done:
  488. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->api_mutex);
  489. return 0;
  490. }
  491. static struct device *wdsp_get_dev_for_cmpnt(struct device *wdsp_dev,
  492. enum wdsp_cmpnt_type type)
  493. {
  494. struct wdsp_mgr_priv *wdsp;
  495. struct wdsp_cmpnt *cmpnt;
  496. if (!wdsp_dev || type >= WDSP_CMPNT_TYPE_MAX)
  497. return NULL;
  498. wdsp = dev_get_drvdata(wdsp_dev);
  499. cmpnt = WDSP_GET_COMPONENT(wdsp, type);
  500. return cmpnt->cdev;
  501. }
  502. static int wdsp_get_devops_for_cmpnt(struct device *wdsp_dev,
  503. enum wdsp_cmpnt_type type,
  504. void *data)
  505. {
  506. struct wdsp_mgr_priv *wdsp;
  507. int ret = 0;
  508. if (!wdsp_dev || type >= WDSP_CMPNT_TYPE_MAX)
  509. return -EINVAL;
  510. wdsp = dev_get_drvdata(wdsp_dev);
  511. ret = wdsp_unicast_event(wdsp, type,
  512. WDSP_EVENT_GET_DEVOPS, data);
  513. if (ret)
  514. WDSP_ERR(wdsp, "get_dev_ops failed for cmpnt type %d",
  515. type);
  516. return ret;
  517. }
  518. static void wdsp_collect_ramdumps(struct wdsp_mgr_priv *wdsp)
  519. {
  520. struct wdsp_img_section img_section;
  521. struct wdsp_err_signal_arg *data = &wdsp->dump_data.err_data;
  522. struct ramdump_segment rd_seg;
  523. int ret = 0;
  524. if (wdsp->ssr_type != WDSP_SSR_TYPE_WDSP_DOWN ||
  525. !data->mem_dumps_enabled) {
  526. WDSP_DBG(wdsp, "cannot dump memory, ssr_type %s, dumps %s",
  527. wdsp_get_ssr_type_string(wdsp->ssr_type),
  528. !(data->mem_dumps_enabled) ? "disabled" : "enabled");
  529. goto done;
  530. }
  531. if (data->dump_size == 0 ||
  532. data->remote_start_addr < wdsp->base_addr) {
  533. WDSP_ERR(wdsp, "Invalid start addr 0x%x or dump_size 0x%zx",
  534. data->remote_start_addr, data->dump_size);
  535. goto done;
  536. }
  537. if (!wdsp->dump_data.rd_dev) {
  538. WDSP_ERR(wdsp, "Ramdump device is not setup");
  539. goto done;
  540. }
  541. WDSP_DBG(wdsp, "base_addr 0x%x, dump_start_addr 0x%x, dump_size 0x%zx",
  542. wdsp->base_addr, data->remote_start_addr, data->dump_size);
  543. /* Allocate memory for dumps */
  544. wdsp->dump_data.rd_v_addr = dma_alloc_coherent(wdsp->mdev,
  545. data->dump_size,
  546. &wdsp->dump_data.rd_addr,
  547. GFP_KERNEL);
  548. if (!wdsp->dump_data.rd_v_addr)
  549. goto done;
  550. img_section.addr = data->remote_start_addr - wdsp->base_addr;
  551. img_section.size = data->dump_size;
  552. img_section.data = wdsp->dump_data.rd_v_addr;
  553. ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_TRANSPORT,
  554. WDSP_EVENT_READ_SECTION,
  555. &img_section);
  556. if (ret < 0) {
  557. WDSP_ERR(wdsp, "Failed to read dumps, size 0x%zx at addr 0x%x",
  558. img_section.size, img_section.addr);
  559. goto err_read_dumps;
  560. }
  561. /*
  562. * If panic_on_error flag is explicitly set through the debugfs,
  563. * then cause a BUG here to aid debugging.
  564. */
  565. BUG_ON(wdsp->panic_on_error);
  566. rd_seg.address = (unsigned long) wdsp->dump_data.rd_v_addr;
  567. rd_seg.size = img_section.size;
  568. rd_seg.v_address = wdsp->dump_data.rd_v_addr;
  569. ret = do_ramdump(wdsp->dump_data.rd_dev, &rd_seg, 1);
  570. if (ret < 0)
  571. WDSP_ERR(wdsp, "do_ramdump failed with error %d", ret);
  572. err_read_dumps:
  573. dma_free_coherent(wdsp->mdev, data->dump_size,
  574. wdsp->dump_data.rd_v_addr, wdsp->dump_data.rd_addr);
  575. done:
  576. return;
  577. }
  578. static void wdsp_ssr_work_fn(struct work_struct *work)
  579. {
  580. struct wdsp_mgr_priv *wdsp;
  581. int ret;
  582. wdsp = container_of(work, struct wdsp_mgr_priv, ssr_work);
  583. if (!wdsp) {
  584. pr_err("%s: Invalid private_data\n", __func__);
  585. return;
  586. }
  587. WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
  588. /* Issue ramdumps and shutdown only if DSP is currently booted */
  589. if (WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_BOOTED)) {
  590. wdsp_collect_ramdumps(wdsp);
  591. ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_CONTROL,
  592. WDSP_EVENT_DO_SHUTDOWN, NULL);
  593. if (ret < 0)
  594. WDSP_ERR(wdsp, "Failed WDSP shutdown, err = %d", ret);
  595. wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_SHUTDOWN,
  596. NULL);
  597. WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_BOOTED);
  598. }
  599. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
  600. ret = wait_for_completion_timeout(&wdsp->ready_compl,
  601. WDSP_SSR_READY_WAIT_TIMEOUT);
  602. WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
  603. if (ret == 0) {
  604. WDSP_ERR(wdsp, "wait_for_ready timed out, status = 0x%x",
  605. wdsp->ready_status);
  606. goto done;
  607. }
  608. /* Data sections are to downloaded per WDSP boot */
  609. WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_DATA_DLOADED);
  610. /*
  611. * Even though code section could possible be retained on DSP
  612. * crash, go ahead and still re-download just to avoid any
  613. * memory corruption from previous crash.
  614. */
  615. WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_CODE_DLOADED);
  616. /* If codec restarted, then all components must be re-initialized */
  617. if (wdsp->ssr_type == WDSP_SSR_TYPE_CDC_UP) {
  618. wdsp_deinit_components(wdsp);
  619. WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_INITIALIZED);
  620. }
  621. ret = wdsp_init_and_dload_code_sections(wdsp);
  622. if (ret < 0) {
  623. WDSP_ERR(wdsp, "Failed to dload code sections err = %d",
  624. ret);
  625. goto done;
  626. }
  627. /* SSR handling is finished, mark SSR type as NO_SSR */
  628. wdsp->ssr_type = WDSP_SSR_TYPE_NO_SSR;
  629. done:
  630. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
  631. }
  632. static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg,
  633. enum wdsp_ssr_type ssr_type)
  634. {
  635. enum wdsp_ssr_type current_ssr_type;
  636. struct wdsp_err_signal_arg *err_data;
  637. WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
  638. current_ssr_type = wdsp->ssr_type;
  639. WDSP_DBG(wdsp, "Current ssr_type %s, handling ssr_type %s",
  640. wdsp_get_ssr_type_string(current_ssr_type),
  641. wdsp_get_ssr_type_string(ssr_type));
  642. wdsp->ssr_type = ssr_type;
  643. if (arg) {
  644. err_data = (struct wdsp_err_signal_arg *) arg;
  645. memcpy(&wdsp->dump_data.err_data, err_data,
  646. sizeof(*err_data));
  647. } else {
  648. memset(&wdsp->dump_data.err_data, 0,
  649. sizeof(wdsp->dump_data.err_data));
  650. }
  651. switch (ssr_type) {
  652. case WDSP_SSR_TYPE_WDSP_DOWN:
  653. __wdsp_clr_ready_locked(wdsp, WDSP_SSR_STATUS_WDSP_READY);
  654. wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_PRE_SHUTDOWN,
  655. NULL);
  656. reinit_completion(&wdsp->ready_compl);
  657. schedule_work(&wdsp->ssr_work);
  658. break;
  659. case WDSP_SSR_TYPE_CDC_DOWN:
  660. __wdsp_clr_ready_locked(wdsp, WDSP_SSR_STATUS_CDC_READY);
  661. /*
  662. * If DSP is booted when CDC_DOWN is received, it needs
  663. * to be shutdown.
  664. */
  665. if (WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_BOOTED)) {
  666. __wdsp_clr_ready_locked(wdsp,
  667. WDSP_SSR_STATUS_WDSP_READY);
  668. wdsp_broadcast_event_downseq(wdsp,
  669. WDSP_EVENT_PRE_SHUTDOWN,
  670. NULL);
  671. }
  672. reinit_completion(&wdsp->ready_compl);
  673. schedule_work(&wdsp->ssr_work);
  674. break;
  675. case WDSP_SSR_TYPE_CDC_UP:
  676. __wdsp_set_ready_locked(wdsp, WDSP_SSR_STATUS_CDC_READY, true);
  677. break;
  678. default:
  679. WDSP_ERR(wdsp, "undefined ssr_type %d\n", ssr_type);
  680. /* Revert back the ssr_type for undefined events */
  681. wdsp->ssr_type = current_ssr_type;
  682. break;
  683. }
  684. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
  685. return 0;
  686. }
  687. #ifdef CONFIG_DEBUG_FS
  688. static int __wdsp_dbg_dump_locked(struct wdsp_mgr_priv *wdsp, void *arg)
  689. {
  690. struct wdsp_err_signal_arg *err_data;
  691. int ret = 0;
  692. /* If there is no SSR, set the SSR type to collect ramdumps */
  693. if (wdsp->ssr_type == WDSP_SSR_TYPE_NO_SSR) {
  694. wdsp->ssr_type = WDSP_SSR_TYPE_WDSP_DOWN;
  695. } else {
  696. WDSP_DBG(wdsp, "SSR handling is running, skip debug ramdump");
  697. ret = 0;
  698. goto done;
  699. }
  700. if (arg) {
  701. err_data = (struct wdsp_err_signal_arg *) arg;
  702. memcpy(&wdsp->dump_data.err_data, err_data,
  703. sizeof(*err_data));
  704. } else {
  705. WDSP_DBG(wdsp, "Invalid input, arg is NULL");
  706. ret = -EINVAL;
  707. goto done;
  708. }
  709. wdsp_collect_ramdumps(wdsp);
  710. wdsp->ssr_type = WDSP_SSR_TYPE_NO_SSR;
  711. done:
  712. return ret;
  713. }
  714. static int wdsp_debug_dump_handler(struct wdsp_mgr_priv *wdsp, void *arg)
  715. {
  716. int ret = 0;
  717. WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
  718. ret = __wdsp_dbg_dump_locked(wdsp, arg);
  719. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
  720. return ret;
  721. }
  722. #else
  723. static int __wdsp_dbg_dump_locked(struct wdsp_mgr_priv *wdsp, void *arg)
  724. {
  725. return 0;
  726. }
  727. static int wdsp_debug_dump_handler(struct wdsp_mgr_priv *wdsp, void *arg)
  728. {
  729. return 0;
  730. }
  731. #endif
  732. static int wdsp_signal_handler(struct device *wdsp_dev,
  733. enum wdsp_signal signal, void *arg)
  734. {
  735. struct wdsp_mgr_priv *wdsp;
  736. int ret;
  737. if (!wdsp_dev)
  738. return -EINVAL;
  739. wdsp = dev_get_drvdata(wdsp_dev);
  740. #ifdef CONFIG_DEBUG_FS
  741. if (signal != WDSP_DEBUG_DUMP_INTERNAL)
  742. WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->api_mutex);
  743. #else
  744. WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->api_mutex);
  745. #endif
  746. WDSP_DBG(wdsp, "Raised signal %d", signal);
  747. switch (signal) {
  748. case WDSP_IPC1_INTR:
  749. ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_IPC,
  750. WDSP_EVENT_IPC1_INTR, NULL);
  751. break;
  752. case WDSP_ERR_INTR:
  753. ret = wdsp_ssr_handler(wdsp, arg, WDSP_SSR_TYPE_WDSP_DOWN);
  754. break;
  755. case WDSP_CDC_DOWN_SIGNAL:
  756. ret = wdsp_ssr_handler(wdsp, arg, WDSP_SSR_TYPE_CDC_DOWN);
  757. break;
  758. case WDSP_CDC_UP_SIGNAL:
  759. ret = wdsp_ssr_handler(wdsp, arg, WDSP_SSR_TYPE_CDC_UP);
  760. break;
  761. case WDSP_DEBUG_DUMP:
  762. ret = wdsp_debug_dump_handler(wdsp, arg);
  763. break;
  764. case WDSP_DEBUG_DUMP_INTERNAL:
  765. ret = __wdsp_dbg_dump_locked(wdsp, arg);
  766. break;
  767. default:
  768. ret = -EINVAL;
  769. break;
  770. }
  771. if (ret < 0)
  772. WDSP_ERR(wdsp, "handling signal %d failed with error %d",
  773. signal, ret);
  774. #ifdef CONFIG_DEBUG_FS
  775. if (signal != WDSP_DEBUG_DUMP_INTERNAL)
  776. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->api_mutex);
  777. #else
  778. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->api_mutex);
  779. #endif
  780. return ret;
  781. }
  782. static int wdsp_vote_for_dsp(struct device *wdsp_dev,
  783. bool vote)
  784. {
  785. struct wdsp_mgr_priv *wdsp;
  786. int ret = 0;
  787. if (!wdsp_dev)
  788. return -EINVAL;
  789. wdsp = dev_get_drvdata(wdsp_dev);
  790. WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->api_mutex);
  791. WDSP_DBG(wdsp, "request %s, current users = %d",
  792. vote ? "enable" : "disable", wdsp->dsp_users);
  793. if (vote) {
  794. wdsp->dsp_users++;
  795. if (wdsp->dsp_users == 1)
  796. ret = wdsp_enable_dsp(wdsp);
  797. } else {
  798. if (wdsp->dsp_users == 0)
  799. goto done;
  800. wdsp->dsp_users--;
  801. if (wdsp->dsp_users == 0)
  802. ret = wdsp_disable_dsp(wdsp);
  803. }
  804. if (ret < 0)
  805. WDSP_DBG(wdsp, "wdsp %s failed, err = %d",
  806. vote ? "enable" : "disable", ret);
  807. done:
  808. WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->api_mutex);
  809. return ret;
  810. }
  811. static int wdsp_suspend(struct device *wdsp_dev)
  812. {
  813. struct wdsp_mgr_priv *wdsp;
  814. int rc = 0, i;
  815. if (!wdsp_dev) {
  816. pr_err("%s: Invalid handle to device\n", __func__);
  817. return -EINVAL;
  818. }
  819. wdsp = dev_get_drvdata(wdsp_dev);
  820. for (i = WDSP_CMPNT_TYPE_MAX - 1; i >= 0; i--) {
  821. rc = wdsp_unicast_event(wdsp, i, WDSP_EVENT_SUSPEND, NULL);
  822. if (rc < 0) {
  823. WDSP_ERR(wdsp, "component %s failed to suspend\n",
  824. WDSP_GET_CMPNT_TYPE_STR(i));
  825. break;
  826. }
  827. }
  828. return rc;
  829. }
  830. static int wdsp_resume(struct device *wdsp_dev)
  831. {
  832. struct wdsp_mgr_priv *wdsp;
  833. int rc = 0, i;
  834. if (!wdsp_dev) {
  835. pr_err("%s: Invalid handle to device\n", __func__);
  836. return -EINVAL;
  837. }
  838. wdsp = dev_get_drvdata(wdsp_dev);
  839. for (i = 0; i < WDSP_CMPNT_TYPE_MAX; i++) {
  840. rc = wdsp_unicast_event(wdsp, i, WDSP_EVENT_RESUME, NULL);
  841. if (rc < 0) {
  842. WDSP_ERR(wdsp, "component %s failed to resume\n",
  843. WDSP_GET_CMPNT_TYPE_STR(i));
  844. break;
  845. }
  846. }
  847. return rc;
  848. }
  849. static struct wdsp_mgr_ops wdsp_ops = {
  850. .register_cmpnt_ops = wdsp_register_cmpnt_ops,
  851. .get_dev_for_cmpnt = wdsp_get_dev_for_cmpnt,
  852. .get_devops_for_cmpnt = wdsp_get_devops_for_cmpnt,
  853. .signal_handler = wdsp_signal_handler,
  854. .vote_for_dsp = wdsp_vote_for_dsp,
  855. .suspend = wdsp_suspend,
  856. .resume = wdsp_resume,
  857. };
  858. static int wdsp_mgr_compare_of(struct device *dev, void *data)
  859. {
  860. struct wdsp_cmpnt *cmpnt = data;
  861. /*
  862. * First try to match based on of_node, if of_node is not
  863. * present, try to match on the dev_name
  864. */
  865. return ((dev->of_node && dev->of_node == cmpnt->np) ||
  866. (cmpnt->cdev_name &&
  867. !strcmp(dev_name(dev), cmpnt->cdev_name)));
  868. }
  869. static void wdsp_mgr_debugfs_init(struct wdsp_mgr_priv *wdsp)
  870. {
  871. wdsp->entry = debugfs_create_dir("wdsp_mgr", NULL);
  872. if (IS_ERR_OR_NULL(wdsp->entry))
  873. return;
  874. debugfs_create_bool("panic_on_error", 0644,
  875. wdsp->entry, &wdsp->panic_on_error);
  876. }
  877. static void wdsp_mgr_debugfs_remove(struct wdsp_mgr_priv *wdsp)
  878. {
  879. debugfs_remove_recursive(wdsp->entry);
  880. wdsp->entry = NULL;
  881. }
  882. static int wdsp_mgr_bind(struct device *dev)
  883. {
  884. struct wdsp_mgr_priv *wdsp = dev_get_drvdata(dev);
  885. struct wdsp_cmpnt *cmpnt;
  886. int ret, idx;
  887. wdsp->ops = &wdsp_ops;
  888. /* Setup ramdump device */
  889. wdsp->dump_data.rd_dev = create_ramdump_device("wdsp", dev);
  890. if (!wdsp->dump_data.rd_dev)
  891. dev_info(dev, "%s: create_ramdump_device failed\n", __func__);
  892. ret = component_bind_all(dev, wdsp->ops);
  893. if (ret < 0) {
  894. WDSP_ERR(wdsp, "component_bind_all failed %d\n", ret);
  895. return ret;
  896. }
  897. /* Make sure all components registered ops */
  898. for (idx = 0; idx < WDSP_CMPNT_TYPE_MAX; idx++) {
  899. cmpnt = WDSP_GET_COMPONENT(wdsp, idx);
  900. if (!cmpnt->cdev || !cmpnt->ops) {
  901. WDSP_ERR(wdsp, "%s did not register ops\n",
  902. WDSP_GET_CMPNT_TYPE_STR(idx));
  903. ret = -EINVAL;
  904. component_unbind_all(dev, wdsp->ops);
  905. break;
  906. }
  907. }
  908. wdsp_mgr_debugfs_init(wdsp);
  909. /* Schedule the work to download image if binding was successful. */
  910. if (!ret)
  911. schedule_work(&wdsp->load_fw_work);
  912. return ret;
  913. }
  914. static void wdsp_mgr_unbind(struct device *dev)
  915. {
  916. struct wdsp_mgr_priv *wdsp = dev_get_drvdata(dev);
  917. struct wdsp_cmpnt *cmpnt;
  918. int idx;
  919. cancel_work_sync(&wdsp->load_fw_work);
  920. component_unbind_all(dev, wdsp->ops);
  921. wdsp_mgr_debugfs_remove(wdsp);
  922. if (wdsp->dump_data.rd_dev) {
  923. destroy_ramdump_device(wdsp->dump_data.rd_dev);
  924. wdsp->dump_data.rd_dev = NULL;
  925. }
  926. /* Clear all status bits */
  927. wdsp->status = 0x00;
  928. /* clean up the components */
  929. for (idx = 0; idx < WDSP_CMPNT_TYPE_MAX; idx++) {
  930. cmpnt = WDSP_GET_COMPONENT(wdsp, idx);
  931. cmpnt->cdev = NULL;
  932. cmpnt->ops = NULL;
  933. cmpnt->priv_data = NULL;
  934. }
  935. }
  936. static const struct component_master_ops wdsp_master_ops = {
  937. .bind = wdsp_mgr_bind,
  938. .unbind = wdsp_mgr_unbind,
  939. };
  940. static void *wdsp_mgr_parse_phandle(struct wdsp_mgr_priv *wdsp,
  941. int index)
  942. {
  943. struct device *mdev = wdsp->mdev;
  944. struct device_node *np;
  945. struct wdsp_cmpnt *cmpnt = NULL;
  946. struct of_phandle_args pargs;
  947. u32 value;
  948. int ret;
  949. ret = of_parse_phandle_with_fixed_args(mdev->of_node,
  950. "qcom,wdsp-components", 1,
  951. index, &pargs);
  952. if (ret) {
  953. WDSP_ERR(wdsp, "parse_phandle at index %d failed %d",
  954. index, ret);
  955. return NULL;
  956. }
  957. np = pargs.np;
  958. value = pargs.args[0];
  959. if (value >= WDSP_CMPNT_TYPE_MAX) {
  960. WDSP_ERR(wdsp, "invalid phandle_arg to of_node %s", np->name);
  961. goto done;
  962. }
  963. cmpnt = WDSP_GET_COMPONENT(wdsp, value);
  964. if (cmpnt->np || cmpnt->cdev_name) {
  965. WDSP_ERR(wdsp, "cmpnt %d already added", value);
  966. cmpnt = NULL;
  967. goto done;
  968. }
  969. cmpnt->np = np;
  970. of_property_read_string(np, "qcom,wdsp-cmpnt-dev-name",
  971. &cmpnt->cdev_name);
  972. done:
  973. of_node_put(np);
  974. return cmpnt;
  975. }
  976. static int wdsp_mgr_parse_dt_entries(struct wdsp_mgr_priv *wdsp)
  977. {
  978. struct device *dev = wdsp->mdev;
  979. void *match_data;
  980. int ph_idx, ret;
  981. ret = of_property_read_string(dev->of_node, "qcom,img-filename",
  982. &wdsp->img_fname);
  983. if (ret < 0) {
  984. WDSP_ERR(wdsp, "Reading property %s failed, error = %d",
  985. "qcom,img-filename", ret);
  986. return ret;
  987. }
  988. ret = of_count_phandle_with_args(dev->of_node,
  989. "qcom,wdsp-components",
  990. NULL);
  991. if (ret == -ENOENT) {
  992. WDSP_ERR(wdsp, "Property %s not defined in DT",
  993. "qcom,wdsp-components");
  994. goto done;
  995. } else if (ret != WDSP_CMPNT_TYPE_MAX * 2) {
  996. WDSP_ERR(wdsp, "Invalid phandle + arg count %d, expected %d",
  997. ret, WDSP_CMPNT_TYPE_MAX * 2);
  998. ret = -EINVAL;
  999. goto done;
  1000. }
  1001. ret = 0;
  1002. for (ph_idx = 0; ph_idx < WDSP_CMPNT_TYPE_MAX; ph_idx++) {
  1003. match_data = wdsp_mgr_parse_phandle(wdsp, ph_idx);
  1004. if (!match_data) {
  1005. WDSP_ERR(wdsp, "component not found at idx %d", ph_idx);
  1006. ret = -EINVAL;
  1007. goto done;
  1008. }
  1009. component_match_add(dev, &wdsp->match,
  1010. wdsp_mgr_compare_of, match_data);
  1011. }
  1012. done:
  1013. return ret;
  1014. }
  1015. static int wdsp_mgr_probe(struct platform_device *pdev)
  1016. {
  1017. struct wdsp_mgr_priv *wdsp;
  1018. struct device *mdev = &pdev->dev;
  1019. int ret;
  1020. wdsp = devm_kzalloc(mdev, sizeof(*wdsp), GFP_KERNEL);
  1021. if (!wdsp)
  1022. return -ENOMEM;
  1023. wdsp->mdev = mdev;
  1024. wdsp->seg_list = devm_kzalloc(mdev, sizeof(struct list_head),
  1025. GFP_KERNEL);
  1026. if (!wdsp->seg_list) {
  1027. devm_kfree(mdev, wdsp);
  1028. return -ENOMEM;
  1029. }
  1030. ret = wdsp_mgr_parse_dt_entries(wdsp);
  1031. if (ret)
  1032. goto err_dt_parse;
  1033. INIT_WORK(&wdsp->load_fw_work, wdsp_load_fw_image);
  1034. INIT_LIST_HEAD(wdsp->seg_list);
  1035. mutex_init(&wdsp->api_mutex);
  1036. mutex_init(&wdsp->ssr_mutex);
  1037. wdsp->ssr_type = WDSP_SSR_TYPE_NO_SSR;
  1038. wdsp->ready_status = WDSP_SSR_STATUS_READY;
  1039. INIT_WORK(&wdsp->ssr_work, wdsp_ssr_work_fn);
  1040. init_completion(&wdsp->ready_compl);
  1041. arch_setup_dma_ops(wdsp->mdev, 0, 0, NULL, 0);
  1042. dev_set_drvdata(mdev, wdsp);
  1043. ret = component_master_add_with_match(mdev, &wdsp_master_ops,
  1044. wdsp->match);
  1045. if (ret < 0) {
  1046. WDSP_ERR(wdsp, "Failed to add master, err = %d", ret);
  1047. goto err_master_add;
  1048. }
  1049. return 0;
  1050. err_master_add:
  1051. mutex_destroy(&wdsp->api_mutex);
  1052. mutex_destroy(&wdsp->ssr_mutex);
  1053. err_dt_parse:
  1054. devm_kfree(mdev, wdsp->seg_list);
  1055. devm_kfree(mdev, wdsp);
  1056. dev_set_drvdata(mdev, NULL);
  1057. return ret;
  1058. }
  1059. static int wdsp_mgr_remove(struct platform_device *pdev)
  1060. {
  1061. struct device *mdev = &pdev->dev;
  1062. struct wdsp_mgr_priv *wdsp = dev_get_drvdata(mdev);
  1063. component_master_del(mdev, &wdsp_master_ops);
  1064. mutex_destroy(&wdsp->api_mutex);
  1065. mutex_destroy(&wdsp->ssr_mutex);
  1066. devm_kfree(mdev, wdsp->seg_list);
  1067. devm_kfree(mdev, wdsp);
  1068. dev_set_drvdata(mdev, NULL);
  1069. return 0;
  1070. };
  1071. static const struct of_device_id wdsp_mgr_dt_match[] = {
  1072. {.compatible = "qcom,wcd-dsp-mgr" },
  1073. { }
  1074. };
  1075. static struct platform_driver wdsp_mgr_driver = {
  1076. .driver = {
  1077. .name = "wcd-dsp-mgr",
  1078. .owner = THIS_MODULE,
  1079. .of_match_table = of_match_ptr(wdsp_mgr_dt_match),
  1080. .suppress_bind_attrs = true,
  1081. },
  1082. .probe = wdsp_mgr_probe,
  1083. .remove = wdsp_mgr_remove,
  1084. };
  1085. int wcd_dsp_mgr_init(void)
  1086. {
  1087. return platform_driver_register(&wdsp_mgr_driver);
  1088. }
  1089. void wcd_dsp_mgr_exit(void)
  1090. {
  1091. platform_driver_unregister(&wdsp_mgr_driver);
  1092. }
  1093. MODULE_DESCRIPTION("WCD DSP manager driver");
  1094. MODULE_DEVICE_TABLE(of, wdsp_mgr_dt_match);
  1095. MODULE_LICENSE("GPL v2");