qcom_q6v5_pas.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Qualcomm Peripheral Authentication Service remoteproc driver
  4. *
  5. * Copyright (C) 2016 Linaro Ltd
  6. * Copyright (C) 2014 Sony Mobile Communications AB
  7. * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  8. */
  9. #include <linux/clk.h>
  10. #include <linux/delay.h>
  11. #include <linux/firmware.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/iommu.h>
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/of.h>
  17. #include <linux/of_address.h>
  18. #include <linux/of_reserved_mem.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/pm_domain.h>
  21. #include <linux/pm_runtime.h>
  22. #include <linux/firmware/qcom/qcom_scm.h>
  23. #include <linux/regulator/consumer.h>
  24. #include <linux/remoteproc.h>
  25. #include <linux/soc/qcom/mdt_loader.h>
  26. #include <linux/soc/qcom/smem.h>
  27. #include <linux/soc/qcom/smem_state.h>
  28. #include "qcom_common.h"
  29. #include "qcom_pil_info.h"
  30. #include "qcom_q6v5.h"
  31. #include "remoteproc_internal.h"
  32. #define QCOM_PAS_DECRYPT_SHUTDOWN_DELAY_MS 100
  33. #define MAX_ASSIGN_COUNT 3
  34. struct qcom_pas_data {
  35. int crash_reason_smem;
  36. const char *firmware_name;
  37. const char *dtb_firmware_name;
  38. int pas_id;
  39. int dtb_pas_id;
  40. int lite_pas_id;
  41. int lite_dtb_pas_id;
  42. unsigned int minidump_id;
  43. bool auto_boot;
  44. bool decrypt_shutdown;
  45. char **proxy_pd_names;
  46. const char *load_state;
  47. const char *ssr_name;
  48. const char *sysmon_name;
  49. int ssctl_id;
  50. unsigned int smem_host_id;
  51. int region_assign_idx;
  52. int region_assign_count;
  53. bool region_assign_shared;
  54. int region_assign_vmid;
  55. };
  56. struct qcom_pas {
  57. struct device *dev;
  58. struct rproc *rproc;
  59. struct qcom_q6v5 q6v5;
  60. struct clk *xo;
  61. struct clk *aggre2_clk;
  62. struct regulator *cx_supply;
  63. struct regulator *px_supply;
  64. struct device *proxy_pds[3];
  65. int proxy_pd_count;
  66. const char *dtb_firmware_name;
  67. int pas_id;
  68. int dtb_pas_id;
  69. int lite_pas_id;
  70. int lite_dtb_pas_id;
  71. unsigned int minidump_id;
  72. int crash_reason_smem;
  73. unsigned int smem_host_id;
  74. bool decrypt_shutdown;
  75. const char *info_name;
  76. const struct firmware *firmware;
  77. const struct firmware *dtb_firmware;
  78. struct completion start_done;
  79. struct completion stop_done;
  80. phys_addr_t mem_phys;
  81. phys_addr_t dtb_mem_phys;
  82. phys_addr_t mem_reloc;
  83. phys_addr_t dtb_mem_reloc;
  84. phys_addr_t region_assign_phys[MAX_ASSIGN_COUNT];
  85. void *mem_region;
  86. void *dtb_mem_region;
  87. size_t mem_size;
  88. size_t dtb_mem_size;
  89. size_t region_assign_size[MAX_ASSIGN_COUNT];
  90. int region_assign_idx;
  91. int region_assign_count;
  92. bool region_assign_shared;
  93. int region_assign_vmid;
  94. u64 region_assign_owners[MAX_ASSIGN_COUNT];
  95. struct qcom_rproc_glink glink_subdev;
  96. struct qcom_rproc_subdev smd_subdev;
  97. struct qcom_rproc_pdm pdm_subdev;
  98. struct qcom_rproc_ssr ssr_subdev;
  99. struct qcom_sysmon *sysmon;
  100. struct qcom_scm_pas_context *pas_ctx;
  101. struct qcom_scm_pas_context *dtb_pas_ctx;
  102. };
  103. static void qcom_pas_segment_dump(struct rproc *rproc,
  104. struct rproc_dump_segment *segment,
  105. void *dest, size_t offset, size_t size)
  106. {
  107. struct qcom_pas *pas = rproc->priv;
  108. int total_offset;
  109. total_offset = segment->da + segment->offset + offset - pas->mem_phys;
  110. if (total_offset < 0 || total_offset + size > pas->mem_size) {
  111. dev_err(pas->dev,
  112. "invalid copy request for segment %pad with offset %zu and size %zu)\n",
  113. &segment->da, offset, size);
  114. memset(dest, 0xff, size);
  115. return;
  116. }
  117. memcpy_fromio(dest, pas->mem_region + total_offset, size);
  118. }
  119. static void qcom_pas_minidump(struct rproc *rproc)
  120. {
  121. struct qcom_pas *pas = rproc->priv;
  122. if (rproc->dump_conf == RPROC_COREDUMP_DISABLED)
  123. return;
  124. qcom_minidump(rproc, pas->minidump_id, qcom_pas_segment_dump);
  125. }
  126. static int qcom_pas_pds_enable(struct qcom_pas *pas, struct device **pds,
  127. size_t pd_count)
  128. {
  129. int ret;
  130. int i;
  131. for (i = 0; i < pd_count; i++) {
  132. dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
  133. ret = pm_runtime_get_sync(pds[i]);
  134. if (ret < 0) {
  135. pm_runtime_put_noidle(pds[i]);
  136. dev_pm_genpd_set_performance_state(pds[i], 0);
  137. goto unroll_pd_votes;
  138. }
  139. }
  140. return 0;
  141. unroll_pd_votes:
  142. for (i--; i >= 0; i--) {
  143. dev_pm_genpd_set_performance_state(pds[i], 0);
  144. pm_runtime_put(pds[i]);
  145. }
  146. return ret;
  147. };
  148. static void qcom_pas_pds_disable(struct qcom_pas *pas, struct device **pds,
  149. size_t pd_count)
  150. {
  151. int i;
  152. for (i = 0; i < pd_count; i++) {
  153. dev_pm_genpd_set_performance_state(pds[i], 0);
  154. pm_runtime_put(pds[i]);
  155. }
  156. }
  157. static int qcom_pas_shutdown_poll_decrypt(struct qcom_pas *pas)
  158. {
  159. unsigned int retry_num = 50;
  160. int ret;
  161. do {
  162. msleep(QCOM_PAS_DECRYPT_SHUTDOWN_DELAY_MS);
  163. ret = qcom_scm_pas_shutdown(pas->pas_id);
  164. } while (ret == -EINVAL && --retry_num);
  165. return ret;
  166. }
  167. static int qcom_pas_unprepare(struct rproc *rproc)
  168. {
  169. struct qcom_pas *pas = rproc->priv;
  170. /*
  171. * qcom_pas_load() did pass pas_metadata to the SCM driver for storing
  172. * metadata context. It might have been released already if
  173. * auth_and_reset() was successful, but in other cases clean it up
  174. * here.
  175. */
  176. qcom_scm_pas_metadata_release(pas->pas_ctx);
  177. if (pas->dtb_pas_id)
  178. qcom_scm_pas_metadata_release(pas->dtb_pas_ctx);
  179. return 0;
  180. }
  181. static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw)
  182. {
  183. struct qcom_pas *pas = rproc->priv;
  184. int ret;
  185. /* Store firmware handle to be used in qcom_pas_start() */
  186. pas->firmware = fw;
  187. if (pas->lite_pas_id)
  188. qcom_scm_pas_shutdown(pas->lite_pas_id);
  189. if (pas->lite_dtb_pas_id)
  190. qcom_scm_pas_shutdown(pas->lite_dtb_pas_id);
  191. if (pas->dtb_pas_id) {
  192. ret = request_firmware(&pas->dtb_firmware, pas->dtb_firmware_name, pas->dev);
  193. if (ret) {
  194. dev_err(pas->dev, "request_firmware failed for %s: %d\n",
  195. pas->dtb_firmware_name, ret);
  196. return ret;
  197. }
  198. ret = qcom_mdt_pas_load(pas->dtb_pas_ctx, pas->dtb_firmware,
  199. pas->dtb_firmware_name, pas->dtb_mem_region,
  200. &pas->dtb_mem_reloc);
  201. if (ret)
  202. goto release_dtb_metadata;
  203. }
  204. return 0;
  205. release_dtb_metadata:
  206. qcom_scm_pas_metadata_release(pas->dtb_pas_ctx);
  207. release_firmware(pas->dtb_firmware);
  208. return ret;
  209. }
  210. static void qcom_pas_unmap_carveout(struct rproc *rproc, phys_addr_t mem_phys, size_t size)
  211. {
  212. if (rproc->has_iommu)
  213. iommu_unmap(rproc->domain, mem_phys, size);
  214. }
  215. static int qcom_pas_map_carveout(struct rproc *rproc, phys_addr_t mem_phys, size_t size)
  216. {
  217. int ret = 0;
  218. if (rproc->has_iommu)
  219. ret = iommu_map(rproc->domain, mem_phys, mem_phys, size,
  220. IOMMU_READ | IOMMU_WRITE, GFP_KERNEL);
  221. return ret;
  222. }
  223. static int qcom_pas_start(struct rproc *rproc)
  224. {
  225. struct qcom_pas *pas = rproc->priv;
  226. int ret;
  227. ret = qcom_q6v5_prepare(&pas->q6v5);
  228. if (ret)
  229. return ret;
  230. ret = qcom_pas_pds_enable(pas, pas->proxy_pds, pas->proxy_pd_count);
  231. if (ret < 0)
  232. goto disable_irqs;
  233. ret = clk_prepare_enable(pas->xo);
  234. if (ret)
  235. goto disable_proxy_pds;
  236. ret = clk_prepare_enable(pas->aggre2_clk);
  237. if (ret)
  238. goto disable_xo_clk;
  239. if (pas->cx_supply) {
  240. ret = regulator_enable(pas->cx_supply);
  241. if (ret)
  242. goto disable_aggre2_clk;
  243. }
  244. if (pas->px_supply) {
  245. ret = regulator_enable(pas->px_supply);
  246. if (ret)
  247. goto disable_cx_supply;
  248. }
  249. if (pas->dtb_pas_id) {
  250. ret = qcom_pas_map_carveout(rproc, pas->dtb_mem_phys, pas->dtb_mem_size);
  251. if (ret)
  252. goto disable_px_supply;
  253. ret = qcom_scm_pas_prepare_and_auth_reset(pas->dtb_pas_ctx);
  254. if (ret) {
  255. dev_err(pas->dev,
  256. "failed to authenticate dtb image and release reset\n");
  257. goto unmap_dtb_carveout;
  258. }
  259. }
  260. ret = qcom_mdt_pas_load(pas->pas_ctx, pas->firmware, rproc->firmware,
  261. pas->mem_region, &pas->mem_reloc);
  262. if (ret)
  263. goto release_pas_metadata;
  264. qcom_pil_info_store(pas->info_name, pas->mem_phys, pas->mem_size);
  265. ret = qcom_pas_map_carveout(rproc, pas->mem_phys, pas->mem_size);
  266. if (ret)
  267. goto release_pas_metadata;
  268. ret = qcom_scm_pas_prepare_and_auth_reset(pas->pas_ctx);
  269. if (ret) {
  270. dev_err(pas->dev,
  271. "failed to authenticate image and release reset\n");
  272. goto unmap_carveout;
  273. }
  274. ret = qcom_q6v5_wait_for_start(&pas->q6v5, msecs_to_jiffies(5000));
  275. if (ret == -ETIMEDOUT) {
  276. dev_err(pas->dev, "start timed out\n");
  277. qcom_scm_pas_shutdown(pas->pas_id);
  278. goto unmap_carveout;
  279. }
  280. qcom_scm_pas_metadata_release(pas->pas_ctx);
  281. if (pas->dtb_pas_id)
  282. qcom_scm_pas_metadata_release(pas->dtb_pas_ctx);
  283. /* firmware is used to pass reference from qcom_pas_start(), drop it now */
  284. pas->firmware = NULL;
  285. return 0;
  286. unmap_carveout:
  287. qcom_pas_unmap_carveout(rproc, pas->mem_phys, pas->mem_size);
  288. release_pas_metadata:
  289. qcom_scm_pas_metadata_release(pas->pas_ctx);
  290. if (pas->dtb_pas_id)
  291. qcom_scm_pas_metadata_release(pas->dtb_pas_ctx);
  292. unmap_dtb_carveout:
  293. if (pas->dtb_pas_id)
  294. qcom_pas_unmap_carveout(rproc, pas->dtb_mem_phys, pas->dtb_mem_size);
  295. disable_px_supply:
  296. if (pas->px_supply)
  297. regulator_disable(pas->px_supply);
  298. disable_cx_supply:
  299. if (pas->cx_supply)
  300. regulator_disable(pas->cx_supply);
  301. disable_aggre2_clk:
  302. clk_disable_unprepare(pas->aggre2_clk);
  303. disable_xo_clk:
  304. clk_disable_unprepare(pas->xo);
  305. disable_proxy_pds:
  306. qcom_pas_pds_disable(pas, pas->proxy_pds, pas->proxy_pd_count);
  307. disable_irqs:
  308. qcom_q6v5_unprepare(&pas->q6v5);
  309. /* firmware is used to pass reference from qcom_pas_start(), drop it now */
  310. pas->firmware = NULL;
  311. return ret;
  312. }
  313. static void qcom_pas_handover(struct qcom_q6v5 *q6v5)
  314. {
  315. struct qcom_pas *pas = container_of(q6v5, struct qcom_pas, q6v5);
  316. if (pas->px_supply)
  317. regulator_disable(pas->px_supply);
  318. if (pas->cx_supply)
  319. regulator_disable(pas->cx_supply);
  320. clk_disable_unprepare(pas->aggre2_clk);
  321. clk_disable_unprepare(pas->xo);
  322. qcom_pas_pds_disable(pas, pas->proxy_pds, pas->proxy_pd_count);
  323. }
  324. static int qcom_pas_stop(struct rproc *rproc)
  325. {
  326. struct qcom_pas *pas = rproc->priv;
  327. int handover;
  328. int ret;
  329. ret = qcom_q6v5_request_stop(&pas->q6v5, pas->sysmon);
  330. if (ret == -ETIMEDOUT)
  331. dev_err(pas->dev, "timed out on wait\n");
  332. ret = qcom_scm_pas_shutdown(pas->pas_id);
  333. if (ret && pas->decrypt_shutdown)
  334. ret = qcom_pas_shutdown_poll_decrypt(pas);
  335. if (ret)
  336. dev_err(pas->dev, "failed to shutdown: %d\n", ret);
  337. if (pas->dtb_pas_id) {
  338. ret = qcom_scm_pas_shutdown(pas->dtb_pas_id);
  339. if (ret)
  340. dev_err(pas->dev, "failed to shutdown dtb: %d\n", ret);
  341. qcom_pas_unmap_carveout(rproc, pas->dtb_mem_phys, pas->dtb_mem_size);
  342. }
  343. qcom_pas_unmap_carveout(rproc, pas->mem_phys, pas->mem_size);
  344. handover = qcom_q6v5_unprepare(&pas->q6v5);
  345. if (handover)
  346. qcom_pas_handover(&pas->q6v5);
  347. if (pas->smem_host_id)
  348. ret = qcom_smem_bust_hwspin_lock_by_host(pas->smem_host_id);
  349. return ret;
  350. }
  351. static void *qcom_pas_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
  352. {
  353. struct qcom_pas *pas = rproc->priv;
  354. int offset;
  355. offset = da - pas->mem_reloc;
  356. if (offset < 0 || offset + len > pas->mem_size)
  357. return NULL;
  358. if (is_iomem)
  359. *is_iomem = true;
  360. return pas->mem_region + offset;
  361. }
  362. static int qcom_pas_parse_firmware(struct rproc *rproc, const struct firmware *fw)
  363. {
  364. struct qcom_pas *pas = rproc->priv;
  365. struct resource_table *table = NULL;
  366. size_t output_rt_size;
  367. void *output_rt;
  368. size_t table_sz;
  369. int ret;
  370. ret = qcom_register_dump_segments(rproc, fw);
  371. if (ret) {
  372. dev_err(pas->dev, "Error in registering dump segments\n");
  373. return ret;
  374. }
  375. if (!rproc->has_iommu)
  376. return 0;
  377. ret = rproc_elf_load_rsc_table(rproc, fw);
  378. if (ret)
  379. dev_dbg(&rproc->dev, "Failed to load resource table from firmware\n");
  380. table = rproc->table_ptr;
  381. table_sz = rproc->table_sz;
  382. /*
  383. * The resources consumed by Qualcomm remote processors fall into two categories:
  384. * static (such as the memory carveouts for the rproc firmware) and dynamic (like
  385. * shared memory pools). Both are managed by a Qualcomm hypervisor (such as QHEE
  386. * or Gunyah), if one is present. Otherwise, a resource table must be retrieved
  387. * via an SCM call. That table will list all dynamic resources (if any) and possibly
  388. * the static ones. The static resources may also come from a resource table embedded
  389. * in the rproc firmware instead.
  390. *
  391. * Here, we call rproc_elf_load_rsc_table() to check firmware binary has resources
  392. * or not and if it is not having then we pass NULL and zero as input resource
  393. * table pointer and size respectively to the argument of qcom_scm_pas_get_rsc_table()
  394. * and this is even true for Qualcomm remote processor who does follow remoteproc
  395. * framework.
  396. */
  397. output_rt = qcom_scm_pas_get_rsc_table(pas->pas_ctx, table, table_sz, &output_rt_size);
  398. ret = IS_ERR(output_rt) ? PTR_ERR(output_rt) : 0;
  399. if (ret) {
  400. dev_err(pas->dev, "Error in getting resource table: %d\n", ret);
  401. return ret;
  402. }
  403. kfree(rproc->cached_table);
  404. rproc->cached_table = output_rt;
  405. rproc->table_ptr = rproc->cached_table;
  406. rproc->table_sz = output_rt_size;
  407. return ret;
  408. }
  409. static unsigned long qcom_pas_panic(struct rproc *rproc)
  410. {
  411. struct qcom_pas *pas = rproc->priv;
  412. return qcom_q6v5_panic(&pas->q6v5);
  413. }
  414. static const struct rproc_ops qcom_pas_ops = {
  415. .unprepare = qcom_pas_unprepare,
  416. .start = qcom_pas_start,
  417. .stop = qcom_pas_stop,
  418. .da_to_va = qcom_pas_da_to_va,
  419. .parse_fw = qcom_pas_parse_firmware,
  420. .load = qcom_pas_load,
  421. .panic = qcom_pas_panic,
  422. };
  423. static const struct rproc_ops qcom_pas_minidump_ops = {
  424. .unprepare = qcom_pas_unprepare,
  425. .start = qcom_pas_start,
  426. .stop = qcom_pas_stop,
  427. .da_to_va = qcom_pas_da_to_va,
  428. .parse_fw = qcom_pas_parse_firmware,
  429. .load = qcom_pas_load,
  430. .panic = qcom_pas_panic,
  431. .coredump = qcom_pas_minidump,
  432. };
  433. static int qcom_pas_init_clock(struct qcom_pas *pas)
  434. {
  435. pas->xo = devm_clk_get(pas->dev, "xo");
  436. if (IS_ERR(pas->xo))
  437. return dev_err_probe(pas->dev, PTR_ERR(pas->xo),
  438. "failed to get xo clock");
  439. pas->aggre2_clk = devm_clk_get_optional(pas->dev, "aggre2");
  440. if (IS_ERR(pas->aggre2_clk))
  441. return dev_err_probe(pas->dev, PTR_ERR(pas->aggre2_clk),
  442. "failed to get aggre2 clock");
  443. return 0;
  444. }
  445. static int qcom_pas_init_regulator(struct qcom_pas *pas)
  446. {
  447. pas->cx_supply = devm_regulator_get_optional(pas->dev, "cx");
  448. if (IS_ERR(pas->cx_supply)) {
  449. if (PTR_ERR(pas->cx_supply) == -ENODEV)
  450. pas->cx_supply = NULL;
  451. else
  452. return PTR_ERR(pas->cx_supply);
  453. }
  454. if (pas->cx_supply)
  455. regulator_set_load(pas->cx_supply, 100000);
  456. pas->px_supply = devm_regulator_get_optional(pas->dev, "px");
  457. if (IS_ERR(pas->px_supply)) {
  458. if (PTR_ERR(pas->px_supply) == -ENODEV)
  459. pas->px_supply = NULL;
  460. else
  461. return PTR_ERR(pas->px_supply);
  462. }
  463. return 0;
  464. }
  465. static int qcom_pas_pds_attach(struct device *dev, struct device **devs, char **pd_names)
  466. {
  467. size_t num_pds = 0;
  468. int ret;
  469. int i;
  470. if (!pd_names)
  471. return 0;
  472. while (pd_names[num_pds])
  473. num_pds++;
  474. /* Handle single power domain */
  475. if (num_pds == 1 && dev->pm_domain) {
  476. devs[0] = dev;
  477. pm_runtime_enable(dev);
  478. return 1;
  479. }
  480. for (i = 0; i < num_pds; i++) {
  481. devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
  482. if (IS_ERR_OR_NULL(devs[i])) {
  483. ret = PTR_ERR(devs[i]) ? : -ENODATA;
  484. goto unroll_attach;
  485. }
  486. }
  487. return num_pds;
  488. unroll_attach:
  489. for (i--; i >= 0; i--)
  490. dev_pm_domain_detach(devs[i], false);
  491. return ret;
  492. };
  493. static void qcom_pas_pds_detach(struct qcom_pas *pas, struct device **pds, size_t pd_count)
  494. {
  495. struct device *dev = pas->dev;
  496. int i;
  497. /* Handle single power domain */
  498. if (pd_count == 1 && dev->pm_domain) {
  499. pm_runtime_disable(dev);
  500. return;
  501. }
  502. for (i = 0; i < pd_count; i++)
  503. dev_pm_domain_detach(pds[i], false);
  504. }
  505. static int qcom_pas_alloc_memory_region(struct qcom_pas *pas)
  506. {
  507. struct resource res;
  508. int ret;
  509. ret = of_reserved_mem_region_to_resource(pas->dev->of_node, 0, &res);
  510. if (ret) {
  511. dev_err(pas->dev, "unable to resolve memory-region\n");
  512. return ret;
  513. }
  514. pas->mem_phys = pas->mem_reloc = res.start;
  515. pas->mem_size = resource_size(&res);
  516. pas->mem_region = devm_ioremap_resource_wc(pas->dev, &res);
  517. if (IS_ERR(pas->mem_region)) {
  518. dev_err(pas->dev, "unable to map memory region: %pR\n", &res);
  519. return PTR_ERR(pas->mem_region);
  520. }
  521. if (!pas->dtb_pas_id)
  522. return 0;
  523. ret = of_reserved_mem_region_to_resource(pas->dev->of_node, 1, &res);
  524. if (ret) {
  525. dev_err(pas->dev, "unable to resolve dtb memory-region\n");
  526. return ret;
  527. }
  528. pas->dtb_mem_phys = pas->dtb_mem_reloc = res.start;
  529. pas->dtb_mem_size = resource_size(&res);
  530. pas->dtb_mem_region = devm_ioremap_resource_wc(pas->dev, &res);
  531. if (IS_ERR(pas->dtb_mem_region)) {
  532. dev_err(pas->dev, "unable to map dtb memory region: %pR\n", &res);
  533. return PTR_ERR(pas->dtb_mem_region);
  534. }
  535. return 0;
  536. }
  537. static int qcom_pas_assign_memory_region(struct qcom_pas *pas)
  538. {
  539. struct qcom_scm_vmperm perm[MAX_ASSIGN_COUNT];
  540. unsigned int perm_size;
  541. int offset;
  542. int ret;
  543. if (!pas->region_assign_idx)
  544. return 0;
  545. for (offset = 0; offset < pas->region_assign_count; ++offset) {
  546. struct resource res;
  547. ret = of_reserved_mem_region_to_resource(pas->dev->of_node,
  548. pas->region_assign_idx + offset,
  549. &res);
  550. if (ret) {
  551. dev_err(pas->dev, "unable to resolve shareable memory-region index %d\n",
  552. offset);
  553. return ret;
  554. }
  555. if (pas->region_assign_shared) {
  556. perm[0].vmid = QCOM_SCM_VMID_HLOS;
  557. perm[0].perm = QCOM_SCM_PERM_RW;
  558. perm[1].vmid = pas->region_assign_vmid;
  559. perm[1].perm = QCOM_SCM_PERM_RW;
  560. perm_size = 2;
  561. } else {
  562. perm[0].vmid = pas->region_assign_vmid;
  563. perm[0].perm = QCOM_SCM_PERM_RW;
  564. perm_size = 1;
  565. }
  566. pas->region_assign_phys[offset] = res.start;
  567. pas->region_assign_size[offset] = resource_size(&res);
  568. pas->region_assign_owners[offset] = BIT(QCOM_SCM_VMID_HLOS);
  569. ret = qcom_scm_assign_mem(pas->region_assign_phys[offset],
  570. pas->region_assign_size[offset],
  571. &pas->region_assign_owners[offset],
  572. perm, perm_size);
  573. if (ret < 0) {
  574. dev_err(pas->dev, "assign memory %d failed\n", offset);
  575. return ret;
  576. }
  577. }
  578. return 0;
  579. }
  580. static void qcom_pas_unassign_memory_region(struct qcom_pas *pas)
  581. {
  582. struct qcom_scm_vmperm perm;
  583. int offset;
  584. int ret;
  585. if (!pas->region_assign_idx || pas->region_assign_shared)
  586. return;
  587. for (offset = 0; offset < pas->region_assign_count; ++offset) {
  588. perm.vmid = QCOM_SCM_VMID_HLOS;
  589. perm.perm = QCOM_SCM_PERM_RW;
  590. ret = qcom_scm_assign_mem(pas->region_assign_phys[offset],
  591. pas->region_assign_size[offset],
  592. &pas->region_assign_owners[offset],
  593. &perm, 1);
  594. if (ret < 0)
  595. dev_err(pas->dev, "unassign memory %d failed\n", offset);
  596. }
  597. }
  598. static int qcom_pas_probe(struct platform_device *pdev)
  599. {
  600. const struct qcom_pas_data *desc;
  601. struct qcom_pas *pas;
  602. struct rproc *rproc;
  603. const char *fw_name, *dtb_fw_name = NULL;
  604. const struct rproc_ops *ops = &qcom_pas_ops;
  605. int ret;
  606. desc = of_device_get_match_data(&pdev->dev);
  607. if (!desc)
  608. return -EINVAL;
  609. if (!qcom_scm_is_available())
  610. return -EPROBE_DEFER;
  611. fw_name = desc->firmware_name;
  612. ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
  613. &fw_name);
  614. if (ret < 0 && ret != -EINVAL)
  615. return ret;
  616. if (desc->dtb_firmware_name) {
  617. dtb_fw_name = desc->dtb_firmware_name;
  618. ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name", 1,
  619. &dtb_fw_name);
  620. if (ret < 0 && ret != -EINVAL)
  621. return ret;
  622. }
  623. if (desc->minidump_id)
  624. ops = &qcom_pas_minidump_ops;
  625. rproc = devm_rproc_alloc(&pdev->dev, desc->sysmon_name, ops, fw_name, sizeof(*pas));
  626. if (!rproc) {
  627. dev_err(&pdev->dev, "unable to allocate remoteproc\n");
  628. return -ENOMEM;
  629. }
  630. rproc->has_iommu = of_property_present(pdev->dev.of_node, "iommus");
  631. rproc->auto_boot = desc->auto_boot;
  632. rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
  633. pas = rproc->priv;
  634. pas->dev = &pdev->dev;
  635. pas->rproc = rproc;
  636. pas->minidump_id = desc->minidump_id;
  637. pas->pas_id = desc->pas_id;
  638. pas->lite_pas_id = desc->lite_pas_id;
  639. pas->lite_dtb_pas_id = desc->lite_dtb_pas_id;
  640. pas->info_name = desc->sysmon_name;
  641. pas->smem_host_id = desc->smem_host_id;
  642. pas->decrypt_shutdown = desc->decrypt_shutdown;
  643. pas->region_assign_idx = desc->region_assign_idx;
  644. pas->region_assign_count = min_t(int, MAX_ASSIGN_COUNT, desc->region_assign_count);
  645. pas->region_assign_vmid = desc->region_assign_vmid;
  646. pas->region_assign_shared = desc->region_assign_shared;
  647. if (dtb_fw_name) {
  648. pas->dtb_firmware_name = dtb_fw_name;
  649. pas->dtb_pas_id = desc->dtb_pas_id;
  650. }
  651. platform_set_drvdata(pdev, pas);
  652. ret = device_init_wakeup(pas->dev, true);
  653. if (ret)
  654. goto free_rproc;
  655. ret = qcom_pas_alloc_memory_region(pas);
  656. if (ret)
  657. goto free_rproc;
  658. ret = qcom_pas_assign_memory_region(pas);
  659. if (ret)
  660. goto free_rproc;
  661. ret = qcom_pas_init_clock(pas);
  662. if (ret)
  663. goto unassign_mem;
  664. ret = qcom_pas_init_regulator(pas);
  665. if (ret)
  666. goto unassign_mem;
  667. ret = qcom_pas_pds_attach(&pdev->dev, pas->proxy_pds, desc->proxy_pd_names);
  668. if (ret < 0)
  669. goto unassign_mem;
  670. pas->proxy_pd_count = ret;
  671. ret = qcom_q6v5_init(&pas->q6v5, pdev, rproc, desc->crash_reason_smem,
  672. desc->load_state, qcom_pas_handover);
  673. if (ret)
  674. goto detach_proxy_pds;
  675. qcom_add_glink_subdev(rproc, &pas->glink_subdev, desc->ssr_name);
  676. qcom_add_smd_subdev(rproc, &pas->smd_subdev);
  677. qcom_add_pdm_subdev(rproc, &pas->pdm_subdev);
  678. pas->sysmon = qcom_add_sysmon_subdev(rproc, desc->sysmon_name, desc->ssctl_id);
  679. if (IS_ERR(pas->sysmon)) {
  680. ret = PTR_ERR(pas->sysmon);
  681. goto deinit_remove_pdm_smd_glink;
  682. }
  683. qcom_add_ssr_subdev(rproc, &pas->ssr_subdev, desc->ssr_name);
  684. pas->pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->pas_id,
  685. pas->mem_phys, pas->mem_size);
  686. if (IS_ERR(pas->pas_ctx)) {
  687. ret = PTR_ERR(pas->pas_ctx);
  688. goto remove_ssr_sysmon;
  689. }
  690. pas->dtb_pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->dtb_pas_id,
  691. pas->dtb_mem_phys,
  692. pas->dtb_mem_size);
  693. if (IS_ERR(pas->dtb_pas_ctx)) {
  694. ret = PTR_ERR(pas->dtb_pas_ctx);
  695. goto remove_ssr_sysmon;
  696. }
  697. pas->pas_ctx->use_tzmem = rproc->has_iommu;
  698. pas->dtb_pas_ctx->use_tzmem = rproc->has_iommu;
  699. ret = rproc_add(rproc);
  700. if (ret)
  701. goto remove_ssr_sysmon;
  702. return 0;
  703. remove_ssr_sysmon:
  704. qcom_remove_ssr_subdev(rproc, &pas->ssr_subdev);
  705. qcom_remove_sysmon_subdev(pas->sysmon);
  706. deinit_remove_pdm_smd_glink:
  707. qcom_remove_pdm_subdev(rproc, &pas->pdm_subdev);
  708. qcom_remove_smd_subdev(rproc, &pas->smd_subdev);
  709. qcom_remove_glink_subdev(rproc, &pas->glink_subdev);
  710. qcom_q6v5_deinit(&pas->q6v5);
  711. detach_proxy_pds:
  712. qcom_pas_pds_detach(pas, pas->proxy_pds, pas->proxy_pd_count);
  713. unassign_mem:
  714. qcom_pas_unassign_memory_region(pas);
  715. free_rproc:
  716. device_init_wakeup(pas->dev, false);
  717. return ret;
  718. }
  719. static void qcom_pas_remove(struct platform_device *pdev)
  720. {
  721. struct qcom_pas *pas = platform_get_drvdata(pdev);
  722. rproc_del(pas->rproc);
  723. qcom_q6v5_deinit(&pas->q6v5);
  724. qcom_pas_unassign_memory_region(pas);
  725. qcom_remove_glink_subdev(pas->rproc, &pas->glink_subdev);
  726. qcom_remove_sysmon_subdev(pas->sysmon);
  727. qcom_remove_smd_subdev(pas->rproc, &pas->smd_subdev);
  728. qcom_remove_pdm_subdev(pas->rproc, &pas->pdm_subdev);
  729. qcom_remove_ssr_subdev(pas->rproc, &pas->ssr_subdev);
  730. qcom_pas_pds_detach(pas, pas->proxy_pds, pas->proxy_pd_count);
  731. device_init_wakeup(pas->dev, false);
  732. }
  733. static const struct qcom_pas_data adsp_resource_init = {
  734. .crash_reason_smem = 423,
  735. .firmware_name = "adsp.mdt",
  736. .pas_id = 1,
  737. .auto_boot = true,
  738. .ssr_name = "lpass",
  739. .sysmon_name = "adsp",
  740. .ssctl_id = 0x14,
  741. };
  742. static const struct qcom_pas_data sa8775p_adsp_resource = {
  743. .crash_reason_smem = 423,
  744. .firmware_name = "adsp.mbn",
  745. .pas_id = 1,
  746. .minidump_id = 5,
  747. .auto_boot = true,
  748. .proxy_pd_names = (char*[]){
  749. "lcx",
  750. "lmx",
  751. NULL
  752. },
  753. .load_state = "adsp",
  754. .ssr_name = "lpass",
  755. .sysmon_name = "adsp",
  756. .ssctl_id = 0x14,
  757. };
  758. static const struct qcom_pas_data sdm845_adsp_resource_init = {
  759. .crash_reason_smem = 423,
  760. .firmware_name = "adsp.mdt",
  761. .pas_id = 1,
  762. .auto_boot = true,
  763. .load_state = "adsp",
  764. .ssr_name = "lpass",
  765. .sysmon_name = "adsp",
  766. .ssctl_id = 0x14,
  767. };
  768. static const struct qcom_pas_data sm6350_adsp_resource = {
  769. .crash_reason_smem = 423,
  770. .firmware_name = "adsp.mdt",
  771. .pas_id = 1,
  772. .auto_boot = true,
  773. .proxy_pd_names = (char*[]){
  774. "lcx",
  775. "lmx",
  776. NULL
  777. },
  778. .load_state = "adsp",
  779. .ssr_name = "lpass",
  780. .sysmon_name = "adsp",
  781. .ssctl_id = 0x14,
  782. };
  783. static const struct qcom_pas_data sm6375_mpss_resource = {
  784. .crash_reason_smem = 421,
  785. .firmware_name = "modem.mdt",
  786. .pas_id = 4,
  787. .minidump_id = 3,
  788. .auto_boot = false,
  789. .proxy_pd_names = (char*[]){
  790. "cx",
  791. NULL
  792. },
  793. .ssr_name = "mpss",
  794. .sysmon_name = "modem",
  795. .ssctl_id = 0x12,
  796. };
  797. static const struct qcom_pas_data sm8150_adsp_resource = {
  798. .crash_reason_smem = 423,
  799. .firmware_name = "adsp.mdt",
  800. .pas_id = 1,
  801. .auto_boot = true,
  802. .proxy_pd_names = (char*[]){
  803. "cx",
  804. NULL
  805. },
  806. .load_state = "adsp",
  807. .ssr_name = "lpass",
  808. .sysmon_name = "adsp",
  809. .ssctl_id = 0x14,
  810. };
  811. static const struct qcom_pas_data sm8250_adsp_resource = {
  812. .crash_reason_smem = 423,
  813. .firmware_name = "adsp.mdt",
  814. .pas_id = 1,
  815. .minidump_id = 5,
  816. .auto_boot = true,
  817. .proxy_pd_names = (char*[]){
  818. "lcx",
  819. "lmx",
  820. NULL
  821. },
  822. .load_state = "adsp",
  823. .ssr_name = "lpass",
  824. .sysmon_name = "adsp",
  825. .ssctl_id = 0x14,
  826. };
  827. static const struct qcom_pas_data sm8350_adsp_resource = {
  828. .crash_reason_smem = 423,
  829. .firmware_name = "adsp.mdt",
  830. .pas_id = 1,
  831. .auto_boot = true,
  832. .proxy_pd_names = (char*[]){
  833. "lcx",
  834. "lmx",
  835. NULL
  836. },
  837. .load_state = "adsp",
  838. .ssr_name = "lpass",
  839. .sysmon_name = "adsp",
  840. .ssctl_id = 0x14,
  841. };
  842. static const struct qcom_pas_data msm8996_adsp_resource = {
  843. .crash_reason_smem = 423,
  844. .firmware_name = "adsp.mdt",
  845. .pas_id = 1,
  846. .auto_boot = true,
  847. .proxy_pd_names = (char*[]){
  848. "cx",
  849. NULL
  850. },
  851. .ssr_name = "lpass",
  852. .sysmon_name = "adsp",
  853. .ssctl_id = 0x14,
  854. };
  855. static const struct qcom_pas_data cdsp_resource_init = {
  856. .crash_reason_smem = 601,
  857. .firmware_name = "cdsp.mdt",
  858. .pas_id = 18,
  859. .auto_boot = true,
  860. .ssr_name = "cdsp",
  861. .sysmon_name = "cdsp",
  862. .ssctl_id = 0x17,
  863. };
  864. static const struct qcom_pas_data sa8775p_cdsp0_resource = {
  865. .crash_reason_smem = 601,
  866. .firmware_name = "cdsp0.mbn",
  867. .pas_id = 18,
  868. .minidump_id = 7,
  869. .auto_boot = true,
  870. .proxy_pd_names = (char*[]){
  871. "cx",
  872. "mxc",
  873. "nsp",
  874. NULL
  875. },
  876. .load_state = "cdsp",
  877. .ssr_name = "cdsp",
  878. .sysmon_name = "cdsp",
  879. .ssctl_id = 0x17,
  880. };
  881. static const struct qcom_pas_data sa8775p_cdsp1_resource = {
  882. .crash_reason_smem = 633,
  883. .firmware_name = "cdsp1.mbn",
  884. .pas_id = 30,
  885. .minidump_id = 20,
  886. .auto_boot = true,
  887. .proxy_pd_names = (char*[]){
  888. "cx",
  889. "mxc",
  890. "nsp",
  891. NULL
  892. },
  893. .load_state = "nsp",
  894. .ssr_name = "cdsp1",
  895. .sysmon_name = "cdsp1",
  896. .ssctl_id = 0x20,
  897. };
  898. static const struct qcom_pas_data sdm845_cdsp_resource_init = {
  899. .crash_reason_smem = 601,
  900. .firmware_name = "cdsp.mdt",
  901. .pas_id = 18,
  902. .auto_boot = true,
  903. .load_state = "cdsp",
  904. .ssr_name = "cdsp",
  905. .sysmon_name = "cdsp",
  906. .ssctl_id = 0x17,
  907. };
  908. static const struct qcom_pas_data sm6350_cdsp_resource = {
  909. .crash_reason_smem = 601,
  910. .firmware_name = "cdsp.mdt",
  911. .pas_id = 18,
  912. .auto_boot = true,
  913. .proxy_pd_names = (char*[]){
  914. "cx",
  915. "mx",
  916. NULL
  917. },
  918. .load_state = "cdsp",
  919. .ssr_name = "cdsp",
  920. .sysmon_name = "cdsp",
  921. .ssctl_id = 0x17,
  922. };
  923. static const struct qcom_pas_data sm8150_cdsp_resource = {
  924. .crash_reason_smem = 601,
  925. .firmware_name = "cdsp.mdt",
  926. .pas_id = 18,
  927. .auto_boot = true,
  928. .proxy_pd_names = (char*[]){
  929. "cx",
  930. NULL
  931. },
  932. .load_state = "cdsp",
  933. .ssr_name = "cdsp",
  934. .sysmon_name = "cdsp",
  935. .ssctl_id = 0x17,
  936. };
  937. static const struct qcom_pas_data sm8250_cdsp_resource = {
  938. .crash_reason_smem = 601,
  939. .firmware_name = "cdsp.mdt",
  940. .pas_id = 18,
  941. .auto_boot = true,
  942. .proxy_pd_names = (char*[]){
  943. "cx",
  944. NULL
  945. },
  946. .load_state = "cdsp",
  947. .ssr_name = "cdsp",
  948. .sysmon_name = "cdsp",
  949. .ssctl_id = 0x17,
  950. };
  951. static const struct qcom_pas_data sc8280xp_nsp0_resource = {
  952. .crash_reason_smem = 601,
  953. .firmware_name = "cdsp.mdt",
  954. .pas_id = 18,
  955. .auto_boot = true,
  956. .proxy_pd_names = (char*[]){
  957. "nsp",
  958. NULL
  959. },
  960. .ssr_name = "cdsp0",
  961. .sysmon_name = "cdsp",
  962. .ssctl_id = 0x17,
  963. };
  964. static const struct qcom_pas_data sc8280xp_nsp1_resource = {
  965. .crash_reason_smem = 633,
  966. .firmware_name = "cdsp.mdt",
  967. .pas_id = 30,
  968. .auto_boot = true,
  969. .proxy_pd_names = (char*[]){
  970. "nsp",
  971. NULL
  972. },
  973. .ssr_name = "cdsp1",
  974. .sysmon_name = "cdsp1",
  975. .ssctl_id = 0x20,
  976. };
  977. static const struct qcom_pas_data x1e80100_adsp_resource = {
  978. .crash_reason_smem = 423,
  979. .firmware_name = "adsp.mdt",
  980. .dtb_firmware_name = "adsp_dtb.mdt",
  981. .pas_id = 1,
  982. .dtb_pas_id = 0x24,
  983. .lite_pas_id = 0x1f,
  984. .lite_dtb_pas_id = 0x29,
  985. .minidump_id = 5,
  986. .auto_boot = true,
  987. .proxy_pd_names = (char*[]){
  988. "lcx",
  989. "lmx",
  990. NULL
  991. },
  992. .load_state = "adsp",
  993. .ssr_name = "lpass",
  994. .sysmon_name = "adsp",
  995. .ssctl_id = 0x14,
  996. };
  997. static const struct qcom_pas_data x1e80100_cdsp_resource = {
  998. .crash_reason_smem = 601,
  999. .firmware_name = "cdsp.mdt",
  1000. .dtb_firmware_name = "cdsp_dtb.mdt",
  1001. .pas_id = 18,
  1002. .dtb_pas_id = 0x25,
  1003. .minidump_id = 7,
  1004. .auto_boot = true,
  1005. .proxy_pd_names = (char*[]){
  1006. "cx",
  1007. "mxc",
  1008. "nsp",
  1009. NULL
  1010. },
  1011. .load_state = "cdsp",
  1012. .ssr_name = "cdsp",
  1013. .sysmon_name = "cdsp",
  1014. .ssctl_id = 0x17,
  1015. };
  1016. static const struct qcom_pas_data sm8350_cdsp_resource = {
  1017. .crash_reason_smem = 601,
  1018. .firmware_name = "cdsp.mdt",
  1019. .pas_id = 18,
  1020. .minidump_id = 7,
  1021. .auto_boot = true,
  1022. .proxy_pd_names = (char*[]){
  1023. "cx",
  1024. "mxc",
  1025. NULL
  1026. },
  1027. .load_state = "cdsp",
  1028. .ssr_name = "cdsp",
  1029. .sysmon_name = "cdsp",
  1030. .ssctl_id = 0x17,
  1031. };
  1032. static const struct qcom_pas_data sa8775p_gpdsp0_resource = {
  1033. .crash_reason_smem = 640,
  1034. .firmware_name = "gpdsp0.mbn",
  1035. .pas_id = 39,
  1036. .minidump_id = 21,
  1037. .auto_boot = true,
  1038. .proxy_pd_names = (char*[]){
  1039. "cx",
  1040. "mxc",
  1041. NULL
  1042. },
  1043. .load_state = "gpdsp0",
  1044. .ssr_name = "gpdsp0",
  1045. .sysmon_name = "gpdsp0",
  1046. .ssctl_id = 0x21,
  1047. };
  1048. static const struct qcom_pas_data sa8775p_gpdsp1_resource = {
  1049. .crash_reason_smem = 641,
  1050. .firmware_name = "gpdsp1.mbn",
  1051. .pas_id = 40,
  1052. .minidump_id = 22,
  1053. .auto_boot = true,
  1054. .proxy_pd_names = (char*[]){
  1055. "cx",
  1056. "mxc",
  1057. NULL
  1058. },
  1059. .load_state = "gpdsp1",
  1060. .ssr_name = "gpdsp1",
  1061. .sysmon_name = "gpdsp1",
  1062. .ssctl_id = 0x22,
  1063. };
  1064. static const struct qcom_pas_data mpss_resource_init = {
  1065. .crash_reason_smem = 421,
  1066. .firmware_name = "modem.mdt",
  1067. .pas_id = 4,
  1068. .minidump_id = 3,
  1069. .auto_boot = false,
  1070. .proxy_pd_names = (char*[]){
  1071. "cx",
  1072. "mss",
  1073. NULL
  1074. },
  1075. .load_state = "modem",
  1076. .ssr_name = "mpss",
  1077. .sysmon_name = "modem",
  1078. .ssctl_id = 0x12,
  1079. };
  1080. static const struct qcom_pas_data sc8180x_mpss_resource = {
  1081. .crash_reason_smem = 421,
  1082. .firmware_name = "modem.mdt",
  1083. .pas_id = 4,
  1084. .auto_boot = false,
  1085. .proxy_pd_names = (char*[]){
  1086. "cx",
  1087. NULL
  1088. },
  1089. .load_state = "modem",
  1090. .ssr_name = "mpss",
  1091. .sysmon_name = "modem",
  1092. .ssctl_id = 0x12,
  1093. };
  1094. static const struct qcom_pas_data msm8996_slpi_resource_init = {
  1095. .crash_reason_smem = 424,
  1096. .firmware_name = "slpi.mdt",
  1097. .pas_id = 12,
  1098. .auto_boot = true,
  1099. .proxy_pd_names = (char*[]){
  1100. "ssc_cx",
  1101. NULL
  1102. },
  1103. .ssr_name = "dsps",
  1104. .sysmon_name = "slpi",
  1105. .ssctl_id = 0x16,
  1106. };
  1107. static const struct qcom_pas_data sdm845_slpi_resource_init = {
  1108. .crash_reason_smem = 424,
  1109. .firmware_name = "slpi.mdt",
  1110. .pas_id = 12,
  1111. .auto_boot = true,
  1112. .proxy_pd_names = (char*[]){
  1113. "lcx",
  1114. "lmx",
  1115. NULL
  1116. },
  1117. .load_state = "slpi",
  1118. .ssr_name = "dsps",
  1119. .sysmon_name = "slpi",
  1120. .ssctl_id = 0x16,
  1121. };
  1122. static const struct qcom_pas_data wcss_resource_init = {
  1123. .crash_reason_smem = 421,
  1124. .firmware_name = "wcnss.mdt",
  1125. .pas_id = 6,
  1126. .auto_boot = true,
  1127. .ssr_name = "mpss",
  1128. .sysmon_name = "wcnss",
  1129. .ssctl_id = 0x12,
  1130. };
  1131. static const struct qcom_pas_data sdx55_mpss_resource = {
  1132. .crash_reason_smem = 421,
  1133. .firmware_name = "modem.mdt",
  1134. .pas_id = 4,
  1135. .auto_boot = true,
  1136. .proxy_pd_names = (char*[]){
  1137. "cx",
  1138. "mss",
  1139. NULL
  1140. },
  1141. .ssr_name = "mpss",
  1142. .sysmon_name = "modem",
  1143. .ssctl_id = 0x22,
  1144. };
  1145. static const struct qcom_pas_data milos_cdsp_resource = {
  1146. .crash_reason_smem = 601,
  1147. .firmware_name = "cdsp.mbn",
  1148. .dtb_firmware_name = "cdsp_dtb.mbn",
  1149. .pas_id = 18,
  1150. .dtb_pas_id = 0x25,
  1151. .minidump_id = 7,
  1152. .auto_boot = true,
  1153. .proxy_pd_names = (char*[]){
  1154. "cx",
  1155. "mx",
  1156. NULL
  1157. },
  1158. .load_state = "cdsp",
  1159. .ssr_name = "cdsp",
  1160. .sysmon_name = "cdsp",
  1161. .ssctl_id = 0x17,
  1162. .smem_host_id = 5,
  1163. };
  1164. static const struct qcom_pas_data sm8450_mpss_resource = {
  1165. .crash_reason_smem = 421,
  1166. .firmware_name = "modem.mdt",
  1167. .pas_id = 4,
  1168. .minidump_id = 3,
  1169. .auto_boot = false,
  1170. .decrypt_shutdown = true,
  1171. .proxy_pd_names = (char*[]){
  1172. "cx",
  1173. "mss",
  1174. NULL
  1175. },
  1176. .load_state = "modem",
  1177. .ssr_name = "mpss",
  1178. .sysmon_name = "modem",
  1179. .ssctl_id = 0x12,
  1180. };
  1181. static const struct qcom_pas_data sm8550_adsp_resource = {
  1182. .crash_reason_smem = 423,
  1183. .firmware_name = "adsp.mdt",
  1184. .dtb_firmware_name = "adsp_dtb.mdt",
  1185. .pas_id = 1,
  1186. .dtb_pas_id = 0x24,
  1187. .minidump_id = 5,
  1188. .auto_boot = true,
  1189. .proxy_pd_names = (char*[]){
  1190. "lcx",
  1191. "lmx",
  1192. NULL
  1193. },
  1194. .load_state = "adsp",
  1195. .ssr_name = "lpass",
  1196. .sysmon_name = "adsp",
  1197. .ssctl_id = 0x14,
  1198. .smem_host_id = 2,
  1199. };
  1200. static const struct qcom_pas_data sm8550_cdsp_resource = {
  1201. .crash_reason_smem = 601,
  1202. .firmware_name = "cdsp.mdt",
  1203. .dtb_firmware_name = "cdsp_dtb.mdt",
  1204. .pas_id = 18,
  1205. .dtb_pas_id = 0x25,
  1206. .minidump_id = 7,
  1207. .auto_boot = true,
  1208. .proxy_pd_names = (char*[]){
  1209. "cx",
  1210. "mxc",
  1211. "nsp",
  1212. NULL
  1213. },
  1214. .load_state = "cdsp",
  1215. .ssr_name = "cdsp",
  1216. .sysmon_name = "cdsp",
  1217. .ssctl_id = 0x17,
  1218. .smem_host_id = 5,
  1219. };
  1220. static const struct qcom_pas_data sm8550_mpss_resource = {
  1221. .crash_reason_smem = 421,
  1222. .firmware_name = "modem.mdt",
  1223. .dtb_firmware_name = "modem_dtb.mdt",
  1224. .pas_id = 4,
  1225. .dtb_pas_id = 0x26,
  1226. .minidump_id = 3,
  1227. .auto_boot = false,
  1228. .decrypt_shutdown = true,
  1229. .proxy_pd_names = (char*[]){
  1230. "cx",
  1231. "mss",
  1232. NULL
  1233. },
  1234. .load_state = "modem",
  1235. .ssr_name = "mpss",
  1236. .sysmon_name = "modem",
  1237. .ssctl_id = 0x12,
  1238. .smem_host_id = 1,
  1239. .region_assign_idx = 2,
  1240. .region_assign_count = 1,
  1241. .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA,
  1242. };
  1243. static const struct qcom_pas_data sc7280_wpss_resource = {
  1244. .crash_reason_smem = 626,
  1245. .firmware_name = "wpss.mdt",
  1246. .pas_id = 6,
  1247. .minidump_id = 4,
  1248. .auto_boot = false,
  1249. .proxy_pd_names = (char*[]){
  1250. "cx",
  1251. "mx",
  1252. NULL
  1253. },
  1254. .load_state = "wpss",
  1255. .ssr_name = "wpss",
  1256. .sysmon_name = "wpss",
  1257. .ssctl_id = 0x19,
  1258. };
  1259. static const struct qcom_pas_data sm8650_cdsp_resource = {
  1260. .crash_reason_smem = 601,
  1261. .firmware_name = "cdsp.mdt",
  1262. .dtb_firmware_name = "cdsp_dtb.mdt",
  1263. .pas_id = 18,
  1264. .dtb_pas_id = 0x25,
  1265. .minidump_id = 7,
  1266. .auto_boot = true,
  1267. .proxy_pd_names = (char*[]){
  1268. "cx",
  1269. "mxc",
  1270. "nsp",
  1271. NULL
  1272. },
  1273. .load_state = "cdsp",
  1274. .ssr_name = "cdsp",
  1275. .sysmon_name = "cdsp",
  1276. .ssctl_id = 0x17,
  1277. .smem_host_id = 5,
  1278. .region_assign_idx = 2,
  1279. .region_assign_count = 1,
  1280. .region_assign_shared = true,
  1281. .region_assign_vmid = QCOM_SCM_VMID_CDSP,
  1282. };
  1283. static const struct qcom_pas_data sm8650_mpss_resource = {
  1284. .crash_reason_smem = 421,
  1285. .firmware_name = "modem.mdt",
  1286. .dtb_firmware_name = "modem_dtb.mdt",
  1287. .pas_id = 4,
  1288. .dtb_pas_id = 0x26,
  1289. .minidump_id = 3,
  1290. .auto_boot = false,
  1291. .decrypt_shutdown = true,
  1292. .proxy_pd_names = (char*[]){
  1293. "cx",
  1294. "mss",
  1295. NULL
  1296. },
  1297. .load_state = "modem",
  1298. .ssr_name = "mpss",
  1299. .sysmon_name = "modem",
  1300. .ssctl_id = 0x12,
  1301. .smem_host_id = 1,
  1302. .region_assign_idx = 2,
  1303. .region_assign_count = 3,
  1304. .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA,
  1305. };
  1306. static const struct qcom_pas_data sm8750_mpss_resource = {
  1307. .crash_reason_smem = 421,
  1308. .firmware_name = "modem.mdt",
  1309. .dtb_firmware_name = "modem_dtb.mdt",
  1310. .pas_id = 4,
  1311. .dtb_pas_id = 0x26,
  1312. .minidump_id = 3,
  1313. .auto_boot = false,
  1314. .decrypt_shutdown = true,
  1315. .proxy_pd_names = (char*[]){
  1316. "cx",
  1317. "mss",
  1318. NULL
  1319. },
  1320. .load_state = "modem",
  1321. .ssr_name = "mpss",
  1322. .sysmon_name = "modem",
  1323. .ssctl_id = 0x12,
  1324. .smem_host_id = 1,
  1325. .region_assign_idx = 2,
  1326. .region_assign_count = 2,
  1327. .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA,
  1328. };
  1329. static const struct of_device_id qcom_pas_of_match[] = {
  1330. { .compatible = "qcom,milos-adsp-pas", .data = &sm8550_adsp_resource},
  1331. { .compatible = "qcom,milos-cdsp-pas", .data = &milos_cdsp_resource},
  1332. { .compatible = "qcom,milos-mpss-pas", .data = &sm8450_mpss_resource},
  1333. { .compatible = "qcom,milos-wpss-pas", .data = &sc7280_wpss_resource},
  1334. { .compatible = "qcom,msm8226-adsp-pil", .data = &msm8996_adsp_resource},
  1335. { .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource},
  1336. { .compatible = "qcom,msm8974-adsp-pil", .data = &msm8996_adsp_resource},
  1337. { .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource},
  1338. { .compatible = "qcom,msm8996-slpi-pil", .data = &msm8996_slpi_resource_init},
  1339. { .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource},
  1340. { .compatible = "qcom,msm8998-slpi-pas", .data = &msm8996_slpi_resource_init},
  1341. { .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init },
  1342. { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init },
  1343. { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },
  1344. { .compatible = "qcom,sa8775p-adsp-pas", .data = &sa8775p_adsp_resource},
  1345. { .compatible = "qcom,sa8775p-cdsp0-pas", .data = &sa8775p_cdsp0_resource},
  1346. { .compatible = "qcom,sa8775p-cdsp1-pas", .data = &sa8775p_cdsp1_resource},
  1347. { .compatible = "qcom,sa8775p-gpdsp0-pas", .data = &sa8775p_gpdsp0_resource},
  1348. { .compatible = "qcom,sa8775p-gpdsp1-pas", .data = &sa8775p_gpdsp1_resource},
  1349. { .compatible = "qcom,sar2130p-adsp-pas", .data = &sm8350_adsp_resource},
  1350. { .compatible = "qcom,sc7180-adsp-pas", .data = &sm8250_adsp_resource},
  1351. { .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init},
  1352. { .compatible = "qcom,sc7280-adsp-pas", .data = &sm8350_adsp_resource},
  1353. { .compatible = "qcom,sc7280-cdsp-pas", .data = &sm6350_cdsp_resource},
  1354. { .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init},
  1355. { .compatible = "qcom,sc7280-wpss-pas", .data = &sc7280_wpss_resource},
  1356. { .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource},
  1357. { .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource},
  1358. { .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource},
  1359. { .compatible = "qcom,sc8280xp-adsp-pas", .data = &sm8250_adsp_resource},
  1360. { .compatible = "qcom,sc8280xp-nsp0-pas", .data = &sc8280xp_nsp0_resource},
  1361. { .compatible = "qcom,sc8280xp-nsp1-pas", .data = &sc8280xp_nsp1_resource},
  1362. { .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init},
  1363. { .compatible = "qcom,sdm660-cdsp-pas", .data = &cdsp_resource_init},
  1364. { .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init},
  1365. { .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init},
  1366. { .compatible = "qcom,sdm845-slpi-pas", .data = &sdm845_slpi_resource_init},
  1367. { .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource},
  1368. { .compatible = "qcom,sdx75-mpss-pas", .data = &sm8650_mpss_resource},
  1369. { .compatible = "qcom,sm6115-adsp-pas", .data = &adsp_resource_init},
  1370. { .compatible = "qcom,sm6115-cdsp-pas", .data = &cdsp_resource_init},
  1371. { .compatible = "qcom,sm6115-mpss-pas", .data = &sc8180x_mpss_resource},
  1372. { .compatible = "qcom,sm6350-adsp-pas", .data = &sm6350_adsp_resource},
  1373. { .compatible = "qcom,sm6350-cdsp-pas", .data = &sm6350_cdsp_resource},
  1374. { .compatible = "qcom,sm6350-mpss-pas", .data = &mpss_resource_init},
  1375. { .compatible = "qcom,sm6375-adsp-pas", .data = &sm6350_adsp_resource},
  1376. { .compatible = "qcom,sm6375-cdsp-pas", .data = &sm8150_cdsp_resource},
  1377. { .compatible = "qcom,sm6375-mpss-pas", .data = &sm6375_mpss_resource},
  1378. { .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource},
  1379. { .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource},
  1380. { .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init},
  1381. { .compatible = "qcom,sm8150-slpi-pas", .data = &sdm845_slpi_resource_init},
  1382. { .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource},
  1383. { .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource},
  1384. { .compatible = "qcom,sm8250-slpi-pas", .data = &sdm845_slpi_resource_init},
  1385. { .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource},
  1386. { .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource},
  1387. { .compatible = "qcom,sm8350-slpi-pas", .data = &sdm845_slpi_resource_init},
  1388. { .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init},
  1389. { .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource},
  1390. { .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource},
  1391. { .compatible = "qcom,sm8450-slpi-pas", .data = &sdm845_slpi_resource_init},
  1392. { .compatible = "qcom,sm8450-mpss-pas", .data = &sm8450_mpss_resource},
  1393. { .compatible = "qcom,sm8550-adsp-pas", .data = &sm8550_adsp_resource},
  1394. { .compatible = "qcom,sm8550-cdsp-pas", .data = &sm8550_cdsp_resource},
  1395. { .compatible = "qcom,sm8550-mpss-pas", .data = &sm8550_mpss_resource},
  1396. { .compatible = "qcom,sm8650-adsp-pas", .data = &sm8550_adsp_resource},
  1397. { .compatible = "qcom,sm8650-cdsp-pas", .data = &sm8650_cdsp_resource},
  1398. { .compatible = "qcom,sm8650-mpss-pas", .data = &sm8650_mpss_resource},
  1399. { .compatible = "qcom,sm8750-mpss-pas", .data = &sm8750_mpss_resource},
  1400. { .compatible = "qcom,x1e80100-adsp-pas", .data = &x1e80100_adsp_resource},
  1401. { .compatible = "qcom,x1e80100-cdsp-pas", .data = &x1e80100_cdsp_resource},
  1402. { },
  1403. };
  1404. MODULE_DEVICE_TABLE(of, qcom_pas_of_match);
  1405. static struct platform_driver qcom_pas_driver = {
  1406. .probe = qcom_pas_probe,
  1407. .remove = qcom_pas_remove,
  1408. .driver = {
  1409. .name = "qcom_q6v5_pas",
  1410. .of_match_table = qcom_pas_of_match,
  1411. },
  1412. };
  1413. module_platform_driver(qcom_pas_driver);
  1414. MODULE_DESCRIPTION("Qualcomm Peripheral Authentication Service remoteproc driver");
  1415. MODULE_LICENSE("GPL v2");