From: Evan Benn <evanbenn@chromium.org> To: LKML <linux-kernel@vger.kernel.org> Cc: jwerner@chromium.org, "Evan Benn" <evanbenn@chromium.org>, "Bjorn Andersson" <bjorn.andersson@linaro.org>, "Guenter Roeck" <linux@roeck-us.net>, "Mauro Carvalho Chehab" <mchehab+samsung@kernel.org>, "Marcin Juszkiewicz" <marcin.juszkiewicz@linaro.org>, "Catalin Marinas" <catalin.marinas@arm.com>, "Olof Johansson" <olof@lixom.net>, "Leonard Crestez" <leonard.crestez@nxp.com>, "Jonathan Cameron" <Jonathan.Cameron@huawei.com>, "Dinh Nguyen" <dinguyen@kernel.org>, linux-arm-kernel@lists.infradead.org, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Will Deacon" <will@kernel.org>, linux-watchdog@vger.kernel.org, "Rob Herring" <robh@kernel.org>, "Wim Van Sebroeck" <wim@linux-watchdog.org>, "Clément Péron" <peron.clem@gmail.com>, "Shawn Guo" <shawnguo@kernel.org>, "David S. Miller" <davem@davemloft.net>, "Anson Huang" <Anson.Huang@nxp.com> Subject: [PATCH 2/2] watchdog: Add new arm_smc_wdt watchdog driver Date: Fri, 14 Feb 2020 17:26:37 +1100 Message-ID: <20200214172512.2.I7c8247c29891a538f258cb47828d58acf22c95a2@changeid> (raw) In-Reply-To: <20200214062637.216209-1-evanbenn@chromium.org> From: Julius Werner <jwerner@chromium.org> This patch adds a stub watchdog driver that can be used on ARM systems with a Secure Monitor firmware to forward watchdog operations to firmware via a Secure Monitor Call. This may be useful for platforms using TrustZone that want the Secure Monitor firmware to have the final control over the watchdog. Signed-off-by: Julius Werner <jwerner@chromium.org> Signed-off-by: Evan Benn <evanbenn@chromium.org> --- MAINTAINERS | 1 + arch/arm64/configs/defconfig | 1 + drivers/watchdog/Kconfig | 12 +++ drivers/watchdog/Makefile | 1 + drivers/watchdog/arm_smc_wdt.c | 191 +++++++++++++++++++++++++++++++++ 5 files changed, 206 insertions(+) create mode 100644 drivers/watchdog/arm_smc_wdt.c diff --git a/MAINTAINERS b/MAINTAINERS index 5c45536e1177..71df3c110fdb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1426,6 +1426,7 @@ M: Julius Werner <jwerner@chromium.org> R: Evan Benn <evanbenn@chromium.org> S: Maintained F: devicetree/bindings/watchdog/arm,smc-wdt.yaml +F: drivers/watchdog/arm_smc_wdt.c ARM SMMU DRIVERS M: Will Deacon <will@kernel.org> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index b2f667307f82..8527db9e92a6 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -451,6 +451,7 @@ CONFIG_QCOM_TSENS=y CONFIG_UNIPHIER_THERMAL=y CONFIG_WATCHDOG=y CONFIG_ARM_SP805_WATCHDOG=y +CONFIG_ARM_SMC_WATCHDOG=y CONFIG_S3C2410_WATCHDOG=y CONFIG_DW_WATCHDOG=y CONFIG_SUNXI_WATCHDOG=m diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index cec868f8db3f..0f7f93342051 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -857,6 +857,18 @@ config DIGICOLOR_WATCHDOG To compile this driver as a module, choose M here: the module will be called digicolor_wdt. +config ARM_SMC_WATCHDOG + tristate "ARM Secure Monitor Call based watchdog support" + depends on ARM || ARM64 + select WATCHDOG_CORE + help + Say Y here to include support for a watchdog timer + implemented by the EL3 Secure Monitor on ARM platforms. + Requires firmware support. + To compile this driver as a module, choose M here: the + module will be called arm_smc_wdt. + + config LPC18XX_WATCHDOG tristate "LPC18xx/43xx Watchdog" depends on ARCH_LPC18XX || COMPILE_TEST diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 2ee352bf3372..a1e6d83a7659 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -92,6 +92,7 @@ obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o obj-$(CONFIG_RTD119X_WATCHDOG) += rtd119x_wdt.o obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o +obj-$(CONFIG_ARM_SMC_WATCHDOG) += arm_smc_wdt.o obj-$(CONFIG_PM8916_WATCHDOG) += pm8916_wdt.o # X86 (i386 + ia64 + x86_64) Architecture diff --git a/drivers/watchdog/arm_smc_wdt.c b/drivers/watchdog/arm_smc_wdt.c new file mode 100644 index 000000000000..58e7294136ef --- /dev/null +++ b/drivers/watchdog/arm_smc_wdt.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ARM Secure Monitor Call watchdog driver + * + * Copyright 2018 The Chromium OS Authors. All rights reserved. + * + * Julius Werner <jwerner@chromium.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * Based on mtk_wdt.c + */ + +#include <linux/arm-smccc.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/watchdog.h> +#include <uapi/linux/psci.h> + +#define DRV_NAME "arm_smc_wdt" +#define DRV_VERSION "1.0" + +#define SMCWD_FUNC_ID 0x82003d06 + +enum smcwd_call { + SMCWD_INFO = 0, + SMCWD_SET_TIMEOUT = 1, + SMCWD_ENABLE = 2, + SMCWD_PET = 3, +}; + +static bool nowayout = WATCHDOG_NOWAYOUT; +static unsigned int timeout; + +static int smcwd_call(enum smcwd_call call, unsigned long arg, + struct arm_smccc_res *res) +{ + struct arm_smccc_res local_res; + + if (!res) + res = &local_res; + + arm_smccc_smc(SMCWD_FUNC_ID, call, arg, 0, 0, 0, 0, 0, res); + + if ((int)res->a0 == PSCI_RET_NOT_SUPPORTED) + return -ENOTSUPP; + if ((int)res->a0 == PSCI_RET_INVALID_PARAMS) + return -EINVAL; + if ((int)res->a0 < 0) + return -EIO; + return res->a0; +} + +static int smcwd_ping(struct watchdog_device *wdd) +{ + return smcwd_call(SMCWD_PET, 0, NULL); +} + +static int smcwd_set_timeout(struct watchdog_device *wdd, + unsigned int timeout) +{ + int res; + + res = smcwd_call(SMCWD_SET_TIMEOUT, timeout, NULL); + if (!res) + wdd->timeout = timeout; + return res; +} + +static int smcwd_stop(struct watchdog_device *wdd) +{ + return smcwd_call(SMCWD_ENABLE, 0, NULL); +} + +static int smcwd_start(struct watchdog_device *wdd) +{ + return smcwd_call(SMCWD_ENABLE, 1, NULL); +} + +static const struct watchdog_info smcwd_info = { + .identity = DRV_NAME, + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, +}; + +static const struct watchdog_ops smcwd_ops = { + .owner = THIS_MODULE, + .start = smcwd_start, + .stop = smcwd_stop, + .ping = smcwd_ping, + .set_timeout = smcwd_set_timeout, +}; + +static int smcwd_probe(struct platform_device *pdev) +{ + struct watchdog_device *wdd; + int err; + struct arm_smccc_res res; + + err = smcwd_call(SMCWD_INFO, 0, &res); + if (err < 0) + return err; + + wdd = devm_kzalloc(&pdev->dev, sizeof(*wdd), GFP_KERNEL); + if (!wdd) + return -ENOMEM; + + platform_set_drvdata(pdev, wdd); + + wdd->info = &smcwd_info; + wdd->ops = &smcwd_ops; + wdd->timeout = res.a2; + wdd->max_timeout = res.a2; + wdd->min_timeout = res.a1; + wdd->parent = &pdev->dev; + + watchdog_set_nowayout(wdd, nowayout); + watchdog_init_timeout(wdd, timeout, &pdev->dev); + err = smcwd_set_timeout(wdd, wdd->timeout); + if (err) + return err; + + err = watchdog_register_device(wdd); + if (err) + return err; + + dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n", + wdd->timeout, nowayout); + + return 0; +} + +static void smcwd_shutdown(struct platform_device *pdev) +{ + struct watchdog_device *wdd = platform_get_drvdata(pdev); + + if (watchdog_active(wdd)) + smcwd_stop(wdd); +} + +static int smcwd_remove(struct platform_device *pdev) +{ + struct watchdog_device *wdd = platform_get_drvdata(pdev); + + watchdog_unregister_device(wdd); + + return 0; +} + +static const struct of_device_id smcwd_dt_ids[] = { + { .compatible = "arm,smc-wdt" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, smcwd_dt_ids); + +static struct platform_driver smcwd_driver = { + .probe = smcwd_probe, + .remove = smcwd_remove, + .shutdown = smcwd_shutdown, + .driver = { + .name = DRV_NAME, + .of_match_table = smcwd_dt_ids, + }, +}; + +module_platform_driver(smcwd_driver); + +module_param(timeout, uint, 0); +MODULE_PARM_DESC(timeout, "Watchdog heartbeat in seconds"); + +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Julius Werner <jwerner@chromium.org>"); +MODULE_DESCRIPTION("ARM Secure Monitor Call Watchdog Driver"); +MODULE_VERSION(DRV_VERSION); -- 2.25.0.265.gbab2e86ba0-goog
next prev parent reply index Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-02-14 6:26 [PATCH 0/2] Add a watchdog driver that uses ARM Secure Monitor Calls Evan Benn 2020-02-14 6:26 ` [PATCH 1/2] dt-bindings: watchdog: Add arm,smc-wdt watchdog arm,smc-wdt compatible Evan Benn 2020-02-19 22:30 ` Rob Herring 2020-02-19 23:04 ` Julius Werner 2020-02-19 23:20 ` Guenter Roeck 2020-02-20 6:41 ` Evan Benn 2020-02-20 15:43 ` Guenter Roeck 2020-02-21 15:36 ` Xingyu Chen 2020-02-21 19:41 ` Julius Werner 2020-02-21 20:46 ` Guenter Roeck 2020-02-22 4:01 ` Xingyu Chen 2020-02-24 1:10 ` Evan Benn 2020-02-25 1:23 ` Julius Werner 2020-02-25 7:44 ` Xingyu Chen 2020-03-10 1:00 ` Evan Benn [not found] ` <ad28aa47-0490-937f-898f-0e4695ef6ec6@amlogic.com> 2020-03-11 19:24 ` Julius Werner 2020-03-13 16:13 ` Xingyu Chen 2020-02-14 6:26 ` Evan Benn [this message] 2020-02-14 9:35 ` [PATCH 2/2] watchdog: Add new arm_smc_wdt watchdog driver Enric Balletbo Serra 2020-02-14 14:10 ` Guenter Roeck 2020-02-14 21:32 ` Julius Werner 2020-02-15 1:39 ` Evan Benn 2020-02-20 6:50 ` Evan Benn 2020-02-20 15:52 ` Guenter Roeck
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200214172512.2.I7c8247c29891a538f258cb47828d58acf22c95a2@changeid \ --to=evanbenn@chromium.org \ --cc=Anson.Huang@nxp.com \ --cc=Jonathan.Cameron@huawei.com \ --cc=bjorn.andersson@linaro.org \ --cc=catalin.marinas@arm.com \ --cc=davem@davemloft.net \ --cc=dinguyen@kernel.org \ --cc=gregkh@linuxfoundation.org \ --cc=jwerner@chromium.org \ --cc=leonard.crestez@nxp.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-watchdog@vger.kernel.org \ --cc=linux@roeck-us.net \ --cc=marcin.juszkiewicz@linaro.org \ --cc=mchehab+samsung@kernel.org \ --cc=olof@lixom.net \ --cc=peron.clem@gmail.com \ --cc=robh@kernel.org \ --cc=shawnguo@kernel.org \ --cc=will@kernel.org \ --cc=wim@linux-watchdog.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Linux-Watchdog Archive on lore.kernel.org Archives are clonable: git clone --mirror https://lore.kernel.org/linux-watchdog/0 linux-watchdog/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 linux-watchdog linux-watchdog/ https://lore.kernel.org/linux-watchdog \ linux-watchdog@vger.kernel.org public-inbox-index linux-watchdog Example config snippet for mirrors Newsgroup available over NNTP: nntp://nntp.lore.kernel.org/org.kernel.vger.linux-watchdog AGPL code for this site: git clone https://public-inbox.org/public-inbox.git