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: Guenter Roeck <linux@roeck-us.net> Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Tested-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> Acked-by: Wim Van Sebroeck <wim@iguana.be> Tested-By: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
This commit is contained in:
parent
bb02c662d6
commit
fc8cd2ac0a
1 changed files with 5 additions and 37 deletions
|
@ -20,7 +20,6 @@
|
||||||
#include <linux/watchdog.h>
|
#include <linux/watchdog.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/spinlock.h>
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
@ -46,25 +45,16 @@ static unsigned int wdt_max_duration; /* (seconds) */
|
||||||
static struct clk *clk;
|
static struct clk *clk;
|
||||||
static unsigned int wdt_tclk;
|
static unsigned int wdt_tclk;
|
||||||
static void __iomem *wdt_reg;
|
static void __iomem *wdt_reg;
|
||||||
static DEFINE_SPINLOCK(wdt_lock);
|
|
||||||
|
|
||||||
static int orion_wdt_ping(struct watchdog_device *wdt_dev)
|
static int orion_wdt_ping(struct watchdog_device *wdt_dev)
|
||||||
{
|
{
|
||||||
spin_lock(&wdt_lock);
|
|
||||||
|
|
||||||
/* Reload watchdog duration */
|
/* Reload watchdog duration */
|
||||||
writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
|
writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
|
||||||
|
|
||||||
spin_unlock(&wdt_lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int orion_wdt_start(struct watchdog_device *wdt_dev)
|
static int orion_wdt_start(struct watchdog_device *wdt_dev)
|
||||||
{
|
{
|
||||||
u32 reg;
|
|
||||||
|
|
||||||
spin_lock(&wdt_lock);
|
|
||||||
|
|
||||||
/* Set watchdog duration */
|
/* Set watchdog duration */
|
||||||
writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
|
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);
|
writel(~WDT_INT_REQ, BRIDGE_CAUSE);
|
||||||
|
|
||||||
/* Enable watchdog timer */
|
/* Enable watchdog timer */
|
||||||
reg = readl(wdt_reg + TIMER_CTRL);
|
atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN);
|
||||||
reg |= WDT_EN;
|
|
||||||
writel(reg, wdt_reg + TIMER_CTRL);
|
|
||||||
|
|
||||||
/* Enable reset on watchdog */
|
/* Enable reset on watchdog */
|
||||||
reg = readl(RSTOUTn_MASK);
|
atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
|
||||||
reg |= WDT_RESET_OUT_EN;
|
|
||||||
writel(reg, RSTOUTn_MASK);
|
|
||||||
|
|
||||||
spin_unlock(&wdt_lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int orion_wdt_stop(struct watchdog_device *wdt_dev)
|
static int orion_wdt_stop(struct watchdog_device *wdt_dev)
|
||||||
{
|
{
|
||||||
u32 reg;
|
|
||||||
|
|
||||||
spin_lock(&wdt_lock);
|
|
||||||
|
|
||||||
/* Disable reset on watchdog */
|
/* Disable reset on watchdog */
|
||||||
reg = readl(RSTOUTn_MASK);
|
atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, 0);
|
||||||
reg &= ~WDT_RESET_OUT_EN;
|
|
||||||
writel(reg, RSTOUTn_MASK);
|
|
||||||
|
|
||||||
/* Disable watchdog timer */
|
/* Disable watchdog timer */
|
||||||
reg = readl(wdt_reg + TIMER_CTRL);
|
atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0);
|
||||||
reg &= ~WDT_EN;
|
|
||||||
writel(reg, wdt_reg + TIMER_CTRL);
|
|
||||||
|
|
||||||
spin_unlock(&wdt_lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
|
static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
|
||||||
{
|
{
|
||||||
unsigned int time_left;
|
return readl(wdt_reg + WDT_VAL) / wdt_tclk;
|
||||||
|
|
||||||
spin_lock(&wdt_lock);
|
|
||||||
time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk;
|
|
||||||
spin_unlock(&wdt_lock);
|
|
||||||
|
|
||||||
return time_left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,
|
static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,
|
||||||
|
|
Loading…
Add table
Reference in a new issue