2020-07-03 00:08:45 +03:00
// SPDX-License-Identifier: GPL-2.0+
# include <linux/module.h>
# include <linux/i2c.h>
# include <linux/regmap.h>
# include <linux/regulator/driver.h>
enum fan53880_regulator_ids {
FAN53880_LDO1 ,
FAN53880_LDO2 ,
FAN53880_LDO3 ,
FAN53880_LDO4 ,
FAN53880_BUCK ,
FAN53880_BOOST ,
} ;
enum fan53880_registers {
FAN53880_PRODUCT_ID = 0x00 ,
FAN53880_SILICON_REV ,
FAN53880_BUCKVOUT ,
FAN53880_BOOSTVOUT ,
FAN53880_LDO1VOUT ,
FAN53880_LDO2VOUT ,
FAN53880_LDO3VOUT ,
FAN53880_LDO4VOUT ,
FAN53880_IOUT ,
FAN53880_ENABLE ,
FAN53880_ENABLE_BOOST ,
} ;
# define FAN53880_ID 0x01
static const struct regulator_ops fan53880_ops = {
. list_voltage = regulator_list_voltage_linear_range ,
. map_voltage = regulator_map_voltage_linear_range ,
. set_voltage_sel = regulator_set_voltage_sel_regmap ,
. get_voltage_sel = regulator_get_voltage_sel_regmap ,
. enable = regulator_enable_regmap ,
. disable = regulator_disable_regmap ,
. is_enabled = regulator_is_enabled_regmap ,
} ;
# define FAN53880_LDO(_num, _supply, _default) \
[ FAN53880_LDO # # _num ] = { \
. name = " LDO " # _num , \
2022-11-24 16:47:08 +03:00
. of_match = " LDO " # _num , \
. regulators_node = " regulators " , \
2020-07-03 00:08:45 +03:00
. type = REGULATOR_VOLTAGE , \
2020-07-06 11:09:44 +03:00
. owner = THIS_MODULE , \
2020-07-03 00:08:45 +03:00
. linear_ranges = ( struct linear_range [ ] ) { \
REGULATOR_LINEAR_RANGE ( _default , 0x0 , 0x0 , 0 ) , \
REGULATOR_LINEAR_RANGE ( 800000 , 0xf , 0x73 , 25000 ) , \
} , \
. n_linear_ranges = 2 , \
2021-05-17 13:53:24 +03:00
. n_voltages = 0x74 , \
2020-07-03 00:08:45 +03:00
. vsel_reg = FAN53880_LDO # # _num # # VOUT , \
. vsel_mask = 0x7f , \
. enable_reg = FAN53880_ENABLE , \
. enable_mask = BIT ( _num - 1 ) , \
. enable_time = 150 , \
. supply_name = _supply , \
. ops = & fan53880_ops , \
}
static const struct regulator_desc fan53880_regulators [ ] = {
FAN53880_LDO ( 1 , " VIN12 " , 2800000 ) ,
FAN53880_LDO ( 2 , " VIN12 " , 2800000 ) ,
FAN53880_LDO ( 3 , " VIN3 " , 1800000 ) ,
FAN53880_LDO ( 4 , " VIN4 " , 1800000 ) ,
[ FAN53880_BUCK ] = {
. name = " BUCK " ,
2022-11-24 16:47:08 +03:00
. of_match = " BUCK " ,
. regulators_node = " regulators " ,
2020-07-03 00:08:45 +03:00
. type = REGULATOR_VOLTAGE ,
2020-07-06 11:09:44 +03:00
. owner = THIS_MODULE ,
2020-07-03 00:08:45 +03:00
. linear_ranges = ( struct linear_range [ ] ) {
REGULATOR_LINEAR_RANGE ( 1100000 , 0x0 , 0x0 , 0 ) ,
REGULATOR_LINEAR_RANGE ( 600000 , 0x1f , 0xf7 , 12500 ) ,
} ,
. n_linear_ranges = 2 ,
2021-05-17 13:53:24 +03:00
. n_voltages = 0xf8 ,
2020-07-03 00:08:45 +03:00
. vsel_reg = FAN53880_BUCKVOUT ,
2021-06-07 17:29:07 +03:00
. vsel_mask = 0xff ,
2020-07-03 00:08:45 +03:00
. enable_reg = FAN53880_ENABLE ,
. enable_mask = 0x10 ,
. enable_time = 480 ,
. supply_name = " PVIN " ,
. ops = & fan53880_ops ,
} ,
[ FAN53880_BOOST ] = {
. name = " BOOST " ,
2022-11-24 16:47:08 +03:00
. of_match = " BOOST " ,
. regulators_node = " regulators " ,
2020-07-03 00:08:45 +03:00
. type = REGULATOR_VOLTAGE ,
2020-07-06 11:09:44 +03:00
. owner = THIS_MODULE ,
2020-07-03 00:08:45 +03:00
. linear_ranges = ( struct linear_range [ ] ) {
REGULATOR_LINEAR_RANGE ( 5000000 , 0x0 , 0x0 , 0 ) ,
REGULATOR_LINEAR_RANGE ( 3000000 , 0x4 , 0x70 , 25000 ) ,
} ,
. n_linear_ranges = 2 ,
2021-05-17 13:53:24 +03:00
. n_voltages = 0x71 ,
2020-07-03 00:08:45 +03:00
. vsel_reg = FAN53880_BOOSTVOUT ,
. vsel_mask = 0x7f ,
. enable_reg = FAN53880_ENABLE_BOOST ,
. enable_mask = 0xff ,
. enable_time = 580 ,
. supply_name = " PVIN " ,
. ops = & fan53880_ops ,
} ,
} ;
static const struct regmap_config fan53880_regmap = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = FAN53880_ENABLE_BOOST ,
} ;
2021-05-17 13:53:25 +03:00
static int fan53880_i2c_probe ( struct i2c_client * i2c )
2020-07-03 00:08:45 +03:00
{
struct regulator_config config = { } ;
struct regulator_dev * rdev ;
struct regmap * regmap ;
int i , ret ;
unsigned int data ;
regmap = devm_regmap_init_i2c ( i2c , & fan53880_regmap ) ;
if ( IS_ERR ( regmap ) ) {
ret = PTR_ERR ( regmap ) ;
dev_err ( & i2c - > dev , " Failed to create regmap: %d \n " , ret ) ;
return ret ;
}
ret = regmap_read ( regmap , FAN53880_PRODUCT_ID , & data ) ;
if ( ret < 0 ) {
dev_err ( & i2c - > dev , " Failed to read PRODUCT_ID: %d \n " , ret ) ;
return ret ;
}
if ( data ! = FAN53880_ID ) {
dev_err ( & i2c - > dev , " Unsupported device id: 0x%x. \n " , data ) ;
return - ENODEV ;
}
config . dev = & i2c - > dev ;
config . init_data = NULL ;
for ( i = 0 ; i < ARRAY_SIZE ( fan53880_regulators ) ; i + + ) {
rdev = devm_regulator_register ( & i2c - > dev ,
& fan53880_regulators [ i ] ,
& config ) ;
if ( IS_ERR ( rdev ) ) {
ret = PTR_ERR ( rdev ) ;
dev_err ( & i2c - > dev , " Failed to register %s: %d \n " ,
fan53880_regulators [ i ] . name , ret ) ;
return ret ;
}
}
return 0 ;
}
static const struct of_device_id fan53880_dt_ids [ ] = {
{ . compatible = " onnn,fan53880 " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , fan53880_dt_ids ) ;
static const struct i2c_device_id fan53880_i2c_id [ ] = {
{ " fan53880 " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , fan53880_i2c_id ) ;
static struct i2c_driver fan53880_regulator_driver = {
. driver = {
. name = " fan53880 " ,
2023-03-16 22:54:41 +03:00
. probe_type = PROBE_PREFER_ASYNCHRONOUS ,
2022-11-24 16:47:08 +03:00
. of_match_table = fan53880_dt_ids ,
2020-07-03 00:08:45 +03:00
} ,
2021-05-17 13:53:25 +03:00
. probe_new = fan53880_i2c_probe ,
2020-07-03 00:08:45 +03:00
. id_table = fan53880_i2c_id ,
} ;
module_i2c_driver ( fan53880_regulator_driver ) ;
MODULE_DESCRIPTION ( " FAN53880 PMIC voltage regulator driver " ) ;
MODULE_AUTHOR ( " Christoph Fritz <chf.fritz@googlemail.com> " ) ;
MODULE_LICENSE ( " GPL " ) ;