watchdog: imx2_wdt: convert to use regmap API.

This watchdog driver will be working on IMX2+, Vybrid, LS1, LS2+
platforms, and will be in different endianness mode in those SoCs:

SoCs         CPU endian mode      WDT endian mode
------------------------------------------------
IMX2+            LE                    LE
Vybird           LE                    LE
LS1              LE                    BE
LS2              LE                    LE

Other possible SoCs:
SoCs         CPU endian mode      WDT endian mode
------------------------------------------------
Soc1             BE                    BE
Soc2             BE                    LE

And also the watchdog's registers will be 32-bits for some versions,
and though it is 16-bits in IMX2+, Vybird and LS+.

Using the regmap APIs, could be more easy to support different
endianness and also more easy to support 32-bits version...

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
This commit is contained in:
Xiubo Li 2014-04-04 09:33:25 +08:00 committed by Wim Van Sebroeck
parent 30cb042a84
commit a797700329
2 changed files with 33 additions and 18 deletions

View File

@ -378,6 +378,7 @@ config MAX63XX_WATCHDOG
config IMX2_WDT config IMX2_WDT
tristate "IMX2+ Watchdog" tristate "IMX2+ Watchdog"
depends on ARCH_MXC depends on ARCH_MXC
select REGMAP_MMIO
help help
This is the driver for the hardware watchdog This is the driver for the hardware watchdog
on the Freescale IMX2 and later processors. on the Freescale IMX2 and later processors.

View File

@ -31,6 +31,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
@ -61,7 +62,7 @@
static struct { static struct {
struct clk *clk; struct clk *clk;
void __iomem *base; struct regmap *regmap;
unsigned timeout; unsigned timeout;
unsigned long status; unsigned long status;
struct timer_list timer; /* Pings the watchdog when closed */ struct timer_list timer; /* Pings the watchdog when closed */
@ -87,7 +88,9 @@ static const struct watchdog_info imx2_wdt_info = {
static inline void imx2_wdt_setup(void) static inline void imx2_wdt_setup(void)
{ {
u16 val = __raw_readw(imx2_wdt.base + IMX2_WDT_WCR); u32 val;
regmap_read(imx2_wdt.regmap, IMX2_WDT_WCR, &val);
/* Suspend timer in low power mode, write once-only */ /* Suspend timer in low power mode, write once-only */
val |= IMX2_WDT_WCR_WDZST; val |= IMX2_WDT_WCR_WDZST;
@ -100,17 +103,17 @@ static inline void imx2_wdt_setup(void)
/* Set the watchdog's Time-Out value */ /* Set the watchdog's Time-Out value */
val |= WDOG_SEC_TO_COUNT(imx2_wdt.timeout); val |= WDOG_SEC_TO_COUNT(imx2_wdt.timeout);
__raw_writew(val, imx2_wdt.base + IMX2_WDT_WCR); regmap_write(imx2_wdt.regmap, IMX2_WDT_WCR, val);
/* enable the watchdog */ /* enable the watchdog */
val |= IMX2_WDT_WCR_WDE; val |= IMX2_WDT_WCR_WDE;
__raw_writew(val, imx2_wdt.base + IMX2_WDT_WCR); regmap_write(imx2_wdt.regmap, IMX2_WDT_WCR, val);
} }
static inline void imx2_wdt_ping(void) static inline void imx2_wdt_ping(void)
{ {
__raw_writew(IMX2_WDT_SEQ1, imx2_wdt.base + IMX2_WDT_WSR); regmap_write(imx2_wdt.regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ1);
__raw_writew(IMX2_WDT_SEQ2, imx2_wdt.base + IMX2_WDT_WSR); regmap_write(imx2_wdt.regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ2);
} }
static void imx2_wdt_timer_ping(unsigned long arg) static void imx2_wdt_timer_ping(unsigned long arg)
@ -143,12 +146,8 @@ static void imx2_wdt_stop(void)
static void imx2_wdt_set_timeout(int new_timeout) static void imx2_wdt_set_timeout(int new_timeout)
{ {
u16 val = __raw_readw(imx2_wdt.base + IMX2_WDT_WCR); regmap_update_bits(imx2_wdt.regmap, IMX2_WDT_WCR, IMX2_WDT_WCR_WT,
WDOG_SEC_TO_COUNT(new_timeout));
/* set the new timeout value in the WSR */
val &= ~IMX2_WDT_WCR_WT;
val |= WDOG_SEC_TO_COUNT(new_timeout);
__raw_writew(val, imx2_wdt.base + IMX2_WDT_WCR);
} }
static int imx2_wdt_open(struct inode *inode, struct file *file) static int imx2_wdt_open(struct inode *inode, struct file *file)
@ -181,7 +180,7 @@ static long imx2_wdt_ioctl(struct file *file, unsigned int cmd,
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
int new_value; int new_value;
u16 val; u32 val;
switch (cmd) { switch (cmd) {
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
@ -192,7 +191,7 @@ static long imx2_wdt_ioctl(struct file *file, unsigned int cmd,
return put_user(0, p); return put_user(0, p);
case WDIOC_GETBOOTSTATUS: case WDIOC_GETBOOTSTATUS:
val = __raw_readw(imx2_wdt.base + IMX2_WDT_WRSR); regmap_read(imx2_wdt.regmap, IMX2_WDT_WRSR, &val);
new_value = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0; new_value = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0;
return put_user(new_value, p); return put_user(new_value, p);
@ -255,15 +254,30 @@ static struct miscdevice imx2_wdt_miscdev = {
.fops = &imx2_wdt_fops, .fops = &imx2_wdt_fops,
}; };
static struct regmap_config imx2_wdt_regmap_config = {
.reg_bits = 16,
.reg_stride = 2,
.val_bits = 16,
.max_register = 0x8,
};
static int __init imx2_wdt_probe(struct platform_device *pdev) static int __init imx2_wdt_probe(struct platform_device *pdev)
{ {
int ret;
struct resource *res; struct resource *res;
void __iomem *base;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
imx2_wdt.base = devm_ioremap_resource(&pdev->dev, res); base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(imx2_wdt.base)) if (IS_ERR(base))
return PTR_ERR(imx2_wdt.base); return PTR_ERR(base);
imx2_wdt.regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
&imx2_wdt_regmap_config);
if (IS_ERR(imx2_wdt.regmap)) {
dev_err(&pdev->dev, "regmap init failed\n");
return PTR_ERR(imx2_wdt.regmap);
}
imx2_wdt.clk = devm_clk_get(&pdev->dev, NULL); imx2_wdt.clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(imx2_wdt.clk)) { if (IS_ERR(imx2_wdt.clk)) {