Re: [PATCH 2/2] watchdog: Add Spreadtrum watchdog driver
On Sat, Sep 09, 2017 at 03:32:48AM +, Guenter Roeck wrote: > On 09/05/2017 10:38 PM, Eric Long wrote: > > This patch adds the watchdog driver for Spreadtrum SC9860 platform. > > > > Signed-off-by: Eric Long> > --- > > drivers/watchdog/Kconfig| 8 + > > drivers/watchdog/Makefile | 1 + > > drivers/watchdog/sprd_wdt.c | 366 > > > > 3 files changed, 375 insertions(+) > > create mode 100644 drivers/watchdog/sprd_wdt.c > > > > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig > > index c722cbf..ea07718 100644 > > --- a/drivers/watchdog/Kconfig > > +++ b/drivers/watchdog/Kconfig > > @@ -787,6 +787,14 @@ config UNIPHIER_WATCHDOG > > To compile this driver as a module, choose M here: the > > module will be called uniphier_wdt. > > > > +config SPRD_WATCHDOG > > + tristate "Spreadtrum watchdog support" > > + depends on ARCH_SPRD > > + select WATCHDOG_CORE > > + help > > + Say Y here to include support watchdog timer embedded > > + into the Spreadtrum system. > > + > > # AVR32 Architecture > > > > config AT32AP700X_WDT > > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile > > index 56adf9f..187cca2 100644 > > --- a/drivers/watchdog/Makefile > > +++ b/drivers/watchdog/Makefile > > @@ -87,6 +87,7 @@ obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o > > obj-$(CONFIG_ZX2967_WATCHDOG) += zx2967_wdt.o > > obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o > > obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o > > +obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o > > > > # AVR32 Architecture > > obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o > > diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c > > new file mode 100644 > > index 000..6006bb4 > > --- /dev/null > > +++ b/drivers/watchdog/sprd_wdt.c > > @@ -0,0 +1,366 @@ > > +/* > > + * Spreadtrum watchdog driver > > + * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License > > + * version 2 as published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, but > > + * WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + * General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define WDT_LOAD_LOW 0x0 > > +#define WDT_LOAD_HIGH 0x4 > > +#define WDT_CTRL 0x8 > > +#define WDT_INT_CLR0xc > > +#define WDT_INT_RAW0x10 > > +#define WDT_INT_MSK0x14 > > +#define WDT_CNT_LOW0x18 > > +#define WDT_CNT_HIGH 0x1c > > +#define WDT_LOCK 0x20 > > +#define WDT_IRQ_LOAD_LOW 0x2c > > +#define WDT_IRQ_LOAD_HIGH 0x30 > > + > > +/* WDT_CTRL */ > > +#define WDT_INT_EN_BIT BIT(0) > > +#define WDT_CNT_EN_BIT BIT(1) > > +#define WDT_NEW_VER_EN BIT(2) > > +#define WDT_RST_EN_BIT BIT(3) > > + > > +/* WDT_INT_CLR */ > > +#define WDT_INT_CLEAR_BIT BIT(0) > > +#define WDT_RST_CLEAR_BIT BIT(3) > > + > > +/* WDT_INT_RAW */ > > +#define WDT_INT_RAW_BITBIT(0) > > +#define WDT_RST_RAW_BITBIT(3) > > +#define WDT_LD_BUSY_BITBIT(4) > > + > > +#define WDT_CLK32768 > > +#define WDT_UNLOCK_KEY 0xe551 > > +#define WDT_IRQ_TMROUT_OFFSET 0x3 > > + > > +#define WDT_CNT_VALUE_SIZE 16 > > +#define WDT_CNT_VALUE_MASK GENMASK(15, 0) > > +#define WDT_LOAD_TIMEOUT_NUM 1 > > + > > +struct sprd_wdt { > > + void __iomem *base; > > + struct watchdog_device wdd; > > + struct clk *enable; > > + struct clk *rtc_enable; > > + u32 irq_tmr_out; > > + u32 rst_tmr_out; > > + unsigned int irq; > > +}; > > + > > +static inline struct sprd_wdt *to_sprd_wdt(struct watchdog_device *wdd) > > +{ > > + return container_of(wdd, struct sprd_wdt, wdd); > > +} > > + > > +static inline void sprd_wdt_lock(void __iomem *addr) > > +{ > > + writel_relaxed(0x0, addr + WDT_LOCK); > > +} > > + > > +static inline void sprd_wdt_unlock(void __iomem *addr) > > +{ > > + writel_relaxed(WDT_UNLOCK_KEY, addr + WDT_LOCK); > > +} > > + > > +static irqreturn_t sprd_wdt_isr(int irq, void *dev_id) > > +{ > > + struct sprd_wdt *wdt = (struct sprd_wdt *)dev_id; > > + > > + sprd_wdt_unlock(wdt->base); > > + writel_relaxed(WDT_INT_CLEAR_BIT, wdt->base + WDT_INT_CLR); > > + sprd_wdt_lock(wdt->base); > > + watchdog_notify_pretimeout(>wdd); > > + return IRQ_HANDLED; > > +} > > + > > +static u32 sprd_wdt_get_cnt_value(struct sprd_wdt *wdt) > > +{ > > +
Re: [PATCH 2/2] watchdog: Add Spreadtrum watchdog driver
On Sat, Sep 09, 2017 at 03:32:48AM +, Guenter Roeck wrote: > On 09/05/2017 10:38 PM, Eric Long wrote: > > This patch adds the watchdog driver for Spreadtrum SC9860 platform. > > > > Signed-off-by: Eric Long > > --- > > drivers/watchdog/Kconfig| 8 + > > drivers/watchdog/Makefile | 1 + > > drivers/watchdog/sprd_wdt.c | 366 > > > > 3 files changed, 375 insertions(+) > > create mode 100644 drivers/watchdog/sprd_wdt.c > > > > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig > > index c722cbf..ea07718 100644 > > --- a/drivers/watchdog/Kconfig > > +++ b/drivers/watchdog/Kconfig > > @@ -787,6 +787,14 @@ config UNIPHIER_WATCHDOG > > To compile this driver as a module, choose M here: the > > module will be called uniphier_wdt. > > > > +config SPRD_WATCHDOG > > + tristate "Spreadtrum watchdog support" > > + depends on ARCH_SPRD > > + select WATCHDOG_CORE > > + help > > + Say Y here to include support watchdog timer embedded > > + into the Spreadtrum system. > > + > > # AVR32 Architecture > > > > config AT32AP700X_WDT > > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile > > index 56adf9f..187cca2 100644 > > --- a/drivers/watchdog/Makefile > > +++ b/drivers/watchdog/Makefile > > @@ -87,6 +87,7 @@ obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o > > obj-$(CONFIG_ZX2967_WATCHDOG) += zx2967_wdt.o > > obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o > > obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o > > +obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o > > > > # AVR32 Architecture > > obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o > > diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c > > new file mode 100644 > > index 000..6006bb4 > > --- /dev/null > > +++ b/drivers/watchdog/sprd_wdt.c > > @@ -0,0 +1,366 @@ > > +/* > > + * Spreadtrum watchdog driver > > + * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License > > + * version 2 as published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, but > > + * WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + * General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define WDT_LOAD_LOW 0x0 > > +#define WDT_LOAD_HIGH 0x4 > > +#define WDT_CTRL 0x8 > > +#define WDT_INT_CLR0xc > > +#define WDT_INT_RAW0x10 > > +#define WDT_INT_MSK0x14 > > +#define WDT_CNT_LOW0x18 > > +#define WDT_CNT_HIGH 0x1c > > +#define WDT_LOCK 0x20 > > +#define WDT_IRQ_LOAD_LOW 0x2c > > +#define WDT_IRQ_LOAD_HIGH 0x30 > > + > > +/* WDT_CTRL */ > > +#define WDT_INT_EN_BIT BIT(0) > > +#define WDT_CNT_EN_BIT BIT(1) > > +#define WDT_NEW_VER_EN BIT(2) > > +#define WDT_RST_EN_BIT BIT(3) > > + > > +/* WDT_INT_CLR */ > > +#define WDT_INT_CLEAR_BIT BIT(0) > > +#define WDT_RST_CLEAR_BIT BIT(3) > > + > > +/* WDT_INT_RAW */ > > +#define WDT_INT_RAW_BITBIT(0) > > +#define WDT_RST_RAW_BITBIT(3) > > +#define WDT_LD_BUSY_BITBIT(4) > > + > > +#define WDT_CLK32768 > > +#define WDT_UNLOCK_KEY 0xe551 > > +#define WDT_IRQ_TMROUT_OFFSET 0x3 > > + > > +#define WDT_CNT_VALUE_SIZE 16 > > +#define WDT_CNT_VALUE_MASK GENMASK(15, 0) > > +#define WDT_LOAD_TIMEOUT_NUM 1 > > + > > +struct sprd_wdt { > > + void __iomem *base; > > + struct watchdog_device wdd; > > + struct clk *enable; > > + struct clk *rtc_enable; > > + u32 irq_tmr_out; > > + u32 rst_tmr_out; > > + unsigned int irq; > > +}; > > + > > +static inline struct sprd_wdt *to_sprd_wdt(struct watchdog_device *wdd) > > +{ > > + return container_of(wdd, struct sprd_wdt, wdd); > > +} > > + > > +static inline void sprd_wdt_lock(void __iomem *addr) > > +{ > > + writel_relaxed(0x0, addr + WDT_LOCK); > > +} > > + > > +static inline void sprd_wdt_unlock(void __iomem *addr) > > +{ > > + writel_relaxed(WDT_UNLOCK_KEY, addr + WDT_LOCK); > > +} > > + > > +static irqreturn_t sprd_wdt_isr(int irq, void *dev_id) > > +{ > > + struct sprd_wdt *wdt = (struct sprd_wdt *)dev_id; > > + > > + sprd_wdt_unlock(wdt->base); > > + writel_relaxed(WDT_INT_CLEAR_BIT, wdt->base + WDT_INT_CLR); > > + sprd_wdt_lock(wdt->base); > > + watchdog_notify_pretimeout(>wdd); > > + return IRQ_HANDLED; > > +} > > + > > +static u32 sprd_wdt_get_cnt_value(struct sprd_wdt *wdt) > > +{ > > + u32 val; > > + > > + val =
Re: [PATCH 2/2] watchdog: Add Spreadtrum watchdog driver
On 09/05/2017 10:38 PM, Eric Long wrote: This patch adds the watchdog driver for Spreadtrum SC9860 platform. Signed-off-by: Eric Long--- drivers/watchdog/Kconfig| 8 + drivers/watchdog/Makefile | 1 + drivers/watchdog/sprd_wdt.c | 366 3 files changed, 375 insertions(+) create mode 100644 drivers/watchdog/sprd_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c722cbf..ea07718 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -787,6 +787,14 @@ config UNIPHIER_WATCHDOG To compile this driver as a module, choose M here: the module will be called uniphier_wdt. +config SPRD_WATCHDOG + tristate "Spreadtrum watchdog support" + depends on ARCH_SPRD + select WATCHDOG_CORE + help + Say Y here to include support watchdog timer embedded + into the Spreadtrum system. + # AVR32 Architecture config AT32AP700X_WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 56adf9f..187cca2 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -87,6 +87,7 @@ obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o obj-$(CONFIG_ZX2967_WATCHDOG) += zx2967_wdt.o obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o +obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c new file mode 100644 index 000..6006bb4 --- /dev/null +++ b/drivers/watchdog/sprd_wdt.c @@ -0,0 +1,366 @@ +/* + * Spreadtrum watchdog driver + * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WDT_LOAD_LOW 0x0 +#define WDT_LOAD_HIGH 0x4 +#define WDT_CTRL 0x8 +#define WDT_INT_CLR0xc +#define WDT_INT_RAW0x10 +#define WDT_INT_MSK0x14 +#define WDT_CNT_LOW0x18 +#define WDT_CNT_HIGH 0x1c +#define WDT_LOCK 0x20 +#define WDT_IRQ_LOAD_LOW 0x2c +#define WDT_IRQ_LOAD_HIGH 0x30 + +/* WDT_CTRL */ +#define WDT_INT_EN_BIT BIT(0) +#define WDT_CNT_EN_BIT BIT(1) +#define WDT_NEW_VER_EN BIT(2) +#define WDT_RST_EN_BIT BIT(3) + +/* WDT_INT_CLR */ +#define WDT_INT_CLEAR_BIT BIT(0) +#define WDT_RST_CLEAR_BIT BIT(3) + +/* WDT_INT_RAW */ +#define WDT_INT_RAW_BITBIT(0) +#define WDT_RST_RAW_BITBIT(3) +#define WDT_LD_BUSY_BITBIT(4) + +#define WDT_CLK32768 +#define WDT_UNLOCK_KEY 0xe551 +#define WDT_IRQ_TMROUT_OFFSET 0x3 + +#define WDT_CNT_VALUE_SIZE 16 +#define WDT_CNT_VALUE_MASK GENMASK(15, 0) +#define WDT_LOAD_TIMEOUT_NUM 1 + +struct sprd_wdt { + void __iomem *base; + struct watchdog_device wdd; + struct clk *enable; + struct clk *rtc_enable; + u32 irq_tmr_out; + u32 rst_tmr_out; + unsigned int irq; +}; + +static inline struct sprd_wdt *to_sprd_wdt(struct watchdog_device *wdd) +{ + return container_of(wdd, struct sprd_wdt, wdd); +} + +static inline void sprd_wdt_lock(void __iomem *addr) +{ + writel_relaxed(0x0, addr + WDT_LOCK); +} + +static inline void sprd_wdt_unlock(void __iomem *addr) +{ + writel_relaxed(WDT_UNLOCK_KEY, addr + WDT_LOCK); +} + +static irqreturn_t sprd_wdt_isr(int irq, void *dev_id) +{ + struct sprd_wdt *wdt = (struct sprd_wdt *)dev_id; + + sprd_wdt_unlock(wdt->base); + writel_relaxed(WDT_INT_CLEAR_BIT, wdt->base + WDT_INT_CLR); + sprd_wdt_lock(wdt->base); + watchdog_notify_pretimeout(>wdd); + return IRQ_HANDLED; +} + +static u32 sprd_wdt_get_cnt_value(struct sprd_wdt *wdt) +{ + u32 val; + + val = readl_relaxed(wdt->base + WDT_CNT_HIGH) << WDT_CNT_VALUE_SIZE; + val |= readl_relaxed(wdt->base + WDT_CNT_LOW) & WDT_CNT_VALUE_MASK; + + return val; +} + +static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 rst_value, + u32 irq_value) +{ + u32 val, cnt = 0; + + sprd_wdt_unlock(wdt->base); + writel_relaxed((rst_value >> WDT_CNT_VALUE_SIZE) & WDT_CNT_VALUE_MASK, + wdt->base + WDT_LOAD_HIGH); + writel_relaxed((rst_value & WDT_CNT_VALUE_MASK),
Re: [PATCH 2/2] watchdog: Add Spreadtrum watchdog driver
On 09/05/2017 10:38 PM, Eric Long wrote: This patch adds the watchdog driver for Spreadtrum SC9860 platform. Signed-off-by: Eric Long --- drivers/watchdog/Kconfig| 8 + drivers/watchdog/Makefile | 1 + drivers/watchdog/sprd_wdt.c | 366 3 files changed, 375 insertions(+) create mode 100644 drivers/watchdog/sprd_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c722cbf..ea07718 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -787,6 +787,14 @@ config UNIPHIER_WATCHDOG To compile this driver as a module, choose M here: the module will be called uniphier_wdt. +config SPRD_WATCHDOG + tristate "Spreadtrum watchdog support" + depends on ARCH_SPRD + select WATCHDOG_CORE + help + Say Y here to include support watchdog timer embedded + into the Spreadtrum system. + # AVR32 Architecture config AT32AP700X_WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 56adf9f..187cca2 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -87,6 +87,7 @@ obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o obj-$(CONFIG_ZX2967_WATCHDOG) += zx2967_wdt.o obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o +obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c new file mode 100644 index 000..6006bb4 --- /dev/null +++ b/drivers/watchdog/sprd_wdt.c @@ -0,0 +1,366 @@ +/* + * Spreadtrum watchdog driver + * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WDT_LOAD_LOW 0x0 +#define WDT_LOAD_HIGH 0x4 +#define WDT_CTRL 0x8 +#define WDT_INT_CLR0xc +#define WDT_INT_RAW0x10 +#define WDT_INT_MSK0x14 +#define WDT_CNT_LOW0x18 +#define WDT_CNT_HIGH 0x1c +#define WDT_LOCK 0x20 +#define WDT_IRQ_LOAD_LOW 0x2c +#define WDT_IRQ_LOAD_HIGH 0x30 + +/* WDT_CTRL */ +#define WDT_INT_EN_BIT BIT(0) +#define WDT_CNT_EN_BIT BIT(1) +#define WDT_NEW_VER_EN BIT(2) +#define WDT_RST_EN_BIT BIT(3) + +/* WDT_INT_CLR */ +#define WDT_INT_CLEAR_BIT BIT(0) +#define WDT_RST_CLEAR_BIT BIT(3) + +/* WDT_INT_RAW */ +#define WDT_INT_RAW_BITBIT(0) +#define WDT_RST_RAW_BITBIT(3) +#define WDT_LD_BUSY_BITBIT(4) + +#define WDT_CLK32768 +#define WDT_UNLOCK_KEY 0xe551 +#define WDT_IRQ_TMROUT_OFFSET 0x3 + +#define WDT_CNT_VALUE_SIZE 16 +#define WDT_CNT_VALUE_MASK GENMASK(15, 0) +#define WDT_LOAD_TIMEOUT_NUM 1 + +struct sprd_wdt { + void __iomem *base; + struct watchdog_device wdd; + struct clk *enable; + struct clk *rtc_enable; + u32 irq_tmr_out; + u32 rst_tmr_out; + unsigned int irq; +}; + +static inline struct sprd_wdt *to_sprd_wdt(struct watchdog_device *wdd) +{ + return container_of(wdd, struct sprd_wdt, wdd); +} + +static inline void sprd_wdt_lock(void __iomem *addr) +{ + writel_relaxed(0x0, addr + WDT_LOCK); +} + +static inline void sprd_wdt_unlock(void __iomem *addr) +{ + writel_relaxed(WDT_UNLOCK_KEY, addr + WDT_LOCK); +} + +static irqreturn_t sprd_wdt_isr(int irq, void *dev_id) +{ + struct sprd_wdt *wdt = (struct sprd_wdt *)dev_id; + + sprd_wdt_unlock(wdt->base); + writel_relaxed(WDT_INT_CLEAR_BIT, wdt->base + WDT_INT_CLR); + sprd_wdt_lock(wdt->base); + watchdog_notify_pretimeout(>wdd); + return IRQ_HANDLED; +} + +static u32 sprd_wdt_get_cnt_value(struct sprd_wdt *wdt) +{ + u32 val; + + val = readl_relaxed(wdt->base + WDT_CNT_HIGH) << WDT_CNT_VALUE_SIZE; + val |= readl_relaxed(wdt->base + WDT_CNT_LOW) & WDT_CNT_VALUE_MASK; + + return val; +} + +static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 rst_value, + u32 irq_value) +{ + u32 val, cnt = 0; + + sprd_wdt_unlock(wdt->base); + writel_relaxed((rst_value >> WDT_CNT_VALUE_SIZE) & WDT_CNT_VALUE_MASK, + wdt->base + WDT_LOAD_HIGH); + writel_relaxed((rst_value & WDT_CNT_VALUE_MASK), +
[PATCH 2/2] watchdog: Add Spreadtrum watchdog driver
This patch adds the watchdog driver for Spreadtrum SC9860 platform. Signed-off-by: Eric Long--- drivers/watchdog/Kconfig| 8 + drivers/watchdog/Makefile | 1 + drivers/watchdog/sprd_wdt.c | 366 3 files changed, 375 insertions(+) create mode 100644 drivers/watchdog/sprd_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c722cbf..ea07718 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -787,6 +787,14 @@ config UNIPHIER_WATCHDOG To compile this driver as a module, choose M here: the module will be called uniphier_wdt. +config SPRD_WATCHDOG + tristate "Spreadtrum watchdog support" + depends on ARCH_SPRD + select WATCHDOG_CORE + help + Say Y here to include support watchdog timer embedded + into the Spreadtrum system. + # AVR32 Architecture config AT32AP700X_WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 56adf9f..187cca2 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -87,6 +87,7 @@ obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o obj-$(CONFIG_ZX2967_WATCHDOG) += zx2967_wdt.o obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o +obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c new file mode 100644 index 000..6006bb4 --- /dev/null +++ b/drivers/watchdog/sprd_wdt.c @@ -0,0 +1,366 @@ +/* + * Spreadtrum watchdog driver + * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WDT_LOAD_LOW 0x0 +#define WDT_LOAD_HIGH 0x4 +#define WDT_CTRL 0x8 +#define WDT_INT_CLR0xc +#define WDT_INT_RAW0x10 +#define WDT_INT_MSK0x14 +#define WDT_CNT_LOW0x18 +#define WDT_CNT_HIGH 0x1c +#define WDT_LOCK 0x20 +#define WDT_IRQ_LOAD_LOW 0x2c +#define WDT_IRQ_LOAD_HIGH 0x30 + +/* WDT_CTRL */ +#define WDT_INT_EN_BIT BIT(0) +#define WDT_CNT_EN_BIT BIT(1) +#define WDT_NEW_VER_EN BIT(2) +#define WDT_RST_EN_BIT BIT(3) + +/* WDT_INT_CLR */ +#define WDT_INT_CLEAR_BIT BIT(0) +#define WDT_RST_CLEAR_BIT BIT(3) + +/* WDT_INT_RAW */ +#define WDT_INT_RAW_BITBIT(0) +#define WDT_RST_RAW_BITBIT(3) +#define WDT_LD_BUSY_BITBIT(4) + +#define WDT_CLK32768 +#define WDT_UNLOCK_KEY 0xe551 +#define WDT_IRQ_TMROUT_OFFSET 0x3 + +#define WDT_CNT_VALUE_SIZE 16 +#define WDT_CNT_VALUE_MASK GENMASK(15, 0) +#define WDT_LOAD_TIMEOUT_NUM 1 + +struct sprd_wdt { + void __iomem *base; + struct watchdog_device wdd; + struct clk *enable; + struct clk *rtc_enable; + u32 irq_tmr_out; + u32 rst_tmr_out; + unsigned int irq; +}; + +static inline struct sprd_wdt *to_sprd_wdt(struct watchdog_device *wdd) +{ + return container_of(wdd, struct sprd_wdt, wdd); +} + +static inline void sprd_wdt_lock(void __iomem *addr) +{ + writel_relaxed(0x0, addr + WDT_LOCK); +} + +static inline void sprd_wdt_unlock(void __iomem *addr) +{ + writel_relaxed(WDT_UNLOCK_KEY, addr + WDT_LOCK); +} + +static irqreturn_t sprd_wdt_isr(int irq, void *dev_id) +{ + struct sprd_wdt *wdt = (struct sprd_wdt *)dev_id; + + sprd_wdt_unlock(wdt->base); + writel_relaxed(WDT_INT_CLEAR_BIT, wdt->base + WDT_INT_CLR); + sprd_wdt_lock(wdt->base); + watchdog_notify_pretimeout(>wdd); + return IRQ_HANDLED; +} + +static u32 sprd_wdt_get_cnt_value(struct sprd_wdt *wdt) +{ + u32 val; + + val = readl_relaxed(wdt->base + WDT_CNT_HIGH) << WDT_CNT_VALUE_SIZE; + val |= readl_relaxed(wdt->base + WDT_CNT_LOW) & WDT_CNT_VALUE_MASK; + + return val; +} + +static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 rst_value, + u32 irq_value) +{ + u32 val, cnt = 0; + + sprd_wdt_unlock(wdt->base); + writel_relaxed((rst_value >> WDT_CNT_VALUE_SIZE) & WDT_CNT_VALUE_MASK, + wdt->base + WDT_LOAD_HIGH); + writel_relaxed((rst_value & WDT_CNT_VALUE_MASK), + wdt->base + WDT_LOAD_LOW); +
[PATCH 2/2] watchdog: Add Spreadtrum watchdog driver
This patch adds the watchdog driver for Spreadtrum SC9860 platform. Signed-off-by: Eric Long --- drivers/watchdog/Kconfig| 8 + drivers/watchdog/Makefile | 1 + drivers/watchdog/sprd_wdt.c | 366 3 files changed, 375 insertions(+) create mode 100644 drivers/watchdog/sprd_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c722cbf..ea07718 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -787,6 +787,14 @@ config UNIPHIER_WATCHDOG To compile this driver as a module, choose M here: the module will be called uniphier_wdt. +config SPRD_WATCHDOG + tristate "Spreadtrum watchdog support" + depends on ARCH_SPRD + select WATCHDOG_CORE + help + Say Y here to include support watchdog timer embedded + into the Spreadtrum system. + # AVR32 Architecture config AT32AP700X_WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 56adf9f..187cca2 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -87,6 +87,7 @@ obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o obj-$(CONFIG_ZX2967_WATCHDOG) += zx2967_wdt.o obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o +obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c new file mode 100644 index 000..6006bb4 --- /dev/null +++ b/drivers/watchdog/sprd_wdt.c @@ -0,0 +1,366 @@ +/* + * Spreadtrum watchdog driver + * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WDT_LOAD_LOW 0x0 +#define WDT_LOAD_HIGH 0x4 +#define WDT_CTRL 0x8 +#define WDT_INT_CLR0xc +#define WDT_INT_RAW0x10 +#define WDT_INT_MSK0x14 +#define WDT_CNT_LOW0x18 +#define WDT_CNT_HIGH 0x1c +#define WDT_LOCK 0x20 +#define WDT_IRQ_LOAD_LOW 0x2c +#define WDT_IRQ_LOAD_HIGH 0x30 + +/* WDT_CTRL */ +#define WDT_INT_EN_BIT BIT(0) +#define WDT_CNT_EN_BIT BIT(1) +#define WDT_NEW_VER_EN BIT(2) +#define WDT_RST_EN_BIT BIT(3) + +/* WDT_INT_CLR */ +#define WDT_INT_CLEAR_BIT BIT(0) +#define WDT_RST_CLEAR_BIT BIT(3) + +/* WDT_INT_RAW */ +#define WDT_INT_RAW_BITBIT(0) +#define WDT_RST_RAW_BITBIT(3) +#define WDT_LD_BUSY_BITBIT(4) + +#define WDT_CLK32768 +#define WDT_UNLOCK_KEY 0xe551 +#define WDT_IRQ_TMROUT_OFFSET 0x3 + +#define WDT_CNT_VALUE_SIZE 16 +#define WDT_CNT_VALUE_MASK GENMASK(15, 0) +#define WDT_LOAD_TIMEOUT_NUM 1 + +struct sprd_wdt { + void __iomem *base; + struct watchdog_device wdd; + struct clk *enable; + struct clk *rtc_enable; + u32 irq_tmr_out; + u32 rst_tmr_out; + unsigned int irq; +}; + +static inline struct sprd_wdt *to_sprd_wdt(struct watchdog_device *wdd) +{ + return container_of(wdd, struct sprd_wdt, wdd); +} + +static inline void sprd_wdt_lock(void __iomem *addr) +{ + writel_relaxed(0x0, addr + WDT_LOCK); +} + +static inline void sprd_wdt_unlock(void __iomem *addr) +{ + writel_relaxed(WDT_UNLOCK_KEY, addr + WDT_LOCK); +} + +static irqreturn_t sprd_wdt_isr(int irq, void *dev_id) +{ + struct sprd_wdt *wdt = (struct sprd_wdt *)dev_id; + + sprd_wdt_unlock(wdt->base); + writel_relaxed(WDT_INT_CLEAR_BIT, wdt->base + WDT_INT_CLR); + sprd_wdt_lock(wdt->base); + watchdog_notify_pretimeout(>wdd); + return IRQ_HANDLED; +} + +static u32 sprd_wdt_get_cnt_value(struct sprd_wdt *wdt) +{ + u32 val; + + val = readl_relaxed(wdt->base + WDT_CNT_HIGH) << WDT_CNT_VALUE_SIZE; + val |= readl_relaxed(wdt->base + WDT_CNT_LOW) & WDT_CNT_VALUE_MASK; + + return val; +} + +static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 rst_value, + u32 irq_value) +{ + u32 val, cnt = 0; + + sprd_wdt_unlock(wdt->base); + writel_relaxed((rst_value >> WDT_CNT_VALUE_SIZE) & WDT_CNT_VALUE_MASK, + wdt->base + WDT_LOAD_HIGH); + writel_relaxed((rst_value & WDT_CNT_VALUE_MASK), + wdt->base + WDT_LOAD_LOW); + writel_relaxed((irq_value >>