2010-09-16 12:48:49 +04:00
/*
* Regulator driver for National Semiconductors LP3972 PMIC chip
*
* Based on lp3971 . c
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
*/
# include <linux/bug.h>
# include <linux/err.h>
# include <linux/i2c.h>
2011-07-18 00:28:23 +04:00
# include <linux/module.h>
2010-09-16 12:48:49 +04:00
# include <linux/kernel.h>
# include <linux/regulator/driver.h>
# include <linux/regulator/lp3972.h>
# include <linux/slab.h>
struct lp3972 {
struct device * dev ;
struct mutex io_lock ;
struct i2c_client * i2c ;
int num_regulators ;
struct regulator_dev * * rdev ;
} ;
/* LP3972 Control Registers */
# define LP3972_SCR_REG 0x07
# define LP3972_OVER1_REG 0x10
# define LP3972_OVSR1_REG 0x11
# define LP3972_OVER2_REG 0x12
# define LP3972_OVSR2_REG 0x13
# define LP3972_VCC1_REG 0x20
# define LP3972_ADTV1_REG 0x23
# define LP3972_ADTV2_REG 0x24
# define LP3972_AVRC_REG 0x25
# define LP3972_CDTC1_REG 0x26
# define LP3972_CDTC2_REG 0x27
# define LP3972_SDTV1_REG 0x29
# define LP3972_SDTV2_REG 0x2A
# define LP3972_MDTV1_REG 0x32
# define LP3972_MDTV2_REG 0x33
# define LP3972_L2VCR_REG 0x39
# define LP3972_L34VCR_REG 0x3A
# define LP3972_SCR1_REG 0x80
# define LP3972_SCR2_REG 0x81
# define LP3972_OEN3_REG 0x82
# define LP3972_OSR3_REG 0x83
# define LP3972_LOER4_REG 0x84
# define LP3972_B2TV_REG 0x85
# define LP3972_B3TV_REG 0x86
# define LP3972_B32RC_REG 0x87
# define LP3972_ISRA_REG 0x88
# define LP3972_BCCR_REG 0x89
# define LP3972_II1RR_REG 0x8E
# define LP3972_II2RR_REG 0x8F
# define LP3972_SYS_CONTROL1_REG LP3972_SCR1_REG
/* System control register 1 initial value,
* bits 5 , 6 and 7 are EPROM programmable */
# define SYS_CONTROL1_INIT_VAL 0x02
# define SYS_CONTROL1_INIT_MASK 0x1F
# define LP3972_VOL_CHANGE_REG LP3972_VCC1_REG
# define LP3972_VOL_CHANGE_FLAG_GO 0x01
# define LP3972_VOL_CHANGE_FLAG_MASK 0x03
/* LDO output enable mask */
# define LP3972_OEN3_L1EN BIT(0)
# define LP3972_OVER2_LDO2_EN BIT(2)
# define LP3972_OVER2_LDO3_EN BIT(3)
# define LP3972_OVER2_LDO4_EN BIT(4)
# define LP3972_OVER1_S_EN BIT(2)
static const int ldo1_voltage_map [ ] = {
1700 , 1725 , 1750 , 1775 , 1800 , 1825 , 1850 , 1875 ,
1900 , 1925 , 1950 , 1975 , 2000 ,
} ;
static const int ldo23_voltage_map [ ] = {
1800 , 1900 , 2000 , 2100 , 2200 , 2300 , 2400 , 2500 ,
2600 , 2700 , 2800 , 2900 , 3000 , 3100 , 3200 , 3300 ,
} ;
static const int ldo4_voltage_map [ ] = {
1000 , 1050 , 1100 , 1150 , 1200 , 1250 , 1300 , 1350 ,
1400 , 1500 , 1800 , 1900 , 2500 , 2800 , 3000 , 3300 ,
} ;
static const int ldo5_voltage_map [ ] = {
0 , 0 , 0 , 0 , 0 , 850 , 875 , 900 ,
925 , 950 , 975 , 1000 , 1025 , 1050 , 1075 , 1100 ,
1125 , 1150 , 1175 , 1200 , 1225 , 1250 , 1275 , 1300 ,
1325 , 1350 , 1375 , 1400 , 1425 , 1450 , 1475 , 1500 ,
} ;
static const int buck1_voltage_map [ ] = {
725 , 750 , 775 , 800 , 825 , 850 , 875 , 900 ,
925 , 950 , 975 , 1000 , 1025 , 1050 , 1075 , 1100 ,
1125 , 1150 , 1175 , 1200 , 1225 , 1250 , 1275 , 1300 ,
1325 , 1350 , 1375 , 1400 , 1425 , 1450 , 1475 , 1500 ,
} ;
static const int buck23_voltage_map [ ] = {
0 , 800 , 850 , 900 , 950 , 1000 , 1050 , 1100 ,
1150 , 1200 , 1250 , 1300 , 1350 , 1400 , 1450 , 1500 ,
1550 , 1600 , 1650 , 1700 , 1800 , 1900 , 2500 , 2800 ,
3000 , 3300 ,
} ;
static const int * ldo_voltage_map [ ] = {
ldo1_voltage_map ,
ldo23_voltage_map ,
ldo23_voltage_map ,
ldo4_voltage_map ,
ldo5_voltage_map ,
} ;
static const int * buck_voltage_map [ ] = {
buck1_voltage_map ,
buck23_voltage_map ,
buck23_voltage_map ,
} ;
static const int ldo_output_enable_mask [ ] = {
LP3972_OEN3_L1EN ,
LP3972_OVER2_LDO2_EN ,
LP3972_OVER2_LDO3_EN ,
LP3972_OVER2_LDO4_EN ,
LP3972_OVER1_S_EN ,
} ;
static const int ldo_output_enable_addr [ ] = {
LP3972_OEN3_REG ,
LP3972_OVER2_REG ,
LP3972_OVER2_REG ,
LP3972_OVER2_REG ,
LP3972_OVER1_REG ,
} ;
static const int ldo_vol_ctl_addr [ ] = {
LP3972_MDTV1_REG ,
LP3972_L2VCR_REG ,
LP3972_L34VCR_REG ,
LP3972_L34VCR_REG ,
LP3972_SDTV1_REG ,
} ;
static const int buck_vol_enable_addr [ ] = {
LP3972_OVER1_REG ,
LP3972_OEN3_REG ,
LP3972_OEN3_REG ,
} ;
static const int buck_base_addr [ ] = {
LP3972_ADTV1_REG ,
LP3972_B2TV_REG ,
LP3972_B3TV_REG ,
} ;
# define LP3972_LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[x])
# define LP3972_LDO_OUTPUT_ENABLE_MASK(x) (ldo_output_enable_mask[x])
# define LP3972_LDO_OUTPUT_ENABLE_REG(x) (ldo_output_enable_addr[x])
/* LDO voltage control registers shift:
LP3972_LDO1 - > 0 , LP3972_LDO2 - > 4
LP3972_LDO3 - > 0 , LP3972_LDO4 - > 4
LP3972_LDO5 - > 0
*/
# define LP3972_LDO_VOL_CONTR_SHIFT(x) (((x) & 1) << 2)
# define LP3972_LDO_VOL_CONTR_REG(x) (ldo_vol_ctl_addr[x])
# define LP3972_LDO_VOL_CHANGE_SHIFT(x) ((x) ? 4 : 6)
# define LP3972_LDO_VOL_MASK(x) (((x) % 4) ? 0x0f : 0x1f)
# define LP3972_LDO_VOL_MIN_IDX(x) (((x) == 4) ? 0x05 : 0x00)
# define LP3972_LDO_VOL_MAX_IDX(x) ((x) ? (((x) == 4) ? 0x1f : 0x0f) : 0x0c)
# define LP3972_BUCK_VOL_VALUE_MAP(x) (buck_voltage_map[x])
# define LP3972_BUCK_VOL_ENABLE_REG(x) (buck_vol_enable_addr[x])
# define LP3972_BUCK_VOL1_REG(x) (buck_base_addr[x])
# define LP3972_BUCK_VOL_MASK 0x1f
# define LP3972_BUCK_VOL_MIN_IDX(x) ((x) ? 0x01 : 0x00)
# define LP3972_BUCK_VOL_MAX_IDX(x) ((x) ? 0x19 : 0x1f)
static int lp3972_i2c_read ( struct i2c_client * i2c , char reg , int count ,
u16 * dest )
{
int ret ;
if ( count ! = 1 )
return - EIO ;
ret = i2c_smbus_read_byte_data ( i2c , reg ) ;
if ( ret < 0 )
2010-09-18 09:13:28 +04:00
return ret ;
2010-09-16 12:48:49 +04:00
* dest = ret ;
return 0 ;
}
static int lp3972_i2c_write ( struct i2c_client * i2c , char reg , int count ,
const u16 * src )
{
if ( count ! = 1 )
return - EIO ;
return i2c_smbus_write_byte_data ( i2c , reg , * src ) ;
}
static u8 lp3972_reg_read ( struct lp3972 * lp3972 , u8 reg )
{
u16 val = 0 ;
mutex_lock ( & lp3972 - > io_lock ) ;
lp3972_i2c_read ( lp3972 - > i2c , reg , 1 , & val ) ;
dev_dbg ( lp3972 - > dev , " reg read 0x%02x -> 0x%02x \n " , ( int ) reg ,
2010-09-18 09:13:28 +04:00
( unsigned ) val & 0xff ) ;
2010-09-16 12:48:49 +04:00
mutex_unlock ( & lp3972 - > io_lock ) ;
return val & 0xff ;
}
static int lp3972_set_bits ( struct lp3972 * lp3972 , u8 reg , u16 mask , u16 val )
{
u16 tmp ;
int ret ;
mutex_lock ( & lp3972 - > io_lock ) ;
ret = lp3972_i2c_read ( lp3972 - > i2c , reg , 1 , & tmp ) ;
tmp = ( tmp & ~ mask ) | val ;
if ( ret = = 0 ) {
ret = lp3972_i2c_write ( lp3972 - > i2c , reg , 1 , & tmp ) ;
dev_dbg ( lp3972 - > dev , " reg write 0x%02x -> 0x%02x \n " , ( int ) reg ,
2010-09-18 09:13:28 +04:00
( unsigned ) val & 0xff ) ;
2010-09-16 12:48:49 +04:00
}
mutex_unlock ( & lp3972 - > io_lock ) ;
return ret ;
}
static int lp3972_ldo_list_voltage ( struct regulator_dev * dev , unsigned index )
{
int ldo = rdev_get_id ( dev ) - LP3972_LDO1 ;
return 1000 * LP3972_LDO_VOL_VALUE_MAP ( ldo ) [ index ] ;
}
static int lp3972_ldo_is_enabled ( struct regulator_dev * dev )
{
struct lp3972 * lp3972 = rdev_get_drvdata ( dev ) ;
int ldo = rdev_get_id ( dev ) - LP3972_LDO1 ;
u16 mask = LP3972_LDO_OUTPUT_ENABLE_MASK ( ldo ) ;
u16 val ;
val = lp3972_reg_read ( lp3972 , LP3972_LDO_OUTPUT_ENABLE_REG ( ldo ) ) ;
return ! ! ( val & mask ) ;
}
static int lp3972_ldo_enable ( struct regulator_dev * dev )
{
struct lp3972 * lp3972 = rdev_get_drvdata ( dev ) ;
int ldo = rdev_get_id ( dev ) - LP3972_LDO1 ;
u16 mask = LP3972_LDO_OUTPUT_ENABLE_MASK ( ldo ) ;
return lp3972_set_bits ( lp3972 , LP3972_LDO_OUTPUT_ENABLE_REG ( ldo ) ,
mask , mask ) ;
}
static int lp3972_ldo_disable ( struct regulator_dev * dev )
{
struct lp3972 * lp3972 = rdev_get_drvdata ( dev ) ;
int ldo = rdev_get_id ( dev ) - LP3972_LDO1 ;
u16 mask = LP3972_LDO_OUTPUT_ENABLE_MASK ( ldo ) ;
return lp3972_set_bits ( lp3972 , LP3972_LDO_OUTPUT_ENABLE_REG ( ldo ) ,
mask , 0 ) ;
}
static int lp3972_ldo_get_voltage ( struct regulator_dev * dev )
{
struct lp3972 * lp3972 = rdev_get_drvdata ( dev ) ;
int ldo = rdev_get_id ( dev ) - LP3972_LDO1 ;
u16 mask = LP3972_LDO_VOL_MASK ( ldo ) ;
u16 val , reg ;
reg = lp3972_reg_read ( lp3972 , LP3972_LDO_VOL_CONTR_REG ( ldo ) ) ;
val = ( reg > > LP3972_LDO_VOL_CONTR_SHIFT ( ldo ) ) & mask ;
return 1000 * LP3972_LDO_VOL_VALUE_MAP ( ldo ) [ val ] ;
}
static int lp3972_ldo_set_voltage ( struct regulator_dev * dev ,
2010-11-10 17:38:29 +03:00
int min_uV , int max_uV ,
unsigned int * selector )
2010-09-16 12:48:49 +04:00
{
struct lp3972 * lp3972 = rdev_get_drvdata ( dev ) ;
int ldo = rdev_get_id ( dev ) - LP3972_LDO1 ;
int min_vol = min_uV / 1000 , max_vol = max_uV / 1000 ;
const int * vol_map = LP3972_LDO_VOL_VALUE_MAP ( ldo ) ;
u16 val ;
int shift , ret ;
if ( min_vol < vol_map [ LP3972_LDO_VOL_MIN_IDX ( ldo ) ] | |
min_vol > vol_map [ LP3972_LDO_VOL_MAX_IDX ( ldo ) ] )
return - EINVAL ;
for ( val = LP3972_LDO_VOL_MIN_IDX ( ldo ) ;
val < = LP3972_LDO_VOL_MAX_IDX ( ldo ) ; val + + )
if ( vol_map [ val ] > = min_vol )
break ;
if ( val > LP3972_LDO_VOL_MAX_IDX ( ldo ) | | vol_map [ val ] > max_vol )
return - EINVAL ;
2010-11-10 17:38:29 +03:00
* selector = val ;
2010-09-16 12:48:49 +04:00
shift = LP3972_LDO_VOL_CONTR_SHIFT ( ldo ) ;
ret = lp3972_set_bits ( lp3972 , LP3972_LDO_VOL_CONTR_REG ( ldo ) ,
LP3972_LDO_VOL_MASK ( ldo ) < < shift , val < < shift ) ;
if ( ret )
return ret ;
2010-09-18 09:13:28 +04:00
/*
* LDO1 and LDO5 support voltage control by either target voltage1
* or target voltage2 register .
* We use target voltage1 register for LDO1 and LDO5 in this driver .
* We need to update voltage change control register ( 0x20 ) to enable
* LDO1 and LDO5 to change to their programmed target values .
*/
2010-09-16 12:48:49 +04:00
switch ( ldo ) {
case LP3972_LDO1 :
case LP3972_LDO5 :
shift = LP3972_LDO_VOL_CHANGE_SHIFT ( ldo ) ;
ret = lp3972_set_bits ( lp3972 , LP3972_VOL_CHANGE_REG ,
LP3972_VOL_CHANGE_FLAG_MASK < < shift ,
LP3972_VOL_CHANGE_FLAG_GO < < shift ) ;
if ( ret )
return ret ;
ret = lp3972_set_bits ( lp3972 , LP3972_VOL_CHANGE_REG ,
LP3972_VOL_CHANGE_FLAG_MASK < < shift , 0 ) ;
break ;
}
return ret ;
}
static struct regulator_ops lp3972_ldo_ops = {
. list_voltage = lp3972_ldo_list_voltage ,
. is_enabled = lp3972_ldo_is_enabled ,
. enable = lp3972_ldo_enable ,
. disable = lp3972_ldo_disable ,
. get_voltage = lp3972_ldo_get_voltage ,
. set_voltage = lp3972_ldo_set_voltage ,
} ;
static int lp3972_dcdc_list_voltage ( struct regulator_dev * dev , unsigned index )
{
int buck = rdev_get_id ( dev ) - LP3972_DCDC1 ;
return 1000 * buck_voltage_map [ buck ] [ index ] ;
}
static int lp3972_dcdc_is_enabled ( struct regulator_dev * dev )
{
struct lp3972 * lp3972 = rdev_get_drvdata ( dev ) ;
int buck = rdev_get_id ( dev ) - LP3972_DCDC1 ;
u16 mask = 1 < < ( buck * 2 ) ;
u16 val ;
val = lp3972_reg_read ( lp3972 , LP3972_BUCK_VOL_ENABLE_REG ( buck ) ) ;
return ! ! ( val & mask ) ;
}
static int lp3972_dcdc_enable ( struct regulator_dev * dev )
{
struct lp3972 * lp3972 = rdev_get_drvdata ( dev ) ;
int buck = rdev_get_id ( dev ) - LP3972_DCDC1 ;
u16 mask = 1 < < ( buck * 2 ) ;
u16 val ;
val = lp3972_set_bits ( lp3972 , LP3972_BUCK_VOL_ENABLE_REG ( buck ) ,
mask , mask ) ;
return val ;
}
static int lp3972_dcdc_disable ( struct regulator_dev * dev )
{
struct lp3972 * lp3972 = rdev_get_drvdata ( dev ) ;
int buck = rdev_get_id ( dev ) - LP3972_DCDC1 ;
u16 mask = 1 < < ( buck * 2 ) ;
u16 val ;
val = lp3972_set_bits ( lp3972 , LP3972_BUCK_VOL_ENABLE_REG ( buck ) ,
mask , 0 ) ;
return val ;
}
static int lp3972_dcdc_get_voltage ( struct regulator_dev * dev )
{
struct lp3972 * lp3972 = rdev_get_drvdata ( dev ) ;
int buck = rdev_get_id ( dev ) - LP3972_DCDC1 ;
u16 reg ;
int val ;
reg = lp3972_reg_read ( lp3972 , LP3972_BUCK_VOL1_REG ( buck ) ) ;
reg & = LP3972_BUCK_VOL_MASK ;
if ( reg < = LP3972_BUCK_VOL_MAX_IDX ( buck ) )
val = 1000 * buck_voltage_map [ buck ] [ reg ] ;
else {
val = 0 ;
2010-09-18 09:13:28 +04:00
dev_warn ( & dev - > dev , " chip reported incorrect voltage value. "
" reg = %d \n " , reg ) ;
2010-09-16 12:48:49 +04:00
}
return val ;
}
static int lp3972_dcdc_set_voltage ( struct regulator_dev * dev ,
2010-11-10 17:38:29 +03:00
int min_uV , int max_uV ,
unsigned int * selector )
2010-09-16 12:48:49 +04:00
{
struct lp3972 * lp3972 = rdev_get_drvdata ( dev ) ;
int buck = rdev_get_id ( dev ) - LP3972_DCDC1 ;
int min_vol = min_uV / 1000 , max_vol = max_uV / 1000 ;
const int * vol_map = buck_voltage_map [ buck ] ;
u16 val ;
int ret ;
if ( min_vol < vol_map [ LP3972_BUCK_VOL_MIN_IDX ( buck ) ] | |
min_vol > vol_map [ LP3972_BUCK_VOL_MAX_IDX ( buck ) ] )
return - EINVAL ;
for ( val = LP3972_BUCK_VOL_MIN_IDX ( buck ) ;
val < = LP3972_BUCK_VOL_MAX_IDX ( buck ) ; val + + )
if ( vol_map [ val ] > = min_vol )
break ;
if ( val > LP3972_BUCK_VOL_MAX_IDX ( buck ) | |
vol_map [ val ] > max_vol )
return - EINVAL ;
2010-11-10 17:38:29 +03:00
* selector = val ;
2010-09-16 12:48:49 +04:00
ret = lp3972_set_bits ( lp3972 , LP3972_BUCK_VOL1_REG ( buck ) ,
LP3972_BUCK_VOL_MASK , val ) ;
if ( ret )
return ret ;
if ( buck ! = 0 )
return ret ;
ret = lp3972_set_bits ( lp3972 , LP3972_VOL_CHANGE_REG ,
LP3972_VOL_CHANGE_FLAG_MASK , LP3972_VOL_CHANGE_FLAG_GO ) ;
if ( ret )
return ret ;
return lp3972_set_bits ( lp3972 , LP3972_VOL_CHANGE_REG ,
LP3972_VOL_CHANGE_FLAG_MASK , 0 ) ;
}
static struct regulator_ops lp3972_dcdc_ops = {
. list_voltage = lp3972_dcdc_list_voltage ,
. is_enabled = lp3972_dcdc_is_enabled ,
. enable = lp3972_dcdc_enable ,
. disable = lp3972_dcdc_disable ,
. get_voltage = lp3972_dcdc_get_voltage ,
. set_voltage = lp3972_dcdc_set_voltage ,
} ;
static struct regulator_desc regulators [ ] = {
{
. name = " LDO1 " ,
. id = LP3972_LDO1 ,
. ops = & lp3972_ldo_ops ,
. n_voltages = ARRAY_SIZE ( ldo1_voltage_map ) ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
} ,
{
. name = " LDO2 " ,
. id = LP3972_LDO2 ,
. ops = & lp3972_ldo_ops ,
. n_voltages = ARRAY_SIZE ( ldo23_voltage_map ) ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
} ,
{
. name = " LDO3 " ,
. id = LP3972_LDO3 ,
. ops = & lp3972_ldo_ops ,
. n_voltages = ARRAY_SIZE ( ldo23_voltage_map ) ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
} ,
{
. name = " LDO4 " ,
. id = LP3972_LDO4 ,
. ops = & lp3972_ldo_ops ,
. n_voltages = ARRAY_SIZE ( ldo4_voltage_map ) ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
} ,
{
. name = " LDO5 " ,
. id = LP3972_LDO5 ,
. ops = & lp3972_ldo_ops ,
. n_voltages = ARRAY_SIZE ( ldo5_voltage_map ) ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
} ,
{
. name = " DCDC1 " ,
. id = LP3972_DCDC1 ,
. ops = & lp3972_dcdc_ops ,
. n_voltages = ARRAY_SIZE ( buck1_voltage_map ) ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
} ,
{
. name = " DCDC2 " ,
. id = LP3972_DCDC2 ,
. ops = & lp3972_dcdc_ops ,
. n_voltages = ARRAY_SIZE ( buck23_voltage_map ) ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
} ,
{
. name = " DCDC3 " ,
. id = LP3972_DCDC3 ,
. ops = & lp3972_dcdc_ops ,
. n_voltages = ARRAY_SIZE ( buck23_voltage_map ) ,
. type = REGULATOR_VOLTAGE ,
. owner = THIS_MODULE ,
} ,
} ;
2010-09-18 09:13:28 +04:00
static int __devinit setup_regulators ( struct lp3972 * lp3972 ,
2010-09-16 12:48:49 +04:00
struct lp3972_platform_data * pdata )
{
int i , err ;
lp3972 - > num_regulators = pdata - > num_regulators ;
lp3972 - > rdev = kcalloc ( pdata - > num_regulators ,
sizeof ( struct regulator_dev * ) , GFP_KERNEL ) ;
if ( ! lp3972 - > rdev ) {
err = - ENOMEM ;
goto err_nomem ;
}
/* Instantiate the regulators */
for ( i = 0 ; i < pdata - > num_regulators ; i + + ) {
struct lp3972_regulator_subdev * reg = & pdata - > regulators [ i ] ;
lp3972 - > rdev [ i ] = regulator_register ( & regulators [ reg - > id ] ,
2011-11-18 15:17:19 +04:00
lp3972 - > dev , reg - > initdata , lp3972 , NULL ) ;
2010-09-16 12:48:49 +04:00
if ( IS_ERR ( lp3972 - > rdev [ i ] ) ) {
err = PTR_ERR ( lp3972 - > rdev [ i ] ) ;
dev_err ( lp3972 - > dev , " regulator init failed: %d \n " ,
err ) ;
goto error ;
}
}
return 0 ;
error :
while ( - - i > = 0 )
regulator_unregister ( lp3972 - > rdev [ i ] ) ;
kfree ( lp3972 - > rdev ) ;
lp3972 - > rdev = NULL ;
err_nomem :
return err ;
}
static int __devinit lp3972_i2c_probe ( struct i2c_client * i2c ,
const struct i2c_device_id * id )
{
struct lp3972 * lp3972 ;
struct lp3972_platform_data * pdata = i2c - > dev . platform_data ;
int ret ;
u16 val ;
if ( ! pdata ) {
dev_dbg ( & i2c - > dev , " No platform init data supplied \n " ) ;
return - ENODEV ;
}
lp3972 = kzalloc ( sizeof ( struct lp3972 ) , GFP_KERNEL ) ;
if ( ! lp3972 )
return - ENOMEM ;
lp3972 - > i2c = i2c ;
lp3972 - > dev = & i2c - > dev ;
mutex_init ( & lp3972 - > io_lock ) ;
/* Detect LP3972 */
ret = lp3972_i2c_read ( i2c , LP3972_SYS_CONTROL1_REG , 1 , & val ) ;
2010-09-18 09:13:28 +04:00
if ( ret = = 0 & &
( val & SYS_CONTROL1_INIT_MASK ) ! = SYS_CONTROL1_INIT_VAL ) {
2010-09-16 12:48:49 +04:00
ret = - ENODEV ;
2010-09-18 09:13:28 +04:00
dev_err ( & i2c - > dev , " chip reported: val = 0x%x \n " , val ) ;
}
2010-09-16 12:48:49 +04:00
if ( ret < 0 ) {
2010-09-18 09:13:28 +04:00
dev_err ( & i2c - > dev , " failed to detect device. ret = %d \n " , ret ) ;
2010-09-16 12:48:49 +04:00
goto err_detect ;
}
ret = setup_regulators ( lp3972 , pdata ) ;
if ( ret < 0 )
goto err_detect ;
i2c_set_clientdata ( i2c , lp3972 ) ;
return 0 ;
err_detect :
kfree ( lp3972 ) ;
return ret ;
}
static int __devexit lp3972_i2c_remove ( struct i2c_client * i2c )
{
struct lp3972 * lp3972 = i2c_get_clientdata ( i2c ) ;
int i ;
for ( i = 0 ; i < lp3972 - > num_regulators ; i + + )
regulator_unregister ( lp3972 - > rdev [ i ] ) ;
kfree ( lp3972 - > rdev ) ;
kfree ( lp3972 ) ;
return 0 ;
}
static const struct i2c_device_id lp3972_i2c_id [ ] = {
{ " lp3972 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , lp3972_i2c_id ) ;
static struct i2c_driver lp3972_i2c_driver = {
. driver = {
. name = " lp3972 " ,
. owner = THIS_MODULE ,
} ,
. probe = lp3972_i2c_probe ,
. remove = __devexit_p ( lp3972_i2c_remove ) ,
. id_table = lp3972_i2c_id ,
} ;
static int __init lp3972_module_init ( void )
{
return i2c_add_driver ( & lp3972_i2c_driver ) ;
}
subsys_initcall ( lp3972_module_init ) ;
static void __exit lp3972_module_exit ( void )
{
i2c_del_driver ( & lp3972_i2c_driver ) ;
}
module_exit ( lp3972_module_exit ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Axel Lin <axel.lin@gmail.com> " ) ;
MODULE_DESCRIPTION ( " LP3972 PMIC driver " ) ;