2012-11-19 20:23:13 +04:00
/*
* Reset Controller framework
*
* Copyright 2013 Philipp Zabel , Pengutronix
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
2016-02-23 20:46:26 +03:00
# include <linux/atomic.h>
2012-11-19 20:23:13 +04:00
# include <linux/device.h>
# include <linux/err.h>
# include <linux/export.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/of.h>
# include <linux/reset.h>
# include <linux/reset-controller.h>
# include <linux/slab.h>
2016-02-23 20:46:25 +03:00
static DEFINE_MUTEX ( reset_list_mutex ) ;
2012-11-19 20:23:13 +04:00
static LIST_HEAD ( reset_controller_list ) ;
/**
* struct reset_control - a reset control
* @ rcdev : a pointer to the reset controller device
* this reset control belongs to
2016-02-23 20:46:25 +03:00
* @ list : list entry for the rcdev ' s reset controller list
2012-11-19 20:23:13 +04:00
* @ id : ID of the reset controller in the reset
* controller device
2016-02-23 20:46:25 +03:00
* @ refcnt : Number of gets of this reset_control
2016-02-23 20:46:26 +03:00
* @ shared : Is this a shared ( 1 ) , or an exclusive ( 0 ) reset_control ?
* @ deassert_cnt : Number of times this reset line has been deasserted
2016-11-12 16:13:03 +03:00
* @ triggered_count : Number of times this reset line has been reset . Currently
* only used for shared resets , which means that the value
* will be either 0 or 1.
2012-11-19 20:23:13 +04:00
*/
struct reset_control {
struct reset_controller_dev * rcdev ;
2016-02-23 20:46:25 +03:00
struct list_head list ;
2012-11-19 20:23:13 +04:00
unsigned int id ;
2016-02-23 20:46:25 +03:00
unsigned int refcnt ;
2016-02-23 20:46:26 +03:00
int shared ;
atomic_t deassert_count ;
2016-11-12 16:13:03 +03:00
atomic_t triggered_count ;
2012-11-19 20:23:13 +04:00
} ;
/**
* of_reset_simple_xlate - translate reset_spec to the reset line number
* @ rcdev : a pointer to the reset controller device
* @ reset_spec : reset line specifier as found in the device tree
* @ flags : a flags pointer to fill in ( optional )
*
* This simple translation function should be used for reset controllers
* with 1 : 1 mapping , where reset lines can be indexed by number without gaps .
*/
2013-12-19 12:41:10 +04:00
static int of_reset_simple_xlate ( struct reset_controller_dev * rcdev ,
2012-11-19 20:23:13 +04:00
const struct of_phandle_args * reset_spec )
{
if ( reset_spec - > args [ 0 ] > = rcdev - > nr_resets )
return - EINVAL ;
return reset_spec - > args [ 0 ] ;
}
/**
* reset_controller_register - register a reset controller device
* @ rcdev : a pointer to the initialized reset controller device
*/
int reset_controller_register ( struct reset_controller_dev * rcdev )
{
if ( ! rcdev - > of_xlate ) {
rcdev - > of_reset_n_cells = 1 ;
rcdev - > of_xlate = of_reset_simple_xlate ;
}
2016-02-23 20:46:25 +03:00
INIT_LIST_HEAD ( & rcdev - > reset_control_head ) ;
mutex_lock ( & reset_list_mutex ) ;
2012-11-19 20:23:13 +04:00
list_add ( & rcdev - > list , & reset_controller_list ) ;
2016-02-23 20:46:25 +03:00
mutex_unlock ( & reset_list_mutex ) ;
2012-11-19 20:23:13 +04:00
return 0 ;
}
EXPORT_SYMBOL_GPL ( reset_controller_register ) ;
/**
* reset_controller_unregister - unregister a reset controller device
* @ rcdev : a pointer to the reset controller device
*/
void reset_controller_unregister ( struct reset_controller_dev * rcdev )
{
2016-02-23 20:46:25 +03:00
mutex_lock ( & reset_list_mutex ) ;
2012-11-19 20:23:13 +04:00
list_del ( & rcdev - > list ) ;
2016-02-23 20:46:25 +03:00
mutex_unlock ( & reset_list_mutex ) ;
2012-11-19 20:23:13 +04:00
}
EXPORT_SYMBOL_GPL ( reset_controller_unregister ) ;
2016-05-01 13:36:57 +03:00
static void devm_reset_controller_release ( struct device * dev , void * res )
{
reset_controller_unregister ( * ( struct reset_controller_dev * * ) res ) ;
}
/**
* devm_reset_controller_register - resource managed reset_controller_register ( )
* @ dev : device that is registering this reset controller
* @ rcdev : a pointer to the initialized reset controller device
*
* Managed reset_controller_register ( ) . For reset controllers registered by
* this function , reset_controller_unregister ( ) is automatically called on
* driver detach . See reset_controller_register ( ) for more information .
*/
int devm_reset_controller_register ( struct device * dev ,
struct reset_controller_dev * rcdev )
{
struct reset_controller_dev * * rcdevp ;
int ret ;
rcdevp = devres_alloc ( devm_reset_controller_release , sizeof ( * rcdevp ) ,
GFP_KERNEL ) ;
if ( ! rcdevp )
return - ENOMEM ;
ret = reset_controller_register ( rcdev ) ;
if ( ! ret ) {
* rcdevp = rcdev ;
devres_add ( dev , rcdevp ) ;
} else {
devres_free ( rcdevp ) ;
}
return ret ;
}
EXPORT_SYMBOL_GPL ( devm_reset_controller_register ) ;
2012-11-19 20:23:13 +04:00
/**
* reset_control_reset - reset the controlled device
* @ rstc : reset controller
2016-02-23 20:46:26 +03:00
*
2016-11-12 16:13:03 +03:00
* On a shared reset line the actual reset pulse is only triggered once for the
* lifetime of the reset_control instance : for all but the first caller this is
* a no - op .
* Consumers must not use reset_control_ ( de ) assert on shared reset lines when
* reset_control_reset has been used .
2012-11-19 20:23:13 +04:00
*/
int reset_control_reset ( struct reset_control * rstc )
{
2016-11-12 16:13:03 +03:00
int ret ;
if ( WARN_ON ( IS_ERR_OR_NULL ( rstc ) ) )
2016-02-23 20:46:26 +03:00
return - EINVAL ;
2016-11-12 16:13:03 +03:00
if ( ! rstc - > rcdev - > ops - > reset )
return - ENOTSUPP ;
if ( rstc - > shared ) {
if ( WARN_ON ( atomic_read ( & rstc - > deassert_count ) ! = 0 ) )
return - EINVAL ;
if ( atomic_inc_return ( & rstc - > triggered_count ) ! = 1 )
return 0 ;
}
2012-11-19 20:23:13 +04:00
2016-11-12 16:13:03 +03:00
ret = rstc - > rcdev - > ops - > reset ( rstc - > rcdev , rstc - > id ) ;
if ( rstc - > shared & & ! ret )
atomic_dec ( & rstc - > triggered_count ) ;
return ret ;
2012-11-19 20:23:13 +04:00
}
EXPORT_SYMBOL_GPL ( reset_control_reset ) ;
/**
* reset_control_assert - asserts the reset line
* @ rstc : reset controller
2016-02-23 20:46:26 +03:00
*
* Calling this on an exclusive reset controller guarantees that the reset
* will be asserted . When called on a shared reset controller the line may
* still be deasserted , as long as other users keep it so .
*
* For shared reset controls a driver cannot expect the hw ' s registers and
* internal state to be reset , but must be prepared for this to happen .
2016-11-12 16:13:03 +03:00
* Consumers must not use reset_control_reset on shared reset lines when
* reset_control_ ( de ) assert has been used .
2012-11-19 20:23:13 +04:00
*/
int reset_control_assert ( struct reset_control * rstc )
{
2016-06-20 14:05:14 +03:00
if ( WARN_ON ( IS_ERR_OR_NULL ( rstc ) ) )
return - EINVAL ;
2016-02-23 20:46:26 +03:00
if ( ! rstc - > rcdev - > ops - > assert )
return - ENOTSUPP ;
2012-11-19 20:23:13 +04:00
2016-02-23 20:46:26 +03:00
if ( rstc - > shared ) {
2016-11-12 16:13:03 +03:00
if ( WARN_ON ( atomic_read ( & rstc - > triggered_count ) ! = 0 ) )
return - EINVAL ;
2016-02-23 20:46:26 +03:00
if ( WARN_ON ( atomic_read ( & rstc - > deassert_count ) = = 0 ) )
return - EINVAL ;
if ( atomic_dec_return ( & rstc - > deassert_count ) ! = 0 )
return 0 ;
}
return rstc - > rcdev - > ops - > assert ( rstc - > rcdev , rstc - > id ) ;
2012-11-19 20:23:13 +04:00
}
EXPORT_SYMBOL_GPL ( reset_control_assert ) ;
/**
* reset_control_deassert - deasserts the reset line
* @ rstc : reset controller
2016-02-23 20:46:26 +03:00
*
* After calling this function , the reset is guaranteed to be deasserted .
2016-11-12 16:13:03 +03:00
* Consumers must not use reset_control_reset on shared reset lines when
* reset_control_ ( de ) assert has been used .
2012-11-19 20:23:13 +04:00
*/
int reset_control_deassert ( struct reset_control * rstc )
{
2016-06-20 14:05:14 +03:00
if ( WARN_ON ( IS_ERR_OR_NULL ( rstc ) ) )
return - EINVAL ;
2016-02-23 20:46:26 +03:00
if ( ! rstc - > rcdev - > ops - > deassert )
return - ENOTSUPP ;
2012-11-19 20:23:13 +04:00
2016-02-23 20:46:26 +03:00
if ( rstc - > shared ) {
2016-11-12 16:13:03 +03:00
if ( WARN_ON ( atomic_read ( & rstc - > triggered_count ) ! = 0 ) )
return - EINVAL ;
2016-02-23 20:46:26 +03:00
if ( atomic_inc_return ( & rstc - > deassert_count ) ! = 1 )
return 0 ;
}
return rstc - > rcdev - > ops - > deassert ( rstc - > rcdev , rstc - > id ) ;
2012-11-19 20:23:13 +04:00
}
EXPORT_SYMBOL_GPL ( reset_control_deassert ) ;
2014-10-10 19:21:14 +04:00
/**
* reset_control_status - returns a negative errno if not supported , a
* positive value if the reset line is asserted , or zero if the reset
* line is not asserted .
* @ rstc : reset controller
*/
int reset_control_status ( struct reset_control * rstc )
{
2016-06-20 14:05:14 +03:00
if ( WARN_ON ( IS_ERR_OR_NULL ( rstc ) ) )
return - EINVAL ;
2014-10-10 19:21:14 +04:00
if ( rstc - > rcdev - > ops - > status )
return rstc - > rcdev - > ops - > status ( rstc - > rcdev , rstc - > id ) ;
2015-10-29 11:55:00 +03:00
return - ENOTSUPP ;
2014-10-10 19:21:14 +04:00
}
EXPORT_SYMBOL_GPL ( reset_control_status ) ;
2016-02-23 20:46:25 +03:00
static struct reset_control * __reset_control_get (
struct reset_controller_dev * rcdev ,
2016-02-23 20:46:26 +03:00
unsigned int index , int shared )
2016-02-23 20:46:25 +03:00
{
struct reset_control * rstc ;
lockdep_assert_held ( & reset_list_mutex ) ;
list_for_each_entry ( rstc , & rcdev - > reset_control_head , list ) {
if ( rstc - > id = = index ) {
2016-02-23 20:46:26 +03:00
if ( WARN_ON ( ! rstc - > shared | | ! shared ) )
return ERR_PTR ( - EBUSY ) ;
2016-02-23 20:46:25 +03:00
rstc - > refcnt + + ;
return rstc ;
}
}
rstc = kzalloc ( sizeof ( * rstc ) , GFP_KERNEL ) ;
if ( ! rstc )
return ERR_PTR ( - ENOMEM ) ;
try_module_get ( rcdev - > owner ) ;
rstc - > rcdev = rcdev ;
list_add ( & rstc - > list , & rcdev - > reset_control_head ) ;
rstc - > id = index ;
rstc - > refcnt = 1 ;
2016-02-23 20:46:26 +03:00
rstc - > shared = shared ;
2016-02-23 20:46:25 +03:00
return rstc ;
}
static void __reset_control_put ( struct reset_control * rstc )
{
lockdep_assert_held ( & reset_list_mutex ) ;
if ( - - rstc - > refcnt )
return ;
module_put ( rstc - > rcdev - > owner ) ;
list_del ( & rstc - > list ) ;
kfree ( rstc ) ;
}
2016-02-23 20:46:24 +03:00
struct reset_control * __of_reset_control_get ( struct device_node * node ,
2016-02-23 20:46:26 +03:00
const char * id , int index , int shared )
2012-11-19 20:23:13 +04:00
{
2015-12-08 20:49:53 +03:00
struct reset_control * rstc ;
2012-11-19 20:23:13 +04:00
struct reset_controller_dev * r , * rcdev ;
struct of_phandle_args args ;
int rstc_id ;
int ret ;
2016-02-23 20:46:24 +03:00
if ( ! node )
return ERR_PTR ( - EINVAL ) ;
if ( id ) {
index = of_property_match_string ( node ,
" reset-names " , id ) ;
if ( index < 0 )
return ERR_PTR ( - ENOENT ) ;
}
2013-12-21 01:41:07 +04:00
ret = of_parse_phandle_with_args ( node , " resets " , " #reset-cells " ,
2012-11-19 20:23:13 +04:00
index , & args ) ;
if ( ret )
return ERR_PTR ( ret ) ;
2016-02-23 20:46:25 +03:00
mutex_lock ( & reset_list_mutex ) ;
2012-11-19 20:23:13 +04:00
rcdev = NULL ;
list_for_each_entry ( r , & reset_controller_list , list ) {
if ( args . np = = r - > of_node ) {
rcdev = r ;
break ;
}
}
of_node_put ( args . np ) ;
if ( ! rcdev ) {
2016-02-23 20:46:25 +03:00
mutex_unlock ( & reset_list_mutex ) ;
2013-07-18 15:55:22 +04:00
return ERR_PTR ( - EPROBE_DEFER ) ;
2012-11-19 20:23:13 +04:00
}
2016-01-14 18:24:44 +03:00
if ( WARN_ON ( args . args_count ! = rcdev - > of_reset_n_cells ) ) {
2016-02-23 20:46:25 +03:00
mutex_unlock ( & reset_list_mutex ) ;
2016-01-14 18:24:44 +03:00
return ERR_PTR ( - EINVAL ) ;
}
2012-11-19 20:23:13 +04:00
rstc_id = rcdev - > of_xlate ( rcdev , & args ) ;
if ( rstc_id < 0 ) {
2016-02-23 20:46:25 +03:00
mutex_unlock ( & reset_list_mutex ) ;
2012-11-19 20:23:13 +04:00
return ERR_PTR ( rstc_id ) ;
}
2016-02-23 20:46:25 +03:00
/* reset_list_mutex also protects the rcdev's reset_control list */
2016-02-23 20:46:26 +03:00
rstc = __reset_control_get ( rcdev , rstc_id , shared ) ;
2012-11-19 20:23:13 +04:00
2016-02-23 20:46:25 +03:00
mutex_unlock ( & reset_list_mutex ) ;
2012-11-19 20:23:13 +04:00
return rstc ;
}
2016-02-23 20:46:24 +03:00
EXPORT_SYMBOL_GPL ( __of_reset_control_get ) ;
2012-11-19 20:23:13 +04:00
/**
* reset_control_put - free the reset controller
* @ rstc : reset controller
*/
void reset_control_put ( struct reset_control * rstc )
{
if ( IS_ERR ( rstc ) )
return ;
2016-02-23 20:46:25 +03:00
mutex_lock ( & reset_list_mutex ) ;
__reset_control_put ( rstc ) ;
mutex_unlock ( & reset_list_mutex ) ;
2012-11-19 20:23:13 +04:00
}
EXPORT_SYMBOL_GPL ( reset_control_put ) ;
static void devm_reset_control_release ( struct device * dev , void * res )
{
reset_control_put ( * ( struct reset_control * * ) res ) ;
}
2016-02-23 20:46:24 +03:00
struct reset_control * __devm_reset_control_get ( struct device * dev ,
2016-02-23 20:46:26 +03:00
const char * id , int index , int shared )
2012-11-19 20:23:13 +04:00
{
struct reset_control * * ptr , * rstc ;
ptr = devres_alloc ( devm_reset_control_release , sizeof ( * ptr ) ,
GFP_KERNEL ) ;
if ( ! ptr )
return ERR_PTR ( - ENOMEM ) ;
2016-02-23 20:46:26 +03:00
rstc = __of_reset_control_get ( dev ? dev - > of_node : NULL ,
id , index , shared ) ;
2012-11-19 20:23:13 +04:00
if ( ! IS_ERR ( rstc ) ) {
* ptr = rstc ;
devres_add ( dev , ptr ) ;
} else {
devres_free ( ptr ) ;
}
return rstc ;
}
2016-02-23 20:46:24 +03:00
EXPORT_SYMBOL_GPL ( __devm_reset_control_get ) ;
2012-11-19 20:23:13 +04:00
/**
* device_reset - find reset controller associated with the device
* and perform reset
* @ dev : device to be reset by the controller
*
* Convenience wrapper for reset_control_get ( ) and reset_control_reset ( ) .
* This is useful for the common case of devices with single , dedicated reset
* lines .
*/
int device_reset ( struct device * dev )
{
struct reset_control * rstc ;
int ret ;
rstc = reset_control_get ( dev , NULL ) ;
if ( IS_ERR ( rstc ) )
return PTR_ERR ( rstc ) ;
ret = reset_control_reset ( rstc ) ;
reset_control_put ( rstc ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( device_reset ) ;