@ -1,13 +1,17 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright ( c ) 2011 - 2013 Xilinx Inc .
* Xilinx AXI platforms watchdog timer driver .
*
* Author ( s ) : Michal Simek < michal . simek @ xilinx . com >
* Shreenidhi Shedi < yesshedi @ gmail . com >
*
* Copyright ( c ) 2011 - 2018 Xilinx Inc .
*/
# include <common.h>
# include <asm/io.h>
# include <asm/microblaze_intc.h>
# include <asm/processor.h>
# include <watchdog.h>
# include <dm.h>
# include <wdt.h>
# include <linux/io.h>
# define XWT_CSR0_WRS_MASK 0x00000008 /* Reset status Mask */
# define XWT_CSR0_WDS_MASK 0x00000004 /* Timer state Mask */
@ -20,49 +24,104 @@ struct watchdog_regs {
u32 tbr ; /* 0x8 */
} ;
static struct watchdog_regs * watchdog_base =
( struct watchdog_regs * ) CONFIG_WATCHDOG_BASEADDR ;
struct xlnx_wdt_platdata {
bool enable_once ;
struct watchdog_regs * regs ;
} ;
void hw_watchdog_reset ( void )
static int xlnx_wdt _reset( struct ude vice * dev )
{
u32 reg ;
struct xlnx_wdt_platdata * platdata = dev_get_platdata ( dev ) ;
debug ( " %s " , __func__ ) ;
/* Read the current contents of TCSR0 */
reg = readl ( & watchdog_base - > twcsr0 ) ;
reg = readl ( & platdata - > regs - > twcsr0 ) ;
/* Clear the watchdog WDS bit */
if ( reg & ( XWT_CSR0_EWDT1_MASK | XWT_CSRX_EWDT2_MASK ) )
writel ( reg | XWT_CSR0_WDS_MASK , & watchdog_base - > twcsr0 ) ;
writel ( reg | XWT_CSR0_WDS_MASK , & platdata - > regs - > twcsr0 ) ;
return 0 ;
}
void hw_watchdog_disable ( void )
static int xlnx_wdt_stop ( struct udevice * dev )
{
u32 reg ;
struct xlnx_wdt_platdata * platdata = dev_get_platdata ( dev ) ;
if ( platdata - > enable_once ) {
debug ( " Can't stop Xilinx watchdog. \n " ) ;
return - EBUSY ;
}
/* Read the current contents of TCSR0 */
reg = readl ( & watchdog_base - > twcsr0 ) ;
reg = readl ( & platdata - > regs - > twcsr0 ) ;
writel ( reg & ~ XWT_CSR0_EWDT1_MASK , & platdata - > regs - > twcsr0 ) ;
writel ( ~ XWT_CSRX_EWDT2_MASK , & platdata - > regs - > twcsr1 ) ;
writel ( reg & ~ XWT_CSR0_EWDT1_MASK , & watchdog_base - > twcsr0 ) ;
writel ( ~ XWT_CSRX_EWDT2_MASK , & watchdog_base - > twcsr1 ) ;
debug ( " Watchdog disabled! \n " ) ;
puts ( " Watchdog disabled! \n " ) ;
return 0 ;
}
static void hw_watchdog_isr ( void * arg )
static int xlnx_wdt_start ( struct udevice * dev , u64 timeout , ulong flags )
{
hw_watchdog_reset ( ) ;
struct xlnx_wdt_platdata * platdata = dev_get_platdata ( dev ) ;
debug ( " %s: \n " , __func__ ) ;
writel ( ( XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK | XWT_CSR0_EWDT1_MASK ) ,
& platdata - > regs - > twcsr0 ) ;
writel ( XWT_CSRX_EWDT2_MASK , & platdata - > regs - > twcsr1 ) ;
return 0 ;
}
void hw_watchdog_init ( void )
static int xlnx_wdt_probe ( struct udevice * dev )
{
int ret ;
debug ( " %s: Probing wdt%u \n " , __func__ , dev - > seq ) ;
writel ( ( XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK | XWT_CSR0_EWDT1_MASK ) ,
& watchdog_base - > twcsr0 ) ;
writel ( XWT_CSRX_EWDT2_MASK , & watchdog_base - > twcsr1 ) ;
return 0 ;
}
ret = install_interrupt_handler ( CONFIG_WATCHDOG_IRQ ,
hw_watchdog_isr , NULL ) ;
if ( ret )
puts ( " Watchdog IRQ registration failed. " ) ;
static int xlnx_wdt_ofdata_to_platdata ( struct udevice * dev )
{
struct xlnx_wdt_platdata * platdata = dev_get_platdata ( dev ) ;
platdata - > regs = ( struct watchdog_regs * ) dev_read_addr ( dev ) ;
if ( IS_ERR ( platdata - > regs ) )
return PTR_ERR ( platdata - > regs ) ;
platdata - > enable_once = dev_read_u32_default ( dev ,
" xlnx,wdt-enable-once " , 0 ) ;
debug ( " %s: wdt-enable-once %d \n " , __func__ , platdata - > enable_once ) ;
return 0 ;
}
static const struct wdt_ops xlnx_wdt_ops = {
. start = xlnx_wdt_start ,
. reset = xlnx_wdt_reset ,
. stop = xlnx_wdt_stop ,
} ;
static const struct udevice_id xlnx_wdt_ids [ ] = {
{ . compatible = " xlnx,xps-timebase-wdt-1.00.a " , } ,
{ . compatible = " xlnx,xps-timebase-wdt-1.01.a " , } ,
{ } ,
} ;
U_BOOT_DRIVER ( xlnx_wdt ) = {
. name = " xlnx_wdt " ,
. id = UCLASS_WDT ,
. of_match = xlnx_wdt_ids ,
. probe = xlnx_wdt_probe ,
. platdata_auto_alloc_size = sizeof ( struct xlnx_wdt_platdata ) ,
. ofdata_to_platdata = xlnx_wdt_ofdata_to_platdata ,
. ops = & xlnx_wdt_ops ,
} ;