Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04085c1d authored by Branden Bonaby's avatar Branden Bonaby
Browse files

soc: qcom: Add qcom watchdog framework support



Refactor the soc watchdog driver to use the
qcom watchdog framework.

Change-Id: I12a6afff4299bb39cacca27bcf483e08a503add0
Signed-off-by: default avatarBranden Bonaby <bbonaby@codeaurora.org>
parent 065a08cb
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -795,6 +795,16 @@ config QCOM_WDT_CORE
	   watchdog module must be loaded along with this for watchdog
	   functionality.

config QCOM_SOC_WATCHDOG
	tristate "Qualcomm Technologies, Inc. Soc Watchdog"
	depends on QCOM_WDT_CORE
	help
	  This enables the Qualcomm Technologies, Inc. watchdog module for the
	  Soc. It provides an interface to perform watchdog actions such as
	  setting the bark/bite time and also petting the hardware watchdog. To
	  utilize this the Qualcomm Technologies, Inc. watchdog framework must
	  also be enabled.

config QCOM_FORCE_WDOG_BITE_ON_PANIC
	bool "QCOM force watchdog bite on panic"
	depends on QCOM_WDT_CORE
+1 −0
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ obj-$(CONFIG_QTI_CRYPTO_COMMON) += crypto-qti-common.o
obj-$(CONFIG_QTI_CRYPTO_TZ) += crypto-qti-tz.o
obj-$(CONFIG_QTI_HW_KEY_MANAGER) += hwkm.o crypto-qti-hwkm.o
obj-$(CONFIG_QCOM_WDT_CORE) += qcom_wdt_core.o
obj-$(CONFIG_QCOM_SOC_WATCHDOG) += qcom_soc_wdt.o
ifdef CONFIG_DEBUG_FS
obj-$(CONFIG_MSM_RPM_SMD)   +=  rpm-smd-debug.o
endif
+150 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
 *
 */

#include <soc/qcom/watchdog.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/io.h>

#define WDT0_RST                0x04
#define WDT0_EN                 0x08
#define WDT0_STS                0x0C
#define WDT0_BARK_TIME          0x10
#define WDT0_BITE_TIME          0x14
#define WDT_HZ                  32765

static inline int qcom_soc_set_wdt_bark(u32 time,
					struct msm_watchdog_data *wdog_dd)
{
	__raw_writel((time * WDT_HZ)/1000, wdog_dd->base + WDT0_BARK_TIME);
	/* Make sure register write is complete before proceeding */
	mb();
	return 0;
}

static inline int qcom_soc_set_wdt_bite(u32 time,
					struct msm_watchdog_data *wdog_dd)
{
	__raw_writel((time * WDT_HZ)/1000, wdog_dd->base + WDT0_BITE_TIME);
	/* Make sure register write is complete before proceeding */
	mb();
	return 0;
}



static inline int qcom_soc_reset_wdt(struct msm_watchdog_data *wdog_dd)
{
	__raw_writel(1, wdog_dd->base + WDT0_RST);
	/* Make sure register write is complete before proceeding */
	mb();
	return 0;
}

static inline int qcom_soc_enable_wdt(u32 val,
					 struct msm_watchdog_data *wdog_dd)
{
	__raw_writel(val, wdog_dd->base + WDT0_EN);
	/* Make sure register write is complete before proceeding */
	mb();
	return 0;
}

static inline int qcom_soc_disable_wdt(struct msm_watchdog_data *wdog_dd)
{
	__raw_writel(0, wdog_dd->base + WDT0_EN);
	/* Make sure register write is complete before proceeding */
	mb();
	return 0;
}

static inline int qcom_soc_show_wdt_status(struct msm_watchdog_data *wdog_dd)
{
	dev_err(wdog_dd->dev, "Wdog - STS: 0x%x, CTL: 0x%x, BARK TIME: 0x%x, BITE TIME: 0x%x\n",
			__raw_readl(wdog_dd->base + WDT0_STS),
			__raw_readl(wdog_dd->base + WDT0_EN),
			__raw_readl(wdog_dd->base + WDT0_BARK_TIME),
			__raw_readl(wdog_dd->base + WDT0_BITE_TIME));
	return 0;
}

static struct qcom_wdt_ops qcom_soc_wdt_ops = {
	.set_bark_time     = qcom_soc_set_wdt_bark,
	.set_bite_time     = qcom_soc_set_wdt_bite,
	.reset_wdt         = qcom_soc_reset_wdt,
	.enable_wdt        = qcom_soc_enable_wdt,
	.disable_wdt       = qcom_soc_disable_wdt,
	.show_wdt_status   = qcom_soc_show_wdt_status
};

static int qcom_soc_wdt_probe(struct platform_device *pdev)
{
	struct resource *res;
	struct msm_watchdog_data *wdog_dd;

	wdog_dd = devm_kzalloc(&pdev->dev, sizeof(*wdog_dd), GFP_KERNEL);
	if (!wdog_dd)
		return -ENOMEM;
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wdt-base");
	if (!res)
		return -ENODEV;

	wdog_dd->base  = devm_ioremap_resource(&pdev->dev, res);
	if (!wdog_dd->base) {
		dev_err(&pdev->dev, "%s cannot map wdog register space\n",
				__func__);
		return -ENXIO;
	}
	wdog_dd->ops = &qcom_soc_wdt_ops;

	return qcom_wdt_register(pdev, wdog_dd, "msm-watchdog");
}

#ifdef CONFIG_PM_SLEEP
static const struct dev_pm_ops qcom_soc_dev_pm_ops = {
	.suspend_noirq = qcom_wdt_suspend,
	.resume_noirq = qcom_wdt_resume,
};
#else
static const struct dev_pm_ops qcom_soc_dev_pm_ops = {
};
#endif

static const struct of_device_id qcom_soc_match_table[] = {
	{ .compatible = "qcom,msm-watchdog" },
	{}
};

static struct platform_driver qcom_soc_wdt_driver = {
	.probe = qcom_soc_wdt_probe,
	.remove = qcom_wdt_remove,
	.driver = {
		.name = "msm_watchdog",
		.pm = &qcom_soc_dev_pm_ops,
		.of_match_table = qcom_soc_match_table,
	},
};

static int __init init_watchdog(void)
{
	return platform_driver_register(&qcom_soc_wdt_driver);
}

#if IS_MODULE(CONFIG_QCOM_SOC_WATCHDOG)
module_init(init_watchdog);
#else
pure_initcall(init_watchdog);
#endif

static __exit void exit_watchdog(void)
{
	platform_driver_unregister(&qcom_soc_wdt_driver);
}
module_exit(exit_watchdog);
MODULE_DESCRIPTION("QCOM Soc Watchdog Driver");
MODULE_LICENSE("GPL v2");