2019-06-01 11:08:37 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-01-18 16:12:38 +03:00
/*
* Pistachio SoC Reset Controller driver
*
* Copyright ( C ) 2015 Imagination Technologies Ltd .
*
* Author : Damien Horsley < Damien . Horsley @ imgtec . com >
*/
2017-02-08 03:18:45 +03:00
# include <linux/init.h>
2016-01-18 16:12:38 +03:00
# include <linux/of.h>
# include <linux/platform_device.h>
# include <linux/regmap.h>
# include <linux/reset-controller.h>
# include <linux/slab.h>
# include <linux/mfd/syscon.h>
# include <dt-bindings/reset/pistachio-resets.h>
# define PISTACHIO_SOFT_RESET 0
struct pistachio_reset_data {
struct reset_controller_dev rcdev ;
struct regmap * periph_regs ;
} ;
static inline int pistachio_reset_shift ( unsigned long id )
{
switch ( id ) {
case PISTACHIO_RESET_I2C0 :
case PISTACHIO_RESET_I2C1 :
case PISTACHIO_RESET_I2C2 :
case PISTACHIO_RESET_I2C3 :
case PISTACHIO_RESET_I2S_IN :
case PISTACHIO_RESET_PRL_OUT :
case PISTACHIO_RESET_SPDIF_OUT :
case PISTACHIO_RESET_SPI :
case PISTACHIO_RESET_PWM_PDM :
case PISTACHIO_RESET_UART0 :
case PISTACHIO_RESET_UART1 :
case PISTACHIO_RESET_QSPI :
case PISTACHIO_RESET_MDC :
case PISTACHIO_RESET_SDHOST :
case PISTACHIO_RESET_ETHERNET :
case PISTACHIO_RESET_IR :
case PISTACHIO_RESET_HASH :
case PISTACHIO_RESET_TIMER :
return id ;
case PISTACHIO_RESET_I2S_OUT :
case PISTACHIO_RESET_SPDIF_IN :
case PISTACHIO_RESET_EVT :
return id + 6 ;
case PISTACHIO_RESET_USB_H :
case PISTACHIO_RESET_USB_PR :
case PISTACHIO_RESET_USB_PHY_PR :
case PISTACHIO_RESET_USB_PHY_PON :
return id + 7 ;
default :
return - EINVAL ;
}
}
static int pistachio_reset_assert ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
struct pistachio_reset_data * rd ;
u32 mask ;
int shift ;
rd = container_of ( rcdev , struct pistachio_reset_data , rcdev ) ;
shift = pistachio_reset_shift ( id ) ;
if ( shift < 0 )
return shift ;
mask = BIT ( shift ) ;
return regmap_update_bits ( rd - > periph_regs , PISTACHIO_SOFT_RESET ,
mask , mask ) ;
}
static int pistachio_reset_deassert ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
struct pistachio_reset_data * rd ;
u32 mask ;
int shift ;
rd = container_of ( rcdev , struct pistachio_reset_data , rcdev ) ;
shift = pistachio_reset_shift ( id ) ;
if ( shift < 0 )
return shift ;
mask = BIT ( shift ) ;
return regmap_update_bits ( rd - > periph_regs , PISTACHIO_SOFT_RESET ,
mask , 0 ) ;
}
2016-02-05 18:49:34 +03:00
static const struct reset_control_ops pistachio_reset_ops = {
2016-01-18 16:12:38 +03:00
. assert = pistachio_reset_assert ,
. deassert = pistachio_reset_deassert ,
} ;
static int pistachio_reset_probe ( struct platform_device * pdev )
{
struct pistachio_reset_data * rd ;
struct device * dev = & pdev - > dev ;
struct device_node * np = pdev - > dev . of_node ;
rd = devm_kzalloc ( dev , sizeof ( * rd ) , GFP_KERNEL ) ;
if ( ! rd )
return - ENOMEM ;
rd - > periph_regs = syscon_node_to_regmap ( np - > parent ) ;
if ( IS_ERR ( rd - > periph_regs ) )
return PTR_ERR ( rd - > periph_regs ) ;
rd - > rcdev . owner = THIS_MODULE ;
rd - > rcdev . nr_resets = PISTACHIO_RESET_MAX + 1 ;
rd - > rcdev . ops = & pistachio_reset_ops ;
rd - > rcdev . of_node = np ;
2016-05-01 13:37:00 +03:00
return devm_reset_controller_register ( dev , & rd - > rcdev ) ;
2016-01-18 16:12:38 +03:00
}
static const struct of_device_id pistachio_reset_dt_ids [ ] = {
{ . compatible = " img,pistachio-reset " , } ,
{ /* sentinel */ } ,
} ;
static struct platform_driver pistachio_reset_driver = {
. probe = pistachio_reset_probe ,
. driver = {
. name = " pistachio-reset " ,
. of_match_table = pistachio_reset_dt_ids ,
} ,
} ;
2017-02-08 03:18:45 +03:00
builtin_platform_driver ( pistachio_reset_driver ) ;