msm: pil-q6v5-lpass: Combine SSR and PIL drivers
Combine both drivers into one so that we can merge the PIL and
SSR frameworks.
Change-Id: I81621ca07794f81ec9e7f5567b27b6aa02a6c138
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
index d39c98c..ac9600d 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
@@ -11,6 +11,7 @@
memory mapped registers.
- reg-names: Names of the bases for the above registers. "qdsp6_base"
and "halt_base" are expected.
+- interrupts: The lpass watchdog interrupt
- qcom,firmware-name: Base name of the firmware image. Ex. "lpass"
Example:
@@ -19,6 +20,7 @@
reg = <0xfe200000 0x00100>,
<0xfd485100 0x00010>;
reg-names = "qdsp6_base", "halt_base";
+ interrupts = <0 194 1>;
qcom,firmware-name = "lpass";
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 172d094..e147b6e 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -659,6 +659,7 @@
reg = <0xfe200000 0x00100>,
<0xfd485100 0x00010>;
reg-names = "qdsp6_base", "halt_base";
+ interrupts = <0 194 1>;
qcom,firmware-name = "adsp";
};
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 08127d2..904dcba 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1958,11 +1958,13 @@
If unsure, say N.
config MSM_PIL_LPASS_QDSP6V5
- tristate "LPASS QDSP6v5 (Hexagon) Boot Support"
- depends on MSM_PIL
- help
- Support for booting and shutting down QDSP6v5 (Hexagon) processors
- in low power audio subsystems.
+ tristate "LPASS QDSP6v5 (Hexagon) Boot Support"
+ depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
+ help
+ Support for booting and shutting down QDSP6v5 (Hexagon) processors
+ in low power audio subsystems. This driver also monitors the ADSP
+ SMSM status bits and the ADSP's watchdog interrupt and restarts the
+ ADSP if the processor encounters a fatal error.
config MSM_PIL_MSS_QDSP6V5
tristate "MSS QDSP6v5 (Hexagon) Boot Support"
@@ -2037,15 +2039,6 @@
bool "Secure Channel Manager (SCM) support"
default n
-config MSM_ADSP_SSR_8974
- bool "MSM 8974 adsp restart driver"
- depends on (ARCH_MSM8974)
- help
- This option enables the adsp restart driver for the MSM8974.
- It monitors the adsp SMSM status bits and the adsp watchdog line and
- restarts the adsp or the 8974 when the adsp encounters a fatal error,
- depending on the restart level selected in the subsystem restart driver.
-
config MSM_WCNSS_SSR_8974
tristate "MSM 8974 WCNSS restart module"
depends on (ARCH_MSM8974)
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 29d74ef..d5de523 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -200,7 +200,6 @@
obj-y += ramdump.o
endif
obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o
-obj-$(CONFIG_MSM_ADSP_SSR_8974) += adsp-8974.o
obj-$(CONFIG_MSM_WCNSS_SSR_8974) += wcnss-ssr-8974.o
ifdef CONFIG_CPU_IDLE
diff --git a/arch/arm/mach-msm/adsp-8974.c b/arch/arm/mach-msm/adsp-8974.c
deleted file mode 100644
index fa7d9d4..0000000
--- a/arch/arm/mach-msm/adsp-8974.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. 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 and
- * only 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/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/err.h>
-
-#include <mach/irqs.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-
-#include "smd_private.h"
-#include "ramdump.h"
-#include "sysmon.h"
-
-#define SCM_Q6_NMI_CMD 0x1
-#define MODULE_NAME "adsp_8974"
-#define MAX_BUF_SIZE 0x51
-
-/* Interrupt line for WDOG bite*/
-#define ADSP_Q6SS_WDOG_EXPIRED 194
-
-/* Subsystem restart: QDSP6 data, functions */
-static void adsp_fatal_fn(struct work_struct *);
-static DECLARE_WORK(adsp_fatal_work, adsp_fatal_fn);
-
-struct adsp_ssr {
- void *adsp_ramdump_dev;
-} adsp_ssr;
-
-static struct adsp_ssr adsp_ssr_8974;
-static int q6_crash_shutdown;
-
-static int riva_notifier_cb(struct notifier_block *this, unsigned long code,
- void *ss_handle)
-{
- int ret;
- switch (code) {
- case SUBSYS_BEFORE_SHUTDOWN:
- pr_debug("%s: R-Notify: Shutdown started\n", __func__);
- ret = sysmon_send_event(SYSMON_SS_LPASS, "wcnss",
- SUBSYS_BEFORE_SHUTDOWN);
- if (ret < 0)
- pr_err("%s: sysmon_send_event error %d", __func__,
- ret);
- break;
- }
- return NOTIFY_DONE;
-}
-
-static void *ssr_notif_hdle;
-static struct notifier_block rnb = {
- .notifier_call = riva_notifier_cb,
-};
-
-static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
- void *ss_handle)
-{
- int ret;
- switch (code) {
- case SUBSYS_BEFORE_SHUTDOWN:
- pr_debug("%s: M-Notify: Shutdown started\n", __func__);
- ret = sysmon_send_event(SYSMON_SS_LPASS, "modem",
- SUBSYS_BEFORE_SHUTDOWN);
- if (ret < 0)
- pr_err("%s: sysmon_send_event error %d", __func__,
- ret);
- break;
- }
- return NOTIFY_DONE;
-}
-
-static void *ssr_modem_notif_hdle;
-static struct notifier_block mnb = {
- .notifier_call = modem_notifier_cb,
-};
-
-static void adsp_log_failure_reason(void)
-{
- char *reason;
- char buffer[MAX_BUF_SIZE];
- unsigned size;
-
- reason = smem_get_entry(SMEM_SSR_REASON_LPASS0, &size);
-
- if (!reason) {
- pr_err("%s: subsystem failure reason: (unknown, smem_get_entry failed).",
- MODULE_NAME);
- return;
- }
-
- if (reason[0] == '\0') {
- pr_err("%s: subsystem failure reason: (unknown, init value found)",
- MODULE_NAME);
- return;
- }
-
- size = size < MAX_BUF_SIZE ? size : (MAX_BUF_SIZE-1);
- memcpy(buffer, reason, size);
- buffer[size] = '\0';
- pr_err("%s: subsystem failure reason: %s", MODULE_NAME, buffer);
- memset((void *)reason, 0x0, size);
- wmb();
-}
-
-static void restart_adsp(void)
-{
- adsp_log_failure_reason();
- subsystem_restart("adsp");
-}
-
-static void adsp_fatal_fn(struct work_struct *work)
-{
- pr_err("%s %s: Watchdog bite received from Q6!\n", MODULE_NAME,
- __func__);
- restart_adsp();
-}
-
-static void adsp_smsm_state_cb(void *data, uint32_t old_state,
- uint32_t new_state)
-{
- /* Ignore if we're the one that set SMSM_RESET */
- if (q6_crash_shutdown)
- return;
-
- if (new_state & SMSM_RESET) {
- pr_debug("%s: ADSP SMSM state changed to SMSM_RESET, new_state= 0x%x, old_state = 0x%x\n",
- __func__, new_state, old_state);
- restart_adsp();
- }
-}
-
-static void send_q6_nmi(void)
-{
- /* Send NMI to QDSP6 via an SCM call. */
- scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
- pr_debug("%s: Q6 NMI was sent.\n", __func__);
-}
-
-static int adsp_shutdown(const struct subsys_desc *subsys)
-{
- send_q6_nmi();
-
- /* The write needs to go through before the q6 is shutdown. */
- mb();
-
- pil_force_shutdown("adsp");
- disable_irq_nosync(ADSP_Q6SS_WDOG_EXPIRED);
-
- return 0;
-}
-
-static int adsp_powerup(const struct subsys_desc *subsys)
-{
- int ret;
-
- if (get_restart_level() == RESET_SUBSYS_INDEPENDENT) {
- pr_debug("%s: Wait for ADSP power up!", __func__);
- msleep(10000);
- }
-
- ret = pil_force_boot("adsp");
- enable_irq(ADSP_Q6SS_WDOG_EXPIRED);
- return ret;
-}
-/* RAM segments - address and size for 8974 */
-static struct ramdump_segment q6_segment = {0xdc00000, 0x1800000};
-
-static int adsp_ramdump(int enable, const struct subsys_desc *subsys)
-{
- pr_debug("%s: enable[%d]\n", __func__, enable);
- if (enable)
- return do_ramdump(adsp_ssr_8974.adsp_ramdump_dev,
- &q6_segment, 1);
- else
- return 0;
-}
-
-static void adsp_crash_shutdown(const struct subsys_desc *subsys)
-{
- q6_crash_shutdown = 1;
- send_q6_nmi();
-}
-
-static irqreturn_t adsp_wdog_bite_irq(int irq, void *dev_id)
-{
- int ret;
-
- pr_debug("%s: rxed irq[0x%x]", __func__, irq);
- disable_irq_nosync(ADSP_Q6SS_WDOG_EXPIRED);
- ret = schedule_work(&adsp_fatal_work);
-
- return IRQ_HANDLED;
-}
-
-static struct subsys_device *adsp_8974_dev;
-
-static struct subsys_desc adsp_8974 = {
- .name = "adsp",
- .shutdown = adsp_shutdown,
- .powerup = adsp_powerup,
- .ramdump = adsp_ramdump,
- .crash_shutdown = adsp_crash_shutdown
-};
-
-static int __init adsp_restart_init(void)
-{
- adsp_8974_dev = subsys_register(&adsp_8974);
- if (IS_ERR(adsp_8974_dev))
- return PTR_ERR(adsp_8974_dev);
- return 0;
-}
-
-static int __init adsp_fatal_init(void)
-{
- int ret;
-
- ret = smsm_state_cb_register(SMSM_Q6_STATE, SMSM_RESET,
- adsp_smsm_state_cb, 0);
-
- if (ret < 0)
- pr_err("%s: Unable to register SMSM callback! (%d)\n",
- __func__, ret);
-
- ret = request_irq(ADSP_Q6SS_WDOG_EXPIRED, adsp_wdog_bite_irq,
- IRQF_TRIGGER_RISING, "q6_wdog", NULL);
-
- if (ret < 0) {
- pr_err("%s: Unable to request ADSP_Q6SS_WDOG_EXPIRED irq.",
- __func__);
- goto out;
- }
- ret = adsp_restart_init();
- if (ret < 0) {
- pr_err("%s: Unable to reg with adsp ssr. (%d)\n",
- __func__, ret);
- goto out;
- }
-
- adsp_ssr_8974.adsp_ramdump_dev = create_ramdump_device("adsp");
-
- if (!adsp_ssr_8974.adsp_ramdump_dev) {
- pr_err("%s: Unable to create ramdump device.\n",
- __func__);
- ret = -ENOMEM;
- goto out;
- }
- ssr_notif_hdle = subsys_notif_register_notifier("riva",
- &rnb);
- if (IS_ERR(ssr_notif_hdle) < 0) {
- ret = PTR_ERR(ssr_notif_hdle);
- pr_err("%s: subsys_register_notifier for Riva: err = %d\n",
- __func__, ret);
- free_irq(ADSP_Q6SS_WDOG_EXPIRED, NULL);
- goto out;
- }
-
- ssr_modem_notif_hdle = subsys_notif_register_notifier("modem",
- &mnb);
- if (IS_ERR(ssr_modem_notif_hdle) < 0) {
- ret = PTR_ERR(ssr_modem_notif_hdle);
- pr_err("%s: subsys_register_notifier for Modem: err = %d\n",
- __func__, ret);
- subsys_notif_unregister_notifier(ssr_notif_hdle, &rnb);
- free_irq(ADSP_Q6SS_WDOG_EXPIRED, NULL);
- goto out;
- }
-
- pr_info("%s: adsp ssr driver init'ed.\n", __func__);
-out:
- return ret;
-}
-
-static void __exit adsp_fatal_exit(void)
-{
- subsys_notif_unregister_notifier(ssr_notif_hdle, &rnb);
- subsys_notif_unregister_notifier(ssr_modem_notif_hdle, &mnb);
- subsys_unregister(adsp_8974_dev);
- free_irq(ADSP_Q6SS_WDOG_EXPIRED, NULL);
-}
-
-module_init(adsp_fatal_init);
-module_exit(adsp_fatal_exit);
-
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index ad17c9b..c48ea02 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -18,14 +18,39 @@
#include <linux/err.h>
#include <linux/of.h>
#include <linux/clk.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
#include <mach/clk.h>
+#include <mach/subsystem_restart.h>
+#include <mach/subsystem_notif.h>
+#include <mach/scm.h>
+#include <mach/peripheral-loader.h>
+
#include "peripheral-loader.h"
#include "pil-q6v5.h"
#include "scm-pas.h"
+#include "ramdump.h"
+#include "sysmon.h"
#define QDSP6SS_RST_EVB 0x010
#define PROXY_TIMEOUT_MS 10000
+struct lpass_data {
+ struct q6v5_data *q6;
+ struct subsys_device *subsys;
+ struct subsys_desc subsys_desc;
+ void *ramdump_dev;
+ int wdog_irq;
+ struct work_struct work;
+ void *riva_notif_hdle;
+ void *modem_notif_hdle;
+ int crash_shutdown;
+};
+
+#define subsys_to_drv(d) container_of(d, struct lpass_data, subsys_desc)
+
static int pil_lpass_enable_clks(struct q6v5_data *drv)
{
int ret;
@@ -147,36 +172,211 @@
.shutdown = pil_lpass_shutdown_trusted,
};
+static int riva_notifier_cb(struct notifier_block *this, unsigned long code,
+ void *ss_handle)
+{
+ int ret;
+ switch (code) {
+ case SUBSYS_BEFORE_SHUTDOWN:
+ pr_debug("%s: R-Notify: Shutdown started\n", __func__);
+ ret = sysmon_send_event(SYSMON_SS_LPASS, "wcnss",
+ SUBSYS_BEFORE_SHUTDOWN);
+ if (ret < 0)
+ pr_err("%s: sysmon_send_event error %d", __func__, ret);
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block rnb = {
+ .notifier_call = riva_notifier_cb,
+};
+
+static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
+ void *ss_handle)
+{
+ int ret;
+ switch (code) {
+ case SUBSYS_BEFORE_SHUTDOWN:
+ pr_debug("%s: M-Notify: Shutdown started\n", __func__);
+ ret = sysmon_send_event(SYSMON_SS_LPASS, "modem",
+ SUBSYS_BEFORE_SHUTDOWN);
+ if (ret < 0)
+ pr_err("%s: sysmon_send_event error %d", __func__, ret);
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block mnb = {
+ .notifier_call = modem_notifier_cb,
+};
+
+static void adsp_log_failure_reason(void)
+{
+ char *reason;
+ char buffer[81];
+ unsigned size;
+
+ reason = smem_get_entry(SMEM_SSR_REASON_LPASS0, &size);
+
+ if (!reason) {
+ pr_err("ADSP subsystem failure reason: (unknown, smem_get_entry failed).");
+ return;
+ }
+
+ if (reason[0] == '\0') {
+ pr_err("ADSP subsystem failure reason: (unknown, init value found)");
+ return;
+ }
+
+ size = min(size, sizeof(buffer) - 1);
+ memcpy(buffer, reason, size);
+ buffer[size] = '\0';
+ pr_err("ADSP subsystem failure reason: %s", buffer);
+ memset((void *)reason, 0x0, size);
+ wmb();
+}
+
+static void restart_adsp(struct lpass_data *drv)
+{
+ adsp_log_failure_reason();
+ subsystem_restart_dev(drv->subsys);
+}
+
+static void adsp_fatal_fn(struct work_struct *work)
+{
+ struct lpass_data *drv = container_of(work, struct lpass_data, work);
+
+ pr_err("Watchdog bite received from ADSP!\n");
+ restart_adsp(drv);
+}
+
+static void adsp_smsm_state_cb(void *data, uint32_t old_state,
+ uint32_t new_state)
+{
+ struct lpass_data *drv = data;
+
+ /* Ignore if we're the one that set SMSM_RESET */
+ if (drv->crash_shutdown)
+ return;
+
+ if (new_state & SMSM_RESET) {
+ pr_err("%s: ADSP SMSM state changed to SMSM_RESET, new_state = %#x, old_state = %#x\n",
+ __func__, new_state, old_state);
+ restart_adsp(drv);
+ }
+}
+
+#define SCM_Q6_NMI_CMD 0x1
+
+static void send_q6_nmi(void)
+{
+ /* Send NMI to QDSP6 via an SCM call. */
+ scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
+ pr_debug("%s: Q6 NMI was sent.\n", __func__);
+}
+
+#define subsys_to_lpass(d) container_of(d, struct lpass_data, subsys_desc)
+
+static int adsp_shutdown(const struct subsys_desc *subsys)
+{
+ struct lpass_data *drv = subsys_to_lpass(subsys);
+
+ send_q6_nmi();
+ /* The write needs to go through before the q6 is shutdown. */
+ mb();
+ pil_force_shutdown("adsp");
+ disable_irq_nosync(drv->wdog_irq);
+
+ return 0;
+}
+
+static int adsp_powerup(const struct subsys_desc *subsys)
+{
+ struct lpass_data *drv = subsys_to_lpass(subsys);
+ int ret = 0;
+
+ if (get_restart_level() == RESET_SUBSYS_INDEPENDENT) {
+ pr_debug("%s: Wait for ADSP power up!", __func__);
+ msleep(10000);
+ }
+
+ ret = pil_force_boot("adsp");
+ enable_irq(drv->wdog_irq);
+
+ return ret;
+}
+
+static struct ramdump_segment segments = { 0xdc00000, 0x1800000 };
+
+static int adsp_ramdump(int enable, const struct subsys_desc *subsys)
+{
+ struct lpass_data *drv = subsys_to_lpass(subsys);
+
+ if (!enable)
+ return 0;
+ return do_ramdump(drv->ramdump_dev, &segments, 1);
+}
+
+static void adsp_crash_shutdown(const struct subsys_desc *subsys)
+{
+ struct lpass_data *drv = subsys_to_lpass(subsys);
+
+ drv->crash_shutdown = 1;
+ send_q6_nmi();
+}
+
+static irqreturn_t adsp_wdog_bite_irq(int irq, void *dev_id)
+{
+ struct lpass_data *drv = dev_id;
+
+ disable_irq_nosync(drv->wdog_irq);
+ schedule_work(&drv->work);
+
+ return IRQ_HANDLED;
+}
+
static int __devinit pil_lpass_driver_probe(struct platform_device *pdev)
{
- struct q6v5_data *drv;
+ struct lpass_data *drv;
+ struct q6v5_data *q6;
struct pil_desc *desc;
+ int ret;
- drv = pil_q6v5_init(pdev);
- if (IS_ERR(drv))
- return PTR_ERR(drv);
+ drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
platform_set_drvdata(pdev, drv);
- desc = &drv->desc;
- desc->ops = &pil_lpass_ops;
+ drv->wdog_irq = platform_get_irq(pdev, 0);
+ if (drv->wdog_irq < 0)
+ return drv->wdog_irq;
+
+ q6 = pil_q6v5_init(pdev);
+ if (IS_ERR(q6))
+ return PTR_ERR(q6);
+ drv->q6 = q6;
+
+ desc = &q6->desc;
desc->owner = THIS_MODULE;
desc->proxy_timeout = PROXY_TIMEOUT_MS;
- drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
- if (IS_ERR(drv->core_clk))
- return PTR_ERR(drv->core_clk);
+ q6->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(q6->core_clk))
+ return PTR_ERR(q6->core_clk);
- drv->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
- if (IS_ERR(drv->ahb_clk))
- return PTR_ERR(drv->ahb_clk);
+ q6->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(q6->ahb_clk))
+ return PTR_ERR(q6->ahb_clk);
- drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
- if (IS_ERR(drv->axi_clk))
- return PTR_ERR(drv->axi_clk);
+ q6->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
+ if (IS_ERR(q6->axi_clk))
+ return PTR_ERR(q6->axi_clk);
- drv->reg_clk = devm_clk_get(&pdev->dev, "reg_clk");
- if (IS_ERR(drv->reg_clk))
- return PTR_ERR(drv->reg_clk);
+ q6->reg_clk = devm_clk_get(&pdev->dev, "reg_clk");
+ if (IS_ERR(q6->reg_clk))
+ return PTR_ERR(q6->reg_clk);
if (pas_supported(PAS_Q6) > 0) {
desc->ops = &pil_lpass_ops_trusted;
@@ -186,17 +386,79 @@
dev_info(&pdev->dev, "using non-secure boot\n");
}
- drv->pil = msm_pil_register(desc);
- if (IS_ERR(drv->pil))
- return PTR_ERR(drv->pil);
+ drv->q6->pil = msm_pil_register(desc);
+ if (IS_ERR(drv->q6->pil))
+ return PTR_ERR(drv->q6->pil);
+ drv->subsys_desc.name = desc->name;
+ drv->subsys_desc.owner = THIS_MODULE;
+ drv->subsys_desc.dev = &pdev->dev;
+ drv->subsys_desc.shutdown = adsp_shutdown;
+ drv->subsys_desc.powerup = adsp_powerup;
+ drv->subsys_desc.ramdump = adsp_ramdump;
+ drv->subsys_desc.crash_shutdown = adsp_crash_shutdown;
+
+ INIT_WORK(&drv->work, adsp_fatal_fn);
+
+ drv->ramdump_dev = create_ramdump_device("adsp");
+ if (!drv->ramdump_dev) {
+ ret = -ENOMEM;
+ goto err_ramdump;
+ }
+
+ drv->subsys = subsys_register(&drv->subsys_desc);
+ if (IS_ERR(drv->subsys)) {
+ ret = PTR_ERR(drv->subsys);
+ goto err_subsys;
+ }
+
+ ret = devm_request_irq(&pdev->dev, drv->wdog_irq, adsp_wdog_bite_irq,
+ IRQF_TRIGGER_RISING, dev_name(&pdev->dev), drv);
+ if (ret)
+ goto err_irq;
+
+ ret = smsm_state_cb_register(SMSM_Q6_STATE, SMSM_RESET,
+ adsp_smsm_state_cb, drv);
+ if (ret < 0)
+ goto err_smsm;
+
+ drv->riva_notif_hdle = subsys_notif_register_notifier("riva", &rnb);
+ if (IS_ERR(drv->riva_notif_hdle)) {
+ ret = PTR_ERR(drv->riva_notif_hdle);
+ goto err_notif_riva;
+ }
+
+ drv->modem_notif_hdle = subsys_notif_register_notifier("modem", &mnb);
+ if (IS_ERR(drv->modem_notif_hdle)) {
+ ret = PTR_ERR(drv->modem_notif_hdle);
+ goto err_notif_modem;
+ }
+ return 0;
+err_notif_modem:
+ subsys_notif_unregister_notifier(drv->riva_notif_hdle, &rnb);
+err_notif_riva:
+ smsm_state_cb_deregister(SMSM_Q6_STATE, SMSM_RESET,
+ adsp_smsm_state_cb, drv);
+err_smsm:
+err_irq:
+ subsys_unregister(drv->subsys);
+err_subsys:
+ destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+ msm_pil_unregister(drv->q6->pil);
return 0;
}
static int __devexit pil_lpass_driver_exit(struct platform_device *pdev)
{
- struct q6v5_data *drv = platform_get_drvdata(pdev);
- msm_pil_unregister(drv->pil);
+ struct lpass_data *drv = platform_get_drvdata(pdev);
+ subsys_notif_unregister_notifier(drv->riva_notif_hdle, &rnb);
+ subsys_notif_unregister_notifier(drv->modem_notif_hdle, &mnb);
+ smsm_state_cb_deregister(SMSM_Q6_STATE, SMSM_RESET,
+ adsp_smsm_state_cb, drv);
+ subsys_unregister(drv->subsys);
+ destroy_ramdump_device(drv->ramdump_dev);
+ msm_pil_unregister(drv->q6->pil);
return 0;
}
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index 43d7a2c..70a12de 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -217,10 +217,7 @@
if (!drv->axi_halt_base)
return ERR_PTR(-ENOMEM);
- desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
- if (!desc)
- return ERR_PTR(-ENOMEM);
-
+ desc = &drv->desc;
ret = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
&desc->name);
if (ret)