]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
remoteproc: qcom: Rename Hexagon v5 PAS driver
authorBjorn Andersson <bjorn.andersson@linaro.org>
Mon, 24 Sep 2018 23:45:25 +0000 (16:45 -0700)
committerBjorn Andersson <bjorn.andersson@linaro.org>
Wed, 26 Sep 2018 17:11:20 +0000 (10:11 -0700)
The Hexagon v5 ADSP driver is used for more than only the ADSP and
there's an upcoming non-PAS ADSP PIL for SDM845, so rename the driver to
qcom_q6v5_pas in order to better suite this.

Cc: Rohit kumar <rohitkr@codeaurora.org>
Reviewed-by: Niklas Cassel <niklas.cassel@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
drivers/remoteproc/Kconfig
drivers/remoteproc/Makefile
drivers/remoteproc/qcom_adsp_pil.c [deleted file]
drivers/remoteproc/qcom_q6v5_pas.c [new file with mode: 0644]

index 052d4dd347f90c185916b5db0708c20379be599d..425e502c64710cae72107fd6461e5acf0338c310 100644 (file)
@@ -84,8 +84,16 @@ config KEYSTONE_REMOTEPROC
          It's safe to say N here if you're not interested in the Keystone
          DSPs or just want to use a bare minimum kernel.
 
-config QCOM_ADSP_PIL
-       tristate "Qualcomm ADSP Peripheral Image Loader"
+config QCOM_RPROC_COMMON
+       tristate
+
+config QCOM_Q6V5_COMMON
+       tristate
+       depends on ARCH_QCOM
+       depends on QCOM_SMEM
+
+config QCOM_Q6V5_PAS
+       tristate "Qualcomm Hexagon v5 Peripheral Authentication Service support"
        depends on OF && ARCH_QCOM
        depends on QCOM_SMEM
        depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
@@ -98,15 +106,7 @@ config QCOM_ADSP_PIL
        select QCOM_SCM
        help
          Say y here to support the TrustZone based Peripherial Image Loader
-         for the Qualcomm ADSP remote processors.
-
-config QCOM_RPROC_COMMON
-       tristate
-
-config QCOM_Q6V5_COMMON
-       tristate
-       depends on ARCH_QCOM
-       depends on QCOM_SMEM
+         for the Qualcomm Hexagon v5 based remote processors.
 
 config QCOM_Q6V5_PIL
        tristate "Qualcomm Hexagon V5 Peripherial Image Loader"
@@ -120,8 +120,9 @@ config QCOM_Q6V5_PIL
        select QCOM_RPROC_COMMON
        select QCOM_SCM
        help
-         Say y here to support the Qualcomm Peripherial Image Loader for the
-         Hexagon V5 based remote processors.
+         Say y here to support the TrustZone based Peripherial Image Loader
+         for the Qualcomm Hexagon v5 based remote processors. This is commonly
+         used to control subsystems such as ADSP, Compute and Sensor.
 
 config QCOM_Q6V5_WCSS
        tristate "Qualcomm Hexagon based WCSS Peripheral Image Loader"
index 03332fa7e2ee7515d5281c175e632d4a600b3382..eb86c8ba5a871717518273b375c2bce932996b43 100644 (file)
@@ -14,9 +14,9 @@ obj-$(CONFIG_OMAP_REMOTEPROC)         += omap_remoteproc.o
 obj-$(CONFIG_WKUP_M3_RPROC)            += wkup_m3_rproc.o
 obj-$(CONFIG_DA8XX_REMOTEPROC)         += da8xx_remoteproc.o
 obj-$(CONFIG_KEYSTONE_REMOTEPROC)      += keystone_remoteproc.o
-obj-$(CONFIG_QCOM_ADSP_PIL)            += qcom_adsp_pil.o
 obj-$(CONFIG_QCOM_RPROC_COMMON)                += qcom_common.o
 obj-$(CONFIG_QCOM_Q6V5_COMMON)         += qcom_q6v5.o
+obj-$(CONFIG_QCOM_Q6V5_PAS)            += qcom_q6v5_pas.o
 obj-$(CONFIG_QCOM_Q6V5_PIL)            += qcom_q6v5_pil.o
 obj-$(CONFIG_QCOM_Q6V5_WCSS)           += qcom_q6v5_wcss.o
 obj-$(CONFIG_QCOM_SYSMON)              += qcom_sysmon.o
diff --git a/drivers/remoteproc/qcom_adsp_pil.c b/drivers/remoteproc/qcom_adsp_pil.c
deleted file mode 100644 (file)
index da2254e..0000000
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Qualcomm ADSP/SLPI Peripheral Image Loader for MSM8974 and MSM8996
- *
- * Copyright (C) 2016 Linaro Ltd
- * Copyright (C) 2014 Sony Mobile Communications AB
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/firmware.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/qcom_scm.h>
-#include <linux/regulator/consumer.h>
-#include <linux/remoteproc.h>
-#include <linux/soc/qcom/mdt_loader.h>
-#include <linux/soc/qcom/smem.h>
-#include <linux/soc/qcom/smem_state.h>
-
-#include "qcom_common.h"
-#include "qcom_q6v5.h"
-#include "remoteproc_internal.h"
-
-struct adsp_data {
-       int crash_reason_smem;
-       const char *firmware_name;
-       int pas_id;
-       bool has_aggre2_clk;
-
-       const char *ssr_name;
-       const char *sysmon_name;
-       int ssctl_id;
-};
-
-struct qcom_adsp {
-       struct device *dev;
-       struct rproc *rproc;
-
-       struct qcom_q6v5 q6v5;
-
-       struct clk *xo;
-       struct clk *aggre2_clk;
-
-       struct regulator *cx_supply;
-       struct regulator *px_supply;
-
-       int pas_id;
-       int crash_reason_smem;
-       bool has_aggre2_clk;
-
-       struct completion start_done;
-       struct completion stop_done;
-
-       phys_addr_t mem_phys;
-       phys_addr_t mem_reloc;
-       void *mem_region;
-       size_t mem_size;
-
-       struct qcom_rproc_glink glink_subdev;
-       struct qcom_rproc_subdev smd_subdev;
-       struct qcom_rproc_ssr ssr_subdev;
-       struct qcom_sysmon *sysmon;
-};
-
-static int adsp_load(struct rproc *rproc, const struct firmware *fw)
-{
-       struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
-
-       return qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id,
-                            adsp->mem_region, adsp->mem_phys, adsp->mem_size,
-                            &adsp->mem_reloc);
-
-}
-
-static int adsp_start(struct rproc *rproc)
-{
-       struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
-       int ret;
-
-       qcom_q6v5_prepare(&adsp->q6v5);
-
-       ret = clk_prepare_enable(adsp->xo);
-       if (ret)
-               return ret;
-
-       ret = clk_prepare_enable(adsp->aggre2_clk);
-       if (ret)
-               goto disable_xo_clk;
-
-       ret = regulator_enable(adsp->cx_supply);
-       if (ret)
-               goto disable_aggre2_clk;
-
-       ret = regulator_enable(adsp->px_supply);
-       if (ret)
-               goto disable_cx_supply;
-
-       ret = qcom_scm_pas_auth_and_reset(adsp->pas_id);
-       if (ret) {
-               dev_err(adsp->dev,
-                       "failed to authenticate image and release reset\n");
-               goto disable_px_supply;
-       }
-
-       ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5000));
-       if (ret == -ETIMEDOUT) {
-               dev_err(adsp->dev, "start timed out\n");
-               qcom_scm_pas_shutdown(adsp->pas_id);
-               goto disable_px_supply;
-       }
-
-       return 0;
-
-disable_px_supply:
-       regulator_disable(adsp->px_supply);
-disable_cx_supply:
-       regulator_disable(adsp->cx_supply);
-disable_aggre2_clk:
-       clk_disable_unprepare(adsp->aggre2_clk);
-disable_xo_clk:
-       clk_disable_unprepare(adsp->xo);
-
-       return ret;
-}
-
-static void qcom_pas_handover(struct qcom_q6v5 *q6v5)
-{
-       struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
-
-       regulator_disable(adsp->px_supply);
-       regulator_disable(adsp->cx_supply);
-       clk_disable_unprepare(adsp->aggre2_clk);
-       clk_disable_unprepare(adsp->xo);
-}
-
-static int adsp_stop(struct rproc *rproc)
-{
-       struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
-       int handover;
-       int ret;
-
-       ret = qcom_q6v5_request_stop(&adsp->q6v5);
-       if (ret == -ETIMEDOUT)
-               dev_err(adsp->dev, "timed out on wait\n");
-
-       ret = qcom_scm_pas_shutdown(adsp->pas_id);
-       if (ret)
-               dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
-
-       handover = qcom_q6v5_unprepare(&adsp->q6v5);
-       if (handover)
-               qcom_pas_handover(&adsp->q6v5);
-
-       return ret;
-}
-
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
-{
-       struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
-       int offset;
-
-       offset = da - adsp->mem_reloc;
-       if (offset < 0 || offset + len > adsp->mem_size)
-               return NULL;
-
-       return adsp->mem_region + offset;
-}
-
-static const struct rproc_ops adsp_ops = {
-       .start = adsp_start,
-       .stop = adsp_stop,
-       .da_to_va = adsp_da_to_va,
-       .parse_fw = qcom_register_dump_segments,
-       .load = adsp_load,
-};
-
-static int adsp_init_clock(struct qcom_adsp *adsp)
-{
-       int ret;
-
-       adsp->xo = devm_clk_get(adsp->dev, "xo");
-       if (IS_ERR(adsp->xo)) {
-               ret = PTR_ERR(adsp->xo);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(adsp->dev, "failed to get xo clock");
-               return ret;
-       }
-
-       if (adsp->has_aggre2_clk) {
-               adsp->aggre2_clk = devm_clk_get(adsp->dev, "aggre2");
-               if (IS_ERR(adsp->aggre2_clk)) {
-                       ret = PTR_ERR(adsp->aggre2_clk);
-                       if (ret != -EPROBE_DEFER)
-                               dev_err(adsp->dev,
-                                       "failed to get aggre2 clock");
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static int adsp_init_regulator(struct qcom_adsp *adsp)
-{
-       adsp->cx_supply = devm_regulator_get(adsp->dev, "cx");
-       if (IS_ERR(adsp->cx_supply))
-               return PTR_ERR(adsp->cx_supply);
-
-       regulator_set_load(adsp->cx_supply, 100000);
-
-       adsp->px_supply = devm_regulator_get(adsp->dev, "px");
-       return PTR_ERR_OR_ZERO(adsp->px_supply);
-}
-
-static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
-{
-       struct device_node *node;
-       struct resource r;
-       int ret;
-
-       node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
-       if (!node) {
-               dev_err(adsp->dev, "no memory-region specified\n");
-               return -EINVAL;
-       }
-
-       ret = of_address_to_resource(node, 0, &r);
-       if (ret)
-               return ret;
-
-       adsp->mem_phys = adsp->mem_reloc = r.start;
-       adsp->mem_size = resource_size(&r);
-       adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size);
-       if (!adsp->mem_region) {
-               dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
-                       &r.start, adsp->mem_size);
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
-static int adsp_probe(struct platform_device *pdev)
-{
-       const struct adsp_data *desc;
-       struct qcom_adsp *adsp;
-       struct rproc *rproc;
-       int ret;
-
-       desc = of_device_get_match_data(&pdev->dev);
-       if (!desc)
-               return -EINVAL;
-
-       if (!qcom_scm_is_available())
-               return -EPROBE_DEFER;
-
-       rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops,
-                           desc->firmware_name, sizeof(*adsp));
-       if (!rproc) {
-               dev_err(&pdev->dev, "unable to allocate remoteproc\n");
-               return -ENOMEM;
-       }
-
-       adsp = (struct qcom_adsp *)rproc->priv;
-       adsp->dev = &pdev->dev;
-       adsp->rproc = rproc;
-       adsp->pas_id = desc->pas_id;
-       adsp->has_aggre2_clk = desc->has_aggre2_clk;
-       platform_set_drvdata(pdev, adsp);
-
-       ret = adsp_alloc_memory_region(adsp);
-       if (ret)
-               goto free_rproc;
-
-       ret = adsp_init_clock(adsp);
-       if (ret)
-               goto free_rproc;
-
-       ret = adsp_init_regulator(adsp);
-       if (ret)
-               goto free_rproc;
-
-       ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
-                            qcom_pas_handover);
-       if (ret)
-               goto free_rproc;
-
-       qcom_add_glink_subdev(rproc, &adsp->glink_subdev);
-       qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
-       qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
-       adsp->sysmon = qcom_add_sysmon_subdev(rproc,
-                                             desc->sysmon_name,
-                                             desc->ssctl_id);
-
-       ret = rproc_add(rproc);
-       if (ret)
-               goto free_rproc;
-
-       return 0;
-
-free_rproc:
-       rproc_free(rproc);
-
-       return ret;
-}
-
-static int adsp_remove(struct platform_device *pdev)
-{
-       struct qcom_adsp *adsp = platform_get_drvdata(pdev);
-
-       rproc_del(adsp->rproc);
-
-       qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
-       qcom_remove_sysmon_subdev(adsp->sysmon);
-       qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
-       qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
-       rproc_free(adsp->rproc);
-
-       return 0;
-}
-
-static const struct adsp_data adsp_resource_init = {
-               .crash_reason_smem = 423,
-               .firmware_name = "adsp.mdt",
-               .pas_id = 1,
-               .has_aggre2_clk = false,
-               .ssr_name = "lpass",
-               .sysmon_name = "adsp",
-               .ssctl_id = 0x14,
-};
-
-static const struct adsp_data cdsp_resource_init = {
-       .crash_reason_smem = 601,
-       .firmware_name = "cdsp.mdt",
-       .pas_id = 18,
-       .has_aggre2_clk = false,
-       .ssr_name = "cdsp",
-       .sysmon_name = "cdsp",
-       .ssctl_id = 0x17,
-};
-
-static const struct adsp_data slpi_resource_init = {
-               .crash_reason_smem = 424,
-               .firmware_name = "slpi.mdt",
-               .pas_id = 12,
-               .has_aggre2_clk = true,
-               .ssr_name = "dsps",
-               .sysmon_name = "slpi",
-               .ssctl_id = 0x16,
-};
-
-static const struct of_device_id adsp_of_match[] = {
-       { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
-       { .compatible = "qcom,msm8996-adsp-pil", .data = &adsp_resource_init},
-       { .compatible = "qcom,msm8996-slpi-pil", .data = &slpi_resource_init},
-       { .compatible = "qcom,sdm845-adsp-pas", .data = &adsp_resource_init},
-       { .compatible = "qcom,sdm845-cdsp-pas", .data = &cdsp_resource_init},
-       { },
-};
-MODULE_DEVICE_TABLE(of, adsp_of_match);
-
-static struct platform_driver adsp_driver = {
-       .probe = adsp_probe,
-       .remove = adsp_remove,
-       .driver = {
-               .name = "qcom_adsp_pil",
-               .of_match_table = adsp_of_match,
-       },
-};
-
-module_platform_driver(adsp_driver);
-MODULE_DESCRIPTION("Qualcomm MSM8974/MSM8996 ADSP Peripherial Image Loader");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
new file mode 100644 (file)
index 0000000..03edf08
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Qualcomm ADSP/SLPI Peripheral Image Loader for MSM8974 and MSM8996
+ *
+ * Copyright (C) 2016 Linaro Ltd
+ * Copyright (C) 2014 Sony Mobile Communications AB
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/qcom_scm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/remoteproc.h>
+#include <linux/soc/qcom/mdt_loader.h>
+#include <linux/soc/qcom/smem.h>
+#include <linux/soc/qcom/smem_state.h>
+
+#include "qcom_common.h"
+#include "qcom_q6v5.h"
+#include "remoteproc_internal.h"
+
+struct adsp_data {
+       int crash_reason_smem;
+       const char *firmware_name;
+       int pas_id;
+       bool has_aggre2_clk;
+
+       const char *ssr_name;
+       const char *sysmon_name;
+       int ssctl_id;
+};
+
+struct qcom_adsp {
+       struct device *dev;
+       struct rproc *rproc;
+
+       struct qcom_q6v5 q6v5;
+
+       struct clk *xo;
+       struct clk *aggre2_clk;
+
+       struct regulator *cx_supply;
+       struct regulator *px_supply;
+
+       int pas_id;
+       int crash_reason_smem;
+       bool has_aggre2_clk;
+
+       struct completion start_done;
+       struct completion stop_done;
+
+       phys_addr_t mem_phys;
+       phys_addr_t mem_reloc;
+       void *mem_region;
+       size_t mem_size;
+
+       struct qcom_rproc_glink glink_subdev;
+       struct qcom_rproc_subdev smd_subdev;
+       struct qcom_rproc_ssr ssr_subdev;
+       struct qcom_sysmon *sysmon;
+};
+
+static int adsp_load(struct rproc *rproc, const struct firmware *fw)
+{
+       struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
+
+       return qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id,
+                            adsp->mem_region, adsp->mem_phys, adsp->mem_size,
+                            &adsp->mem_reloc);
+
+}
+
+static int adsp_start(struct rproc *rproc)
+{
+       struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
+       int ret;
+
+       qcom_q6v5_prepare(&adsp->q6v5);
+
+       ret = clk_prepare_enable(adsp->xo);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(adsp->aggre2_clk);
+       if (ret)
+               goto disable_xo_clk;
+
+       ret = regulator_enable(adsp->cx_supply);
+       if (ret)
+               goto disable_aggre2_clk;
+
+       ret = regulator_enable(adsp->px_supply);
+       if (ret)
+               goto disable_cx_supply;
+
+       ret = qcom_scm_pas_auth_and_reset(adsp->pas_id);
+       if (ret) {
+               dev_err(adsp->dev,
+                       "failed to authenticate image and release reset\n");
+               goto disable_px_supply;
+       }
+
+       ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5000));
+       if (ret == -ETIMEDOUT) {
+               dev_err(adsp->dev, "start timed out\n");
+               qcom_scm_pas_shutdown(adsp->pas_id);
+               goto disable_px_supply;
+       }
+
+       return 0;
+
+disable_px_supply:
+       regulator_disable(adsp->px_supply);
+disable_cx_supply:
+       regulator_disable(adsp->cx_supply);
+disable_aggre2_clk:
+       clk_disable_unprepare(adsp->aggre2_clk);
+disable_xo_clk:
+       clk_disable_unprepare(adsp->xo);
+
+       return ret;
+}
+
+static void qcom_pas_handover(struct qcom_q6v5 *q6v5)
+{
+       struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
+
+       regulator_disable(adsp->px_supply);
+       regulator_disable(adsp->cx_supply);
+       clk_disable_unprepare(adsp->aggre2_clk);
+       clk_disable_unprepare(adsp->xo);
+}
+
+static int adsp_stop(struct rproc *rproc)
+{
+       struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
+       int handover;
+       int ret;
+
+       ret = qcom_q6v5_request_stop(&adsp->q6v5);
+       if (ret == -ETIMEDOUT)
+               dev_err(adsp->dev, "timed out on wait\n");
+
+       ret = qcom_scm_pas_shutdown(adsp->pas_id);
+       if (ret)
+               dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
+
+       handover = qcom_q6v5_unprepare(&adsp->q6v5);
+       if (handover)
+               qcom_pas_handover(&adsp->q6v5);
+
+       return ret;
+}
+
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
+{
+       struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
+       int offset;
+
+       offset = da - adsp->mem_reloc;
+       if (offset < 0 || offset + len > adsp->mem_size)
+               return NULL;
+
+       return adsp->mem_region + offset;
+}
+
+static const struct rproc_ops adsp_ops = {
+       .start = adsp_start,
+       .stop = adsp_stop,
+       .da_to_va = adsp_da_to_va,
+       .parse_fw = qcom_register_dump_segments,
+       .load = adsp_load,
+};
+
+static int adsp_init_clock(struct qcom_adsp *adsp)
+{
+       int ret;
+
+       adsp->xo = devm_clk_get(adsp->dev, "xo");
+       if (IS_ERR(adsp->xo)) {
+               ret = PTR_ERR(adsp->xo);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(adsp->dev, "failed to get xo clock");
+               return ret;
+       }
+
+       if (adsp->has_aggre2_clk) {
+               adsp->aggre2_clk = devm_clk_get(adsp->dev, "aggre2");
+               if (IS_ERR(adsp->aggre2_clk)) {
+                       ret = PTR_ERR(adsp->aggre2_clk);
+                       if (ret != -EPROBE_DEFER)
+                               dev_err(adsp->dev,
+                                       "failed to get aggre2 clock");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int adsp_init_regulator(struct qcom_adsp *adsp)
+{
+       adsp->cx_supply = devm_regulator_get(adsp->dev, "cx");
+       if (IS_ERR(adsp->cx_supply))
+               return PTR_ERR(adsp->cx_supply);
+
+       regulator_set_load(adsp->cx_supply, 100000);
+
+       adsp->px_supply = devm_regulator_get(adsp->dev, "px");
+       return PTR_ERR_OR_ZERO(adsp->px_supply);
+}
+
+static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
+{
+       struct device_node *node;
+       struct resource r;
+       int ret;
+
+       node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
+       if (!node) {
+               dev_err(adsp->dev, "no memory-region specified\n");
+               return -EINVAL;
+       }
+
+       ret = of_address_to_resource(node, 0, &r);
+       if (ret)
+               return ret;
+
+       adsp->mem_phys = adsp->mem_reloc = r.start;
+       adsp->mem_size = resource_size(&r);
+       adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size);
+       if (!adsp->mem_region) {
+               dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
+                       &r.start, adsp->mem_size);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+static int adsp_probe(struct platform_device *pdev)
+{
+       const struct adsp_data *desc;
+       struct qcom_adsp *adsp;
+       struct rproc *rproc;
+       int ret;
+
+       desc = of_device_get_match_data(&pdev->dev);
+       if (!desc)
+               return -EINVAL;
+
+       if (!qcom_scm_is_available())
+               return -EPROBE_DEFER;
+
+       rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops,
+                           desc->firmware_name, sizeof(*adsp));
+       if (!rproc) {
+               dev_err(&pdev->dev, "unable to allocate remoteproc\n");
+               return -ENOMEM;
+       }
+
+       adsp = (struct qcom_adsp *)rproc->priv;
+       adsp->dev = &pdev->dev;
+       adsp->rproc = rproc;
+       adsp->pas_id = desc->pas_id;
+       adsp->has_aggre2_clk = desc->has_aggre2_clk;
+       platform_set_drvdata(pdev, adsp);
+
+       ret = adsp_alloc_memory_region(adsp);
+       if (ret)
+               goto free_rproc;
+
+       ret = adsp_init_clock(adsp);
+       if (ret)
+               goto free_rproc;
+
+       ret = adsp_init_regulator(adsp);
+       if (ret)
+               goto free_rproc;
+
+       ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
+                            qcom_pas_handover);
+       if (ret)
+               goto free_rproc;
+
+       qcom_add_glink_subdev(rproc, &adsp->glink_subdev);
+       qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
+       qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+       adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+                                             desc->sysmon_name,
+                                             desc->ssctl_id);
+
+       ret = rproc_add(rproc);
+       if (ret)
+               goto free_rproc;
+
+       return 0;
+
+free_rproc:
+       rproc_free(rproc);
+
+       return ret;
+}
+
+static int adsp_remove(struct platform_device *pdev)
+{
+       struct qcom_adsp *adsp = platform_get_drvdata(pdev);
+
+       rproc_del(adsp->rproc);
+
+       qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+       qcom_remove_sysmon_subdev(adsp->sysmon);
+       qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
+       qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+       rproc_free(adsp->rproc);
+
+       return 0;
+}
+
+static const struct adsp_data adsp_resource_init = {
+               .crash_reason_smem = 423,
+               .firmware_name = "adsp.mdt",
+               .pas_id = 1,
+               .has_aggre2_clk = false,
+               .ssr_name = "lpass",
+               .sysmon_name = "adsp",
+               .ssctl_id = 0x14,
+};
+
+static const struct adsp_data cdsp_resource_init = {
+       .crash_reason_smem = 601,
+       .firmware_name = "cdsp.mdt",
+       .pas_id = 18,
+       .has_aggre2_clk = false,
+       .ssr_name = "cdsp",
+       .sysmon_name = "cdsp",
+       .ssctl_id = 0x17,
+};
+
+static const struct adsp_data slpi_resource_init = {
+               .crash_reason_smem = 424,
+               .firmware_name = "slpi.mdt",
+               .pas_id = 12,
+               .has_aggre2_clk = true,
+               .ssr_name = "dsps",
+               .sysmon_name = "slpi",
+               .ssctl_id = 0x16,
+};
+
+static const struct of_device_id adsp_of_match[] = {
+       { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
+       { .compatible = "qcom,msm8996-adsp-pil", .data = &adsp_resource_init},
+       { .compatible = "qcom,msm8996-slpi-pil", .data = &slpi_resource_init},
+       { .compatible = "qcom,sdm845-adsp-pas", .data = &adsp_resource_init},
+       { .compatible = "qcom,sdm845-cdsp-pas", .data = &cdsp_resource_init},
+       { },
+};
+MODULE_DEVICE_TABLE(of, adsp_of_match);
+
+static struct platform_driver adsp_driver = {
+       .probe = adsp_probe,
+       .remove = adsp_remove,
+       .driver = {
+               .name = "qcom_q6v5_pas",
+               .of_match_table = adsp_of_match,
+       },
+};
+
+module_platform_driver(adsp_driver);
+MODULE_DESCRIPTION("Qualcomm Hexagon v5 Peripheral Authentication Service driver");
+MODULE_LICENSE("GPL v2");