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