2019-05-29 17:17:58 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2014-05-23 13:08:38 +04:00
/*
* Reset driver for Axxia devices
*
* Copyright ( C ) 2014 LSI
*/
# include <linux/init.h>
# include <linux/err.h>
# include <linux/io.h>
# include <linux/kernel.h>
# include <linux/mfd/syscon.h>
# include <linux/module.h>
2014-09-30 21:48:33 +04:00
# include <linux/notifier.h>
2014-05-23 13:08:38 +04:00
# include <linux/of.h>
# include <linux/platform_device.h>
# include <linux/reboot.h>
# include <linux/regmap.h>
# define SC_CRIT_WRITE_KEY 0x1000
# define SC_LATCH_ON_RESET 0x1004
# define SC_RESET_CONTROL 0x1008
# define RSTCTL_RST_ZERO (1<<3)
# define RSTCTL_RST_FAB (1<<2)
# define RSTCTL_RST_CHIP (1<<1)
# define RSTCTL_RST_SYS (1<<0)
# define SC_EFUSE_INT_STATUS 0x180c
# define EFUSE_READ_DONE (1<<31)
static struct regmap * syscon ;
2014-09-30 21:48:33 +04:00
static int axxia_restart_handler ( struct notifier_block * this ,
unsigned long mode , void * cmd )
2014-05-23 13:08:38 +04:00
{
/* Access Key (0xab) */
regmap_write ( syscon , SC_CRIT_WRITE_KEY , 0xab ) ;
/* Select internal boot from 0xffff0000 */
regmap_write ( syscon , SC_LATCH_ON_RESET , 0x00000040 ) ;
/* Assert ResetReadDone (to avoid hanging in boot ROM) */
regmap_write ( syscon , SC_EFUSE_INT_STATUS , EFUSE_READ_DONE ) ;
/* Assert chip reset */
regmap_update_bits ( syscon , SC_RESET_CONTROL ,
RSTCTL_RST_CHIP , RSTCTL_RST_CHIP ) ;
2014-09-30 21:48:33 +04:00
return NOTIFY_DONE ;
2014-05-23 13:08:38 +04:00
}
2014-09-30 21:48:33 +04:00
static struct notifier_block axxia_restart_nb = {
. notifier_call = axxia_restart_handler ,
. priority = 128 ,
} ;
2014-05-23 13:08:38 +04:00
static int axxia_reset_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
2014-09-30 21:48:33 +04:00
int err ;
2014-05-23 13:08:38 +04:00
syscon = syscon_regmap_lookup_by_phandle ( dev - > of_node , " syscon " ) ;
if ( IS_ERR ( syscon ) ) {
2018-09-05 19:34:56 +03:00
pr_err ( " %pOFn: syscon lookup failed \n " , dev - > of_node ) ;
2014-05-23 13:08:38 +04:00
return PTR_ERR ( syscon ) ;
}
2014-09-30 21:48:33 +04:00
err = register_restart_handler ( & axxia_restart_nb ) ;
if ( err )
dev_err ( dev , " cannot register restart handler (err=%d) \n " , err ) ;
2014-05-23 13:08:38 +04:00
2014-09-30 21:48:33 +04:00
return err ;
2014-05-23 13:08:38 +04:00
}
static const struct of_device_id of_axxia_reset_match [ ] = {
{ . compatible = " lsi,axm55xx-reset " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , of_axxia_reset_match ) ;
static struct platform_driver axxia_reset_driver = {
. probe = axxia_reset_probe ,
. driver = {
. name = " axxia-reset " ,
. of_match_table = of_match_ptr ( of_axxia_reset_match ) ,
} ,
} ;
static int __init axxia_reset_init ( void )
{
return platform_driver_register ( & axxia_reset_driver ) ;
}
device_initcall ( axxia_reset_init ) ;