2 * Qualcomm Peripheral Image Loader
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.
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.
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.
18 #include <linux/clk.h>
19 #include <linux/delay.h>
20 #include <linux/dma-mapping.h>
21 #include <linux/interrupt.h>
22 #include <linux/kernel.h>
23 #include <linux/mfd/syscon.h>
24 #include <linux/module.h>
25 #include <linux/of_address.h>
26 #include <linux/of_device.h>
27 #include <linux/platform_device.h>
28 #include <linux/regmap.h>
29 #include <linux/regulator/consumer.h>
30 #include <linux/remoteproc.h>
31 #include <linux/reset.h>
32 #include <linux/soc/qcom/mdt_loader.h>
33 #include <linux/soc/qcom/smem.h>
34 #include <linux/soc/qcom/smem_state.h>
35 #include <linux/iopoll.h>
37 #include "remoteproc_internal.h"
38 #include "qcom_common.h"
40 #include <linux/qcom_scm.h>
42 #define MPSS_CRASH_REASON_SMEM 421
44 /* RMB Status Register Values */
45 #define RMB_PBL_SUCCESS 0x1
47 #define RMB_MBA_XPU_UNLOCKED 0x1
48 #define RMB_MBA_XPU_UNLOCKED_SCRIBBLED 0x2
49 #define RMB_MBA_META_DATA_AUTH_SUCCESS 0x3
50 #define RMB_MBA_AUTH_COMPLETE 0x4
52 /* PBL/MBA interface registers */
53 #define RMB_MBA_IMAGE_REG 0x00
54 #define RMB_PBL_STATUS_REG 0x04
55 #define RMB_MBA_COMMAND_REG 0x08
56 #define RMB_MBA_STATUS_REG 0x0C
57 #define RMB_PMI_META_DATA_REG 0x10
58 #define RMB_PMI_CODE_START_REG 0x14
59 #define RMB_PMI_CODE_LENGTH_REG 0x18
61 #define RMB_CMD_META_DATA_READY 0x1
62 #define RMB_CMD_LOAD_READY 0x2
64 /* QDSP6SS Register Offsets */
65 #define QDSP6SS_RESET_REG 0x014
66 #define QDSP6SS_GFMUX_CTL_REG 0x020
67 #define QDSP6SS_PWR_CTL_REG 0x030
68 #define QDSP6SS_MEM_PWR_CTL 0x0B0
69 #define QDSP6SS_STRAP_ACC 0x110
71 /* AXI Halt Register Offsets */
72 #define AXI_HALTREQ_REG 0x0
73 #define AXI_HALTACK_REG 0x4
74 #define AXI_IDLE_REG 0x8
76 #define HALT_ACK_TIMEOUT_MS 100
79 #define Q6SS_STOP_CORE BIT(0)
80 #define Q6SS_CORE_ARES BIT(1)
81 #define Q6SS_BUS_ARES_ENABLE BIT(2)
83 /* QDSP6SS_GFMUX_CTL */
84 #define Q6SS_CLK_ENABLE BIT(1)
87 #define Q6SS_L2DATA_SLP_NRET_N_0 BIT(0)
88 #define Q6SS_L2DATA_SLP_NRET_N_1 BIT(1)
89 #define Q6SS_L2DATA_SLP_NRET_N_2 BIT(2)
90 #define Q6SS_L2TAG_SLP_NRET_N BIT(16)
91 #define Q6SS_ETB_SLP_NRET_N BIT(17)
92 #define Q6SS_L2DATA_STBY_N BIT(18)
93 #define Q6SS_SLP_RET_N BIT(19)
94 #define Q6SS_CLAMP_IO BIT(20)
95 #define QDSS_BHS_ON BIT(21)
96 #define QDSS_LDO_BYP BIT(22)
98 /* QDSP6v56 parameters */
99 #define QDSP6v56_LDO_BYP BIT(25)
100 #define QDSP6v56_BHS_ON BIT(24)
101 #define QDSP6v56_CLAMP_WL BIT(21)
102 #define QDSP6v56_CLAMP_QMC_MEM BIT(22)
103 #define HALT_CHECK_MAX_LOOPS 200
104 #define QDSP6SS_XO_CBCR 0x0038
105 #define QDSP6SS_ACC_OVERRIDE_VAL 0x20
108 struct regulator
*reg
;
113 struct qcom_mss_reg_res
{
119 struct rproc_hexagon_res
{
120 const char *hexagon_mba_image
;
121 struct qcom_mss_reg_res
*proxy_supply
;
122 struct qcom_mss_reg_res
*active_supply
;
123 char **proxy_clk_names
;
124 char **active_clk_names
;
126 bool need_mem_protection
;
133 void __iomem
*reg_base
;
134 void __iomem
*rmb_base
;
136 struct regmap
*halt_map
;
141 struct reset_control
*mss_restart
;
143 struct qcom_smem_state
*state
;
146 struct clk
*active_clks
[8];
147 struct clk
*proxy_clks
[4];
148 int active_clk_count
;
151 struct reg_info active_regs
[1];
152 struct reg_info proxy_regs
[3];
153 int active_reg_count
;
156 struct completion start_done
;
157 struct completion stop_done
;
160 phys_addr_t mba_phys
;
164 phys_addr_t mpss_phys
;
165 phys_addr_t mpss_reloc
;
169 struct qcom_rproc_subdev smd_subdev
;
170 struct qcom_rproc_ssr ssr_subdev
;
171 struct qcom_sysmon
*sysmon
;
172 bool need_mem_protection
;
184 static int q6v5_regulator_init(struct device
*dev
, struct reg_info
*regs
,
185 const struct qcom_mss_reg_res
*reg_res
)
193 for (i
= 0; reg_res
[i
].supply
; i
++) {
194 regs
[i
].reg
= devm_regulator_get(dev
, reg_res
[i
].supply
);
195 if (IS_ERR(regs
[i
].reg
)) {
196 rc
= PTR_ERR(regs
[i
].reg
);
197 if (rc
!= -EPROBE_DEFER
)
198 dev_err(dev
, "Failed to get %s\n regulator",
203 regs
[i
].uV
= reg_res
[i
].uV
;
204 regs
[i
].uA
= reg_res
[i
].uA
;
210 static int q6v5_regulator_enable(struct q6v5
*qproc
,
211 struct reg_info
*regs
, int count
)
216 for (i
= 0; i
< count
; i
++) {
217 if (regs
[i
].uV
> 0) {
218 ret
= regulator_set_voltage(regs
[i
].reg
,
219 regs
[i
].uV
, INT_MAX
);
222 "Failed to request voltage for %d.\n",
228 if (regs
[i
].uA
> 0) {
229 ret
= regulator_set_load(regs
[i
].reg
,
233 "Failed to set regulator mode\n");
238 ret
= regulator_enable(regs
[i
].reg
);
240 dev_err(qproc
->dev
, "Regulator enable failed\n");
247 for (; i
>= 0; i
--) {
249 regulator_set_voltage(regs
[i
].reg
, 0, INT_MAX
);
252 regulator_set_load(regs
[i
].reg
, 0);
254 regulator_disable(regs
[i
].reg
);
260 static void q6v5_regulator_disable(struct q6v5
*qproc
,
261 struct reg_info
*regs
, int count
)
265 for (i
= 0; i
< count
; i
++) {
267 regulator_set_voltage(regs
[i
].reg
, 0, INT_MAX
);
270 regulator_set_load(regs
[i
].reg
, 0);
272 regulator_disable(regs
[i
].reg
);
276 static int q6v5_clk_enable(struct device
*dev
,
277 struct clk
**clks
, int count
)
282 for (i
= 0; i
< count
; i
++) {
283 rc
= clk_prepare_enable(clks
[i
]);
285 dev_err(dev
, "Clock enable failed\n");
292 for (i
--; i
>= 0; i
--)
293 clk_disable_unprepare(clks
[i
]);
298 static void q6v5_clk_disable(struct device
*dev
,
299 struct clk
**clks
, int count
)
303 for (i
= 0; i
< count
; i
++)
304 clk_disable_unprepare(clks
[i
]);
307 static int q6v5_xfer_mem_ownership(struct q6v5
*qproc
, int *current_perm
,
308 bool remote_owner
, phys_addr_t addr
,
311 struct qcom_scm_vmperm next
;
313 if (!qproc
->need_mem_protection
)
315 if (remote_owner
&& *current_perm
== BIT(QCOM_SCM_VMID_MSS_MSA
))
317 if (!remote_owner
&& *current_perm
== BIT(QCOM_SCM_VMID_HLOS
))
320 next
.vmid
= remote_owner
? QCOM_SCM_VMID_MSS_MSA
: QCOM_SCM_VMID_HLOS
;
321 next
.perm
= remote_owner
? QCOM_SCM_PERM_RW
: QCOM_SCM_PERM_RWX
;
323 return qcom_scm_assign_mem(addr
, ALIGN(size
, SZ_4K
),
324 current_perm
, &next
, 1);
327 static int q6v5_load(struct rproc
*rproc
, const struct firmware
*fw
)
329 struct q6v5
*qproc
= rproc
->priv
;
331 memcpy(qproc
->mba_region
, fw
->data
, fw
->size
);
336 static int q6v5_rmb_pbl_wait(struct q6v5
*qproc
, int ms
)
338 unsigned long timeout
;
341 timeout
= jiffies
+ msecs_to_jiffies(ms
);
343 val
= readl(qproc
->rmb_base
+ RMB_PBL_STATUS_REG
);
347 if (time_after(jiffies
, timeout
))
356 static int q6v5_rmb_mba_wait(struct q6v5
*qproc
, u32 status
, int ms
)
359 unsigned long timeout
;
362 timeout
= jiffies
+ msecs_to_jiffies(ms
);
364 val
= readl(qproc
->rmb_base
+ RMB_MBA_STATUS_REG
);
370 else if (status
&& val
== status
)
373 if (time_after(jiffies
, timeout
))
382 static int q6v5proc_reset(struct q6v5
*qproc
)
389 if (qproc
->version
== MSS_MSM8996
) {
390 /* Override the ACC value if required */
391 writel(QDSP6SS_ACC_OVERRIDE_VAL
,
392 qproc
->reg_base
+ QDSP6SS_STRAP_ACC
);
394 /* Assert resets, stop core */
395 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
396 val
|= Q6SS_CORE_ARES
| Q6SS_BUS_ARES_ENABLE
| Q6SS_STOP_CORE
;
397 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
399 /* BHS require xo cbcr to be enabled */
400 val
= readl(qproc
->reg_base
+ QDSP6SS_XO_CBCR
);
402 writel(val
, qproc
->reg_base
+ QDSP6SS_XO_CBCR
);
404 /* Read CLKOFF bit to go low indicating CLK is enabled */
405 ret
= readl_poll_timeout(qproc
->reg_base
+ QDSP6SS_XO_CBCR
,
406 val
, !(val
& BIT(31)), 1,
407 HALT_CHECK_MAX_LOOPS
);
410 "xo cbcr enabling timed out (rc:%d)\n", ret
);
413 /* Enable power block headswitch and wait for it to stabilize */
414 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
415 val
|= QDSP6v56_BHS_ON
;
416 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
417 val
|= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
420 /* Put LDO in bypass mode */
421 val
|= QDSP6v56_LDO_BYP
;
422 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
424 /* Deassert QDSP6 compiler memory clamp */
425 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
426 val
&= ~QDSP6v56_CLAMP_QMC_MEM
;
427 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
429 /* Deassert memory peripheral sleep and L2 memory standby */
430 val
|= Q6SS_L2DATA_STBY_N
| Q6SS_SLP_RET_N
;
431 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
433 /* Turn on L1, L2, ETB and JU memories 1 at a time */
434 val
= readl(qproc
->reg_base
+ QDSP6SS_MEM_PWR_CTL
);
435 for (i
= 19; i
>= 0; i
--) {
437 writel(val
, qproc
->reg_base
+
438 QDSP6SS_MEM_PWR_CTL
);
440 * Read back value to ensure the write is done then
441 * wait for 1us for both memory peripheral and data
444 val
|= readl(qproc
->reg_base
+ QDSP6SS_MEM_PWR_CTL
);
447 /* Remove word line clamp */
448 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
449 val
&= ~QDSP6v56_CLAMP_WL
;
450 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
452 /* Assert resets, stop core */
453 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
454 val
|= Q6SS_CORE_ARES
| Q6SS_BUS_ARES_ENABLE
| Q6SS_STOP_CORE
;
455 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
457 /* Enable power block headswitch and wait for it to stabilize */
458 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
459 val
|= QDSS_BHS_ON
| QDSS_LDO_BYP
;
460 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
461 val
|= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
464 * Turn on memories. L2 banks should be done individually
465 * to minimize inrush current.
467 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
468 val
|= Q6SS_SLP_RET_N
| Q6SS_L2TAG_SLP_NRET_N
|
469 Q6SS_ETB_SLP_NRET_N
| Q6SS_L2DATA_STBY_N
;
470 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
471 val
|= Q6SS_L2DATA_SLP_NRET_N_2
;
472 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
473 val
|= Q6SS_L2DATA_SLP_NRET_N_1
;
474 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
475 val
|= Q6SS_L2DATA_SLP_NRET_N_0
;
476 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
478 /* Remove IO clamp */
479 val
&= ~Q6SS_CLAMP_IO
;
480 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
482 /* Bring core out of reset */
483 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
484 val
&= ~Q6SS_CORE_ARES
;
485 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
487 /* Turn on core clock */
488 val
= readl(qproc
->reg_base
+ QDSP6SS_GFMUX_CTL_REG
);
489 val
|= Q6SS_CLK_ENABLE
;
490 writel(val
, qproc
->reg_base
+ QDSP6SS_GFMUX_CTL_REG
);
492 /* Start core execution */
493 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
494 val
&= ~Q6SS_STOP_CORE
;
495 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
497 /* Wait for PBL status */
498 ret
= q6v5_rmb_pbl_wait(qproc
, 1000);
499 if (ret
== -ETIMEDOUT
) {
500 dev_err(qproc
->dev
, "PBL boot timed out\n");
501 } else if (ret
!= RMB_PBL_SUCCESS
) {
502 dev_err(qproc
->dev
, "PBL returned unexpected status %d\n", ret
);
511 static void q6v5proc_halt_axi_port(struct q6v5
*qproc
,
512 struct regmap
*halt_map
,
515 unsigned long timeout
;
519 /* Check if we're already idle */
520 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
524 /* Assert halt request */
525 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 1);
528 timeout
= jiffies
+ msecs_to_jiffies(HALT_ACK_TIMEOUT_MS
);
530 ret
= regmap_read(halt_map
, offset
+ AXI_HALTACK_REG
, &val
);
531 if (ret
|| val
|| time_after(jiffies
, timeout
))
537 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
539 dev_err(qproc
->dev
, "port failed halt\n");
541 /* Clear halt request (port will remain halted until reset) */
542 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 0);
545 static int q6v5_mpss_init_image(struct q6v5
*qproc
, const struct firmware
*fw
)
547 unsigned long dma_attrs
= DMA_ATTR_FORCE_CONTIGUOUS
;
554 ptr
= dma_alloc_attrs(qproc
->dev
, fw
->size
, &phys
, GFP_KERNEL
, dma_attrs
);
556 dev_err(qproc
->dev
, "failed to allocate mdt buffer\n");
560 memcpy(ptr
, fw
->data
, fw
->size
);
562 /* Hypervisor mapping to access metadata by modem */
563 mdata_perm
= BIT(QCOM_SCM_VMID_HLOS
);
564 ret
= q6v5_xfer_mem_ownership(qproc
, &mdata_perm
,
565 true, phys
, fw
->size
);
568 "assigning Q6 access to metadata failed: %d\n", ret
);
573 writel(phys
, qproc
->rmb_base
+ RMB_PMI_META_DATA_REG
);
574 writel(RMB_CMD_META_DATA_READY
, qproc
->rmb_base
+ RMB_MBA_COMMAND_REG
);
576 ret
= q6v5_rmb_mba_wait(qproc
, RMB_MBA_META_DATA_AUTH_SUCCESS
, 1000);
577 if (ret
== -ETIMEDOUT
)
578 dev_err(qproc
->dev
, "MPSS header authentication timed out\n");
580 dev_err(qproc
->dev
, "MPSS header authentication failed: %d\n", ret
);
582 /* Metadata authentication done, remove modem access */
583 xferop_ret
= q6v5_xfer_mem_ownership(qproc
, &mdata_perm
,
584 false, phys
, fw
->size
);
587 "mdt buffer not reclaimed system may become unstable\n");
590 dma_free_attrs(qproc
->dev
, fw
->size
, ptr
, phys
, dma_attrs
);
592 return ret
< 0 ? ret
: 0;
595 static bool q6v5_phdr_valid(const struct elf32_phdr
*phdr
)
597 if (phdr
->p_type
!= PT_LOAD
)
600 if ((phdr
->p_flags
& QCOM_MDT_TYPE_MASK
) == QCOM_MDT_TYPE_HASH
)
609 static int q6v5_mpss_load(struct q6v5
*qproc
)
611 const struct elf32_phdr
*phdrs
;
612 const struct elf32_phdr
*phdr
;
613 const struct firmware
*seg_fw
;
614 const struct firmware
*fw
;
615 struct elf32_hdr
*ehdr
;
616 phys_addr_t mpss_reloc
;
617 phys_addr_t boot_addr
;
618 phys_addr_t min_addr
= (phys_addr_t
)ULLONG_MAX
;
619 phys_addr_t max_addr
= 0;
620 bool relocate
= false;
628 ret
= request_firmware(&fw
, "modem.mdt", qproc
->dev
);
630 dev_err(qproc
->dev
, "unable to load modem.mdt\n");
634 /* Initialize the RMB validator */
635 writel(0, qproc
->rmb_base
+ RMB_PMI_CODE_LENGTH_REG
);
637 ret
= q6v5_mpss_init_image(qproc
, fw
);
639 goto release_firmware
;
641 ehdr
= (struct elf32_hdr
*)fw
->data
;
642 phdrs
= (struct elf32_phdr
*)(ehdr
+ 1);
644 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
647 if (!q6v5_phdr_valid(phdr
))
650 if (phdr
->p_flags
& QCOM_MDT_RELOCATABLE
)
653 if (phdr
->p_paddr
< min_addr
)
654 min_addr
= phdr
->p_paddr
;
656 if (phdr
->p_paddr
+ phdr
->p_memsz
> max_addr
)
657 max_addr
= ALIGN(phdr
->p_paddr
+ phdr
->p_memsz
, SZ_4K
);
660 mpss_reloc
= relocate
? min_addr
: qproc
->mpss_phys
;
661 /* Load firmware segments */
662 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
665 if (!q6v5_phdr_valid(phdr
))
668 offset
= phdr
->p_paddr
- mpss_reloc
;
669 if (offset
< 0 || offset
+ phdr
->p_memsz
> qproc
->mpss_size
) {
670 dev_err(qproc
->dev
, "segment outside memory range\n");
672 goto release_firmware
;
675 ptr
= qproc
->mpss_region
+ offset
;
677 if (phdr
->p_filesz
) {
678 snprintf(seg_name
, sizeof(seg_name
), "modem.b%02d", i
);
679 ret
= request_firmware(&seg_fw
, seg_name
, qproc
->dev
);
681 dev_err(qproc
->dev
, "failed to load %s\n", seg_name
);
682 goto release_firmware
;
685 memcpy(ptr
, seg_fw
->data
, seg_fw
->size
);
687 release_firmware(seg_fw
);
690 if (phdr
->p_memsz
> phdr
->p_filesz
) {
691 memset(ptr
+ phdr
->p_filesz
, 0,
692 phdr
->p_memsz
- phdr
->p_filesz
);
694 size
+= phdr
->p_memsz
;
697 /* Transfer ownership of modem ddr region to q6 */
698 ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mpss_perm
, true,
699 qproc
->mpss_phys
, qproc
->mpss_size
);
702 "assigning Q6 access to mpss memory failed: %d\n", ret
);
704 goto release_firmware
;
707 boot_addr
= relocate
? qproc
->mpss_phys
: min_addr
;
708 writel(boot_addr
, qproc
->rmb_base
+ RMB_PMI_CODE_START_REG
);
709 writel(RMB_CMD_LOAD_READY
, qproc
->rmb_base
+ RMB_MBA_COMMAND_REG
);
710 writel(size
, qproc
->rmb_base
+ RMB_PMI_CODE_LENGTH_REG
);
712 ret
= q6v5_rmb_mba_wait(qproc
, RMB_MBA_AUTH_COMPLETE
, 10000);
713 if (ret
== -ETIMEDOUT
)
714 dev_err(qproc
->dev
, "MPSS authentication timed out\n");
716 dev_err(qproc
->dev
, "MPSS authentication failed: %d\n", ret
);
719 release_firmware(fw
);
721 return ret
< 0 ? ret
: 0;
724 static int q6v5_start(struct rproc
*rproc
)
726 struct q6v5
*qproc
= (struct q6v5
*)rproc
->priv
;
730 ret
= q6v5_regulator_enable(qproc
, qproc
->proxy_regs
,
731 qproc
->proxy_reg_count
);
733 dev_err(qproc
->dev
, "failed to enable proxy supplies\n");
737 ret
= q6v5_clk_enable(qproc
->dev
, qproc
->proxy_clks
,
738 qproc
->proxy_clk_count
);
740 dev_err(qproc
->dev
, "failed to enable proxy clocks\n");
741 goto disable_proxy_reg
;
744 ret
= q6v5_regulator_enable(qproc
, qproc
->active_regs
,
745 qproc
->active_reg_count
);
747 dev_err(qproc
->dev
, "failed to enable supplies\n");
748 goto disable_proxy_clk
;
750 ret
= reset_control_deassert(qproc
->mss_restart
);
752 dev_err(qproc
->dev
, "failed to deassert mss restart\n");
756 ret
= q6v5_clk_enable(qproc
->dev
, qproc
->active_clks
,
757 qproc
->active_clk_count
);
759 dev_err(qproc
->dev
, "failed to enable clocks\n");
763 /* Assign MBA image access in DDR to q6 */
764 xfermemop_ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mba_perm
, true,
769 "assigning Q6 access to mba memory failed: %d\n",
771 goto disable_active_clks
;
774 writel(qproc
->mba_phys
, qproc
->rmb_base
+ RMB_MBA_IMAGE_REG
);
776 ret
= q6v5proc_reset(qproc
);
780 ret
= q6v5_rmb_mba_wait(qproc
, 0, 5000);
781 if (ret
== -ETIMEDOUT
) {
782 dev_err(qproc
->dev
, "MBA boot timed out\n");
784 } else if (ret
!= RMB_MBA_XPU_UNLOCKED
&&
785 ret
!= RMB_MBA_XPU_UNLOCKED_SCRIBBLED
) {
786 dev_err(qproc
->dev
, "MBA returned unexpected status %d\n", ret
);
791 dev_info(qproc
->dev
, "MBA booted, loading mpss\n");
793 ret
= q6v5_mpss_load(qproc
);
797 ret
= wait_for_completion_timeout(&qproc
->start_done
,
798 msecs_to_jiffies(5000));
800 dev_err(qproc
->dev
, "start timed out\n");
805 xfermemop_ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mba_perm
, false,
810 "Failed to reclaim mba buffer system may become unstable\n");
811 qproc
->running
= true;
813 q6v5_clk_disable(qproc
->dev
, qproc
->proxy_clks
,
814 qproc
->proxy_clk_count
);
815 q6v5_regulator_disable(qproc
, qproc
->proxy_regs
,
816 qproc
->proxy_reg_count
);
821 xfermemop_ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mpss_perm
,
822 false, qproc
->mpss_phys
,
824 WARN_ON(xfermemop_ret
);
827 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_q6
);
828 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_modem
);
829 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_nc
);
832 xfermemop_ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mba_perm
, false,
837 "Failed to reclaim mba buffer, system may become unstable\n");
841 q6v5_clk_disable(qproc
->dev
, qproc
->active_clks
,
842 qproc
->active_clk_count
);
845 reset_control_assert(qproc
->mss_restart
);
847 q6v5_regulator_disable(qproc
, qproc
->active_regs
,
848 qproc
->active_reg_count
);
850 q6v5_clk_disable(qproc
->dev
, qproc
->proxy_clks
,
851 qproc
->proxy_clk_count
);
853 q6v5_regulator_disable(qproc
, qproc
->proxy_regs
,
854 qproc
->proxy_reg_count
);
859 static int q6v5_stop(struct rproc
*rproc
)
861 struct q6v5
*qproc
= (struct q6v5
*)rproc
->priv
;
865 qproc
->running
= false;
867 qcom_smem_state_update_bits(qproc
->state
,
868 BIT(qproc
->stop_bit
), BIT(qproc
->stop_bit
));
870 ret
= wait_for_completion_timeout(&qproc
->stop_done
,
871 msecs_to_jiffies(5000));
873 dev_err(qproc
->dev
, "timed out on wait\n");
875 qcom_smem_state_update_bits(qproc
->state
, BIT(qproc
->stop_bit
), 0);
877 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_q6
);
878 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_modem
);
879 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_nc
);
880 if (qproc
->version
== MSS_MSM8996
) {
882 * To avoid high MX current during LPASS/MSS restart.
884 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
885 val
|= Q6SS_CLAMP_IO
| QDSP6v56_CLAMP_WL
|
886 QDSP6v56_CLAMP_QMC_MEM
;
887 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
891 ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mpss_perm
, false,
892 qproc
->mpss_phys
, qproc
->mpss_size
);
895 reset_control_assert(qproc
->mss_restart
);
896 q6v5_clk_disable(qproc
->dev
, qproc
->active_clks
,
897 qproc
->active_clk_count
);
898 q6v5_regulator_disable(qproc
, qproc
->active_regs
,
899 qproc
->active_reg_count
);
904 static void *q6v5_da_to_va(struct rproc
*rproc
, u64 da
, int len
)
906 struct q6v5
*qproc
= rproc
->priv
;
909 offset
= da
- qproc
->mpss_reloc
;
910 if (offset
< 0 || offset
+ len
> qproc
->mpss_size
)
913 return qproc
->mpss_region
+ offset
;
916 static const struct rproc_ops q6v5_ops
= {
919 .da_to_va
= q6v5_da_to_va
,
923 static irqreturn_t
q6v5_wdog_interrupt(int irq
, void *dev
)
925 struct q6v5
*qproc
= dev
;
929 /* Sometimes the stop triggers a watchdog rather than a stop-ack */
930 if (!qproc
->running
) {
931 complete(&qproc
->stop_done
);
935 msg
= qcom_smem_get(QCOM_SMEM_HOST_ANY
, MPSS_CRASH_REASON_SMEM
, &len
);
936 if (!IS_ERR(msg
) && len
> 0 && msg
[0])
937 dev_err(qproc
->dev
, "watchdog received: %s\n", msg
);
939 dev_err(qproc
->dev
, "watchdog without message\n");
941 rproc_report_crash(qproc
->rproc
, RPROC_WATCHDOG
);
946 static irqreturn_t
q6v5_fatal_interrupt(int irq
, void *dev
)
948 struct q6v5
*qproc
= dev
;
952 msg
= qcom_smem_get(QCOM_SMEM_HOST_ANY
, MPSS_CRASH_REASON_SMEM
, &len
);
953 if (!IS_ERR(msg
) && len
> 0 && msg
[0])
954 dev_err(qproc
->dev
, "fatal error received: %s\n", msg
);
956 dev_err(qproc
->dev
, "fatal error without message\n");
958 rproc_report_crash(qproc
->rproc
, RPROC_FATAL_ERROR
);
963 static irqreturn_t
q6v5_handover_interrupt(int irq
, void *dev
)
965 struct q6v5
*qproc
= dev
;
967 complete(&qproc
->start_done
);
971 static irqreturn_t
q6v5_stop_ack_interrupt(int irq
, void *dev
)
973 struct q6v5
*qproc
= dev
;
975 complete(&qproc
->stop_done
);
979 static int q6v5_init_mem(struct q6v5
*qproc
, struct platform_device
*pdev
)
981 struct of_phandle_args args
;
982 struct resource
*res
;
985 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "qdsp6");
986 qproc
->reg_base
= devm_ioremap_resource(&pdev
->dev
, res
);
987 if (IS_ERR(qproc
->reg_base
))
988 return PTR_ERR(qproc
->reg_base
);
990 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "rmb");
991 qproc
->rmb_base
= devm_ioremap_resource(&pdev
->dev
, res
);
992 if (IS_ERR(qproc
->rmb_base
))
993 return PTR_ERR(qproc
->rmb_base
);
995 ret
= of_parse_phandle_with_fixed_args(pdev
->dev
.of_node
,
996 "qcom,halt-regs", 3, 0, &args
);
998 dev_err(&pdev
->dev
, "failed to parse qcom,halt-regs\n");
1002 qproc
->halt_map
= syscon_node_to_regmap(args
.np
);
1003 of_node_put(args
.np
);
1004 if (IS_ERR(qproc
->halt_map
))
1005 return PTR_ERR(qproc
->halt_map
);
1007 qproc
->halt_q6
= args
.args
[0];
1008 qproc
->halt_modem
= args
.args
[1];
1009 qproc
->halt_nc
= args
.args
[2];
1014 static int q6v5_init_clocks(struct device
*dev
, struct clk
**clks
,
1022 for (i
= 0; clk_names
[i
]; i
++) {
1023 clks
[i
] = devm_clk_get(dev
, clk_names
[i
]);
1024 if (IS_ERR(clks
[i
])) {
1025 int rc
= PTR_ERR(clks
[i
]);
1027 if (rc
!= -EPROBE_DEFER
)
1028 dev_err(dev
, "Failed to get %s clock\n",
1037 static int q6v5_init_reset(struct q6v5
*qproc
)
1039 qproc
->mss_restart
= devm_reset_control_get_exclusive(qproc
->dev
,
1041 if (IS_ERR(qproc
->mss_restart
)) {
1042 dev_err(qproc
->dev
, "failed to acquire mss restart\n");
1043 return PTR_ERR(qproc
->mss_restart
);
1049 static int q6v5_request_irq(struct q6v5
*qproc
,
1050 struct platform_device
*pdev
,
1052 irq_handler_t thread_fn
)
1056 ret
= platform_get_irq_byname(pdev
, name
);
1058 dev_err(&pdev
->dev
, "no %s IRQ defined\n", name
);
1062 ret
= devm_request_threaded_irq(&pdev
->dev
, ret
,
1064 IRQF_TRIGGER_RISING
| IRQF_ONESHOT
,
1067 dev_err(&pdev
->dev
, "request %s IRQ failed\n", name
);
1072 static int q6v5_alloc_memory_region(struct q6v5
*qproc
)
1074 struct device_node
*child
;
1075 struct device_node
*node
;
1079 child
= of_get_child_by_name(qproc
->dev
->of_node
, "mba");
1080 node
= of_parse_phandle(child
, "memory-region", 0);
1081 ret
= of_address_to_resource(node
, 0, &r
);
1083 dev_err(qproc
->dev
, "unable to resolve mba region\n");
1088 qproc
->mba_phys
= r
.start
;
1089 qproc
->mba_size
= resource_size(&r
);
1090 qproc
->mba_region
= devm_ioremap_wc(qproc
->dev
, qproc
->mba_phys
, qproc
->mba_size
);
1091 if (!qproc
->mba_region
) {
1092 dev_err(qproc
->dev
, "unable to map memory region: %pa+%zx\n",
1093 &r
.start
, qproc
->mba_size
);
1097 child
= of_get_child_by_name(qproc
->dev
->of_node
, "mpss");
1098 node
= of_parse_phandle(child
, "memory-region", 0);
1099 ret
= of_address_to_resource(node
, 0, &r
);
1101 dev_err(qproc
->dev
, "unable to resolve mpss region\n");
1106 qproc
->mpss_phys
= qproc
->mpss_reloc
= r
.start
;
1107 qproc
->mpss_size
= resource_size(&r
);
1108 qproc
->mpss_region
= devm_ioremap_wc(qproc
->dev
, qproc
->mpss_phys
, qproc
->mpss_size
);
1109 if (!qproc
->mpss_region
) {
1110 dev_err(qproc
->dev
, "unable to map memory region: %pa+%zx\n",
1111 &r
.start
, qproc
->mpss_size
);
1118 static int q6v5_probe(struct platform_device
*pdev
)
1120 const struct rproc_hexagon_res
*desc
;
1122 struct rproc
*rproc
;
1125 desc
= of_device_get_match_data(&pdev
->dev
);
1129 rproc
= rproc_alloc(&pdev
->dev
, pdev
->name
, &q6v5_ops
,
1130 desc
->hexagon_mba_image
, sizeof(*qproc
));
1132 dev_err(&pdev
->dev
, "failed to allocate rproc\n");
1136 qproc
= (struct q6v5
*)rproc
->priv
;
1137 qproc
->dev
= &pdev
->dev
;
1138 qproc
->rproc
= rproc
;
1139 platform_set_drvdata(pdev
, qproc
);
1141 init_completion(&qproc
->start_done
);
1142 init_completion(&qproc
->stop_done
);
1144 ret
= q6v5_init_mem(qproc
, pdev
);
1148 ret
= q6v5_alloc_memory_region(qproc
);
1152 ret
= q6v5_init_clocks(&pdev
->dev
, qproc
->proxy_clks
,
1153 desc
->proxy_clk_names
);
1155 dev_err(&pdev
->dev
, "Failed to get proxy clocks.\n");
1158 qproc
->proxy_clk_count
= ret
;
1160 ret
= q6v5_init_clocks(&pdev
->dev
, qproc
->active_clks
,
1161 desc
->active_clk_names
);
1163 dev_err(&pdev
->dev
, "Failed to get active clocks.\n");
1166 qproc
->active_clk_count
= ret
;
1168 ret
= q6v5_regulator_init(&pdev
->dev
, qproc
->proxy_regs
,
1169 desc
->proxy_supply
);
1171 dev_err(&pdev
->dev
, "Failed to get proxy regulators.\n");
1174 qproc
->proxy_reg_count
= ret
;
1176 ret
= q6v5_regulator_init(&pdev
->dev
, qproc
->active_regs
,
1177 desc
->active_supply
);
1179 dev_err(&pdev
->dev
, "Failed to get active regulators.\n");
1182 qproc
->active_reg_count
= ret
;
1184 ret
= q6v5_init_reset(qproc
);
1188 qproc
->version
= desc
->version
;
1189 qproc
->need_mem_protection
= desc
->need_mem_protection
;
1190 ret
= q6v5_request_irq(qproc
, pdev
, "wdog", q6v5_wdog_interrupt
);
1194 ret
= q6v5_request_irq(qproc
, pdev
, "fatal", q6v5_fatal_interrupt
);
1198 ret
= q6v5_request_irq(qproc
, pdev
, "handover", q6v5_handover_interrupt
);
1202 ret
= q6v5_request_irq(qproc
, pdev
, "stop-ack", q6v5_stop_ack_interrupt
);
1206 qproc
->state
= qcom_smem_state_get(&pdev
->dev
, "stop", &qproc
->stop_bit
);
1207 if (IS_ERR(qproc
->state
)) {
1208 ret
= PTR_ERR(qproc
->state
);
1211 qproc
->mpss_perm
= BIT(QCOM_SCM_VMID_HLOS
);
1212 qproc
->mba_perm
= BIT(QCOM_SCM_VMID_HLOS
);
1213 qcom_add_smd_subdev(rproc
, &qproc
->smd_subdev
);
1214 qcom_add_ssr_subdev(rproc
, &qproc
->ssr_subdev
, "mpss");
1215 qproc
->sysmon
= qcom_add_sysmon_subdev(rproc
, "modem", 0x12);
1217 ret
= rproc_add(rproc
);
1229 static int q6v5_remove(struct platform_device
*pdev
)
1231 struct q6v5
*qproc
= platform_get_drvdata(pdev
);
1233 rproc_del(qproc
->rproc
);
1235 qcom_remove_sysmon_subdev(qproc
->sysmon
);
1236 qcom_remove_smd_subdev(qproc
->rproc
, &qproc
->smd_subdev
);
1237 qcom_remove_ssr_subdev(qproc
->rproc
, &qproc
->ssr_subdev
);
1238 rproc_free(qproc
->rproc
);
1243 static const struct rproc_hexagon_res msm8996_mss
= {
1244 .hexagon_mba_image
= "mba.mbn",
1245 .proxy_clk_names
= (char*[]){
1250 .active_clk_names
= (char*[]){
1257 .need_mem_protection
= true,
1258 .version
= MSS_MSM8996
,
1261 static const struct rproc_hexagon_res msm8916_mss
= {
1262 .hexagon_mba_image
= "mba.mbn",
1263 .proxy_supply
= (struct qcom_mss_reg_res
[]) {
1278 .proxy_clk_names
= (char*[]){
1282 .active_clk_names
= (char*[]){
1288 .need_mem_protection
= false,
1289 .version
= MSS_MSM8916
,
1292 static const struct rproc_hexagon_res msm8974_mss
= {
1293 .hexagon_mba_image
= "mba.b00",
1294 .proxy_supply
= (struct qcom_mss_reg_res
[]) {
1309 .active_supply
= (struct qcom_mss_reg_res
[]) {
1317 .proxy_clk_names
= (char*[]){
1321 .active_clk_names
= (char*[]){
1327 .need_mem_protection
= false,
1328 .version
= MSS_MSM8974
,
1331 static const struct of_device_id q6v5_of_match
[] = {
1332 { .compatible
= "qcom,q6v5-pil", .data
= &msm8916_mss
},
1333 { .compatible
= "qcom,msm8916-mss-pil", .data
= &msm8916_mss
},
1334 { .compatible
= "qcom,msm8974-mss-pil", .data
= &msm8974_mss
},
1335 { .compatible
= "qcom,msm8996-mss-pil", .data
= &msm8996_mss
},
1338 MODULE_DEVICE_TABLE(of
, q6v5_of_match
);
1340 static struct platform_driver q6v5_driver
= {
1341 .probe
= q6v5_probe
,
1342 .remove
= q6v5_remove
,
1344 .name
= "qcom-q6v5-pil",
1345 .of_match_table
= q6v5_of_match
,
1348 module_platform_driver(q6v5_driver
);
1350 MODULE_DESCRIPTION("Peripheral Image Loader for Hexagon");
1351 MODULE_LICENSE("GPL v2");