2019-05-20 09:19:02 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-16 15:20:36 -07:00
/*
* lm90 . c - Part of lm_sensors , Linux kernel modules for hardware
* monitoring
2014-01-29 20:40:08 +01:00
* Copyright ( C ) 2003 - 2010 Jean Delvare < jdelvare @ suse . de >
2005-04-16 15:20:36 -07:00
*
* Based on the lm83 driver . The LM90 is a sensor chip made by National
* Semiconductor . It reports up to two temperatures ( its own plus up to
* one external one ) with a 0.125 deg resolution ( 1 deg for local
2008-10-17 17:51:10 +02:00
* temperature ) and a 3 - 4 deg accuracy .
2005-04-16 15:20:36 -07:00
*
* This driver also supports the LM89 and LM99 , two other sensor chips
* made by National Semiconductor . Both have an increased remote
* temperature measurement accuracy ( 1 degree ) , and the LM99
* additionally shifts remote temperatures ( measured and limits ) by 16
2008-10-26 17:04:39 +01:00
* degrees , which allows for higher temperatures measurement .
2005-05-03 18:21:25 -06:00
* Note that there is no way to differentiate between both chips .
2008-10-26 17:04:39 +01:00
* When device is auto - detected , the driver will assume an LM99 .
2005-04-16 15:20:36 -07:00
*
* This driver also supports the LM86 , another sensor chip made by
* National Semiconductor . It is exactly similar to the LM90 except it
* has a higher accuracy .
*
* This driver also supports the ADM1032 , a sensor chip made by Analog
* Devices . That chip is similar to the LM90 , with a few differences
2008-10-17 17:51:10 +02:00
* that are not handled by this driver . Among others , it has a higher
* accuracy than the LM90 , much like the LM86 does .
2005-04-16 15:20:36 -07:00
*
* This driver also supports the MAX6657 , MAX6658 and MAX6659 sensor
2008-10-17 17:51:10 +02:00
* chips made by Maxim . These chips are similar to the LM86 .
2005-05-03 18:21:25 -06:00
* Note that there is no easy way to differentiate between the three
2010-10-28 20:31:43 +02:00
* variants . We use the device address to detect MAX6659 , which will result
* in a detection as max6657 if it is on address 0x4c . The extra address
* and features of the MAX6659 are only supported if the chip is configured
* explicitly as max6659 , or if its address is not 0x4c .
* These chips lack the remote temperature offset feature .
2005-04-16 15:20:36 -07:00
*
2021-11-13 08:55:06 -08:00
* This driver also supports the MAX6654 chip made by Maxim . This chip can be
* at 9 different addresses , similar to MAX6680 / MAX6681 . The MAX6654 is similar
* to MAX6657 / MAX6658 / MAX6659 , but does not support critical temperature
* limits . Extended range is available by setting the configuration register
* accordingly , and is done during initialization . Extended precision is only
* available at conversion rates of 1 Hz and slower . Note that extended
* precision is not enabled by default , as this driver initializes all chips
2021-11-12 22:03:31 -08:00
* to 2 Hz by design . The driver also supports MAX6690 , which is practically
* identical to MAX6654 .
2020-05-13 11:42:48 -07:00
*
2009-03-12 13:36:38 +01:00
* This driver also supports the MAX6646 , MAX6647 , MAX6648 , MAX6649 and
* MAX6692 chips made by Maxim . These are again similar to the LM86 ,
* but they use unsigned temperature values and can report temperatures
* from 0 to 145 degrees .
2008-10-17 17:51:11 +02:00
*
2007-06-09 10:11:16 -04:00
* This driver also supports the MAX6680 and MAX6681 , two other sensor
* chips made by Maxim . These are quite similar to the other Maxim
2008-10-17 17:51:10 +02:00
* chips . The MAX6680 and MAX6681 only differ in the pinout so they can
* be treated identically .
2007-06-09 10:11:16 -04:00
*
2010-10-28 20:31:43 +02:00
* This driver also supports the MAX6695 and MAX6696 , two other sensor
* chips made by Maxim . These are also quite similar to other Maxim
* chips , but support three temperature sensors instead of two . MAX6695
* and MAX6696 only differ in the pinout so they can be treated identically .
*
2011-04-29 16:33:35 +02:00
* This driver also supports ADT7461 and ADT7461A from Analog Devices as well as
* NCT1008 from ON Semiconductor . The chips are supported in both compatibility
* and extended mode . They are mostly compatible with LM90 except for a data
* format difference for the temperature value registers .
2005-04-16 15:20:36 -07:00
*
2021-11-06 09:59:26 -07:00
* This driver also supports ADT7481 , ADT7482 , and ADT7483 from Analog Devices
* / ON Semiconductor . The chips are similar to ADT7461 but support two external
* temperature sensors .
*
2011-06-06 10:40:45 +00:00
* This driver also supports the SA56004 from Philips . This device is
* pin - compatible with the LM86 , the ED / EDP parts are also address - compatible .
*
2012-03-23 10:02:18 +01:00
* This driver also supports the G781 from GMT . This device is compatible
* with the ADM1032 .
*
2021-10-18 20:03:32 -07:00
* This driver also supports TMP451 and TMP461 from Texas Instruments .
* Those devices are supported in both compatibility and extended mode .
* They are mostly compatible with ADT7461 except for local temperature
* low byte register and max conversion rate .
2013-11-15 10:40:39 +01:00
*
2005-04-16 15:20:36 -07:00
* Since the LM90 was the first chipset supported by this driver , most
* comments will refer to this chipset , but are actually general and
* concern all supported chipsets , unless mentioned otherwise .
*/
2021-10-30 09:11:20 -07:00
# include <linux/bits.h>
2021-10-30 09:02:56 -07:00
# include <linux/device.h>
# include <linux/err.h>
# include <linux/i2c.h>
2005-04-16 15:20:36 -07:00
# include <linux/init.h>
2021-10-30 09:02:56 -07:00
# include <linux/interrupt.h>
2005-04-16 15:20:36 -07:00
# include <linux/jiffies.h>
2005-07-15 21:39:18 -04:00
# include <linux/hwmon.h>
2021-10-30 09:02:56 -07:00
# include <linux/module.h>
2006-01-18 23:19:26 +01:00
# include <linux/mutex.h>
2017-02-24 10:13:04 -03:00
# include <linux/of_device.h>
2013-11-15 10:40:39 +01:00
# include <linux/regulator/consumer.h>
2021-10-30 09:02:56 -07:00
# include <linux/slab.h>
2022-01-09 14:19:01 -08:00
# include <linux/workqueue.h>
2005-04-16 15:20:36 -07:00
/*
* Addresses to scan
* Address is fully defined internally and cannot be changed except for
2007-06-09 10:11:16 -04:00
* MAX6659 , MAX6680 and MAX6681 .
2011-04-29 16:33:35 +02:00
* LM86 , LM89 , LM90 , LM99 , ADM1032 , ADM1032 - 1 , ADT7461 , ADT7461A , MAX6649 ,
* MAX6657 , MAX6658 , NCT1008 and W83L771 have address 0x4c .
* ADM1032 - 2 , ADT7461 - 2 , ADT7461A - 2 , LM89 - 1 , LM99 - 1 , MAX6646 , and NCT1008D
* have address 0x4d .
2008-10-17 17:51:11 +02:00
* MAX6647 has address 0x4e .
2010-10-28 20:31:43 +02:00
* MAX6659 can have address 0x4c , 0x4d or 0x4e .
2020-05-13 11:42:48 -07:00
* MAX6654 , MAX6680 , and MAX6681 can have address 0x18 , 0x19 , 0x1a , 0x29 ,
* 0x2a , 0x2b , 0x4c , 0x4d or 0x4e .
2011-06-06 10:40:45 +00:00
* SA56004 can have address 0x48 through 0x4F .
2005-04-16 15:20:36 -07:00
*/
2008-02-17 22:28:03 -05:00
static const unsigned short normal_i2c [ ] = {
2011-06-06 10:40:45 +00:00
0x18 , 0x19 , 0x1a , 0x29 , 0x2a , 0x2b , 0x48 , 0x49 , 0x4a , 0x4b , 0x4c ,
0x4d , 0x4e , 0x4f , I2C_CLIENT_END } ;
2005-04-16 15:20:36 -07:00
2021-11-06 09:59:26 -07:00
enum chips { adm1032 , adt7461 , adt7461a , adt7481 , g781 , lm86 , lm90 , lm99 ,
2021-11-05 21:58:51 -07:00
max6646 , max6648 , max6654 , max6657 , max6659 , max6680 , max6696 ,
2021-10-30 09:05:45 -07:00
sa56004 , tmp451 , tmp461 , w83l771 ,
} ;
2005-04-16 15:20:36 -07:00
/*
* The LM90 registers
*/
2021-10-31 02:01:41 -07:00
# define LM90_REG_MAN_ID 0xFE
# define LM90_REG_CHIP_ID 0xFF
# define LM90_REG_CONFIG1 0x03
# define LM90_REG_CONFIG2 0xBF
# define LM90_REG_CONVRATE 0x04
# define LM90_REG_STATUS 0x02
# define LM90_REG_LOCAL_TEMP 0x00
# define LM90_REG_LOCAL_HIGH 0x05
# define LM90_REG_LOCAL_LOW 0x06
# define LM90_REG_LOCAL_CRIT 0x20
# define LM90_REG_REMOTE_TEMPH 0x01
# define LM90_REG_REMOTE_TEMPL 0x10
# define LM90_REG_REMOTE_OFFSH 0x11
# define LM90_REG_REMOTE_OFFSL 0x12
# define LM90_REG_REMOTE_HIGHH 0x07
# define LM90_REG_REMOTE_HIGHL 0x13
# define LM90_REG_REMOTE_LOWH 0x08
# define LM90_REG_REMOTE_LOWL 0x14
# define LM90_REG_REMOTE_CRIT 0x19
# define LM90_REG_TCRIT_HYST 0x21
2005-04-16 15:20:36 -07:00
2020-05-13 11:42:48 -07:00
/* MAX6646/6647/6649/6654/6657/6658/6659/6695/6696 registers */
2008-10-17 17:51:09 +02:00
2021-10-31 02:01:41 -07:00
# define MAX6657_REG_LOCAL_TEMPL 0x11
# define MAX6696_REG_STATUS2 0x12
# define MAX6659_REG_REMOTE_EMERG 0x16
# define MAX6659_REG_LOCAL_EMERG 0x17
2008-10-17 17:51:09 +02:00
2011-06-06 10:40:45 +00:00
/* SA56004 registers */
2021-10-31 02:01:41 -07:00
# define SA56004_REG_LOCAL_TEMPL 0x22
2011-06-06 10:40:45 +00:00
2010-10-28 20:31:44 +02:00
# define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */
2021-10-18 20:03:32 -07:00
/* TMP451/TMP461 registers */
2021-10-31 02:01:41 -07:00
# define TMP451_REG_LOCAL_TEMPL 0x15
2021-10-18 20:03:32 -07:00
# define TMP451_REG_CONALERT 0x22
# define TMP461_REG_CHEN 0x16
# define TMP461_REG_DFC 0x24
2013-11-15 10:40:39 +01:00
2021-11-06 09:59:26 -07:00
/* ADT7481 registers */
# define ADT7481_REG_STATUS2 0x23
# define ADT7481_REG_CONFIG2 0x24
# define ADT7481_REG_MAN_ID 0x3e
# define ADT7481_REG_CHIP_ID 0x3d
2010-10-28 20:31:43 +02:00
/* Device features */
2021-11-22 08:13:58 -08:00
# define LM90_HAVE_EXTENDED_TEMP BIT(0) /* extended temperature support */
2021-10-30 09:11:20 -07:00
# define LM90_HAVE_OFFSET BIT(1) /* temperature offset register */
2021-12-04 07:53:00 -08:00
# define LM90_HAVE_UNSIGNED_TEMP BIT(2) /* temperatures are unsigned */
2021-10-30 09:11:20 -07:00
# define LM90_HAVE_REM_LIMIT_EXT BIT(3) /* extended remote limit */
# define LM90_HAVE_EMERGENCY BIT(4) /* 3rd upper (emergency) limit */
# define LM90_HAVE_EMERGENCY_ALARM BIT(5) /* emergency alarm */
# define LM90_HAVE_TEMP3 BIT(6) /* 3rd temperature sensor */
# define LM90_HAVE_BROKEN_ALERT BIT(7) /* Broken alert */
2021-11-22 08:13:58 -08:00
# define LM90_PAUSE_FOR_CONFIG BIT(8) /* Pause conversion for config */
# define LM90_HAVE_CRIT BIT(9) /* Chip supports CRIT/OVERT register */
# define LM90_HAVE_CRIT_ALRM_SWP BIT(10) /* critical alarm bits swapped */
# define LM90_HAVE_PEC BIT(11) /* Chip supports PEC */
# define LM90_HAVE_PARTIAL_PEC BIT(12) /* Partial PEC support (adm1032)*/
2021-11-17 11:57:57 -08:00
# define LM90_HAVE_ALARMS BIT(13) /* Create 'alarms' attribute */
2021-11-05 21:58:51 -07:00
# define LM90_HAVE_EXT_UNSIGNED BIT(14) /* extended unsigned temperature*/
2021-11-15 17:48:13 -08:00
# define LM90_HAVE_LOW BIT(15) /* low limits */
2021-11-15 18:14:35 -08:00
# define LM90_HAVE_CONVRATE BIT(16) /* conversion rate */
2008-10-17 17:51:10 +02:00
2013-11-15 10:40:38 +01:00
/* LM90 status */
2021-10-30 09:11:20 -07:00
# define LM90_STATUS_LTHRM BIT(0) /* local THERM limit tripped */
# define LM90_STATUS_RTHRM BIT(1) /* remote THERM limit tripped */
# define LM90_STATUS_ROPEN BIT(2) /* remote is an open circuit */
# define LM90_STATUS_RLOW BIT(3) /* remote low temp limit tripped */
# define LM90_STATUS_RHIGH BIT(4) /* remote high temp limit tripped */
# define LM90_STATUS_LLOW BIT(5) /* local low temp limit tripped */
# define LM90_STATUS_LHIGH BIT(6) /* local high temp limit tripped */
# define LM90_STATUS_BUSY BIT(7) /* conversion is ongoing */
2021-11-06 09:59:26 -07:00
/* MAX6695/6696 and ADT7481 2nd status register */
2021-10-30 09:11:20 -07:00
# define MAX6696_STATUS2_R2THRM BIT(1) /* remote2 THERM limit tripped */
# define MAX6696_STATUS2_R2OPEN BIT(2) /* remote2 is an open circuit */
# define MAX6696_STATUS2_R2LOW BIT(3) /* remote2 low temp limit tripped */
# define MAX6696_STATUS2_R2HIGH BIT(4) /* remote2 high temp limit tripped */
# define MAX6696_STATUS2_ROT2 BIT(5) /* remote emergency limit tripped */
# define MAX6696_STATUS2_R2OT2 BIT(6) /* remote2 emergency limit tripped */
# define MAX6696_STATUS2_LOT2 BIT(7) /* local emergency limit tripped */
2013-11-15 10:40:38 +01:00
2005-04-16 15:20:36 -07:00
/*
* Driver data ( common to all clients )
*/
2008-07-16 19:30:15 +02:00
static const struct i2c_device_id lm90_id [ ] = {
{ " adm1032 " , adm1032 } ,
{ " adt7461 " , adt7461 } ,
2021-12-10 21:18:27 -08:00
{ " adt7461a " , adt7461a } ,
2021-11-06 09:59:26 -07:00
{ " adt7481 " , adt7481 } ,
{ " adt7482 " , adt7481 } ,
{ " adt7483a " , adt7481 } ,
2012-03-23 10:02:18 +01:00
{ " g781 " , g781 } ,
2008-07-16 19:30:15 +02:00
{ " lm90 " , lm90 } ,
{ " lm86 " , lm86 } ,
2008-10-26 17:04:39 +01:00
{ " lm89 " , lm86 } ,
{ " lm99 " , lm99 } ,
2008-10-17 17:51:11 +02:00
{ " max6646 " , max6646 } ,
{ " max6647 " , max6646 } ,
2021-11-05 21:58:51 -07:00
{ " max6648 " , max6648 } ,
2008-10-17 17:51:11 +02:00
{ " max6649 " , max6646 } ,
2020-05-13 11:42:48 -07:00
{ " max6654 " , max6654 } ,
2008-07-16 19:30:15 +02:00
{ " max6657 " , max6657 } ,
{ " max6658 " , max6657 } ,
2010-10-28 20:31:43 +02:00
{ " max6659 " , max6659 } ,
2008-07-16 19:30:15 +02:00
{ " max6680 " , max6680 } ,
{ " max6681 " , max6680 } ,
2021-11-12 22:03:31 -08:00
{ " max6690 " , max6654 } ,
2021-11-05 21:58:51 -07:00
{ " max6692 " , max6648 } ,
2010-10-28 20:31:43 +02:00
{ " max6695 " , max6696 } ,
{ " max6696 " , max6696 } ,
2021-12-10 21:18:27 -08:00
{ " nct1008 " , adt7461a } ,
2010-03-05 22:17:13 +01:00
{ " w83l771 " , w83l771 } ,
2011-06-06 10:40:45 +00:00
{ " sa56004 " , sa56004 } ,
2013-11-15 10:40:39 +01:00
{ " tmp451 " , tmp451 } ,
2021-10-18 20:03:32 -07:00
{ " tmp461 " , tmp461 } ,
2008-07-16 19:30:15 +02:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , lm90_id ) ;
2019-04-04 06:21:17 -07:00
static const struct of_device_id __maybe_unused lm90_of_match [ ] = {
2017-02-24 10:13:04 -03:00
{
. compatible = " adi,adm1032 " ,
. data = ( void * ) adm1032
} ,
{
. compatible = " adi,adt7461 " ,
. data = ( void * ) adt7461
} ,
{
. compatible = " adi,adt7461a " ,
2021-12-10 21:18:27 -08:00
. data = ( void * ) adt7461a
2017-02-24 10:13:04 -03:00
} ,
{
. compatible = " gmt,g781 " ,
. data = ( void * ) g781
} ,
{
. compatible = " national,lm90 " ,
. data = ( void * ) lm90
} ,
{
. compatible = " national,lm86 " ,
. data = ( void * ) lm86
} ,
{
. compatible = " national,lm89 " ,
. data = ( void * ) lm86
} ,
{
. compatible = " national,lm99 " ,
. data = ( void * ) lm99
} ,
{
. compatible = " dallas,max6646 " ,
. data = ( void * ) max6646
} ,
{
. compatible = " dallas,max6647 " ,
. data = ( void * ) max6646
} ,
{
. compatible = " dallas,max6649 " ,
. data = ( void * ) max6646
} ,
2020-05-13 11:42:48 -07:00
{
. compatible = " dallas,max6654 " ,
. data = ( void * ) max6654
} ,
2017-02-24 10:13:04 -03:00
{
. compatible = " dallas,max6657 " ,
. data = ( void * ) max6657
} ,
{
. compatible = " dallas,max6658 " ,
. data = ( void * ) max6657
} ,
{
. compatible = " dallas,max6659 " ,
. data = ( void * ) max6659
} ,
{
. compatible = " dallas,max6680 " ,
. data = ( void * ) max6680
} ,
{
. compatible = " dallas,max6681 " ,
. data = ( void * ) max6680
} ,
{
. compatible = " dallas,max6695 " ,
. data = ( void * ) max6696
} ,
{
. compatible = " dallas,max6696 " ,
. data = ( void * ) max6696
} ,
{
. compatible = " onnn,nct1008 " ,
2021-12-10 21:18:27 -08:00
. data = ( void * ) adt7461a
2017-02-24 10:13:04 -03:00
} ,
{
. compatible = " winbond,w83l771 " ,
. data = ( void * ) w83l771
} ,
{
. compatible = " nxp,sa56004 " ,
. data = ( void * ) sa56004
} ,
{
. compatible = " ti,tmp451 " ,
. data = ( void * ) tmp451
} ,
2021-10-18 20:03:32 -07:00
{
. compatible = " ti,tmp461 " ,
. data = ( void * ) tmp461
} ,
2017-02-24 10:13:04 -03:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , lm90_of_match ) ;
2010-10-28 20:31:43 +02:00
/*
* chip type specific parameters
*/
struct lm90_params {
u32 flags ; /* Capabilities */
u16 alert_alarms ; /* Which alarm bits trigger ALERT# */
/* Upper 8 bits for max6695/96 */
2010-10-28 20:31:44 +02:00
u8 max_convrate ; /* Maximum conversion rate register value */
2021-11-02 22:38:59 -07:00
u8 resolution ; /* 16-bit resolution (default 11 bit) */
2021-11-06 09:59:26 -07:00
u8 reg_status2 ; /* 2nd status register (optional) */
2011-07-27 23:22:25 -07:00
u8 reg_local_ext ; /* Extended local temp register (optional) */
2010-10-28 20:31:43 +02:00
} ;
static const struct lm90_params lm90_params [ ] = {
[ adm1032 ] = {
2010-10-28 20:31:44 +02:00
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
2021-10-31 09:34:33 -07:00
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_CRIT
2021-11-15 17:48:13 -08:00
| LM90_HAVE_PARTIAL_PEC | LM90_HAVE_ALARMS
2021-11-15 18:14:35 -08:00
| LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2010-10-28 20:31:43 +02:00
. alert_alarms = 0x7c ,
2010-10-28 20:31:44 +02:00
. max_convrate = 10 ,
2010-10-28 20:31:43 +02:00
} ,
[ adt7461 ] = {
2021-12-04 07:53:00 -08:00
/*
* Standard temperature range is supposed to be unsigned ,
* but that does not match reality . Negative temperatures
* are always reported .
*/
2010-10-28 20:31:44 +02:00
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
2021-11-13 08:55:06 -08:00
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP
2021-11-17 11:57:57 -08:00
| LM90_HAVE_CRIT | LM90_HAVE_PARTIAL_PEC
2021-11-15 18:14:35 -08:00
| LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2010-10-28 20:31:43 +02:00
. alert_alarms = 0x7c ,
2010-10-28 20:31:44 +02:00
. max_convrate = 10 ,
2021-11-02 22:38:59 -07:00
. resolution = 10 ,
2010-10-28 20:31:43 +02:00
} ,
2021-12-10 21:18:27 -08:00
[ adt7461a ] = {
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP
2021-11-15 17:48:13 -08:00
| LM90_HAVE_CRIT | LM90_HAVE_PEC | LM90_HAVE_ALARMS
2021-11-15 18:14:35 -08:00
| LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2021-12-10 21:18:27 -08:00
. alert_alarms = 0x7c ,
. max_convrate = 10 ,
} ,
2021-11-06 09:59:26 -07:00
[ adt7481 ] = {
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP
| LM90_HAVE_UNSIGNED_TEMP | LM90_HAVE_PEC
2021-11-15 18:14:35 -08:00
| LM90_HAVE_TEMP3 | LM90_HAVE_CRIT | LM90_HAVE_LOW
| LM90_HAVE_CONVRATE ,
2021-11-06 09:59:26 -07:00
. alert_alarms = 0x1c7c ,
. max_convrate = 11 ,
. resolution = 10 ,
. reg_status2 = ADT7481_REG_STATUS2 ,
} ,
2012-03-23 10:02:18 +01:00
[ g781 ] = {
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
2021-11-17 11:57:57 -08:00
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_CRIT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2012-03-23 10:02:18 +01:00
. alert_alarms = 0x7c ,
2022-01-06 11:48:52 -08:00
. max_convrate = 7 ,
2012-03-23 10:02:18 +01:00
} ,
2010-10-28 20:31:43 +02:00
[ lm86 ] = {
2021-11-13 08:55:06 -08:00
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_CRIT | LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2010-10-28 20:31:43 +02:00
. alert_alarms = 0x7b ,
2010-10-28 20:31:44 +02:00
. max_convrate = 9 ,
2010-10-28 20:31:43 +02:00
} ,
[ lm90 ] = {
2021-11-13 08:55:06 -08:00
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_CRIT | LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2010-10-28 20:31:43 +02:00
. alert_alarms = 0x7b ,
2010-10-28 20:31:44 +02:00
. max_convrate = 9 ,
2010-10-28 20:31:43 +02:00
} ,
[ lm99 ] = {
2021-11-13 08:55:06 -08:00
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_CRIT | LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2010-10-28 20:31:43 +02:00
. alert_alarms = 0x7b ,
2010-10-28 20:31:44 +02:00
. max_convrate = 9 ,
2010-10-28 20:31:43 +02:00
} ,
[ max6646 ] = {
2021-12-04 07:53:00 -08:00
. flags = LM90_HAVE_CRIT | LM90_HAVE_BROKEN_ALERT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_EXT_UNSIGNED | LM90_HAVE_ALARMS | LM90_HAVE_LOW
| LM90_HAVE_CONVRATE ,
2021-11-05 21:58:51 -07:00
. alert_alarms = 0x7c ,
. max_convrate = 6 ,
. reg_local_ext = MAX6657_REG_LOCAL_TEMPL ,
} ,
[ max6648 ] = {
. flags = LM90_HAVE_UNSIGNED_TEMP | LM90_HAVE_CRIT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_LOW
| LM90_HAVE_CONVRATE ,
2010-10-28 20:31:43 +02:00
. alert_alarms = 0x7c ,
2010-10-28 20:31:44 +02:00
. max_convrate = 6 ,
2021-10-31 02:01:41 -07:00
. reg_local_ext = MAX6657_REG_LOCAL_TEMPL ,
2010-10-28 20:31:43 +02:00
} ,
2020-05-13 11:42:48 -07:00
[ max6654 ] = {
2021-11-15 18:14:35 -08:00
. flags = LM90_HAVE_BROKEN_ALERT | LM90_HAVE_ALARMS | LM90_HAVE_LOW
| LM90_HAVE_CONVRATE ,
2020-05-13 11:42:48 -07:00
. alert_alarms = 0x7c ,
. max_convrate = 7 ,
2021-10-31 02:01:41 -07:00
. reg_local_ext = MAX6657_REG_LOCAL_TEMPL ,
2020-05-13 11:42:48 -07:00
} ,
2010-10-28 20:31:43 +02:00
[ max6657 ] = {
2021-11-17 11:57:57 -08:00
. flags = LM90_PAUSE_FOR_CONFIG | LM90_HAVE_CRIT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2010-10-28 20:31:43 +02:00
. alert_alarms = 0x7c ,
2010-10-28 20:31:44 +02:00
. max_convrate = 8 ,
2021-10-31 02:01:41 -07:00
. reg_local_ext = MAX6657_REG_LOCAL_TEMPL ,
2010-10-28 20:31:43 +02:00
} ,
[ max6659 ] = {
2021-11-17 11:57:57 -08:00
. flags = LM90_HAVE_EMERGENCY | LM90_HAVE_CRIT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2010-10-28 20:31:43 +02:00
. alert_alarms = 0x7c ,
2010-10-28 20:31:44 +02:00
. max_convrate = 8 ,
2021-10-31 02:01:41 -07:00
. reg_local_ext = MAX6657_REG_LOCAL_TEMPL ,
2010-10-28 20:31:43 +02:00
} ,
[ max6680 ] = {
2021-12-04 07:53:00 -08:00
/*
* Apparent temperatures of 128 degrees C or higher are reported
* and treated as negative temperatures ( meaning min_alarm will
* be set ) .
*/
2021-11-26 22:43:39 -08:00
. flags = LM90_HAVE_OFFSET | LM90_HAVE_CRIT
2021-11-17 11:57:57 -08:00
| LM90_HAVE_CRIT_ALRM_SWP | LM90_HAVE_BROKEN_ALERT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2010-10-28 20:31:43 +02:00
. alert_alarms = 0x7c ,
2010-10-28 20:31:44 +02:00
. max_convrate = 7 ,
2010-10-28 20:31:43 +02:00
} ,
[ max6696 ] = {
2011-07-27 23:22:25 -07:00
. flags = LM90_HAVE_EMERGENCY
2021-11-17 11:57:57 -08:00
| LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3 | LM90_HAVE_CRIT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2013-11-15 10:40:38 +01:00
. alert_alarms = 0x1c7c ,
2010-10-28 20:31:44 +02:00
. max_convrate = 6 ,
2021-11-06 09:59:26 -07:00
. reg_status2 = MAX6696_REG_STATUS2 ,
2021-10-31 02:01:41 -07:00
. reg_local_ext = MAX6657_REG_LOCAL_TEMPL ,
2010-10-28 20:31:43 +02:00
} ,
[ w83l771 ] = {
2021-11-17 11:57:57 -08:00
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT | LM90_HAVE_CRIT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2010-10-28 20:31:43 +02:00
. alert_alarms = 0x7c ,
2010-10-28 20:31:44 +02:00
. max_convrate = 8 ,
2010-10-28 20:31:43 +02:00
} ,
2011-06-06 10:40:45 +00:00
[ sa56004 ] = {
2021-12-04 07:53:00 -08:00
/*
* Apparent temperatures of 128 degrees C or higher are reported
* and treated as negative temperatures ( meaning min_alarm will
* be set ) .
*/
2021-11-17 11:57:57 -08:00
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT | LM90_HAVE_CRIT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2011-06-06 10:40:45 +00:00
. alert_alarms = 0x7b ,
. max_convrate = 9 ,
2021-10-31 02:01:41 -07:00
. reg_local_ext = SA56004_REG_LOCAL_TEMPL ,
2011-06-06 10:40:45 +00:00
} ,
2013-11-15 10:40:39 +01:00
[ tmp451 ] = {
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
2021-12-04 07:53:00 -08:00
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP | LM90_HAVE_CRIT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_UNSIGNED_TEMP | LM90_HAVE_ALARMS | LM90_HAVE_LOW
| LM90_HAVE_CONVRATE ,
2013-11-15 10:40:39 +01:00
. alert_alarms = 0x7c ,
. max_convrate = 9 ,
2021-11-02 22:38:59 -07:00
. resolution = 12 ,
2021-10-31 02:01:41 -07:00
. reg_local_ext = TMP451_REG_LOCAL_TEMPL ,
2016-06-18 19:56:08 -07:00
} ,
2021-10-18 20:03:32 -07:00
[ tmp461 ] = {
. flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
2021-11-17 11:57:57 -08:00
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP | LM90_HAVE_CRIT
2021-11-15 18:14:35 -08:00
| LM90_HAVE_ALARMS | LM90_HAVE_LOW | LM90_HAVE_CONVRATE ,
2021-10-18 20:03:32 -07:00
. alert_alarms = 0x7c ,
. max_convrate = 9 ,
2021-11-02 22:38:59 -07:00
. resolution = 12 ,
2021-10-31 02:01:41 -07:00
. reg_local_ext = TMP451_REG_LOCAL_TEMPL ,
2021-10-18 20:03:32 -07:00
} ,
2010-10-28 20:31:43 +02:00
} ;
2013-11-15 10:40:39 +01:00
/*
2021-11-02 22:38:59 -07:00
* temperature register index
2013-11-15 10:40:39 +01:00
*/
2021-11-02 22:38:59 -07:00
enum lm90_temp_reg_index {
2013-11-15 10:40:39 +01:00
LOCAL_LOW = 0 ,
LOCAL_HIGH ,
LOCAL_CRIT ,
REMOTE_CRIT ,
LOCAL_EMERG , /* max6659 and max6695/96 */
REMOTE_EMERG , /* max6659 and max6695/96 */
REMOTE2_CRIT , /* max6695/96 only */
REMOTE2_EMERG , /* max6695/96 only */
2021-11-02 22:38:59 -07:00
REMOTE_TEMP ,
2013-11-15 10:40:39 +01:00
REMOTE_LOW ,
REMOTE_HIGH ,
REMOTE_OFFSET , /* except max6646, max6657/58/59, and max6695/96 */
LOCAL_TEMP ,
REMOTE2_TEMP , /* max6695/96 only */
REMOTE2_LOW , /* max6695/96 only */
REMOTE2_HIGH , /* max6695/96 only */
2021-11-02 22:38:59 -07:00
TEMP_REG_NUM
2013-11-15 10:40:39 +01:00
} ;
2005-04-16 15:20:36 -07:00
/*
* Client data ( each client gets its own )
*/
struct lm90_data {
2014-04-04 18:01:35 +02:00
struct i2c_client * client ;
2021-06-19 00:54:53 +03:00
struct device * hwmon_dev ;
2021-11-17 11:57:57 -08:00
u32 chip_config [ 2 ] ;
2016-06-18 19:56:08 -07:00
u32 channel_config [ 4 ] ;
2021-11-17 11:57:57 -08:00
struct hwmon_channel_info chip_info ;
2016-06-18 19:56:08 -07:00
struct hwmon_channel_info temp_info ;
const struct hwmon_channel_info * info [ 3 ] ;
struct hwmon_chip_info chip ;
2006-01-18 23:19:26 +01:00
struct mutex update_lock ;
2022-01-09 14:19:01 -08:00
struct delayed_work alert_work ;
2016-06-18 15:39:08 -07:00
bool valid ; /* true if register values are valid */
2022-01-09 14:19:01 -08:00
bool alarms_valid ; /* true if status register values are valid */
2005-04-16 15:20:36 -07:00
unsigned long last_updated ; /* in jiffies */
2022-01-09 14:19:01 -08:00
unsigned long alarms_updated ; /* in jiffies */
2005-04-16 15:20:36 -07:00
int kind ;
2010-10-28 20:31:43 +02:00
u32 flags ;
2005-04-16 15:20:36 -07:00
2016-06-05 09:35:43 +02:00
unsigned int update_interval ; /* in milliseconds */
2010-10-28 20:31:44 +02:00
2019-06-30 15:14:19 -07:00
u8 config ; /* Current configuration register value */
2010-03-05 22:17:14 +01:00
u8 config_orig ; /* Original configuration register value */
2010-10-28 20:31:44 +02:00
u8 convrate_orig ; /* Original conversion rate register value */
2021-11-02 22:38:59 -07:00
u8 resolution ; /* temperature resolution in bit */
2010-10-28 20:31:43 +02:00
u16 alert_alarms ; /* Which alarm bits trigger ALERT# */
/* Upper 8 bits for max6695/96 */
2010-10-28 20:31:44 +02:00
u8 max_convrate ; /* Maximum conversion rate */
2021-11-06 09:59:26 -07:00
u8 reg_status2 ; /* 2nd status register (optional) */
2011-06-06 10:40:45 +00:00
u8 reg_local_ext ; /* local extension register offset */
2010-03-05 22:17:14 +01:00
2005-04-16 15:20:36 -07:00
/* registers values */
2021-11-02 22:38:59 -07:00
u16 temp [ TEMP_REG_NUM ] ;
2005-04-16 15:20:36 -07:00
u8 temp_hyst ;
2022-01-09 14:19:01 -08:00
u16 reported_alarms ; /* alarms reported as sysfs/udev events */
u16 current_alarms ; /* current alarms, reported by chip */
u16 alarms ; /* alarms not yet reported to user */
2005-04-16 15:20:36 -07:00
} ;
2010-10-28 20:31:43 +02:00
/*
* Support functions
*/
/*
2021-10-31 09:34:33 -07:00
* If the chip supports PEC but not on write byte transactions , we need
2010-10-28 20:31:43 +02:00
* to explicitly ask for a transaction without PEC .
*/
2021-10-31 09:34:33 -07:00
static inline s32 lm90_write_no_pec ( struct i2c_client * client , u8 value )
2010-10-28 20:31:43 +02:00
{
return i2c_smbus_xfer ( client - > adapter , client - > addr ,
client - > flags & ~ I2C_CLIENT_PEC ,
I2C_SMBUS_WRITE , value , I2C_SMBUS_BYTE , NULL ) ;
}
/*
* It is assumed that client - > update_lock is held ( unless we are in
2021-10-31 09:34:33 -07:00
* detection or initialization steps ) . This matters when PEC is enabled
* for chips with partial PEC support , because we don ' t want the address
* pointer to change between the write byte and the read byte transactions .
2010-10-28 20:31:43 +02:00
*/
2016-06-13 06:57:37 -07:00
static int lm90_read_reg ( struct i2c_client * client , u8 reg )
2010-10-28 20:31:43 +02:00
{
2021-10-31 09:34:33 -07:00
struct lm90_data * data = i2c_get_clientdata ( client ) ;
bool partial_pec = ( client - > flags & I2C_CLIENT_PEC ) & &
( data - > flags & LM90_HAVE_PARTIAL_PEC ) ;
2010-10-28 20:31:43 +02:00
int err ;
2021-10-31 09:34:33 -07:00
if ( partial_pec ) {
err = lm90_write_no_pec ( client , reg ) ;
if ( err )
return err ;
return i2c_smbus_read_byte ( client ) ;
}
return i2c_smbus_read_byte_data ( client , reg ) ;
2010-10-28 20:31:43 +02:00
}
2021-10-31 02:01:41 -07:00
/*
* Return register write address
*
* The write address for registers 0x03 . . 0x08 is the read address plus 6.
* For other registers the write address matches the read address .
*/
static u8 lm90_write_reg_addr ( u8 reg )
{
if ( reg > = LM90_REG_CONFIG1 & & reg < = LM90_REG_REMOTE_LOWH )
return reg + 6 ;
return reg ;
}
/*
* Write into LM90 register .
* Convert register address to write address if needed , then execute the
* operation .
*/
static int lm90_write_reg ( struct i2c_client * client , u8 reg , u8 val )
{
return i2c_smbus_write_byte_data ( client , lm90_write_reg_addr ( reg ) , val ) ;
}
2021-11-05 16:04:52 -07:00
static int lm90_read16 ( struct i2c_client * client , u8 regh , u8 regl ,
bool is_volatile )
2010-10-28 20:31:43 +02:00
{
2016-06-13 06:57:37 -07:00
int oldh , newh , l ;
2010-10-28 20:31:43 +02:00
2016-06-13 06:57:37 -07:00
oldh = lm90_read_reg ( client , regh ) ;
if ( oldh < 0 )
return oldh ;
l = lm90_read_reg ( client , regl ) ;
if ( l < 0 )
return l ;
2021-11-05 16:04:52 -07:00
if ( ! is_volatile )
return ( oldh < < 8 ) | l ;
/*
* For volatile registers we have to use a trick .
* We have to read two registers to have the sensor temperature ,
* but we have to beware a conversion could occur between the
* readings . The datasheet says we should either use
* the one - shot conversion register , which we don ' t want to do
* ( disables hardware monitoring ) or monitor the busy bit , which is
* impossible ( we can ' t read the values and monitor that bit at the
* exact same time ) . So the solution used here is to read the high
* the high byte again . If the new high byte matches the old one ,
* then we have a valid reading . Otherwise we have to read the low
* byte again , and now we believe we have a correct reading .
*/
2016-06-13 06:57:37 -07:00
newh = lm90_read_reg ( client , regh ) ;
if ( newh < 0 )
return newh ;
2010-10-28 20:31:43 +02:00
if ( oldh ! = newh ) {
2016-06-13 06:57:37 -07:00
l = lm90_read_reg ( client , regl ) ;
if ( l < 0 )
return l ;
2010-10-28 20:31:43 +02:00
}
2016-06-13 06:57:37 -07:00
return ( newh < < 8 ) | l ;
2010-10-28 20:31:43 +02:00
}
2019-06-30 15:40:34 -07:00
static int lm90_update_confreg ( struct lm90_data * data , u8 config )
{
if ( data - > config ! = config ) {
int err ;
2021-10-31 02:01:41 -07:00
err = lm90_write_reg ( data - > client , LM90_REG_CONFIG1 , config ) ;
2019-06-30 15:40:34 -07:00
if ( err )
return err ;
data - > config = config ;
}
return 0 ;
}
2010-10-28 20:31:43 +02:00
/*
* client - > update_lock must be held when calling this function ( unless we are
* in detection or initialization steps ) , and while a remote channel other
* than channel 0 is selected . Also , calling code must make sure to re - select
* external channel 0 before releasing the lock . This is necessary because
* various registers have different meanings as a result of selecting a
* non - default remote channel .
*/
2021-11-06 09:59:26 -07:00
static int lm90_select_remote_channel ( struct lm90_data * data , bool second )
2010-10-28 20:31:43 +02:00
{
2021-11-06 09:59:26 -07:00
u8 config = data - > config & ~ 0x08 ;
2019-06-30 15:40:34 -07:00
2021-11-06 09:59:26 -07:00
if ( second )
config | = 0x08 ;
2019-06-30 15:14:19 -07:00
2021-11-06 09:59:26 -07:00
return lm90_update_confreg ( data , config ) ;
2010-10-28 20:31:43 +02:00
}
2019-06-30 15:40:34 -07:00
static int lm90_write_convrate ( struct lm90_data * data , int val )
2019-06-28 19:06:36 +00:00
{
2019-06-30 15:14:19 -07:00
u8 config = data - > config ;
2019-06-28 19:06:36 +00:00
int err ;
/* Save config and pause conversion */
if ( data - > flags & LM90_PAUSE_FOR_CONFIG ) {
2019-06-30 15:40:34 -07:00
err = lm90_update_confreg ( data , config | 0x40 ) ;
if ( err < 0 )
return err ;
2019-06-28 19:06:36 +00:00
}
/* Set conv rate */
2021-10-31 02:01:41 -07:00
err = lm90_write_reg ( data - > client , LM90_REG_CONVRATE , val ) ;
2019-06-28 19:06:36 +00:00
/* Revert change to config */
2019-06-30 15:40:34 -07:00
lm90_update_confreg ( data , config ) ;
2019-06-28 19:06:36 +00:00
return err ;
}
2010-10-28 20:31:44 +02:00
/*
* Set conversion rate .
* client - > update_lock must be held when calling this function ( unless we are
* in detection or initialization steps ) .
*/
2016-06-18 19:56:08 -07:00
static int lm90_set_convrate ( struct i2c_client * client , struct lm90_data * data ,
unsigned int interval )
2010-10-28 20:31:44 +02:00
{
unsigned int update_interval ;
2016-06-18 19:56:08 -07:00
int i , err ;
2010-10-28 20:31:44 +02:00
/* Shift calculations to avoid rounding errors */
interval < < = 6 ;
/* find the nearest update rate */
for ( i = 0 , update_interval = LM90_MAX_CONVRATE_MS < < 6 ;
i < data - > max_convrate ; i + + , update_interval > > = 1 )
if ( interval > = update_interval * 3 / 4 )
break ;
2019-06-30 15:40:34 -07:00
err = lm90_write_convrate ( data , i ) ;
2010-10-28 20:31:44 +02:00
data - > update_interval = DIV_ROUND_CLOSEST ( update_interval , 64 ) ;
2016-06-18 19:56:08 -07:00
return err ;
2010-10-28 20:31:44 +02:00
}
2016-06-13 19:26:45 -07:00
static int lm90_update_limits ( struct device * dev )
{
struct lm90_data * data = dev_get_drvdata ( dev ) ;
struct i2c_client * client = data - > client ;
int val ;
2021-11-13 08:55:06 -08:00
if ( data - > flags & LM90_HAVE_CRIT ) {
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_LOCAL_CRIT ) ;
2021-11-13 08:55:06 -08:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ LOCAL_CRIT ] = val < < 8 ;
2016-06-13 19:26:45 -07:00
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_REMOTE_CRIT ) ;
2021-11-13 08:55:06 -08:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE_CRIT ] = val < < 8 ;
2016-06-13 19:26:45 -07:00
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_TCRIT_HYST ) ;
2021-11-13 08:55:06 -08:00
if ( val < 0 )
return val ;
data - > temp_hyst = val ;
}
2016-06-13 19:26:45 -07:00
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_REMOTE_LOWH ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE_LOW ] = val < < 8 ;
2016-06-13 19:26:45 -07:00
if ( data - > flags & LM90_HAVE_REM_LIMIT_EXT ) {
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_REMOTE_LOWL ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE_LOW ] | = val ;
2016-06-13 19:26:45 -07:00
}
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_REMOTE_HIGHH ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE_HIGH ] = val < < 8 ;
2016-06-13 19:26:45 -07:00
if ( data - > flags & LM90_HAVE_REM_LIMIT_EXT ) {
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_REMOTE_HIGHL ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE_HIGH ] | = val ;
2016-06-13 19:26:45 -07:00
}
if ( data - > flags & LM90_HAVE_OFFSET ) {
2021-10-31 02:01:41 -07:00
val = lm90_read16 ( client , LM90_REG_REMOTE_OFFSH ,
2021-11-05 16:04:52 -07:00
LM90_REG_REMOTE_OFFSL , false ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE_OFFSET ] = val ;
2016-06-13 19:26:45 -07:00
}
if ( data - > flags & LM90_HAVE_EMERGENCY ) {
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , MAX6659_REG_LOCAL_EMERG ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ LOCAL_EMERG ] = val < < 8 ;
2016-06-13 19:26:45 -07:00
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , MAX6659_REG_REMOTE_EMERG ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE_EMERG ] = val < < 8 ;
2016-06-13 19:26:45 -07:00
}
2021-11-06 09:59:26 -07:00
if ( data - > flags & LM90_HAVE_TEMP3 ) {
val = lm90_select_remote_channel ( data , true ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_REMOTE_CRIT ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE2_CRIT ] = val < < 8 ;
2016-06-13 19:26:45 -07:00
2021-11-06 09:59:26 -07:00
if ( data - > flags & LM90_HAVE_EMERGENCY ) {
val = lm90_read_reg ( client , MAX6659_REG_REMOTE_EMERG ) ;
if ( val < 0 )
return val ;
data - > temp [ REMOTE2_EMERG ] = val < < 8 ;
}
2016-06-13 19:26:45 -07:00
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_REMOTE_LOWH ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE2_LOW ] = val < < 8 ;
2016-06-13 19:26:45 -07:00
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_REMOTE_HIGHH ) ;
2016-06-13 19:26:45 -07:00
if ( val < 0 )
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE2_HIGH ] = val < < 8 ;
2016-06-13 19:26:45 -07:00
2021-11-06 09:59:26 -07:00
lm90_select_remote_channel ( data , false ) ;
2016-06-13 19:26:45 -07:00
}
return 0 ;
}
2022-01-09 14:19:01 -08:00
static void lm90_report_alarms ( struct device * dev , struct lm90_data * data )
{
u16 cleared_alarms = data - > reported_alarms & ~ data - > current_alarms ;
u16 new_alarms = data - > current_alarms & ~ data - > reported_alarms ;
struct device * hwmon_dev = data - > hwmon_dev ;
int st , st2 ;
if ( ! cleared_alarms & & ! new_alarms )
return ;
st = new_alarms & 0xff ;
st2 = new_alarms > > 8 ;
if ( ( st & ( LM90_STATUS_LLOW | LM90_STATUS_LHIGH | LM90_STATUS_LTHRM ) ) | |
( st2 & MAX6696_STATUS2_LOT2 ) )
dev_dbg ( dev , " temp%d out of range, please check! \n " , 1 ) ;
if ( ( st & ( LM90_STATUS_RLOW | LM90_STATUS_RHIGH | LM90_STATUS_RTHRM ) ) | |
( st2 & MAX6696_STATUS2_ROT2 ) )
dev_dbg ( dev , " temp%d out of range, please check! \n " , 2 ) ;
if ( st & LM90_STATUS_ROPEN )
dev_dbg ( dev , " temp%d diode open, please check! \n " , 2 ) ;
if ( st2 & ( MAX6696_STATUS2_R2LOW | MAX6696_STATUS2_R2HIGH |
MAX6696_STATUS2_R2THRM | MAX6696_STATUS2_R2OT2 ) )
dev_dbg ( dev , " temp%d out of range, please check! \n " , 3 ) ;
if ( st2 & MAX6696_STATUS2_R2OPEN )
dev_dbg ( dev , " temp%d diode open, please check! \n " , 3 ) ;
st | = cleared_alarms & 0xff ;
st2 | = cleared_alarms > > 8 ;
if ( st & LM90_STATUS_LLOW )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_min_alarm , 0 ) ;
if ( st & LM90_STATUS_RLOW )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_min_alarm , 1 ) ;
if ( st2 & MAX6696_STATUS2_R2LOW )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_min_alarm , 2 ) ;
if ( st & LM90_STATUS_LHIGH )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_max_alarm , 0 ) ;
if ( st & LM90_STATUS_RHIGH )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_max_alarm , 1 ) ;
if ( st2 & MAX6696_STATUS2_R2HIGH )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_max_alarm , 2 ) ;
if ( st & LM90_STATUS_LTHRM )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_crit_alarm , 0 ) ;
if ( st & LM90_STATUS_RTHRM )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_crit_alarm , 1 ) ;
if ( st2 & MAX6696_STATUS2_R2THRM )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_crit_alarm , 2 ) ;
if ( st2 & MAX6696_STATUS2_LOT2 )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_emergency_alarm , 0 ) ;
if ( st2 & MAX6696_STATUS2_ROT2 )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_emergency_alarm , 1 ) ;
if ( st2 & MAX6696_STATUS2_R2OT2 )
hwmon_notify_event ( hwmon_dev , hwmon_temp , hwmon_temp_emergency_alarm , 2 ) ;
data - > reported_alarms = data - > current_alarms ;
}
static int lm90_update_alarms_locked ( struct lm90_data * data , bool force )
{
if ( force | | ! data - > alarms_valid | |
time_after ( jiffies , data - > alarms_updated + msecs_to_jiffies ( data - > update_interval ) ) ) {
struct i2c_client * client = data - > client ;
bool check_enable ;
u16 alarms ;
int val ;
data - > alarms_valid = false ;
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_STATUS ) ;
2022-01-09 14:19:01 -08:00
if ( val < 0 )
return val ;
alarms = val & ~ LM90_STATUS_BUSY ;
2021-11-06 09:59:26 -07:00
if ( data - > reg_status2 ) {
val = lm90_read_reg ( client , data - > reg_status2 ) ;
2022-01-09 14:19:01 -08:00
if ( val < 0 )
return val ;
alarms | = val < < 8 ;
}
/*
* If the update is forced ( called from interrupt or alert
* handler ) and alarm data is valid , the alarms may have been
* updated after the last update interval , and the status
* register may still be cleared . Only add additional alarms
* in this case . Alarms will be cleared later if appropriate .
*/
if ( force & & data - > alarms_valid )
data - > current_alarms | = alarms ;
else
data - > current_alarms = alarms ;
data - > alarms | = alarms ;
check_enable = ( client - > irq | | ! ( data - > config_orig & 0x80 ) ) & &
( data - > config & 0x80 ) ;
if ( force | | check_enable )
lm90_report_alarms ( & client - > dev , data ) ;
/*
* Re - enable ALERT # output if it was originally enabled , relevant
* alarms are all clear , and alerts are currently disabled .
* Otherwise ( re ) schedule worker if needed .
*/
if ( check_enable ) {
if ( ! ( data - > current_alarms & data - > alert_alarms ) ) {
dev_dbg ( & client - > dev , " Re-enabling ALERT# \n " ) ;
lm90_update_confreg ( data , data - > config & ~ 0x80 ) ;
/*
* We may have been called from the update handler .
* If so , the worker , if scheduled , is no longer
* needed . Cancel it . Don ' t synchronize because
* it may already be running .
*/
cancel_delayed_work ( & data - > alert_work ) ;
} else {
schedule_delayed_work ( & data - > alert_work ,
max_t ( int , HZ , msecs_to_jiffies ( data - > update_interval ) ) ) ;
}
}
data - > alarms_updated = jiffies ;
data - > alarms_valid = true ;
}
return 0 ;
}
static int lm90_update_alarms ( struct lm90_data * data , bool force )
{
int err ;
mutex_lock ( & data - > update_lock ) ;
err = lm90_update_alarms_locked ( data , force ) ;
mutex_unlock ( & data - > update_lock ) ;
return err ;
}
static void lm90_alert_work ( struct work_struct * __work )
{
struct delayed_work * delayed_work = container_of ( __work , struct delayed_work , work ) ;
struct lm90_data * data = container_of ( delayed_work , struct lm90_data , alert_work ) ;
/* Nothing to do if alerts are enabled */
if ( ! ( data - > config & 0x80 ) )
return ;
lm90_update_alarms ( data , true ) ;
}
2016-06-18 19:56:08 -07:00
static int lm90_update_device ( struct device * dev )
2010-10-28 20:31:43 +02:00
{
2014-04-04 18:01:35 +02:00
struct lm90_data * data = dev_get_drvdata ( dev ) ;
struct i2c_client * client = data - > client ;
2010-10-28 20:31:44 +02:00
unsigned long next_update ;
2016-06-18 19:56:08 -07:00
int val ;
2010-10-28 20:31:43 +02:00
2016-06-13 19:26:45 -07:00
if ( ! data - > valid ) {
val = lm90_update_limits ( dev ) ;
if ( val < 0 )
2016-06-18 19:56:08 -07:00
return val ;
2016-06-13 19:26:45 -07:00
}
2013-07-08 14:18:24 +02:00
next_update = data - > last_updated +
msecs_to_jiffies ( data - > update_interval ) ;
2010-10-28 20:31:44 +02:00
if ( time_after ( jiffies , next_update ) | | ! data - > valid ) {
2010-10-28 20:31:43 +02:00
dev_dbg ( & client - > dev , " Updating lm90 data. \n " ) ;
2016-06-13 19:26:45 -07:00
2016-06-18 15:39:08 -07:00
data - > valid = false ;
2016-06-13 19:26:45 -07:00
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_LOCAL_LOW ) ;
2016-06-13 06:57:37 -07:00
if ( val < 0 )
2016-06-18 19:56:08 -07:00
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ LOCAL_LOW ] = val < < 8 ;
2016-06-13 06:57:37 -07:00
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_LOCAL_HIGH ) ;
2016-06-13 06:57:37 -07:00
if ( val < 0 )
2016-06-18 19:56:08 -07:00
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ LOCAL_HIGH ] = val < < 8 ;
2016-06-13 06:57:37 -07:00
2011-07-27 23:22:25 -07:00
if ( data - > reg_local_ext ) {
2021-10-31 02:01:41 -07:00
val = lm90_read16 ( client , LM90_REG_LOCAL_TEMP ,
2021-11-05 16:04:52 -07:00
data - > reg_local_ext , true ) ;
2016-06-13 06:57:37 -07:00
if ( val < 0 )
2016-06-18 19:56:08 -07:00
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ LOCAL_TEMP ] = val ;
2010-10-28 20:31:43 +02:00
} else {
2021-10-31 02:01:41 -07:00
val = lm90_read_reg ( client , LM90_REG_LOCAL_TEMP ) ;
2016-06-13 06:57:37 -07:00
if ( val < 0 )
2016-06-18 19:56:08 -07:00
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ LOCAL_TEMP ] = val < < 8 ;
2010-10-28 20:31:43 +02:00
}
2021-10-31 02:01:41 -07:00
val = lm90_read16 ( client , LM90_REG_REMOTE_TEMPH ,
2021-11-05 16:04:52 -07:00
LM90_REG_REMOTE_TEMPL , true ) ;
2016-06-13 06:57:37 -07:00
if ( val < 0 )
2016-06-18 19:56:08 -07:00
return val ;
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE_TEMP ] = val ;
2016-06-13 06:57:37 -07:00
2021-11-06 09:59:26 -07:00
if ( data - > flags & LM90_HAVE_TEMP3 ) {
val = lm90_select_remote_channel ( data , true ) ;
2016-06-13 06:57:37 -07:00
if ( val < 0 )
2016-06-18 19:56:08 -07:00
return val ;
2016-06-13 06:57:37 -07:00
2021-10-31 02:01:41 -07:00
val = lm90_read16 ( client , LM90_REG_REMOTE_TEMPH ,
2021-11-05 16:04:52 -07:00
LM90_REG_REMOTE_TEMPL , true ) ;
2016-06-18 19:56:08 -07:00
if ( val < 0 ) {
2021-11-06 09:59:26 -07:00
lm90_select_remote_channel ( data , false ) ;
2016-06-18 19:56:08 -07:00
return val ;
}
2021-11-02 22:38:59 -07:00
data - > temp [ REMOTE2_TEMP ] = val ;
2016-06-13 06:57:37 -07:00
2021-11-06 09:59:26 -07:00
lm90_select_remote_channel ( data , false ) ;
2010-10-28 20:31:43 +02:00
}
2022-01-09 14:19:01 -08:00
val = lm90_update_alarms_locked ( data , false ) ;
if ( val < 0 )
return val ;
2010-10-28 20:31:43 +02:00
data - > last_updated = jiffies ;
2016-06-18 15:39:08 -07:00
data - > valid = true ;
2010-10-28 20:31:43 +02:00
}
2016-06-18 19:56:08 -07:00
return 0 ;
2010-10-28 20:31:43 +02:00
}
2021-10-31 09:34:33 -07:00
/* pec used for devices with PEC support */
2016-12-22 13:05:22 +01:00
static ssize_t pec_show ( struct device * dev , struct device_attribute * dummy ,
2016-06-18 19:56:08 -07:00
char * buf )
2005-06-05 21:27:28 +02:00
{
2016-06-18 19:56:08 -07:00
struct i2c_client * client = to_i2c_client ( dev ) ;
2008-10-26 17:04:39 +01:00
2016-06-18 19:56:08 -07:00
return sprintf ( buf , " %d \n " , ! ! ( client - > flags & I2C_CLIENT_PEC ) ) ;
2005-06-05 21:27:28 +02:00
}
2016-12-22 13:05:22 +01:00
static ssize_t pec_store ( struct device * dev , struct device_attribute * dummy ,
const char * buf , size_t count )
2005-06-05 21:27:28 +02:00
{
2016-06-18 19:56:08 -07:00
struct i2c_client * client = to_i2c_client ( dev ) ;
2010-10-28 20:31:42 +02:00
long val ;
int err ;
2012-01-04 20:58:52 +01:00
err = kstrtol ( buf , 10 , & val ) ;
2010-10-28 20:31:42 +02:00
if ( err < 0 )
return err ;
2005-06-05 21:27:28 +02:00
2016-06-18 19:56:08 -07:00
switch ( val ) {
case 0 :
client - > flags & = ~ I2C_CLIENT_PEC ;
break ;
case 1 :
client - > flags | = I2C_CLIENT_PEC ;
break ;
default :
return - EINVAL ;
}
2010-10-28 20:31:43 +02:00
2005-06-05 21:27:28 +02:00
return count ;
2005-04-16 15:20:36 -07:00
}
2005-06-05 21:27:28 +02:00
2016-12-22 13:05:22 +01:00
static DEVICE_ATTR_RW ( pec ) ;
2016-06-18 19:56:08 -07:00
2021-11-02 22:38:59 -07:00
static int lm90_temp_get_resolution ( struct lm90_data * data , int index )
2005-06-05 21:27:28 +02:00
{
2021-11-02 22:38:59 -07:00
switch ( index ) {
case REMOTE_TEMP :
case REMOTE_OFFSET :
case REMOTE2_TEMP :
return data - > resolution ;
case LOCAL_TEMP :
if ( data - > reg_local_ext )
return data - > resolution ;
return 8 ;
case REMOTE_LOW :
case REMOTE_HIGH :
case REMOTE2_LOW :
case REMOTE2_HIGH :
if ( data - > flags & LM90_HAVE_REM_LIMIT_EXT )
return data - > resolution ;
return 8 ;
default :
return 8 ;
}
2005-04-16 15:20:36 -07:00
}
2005-06-05 21:27:28 +02:00
2021-11-02 22:38:59 -07:00
static int lm90_temp_from_reg ( u32 flags , u16 regval , u8 resolution )
2005-06-05 21:27:28 +02:00
{
2021-11-02 22:38:59 -07:00
int val ;
2008-10-26 17:04:39 +01:00
2021-11-22 08:13:58 -08:00
if ( flags & LM90_HAVE_EXTENDED_TEMP )
2021-11-02 22:38:59 -07:00
val = regval - 0x4000 ;
2021-11-05 21:58:51 -07:00
else if ( flags & ( LM90_HAVE_UNSIGNED_TEMP | LM90_HAVE_EXT_UNSIGNED ) )
2021-11-02 22:38:59 -07:00
val = regval ;
2010-10-28 20:31:43 +02:00
else
2021-11-02 22:38:59 -07:00
val = ( s16 ) regval ;
2008-10-17 17:51:09 +02:00
2021-11-02 22:38:59 -07:00
return ( ( val > > ( 16 - resolution ) ) * 1000 ) > > ( resolution - 8 ) ;
2005-04-16 15:20:36 -07:00
}
2005-06-05 21:27:28 +02:00
2021-11-02 22:38:59 -07:00
static int lm90_get_temp ( struct lm90_data * data , int index , int channel )
2005-06-05 21:27:28 +02:00
{
2021-11-02 22:38:59 -07:00
int temp = lm90_temp_from_reg ( data - > flags , data - > temp [ index ] ,
lm90_temp_get_resolution ( data , index ) ) ;
2008-10-17 17:51:10 +02:00
2021-11-02 22:38:59 -07:00
/* +16 degrees offset for remote temperature on LM99 */
if ( data - > kind = = lm99 & & channel )
2008-10-26 17:04:39 +01:00
temp + = 16000 ;
2016-06-18 19:56:08 -07:00
return temp ;
2005-04-16 15:20:36 -07:00
}
2021-11-02 22:38:59 -07:00
static u16 lm90_temp_to_reg ( u32 flags , long val , u8 resolution )
{
int fraction = resolution > 8 ?
1000 - DIV_ROUND_CLOSEST ( 1000 , BIT ( resolution - 8 ) ) : 0 ;
2021-11-22 08:13:58 -08:00
if ( flags & LM90_HAVE_EXTENDED_TEMP ) {
2021-11-02 22:38:59 -07:00
val = clamp_val ( val , - 64000 , 191000 + fraction ) ;
val + = 64000 ;
2021-11-05 21:58:51 -07:00
} else if ( flags & LM90_HAVE_EXT_UNSIGNED ) {
val = clamp_val ( val , 0 , 255000 + fraction ) ;
2021-11-02 22:38:59 -07:00
} else if ( flags & LM90_HAVE_UNSIGNED_TEMP ) {
val = clamp_val ( val , 0 , 127000 + fraction ) ;
} else {
val = clamp_val ( val , - 128000 , 127000 + fraction ) ;
}
return DIV_ROUND_CLOSEST ( val < < ( resolution - 8 ) , 1000 ) < < ( 16 - resolution ) ;
}
static int lm90_set_temp ( struct lm90_data * data , int index , int channel , long val )
2005-04-16 15:20:36 -07:00
{
2021-11-02 22:38:59 -07:00
static const u8 regs [ ] = {
[ LOCAL_LOW ] = LM90_REG_LOCAL_LOW ,
[ LOCAL_HIGH ] = LM90_REG_LOCAL_HIGH ,
[ LOCAL_CRIT ] = LM90_REG_LOCAL_CRIT ,
[ REMOTE_CRIT ] = LM90_REG_REMOTE_CRIT ,
[ LOCAL_EMERG ] = MAX6659_REG_LOCAL_EMERG ,
[ REMOTE_EMERG ] = MAX6659_REG_REMOTE_EMERG ,
[ REMOTE2_CRIT ] = LM90_REG_REMOTE_CRIT ,
[ REMOTE2_EMERG ] = MAX6659_REG_REMOTE_EMERG ,
[ REMOTE_LOW ] = LM90_REG_REMOTE_LOWH ,
[ REMOTE_HIGH ] = LM90_REG_REMOTE_HIGHH ,
[ REMOTE2_LOW ] = LM90_REG_REMOTE_LOWH ,
[ REMOTE2_HIGH ] = LM90_REG_REMOTE_HIGHH ,
2016-06-18 19:56:08 -07:00
} ;
2014-04-04 18:01:35 +02:00
struct i2c_client * client = data - > client ;
2021-11-02 22:38:59 -07:00
u8 regh = regs [ index ] ;
u8 regl = 0 ;
2010-10-28 20:31:42 +02:00
int err ;
2005-04-16 15:20:36 -07:00
2021-11-02 22:38:59 -07:00
if ( channel & & ( data - > flags & LM90_HAVE_REM_LIMIT_EXT ) ) {
if ( index = = REMOTE_LOW | | index = = REMOTE2_LOW )
regl = LM90_REG_REMOTE_LOWL ;
else if ( index = = REMOTE_HIGH | | index = = REMOTE2_HIGH )
regl = LM90_REG_REMOTE_HIGHL ;
}
/* +16 degrees offset for remote temperature on LM99 */
if ( data - > kind = = lm99 & & channel ) {
2021-06-23 07:22:30 +03:00
/* prevent integer underflow */
val = max ( val , - 128000l ) ;
2016-06-18 19:56:08 -07:00
val - = 16000 ;
2021-06-23 07:22:30 +03:00
}
2010-10-28 20:31:42 +02:00
2021-11-02 22:38:59 -07:00
data - > temp [ index ] = lm90_temp_to_reg ( data - > flags , val ,
lm90_temp_get_resolution ( data , index ) ) ;
if ( channel > 1 )
2021-11-06 09:59:26 -07:00
lm90_select_remote_channel ( data , true ) ;
2008-10-26 17:04:39 +01:00
2021-11-02 22:38:59 -07:00
err = lm90_write_reg ( client , regh , data - > temp [ index ] > > 8 ) ;
if ( err < 0 )
goto deselect ;
if ( regl )
err = lm90_write_reg ( client , regl , data - > temp [ index ] & 0xff ) ;
deselect :
if ( channel > 1 )
2021-11-06 09:59:26 -07:00
lm90_select_remote_channel ( data , false ) ;
2016-06-13 06:57:37 -07:00
2016-06-18 19:56:08 -07:00
return err ;
2005-04-16 15:20:36 -07:00
}
2021-11-02 22:38:59 -07:00
static int lm90_get_temphyst ( struct lm90_data * data , int index , int channel )
2006-09-24 20:52:15 +02:00
{
2021-11-02 22:38:59 -07:00
int temp = lm90_get_temp ( data , index , channel ) ;
2006-09-24 20:52:15 +02:00
2021-11-02 22:38:59 -07:00
return temp - data - > temp_hyst * 1000 ;
2010-10-28 20:31:44 +02:00
}
2016-06-18 19:56:08 -07:00
static int lm90_set_temphyst ( struct lm90_data * data , long val )
2010-10-28 20:31:44 +02:00
{
2021-11-02 22:38:59 -07:00
int temp = lm90_get_temp ( data , LOCAL_CRIT , 0 ) ;
2010-10-28 20:31:44 +02:00
2021-11-17 09:51:47 -08:00
/* prevent integer overflow/underflow */
val = clamp_val ( val , - 128000l , 255000l ) ;
2021-11-02 22:38:59 -07:00
data - > temp_hyst = clamp_val ( DIV_ROUND_CLOSEST ( temp - val , 1000 ) , 0 , 31 ) ;
2021-06-23 07:22:30 +03:00
2021-11-02 22:38:59 -07:00
return lm90_write_reg ( data - > client , LM90_REG_TCRIT_HYST , data - > temp_hyst ) ;
2010-10-28 20:31:44 +02:00
}
2016-06-18 19:56:08 -07:00
static const u8 lm90_temp_index [ 3 ] = {
LOCAL_TEMP , REMOTE_TEMP , REMOTE2_TEMP
2006-09-24 21:16:40 +02:00
} ;
2016-06-18 19:56:08 -07:00
static const u8 lm90_temp_min_index [ 3 ] = {
LOCAL_LOW , REMOTE_LOW , REMOTE2_LOW
2006-09-24 21:16:40 +02:00
} ;
2016-06-18 19:56:08 -07:00
static const u8 lm90_temp_max_index [ 3 ] = {
LOCAL_HIGH , REMOTE_HIGH , REMOTE2_HIGH
2014-04-04 18:01:34 +02:00
} ;
2016-06-18 19:56:08 -07:00
static const u8 lm90_temp_crit_index [ 3 ] = {
LOCAL_CRIT , REMOTE_CRIT , REMOTE2_CRIT
2014-04-04 18:01:34 +02:00
} ;
2016-06-18 19:56:08 -07:00
static const u8 lm90_temp_emerg_index [ 3 ] = {
LOCAL_EMERG , REMOTE_EMERG , REMOTE2_EMERG
2010-10-28 20:31:43 +02:00
} ;
2021-11-29 12:17:41 -08:00
static const u16 lm90_min_alarm_bits [ 3 ] = { BIT ( 5 ) , BIT ( 3 ) , BIT ( 11 ) } ;
static const u16 lm90_max_alarm_bits [ 3 ] = { BIT ( 6 ) , BIT ( 4 ) , BIT ( 12 ) } ;
static const u16 lm90_crit_alarm_bits [ 3 ] = { BIT ( 0 ) , BIT ( 1 ) , BIT ( 9 ) } ;
static const u16 lm90_crit_alarm_bits_swapped [ 3 ] = { BIT ( 1 ) , BIT ( 0 ) , BIT ( 9 ) } ;
static const u16 lm90_emergency_alarm_bits [ 3 ] = { BIT ( 15 ) , BIT ( 13 ) , BIT ( 14 ) } ;
static const u16 lm90_fault_bits [ 3 ] = { BIT ( 0 ) , BIT ( 2 ) , BIT ( 10 ) } ;
2010-10-28 20:31:43 +02:00
2016-06-18 19:56:08 -07:00
static int lm90_temp_read ( struct device * dev , u32 attr , int channel , long * val )
{
struct lm90_data * data = dev_get_drvdata ( dev ) ;
2021-11-29 12:17:41 -08:00
int err ;
u16 bit ;
2010-10-28 20:31:43 +02:00
2016-06-18 19:56:08 -07:00
mutex_lock ( & data - > update_lock ) ;
err = lm90_update_device ( dev ) ;
mutex_unlock ( & data - > update_lock ) ;
if ( err )
return err ;
2010-10-28 20:31:43 +02:00
2016-06-18 19:56:08 -07:00
switch ( attr ) {
case hwmon_temp_input :
2021-11-02 22:38:59 -07:00
* val = lm90_get_temp ( data , lm90_temp_index [ channel ] , channel ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_min_alarm :
case hwmon_temp_max_alarm :
case hwmon_temp_crit_alarm :
case hwmon_temp_emergency_alarm :
case hwmon_temp_fault :
2022-01-09 14:19:01 -08:00
switch ( attr ) {
case hwmon_temp_min_alarm :
2021-11-29 12:17:41 -08:00
bit = lm90_min_alarm_bits [ channel ] ;
2022-01-09 14:19:01 -08:00
break ;
case hwmon_temp_max_alarm :
2021-11-29 12:17:41 -08:00
bit = lm90_max_alarm_bits [ channel ] ;
2022-01-09 14:19:01 -08:00
break ;
case hwmon_temp_crit_alarm :
if ( data - > flags & LM90_HAVE_CRIT_ALRM_SWP )
2021-11-29 12:17:41 -08:00
bit = lm90_crit_alarm_bits_swapped [ channel ] ;
2022-01-09 14:19:01 -08:00
else
2021-11-29 12:17:41 -08:00
bit = lm90_crit_alarm_bits [ channel ] ;
2022-01-09 14:19:01 -08:00
break ;
case hwmon_temp_emergency_alarm :
2021-11-29 12:17:41 -08:00
bit = lm90_emergency_alarm_bits [ channel ] ;
2022-01-09 14:19:01 -08:00
break ;
case hwmon_temp_fault :
2021-11-29 12:17:41 -08:00
bit = lm90_fault_bits [ channel ] ;
2022-01-09 14:19:01 -08:00
break ;
}
* val = ! ! ( data - > alarms & bit ) ;
data - > alarms & = ~ bit ;
data - > alarms | = data - > current_alarms ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_min :
2021-11-02 22:38:59 -07:00
* val = lm90_get_temp ( data , lm90_temp_min_index [ channel ] , channel ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_max :
2021-11-02 22:38:59 -07:00
* val = lm90_get_temp ( data , lm90_temp_max_index [ channel ] , channel ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_crit :
2021-11-02 22:38:59 -07:00
* val = lm90_get_temp ( data , lm90_temp_crit_index [ channel ] , channel ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_crit_hyst :
2021-11-02 22:38:59 -07:00
* val = lm90_get_temphyst ( data , lm90_temp_crit_index [ channel ] , channel ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_emergency :
2021-11-02 22:38:59 -07:00
* val = lm90_get_temp ( data , lm90_temp_emerg_index [ channel ] , channel ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_emergency_hyst :
2021-11-02 22:38:59 -07:00
* val = lm90_get_temphyst ( data , lm90_temp_emerg_index [ channel ] , channel ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_offset :
2021-11-02 22:38:59 -07:00
* val = lm90_temp_from_reg ( 0 , data - > temp [ REMOTE_OFFSET ] ,
lm90_temp_get_resolution ( data , REMOTE_OFFSET ) ) ;
2016-06-18 19:56:08 -07:00
break ;
default :
return - EOPNOTSUPP ;
}
return 0 ;
}
2010-10-28 20:31:43 +02:00
2016-06-18 19:56:08 -07:00
static int lm90_temp_write ( struct device * dev , u32 attr , int channel , long val )
{
struct lm90_data * data = dev_get_drvdata ( dev ) ;
int err ;
2010-10-28 20:31:43 +02:00
2016-06-18 19:56:08 -07:00
mutex_lock ( & data - > update_lock ) ;
2010-10-28 20:31:43 +02:00
2016-06-18 19:56:08 -07:00
err = lm90_update_device ( dev ) ;
if ( err )
goto error ;
switch ( attr ) {
case hwmon_temp_min :
2021-11-02 22:38:59 -07:00
err = lm90_set_temp ( data , lm90_temp_min_index [ channel ] ,
channel , val ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_max :
2021-11-02 22:38:59 -07:00
err = lm90_set_temp ( data , lm90_temp_max_index [ channel ] ,
channel , val ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_crit :
2021-11-02 22:38:59 -07:00
err = lm90_set_temp ( data , lm90_temp_crit_index [ channel ] ,
channel , val ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_crit_hyst :
err = lm90_set_temphyst ( data , val ) ;
break ;
case hwmon_temp_emergency :
2021-11-02 22:38:59 -07:00
err = lm90_set_temp ( data , lm90_temp_emerg_index [ channel ] ,
channel , val ) ;
2016-06-18 19:56:08 -07:00
break ;
case hwmon_temp_offset :
2021-11-02 22:38:59 -07:00
val = lm90_temp_to_reg ( 0 , val ,
lm90_temp_get_resolution ( data , REMOTE_OFFSET ) ) ;
err = i2c_smbus_write_byte_data ( data - > client ,
LM90_REG_REMOTE_OFFSH ,
val > > 8 ) ;
if ( err )
break ;
err = i2c_smbus_write_byte_data ( data - > client ,
LM90_REG_REMOTE_OFFSL ,
val & 0xff ) ;
if ( err )
break ;
data - > temp [ REMOTE_OFFSET ] = val ;
2016-06-18 19:56:08 -07:00
break ;
default :
err = - EOPNOTSUPP ;
break ;
}
error :
mutex_unlock ( & data - > update_lock ) ;
return err ;
}
static umode_t lm90_temp_is_visible ( const void * data , u32 attr , int channel )
2005-10-26 21:39:40 +02:00
{
2016-06-18 19:56:08 -07:00
switch ( attr ) {
case hwmon_temp_input :
case hwmon_temp_min_alarm :
case hwmon_temp_max_alarm :
case hwmon_temp_crit_alarm :
case hwmon_temp_emergency_alarm :
case hwmon_temp_emergency_hyst :
case hwmon_temp_fault :
2018-12-10 14:02:12 -08:00
return 0444 ;
2016-06-18 19:56:08 -07:00
case hwmon_temp_min :
case hwmon_temp_max :
case hwmon_temp_crit :
case hwmon_temp_emergency :
case hwmon_temp_offset :
2018-12-10 14:02:12 -08:00
return 0644 ;
2016-06-18 19:56:08 -07:00
case hwmon_temp_crit_hyst :
if ( channel = = 0 )
2018-12-10 14:02:12 -08:00
return 0644 ;
return 0444 ;
2016-06-18 19:56:08 -07:00
default :
return 0 ;
}
2005-10-26 21:39:40 +02:00
}
2016-06-18 19:56:08 -07:00
static int lm90_chip_read ( struct device * dev , u32 attr , int channel , long * val )
2005-10-26 21:39:40 +02:00
{
2016-06-18 19:56:08 -07:00
struct lm90_data * data = dev_get_drvdata ( dev ) ;
2010-10-28 20:31:42 +02:00
int err ;
2016-06-18 19:56:08 -07:00
mutex_lock ( & data - > update_lock ) ;
err = lm90_update_device ( dev ) ;
mutex_unlock ( & data - > update_lock ) ;
if ( err )
2010-10-28 20:31:42 +02:00
return err ;
2005-10-26 21:39:40 +02:00
2016-06-18 19:56:08 -07:00
switch ( attr ) {
case hwmon_chip_update_interval :
* val = data - > update_interval ;
2005-10-26 21:39:40 +02:00
break ;
2016-06-18 19:56:08 -07:00
case hwmon_chip_alarms :
* val = data - > alarms ;
2005-10-26 21:39:40 +02:00
break ;
default :
2016-06-18 19:56:08 -07:00
return - EOPNOTSUPP ;
2005-10-26 21:39:40 +02:00
}
2016-06-18 19:56:08 -07:00
return 0 ;
2005-10-26 21:39:40 +02:00
}
2016-06-18 19:56:08 -07:00
static int lm90_chip_write ( struct device * dev , u32 attr , int channel , long val )
{
struct lm90_data * data = dev_get_drvdata ( dev ) ;
struct i2c_client * client = data - > client ;
int err ;
2005-10-26 21:39:40 +02:00
2016-06-18 19:56:08 -07:00
mutex_lock ( & data - > update_lock ) ;
err = lm90_update_device ( dev ) ;
if ( err )
goto error ;
switch ( attr ) {
case hwmon_chip_update_interval :
err = lm90_set_convrate ( client , data ,
clamp_val ( val , 0 , 100000 ) ) ;
break ;
default :
err = - EOPNOTSUPP ;
break ;
}
error :
mutex_unlock ( & data - > update_lock ) ;
return err ;
}
static umode_t lm90_chip_is_visible ( const void * data , u32 attr , int channel )
{
switch ( attr ) {
case hwmon_chip_update_interval :
2018-12-10 14:02:12 -08:00
return 0644 ;
2016-06-18 19:56:08 -07:00
case hwmon_chip_alarms :
2018-12-10 14:02:12 -08:00
return 0444 ;
2016-06-18 19:56:08 -07:00
default :
return 0 ;
}
}
static int lm90_read ( struct device * dev , enum hwmon_sensor_types type ,
u32 attr , int channel , long * val )
{
switch ( type ) {
case hwmon_chip :
return lm90_chip_read ( dev , attr , channel , val ) ;
case hwmon_temp :
return lm90_temp_read ( dev , attr , channel , val ) ;
default :
return - EOPNOTSUPP ;
}
}
static int lm90_write ( struct device * dev , enum hwmon_sensor_types type ,
u32 attr , int channel , long val )
{
switch ( type ) {
case hwmon_chip :
return lm90_chip_write ( dev , attr , channel , val ) ;
case hwmon_temp :
return lm90_temp_write ( dev , attr , channel , val ) ;
default :
return - EOPNOTSUPP ;
}
}
static umode_t lm90_is_visible ( const void * data , enum hwmon_sensor_types type ,
u32 attr , int channel )
{
switch ( type ) {
case hwmon_chip :
return lm90_chip_is_visible ( data , attr , channel ) ;
case hwmon_temp :
return lm90_temp_is_visible ( data , attr , channel ) ;
default :
return 0 ;
}
}
2005-04-16 15:20:36 -07:00
2021-11-09 20:38:22 -08:00
/*
* Per - manufacturer chip detect functions .
* Functions are expected to return a pointer to the chip name or NULL
* if detection was not successful .
*/
static const char * lm90_detect_national ( struct i2c_client * client , int chip_id ,
int config1 , int convrate )
2005-10-26 21:37:52 +02:00
{
2021-11-09 20:38:22 -08:00
int config2 = i2c_smbus_read_byte_data ( client , LM90_REG_CONFIG2 ) ;
2011-11-04 12:00:47 +01:00
int address = client - > addr ;
2010-10-28 20:31:43 +02:00
const char * name = NULL ;
2005-10-26 21:37:52 +02:00
2021-11-09 20:38:22 -08:00
if ( config2 < 0 )
return NULL ;
2005-04-16 15:20:36 -07:00
2021-11-09 20:38:22 -08:00
if ( ( config1 & 0x2a ) | | ( config2 & 0xf8 ) | | convrate > 0x09 )
return NULL ;
2009-12-09 20:35:53 +01:00
2021-11-09 20:38:22 -08:00
if ( address ! = 0x4c & & address ! = 0x4d )
return NULL ;
switch ( chip_id & 0xf0 ) {
case 0x10 : /* LM86 */
if ( address = = 0x4c )
name = " lm86 " ;
break ;
case 0x20 : /* LM90 */
if ( address = = 0x4c )
name = " lm90 " ;
break ;
case 0x30 : /* LM89/LM99 */
name = " lm99 " ; /* detect LM89 as LM99 */
break ;
default :
break ;
2021-11-06 10:02:44 -07:00
}
2009-12-09 20:35:53 +01:00
2021-11-09 20:38:22 -08:00
return name ;
}
static const char * lm90_detect_analog ( struct i2c_client * client , int chip_id ,
int config1 , int convrate )
{
2021-11-06 09:59:26 -07:00
int config2 = i2c_smbus_read_byte_data ( client , ADT7481_REG_CONFIG2 ) ;
int man_id2 = i2c_smbus_read_byte_data ( client , ADT7481_REG_MAN_ID ) ;
int chip_id2 = i2c_smbus_read_byte_data ( client , ADT7481_REG_CHIP_ID ) ;
2021-11-09 20:38:22 -08:00
int address = client - > addr ;
const char * name = NULL ;
2021-11-06 09:59:26 -07:00
if ( config2 < 0 | | man_id2 < 0 | | chip_id2 < 0 )
return NULL ;
2021-11-09 20:38:22 -08:00
switch ( chip_id ) {
case 0x40 . . . 0x4f : /* ADM1032 */
2021-12-10 19:35:20 -08:00
if ( man_id2 = = 0x00 & & chip_id2 = = 0x00 & &
( address = = 0x4c | | address = = 0x4d ) & & ! ( config1 & 0x3f ) & &
2021-11-09 20:38:22 -08:00
convrate < = 0x0a )
2009-12-09 20:35:53 +01:00
name = " adm1032 " ;
2021-11-09 20:38:22 -08:00
break ;
case 0x51 : /* ADT7461 */
2021-12-10 19:35:20 -08:00
if ( man_id2 = = 0x00 & & chip_id2 = = 0x00 & &
( address = = 0x4c | | address = = 0x4d ) & & ! ( config1 & 0x1b ) & &
2021-11-09 20:38:22 -08:00
convrate < = 0x0a )
2009-12-09 20:35:53 +01:00
name = " adt7461 " ;
2021-11-09 20:38:22 -08:00
break ;
2021-12-20 17:02:36 -08:00
case 0x54 : /* NCT1008 */
2021-12-10 19:35:20 -08:00
if ( man_id2 = = 0x41 & & chip_id2 = = 0x61 & &
( address = = 0x4c | | address = = 0x4d ) & & ! ( config1 & 0x1b ) & &
2021-12-20 17:02:36 -08:00
convrate < = 0x0a )
name = " nct1008 " ;
break ;
case 0x57 : /* ADT7461A, NCT1008 (datasheet rev. 3) */
2021-12-10 19:35:20 -08:00
if ( man_id2 = = 0x41 & & chip_id2 = = 0x61 & &
( address = = 0x4c | | address = = 0x4d ) & & ! ( config1 & 0x1b ) & &
2021-11-09 20:38:22 -08:00
convrate < = 0x0a )
2011-04-29 16:33:35 +02:00
name = " adt7461a " ;
2021-11-09 20:38:22 -08:00
break ;
2021-11-06 09:59:26 -07:00
case 0x62 : /* ADT7481, undocumented */
if ( man_id2 = = 0x41 & & chip_id2 = = 0x81 & &
( address = = 0x4b | | address = = 0x4c ) & & ! ( config1 & 0x10 ) & &
! ( config2 & 0x7f ) & & ( convrate & 0x0f ) < = 0x0b ) {
name = " adt7481 " ;
}
break ;
case 0x65 : /* ADT7482, datasheet */
case 0x75 : /* ADT7482, real chip */
if ( man_id2 = = 0x41 & & chip_id2 = = 0x82 & &
address = = 0x4c & & ! ( config1 & 0x10 ) & & ! ( config2 & 0x7f ) & &
convrate < = 0x0a )
name = " adt7482 " ;
break ;
case 0x94 : /* ADT7483 */
if ( man_id2 = = 0x41 & & chip_id2 = = 0x83 & &
( ( address > = 0x18 & & address < = 0x1a ) | |
( address > = 0x29 & & address < = 0x2b ) | |
( address > = 0x4c & & address < = 0x4e ) ) & &
! ( config1 & 0x10 ) & & ! ( config2 & 0x7f ) & & convrate < = 0x0a )
name = " adt7483a " ;
break ;
2021-11-09 20:38:22 -08:00
default :
break ;
}
2010-10-28 20:31:43 +02:00
2021-11-09 20:38:22 -08:00
return name ;
}
static const char * lm90_detect_maxim ( struct i2c_client * client , int chip_id ,
int config1 , int convrate )
{
int man_id , emerg , emerg2 , status2 ;
int address = client - > addr ;
const char * name = NULL ;
if ( ( address > = 0x48 & & address < = 0x4b ) | | address = = 0x4f )
return NULL ;
switch ( chip_id ) {
case 0x01 :
2010-10-28 20:31:43 +02:00
/*
2021-10-31 02:01:41 -07:00
* We read MAX6659_REG_REMOTE_EMERG twice , and re - read
* LM90_REG_MAN_ID in between . If MAX6659_REG_REMOTE_EMERG
2010-10-28 20:31:43 +02:00
* exists , both readings will reflect the same value . Otherwise ,
* the readings will be different .
*/
2011-11-04 12:00:47 +01:00
emerg = i2c_smbus_read_byte_data ( client ,
2021-10-31 02:01:41 -07:00
MAX6659_REG_REMOTE_EMERG ) ;
2011-11-04 12:00:47 +01:00
man_id = i2c_smbus_read_byte_data ( client ,
2021-10-31 02:01:41 -07:00
LM90_REG_MAN_ID ) ;
2011-11-04 12:00:47 +01:00
emerg2 = i2c_smbus_read_byte_data ( client ,
2021-10-31 02:01:41 -07:00
MAX6659_REG_REMOTE_EMERG ) ;
2011-11-04 12:00:47 +01:00
status2 = i2c_smbus_read_byte_data ( client ,
2021-10-31 02:01:41 -07:00
MAX6696_REG_STATUS2 ) ;
2011-11-04 12:00:47 +01:00
if ( emerg < 0 | | man_id < 0 | | emerg2 < 0 | | status2 < 0 )
2021-11-09 20:38:22 -08:00
return NULL ;
2010-10-28 20:31:43 +02:00
/*
* Even though MAX6695 and MAX6696 do not have a chip ID
* register , reading it returns 0x01 . Bit 4 of the config1
* register is unused and should return zero when read . Bit 0 of
* the status2 register is unused and should return zero when
* read .
*
* MAX6695 and MAX6696 have an additional set of temperature
* limit registers . We can detect those chips by checking if
* one of those registers exists .
*/
2021-11-09 20:38:22 -08:00
if ( ! ( config1 & 0x10 ) & & ! ( status2 & 0x01 ) & & emerg = = emerg2 & &
convrate < = 0x07 )
2010-10-28 20:31:43 +02:00
name = " max6696 " ;
2009-12-09 20:35:53 +01:00
/*
* The chip_id register of the MAX6680 and MAX6681 holds the
* revision of the chip . The lowest bit of the config1 register
* is unused and should return zero when read , so should the
* second to last bit of config1 ( software reset ) .
*/
2021-11-09 20:38:22 -08:00
else if ( ! ( config1 & 0x03 ) & & convrate < = 0x07 )
2009-12-09 20:35:53 +01:00
name = " max6680 " ;
2021-11-09 20:38:22 -08:00
break ;
case 0x08 :
2020-05-13 11:42:48 -07:00
/*
* The chip_id of the MAX6654 holds the revision of the chip .
* The lowest 3 bits of the config1 register are unused and
* should return zero when read .
*/
2021-11-09 20:38:22 -08:00
if ( ! ( config1 & 0x07 ) & & convrate < = 0x07 )
2020-05-13 11:42:48 -07:00
name = " max6654 " ;
2021-11-09 20:38:22 -08:00
break ;
2021-11-12 22:03:31 -08:00
case 0x09 :
/*
* The chip_id of the MAX6690 holds the revision of the chip .
* The lowest 3 bits of the config1 register are unused and
* should return zero when read .
* Note that MAX6654 and MAX6690 are practically the same chips .
* The only diference is the rated accuracy . Rev . 1 of the
* MAX6690 datasheet lists a chip ID of 0x08 , and a chip labeled
* MAX6654 was observed to have a chip ID of 0x09 .
*/
if ( ! ( config1 & 0x07 ) & & convrate < = 0x07 )
name = " max6690 " ;
break ;
2021-11-09 20:38:22 -08:00
case 0x4d :
/*
* The MAX6657 , MAX6658 and MAX6659 do NOT have a chip_id
* register . Reading from that address will return the last
* read value , which in our case is those of the man_id
* register , or 0x4d . Likewise , the config1 register seems to
* lack a low nibble , so the value will be those of the previous
* read , so in our case again those of the man_id register .
* MAX6659 has a third set of upper temperature limit registers .
* Those registers also return values on MAX6657 and MAX6658 ,
* thus the only way to detect MAX6659 is by its address .
* For this reason it will be mis - detected as MAX6657 if its
* address is 0x4c .
*/
if ( ( address = = 0x4c | | address = = 0x4d | | address = = 0x4e ) & &
( config1 & 0x1f ) = = 0x0d & & convrate < = 0x09 ) {
if ( address = = 0x4c )
name = " max6657 " ;
else
name = " max6659 " ;
2005-04-16 15:20:36 -07:00
}
2021-11-09 20:38:22 -08:00
break ;
case 0x59 :
/*
* The chip_id register of the MAX6646 / 6647 / 6649 holds the
* revision of the chip . The lowest 6 bits of the config1
* register are unused and should return zero when read .
2021-11-05 21:58:51 -07:00
* The I2C address of MAX6648 / 6692 is fixed at 0x4c .
* MAX6646 is at address 0x4d , MAX6647 is at address 0x4e ,
* and MAX6649 is at address 0x4c . A slight difference between
* the two sets of chips is that the remote temperature register
* reports different values if the DXP pin is open or shorted .
* We can use that information to help distinguish between the
* chips . MAX6648 will be mis - detected as MAX6649 if the remote
* diode is connected , but there isn ' t really anything we can
* do about that .
2021-11-09 20:38:22 -08:00
*/
if ( ! ( config1 & 0x3f ) & & convrate < = 0x07 ) {
2021-11-05 21:58:51 -07:00
int temp ;
2021-11-09 20:38:22 -08:00
switch ( address ) {
case 0x4c :
2021-11-05 21:58:51 -07:00
/*
* MAX6649 reports an external temperature
* value of 0xff if DXP is open or shorted .
* MAX6648 reports 0x80 in that case .
*/
temp = i2c_smbus_read_byte_data ( client ,
LM90_REG_REMOTE_TEMPH ) ;
if ( temp = = 0x80 )
name = " max6648 " ;
else
name = " max6649 " ;
2021-11-09 20:38:22 -08:00
break ;
case 0x4d :
name = " max6646 " ;
break ;
case 0x4e :
name = " max6647 " ;
break ;
default :
break ;
2010-10-28 20:31:44 +02:00
}
2010-03-05 22:17:13 +01:00
}
2021-11-09 20:38:22 -08:00
break ;
default :
break ;
}
return name ;
}
static const char * lm90_detect_nuvoton ( struct i2c_client * client , int chip_id ,
int config1 , int convrate )
{
int config2 = i2c_smbus_read_byte_data ( client , LM90_REG_CONFIG2 ) ;
int address = client - > addr ;
const char * name = NULL ;
if ( config2 < 0 )
return ERR_PTR ( - ENODEV ) ;
if ( address = = 0x4c & & ! ( config1 & 0x2a ) & & ! ( config2 & 0xf8 ) ) {
if ( chip_id = = 0x01 & & convrate < = 0x09 ) {
/* W83L771W/G */
name = " w83l771 " ;
} else if ( ( chip_id & 0xfe ) = = 0x10 & & convrate < = 0x08 ) {
/* W83L771AWG/ASG */
name = " w83l771 " ;
2011-06-06 10:40:45 +00:00
}
2021-11-09 20:38:22 -08:00
}
return name ;
}
static const char * lm90_detect_nxp ( struct i2c_client * client , int chip_id ,
int config1 , int convrate )
{
int config2 = i2c_smbus_read_byte_data ( client , LM90_REG_CONFIG2 ) ;
int address = client - > addr ;
const char * name = NULL ;
if ( config2 < 0 )
return NULL ;
if ( address > = 0x48 & & address < = 0x4f & & chip_id = = 0x00 & &
! ( config1 & 0x2a ) & & ! ( config2 & 0xfe ) & & convrate < = 0x09 )
name = " sa56004 " ;
return name ;
}
static const char * lm90_detect_gmt ( struct i2c_client * client , int chip_id ,
int config1 , int convrate )
{
int address = client - > addr ;
2021-12-02 16:19:27 -08:00
/*
* According to the datasheet , G781 is supposed to be at I2C Address
* 0x4c and have a chip ID of 0x01 . G781 - 1 is supposed to be at I2C
* address 0x4d and have a chip ID of 0x03 . However , when support
* for G781 was added , chips at 0x4c and 0x4d were found to have a
* chip ID of 0x01 . A G781 - 1 at I2C address 0x4d was now found with
* chip ID 0x03 .
* To avoid detection failures , accept chip ID 0x01 and 0x03 at both
* addresses .
* G784 reports manufacturer ID 0x47 and chip ID 0x01 . A public
* datasheet is not available . Extensive testing suggests that
* the chip appears to be fully compatible with G781 .
* Available register dumps show that G751 also reports manufacturer
* ID 0x47 and chip ID 0x01 even though that chip does not officially
* support those registers . This makes chip detection somewhat
* vulnerable . To improve detection quality , read the offset low byte
* and alert fault queue registers and verify that only expected bits
* are set .
*/
if ( ( chip_id = = 0x01 | | chip_id = = 0x03 ) & &
( address = = 0x4c | | address = = 0x4d ) & &
! ( config1 & 0x3f ) & & convrate < = 0x08 ) {
int reg ;
2021-11-09 20:38:22 -08:00
2021-12-02 16:19:27 -08:00
reg = i2c_smbus_read_byte_data ( client , LM90_REG_REMOTE_OFFSL ) ;
if ( reg < 0 | | reg & 0x1f )
return NULL ;
reg = i2c_smbus_read_byte_data ( client , TMP451_REG_CONALERT ) ;
if ( reg < 0 | | reg & 0xf1 )
return NULL ;
return " g781 " ;
}
return NULL ;
2021-11-09 20:38:22 -08:00
}
static const char * lm90_detect_ti ( struct i2c_client * client , int chip_id ,
int config1 , int convrate )
{
int address = client - > addr ;
const char * name = NULL ;
if ( chip_id = = 0x00 & & ! ( config1 & 0x1b ) & & convrate < = 0x09 ) {
2021-10-18 20:03:32 -07:00
int local_ext , conalert , chen , dfc ;
2013-11-15 10:40:39 +01:00
local_ext = i2c_smbus_read_byte_data ( client ,
2021-10-31 02:01:41 -07:00
TMP451_REG_LOCAL_TEMPL ) ;
2021-10-18 20:03:32 -07:00
conalert = i2c_smbus_read_byte_data ( client ,
TMP451_REG_CONALERT ) ;
chen = i2c_smbus_read_byte_data ( client , TMP461_REG_CHEN ) ;
dfc = i2c_smbus_read_byte_data ( client , TMP461_REG_DFC ) ;
2021-11-09 20:38:22 -08:00
if ( ! ( local_ext & 0x0f ) & & ( conalert & 0xf1 ) = = 0x01 & &
( chen & 0xfc ) = = 0x00 & & ( dfc & 0xfc ) = = 0x00 ) {
2021-10-18 20:03:32 -07:00
if ( address = = 0x4c & & ! ( chen & 0x03 ) )
name = " tmp451 " ;
else if ( address > = 0x48 & & address < = 0x4f )
name = " tmp461 " ;
}
2005-04-16 15:20:36 -07:00
}
2021-11-09 20:38:22 -08:00
return name ;
}
/* Return 0 if detection is successful, -ENODEV otherwise */
static int lm90_detect ( struct i2c_client * client , struct i2c_board_info * info )
{
struct i2c_adapter * adapter = client - > adapter ;
int man_id , chip_id , config1 , convrate ;
const char * name = NULL ;
if ( ! i2c_check_functionality ( adapter , I2C_FUNC_SMBUS_BYTE_DATA ) )
return - ENODEV ;
/* detection and identification */
man_id = i2c_smbus_read_byte_data ( client , LM90_REG_MAN_ID ) ;
chip_id = i2c_smbus_read_byte_data ( client , LM90_REG_CHIP_ID ) ;
config1 = i2c_smbus_read_byte_data ( client , LM90_REG_CONFIG1 ) ;
convrate = i2c_smbus_read_byte_data ( client , LM90_REG_CONVRATE ) ;
if ( man_id < 0 | | chip_id < 0 | | config1 < 0 | | convrate < 0 )
return - ENODEV ;
switch ( man_id ) {
case 0x01 : /* National Semiconductor */
name = lm90_detect_national ( client , chip_id , config1 , convrate ) ;
break ;
case 0x41 : /* Analog Devices */
name = lm90_detect_analog ( client , chip_id , config1 , convrate ) ;
break ;
case 0x47 : /* GMT */
name = lm90_detect_gmt ( client , chip_id , config1 , convrate ) ;
break ;
case 0x4d : /* Maxim Integrated */
name = lm90_detect_maxim ( client , chip_id , config1 , convrate ) ;
break ;
case 0x55 : /* TI */
name = lm90_detect_ti ( client , chip_id , config1 , convrate ) ;
break ;
case 0x5c : /* Winbond/Nuvoton */
name = lm90_detect_nuvoton ( client , chip_id , config1 , convrate ) ;
break ;
case 0xa1 : /* NXP Semiconductor/Philips */
name = lm90_detect_nxp ( client , chip_id , config1 , convrate ) ;
break ;
default :
break ;
}
if ( ! name ) { /* identification failed */
2009-12-09 20:35:53 +01:00
dev_dbg ( & adapter - > dev ,
2021-11-09 20:38:22 -08:00
" Unsupported chip at 0x%02x (man_id=0x%02X, chip_id=0x%02X) \n " ,
client - > addr , man_id , chip_id ) ;
2009-12-09 20:35:53 +01:00
return - ENODEV ;
2005-04-16 15:20:36 -07:00
}
2009-12-09 20:35:53 +01:00
2008-07-16 19:30:15 +02:00
strlcpy ( info - > type , name , I2C_NAME_SIZE ) ;
return 0 ;
}
2016-06-13 06:19:11 -07:00
static void lm90_restore_conf ( void * _data )
2012-03-23 10:02:18 +01:00
{
2016-06-13 06:19:11 -07:00
struct lm90_data * data = _data ;
struct i2c_client * client = data - > client ;
2022-01-09 14:19:01 -08:00
cancel_delayed_work_sync ( & data - > alert_work ) ;
2012-03-23 10:02:18 +01:00
/* Restore initial configuration */
2021-11-15 18:14:35 -08:00
if ( data - > flags & LM90_HAVE_CONVRATE )
lm90_write_convrate ( data , data - > convrate_orig ) ;
2021-10-31 02:01:41 -07:00
lm90_write_reg ( client , LM90_REG_CONFIG1 , data - > config_orig ) ;
2012-03-23 10:02:18 +01:00
}
2016-06-13 06:57:37 -07:00
static int lm90_init_client ( struct i2c_client * client , struct lm90_data * data )
2010-10-28 20:31:43 +02:00
{
2022-05-17 15:56:14 +02:00
struct device_node * np = client - > dev . of_node ;
2016-06-13 06:57:37 -07:00
int config , convrate ;
2010-10-28 20:31:43 +02:00
2021-11-15 18:14:35 -08:00
if ( data - > flags & LM90_HAVE_CONVRATE ) {
convrate = lm90_read_reg ( client , LM90_REG_CONVRATE ) ;
if ( convrate < 0 )
return convrate ;
data - > convrate_orig = convrate ;
lm90_set_convrate ( client , data , 500 ) ; /* 500ms; 2Hz conversion rate */
} else {
data - > update_interval = 500 ;
}
2010-10-28 20:31:44 +02:00
2010-10-28 20:31:43 +02:00
/*
* Start the conversions .
*/
2021-10-31 02:01:41 -07:00
config = lm90_read_reg ( client , LM90_REG_CONFIG1 ) ;
2016-06-13 06:57:37 -07:00
if ( config < 0 )
return config ;
2010-10-28 20:31:43 +02:00
data - > config_orig = config ;
2019-06-30 15:14:19 -07:00
data - > config = config ;
2010-10-28 20:31:43 +02:00
/* Check Temperature Range Select */
2021-10-21 01:49:50 -07:00
if ( data - > flags & LM90_HAVE_EXTENDED_TEMP ) {
2022-05-17 15:56:14 +02:00
if ( of_property_read_bool ( np , " ti,extended-range-enable " ) )
config | = 0x04 ;
2021-11-22 08:13:58 -08:00
if ( ! ( config & 0x04 ) )
data - > flags & = ~ LM90_HAVE_EXTENDED_TEMP ;
2010-10-28 20:31:43 +02:00
}
/*
* Put MAX6680 / MAX8881 into extended resolution ( bit 0x10 ,
* 0.125 degree resolution ) and range ( 0x08 , extend range
* to - 64 degree ) mode for the remote temperature sensor .
2021-12-04 07:53:00 -08:00
* Note that expeciments with an actual chip do not show a difference
* if bit 3 is set or not .
2010-10-28 20:31:43 +02:00
*/
if ( data - > kind = = max6680 )
config | = 0x18 ;
2020-05-13 11:42:48 -07:00
/*
* Put MAX6654 into extended range ( 0x20 , extend minimum range from
* 0 degrees to - 64 degrees ) . Note that extended resolution is not
* possible on the MAX6654 unless conversion rate is set to 1 Hz or
* slower , which is intentionally not done by default .
*/
if ( data - > kind = = max6654 )
config | = 0x20 ;
2010-10-28 20:31:43 +02:00
/*
2021-11-06 09:59:26 -07:00
* Select external channel 0 for devices with three sensors
2010-10-28 20:31:43 +02:00
*/
2021-11-06 09:59:26 -07:00
if ( data - > flags & LM90_HAVE_TEMP3 )
2010-10-28 20:31:43 +02:00
config & = ~ 0x08 ;
2021-06-19 00:54:54 +03:00
/*
* Interrupt is enabled by default on reset , but it may be disabled
* by bootloader , unmask it .
*/
if ( client - > irq )
config & = ~ 0x80 ;
2010-10-28 20:31:43 +02:00
config & = 0xBF ; /* run */
2019-06-30 15:40:34 -07:00
lm90_update_confreg ( data , config ) ;
2016-06-13 06:19:11 -07:00
2016-07-25 14:53:23 -07:00
return devm_add_action_or_reset ( & client - > dev , lm90_restore_conf , data ) ;
2010-10-28 20:31:43 +02:00
}
2022-01-09 14:19:01 -08:00
static bool lm90_is_tripped ( struct i2c_client * client )
2013-11-15 10:40:38 +01:00
{
struct lm90_data * data = i2c_get_clientdata ( client ) ;
2022-01-09 14:19:01 -08:00
int ret ;
2013-11-15 10:40:38 +01:00
2022-01-09 14:19:01 -08:00
ret = lm90_update_alarms ( data , true ) ;
if ( ret < 0 )
2013-11-15 10:40:38 +01:00
return false ;
2022-01-09 14:19:01 -08:00
return ! ! data - > current_alarms ;
2013-11-15 10:40:38 +01:00
}
2013-11-15 10:40:39 +01:00
static irqreturn_t lm90_irq_thread ( int irq , void * dev_id )
{
struct i2c_client * client = dev_id ;
2022-01-09 14:19:01 -08:00
if ( lm90_is_tripped ( client ) )
2013-11-15 10:40:39 +01:00
return IRQ_HANDLED ;
else
return IRQ_NONE ;
}
2016-06-13 06:19:11 -07:00
static void lm90_remove_pec ( void * dev )
{
device_remove_file ( dev , & dev_attr_pec ) ;
}
static void lm90_regulator_disable ( void * regulator )
{
regulator_disable ( regulator ) ;
}
2016-06-18 19:56:08 -07:00
static const struct hwmon_ops lm90_ops = {
. is_visible = lm90_is_visible ,
. read = lm90_read ,
. write = lm90_write ,
} ;
2020-08-13 18:02:22 +02:00
static int lm90_probe ( struct i2c_client * client )
2008-07-16 19:30:15 +02:00
{
2011-11-04 12:00:47 +01:00
struct device * dev = & client - > dev ;
2019-06-10 11:51:54 +02:00
struct i2c_adapter * adapter = client - > adapter ;
2016-06-18 19:56:08 -07:00
struct hwmon_channel_info * info ;
2013-11-15 10:40:39 +01:00
struct regulator * regulator ;
2016-06-13 06:28:03 -07:00
struct device * hwmon_dev ;
2016-06-18 19:56:08 -07:00
struct lm90_data * data ;
2008-07-16 19:30:15 +02:00
int err ;
2005-04-16 15:20:36 -07:00
2013-11-15 10:40:39 +01:00
regulator = devm_regulator_get ( dev , " vcc " ) ;
if ( IS_ERR ( regulator ) )
return PTR_ERR ( regulator ) ;
err = regulator_enable ( regulator ) ;
if ( err < 0 ) {
2014-04-04 18:01:35 +02:00
dev_err ( dev , " Failed to enable regulator: %d \n " , err ) ;
2013-11-15 10:40:39 +01:00
return err ;
}
2016-07-25 14:53:23 -07:00
err = devm_add_action_or_reset ( dev , lm90_regulator_disable , regulator ) ;
if ( err )
return err ;
2016-06-13 06:19:11 -07:00
2014-04-04 18:01:35 +02:00
data = devm_kzalloc ( dev , sizeof ( struct lm90_data ) , GFP_KERNEL ) ;
2012-06-02 09:58:10 -07:00
if ( ! data )
return - ENOMEM ;
2014-04-04 18:01:35 +02:00
data - > client = client ;
2011-11-04 12:00:47 +01:00
i2c_set_clientdata ( client , data ) ;
2006-01-18 23:19:26 +01:00
mutex_init ( & data - > update_lock ) ;
2022-01-09 14:19:01 -08:00
INIT_DELAYED_WORK ( & data - > alert_work , lm90_alert_work ) ;
2005-04-16 15:20:36 -07:00
2008-07-16 19:30:15 +02:00
/* Set the device type */
2017-02-24 10:13:04 -03:00
if ( client - > dev . of_node )
data - > kind = ( enum chips ) of_device_get_match_data ( & client - > dev ) ;
else
2020-08-13 18:02:22 +02:00
data - > kind = i2c_match_id ( lm90_id , client ) - > driver_data ;
2005-04-16 15:20:36 -07:00
2012-03-23 10:02:18 +01:00
/*
* Different devices have different alarm bits triggering the
* ALERT # output
*/
2010-10-28 20:31:43 +02:00
data - > alert_alarms = lm90_params [ data - > kind ] . alert_alarms ;
2021-11-02 22:38:59 -07:00
data - > resolution = lm90_params [ data - > kind ] . resolution ? : 11 ;
2010-03-05 22:17:15 +01:00
2010-10-28 20:31:43 +02:00
/* Set chip capabilities */
2010-10-28 20:31:43 +02:00
data - > flags = lm90_params [ data - > kind ] . flags ;
2016-06-18 19:56:08 -07:00
2021-10-31 09:34:33 -07:00
if ( ( data - > flags & ( LM90_HAVE_PEC | LM90_HAVE_PARTIAL_PEC ) ) & &
! i2c_check_functionality ( adapter , I2C_FUNC_SMBUS_PEC ) )
data - > flags & = ~ ( LM90_HAVE_PEC | LM90_HAVE_PARTIAL_PEC ) ;
if ( ( data - > flags & LM90_HAVE_PARTIAL_PEC ) & &
! i2c_check_functionality ( adapter , I2C_FUNC_SMBUS_BYTE ) )
data - > flags & = ~ LM90_HAVE_PARTIAL_PEC ;
2016-06-18 19:56:08 -07:00
data - > chip . ops = & lm90_ops ;
data - > chip . info = data - > info ;
2021-11-17 11:57:57 -08:00
data - > info [ 0 ] = & data - > chip_info ;
info = & data - > chip_info ;
info - > type = hwmon_chip ;
info - > config = data - > chip_config ;
2021-11-15 18:14:35 -08:00
data - > chip_config [ 0 ] = HWMON_C_REGISTER_TZ ;
2021-11-17 11:57:57 -08:00
if ( data - > flags & LM90_HAVE_ALARMS )
data - > chip_config [ 0 ] | = HWMON_C_ALARMS ;
2021-11-15 18:14:35 -08:00
if ( data - > flags & LM90_HAVE_CONVRATE )
data - > chip_config [ 0 ] | = HWMON_C_UPDATE_INTERVAL ;
2021-11-17 11:57:57 -08:00
2016-06-18 19:56:08 -07:00
data - > info [ 1 ] = & data - > temp_info ;
info = & data - > temp_info ;
info - > type = hwmon_temp ;
info - > config = data - > channel_config ;
2021-11-15 17:48:13 -08:00
data - > channel_config [ 0 ] = HWMON_T_INPUT | HWMON_T_MAX |
HWMON_T_MAX_ALARM ;
data - > channel_config [ 1 ] = HWMON_T_INPUT | HWMON_T_MAX |
HWMON_T_MAX_ALARM | HWMON_T_FAULT ;
if ( data - > flags & LM90_HAVE_LOW ) {
data - > channel_config [ 0 ] | = HWMON_T_MIN | HWMON_T_MIN_ALARM ;
data - > channel_config [ 1 ] | = HWMON_T_MIN | HWMON_T_MIN_ALARM ;
}
2021-11-13 08:55:06 -08:00
if ( data - > flags & LM90_HAVE_CRIT ) {
data - > channel_config [ 0 ] | = HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_CRIT_HYST ;
data - > channel_config [ 1 ] | = HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_CRIT_HYST ;
}
2016-06-18 19:56:08 -07:00
if ( data - > flags & LM90_HAVE_OFFSET )
data - > channel_config [ 1 ] | = HWMON_T_OFFSET ;
if ( data - > flags & LM90_HAVE_EMERGENCY ) {
data - > channel_config [ 0 ] | = HWMON_T_EMERGENCY |
HWMON_T_EMERGENCY_HYST ;
data - > channel_config [ 1 ] | = HWMON_T_EMERGENCY |
HWMON_T_EMERGENCY_HYST ;
}
if ( data - > flags & LM90_HAVE_EMERGENCY_ALARM ) {
data - > channel_config [ 0 ] | = HWMON_T_EMERGENCY_ALARM ;
data - > channel_config [ 1 ] | = HWMON_T_EMERGENCY_ALARM ;
}
if ( data - > flags & LM90_HAVE_TEMP3 ) {
data - > channel_config [ 2 ] = HWMON_T_INPUT |
HWMON_T_MIN | HWMON_T_MAX |
HWMON_T_CRIT | HWMON_T_CRIT_HYST |
HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM |
2021-11-06 09:59:26 -07:00
HWMON_T_CRIT_ALARM | HWMON_T_FAULT ;
if ( data - > flags & LM90_HAVE_EMERGENCY ) {
data - > channel_config [ 2 ] | = HWMON_T_EMERGENCY |
HWMON_T_EMERGENCY_HYST ;
}
if ( data - > flags & LM90_HAVE_EMERGENCY_ALARM )
data - > channel_config [ 2 ] | = HWMON_T_EMERGENCY_ALARM ;
2016-06-18 19:56:08 -07:00
}
2011-07-27 23:22:25 -07:00
data - > reg_local_ext = lm90_params [ data - > kind ] . reg_local_ext ;
2021-11-06 09:59:26 -07:00
data - > reg_status2 = lm90_params [ data - > kind ] . reg_status2 ;
2010-10-28 20:31:43 +02:00
2010-10-28 20:31:44 +02:00
/* Set maximum conversion rate */
data - > max_convrate = lm90_params [ data - > kind ] . max_convrate ;
2005-04-16 15:20:36 -07:00
/* Initialize the LM90 chip */
2016-06-13 06:57:37 -07:00
err = lm90_init_client ( client , data ) ;
if ( err < 0 ) {
dev_err ( dev , " Failed to initialize device \n " ) ;
return err ;
}
2005-04-16 15:20:36 -07:00
2016-06-18 19:56:08 -07:00
/*
* The ' pec ' attribute is attached to the i2c device and thus created
* separately .
*/
2021-10-31 09:34:33 -07:00
if ( data - > flags & ( LM90_HAVE_PEC | LM90_HAVE_PARTIAL_PEC ) ) {
2011-11-04 12:00:47 +01:00
err = device_create_file ( dev , & dev_attr_pec ) ;
2010-10-28 20:31:42 +02:00
if ( err )
2016-06-13 06:19:11 -07:00
return err ;
2016-07-25 14:53:23 -07:00
err = devm_add_action_or_reset ( dev , lm90_remove_pec , dev ) ;
if ( err )
return err ;
2010-10-28 20:31:43 +02:00
}
2006-09-24 21:16:40 +02:00
2016-06-18 19:56:08 -07:00
hwmon_dev = devm_hwmon_device_register_with_info ( dev , client - > name ,
data , & data - > chip ,
NULL ) ;
2016-06-13 06:28:03 -07:00
if ( IS_ERR ( hwmon_dev ) )
return PTR_ERR ( hwmon_dev ) ;
2005-07-15 21:39:18 -04:00
2021-06-19 00:54:53 +03:00
data - > hwmon_dev = hwmon_dev ;
2013-11-15 10:40:39 +01:00
if ( client - > irq ) {
dev_dbg ( dev , " IRQ: %d \n " , client - > irq ) ;
err = devm_request_threaded_irq ( dev , client - > irq ,
NULL , lm90_irq_thread ,
2021-06-19 00:54:52 +03:00
IRQF_ONESHOT , " lm90 " , client ) ;
2013-11-15 10:40:39 +01:00
if ( err < 0 ) {
dev_err ( dev , " cannot request IRQ %d \n " , client - > irq ) ;
2016-06-13 06:28:03 -07:00
return err ;
2013-11-15 10:40:39 +01:00
}
}
2005-04-16 15:20:36 -07:00
return 0 ;
}
2016-06-09 16:53:47 +02:00
static void lm90_alert ( struct i2c_client * client , enum i2c_alert_protocol type ,
unsigned int flag )
2010-03-05 22:17:15 +01:00
{
2016-06-09 16:53:47 +02:00
if ( type ! = I2C_PROTOCOL_SMBUS_ALERT )
return ;
2022-01-09 14:19:01 -08:00
if ( lm90_is_tripped ( client ) ) {
2012-03-23 10:02:18 +01:00
/*
* Disable ALERT # output , because these chips don ' t implement
* SMBus alert correctly ; they should only hold the alert line
* low briefly .
*/
2013-11-15 10:40:38 +01:00
struct lm90_data * data = i2c_get_clientdata ( client ) ;
2016-06-13 06:57:37 -07:00
if ( ( data - > flags & LM90_HAVE_BROKEN_ALERT ) & &
2022-01-09 14:19:01 -08:00
( data - > current_alarms & data - > alert_alarms ) ) {
2010-03-05 22:17:15 +01:00
dev_dbg ( & client - > dev , " Disabling ALERT# \n " ) ;
2019-06-30 15:40:34 -07:00
lm90_update_confreg ( data , data - > config | 0x80 ) ;
2022-01-09 14:19:01 -08:00
schedule_delayed_work ( & data - > alert_work ,
max_t ( int , HZ , msecs_to_jiffies ( data - > update_interval ) ) ) ;
2010-03-05 22:17:15 +01:00
}
2013-11-15 10:40:38 +01:00
} else {
2021-06-19 00:54:53 +03:00
dev_dbg ( & client - > dev , " Everything OK \n " ) ;
2010-03-05 22:17:15 +01:00
}
}
2021-06-19 00:54:55 +03:00
static int __maybe_unused lm90_suspend ( struct device * dev )
{
struct lm90_data * data = dev_get_drvdata ( dev ) ;
struct i2c_client * client = data - > client ;
if ( client - > irq )
disable_irq ( client - > irq ) ;
return 0 ;
}
static int __maybe_unused lm90_resume ( struct device * dev )
{
struct lm90_data * data = dev_get_drvdata ( dev ) ;
struct i2c_client * client = data - > client ;
if ( client - > irq )
enable_irq ( client - > irq ) ;
return 0 ;
}
static SIMPLE_DEV_PM_OPS ( lm90_pm_ops , lm90_suspend , lm90_resume ) ;
2010-10-28 20:31:43 +02:00
static struct i2c_driver lm90_driver = {
. class = I2C_CLASS_HWMON ,
. driver = {
. name = " lm90 " ,
2017-02-24 10:13:04 -03:00
. of_match_table = of_match_ptr ( lm90_of_match ) ,
2021-06-19 00:54:55 +03:00
. pm = & lm90_pm_ops ,
2010-10-28 20:31:43 +02:00
} ,
2020-08-13 18:02:22 +02:00
. probe_new = lm90_probe ,
2010-10-28 20:31:43 +02:00
. alert = lm90_alert ,
. id_table = lm90_id ,
. detect = lm90_detect ,
. address_list = normal_i2c ,
} ;
2005-04-16 15:20:36 -07:00
2012-01-20 15:38:18 +08:00
module_i2c_driver ( lm90_driver ) ;
2005-04-16 15:20:36 -07:00
2014-01-29 20:40:08 +01:00
MODULE_AUTHOR ( " Jean Delvare <jdelvare@suse.de> " ) ;
2005-04-16 15:20:36 -07:00
MODULE_DESCRIPTION ( " LM90/ADM1032 driver " ) ;
MODULE_LICENSE ( " GPL " ) ;