@ -62,9 +62,15 @@
# define CONFIG_S3C2410_WATCHDOG_ATBOOT (0)
# define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15)
# define EXYNOS5_RST_STAT_REG_OFFSET 0x0404
# define EXYNOS5_WDT_DISABLE_REG_OFFSET 0x0408
# define EXYNOS5_WDT_MASK_RESET_REG_OFFSET 0x040c
# define QUIRK_HAS_PMU_CONFIG (1 << 0)
# define QUIRK_HAS_RST_STAT (1 << 1)
/* These quirks require that we have a PMU register map */
# define QUIRKS_HAVE_PMUREG (QUIRK_HAS_PMU_CONFIG | \
QUIRK_HAS_RST_STAT )
static bool nowayout = WATCHDOG_NOWAYOUT ;
static int tmr_margin ;
@ -98,6 +104,9 @@ MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug (default 0)");
* timer reset functionality .
* @ mask_bit : Bit number for the watchdog timer in the disable register and the
* mask reset register .
* @ rst_stat_reg : Offset in pmureg for the register that has the reset status .
* @ rst_stat_bit : Bit number in the rst_stat register indicating a watchdog
* reset .
* @ quirks : A bitfield of quirks .
*/
@ -105,6 +114,8 @@ struct s3c2410_wdt_variant {
int disable_reg ;
int mask_reset_reg ;
int mask_bit ;
int rst_stat_reg ;
int rst_stat_bit ;
u32 quirks ;
} ;
@ -131,14 +142,18 @@ static const struct s3c2410_wdt_variant drv_data_exynos5250 = {
. disable_reg = EXYNOS5_WDT_DISABLE_REG_OFFSET ,
. mask_reset_reg = EXYNOS5_WDT_MASK_RESET_REG_OFFSET ,
. mask_bit = 20 ,
. quirks = QUIRK_HAS_PMU_CONFIG
. rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET ,
. rst_stat_bit = 20 ,
. quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT ,
} ;
static const struct s3c2410_wdt_variant drv_data_exynos5420 = {
. disable_reg = EXYNOS5_WDT_DISABLE_REG_OFFSET ,
. mask_reset_reg = EXYNOS5_WDT_MASK_RESET_REG_OFFSET ,
. mask_bit = 0 ,
. quirks = QUIRK_HAS_PMU_CONFIG
. rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET ,
. rst_stat_bit = 9 ,
. quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT ,
} ;
static const struct of_device_id s3c2410_wdt_match [ ] = {
@ -424,6 +439,23 @@ static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt)
}
# endif
static inline unsigned int s3c2410wdt_get_bootstatus ( struct s3c2410_wdt * wdt )
{
unsigned int rst_stat ;
int ret ;
if ( ! ( wdt - > drv_data - > quirks & QUIRK_HAS_RST_STAT ) )
return 0 ;
ret = regmap_read ( wdt - > pmureg , wdt - > drv_data - > rst_stat_reg , & rst_stat ) ;
if ( ret )
dev_warn ( wdt - > dev , " Couldn't get RST_STAT register \n " ) ;
else if ( rst_stat & BIT ( wdt - > drv_data - > rst_stat_bit ) )
return WDIOF_CARDRESET ;
return 0 ;
}
/* s3c2410_get_wdt_driver_data */
static inline struct s3c2410_wdt_variant *
get_wdt_drv_data ( struct platform_device * pdev )
@ -461,7 +493,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
wdt - > wdt_device = s3c2410_wdd ;
wdt - > drv_data = get_wdt_drv_data ( pdev ) ;
if ( wdt - > drv_data - > quirks & QUIRK_HAS_PMU_CONFI G ) {
if ( wdt - > drv_data - > quirks & QUIRKS_HAVE_PMURE G ) {
wdt - > pmureg = syscon_regmap_lookup_by_phandle ( dev - > of_node ,
" samsung,syscon-phandle " ) ;
if ( IS_ERR ( wdt - > pmureg ) ) {
@ -532,6 +564,8 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
watchdog_set_nowayout ( & wdt - > wdt_device , nowayout ) ;
wdt - > wdt_device . bootstatus = s3c2410wdt_get_bootstatus ( wdt ) ;
ret = watchdog_register_device ( & wdt - > wdt_device ) ;
if ( ret ) {
dev_err ( dev , " cannot register watchdog (%d) \n " , ret ) ;