File Index
Files and directories
Sign in
FILE

qcom_q6v5_mss.c

File preview with syntax highlighting.

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