aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/watchdog/renesas_wdt.c49
1 files 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 @@
16#include <linux/of.h> 16#include <linux/of.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/pm_runtime.h> 18#include <linux/pm_runtime.h>
19#include <linux/smp.h>
20#include <linux/sys_soc.h>
19#include <linux/watchdog.h> 21#include <linux/watchdog.h>
20 22
21#define RWTCNT 0 23#define RWTCNT 0
@@ -121,6 +123,44 @@ static const struct watchdog_ops rwdt_ops = {
121 .get_timeleft = rwdt_get_timeleft, 123 .get_timeleft = rwdt_get_timeleft,
122}; 124};
123 125
126#if defined(CONFIG_ARCH_RCAR_GEN2) && defined(CONFIG_SMP)
127/*
128 * Watchdog-reset integration is broken on early revisions of R-Car Gen2 SoCs
129 */
130static const struct soc_device_attribute rwdt_quirks_match[] = {
131 {
132 .soc_id = "r8a7790",
133 .revision = "ES1.*",
134 .data = (void *)1, /* needs single CPU */
135 }, {
136 .soc_id = "r8a7791",
137 .revision = "ES[12].*",
138 .data = (void *)1, /* needs single CPU */
139 }, {
140 .soc_id = "r8a7792",
141 .revision = "*",
142 .data = (void *)0, /* needs SMP disabled */
143 },
144 { /* sentinel */ }
145};
146
147static bool rwdt_blacklisted(struct device *dev)
148{
149 const struct soc_device_attribute *attr;
150
151 attr = soc_device_match(rwdt_quirks_match);
152 if (attr && setup_max_cpus > (uintptr_t)attr->data) {
153 dev_info(dev, "Watchdog blacklisted on %s %s\n", attr->soc_id,
154 attr->revision);
155 return true;
156 }
157
158 return false;
159}
160#else /* !CONFIG_ARCH_RCAR_GEN2 || !CONFIG_SMP */
161static inline bool rwdt_blacklisted(struct device *dev) { return false; }
162#endif /* !CONFIG_ARCH_RCAR_GEN2 || !CONFIG_SMP */
163
124static int rwdt_probe(struct platform_device *pdev) 164static int rwdt_probe(struct platform_device *pdev)
125{ 165{
126 struct rwdt_priv *priv; 166 struct rwdt_priv *priv;
@@ -129,6 +169,9 @@ static int rwdt_probe(struct platform_device *pdev)
129 unsigned long clks_per_sec; 169 unsigned long clks_per_sec;
130 int ret, i; 170 int ret, i;
131 171
172 if (rwdt_blacklisted(&pdev->dev))
173 return -ENODEV;
174
132 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 175 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
133 if (!priv) 176 if (!priv)
134 return -ENOMEM; 177 return -ENOMEM;
@@ -228,12 +271,8 @@ static int __maybe_unused rwdt_resume(struct device *dev)
228 271
229static SIMPLE_DEV_PM_OPS(rwdt_pm_ops, rwdt_suspend, rwdt_resume); 272static SIMPLE_DEV_PM_OPS(rwdt_pm_ops, rwdt_suspend, rwdt_resume);
230 273
231/*
232 * This driver does also fit for R-Car Gen2 (r8a779[0-4]) WDT. However, for SMP
233 * to work there, one also needs a RESET (RST) driver which does not exist yet
234 * due to HW issues. This needs to be solved before adding compatibles here.
235 */
236static const struct of_device_id rwdt_ids[] = { 274static const struct of_device_id rwdt_ids[] = {
275 { .compatible = "renesas,rcar-gen2-wdt", },
237 { .compatible = "renesas,rcar-gen3-wdt", }, 276 { .compatible = "renesas,rcar-gen3-wdt", },
238 { /* sentinel */ } 277 { /* sentinel */ }
239}; 278};