2012-03-17 14:04:41 +04:00
/*
* HWMON Driver for Dialog DA9052
*
* Copyright ( c ) 2012 Dialog Semiconductor Ltd .
*
* Author : David Dajun Chen < dchen @ diasemi . 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 ; either version 2 of the License , or ( at your
* option ) any later version .
*
*/
# include <linux/err.h>
# include <linux/hwmon.h>
# include <linux/hwmon-sysfs.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/platform_device.h>
2017-08-21 17:54:04 +03:00
# include <linux/property.h>
2012-03-17 14:04:41 +04:00
# include <linux/mfd/da9052/da9052.h>
# include <linux/mfd/da9052/reg.h>
2017-08-21 17:54:04 +03:00
# include <linux/regulator/consumer.h>
2012-03-17 14:04:41 +04:00
struct da9052_hwmon {
2017-08-21 17:54:04 +03:00
struct da9052 * da9052 ;
struct mutex hwmon_lock ;
bool tsi_as_adc ;
int tsiref_mv ;
struct regulator * tsiref ;
struct completion tsidone ;
2012-03-17 14:04:41 +04:00
} ;
static const char * const input_names [ ] = {
[ DA9052_ADC_VDDOUT ] = " VDDOUT " ,
[ DA9052_ADC_ICH ] = " CHARGING CURRENT " ,
[ DA9052_ADC_TBAT ] = " BATTERY TEMP " ,
[ DA9052_ADC_VBAT ] = " BATTERY VOLTAGE " ,
[ DA9052_ADC_IN4 ] = " ADC IN4 " ,
[ DA9052_ADC_IN5 ] = " ADC IN5 " ,
[ DA9052_ADC_IN6 ] = " ADC IN6 " ,
2017-08-21 17:54:04 +03:00
[ DA9052_ADC_TSI_XP ] = " ADC TS X+ " ,
[ DA9052_ADC_TSI_YP ] = " ADC TS Y+ " ,
[ DA9052_ADC_TSI_XN ] = " ADC TS X- " ,
[ DA9052_ADC_TSI_YN ] = " ADC TS Y- " ,
2012-03-17 14:04:41 +04:00
[ DA9052_ADC_TJUNC ] = " BATTERY JUNCTION TEMP " ,
[ DA9052_ADC_VBBAT ] = " BACK-UP BATTERY VOLTAGE " ,
} ;
/* Conversion function for VDDOUT and VBAT */
2013-03-14 03:40:39 +04:00
static inline int volt_reg_to_mv ( int value )
2012-03-17 14:04:41 +04:00
{
2013-12-18 19:15:31 +04:00
return DIV_ROUND_CLOSEST ( value * 2000 , 1023 ) + 2500 ;
2012-03-17 14:04:41 +04:00
}
/* Conversion function for ADC channels 4, 5 and 6 */
2013-03-14 03:40:39 +04:00
static inline int input_reg_to_mv ( int value )
2012-03-17 14:04:41 +04:00
{
return DIV_ROUND_CLOSEST ( value * 2500 , 1023 ) ;
}
/* Conversion function for VBBAT */
2013-03-14 03:40:39 +04:00
static inline int vbbat_reg_to_mv ( int value )
2012-03-17 14:04:41 +04:00
{
2013-12-18 19:15:31 +04:00
return DIV_ROUND_CLOSEST ( value * 5000 , 1023 ) ;
2012-03-17 14:04:41 +04:00
}
2017-08-21 17:54:04 +03:00
static inline int input_tsireg_to_mv ( struct da9052_hwmon * hwmon , int value )
{
return DIV_ROUND_CLOSEST ( value * hwmon - > tsiref_mv , 1023 ) ;
}
2012-10-11 18:03:51 +04:00
static inline int da9052_enable_vddout_channel ( struct da9052 * da9052 )
2012-03-17 14:04:41 +04:00
{
2012-10-11 18:03:51 +04:00
return da9052_reg_update ( da9052 , DA9052_ADC_CONT_REG ,
DA9052_ADCCONT_AUTOVDDEN ,
DA9052_ADCCONT_AUTOVDDEN ) ;
2012-03-17 14:04:41 +04:00
}
2012-10-11 18:03:51 +04:00
static inline int da9052_disable_vddout_channel ( struct da9052 * da9052 )
2012-03-17 14:04:41 +04:00
{
2012-10-11 18:03:51 +04:00
return da9052_reg_update ( da9052 , DA9052_ADC_CONT_REG ,
DA9052_ADCCONT_AUTOVDDEN , 0 ) ;
2012-03-17 14:04:41 +04:00
}
static ssize_t da9052_read_vddout ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
struct da9052_hwmon * hwmon = dev_get_drvdata ( dev ) ;
int ret , vdd ;
mutex_lock ( & hwmon - > hwmon_lock ) ;
ret = da9052_enable_vddout_channel ( hwmon - > da9052 ) ;
if ( ret < 0 )
goto hwmon_err ;
vdd = da9052_reg_read ( hwmon - > da9052 , DA9052_VDD_RES_REG ) ;
if ( vdd < 0 ) {
ret = vdd ;
goto hwmon_err_release ;
}
ret = da9052_disable_vddout_channel ( hwmon - > da9052 ) ;
if ( ret < 0 )
goto hwmon_err ;
mutex_unlock ( & hwmon - > hwmon_lock ) ;
2013-03-14 03:40:39 +04:00
return sprintf ( buf , " %d \n " , volt_reg_to_mv ( vdd ) ) ;
2012-03-17 14:04:41 +04:00
hwmon_err_release :
da9052_disable_vddout_channel ( hwmon - > da9052 ) ;
hwmon_err :
mutex_unlock ( & hwmon - > hwmon_lock ) ;
return ret ;
}
static ssize_t da9052_read_ich ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
struct da9052_hwmon * hwmon = dev_get_drvdata ( dev ) ;
int ret ;
ret = da9052_reg_read ( hwmon - > da9052 , DA9052_ICHG_AV_REG ) ;
if ( ret < 0 )
return ret ;
/* Equivalent to 3.9mA/bit in register ICHG_AV */
return sprintf ( buf , " %d \n " , DIV_ROUND_CLOSEST ( ret * 39 , 10 ) ) ;
}
static ssize_t da9052_read_tbat ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
struct da9052_hwmon * hwmon = dev_get_drvdata ( dev ) ;
return sprintf ( buf , " %d \n " , da9052_adc_read_temp ( hwmon - > da9052 ) ) ;
}
static ssize_t da9052_read_vbat ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
struct da9052_hwmon * hwmon = dev_get_drvdata ( dev ) ;
int ret ;
ret = da9052_adc_manual_read ( hwmon - > da9052 , DA9052_ADC_VBAT ) ;
if ( ret < 0 )
return ret ;
2013-03-14 03:40:39 +04:00
return sprintf ( buf , " %d \n " , volt_reg_to_mv ( ret ) ) ;
2012-03-17 14:04:41 +04:00
}
static ssize_t da9052_read_misc_channel ( struct device * dev ,
struct device_attribute * devattr ,
char * buf )
{
struct da9052_hwmon * hwmon = dev_get_drvdata ( dev ) ;
int channel = to_sensor_dev_attr ( devattr ) - > index ;
int ret ;
ret = da9052_adc_manual_read ( hwmon - > da9052 , channel ) ;
if ( ret < 0 )
return ret ;
2013-03-14 03:40:39 +04:00
return sprintf ( buf , " %d \n " , input_reg_to_mv ( ret ) ) ;
2012-03-17 14:04:41 +04:00
}
2017-08-21 17:54:04 +03:00
static int da9052_request_tsi_read ( struct da9052_hwmon * hwmon , int channel )
{
u8 val = DA9052_TSICONTB_TSIMAN ;
switch ( channel ) {
case DA9052_ADC_TSI_XP :
val | = DA9052_TSICONTB_TSIMUX_XP ;
break ;
case DA9052_ADC_TSI_YP :
val | = DA9052_TSICONTB_TSIMUX_YP ;
break ;
case DA9052_ADC_TSI_XN :
val | = DA9052_TSICONTB_TSIMUX_XN ;
break ;
case DA9052_ADC_TSI_YN :
val | = DA9052_TSICONTB_TSIMUX_YN ;
break ;
}
return da9052_reg_write ( hwmon - > da9052 , DA9052_TSI_CONT_B_REG , val ) ;
}
static int da9052_get_tsi_result ( struct da9052_hwmon * hwmon , int channel )
{
u8 regs [ 3 ] ;
int msb , lsb , err ;
/* block read to avoid separation of MSB and LSB */
err = da9052_group_read ( hwmon - > da9052 , DA9052_TSI_X_MSB_REG ,
ARRAY_SIZE ( regs ) , regs ) ;
if ( err )
return err ;
switch ( channel ) {
case DA9052_ADC_TSI_XP :
case DA9052_ADC_TSI_XN :
msb = regs [ 0 ] < < DA9052_TSILSB_TSIXL_BITS ;
lsb = regs [ 2 ] & DA9052_TSILSB_TSIXL ;
lsb > > = DA9052_TSILSB_TSIXL_SHIFT ;
break ;
case DA9052_ADC_TSI_YP :
case DA9052_ADC_TSI_YN :
msb = regs [ 1 ] < < DA9052_TSILSB_TSIYL_BITS ;
lsb = regs [ 2 ] & DA9052_TSILSB_TSIYL ;
lsb > > = DA9052_TSILSB_TSIYL_SHIFT ;
break ;
default :
return - EINVAL ;
}
return msb | lsb ;
}
static ssize_t __da9052_read_tsi ( struct device * dev , int channel )
{
struct da9052_hwmon * hwmon = dev_get_drvdata ( dev ) ;
int ret ;
reinit_completion ( & hwmon - > tsidone ) ;
ret = da9052_request_tsi_read ( hwmon , channel ) ;
if ( ret < 0 )
return ret ;
/* Wait for an conversion done interrupt */
if ( ! wait_for_completion_timeout ( & hwmon - > tsidone ,
msecs_to_jiffies ( 500 ) ) )
return - ETIMEDOUT ;
return da9052_get_tsi_result ( hwmon , channel ) ;
}
static ssize_t da9052_read_tsi ( struct device * dev ,
struct device_attribute * devattr ,
char * buf )
{
struct da9052_hwmon * hwmon = dev_get_drvdata ( dev ) ;
int channel = to_sensor_dev_attr ( devattr ) - > index ;
int ret ;
mutex_lock ( & hwmon - > hwmon_lock ) ;
ret = __da9052_read_tsi ( dev , channel ) ;
mutex_unlock ( & hwmon - > hwmon_lock ) ;
if ( ret < 0 )
return ret ;
else
return sprintf ( buf , " %d \n " , input_tsireg_to_mv ( hwmon , ret ) ) ;
}
2012-03-17 14:04:41 +04:00
static ssize_t da9052_read_tjunc ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
struct da9052_hwmon * hwmon = dev_get_drvdata ( dev ) ;
int tjunc ;
int toffset ;
tjunc = da9052_reg_read ( hwmon - > da9052 , DA9052_TJUNC_RES_REG ) ;
if ( tjunc < 0 )
return tjunc ;
toffset = da9052_reg_read ( hwmon - > da9052 , DA9052_T_OFFSET_REG ) ;
if ( toffset < 0 )
return toffset ;
/*
* Degrees celsius = 1.708 * ( TJUNC_RES - T_OFFSET ) - 108.8
* T_OFFSET is a trim value used to improve accuracy of the result
*/
return sprintf ( buf , " %d \n " , 1708 * ( tjunc - toffset ) - 108800 ) ;
}
static ssize_t da9052_read_vbbat ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
struct da9052_hwmon * hwmon = dev_get_drvdata ( dev ) ;
int ret ;
ret = da9052_adc_manual_read ( hwmon - > da9052 , DA9052_ADC_VBBAT ) ;
if ( ret < 0 )
return ret ;
2013-03-14 03:40:39 +04:00
return sprintf ( buf , " %d \n " , vbbat_reg_to_mv ( ret ) ) ;
2012-03-17 14:04:41 +04:00
}
static ssize_t show_label ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
return sprintf ( buf , " %s \n " ,
input_names [ to_sensor_dev_attr ( devattr ) - > index ] ) ;
}
2017-08-21 17:54:04 +03:00
static umode_t da9052_channel_is_visible ( struct kobject * kobj ,
struct attribute * attr , int index )
{
struct device * dev = container_of ( kobj , struct device , kobj ) ;
struct da9052_hwmon * hwmon = dev_get_drvdata ( dev ) ;
struct device_attribute * dattr = container_of ( attr ,
struct device_attribute , attr ) ;
struct sensor_device_attribute * sattr = to_sensor_dev_attr ( dattr ) ;
if ( ! hwmon - > tsi_as_adc ) {
switch ( sattr - > index ) {
case DA9052_ADC_TSI_XP :
case DA9052_ADC_TSI_YP :
case DA9052_ADC_TSI_XN :
case DA9052_ADC_TSI_YN :
return 0 ;
}
}
return attr - > mode ;
}
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in0_input , 0444 , da9052_read_vddout , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_VDDOUT ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in0_label , 0444 , show_label , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_VDDOUT ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in3_input , 0444 , da9052_read_vbat , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_VBAT ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in3_label , 0444 , show_label , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_VBAT ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in4_input , 0444 , da9052_read_misc_channel , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_IN4 ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in4_label , 0444 , show_label , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_IN4 ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in5_input , 0444 , da9052_read_misc_channel , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_IN5 ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in5_label , 0444 , show_label , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_IN5 ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in6_input , 0444 , da9052_read_misc_channel , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_IN6 ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in6_label , 0444 , show_label , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_IN6 ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in9_input , 0444 , da9052_read_vbbat , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_VBBAT ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( in9_label , 0444 , show_label , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_VBBAT ) ;
2017-08-21 17:54:04 +03:00
static SENSOR_DEVICE_ATTR ( in70_input , 0444 , da9052_read_tsi , NULL ,
DA9052_ADC_TSI_XP ) ;
static SENSOR_DEVICE_ATTR ( in70_label , 0444 , show_label , NULL ,
DA9052_ADC_TSI_XP ) ;
static SENSOR_DEVICE_ATTR ( in71_input , 0444 , da9052_read_tsi , NULL ,
DA9052_ADC_TSI_XN ) ;
static SENSOR_DEVICE_ATTR ( in71_label , 0444 , show_label , NULL ,
DA9052_ADC_TSI_XN ) ;
static SENSOR_DEVICE_ATTR ( in72_input , 0444 , da9052_read_tsi , NULL ,
DA9052_ADC_TSI_YP ) ;
static SENSOR_DEVICE_ATTR ( in72_label , 0444 , show_label , NULL ,
DA9052_ADC_TSI_YP ) ;
static SENSOR_DEVICE_ATTR ( in73_input , 0444 , da9052_read_tsi , NULL ,
DA9052_ADC_TSI_YN ) ;
static SENSOR_DEVICE_ATTR ( in73_label , 0444 , show_label , NULL ,
DA9052_ADC_TSI_YN ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( curr1_input , 0444 , da9052_read_ich , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_ICH ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( curr1_label , 0444 , show_label , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_ICH ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( temp2_input , 0444 , da9052_read_tbat , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_TBAT ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( temp2_label , 0444 , show_label , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_TBAT ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( temp8_input , 0444 , da9052_read_tjunc , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_TJUNC ) ;
2017-08-21 17:54:03 +03:00
static SENSOR_DEVICE_ATTR ( temp8_label , 0444 , show_label , NULL ,
2012-03-17 14:04:41 +04:00
DA9052_ADC_TJUNC ) ;
2014-07-09 05:20:41 +04:00
static struct attribute * da9052_attrs [ ] = {
2012-03-17 14:04:41 +04:00
& sensor_dev_attr_in0_input . dev_attr . attr ,
& sensor_dev_attr_in0_label . dev_attr . attr ,
& sensor_dev_attr_in3_input . dev_attr . attr ,
& sensor_dev_attr_in3_label . dev_attr . attr ,
& sensor_dev_attr_in4_input . dev_attr . attr ,
& sensor_dev_attr_in4_label . dev_attr . attr ,
& sensor_dev_attr_in5_input . dev_attr . attr ,
& sensor_dev_attr_in5_label . dev_attr . attr ,
& sensor_dev_attr_in6_input . dev_attr . attr ,
& sensor_dev_attr_in6_label . dev_attr . attr ,
2017-08-21 17:54:04 +03:00
& sensor_dev_attr_in70_input . dev_attr . attr ,
& sensor_dev_attr_in70_label . dev_attr . attr ,
& sensor_dev_attr_in71_input . dev_attr . attr ,
& sensor_dev_attr_in71_label . dev_attr . attr ,
& sensor_dev_attr_in72_input . dev_attr . attr ,
& sensor_dev_attr_in72_label . dev_attr . attr ,
& sensor_dev_attr_in73_input . dev_attr . attr ,
& sensor_dev_attr_in73_label . dev_attr . attr ,
2012-03-17 14:04:41 +04:00
& sensor_dev_attr_in9_input . dev_attr . attr ,
& sensor_dev_attr_in9_label . dev_attr . attr ,
& sensor_dev_attr_curr1_input . dev_attr . attr ,
& sensor_dev_attr_curr1_label . dev_attr . attr ,
& sensor_dev_attr_temp2_input . dev_attr . attr ,
& sensor_dev_attr_temp2_label . dev_attr . attr ,
& sensor_dev_attr_temp8_input . dev_attr . attr ,
& sensor_dev_attr_temp8_label . dev_attr . attr ,
NULL
} ;
2017-08-21 17:54:04 +03:00
static const struct attribute_group da9052_group = {
. attrs = da9052_attrs ,
. is_visible = da9052_channel_is_visible ,
} ;
__ATTRIBUTE_GROUPS ( da9052 ) ;
static irqreturn_t da9052_tsi_datardy_irq ( int irq , void * data )
{
struct da9052_hwmon * hwmon = data ;
complete ( & hwmon - > tsidone ) ;
return IRQ_HANDLED ;
}
2012-03-17 14:04:41 +04:00
2012-11-19 22:22:35 +04:00
static int da9052_hwmon_probe ( struct platform_device * pdev )
2012-03-17 14:04:41 +04:00
{
2014-07-09 05:20:41 +04:00
struct device * dev = & pdev - > dev ;
2012-03-17 14:04:41 +04:00
struct da9052_hwmon * hwmon ;
2014-07-09 05:20:41 +04:00
struct device * hwmon_dev ;
2017-08-21 17:54:04 +03:00
int err ;
2012-03-17 14:04:41 +04:00
2014-07-09 05:20:41 +04:00
hwmon = devm_kzalloc ( dev , sizeof ( struct da9052_hwmon ) , GFP_KERNEL ) ;
2012-03-17 14:04:41 +04:00
if ( ! hwmon )
return - ENOMEM ;
2017-08-21 17:54:04 +03:00
platform_set_drvdata ( pdev , hwmon ) ;
2012-03-17 14:04:41 +04:00
mutex_init ( & hwmon - > hwmon_lock ) ;
hwmon - > da9052 = dev_get_drvdata ( pdev - > dev . parent ) ;
2017-08-21 17:54:04 +03:00
init_completion ( & hwmon - > tsidone ) ;
hwmon - > tsi_as_adc =
device_property_read_bool ( pdev - > dev . parent , " dlg,tsi-as-adc " ) ;
if ( hwmon - > tsi_as_adc ) {
hwmon - > tsiref = devm_regulator_get ( pdev - > dev . parent , " tsiref " ) ;
if ( IS_ERR ( hwmon - > tsiref ) ) {
err = PTR_ERR ( hwmon - > tsiref ) ;
dev_err ( & pdev - > dev , " failed to get tsiref: %d " , err ) ;
return err ;
}
err = regulator_enable ( hwmon - > tsiref ) ;
if ( err )
return err ;
hwmon - > tsiref_mv = regulator_get_voltage ( hwmon - > tsiref ) ;
if ( hwmon - > tsiref_mv < 0 ) {
err = hwmon - > tsiref_mv ;
goto exit_regulator ;
}
/* convert from microvolt (DT) to millivolt (hwmon) */
hwmon - > tsiref_mv / = 1000 ;
/* TSIREF limits from datasheet */
if ( hwmon - > tsiref_mv < 1800 | | hwmon - > tsiref_mv > 2600 ) {
dev_err ( hwmon - > da9052 - > dev , " invalid TSIREF voltage: %d " ,
hwmon - > tsiref_mv ) ;
err = - ENXIO ;
goto exit_regulator ;
}
/* disable touchscreen features */
da9052_reg_write ( hwmon - > da9052 , DA9052_TSI_CONT_A_REG , 0x00 ) ;
2017-10-19 18:51:44 +03:00
/* Sample every 1ms */
da9052_reg_update ( hwmon - > da9052 , DA9052_ADC_CONT_REG ,
DA9052_ADCCONT_ADCMODE ,
DA9052_ADCCONT_ADCMODE ) ;
2017-08-21 17:54:04 +03:00
err = da9052_request_irq ( hwmon - > da9052 , DA9052_IRQ_TSIREADY ,
" tsiready-irq " , da9052_tsi_datardy_irq ,
hwmon ) ;
if ( err ) {
dev_err ( & pdev - > dev , " Failed to register TSIRDY IRQ: %d " ,
err ) ;
goto exit_regulator ;
}
}
2014-07-09 05:20:41 +04:00
hwmon_dev = devm_hwmon_device_register_with_groups ( dev , " da9052 " ,
hwmon ,
da9052_groups ) ;
2017-08-21 17:54:04 +03:00
err = PTR_ERR_OR_ZERO ( hwmon_dev ) ;
if ( err )
goto exit_irq ;
return 0 ;
exit_irq :
if ( hwmon - > tsi_as_adc )
da9052_free_irq ( hwmon - > da9052 , DA9052_IRQ_TSIREADY , hwmon ) ;
exit_regulator :
if ( hwmon - > tsiref )
regulator_disable ( hwmon - > tsiref ) ;
return err ;
}
static int da9052_hwmon_remove ( struct platform_device * pdev )
{
struct da9052_hwmon * hwmon = platform_get_drvdata ( pdev ) ;
if ( hwmon - > tsi_as_adc ) {
da9052_free_irq ( hwmon - > da9052 , DA9052_IRQ_TSIREADY , hwmon ) ;
regulator_disable ( hwmon - > tsiref ) ;
}
return 0 ;
2012-03-17 14:04:41 +04:00
}
static struct platform_driver da9052_hwmon_driver = {
. probe = da9052_hwmon_probe ,
2017-08-21 17:54:04 +03:00
. remove = da9052_hwmon_remove ,
2012-03-17 14:04:41 +04:00
. driver = {
. name = " da9052-hwmon " ,
} ,
} ;
module_platform_driver ( da9052_hwmon_driver ) ;
MODULE_AUTHOR ( " David Dajun Chen <dchen@diasemi.com> " ) ;
MODULE_DESCRIPTION ( " DA9052 HWMON driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " platform:da9052-hwmon " ) ;