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/iopoll.h>
35 #include "remoteproc_internal.h"
36 #include "qcom_common.h"
37 #include "qcom_q6v5.h"
39 #include <linux/qcom_scm.h>
41 #define MPSS_CRASH_REASON_SMEM 421
43 /* RMB Status Register Values */
44 #define RMB_PBL_SUCCESS 0x1
46 #define RMB_MBA_XPU_UNLOCKED 0x1
47 #define RMB_MBA_XPU_UNLOCKED_SCRIBBLED 0x2
48 #define RMB_MBA_META_DATA_AUTH_SUCCESS 0x3
49 #define RMB_MBA_AUTH_COMPLETE 0x4
51 /* PBL/MBA interface registers */
52 #define RMB_MBA_IMAGE_REG 0x00
53 #define RMB_PBL_STATUS_REG 0x04
54 #define RMB_MBA_COMMAND_REG 0x08
55 #define RMB_MBA_STATUS_REG 0x0C
56 #define RMB_PMI_META_DATA_REG 0x10
57 #define RMB_PMI_CODE_START_REG 0x14
58 #define RMB_PMI_CODE_LENGTH_REG 0x18
59 #define RMB_MBA_MSS_STATUS 0x40
60 #define RMB_MBA_ALT_RESET 0x44
62 #define RMB_CMD_META_DATA_READY 0x1
63 #define RMB_CMD_LOAD_READY 0x2
65 /* QDSP6SS Register Offsets */
66 #define QDSP6SS_RESET_REG 0x014
67 #define QDSP6SS_GFMUX_CTL_REG 0x020
68 #define QDSP6SS_PWR_CTL_REG 0x030
69 #define QDSP6SS_MEM_PWR_CTL 0x0B0
70 #define QDSP6SS_STRAP_ACC 0x110
72 /* AXI Halt Register Offsets */
73 #define AXI_HALTREQ_REG 0x0
74 #define AXI_HALTACK_REG 0x4
75 #define AXI_IDLE_REG 0x8
77 #define HALT_ACK_TIMEOUT_MS 100
80 #define Q6SS_STOP_CORE BIT(0)
81 #define Q6SS_CORE_ARES BIT(1)
82 #define Q6SS_BUS_ARES_ENABLE BIT(2)
84 /* QDSP6SS_GFMUX_CTL */
85 #define Q6SS_CLK_ENABLE BIT(1)
88 #define Q6SS_L2DATA_SLP_NRET_N_0 BIT(0)
89 #define Q6SS_L2DATA_SLP_NRET_N_1 BIT(1)
90 #define Q6SS_L2DATA_SLP_NRET_N_2 BIT(2)
91 #define Q6SS_L2TAG_SLP_NRET_N BIT(16)
92 #define Q6SS_ETB_SLP_NRET_N BIT(17)
93 #define Q6SS_L2DATA_STBY_N BIT(18)
94 #define Q6SS_SLP_RET_N BIT(19)
95 #define Q6SS_CLAMP_IO BIT(20)
96 #define QDSS_BHS_ON BIT(21)
97 #define QDSS_LDO_BYP BIT(22)
99 /* QDSP6v56 parameters */
100 #define QDSP6v56_LDO_BYP BIT(25)
101 #define QDSP6v56_BHS_ON BIT(24)
102 #define QDSP6v56_CLAMP_WL BIT(21)
103 #define QDSP6v56_CLAMP_QMC_MEM BIT(22)
104 #define HALT_CHECK_MAX_LOOPS 200
105 #define QDSP6SS_XO_CBCR 0x0038
106 #define QDSP6SS_ACC_OVERRIDE_VAL 0x20
108 /* QDSP6v65 parameters */
109 #define QDSP6SS_SLEEP 0x3C
110 #define QDSP6SS_BOOT_CORE_START 0x400
111 #define QDSP6SS_BOOT_CMD 0x404
112 #define SLEEP_CHECK_MAX_LOOPS 200
113 #define BOOT_FSM_TIMEOUT 10000
116 struct regulator
*reg
;
121 struct qcom_mss_reg_res
{
127 struct rproc_hexagon_res
{
128 const char *hexagon_mba_image
;
129 struct qcom_mss_reg_res
*proxy_supply
;
130 struct qcom_mss_reg_res
*active_supply
;
131 char **proxy_clk_names
;
132 char **reset_clk_names
;
133 char **active_clk_names
;
135 bool need_mem_protection
;
143 void __iomem
*reg_base
;
144 void __iomem
*rmb_base
;
146 struct regmap
*halt_map
;
151 struct reset_control
*mss_restart
;
153 struct qcom_q6v5 q6v5
;
155 struct clk
*active_clks
[8];
156 struct clk
*reset_clks
[4];
157 struct clk
*proxy_clks
[4];
158 int active_clk_count
;
162 struct reg_info active_regs
[1];
163 struct reg_info proxy_regs
[3];
164 int active_reg_count
;
169 phys_addr_t mba_phys
;
173 phys_addr_t mpss_phys
;
174 phys_addr_t mpss_reloc
;
178 struct qcom_rproc_glink glink_subdev
;
179 struct qcom_rproc_subdev smd_subdev
;
180 struct qcom_rproc_ssr ssr_subdev
;
181 struct qcom_sysmon
*sysmon
;
182 bool need_mem_protection
;
196 static int q6v5_regulator_init(struct device
*dev
, struct reg_info
*regs
,
197 const struct qcom_mss_reg_res
*reg_res
)
205 for (i
= 0; reg_res
[i
].supply
; i
++) {
206 regs
[i
].reg
= devm_regulator_get(dev
, reg_res
[i
].supply
);
207 if (IS_ERR(regs
[i
].reg
)) {
208 rc
= PTR_ERR(regs
[i
].reg
);
209 if (rc
!= -EPROBE_DEFER
)
210 dev_err(dev
, "Failed to get %s\n regulator",
215 regs
[i
].uV
= reg_res
[i
].uV
;
216 regs
[i
].uA
= reg_res
[i
].uA
;
222 static int q6v5_regulator_enable(struct q6v5
*qproc
,
223 struct reg_info
*regs
, int count
)
228 for (i
= 0; i
< count
; i
++) {
229 if (regs
[i
].uV
> 0) {
230 ret
= regulator_set_voltage(regs
[i
].reg
,
231 regs
[i
].uV
, INT_MAX
);
234 "Failed to request voltage for %d.\n",
240 if (regs
[i
].uA
> 0) {
241 ret
= regulator_set_load(regs
[i
].reg
,
245 "Failed to set regulator mode\n");
250 ret
= regulator_enable(regs
[i
].reg
);
252 dev_err(qproc
->dev
, "Regulator enable failed\n");
259 for (; i
>= 0; i
--) {
261 regulator_set_voltage(regs
[i
].reg
, 0, INT_MAX
);
264 regulator_set_load(regs
[i
].reg
, 0);
266 regulator_disable(regs
[i
].reg
);
272 static void q6v5_regulator_disable(struct q6v5
*qproc
,
273 struct reg_info
*regs
, int count
)
277 for (i
= 0; i
< count
; i
++) {
279 regulator_set_voltage(regs
[i
].reg
, 0, INT_MAX
);
282 regulator_set_load(regs
[i
].reg
, 0);
284 regulator_disable(regs
[i
].reg
);
288 static int q6v5_clk_enable(struct device
*dev
,
289 struct clk
**clks
, int count
)
294 for (i
= 0; i
< count
; i
++) {
295 rc
= clk_prepare_enable(clks
[i
]);
297 dev_err(dev
, "Clock enable failed\n");
304 for (i
--; i
>= 0; i
--)
305 clk_disable_unprepare(clks
[i
]);
310 static void q6v5_clk_disable(struct device
*dev
,
311 struct clk
**clks
, int count
)
315 for (i
= 0; i
< count
; i
++)
316 clk_disable_unprepare(clks
[i
]);
319 static int q6v5_xfer_mem_ownership(struct q6v5
*qproc
, int *current_perm
,
320 bool remote_owner
, phys_addr_t addr
,
323 struct qcom_scm_vmperm next
;
325 if (!qproc
->need_mem_protection
)
327 if (remote_owner
&& *current_perm
== BIT(QCOM_SCM_VMID_MSS_MSA
))
329 if (!remote_owner
&& *current_perm
== BIT(QCOM_SCM_VMID_HLOS
))
332 next
.vmid
= remote_owner
? QCOM_SCM_VMID_MSS_MSA
: QCOM_SCM_VMID_HLOS
;
333 next
.perm
= remote_owner
? QCOM_SCM_PERM_RW
: QCOM_SCM_PERM_RWX
;
335 return qcom_scm_assign_mem(addr
, ALIGN(size
, SZ_4K
),
336 current_perm
, &next
, 1);
339 static int q6v5_load(struct rproc
*rproc
, const struct firmware
*fw
)
341 struct q6v5
*qproc
= rproc
->priv
;
343 memcpy(qproc
->mba_region
, fw
->data
, fw
->size
);
348 static int q6v5_reset_assert(struct q6v5
*qproc
)
350 if (qproc
->has_alt_reset
)
351 return reset_control_reset(qproc
->mss_restart
);
353 return reset_control_assert(qproc
->mss_restart
);
356 static int q6v5_reset_deassert(struct q6v5
*qproc
)
360 if (qproc
->has_alt_reset
) {
361 writel(1, qproc
->rmb_base
+ RMB_MBA_ALT_RESET
);
362 ret
= reset_control_reset(qproc
->mss_restart
);
363 writel(0, qproc
->rmb_base
+ RMB_MBA_ALT_RESET
);
365 ret
= reset_control_deassert(qproc
->mss_restart
);
371 static int q6v5_rmb_pbl_wait(struct q6v5
*qproc
, int ms
)
373 unsigned long timeout
;
376 timeout
= jiffies
+ msecs_to_jiffies(ms
);
378 val
= readl(qproc
->rmb_base
+ RMB_PBL_STATUS_REG
);
382 if (time_after(jiffies
, timeout
))
391 static int q6v5_rmb_mba_wait(struct q6v5
*qproc
, u32 status
, int ms
)
394 unsigned long timeout
;
397 timeout
= jiffies
+ msecs_to_jiffies(ms
);
399 val
= readl(qproc
->rmb_base
+ RMB_MBA_STATUS_REG
);
405 else if (status
&& val
== status
)
408 if (time_after(jiffies
, timeout
))
417 static int q6v5proc_reset(struct q6v5
*qproc
)
423 if (qproc
->version
== MSS_SDM845
) {
424 val
= readl(qproc
->reg_base
+ QDSP6SS_SLEEP
);
426 writel(val
, qproc
->reg_base
+ QDSP6SS_SLEEP
);
428 ret
= readl_poll_timeout(qproc
->reg_base
+ QDSP6SS_SLEEP
,
429 val
, !(val
& BIT(31)), 1,
430 SLEEP_CHECK_MAX_LOOPS
);
432 dev_err(qproc
->dev
, "QDSP6SS Sleep clock timed out\n");
436 /* De-assert QDSP6 stop core */
437 writel(1, qproc
->reg_base
+ QDSP6SS_BOOT_CORE_START
);
438 /* Trigger boot FSM */
439 writel(1, qproc
->reg_base
+ QDSP6SS_BOOT_CMD
);
441 ret
= readl_poll_timeout(qproc
->rmb_base
+ RMB_MBA_MSS_STATUS
,
442 val
, (val
& BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT
);
444 dev_err(qproc
->dev
, "Boot FSM failed to complete.\n");
445 /* Reset the modem so that boot FSM is in reset state */
446 q6v5_reset_deassert(qproc
);
451 } else if (qproc
->version
== MSS_MSM8996
) {
452 /* Override the ACC value if required */
453 writel(QDSP6SS_ACC_OVERRIDE_VAL
,
454 qproc
->reg_base
+ QDSP6SS_STRAP_ACC
);
456 /* Assert resets, stop core */
457 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
458 val
|= Q6SS_CORE_ARES
| Q6SS_BUS_ARES_ENABLE
| Q6SS_STOP_CORE
;
459 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
461 /* BHS require xo cbcr to be enabled */
462 val
= readl(qproc
->reg_base
+ QDSP6SS_XO_CBCR
);
464 writel(val
, qproc
->reg_base
+ QDSP6SS_XO_CBCR
);
466 /* Read CLKOFF bit to go low indicating CLK is enabled */
467 ret
= readl_poll_timeout(qproc
->reg_base
+ QDSP6SS_XO_CBCR
,
468 val
, !(val
& BIT(31)), 1,
469 HALT_CHECK_MAX_LOOPS
);
472 "xo cbcr enabling timed out (rc:%d)\n", ret
);
475 /* Enable power block headswitch and wait for it to stabilize */
476 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
477 val
|= QDSP6v56_BHS_ON
;
478 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
479 val
|= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
482 /* Put LDO in bypass mode */
483 val
|= QDSP6v56_LDO_BYP
;
484 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
486 /* Deassert QDSP6 compiler memory clamp */
487 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
488 val
&= ~QDSP6v56_CLAMP_QMC_MEM
;
489 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
491 /* Deassert memory peripheral sleep and L2 memory standby */
492 val
|= Q6SS_L2DATA_STBY_N
| Q6SS_SLP_RET_N
;
493 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
495 /* Turn on L1, L2, ETB and JU memories 1 at a time */
496 val
= readl(qproc
->reg_base
+ QDSP6SS_MEM_PWR_CTL
);
497 for (i
= 19; i
>= 0; i
--) {
499 writel(val
, qproc
->reg_base
+
500 QDSP6SS_MEM_PWR_CTL
);
502 * Read back value to ensure the write is done then
503 * wait for 1us for both memory peripheral and data
506 val
|= readl(qproc
->reg_base
+ QDSP6SS_MEM_PWR_CTL
);
509 /* Remove word line clamp */
510 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
511 val
&= ~QDSP6v56_CLAMP_WL
;
512 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
514 /* Assert resets, stop core */
515 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
516 val
|= Q6SS_CORE_ARES
| Q6SS_BUS_ARES_ENABLE
| Q6SS_STOP_CORE
;
517 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
519 /* Enable power block headswitch and wait for it to stabilize */
520 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
521 val
|= QDSS_BHS_ON
| QDSS_LDO_BYP
;
522 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
523 val
|= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
526 * Turn on memories. L2 banks should be done individually
527 * to minimize inrush current.
529 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
530 val
|= Q6SS_SLP_RET_N
| Q6SS_L2TAG_SLP_NRET_N
|
531 Q6SS_ETB_SLP_NRET_N
| Q6SS_L2DATA_STBY_N
;
532 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
533 val
|= Q6SS_L2DATA_SLP_NRET_N_2
;
534 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
535 val
|= Q6SS_L2DATA_SLP_NRET_N_1
;
536 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
537 val
|= Q6SS_L2DATA_SLP_NRET_N_0
;
538 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
540 /* Remove IO clamp */
541 val
&= ~Q6SS_CLAMP_IO
;
542 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
544 /* Bring core out of reset */
545 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
546 val
&= ~Q6SS_CORE_ARES
;
547 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
549 /* Turn on core clock */
550 val
= readl(qproc
->reg_base
+ QDSP6SS_GFMUX_CTL_REG
);
551 val
|= Q6SS_CLK_ENABLE
;
552 writel(val
, qproc
->reg_base
+ QDSP6SS_GFMUX_CTL_REG
);
554 /* Start core execution */
555 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
556 val
&= ~Q6SS_STOP_CORE
;
557 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
560 /* Wait for PBL status */
561 ret
= q6v5_rmb_pbl_wait(qproc
, 1000);
562 if (ret
== -ETIMEDOUT
) {
563 dev_err(qproc
->dev
, "PBL boot timed out\n");
564 } else if (ret
!= RMB_PBL_SUCCESS
) {
565 dev_err(qproc
->dev
, "PBL returned unexpected status %d\n", ret
);
574 static void q6v5proc_halt_axi_port(struct q6v5
*qproc
,
575 struct regmap
*halt_map
,
578 unsigned long timeout
;
582 /* Check if we're already idle */
583 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
587 /* Assert halt request */
588 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 1);
591 timeout
= jiffies
+ msecs_to_jiffies(HALT_ACK_TIMEOUT_MS
);
593 ret
= regmap_read(halt_map
, offset
+ AXI_HALTACK_REG
, &val
);
594 if (ret
|| val
|| time_after(jiffies
, timeout
))
600 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
602 dev_err(qproc
->dev
, "port failed halt\n");
604 /* Clear halt request (port will remain halted until reset) */
605 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 0);
608 static int q6v5_mpss_init_image(struct q6v5
*qproc
, const struct firmware
*fw
)
610 unsigned long dma_attrs
= DMA_ATTR_FORCE_CONTIGUOUS
;
617 ptr
= dma_alloc_attrs(qproc
->dev
, fw
->size
, &phys
, GFP_KERNEL
, dma_attrs
);
619 dev_err(qproc
->dev
, "failed to allocate mdt buffer\n");
623 memcpy(ptr
, fw
->data
, fw
->size
);
625 /* Hypervisor mapping to access metadata by modem */
626 mdata_perm
= BIT(QCOM_SCM_VMID_HLOS
);
627 ret
= q6v5_xfer_mem_ownership(qproc
, &mdata_perm
,
628 true, phys
, fw
->size
);
631 "assigning Q6 access to metadata failed: %d\n", ret
);
636 writel(phys
, qproc
->rmb_base
+ RMB_PMI_META_DATA_REG
);
637 writel(RMB_CMD_META_DATA_READY
, qproc
->rmb_base
+ RMB_MBA_COMMAND_REG
);
639 ret
= q6v5_rmb_mba_wait(qproc
, RMB_MBA_META_DATA_AUTH_SUCCESS
, 1000);
640 if (ret
== -ETIMEDOUT
)
641 dev_err(qproc
->dev
, "MPSS header authentication timed out\n");
643 dev_err(qproc
->dev
, "MPSS header authentication failed: %d\n", ret
);
645 /* Metadata authentication done, remove modem access */
646 xferop_ret
= q6v5_xfer_mem_ownership(qproc
, &mdata_perm
,
647 false, phys
, fw
->size
);
650 "mdt buffer not reclaimed system may become unstable\n");
653 dma_free_attrs(qproc
->dev
, fw
->size
, ptr
, phys
, dma_attrs
);
655 return ret
< 0 ? ret
: 0;
658 static bool q6v5_phdr_valid(const struct elf32_phdr
*phdr
)
660 if (phdr
->p_type
!= PT_LOAD
)
663 if ((phdr
->p_flags
& QCOM_MDT_TYPE_MASK
) == QCOM_MDT_TYPE_HASH
)
672 static int q6v5_mpss_load(struct q6v5
*qproc
)
674 const struct elf32_phdr
*phdrs
;
675 const struct elf32_phdr
*phdr
;
676 const struct firmware
*seg_fw
;
677 const struct firmware
*fw
;
678 struct elf32_hdr
*ehdr
;
679 phys_addr_t mpss_reloc
;
680 phys_addr_t boot_addr
;
681 phys_addr_t min_addr
= PHYS_ADDR_MAX
;
682 phys_addr_t max_addr
= 0;
683 bool relocate
= false;
691 ret
= request_firmware(&fw
, "modem.mdt", qproc
->dev
);
693 dev_err(qproc
->dev
, "unable to load modem.mdt\n");
697 /* Initialize the RMB validator */
698 writel(0, qproc
->rmb_base
+ RMB_PMI_CODE_LENGTH_REG
);
700 ret
= q6v5_mpss_init_image(qproc
, fw
);
702 goto release_firmware
;
704 ehdr
= (struct elf32_hdr
*)fw
->data
;
705 phdrs
= (struct elf32_phdr
*)(ehdr
+ 1);
707 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
710 if (!q6v5_phdr_valid(phdr
))
713 if (phdr
->p_flags
& QCOM_MDT_RELOCATABLE
)
716 if (phdr
->p_paddr
< min_addr
)
717 min_addr
= phdr
->p_paddr
;
719 if (phdr
->p_paddr
+ phdr
->p_memsz
> max_addr
)
720 max_addr
= ALIGN(phdr
->p_paddr
+ phdr
->p_memsz
, SZ_4K
);
723 mpss_reloc
= relocate
? min_addr
: qproc
->mpss_phys
;
724 /* Load firmware segments */
725 for (i
= 0; i
< ehdr
->e_phnum
; i
++) {
728 if (!q6v5_phdr_valid(phdr
))
731 offset
= phdr
->p_paddr
- mpss_reloc
;
732 if (offset
< 0 || offset
+ phdr
->p_memsz
> qproc
->mpss_size
) {
733 dev_err(qproc
->dev
, "segment outside memory range\n");
735 goto release_firmware
;
738 ptr
= qproc
->mpss_region
+ offset
;
740 if (phdr
->p_filesz
) {
741 snprintf(seg_name
, sizeof(seg_name
), "modem.b%02d", i
);
742 ret
= request_firmware(&seg_fw
, seg_name
, qproc
->dev
);
744 dev_err(qproc
->dev
, "failed to load %s\n", seg_name
);
745 goto release_firmware
;
748 memcpy(ptr
, seg_fw
->data
, seg_fw
->size
);
750 release_firmware(seg_fw
);
753 if (phdr
->p_memsz
> phdr
->p_filesz
) {
754 memset(ptr
+ phdr
->p_filesz
, 0,
755 phdr
->p_memsz
- phdr
->p_filesz
);
757 size
+= phdr
->p_memsz
;
760 /* Transfer ownership of modem ddr region to q6 */
761 ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mpss_perm
, true,
762 qproc
->mpss_phys
, qproc
->mpss_size
);
765 "assigning Q6 access to mpss memory failed: %d\n", ret
);
767 goto release_firmware
;
770 boot_addr
= relocate
? qproc
->mpss_phys
: min_addr
;
771 writel(boot_addr
, qproc
->rmb_base
+ RMB_PMI_CODE_START_REG
);
772 writel(RMB_CMD_LOAD_READY
, qproc
->rmb_base
+ RMB_MBA_COMMAND_REG
);
773 writel(size
, qproc
->rmb_base
+ RMB_PMI_CODE_LENGTH_REG
);
775 ret
= q6v5_rmb_mba_wait(qproc
, RMB_MBA_AUTH_COMPLETE
, 10000);
776 if (ret
== -ETIMEDOUT
)
777 dev_err(qproc
->dev
, "MPSS authentication timed out\n");
779 dev_err(qproc
->dev
, "MPSS authentication failed: %d\n", ret
);
782 release_firmware(fw
);
784 return ret
< 0 ? ret
: 0;
787 static int q6v5_start(struct rproc
*rproc
)
789 struct q6v5
*qproc
= (struct q6v5
*)rproc
->priv
;
793 qcom_q6v5_prepare(&qproc
->q6v5
);
795 ret
= q6v5_regulator_enable(qproc
, qproc
->proxy_regs
,
796 qproc
->proxy_reg_count
);
798 dev_err(qproc
->dev
, "failed to enable proxy supplies\n");
802 ret
= q6v5_clk_enable(qproc
->dev
, qproc
->proxy_clks
,
803 qproc
->proxy_clk_count
);
805 dev_err(qproc
->dev
, "failed to enable proxy clocks\n");
806 goto disable_proxy_reg
;
809 ret
= q6v5_regulator_enable(qproc
, qproc
->active_regs
,
810 qproc
->active_reg_count
);
812 dev_err(qproc
->dev
, "failed to enable supplies\n");
813 goto disable_proxy_clk
;
816 ret
= q6v5_clk_enable(qproc
->dev
, qproc
->reset_clks
,
817 qproc
->reset_clk_count
);
819 dev_err(qproc
->dev
, "failed to enable reset clocks\n");
823 ret
= q6v5_reset_deassert(qproc
);
825 dev_err(qproc
->dev
, "failed to deassert mss restart\n");
826 goto disable_reset_clks
;
829 ret
= q6v5_clk_enable(qproc
->dev
, qproc
->active_clks
,
830 qproc
->active_clk_count
);
832 dev_err(qproc
->dev
, "failed to enable clocks\n");
836 /* Assign MBA image access in DDR to q6 */
837 ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mba_perm
, true,
838 qproc
->mba_phys
, qproc
->mba_size
);
841 "assigning Q6 access to mba memory failed: %d\n", ret
);
842 goto disable_active_clks
;
845 writel(qproc
->mba_phys
, qproc
->rmb_base
+ RMB_MBA_IMAGE_REG
);
847 ret
= q6v5proc_reset(qproc
);
851 ret
= q6v5_rmb_mba_wait(qproc
, 0, 5000);
852 if (ret
== -ETIMEDOUT
) {
853 dev_err(qproc
->dev
, "MBA boot timed out\n");
855 } else if (ret
!= RMB_MBA_XPU_UNLOCKED
&&
856 ret
!= RMB_MBA_XPU_UNLOCKED_SCRIBBLED
) {
857 dev_err(qproc
->dev
, "MBA returned unexpected status %d\n", ret
);
862 dev_info(qproc
->dev
, "MBA booted, loading mpss\n");
864 ret
= q6v5_mpss_load(qproc
);
868 ret
= qcom_q6v5_wait_for_start(&qproc
->q6v5
, msecs_to_jiffies(5000));
869 if (ret
== -ETIMEDOUT
) {
870 dev_err(qproc
->dev
, "start timed out\n");
874 xfermemop_ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mba_perm
, false,
879 "Failed to reclaim mba buffer system may become unstable\n");
880 qproc
->running
= true;
885 xfermemop_ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mpss_perm
,
886 false, qproc
->mpss_phys
,
888 WARN_ON(xfermemop_ret
);
891 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_q6
);
892 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_modem
);
893 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_nc
);
896 xfermemop_ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mba_perm
, false,
901 "Failed to reclaim mba buffer, system may become unstable\n");
905 q6v5_clk_disable(qproc
->dev
, qproc
->active_clks
,
906 qproc
->active_clk_count
);
909 q6v5_reset_assert(qproc
);
911 q6v5_clk_disable(qproc
->dev
, qproc
->reset_clks
,
912 qproc
->reset_clk_count
);
914 q6v5_regulator_disable(qproc
, qproc
->active_regs
,
915 qproc
->active_reg_count
);
917 q6v5_clk_disable(qproc
->dev
, qproc
->proxy_clks
,
918 qproc
->proxy_clk_count
);
920 q6v5_regulator_disable(qproc
, qproc
->proxy_regs
,
921 qproc
->proxy_reg_count
);
924 qcom_q6v5_unprepare(&qproc
->q6v5
);
929 static int q6v5_stop(struct rproc
*rproc
)
931 struct q6v5
*qproc
= (struct q6v5
*)rproc
->priv
;
935 qproc
->running
= false;
937 ret
= qcom_q6v5_request_stop(&qproc
->q6v5
);
938 if (ret
== -ETIMEDOUT
)
939 dev_err(qproc
->dev
, "timed out on wait\n");
941 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_q6
);
942 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_modem
);
943 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_nc
);
944 if (qproc
->version
== MSS_MSM8996
) {
946 * To avoid high MX current during LPASS/MSS restart.
948 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
949 val
|= Q6SS_CLAMP_IO
| QDSP6v56_CLAMP_WL
|
950 QDSP6v56_CLAMP_QMC_MEM
;
951 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
955 ret
= q6v5_xfer_mem_ownership(qproc
, &qproc
->mpss_perm
, false,
956 qproc
->mpss_phys
, qproc
->mpss_size
);
959 q6v5_reset_assert(qproc
);
961 ret
= qcom_q6v5_unprepare(&qproc
->q6v5
);
963 q6v5_clk_disable(qproc
->dev
, qproc
->proxy_clks
,
964 qproc
->proxy_clk_count
);
965 q6v5_regulator_disable(qproc
, qproc
->proxy_regs
,
966 qproc
->proxy_reg_count
);
969 q6v5_clk_disable(qproc
->dev
, qproc
->reset_clks
,
970 qproc
->reset_clk_count
);
971 q6v5_clk_disable(qproc
->dev
, qproc
->active_clks
,
972 qproc
->active_clk_count
);
973 q6v5_regulator_disable(qproc
, qproc
->active_regs
,
974 qproc
->active_reg_count
);
979 static void *q6v5_da_to_va(struct rproc
*rproc
, u64 da
, int len
)
981 struct q6v5
*qproc
= rproc
->priv
;
984 offset
= da
- qproc
->mpss_reloc
;
985 if (offset
< 0 || offset
+ len
> qproc
->mpss_size
)
988 return qproc
->mpss_region
+ offset
;
991 static const struct rproc_ops q6v5_ops
= {
994 .da_to_va
= q6v5_da_to_va
,
998 static void qcom_msa_handover(struct qcom_q6v5
*q6v5
)
1000 struct q6v5
*qproc
= container_of(q6v5
, struct q6v5
, q6v5
);
1002 q6v5_clk_disable(qproc
->dev
, qproc
->proxy_clks
,
1003 qproc
->proxy_clk_count
);
1004 q6v5_regulator_disable(qproc
, qproc
->proxy_regs
,
1005 qproc
->proxy_reg_count
);
1008 static int q6v5_init_mem(struct q6v5
*qproc
, struct platform_device
*pdev
)
1010 struct of_phandle_args args
;
1011 struct resource
*res
;
1014 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "qdsp6");
1015 qproc
->reg_base
= devm_ioremap_resource(&pdev
->dev
, res
);
1016 if (IS_ERR(qproc
->reg_base
))
1017 return PTR_ERR(qproc
->reg_base
);
1019 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "rmb");
1020 qproc
->rmb_base
= devm_ioremap_resource(&pdev
->dev
, res
);
1021 if (IS_ERR(qproc
->rmb_base
))
1022 return PTR_ERR(qproc
->rmb_base
);
1024 ret
= of_parse_phandle_with_fixed_args(pdev
->dev
.of_node
,
1025 "qcom,halt-regs", 3, 0, &args
);
1027 dev_err(&pdev
->dev
, "failed to parse qcom,halt-regs\n");
1031 qproc
->halt_map
= syscon_node_to_regmap(args
.np
);
1032 of_node_put(args
.np
);
1033 if (IS_ERR(qproc
->halt_map
))
1034 return PTR_ERR(qproc
->halt_map
);
1036 qproc
->halt_q6
= args
.args
[0];
1037 qproc
->halt_modem
= args
.args
[1];
1038 qproc
->halt_nc
= args
.args
[2];
1043 static int q6v5_init_clocks(struct device
*dev
, struct clk
**clks
,
1051 for (i
= 0; clk_names
[i
]; i
++) {
1052 clks
[i
] = devm_clk_get(dev
, clk_names
[i
]);
1053 if (IS_ERR(clks
[i
])) {
1054 int rc
= PTR_ERR(clks
[i
]);
1056 if (rc
!= -EPROBE_DEFER
)
1057 dev_err(dev
, "Failed to get %s clock\n",
1066 static int q6v5_init_reset(struct q6v5
*qproc
)
1068 qproc
->mss_restart
= devm_reset_control_get_exclusive(qproc
->dev
,
1070 if (IS_ERR(qproc
->mss_restart
)) {
1071 dev_err(qproc
->dev
, "failed to acquire mss restart\n");
1072 return PTR_ERR(qproc
->mss_restart
);
1078 static int q6v5_alloc_memory_region(struct q6v5
*qproc
)
1080 struct device_node
*child
;
1081 struct device_node
*node
;
1085 child
= of_get_child_by_name(qproc
->dev
->of_node
, "mba");
1086 node
= of_parse_phandle(child
, "memory-region", 0);
1087 ret
= of_address_to_resource(node
, 0, &r
);
1089 dev_err(qproc
->dev
, "unable to resolve mba region\n");
1094 qproc
->mba_phys
= r
.start
;
1095 qproc
->mba_size
= resource_size(&r
);
1096 qproc
->mba_region
= devm_ioremap_wc(qproc
->dev
, qproc
->mba_phys
, qproc
->mba_size
);
1097 if (!qproc
->mba_region
) {
1098 dev_err(qproc
->dev
, "unable to map memory region: %pa+%zx\n",
1099 &r
.start
, qproc
->mba_size
);
1103 child
= of_get_child_by_name(qproc
->dev
->of_node
, "mpss");
1104 node
= of_parse_phandle(child
, "memory-region", 0);
1105 ret
= of_address_to_resource(node
, 0, &r
);
1107 dev_err(qproc
->dev
, "unable to resolve mpss region\n");
1112 qproc
->mpss_phys
= qproc
->mpss_reloc
= r
.start
;
1113 qproc
->mpss_size
= resource_size(&r
);
1114 qproc
->mpss_region
= devm_ioremap_wc(qproc
->dev
, qproc
->mpss_phys
, qproc
->mpss_size
);
1115 if (!qproc
->mpss_region
) {
1116 dev_err(qproc
->dev
, "unable to map memory region: %pa+%zx\n",
1117 &r
.start
, qproc
->mpss_size
);
1124 static int q6v5_probe(struct platform_device
*pdev
)
1126 const struct rproc_hexagon_res
*desc
;
1128 struct rproc
*rproc
;
1131 desc
= of_device_get_match_data(&pdev
->dev
);
1135 if (desc
->need_mem_protection
&& !qcom_scm_is_available())
1136 return -EPROBE_DEFER
;
1138 rproc
= rproc_alloc(&pdev
->dev
, pdev
->name
, &q6v5_ops
,
1139 desc
->hexagon_mba_image
, sizeof(*qproc
));
1141 dev_err(&pdev
->dev
, "failed to allocate rproc\n");
1145 qproc
= (struct q6v5
*)rproc
->priv
;
1146 qproc
->dev
= &pdev
->dev
;
1147 qproc
->rproc
= rproc
;
1148 platform_set_drvdata(pdev
, qproc
);
1150 ret
= q6v5_init_mem(qproc
, pdev
);
1154 ret
= q6v5_alloc_memory_region(qproc
);
1158 ret
= q6v5_init_clocks(&pdev
->dev
, qproc
->proxy_clks
,
1159 desc
->proxy_clk_names
);
1161 dev_err(&pdev
->dev
, "Failed to get proxy clocks.\n");
1164 qproc
->proxy_clk_count
= ret
;
1166 ret
= q6v5_init_clocks(&pdev
->dev
, qproc
->reset_clks
,
1167 desc
->reset_clk_names
);
1169 dev_err(&pdev
->dev
, "Failed to get reset clocks.\n");
1172 qproc
->reset_clk_count
= ret
;
1174 ret
= q6v5_init_clocks(&pdev
->dev
, qproc
->active_clks
,
1175 desc
->active_clk_names
);
1177 dev_err(&pdev
->dev
, "Failed to get active clocks.\n");
1180 qproc
->active_clk_count
= ret
;
1182 ret
= q6v5_regulator_init(&pdev
->dev
, qproc
->proxy_regs
,
1183 desc
->proxy_supply
);
1185 dev_err(&pdev
->dev
, "Failed to get proxy regulators.\n");
1188 qproc
->proxy_reg_count
= ret
;
1190 ret
= q6v5_regulator_init(&pdev
->dev
, qproc
->active_regs
,
1191 desc
->active_supply
);
1193 dev_err(&pdev
->dev
, "Failed to get active regulators.\n");
1196 qproc
->active_reg_count
= ret
;
1198 ret
= q6v5_init_reset(qproc
);
1202 qproc
->version
= desc
->version
;
1203 qproc
->has_alt_reset
= desc
->has_alt_reset
;
1204 qproc
->need_mem_protection
= desc
->need_mem_protection
;
1206 ret
= qcom_q6v5_init(&qproc
->q6v5
, pdev
, rproc
, MPSS_CRASH_REASON_SMEM
,
1211 qproc
->mpss_perm
= BIT(QCOM_SCM_VMID_HLOS
);
1212 qproc
->mba_perm
= BIT(QCOM_SCM_VMID_HLOS
);
1213 qcom_add_glink_subdev(rproc
, &qproc
->glink_subdev
);
1214 qcom_add_smd_subdev(rproc
, &qproc
->smd_subdev
);
1215 qcom_add_ssr_subdev(rproc
, &qproc
->ssr_subdev
, "mpss");
1216 qproc
->sysmon
= qcom_add_sysmon_subdev(rproc
, "modem", 0x12);
1218 ret
= rproc_add(rproc
);
1230 static int q6v5_remove(struct platform_device
*pdev
)
1232 struct q6v5
*qproc
= platform_get_drvdata(pdev
);
1234 rproc_del(qproc
->rproc
);
1236 qcom_remove_sysmon_subdev(qproc
->sysmon
);
1237 qcom_remove_glink_subdev(qproc
->rproc
, &qproc
->glink_subdev
);
1238 qcom_remove_smd_subdev(qproc
->rproc
, &qproc
->smd_subdev
);
1239 qcom_remove_ssr_subdev(qproc
->rproc
, &qproc
->ssr_subdev
);
1240 rproc_free(qproc
->rproc
);
1245 static const struct rproc_hexagon_res sdm845_mss
= {
1246 .hexagon_mba_image
= "mba.mbn",
1247 .proxy_clk_names
= (char*[]){
1252 .reset_clk_names
= (char*[]){
1257 .active_clk_names
= (char*[]){
1264 .need_mem_protection
= true,
1265 .has_alt_reset
= true,
1266 .version
= MSS_SDM845
,
1269 static const struct rproc_hexagon_res msm8996_mss
= {
1270 .hexagon_mba_image
= "mba.mbn",
1271 .proxy_supply
= (struct qcom_mss_reg_res
[]) {
1278 .proxy_clk_names
= (char*[]){
1284 .active_clk_names
= (char*[]){
1293 .need_mem_protection
= true,
1294 .has_alt_reset
= false,
1295 .version
= MSS_MSM8996
,
1298 static const struct rproc_hexagon_res msm8916_mss
= {
1299 .hexagon_mba_image
= "mba.mbn",
1300 .proxy_supply
= (struct qcom_mss_reg_res
[]) {
1315 .proxy_clk_names
= (char*[]){
1319 .active_clk_names
= (char*[]){
1325 .need_mem_protection
= false,
1326 .has_alt_reset
= false,
1327 .version
= MSS_MSM8916
,
1330 static const struct rproc_hexagon_res msm8974_mss
= {
1331 .hexagon_mba_image
= "mba.b00",
1332 .proxy_supply
= (struct qcom_mss_reg_res
[]) {
1347 .active_supply
= (struct qcom_mss_reg_res
[]) {
1355 .proxy_clk_names
= (char*[]){
1359 .active_clk_names
= (char*[]){
1365 .need_mem_protection
= false,
1366 .has_alt_reset
= false,
1367 .version
= MSS_MSM8974
,
1370 static const struct of_device_id q6v5_of_match
[] = {
1371 { .compatible
= "qcom,q6v5-pil", .data
= &msm8916_mss
},
1372 { .compatible
= "qcom,msm8916-mss-pil", .data
= &msm8916_mss
},
1373 { .compatible
= "qcom,msm8974-mss-pil", .data
= &msm8974_mss
},
1374 { .compatible
= "qcom,msm8996-mss-pil", .data
= &msm8996_mss
},
1375 { .compatible
= "qcom,sdm845-mss-pil", .data
= &sdm845_mss
},
1378 MODULE_DEVICE_TABLE(of
, q6v5_of_match
);
1380 static struct platform_driver q6v5_driver
= {
1381 .probe
= q6v5_probe
,
1382 .remove
= q6v5_remove
,
1384 .name
= "qcom-q6v5-pil",
1385 .of_match_table
= q6v5_of_match
,
1388 module_platform_driver(q6v5_driver
);
1390 MODULE_DESCRIPTION("Peripheral Image Loader for Hexagon");
1391 MODULE_LICENSE("GPL v2");