*/
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include "qcom_q6v5.h"
 #include "remoteproc_internal.h"
 
+#define ADSP_DECRYPT_SHUTDOWN_DELAY_MS 100
+
 struct adsp_data {
        int crash_reason_smem;
        const char *firmware_name;
        unsigned int minidump_id;
        bool has_aggre2_clk;
        bool auto_boot;
+       bool decrypt_shutdown;
 
        char **proxy_pd_names;
 
        unsigned int minidump_id;
        int crash_reason_smem;
        bool has_aggre2_clk;
+       bool decrypt_shutdown;
        const char *info_name;
 
        struct completion start_done;
        }
 }
 
+static int adsp_shutdown_poll_decrypt(struct qcom_adsp *adsp)
+{
+       unsigned int retry_num = 50;
+       int ret;
+
+       do {
+               msleep(ADSP_DECRYPT_SHUTDOWN_DELAY_MS);
+               ret = qcom_scm_pas_shutdown(adsp->pas_id);
+       } while (ret == -EINVAL && --retry_num);
+
+       return ret;
+}
+
 static int adsp_unprepare(struct rproc *rproc)
 {
        struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
                dev_err(adsp->dev, "timed out on wait\n");
 
        ret = qcom_scm_pas_shutdown(adsp->pas_id);
+       if (ret && adsp->decrypt_shutdown)
+               ret = adsp_shutdown_poll_decrypt(adsp);
+
        if (ret)
                dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
 
        adsp->pas_id = desc->pas_id;
        adsp->has_aggre2_clk = desc->has_aggre2_clk;
        adsp->info_name = desc->sysmon_name;
+       adsp->decrypt_shutdown = desc->decrypt_shutdown;
        platform_set_drvdata(pdev, adsp);
 
        device_wakeup_enable(adsp->dev);
        .ssctl_id = 0x22,
 };
 
+static const struct adsp_data sm8450_mpss_resource = {
+       .crash_reason_smem = 421,
+       .firmware_name = "modem.mdt",
+       .pas_id = 4,
+       .minidump_id = 3,
+       .has_aggre2_clk = false,
+       .auto_boot = false,
+       .decrypt_shutdown = true,
+       .proxy_pd_names = (char*[]){
+               "cx",
+               "mss",
+               NULL
+       },
+       .load_state = "modem",
+       .ssr_name = "mpss",
+       .sysmon_name = "modem",
+       .ssctl_id = 0x12,
+};
+
 static const struct of_device_id adsp_of_match[] = {
        { .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init},
        { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
        { .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource},
        { .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource},
        { .compatible = "qcom,sm8450-slpi-pas", .data = &sm8350_slpi_resource},
-       { .compatible = "qcom,sm8450-mpss-pas", .data = &mpss_resource_init},
+       { .compatible = "qcom,sm8450-mpss-pas", .data = &sm8450_mpss_resource},
        { },
 };
 MODULE_DEVICE_TABLE(of, adsp_of_match);