2023-01-24 21:44:39 +03:00
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright ( c ) 2021 , The Linux Foundation . All rights reserved .
* Copyright ( c ) 2022 , Linaro Ltd .
*/
2023-01-27 01:51:39 +03:00
# include <linux/bitfield.h>
2023-01-24 21:44:39 +03:00
# include <linux/gpio/consumer.h>
# include <linux/i2c.h>
# include <linux/module.h>
# include <linux/of_platform.h>
# include <linux/regmap.h>
# include <linux/regulator/driver.h>
# include <linux/regulator/machine.h>
# include <linux/regulator/of_regulator.h>
# define MAX20411_UV_STEP 6250
# define MAX20411_BASE_UV 243750
# define MAX20411_MIN_SEL 41 /* 0.5V */
# define MAX20411_MAX_SEL 165 /* 1.275V */
# define MAX20411_VID_OFFSET 0x7
# define MAX20411_VID_MASK 0xff
# define MAX20411_SLEW_OFFSET 0x6
# define MAX20411_SLEW_DVS_MASK 0xc
# define MAX20411_SLEW_SR_MASK 0x3
struct max20411 {
struct device * dev ;
struct device_node * of_node ;
struct regulator_desc desc ;
struct regulator_dev * rdev ;
struct regmap * regmap ;
} ;
static const unsigned int max20411_slew_rates [ ] = { 13100 , 6600 , 3300 , 1600 } ;
static int max20411_enable_time ( struct regulator_dev * rdev )
{
int voltage , rate , ret ;
unsigned int val ;
/* get voltage */
ret = regmap_read ( rdev - > regmap , rdev - > desc - > vsel_reg , & val ) ;
if ( ret )
return ret ;
val & = rdev - > desc - > vsel_mask ;
voltage = regulator_list_voltage_linear ( rdev , val ) ;
/* get rate */
ret = regmap_read ( rdev - > regmap , MAX20411_SLEW_OFFSET , & val ) ;
if ( ret )
return ret ;
val = FIELD_GET ( MAX20411_SLEW_SR_MASK , val ) ;
rate = max20411_slew_rates [ val ] ;
return DIV_ROUND_UP ( voltage , rate ) ;
}
static const struct regmap_config max20411_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = 0xe ,
} ;
static const struct regulator_ops max20411_ops = {
. get_voltage_sel = regulator_get_voltage_sel_regmap ,
. set_voltage_sel = regulator_set_voltage_sel_regmap ,
. list_voltage = regulator_list_voltage_linear ,
. enable_time = max20411_enable_time ,
} ;
static const struct regulator_desc max20411_desc = {
. ops = & max20411_ops ,
. owner = THIS_MODULE ,
. type = REGULATOR_VOLTAGE ,
. supply_name = " vin " ,
. name = " max20411 " ,
/*
* voltage = 0.24375 V + selector * 6.25 mV
* with valid selector between 41 to 165 ( 0.5 V to 1.275 V )
*/
. min_uV = MAX20411_BASE_UV ,
. uV_step = MAX20411_UV_STEP ,
. linear_min_sel = MAX20411_MIN_SEL ,
2023-02-11 18:00:19 +03:00
. n_voltages = MAX20411_MAX_SEL + 1 ,
2023-01-24 21:44:39 +03:00
. vsel_reg = MAX20411_VID_OFFSET ,
. vsel_mask = MAX20411_VID_MASK ,
. ramp_reg = MAX20411_SLEW_OFFSET ,
. ramp_mask = MAX20411_SLEW_DVS_MASK ,
. ramp_delay_table = max20411_slew_rates ,
. n_ramp_values = ARRAY_SIZE ( max20411_slew_rates ) ,
} ;
2023-01-27 13:17:26 +03:00
static int max20411_probe ( struct i2c_client * client )
2023-01-24 21:44:39 +03:00
{
struct regulator_init_data * init_data ;
struct device * dev = & client - > dev ;
struct regulator_config cfg = { } ;
struct max20411 * max20411 ;
max20411 = devm_kzalloc ( dev , sizeof ( * max20411 ) , GFP_KERNEL ) ;
if ( ! max20411 )
return - ENOMEM ;
max20411 - > regmap = devm_regmap_init_i2c ( client , & max20411_regmap_config ) ;
if ( IS_ERR ( max20411 - > regmap ) ) {
dev_err ( dev , " Failed to allocate regmap! \n " ) ;
return PTR_ERR ( max20411 - > regmap ) ;
}
max20411 - > dev = dev ;
max20411 - > of_node = dev - > of_node ;
max20411 - > desc = max20411_desc ;
init_data = of_get_regulator_init_data ( max20411 - > dev , max20411 - > of_node , & max20411 - > desc ) ;
if ( ! init_data )
return - ENODATA ;
cfg . dev = max20411 - > dev ;
cfg . init_data = init_data ;
cfg . of_node = max20411 - > of_node ;
cfg . driver_data = max20411 ;
cfg . ena_gpiod = gpiod_get ( max20411 - > dev , " enable " , GPIOD_ASIS ) ;
if ( IS_ERR ( cfg . ena_gpiod ) )
return dev_err_probe ( dev , PTR_ERR ( cfg . ena_gpiod ) ,
" unable to acquire enable gpio \n " ) ;
max20411 - > rdev = devm_regulator_register ( max20411 - > dev , & max20411 - > desc , & cfg ) ;
if ( IS_ERR ( max20411 - > rdev ) )
dev_err ( max20411 - > dev , " Failed to register regulator \n " ) ;
return PTR_ERR_OR_ZERO ( max20411 - > rdev ) ;
}
static const struct of_device_id of_max20411_match_tbl [ ] = {
{ . compatible = " maxim,max20411 " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , of_max20411_match_tbl ) ;
static const struct i2c_device_id max20411_id [ ] = {
{ " max20411 " , 0 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( i2c , max20411_id ) ;
static struct i2c_driver max20411_i2c_driver = {
. driver = {
. name = " max20411 " ,
2023-03-16 22:54:44 +03:00
. probe_type = PROBE_PREFER_ASYNCHRONOUS ,
2023-01-24 21:44:39 +03:00
. of_match_table = of_max20411_match_tbl ,
} ,
2023-05-06 01:02:18 +03:00
. probe = max20411_probe ,
2023-01-24 21:44:39 +03:00
. id_table = max20411_id ,
} ;
module_i2c_driver ( max20411_i2c_driver ) ;
MODULE_LICENSE ( " GPL " ) ;