qcom_q6v5_pil.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. /*
  2. * Qualcomm Peripheral Image Loader
  3. *
  4. * Copyright (C) 2016 Linaro Ltd.
  5. * Copyright (C) 2014 Sony Mobile Communications AB
  6. * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * version 2 as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. */
  17. #include <linux/clk.h>
  18. #include <linux/delay.h>
  19. #include <linux/dma-mapping.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/kernel.h>
  22. #include <linux/mfd/syscon.h>
  23. #include <linux/module.h>
  24. #include <linux/of_address.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/regmap.h>
  27. #include <linux/regulator/consumer.h>
  28. #include <linux/remoteproc.h>
  29. #include <linux/reset.h>
  30. #include <linux/soc/qcom/smem.h>
  31. #include <linux/soc/qcom/smem_state.h>
  32. #include "remoteproc_internal.h"
  33. #include "qcom_mdt_loader.h"
  34. #include <linux/qcom_scm.h>
  35. #define MBA_FIRMWARE_NAME "/*(DEBLOBBED)*/"
  36. #define MPSS_FIRMWARE_NAME "/*(DEBLOBBED)*/"
  37. #define MPSS_CRASH_REASON_SMEM 421
  38. /* RMB Status Register Values */
  39. #define RMB_PBL_SUCCESS 0x1
  40. #define RMB_MBA_XPU_UNLOCKED 0x1
  41. #define RMB_MBA_XPU_UNLOCKED_SCRIBBLED 0x2
  42. #define RMB_MBA_META_DATA_AUTH_SUCCESS 0x3
  43. #define RMB_MBA_AUTH_COMPLETE 0x4
  44. /* PBL/MBA interface registers */
  45. #define RMB_MBA_IMAGE_REG 0x00
  46. #define RMB_PBL_STATUS_REG 0x04
  47. #define RMB_MBA_COMMAND_REG 0x08
  48. #define RMB_MBA_STATUS_REG 0x0C
  49. #define RMB_PMI_META_DATA_REG 0x10
  50. #define RMB_PMI_CODE_START_REG 0x14
  51. #define RMB_PMI_CODE_LENGTH_REG 0x18
  52. #define RMB_CMD_META_DATA_READY 0x1
  53. #define RMB_CMD_LOAD_READY 0x2
  54. /* QDSP6SS Register Offsets */
  55. #define QDSP6SS_RESET_REG 0x014
  56. #define QDSP6SS_GFMUX_CTL_REG 0x020
  57. #define QDSP6SS_PWR_CTL_REG 0x030
  58. /* AXI Halt Register Offsets */
  59. #define AXI_HALTREQ_REG 0x0
  60. #define AXI_HALTACK_REG 0x4
  61. #define AXI_IDLE_REG 0x8
  62. #define HALT_ACK_TIMEOUT_MS 100
  63. /* QDSP6SS_RESET */
  64. #define Q6SS_STOP_CORE BIT(0)
  65. #define Q6SS_CORE_ARES BIT(1)
  66. #define Q6SS_BUS_ARES_ENABLE BIT(2)
  67. /* QDSP6SS_GFMUX_CTL */
  68. #define Q6SS_CLK_ENABLE BIT(1)
  69. /* QDSP6SS_PWR_CTL */
  70. #define Q6SS_L2DATA_SLP_NRET_N_0 BIT(0)
  71. #define Q6SS_L2DATA_SLP_NRET_N_1 BIT(1)
  72. #define Q6SS_L2DATA_SLP_NRET_N_2 BIT(2)
  73. #define Q6SS_L2TAG_SLP_NRET_N BIT(16)
  74. #define Q6SS_ETB_SLP_NRET_N BIT(17)
  75. #define Q6SS_L2DATA_STBY_N BIT(18)
  76. #define Q6SS_SLP_RET_N BIT(19)
  77. #define Q6SS_CLAMP_IO BIT(20)
  78. #define QDSS_BHS_ON BIT(21)
  79. #define QDSS_LDO_BYP BIT(22)
  80. struct q6v5 {
  81. struct device *dev;
  82. struct rproc *rproc;
  83. void __iomem *reg_base;
  84. void __iomem *rmb_base;
  85. struct regmap *halt_map;
  86. u32 halt_q6;
  87. u32 halt_modem;
  88. u32 halt_nc;
  89. struct reset_control *mss_restart;
  90. struct qcom_smem_state *state;
  91. unsigned stop_bit;
  92. struct regulator_bulk_data supply[4];
  93. struct clk *ahb_clk;
  94. struct clk *axi_clk;
  95. struct clk *rom_clk;
  96. struct completion start_done;
  97. struct completion stop_done;
  98. bool running;
  99. phys_addr_t mba_phys;
  100. void *mba_region;
  101. size_t mba_size;
  102. phys_addr_t mpss_phys;
  103. phys_addr_t mpss_reloc;
  104. void *mpss_region;
  105. size_t mpss_size;
  106. };
  107. enum {
  108. Q6V5_SUPPLY_CX,
  109. Q6V5_SUPPLY_MX,
  110. Q6V5_SUPPLY_MSS,
  111. Q6V5_SUPPLY_PLL,
  112. };
  113. static int q6v5_regulator_init(struct q6v5 *qproc)
  114. {
  115. int ret;
  116. qproc->supply[Q6V5_SUPPLY_CX].supply = "cx";
  117. qproc->supply[Q6V5_SUPPLY_MX].supply = "mx";
  118. qproc->supply[Q6V5_SUPPLY_MSS].supply = "mss";
  119. qproc->supply[Q6V5_SUPPLY_PLL].supply = "pll";
  120. ret = devm_regulator_bulk_get(qproc->dev,
  121. ARRAY_SIZE(qproc->supply), qproc->supply);
  122. if (ret < 0) {
  123. dev_err(qproc->dev, "failed to get supplies\n");
  124. return ret;
  125. }
  126. regulator_set_load(qproc->supply[Q6V5_SUPPLY_CX].consumer, 100000);
  127. regulator_set_load(qproc->supply[Q6V5_SUPPLY_MSS].consumer, 100000);
  128. regulator_set_load(qproc->supply[Q6V5_SUPPLY_PLL].consumer, 10000);
  129. return 0;
  130. }
  131. static int q6v5_regulator_enable(struct q6v5 *qproc)
  132. {
  133. struct regulator *mss = qproc->supply[Q6V5_SUPPLY_MSS].consumer;
  134. struct regulator *mx = qproc->supply[Q6V5_SUPPLY_MX].consumer;
  135. int ret;
  136. /* TODO: Q6V5_SUPPLY_CX is supposed to be set to super-turbo here */
  137. ret = regulator_set_voltage(mx, 1050000, INT_MAX);
  138. if (ret)
  139. return ret;
  140. regulator_set_voltage(mss, 1000000, 1150000);
  141. return regulator_bulk_enable(ARRAY_SIZE(qproc->supply), qproc->supply);
  142. }
  143. static void q6v5_regulator_disable(struct q6v5 *qproc)
  144. {
  145. struct regulator *mss = qproc->supply[Q6V5_SUPPLY_MSS].consumer;
  146. struct regulator *mx = qproc->supply[Q6V5_SUPPLY_MX].consumer;
  147. /* TODO: Q6V5_SUPPLY_CX corner votes should be released */
  148. regulator_bulk_disable(ARRAY_SIZE(qproc->supply), qproc->supply);
  149. regulator_set_voltage(mx, 0, INT_MAX);
  150. regulator_set_voltage(mss, 0, 1150000);
  151. }
  152. static int q6v5_load(struct rproc *rproc, const struct firmware *fw)
  153. {
  154. struct q6v5 *qproc = rproc->priv;
  155. memcpy(qproc->mba_region, fw->data, fw->size);
  156. return 0;
  157. }
  158. static const struct rproc_fw_ops q6v5_fw_ops = {
  159. .find_rsc_table = qcom_mdt_find_rsc_table,
  160. .load = q6v5_load,
  161. };
  162. static int q6v5_rmb_pbl_wait(struct q6v5 *qproc, int ms)
  163. {
  164. unsigned long timeout;
  165. s32 val;
  166. timeout = jiffies + msecs_to_jiffies(ms);
  167. for (;;) {
  168. val = readl(qproc->rmb_base + RMB_PBL_STATUS_REG);
  169. if (val)
  170. break;
  171. if (time_after(jiffies, timeout))
  172. return -ETIMEDOUT;
  173. msleep(1);
  174. }
  175. return val;
  176. }
  177. static int q6v5_rmb_mba_wait(struct q6v5 *qproc, u32 status, int ms)
  178. {
  179. unsigned long timeout;
  180. s32 val;
  181. timeout = jiffies + msecs_to_jiffies(ms);
  182. for (;;) {
  183. val = readl(qproc->rmb_base + RMB_MBA_STATUS_REG);
  184. if (val < 0)
  185. break;
  186. if (!status && val)
  187. break;
  188. else if (status && val == status)
  189. break;
  190. if (time_after(jiffies, timeout))
  191. return -ETIMEDOUT;
  192. msleep(1);
  193. }
  194. return val;
  195. }
  196. static int q6v5proc_reset(struct q6v5 *qproc)
  197. {
  198. u32 val;
  199. int ret;
  200. /* Assert resets, stop core */
  201. val = readl(qproc->reg_base + QDSP6SS_RESET_REG);
  202. val |= (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE);
  203. writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
  204. /* Enable power block headswitch, and wait for it to stabilize */
  205. val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
  206. val |= QDSS_BHS_ON | QDSS_LDO_BYP;
  207. writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
  208. udelay(1);
  209. /*
  210. * Turn on memories. L2 banks should be done individually
  211. * to minimize inrush current.
  212. */
  213. val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
  214. val |= Q6SS_SLP_RET_N | Q6SS_L2TAG_SLP_NRET_N |
  215. Q6SS_ETB_SLP_NRET_N | Q6SS_L2DATA_STBY_N;
  216. writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
  217. val |= Q6SS_L2DATA_SLP_NRET_N_2;
  218. writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
  219. val |= Q6SS_L2DATA_SLP_NRET_N_1;
  220. writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
  221. val |= Q6SS_L2DATA_SLP_NRET_N_0;
  222. writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
  223. /* Remove IO clamp */
  224. val &= ~Q6SS_CLAMP_IO;
  225. writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
  226. /* Bring core out of reset */
  227. val = readl(qproc->reg_base + QDSP6SS_RESET_REG);
  228. val &= ~Q6SS_CORE_ARES;
  229. writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
  230. /* Turn on core clock */
  231. val = readl(qproc->reg_base + QDSP6SS_GFMUX_CTL_REG);
  232. val |= Q6SS_CLK_ENABLE;
  233. writel(val, qproc->reg_base + QDSP6SS_GFMUX_CTL_REG);
  234. /* Start core execution */
  235. val = readl(qproc->reg_base + QDSP6SS_RESET_REG);
  236. val &= ~Q6SS_STOP_CORE;
  237. writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
  238. /* Wait for PBL status */
  239. ret = q6v5_rmb_pbl_wait(qproc, 1000);
  240. if (ret == -ETIMEDOUT) {
  241. dev_err(qproc->dev, "PBL boot timed out\n");
  242. } else if (ret != RMB_PBL_SUCCESS) {
  243. dev_err(qproc->dev, "PBL returned unexpected status %d\n", ret);
  244. ret = -EINVAL;
  245. } else {
  246. ret = 0;
  247. }
  248. return ret;
  249. }
  250. static void q6v5proc_halt_axi_port(struct q6v5 *qproc,
  251. struct regmap *halt_map,
  252. u32 offset)
  253. {
  254. unsigned long timeout;
  255. unsigned int val;
  256. int ret;
  257. /* Check if we're already idle */
  258. ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
  259. if (!ret && val)
  260. return;
  261. /* Assert halt request */
  262. regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1);
  263. /* Wait for halt */
  264. timeout = jiffies + msecs_to_jiffies(HALT_ACK_TIMEOUT_MS);
  265. for (;;) {
  266. ret = regmap_read(halt_map, offset + AXI_HALTACK_REG, &val);
  267. if (ret || val || time_after(jiffies, timeout))
  268. break;
  269. msleep(1);
  270. }
  271. ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
  272. if (ret || !val)
  273. dev_err(qproc->dev, "port failed halt\n");
  274. /* Clear halt request (port will remain halted until reset) */
  275. regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0);
  276. }
  277. static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
  278. {
  279. unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
  280. dma_addr_t phys;
  281. void *ptr;
  282. int ret;
  283. ptr = dma_alloc_attrs(qproc->dev, fw->size, &phys, GFP_KERNEL, dma_attrs);
  284. if (!ptr) {
  285. dev_err(qproc->dev, "failed to allocate mdt buffer\n");
  286. return -ENOMEM;
  287. }
  288. memcpy(ptr, fw->data, fw->size);
  289. writel(phys, qproc->rmb_base + RMB_PMI_META_DATA_REG);
  290. writel(RMB_CMD_META_DATA_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG);
  291. ret = q6v5_rmb_mba_wait(qproc, RMB_MBA_META_DATA_AUTH_SUCCESS, 1000);
  292. if (ret == -ETIMEDOUT)
  293. dev_err(qproc->dev, "MPSS header authentication timed out\n");
  294. else if (ret < 0)
  295. dev_err(qproc->dev, "MPSS header authentication failed: %d\n", ret);
  296. dma_free_attrs(qproc->dev, fw->size, ptr, phys, dma_attrs);
  297. return ret < 0 ? ret : 0;
  298. }
  299. static int q6v5_mpss_validate(struct q6v5 *qproc, const struct firmware *fw)
  300. {
  301. const struct elf32_phdr *phdrs;
  302. const struct elf32_phdr *phdr;
  303. struct elf32_hdr *ehdr;
  304. phys_addr_t boot_addr;
  305. phys_addr_t fw_addr;
  306. bool relocate;
  307. size_t size;
  308. int ret;
  309. int i;
  310. ret = qcom_mdt_parse(fw, &fw_addr, NULL, &relocate);
  311. if (ret) {
  312. dev_err(qproc->dev, "failed to parse mdt header\n");
  313. return ret;
  314. }
  315. if (relocate)
  316. boot_addr = qproc->mpss_phys;
  317. else
  318. boot_addr = fw_addr;
  319. ehdr = (struct elf32_hdr *)fw->data;
  320. phdrs = (struct elf32_phdr *)(ehdr + 1);
  321. for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
  322. phdr = &phdrs[i];
  323. if (phdr->p_type != PT_LOAD)
  324. continue;
  325. if ((phdr->p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH)
  326. continue;
  327. if (!phdr->p_memsz)
  328. continue;
  329. size = readl(qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);
  330. if (!size) {
  331. writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG);
  332. writel(RMB_CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG);
  333. }
  334. size += phdr->p_memsz;
  335. writel(size, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);
  336. }
  337. ret = q6v5_rmb_mba_wait(qproc, RMB_MBA_AUTH_COMPLETE, 10000);
  338. if (ret == -ETIMEDOUT)
  339. dev_err(qproc->dev, "MPSS authentication timed out\n");
  340. else if (ret < 0)
  341. dev_err(qproc->dev, "MPSS authentication failed: %d\n", ret);
  342. return ret < 0 ? ret : 0;
  343. }
  344. static int q6v5_mpss_load(struct q6v5 *qproc)
  345. {
  346. const struct firmware *fw;
  347. phys_addr_t fw_addr;
  348. bool relocate;
  349. int ret;
  350. ret = reject_firmware(&fw, MPSS_FIRMWARE_NAME, qproc->dev);
  351. if (ret < 0) {
  352. dev_err(qproc->dev, "unable to load " MPSS_FIRMWARE_NAME "\n");
  353. return ret;
  354. }
  355. ret = qcom_mdt_parse(fw, &fw_addr, NULL, &relocate);
  356. if (ret) {
  357. dev_err(qproc->dev, "failed to parse mdt header\n");
  358. goto release_firmware;
  359. }
  360. if (relocate)
  361. qproc->mpss_reloc = fw_addr;
  362. /* Initialize the RMB validator */
  363. writel(0, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);
  364. ret = q6v5_mpss_init_image(qproc, fw);
  365. if (ret)
  366. goto release_firmware;
  367. ret = qcom_mdt_load(qproc->rproc, fw, MPSS_FIRMWARE_NAME);
  368. if (ret)
  369. goto release_firmware;
  370. ret = q6v5_mpss_validate(qproc, fw);
  371. release_firmware:
  372. release_firmware(fw);
  373. return ret < 0 ? ret : 0;
  374. }
  375. static int q6v5_start(struct rproc *rproc)
  376. {
  377. struct q6v5 *qproc = (struct q6v5 *)rproc->priv;
  378. int ret;
  379. ret = q6v5_regulator_enable(qproc);
  380. if (ret) {
  381. dev_err(qproc->dev, "failed to enable supplies\n");
  382. return ret;
  383. }
  384. ret = reset_control_deassert(qproc->mss_restart);
  385. if (ret) {
  386. dev_err(qproc->dev, "failed to deassert mss restart\n");
  387. goto disable_vdd;
  388. }
  389. ret = clk_prepare_enable(qproc->ahb_clk);
  390. if (ret)
  391. goto assert_reset;
  392. ret = clk_prepare_enable(qproc->axi_clk);
  393. if (ret)
  394. goto disable_ahb_clk;
  395. ret = clk_prepare_enable(qproc->rom_clk);
  396. if (ret)
  397. goto disable_axi_clk;
  398. writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG);
  399. ret = q6v5proc_reset(qproc);
  400. if (ret)
  401. goto halt_axi_ports;
  402. ret = q6v5_rmb_mba_wait(qproc, 0, 5000);
  403. if (ret == -ETIMEDOUT) {
  404. dev_err(qproc->dev, "MBA boot timed out\n");
  405. goto halt_axi_ports;
  406. } else if (ret != RMB_MBA_XPU_UNLOCKED &&
  407. ret != RMB_MBA_XPU_UNLOCKED_SCRIBBLED) {
  408. dev_err(qproc->dev, "MBA returned unexpected status %d\n", ret);
  409. ret = -EINVAL;
  410. goto halt_axi_ports;
  411. }
  412. dev_info(qproc->dev, "MBA booted, loading mpss\n");
  413. ret = q6v5_mpss_load(qproc);
  414. if (ret)
  415. goto halt_axi_ports;
  416. ret = wait_for_completion_timeout(&qproc->start_done,
  417. msecs_to_jiffies(5000));
  418. if (ret == 0) {
  419. dev_err(qproc->dev, "start timed out\n");
  420. ret = -ETIMEDOUT;
  421. goto halt_axi_ports;
  422. }
  423. qproc->running = true;
  424. /* TODO: All done, release the handover resources */
  425. return 0;
  426. halt_axi_ports:
  427. q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6);
  428. q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);
  429. q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);
  430. clk_disable_unprepare(qproc->rom_clk);
  431. disable_axi_clk:
  432. clk_disable_unprepare(qproc->axi_clk);
  433. disable_ahb_clk:
  434. clk_disable_unprepare(qproc->ahb_clk);
  435. assert_reset:
  436. reset_control_assert(qproc->mss_restart);
  437. disable_vdd:
  438. q6v5_regulator_disable(qproc);
  439. return ret;
  440. }
  441. static int q6v5_stop(struct rproc *rproc)
  442. {
  443. struct q6v5 *qproc = (struct q6v5 *)rproc->priv;
  444. int ret;
  445. qproc->running = false;
  446. qcom_smem_state_update_bits(qproc->state,
  447. BIT(qproc->stop_bit), BIT(qproc->stop_bit));
  448. ret = wait_for_completion_timeout(&qproc->stop_done,
  449. msecs_to_jiffies(5000));
  450. if (ret == 0)
  451. dev_err(qproc->dev, "timed out on wait\n");
  452. qcom_smem_state_update_bits(qproc->state, BIT(qproc->stop_bit), 0);
  453. q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6);
  454. q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);
  455. q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);
  456. reset_control_assert(qproc->mss_restart);
  457. clk_disable_unprepare(qproc->rom_clk);
  458. clk_disable_unprepare(qproc->axi_clk);
  459. clk_disable_unprepare(qproc->ahb_clk);
  460. q6v5_regulator_disable(qproc);
  461. return 0;
  462. }
  463. static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
  464. {
  465. struct q6v5 *qproc = rproc->priv;
  466. int offset;
  467. offset = da - qproc->mpss_reloc;
  468. if (offset < 0 || offset + len > qproc->mpss_size)
  469. return NULL;
  470. return qproc->mpss_region + offset;
  471. }
  472. static const struct rproc_ops q6v5_ops = {
  473. .start = q6v5_start,
  474. .stop = q6v5_stop,
  475. .da_to_va = q6v5_da_to_va,
  476. };
  477. static irqreturn_t q6v5_wdog_interrupt(int irq, void *dev)
  478. {
  479. struct q6v5 *qproc = dev;
  480. size_t len;
  481. char *msg;
  482. /* Sometimes the stop triggers a watchdog rather than a stop-ack */
  483. if (!qproc->running) {
  484. complete(&qproc->stop_done);
  485. return IRQ_HANDLED;
  486. }
  487. msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, MPSS_CRASH_REASON_SMEM, &len);
  488. if (!IS_ERR(msg) && len > 0 && msg[0])
  489. dev_err(qproc->dev, "watchdog received: %s\n", msg);
  490. else
  491. dev_err(qproc->dev, "watchdog without message\n");
  492. rproc_report_crash(qproc->rproc, RPROC_WATCHDOG);
  493. if (!IS_ERR(msg))
  494. msg[0] = '\0';
  495. return IRQ_HANDLED;
  496. }
  497. static irqreturn_t q6v5_fatal_interrupt(int irq, void *dev)
  498. {
  499. struct q6v5 *qproc = dev;
  500. size_t len;
  501. char *msg;
  502. msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, MPSS_CRASH_REASON_SMEM, &len);
  503. if (!IS_ERR(msg) && len > 0 && msg[0])
  504. dev_err(qproc->dev, "fatal error received: %s\n", msg);
  505. else
  506. dev_err(qproc->dev, "fatal error without message\n");
  507. rproc_report_crash(qproc->rproc, RPROC_FATAL_ERROR);
  508. if (!IS_ERR(msg))
  509. msg[0] = '\0';
  510. return IRQ_HANDLED;
  511. }
  512. static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
  513. {
  514. struct q6v5 *qproc = dev;
  515. complete(&qproc->start_done);
  516. return IRQ_HANDLED;
  517. }
  518. static irqreturn_t q6v5_stop_ack_interrupt(int irq, void *dev)
  519. {
  520. struct q6v5 *qproc = dev;
  521. complete(&qproc->stop_done);
  522. return IRQ_HANDLED;
  523. }
  524. static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev)
  525. {
  526. struct of_phandle_args args;
  527. struct resource *res;
  528. int ret;
  529. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6");
  530. qproc->reg_base = devm_ioremap_resource(&pdev->dev, res);
  531. if (IS_ERR(qproc->reg_base))
  532. return PTR_ERR(qproc->reg_base);
  533. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb");
  534. qproc->rmb_base = devm_ioremap_resource(&pdev->dev, res);
  535. if (IS_ERR(qproc->rmb_base))
  536. return PTR_ERR(qproc->rmb_base);
  537. ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
  538. "qcom,halt-regs", 3, 0, &args);
  539. if (ret < 0) {
  540. dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
  541. return -EINVAL;
  542. }
  543. qproc->halt_map = syscon_node_to_regmap(args.np);
  544. of_node_put(args.np);
  545. if (IS_ERR(qproc->halt_map))
  546. return PTR_ERR(qproc->halt_map);
  547. qproc->halt_q6 = args.args[0];
  548. qproc->halt_modem = args.args[1];
  549. qproc->halt_nc = args.args[2];
  550. return 0;
  551. }
  552. static int q6v5_init_clocks(struct q6v5 *qproc)
  553. {
  554. qproc->ahb_clk = devm_clk_get(qproc->dev, "iface");
  555. if (IS_ERR(qproc->ahb_clk)) {
  556. dev_err(qproc->dev, "failed to get iface clock\n");
  557. return PTR_ERR(qproc->ahb_clk);
  558. }
  559. qproc->axi_clk = devm_clk_get(qproc->dev, "bus");
  560. if (IS_ERR(qproc->axi_clk)) {
  561. dev_err(qproc->dev, "failed to get bus clock\n");
  562. return PTR_ERR(qproc->axi_clk);
  563. }
  564. qproc->rom_clk = devm_clk_get(qproc->dev, "mem");
  565. if (IS_ERR(qproc->rom_clk)) {
  566. dev_err(qproc->dev, "failed to get mem clock\n");
  567. return PTR_ERR(qproc->rom_clk);
  568. }
  569. return 0;
  570. }
  571. static int q6v5_init_reset(struct q6v5 *qproc)
  572. {
  573. qproc->mss_restart = devm_reset_control_get(qproc->dev, NULL);
  574. if (IS_ERR(qproc->mss_restart)) {
  575. dev_err(qproc->dev, "failed to acquire mss restart\n");
  576. return PTR_ERR(qproc->mss_restart);
  577. }
  578. return 0;
  579. }
  580. static int q6v5_request_irq(struct q6v5 *qproc,
  581. struct platform_device *pdev,
  582. const char *name,
  583. irq_handler_t thread_fn)
  584. {
  585. int ret;
  586. ret = platform_get_irq_byname(pdev, name);
  587. if (ret < 0) {
  588. dev_err(&pdev->dev, "no %s IRQ defined\n", name);
  589. return ret;
  590. }
  591. ret = devm_request_threaded_irq(&pdev->dev, ret,
  592. NULL, thread_fn,
  593. IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  594. "q6v5", qproc);
  595. if (ret)
  596. dev_err(&pdev->dev, "request %s IRQ failed\n", name);
  597. return ret;
  598. }
  599. static int q6v5_alloc_memory_region(struct q6v5 *qproc)
  600. {
  601. struct device_node *child;
  602. struct device_node *node;
  603. struct resource r;
  604. int ret;
  605. child = of_get_child_by_name(qproc->dev->of_node, "mba");
  606. node = of_parse_phandle(child, "memory-region", 0);
  607. ret = of_address_to_resource(node, 0, &r);
  608. if (ret) {
  609. dev_err(qproc->dev, "unable to resolve mba region\n");
  610. return ret;
  611. }
  612. qproc->mba_phys = r.start;
  613. qproc->mba_size = resource_size(&r);
  614. qproc->mba_region = devm_ioremap_wc(qproc->dev, qproc->mba_phys, qproc->mba_size);
  615. if (!qproc->mba_region) {
  616. dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n",
  617. &r.start, qproc->mba_size);
  618. return -EBUSY;
  619. }
  620. child = of_get_child_by_name(qproc->dev->of_node, "mpss");
  621. node = of_parse_phandle(child, "memory-region", 0);
  622. ret = of_address_to_resource(node, 0, &r);
  623. if (ret) {
  624. dev_err(qproc->dev, "unable to resolve mpss region\n");
  625. return ret;
  626. }
  627. qproc->mpss_phys = qproc->mpss_reloc = r.start;
  628. qproc->mpss_size = resource_size(&r);
  629. qproc->mpss_region = devm_ioremap_wc(qproc->dev, qproc->mpss_phys, qproc->mpss_size);
  630. if (!qproc->mpss_region) {
  631. dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n",
  632. &r.start, qproc->mpss_size);
  633. return -EBUSY;
  634. }
  635. return 0;
  636. }
  637. static int q6v5_probe(struct platform_device *pdev)
  638. {
  639. struct q6v5 *qproc;
  640. struct rproc *rproc;
  641. int ret;
  642. rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_ops,
  643. MBA_FIRMWARE_NAME, sizeof(*qproc));
  644. if (!rproc) {
  645. dev_err(&pdev->dev, "failed to allocate rproc\n");
  646. return -ENOMEM;
  647. }
  648. rproc->fw_ops = &q6v5_fw_ops;
  649. qproc = (struct q6v5 *)rproc->priv;
  650. qproc->dev = &pdev->dev;
  651. qproc->rproc = rproc;
  652. platform_set_drvdata(pdev, qproc);
  653. init_completion(&qproc->start_done);
  654. init_completion(&qproc->stop_done);
  655. ret = q6v5_init_mem(qproc, pdev);
  656. if (ret)
  657. goto free_rproc;
  658. ret = q6v5_alloc_memory_region(qproc);
  659. if (ret)
  660. goto free_rproc;
  661. ret = q6v5_init_clocks(qproc);
  662. if (ret)
  663. goto free_rproc;
  664. ret = q6v5_regulator_init(qproc);
  665. if (ret)
  666. goto free_rproc;
  667. ret = q6v5_init_reset(qproc);
  668. if (ret)
  669. goto free_rproc;
  670. ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt);
  671. if (ret < 0)
  672. goto free_rproc;
  673. ret = q6v5_request_irq(qproc, pdev, "fatal", q6v5_fatal_interrupt);
  674. if (ret < 0)
  675. goto free_rproc;
  676. ret = q6v5_request_irq(qproc, pdev, "handover", q6v5_handover_interrupt);
  677. if (ret < 0)
  678. goto free_rproc;
  679. ret = q6v5_request_irq(qproc, pdev, "stop-ack", q6v5_stop_ack_interrupt);
  680. if (ret < 0)
  681. goto free_rproc;
  682. qproc->state = qcom_smem_state_get(&pdev->dev, "stop", &qproc->stop_bit);
  683. if (IS_ERR(qproc->state)) {
  684. ret = PTR_ERR(qproc->state);
  685. goto free_rproc;
  686. }
  687. ret = rproc_add(rproc);
  688. if (ret)
  689. goto free_rproc;
  690. return 0;
  691. free_rproc:
  692. rproc_free(rproc);
  693. return ret;
  694. }
  695. static int q6v5_remove(struct platform_device *pdev)
  696. {
  697. struct q6v5 *qproc = platform_get_drvdata(pdev);
  698. rproc_del(qproc->rproc);
  699. rproc_free(qproc->rproc);
  700. return 0;
  701. }
  702. static const struct of_device_id q6v5_of_match[] = {
  703. { .compatible = "qcom,q6v5-pil", },
  704. { },
  705. };
  706. static struct platform_driver q6v5_driver = {
  707. .probe = q6v5_probe,
  708. .remove = q6v5_remove,
  709. .driver = {
  710. .name = "qcom-q6v5-pil",
  711. .of_match_table = q6v5_of_match,
  712. },
  713. };
  714. module_platform_driver(q6v5_driver);
  715. MODULE_DESCRIPTION("Peripheral Image Loader for Hexagon");
  716. MODULE_LICENSE("GPL v2");