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
2022-05-23 12:33:33 +03:00
static inline struct mtk_clk_rst_data * to_mtk_clk_rst_data ( struct reset_controller_dev * rcdev )
{
return container_of ( rcdev , struct mtk_clk_rst_data , rcdev ) ;
}
2022-05-23 12:33:31 +03:00
static int mtk_reset_update ( struct reset_controller_dev * rcdev ,
unsigned long id , bool deassert )
2019-07-26 10:01:35 +03:00
{
2022-05-23 12:33:33 +03:00
struct mtk_clk_rst_data * data = to_mtk_clk_rst_data ( rcdev ) ;
2022-05-23 12:33:31 +03:00
unsigned int val = deassert ? 0 : ~ 0 ;
2019-07-26 10:01:35 +03:00
2022-05-23 12:33:30 +03:00
return regmap_update_bits ( data - > regmap ,
2022-05-23 12:33:33 +03:00
data - > desc - > reg_ofs + ( ( id / 32 ) < < 2 ) ,
2022-05-23 12:33:31 +03:00
BIT ( id % 32 ) , val ) ;
}
static int mtk_reset_assert ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
return mtk_reset_update ( rcdev , id , false ) ;
2019-07-26 10:01:35 +03:00
}
2022-05-23 12:33:30 +03:00
static int mtk_reset_deassert ( struct reset_controller_dev * rcdev ,
unsigned long id )
2019-07-26 10:01:35 +03:00
{
2022-05-23 12:33:31 +03:00
return mtk_reset_update ( rcdev , id , true ) ;
2019-07-26 10:01:35 +03:00
}
2022-05-23 12:33:30 +03:00
static int mtk_reset ( struct reset_controller_dev * rcdev , unsigned long id )
2015-04-23 11:35:40 +03:00
{
2022-05-23 12:33:30 +03:00
int ret ;
ret = mtk_reset_assert ( rcdev , id ) ;
if ( ret )
return ret ;
2015-04-23 11:35:40 +03:00
2022-05-23 12:33:30 +03:00
return mtk_reset_deassert ( rcdev , id ) ;
2015-04-23 11:35:40 +03:00
}
2022-05-23 12:33:31 +03:00
static int mtk_reset_update_set_clr ( struct reset_controller_dev * rcdev ,
unsigned long id , bool deassert )
2015-04-23 11:35:40 +03:00
{
2022-05-23 12:33:33 +03:00
struct mtk_clk_rst_data * data = to_mtk_clk_rst_data ( rcdev ) ;
2022-05-23 12:33:31 +03:00
unsigned int deassert_ofs = deassert ? 0x4 : 0 ;
2015-04-23 11:35:40 +03:00
2022-05-23 12:33:30 +03:00
return regmap_write ( data - > regmap ,
2022-05-23 12:33:33 +03:00
data - > desc - > reg_ofs + ( ( id / 32 ) < < 4 ) + deassert_ofs ,
2022-05-23 12:33:30 +03:00
BIT ( id % 32 ) ) ;
2015-04-23 11:35:40 +03:00
}
2022-05-23 12:33:31 +03:00
static int mtk_reset_assert_set_clr ( struct reset_controller_dev * rcdev ,
unsigned long id )
{
return mtk_reset_update_set_clr ( rcdev , id , false ) ;
}
2022-05-23 12:33:30 +03:00
static int mtk_reset_deassert_set_clr ( struct reset_controller_dev * rcdev ,
unsigned long id )
2015-04-23 11:35:40 +03:00
{
2022-05-23 12:33:31 +03:00
return mtk_reset_update_set_clr ( rcdev , id , true ) ;
2015-04-23 11:35:40 +03:00
}
2019-07-26 10:01:35 +03:00
static int mtk_reset_set_clr ( struct reset_controller_dev * rcdev ,
2022-05-23 12:33:30 +03:00
unsigned long id )
2019-07-26 10:01:35 +03:00
{
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 ,
} ;
2022-05-23 12:33:32 +03:00
void mtk_register_reset_controller ( struct device_node * np ,
2022-05-23 12:33:33 +03:00
const struct mtk_clk_rst_desc * desc )
2015-04-23 11:35:40 +03:00
{
struct regmap * regmap ;
2022-05-23 12:33:32 +03:00
const struct reset_control_ops * rcops = NULL ;
2022-05-23 12:33:33 +03:00
struct mtk_clk_rst_data * data ;
int ret ;
if ( ! desc ) {
pr_err ( " mtk clock reset desc is NULL \n " ) ;
return ;
}
2022-05-23 12:33:32 +03:00
2022-05-23 12:33:33 +03:00
switch ( desc - > version ) {
2022-05-23 12:33:32 +03:00
case MTK_RST_SIMPLE :
rcops = & mtk_reset_ops ;
break ;
case MTK_RST_SET_CLR :
rcops = & mtk_reset_ops_set_clr ;
break ;
default :
2022-05-23 12:33:33 +03:00
pr_err ( " Unknown reset version %d \n " , desc - > version ) ;
2022-05-23 12:33:32 +03:00
return ;
}
2015-04-23 11:35:40 +03:00
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 ;
2022-05-23 12:33:33 +03:00
data - > desc = desc ;
2015-04-23 11:35:40 +03:00
data - > regmap = regmap ;
data - > rcdev . owner = THIS_MODULE ;
2022-05-23 12:33:33 +03:00
data - > rcdev . nr_resets = desc - > rst_bank_nr * 32 ;
2022-05-23 12:33:32 +03:00
data - > rcdev . ops = rcops ;
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 ) ;
}
}
2019-07-26 10:01:35 +03:00
2021-09-02 01:25:25 +03:00
MODULE_LICENSE ( " GPL " ) ;