2020-02-04 14:04:18 +03:00
// SPDX-License-Identifier: GPL-2.0+
//
// mp5416.c - regulator driver for mps mp5416
//
// Copyright 2020 Monolithic Power Systems, Inc
//
// Author: Saravanan Sekar <sravanhome@gmail.com>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/err.h>
# include <linux/platform_device.h>
# include <linux/regmap.h>
# include <linux/regulator/driver.h>
# include <linux/i2c.h>
# define MP5416_REG_CTL0 0x00
# define MP5416_REG_CTL1 0x01
# define MP5416_REG_CTL2 0x02
# define MP5416_REG_ILIM 0x03
# define MP5416_REG_BUCK1 0x04
# define MP5416_REG_BUCK2 0x05
# define MP5416_REG_BUCK3 0x06
# define MP5416_REG_BUCK4 0x07
# define MP5416_REG_LDO1 0x08
# define MP5416_REG_LDO2 0x09
# define MP5416_REG_LDO3 0x0a
# define MP5416_REG_LDO4 0x0b
# define MP5416_REGULATOR_EN BIT(7)
# define MP5416_MASK_VSET 0x7f
# define MP5416_MASK_BUCK1_ILIM 0xc0
# define MP5416_MASK_BUCK2_ILIM 0x0c
# define MP5416_MASK_BUCK3_ILIM 0x30
# define MP5416_MASK_BUCK4_ILIM 0x03
# define MP5416_MASK_DVS_SLEWRATE 0xc0
/* values in uV */
# define MP5416_VOLT1_MIN 600000
# define MP5416_VOLT1_MAX 2187500
# define MP5416_VOLT1_STEP 12500
# define MP5416_VOLT2_MIN 800000
# define MP5416_VOLT2_MAX 3975000
# define MP5416_VOLT2_STEP 25000
# define MP5416_VOLT1_RANGE \
( ( MP5416_VOLT1_MAX - MP5416_VOLT1_MIN ) / MP5416_VOLT1_STEP + 1 )
# define MP5416_VOLT2_RANGE \
( ( MP5416_VOLT2_MAX - MP5416_VOLT2_MIN ) / MP5416_VOLT2_STEP + 1 )
# define MP5416BUCK(_name, _id, _ilim, _dreg, _dval, _vsel) \
[ MP5416_BUCK # # _id ] = { \
. id = MP5416_BUCK # # _id , \
. name = _name , \
. of_match = _name , \
. regulators_node = " regulators " , \
. ops = & mp5416_buck_ops , \
. min_uV = MP5416_VOLT # # _vsel # # _MIN , \
. uV_step = MP5416_VOLT # # _vsel # # _STEP , \
. n_voltages = MP5416_VOLT # # _vsel # # _RANGE , \
. curr_table = _ilim , \
. n_current_limits = ARRAY_SIZE ( _ilim ) , \
. csel_reg = MP5416_REG_ILIM , \
. csel_mask = MP5416_MASK_BUCK # # _id # # _ILIM , \
. vsel_reg = MP5416_REG_BUCK # # _id , \
. vsel_mask = MP5416_MASK_VSET , \
. enable_reg = MP5416_REG_BUCK # # _id , \
. enable_mask = MP5416_REGULATOR_EN , \
. active_discharge_on = _dval , \
. active_discharge_reg = _dreg , \
. active_discharge_mask = _dval , \
. owner = THIS_MODULE , \
}
2020-02-12 18:02:23 +03:00
# define MP5416LDO(_name, _id, _dval) \
2020-02-04 14:04:18 +03:00
[ MP5416_LDO # # _id ] = { \
. id = MP5416_LDO # # _id , \
. name = _name , \
. of_match = _name , \
. regulators_node = " regulators " , \
. ops = & mp5416_ldo_ops , \
. min_uV = MP5416_VOLT2_MIN , \
. uV_step = MP5416_VOLT2_STEP , \
. n_voltages = MP5416_VOLT2_RANGE , \
. vsel_reg = MP5416_REG_LDO # # _id , \
. vsel_mask = MP5416_MASK_VSET , \
. enable_reg = MP5416_REG_LDO # # _id , \
. enable_mask = MP5416_REGULATOR_EN , \
2020-02-12 18:02:23 +03:00
. active_discharge_on = _dval , \
2020-02-04 14:04:18 +03:00
. active_discharge_reg = MP5416_REG_CTL2 , \
2020-02-12 18:02:23 +03:00
. active_discharge_mask = _dval , \
2020-02-04 14:04:18 +03:00
. owner = THIS_MODULE , \
}
enum mp5416_regulators {
MP5416_BUCK1 ,
MP5416_BUCK2 ,
MP5416_BUCK3 ,
MP5416_BUCK4 ,
MP5416_LDO1 ,
MP5416_LDO2 ,
MP5416_LDO3 ,
MP5416_LDO4 ,
MP5416_MAX_REGULATORS ,
} ;
static const struct regmap_config mp5416_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = 0x0d ,
} ;
/* Current limits array (in uA)
* ILIM1 & ILIM3
*/
static const unsigned int mp5416_I_limits1 [ ] = {
3800000 , 4600000 , 5600000 , 6800000
} ;
/* ILIM2 & ILIM4 */
static const unsigned int mp5416_I_limits2 [ ] = {
2200000 , 3200000 , 4200000 , 5200000
} ;
static int mp5416_set_ramp_delay ( struct regulator_dev * rdev , int ramp_delay ) ;
static const struct regulator_ops mp5416_ldo_ops = {
. enable = regulator_enable_regmap ,
. disable = regulator_disable_regmap ,
. is_enabled = regulator_is_enabled_regmap ,
. list_voltage = regulator_list_voltage_linear ,
. map_voltage = regulator_map_voltage_linear ,
. get_voltage_sel = regulator_get_voltage_sel_regmap ,
. set_voltage_sel = regulator_set_voltage_sel_regmap ,
. set_active_discharge = regulator_set_active_discharge_regmap ,
} ;
static const struct regulator_ops mp5416_buck_ops = {
. enable = regulator_enable_regmap ,
. disable = regulator_disable_regmap ,
. is_enabled = regulator_is_enabled_regmap ,
. list_voltage = regulator_list_voltage_linear ,
. map_voltage = regulator_map_voltage_linear ,
. get_voltage_sel = regulator_get_voltage_sel_regmap ,
. set_voltage_sel = regulator_set_voltage_sel_regmap ,
. set_active_discharge = regulator_set_active_discharge_regmap ,
. get_current_limit = regulator_get_current_limit_regmap ,
. set_current_limit = regulator_set_current_limit_regmap ,
. set_ramp_delay = mp5416_set_ramp_delay ,
} ;
static struct regulator_desc mp5416_regulators_desc [ MP5416_MAX_REGULATORS ] = {
MP5416BUCK ( " buck1 " , 1 , mp5416_I_limits1 , MP5416_REG_CTL1 , BIT ( 0 ) , 1 ) ,
MP5416BUCK ( " buck2 " , 2 , mp5416_I_limits2 , MP5416_REG_CTL1 , BIT ( 1 ) , 2 ) ,
MP5416BUCK ( " buck3 " , 3 , mp5416_I_limits1 , MP5416_REG_CTL1 , BIT ( 2 ) , 1 ) ,
MP5416BUCK ( " buck4 " , 4 , mp5416_I_limits2 , MP5416_REG_CTL2 , BIT ( 5 ) , 2 ) ,
2020-02-12 18:02:23 +03:00
MP5416LDO ( " ldo1 " , 1 , BIT ( 4 ) ) ,
MP5416LDO ( " ldo2 " , 2 , BIT ( 3 ) ) ,
MP5416LDO ( " ldo3 " , 3 , BIT ( 2 ) ) ,
MP5416LDO ( " ldo4 " , 4 , BIT ( 1 ) ) ,
2020-02-04 14:04:18 +03:00
} ;
/*
* DVS ramp rate BUCK1 to BUCK4
* 00 : 32 mV / us
* 01 : 16 mV / us
* 10 : 8 mV / us
* 11 : 4 mV / us
*/
static int mp5416_set_ramp_delay ( struct regulator_dev * rdev , int ramp_delay )
{
unsigned int ramp_val ;
if ( ramp_delay > 32000 | | ramp_delay < 0 )
return - EINVAL ;
if ( ramp_delay < = 4000 )
ramp_val = 3 ;
else if ( ramp_delay < = 8000 )
ramp_val = 2 ;
else if ( ramp_delay < = 16000 )
ramp_val = 1 ;
else
ramp_val = 0 ;
return regmap_update_bits ( rdev - > regmap , MP5416_REG_CTL2 ,
MP5416_MASK_DVS_SLEWRATE , ramp_val < < 6 ) ;
}
static int mp5416_i2c_probe ( struct i2c_client * client )
{
struct device * dev = & client - > dev ;
struct regulator_config config = { NULL , } ;
struct regulator_dev * rdev ;
struct regmap * regmap ;
int i ;
regmap = devm_regmap_init_i2c ( client , & mp5416_regmap_config ) ;
if ( IS_ERR ( regmap ) ) {
dev_err ( dev , " Failed to allocate regmap! \n " ) ;
return PTR_ERR ( regmap ) ;
}
config . dev = dev ;
config . regmap = regmap ;
for ( i = 0 ; i < MP5416_MAX_REGULATORS ; i + + ) {
rdev = devm_regulator_register ( dev ,
& mp5416_regulators_desc [ i ] ,
& config ) ;
if ( IS_ERR ( rdev ) ) {
dev_err ( dev , " Failed to register regulator! \n " ) ;
return PTR_ERR ( rdev ) ;
}
}
return 0 ;
}
static const struct of_device_id mp5416_of_match [ ] = {
{ . compatible = " mps,mp5416 " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , mp5416_of_match ) ;
static const struct i2c_device_id mp5416_id [ ] = {
{ " mp5416 " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( i2c , mp5416_id ) ;
static struct i2c_driver mp5416_regulator_driver = {
. driver = {
. name = " mp5416 " ,
. of_match_table = of_match_ptr ( mp5416_of_match ) ,
} ,
. probe_new = mp5416_i2c_probe ,
. id_table = mp5416_id ,
} ;
module_i2c_driver ( mp5416_regulator_driver ) ;
MODULE_AUTHOR ( " Saravanan Sekar <sravanhome@gmail.com> " ) ;
MODULE_DESCRIPTION ( " MP5416 PMIC regulator driver " ) ;
MODULE_LICENSE ( " GPL " ) ;