wcd-dsp-mgr.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2016-2018, 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. },
  1081. .probe = wdsp_mgr_probe,
  1082. .remove = wdsp_mgr_remove,
  1083. };
  1084. int wcd_dsp_mgr_init(void)
  1085. {
  1086. return platform_driver_register(&wdsp_mgr_driver);
  1087. }
  1088. void wcd_dsp_mgr_exit(void)
  1089. {
  1090. platform_driver_unregister(&wdsp_mgr_driver);
  1091. }
  1092. MODULE_DESCRIPTION("WCD DSP manager driver");
  1093. MODULE_DEVICE_TABLE(of, wdsp_mgr_dt_match);
  1094. MODULE_LICENSE("GPL v2");