2019-05-27 09:55:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2015-04-23 11:35:40 +03:00
/*
* Copyright ( c ) 2014 MediaTek Inc .
*/
# include <linux/mfd/syscon.h>
# include <linux/module.h>
# include <linux/of.h>
# include <linux/platform_device.h>
# include <linux/regmap.h>
# include <linux/slab.h>
2022-05-23 12:33:28 +03:00
# include "reset.h"
2015-04-23 11:35:40 +03:00
2019-07-26 10:01:35 +03:00
static int mtk_reset_assert_set_clr ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
struct mtk_reset * data = container_of ( rcdev , struct mtk_reset , rcdev ) ;
unsigned int reg = data - > regofs + ( ( id / 32 ) < < 4 ) ;
2022-05-23 12:33:29 +03:00
return regmap_write ( data - > regmap , reg , BIT ( id % 32 ) ) ;
2019-07-26 10:01:35 +03:00
}
static int mtk_reset_deassert_set_clr ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
struct mtk_reset * data = container_of ( rcdev , struct mtk_reset , rcdev ) ;
unsigned int reg = data - > regofs + ( ( id / 32 ) < < 4 ) + 0x4 ;
2022-05-23 12:33:29 +03:00
return regmap_write ( data - > regmap , reg , BIT ( id % 32 ) ) ;
2019-07-26 10:01:35 +03:00
}
2015-04-23 11:35:40 +03:00
static int mtk_reset_assert ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
struct mtk_reset * data = container_of ( rcdev , struct mtk_reset , rcdev ) ;
return regmap_update_bits ( data - > regmap , data - > regofs + ( ( id / 32 ) < < 2 ) ,
BIT ( id % 32 ) , ~ 0 ) ;
}
static int mtk_reset_deassert ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
struct mtk_reset * data = container_of ( rcdev , struct mtk_reset , rcdev ) ;
return regmap_update_bits ( data - > regmap , data - > regofs + ( ( id / 32 ) < < 2 ) ,
BIT ( id % 32 ) , 0 ) ;
}
static int mtk_reset ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
int ret ;
ret = mtk_reset_assert ( rcdev , id ) ;
if ( ret )
return ret ;
return mtk_reset_deassert ( rcdev , id ) ;
}
2019-07-26 10:01:35 +03:00
static int mtk_reset_set_clr ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
int ret ;
ret = mtk_reset_assert_set_clr ( rcdev , id ) ;
if ( ret )
return ret ;
return mtk_reset_deassert_set_clr ( rcdev , id ) ;
}
2016-02-25 12:45:06 +03:00
static const struct reset_control_ops mtk_reset_ops = {
2015-04-23 11:35:40 +03:00
. assert = mtk_reset_assert ,
. deassert = mtk_reset_deassert ,
. reset = mtk_reset ,
} ;
2019-07-26 10:01:35 +03:00
static const struct reset_control_ops mtk_reset_ops_set_clr = {
. assert = mtk_reset_assert_set_clr ,
. deassert = mtk_reset_deassert_set_clr ,
. reset = mtk_reset_set_clr ,
} ;
static void mtk_register_reset_controller_common ( struct device_node * np ,
unsigned int num_regs , int regofs ,
const struct reset_control_ops * reset_ops )
2015-04-23 11:35:40 +03:00
{
struct mtk_reset * data ;
int ret ;
struct regmap * regmap ;
2021-07-26 13:57:03 +03:00
regmap = device_node_to_regmap ( np ) ;
2015-04-23 11:35:40 +03:00
if ( IS_ERR ( regmap ) ) {
2022-02-08 15:40:04 +03:00
pr_err ( " Cannot find regmap for %pOF: %pe \n " , np , regmap ) ;
2015-04-23 11:35:40 +03:00
return ;
}
data = kzalloc ( sizeof ( * data ) , GFP_KERNEL ) ;
if ( ! data )
return ;
data - > regmap = regmap ;
data - > regofs = regofs ;
data - > rcdev . owner = THIS_MODULE ;
data - > rcdev . nr_resets = num_regs * 32 ;
2019-07-26 10:01:35 +03:00
data - > rcdev . ops = reset_ops ;
2015-04-23 11:35:40 +03:00
data - > rcdev . of_node = np ;
ret = reset_controller_register ( & data - > rcdev ) ;
if ( ret ) {
pr_err ( " could not register reset controller: %d \n " , ret ) ;
kfree ( data ) ;
return ;
}
}
2019-07-26 10:01:35 +03:00
void mtk_register_reset_controller ( struct device_node * np ,
unsigned int num_regs , int regofs )
{
mtk_register_reset_controller_common ( np , num_regs , regofs ,
& mtk_reset_ops ) ;
}
void mtk_register_reset_controller_set_clr ( struct device_node * np ,
unsigned int num_regs , int regofs )
{
mtk_register_reset_controller_common ( np , num_regs , regofs ,
& mtk_reset_ops_set_clr ) ;
}
2021-09-02 01:25:25 +03:00
MODULE_LICENSE ( " GPL " ) ;