^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Qualcomm Technology Inc. ADSP Peripheral Image Loader for SDM845.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2018, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/pm_domain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/remoteproc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/soc/qcom/mdt_loader.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/soc/qcom/smem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/soc/qcom/smem_state.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "qcom_common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "qcom_pil_info.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "qcom_q6v5.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "remoteproc_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* time out value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define ACK_TIMEOUT 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define BOOT_FSM_TIMEOUT 10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* mask values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define EVB_MASK GENMASK(27, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /*QDSP6SS register offsets*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define RST_EVB_REG 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define CORE_START_REG 0x400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define BOOT_CMD_REG 0x404
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define BOOT_STATUS_REG 0x408
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define RET_CFG_REG 0x1C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /*TCSR register offsets*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define LPASS_MASTER_IDLE_REG 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define LPASS_HALTACK_REG 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define LPASS_PWR_ON_REG 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define LPASS_HALTREQ_REG 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define QDSP6SS_XO_CBCR 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define QDSP6SS_CORE_CBCR 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define QDSP6SS_SLEEP_CBCR 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct adsp_pil_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int crash_reason_smem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const char *firmware_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) const char *ssr_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) const char *sysmon_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int ssctl_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) const char **clk_ids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int num_clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct qcom_adsp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct rproc *rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct qcom_q6v5 q6v5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct clk *xo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int num_clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct clk_bulk_data *clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) void __iomem *qdsp6ss_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct reset_control *pdc_sync_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct reset_control *restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct regmap *halt_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned int halt_lpass;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int crash_reason_smem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) const char *info_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct completion start_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct completion stop_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) phys_addr_t mem_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) phys_addr_t mem_reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) void *mem_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) size_t mem_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct qcom_rproc_glink glink_subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct qcom_rproc_ssr ssr_subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct qcom_sysmon *sysmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int qcom_adsp_shutdown(struct qcom_adsp *adsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* Reset the retention logic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) val = readl(adsp->qdsp6ss_base + RET_CFG_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) val |= 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) writel(val, adsp->qdsp6ss_base + RET_CFG_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* QDSP6 master port needs to be explicitly halted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ret = regmap_read(adsp->halt_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) adsp->halt_lpass + LPASS_PWR_ON_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (ret || !val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) goto reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ret = regmap_read(adsp->halt_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) adsp->halt_lpass + LPASS_MASTER_IDLE_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (ret || val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) goto reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) regmap_write(adsp->halt_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) adsp->halt_lpass + LPASS_HALTREQ_REG, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* Wait for halt ACK from QDSP6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) timeout = jiffies + msecs_to_jiffies(ACK_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ret = regmap_read(adsp->halt_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) adsp->halt_lpass + LPASS_HALTACK_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (ret || val || time_after(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) usleep_range(1000, 1100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ret = regmap_read(adsp->halt_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) adsp->halt_lpass + LPASS_MASTER_IDLE_REG, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (ret || !val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) dev_err(adsp->dev, "port failed halt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) reset:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* Assert the LPASS PDC Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) reset_control_assert(adsp->pdc_sync_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* Place the LPASS processor into reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) reset_control_assert(adsp->restart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* wait after asserting subsystem restart from AOSS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) usleep_range(200, 300);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* Clear the halt request for the AXIM and AHBM for Q6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) regmap_write(adsp->halt_map, adsp->halt_lpass + LPASS_HALTREQ_REG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* De-assert the LPASS PDC Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) reset_control_deassert(adsp->pdc_sync_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* Remove the LPASS reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) reset_control_deassert(adsp->restart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* wait after de-asserting subsystem restart from AOSS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) usleep_range(200, 300);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static int adsp_load(struct rproc *rproc, const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ret = qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) adsp->mem_region, adsp->mem_phys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) adsp->mem_size, &adsp->mem_reloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static int adsp_start(struct rproc *rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) qcom_q6v5_prepare(&adsp->q6v5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ret = clk_prepare_enable(adsp->xo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) goto disable_irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) dev_pm_genpd_set_performance_state(adsp->dev, INT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ret = pm_runtime_get_sync(adsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) pm_runtime_put_noidle(adsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) goto disable_xo_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ret = clk_bulk_prepare_enable(adsp->num_clks, adsp->clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) dev_err(adsp->dev, "adsp clk_enable failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) goto disable_power_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* Enable the XO clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) writel(1, adsp->qdsp6ss_base + QDSP6SS_XO_CBCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* Enable the QDSP6SS sleep clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) writel(1, adsp->qdsp6ss_base + QDSP6SS_SLEEP_CBCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* Enable the QDSP6 core clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) writel(1, adsp->qdsp6ss_base + QDSP6SS_CORE_CBCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* Program boot address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) writel(adsp->mem_phys >> 4, adsp->qdsp6ss_base + RST_EVB_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* De-assert QDSP6 stop core. QDSP6 will execute after out of reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) writel(0x1, adsp->qdsp6ss_base + CORE_START_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* Trigger boot FSM to start QDSP6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) writel(0x1, adsp->qdsp6ss_base + BOOT_CMD_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* Wait for core to come out of reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ret = readl_poll_timeout(adsp->qdsp6ss_base + BOOT_STATUS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) dev_err(adsp->dev, "failed to bootup adsp\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) goto disable_adsp_clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5 * HZ));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (ret == -ETIMEDOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) dev_err(adsp->dev, "start timed out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) goto disable_adsp_clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) disable_adsp_clks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) disable_power_domain:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) dev_pm_genpd_set_performance_state(adsp->dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) pm_runtime_put(adsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) disable_xo_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) clk_disable_unprepare(adsp->xo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) disable_irqs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) qcom_q6v5_unprepare(&adsp->q6v5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static void qcom_adsp_pil_handover(struct qcom_q6v5 *q6v5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) clk_disable_unprepare(adsp->xo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) dev_pm_genpd_set_performance_state(adsp->dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) pm_runtime_put(adsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static int adsp_stop(struct rproc *rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) int handover;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ret = qcom_q6v5_request_stop(&adsp->q6v5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (ret == -ETIMEDOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) dev_err(adsp->dev, "timed out on wait\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ret = qcom_adsp_shutdown(adsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) handover = qcom_q6v5_unprepare(&adsp->q6v5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (handover)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) qcom_adsp_pil_handover(&adsp->q6v5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) offset = da - adsp->mem_reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (offset < 0 || offset + len > adsp->mem_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return adsp->mem_region + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static unsigned long adsp_panic(struct rproc *rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct qcom_adsp *adsp = rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return qcom_q6v5_panic(&adsp->q6v5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static const struct rproc_ops adsp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .start = adsp_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .stop = adsp_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .da_to_va = adsp_da_to_va,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .parse_fw = qcom_register_dump_segments,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .load = adsp_load,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) .panic = adsp_panic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static int adsp_init_clock(struct qcom_adsp *adsp, const char **clk_ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int num_clks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) adsp->xo = devm_clk_get(adsp->dev, "xo");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (IS_ERR(adsp->xo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ret = PTR_ERR(adsp->xo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) dev_err(adsp->dev, "failed to get xo clock");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) for (i = 0; clk_ids[i]; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) num_clks++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) adsp->num_clks = num_clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) adsp->clks = devm_kcalloc(adsp->dev, adsp->num_clks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) sizeof(*adsp->clks), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (!adsp->clks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) for (i = 0; i < adsp->num_clks; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) adsp->clks[i].id = clk_ids[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return devm_clk_bulk_get(adsp->dev, adsp->num_clks, adsp->clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static int adsp_init_reset(struct qcom_adsp *adsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) adsp->pdc_sync_reset = devm_reset_control_get_optional_exclusive(adsp->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) "pdc_sync");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (IS_ERR(adsp->pdc_sync_reset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) dev_err(adsp->dev, "failed to acquire pdc_sync reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return PTR_ERR(adsp->pdc_sync_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) adsp->restart = devm_reset_control_get_optional_exclusive(adsp->dev, "restart");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* Fall back to the old "cc_lpass" if "restart" is absent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (!adsp->restart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) adsp->restart = devm_reset_control_get_exclusive(adsp->dev, "cc_lpass");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (IS_ERR(adsp->restart)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dev_err(adsp->dev, "failed to acquire restart\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return PTR_ERR(adsp->restart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int adsp_init_mmio(struct qcom_adsp *adsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct device_node *syscon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) adsp->qdsp6ss_base = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (IS_ERR(adsp->qdsp6ss_base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) dev_err(adsp->dev, "failed to map QDSP6SS registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return PTR_ERR(adsp->qdsp6ss_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) syscon = of_parse_phandle(pdev->dev.of_node, "qcom,halt-regs", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (!syscon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) adsp->halt_map = syscon_node_to_regmap(syscon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) of_node_put(syscon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (IS_ERR(adsp->halt_map))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return PTR_ERR(adsp->halt_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ret = of_property_read_u32_index(pdev->dev.of_node, "qcom,halt-regs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 1, &adsp->halt_lpass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) dev_err(&pdev->dev, "no offset in syscon\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct resource r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (!node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) dev_err(adsp->dev, "no memory-region specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ret = of_address_to_resource(node, 0, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) adsp->mem_phys = adsp->mem_reloc = r.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) adsp->mem_size = resource_size(&r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) adsp->mem_region = devm_ioremap_wc(adsp->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) adsp->mem_phys, adsp->mem_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (!adsp->mem_region) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) &r.start, adsp->mem_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static int adsp_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) const struct adsp_pil_data *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct qcom_adsp *adsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct rproc *rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) desc = of_device_get_match_data(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (!desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) desc->firmware_name, sizeof(*adsp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (!rproc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) dev_err(&pdev->dev, "unable to allocate remoteproc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) adsp = (struct qcom_adsp *)rproc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) adsp->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) adsp->rproc = rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) adsp->info_name = desc->sysmon_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) platform_set_drvdata(pdev, adsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) ret = adsp_alloc_memory_region(adsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) goto free_rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ret = adsp_init_clock(adsp, desc->clk_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) goto free_rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) pm_runtime_enable(adsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ret = adsp_init_reset(adsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) goto disable_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) ret = adsp_init_mmio(adsp, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) goto disable_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) qcom_adsp_pil_handover);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) goto disable_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) adsp->sysmon = qcom_add_sysmon_subdev(rproc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) desc->sysmon_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) desc->ssctl_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (IS_ERR(adsp->sysmon)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) ret = PTR_ERR(adsp->sysmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) goto disable_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) ret = rproc_add(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) goto disable_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) disable_pm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) pm_runtime_disable(adsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) free_rproc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) rproc_free(rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static int adsp_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct qcom_adsp *adsp = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) rproc_del(adsp->rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) qcom_remove_sysmon_subdev(adsp->sysmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) pm_runtime_disable(adsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) rproc_free(adsp->rproc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static const struct adsp_pil_data adsp_resource_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) .crash_reason_smem = 423,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) .firmware_name = "adsp.mdt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) .ssr_name = "lpass",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) .sysmon_name = "adsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) .ssctl_id = 0x14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) .clk_ids = (const char*[]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) "sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) "qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core", NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) .num_clks = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static const struct adsp_pil_data cdsp_resource_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) .crash_reason_smem = 601,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) .firmware_name = "cdsp.mdt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) .ssr_name = "cdsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) .sysmon_name = "cdsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) .ssctl_id = 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) .clk_ids = (const char*[]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) "sway", "tbu", "bimc", "ahb_aon", "q6ss_slave", "q6ss_master",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) "q6_axim", NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) .num_clks = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static const struct of_device_id adsp_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) { .compatible = "qcom,qcs404-cdsp-pil", .data = &cdsp_resource_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) { .compatible = "qcom,sdm845-adsp-pil", .data = &adsp_resource_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) MODULE_DEVICE_TABLE(of, adsp_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static struct platform_driver adsp_pil_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) .probe = adsp_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) .remove = adsp_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) .name = "qcom_q6v5_adsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .of_match_table = adsp_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) module_platform_driver(adsp_pil_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) MODULE_DESCRIPTION("QTI SDM845 ADSP Peripheral Image Loader");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) MODULE_LICENSE("GPL v2");