wcd-dsp-mgr.c 33 KB

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