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/smem.h>
33 #include <linux/soc/qcom/smem_state.h>
35 #include "remoteproc_internal.h"
36 #include "qcom_mdt_loader.h"
38 #include <linux/qcom_scm.h>
40 #define MPSS_FIRMWARE_NAME "modem.mdt"
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
69 /* AXI Halt Register Offsets */
70 #define AXI_HALTREQ_REG 0x0
71 #define AXI_HALTACK_REG 0x4
72 #define AXI_IDLE_REG 0x8
74 #define HALT_ACK_TIMEOUT_MS 100
77 #define Q6SS_STOP_CORE BIT(0)
78 #define Q6SS_CORE_ARES BIT(1)
79 #define Q6SS_BUS_ARES_ENABLE BIT(2)
81 /* QDSP6SS_GFMUX_CTL */
82 #define Q6SS_CLK_ENABLE BIT(1)
85 #define Q6SS_L2DATA_SLP_NRET_N_0 BIT(0)
86 #define Q6SS_L2DATA_SLP_NRET_N_1 BIT(1)
87 #define Q6SS_L2DATA_SLP_NRET_N_2 BIT(2)
88 #define Q6SS_L2TAG_SLP_NRET_N BIT(16)
89 #define Q6SS_ETB_SLP_NRET_N BIT(17)
90 #define Q6SS_L2DATA_STBY_N BIT(18)
91 #define Q6SS_SLP_RET_N BIT(19)
92 #define Q6SS_CLAMP_IO BIT(20)
93 #define QDSS_BHS_ON BIT(21)
94 #define QDSS_LDO_BYP BIT(22)
97 struct regulator
*reg
;
102 struct qcom_mss_reg_res
{
108 struct rproc_hexagon_res
{
109 const char *hexagon_mba_image
;
110 struct qcom_mss_reg_res proxy_supply
[4];
111 struct qcom_mss_reg_res active_supply
[2];
112 char **proxy_clk_names
;
113 char **active_clk_names
;
120 void __iomem
*reg_base
;
121 void __iomem
*rmb_base
;
123 struct regmap
*halt_map
;
128 struct reset_control
*mss_restart
;
130 struct qcom_smem_state
*state
;
133 struct clk
*active_clks
[8];
134 struct clk
*proxy_clks
[4];
135 int active_clk_count
;
138 struct reg_info active_regs
[1];
139 struct reg_info proxy_regs
[3];
140 int active_reg_count
;
143 struct completion start_done
;
144 struct completion stop_done
;
147 phys_addr_t mba_phys
;
151 phys_addr_t mpss_phys
;
152 phys_addr_t mpss_reloc
;
157 static int q6v5_regulator_init(struct device
*dev
, struct reg_info
*regs
,
158 const struct qcom_mss_reg_res
*reg_res
)
163 for (i
= 0; reg_res
[i
].supply
; i
++) {
164 regs
[i
].reg
= devm_regulator_get(dev
, reg_res
[i
].supply
);
165 if (IS_ERR(regs
[i
].reg
)) {
166 rc
= PTR_ERR(regs
[i
].reg
);
167 if (rc
!= -EPROBE_DEFER
)
168 dev_err(dev
, "Failed to get %s\n regulator",
173 regs
[i
].uV
= reg_res
[i
].uV
;
174 regs
[i
].uA
= reg_res
[i
].uA
;
180 static int q6v5_regulator_enable(struct q6v5
*qproc
,
181 struct reg_info
*regs
, int count
)
186 for (i
= 0; i
< count
; i
++) {
187 if (regs
[i
].uV
> 0) {
188 ret
= regulator_set_voltage(regs
[i
].reg
,
189 regs
[i
].uV
, INT_MAX
);
192 "Failed to request voltage for %d.\n",
198 if (regs
[i
].uA
> 0) {
199 ret
= regulator_set_load(regs
[i
].reg
,
203 "Failed to set regulator mode\n");
208 ret
= regulator_enable(regs
[i
].reg
);
210 dev_err(qproc
->dev
, "Regulator enable failed\n");
217 for (; i
>= 0; i
--) {
219 regulator_set_voltage(regs
[i
].reg
, 0, INT_MAX
);
222 regulator_set_load(regs
[i
].reg
, 0);
224 regulator_disable(regs
[i
].reg
);
230 static void q6v5_regulator_disable(struct q6v5
*qproc
,
231 struct reg_info
*regs
, int count
)
235 for (i
= 0; i
< count
; i
++) {
237 regulator_set_voltage(regs
[i
].reg
, 0, INT_MAX
);
240 regulator_set_load(regs
[i
].reg
, 0);
242 regulator_disable(regs
[i
].reg
);
246 static int q6v5_clk_enable(struct device
*dev
,
247 struct clk
**clks
, int count
)
252 for (i
= 0; i
< count
; i
++) {
253 rc
= clk_prepare_enable(clks
[i
]);
255 dev_err(dev
, "Clock enable failed\n");
262 for (i
--; i
>= 0; i
--)
263 clk_disable_unprepare(clks
[i
]);
268 static void q6v5_clk_disable(struct device
*dev
,
269 struct clk
**clks
, int count
)
273 for (i
= 0; i
< count
; i
++)
274 clk_disable_unprepare(clks
[i
]);
277 static int q6v5_load(struct rproc
*rproc
, const struct firmware
*fw
)
279 struct q6v5
*qproc
= rproc
->priv
;
281 memcpy(qproc
->mba_region
, fw
->data
, fw
->size
);
286 static const struct rproc_fw_ops q6v5_fw_ops
= {
287 .find_rsc_table
= qcom_mdt_find_rsc_table
,
291 static int q6v5_rmb_pbl_wait(struct q6v5
*qproc
, int ms
)
293 unsigned long timeout
;
296 timeout
= jiffies
+ msecs_to_jiffies(ms
);
298 val
= readl(qproc
->rmb_base
+ RMB_PBL_STATUS_REG
);
302 if (time_after(jiffies
, timeout
))
311 static int q6v5_rmb_mba_wait(struct q6v5
*qproc
, u32 status
, int ms
)
314 unsigned long timeout
;
317 timeout
= jiffies
+ msecs_to_jiffies(ms
);
319 val
= readl(qproc
->rmb_base
+ RMB_MBA_STATUS_REG
);
325 else if (status
&& val
== status
)
328 if (time_after(jiffies
, timeout
))
337 static int q6v5proc_reset(struct q6v5
*qproc
)
342 /* Assert resets, stop core */
343 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
344 val
|= (Q6SS_CORE_ARES
| Q6SS_BUS_ARES_ENABLE
| Q6SS_STOP_CORE
);
345 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
347 /* Enable power block headswitch, and wait for it to stabilize */
348 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
349 val
|= QDSS_BHS_ON
| QDSS_LDO_BYP
;
350 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
354 * Turn on memories. L2 banks should be done individually
355 * to minimize inrush current.
357 val
= readl(qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
358 val
|= Q6SS_SLP_RET_N
| Q6SS_L2TAG_SLP_NRET_N
|
359 Q6SS_ETB_SLP_NRET_N
| Q6SS_L2DATA_STBY_N
;
360 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
361 val
|= Q6SS_L2DATA_SLP_NRET_N_2
;
362 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
363 val
|= Q6SS_L2DATA_SLP_NRET_N_1
;
364 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
365 val
|= Q6SS_L2DATA_SLP_NRET_N_0
;
366 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
368 /* Remove IO clamp */
369 val
&= ~Q6SS_CLAMP_IO
;
370 writel(val
, qproc
->reg_base
+ QDSP6SS_PWR_CTL_REG
);
372 /* Bring core out of reset */
373 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
374 val
&= ~Q6SS_CORE_ARES
;
375 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
377 /* Turn on core clock */
378 val
= readl(qproc
->reg_base
+ QDSP6SS_GFMUX_CTL_REG
);
379 val
|= Q6SS_CLK_ENABLE
;
380 writel(val
, qproc
->reg_base
+ QDSP6SS_GFMUX_CTL_REG
);
382 /* Start core execution */
383 val
= readl(qproc
->reg_base
+ QDSP6SS_RESET_REG
);
384 val
&= ~Q6SS_STOP_CORE
;
385 writel(val
, qproc
->reg_base
+ QDSP6SS_RESET_REG
);
387 /* Wait for PBL status */
388 ret
= q6v5_rmb_pbl_wait(qproc
, 1000);
389 if (ret
== -ETIMEDOUT
) {
390 dev_err(qproc
->dev
, "PBL boot timed out\n");
391 } else if (ret
!= RMB_PBL_SUCCESS
) {
392 dev_err(qproc
->dev
, "PBL returned unexpected status %d\n", ret
);
401 static void q6v5proc_halt_axi_port(struct q6v5
*qproc
,
402 struct regmap
*halt_map
,
405 unsigned long timeout
;
409 /* Check if we're already idle */
410 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
414 /* Assert halt request */
415 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 1);
418 timeout
= jiffies
+ msecs_to_jiffies(HALT_ACK_TIMEOUT_MS
);
420 ret
= regmap_read(halt_map
, offset
+ AXI_HALTACK_REG
, &val
);
421 if (ret
|| val
|| time_after(jiffies
, timeout
))
427 ret
= regmap_read(halt_map
, offset
+ AXI_IDLE_REG
, &val
);
429 dev_err(qproc
->dev
, "port failed halt\n");
431 /* Clear halt request (port will remain halted until reset) */
432 regmap_write(halt_map
, offset
+ AXI_HALTREQ_REG
, 0);
435 static int q6v5_mpss_init_image(struct q6v5
*qproc
, const struct firmware
*fw
)
437 unsigned long dma_attrs
= DMA_ATTR_FORCE_CONTIGUOUS
;
442 ptr
= dma_alloc_attrs(qproc
->dev
, fw
->size
, &phys
, GFP_KERNEL
, dma_attrs
);
444 dev_err(qproc
->dev
, "failed to allocate mdt buffer\n");
448 memcpy(ptr
, fw
->data
, fw
->size
);
450 writel(phys
, qproc
->rmb_base
+ RMB_PMI_META_DATA_REG
);
451 writel(RMB_CMD_META_DATA_READY
, qproc
->rmb_base
+ RMB_MBA_COMMAND_REG
);
453 ret
= q6v5_rmb_mba_wait(qproc
, RMB_MBA_META_DATA_AUTH_SUCCESS
, 1000);
454 if (ret
== -ETIMEDOUT
)
455 dev_err(qproc
->dev
, "MPSS header authentication timed out\n");
457 dev_err(qproc
->dev
, "MPSS header authentication failed: %d\n", ret
);
459 dma_free_attrs(qproc
->dev
, fw
->size
, ptr
, phys
, dma_attrs
);
461 return ret
< 0 ? ret
: 0;
464 static int q6v5_mpss_validate(struct q6v5
*qproc
, const struct firmware
*fw
)
466 const struct elf32_phdr
*phdrs
;
467 const struct elf32_phdr
*phdr
;
468 struct elf32_hdr
*ehdr
;
469 phys_addr_t boot_addr
;
476 ret
= qcom_mdt_parse(fw
, &fw_addr
, NULL
, &relocate
);
478 dev_err(qproc
->dev
, "failed to parse mdt header\n");
483 boot_addr
= qproc
->mpss_phys
;
487 ehdr
= (struct elf32_hdr
*)fw
->data
;
488 phdrs
= (struct elf32_phdr
*)(ehdr
+ 1);
489 for (i
= 0; i
< ehdr
->e_phnum
; i
++, phdr
++) {
492 if (phdr
->p_type
!= PT_LOAD
)
495 if ((phdr
->p_flags
& QCOM_MDT_TYPE_MASK
) == QCOM_MDT_TYPE_HASH
)
501 size
= readl(qproc
->rmb_base
+ RMB_PMI_CODE_LENGTH_REG
);
503 writel(boot_addr
, qproc
->rmb_base
+ RMB_PMI_CODE_START_REG
);
504 writel(RMB_CMD_LOAD_READY
, qproc
->rmb_base
+ RMB_MBA_COMMAND_REG
);
507 size
+= phdr
->p_memsz
;
508 writel(size
, qproc
->rmb_base
+ RMB_PMI_CODE_LENGTH_REG
);
511 ret
= q6v5_rmb_mba_wait(qproc
, RMB_MBA_AUTH_COMPLETE
, 10000);
512 if (ret
== -ETIMEDOUT
)
513 dev_err(qproc
->dev
, "MPSS authentication timed out\n");
515 dev_err(qproc
->dev
, "MPSS authentication failed: %d\n", ret
);
517 return ret
< 0 ? ret
: 0;
520 static int q6v5_mpss_load(struct q6v5
*qproc
)
522 const struct firmware
*fw
;
527 ret
= request_firmware(&fw
, MPSS_FIRMWARE_NAME
, qproc
->dev
);
529 dev_err(qproc
->dev
, "unable to load " MPSS_FIRMWARE_NAME
"\n");
533 ret
= qcom_mdt_parse(fw
, &fw_addr
, NULL
, &relocate
);
535 dev_err(qproc
->dev
, "failed to parse mdt header\n");
536 goto release_firmware
;
540 qproc
->mpss_reloc
= fw_addr
;
542 /* Initialize the RMB validator */
543 writel(0, qproc
->rmb_base
+ RMB_PMI_CODE_LENGTH_REG
);
545 ret
= q6v5_mpss_init_image(qproc
, fw
);
547 goto release_firmware
;
549 ret
= qcom_mdt_load(qproc
->rproc
, fw
, MPSS_FIRMWARE_NAME
);
551 goto release_firmware
;
553 ret
= q6v5_mpss_validate(qproc
, fw
);
556 release_firmware(fw
);
558 return ret
< 0 ? ret
: 0;
561 static int q6v5_start(struct rproc
*rproc
)
563 struct q6v5
*qproc
= (struct q6v5
*)rproc
->priv
;
566 ret
= q6v5_regulator_enable(qproc
, qproc
->proxy_regs
,
567 qproc
->proxy_reg_count
);
569 dev_err(qproc
->dev
, "failed to enable proxy supplies\n");
573 ret
= q6v5_clk_enable(qproc
->dev
, qproc
->proxy_clks
,
574 qproc
->proxy_clk_count
);
576 dev_err(qproc
->dev
, "failed to enable proxy clocks\n");
577 goto disable_proxy_reg
;
580 ret
= q6v5_regulator_enable(qproc
, qproc
->active_regs
,
581 qproc
->active_reg_count
);
583 dev_err(qproc
->dev
, "failed to enable supplies\n");
584 goto disable_proxy_clk
;
586 ret
= reset_control_deassert(qproc
->mss_restart
);
588 dev_err(qproc
->dev
, "failed to deassert mss restart\n");
592 ret
= q6v5_clk_enable(qproc
->dev
, qproc
->active_clks
,
593 qproc
->active_clk_count
);
595 dev_err(qproc
->dev
, "failed to enable clocks\n");
599 writel(qproc
->mba_phys
, qproc
->rmb_base
+ RMB_MBA_IMAGE_REG
);
601 ret
= q6v5proc_reset(qproc
);
605 ret
= q6v5_rmb_mba_wait(qproc
, 0, 5000);
606 if (ret
== -ETIMEDOUT
) {
607 dev_err(qproc
->dev
, "MBA boot timed out\n");
609 } else if (ret
!= RMB_MBA_XPU_UNLOCKED
&&
610 ret
!= RMB_MBA_XPU_UNLOCKED_SCRIBBLED
) {
611 dev_err(qproc
->dev
, "MBA returned unexpected status %d\n", ret
);
616 dev_info(qproc
->dev
, "MBA booted, loading mpss\n");
618 ret
= q6v5_mpss_load(qproc
);
622 ret
= wait_for_completion_timeout(&qproc
->start_done
,
623 msecs_to_jiffies(5000));
625 dev_err(qproc
->dev
, "start timed out\n");
630 qproc
->running
= true;
632 q6v5_clk_disable(qproc
->dev
, qproc
->proxy_clks
,
633 qproc
->proxy_clk_count
);
634 q6v5_regulator_disable(qproc
, qproc
->proxy_regs
,
635 qproc
->proxy_reg_count
);
640 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_q6
);
641 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_modem
);
642 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_nc
);
643 q6v5_clk_disable(qproc
->dev
, qproc
->active_clks
,
644 qproc
->active_clk_count
);
646 reset_control_assert(qproc
->mss_restart
);
648 q6v5_regulator_disable(qproc
, qproc
->active_regs
,
649 qproc
->active_reg_count
);
651 q6v5_clk_disable(qproc
->dev
, qproc
->proxy_clks
,
652 qproc
->proxy_clk_count
);
654 q6v5_regulator_disable(qproc
, qproc
->proxy_regs
,
655 qproc
->proxy_reg_count
);
660 static int q6v5_stop(struct rproc
*rproc
)
662 struct q6v5
*qproc
= (struct q6v5
*)rproc
->priv
;
665 qproc
->running
= false;
667 qcom_smem_state_update_bits(qproc
->state
,
668 BIT(qproc
->stop_bit
), BIT(qproc
->stop_bit
));
670 ret
= wait_for_completion_timeout(&qproc
->stop_done
,
671 msecs_to_jiffies(5000));
673 dev_err(qproc
->dev
, "timed out on wait\n");
675 qcom_smem_state_update_bits(qproc
->state
, BIT(qproc
->stop_bit
), 0);
677 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_q6
);
678 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_modem
);
679 q6v5proc_halt_axi_port(qproc
, qproc
->halt_map
, qproc
->halt_nc
);
681 reset_control_assert(qproc
->mss_restart
);
682 q6v5_clk_disable(qproc
->dev
, qproc
->active_clks
,
683 qproc
->active_clk_count
);
684 q6v5_regulator_disable(qproc
, qproc
->active_regs
,
685 qproc
->active_reg_count
);
690 static void *q6v5_da_to_va(struct rproc
*rproc
, u64 da
, int len
)
692 struct q6v5
*qproc
= rproc
->priv
;
695 offset
= da
- qproc
->mpss_reloc
;
696 if (offset
< 0 || offset
+ len
> qproc
->mpss_size
)
699 return qproc
->mpss_region
+ offset
;
702 static const struct rproc_ops q6v5_ops
= {
705 .da_to_va
= q6v5_da_to_va
,
708 static irqreturn_t
q6v5_wdog_interrupt(int irq
, void *dev
)
710 struct q6v5
*qproc
= dev
;
714 /* Sometimes the stop triggers a watchdog rather than a stop-ack */
715 if (!qproc
->running
) {
716 complete(&qproc
->stop_done
);
720 msg
= qcom_smem_get(QCOM_SMEM_HOST_ANY
, MPSS_CRASH_REASON_SMEM
, &len
);
721 if (!IS_ERR(msg
) && len
> 0 && msg
[0])
722 dev_err(qproc
->dev
, "watchdog received: %s\n", msg
);
724 dev_err(qproc
->dev
, "watchdog without message\n");
726 rproc_report_crash(qproc
->rproc
, RPROC_WATCHDOG
);
734 static irqreturn_t
q6v5_fatal_interrupt(int irq
, void *dev
)
736 struct q6v5
*qproc
= dev
;
740 msg
= qcom_smem_get(QCOM_SMEM_HOST_ANY
, MPSS_CRASH_REASON_SMEM
, &len
);
741 if (!IS_ERR(msg
) && len
> 0 && msg
[0])
742 dev_err(qproc
->dev
, "fatal error received: %s\n", msg
);
744 dev_err(qproc
->dev
, "fatal error without message\n");
746 rproc_report_crash(qproc
->rproc
, RPROC_FATAL_ERROR
);
754 static irqreturn_t
q6v5_handover_interrupt(int irq
, void *dev
)
756 struct q6v5
*qproc
= dev
;
758 complete(&qproc
->start_done
);
762 static irqreturn_t
q6v5_stop_ack_interrupt(int irq
, void *dev
)
764 struct q6v5
*qproc
= dev
;
766 complete(&qproc
->stop_done
);
770 static int q6v5_init_mem(struct q6v5
*qproc
, struct platform_device
*pdev
)
772 struct of_phandle_args args
;
773 struct resource
*res
;
776 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "qdsp6");
777 qproc
->reg_base
= devm_ioremap_resource(&pdev
->dev
, res
);
778 if (IS_ERR(qproc
->reg_base
))
779 return PTR_ERR(qproc
->reg_base
);
781 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "rmb");
782 qproc
->rmb_base
= devm_ioremap_resource(&pdev
->dev
, res
);
783 if (IS_ERR(qproc
->rmb_base
))
784 return PTR_ERR(qproc
->rmb_base
);
786 ret
= of_parse_phandle_with_fixed_args(pdev
->dev
.of_node
,
787 "qcom,halt-regs", 3, 0, &args
);
789 dev_err(&pdev
->dev
, "failed to parse qcom,halt-regs\n");
793 qproc
->halt_map
= syscon_node_to_regmap(args
.np
);
794 of_node_put(args
.np
);
795 if (IS_ERR(qproc
->halt_map
))
796 return PTR_ERR(qproc
->halt_map
);
798 qproc
->halt_q6
= args
.args
[0];
799 qproc
->halt_modem
= args
.args
[1];
800 qproc
->halt_nc
= args
.args
[2];
805 static int q6v5_init_clocks(struct device
*dev
, struct clk
**clks
,
813 for (i
= 0; clk_names
[i
]; i
++) {
814 clks
[i
] = devm_clk_get(dev
, clk_names
[i
]);
815 if (IS_ERR(clks
[i
])) {
816 int rc
= PTR_ERR(clks
[i
]);
818 if (rc
!= -EPROBE_DEFER
)
819 dev_err(dev
, "Failed to get %s clock\n",
828 static int q6v5_init_reset(struct q6v5
*qproc
)
830 qproc
->mss_restart
= devm_reset_control_get(qproc
->dev
, NULL
);
831 if (IS_ERR(qproc
->mss_restart
)) {
832 dev_err(qproc
->dev
, "failed to acquire mss restart\n");
833 return PTR_ERR(qproc
->mss_restart
);
839 static int q6v5_request_irq(struct q6v5
*qproc
,
840 struct platform_device
*pdev
,
842 irq_handler_t thread_fn
)
846 ret
= platform_get_irq_byname(pdev
, name
);
848 dev_err(&pdev
->dev
, "no %s IRQ defined\n", name
);
852 ret
= devm_request_threaded_irq(&pdev
->dev
, ret
,
854 IRQF_TRIGGER_RISING
| IRQF_ONESHOT
,
857 dev_err(&pdev
->dev
, "request %s IRQ failed\n", name
);
862 static int q6v5_alloc_memory_region(struct q6v5
*qproc
)
864 struct device_node
*child
;
865 struct device_node
*node
;
869 child
= of_get_child_by_name(qproc
->dev
->of_node
, "mba");
870 node
= of_parse_phandle(child
, "memory-region", 0);
871 ret
= of_address_to_resource(node
, 0, &r
);
873 dev_err(qproc
->dev
, "unable to resolve mba region\n");
877 qproc
->mba_phys
= r
.start
;
878 qproc
->mba_size
= resource_size(&r
);
879 qproc
->mba_region
= devm_ioremap_wc(qproc
->dev
, qproc
->mba_phys
, qproc
->mba_size
);
880 if (!qproc
->mba_region
) {
881 dev_err(qproc
->dev
, "unable to map memory region: %pa+%zx\n",
882 &r
.start
, qproc
->mba_size
);
886 child
= of_get_child_by_name(qproc
->dev
->of_node
, "mpss");
887 node
= of_parse_phandle(child
, "memory-region", 0);
888 ret
= of_address_to_resource(node
, 0, &r
);
890 dev_err(qproc
->dev
, "unable to resolve mpss region\n");
894 qproc
->mpss_phys
= qproc
->mpss_reloc
= r
.start
;
895 qproc
->mpss_size
= resource_size(&r
);
896 qproc
->mpss_region
= devm_ioremap_wc(qproc
->dev
, qproc
->mpss_phys
, qproc
->mpss_size
);
897 if (!qproc
->mpss_region
) {
898 dev_err(qproc
->dev
, "unable to map memory region: %pa+%zx\n",
899 &r
.start
, qproc
->mpss_size
);
906 static int q6v5_probe(struct platform_device
*pdev
)
908 const struct rproc_hexagon_res
*desc
;
913 desc
= of_device_get_match_data(&pdev
->dev
);
917 rproc
= rproc_alloc(&pdev
->dev
, pdev
->name
, &q6v5_ops
,
918 desc
->hexagon_mba_image
, sizeof(*qproc
));
920 dev_err(&pdev
->dev
, "failed to allocate rproc\n");
924 rproc
->fw_ops
= &q6v5_fw_ops
;
926 qproc
= (struct q6v5
*)rproc
->priv
;
927 qproc
->dev
= &pdev
->dev
;
928 qproc
->rproc
= rproc
;
929 platform_set_drvdata(pdev
, qproc
);
931 init_completion(&qproc
->start_done
);
932 init_completion(&qproc
->stop_done
);
934 ret
= q6v5_init_mem(qproc
, pdev
);
938 ret
= q6v5_alloc_memory_region(qproc
);
942 ret
= q6v5_init_clocks(&pdev
->dev
, qproc
->proxy_clks
,
943 desc
->proxy_clk_names
);
945 dev_err(&pdev
->dev
, "Failed to get proxy clocks.\n");
948 qproc
->proxy_clk_count
= ret
;
950 ret
= q6v5_init_clocks(&pdev
->dev
, qproc
->active_clks
,
951 desc
->active_clk_names
);
953 dev_err(&pdev
->dev
, "Failed to get active clocks.\n");
956 qproc
->active_clk_count
= ret
;
958 ret
= q6v5_regulator_init(&pdev
->dev
, qproc
->proxy_regs
,
961 dev_err(&pdev
->dev
, "Failed to get proxy regulators.\n");
964 qproc
->proxy_reg_count
= ret
;
966 ret
= q6v5_regulator_init(&pdev
->dev
, qproc
->active_regs
,
967 desc
->active_supply
);
969 dev_err(&pdev
->dev
, "Failed to get active regulators.\n");
972 qproc
->active_reg_count
= ret
;
974 ret
= q6v5_init_reset(qproc
);
978 ret
= q6v5_request_irq(qproc
, pdev
, "wdog", q6v5_wdog_interrupt
);
982 ret
= q6v5_request_irq(qproc
, pdev
, "fatal", q6v5_fatal_interrupt
);
986 ret
= q6v5_request_irq(qproc
, pdev
, "handover", q6v5_handover_interrupt
);
990 ret
= q6v5_request_irq(qproc
, pdev
, "stop-ack", q6v5_stop_ack_interrupt
);
994 qproc
->state
= qcom_smem_state_get(&pdev
->dev
, "stop", &qproc
->stop_bit
);
995 if (IS_ERR(qproc
->state
)) {
996 ret
= PTR_ERR(qproc
->state
);
1000 ret
= rproc_add(rproc
);
1012 static int q6v5_remove(struct platform_device
*pdev
)
1014 struct q6v5
*qproc
= platform_get_drvdata(pdev
);
1016 rproc_del(qproc
->rproc
);
1017 rproc_free(qproc
->rproc
);
1022 static const struct rproc_hexagon_res msm8916_mss
= {
1023 .hexagon_mba_image
= "mba.mbn",
1024 .proxy_supply
= (struct qcom_mss_reg_res
[]) {
1039 .active_supply
= (struct qcom_mss_reg_res
[]) {
1047 .proxy_clk_names
= (char*[]){
1051 .active_clk_names
= (char*[]){
1059 static const struct rproc_hexagon_res msm8974_mss
= {
1060 .hexagon_mba_image
= "mba.b00",
1061 .proxy_supply
= (struct qcom_mss_reg_res
[]) {
1076 .active_supply
= (struct qcom_mss_reg_res
[]) {
1084 .proxy_clk_names
= (char*[]){
1088 .active_clk_names
= (char*[]){
1096 static const struct of_device_id q6v5_of_match
[] = {
1097 { .compatible
= "qcom,q6v5-pil", .data
= &msm8916_mss
},
1098 { .compatible
= "qcom,msm8916-mss-pil", .data
= &msm8916_mss
},
1099 { .compatible
= "qcom,msm8974-mss-pil", .data
= &msm8974_mss
},
1102 MODULE_DEVICE_TABLE(of
, q6v5_of_match
);
1104 static struct platform_driver q6v5_driver
= {
1105 .probe
= q6v5_probe
,
1106 .remove
= q6v5_remove
,
1108 .name
= "qcom-q6v5-pil",
1109 .of_match_table
= q6v5_of_match
,
1112 module_platform_driver(q6v5_driver
);
1114 MODULE_DESCRIPTION("Peripheral Image Loader for Hexagon");
1115 MODULE_LICENSE("GPL v2");