| From e3cabcd484fc0c36f73e482743225be9875f4f2b Mon Sep 17 00:00:00 2001 |
| From: Fabrizio Castro <fabrizio.castro@bp.renesas.com> |
| Date: Mon, 5 Mar 2018 15:30:25 +0000 |
| Subject: [PATCH 0891/1795] watchdog: renesas_wdt: Add R-Car Gen2 support |
| |
| Due to commits: |
| * "ARM: shmobile: Add watchdog support", |
| * "ARM: shmobile: rcar-gen2: Add watchdog support", and |
| * "soc: renesas: rcar-rst: Enable watchdog as reset trigger for Gen2", |
| we now have everything we needed for the watchdog to work on Gen2 and |
| RZ/G1. |
| |
| However, on early revisions of some R-Car Gen2 SoCs, and depending on SMP |
| configuration, the system may fail to restart on watchdog time-out, and |
| lock up instead. |
| |
| Specifically: |
| - On R-Car H2 ES1.0 and M2-W ES1.0, watchdog restart fails unless |
| only the first CPU core is in use (using e.g. the "maxcpus=1" kernel |
| commandline option). |
| - On R-Car V2H ES1.1, watchdog restart fails unless SMP is disabled |
| completely (using CONFIG_SMP=n during build configuration, or using |
| the "nosmp" or "maxcpus=0" kernel commandline options). |
| |
| This commit adds "renesas,rcar-gen2-wdt" as compatible string for R-Car |
| Gen2 and RZ/G1, but also prevents the system from using the watchdog |
| driver in cases where the system would fail to restart by blacklisting |
| the affected SoCs, using the minimum known working revisions (ES2.0 on R-Car |
| H2, and ES3.0 on M2-W), and taking the actual SMP software configuration |
| into account. |
| |
| Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com> |
| Signed-off-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com> |
| [Geert: blacklisting logic] |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com> |
| Reviewed-by: Guenter Roeck <linux@roeck-us.net> |
| Signed-off-by: Guenter Roeck <linux@roeck-us.net> |
| Signed-off-by: Wim Van Sebroeck <wim@iguana.be> |
| |
| (cherry picked from commit 3fe95e6c68e6258410e85488af9e1b1ff545b831) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| drivers/watchdog/renesas_wdt.c | 49 ++++++++++++++++++++++++++++++---- |
| 1 file changed, 44 insertions(+), 5 deletions(-) |
| |
| diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c |
| index 024d54eda11e..0dede5beb3f1 100644 |
| --- a/drivers/watchdog/renesas_wdt.c |
| +++ b/drivers/watchdog/renesas_wdt.c |
| @@ -16,6 +16,8 @@ |
| #include <linux/of.h> |
| #include <linux/platform_device.h> |
| #include <linux/pm_runtime.h> |
| +#include <linux/smp.h> |
| +#include <linux/sys_soc.h> |
| #include <linux/watchdog.h> |
| |
| #define RWTCNT 0 |
| @@ -121,6 +123,44 @@ static const struct watchdog_ops rwdt_ops = { |
| .get_timeleft = rwdt_get_timeleft, |
| }; |
| |
| +#if defined(CONFIG_ARCH_RCAR_GEN2) && defined(CONFIG_SMP) |
| +/* |
| + * Watchdog-reset integration is broken on early revisions of R-Car Gen2 SoCs |
| + */ |
| +static const struct soc_device_attribute rwdt_quirks_match[] = { |
| + { |
| + .soc_id = "r8a7790", |
| + .revision = "ES1.*", |
| + .data = (void *)1, /* needs single CPU */ |
| + }, { |
| + .soc_id = "r8a7791", |
| + .revision = "ES[12].*", |
| + .data = (void *)1, /* needs single CPU */ |
| + }, { |
| + .soc_id = "r8a7792", |
| + .revision = "*", |
| + .data = (void *)0, /* needs SMP disabled */ |
| + }, |
| + { /* sentinel */ } |
| +}; |
| + |
| +static bool rwdt_blacklisted(struct device *dev) |
| +{ |
| + const struct soc_device_attribute *attr; |
| + |
| + attr = soc_device_match(rwdt_quirks_match); |
| + if (attr && setup_max_cpus > (uintptr_t)attr->data) { |
| + dev_info(dev, "Watchdog blacklisted on %s %s\n", attr->soc_id, |
| + attr->revision); |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| +#else /* !CONFIG_ARCH_RCAR_GEN2 || !CONFIG_SMP */ |
| +static inline bool rwdt_blacklisted(struct device *dev) { return false; } |
| +#endif /* !CONFIG_ARCH_RCAR_GEN2 || !CONFIG_SMP */ |
| + |
| static int rwdt_probe(struct platform_device *pdev) |
| { |
| struct rwdt_priv *priv; |
| @@ -129,6 +169,9 @@ static int rwdt_probe(struct platform_device *pdev) |
| unsigned long clks_per_sec; |
| int ret, i; |
| |
| + if (rwdt_blacklisted(&pdev->dev)) |
| + return -ENODEV; |
| + |
| priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
| if (!priv) |
| return -ENOMEM; |
| @@ -228,12 +271,8 @@ static int __maybe_unused rwdt_resume(struct device *dev) |
| |
| static SIMPLE_DEV_PM_OPS(rwdt_pm_ops, rwdt_suspend, rwdt_resume); |
| |
| -/* |
| - * This driver does also fit for R-Car Gen2 (r8a779[0-4]) WDT. However, for SMP |
| - * to work there, one also needs a RESET (RST) driver which does not exist yet |
| - * due to HW issues. This needs to be solved before adding compatibles here. |
| - */ |
| static const struct of_device_id rwdt_ids[] = { |
| + { .compatible = "renesas,rcar-gen2-wdt", }, |
| { .compatible = "renesas,rcar-gen3-wdt", }, |
| { /* sentinel */ } |
| }; |
| -- |
| 2.19.0 |
| |