mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
watchdog: sama5d4_wdt: Fix WDDIS detection on SAM9X60 and SAMA7G5
The driver hardcoded AT91_WDT_WDDIS (bit 15) in wdt_enabled and the
probe initial state readout. SAM9X60 and SAMA7G5 use bit 12
(AT91_SAM9X60_WDDIS), causing incorrect WDDIS detection.
Introduce a per-device wddis_mask field to select the correct WDDIS
bit based on the compatible string.
Fixes: 266da53c35 ("watchdog: sama5d4: readout initial state")
Co-developed-by: Andrei Simion <andrei.simion@microchip.com>
Signed-off-by: Andrei Simion <andrei.simion@microchip.com>
Signed-off-by: Balakrishnan Sambath <balakrishnan.s@microchip.com>
Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20260302113310.133989-2-balakrishnan.s@microchip.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
parent
ca316e145c
commit
e8bc610b14
|
|
@ -30,6 +30,7 @@ struct sama5d4_wdt {
|
|||
void __iomem *reg_base;
|
||||
u32 mr;
|
||||
u32 ir;
|
||||
u32 wddis_mask;
|
||||
unsigned long last_ping;
|
||||
bool need_irq;
|
||||
bool sam9x60_support;
|
||||
|
|
@ -48,7 +49,10 @@ MODULE_PARM_DESC(nowayout,
|
|||
"Watchdog cannot be stopped once started (default="
|
||||
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
||||
#define wdt_enabled (!(wdt->mr & AT91_WDT_WDDIS))
|
||||
static inline bool wdt_enabled(struct sama5d4_wdt *wdt)
|
||||
{
|
||||
return !(wdt->mr & wdt->wddis_mask);
|
||||
}
|
||||
|
||||
#define wdt_read(wdt, field) \
|
||||
readl_relaxed((wdt)->reg_base + (field))
|
||||
|
|
@ -81,12 +85,9 @@ static int sama5d4_wdt_start(struct watchdog_device *wdd)
|
|||
{
|
||||
struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
|
||||
if (wdt->sam9x60_support) {
|
||||
if (wdt->sam9x60_support)
|
||||
writel_relaxed(wdt->ir, wdt->reg_base + AT91_SAM9X60_IER);
|
||||
wdt->mr &= ~AT91_SAM9X60_WDDIS;
|
||||
} else {
|
||||
wdt->mr &= ~AT91_WDT_WDDIS;
|
||||
}
|
||||
wdt->mr &= ~wdt->wddis_mask;
|
||||
wdt_write(wdt, AT91_WDT_MR, wdt->mr);
|
||||
|
||||
return 0;
|
||||
|
|
@ -96,12 +97,9 @@ static int sama5d4_wdt_stop(struct watchdog_device *wdd)
|
|||
{
|
||||
struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
|
||||
if (wdt->sam9x60_support) {
|
||||
if (wdt->sam9x60_support)
|
||||
writel_relaxed(wdt->ir, wdt->reg_base + AT91_SAM9X60_IDR);
|
||||
wdt->mr |= AT91_SAM9X60_WDDIS;
|
||||
} else {
|
||||
wdt->mr |= AT91_WDT_WDDIS;
|
||||
}
|
||||
wdt->mr |= wdt->wddis_mask;
|
||||
wdt_write(wdt, AT91_WDT_MR, wdt->mr);
|
||||
|
||||
return 0;
|
||||
|
|
@ -117,7 +115,7 @@ static int sama5d4_wdt_ping(struct watchdog_device *wdd)
|
|||
}
|
||||
|
||||
static int sama5d4_wdt_set_timeout(struct watchdog_device *wdd,
|
||||
unsigned int timeout)
|
||||
unsigned int timeout)
|
||||
{
|
||||
struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
u32 value = WDT_SEC2TICKS(timeout);
|
||||
|
|
@ -140,8 +138,8 @@ static int sama5d4_wdt_set_timeout(struct watchdog_device *wdd,
|
|||
* If the watchdog is enabled, then the timeout can be updated. Else,
|
||||
* wait that the user enables it.
|
||||
*/
|
||||
if (wdt_enabled)
|
||||
wdt_write(wdt, AT91_WDT_MR, wdt->mr & ~AT91_WDT_WDDIS);
|
||||
if (wdt_enabled(wdt))
|
||||
wdt_write(wdt, AT91_WDT_MR, wdt->mr & ~wdt->wddis_mask);
|
||||
|
||||
wdd->timeout = timeout;
|
||||
|
||||
|
|
@ -184,10 +182,7 @@ static int of_sama5d4_wdt_init(struct device_node *np, struct sama5d4_wdt *wdt)
|
|||
{
|
||||
const char *tmp;
|
||||
|
||||
if (wdt->sam9x60_support)
|
||||
wdt->mr = AT91_SAM9X60_WDDIS;
|
||||
else
|
||||
wdt->mr = AT91_WDT_WDDIS;
|
||||
wdt->mr = wdt->wddis_mask;
|
||||
|
||||
if (!of_property_read_string(np, "atmel,watchdog-type", &tmp) &&
|
||||
!strcmp(tmp, "software"))
|
||||
|
|
@ -213,15 +208,11 @@ static int sama5d4_wdt_init(struct sama5d4_wdt *wdt)
|
|||
* If the watchdog is already running, we can safely update it.
|
||||
* Else, we have to disable it properly.
|
||||
*/
|
||||
if (!wdt_enabled) {
|
||||
if (!wdt_enabled(wdt)) {
|
||||
reg = wdt_read(wdt, AT91_WDT_MR);
|
||||
if (wdt->sam9x60_support && (!(reg & AT91_SAM9X60_WDDIS)))
|
||||
if (!(reg & wdt->wddis_mask))
|
||||
wdt_write_nosleep(wdt, AT91_WDT_MR,
|
||||
reg | AT91_SAM9X60_WDDIS);
|
||||
else if (!wdt->sam9x60_support &&
|
||||
(!(reg & AT91_WDT_WDDIS)))
|
||||
wdt_write_nosleep(wdt, AT91_WDT_MR,
|
||||
reg | AT91_WDT_WDDIS);
|
||||
reg | wdt->wddis_mask);
|
||||
}
|
||||
|
||||
if (wdt->sam9x60_support) {
|
||||
|
|
@ -273,6 +264,9 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)
|
|||
of_device_is_compatible(dev->of_node, "microchip,sama7g5-wdt"))
|
||||
wdt->sam9x60_support = true;
|
||||
|
||||
wdt->wddis_mask = wdt->sam9x60_support ? AT91_SAM9X60_WDDIS
|
||||
: AT91_WDT_WDDIS;
|
||||
|
||||
watchdog_set_drvdata(wdd, wdt);
|
||||
|
||||
regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
|
|
@ -306,8 +300,8 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)
|
|||
watchdog_init_timeout(wdd, wdt_timeout, dev);
|
||||
|
||||
reg = wdt_read(wdt, AT91_WDT_MR);
|
||||
if (!(reg & AT91_WDT_WDDIS)) {
|
||||
wdt->mr &= ~AT91_WDT_WDDIS;
|
||||
if (!(reg & wdt->wddis_mask)) {
|
||||
wdt->mr &= ~wdt->wddis_mask;
|
||||
set_bit(WDOG_HW_RUNNING, &wdd->status);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user