2019-05-27 09:55:05 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2013-07-03 00:38:58 +04:00
/*
* AppliedMicro X - Gene SoC Reboot Driver
*
* Copyright ( c ) 2013 , Applied Micro Circuits Corporation
* Author : Feng Kan < fkan @ apm . com >
* Author : Loc Ho < lho @ apm . com >
*
* This driver provides system reboot functionality for APM X - Gene SoC .
* For system shutdown , this is board specify . If a board designer
* implements GPIO shutdown , use the gpio - poweroff . c driver .
*/
2014-09-30 21:48:31 +04:00
# include <linux/delay.h>
2013-07-03 00:38:58 +04:00
# include <linux/io.h>
2014-09-30 21:48:32 +04:00
# include <linux/notifier.h>
2013-07-03 00:38:58 +04:00
# include <linux/of_device.h>
# include <linux/of_address.h>
# include <linux/platform_device.h>
2014-09-30 21:48:32 +04:00
# include <linux/reboot.h>
2013-07-03 00:38:58 +04:00
# include <linux/stat.h>
# include <linux/slab.h>
struct xgene_reboot_context {
2014-09-30 21:48:30 +04:00
struct device * dev ;
2013-07-03 00:38:58 +04:00
void * csr ;
u32 mask ;
2014-09-30 21:48:32 +04:00
struct notifier_block restart_handler ;
2013-07-03 00:38:58 +04:00
} ;
2014-09-30 21:48:32 +04:00
static int xgene_restart_handler ( struct notifier_block * this ,
unsigned long mode , void * cmd )
2013-07-03 00:38:58 +04:00
{
2014-09-30 21:48:32 +04:00
struct xgene_reboot_context * ctx =
container_of ( this , struct xgene_reboot_context ,
restart_handler ) ;
2013-07-03 00:38:58 +04:00
/* Issue the reboot */
2014-09-30 21:48:32 +04:00
writel ( ctx - > mask , ctx - > csr ) ;
2013-07-03 00:38:58 +04:00
2014-09-30 21:48:31 +04:00
mdelay ( 1000 ) ;
2013-07-03 00:38:58 +04:00
2014-09-30 21:48:30 +04:00
dev_emerg ( ctx - > dev , " Unable to restart system \n " ) ;
2014-09-30 21:48:32 +04:00
return NOTIFY_DONE ;
2013-07-03 00:38:58 +04:00
}
static int xgene_reboot_probe ( struct platform_device * pdev )
{
struct xgene_reboot_context * ctx ;
2014-09-30 21:48:30 +04:00
struct device * dev = & pdev - > dev ;
2014-09-30 21:48:32 +04:00
int err ;
2013-07-03 00:38:58 +04:00
2014-09-30 21:48:30 +04:00
ctx = devm_kzalloc ( dev , sizeof ( * ctx ) , GFP_KERNEL ) ;
2014-09-30 21:48:28 +04:00
if ( ! ctx )
return - ENOMEM ;
2013-07-03 00:38:58 +04:00
2014-09-30 21:48:30 +04:00
ctx - > csr = of_iomap ( dev - > of_node , 0 ) ;
2013-07-03 00:38:58 +04:00
if ( ! ctx - > csr ) {
2014-09-30 21:48:30 +04:00
dev_err ( dev , " can not map resource \n " ) ;
2013-07-03 00:38:58 +04:00
return - ENODEV ;
}
2014-09-30 21:48:30 +04:00
if ( of_property_read_u32 ( dev - > of_node , " mask " , & ctx - > mask ) )
2013-07-03 00:38:58 +04:00
ctx - > mask = 0xFFFFFFFF ;
2014-09-30 21:48:30 +04:00
ctx - > dev = dev ;
2014-09-30 21:48:32 +04:00
ctx - > restart_handler . notifier_call = xgene_restart_handler ;
ctx - > restart_handler . priority = 128 ;
err = register_restart_handler ( & ctx - > restart_handler ) ;
2016-09-14 13:55:39 +03:00
if ( err ) {
iounmap ( ctx - > csr ) ;
2014-09-30 21:48:32 +04:00
dev_err ( dev , " cannot register restart handler (err=%d) \n " , err ) ;
2016-09-14 13:55:39 +03:00
}
2013-07-03 00:38:58 +04:00
2014-09-30 21:48:32 +04:00
return err ;
2013-07-03 00:38:58 +04:00
}
2015-03-16 22:17:12 +03:00
static const struct of_device_id xgene_reboot_of_match [ ] = {
2013-07-03 00:38:58 +04:00
{ . compatible = " apm,xgene-reboot " } ,
{ }
} ;
static struct platform_driver xgene_reboot_driver = {
. probe = xgene_reboot_probe ,
. driver = {
. name = " xgene-reboot " ,
. of_match_table = xgene_reboot_of_match ,
} ,
} ;
static int __init xgene_reboot_init ( void )
{
return platform_driver_register ( & xgene_reboot_driver ) ;
}
device_initcall ( xgene_reboot_init ) ;