Commit fc8cd2ac authored by Ezequiel Garcia's avatar Ezequiel Garcia Committed by Jason Cooper

watchdog: orion: Use atomic access for shared registers

Since the timer control register is shared with the clocksource driver,
use the recently introduced atomic_io_clear_set() to access such register.
Given the watchdog core already provides serialization for all the
watchdog ops, this commit allows to remove the spinlock entirely.
Reviewed-by: default avatarGuenter Roeck <linux@roeck-us.net>
Tested-by: default avatarSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: default avatarWilly Tarreau <w@1wt.eu>
Signed-off-by: default avatarEzequiel Garcia <ezequiel.garcia@free-electrons.com>
Acked-by: default avatarWim Van Sebroeck <wim@iguana.be>
Tested-By: default avatarJason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: default avatarJason Cooper <jason@lakedaemon.net>
parent bb02c662
......@@ -20,7 +20,6 @@
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/of.h>
......@@ -46,25 +45,16 @@ static unsigned int wdt_max_duration; /* (seconds) */
static struct clk *clk;
static unsigned int wdt_tclk;
static void __iomem *wdt_reg;
static DEFINE_SPINLOCK(wdt_lock);
static int orion_wdt_ping(struct watchdog_device *wdt_dev)
{
spin_lock(&wdt_lock);
/* Reload watchdog duration */
writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
spin_unlock(&wdt_lock);
return 0;
}
static int orion_wdt_start(struct watchdog_device *wdt_dev)
{
u32 reg;
spin_lock(&wdt_lock);
/* Set watchdog duration */
writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
......@@ -72,48 +62,26 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
writel(~WDT_INT_REQ, BRIDGE_CAUSE);
/* Enable watchdog timer */
reg = readl(wdt_reg + TIMER_CTRL);
reg |= WDT_EN;
writel(reg, wdt_reg + TIMER_CTRL);
atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN);
/* Enable reset on watchdog */
reg = readl(RSTOUTn_MASK);
reg |= WDT_RESET_OUT_EN;
writel(reg, RSTOUTn_MASK);
spin_unlock(&wdt_lock);
atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
return 0;
}
static int orion_wdt_stop(struct watchdog_device *wdt_dev)
{
u32 reg;
spin_lock(&wdt_lock);
/* Disable reset on watchdog */
reg = readl(RSTOUTn_MASK);
reg &= ~WDT_RESET_OUT_EN;
writel(reg, RSTOUTn_MASK);
atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, 0);
/* Disable watchdog timer */
reg = readl(wdt_reg + TIMER_CTRL);
reg &= ~WDT_EN;
writel(reg, wdt_reg + TIMER_CTRL);
spin_unlock(&wdt_lock);
atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0);
return 0;
}
static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
{
unsigned int time_left;
spin_lock(&wdt_lock);
time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk;
spin_unlock(&wdt_lock);
return time_left;
return readl(wdt_reg + WDT_VAL) / wdt_tclk;
}
static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment