#include "qcom_common.h"
 #include "qcom_q6v5.h"
 
+#define Q6V5_LOAD_STATE_MSG_LEN        64
 #define Q6V5_PANIC_DELAY_MS    200
 
+static int q6v5_load_state_toggle(struct qcom_q6v5 *q6v5, bool enable)
+{
+       char buf[Q6V5_LOAD_STATE_MSG_LEN];
+       int ret;
+
+       if (!q6v5->qmp)
+               return 0;
+
+       ret = snprintf(buf, sizeof(buf),
+                      "{class: image, res: load_state, name: %s, val: %s}",
+                      q6v5->load_state, enable ? "on" : "off");
+
+       WARN_ON(ret >= Q6V5_LOAD_STATE_MSG_LEN);
+
+       ret = qmp_send(q6v5->qmp, buf, sizeof(buf));
+       if (ret)
+               dev_err(q6v5->dev, "failed to toggle load state\n");
+
+       return ret;
+}
+
 /**
  * qcom_q6v5_prepare() - reinitialize the qcom_q6v5 context before start
  * @q6v5:      reference to qcom_q6v5 context to be reinitialized
  */
 int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5)
 {
+       int ret;
+
+       ret = q6v5_load_state_toggle(q6v5, true);
+       if (ret)
+               return ret;
+
        reinit_completion(&q6v5->start_done);
        reinit_completion(&q6v5->stop_done);
 
 int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5)
 {
        disable_irq(q6v5->handover_irq);
+       q6v5_load_state_toggle(q6v5, false);
 
        return !q6v5->handover_issued;
 }
  * @pdev:      platform_device reference for acquiring resources
  * @rproc:     associated remoteproc instance
  * @crash_reason: SMEM id for crash reason string, or 0 if none
+ * @load_state: load state resource string
  * @handover:  function to be called when proxy resources should be released
  *
  * Return: 0 on success, negative errno on failure
  */
 int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev,
-                  struct rproc *rproc, int crash_reason,
+                  struct rproc *rproc, int crash_reason, const char *load_state,
                   void (*handover)(struct qcom_q6v5 *q6v5))
 {
        int ret;
                return PTR_ERR(q6v5->state);
        }
 
+       q6v5->load_state = devm_kstrdup_const(&pdev->dev, load_state, GFP_KERNEL);
+       q6v5->qmp = qmp_get(&pdev->dev);
+       if (IS_ERR(q6v5->qmp)) {
+               if (PTR_ERR(q6v5->qmp) != -ENODEV)
+                       return dev_err_probe(&pdev->dev, PTR_ERR(q6v5->qmp),
+                                            "failed to acquire load state\n");
+               q6v5->qmp = NULL;
+       } else if (!q6v5->load_state) {
+               if (!load_state)
+                       dev_err(&pdev->dev, "load state resource string empty\n");
+
+               qmp_put(q6v5->qmp);
+               return load_state ? -ENOMEM : -EINVAL;
+       }
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(qcom_q6v5_init);
 
+/**
+ * qcom_q6v5_deinit() - deinitialize the q6v5 common struct
+ * @q6v5:      reference to qcom_q6v5 context to be deinitialized
+ */
+void qcom_q6v5_deinit(struct qcom_q6v5 *q6v5)
+{
+       qmp_put(q6v5->qmp);
+}
+EXPORT_SYMBOL_GPL(qcom_q6v5_deinit);
+
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Qualcomm Peripheral Image Loader for Q6V5");
 
 
 #include <linux/kernel.h>
 #include <linux/completion.h>
+#include <linux/soc/qcom/qcom_aoss.h>
 
 struct rproc;
 struct qcom_smem_state;
        struct rproc *rproc;
 
        struct qcom_smem_state *state;
+       struct qmp *qmp;
+
        unsigned stop_bit;
 
        int wdog_irq;
 
        bool running;
 
+       const char *load_state;
        void (*handover)(struct qcom_q6v5 *q6v5);
 };
 
 int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev,
-                  struct rproc *rproc, int crash_reason,
+                  struct rproc *rproc, int crash_reason, const char *load_state,
                   void (*handover)(struct qcom_q6v5 *q6v5));
+void qcom_q6v5_deinit(struct qcom_q6v5 *q6v5);
 
 int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5);
 int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5);
 
        int ret;
        unsigned int val;
 
-       qcom_q6v5_prepare(&adsp->q6v5);
+       ret = qcom_q6v5_prepare(&adsp->q6v5);
+       if (ret)
+               return ret;
 
        ret = clk_prepare_enable(adsp->xo);
        if (ret)
        if (ret)
                goto disable_pm;
 
-       ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
+       ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, NULL,
                             qcom_adsp_pil_handover);
        if (ret)
                goto disable_pm;
 
        rproc_del(adsp->rproc);
 
+       qcom_q6v5_deinit(&adsp->q6v5);
        qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
        qcom_remove_sysmon_subdev(adsp->sysmon);
        qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
 
        char **proxy_clk_names;
        char **reset_clk_names;
        char **active_clk_names;
-       char **active_pd_names;
        char **proxy_pd_names;
        int version;
        bool need_mem_protection;
        struct clk *active_clks[8];
        struct clk *reset_clks[4];
        struct clk *proxy_clks[4];
-       struct device *active_pds[1];
        struct device *proxy_pds[3];
        int active_clk_count;
        int reset_clk_count;
        int proxy_clk_count;
-       int active_pd_count;
        int proxy_pd_count;
 
        struct reg_info active_regs[1];
        int xfermemop_ret;
        bool mba_load_err = false;
 
-       qcom_q6v5_prepare(&qproc->q6v5);
-
-       ret = q6v5_pds_enable(qproc, qproc->active_pds, qproc->active_pd_count);
-       if (ret < 0) {
-               dev_err(qproc->dev, "failed to enable active power domains\n");
-               goto disable_irqs;
-       }
+       ret = qcom_q6v5_prepare(&qproc->q6v5);
+       if (ret)
+               return ret;
 
        ret = q6v5_pds_enable(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
        if (ret < 0) {
                dev_err(qproc->dev, "failed to enable proxy power domains\n");
-               goto disable_active_pds;
+               goto disable_irqs;
        }
 
        ret = q6v5_regulator_enable(qproc, qproc->fallback_proxy_regs,
                               qproc->fallback_proxy_reg_count);
 disable_proxy_pds:
        q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
-disable_active_pds:
-       q6v5_pds_disable(qproc, qproc->active_pds, qproc->active_pd_count);
 disable_irqs:
        qcom_q6v5_unprepare(&qproc->q6v5);
 
                         qproc->active_clk_count);
        q6v5_regulator_disable(qproc, qproc->active_regs,
                               qproc->active_reg_count);
-       q6v5_pds_disable(qproc, qproc->active_pds, qproc->active_pd_count);
 
        /* In case of failure or coredump scenario where reclaiming MBA memory
         * could not happen reclaim it here.
        }
        qproc->active_reg_count = ret;
 
-       ret = q6v5_pds_attach(&pdev->dev, qproc->active_pds,
-                             desc->active_pd_names);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Failed to attach active power domains\n");
-               goto free_rproc;
-       }
-       qproc->active_pd_count = ret;
-
        ret = q6v5_pds_attach(&pdev->dev, qproc->proxy_pds,
                              desc->proxy_pd_names);
        /* Fallback to regulators for old device trees */
                                          desc->fallback_proxy_supply);
                if (ret < 0) {
                        dev_err(&pdev->dev, "Failed to get fallback proxy regulators.\n");
-                       goto detach_active_pds;
+                       goto free_rproc;
                }
                qproc->fallback_proxy_reg_count = ret;
        } else if (ret < 0) {
                dev_err(&pdev->dev, "Failed to init power domains\n");
-               goto detach_active_pds;
+               goto free_rproc;
        } else {
                qproc->proxy_pd_count = ret;
        }
        qproc->need_mem_protection = desc->need_mem_protection;
        qproc->has_mba_logs = desc->has_mba_logs;
 
-       ret = qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM,
+       ret = qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM, "modem",
                             qcom_msa_handover);
        if (ret)
                goto detach_proxy_pds;
        qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
 detach_proxy_pds:
        q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
-detach_active_pds:
-       q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
 free_rproc:
        rproc_free(rproc);
 
 
        rproc_del(rproc);
 
+       qcom_q6v5_deinit(&qproc->q6v5);
        qcom_remove_sysmon_subdev(qproc->sysmon);
        qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
        qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
        qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
 
        q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
-       q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
 
        rproc_free(rproc);
 
                "nav",
                NULL
        },
-       .active_pd_names = (char*[]){
-               "load_state",
-               NULL
-       },
        .proxy_pd_names = (char*[]){
                "cx",
                "mx",
                        "mnoc_axi",
                        NULL
        },
-       .active_pd_names = (char*[]){
-                       "load_state",
-                       NULL
-       },
        .proxy_pd_names = (char*[]){
                        "cx",
                        "mx",
 
        bool has_aggre2_clk;
        bool auto_boot;
 
-       char **active_pd_names;
        char **proxy_pd_names;
 
+       const char *load_state;
        const char *ssr_name;
        const char *sysmon_name;
        int ssctl_id;
        struct regulator *cx_supply;
        struct regulator *px_supply;
 
-       struct device *active_pds[1];
        struct device *proxy_pds[3];
 
-       int active_pd_count;
        int proxy_pd_count;
 
        int pas_id;
        struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
        int ret;
 
-       qcom_q6v5_prepare(&adsp->q6v5);
-
-       ret = adsp_pds_enable(adsp, adsp->active_pds, adsp->active_pd_count);
-       if (ret < 0)
-               goto disable_irqs;
+       ret = qcom_q6v5_prepare(&adsp->q6v5);
+       if (ret)
+               return ret;
 
        ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
        if (ret < 0)
-               goto disable_active_pds;
+               goto disable_irqs;
 
        ret = clk_prepare_enable(adsp->xo);
        if (ret)
        clk_disable_unprepare(adsp->xo);
 disable_proxy_pds:
        adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
-disable_active_pds:
-       adsp_pds_disable(adsp, adsp->active_pds, adsp->active_pd_count);
 disable_irqs:
        qcom_q6v5_unprepare(&adsp->q6v5);
 
        if (ret)
                dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
 
-       adsp_pds_disable(adsp, adsp->active_pds, adsp->active_pd_count);
        handover = qcom_q6v5_unprepare(&adsp->q6v5);
        if (handover)
                qcom_pas_handover(&adsp->q6v5);
        if (ret)
                goto free_rproc;
 
-       ret = adsp_pds_attach(&pdev->dev, adsp->active_pds,
-                             desc->active_pd_names);
-       if (ret < 0)
-               goto free_rproc;
-       adsp->active_pd_count = ret;
-
        ret = adsp_pds_attach(&pdev->dev, adsp->proxy_pds,
                              desc->proxy_pd_names);
        if (ret < 0)
-               goto detach_active_pds;
+               goto free_rproc;
        adsp->proxy_pd_count = ret;
 
-       ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
+       ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, desc->load_state,
                             qcom_pas_handover);
        if (ret)
                goto detach_proxy_pds;
 
 detach_proxy_pds:
        adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
-detach_active_pds:
-       adsp_pds_detach(adsp, adsp->active_pds, adsp->active_pd_count);
 free_rproc:
        rproc_free(rproc);
 
 
        rproc_del(adsp->rproc);
 
+       qcom_q6v5_deinit(&adsp->q6v5);
        qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
        qcom_remove_sysmon_subdev(adsp->sysmon);
        qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
                .ssctl_id = 0x14,
 };
 
+static const struct adsp_data sdm845_adsp_resource_init = {
+               .crash_reason_smem = 423,
+               .firmware_name = "adsp.mdt",
+               .pas_id = 1,
+               .has_aggre2_clk = false,
+               .auto_boot = true,
+               .load_state = "adsp",
+               .ssr_name = "lpass",
+               .sysmon_name = "adsp",
+               .ssctl_id = 0x14,
+};
+
 static const struct adsp_data sm8150_adsp_resource = {
                .crash_reason_smem = 423,
                .firmware_name = "adsp.mdt",
                .pas_id = 1,
                .has_aggre2_clk = false,
                .auto_boot = true,
-               .active_pd_names = (char*[]){
-                       "load_state",
-                       NULL
-               },
                .proxy_pd_names = (char*[]){
                        "cx",
                        NULL
                },
+               .load_state = "adsp",
                .ssr_name = "lpass",
                .sysmon_name = "adsp",
                .ssctl_id = 0x14,
        .pas_id = 1,
        .has_aggre2_clk = false,
        .auto_boot = true,
-       .active_pd_names = (char*[]){
-               "load_state",
-               NULL
-       },
        .proxy_pd_names = (char*[]){
                "lcx",
                "lmx",
                NULL
        },
+       .load_state = "adsp",
        .ssr_name = "lpass",
        .sysmon_name = "adsp",
        .ssctl_id = 0x14,
        .pas_id = 1,
        .has_aggre2_clk = false,
        .auto_boot = true,
-       .active_pd_names = (char*[]){
-               "load_state",
-               NULL
-       },
        .proxy_pd_names = (char*[]){
                "lcx",
                "lmx",
                NULL
        },
+       .load_state = "adsp",
        .ssr_name = "lpass",
        .sysmon_name = "adsp",
        .ssctl_id = 0x14,
        .ssctl_id = 0x17,
 };
 
+static const struct adsp_data sdm845_cdsp_resource_init = {
+       .crash_reason_smem = 601,
+       .firmware_name = "cdsp.mdt",
+       .pas_id = 18,
+       .has_aggre2_clk = false,
+       .auto_boot = true,
+       .load_state = "cdsp",
+       .ssr_name = "cdsp",
+       .sysmon_name = "cdsp",
+       .ssctl_id = 0x17,
+};
+
 static const struct adsp_data sm8150_cdsp_resource = {
        .crash_reason_smem = 601,
        .firmware_name = "cdsp.mdt",
        .pas_id = 18,
        .has_aggre2_clk = false,
        .auto_boot = true,
-       .active_pd_names = (char*[]){
-               "load_state",
-               NULL
-       },
        .proxy_pd_names = (char*[]){
                "cx",
                NULL
        },
+       .load_state = "cdsp",
        .ssr_name = "cdsp",
        .sysmon_name = "cdsp",
        .ssctl_id = 0x17,
        .pas_id = 18,
        .has_aggre2_clk = false,
        .auto_boot = true,
-       .active_pd_names = (char*[]){
-               "load_state",
-               NULL
-       },
        .proxy_pd_names = (char*[]){
                "cx",
                NULL
        },
+       .load_state = "cdsp",
        .ssr_name = "cdsp",
        .sysmon_name = "cdsp",
        .ssctl_id = 0x17,
        .pas_id = 18,
        .has_aggre2_clk = false,
        .auto_boot = true,
-       .active_pd_names = (char*[]){
-               "load_state",
-               NULL
-       },
        .proxy_pd_names = (char*[]){
                "cx",
                NULL
        },
+       .load_state = "cdsp",
        .ssr_name = "cdsp",
        .sysmon_name = "cdsp",
        .ssctl_id = 0x17,
        .minidump_id = 3,
        .has_aggre2_clk = false,
        .auto_boot = false,
-       .active_pd_names = (char*[]){
-               "load_state",
-               NULL
-       },
        .proxy_pd_names = (char*[]){
                "cx",
                "mss",
                NULL
        },
+       .load_state = "modem",
        .ssr_name = "mpss",
        .sysmon_name = "modem",
        .ssctl_id = 0x12,
        .pas_id = 4,
        .has_aggre2_clk = false,
        .auto_boot = false,
-       .active_pd_names = (char*[]){
-               "load_state",
-               NULL
-       },
        .proxy_pd_names = (char*[]){
                "cx",
                NULL
        },
+       .load_state = "modem",
        .ssr_name = "mpss",
        .sysmon_name = "modem",
        .ssctl_id = 0x12,
                .pas_id = 12,
                .has_aggre2_clk = false,
                .auto_boot = true,
-               .active_pd_names = (char*[]){
-                       "load_state",
-                       NULL
-               },
                .proxy_pd_names = (char*[]){
                        "lcx",
                        "lmx",
                        NULL
                },
+               .load_state = "slpi",
                .ssr_name = "dsps",
                .sysmon_name = "slpi",
                .ssctl_id = 0x16,
        .pas_id = 12,
        .has_aggre2_clk = false,
        .auto_boot = true,
-       .active_pd_names = (char*[]){
-               "load_state",
-               NULL
-       },
        .proxy_pd_names = (char*[]){
                "lcx",
                "lmx",
                NULL
        },
+       .load_state = "slpi",
        .ssr_name = "dsps",
        .sysmon_name = "slpi",
        .ssctl_id = 0x16,
        .pas_id = 12,
        .has_aggre2_clk = false,
        .auto_boot = true,
-       .active_pd_names = (char*[]){
-               "load_state",
-               NULL
-       },
        .proxy_pd_names = (char*[]){
                "lcx",
                "lmx",
                NULL
        },
+       .load_state = "slpi",
        .ssr_name = "dsps",
        .sysmon_name = "slpi",
        .ssctl_id = 0x16,
        { .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource},
        { .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource},
        { .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init},
-       { .compatible = "qcom,sdm845-adsp-pas", .data = &adsp_resource_init},
-       { .compatible = "qcom,sdm845-cdsp-pas", .data = &cdsp_resource_init},
+       { .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init},
+       { .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init},
        { .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource},
        { .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource},
        { .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource},
 
        if (ret)
                goto free_rproc;
 
-       ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, desc->crash_reason_smem,
-                            NULL);
+       ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, desc->crash_reason_smem, NULL, NULL);
        if (ret)
                goto free_rproc;
 
 static int q6v5_wcss_remove(struct platform_device *pdev)
 {
        struct rproc *rproc = platform_get_drvdata(pdev);
+       struct q6v5_wcss *wcss = rproc->priv;
 
+       qcom_q6v5_deinit(&wcss->q6v5);
        rproc_del(rproc);
        rproc_free(rproc);