summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@atmel.com>2015-03-16 18:09:48 +0100
committerNicolas Ferre <nicolas.ferre@atmel.com>2015-03-16 18:09:48 +0100
commit88c5544ab2240cf2a2dc87b5af9cd7990d06d028 (patch)
tree7474b7d520d4a0604bc9879c7e4e183b9509ff04
parent2197cf7006b645893dbccaef454815fb6d7b3fda (diff)
parent8590ca655a19f9e124b52bfbf28f14eb16a05bec (diff)
Merge tag 'at91-cleanup3' into at91-4.1-multiplatform
Third batch of cleanup for 4.1: - System Timer (ST) for at91rm9200 re-work (syscon/regmap): - watchdog - restart handler - timer as a proper clocksource => remove mach dependency + cleanup
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-at91.txt4
-rw-r--r--arch/arm/boot/dts/at91rm9200.dtsi6
-rw-r--r--arch/arm/mach-at91/Kconfig1
-rw-r--r--arch/arm/mach-at91/Makefile2
-rw-r--r--arch/arm/mach-at91/at91rm9200.c19
-rw-r--r--arch/arm/mach-at91/generic.h3
-rw-r--r--arch/arm/mach-at91/include/mach/at91_st.h61
-rw-r--r--drivers/clocksource/Kconfig4
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/timer-atmel-st.c (renamed from arch/arm/mach-at91/at91rm9200_time.c)117
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/at91rm9200_wdt.c61
-rw-r--r--include/linux/mfd/syscon/atmel-st.h49
13 files changed, 164 insertions, 166 deletions
diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt
index ad319f84f560..2e99b5b57350 100644
--- a/Documentation/devicetree/bindings/arm/atmel-at91.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt
@@ -46,10 +46,12 @@ PIT Timer required properties:
shared across all System Controller members.
System Timer (ST) required properties:
-- compatible: Should be "atmel,at91rm9200-st"
+- compatible: Should be "atmel,at91rm9200-st", "syscon", "simple-mfd"
- reg: Should contain registers location and length
- interrupts: Should contain interrupt for the ST which is the IRQ line
shared across all System Controller members.
+Its subnodes can be:
+- watchdog: compatible should be "atmel,at91rm9200-wdt"
TC/TCLIB Timer required properties:
- compatible: Should be "atmel,<chip>-tcb".
diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi
index c515e4b160be..4fb333bd1f85 100644
--- a/arch/arm/boot/dts/at91rm9200.dtsi
+++ b/arch/arm/boot/dts/at91rm9200.dtsi
@@ -356,9 +356,13 @@
};
st: timer@fffffd00 {
- compatible = "atmel,at91rm9200-st";
+ compatible = "atmel,at91rm9200-st", "syscon", "simple-mfd";
reg = <0xfffffd00 0x100>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+
+ watchdog {
+ compatible = "atmel,at91rm9200-wdt";
+ };
};
rtc: rtc@fffffe00 {
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 4da6bae047f3..24b59c75f6af 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -77,6 +77,7 @@ if SOC_SAM_V4_V5
config SOC_AT91RM9200
bool "AT91RM9200"
select ATMEL_AIC_IRQ
+ select ATMEL_ST
select COMMON_CLK_AT91
select CPU_ARM920T
select GENERIC_CLOCKEVENTS
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index ea54c9824d89..38aaef7b994e 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -7,7 +7,7 @@ obj-y := soc.o
obj-$(CONFIG_SOC_AT91SAM9) += sam9_smc.o
# CPU-specific support
-obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o at91rm9200_time.o
+obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o
obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o
obj-$(CONFIG_SOC_SAMA5) += sama5.o
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index bfc9aed90b91..eaf58f88ef5d 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -15,8 +15,6 @@
#include <asm/mach/arch.h>
#include <asm/system_misc.h>
-#include <mach/at91_st.h>
-
#include "generic.h"
#include "soc.h"
@@ -25,21 +23,6 @@ static const struct at91_soc rm9200_socs[] = {
{ /* sentinel */ },
};
-static void at91rm9200_restart(enum reboot_mode reboot_mode, const char *cmd)
-{
- /*
- * Perform a hardware reset with the use of the Watchdog timer.
- */
- at91_st_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
- at91_st_write(AT91_ST_CR, AT91_ST_WDRST);
-}
-
-static void __init at91rm9200_dt_timer_init(void)
-{
- of_clk_init(NULL);
- at91rm9200_timer_init();
-}
-
static void __init at91rm9200_dt_device_init(void)
{
struct soc_device *soc;
@@ -52,7 +35,6 @@ static void __init at91rm9200_dt_device_init(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
arm_pm_idle = at91rm9200_idle;
- arm_pm_restart = at91rm9200_restart;
at91rm9200_pm_init();
}
@@ -62,7 +44,6 @@ static const char *at91rm9200_dt_board_compat[] __initconst = {
};
DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200")
- .init_time = at91rm9200_dt_timer_init,
.init_machine = at91rm9200_dt_device_init,
.dt_compat = at91rm9200_dt_board_compat,
MACHINE_END
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 2b396c4e1fc1..b0fa7dc7286d 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -18,9 +18,6 @@
extern void __init at91_map_io(void);
extern void __init at91_alt_map_io(void);
- /* Timer */
-extern void at91rm9200_timer_init(void);
-
/* idle */
extern void at91rm9200_idle(void);
extern void at91sam9_idle(void);
diff --git a/arch/arm/mach-at91/include/mach/at91_st.h b/arch/arm/mach-at91/include/mach/at91_st.h
deleted file mode 100644
index 67fdbd13c3ed..000000000000
--- a/arch/arm/mach-at91/include/mach/at91_st.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_st.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * System Timer (ST) - System peripherals registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_ST_H
-#define AT91_ST_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_st_base;
-
-#define at91_st_read(field) \
- __raw_readl(at91_st_base + field)
-
-#define at91_st_write(field, value) \
- __raw_writel(value, at91_st_base + field)
-#else
-.extern at91_st_base
-#endif
-
-#define AT91_ST_CR 0x00 /* Control Register */
-#define AT91_ST_WDRST (1 << 0) /* Watchdog Timer Restart */
-
-#define AT91_ST_PIMR 0x04 /* Period Interval Mode Register */
-#define AT91_ST_PIV (0xffff << 0) /* Period Interval Value */
-
-#define AT91_ST_WDMR 0x08 /* Watchdog Mode Register */
-#define AT91_ST_WDV (0xffff << 0) /* Watchdog Counter Value */
-#define AT91_ST_RSTEN (1 << 16) /* Reset Enable */
-#define AT91_ST_EXTEN (1 << 17) /* External Signal Assertion Enable */
-
-#define AT91_ST_RTMR 0x0c /* Real-time Mode Register */
-#define AT91_ST_RTPRES (0xffff << 0) /* Real-time Prescalar Value */
-
-#define AT91_ST_SR 0x10 /* Status Register */
-#define AT91_ST_PITS (1 << 0) /* Period Interval Timer Status */
-#define AT91_ST_WDOVF (1 << 1) /* Watchdog Overflow */
-#define AT91_ST_RTTINC (1 << 2) /* Real-time Timer Increment */
-#define AT91_ST_ALMS (1 << 3) /* Alarm Status */
-
-#define AT91_ST_IER 0x14 /* Interrupt Enable Register */
-#define AT91_ST_IDR 0x18 /* Interrupt Disable Register */
-#define AT91_ST_IMR 0x1c /* Interrupt Mask Register */
-
-#define AT91_ST_RTAR 0x20 /* Real-time Alarm Register */
-#define AT91_ST_ALMV (0xfffff << 0) /* Alarm Value */
-
-#define AT91_ST_CRTR 0x24 /* Current Real-time Register */
-#define AT91_ST_CRTV (0xfffff << 0) /* Current Real-Time Value */
-
-#endif
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 68161f7a07d6..168035883afa 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -143,6 +143,10 @@ config ATMEL_PIT
select CLKSRC_OF if OF
def_bool SOC_AT91SAM9 || SOC_SAMA5
+config ATMEL_ST
+ bool
+ select CLKSRC_OF
+
config CLKSRC_METAG_GENERIC
def_bool y if METAG
help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 752d5c70b0ef..5b85f6adb258 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_CLKSRC_OF) += clksrc-of.o
obj-$(CONFIG_ATMEL_PIT) += timer-atmel-pit.o
+obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/drivers/clocksource/timer-atmel-st.c
index b00d09555f2b..1692e17e096b 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/drivers/clocksource/timer-atmel-st.c
@@ -24,19 +24,17 @@
#include <linux/irq.h>
#include <linux/clockchips.h>
#include <linux/export.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/atmel-st.h>
#include <linux/of_irq.h>
-
-#include <asm/mach/time.h>
-
-#include <mach/at91_st.h>
-#include <mach/hardware.h>
+#include <linux/regmap.h>
static unsigned long last_crtr;
static u32 irqmask;
static struct clock_event_device clkevt;
+static struct regmap *regmap_st;
+#define AT91_SLOW_CLOCK 32768
#define RM9200_TIMER_LATCH ((AT91_SLOW_CLOCK + HZ/2) / HZ)
/*
@@ -46,11 +44,11 @@ static struct clock_event_device clkevt;
*/
static inline unsigned long read_CRTR(void)
{
- unsigned long x1, x2;
+ unsigned int x1, x2;
- x1 = at91_st_read(AT91_ST_CRTR);
+ regmap_read(regmap_st, AT91_ST_CRTR, &x1);
do {
- x2 = at91_st_read(AT91_ST_CRTR);
+ regmap_read(regmap_st, AT91_ST_CRTR, &x2);
if (x1 == x2)
break;
x1 = x2;
@@ -63,7 +61,10 @@ static inline unsigned long read_CRTR(void)
*/
static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
{
- u32 sr = at91_st_read(AT91_ST_SR) & irqmask;
+ u32 sr;
+
+ regmap_read(regmap_st, AT91_ST_SR, &sr);
+ sr &= irqmask;
/*
* irqs should be disabled here, but as the irq is shared they are only
@@ -92,13 +93,6 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
-static struct irqaction at91rm9200_timer_irq = {
- .name = "at91_tick",
- .flags = IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = at91rm9200_timer_interrupt,
- .irq = NR_IRQS_LEGACY + AT91_ID_SYS,
-};
-
static cycle_t read_clk32k(struct clocksource *cs)
{
return read_CRTR();
@@ -115,23 +109,25 @@ static struct clocksource clk32k = {
static void
clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
{
+ unsigned int val;
+
/* Disable and flush pending timer interrupts */
- at91_st_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
- at91_st_read(AT91_ST_SR);
+ regmap_write(regmap_st, AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
+ regmap_read(regmap_st, AT91_ST_SR, &val);
last_crtr = read_CRTR();
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
/* PIT for periodic irqs; fixed rate of 1/HZ */
irqmask = AT91_ST_PITS;
- at91_st_write(AT91_ST_PIMR, RM9200_TIMER_LATCH);
+ regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH);
break;
case CLOCK_EVT_MODE_ONESHOT:
/* ALM for oneshot irqs, set by next_event()
* before 32 seconds have passed
*/
irqmask = AT91_ST_ALMS;
- at91_st_write(AT91_ST_RTAR, last_crtr);
+ regmap_write(regmap_st, AT91_ST_RTAR, last_crtr);
break;
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
@@ -139,7 +135,7 @@ clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
irqmask = 0;
break;
}
- at91_st_write(AT91_ST_IER, irqmask);
+ regmap_write(regmap_st, AT91_ST_IER, irqmask);
}
static int
@@ -147,6 +143,7 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
{
u32 alm;
int status = 0;
+ unsigned int val;
BUG_ON(delta < 2);
@@ -162,12 +159,12 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
alm = read_CRTR();
/* Cancel any pending alarm; flush any pending IRQ */
- at91_st_write(AT91_ST_RTAR, alm);
- at91_st_read(AT91_ST_SR);
+ regmap_write(regmap_st, AT91_ST_RTAR, alm);
+ regmap_read(regmap_st, AT91_ST_SR, &val);
/* Schedule alarm by writing RTAR. */
alm += delta;
- at91_st_write(AT91_ST_RTAR, alm);
+ regmap_write(regmap_st, AT91_ST_RTAR, alm);
return status;
}
@@ -180,66 +177,40 @@ static struct clock_event_device clkevt = {
.set_mode = clkevt32k_mode,
};
-void __iomem *at91_st_base;
-EXPORT_SYMBOL_GPL(at91_st_base);
-
-static const struct of_device_id at91rm9200_st_timer_ids[] = {
- { .compatible = "atmel,at91rm9200-st" },
- { /* sentinel */ }
-};
-
-static int __init of_at91rm9200_st_init(void)
-{
- struct device_node *np;
- int ret;
-
- np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
- if (!np)
- goto err;
-
- at91_st_base = of_iomap(np, 0);
- if (!at91_st_base)
- goto node_err;
-
- /* Get the interrupts property */
- ret = irq_of_parse_and_map(np, 0);
- if (!ret)
- goto ioremap_err;
- at91rm9200_timer_irq.irq = ret;
-
- of_node_put(np);
-
- return 0;
-
-ioremap_err:
- iounmap(at91_st_base);
-node_err:
- of_node_put(np);
-err:
- return -EINVAL;
-}
-
/*
* ST (system timer) module supports both clockevents and clocksource.
*/
-void __init at91rm9200_timer_init(void)
+static void __init atmel_st_timer_init(struct device_node *node)
{
- /* For device tree enabled device: initialize here */
- of_at91rm9200_st_init();
+ unsigned int val;
+ int irq, ret;
+
+ regmap_st = syscon_node_to_regmap(node);
+ if (IS_ERR(regmap_st))
+ panic(pr_fmt("Unable to get regmap\n"));
/* Disable all timer interrupts, and clear any pending ones */
- at91_st_write(AT91_ST_IDR,
+ regmap_write(regmap_st, AT91_ST_IDR,
AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
- at91_st_read(AT91_ST_SR);
+ regmap_read(regmap_st, AT91_ST_SR, &val);
+
+ /* Get the interrupts property */
+ irq = irq_of_parse_and_map(node, 0);
+ if (!irq)
+ panic(pr_fmt("Unable to get IRQ from DT\n"));
/* Make IRQs happen for the system timer */
- setup_irq(at91rm9200_timer_irq.irq, &at91rm9200_timer_irq);
+ ret = request_irq(irq, at91rm9200_timer_interrupt,
+ IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
+ "at91_tick", regmap_st);
+ if (ret)
+ panic(pr_fmt("Unable to setup IRQ\n"));
/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
* directly for the clocksource and all clockevents, after adjusting
* its prescaler from the 1 Hz default.
*/
- at91_st_write(AT91_ST_RTMR, 1);
+ regmap_write(regmap_st, AT91_ST_RTMR, 1);
/* Setup timer clockevent, with minimum of two ticks (important!!) */
clkevt.cpumask = cpumask_of(0);
@@ -249,3 +220,5 @@ void __init at91rm9200_timer_init(void)
/* register clocksource */
clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
}
+CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",
+ atmel_st_timer_init);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 16f202350997..ce4f3a7f95fd 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -154,7 +154,7 @@ config ARM_SP805_WATCHDOG
config AT91RM9200_WATCHDOG
tristate "AT91RM9200 watchdog"
- depends on SOC_AT91RM9200
+ depends on SOC_AT91RM9200 && MFD_SYSCON
help
Watchdog timer embedded into AT91RM9200 chips. This will reboot your
system when the timeout is reached.
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index d244112d5b6f..41cecb55766c 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -12,27 +12,32 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bitops.h>
+#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/atmel-st.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/regmap.h>
#include <linux/types.h>
#include <linux/watchdog.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <mach/at91_st.h>
#define WDT_DEFAULT_TIME 5 /* seconds */
#define WDT_MAX_TIME 256 /* seconds */
static int wdt_time = WDT_DEFAULT_TIME;
static bool nowayout = WATCHDOG_NOWAYOUT;
+static struct regmap *regmap_st;
module_param(wdt_time, int, 0);
MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
@@ -50,12 +55,33 @@ static unsigned long at91wdt_busy;
/* ......................................................................... */
+static int at91rm9200_restart(struct notifier_block *this,
+ unsigned long mode, void *cmd)
+{
+ /*
+ * Perform a hardware reset with the use of the Watchdog timer.
+ */
+ regmap_write(regmap_st, AT91_ST_WDMR,
+ AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
+ regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST);
+
+ mdelay(2000);
+
+ pr_emerg("Unable to restart system\n");
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block at91rm9200_restart_nb = {
+ .notifier_call = at91rm9200_restart,
+ .priority = 192,
+};
+
/*
* Disable the watchdog.
*/
static inline void at91_wdt_stop(void)
{
- at91_st_write(AT91_ST_WDMR, AT91_ST_EXTEN);
+ regmap_write(regmap_st, AT91_ST_WDMR, AT91_ST_EXTEN);
}
/*
@@ -63,9 +89,9 @@ static inline void at91_wdt_stop(void)
*/
static inline void at91_wdt_start(void)
{
- at91_st_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN |
+ regmap_write(regmap_st, AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN |
(((65536 * wdt_time) >> 8) & AT91_ST_WDV));
- at91_st_write(AT91_ST_CR, AT91_ST_WDRST);
+ regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST);
}
/*
@@ -73,7 +99,7 @@ static inline void at91_wdt_start(void)
*/
static inline void at91_wdt_reload(void)
{
- at91_st_write(AT91_ST_CR, AT91_ST_WDRST);
+ regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST);
}
/* ......................................................................... */
@@ -203,16 +229,32 @@ static struct miscdevice at91wdt_miscdev = {
static int at91wdt_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
+ struct device *parent;
int res;
if (at91wdt_miscdev.parent)
return -EBUSY;
at91wdt_miscdev.parent = &pdev->dev;
+ parent = dev->parent;
+ if (!parent) {
+ dev_err(dev, "no parent\n");
+ return -ENODEV;
+ }
+
+ regmap_st = syscon_node_to_regmap(parent->of_node);
+ if (!regmap_st)
+ return -ENODEV;
+
res = misc_register(&at91wdt_miscdev);
if (res)
return res;
+ res = register_restart_handler(&at91rm9200_restart_nb);
+ if (res)
+ dev_warn(dev, "failed to register restart handler\n");
+
pr_info("AT91 Watchdog Timer enabled (%d seconds%s)\n",
wdt_time, nowayout ? ", nowayout" : "");
return 0;
@@ -220,8 +262,13 @@ static int at91wdt_probe(struct platform_device *pdev)
static int at91wdt_remove(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
int res;
+ res = unregister_restart_handler(&at91rm9200_restart_nb);
+ if (res)
+ dev_warn(dev, "failed to unregister restart handler\n");
+
res = misc_deregister(&at91wdt_miscdev);
if (!res)
at91wdt_miscdev.parent = NULL;
@@ -267,7 +314,7 @@ static struct platform_driver at91wdt_driver = {
.suspend = at91wdt_suspend,
.resume = at91wdt_resume,
.driver = {
- .name = "at91_wdt",
+ .name = "atmel_st_watchdog",
.of_match_table = at91_wdt_dt_ids,
},
};
@@ -296,4 +343,4 @@ module_exit(at91_wdt_exit);
MODULE_AUTHOR("Andrew Victor");
MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:at91_wdt");
+MODULE_ALIAS("platform:atmel_st_watchdog");
diff --git a/include/linux/mfd/syscon/atmel-st.h b/include/linux/mfd/syscon/atmel-st.h
new file mode 100644
index 000000000000..8acf1ec1fa32
--- /dev/null
+++ b/include/linux/mfd/syscon/atmel-st.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * System Timer (ST) - System peripherals registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _LINUX_MFD_SYSCON_ATMEL_ST_H
+#define _LINUX_MFD_SYSCON_ATMEL_ST_H
+
+#include <linux/bitops.h>
+
+#define AT91_ST_CR 0x00 /* Control Register */
+#define AT91_ST_WDRST BIT(0) /* Watchdog Timer Restart */
+
+#define AT91_ST_PIMR 0x04 /* Period Interval Mode Register */
+#define AT91_ST_PIV 0xffff /* Period Interval Value */
+
+#define AT91_ST_WDMR 0x08 /* Watchdog Mode Register */
+#define AT91_ST_WDV 0xffff /* Watchdog Counter Value */
+#define AT91_ST_RSTEN BIT(16) /* Reset Enable */
+#define AT91_ST_EXTEN BIT(17) /* External Signal Assertion Enable */
+
+#define AT91_ST_RTMR 0x0c /* Real-time Mode Register */
+#define AT91_ST_RTPRES 0xffff /* Real-time Prescalar Value */
+
+#define AT91_ST_SR 0x10 /* Status Register */
+#define AT91_ST_PITS BIT(0) /* Period Interval Timer Status */
+#define AT91_ST_WDOVF BIT(1) /* Watchdog Overflow */
+#define AT91_ST_RTTINC BIT(2) /* Real-time Timer Increment */
+#define AT91_ST_ALMS BIT(3) /* Alarm Status */
+
+#define AT91_ST_IER 0x14 /* Interrupt Enable Register */
+#define AT91_ST_IDR 0x18 /* Interrupt Disable Register */
+#define AT91_ST_IMR 0x1c /* Interrupt Mask Register */
+
+#define AT91_ST_RTAR 0x20 /* Real-time Alarm Register */
+#define AT91_ST_ALMV 0xfffff /* Alarm Value */
+
+#define AT91_ST_CRTR 0x24 /* Current Real-time Register */
+#define AT91_ST_CRTV 0xfffff /* Current Real-Time Value */
+
+#endif /* _LINUX_MFD_SYSCON_ATMEL_ST_H */