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