2011-06-28 19:11:23 +04:00
/*
* Copyright ( C ) 2011 Alexander Stein < alexander . stein @ systec - electronic . com >
*
2014-04-22 19:48:57 +04:00
* The LM95245 is a sensor chip made by TI / National Semiconductor .
2011-06-28 19:11:23 +04:00
* It reports up to two temperatures ( its own plus an external one ) .
*
* This driver is based on lm95241 . c
*
* 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 .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
2016-07-06 05:10:52 +03:00
# include <linux/err.h>
2011-06-28 19:11:23 +04:00
# include <linux/init.h>
# include <linux/hwmon.h>
2016-07-06 05:10:52 +03:00
# include <linux/i2c.h>
# include <linux/module.h>
2011-06-28 19:11:23 +04:00
# include <linux/mutex.h>
2016-07-06 05:10:52 +03:00
# include <linux/regmap.h>
# include <linux/slab.h>
2011-06-28 19:11:23 +04:00
static const unsigned short normal_i2c [ ] = {
0x18 , 0x19 , 0x29 , 0x4c , 0x4d , I2C_CLIENT_END } ;
/* LM95245 registers */
/* general registers */
# define LM95245_REG_RW_CONFIG1 0x03
# define LM95245_REG_RW_CONVERS_RATE 0x04
# define LM95245_REG_W_ONE_SHOT 0x0F
/* diode configuration */
# define LM95245_REG_RW_CONFIG2 0xBF
# define LM95245_REG_RW_REMOTE_OFFH 0x11
# define LM95245_REG_RW_REMOTE_OFFL 0x12
/* status registers */
# define LM95245_REG_R_STATUS1 0x02
# define LM95245_REG_R_STATUS2 0x33
/* limit registers */
# define LM95245_REG_RW_REMOTE_OS_LIMIT 0x07
# define LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT 0x20
# define LM95245_REG_RW_REMOTE_TCRIT_LIMIT 0x19
# define LM95245_REG_RW_COMMON_HYSTERESIS 0x21
/* temperature signed */
# define LM95245_REG_R_LOCAL_TEMPH_S 0x00
# define LM95245_REG_R_LOCAL_TEMPL_S 0x30
# define LM95245_REG_R_REMOTE_TEMPH_S 0x01
# define LM95245_REG_R_REMOTE_TEMPL_S 0x10
/* temperature unsigned */
# define LM95245_REG_R_REMOTE_TEMPH_U 0x31
# define LM95245_REG_R_REMOTE_TEMPL_U 0x32
/* id registers */
# define LM95245_REG_R_MAN_ID 0xFE
# define LM95245_REG_R_CHIP_ID 0xFF
/* LM95245 specific bitfields */
# define CFG_STOP 0x40
# define CFG_REMOTE_TCRIT_MASK 0x10
# define CFG_REMOTE_OS_MASK 0x08
# define CFG_LOCAL_TCRIT_MASK 0x04
# define CFG_LOCAL_OS_MASK 0x02
# define CFG2_OS_A0 0x40
# define CFG2_DIODE_FAULT_OS 0x20
# define CFG2_DIODE_FAULT_TCRIT 0x10
# define CFG2_REMOTE_TT 0x08
# define CFG2_REMOTE_FILTER_DIS 0x00
# define CFG2_REMOTE_FILTER_EN 0x06
/* conversation rate in ms */
# define RATE_CR0063 0x00
# define RATE_CR0364 0x01
# define RATE_CR1000 0x02
# define RATE_CR2500 0x03
2016-07-06 05:10:52 +03:00
# define STATUS1_ROS 0x10
2011-06-28 19:11:23 +04:00
# define STATUS1_DIODE_FAULT 0x04
# define STATUS1_RTCRIT 0x02
# define STATUS1_LOC 0x01
# define MANUFACTURER_ID 0x01
2014-04-22 19:48:57 +04:00
# define LM95235_REVISION 0xB1
# define LM95245_REVISION 0xB3
2011-06-28 19:11:23 +04:00
static const u8 lm95245_reg_address [ ] = {
LM95245_REG_R_LOCAL_TEMPH_S ,
LM95245_REG_R_LOCAL_TEMPL_S ,
LM95245_REG_R_REMOTE_TEMPH_S ,
LM95245_REG_R_REMOTE_TEMPL_S ,
LM95245_REG_R_REMOTE_TEMPH_U ,
LM95245_REG_R_REMOTE_TEMPL_U ,
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT ,
LM95245_REG_RW_REMOTE_TCRIT_LIMIT ,
LM95245_REG_RW_COMMON_HYSTERESIS ,
LM95245_REG_R_STATUS1 ,
} ;
/* Client data (each client gets its own) */
struct lm95245_data {
2016-07-06 05:10:52 +03:00
struct regmap * regmap ;
2011-06-28 19:11:23 +04:00
struct mutex update_lock ;
2016-07-06 05:10:52 +03:00
int interval ; /* in msecs */
2011-06-28 19:11:23 +04:00
} ;
/* Conversions */
static int temp_from_reg_unsigned ( u8 val_h , u8 val_l )
{
return val_h * 1000 + val_l * 1000 / 256 ;
}
static int temp_from_reg_signed ( u8 val_h , u8 val_l )
{
if ( val_h & 0x80 )
return ( val_h - 0x100 ) * 1000 ;
return temp_from_reg_unsigned ( val_h , val_l ) ;
}
2016-07-06 05:10:52 +03:00
static int lm95245_read_conversion_rate ( struct lm95245_data * data )
2011-06-28 19:11:23 +04:00
{
2016-07-06 05:10:52 +03:00
unsigned int rate ;
int ret ;
2011-06-28 19:11:23 +04:00
2016-07-06 05:10:52 +03:00
ret = regmap_read ( data - > regmap , LM95245_REG_RW_CONVERS_RATE , & rate ) ;
if ( ret < 0 )
return ret ;
2011-06-28 19:11:23 +04:00
switch ( rate ) {
case RATE_CR0063 :
2016-07-06 05:10:52 +03:00
data - > interval = 63 ;
2011-06-28 19:11:23 +04:00
break ;
case RATE_CR0364 :
2016-07-06 05:10:52 +03:00
data - > interval = 364 ;
2011-06-28 19:11:23 +04:00
break ;
case RATE_CR1000 :
2016-07-06 05:10:52 +03:00
data - > interval = 1000 ;
2011-06-28 19:11:23 +04:00
break ;
case RATE_CR2500 :
default :
2016-07-06 05:10:52 +03:00
data - > interval = 2500 ;
2011-06-28 19:11:23 +04:00
break ;
}
2016-07-06 05:10:52 +03:00
return 0 ;
2011-06-28 19:11:23 +04:00
}
2016-07-06 05:10:52 +03:00
static int lm95245_set_conversion_rate ( struct lm95245_data * data , long interval )
2011-06-28 19:11:23 +04:00
{
2016-07-06 05:10:52 +03:00
int ret , rate ;
2011-06-28 19:11:23 +04:00
if ( interval < = 63 ) {
interval = 63 ;
rate = RATE_CR0063 ;
} else if ( interval < = 364 ) {
interval = 364 ;
rate = RATE_CR0364 ;
} else if ( interval < = 1000 ) {
interval = 1000 ;
rate = RATE_CR1000 ;
} else {
interval = 2500 ;
rate = RATE_CR2500 ;
}
2016-07-06 05:10:52 +03:00
ret = regmap_write ( data - > regmap , LM95245_REG_RW_CONVERS_RATE , rate ) ;
if ( ret < 0 )
return ret ;
2011-06-28 19:11:23 +04:00
2016-07-06 05:10:52 +03:00
data - > interval = interval ;
return 0 ;
2011-06-28 19:11:23 +04:00
}
2016-07-06 05:10:52 +03:00
static int lm95245_read_temp ( struct device * dev , u32 attr , int channel ,
long * val )
2011-06-28 19:11:23 +04:00
{
2014-01-20 21:17:16 +04:00
struct lm95245_data * data = dev_get_drvdata ( dev ) ;
2016-07-06 05:10:52 +03:00
struct regmap * regmap = data - > regmap ;
int ret , regl , regh , regvall , regvalh ;
switch ( attr ) {
case hwmon_temp_input :
regl = channel ? LM95245_REG_R_REMOTE_TEMPL_S :
LM95245_REG_R_LOCAL_TEMPL_S ;
regh = channel ? LM95245_REG_R_REMOTE_TEMPH_S :
LM95245_REG_R_LOCAL_TEMPH_S ;
ret = regmap_read ( regmap , regl , & regvall ) ;
if ( ret < 0 )
return ret ;
ret = regmap_read ( regmap , regh , & regvalh ) ;
if ( ret < 0 )
return ret ;
/*
* Local temp is always signed .
* Remote temp has both signed and unsigned data .
* Use signed calculation for remote if signed bit is set
* or if reported temperature is below signed limit .
*/
if ( ! channel | | ( regvalh & 0x80 ) | | regvalh < 0x7f ) {
* val = temp_from_reg_signed ( regvalh , regvall ) ;
return 0 ;
}
ret = regmap_read ( regmap , LM95245_REG_R_REMOTE_TEMPL_U ,
& regvall ) ;
if ( ret < 0 )
return ret ;
ret = regmap_read ( regmap , LM95245_REG_R_REMOTE_TEMPH_U ,
& regvalh ) ;
if ( ret < 0 )
return ret ;
* val = temp_from_reg_unsigned ( regvalh , regvall ) ;
return 0 ;
case hwmon_temp_max :
ret = regmap_read ( regmap , LM95245_REG_RW_REMOTE_OS_LIMIT ,
& regvalh ) ;
if ( ret < 0 )
return ret ;
* val = regvalh * 1000 ;
return 0 ;
case hwmon_temp_crit :
regh = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT ;
ret = regmap_read ( regmap , regh , & regvalh ) ;
if ( ret < 0 )
return ret ;
* val = regvalh * 1000 ;
return 0 ;
case hwmon_temp_max_hyst :
ret = regmap_read ( regmap , LM95245_REG_RW_REMOTE_OS_LIMIT ,
& regvalh ) ;
if ( ret < 0 )
return ret ;
ret = regmap_read ( regmap , LM95245_REG_RW_COMMON_HYSTERESIS ,
& regvall ) ;
if ( ret < 0 )
return ret ;
* val = ( regvalh - regvall ) * 1000 ;
return 0 ;
case hwmon_temp_crit_hyst :
regh = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT ;
ret = regmap_read ( regmap , regh , & regvalh ) ;
if ( ret < 0 )
return ret ;
ret = regmap_read ( regmap , LM95245_REG_RW_COMMON_HYSTERESIS ,
& regvall ) ;
if ( ret < 0 )
return ret ;
* val = ( regvalh - regvall ) * 1000 ;
return 0 ;
case hwmon_temp_type :
ret = regmap_read ( regmap , LM95245_REG_RW_CONFIG2 , & regvalh ) ;
if ( ret < 0 )
return ret ;
* val = ( regvalh & CFG2_REMOTE_TT ) ? 1 : 2 ;
return 0 ;
case hwmon_temp_offset :
ret = regmap_read ( regmap , LM95245_REG_RW_REMOTE_OFFL ,
& regvall ) ;
if ( ret < 0 )
return ret ;
ret = regmap_read ( regmap , LM95245_REG_RW_REMOTE_OFFH ,
& regvalh ) ;
if ( ret < 0 )
return ret ;
* val = temp_from_reg_signed ( regvalh , regvall ) ;
return 0 ;
case hwmon_temp_max_alarm :
ret = regmap_read ( regmap , LM95245_REG_R_STATUS1 , & regvalh ) ;
if ( ret < 0 )
return ret ;
* val = ! ! ( regvalh & STATUS1_ROS ) ;
return 0 ;
case hwmon_temp_crit_alarm :
ret = regmap_read ( regmap , LM95245_REG_R_STATUS1 , & regvalh ) ;
if ( ret < 0 )
return ret ;
* val = ! ! ( regvalh & ( channel ? STATUS1_RTCRIT : STATUS1_LOC ) ) ;
return 0 ;
case hwmon_temp_fault :
ret = regmap_read ( regmap , LM95245_REG_R_STATUS1 , & regvalh ) ;
if ( ret < 0 )
return ret ;
* val = ! ! ( regvalh & STATUS1_DIODE_FAULT ) ;
return 0 ;
default :
return - EOPNOTSUPP ;
}
2011-06-28 19:11:23 +04:00
}
2016-07-06 05:10:52 +03:00
static int lm95245_write_temp ( struct device * dev , u32 attr , int channel ,
long val )
2014-02-03 06:29:28 +04:00
{
2016-07-06 05:10:52 +03:00
struct lm95245_data * data = dev_get_drvdata ( dev ) ;
struct regmap * regmap = data - > regmap ;
unsigned int regval ;
int ret , reg ;
switch ( attr ) {
case hwmon_temp_max :
val = clamp_val ( val / 1000 , 0 , 255 ) ;
ret = regmap_write ( regmap , LM95245_REG_RW_REMOTE_OS_LIMIT , val ) ;
return ret ;
case hwmon_temp_crit :
reg = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT ;
val = clamp_val ( val / 1000 , 0 , channel ? 255 : 127 ) ;
ret = regmap_write ( regmap , reg , val ) ;
return ret ;
case hwmon_temp_crit_hyst :
mutex_lock ( & data - > update_lock ) ;
ret = regmap_read ( regmap , LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT ,
& regval ) ;
if ( ret < 0 ) {
mutex_unlock ( & data - > update_lock ) ;
return ret ;
}
/* Clamp to reasonable range to prevent overflow */
val = clamp_val ( val , - 1000000 , 1000000 ) ;
val = regval - val / 1000 ;
val = clamp_val ( val , 0 , 31 ) ;
ret = regmap_write ( regmap , LM95245_REG_RW_COMMON_HYSTERESIS ,
val ) ;
mutex_unlock ( & data - > update_lock ) ;
return ret ;
case hwmon_temp_offset :
val = clamp_val ( val , - 128000 , 127875 ) ;
val = val * 256 / 1000 ;
mutex_lock ( & data - > update_lock ) ;
ret = regmap_write ( regmap , LM95245_REG_RW_REMOTE_OFFL ,
val & 0xe0 ) ;
if ( ret < 0 ) {
mutex_unlock ( & data - > update_lock ) ;
return ret ;
}
ret = regmap_write ( regmap , LM95245_REG_RW_REMOTE_OFFH ,
( val > > 8 ) & 0xff ) ;
mutex_unlock ( & data - > update_lock ) ;
return ret ;
case hwmon_temp_type :
if ( val ! = 1 & & val ! = 2 )
return - EINVAL ;
ret = regmap_update_bits ( regmap , LM95245_REG_RW_CONFIG2 ,
CFG2_REMOTE_TT ,
val = = 1 ? CFG2_REMOTE_TT : 0 ) ;
return ret ;
default :
return - EOPNOTSUPP ;
}
2014-02-03 06:29:28 +04:00
}
2016-07-06 05:10:52 +03:00
static int lm95245_read_chip ( struct device * dev , u32 attr , int channel ,
long * val )
2011-06-28 19:11:23 +04:00
{
2014-01-20 21:17:16 +04:00
struct lm95245_data * data = dev_get_drvdata ( dev ) ;
2011-06-28 19:11:23 +04:00
2016-07-06 05:10:52 +03:00
switch ( attr ) {
case hwmon_chip_update_interval :
* val = data - > interval ;
return 0 ;
default :
return - EOPNOTSUPP ;
}
2011-06-28 19:11:23 +04:00
}
2016-07-06 05:10:52 +03:00
static int lm95245_write_chip ( struct device * dev , u32 attr , int channel ,
long val )
2011-06-28 19:11:23 +04:00
{
2014-01-20 21:17:16 +04:00
struct lm95245_data * data = dev_get_drvdata ( dev ) ;
2016-07-06 05:10:52 +03:00
int ret ;
switch ( attr ) {
case hwmon_chip_update_interval :
mutex_lock ( & data - > update_lock ) ;
ret = lm95245_set_conversion_rate ( data , val ) ;
mutex_unlock ( & data - > update_lock ) ;
return ret ;
default :
return - EOPNOTSUPP ;
}
2011-06-28 19:11:23 +04:00
}
2016-07-06 05:10:52 +03:00
static int lm95245_read ( struct device * dev , enum hwmon_sensor_types type ,
u32 attr , int channel , long * val )
2011-06-28 19:11:23 +04:00
{
2016-07-06 05:10:52 +03:00
switch ( type ) {
case hwmon_chip :
return lm95245_read_chip ( dev , attr , channel , val ) ;
case hwmon_temp :
return lm95245_read_temp ( dev , attr , channel , val ) ;
default :
return - EOPNOTSUPP ;
}
2011-06-28 19:11:23 +04:00
}
2016-07-06 05:10:52 +03:00
static int lm95245_write ( struct device * dev , enum hwmon_sensor_types type ,
u32 attr , int channel , long val )
2011-06-28 19:11:23 +04:00
{
2016-07-06 05:10:52 +03:00
switch ( type ) {
case hwmon_chip :
return lm95245_write_chip ( dev , attr , channel , val ) ;
case hwmon_temp :
return lm95245_write_temp ( dev , attr , channel , val ) ;
default :
return - EOPNOTSUPP ;
}
2011-06-28 19:11:23 +04:00
}
2016-07-06 05:10:52 +03:00
static umode_t lm95245_temp_is_visible ( const void * data , u32 attr , int channel )
2011-06-28 19:11:23 +04:00
{
2016-07-06 05:10:52 +03:00
switch ( attr ) {
case hwmon_temp_input :
case hwmon_temp_max_alarm :
case hwmon_temp_max_hyst :
case hwmon_temp_crit_alarm :
case hwmon_temp_fault :
return S_IRUGO ;
case hwmon_temp_type :
case hwmon_temp_max :
case hwmon_temp_crit :
case hwmon_temp_offset :
return S_IRUGO | S_IWUSR ;
case hwmon_temp_crit_hyst :
return ( channel = = 0 ) ? S_IRUGO | S_IWUSR : S_IRUGO ;
default :
return 0 ;
}
2011-06-28 19:11:23 +04:00
}
2016-07-06 05:10:52 +03:00
static umode_t lm95245_is_visible ( const void * data ,
enum hwmon_sensor_types type ,
u32 attr , int channel )
2011-06-28 19:11:23 +04:00
{
2016-07-06 05:10:52 +03:00
switch ( type ) {
case hwmon_chip :
switch ( attr ) {
case hwmon_chip_update_interval :
return S_IRUGO | S_IWUSR ;
default :
return 0 ;
}
case hwmon_temp :
return lm95245_temp_is_visible ( data , attr , channel ) ;
default :
return 0 ;
}
2011-06-28 19:11:23 +04:00
}
/* Return 0 if detection is successful, -ENODEV otherwise */
static int lm95245_detect ( struct i2c_client * new_client ,
struct i2c_board_info * info )
{
struct i2c_adapter * adapter = new_client - > adapter ;
2014-04-22 19:48:57 +04:00
int address = new_client - > addr ;
const char * name ;
int rev , id ;
2011-06-28 19:11:23 +04:00
if ( ! i2c_check_functionality ( adapter , I2C_FUNC_SMBUS_BYTE_DATA ) )
return - ENODEV ;
2014-04-22 19:48:57 +04:00
id = i2c_smbus_read_byte_data ( new_client , LM95245_REG_R_MAN_ID ) ;
if ( id ! = MANUFACTURER_ID )
2011-06-28 19:11:23 +04:00
return - ENODEV ;
2014-04-22 19:48:57 +04:00
rev = i2c_smbus_read_byte_data ( new_client , LM95245_REG_R_CHIP_ID ) ;
switch ( rev ) {
case LM95235_REVISION :
if ( address ! = 0x18 & & address ! = 0x29 & & address ! = 0x4c )
return - ENODEV ;
name = " lm95235 " ;
break ;
case LM95245_REVISION :
name = " lm95245 " ;
break ;
default :
return - ENODEV ;
}
strlcpy ( info - > type , name , I2C_NAME_SIZE ) ;
2011-06-28 19:11:23 +04:00
return 0 ;
}
2016-07-06 05:10:52 +03:00
static int lm95245_init_client ( struct lm95245_data * data )
2011-06-28 19:11:23 +04:00
{
2016-07-06 05:10:52 +03:00
int ret ;
ret = lm95245_read_conversion_rate ( data ) ;
if ( ret < 0 )
return ret ;
return regmap_update_bits ( data - > regmap , LM95245_REG_RW_CONFIG1 ,
CFG_STOP , 0 ) ;
}
static bool lm95245_is_writeable_reg ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case LM95245_REG_RW_CONFIG1 :
case LM95245_REG_RW_CONVERS_RATE :
case LM95245_REG_W_ONE_SHOT :
case LM95245_REG_RW_CONFIG2 :
case LM95245_REG_RW_REMOTE_OFFH :
case LM95245_REG_RW_REMOTE_OFFL :
case LM95245_REG_RW_REMOTE_OS_LIMIT :
case LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT :
case LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
case LM95245_REG_RW_COMMON_HYSTERESIS :
return true ;
default :
return false ;
}
}
static bool lm95245_is_volatile_reg ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case LM95245_REG_R_STATUS1 :
case LM95245_REG_R_STATUS2 :
case LM95245_REG_R_LOCAL_TEMPH_S :
case LM95245_REG_R_LOCAL_TEMPL_S :
case LM95245_REG_R_REMOTE_TEMPH_S :
case LM95245_REG_R_REMOTE_TEMPL_S :
case LM95245_REG_R_REMOTE_TEMPH_U :
case LM95245_REG_R_REMOTE_TEMPL_U :
return true ;
default :
return false ;
2011-06-28 19:11:23 +04:00
}
}
2016-07-06 05:10:52 +03:00
static const struct regmap_config lm95245_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. writeable_reg = lm95245_is_writeable_reg ,
. volatile_reg = lm95245_is_volatile_reg ,
. cache_type = REGCACHE_RBTREE ,
2018-09-01 19:50:41 +03:00
. use_single_read = true ,
. use_single_write = true ,
2016-07-06 05:10:52 +03:00
} ;
static const u32 lm95245_chip_config [ ] = {
HWMON_C_UPDATE_INTERVAL ,
0
} ;
static const struct hwmon_channel_info lm95245_chip = {
. type = hwmon_chip ,
. config = lm95245_chip_config ,
} ;
static const u32 lm95245_temp_config [ ] = {
HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_CRIT_ALARM ,
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST | HWMON_T_CRIT |
HWMON_T_CRIT_HYST | HWMON_T_FAULT | HWMON_T_MAX_ALARM |
HWMON_T_CRIT_ALARM | HWMON_T_TYPE | HWMON_T_OFFSET ,
0
} ;
static const struct hwmon_channel_info lm95245_temp = {
. type = hwmon_temp ,
. config = lm95245_temp_config ,
} ;
static const struct hwmon_channel_info * lm95245_info [ ] = {
& lm95245_chip ,
& lm95245_temp ,
NULL
} ;
static const struct hwmon_ops lm95245_hwmon_ops = {
. is_visible = lm95245_is_visible ,
. read = lm95245_read ,
. write = lm95245_write ,
} ;
static const struct hwmon_chip_info lm95245_chip_info = {
. ops = & lm95245_hwmon_ops ,
. info = lm95245_info ,
} ;
2014-01-20 21:17:16 +04:00
static int lm95245_probe ( struct i2c_client * client ,
2011-06-28 19:11:23 +04:00
const struct i2c_device_id * id )
{
2014-01-20 21:17:16 +04:00
struct device * dev = & client - > dev ;
2011-06-28 19:11:23 +04:00
struct lm95245_data * data ;
2014-01-20 21:17:16 +04:00
struct device * hwmon_dev ;
2016-07-06 05:10:52 +03:00
int ret ;
2011-06-28 19:11:23 +04:00
2014-01-20 21:17:16 +04:00
data = devm_kzalloc ( dev , sizeof ( struct lm95245_data ) , GFP_KERNEL ) ;
2012-06-02 20:58:12 +04:00
if ( ! data )
return - ENOMEM ;
2011-06-28 19:11:23 +04:00
2016-07-06 05:10:52 +03:00
data - > regmap = devm_regmap_init_i2c ( client , & lm95245_regmap_config ) ;
if ( IS_ERR ( data - > regmap ) )
return PTR_ERR ( data - > regmap ) ;
2011-06-28 19:11:23 +04:00
mutex_init ( & data - > update_lock ) ;
/* Initialize the LM95245 chip */
2016-07-06 05:10:52 +03:00
ret = lm95245_init_client ( data ) ;
if ( ret < 0 )
return ret ;
hwmon_dev = devm_hwmon_device_register_with_info ( dev , client - > name ,
data ,
& lm95245_chip_info ,
NULL ) ;
2014-01-20 21:17:16 +04:00
return PTR_ERR_OR_ZERO ( hwmon_dev ) ;
2011-06-28 19:11:23 +04:00
}
/* Driver data (common to all clients) */
static const struct i2c_device_id lm95245_id [ ] = {
2014-04-22 19:48:57 +04:00
{ " lm95235 " , 0 } ,
{ " lm95245 " , 0 } ,
2011-06-28 19:11:23 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , lm95245_id ) ;
2017-02-24 16:13:05 +03:00
static const struct of_device_id lm95245_of_match [ ] = {
{ . compatible = " national,lm95235 " } ,
{ . compatible = " national,lm95245 " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , lm95245_of_match ) ;
2011-06-28 19:11:23 +04:00
static struct i2c_driver lm95245_driver = {
. class = I2C_CLASS_HWMON ,
. driver = {
2014-04-22 19:48:57 +04:00
. name = " lm95245 " ,
2017-02-24 16:13:05 +03:00
. of_match_table = of_match_ptr ( lm95245_of_match ) ,
2011-06-28 19:11:23 +04:00
} ,
. probe = lm95245_probe ,
. id_table = lm95245_id ,
. detect = lm95245_detect ,
. address_list = normal_i2c ,
} ;
2012-01-20 11:38:18 +04:00
module_i2c_driver ( lm95245_driver ) ;
2011-06-28 19:11:23 +04:00
MODULE_AUTHOR ( " Alexander Stein <alexander.stein@systec-electronic.com> " ) ;
2014-04-22 19:48:57 +04:00
MODULE_DESCRIPTION ( " LM95235/LM95245 sensor driver " ) ;
2011-06-28 19:11:23 +04:00
MODULE_LICENSE ( " GPL " ) ;