2010-06-13 19:25:51 +04:00
/*
* isl6271a - regulator . c
*
* Support for Intersil ISL6271A voltage regulator
*
* Copyright ( C ) 2010 Marek Vasut < marek . vasut @ gmail . com >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed " as is " WITHOUT ANY WARRANTY of any kind ,
* whether express or implied ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/err.h>
# include <linux/platform_device.h>
# include <linux/regulator/driver.h>
# include <linux/i2c.h>
# include <linux/slab.h>
# define ISL6271A_VOLTAGE_MIN 850000
# define ISL6271A_VOLTAGE_MAX 1600000
# define ISL6271A_VOLTAGE_STEP 50000
/* PMIC details */
struct isl_pmic {
struct i2c_client * client ;
struct mutex mtx ;
} ;
2012-05-16 06:10:22 +04:00
static int isl6271a_get_voltage_sel ( struct regulator_dev * dev )
2010-06-13 19:25:51 +04:00
{
struct isl_pmic * pmic = rdev_get_drvdata ( dev ) ;
2012-05-16 06:10:22 +04:00
int idx ;
2010-06-13 19:25:51 +04:00
mutex_lock ( & pmic - > mtx ) ;
idx = i2c_smbus_read_byte ( pmic - > client ) ;
2012-05-16 06:10:22 +04:00
if ( idx < 0 )
2010-06-13 19:25:51 +04:00
dev_err ( & pmic - > client - > dev , " Error getting voltage \n " ) ;
mutex_unlock ( & pmic - > mtx ) ;
2012-05-16 06:10:22 +04:00
return idx ;
2010-06-13 19:25:51 +04:00
}
2012-05-16 06:11:13 +04:00
static int isl6271a_set_voltage_sel ( struct regulator_dev * dev ,
unsigned selector )
2010-06-13 19:25:51 +04:00
{
struct isl_pmic * pmic = rdev_get_drvdata ( dev ) ;
2012-05-16 06:11:13 +04:00
int err ;
2010-11-10 17:38:29 +03:00
2010-06-13 19:25:51 +04:00
mutex_lock ( & pmic - > mtx ) ;
2012-05-16 06:11:13 +04:00
err = i2c_smbus_write_byte ( pmic - > client , selector ) ;
2010-06-13 19:25:51 +04:00
if ( err < 0 )
dev_err ( & pmic - > client - > dev , " Error setting voltage \n " ) ;
mutex_unlock ( & pmic - > mtx ) ;
return err ;
}
2019-01-28 17:19:21 +03:00
static const struct regulator_ops isl_core_ops = {
2012-05-16 06:10:22 +04:00
. get_voltage_sel = isl6271a_get_voltage_sel ,
2012-05-16 06:11:13 +04:00
. set_voltage_sel = isl6271a_set_voltage_sel ,
2012-05-16 06:09:27 +04:00
. list_voltage = regulator_list_voltage_linear ,
2012-05-16 06:11:13 +04:00
. map_voltage = regulator_map_voltage_linear ,
2010-06-13 19:25:51 +04:00
} ;
2019-01-28 17:19:21 +03:00
static const struct regulator_ops isl_fixed_ops = {
2012-06-07 06:06:40 +04:00
. list_voltage = regulator_list_voltage_linear ,
2010-06-13 19:25:51 +04:00
} ;
2012-04-05 07:58:06 +04:00
static const struct regulator_desc isl_rd [ ] = {
2010-06-13 19:25:51 +04:00
{
. name = " Core Buck " ,
. id = 0 ,
. n_voltages = 16 ,
. ops = & isl_core_ops ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
2012-05-16 06:09:27 +04:00
. min_uV = ISL6271A_VOLTAGE_MIN ,
. uV_step = ISL6271A_VOLTAGE_STEP ,
2010-06-13 19:25:51 +04:00
} , {
. name = " LDO1 " ,
. id = 1 ,
. n_voltages = 1 ,
. ops = & isl_fixed_ops ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
2012-06-07 06:06:40 +04:00
. min_uV = 1100000 ,
2010-06-13 19:25:51 +04:00
} , {
. name = " LDO2 " ,
. id = 2 ,
. n_voltages = 1 ,
. ops = & isl_fixed_ops ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
2012-06-07 06:06:40 +04:00
. min_uV = 1300000 ,
2010-06-13 19:25:51 +04:00
} ,
} ;
2012-11-19 22:22:22 +04:00
static int isl6271a_probe ( struct i2c_client * i2c ,
2010-06-13 19:25:51 +04:00
const struct i2c_device_id * id )
{
2019-01-28 17:19:20 +03:00
struct regulator_dev * rdev ;
2012-04-04 03:50:22 +04:00
struct regulator_config config = { } ;
2013-07-30 12:20:47 +04:00
struct regulator_init_data * init_data = dev_get_platdata ( & i2c - > dev ) ;
2010-06-13 19:25:51 +04:00
struct isl_pmic * pmic ;
2013-09-04 10:30:58 +04:00
int i ;
2010-06-13 19:25:51 +04:00
if ( ! i2c_check_functionality ( i2c - > adapter , I2C_FUNC_SMBUS_BYTE_DATA ) )
return - EIO ;
2012-04-11 19:05:49 +04:00
pmic = devm_kzalloc ( & i2c - > dev , sizeof ( struct isl_pmic ) , GFP_KERNEL ) ;
2010-06-13 19:25:51 +04:00
if ( ! pmic )
return - ENOMEM ;
pmic - > client = i2c ;
mutex_init ( & pmic - > mtx ) ;
for ( i = 0 ; i < 3 ; i + + ) {
2012-04-04 03:50:22 +04:00
config . dev = & i2c - > dev ;
if ( i = = 0 )
config . init_data = init_data ;
else
2013-05-08 14:39:05 +04:00
config . init_data = NULL ;
2012-04-04 03:50:22 +04:00
config . driver_data = pmic ;
2019-01-28 17:19:20 +03:00
rdev = devm_regulator_register ( & i2c - > dev , & isl_rd [ i ] , & config ) ;
if ( IS_ERR ( rdev ) ) {
2010-06-13 19:25:51 +04:00
dev_err ( & i2c - > dev , " failed to register %s \n " , id - > name ) ;
2019-01-28 17:19:20 +03:00
return PTR_ERR ( rdev ) ;
2010-06-13 19:25:51 +04:00
}
}
i2c_set_clientdata ( i2c , pmic ) ;
return 0 ;
}
static const struct i2c_device_id isl6271a_id [ ] = {
{ . name = " isl6271a " , 0 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( i2c , isl6271a_id ) ;
static struct i2c_driver isl6271a_i2c_driver = {
. driver = {
. name = " isl6271a " ,
} ,
. probe = isl6271a_probe ,
. id_table = isl6271a_id ,
} ;
static int __init isl6271a_init ( void )
{
return i2c_add_driver ( & isl6271a_i2c_driver ) ;
}
static void __exit isl6271a_cleanup ( void )
{
i2c_del_driver ( & isl6271a_i2c_driver ) ;
}
subsys_initcall ( isl6271a_init ) ;
module_exit ( isl6271a_cleanup ) ;
MODULE_AUTHOR ( " Marek Vasut <marek.vasut@gmail.com> " ) ;
MODULE_DESCRIPTION ( " Intersil ISL6271A voltage regulator driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;