brintos

brintos / linux-shallow public Read only

0
0
Text · 61.3 KiB · 2a42215 Raw
2546 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Qualcomm self-authenticating modem subsystem remoteproc driver4 *5 * Copyright (C) 2016 Linaro Ltd.6 * Copyright (C) 2014 Sony Mobile Communications AB7 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.8 */9 10#include <linux/clk.h>11#include <linux/delay.h>12#include <linux/devcoredump.h>13#include <linux/dma-mapping.h>14#include <linux/interrupt.h>15#include <linux/kernel.h>16#include <linux/mfd/syscon.h>17#include <linux/module.h>18#include <linux/of.h>19#include <linux/of_reserved_mem.h>20#include <linux/of_platform.h>21#include <linux/platform_device.h>22#include <linux/pm_domain.h>23#include <linux/pm_runtime.h>24#include <linux/regmap.h>25#include <linux/regulator/consumer.h>26#include <linux/remoteproc.h>27#include <linux/reset.h>28#include <linux/soc/qcom/mdt_loader.h>29#include <linux/iopoll.h>30#include <linux/slab.h>31 32#include "remoteproc_internal.h"33#include "qcom_common.h"34#include "qcom_pil_info.h"35#include "qcom_q6v5.h"36 37#include <linux/firmware/qcom/qcom_scm.h>38 39#define MPSS_CRASH_REASON_SMEM		42140 41#define MBA_LOG_SIZE			SZ_4K42 43#define MPSS_PAS_ID			544 45/* RMB Status Register Values */46#define RMB_PBL_SUCCESS			0x147 48#define RMB_MBA_XPU_UNLOCKED		0x149#define RMB_MBA_XPU_UNLOCKED_SCRIBBLED	0x250#define RMB_MBA_META_DATA_AUTH_SUCCESS	0x351#define RMB_MBA_AUTH_COMPLETE		0x452 53/* PBL/MBA interface registers */54#define RMB_MBA_IMAGE_REG		0x0055#define RMB_PBL_STATUS_REG		0x0456#define RMB_MBA_COMMAND_REG		0x0857#define RMB_MBA_STATUS_REG		0x0C58#define RMB_PMI_META_DATA_REG		0x1059#define RMB_PMI_CODE_START_REG		0x1460#define RMB_PMI_CODE_LENGTH_REG		0x1861#define RMB_MBA_MSS_STATUS		0x4062#define RMB_MBA_ALT_RESET		0x4463 64#define RMB_CMD_META_DATA_READY		0x165#define RMB_CMD_LOAD_READY		0x266 67/* QDSP6SS Register Offsets */68#define QDSP6SS_RESET_REG		0x01469#define QDSP6SS_GFMUX_CTL_REG		0x02070#define QDSP6SS_PWR_CTL_REG		0x03071#define QDSP6SS_MEM_PWR_CTL		0x0B072#define QDSP6V6SS_MEM_PWR_CTL		0x03473#define QDSP6SS_STRAP_ACC		0x11074#define QDSP6V62SS_BHS_STATUS		0x0C475 76/* AXI Halt Register Offsets */77#define AXI_HALTREQ_REG			0x078#define AXI_HALTACK_REG			0x479#define AXI_IDLE_REG			0x880#define AXI_GATING_VALID_OVERRIDE	BIT(0)81 82#define HALT_ACK_TIMEOUT_US		10000083 84/* QACCEPT Register Offsets */85#define QACCEPT_ACCEPT_REG		0x086#define QACCEPT_ACTIVE_REG		0x487#define QACCEPT_DENY_REG		0x888#define QACCEPT_REQ_REG			0xC89 90#define QACCEPT_TIMEOUT_US		5091 92/* QDSP6SS_RESET */93#define Q6SS_STOP_CORE			BIT(0)94#define Q6SS_CORE_ARES			BIT(1)95#define Q6SS_BUS_ARES_ENABLE		BIT(2)96 97/* QDSP6SS CBCR */98#define Q6SS_CBCR_CLKEN			BIT(0)99#define Q6SS_CBCR_CLKOFF		BIT(31)100#define Q6SS_CBCR_TIMEOUT_US		200101 102/* QDSP6SS_GFMUX_CTL */103#define Q6SS_CLK_ENABLE			BIT(1)104 105/* QDSP6SS_PWR_CTL */106#define Q6SS_L2DATA_SLP_NRET_N_0	BIT(0)107#define Q6SS_L2DATA_SLP_NRET_N_1	BIT(1)108#define Q6SS_L2DATA_SLP_NRET_N_2	BIT(2)109#define Q6SS_L2TAG_SLP_NRET_N		BIT(16)110#define Q6SS_ETB_SLP_NRET_N		BIT(17)111#define Q6SS_L2DATA_STBY_N		BIT(18)112#define Q6SS_SLP_RET_N			BIT(19)113#define Q6SS_CLAMP_IO			BIT(20)114#define QDSS_BHS_ON			BIT(21)115#define QDSS_LDO_BYP			BIT(22)116 117/* QDSP6v55 parameters */118#define QDSP6V55_MEM_BITS		GENMASK(16, 8)119 120/* QDSP6v56 parameters */121#define QDSP6v56_LDO_BYP		BIT(25)122#define QDSP6v56_BHS_ON		BIT(24)123#define QDSP6v56_CLAMP_WL		BIT(21)124#define QDSP6v56_CLAMP_QMC_MEM		BIT(22)125#define QDSP6SS_XO_CBCR		0x0038126#define QDSP6SS_ACC_OVERRIDE_VAL		0x20127#define QDSP6v55_BHS_EN_REST_ACK	BIT(0)128 129/* QDSP6v65 parameters */130#define QDSP6SS_CORE_CBCR		0x20131#define QDSP6SS_SLEEP                   0x3C132#define QDSP6SS_BOOT_CORE_START         0x400133#define QDSP6SS_BOOT_CMD                0x404134#define BOOT_FSM_TIMEOUT                10000135#define BHS_CHECK_MAX_LOOPS             200136 137struct reg_info {138	struct regulator *reg;139	int uV;140	int uA;141};142 143struct qcom_mss_reg_res {144	const char *supply;145	int uV;146	int uA;147};148 149struct rproc_hexagon_res {150	const char *hexagon_mba_image;151	struct qcom_mss_reg_res *proxy_supply;152	struct qcom_mss_reg_res *fallback_proxy_supply;153	struct qcom_mss_reg_res *active_supply;154	char **proxy_clk_names;155	char **reset_clk_names;156	char **active_clk_names;157	char **proxy_pd_names;158	int version;159	bool need_mem_protection;160	bool has_alt_reset;161	bool has_mba_logs;162	bool has_spare_reg;163	bool has_qaccept_regs;164	bool has_ext_cntl_regs;165	bool has_vq6;166};167 168struct q6v5 {169	struct device *dev;170	struct rproc *rproc;171 172	void __iomem *reg_base;173	void __iomem *rmb_base;174 175	struct regmap *halt_map;176	struct regmap *conn_map;177 178	u32 halt_q6;179	u32 halt_modem;180	u32 halt_nc;181	u32 halt_vq6;182	u32 conn_box;183 184	u32 qaccept_mdm;185	u32 qaccept_cx;186	u32 qaccept_axi;187 188	u32 axim1_clk_off;189	u32 crypto_clk_off;190	u32 force_clk_on;191	u32 rscc_disable;192 193	struct reset_control *mss_restart;194	struct reset_control *pdc_reset;195 196	struct qcom_q6v5 q6v5;197 198	struct clk *active_clks[8];199	struct clk *reset_clks[4];200	struct clk *proxy_clks[4];201	struct device *proxy_pds[3];202	int active_clk_count;203	int reset_clk_count;204	int proxy_clk_count;205	int proxy_pd_count;206 207	struct reg_info active_regs[1];208	struct reg_info proxy_regs[1];209	struct reg_info fallback_proxy_regs[2];210	int active_reg_count;211	int proxy_reg_count;212	int fallback_proxy_reg_count;213 214	bool dump_mba_loaded;215	size_t current_dump_size;216	size_t total_dump_size;217 218	phys_addr_t mba_phys;219	size_t mba_size;220	size_t dp_size;221 222	phys_addr_t mdata_phys;223	size_t mdata_size;224 225	phys_addr_t mpss_phys;226	phys_addr_t mpss_reloc;227	size_t mpss_size;228 229	struct qcom_rproc_glink glink_subdev;230	struct qcom_rproc_subdev smd_subdev;231	struct qcom_rproc_pdm pdm_subdev;232	struct qcom_rproc_ssr ssr_subdev;233	struct qcom_sysmon *sysmon;234	struct platform_device *bam_dmux;235	bool need_mem_protection;236	bool has_alt_reset;237	bool has_mba_logs;238	bool has_spare_reg;239	bool has_qaccept_regs;240	bool has_ext_cntl_regs;241	bool has_vq6;242	u64 mpss_perm;243	u64 mba_perm;244	const char *hexagon_mdt_image;245	int version;246};247 248enum {249	MSS_MSM8909,250	MSS_MSM8916,251	MSS_MSM8953,252	MSS_MSM8974,253	MSS_MSM8996,254	MSS_MSM8998,255	MSS_SC7180,256	MSS_SC7280,257	MSS_SDM660,258	MSS_SDM845,259};260 261static int q6v5_regulator_init(struct device *dev, struct reg_info *regs,262			       const struct qcom_mss_reg_res *reg_res)263{264	int rc;265	int i;266 267	if (!reg_res)268		return 0;269 270	for (i = 0; reg_res[i].supply; i++) {271		regs[i].reg = devm_regulator_get(dev, reg_res[i].supply);272		if (IS_ERR(regs[i].reg)) {273			rc = PTR_ERR(regs[i].reg);274			if (rc != -EPROBE_DEFER)275				dev_err(dev, "Failed to get %s\n regulator",276					reg_res[i].supply);277			return rc;278		}279 280		regs[i].uV = reg_res[i].uV;281		regs[i].uA = reg_res[i].uA;282	}283 284	return i;285}286 287static int q6v5_regulator_enable(struct q6v5 *qproc,288				 struct reg_info *regs, int count)289{290	int ret;291	int i;292 293	for (i = 0; i < count; i++) {294		if (regs[i].uV > 0) {295			ret = regulator_set_voltage(regs[i].reg,296					regs[i].uV, INT_MAX);297			if (ret) {298				dev_err(qproc->dev,299					"Failed to request voltage for %d.\n",300						i);301				goto err;302			}303		}304 305		if (regs[i].uA > 0) {306			ret = regulator_set_load(regs[i].reg,307						 regs[i].uA);308			if (ret < 0) {309				dev_err(qproc->dev,310					"Failed to set regulator mode\n");311				goto err;312			}313		}314 315		ret = regulator_enable(regs[i].reg);316		if (ret) {317			dev_err(qproc->dev, "Regulator enable failed\n");318			goto err;319		}320	}321 322	return 0;323err:324	for (; i >= 0; i--) {325		if (regs[i].uV > 0)326			regulator_set_voltage(regs[i].reg, 0, INT_MAX);327 328		if (regs[i].uA > 0)329			regulator_set_load(regs[i].reg, 0);330 331		regulator_disable(regs[i].reg);332	}333 334	return ret;335}336 337static void q6v5_regulator_disable(struct q6v5 *qproc,338				   struct reg_info *regs, int count)339{340	int i;341 342	for (i = 0; i < count; i++) {343		if (regs[i].uV > 0)344			regulator_set_voltage(regs[i].reg, 0, INT_MAX);345 346		if (regs[i].uA > 0)347			regulator_set_load(regs[i].reg, 0);348 349		regulator_disable(regs[i].reg);350	}351}352 353static int q6v5_clk_enable(struct device *dev,354			   struct clk **clks, int count)355{356	int rc;357	int i;358 359	for (i = 0; i < count; i++) {360		rc = clk_prepare_enable(clks[i]);361		if (rc) {362			dev_err(dev, "Clock enable failed\n");363			goto err;364		}365	}366 367	return 0;368err:369	for (i--; i >= 0; i--)370		clk_disable_unprepare(clks[i]);371 372	return rc;373}374 375static void q6v5_clk_disable(struct device *dev,376			     struct clk **clks, int count)377{378	int i;379 380	for (i = 0; i < count; i++)381		clk_disable_unprepare(clks[i]);382}383 384static int q6v5_pds_enable(struct q6v5 *qproc, struct device **pds,385			   size_t pd_count)386{387	int ret;388	int i;389 390	for (i = 0; i < pd_count; i++) {391		dev_pm_genpd_set_performance_state(pds[i], INT_MAX);392		ret = pm_runtime_get_sync(pds[i]);393		if (ret < 0) {394			pm_runtime_put_noidle(pds[i]);395			dev_pm_genpd_set_performance_state(pds[i], 0);396			goto unroll_pd_votes;397		}398	}399 400	return 0;401 402unroll_pd_votes:403	for (i--; i >= 0; i--) {404		dev_pm_genpd_set_performance_state(pds[i], 0);405		pm_runtime_put(pds[i]);406	}407 408	return ret;409}410 411static void q6v5_pds_disable(struct q6v5 *qproc, struct device **pds,412			     size_t pd_count)413{414	int i;415 416	for (i = 0; i < pd_count; i++) {417		dev_pm_genpd_set_performance_state(pds[i], 0);418		pm_runtime_put(pds[i]);419	}420}421 422static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, u64 *current_perm,423				   bool local, bool remote, phys_addr_t addr,424				   size_t size)425{426	struct qcom_scm_vmperm next[2];427	int perms = 0;428 429	if (!qproc->need_mem_protection)430		return 0;431 432	if (local == !!(*current_perm & BIT(QCOM_SCM_VMID_HLOS)) &&433	    remote == !!(*current_perm & BIT(QCOM_SCM_VMID_MSS_MSA)))434		return 0;435 436	if (local) {437		next[perms].vmid = QCOM_SCM_VMID_HLOS;438		next[perms].perm = QCOM_SCM_PERM_RWX;439		perms++;440	}441 442	if (remote) {443		next[perms].vmid = QCOM_SCM_VMID_MSS_MSA;444		next[perms].perm = QCOM_SCM_PERM_RW;445		perms++;446	}447 448	return qcom_scm_assign_mem(addr, ALIGN(size, SZ_4K),449				   current_perm, next, perms);450}451 452static void q6v5_debug_policy_load(struct q6v5 *qproc, void *mba_region)453{454	const struct firmware *dp_fw;455 456	if (request_firmware_direct(&dp_fw, "msadp", qproc->dev))457		return;458 459	if (SZ_1M + dp_fw->size <= qproc->mba_size) {460		memcpy(mba_region + SZ_1M, dp_fw->data, dp_fw->size);461		qproc->dp_size = dp_fw->size;462	}463 464	release_firmware(dp_fw);465}466 467static int q6v5_load(struct rproc *rproc, const struct firmware *fw)468{469	struct q6v5 *qproc = rproc->priv;470	void *mba_region;471 472	/* MBA is restricted to a maximum size of 1M */473	if (fw->size > qproc->mba_size || fw->size > SZ_1M) {474		dev_err(qproc->dev, "MBA firmware load failed\n");475		return -EINVAL;476	}477 478	mba_region = memremap(qproc->mba_phys, qproc->mba_size, MEMREMAP_WC);479	if (!mba_region) {480		dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n",481			&qproc->mba_phys, qproc->mba_size);482		return -EBUSY;483	}484 485	memcpy(mba_region, fw->data, fw->size);486	q6v5_debug_policy_load(qproc, mba_region);487	memunmap(mba_region);488 489	return 0;490}491 492static int q6v5_reset_assert(struct q6v5 *qproc)493{494	int ret;495 496	if (qproc->has_alt_reset) {497		reset_control_assert(qproc->pdc_reset);498		ret = reset_control_reset(qproc->mss_restart);499		reset_control_deassert(qproc->pdc_reset);500	} else if (qproc->has_spare_reg) {501		/*502		 * When the AXI pipeline is being reset with the Q6 modem partly503		 * operational there is possibility of AXI valid signal to504		 * glitch, leading to spurious transactions and Q6 hangs. A work505		 * around is employed by asserting the AXI_GATING_VALID_OVERRIDE506		 * BIT before triggering Q6 MSS reset. AXI_GATING_VALID_OVERRIDE507		 * is withdrawn post MSS assert followed by a MSS deassert,508		 * while holding the PDC reset.509		 */510		reset_control_assert(qproc->pdc_reset);511		regmap_update_bits(qproc->conn_map, qproc->conn_box,512				   AXI_GATING_VALID_OVERRIDE, 1);513		reset_control_assert(qproc->mss_restart);514		reset_control_deassert(qproc->pdc_reset);515		regmap_update_bits(qproc->conn_map, qproc->conn_box,516				   AXI_GATING_VALID_OVERRIDE, 0);517		ret = reset_control_deassert(qproc->mss_restart);518	} else if (qproc->has_ext_cntl_regs) {519		regmap_write(qproc->conn_map, qproc->rscc_disable, 0);520		reset_control_assert(qproc->pdc_reset);521		reset_control_assert(qproc->mss_restart);522		reset_control_deassert(qproc->pdc_reset);523		ret = reset_control_deassert(qproc->mss_restart);524	} else {525		ret = reset_control_assert(qproc->mss_restart);526	}527 528	return ret;529}530 531static int q6v5_reset_deassert(struct q6v5 *qproc)532{533	int ret;534 535	if (qproc->has_alt_reset) {536		reset_control_assert(qproc->pdc_reset);537		writel(1, qproc->rmb_base + RMB_MBA_ALT_RESET);538		ret = reset_control_reset(qproc->mss_restart);539		writel(0, qproc->rmb_base + RMB_MBA_ALT_RESET);540		reset_control_deassert(qproc->pdc_reset);541	} else if (qproc->has_spare_reg || qproc->has_ext_cntl_regs) {542		ret = reset_control_reset(qproc->mss_restart);543	} else {544		ret = reset_control_deassert(qproc->mss_restart);545	}546 547	return ret;548}549 550static int q6v5_rmb_pbl_wait(struct q6v5 *qproc, int ms)551{552	unsigned long timeout;553	s32 val;554 555	timeout = jiffies + msecs_to_jiffies(ms);556	for (;;) {557		val = readl(qproc->rmb_base + RMB_PBL_STATUS_REG);558		if (val)559			break;560 561		if (time_after(jiffies, timeout))562			return -ETIMEDOUT;563 564		msleep(1);565	}566 567	return val;568}569 570static int q6v5_rmb_mba_wait(struct q6v5 *qproc, u32 status, int ms)571{572 573	unsigned long timeout;574	s32 val;575 576	timeout = jiffies + msecs_to_jiffies(ms);577	for (;;) {578		val = readl(qproc->rmb_base + RMB_MBA_STATUS_REG);579		if (val < 0)580			break;581 582		if (!status && val)583			break;584		else if (status && val == status)585			break;586 587		if (time_after(jiffies, timeout))588			return -ETIMEDOUT;589 590		msleep(1);591	}592 593	return val;594}595 596static void q6v5_dump_mba_logs(struct q6v5 *qproc)597{598	struct rproc *rproc = qproc->rproc;599	void *data;600	void *mba_region;601 602	if (!qproc->has_mba_logs)603		return;604 605	if (q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true, false, qproc->mba_phys,606				    qproc->mba_size))607		return;608 609	mba_region = memremap(qproc->mba_phys, qproc->mba_size, MEMREMAP_WC);610	if (!mba_region)611		return;612 613	data = vmalloc(MBA_LOG_SIZE);614	if (data) {615		memcpy(data, mba_region, MBA_LOG_SIZE);616		dev_coredumpv(&rproc->dev, data, MBA_LOG_SIZE, GFP_KERNEL);617	}618	memunmap(mba_region);619}620 621static int q6v5proc_reset(struct q6v5 *qproc)622{623	u32 val;624	int ret;625	int i;626 627	if (qproc->version == MSS_SDM845) {628		val = readl(qproc->reg_base + QDSP6SS_SLEEP);629		val |= Q6SS_CBCR_CLKEN;630		writel(val, qproc->reg_base + QDSP6SS_SLEEP);631 632		ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_SLEEP,633					 val, !(val & Q6SS_CBCR_CLKOFF), 1,634					 Q6SS_CBCR_TIMEOUT_US);635		if (ret) {636			dev_err(qproc->dev, "QDSP6SS Sleep clock timed out\n");637			return -ETIMEDOUT;638		}639 640		/* De-assert QDSP6 stop core */641		writel(1, qproc->reg_base + QDSP6SS_BOOT_CORE_START);642		/* Trigger boot FSM */643		writel(1, qproc->reg_base + QDSP6SS_BOOT_CMD);644 645		ret = readl_poll_timeout(qproc->rmb_base + RMB_MBA_MSS_STATUS,646				val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT);647		if (ret) {648			dev_err(qproc->dev, "Boot FSM failed to complete.\n");649			/* Reset the modem so that boot FSM is in reset state */650			q6v5_reset_deassert(qproc);651			return ret;652		}653 654		goto pbl_wait;655	} else if (qproc->version == MSS_SC7180 || qproc->version == MSS_SC7280) {656		val = readl(qproc->reg_base + QDSP6SS_SLEEP);657		val |= Q6SS_CBCR_CLKEN;658		writel(val, qproc->reg_base + QDSP6SS_SLEEP);659 660		ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_SLEEP,661					 val, !(val & Q6SS_CBCR_CLKOFF), 1,662					 Q6SS_CBCR_TIMEOUT_US);663		if (ret) {664			dev_err(qproc->dev, "QDSP6SS Sleep clock timed out\n");665			return -ETIMEDOUT;666		}667 668		/* Turn on the XO clock needed for PLL setup */669		val = readl(qproc->reg_base + QDSP6SS_XO_CBCR);670		val |= Q6SS_CBCR_CLKEN;671		writel(val, qproc->reg_base + QDSP6SS_XO_CBCR);672 673		ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_XO_CBCR,674					 val, !(val & Q6SS_CBCR_CLKOFF), 1,675					 Q6SS_CBCR_TIMEOUT_US);676		if (ret) {677			dev_err(qproc->dev, "QDSP6SS XO clock timed out\n");678			return -ETIMEDOUT;679		}680 681		/* Configure Q6 core CBCR to auto-enable after reset sequence */682		val = readl(qproc->reg_base + QDSP6SS_CORE_CBCR);683		val |= Q6SS_CBCR_CLKEN;684		writel(val, qproc->reg_base + QDSP6SS_CORE_CBCR);685 686		/* De-assert the Q6 stop core signal */687		writel(1, qproc->reg_base + QDSP6SS_BOOT_CORE_START);688 689		/* Wait for 10 us for any staggering logic to settle */690		usleep_range(10, 20);691 692		/* Trigger the boot FSM to start the Q6 out-of-reset sequence */693		writel(1, qproc->reg_base + QDSP6SS_BOOT_CMD);694 695		/* Poll the MSS_STATUS for FSM completion */696		ret = readl_poll_timeout(qproc->rmb_base + RMB_MBA_MSS_STATUS,697					 val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT);698		if (ret) {699			dev_err(qproc->dev, "Boot FSM failed to complete.\n");700			/* Reset the modem so that boot FSM is in reset state */701			q6v5_reset_deassert(qproc);702			return ret;703		}704		goto pbl_wait;705	} else if (qproc->version == MSS_MSM8909 ||706		   qproc->version == MSS_MSM8953 ||707		   qproc->version == MSS_MSM8996 ||708		   qproc->version == MSS_MSM8998 ||709		   qproc->version == MSS_SDM660) {710 711		if (qproc->version != MSS_MSM8909 &&712		    qproc->version != MSS_MSM8953)713			/* Override the ACC value if required */714			writel(QDSP6SS_ACC_OVERRIDE_VAL,715			       qproc->reg_base + QDSP6SS_STRAP_ACC);716 717		/* Assert resets, stop core */718		val = readl(qproc->reg_base + QDSP6SS_RESET_REG);719		val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE;720		writel(val, qproc->reg_base + QDSP6SS_RESET_REG);721 722		/* BHS require xo cbcr to be enabled */723		val = readl(qproc->reg_base + QDSP6SS_XO_CBCR);724		val |= Q6SS_CBCR_CLKEN;725		writel(val, qproc->reg_base + QDSP6SS_XO_CBCR);726 727		/* Read CLKOFF bit to go low indicating CLK is enabled */728		ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_XO_CBCR,729					 val, !(val & Q6SS_CBCR_CLKOFF), 1,730					 Q6SS_CBCR_TIMEOUT_US);731		if (ret) {732			dev_err(qproc->dev,733				"xo cbcr enabling timed out (rc:%d)\n", ret);734			return ret;735		}736		/* Enable power block headswitch and wait for it to stabilize */737		val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);738		val |= QDSP6v56_BHS_ON;739		writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);740		val |= readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);741		udelay(1);742 743		if (qproc->version == MSS_SDM660) {744			ret = readl_relaxed_poll_timeout(qproc->reg_base + QDSP6V62SS_BHS_STATUS,745							 i, (i & QDSP6v55_BHS_EN_REST_ACK),746							 1, BHS_CHECK_MAX_LOOPS);747			if (ret == -ETIMEDOUT) {748				dev_err(qproc->dev, "BHS_EN_REST_ACK not set!\n");749				return -ETIMEDOUT;750			}751		}752 753		/* Put LDO in bypass mode */754		val |= QDSP6v56_LDO_BYP;755		writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);756 757		if (qproc->version != MSS_MSM8909) {758			int mem_pwr_ctl;759 760			/* Deassert QDSP6 compiler memory clamp */761			val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);762			val &= ~QDSP6v56_CLAMP_QMC_MEM;763			writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);764 765			/* Deassert memory peripheral sleep and L2 memory standby */766			val |= Q6SS_L2DATA_STBY_N | Q6SS_SLP_RET_N;767			writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);768 769			/* Turn on L1, L2, ETB and JU memories 1 at a time */770			if (qproc->version == MSS_MSM8953 ||771			    qproc->version == MSS_MSM8996) {772				mem_pwr_ctl = QDSP6SS_MEM_PWR_CTL;773				i = 19;774			} else {775				/* MSS_MSM8998, MSS_SDM660 */776				mem_pwr_ctl = QDSP6V6SS_MEM_PWR_CTL;777				i = 28;778			}779			val = readl(qproc->reg_base + mem_pwr_ctl);780			for (; i >= 0; i--) {781				val |= BIT(i);782				writel(val, qproc->reg_base + mem_pwr_ctl);783				/*784				 * Read back value to ensure the write is done then785				 * wait for 1us for both memory peripheral and data786				 * array to turn on.787				 */788				val |= readl(qproc->reg_base + mem_pwr_ctl);789				udelay(1);790			}791		} else {792			/* Turn on memories */793			val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);794			val |= Q6SS_SLP_RET_N | Q6SS_L2DATA_STBY_N |795			       Q6SS_ETB_SLP_NRET_N | QDSP6V55_MEM_BITS;796			writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);797 798			/* Turn on L2 banks 1 at a time */799			for (i = 0; i <= 7; i++) {800				val |= BIT(i);801				writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);802			}803		}804 805		/* Remove word line clamp */806		val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);807		val &= ~QDSP6v56_CLAMP_WL;808		writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);809	} else {810		/* Assert resets, stop core */811		val = readl(qproc->reg_base + QDSP6SS_RESET_REG);812		val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE;813		writel(val, qproc->reg_base + QDSP6SS_RESET_REG);814 815		/* Enable power block headswitch and wait for it to stabilize */816		val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);817		val |= QDSS_BHS_ON | QDSS_LDO_BYP;818		writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);819		val |= readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);820		udelay(1);821		/*822		 * Turn on memories. L2 banks should be done individually823		 * to minimize inrush current.824		 */825		val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);826		val |= Q6SS_SLP_RET_N | Q6SS_L2TAG_SLP_NRET_N |827			Q6SS_ETB_SLP_NRET_N | Q6SS_L2DATA_STBY_N;828		writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);829		val |= Q6SS_L2DATA_SLP_NRET_N_2;830		writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);831		val |= Q6SS_L2DATA_SLP_NRET_N_1;832		writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);833		val |= Q6SS_L2DATA_SLP_NRET_N_0;834		writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);835	}836	/* Remove IO clamp */837	val &= ~Q6SS_CLAMP_IO;838	writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);839 840	/* Bring core out of reset */841	val = readl(qproc->reg_base + QDSP6SS_RESET_REG);842	val &= ~Q6SS_CORE_ARES;843	writel(val, qproc->reg_base + QDSP6SS_RESET_REG);844 845	/* Turn on core clock */846	val = readl(qproc->reg_base + QDSP6SS_GFMUX_CTL_REG);847	val |= Q6SS_CLK_ENABLE;848	writel(val, qproc->reg_base + QDSP6SS_GFMUX_CTL_REG);849 850	/* Start core execution */851	val = readl(qproc->reg_base + QDSP6SS_RESET_REG);852	val &= ~Q6SS_STOP_CORE;853	writel(val, qproc->reg_base + QDSP6SS_RESET_REG);854 855pbl_wait:856	/* Wait for PBL status */857	ret = q6v5_rmb_pbl_wait(qproc, 1000);858	if (ret == -ETIMEDOUT) {859		dev_err(qproc->dev, "PBL boot timed out\n");860	} else if (ret != RMB_PBL_SUCCESS) {861		dev_err(qproc->dev, "PBL returned unexpected status %d\n", ret);862		ret = -EINVAL;863	} else {864		ret = 0;865	}866 867	return ret;868}869 870static int q6v5proc_enable_qchannel(struct q6v5 *qproc, struct regmap *map, u32 offset)871{872	unsigned int val;873	int ret;874 875	if (!qproc->has_qaccept_regs)876		return 0;877 878	if (qproc->has_ext_cntl_regs) {879		regmap_write(qproc->conn_map, qproc->rscc_disable, 0);880		regmap_write(qproc->conn_map, qproc->force_clk_on, 1);881 882		ret = regmap_read_poll_timeout(qproc->halt_map, qproc->axim1_clk_off, val,883					       !val, 1, Q6SS_CBCR_TIMEOUT_US);884		if (ret) {885			dev_err(qproc->dev, "failed to enable axim1 clock\n");886			return -ETIMEDOUT;887		}888	}889 890	regmap_write(map, offset + QACCEPT_REQ_REG, 1);891 892	/* Wait for accept */893	ret = regmap_read_poll_timeout(map, offset + QACCEPT_ACCEPT_REG, val, val, 5,894				       QACCEPT_TIMEOUT_US);895	if (ret) {896		dev_err(qproc->dev, "qchannel enable failed\n");897		return -ETIMEDOUT;898	}899 900	return 0;901}902 903static void q6v5proc_disable_qchannel(struct q6v5 *qproc, struct regmap *map, u32 offset)904{905	int ret;906	unsigned int val, retry;907	unsigned int nretry = 10;908	bool takedown_complete = false;909 910	if (!qproc->has_qaccept_regs)911		return;912 913	while (!takedown_complete && nretry) {914		nretry--;915 916		/* Wait for active transactions to complete */917		regmap_read_poll_timeout(map, offset + QACCEPT_ACTIVE_REG, val, !val, 5,918					 QACCEPT_TIMEOUT_US);919 920		/* Request Q-channel transaction takedown */921		regmap_write(map, offset + QACCEPT_REQ_REG, 0);922 923		/*924		 * If the request is denied, reset the Q-channel takedown request,925		 * wait for active transactions to complete and retry takedown.926		 */927		retry = 10;928		while (retry) {929			usleep_range(5, 10);930			retry--;931			ret = regmap_read(map, offset + QACCEPT_DENY_REG, &val);932			if (!ret && val) {933				regmap_write(map, offset + QACCEPT_REQ_REG, 1);934				break;935			}936 937			ret = regmap_read(map, offset + QACCEPT_ACCEPT_REG, &val);938			if (!ret && !val) {939				takedown_complete = true;940				break;941			}942		}943 944		if (!retry)945			break;946	}947 948	/* Rely on mss_restart to clear out pending transactions on takedown failure */949	if (!takedown_complete)950		dev_err(qproc->dev, "qchannel takedown failed\n");951}952 953static void q6v5proc_halt_axi_port(struct q6v5 *qproc,954				   struct regmap *halt_map,955				   u32 offset)956{957	unsigned int val;958	int ret;959 960	/* Check if we're already idle */961	ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);962	if (!ret && val)963		return;964 965	/* Assert halt request */966	regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1);967 968	/* Wait for halt */969	regmap_read_poll_timeout(halt_map, offset + AXI_HALTACK_REG, val,970				 val, 1000, HALT_ACK_TIMEOUT_US);971 972	ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);973	if (ret || !val)974		dev_err(qproc->dev, "port failed halt\n");975 976	/* Clear halt request (port will remain halted until reset) */977	regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0);978}979 980static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw,981				const char *fw_name)982{983	unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;984	dma_addr_t phys;985	void *metadata;986	u64 mdata_perm;987	int xferop_ret;988	size_t size;989	void *ptr;990	int ret;991 992	metadata = qcom_mdt_read_metadata(fw, &size, fw_name, qproc->dev);993	if (IS_ERR(metadata))994		return PTR_ERR(metadata);995 996	if (qproc->mdata_phys) {997		if (size > qproc->mdata_size) {998			ret = -EINVAL;999			dev_err(qproc->dev, "metadata size outside memory range\n");1000			goto free_metadata;1001		}1002 1003		phys = qproc->mdata_phys;1004		ptr = memremap(qproc->mdata_phys, size, MEMREMAP_WC);1005		if (!ptr) {1006			ret = -EBUSY;1007			dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n",1008				&qproc->mdata_phys, size);1009			goto free_metadata;1010		}1011	} else {1012		ptr = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, dma_attrs);1013		if (!ptr) {1014			ret = -ENOMEM;1015			dev_err(qproc->dev, "failed to allocate mdt buffer\n");1016			goto free_metadata;1017		}1018	}1019 1020	memcpy(ptr, metadata, size);1021 1022	if (qproc->mdata_phys)1023		memunmap(ptr);1024 1025	/* Hypervisor mapping to access metadata by modem */1026	mdata_perm = BIT(QCOM_SCM_VMID_HLOS);1027	ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, false, true,1028				      phys, size);1029	if (ret) {1030		dev_err(qproc->dev,1031			"assigning Q6 access to metadata failed: %d\n", ret);1032		ret = -EAGAIN;1033		goto free_dma_attrs;1034	}1035 1036	writel(phys, qproc->rmb_base + RMB_PMI_META_DATA_REG);1037	writel(RMB_CMD_META_DATA_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG);1038 1039	ret = q6v5_rmb_mba_wait(qproc, RMB_MBA_META_DATA_AUTH_SUCCESS, 1000);1040	if (ret == -ETIMEDOUT)1041		dev_err(qproc->dev, "MPSS header authentication timed out\n");1042	else if (ret < 0)1043		dev_err(qproc->dev, "MPSS header authentication failed: %d\n", ret);1044 1045	/* Metadata authentication done, remove modem access */1046	xferop_ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, true, false,1047					     phys, size);1048	if (xferop_ret)1049		dev_warn(qproc->dev,1050			 "mdt buffer not reclaimed system may become unstable\n");1051 1052free_dma_attrs:1053	if (!qproc->mdata_phys)1054		dma_free_attrs(qproc->dev, size, ptr, phys, dma_attrs);1055free_metadata:1056	kfree(metadata);1057 1058	return ret < 0 ? ret : 0;1059}1060 1061static bool q6v5_phdr_valid(const struct elf32_phdr *phdr)1062{1063	if (phdr->p_type != PT_LOAD)1064		return false;1065 1066	if ((phdr->p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH)1067		return false;1068 1069	if (!phdr->p_memsz)1070		return false;1071 1072	return true;1073}1074 1075static int q6v5_mba_load(struct q6v5 *qproc)1076{1077	int ret;1078	int xfermemop_ret;1079	bool mba_load_err = false;1080 1081	ret = qcom_q6v5_prepare(&qproc->q6v5);1082	if (ret)1083		return ret;1084 1085	ret = q6v5_pds_enable(qproc, qproc->proxy_pds, qproc->proxy_pd_count);1086	if (ret < 0) {1087		dev_err(qproc->dev, "failed to enable proxy power domains\n");1088		goto disable_irqs;1089	}1090 1091	ret = q6v5_regulator_enable(qproc, qproc->fallback_proxy_regs,1092				    qproc->fallback_proxy_reg_count);1093	if (ret) {1094		dev_err(qproc->dev, "failed to enable fallback proxy supplies\n");1095		goto disable_proxy_pds;1096	}1097 1098	ret = q6v5_regulator_enable(qproc, qproc->proxy_regs,1099				    qproc->proxy_reg_count);1100	if (ret) {1101		dev_err(qproc->dev, "failed to enable proxy supplies\n");1102		goto disable_fallback_proxy_reg;1103	}1104 1105	ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks,1106			      qproc->proxy_clk_count);1107	if (ret) {1108		dev_err(qproc->dev, "failed to enable proxy clocks\n");1109		goto disable_proxy_reg;1110	}1111 1112	ret = q6v5_regulator_enable(qproc, qproc->active_regs,1113				    qproc->active_reg_count);1114	if (ret) {1115		dev_err(qproc->dev, "failed to enable supplies\n");1116		goto disable_proxy_clk;1117	}1118 1119	ret = q6v5_clk_enable(qproc->dev, qproc->reset_clks,1120			      qproc->reset_clk_count);1121	if (ret) {1122		dev_err(qproc->dev, "failed to enable reset clocks\n");1123		goto disable_vdd;1124	}1125 1126	ret = q6v5_reset_deassert(qproc);1127	if (ret) {1128		dev_err(qproc->dev, "failed to deassert mss restart\n");1129		goto disable_reset_clks;1130	}1131 1132	ret = q6v5_clk_enable(qproc->dev, qproc->active_clks,1133			      qproc->active_clk_count);1134	if (ret) {1135		dev_err(qproc->dev, "failed to enable clocks\n");1136		goto assert_reset;1137	}1138 1139	ret = q6v5proc_enable_qchannel(qproc, qproc->halt_map, qproc->qaccept_axi);1140	if (ret) {1141		dev_err(qproc->dev, "failed to enable axi bridge\n");1142		goto disable_active_clks;1143	}1144 1145	/*1146	 * Some versions of the MBA firmware will upon boot wipe the MPSS region as well, so provide1147	 * the Q6 access to this region.1148	 */1149	ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, false, true,1150				      qproc->mpss_phys, qproc->mpss_size);1151	if (ret) {1152		dev_err(qproc->dev, "assigning Q6 access to mpss memory failed: %d\n", ret);1153		goto disable_active_clks;1154	}1155 1156	/* Assign MBA image access in DDR to q6 */1157	ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, false, true,1158				      qproc->mba_phys, qproc->mba_size);1159	if (ret) {1160		dev_err(qproc->dev,1161			"assigning Q6 access to mba memory failed: %d\n", ret);1162		goto disable_active_clks;1163	}1164 1165	writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG);1166	if (qproc->dp_size) {1167		writel(qproc->mba_phys + SZ_1M, qproc->rmb_base + RMB_PMI_CODE_START_REG);1168		writel(qproc->dp_size, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);1169	}1170 1171	ret = q6v5proc_reset(qproc);1172	if (ret)1173		goto reclaim_mba;1174 1175	if (qproc->has_mba_logs)1176		qcom_pil_info_store("mba", qproc->mba_phys, MBA_LOG_SIZE);1177 1178	ret = q6v5_rmb_mba_wait(qproc, 0, 5000);1179	if (ret == -ETIMEDOUT) {1180		dev_err(qproc->dev, "MBA boot timed out\n");1181		goto halt_axi_ports;1182	} else if (ret != RMB_MBA_XPU_UNLOCKED &&1183		   ret != RMB_MBA_XPU_UNLOCKED_SCRIBBLED) {1184		dev_err(qproc->dev, "MBA returned unexpected status %d\n", ret);1185		ret = -EINVAL;1186		goto halt_axi_ports;1187	}1188 1189	qproc->dump_mba_loaded = true;1190	return 0;1191 1192halt_axi_ports:1193	q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6);1194	if (qproc->has_vq6)1195		q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_vq6);1196	q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);1197	q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);1198	q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_mdm);1199	q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_cx);1200	q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_axi);1201	mba_load_err = true;1202reclaim_mba:1203	xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true,1204						false, qproc->mba_phys,1205						qproc->mba_size);1206	if (xfermemop_ret) {1207		dev_err(qproc->dev,1208			"Failed to reclaim mba buffer, system may become unstable\n");1209	} else if (mba_load_err) {1210		q6v5_dump_mba_logs(qproc);1211	}1212 1213disable_active_clks:1214	q6v5_clk_disable(qproc->dev, qproc->active_clks,1215			 qproc->active_clk_count);1216assert_reset:1217	q6v5_reset_assert(qproc);1218disable_reset_clks:1219	q6v5_clk_disable(qproc->dev, qproc->reset_clks,1220			 qproc->reset_clk_count);1221disable_vdd:1222	q6v5_regulator_disable(qproc, qproc->active_regs,1223			       qproc->active_reg_count);1224disable_proxy_clk:1225	q6v5_clk_disable(qproc->dev, qproc->proxy_clks,1226			 qproc->proxy_clk_count);1227disable_proxy_reg:1228	q6v5_regulator_disable(qproc, qproc->proxy_regs,1229			       qproc->proxy_reg_count);1230disable_fallback_proxy_reg:1231	q6v5_regulator_disable(qproc, qproc->fallback_proxy_regs,1232			       qproc->fallback_proxy_reg_count);1233disable_proxy_pds:1234	q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count);1235disable_irqs:1236	qcom_q6v5_unprepare(&qproc->q6v5);1237 1238	return ret;1239}1240 1241static void q6v5_mba_reclaim(struct q6v5 *qproc)1242{1243	int ret;1244	u32 val;1245 1246	qproc->dump_mba_loaded = false;1247	qproc->dp_size = 0;1248 1249	q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6);1250	if (qproc->has_vq6)1251		q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_vq6);1252	q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);1253	q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);1254	if (qproc->version == MSS_MSM8996) {1255		/*1256		 * To avoid high MX current during LPASS/MSS restart.1257		 */1258		val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);1259		val |= Q6SS_CLAMP_IO | QDSP6v56_CLAMP_WL |1260			QDSP6v56_CLAMP_QMC_MEM;1261		writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);1262	}1263 1264	if (qproc->has_ext_cntl_regs) {1265		regmap_write(qproc->conn_map, qproc->rscc_disable, 1);1266 1267		ret = regmap_read_poll_timeout(qproc->halt_map, qproc->axim1_clk_off, val,1268					       !val, 1, Q6SS_CBCR_TIMEOUT_US);1269		if (ret)1270			dev_err(qproc->dev, "failed to enable axim1 clock\n");1271 1272		ret = regmap_read_poll_timeout(qproc->halt_map, qproc->crypto_clk_off, val,1273					       !val, 1, Q6SS_CBCR_TIMEOUT_US);1274		if (ret)1275			dev_err(qproc->dev, "failed to enable crypto clock\n");1276	}1277 1278	q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_mdm);1279	q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_cx);1280	q6v5proc_disable_qchannel(qproc, qproc->halt_map, qproc->qaccept_axi);1281 1282	q6v5_reset_assert(qproc);1283 1284	q6v5_clk_disable(qproc->dev, qproc->reset_clks,1285			 qproc->reset_clk_count);1286	q6v5_clk_disable(qproc->dev, qproc->active_clks,1287			 qproc->active_clk_count);1288	q6v5_regulator_disable(qproc, qproc->active_regs,1289			       qproc->active_reg_count);1290 1291	/* In case of failure or coredump scenario where reclaiming MBA memory1292	 * could not happen reclaim it here.1293	 */1294	ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true, false,1295				      qproc->mba_phys,1296				      qproc->mba_size);1297	WARN_ON(ret);1298 1299	ret = qcom_q6v5_unprepare(&qproc->q6v5);1300	if (ret) {1301		q6v5_pds_disable(qproc, qproc->proxy_pds,1302				 qproc->proxy_pd_count);1303		q6v5_clk_disable(qproc->dev, qproc->proxy_clks,1304				 qproc->proxy_clk_count);1305		q6v5_regulator_disable(qproc, qproc->fallback_proxy_regs,1306				       qproc->fallback_proxy_reg_count);1307		q6v5_regulator_disable(qproc, qproc->proxy_regs,1308				       qproc->proxy_reg_count);1309	}1310}1311 1312static int q6v5_reload_mba(struct rproc *rproc)1313{1314	struct q6v5 *qproc = rproc->priv;1315	const struct firmware *fw;1316	int ret;1317 1318	ret = request_firmware(&fw, rproc->firmware, qproc->dev);1319	if (ret < 0)1320		return ret;1321 1322	q6v5_load(rproc, fw);1323	ret = q6v5_mba_load(qproc);1324	release_firmware(fw);1325 1326	return ret;1327}1328 1329static int q6v5_mpss_load(struct q6v5 *qproc)1330{1331	const struct elf32_phdr *phdrs;1332	const struct elf32_phdr *phdr;1333	const struct firmware *seg_fw;1334	const struct firmware *fw;1335	struct elf32_hdr *ehdr;1336	phys_addr_t mpss_reloc;1337	phys_addr_t boot_addr;1338	phys_addr_t min_addr = PHYS_ADDR_MAX;1339	phys_addr_t max_addr = 0;1340	u32 code_length;1341	bool relocate = false;1342	char *fw_name;1343	size_t fw_name_len;1344	ssize_t offset;1345	size_t size = 0;1346	void *ptr;1347	int ret;1348	int i;1349 1350	fw_name_len = strlen(qproc->hexagon_mdt_image);1351	if (fw_name_len <= 4)1352		return -EINVAL;1353 1354	fw_name = kstrdup(qproc->hexagon_mdt_image, GFP_KERNEL);1355	if (!fw_name)1356		return -ENOMEM;1357 1358	ret = request_firmware(&fw, fw_name, qproc->dev);1359	if (ret < 0) {1360		dev_err(qproc->dev, "unable to load %s\n", fw_name);1361		goto out;1362	}1363 1364	/* Initialize the RMB validator */1365	writel(0, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);1366 1367	ret = q6v5_mpss_init_image(qproc, fw, qproc->hexagon_mdt_image);1368	if (ret)1369		goto release_firmware;1370 1371	ehdr = (struct elf32_hdr *)fw->data;1372	phdrs = (struct elf32_phdr *)(ehdr + 1);1373 1374	for (i = 0; i < ehdr->e_phnum; i++) {1375		phdr = &phdrs[i];1376 1377		if (!q6v5_phdr_valid(phdr))1378			continue;1379 1380		if (phdr->p_flags & QCOM_MDT_RELOCATABLE)1381			relocate = true;1382 1383		if (phdr->p_paddr < min_addr)1384			min_addr = phdr->p_paddr;1385 1386		if (phdr->p_paddr + phdr->p_memsz > max_addr)1387			max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K);1388	}1389 1390	if (qproc->version == MSS_MSM8953) {1391		ret = qcom_scm_pas_mem_setup(MPSS_PAS_ID, qproc->mpss_phys, qproc->mpss_size);1392		if (ret) {1393			dev_err(qproc->dev,1394				"setting up mpss memory failed: %d\n", ret);1395			goto release_firmware;1396		}1397	}1398 1399	/*1400	 * In case of a modem subsystem restart on secure devices, the modem1401	 * memory can be reclaimed only after MBA is loaded.1402	 */1403	q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, true, false,1404				qproc->mpss_phys, qproc->mpss_size);1405 1406	/* Share ownership between Linux and MSS, during segment loading */1407	ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, true, true,1408				      qproc->mpss_phys, qproc->mpss_size);1409	if (ret) {1410		dev_err(qproc->dev,1411			"assigning Q6 access to mpss memory failed: %d\n", ret);1412		ret = -EAGAIN;1413		goto release_firmware;1414	}1415 1416	mpss_reloc = relocate ? min_addr : qproc->mpss_phys;1417	qproc->mpss_reloc = mpss_reloc;1418	/* Load firmware segments */1419	for (i = 0; i < ehdr->e_phnum; i++) {1420		phdr = &phdrs[i];1421 1422		if (!q6v5_phdr_valid(phdr))1423			continue;1424 1425		offset = phdr->p_paddr - mpss_reloc;1426		if (offset < 0 || offset + phdr->p_memsz > qproc->mpss_size) {1427			dev_err(qproc->dev, "segment outside memory range\n");1428			ret = -EINVAL;1429			goto release_firmware;1430		}1431 1432		if (phdr->p_filesz > phdr->p_memsz) {1433			dev_err(qproc->dev,1434				"refusing to load segment %d with p_filesz > p_memsz\n",1435				i);1436			ret = -EINVAL;1437			goto release_firmware;1438		}1439 1440		ptr = memremap(qproc->mpss_phys + offset, phdr->p_memsz, MEMREMAP_WC);1441		if (!ptr) {1442			dev_err(qproc->dev,1443				"unable to map memory region: %pa+%zx-%x\n",1444				&qproc->mpss_phys, offset, phdr->p_memsz);1445			goto release_firmware;1446		}1447 1448		if (phdr->p_filesz && phdr->p_offset < fw->size) {1449			/* Firmware is large enough to be non-split */1450			if (phdr->p_offset + phdr->p_filesz > fw->size) {1451				dev_err(qproc->dev,1452					"failed to load segment %d from truncated file %s\n",1453					i, fw_name);1454				ret = -EINVAL;1455				memunmap(ptr);1456				goto release_firmware;1457			}1458 1459			memcpy(ptr, fw->data + phdr->p_offset, phdr->p_filesz);1460		} else if (phdr->p_filesz) {1461			/* Replace "xxx.xxx" with "xxx.bxx" */1462			sprintf(fw_name + fw_name_len - 3, "b%02d", i);1463			ret = request_firmware_into_buf(&seg_fw, fw_name, qproc->dev,1464							ptr, phdr->p_filesz);1465			if (ret) {1466				dev_err(qproc->dev, "failed to load %s\n", fw_name);1467				memunmap(ptr);1468				goto release_firmware;1469			}1470 1471			if (seg_fw->size != phdr->p_filesz) {1472				dev_err(qproc->dev,1473					"failed to load segment %d from truncated file %s\n",1474					i, fw_name);1475				ret = -EINVAL;1476				release_firmware(seg_fw);1477				memunmap(ptr);1478				goto release_firmware;1479			}1480 1481			release_firmware(seg_fw);1482		}1483 1484		if (phdr->p_memsz > phdr->p_filesz) {1485			memset(ptr + phdr->p_filesz, 0,1486			       phdr->p_memsz - phdr->p_filesz);1487		}1488		memunmap(ptr);1489		size += phdr->p_memsz;1490 1491		code_length = readl(qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);1492		if (!code_length) {1493			boot_addr = relocate ? qproc->mpss_phys : min_addr;1494			writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG);1495			writel(RMB_CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG);1496		}1497		writel(size, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);1498 1499		ret = readl(qproc->rmb_base + RMB_MBA_STATUS_REG);1500		if (ret < 0) {1501			dev_err(qproc->dev, "MPSS authentication failed: %d\n",1502				ret);1503			goto release_firmware;1504		}1505	}1506 1507	/* Transfer ownership of modem ddr region to q6 */1508	ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, false, true,1509				      qproc->mpss_phys, qproc->mpss_size);1510	if (ret) {1511		dev_err(qproc->dev,1512			"assigning Q6 access to mpss memory failed: %d\n", ret);1513		ret = -EAGAIN;1514		goto release_firmware;1515	}1516 1517	ret = q6v5_rmb_mba_wait(qproc, RMB_MBA_AUTH_COMPLETE, 10000);1518	if (ret == -ETIMEDOUT)1519		dev_err(qproc->dev, "MPSS authentication timed out\n");1520	else if (ret < 0)1521		dev_err(qproc->dev, "MPSS authentication failed: %d\n", ret);1522 1523	qcom_pil_info_store("modem", qproc->mpss_phys, qproc->mpss_size);1524 1525release_firmware:1526	release_firmware(fw);1527out:1528	kfree(fw_name);1529 1530	return ret < 0 ? ret : 0;1531}1532 1533static void qcom_q6v5_dump_segment(struct rproc *rproc,1534				   struct rproc_dump_segment *segment,1535				   void *dest, size_t cp_offset, size_t size)1536{1537	int ret = 0;1538	struct q6v5 *qproc = rproc->priv;1539	int offset = segment->da - qproc->mpss_reloc;1540	void *ptr = NULL;1541 1542	/* Unlock mba before copying segments */1543	if (!qproc->dump_mba_loaded) {1544		ret = q6v5_reload_mba(rproc);1545		if (!ret) {1546			/* Reset ownership back to Linux to copy segments */1547			ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm,1548						      true, false,1549						      qproc->mpss_phys,1550						      qproc->mpss_size);1551		}1552	}1553 1554	if (!ret)1555		ptr = memremap(qproc->mpss_phys + offset + cp_offset, size, MEMREMAP_WC);1556 1557	if (ptr) {1558		memcpy(dest, ptr, size);1559		memunmap(ptr);1560	} else {1561		memset(dest, 0xff, size);1562	}1563 1564	qproc->current_dump_size += size;1565 1566	/* Reclaim mba after copying segments */1567	if (qproc->current_dump_size == qproc->total_dump_size) {1568		if (qproc->dump_mba_loaded) {1569			/* Try to reset ownership back to Q6 */1570			q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm,1571						false, true,1572						qproc->mpss_phys,1573						qproc->mpss_size);1574			q6v5_mba_reclaim(qproc);1575		}1576	}1577}1578 1579static int q6v5_start(struct rproc *rproc)1580{1581	struct q6v5 *qproc = rproc->priv;1582	int xfermemop_ret;1583	int ret;1584 1585	ret = q6v5_mba_load(qproc);1586	if (ret)1587		return ret;1588 1589	dev_info(qproc->dev, "MBA booted with%s debug policy, loading mpss\n",1590		 qproc->dp_size ? "" : "out");1591 1592	ret = q6v5_mpss_load(qproc);1593	if (ret)1594		goto reclaim_mpss;1595 1596	ret = qcom_q6v5_wait_for_start(&qproc->q6v5, msecs_to_jiffies(5000));1597	if (ret == -ETIMEDOUT) {1598		dev_err(qproc->dev, "start timed out\n");1599		goto reclaim_mpss;1600	}1601 1602	xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true,1603						false, qproc->mba_phys,1604						qproc->mba_size);1605	if (xfermemop_ret)1606		dev_err(qproc->dev,1607			"Failed to reclaim mba buffer system may become unstable\n");1608 1609	/* Reset Dump Segment Mask */1610	qproc->current_dump_size = 0;1611 1612	return 0;1613 1614reclaim_mpss:1615	q6v5_mba_reclaim(qproc);1616	q6v5_dump_mba_logs(qproc);1617 1618	return ret;1619}1620 1621static int q6v5_stop(struct rproc *rproc)1622{1623	struct q6v5 *qproc = rproc->priv;1624	int ret;1625 1626	ret = qcom_q6v5_request_stop(&qproc->q6v5, qproc->sysmon);1627	if (ret == -ETIMEDOUT)1628		dev_err(qproc->dev, "timed out on wait\n");1629 1630	q6v5_mba_reclaim(qproc);1631 1632	return 0;1633}1634 1635static int qcom_q6v5_register_dump_segments(struct rproc *rproc,1636					    const struct firmware *mba_fw)1637{1638	const struct firmware *fw;1639	const struct elf32_phdr *phdrs;1640	const struct elf32_phdr *phdr;1641	const struct elf32_hdr *ehdr;1642	struct q6v5 *qproc = rproc->priv;1643	unsigned long i;1644	int ret;1645 1646	ret = request_firmware(&fw, qproc->hexagon_mdt_image, qproc->dev);1647	if (ret < 0) {1648		dev_err(qproc->dev, "unable to load %s\n",1649			qproc->hexagon_mdt_image);1650		return ret;1651	}1652 1653	rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);1654 1655	ehdr = (struct elf32_hdr *)fw->data;1656	phdrs = (struct elf32_phdr *)(ehdr + 1);1657	qproc->total_dump_size = 0;1658 1659	for (i = 0; i < ehdr->e_phnum; i++) {1660		phdr = &phdrs[i];1661 1662		if (!q6v5_phdr_valid(phdr))1663			continue;1664 1665		ret = rproc_coredump_add_custom_segment(rproc, phdr->p_paddr,1666							phdr->p_memsz,1667							qcom_q6v5_dump_segment,1668							NULL);1669		if (ret)1670			break;1671 1672		qproc->total_dump_size += phdr->p_memsz;1673	}1674 1675	release_firmware(fw);1676	return ret;1677}1678 1679static unsigned long q6v5_panic(struct rproc *rproc)1680{1681	struct q6v5 *qproc = rproc->priv;1682 1683	return qcom_q6v5_panic(&qproc->q6v5);1684}1685 1686static const struct rproc_ops q6v5_ops = {1687	.start = q6v5_start,1688	.stop = q6v5_stop,1689	.parse_fw = qcom_q6v5_register_dump_segments,1690	.load = q6v5_load,1691	.panic = q6v5_panic,1692};1693 1694static void qcom_msa_handover(struct qcom_q6v5 *q6v5)1695{1696	struct q6v5 *qproc = container_of(q6v5, struct q6v5, q6v5);1697 1698	q6v5_clk_disable(qproc->dev, qproc->proxy_clks,1699			 qproc->proxy_clk_count);1700	q6v5_regulator_disable(qproc, qproc->proxy_regs,1701			       qproc->proxy_reg_count);1702	q6v5_regulator_disable(qproc, qproc->fallback_proxy_regs,1703			       qproc->fallback_proxy_reg_count);1704	q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count);1705}1706 1707static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev)1708{1709	struct of_phandle_args args;1710	int halt_cell_cnt = 3;1711	int ret;1712 1713	qproc->reg_base = devm_platform_ioremap_resource_byname(pdev, "qdsp6");1714	if (IS_ERR(qproc->reg_base))1715		return PTR_ERR(qproc->reg_base);1716 1717	qproc->rmb_base = devm_platform_ioremap_resource_byname(pdev, "rmb");1718	if (IS_ERR(qproc->rmb_base))1719		return PTR_ERR(qproc->rmb_base);1720 1721	if (qproc->has_vq6)1722		halt_cell_cnt++;1723 1724	ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,1725					       "qcom,halt-regs", halt_cell_cnt, 0, &args);1726	if (ret < 0) {1727		dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");1728		return -EINVAL;1729	}1730 1731	qproc->halt_map = syscon_node_to_regmap(args.np);1732	of_node_put(args.np);1733	if (IS_ERR(qproc->halt_map))1734		return PTR_ERR(qproc->halt_map);1735 1736	qproc->halt_q6 = args.args[0];1737	qproc->halt_modem = args.args[1];1738	qproc->halt_nc = args.args[2];1739 1740	if (qproc->has_vq6)1741		qproc->halt_vq6 = args.args[3];1742 1743	if (qproc->has_qaccept_regs) {1744		ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,1745						       "qcom,qaccept-regs",1746						       3, 0, &args);1747		if (ret < 0) {1748			dev_err(&pdev->dev, "failed to parse qaccept-regs\n");1749			return -EINVAL;1750		}1751 1752		qproc->qaccept_mdm = args.args[0];1753		qproc->qaccept_cx = args.args[1];1754		qproc->qaccept_axi = args.args[2];1755	}1756 1757	if (qproc->has_ext_cntl_regs) {1758		ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,1759						       "qcom,ext-regs",1760						       2, 0, &args);1761		if (ret < 0) {1762			dev_err(&pdev->dev, "failed to parse ext-regs index 0\n");1763			return -EINVAL;1764		}1765 1766		qproc->conn_map = syscon_node_to_regmap(args.np);1767		of_node_put(args.np);1768		if (IS_ERR(qproc->conn_map))1769			return PTR_ERR(qproc->conn_map);1770 1771		qproc->force_clk_on = args.args[0];1772		qproc->rscc_disable = args.args[1];1773 1774		ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,1775						       "qcom,ext-regs",1776						       2, 1, &args);1777		if (ret < 0) {1778			dev_err(&pdev->dev, "failed to parse ext-regs index 1\n");1779			return -EINVAL;1780		}1781 1782		qproc->axim1_clk_off = args.args[0];1783		qproc->crypto_clk_off = args.args[1];1784	}1785 1786	if (qproc->has_spare_reg) {1787		ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,1788						       "qcom,spare-regs",1789						       1, 0, &args);1790		if (ret < 0) {1791			dev_err(&pdev->dev, "failed to parse spare-regs\n");1792			return -EINVAL;1793		}1794 1795		qproc->conn_map = syscon_node_to_regmap(args.np);1796		of_node_put(args.np);1797		if (IS_ERR(qproc->conn_map))1798			return PTR_ERR(qproc->conn_map);1799 1800		qproc->conn_box = args.args[0];1801	}1802 1803	return 0;1804}1805 1806static int q6v5_init_clocks(struct device *dev, struct clk **clks,1807		char **clk_names)1808{1809	int i;1810 1811	if (!clk_names)1812		return 0;1813 1814	for (i = 0; clk_names[i]; i++) {1815		clks[i] = devm_clk_get(dev, clk_names[i]);1816		if (IS_ERR(clks[i])) {1817			int rc = PTR_ERR(clks[i]);1818 1819			if (rc != -EPROBE_DEFER)1820				dev_err(dev, "Failed to get %s clock\n",1821					clk_names[i]);1822			return rc;1823		}1824	}1825 1826	return i;1827}1828 1829static int q6v5_pds_attach(struct device *dev, struct device **devs,1830			   char **pd_names)1831{1832	size_t num_pds = 0;1833	int ret;1834	int i;1835 1836	if (!pd_names)1837		return 0;1838 1839	while (pd_names[num_pds])1840		num_pds++;1841 1842	for (i = 0; i < num_pds; i++) {1843		devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);1844		if (IS_ERR_OR_NULL(devs[i])) {1845			ret = PTR_ERR(devs[i]) ? : -ENODATA;1846			goto unroll_attach;1847		}1848	}1849 1850	return num_pds;1851 1852unroll_attach:1853	for (i--; i >= 0; i--)1854		dev_pm_domain_detach(devs[i], false);1855 1856	return ret;1857}1858 1859static void q6v5_pds_detach(struct q6v5 *qproc, struct device **pds,1860			    size_t pd_count)1861{1862	int i;1863 1864	for (i = 0; i < pd_count; i++)1865		dev_pm_domain_detach(pds[i], false);1866}1867 1868static int q6v5_init_reset(struct q6v5 *qproc)1869{1870	qproc->mss_restart = devm_reset_control_get_exclusive(qproc->dev,1871							      "mss_restart");1872	if (IS_ERR(qproc->mss_restart)) {1873		dev_err(qproc->dev, "failed to acquire mss restart\n");1874		return PTR_ERR(qproc->mss_restart);1875	}1876 1877	if (qproc->has_alt_reset || qproc->has_spare_reg || qproc->has_ext_cntl_regs) {1878		qproc->pdc_reset = devm_reset_control_get_exclusive(qproc->dev,1879								    "pdc_reset");1880		if (IS_ERR(qproc->pdc_reset)) {1881			dev_err(qproc->dev, "failed to acquire pdc reset\n");1882			return PTR_ERR(qproc->pdc_reset);1883		}1884	}1885 1886	return 0;1887}1888 1889static int q6v5_alloc_memory_region(struct q6v5 *qproc)1890{1891	struct device_node *child;1892	struct reserved_mem *rmem;1893	struct device_node *node;1894 1895	/*1896	 * In the absence of mba/mpss sub-child, extract the mba and mpss1897	 * reserved memory regions from device's memory-region property.1898	 */1899	child = of_get_child_by_name(qproc->dev->of_node, "mba");1900	if (!child) {1901		node = of_parse_phandle(qproc->dev->of_node,1902					"memory-region", 0);1903	} else {1904		node = of_parse_phandle(child, "memory-region", 0);1905		of_node_put(child);1906	}1907 1908	if (!node) {1909		dev_err(qproc->dev, "no mba memory-region specified\n");1910		return -EINVAL;1911	}1912 1913	rmem = of_reserved_mem_lookup(node);1914	of_node_put(node);1915	if (!rmem) {1916		dev_err(qproc->dev, "unable to resolve mba region\n");1917		return -EINVAL;1918	}1919 1920	qproc->mba_phys = rmem->base;1921	qproc->mba_size = rmem->size;1922 1923	if (!child) {1924		node = of_parse_phandle(qproc->dev->of_node,1925					"memory-region", 1);1926	} else {1927		child = of_get_child_by_name(qproc->dev->of_node, "mpss");1928		node = of_parse_phandle(child, "memory-region", 0);1929		of_node_put(child);1930	}1931 1932	if (!node) {1933		dev_err(qproc->dev, "no mpss memory-region specified\n");1934		return -EINVAL;1935	}1936 1937	rmem = of_reserved_mem_lookup(node);1938	of_node_put(node);1939	if (!rmem) {1940		dev_err(qproc->dev, "unable to resolve mpss region\n");1941		return -EINVAL;1942	}1943 1944	qproc->mpss_phys = qproc->mpss_reloc = rmem->base;1945	qproc->mpss_size = rmem->size;1946 1947	if (!child) {1948		node = of_parse_phandle(qproc->dev->of_node, "memory-region", 2);1949	} else {1950		child = of_get_child_by_name(qproc->dev->of_node, "metadata");1951		node = of_parse_phandle(child, "memory-region", 0);1952		of_node_put(child);1953	}1954 1955	if (!node)1956		return 0;1957 1958	rmem = of_reserved_mem_lookup(node);1959	if (!rmem) {1960		dev_err(qproc->dev, "unable to resolve metadata region\n");1961		return -EINVAL;1962	}1963 1964	qproc->mdata_phys = rmem->base;1965	qproc->mdata_size = rmem->size;1966 1967	return 0;1968}1969 1970static int q6v5_probe(struct platform_device *pdev)1971{1972	const struct rproc_hexagon_res *desc;1973	struct device_node *node;1974	struct q6v5 *qproc;1975	struct rproc *rproc;1976	const char *mba_image;1977	int ret;1978 1979	desc = of_device_get_match_data(&pdev->dev);1980	if (!desc)1981		return -EINVAL;1982 1983	if (desc->need_mem_protection && !qcom_scm_is_available())1984		return -EPROBE_DEFER;1985 1986	mba_image = desc->hexagon_mba_image;1987	ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name",1988					    0, &mba_image);1989	if (ret < 0 && ret != -EINVAL) {1990		dev_err(&pdev->dev, "unable to read mba firmware-name\n");1991		return ret;1992	}1993 1994	rproc = devm_rproc_alloc(&pdev->dev, pdev->name, &q6v5_ops,1995				 mba_image, sizeof(*qproc));1996	if (!rproc) {1997		dev_err(&pdev->dev, "failed to allocate rproc\n");1998		return -ENOMEM;1999	}2000 2001	rproc->auto_boot = false;2002	rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);2003 2004	qproc = rproc->priv;2005	qproc->dev = &pdev->dev;2006	qproc->rproc = rproc;2007	qproc->hexagon_mdt_image = "modem.mdt";2008	ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name",2009					    1, &qproc->hexagon_mdt_image);2010	if (ret < 0 && ret != -EINVAL) {2011		dev_err(&pdev->dev, "unable to read mpss firmware-name\n");2012		return ret;2013	}2014 2015	platform_set_drvdata(pdev, qproc);2016 2017	qproc->has_qaccept_regs = desc->has_qaccept_regs;2018	qproc->has_ext_cntl_regs = desc->has_ext_cntl_regs;2019	qproc->has_vq6 = desc->has_vq6;2020	qproc->has_spare_reg = desc->has_spare_reg;2021	ret = q6v5_init_mem(qproc, pdev);2022	if (ret)2023		return ret;2024 2025	ret = q6v5_alloc_memory_region(qproc);2026	if (ret)2027		return ret;2028 2029	ret = q6v5_init_clocks(&pdev->dev, qproc->proxy_clks,2030			       desc->proxy_clk_names);2031	if (ret < 0) {2032		dev_err(&pdev->dev, "Failed to get proxy clocks.\n");2033		return ret;2034	}2035	qproc->proxy_clk_count = ret;2036 2037	ret = q6v5_init_clocks(&pdev->dev, qproc->reset_clks,2038			       desc->reset_clk_names);2039	if (ret < 0) {2040		dev_err(&pdev->dev, "Failed to get reset clocks.\n");2041		return ret;2042	}2043	qproc->reset_clk_count = ret;2044 2045	ret = q6v5_init_clocks(&pdev->dev, qproc->active_clks,2046			       desc->active_clk_names);2047	if (ret < 0) {2048		dev_err(&pdev->dev, "Failed to get active clocks.\n");2049		return ret;2050	}2051	qproc->active_clk_count = ret;2052 2053	ret = q6v5_regulator_init(&pdev->dev, qproc->proxy_regs,2054				  desc->proxy_supply);2055	if (ret < 0) {2056		dev_err(&pdev->dev, "Failed to get proxy regulators.\n");2057		return ret;2058	}2059	qproc->proxy_reg_count = ret;2060 2061	ret = q6v5_regulator_init(&pdev->dev,  qproc->active_regs,2062				  desc->active_supply);2063	if (ret < 0) {2064		dev_err(&pdev->dev, "Failed to get active regulators.\n");2065		return ret;2066	}2067	qproc->active_reg_count = ret;2068 2069	ret = q6v5_pds_attach(&pdev->dev, qproc->proxy_pds,2070			      desc->proxy_pd_names);2071	/* Fallback to regulators for old device trees */2072	if (ret == -ENODATA && desc->fallback_proxy_supply) {2073		ret = q6v5_regulator_init(&pdev->dev,2074					  qproc->fallback_proxy_regs,2075					  desc->fallback_proxy_supply);2076		if (ret < 0) {2077			dev_err(&pdev->dev, "Failed to get fallback proxy regulators.\n");2078			return ret;2079		}2080		qproc->fallback_proxy_reg_count = ret;2081	} else if (ret < 0) {2082		dev_err(&pdev->dev, "Failed to init power domains\n");2083		return ret;2084	} else {2085		qproc->proxy_pd_count = ret;2086	}2087 2088	qproc->has_alt_reset = desc->has_alt_reset;2089	ret = q6v5_init_reset(qproc);2090	if (ret)2091		goto detach_proxy_pds;2092 2093	qproc->version = desc->version;2094	qproc->need_mem_protection = desc->need_mem_protection;2095	qproc->has_mba_logs = desc->has_mba_logs;2096 2097	ret = qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM, "modem",2098			     qcom_msa_handover);2099	if (ret)2100		goto detach_proxy_pds;2101 2102	qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS);2103	qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);2104	qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");2105	qcom_add_smd_subdev(rproc, &qproc->smd_subdev);2106	qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);2107	qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");2108	qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);2109	if (IS_ERR(qproc->sysmon)) {2110		ret = PTR_ERR(qproc->sysmon);2111		goto remove_subdevs;2112	}2113 2114	ret = rproc_add(rproc);2115	if (ret)2116		goto remove_sysmon_subdev;2117 2118	node = of_get_compatible_child(pdev->dev.of_node, "qcom,bam-dmux");2119	qproc->bam_dmux = of_platform_device_create(node, NULL, &pdev->dev);2120	of_node_put(node);2121 2122	return 0;2123 2124remove_sysmon_subdev:2125	qcom_remove_sysmon_subdev(qproc->sysmon);2126remove_subdevs:2127	qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);2128	qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);2129	qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);2130detach_proxy_pds:2131	q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);2132 2133	return ret;2134}2135 2136static void q6v5_remove(struct platform_device *pdev)2137{2138	struct q6v5 *qproc = platform_get_drvdata(pdev);2139	struct rproc *rproc = qproc->rproc;2140 2141	if (qproc->bam_dmux)2142		of_platform_device_destroy(&qproc->bam_dmux->dev, NULL);2143	rproc_del(rproc);2144 2145	qcom_q6v5_deinit(&qproc->q6v5);2146	qcom_remove_sysmon_subdev(qproc->sysmon);2147	qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);2148	qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);2149	qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);2150	qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);2151 2152	q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);2153}2154 2155static const struct rproc_hexagon_res sc7180_mss = {2156	.hexagon_mba_image = "mba.mbn",2157	.proxy_clk_names = (char*[]){2158		"xo",2159		NULL2160	},2161	.reset_clk_names = (char*[]){2162		"iface",2163		"bus",2164		"snoc_axi",2165		NULL2166	},2167	.active_clk_names = (char*[]){2168		"mnoc_axi",2169		"nav",2170		NULL2171	},2172	.proxy_pd_names = (char*[]){2173		"cx",2174		"mx",2175		"mss",2176		NULL2177	},2178	.need_mem_protection = true,2179	.has_alt_reset = false,2180	.has_mba_logs = true,2181	.has_spare_reg = true,2182	.has_qaccept_regs = false,2183	.has_ext_cntl_regs = false,2184	.has_vq6 = false,2185	.version = MSS_SC7180,2186};2187 2188static const struct rproc_hexagon_res sc7280_mss = {2189	.hexagon_mba_image = "mba.mbn",2190	.proxy_clk_names = (char*[]){2191		"xo",2192		"pka",2193		NULL2194	},2195	.active_clk_names = (char*[]){2196		"iface",2197		"offline",2198		"snoc_axi",2199		NULL2200	},2201	.proxy_pd_names = (char*[]){2202		"cx",2203		"mss",2204		NULL2205	},2206	.need_mem_protection = true,2207	.has_alt_reset = false,2208	.has_mba_logs = true,2209	.has_spare_reg = false,2210	.has_qaccept_regs = true,2211	.has_ext_cntl_regs = true,2212	.has_vq6 = true,2213	.version = MSS_SC7280,2214};2215 2216static const struct rproc_hexagon_res sdm660_mss = {2217	.hexagon_mba_image = "mba.mbn",2218	.proxy_clk_names = (char*[]){2219			"xo",2220			"qdss",2221			"mem",2222			NULL2223	},2224	.active_clk_names = (char*[]){2225			"iface",2226			"bus",2227			"gpll0_mss",2228			"mnoc_axi",2229			"snoc_axi",2230			NULL2231	},2232	.proxy_pd_names = (char*[]){2233			"cx",2234			"mx",2235			NULL2236	},2237	.need_mem_protection = true,2238	.has_alt_reset = false,2239	.has_mba_logs = false,2240	.has_spare_reg = false,2241	.has_qaccept_regs = false,2242	.has_ext_cntl_regs = false,2243	.has_vq6 = false,2244	.version = MSS_SDM660,2245};2246 2247static const struct rproc_hexagon_res sdm845_mss = {2248	.hexagon_mba_image = "mba.mbn",2249	.proxy_clk_names = (char*[]){2250			"xo",2251			"prng",2252			NULL2253	},2254	.reset_clk_names = (char*[]){2255			"iface",2256			"snoc_axi",2257			NULL2258	},2259	.active_clk_names = (char*[]){2260			"bus",2261			"mem",2262			"gpll0_mss",2263			"mnoc_axi",2264			NULL2265	},2266	.proxy_pd_names = (char*[]){2267			"cx",2268			"mx",2269			"mss",2270			NULL2271	},2272	.need_mem_protection = true,2273	.has_alt_reset = true,2274	.has_mba_logs = false,2275	.has_spare_reg = false,2276	.has_qaccept_regs = false,2277	.has_ext_cntl_regs = false,2278	.has_vq6 = false,2279	.version = MSS_SDM845,2280};2281 2282static const struct rproc_hexagon_res msm8998_mss = {2283	.hexagon_mba_image = "mba.mbn",2284	.proxy_clk_names = (char*[]){2285			"xo",2286			"qdss",2287			"mem",2288			NULL2289	},2290	.active_clk_names = (char*[]){2291			"iface",2292			"bus",2293			"gpll0_mss",2294			"mnoc_axi",2295			"snoc_axi",2296			NULL2297	},2298	.proxy_pd_names = (char*[]){2299			"cx",2300			"mx",2301			NULL2302	},2303	.need_mem_protection = true,2304	.has_alt_reset = false,2305	.has_mba_logs = false,2306	.has_spare_reg = false,2307	.has_qaccept_regs = false,2308	.has_ext_cntl_regs = false,2309	.has_vq6 = false,2310	.version = MSS_MSM8998,2311};2312 2313static const struct rproc_hexagon_res msm8996_mss = {2314	.hexagon_mba_image = "mba.mbn",2315	.proxy_supply = (struct qcom_mss_reg_res[]) {2316		{2317			.supply = "pll",2318			.uA = 100000,2319		},2320		{}2321	},2322	.proxy_clk_names = (char*[]){2323			"xo",2324			"qdss",2325			NULL2326	},2327	.active_clk_names = (char*[]){2328			"iface",2329			"bus",2330			"mem",2331			"gpll0_mss",2332			"snoc_axi",2333			"mnoc_axi",2334			NULL2335	},2336	.proxy_pd_names = (char*[]){2337			"mx",2338			"cx",2339			NULL2340	},2341	.need_mem_protection = true,2342	.has_alt_reset = false,2343	.has_mba_logs = false,2344	.has_spare_reg = false,2345	.has_qaccept_regs = false,2346	.has_ext_cntl_regs = false,2347	.has_vq6 = false,2348	.version = MSS_MSM8996,2349};2350 2351static const struct rproc_hexagon_res msm8909_mss = {2352	.hexagon_mba_image = "mba.mbn",2353	.proxy_supply = (struct qcom_mss_reg_res[]) {2354		{2355			.supply = "pll",2356			.uA = 100000,2357		},2358		{}2359	},2360	.proxy_clk_names = (char*[]){2361		"xo",2362		NULL2363	},2364	.active_clk_names = (char*[]){2365		"iface",2366		"bus",2367		"mem",2368		NULL2369	},2370	.proxy_pd_names = (char*[]){2371		"mx",2372		"cx",2373		NULL2374	},2375	.need_mem_protection = false,2376	.has_alt_reset = false,2377	.has_mba_logs = false,2378	.has_spare_reg = false,2379	.has_qaccept_regs = false,2380	.has_ext_cntl_regs = false,2381	.has_vq6 = false,2382	.version = MSS_MSM8909,2383};2384 2385static const struct rproc_hexagon_res msm8916_mss = {2386	.hexagon_mba_image = "mba.mbn",2387	.proxy_supply = (struct qcom_mss_reg_res[]) {2388		{2389			.supply = "pll",2390			.uA = 100000,2391		},2392		{}2393	},2394	.fallback_proxy_supply = (struct qcom_mss_reg_res[]) {2395		{2396			.supply = "mx",2397			.uV = 1050000,2398		},2399		{2400			.supply = "cx",2401			.uA = 100000,2402		},2403		{}2404	},2405	.proxy_clk_names = (char*[]){2406		"xo",2407		NULL2408	},2409	.active_clk_names = (char*[]){2410		"iface",2411		"bus",2412		"mem",2413		NULL2414	},2415	.proxy_pd_names = (char*[]){2416		"mx",2417		"cx",2418		NULL2419	},2420	.need_mem_protection = false,2421	.has_alt_reset = false,2422	.has_mba_logs = false,2423	.has_spare_reg = false,2424	.has_qaccept_regs = false,2425	.has_ext_cntl_regs = false,2426	.has_vq6 = false,2427	.version = MSS_MSM8916,2428};2429 2430static const struct rproc_hexagon_res msm8953_mss = {2431	.hexagon_mba_image = "mba.mbn",2432	.proxy_supply = (struct qcom_mss_reg_res[]) {2433		{2434			.supply = "pll",2435			.uA = 100000,2436		},2437		{}2438	},2439	.proxy_clk_names = (char*[]){2440		"xo",2441		NULL2442	},2443	.active_clk_names = (char*[]){2444		"iface",2445		"bus",2446		"mem",2447		NULL2448	},2449	.proxy_pd_names = (char*[]) {2450		"cx",2451		"mx",2452		"mss",2453		NULL2454	},2455	.need_mem_protection = false,2456	.has_alt_reset = false,2457	.has_mba_logs = false,2458	.has_spare_reg = false,2459	.has_qaccept_regs = false,2460	.has_ext_cntl_regs = false,2461	.has_vq6 = false,2462	.version = MSS_MSM8953,2463};2464 2465static const struct rproc_hexagon_res msm8974_mss = {2466	.hexagon_mba_image = "mba.b00",2467	.proxy_supply = (struct qcom_mss_reg_res[]) {2468		{2469			.supply = "pll",2470			.uA = 100000,2471		},2472		{}2473	},2474	.fallback_proxy_supply = (struct qcom_mss_reg_res[]) {2475		{2476			.supply = "mx",2477			.uV = 1050000,2478		},2479		{2480			.supply = "cx",2481			.uA = 100000,2482		},2483		{}2484	},2485	.active_supply = (struct qcom_mss_reg_res[]) {2486		{2487			.supply = "mss",2488			.uV = 1050000,2489			.uA = 100000,2490		},2491		{}2492	},2493	.proxy_clk_names = (char*[]){2494		"xo",2495		NULL2496	},2497	.active_clk_names = (char*[]){2498		"iface",2499		"bus",2500		"mem",2501		NULL2502	},2503	.proxy_pd_names = (char*[]){2504		"mx",2505		"cx",2506		NULL2507	},2508	.need_mem_protection = false,2509	.has_alt_reset = false,2510	.has_mba_logs = false,2511	.has_spare_reg = false,2512	.has_qaccept_regs = false,2513	.has_ext_cntl_regs = false,2514	.has_vq6 = false,2515	.version = MSS_MSM8974,2516};2517 2518static const struct of_device_id q6v5_of_match[] = {2519	{ .compatible = "qcom,q6v5-pil", .data = &msm8916_mss},2520	{ .compatible = "qcom,msm8909-mss-pil", .data = &msm8909_mss},2521	{ .compatible = "qcom,msm8916-mss-pil", .data = &msm8916_mss},2522	{ .compatible = "qcom,msm8953-mss-pil", .data = &msm8953_mss},2523	{ .compatible = "qcom,msm8974-mss-pil", .data = &msm8974_mss},2524	{ .compatible = "qcom,msm8996-mss-pil", .data = &msm8996_mss},2525	{ .compatible = "qcom,msm8998-mss-pil", .data = &msm8998_mss},2526	{ .compatible = "qcom,sc7180-mss-pil", .data = &sc7180_mss},2527	{ .compatible = "qcom,sc7280-mss-pil", .data = &sc7280_mss},2528	{ .compatible = "qcom,sdm660-mss-pil", .data = &sdm660_mss},2529	{ .compatible = "qcom,sdm845-mss-pil", .data = &sdm845_mss},2530	{ },2531};2532MODULE_DEVICE_TABLE(of, q6v5_of_match);2533 2534static struct platform_driver q6v5_driver = {2535	.probe = q6v5_probe,2536	.remove_new = q6v5_remove,2537	.driver = {2538		.name = "qcom-q6v5-mss",2539		.of_match_table = q6v5_of_match,2540	},2541};2542module_platform_driver(q6v5_driver);2543 2544MODULE_DESCRIPTION("Qualcomm Self-authenticating modem remoteproc driver");2545MODULE_LICENSE("GPL v2");2546