2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2013-08-08 13:31:43 +04:00
/*
* Ralink RT288x / RT3xxx / MT76xx built - in hardware watchdog timer
*
* Copyright ( C ) 2011 Gabor Juhos < juhosg @ openwrt . org >
2016-12-20 21:56:59 +03:00
* Copyright ( C ) 2013 John Crispin < john @ phrozen . org >
2013-08-08 13:31:43 +04:00
*
* This driver was based on : drivers / watchdog / softdog . c
*/
# include <linux/clk.h>
# include <linux/reset.h>
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/watchdog.h>
# include <linux/moduleparam.h>
# include <linux/platform_device.h>
2018-12-30 06:21:52 +03:00
# include <linux/mod_devicetable.h>
2013-08-08 13:31:43 +04:00
# include <asm/mach-ralink/ralink_regs.h>
# define SYSC_RSTSTAT 0x38
# define WDT_RST_CAUSE BIT(1)
# define RALINK_WDT_TIMEOUT 30
# define RALINK_WDT_PRESCALE 65536
# define TIMER_REG_TMR1LOAD 0x00
# define TIMER_REG_TMR1CTL 0x08
# define TMRSTAT_TMR1RST BIT(5)
# define TMR1CTL_ENABLE BIT(7)
# define TMR1CTL_MODE_SHIFT 4
# define TMR1CTL_MODE_MASK 0x3
# define TMR1CTL_MODE_FREE_RUNNING 0x0
# define TMR1CTL_MODE_PERIODIC 0x1
# define TMR1CTL_MODE_TIMEOUT 0x2
# define TMR1CTL_MODE_WDT 0x3
# define TMR1CTL_PRESCALE_MASK 0xf
# define TMR1CTL_PRESCALE_65536 0xf
static struct clk * rt288x_wdt_clk ;
static unsigned long rt288x_wdt_freq ;
static void __iomem * rt288x_wdt_base ;
2014-10-17 00:01:05 +04:00
static struct reset_control * rt288x_wdt_reset ;
2013-08-08 13:31:43 +04:00
static bool nowayout = WATCHDOG_NOWAYOUT ;
module_param ( nowayout , bool , 0 ) ;
MODULE_PARM_DESC ( nowayout ,
" Watchdog cannot be stopped once started (default= "
__MODULE_STRING ( WATCHDOG_NOWAYOUT ) " ) " ) ;
static inline void rt_wdt_w32 ( unsigned reg , u32 val )
{
iowrite32 ( val , rt288x_wdt_base + reg ) ;
}
static inline u32 rt_wdt_r32 ( unsigned reg )
{
return ioread32 ( rt288x_wdt_base + reg ) ;
}
static int rt288x_wdt_ping ( struct watchdog_device * w )
{
rt_wdt_w32 ( TIMER_REG_TMR1LOAD , w - > timeout * rt288x_wdt_freq ) ;
return 0 ;
}
static int rt288x_wdt_start ( struct watchdog_device * w )
{
u32 t ;
t = rt_wdt_r32 ( TIMER_REG_TMR1CTL ) ;
t & = ~ ( TMR1CTL_MODE_MASK < < TMR1CTL_MODE_SHIFT |
TMR1CTL_PRESCALE_MASK ) ;
t | = ( TMR1CTL_MODE_WDT < < TMR1CTL_MODE_SHIFT |
TMR1CTL_PRESCALE_65536 ) ;
rt_wdt_w32 ( TIMER_REG_TMR1CTL , t ) ;
rt288x_wdt_ping ( w ) ;
t = rt_wdt_r32 ( TIMER_REG_TMR1CTL ) ;
t | = TMR1CTL_ENABLE ;
rt_wdt_w32 ( TIMER_REG_TMR1CTL , t ) ;
return 0 ;
}
static int rt288x_wdt_stop ( struct watchdog_device * w )
{
u32 t ;
rt288x_wdt_ping ( w ) ;
t = rt_wdt_r32 ( TIMER_REG_TMR1CTL ) ;
t & = ~ TMR1CTL_ENABLE ;
rt_wdt_w32 ( TIMER_REG_TMR1CTL , t ) ;
return 0 ;
}
static int rt288x_wdt_set_timeout ( struct watchdog_device * w , unsigned int t )
{
w - > timeout = t ;
rt288x_wdt_ping ( w ) ;
return 0 ;
}
static int rt288x_wdt_bootcause ( void )
{
if ( rt_sysc_r32 ( SYSC_RSTSTAT ) & WDT_RST_CAUSE )
return WDIOF_CARDRESET ;
return 0 ;
}
2017-08-04 00:21:31 +03:00
static const struct watchdog_info rt288x_wdt_info = {
2013-08-08 13:31:43 +04:00
. identity = " Ralink Watchdog " ,
. options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE ,
} ;
2017-01-28 10:41:17 +03:00
static const struct watchdog_ops rt288x_wdt_ops = {
2013-08-08 13:31:43 +04:00
. owner = THIS_MODULE ,
. start = rt288x_wdt_start ,
. stop = rt288x_wdt_stop ,
. ping = rt288x_wdt_ping ,
. set_timeout = rt288x_wdt_set_timeout ,
} ;
static struct watchdog_device rt288x_wdt_dev = {
. info = & rt288x_wdt_info ,
. ops = & rt288x_wdt_ops ,
. min_timeout = 1 ,
} ;
static int rt288x_wdt_probe ( struct platform_device * pdev )
{
2019-04-10 19:28:00 +03:00
struct device * dev = & pdev - > dev ;
2013-08-08 13:31:43 +04:00
int ret ;
watchdog: Convert to use devm_platform_ioremap_resource
Use devm_platform_ioremap_resource to reduce source code size,
improve readability, and reduce the likelyhood of bugs.
The conversion was done automatically with coccinelle using the
following semantic patch.
@r@
identifier res, pdev;
expression a;
expression index;
expression e;
@@
<+...
- res = platform_get_resource(pdev, IORESOURCE_MEM, index);
- a = devm_ioremap_resource(e, res);
+ a = devm_platform_ioremap_resource(pdev, index);
...+>
@depends on r@
identifier r.res;
@@
- struct resource *res;
... when != res
@@
identifier res, pdev;
expression index;
expression a;
@@
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, index);
- a = devm_ioremap_resource(&pdev->dev, res);
+ a = devm_platform_ioremap_resource(pdev, index);
Cc: Joel Stanley <joel@jms.id.au>
Cc: Nicolas Ferre <nicolas.ferre@microchip.com>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Baruch Siach <baruch@tkos.co.il>
Cc: Keguang Zhang <keguang.zhang@gmail.com>
Cc: Vladimir Zapolskiy <vz@mleia.com>
Cc: Kevin Hilman <khilman@baylibre.com>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Avi Fishman <avifishman70@gmail.com>
Cc: Nancy Yuen <yuenn@google.com>
Cc: Brendan Higgins <brendanhiggins@google.com>
Cc: Wan ZongShun <mcuos.com@gmail.com>
Cc: Michal Simek <michal.simek@xilinx.com>
Cc: Sylvain Lemieux <slemieux.tyco@gmail.com>
Cc: Kukjin Kim <kgene@kernel.org>
Cc: Barry Song <baohua@kernel.org>
Cc: Orson Zhai <orsonzhai@gmail.com>
Cc: Patrice Chotard <patrice.chotard@st.com>
Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Cc: Maxime Ripard <maxime.ripard@bootlin.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Marc Gonzalez <marc.w.gonzalez@free.fr>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Shawn Guo <shawnguo@kernel.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Tested-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Acked-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
Acked-by: Michal Simek <michal.simek@xilinx.com> (cadence/xilinx wdts)
Acked-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Patrice Chotard <patrice.chotard@st.com>
Acked-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
2019-04-02 22:01:53 +03:00
rt288x_wdt_base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2013-08-08 13:31:43 +04:00
if ( IS_ERR ( rt288x_wdt_base ) )
return PTR_ERR ( rt288x_wdt_base ) ;
2019-04-10 19:28:00 +03:00
rt288x_wdt_clk = devm_clk_get ( dev , NULL ) ;
2013-08-08 13:31:43 +04:00
if ( IS_ERR ( rt288x_wdt_clk ) )
return PTR_ERR ( rt288x_wdt_clk ) ;
2019-04-10 19:28:00 +03:00
rt288x_wdt_reset = devm_reset_control_get_exclusive ( dev , NULL ) ;
2014-10-17 00:01:05 +04:00
if ( ! IS_ERR ( rt288x_wdt_reset ) )
reset_control_deassert ( rt288x_wdt_reset ) ;
2013-08-08 13:31:43 +04:00
rt288x_wdt_freq = clk_get_rate ( rt288x_wdt_clk ) / RALINK_WDT_PRESCALE ;
rt288x_wdt_dev . bootstatus = rt288x_wdt_bootcause ( ) ;
rt288x_wdt_dev . max_timeout = ( 0xfffful / rt288x_wdt_freq ) ;
2019-04-10 19:28:00 +03:00
rt288x_wdt_dev . parent = dev ;
2013-08-08 13:31:43 +04:00
2014-10-17 00:01:05 +04:00
watchdog_init_timeout ( & rt288x_wdt_dev , rt288x_wdt_dev . max_timeout ,
2019-04-10 19:28:00 +03:00
dev ) ;
2013-08-08 13:31:43 +04:00
watchdog_set_nowayout ( & rt288x_wdt_dev , nowayout ) ;
2019-04-10 19:28:00 +03:00
watchdog_stop_on_reboot ( & rt288x_wdt_dev ) ;
ret = devm_watchdog_register_device ( dev , & rt288x_wdt_dev ) ;
2013-08-08 13:31:43 +04:00
if ( ! ret )
2019-04-10 19:28:00 +03:00
dev_info ( dev , " Initialized \n " ) ;
2013-08-08 13:31:43 +04:00
return 0 ;
}
static const struct of_device_id rt288x_wdt_match [ ] = {
{ . compatible = " ralink,rt2880-wdt " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , rt288x_wdt_match ) ;
static struct platform_driver rt288x_wdt_driver = {
. probe = rt288x_wdt_probe ,
. driver = {
. name = KBUILD_MODNAME ,
. of_match_table = rt288x_wdt_match ,
} ,
} ;
module_platform_driver ( rt288x_wdt_driver ) ;
MODULE_DESCRIPTION ( " MediaTek/Ralink RT288x/RT3xxx hardware watchdog driver " ) ;
MODULE_AUTHOR ( " Gabor Juhos <juhosg@openwrt.org " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;