2019-05-30 02:57:44 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-03-30 19:16:24 +03:00
/*
* max31722 - hwmon driver for Maxim Integrated MAX31722 / MAX31723 SPI
* digital thermometer and thermostats .
*
* Copyright ( c ) 2016 , Intel Corporation .
*/
# include <linux/acpi.h>
# include <linux/hwmon.h>
# include <linux/hwmon-sysfs.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/spi/spi.h>
# define MAX31722_REG_CFG 0x00
# define MAX31722_REG_TEMP_LSB 0x01
# define MAX31722_MODE_CONTINUOUS 0x00
# define MAX31722_MODE_STANDBY 0x01
# define MAX31722_MODE_MASK 0xFE
# define MAX31722_RESOLUTION_12BIT 0x06
# define MAX31722_WRITE_MASK 0x80
struct max31722_data {
struct device * hwmon_dev ;
struct spi_device * spi_device ;
u8 mode ;
} ;
static int max31722_set_mode ( struct max31722_data * data , u8 mode )
{
int ret ;
struct spi_device * spi = data - > spi_device ;
u8 buf [ 2 ] = {
MAX31722_REG_CFG | MAX31722_WRITE_MASK ,
( data - > mode & MAX31722_MODE_MASK ) | mode
} ;
ret = spi_write ( spi , & buf , sizeof ( buf ) ) ;
if ( ret < 0 ) {
dev_err ( & spi - > dev , " failed to set sensor mode. \n " ) ;
return ret ;
}
data - > mode = ( data - > mode & MAX31722_MODE_MASK ) | mode ;
return 0 ;
}
2018-12-11 01:02:16 +03:00
static ssize_t max31722_temp_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
2016-03-30 19:16:24 +03:00
{
ssize_t ret ;
struct max31722_data * data = dev_get_drvdata ( dev ) ;
ret = spi_w8r16 ( data - > spi_device , MAX31722_REG_TEMP_LSB ) ;
if ( ret < 0 )
return ret ;
/* Keep 12 bits and multiply by the scale of 62.5 millidegrees/bit. */
return sprintf ( buf , " %d \n " , ( s16 ) le16_to_cpu ( ret ) * 125 / 32 ) ;
}
2018-12-11 01:02:16 +03:00
static SENSOR_DEVICE_ATTR_RO ( temp1_input , max31722_temp , 0 ) ;
2016-03-30 19:16:24 +03:00
static struct attribute * max31722_attrs [ ] = {
& sensor_dev_attr_temp1_input . dev_attr . attr ,
NULL ,
} ;
ATTRIBUTE_GROUPS ( max31722 ) ;
static int max31722_probe ( struct spi_device * spi )
{
int ret ;
struct max31722_data * data ;
data = devm_kzalloc ( & spi - > dev , sizeof ( * data ) , GFP_KERNEL ) ;
if ( ! data )
return - ENOMEM ;
spi_set_drvdata ( spi , data ) ;
data - > spi_device = spi ;
/*
* Set SD bit to 0 so we can have continuous measurements .
* Set resolution to 12 bits for maximum precision .
*/
data - > mode = MAX31722_MODE_CONTINUOUS | MAX31722_RESOLUTION_12BIT ;
ret = max31722_set_mode ( data , MAX31722_MODE_CONTINUOUS ) ;
if ( ret < 0 )
return ret ;
data - > hwmon_dev = hwmon_device_register_with_groups ( & spi - > dev ,
spi - > modalias ,
data ,
max31722_groups ) ;
if ( IS_ERR ( data - > hwmon_dev ) ) {
max31722_set_mode ( data , MAX31722_MODE_STANDBY ) ;
return PTR_ERR ( data - > hwmon_dev ) ;
}
return 0 ;
}
static int max31722_remove ( struct spi_device * spi )
{
struct max31722_data * data = spi_get_drvdata ( spi ) ;
hwmon_device_unregister ( data - > hwmon_dev ) ;
return max31722_set_mode ( data , MAX31722_MODE_STANDBY ) ;
}
static int __maybe_unused max31722_suspend ( struct device * dev )
{
struct spi_device * spi_device = to_spi_device ( dev ) ;
struct max31722_data * data = spi_get_drvdata ( spi_device ) ;
return max31722_set_mode ( data , MAX31722_MODE_STANDBY ) ;
}
static int __maybe_unused max31722_resume ( struct device * dev )
{
struct spi_device * spi_device = to_spi_device ( dev ) ;
struct max31722_data * data = spi_get_drvdata ( spi_device ) ;
return max31722_set_mode ( data , MAX31722_MODE_CONTINUOUS ) ;
}
static SIMPLE_DEV_PM_OPS ( max31722_pm_ops , max31722_suspend , max31722_resume ) ;
static const struct spi_device_id max31722_spi_id [ ] = {
{ " max31722 " , 0 } ,
{ " max31723 " , 0 } ,
{ }
} ;
static const struct acpi_device_id __maybe_unused max31722_acpi_id [ ] = {
{ " MAX31722 " , 0 } ,
{ " MAX31723 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( spi , max31722_spi_id ) ;
static struct spi_driver max31722_driver = {
. driver = {
. name = " max31722 " ,
. pm = & max31722_pm_ops ,
. acpi_match_table = ACPI_PTR ( max31722_acpi_id ) ,
} ,
. probe = max31722_probe ,
. remove = max31722_remove ,
. id_table = max31722_spi_id ,
} ;
module_spi_driver ( max31722_driver ) ;
MODULE_AUTHOR ( " Tiberiu Breana <tiberiu.a.breana@intel.com> " ) ;
MODULE_DESCRIPTION ( " max31722 sensor driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;