linux/drivers/remoteproc/qcom_q6v5_pil.c
<<
>>
Prefs
   1/*
   2 * Qualcomm Peripheral Image Loader
   3 *
   4 * Copyright (C) 2016 Linaro Ltd.
   5 * Copyright (C) 2014 Sony Mobile Communications AB
   6 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * version 2 as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 */
  17
  18#include <linux/clk.h>
  19#include <linux/delay.h>
  20#include <linux/dma-mapping.h>
  21#include <linux/interrupt.h>
  22#include <linux/kernel.h>
  23#include <linux/mfd/syscon.h>
  24#include <linux/module.h>
  25#include <linux/of_address.h>
  26#include <linux/of_device.h>
  27#include <linux/platform_device.h>
  28#include <linux/regmap.h>
  29#include <linux/regulator/consumer.h>
  30#include <linux/remoteproc.h>
  31#include <linux/reset.h>
  32#include <linux/soc/qcom/mdt_loader.h>
  33#include <linux/soc/qcom/smem.h>
  34#include <linux/soc/qcom/smem_state.h>
  35#include <linux/iopoll.h>
  36
  37#include "remoteproc_internal.h"
  38#include "qcom_common.h"
  39
  40#include <linux/qcom_scm.h>
  41
  42#define MPSS_CRASH_REASON_SMEM          421
  43
  44/* RMB Status Register Values */
  45#define RMB_PBL_SUCCESS                 0x1
  46
  47#define RMB_MBA_XPU_UNLOCKED            0x1
  48#define RMB_MBA_XPU_UNLOCKED_SCRIBBLED  0x2
  49#define RMB_MBA_META_DATA_AUTH_SUCCESS  0x3
  50#define RMB_MBA_AUTH_COMPLETE           0x4
  51
  52/* PBL/MBA interface registers */
  53#define RMB_MBA_IMAGE_REG               0x00
  54#define RMB_PBL_STATUS_REG              0x04
  55#define RMB_MBA_COMMAND_REG             0x08
  56#define RMB_MBA_STATUS_REG              0x0C
  57#define RMB_PMI_META_DATA_REG           0x10
  58#define RMB_PMI_CODE_START_REG          0x14
  59#define RMB_PMI_CODE_LENGTH_REG         0x18
  60#define RMB_MBA_MSS_STATUS              0x40
  61#define RMB_MBA_ALT_RESET               0x44
  62
  63#define RMB_CMD_META_DATA_READY         0x1
  64#define RMB_CMD_LOAD_READY              0x2
  65
  66/* QDSP6SS Register Offsets */
  67#define QDSP6SS_RESET_REG               0x014
  68#define QDSP6SS_GFMUX_CTL_REG           0x020
  69#define QDSP6SS_PWR_CTL_REG             0x030
  70#define QDSP6SS_MEM_PWR_CTL             0x0B0
  71#define QDSP6SS_STRAP_ACC               0x110
  72
  73/* AXI Halt Register Offsets */
  74#define AXI_HALTREQ_REG                 0x0
  75#define AXI_HALTACK_REG                 0x4
  76#define AXI_IDLE_REG                    0x8
  77
  78#define HALT_ACK_TIMEOUT_MS             100
  79
  80/* QDSP6SS_RESET */
  81#define Q6SS_STOP_CORE                  BIT(0)
  82#define Q6SS_CORE_ARES                  BIT(1)
  83#define Q6SS_BUS_ARES_ENABLE            BIT(2)
  84
  85/* QDSP6SS_GFMUX_CTL */
  86#define Q6SS_CLK_ENABLE                 BIT(1)
  87
  88/* QDSP6SS_PWR_CTL */
  89#define Q6SS_L2DATA_SLP_NRET_N_0        BIT(0)
  90#define Q6SS_L2DATA_SLP_NRET_N_1        BIT(1)
  91#define Q6SS_L2DATA_SLP_NRET_N_2        BIT(2)
  92#define Q6SS_L2TAG_SLP_NRET_N           BIT(16)
  93#define Q6SS_ETB_SLP_NRET_N             BIT(17)
  94#define Q6SS_L2DATA_STBY_N              BIT(18)
  95#define Q6SS_SLP_RET_N                  BIT(19)
  96#define Q6SS_CLAMP_IO                   BIT(20)
  97#define QDSS_BHS_ON                     BIT(21)
  98#define QDSS_LDO_BYP                    BIT(22)
  99
 100/* QDSP6v56 parameters */
 101#define QDSP6v56_LDO_BYP                BIT(25)
 102#define QDSP6v56_BHS_ON         BIT(24)
 103#define QDSP6v56_CLAMP_WL               BIT(21)
 104#define QDSP6v56_CLAMP_QMC_MEM          BIT(22)
 105#define HALT_CHECK_MAX_LOOPS            200
 106#define QDSP6SS_XO_CBCR         0x0038
 107#define QDSP6SS_ACC_OVERRIDE_VAL                0x20
 108
 109/* QDSP6v65 parameters */
 110#define QDSP6SS_SLEEP                   0x3C
 111#define QDSP6SS_BOOT_CORE_START         0x400
 112#define QDSP6SS_BOOT_CMD                0x404
 113#define SLEEP_CHECK_MAX_LOOPS           200
 114#define BOOT_FSM_TIMEOUT                10000
 115
 116struct reg_info {
 117        struct regulator *reg;
 118        int uV;
 119        int uA;
 120};
 121
 122struct qcom_mss_reg_res {
 123        const char *supply;
 124        int uV;
 125        int uA;
 126};
 127
 128struct rproc_hexagon_res {
 129        const char *hexagon_mba_image;
 130        struct qcom_mss_reg_res *proxy_supply;
 131        struct qcom_mss_reg_res *active_supply;
 132        char **proxy_clk_names;
 133        char **reset_clk_names;
 134        char **active_clk_names;
 135        int version;
 136        bool need_mem_protection;
 137        bool has_alt_reset;
 138};
 139
 140struct q6v5 {
 141        struct device *dev;
 142        struct rproc *rproc;
 143
 144        void __iomem *reg_base;
 145        void __iomem *rmb_base;
 146
 147        struct regmap *halt_map;
 148        u32 halt_q6;
 149        u32 halt_modem;
 150        u32 halt_nc;
 151
 152        struct reset_control *mss_restart;
 153
 154        struct qcom_smem_state *state;
 155        unsigned stop_bit;
 156
 157        int handover_irq;
 158
 159        bool proxy_unvoted;
 160
 161        struct clk *active_clks[8];
 162        struct clk *reset_clks[4];
 163        struct clk *proxy_clks[4];
 164        int active_clk_count;
 165        int reset_clk_count;
 166        int proxy_clk_count;
 167
 168        struct reg_info active_regs[1];
 169        struct reg_info proxy_regs[3];
 170        int active_reg_count;
 171        int proxy_reg_count;
 172
 173        struct completion start_done;
 174        struct completion stop_done;
 175        bool running;
 176
 177        phys_addr_t mba_phys;
 178        void *mba_region;
 179        size_t mba_size;
 180
 181        phys_addr_t mpss_phys;
 182        phys_addr_t mpss_reloc;
 183        void *mpss_region;
 184        size_t mpss_size;
 185
 186        struct qcom_rproc_glink glink_subdev;
 187        struct qcom_rproc_subdev smd_subdev;
 188        struct qcom_rproc_ssr ssr_subdev;
 189        struct qcom_sysmon *sysmon;
 190        bool need_mem_protection;
 191        bool has_alt_reset;
 192        int mpss_perm;
 193        int mba_perm;
 194        int version;
 195};
 196
 197enum {
 198        MSS_MSM8916,
 199        MSS_MSM8974,
 200        MSS_MSM8996,
 201        MSS_SDM845,
 202};
 203
 204static int q6v5_regulator_init(struct device *dev, struct reg_info *regs,
 205                               const struct qcom_mss_reg_res *reg_res)
 206{
 207        int rc;
 208        int i;
 209
 210        if (!reg_res)
 211                return 0;
 212
 213        for (i = 0; reg_res[i].supply; i++) {
 214                regs[i].reg = devm_regulator_get(dev, reg_res[i].supply);
 215                if (IS_ERR(regs[i].reg)) {
 216                        rc = PTR_ERR(regs[i].reg);
 217                        if (rc != -EPROBE_DEFER)
 218                                dev_err(dev, "Failed to get %s\n regulator",
 219                                        reg_res[i].supply);
 220                        return rc;
 221                }
 222
 223                regs[i].uV = reg_res[i].uV;
 224                regs[i].uA = reg_res[i].uA;
 225        }
 226
 227        return i;
 228}
 229
 230static int q6v5_regulator_enable(struct q6v5 *qproc,
 231                                 struct reg_info *regs, int count)
 232{
 233        int ret;
 234        int i;
 235
 236        for (i = 0; i < count; i++) {
 237                if (regs[i].uV > 0) {
 238                        ret = regulator_set_voltage(regs[i].reg,
 239                                        regs[i].uV, INT_MAX);
 240                        if (ret) {
 241                                dev_err(qproc->dev,
 242                                        "Failed to request voltage for %d.\n",
 243                                                i);
 244                                goto err;
 245                        }
 246                }
 247
 248                if (regs[i].uA > 0) {
 249                        ret = regulator_set_load(regs[i].reg,
 250                                                 regs[i].uA);
 251                        if (ret < 0) {
 252                                dev_err(qproc->dev,
 253                                        "Failed to set regulator mode\n");
 254                                goto err;
 255                        }
 256                }
 257
 258                ret = regulator_enable(regs[i].reg);
 259                if (ret) {
 260                        dev_err(qproc->dev, "Regulator enable failed\n");
 261                        goto err;
 262                }
 263        }
 264
 265        return 0;
 266err:
 267        for (; i >= 0; i--) {
 268                if (regs[i].uV > 0)
 269                        regulator_set_voltage(regs[i].reg, 0, INT_MAX);
 270
 271                if (regs[i].uA > 0)
 272                        regulator_set_load(regs[i].reg, 0);
 273
 274                regulator_disable(regs[i].reg);
 275        }
 276
 277        return ret;
 278}
 279
 280static void q6v5_regulator_disable(struct q6v5 *qproc,
 281                                   struct reg_info *regs, int count)
 282{
 283        int i;
 284
 285        for (i = 0; i < count; i++) {
 286                if (regs[i].uV > 0)
 287                        regulator_set_voltage(regs[i].reg, 0, INT_MAX);
 288
 289                if (regs[i].uA > 0)
 290                        regulator_set_load(regs[i].reg, 0);
 291
 292                regulator_disable(regs[i].reg);
 293        }
 294}
 295
 296static int q6v5_clk_enable(struct device *dev,
 297                           struct clk **clks, int count)
 298{
 299        int rc;
 300        int i;
 301
 302        for (i = 0; i < count; i++) {
 303                rc = clk_prepare_enable(clks[i]);
 304                if (rc) {
 305                        dev_err(dev, "Clock enable failed\n");
 306                        goto err;
 307                }
 308        }
 309
 310        return 0;
 311err:
 312        for (i--; i >= 0; i--)
 313                clk_disable_unprepare(clks[i]);
 314
 315        return rc;
 316}
 317
 318static void q6v5_clk_disable(struct device *dev,
 319                             struct clk **clks, int count)
 320{
 321        int i;
 322
 323        for (i = 0; i < count; i++)
 324                clk_disable_unprepare(clks[i]);
 325}
 326
 327static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm,
 328                                   bool remote_owner, phys_addr_t addr,
 329                                   size_t size)
 330{
 331        struct qcom_scm_vmperm next;
 332
 333        if (!qproc->need_mem_protection)
 334                return 0;
 335        if (remote_owner && *current_perm == BIT(QCOM_SCM_VMID_MSS_MSA))
 336                return 0;
 337        if (!remote_owner && *current_perm == BIT(QCOM_SCM_VMID_HLOS))
 338                return 0;
 339
 340        next.vmid = remote_owner ? QCOM_SCM_VMID_MSS_MSA : QCOM_SCM_VMID_HLOS;
 341        next.perm = remote_owner ? QCOM_SCM_PERM_RW : QCOM_SCM_PERM_RWX;
 342
 343        return qcom_scm_assign_mem(addr, ALIGN(size, SZ_4K),
 344                                   current_perm, &next, 1);
 345}
 346
 347static int q6v5_load(struct rproc *rproc, const struct firmware *fw)
 348{
 349        struct q6v5 *qproc = rproc->priv;
 350
 351        memcpy(qproc->mba_region, fw->data, fw->size);
 352
 353        return 0;
 354}
 355
 356static int q6v5_reset_assert(struct q6v5 *qproc)
 357{
 358        if (qproc->has_alt_reset)
 359                return reset_control_reset(qproc->mss_restart);
 360        else
 361                return reset_control_assert(qproc->mss_restart);
 362}
 363
 364static int q6v5_reset_deassert(struct q6v5 *qproc)
 365{
 366        int ret;
 367
 368        if (qproc->has_alt_reset) {
 369                writel(1, qproc->rmb_base + RMB_MBA_ALT_RESET);
 370                ret = reset_control_reset(qproc->mss_restart);
 371                writel(0, qproc->rmb_base + RMB_MBA_ALT_RESET);
 372        } else {
 373                ret = reset_control_deassert(qproc->mss_restart);
 374        }
 375
 376        return ret;
 377}
 378
 379static int q6v5_rmb_pbl_wait(struct q6v5 *qproc, int ms)
 380{
 381        unsigned long timeout;
 382        s32 val;
 383
 384        timeout = jiffies + msecs_to_jiffies(ms);
 385        for (;;) {
 386                val = readl(qproc->rmb_base + RMB_PBL_STATUS_REG);
 387                if (val)
 388                        break;
 389
 390                if (time_after(jiffies, timeout))
 391                        return -ETIMEDOUT;
 392
 393                msleep(1);
 394        }
 395
 396        return val;
 397}
 398
 399static int q6v5_rmb_mba_wait(struct q6v5 *qproc, u32 status, int ms)
 400{
 401
 402        unsigned long timeout;
 403        s32 val;
 404
 405        timeout = jiffies + msecs_to_jiffies(ms);
 406        for (;;) {
 407                val = readl(qproc->rmb_base + RMB_MBA_STATUS_REG);
 408                if (val < 0)
 409                        break;
 410
 411                if (!status && val)
 412                        break;
 413                else if (status && val == status)
 414                        break;
 415
 416                if (time_after(jiffies, timeout))
 417                        return -ETIMEDOUT;
 418
 419                msleep(1);
 420        }
 421
 422        return val;
 423}
 424
 425static int q6v5proc_reset(struct q6v5 *qproc)
 426{
 427        u32 val;
 428        int ret;
 429        int i;
 430
 431        if (qproc->version == MSS_SDM845) {
 432                val = readl(qproc->reg_base + QDSP6SS_SLEEP);
 433                val |= 0x1;
 434                writel(val, qproc->reg_base + QDSP6SS_SLEEP);
 435
 436                ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_SLEEP,
 437                                         val, !(val & BIT(31)), 1,
 438                                         SLEEP_CHECK_MAX_LOOPS);
 439                if (ret) {
 440                        dev_err(qproc->dev, "QDSP6SS Sleep clock timed out\n");
 441                        return -ETIMEDOUT;
 442                }
 443
 444                /* De-assert QDSP6 stop core */
 445                writel(1, qproc->reg_base + QDSP6SS_BOOT_CORE_START);
 446                /* Trigger boot FSM */
 447                writel(1, qproc->reg_base + QDSP6SS_BOOT_CMD);
 448
 449                ret = readl_poll_timeout(qproc->rmb_base + RMB_MBA_MSS_STATUS,
 450                                val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT);
 451                if (ret) {
 452                        dev_err(qproc->dev, "Boot FSM failed to complete.\n");
 453                        /* Reset the modem so that boot FSM is in reset state */
 454                        q6v5_reset_deassert(qproc);
 455                        return ret;
 456                }
 457
 458                goto pbl_wait;
 459        } else if (qproc->version == MSS_MSM8996) {
 460                /* Override the ACC value if required */
 461                writel(QDSP6SS_ACC_OVERRIDE_VAL,
 462                       qproc->reg_base + QDSP6SS_STRAP_ACC);
 463
 464                /* Assert resets, stop core */
 465                val = readl(qproc->reg_base + QDSP6SS_RESET_REG);
 466                val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE;
 467                writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
 468
 469                /* BHS require xo cbcr to be enabled */
 470                val = readl(qproc->reg_base + QDSP6SS_XO_CBCR);
 471                val |= 0x1;
 472                writel(val, qproc->reg_base + QDSP6SS_XO_CBCR);
 473
 474                /* Read CLKOFF bit to go low indicating CLK is enabled */
 475                ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_XO_CBCR,
 476                                         val, !(val & BIT(31)), 1,
 477                                         HALT_CHECK_MAX_LOOPS);
 478                if (ret) {
 479                        dev_err(qproc->dev,
 480                                "xo cbcr enabling timed out (rc:%d)\n", ret);
 481                        return ret;
 482                }
 483                /* Enable power block headswitch and wait for it to stabilize */
 484                val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 485                val |= QDSP6v56_BHS_ON;
 486                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 487                val |= readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 488                udelay(1);
 489
 490                /* Put LDO in bypass mode */
 491                val |= QDSP6v56_LDO_BYP;
 492                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 493
 494                /* Deassert QDSP6 compiler memory clamp */
 495                val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 496                val &= ~QDSP6v56_CLAMP_QMC_MEM;
 497                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 498
 499                /* Deassert memory peripheral sleep and L2 memory standby */
 500                val |= Q6SS_L2DATA_STBY_N | Q6SS_SLP_RET_N;
 501                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 502
 503                /* Turn on L1, L2, ETB and JU memories 1 at a time */
 504                val = readl(qproc->reg_base + QDSP6SS_MEM_PWR_CTL);
 505                for (i = 19; i >= 0; i--) {
 506                        val |= BIT(i);
 507                        writel(val, qproc->reg_base +
 508                                                QDSP6SS_MEM_PWR_CTL);
 509                        /*
 510                         * Read back value to ensure the write is done then
 511                         * wait for 1us for both memory peripheral and data
 512                         * array to turn on.
 513                         */
 514                        val |= readl(qproc->reg_base + QDSP6SS_MEM_PWR_CTL);
 515                        udelay(1);
 516                }
 517                /* Remove word line clamp */
 518                val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 519                val &= ~QDSP6v56_CLAMP_WL;
 520                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 521        } else {
 522                /* Assert resets, stop core */
 523                val = readl(qproc->reg_base + QDSP6SS_RESET_REG);
 524                val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE;
 525                writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
 526
 527                /* Enable power block headswitch and wait for it to stabilize */
 528                val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 529                val |= QDSS_BHS_ON | QDSS_LDO_BYP;
 530                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 531                val |= readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 532                udelay(1);
 533                /*
 534                 * Turn on memories. L2 banks should be done individually
 535                 * to minimize inrush current.
 536                 */
 537                val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 538                val |= Q6SS_SLP_RET_N | Q6SS_L2TAG_SLP_NRET_N |
 539                        Q6SS_ETB_SLP_NRET_N | Q6SS_L2DATA_STBY_N;
 540                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 541                val |= Q6SS_L2DATA_SLP_NRET_N_2;
 542                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 543                val |= Q6SS_L2DATA_SLP_NRET_N_1;
 544                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 545                val |= Q6SS_L2DATA_SLP_NRET_N_0;
 546                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 547        }
 548        /* Remove IO clamp */
 549        val &= ~Q6SS_CLAMP_IO;
 550        writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 551
 552        /* Bring core out of reset */
 553        val = readl(qproc->reg_base + QDSP6SS_RESET_REG);
 554        val &= ~Q6SS_CORE_ARES;
 555        writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
 556
 557        /* Turn on core clock */
 558        val = readl(qproc->reg_base + QDSP6SS_GFMUX_CTL_REG);
 559        val |= Q6SS_CLK_ENABLE;
 560        writel(val, qproc->reg_base + QDSP6SS_GFMUX_CTL_REG);
 561
 562        /* Start core execution */
 563        val = readl(qproc->reg_base + QDSP6SS_RESET_REG);
 564        val &= ~Q6SS_STOP_CORE;
 565        writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
 566
 567pbl_wait:
 568        /* Wait for PBL status */
 569        ret = q6v5_rmb_pbl_wait(qproc, 1000);
 570        if (ret == -ETIMEDOUT) {
 571                dev_err(qproc->dev, "PBL boot timed out\n");
 572        } else if (ret != RMB_PBL_SUCCESS) {
 573                dev_err(qproc->dev, "PBL returned unexpected status %d\n", ret);
 574                ret = -EINVAL;
 575        } else {
 576                ret = 0;
 577        }
 578
 579        return ret;
 580}
 581
 582static void q6v5proc_halt_axi_port(struct q6v5 *qproc,
 583                                   struct regmap *halt_map,
 584                                   u32 offset)
 585{
 586        unsigned long timeout;
 587        unsigned int val;
 588        int ret;
 589
 590        /* Check if we're already idle */
 591        ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
 592        if (!ret && val)
 593                return;
 594
 595        /* Assert halt request */
 596        regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1);
 597
 598        /* Wait for halt */
 599        timeout = jiffies + msecs_to_jiffies(HALT_ACK_TIMEOUT_MS);
 600        for (;;) {
 601                ret = regmap_read(halt_map, offset + AXI_HALTACK_REG, &val);
 602                if (ret || val || time_after(jiffies, timeout))
 603                        break;
 604
 605                msleep(1);
 606        }
 607
 608        ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val);
 609        if (ret || !val)
 610                dev_err(qproc->dev, "port failed halt\n");
 611
 612        /* Clear halt request (port will remain halted until reset) */
 613        regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0);
 614}
 615
 616static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
 617{
 618        unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
 619        dma_addr_t phys;
 620        int mdata_perm;
 621        int xferop_ret;
 622        void *ptr;
 623        int ret;
 624
 625        ptr = dma_alloc_attrs(qproc->dev, fw->size, &phys, GFP_KERNEL, dma_attrs);
 626        if (!ptr) {
 627                dev_err(qproc->dev, "failed to allocate mdt buffer\n");
 628                return -ENOMEM;
 629        }
 630
 631        memcpy(ptr, fw->data, fw->size);
 632
 633        /* Hypervisor mapping to access metadata by modem */
 634        mdata_perm = BIT(QCOM_SCM_VMID_HLOS);
 635        ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm,
 636                                      true, phys, fw->size);
 637        if (ret) {
 638                dev_err(qproc->dev,
 639                        "assigning Q6 access to metadata failed: %d\n", ret);
 640                ret = -EAGAIN;
 641                goto free_dma_attrs;
 642        }
 643
 644        writel(phys, qproc->rmb_base + RMB_PMI_META_DATA_REG);
 645        writel(RMB_CMD_META_DATA_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG);
 646
 647        ret = q6v5_rmb_mba_wait(qproc, RMB_MBA_META_DATA_AUTH_SUCCESS, 1000);
 648        if (ret == -ETIMEDOUT)
 649                dev_err(qproc->dev, "MPSS header authentication timed out\n");
 650        else if (ret < 0)
 651                dev_err(qproc->dev, "MPSS header authentication failed: %d\n", ret);
 652
 653        /* Metadata authentication done, remove modem access */
 654        xferop_ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm,
 655                                             false, phys, fw->size);
 656        if (xferop_ret)
 657                dev_warn(qproc->dev,
 658                         "mdt buffer not reclaimed system may become unstable\n");
 659
 660free_dma_attrs:
 661        dma_free_attrs(qproc->dev, fw->size, ptr, phys, dma_attrs);
 662
 663        return ret < 0 ? ret : 0;
 664}
 665
 666static bool q6v5_phdr_valid(const struct elf32_phdr *phdr)
 667{
 668        if (phdr->p_type != PT_LOAD)
 669                return false;
 670
 671        if ((phdr->p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH)
 672                return false;
 673
 674        if (!phdr->p_memsz)
 675                return false;
 676
 677        return true;
 678}
 679
 680static int q6v5_mpss_load(struct q6v5 *qproc)
 681{
 682        const struct elf32_phdr *phdrs;
 683        const struct elf32_phdr *phdr;
 684        const struct firmware *seg_fw;
 685        const struct firmware *fw;
 686        struct elf32_hdr *ehdr;
 687        phys_addr_t mpss_reloc;
 688        phys_addr_t boot_addr;
 689        phys_addr_t min_addr = PHYS_ADDR_MAX;
 690        phys_addr_t max_addr = 0;
 691        bool relocate = false;
 692        char seg_name[10];
 693        ssize_t offset;
 694        size_t size = 0;
 695        void *ptr;
 696        int ret;
 697        int i;
 698
 699        ret = request_firmware(&fw, "modem.mdt", qproc->dev);
 700        if (ret < 0) {
 701                dev_err(qproc->dev, "unable to load modem.mdt\n");
 702                return ret;
 703        }
 704
 705        /* Initialize the RMB validator */
 706        writel(0, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);
 707
 708        ret = q6v5_mpss_init_image(qproc, fw);
 709        if (ret)
 710                goto release_firmware;
 711
 712        ehdr = (struct elf32_hdr *)fw->data;
 713        phdrs = (struct elf32_phdr *)(ehdr + 1);
 714
 715        for (i = 0; i < ehdr->e_phnum; i++) {
 716                phdr = &phdrs[i];
 717
 718                if (!q6v5_phdr_valid(phdr))
 719                        continue;
 720
 721                if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
 722                        relocate = true;
 723
 724                if (phdr->p_paddr < min_addr)
 725                        min_addr = phdr->p_paddr;
 726
 727                if (phdr->p_paddr + phdr->p_memsz > max_addr)
 728                        max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K);
 729        }
 730
 731        mpss_reloc = relocate ? min_addr : qproc->mpss_phys;
 732        /* Load firmware segments */
 733        for (i = 0; i < ehdr->e_phnum; i++) {
 734                phdr = &phdrs[i];
 735
 736                if (!q6v5_phdr_valid(phdr))
 737                        continue;
 738
 739                offset = phdr->p_paddr - mpss_reloc;
 740                if (offset < 0 || offset + phdr->p_memsz > qproc->mpss_size) {
 741                        dev_err(qproc->dev, "segment outside memory range\n");
 742                        ret = -EINVAL;
 743                        goto release_firmware;
 744                }
 745
 746                ptr = qproc->mpss_region + offset;
 747
 748                if (phdr->p_filesz) {
 749                        snprintf(seg_name, sizeof(seg_name), "modem.b%02d", i);
 750                        ret = request_firmware(&seg_fw, seg_name, qproc->dev);
 751                        if (ret) {
 752                                dev_err(qproc->dev, "failed to load %s\n", seg_name);
 753                                goto release_firmware;
 754                        }
 755
 756                        memcpy(ptr, seg_fw->data, seg_fw->size);
 757
 758                        release_firmware(seg_fw);
 759                }
 760
 761                if (phdr->p_memsz > phdr->p_filesz) {
 762                        memset(ptr + phdr->p_filesz, 0,
 763                               phdr->p_memsz - phdr->p_filesz);
 764                }
 765                size += phdr->p_memsz;
 766        }
 767
 768        /* Transfer ownership of modem ddr region to q6 */
 769        ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, true,
 770                                      qproc->mpss_phys, qproc->mpss_size);
 771        if (ret) {
 772                dev_err(qproc->dev,
 773                        "assigning Q6 access to mpss memory failed: %d\n", ret);
 774                ret = -EAGAIN;
 775                goto release_firmware;
 776        }
 777
 778        boot_addr = relocate ? qproc->mpss_phys : min_addr;
 779        writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG);
 780        writel(RMB_CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG);
 781        writel(size, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);
 782
 783        ret = q6v5_rmb_mba_wait(qproc, RMB_MBA_AUTH_COMPLETE, 10000);
 784        if (ret == -ETIMEDOUT)
 785                dev_err(qproc->dev, "MPSS authentication timed out\n");
 786        else if (ret < 0)
 787                dev_err(qproc->dev, "MPSS authentication failed: %d\n", ret);
 788
 789release_firmware:
 790        release_firmware(fw);
 791
 792        return ret < 0 ? ret : 0;
 793}
 794
 795static int q6v5_start(struct rproc *rproc)
 796{
 797        struct q6v5 *qproc = (struct q6v5 *)rproc->priv;
 798        int xfermemop_ret;
 799        int ret;
 800
 801        qproc->proxy_unvoted = false;
 802
 803        enable_irq(qproc->handover_irq);
 804
 805        ret = q6v5_regulator_enable(qproc, qproc->proxy_regs,
 806                                    qproc->proxy_reg_count);
 807        if (ret) {
 808                dev_err(qproc->dev, "failed to enable proxy supplies\n");
 809                goto disable_irqs;
 810        }
 811
 812        ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks,
 813                              qproc->proxy_clk_count);
 814        if (ret) {
 815                dev_err(qproc->dev, "failed to enable proxy clocks\n");
 816                goto disable_proxy_reg;
 817        }
 818
 819        ret = q6v5_regulator_enable(qproc, qproc->active_regs,
 820                                    qproc->active_reg_count);
 821        if (ret) {
 822                dev_err(qproc->dev, "failed to enable supplies\n");
 823                goto disable_proxy_clk;
 824        }
 825
 826        ret = q6v5_clk_enable(qproc->dev, qproc->reset_clks,
 827                              qproc->reset_clk_count);
 828        if (ret) {
 829                dev_err(qproc->dev, "failed to enable reset clocks\n");
 830                goto disable_vdd;
 831        }
 832
 833        ret = q6v5_reset_deassert(qproc);
 834        if (ret) {
 835                dev_err(qproc->dev, "failed to deassert mss restart\n");
 836                goto disable_reset_clks;
 837        }
 838
 839        ret = q6v5_clk_enable(qproc->dev, qproc->active_clks,
 840                              qproc->active_clk_count);
 841        if (ret) {
 842                dev_err(qproc->dev, "failed to enable clocks\n");
 843                goto assert_reset;
 844        }
 845
 846        /* Assign MBA image access in DDR to q6 */
 847        ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true,
 848                                      qproc->mba_phys, qproc->mba_size);
 849        if (ret) {
 850                dev_err(qproc->dev,
 851                        "assigning Q6 access to mba memory failed: %d\n", ret);
 852                goto disable_active_clks;
 853        }
 854
 855        writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG);
 856
 857        ret = q6v5proc_reset(qproc);
 858        if (ret)
 859                goto reclaim_mba;
 860
 861        ret = q6v5_rmb_mba_wait(qproc, 0, 5000);
 862        if (ret == -ETIMEDOUT) {
 863                dev_err(qproc->dev, "MBA boot timed out\n");
 864                goto halt_axi_ports;
 865        } else if (ret != RMB_MBA_XPU_UNLOCKED &&
 866                   ret != RMB_MBA_XPU_UNLOCKED_SCRIBBLED) {
 867                dev_err(qproc->dev, "MBA returned unexpected status %d\n", ret);
 868                ret = -EINVAL;
 869                goto halt_axi_ports;
 870        }
 871
 872        dev_info(qproc->dev, "MBA booted, loading mpss\n");
 873
 874        ret = q6v5_mpss_load(qproc);
 875        if (ret)
 876                goto reclaim_mpss;
 877
 878        ret = wait_for_completion_timeout(&qproc->start_done,
 879                                          msecs_to_jiffies(5000));
 880        if (ret == 0) {
 881                dev_err(qproc->dev, "start timed out\n");
 882                ret = -ETIMEDOUT;
 883                goto reclaim_mpss;
 884        }
 885
 886        xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, false,
 887                                                qproc->mba_phys,
 888                                                qproc->mba_size);
 889        if (xfermemop_ret)
 890                dev_err(qproc->dev,
 891                        "Failed to reclaim mba buffer system may become unstable\n");
 892        qproc->running = true;
 893
 894        return 0;
 895
 896reclaim_mpss:
 897        xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm,
 898                                                false, qproc->mpss_phys,
 899                                                qproc->mpss_size);
 900        WARN_ON(xfermemop_ret);
 901
 902halt_axi_ports:
 903        q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6);
 904        q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);
 905        q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);
 906
 907reclaim_mba:
 908        xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, false,
 909                                                qproc->mba_phys,
 910                                                qproc->mba_size);
 911        if (xfermemop_ret) {
 912                dev_err(qproc->dev,
 913                        "Failed to reclaim mba buffer, system may become unstable\n");
 914        }
 915
 916disable_active_clks:
 917        q6v5_clk_disable(qproc->dev, qproc->active_clks,
 918                         qproc->active_clk_count);
 919
 920assert_reset:
 921        q6v5_reset_assert(qproc);
 922disable_reset_clks:
 923        q6v5_clk_disable(qproc->dev, qproc->reset_clks,
 924                         qproc->reset_clk_count);
 925disable_vdd:
 926        q6v5_regulator_disable(qproc, qproc->active_regs,
 927                               qproc->active_reg_count);
 928disable_proxy_clk:
 929        q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
 930                         qproc->proxy_clk_count);
 931disable_proxy_reg:
 932        q6v5_regulator_disable(qproc, qproc->proxy_regs,
 933                               qproc->proxy_reg_count);
 934
 935disable_irqs:
 936        disable_irq(qproc->handover_irq);
 937
 938        return ret;
 939}
 940
 941static int q6v5_stop(struct rproc *rproc)
 942{
 943        struct q6v5 *qproc = (struct q6v5 *)rproc->priv;
 944        int ret;
 945        u32 val;
 946
 947        qproc->running = false;
 948
 949        qcom_smem_state_update_bits(qproc->state,
 950                                    BIT(qproc->stop_bit), BIT(qproc->stop_bit));
 951
 952        ret = wait_for_completion_timeout(&qproc->stop_done,
 953                                          msecs_to_jiffies(5000));
 954        if (ret == 0)
 955                dev_err(qproc->dev, "timed out on wait\n");
 956
 957        qcom_smem_state_update_bits(qproc->state, BIT(qproc->stop_bit), 0);
 958
 959        q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6);
 960        q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);
 961        q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);
 962        if (qproc->version == MSS_MSM8996) {
 963                /*
 964                 * To avoid high MX current during LPASS/MSS restart.
 965                 */
 966                val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 967                val |= Q6SS_CLAMP_IO | QDSP6v56_CLAMP_WL |
 968                        QDSP6v56_CLAMP_QMC_MEM;
 969                writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 970        }
 971
 972
 973        ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, false,
 974                                      qproc->mpss_phys, qproc->mpss_size);
 975        WARN_ON(ret);
 976
 977        q6v5_reset_assert(qproc);
 978
 979        disable_irq(qproc->handover_irq);
 980
 981        if (!qproc->proxy_unvoted) {
 982                q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
 983                                 qproc->proxy_clk_count);
 984                q6v5_regulator_disable(qproc, qproc->proxy_regs,
 985                                       qproc->proxy_reg_count);
 986        }
 987
 988        q6v5_clk_disable(qproc->dev, qproc->reset_clks,
 989                         qproc->reset_clk_count);
 990        q6v5_clk_disable(qproc->dev, qproc->active_clks,
 991                         qproc->active_clk_count);
 992        q6v5_regulator_disable(qproc, qproc->active_regs,
 993                               qproc->active_reg_count);
 994
 995        return 0;
 996}
 997
 998static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
 999{
1000        struct q6v5 *qproc = rproc->priv;
1001        int offset;
1002
1003        offset = da - qproc->mpss_reloc;
1004        if (offset < 0 || offset + len > qproc->mpss_size)
1005                return NULL;
1006
1007        return qproc->mpss_region + offset;
1008}
1009
1010static const struct rproc_ops q6v5_ops = {
1011        .start = q6v5_start,
1012        .stop = q6v5_stop,
1013        .da_to_va = q6v5_da_to_va,
1014        .load = q6v5_load,
1015};
1016
1017static irqreturn_t q6v5_wdog_interrupt(int irq, void *dev)
1018{
1019        struct q6v5 *qproc = dev;
1020        size_t len;
1021        char *msg;
1022
1023        /* Sometimes the stop triggers a watchdog rather than a stop-ack */
1024        if (!qproc->running) {
1025                complete(&qproc->stop_done);
1026                return IRQ_HANDLED;
1027        }
1028
1029        msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, MPSS_CRASH_REASON_SMEM, &len);
1030        if (!IS_ERR(msg) && len > 0 && msg[0])
1031                dev_err(qproc->dev, "watchdog received: %s\n", msg);
1032        else
1033                dev_err(qproc->dev, "watchdog without message\n");
1034
1035        rproc_report_crash(qproc->rproc, RPROC_WATCHDOG);
1036
1037        return IRQ_HANDLED;
1038}
1039
1040static irqreturn_t q6v5_fatal_interrupt(int irq, void *dev)
1041{
1042        struct q6v5 *qproc = dev;
1043        size_t len;
1044        char *msg;
1045
1046        msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, MPSS_CRASH_REASON_SMEM, &len);
1047        if (!IS_ERR(msg) && len > 0 && msg[0])
1048                dev_err(qproc->dev, "fatal error received: %s\n", msg);
1049        else
1050                dev_err(qproc->dev, "fatal error without message\n");
1051
1052        rproc_report_crash(qproc->rproc, RPROC_FATAL_ERROR);
1053
1054        return IRQ_HANDLED;
1055}
1056
1057static irqreturn_t q6v5_ready_interrupt(int irq, void *dev)
1058{
1059        struct q6v5 *qproc = dev;
1060
1061        complete(&qproc->start_done);
1062        return IRQ_HANDLED;
1063}
1064
1065static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
1066{
1067        struct q6v5 *qproc = dev;
1068
1069        q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
1070                         qproc->proxy_clk_count);
1071        q6v5_regulator_disable(qproc, qproc->proxy_regs,
1072                               qproc->proxy_reg_count);
1073
1074        qproc->proxy_unvoted = true;
1075
1076        return IRQ_HANDLED;
1077}
1078
1079static irqreturn_t q6v5_stop_ack_interrupt(int irq, void *dev)
1080{
1081        struct q6v5 *qproc = dev;
1082
1083        complete(&qproc->stop_done);
1084        return IRQ_HANDLED;
1085}
1086
1087static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev)
1088{
1089        struct of_phandle_args args;
1090        struct resource *res;
1091        int ret;
1092
1093        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6");
1094        qproc->reg_base = devm_ioremap_resource(&pdev->dev, res);
1095        if (IS_ERR(qproc->reg_base))
1096                return PTR_ERR(qproc->reg_base);
1097
1098        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb");
1099        qproc->rmb_base = devm_ioremap_resource(&pdev->dev, res);
1100        if (IS_ERR(qproc->rmb_base))
1101                return PTR_ERR(qproc->rmb_base);
1102
1103        ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
1104                                               "qcom,halt-regs", 3, 0, &args);
1105        if (ret < 0) {
1106                dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
1107                return -EINVAL;
1108        }
1109
1110        qproc->halt_map = syscon_node_to_regmap(args.np);
1111        of_node_put(args.np);
1112        if (IS_ERR(qproc->halt_map))
1113                return PTR_ERR(qproc->halt_map);
1114
1115        qproc->halt_q6 = args.args[0];
1116        qproc->halt_modem = args.args[1];
1117        qproc->halt_nc = args.args[2];
1118
1119        return 0;
1120}
1121
1122static int q6v5_init_clocks(struct device *dev, struct clk **clks,
1123                char **clk_names)
1124{
1125        int i;
1126
1127        if (!clk_names)
1128                return 0;
1129
1130        for (i = 0; clk_names[i]; i++) {
1131                clks[i] = devm_clk_get(dev, clk_names[i]);
1132                if (IS_ERR(clks[i])) {
1133                        int rc = PTR_ERR(clks[i]);
1134
1135                        if (rc != -EPROBE_DEFER)
1136                                dev_err(dev, "Failed to get %s clock\n",
1137                                        clk_names[i]);
1138                        return rc;
1139                }
1140        }
1141
1142        return i;
1143}
1144
1145static int q6v5_init_reset(struct q6v5 *qproc)
1146{
1147        qproc->mss_restart = devm_reset_control_get_exclusive(qproc->dev,
1148                                                              NULL);
1149        if (IS_ERR(qproc->mss_restart)) {
1150                dev_err(qproc->dev, "failed to acquire mss restart\n");
1151                return PTR_ERR(qproc->mss_restart);
1152        }
1153
1154        return 0;
1155}
1156
1157static int q6v5_request_irq(struct q6v5 *qproc,
1158                             struct platform_device *pdev,
1159                             const char *name,
1160                             irq_handler_t thread_fn)
1161{
1162        int irq;
1163        int ret;
1164
1165        irq = platform_get_irq_byname(pdev, name);
1166        if (irq < 0) {
1167                dev_err(&pdev->dev, "no %s IRQ defined\n", name);
1168                return irq;
1169        }
1170
1171        ret = devm_request_threaded_irq(&pdev->dev, irq,
1172                                        NULL, thread_fn,
1173                                        IRQF_TRIGGER_RISING | IRQF_ONESHOT,
1174                                        "q6v5", qproc);
1175        if (ret)
1176                dev_err(&pdev->dev, "request %s IRQ failed\n", name);
1177
1178        return ret ? : irq;
1179}
1180
1181static int q6v5_alloc_memory_region(struct q6v5 *qproc)
1182{
1183        struct device_node *child;
1184        struct device_node *node;
1185        struct resource r;
1186        int ret;
1187
1188        child = of_get_child_by_name(qproc->dev->of_node, "mba");
1189        node = of_parse_phandle(child, "memory-region", 0);
1190        ret = of_address_to_resource(node, 0, &r);
1191        if (ret) {
1192                dev_err(qproc->dev, "unable to resolve mba region\n");
1193                return ret;
1194        }
1195        of_node_put(node);
1196
1197        qproc->mba_phys = r.start;
1198        qproc->mba_size = resource_size(&r);
1199        qproc->mba_region = devm_ioremap_wc(qproc->dev, qproc->mba_phys, qproc->mba_size);
1200        if (!qproc->mba_region) {
1201                dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n",
1202                        &r.start, qproc->mba_size);
1203                return -EBUSY;
1204        }
1205
1206        child = of_get_child_by_name(qproc->dev->of_node, "mpss");
1207        node = of_parse_phandle(child, "memory-region", 0);
1208        ret = of_address_to_resource(node, 0, &r);
1209        if (ret) {
1210                dev_err(qproc->dev, "unable to resolve mpss region\n");
1211                return ret;
1212        }
1213        of_node_put(node);
1214
1215        qproc->mpss_phys = qproc->mpss_reloc = r.start;
1216        qproc->mpss_size = resource_size(&r);
1217        qproc->mpss_region = devm_ioremap_wc(qproc->dev, qproc->mpss_phys, qproc->mpss_size);
1218        if (!qproc->mpss_region) {
1219                dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n",
1220                        &r.start, qproc->mpss_size);
1221                return -EBUSY;
1222        }
1223
1224        return 0;
1225}
1226
1227static int q6v5_probe(struct platform_device *pdev)
1228{
1229        const struct rproc_hexagon_res *desc;
1230        struct q6v5 *qproc;
1231        struct rproc *rproc;
1232        int ret;
1233
1234        desc = of_device_get_match_data(&pdev->dev);
1235        if (!desc)
1236                return -EINVAL;
1237
1238        rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_ops,
1239                            desc->hexagon_mba_image, sizeof(*qproc));
1240        if (!rproc) {
1241                dev_err(&pdev->dev, "failed to allocate rproc\n");
1242                return -ENOMEM;
1243        }
1244
1245        qproc = (struct q6v5 *)rproc->priv;
1246        qproc->dev = &pdev->dev;
1247        qproc->rproc = rproc;
1248        platform_set_drvdata(pdev, qproc);
1249
1250        init_completion(&qproc->start_done);
1251        init_completion(&qproc->stop_done);
1252
1253        ret = q6v5_init_mem(qproc, pdev);
1254        if (ret)
1255                goto free_rproc;
1256
1257        ret = q6v5_alloc_memory_region(qproc);
1258        if (ret)
1259                goto free_rproc;
1260
1261        ret = q6v5_init_clocks(&pdev->dev, qproc->proxy_clks,
1262                               desc->proxy_clk_names);
1263        if (ret < 0) {
1264                dev_err(&pdev->dev, "Failed to get proxy clocks.\n");
1265                goto free_rproc;
1266        }
1267        qproc->proxy_clk_count = ret;
1268
1269        ret = q6v5_init_clocks(&pdev->dev, qproc->reset_clks,
1270                               desc->reset_clk_names);
1271        if (ret < 0) {
1272                dev_err(&pdev->dev, "Failed to get reset clocks.\n");
1273                goto free_rproc;
1274        }
1275        qproc->reset_clk_count = ret;
1276
1277        ret = q6v5_init_clocks(&pdev->dev, qproc->active_clks,
1278                               desc->active_clk_names);
1279        if (ret < 0) {
1280                dev_err(&pdev->dev, "Failed to get active clocks.\n");
1281                goto free_rproc;
1282        }
1283        qproc->active_clk_count = ret;
1284
1285        ret = q6v5_regulator_init(&pdev->dev, qproc->proxy_regs,
1286                                  desc->proxy_supply);
1287        if (ret < 0) {
1288                dev_err(&pdev->dev, "Failed to get proxy regulators.\n");
1289                goto free_rproc;
1290        }
1291        qproc->proxy_reg_count = ret;
1292
1293        ret = q6v5_regulator_init(&pdev->dev,  qproc->active_regs,
1294                                  desc->active_supply);
1295        if (ret < 0) {
1296                dev_err(&pdev->dev, "Failed to get active regulators.\n");
1297                goto free_rproc;
1298        }
1299        qproc->active_reg_count = ret;
1300
1301        ret = q6v5_init_reset(qproc);
1302        if (ret)
1303                goto free_rproc;
1304
1305        qproc->version = desc->version;
1306        qproc->has_alt_reset = desc->has_alt_reset;
1307        qproc->need_mem_protection = desc->need_mem_protection;
1308        ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt);
1309        if (ret < 0)
1310                goto free_rproc;
1311
1312        ret = q6v5_request_irq(qproc, pdev, "fatal", q6v5_fatal_interrupt);
1313        if (ret < 0)
1314                goto free_rproc;
1315
1316        ret = q6v5_request_irq(qproc, pdev, "ready", q6v5_ready_interrupt);
1317        if (ret < 0)
1318                goto free_rproc;
1319
1320        ret = q6v5_request_irq(qproc, pdev, "handover", q6v5_handover_interrupt);
1321        if (ret < 0)
1322                goto free_rproc;
1323        qproc->handover_irq = ret;
1324        disable_irq(qproc->handover_irq);
1325
1326        ret = q6v5_request_irq(qproc, pdev, "stop-ack", q6v5_stop_ack_interrupt);
1327        if (ret < 0)
1328                goto free_rproc;
1329
1330        qproc->state = qcom_smem_state_get(&pdev->dev, "stop", &qproc->stop_bit);
1331        if (IS_ERR(qproc->state)) {
1332                ret = PTR_ERR(qproc->state);
1333                goto free_rproc;
1334        }
1335        qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS);
1336        qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
1337        qcom_add_glink_subdev(rproc, &qproc->glink_subdev);
1338        qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
1339        qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
1340        qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
1341
1342        ret = rproc_add(rproc);
1343        if (ret)
1344                goto free_rproc;
1345
1346        return 0;
1347
1348free_rproc:
1349        rproc_free(rproc);
1350
1351        return ret;
1352}
1353
1354static int q6v5_remove(struct platform_device *pdev)
1355{
1356        struct q6v5 *qproc = platform_get_drvdata(pdev);
1357
1358        rproc_del(qproc->rproc);
1359
1360        qcom_remove_sysmon_subdev(qproc->sysmon);
1361        qcom_remove_glink_subdev(qproc->rproc, &qproc->glink_subdev);
1362        qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev);
1363        qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev);
1364        rproc_free(qproc->rproc);
1365
1366        return 0;
1367}
1368
1369static const struct rproc_hexagon_res sdm845_mss = {
1370        .hexagon_mba_image = "mba.mbn",
1371        .proxy_clk_names = (char*[]){
1372                        "xo",
1373                        "axis2",
1374                        "prng",
1375                        NULL
1376        },
1377        .reset_clk_names = (char*[]){
1378                        "iface",
1379                        "snoc_axi",
1380                        NULL
1381        },
1382        .active_clk_names = (char*[]){
1383                        "bus",
1384                        "mem",
1385                        "gpll0_mss",
1386                        "mnoc_axi",
1387                        NULL
1388        },
1389        .need_mem_protection = true,
1390        .has_alt_reset = true,
1391        .version = MSS_SDM845,
1392};
1393
1394static const struct rproc_hexagon_res msm8996_mss = {
1395        .hexagon_mba_image = "mba.mbn",
1396        .proxy_clk_names = (char*[]){
1397                        "xo",
1398                        "pnoc",
1399                        NULL
1400        },
1401        .active_clk_names = (char*[]){
1402                        "iface",
1403                        "bus",
1404                        "mem",
1405                        "gpll0_mss_clk",
1406                        NULL
1407        },
1408        .need_mem_protection = true,
1409        .has_alt_reset = false,
1410        .version = MSS_MSM8996,
1411};
1412
1413static const struct rproc_hexagon_res msm8916_mss = {
1414        .hexagon_mba_image = "mba.mbn",
1415        .proxy_supply = (struct qcom_mss_reg_res[]) {
1416                {
1417                        .supply = "mx",
1418                        .uV = 1050000,
1419                },
1420                {
1421                        .supply = "cx",
1422                        .uA = 100000,
1423                },
1424                {
1425                        .supply = "pll",
1426                        .uA = 100000,
1427                },
1428                {}
1429        },
1430        .proxy_clk_names = (char*[]){
1431                "xo",
1432                NULL
1433        },
1434        .active_clk_names = (char*[]){
1435                "iface",
1436                "bus",
1437                "mem",
1438                NULL
1439        },
1440        .need_mem_protection = false,
1441        .has_alt_reset = false,
1442        .version = MSS_MSM8916,
1443};
1444
1445static const struct rproc_hexagon_res msm8974_mss = {
1446        .hexagon_mba_image = "mba.b00",
1447        .proxy_supply = (struct qcom_mss_reg_res[]) {
1448                {
1449                        .supply = "mx",
1450                        .uV = 1050000,
1451                },
1452                {
1453                        .supply = "cx",
1454                        .uA = 100000,
1455                },
1456                {
1457                        .supply = "pll",
1458                        .uA = 100000,
1459                },
1460                {}
1461        },
1462        .active_supply = (struct qcom_mss_reg_res[]) {
1463                {
1464                        .supply = "mss",
1465                        .uV = 1050000,
1466                        .uA = 100000,
1467                },
1468                {}
1469        },
1470        .proxy_clk_names = (char*[]){
1471                "xo",
1472                NULL
1473        },
1474        .active_clk_names = (char*[]){
1475                "iface",
1476                "bus",
1477                "mem",
1478                NULL
1479        },
1480        .need_mem_protection = false,
1481        .has_alt_reset = false,
1482        .version = MSS_MSM8974,
1483};
1484
1485static const struct of_device_id q6v5_of_match[] = {
1486        { .compatible = "qcom,q6v5-pil", .data = &msm8916_mss},
1487        { .compatible = "qcom,msm8916-mss-pil", .data = &msm8916_mss},
1488        { .compatible = "qcom,msm8974-mss-pil", .data = &msm8974_mss},
1489        { .compatible = "qcom,msm8996-mss-pil", .data = &msm8996_mss},
1490        { .compatible = "qcom,sdm845-mss-pil", .data = &sdm845_mss},
1491        { },
1492};
1493MODULE_DEVICE_TABLE(of, q6v5_of_match);
1494
1495static struct platform_driver q6v5_driver = {
1496        .probe = q6v5_probe,
1497        .remove = q6v5_remove,
1498        .driver = {
1499                .name = "qcom-q6v5-pil",
1500                .of_match_table = q6v5_of_match,
1501        },
1502};
1503module_platform_driver(q6v5_driver);
1504
1505MODULE_DESCRIPTION("Peripheral Image Loader for Hexagon");
1506MODULE_LICENSE("GPL v2");
1507