@ -31,14 +31,44 @@
# define ADM1275_VIN_VOUT_SELECT (1 << 6)
# define ADM1275_VRANGE (1 << 5)
# define ADM1275_IOUT_WARN2_LIMIT 0xd7
# define ADM1275_DEVICE_CONFIG 0xd8
# define ADM1275_IOUT_WARN2_SELECT (1 << 4)
# define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0)
struct adm1275_data {
bool have_oc_fault ;
struct pmbus_driver_info info ;
} ;
# define to_adm1275_data(x) container_of(x, struct adm1275_data, info)
static int adm1275_read_word_data ( struct i2c_client * client , int page , int reg )
{
const struct pmbus_driver_info * info = pmbus_get_driver_info ( client ) ;
const struct adm1275_data * data = to_adm1275_data ( info ) ;
int ret ;
if ( page )
return - EINVAL ;
return - ENXIO ;
switch ( reg ) {
case PMBUS_IOUT_UC_FAULT_LIMIT :
if ( data - > have_oc_fault ) {
ret = - ENXIO ;
break ;
}
ret = pmbus_read_word_data ( client , 0 , ADM1275_IOUT_WARN2_LIMIT ) ;
break ;
case PMBUS_IOUT_OC_FAULT_LIMIT :
if ( ! data - > have_oc_fault ) {
ret = - ENXIO ;
break ;
}
ret = pmbus_read_word_data ( client , 0 , ADM1275_IOUT_WARN2_LIMIT ) ;
break ;
case PMBUS_VIRT_READ_IOUT_MAX :
ret = pmbus_read_word_data ( client , 0 , ADM1275_PEAK_IOUT ) ;
break ;
@ -66,9 +96,14 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
int ret ;
if ( page )
return - EINVAL ;
return - ENXIO ;
switch ( reg ) {
case PMBUS_IOUT_UC_FAULT_LIMIT :
case PMBUS_IOUT_OC_FAULT_LIMIT :
ret = pmbus_write_word_data ( client , 0 , ADM1275_IOUT_WARN2_LIMIT ,
word ) ;
break ;
case PMBUS_VIRT_RESET_IOUT_HISTORY :
ret = pmbus_write_word_data ( client , 0 , ADM1275_PEAK_IOUT , 0 ) ;
break ;
@ -85,19 +120,52 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
return ret ;
}
static int adm1275_read_byte_data ( struct i2c_client * client , int page , int reg )
{
const struct pmbus_driver_info * info = pmbus_get_driver_info ( client ) ;
const struct adm1275_data * data = to_adm1275_data ( info ) ;
int mfr_status , ret ;
if ( page )
return - ENXIO ;
switch ( reg ) {
case PMBUS_STATUS_IOUT :
ret = pmbus_read_byte_data ( client , page , PMBUS_STATUS_IOUT ) ;
if ( ret < 0 )
break ;
mfr_status = pmbus_read_byte_data ( client , page ,
PMBUS_STATUS_MFR_SPECIFIC ) ;
if ( mfr_status < 0 ) {
ret = mfr_status ;
break ;
}
if ( mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2 ) {
ret | = data - > have_oc_fault ?
PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT ;
}
break ;
default :
ret = - ENODATA ;
break ;
}
return ret ;
}
static int adm1275_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
int config ;
int config , device_config ;
int ret ;
struct pmbus_driver_info * info ;
struct adm1275_data * data ;
if ( ! i2c_check_functionality ( client - > adapter ,
I2C_FUNC_SMBUS_READ_BYTE_DATA ) )
return - ENODEV ;
info = kzalloc ( sizeof ( struct pmbus_driver_info ) , GFP_KERNEL ) ;
if ( ! info )
data = kzalloc ( sizeof ( struct adm1275_data ) , GFP_KERNEL ) ;
if ( ! data )
return - ENOMEM ;
config = i2c_smbus_read_byte_data ( client , ADM1275_PMON_CONFIG ) ;
@ -106,6 +174,14 @@ static int adm1275_probe(struct i2c_client *client,
goto err_mem ;
}
device_config = i2c_smbus_read_byte_data ( client , ADM1275_DEVICE_CONFIG ) ;
if ( device_config < 0 ) {
ret = device_config ;
goto err_mem ;
}
info = & data - > info ;
info - > pages = 1 ;
info - > format [ PSC_VOLTAGE_IN ] = direct ;
info - > format [ PSC_VOLTAGE_OUT ] = direct ;
@ -116,6 +192,7 @@ static int adm1275_probe(struct i2c_client *client,
info - > func [ 0 ] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT ;
info - > read_word_data = adm1275_read_word_data ;
info - > read_byte_data = adm1275_read_byte_data ;
info - > write_word_data = adm1275_write_word_data ;
if ( config & ADM1275_VRANGE ) {
@ -134,6 +211,9 @@ static int adm1275_probe(struct i2c_client *client,
info - > R [ PSC_VOLTAGE_OUT ] = - 1 ;
}
if ( device_config & ADM1275_IOUT_WARN2_SELECT )
data - > have_oc_fault = true ;
if ( config & ADM1275_VIN_VOUT_SELECT )
info - > func [ 0 ] | = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT ;
else
@ -145,16 +225,17 @@ static int adm1275_probe(struct i2c_client *client,
return 0 ;
err_mem :
kfree ( info ) ;
kfree ( data ) ;
return ret ;
}
static int adm1275_remove ( struct i2c_client * client )
{
const struct pmbus_driver_info * info = pmbus_get_driver_info ( client ) ;
const struct adm1275_data * data = to_adm1275_data ( info ) ;
pmbus_do_remove ( client ) ;
kfree ( info ) ;
kfree ( data ) ;
return 0 ;
}