2019-05-20 10:19:02 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2007-05-08 19:22:00 +04:00
/*
* max6650 . c - Part of lm_sensors , Linux kernel modules for hardware
* monitoring .
*
2010-11-15 23:38:56 +03:00
* ( C ) 2007 by Hans J . Koch < hjk @ hansjkoch . de >
2007-05-08 19:22:00 +04:00
*
* based on code written by John Morris < john . morris @ spirentcom . com >
* Copyright ( c ) 2003 Spirent Communications
* and Claus Gindhart < claus . gindhart @ kontron . com >
*
* This module has only been tested with the MAX6650 chip . It should
* also work with the MAX6651 . It does not distinguish max6650 and max6651
* chips .
*
2009-06-15 20:39:52 +04:00
* The datasheet was last seen at :
2007-05-08 19:22:00 +04:00
*
* http : //pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/slab.h>
# include <linux/jiffies.h>
# include <linux/i2c.h>
# include <linux/hwmon.h>
# include <linux/hwmon-sysfs.h>
# include <linux/err.h>
2016-08-22 09:47:51 +03:00
# include <linux/of_device.h>
2019-04-19 03:57:22 +03:00
# include <linux/thermal.h>
2007-05-08 19:22:00 +04:00
/*
* Insmod parameters
*/
/* fan_voltage: 5=5V fan, 12=12V fan, 0=don't change */
static int fan_voltage ;
/* prescaler: Possible values are 1, 2, 4, 8, 16 or 0 for don't change */
static int prescaler ;
2016-08-22 09:47:51 +03:00
/* clock: The clock frequency of the chip (max6651 can be clocked externally) */
2007-05-08 19:22:00 +04:00
static int clock = 254000 ;
2018-12-11 01:02:17 +03:00
module_param ( fan_voltage , int , 0444 ) ;
module_param ( prescaler , int , 0444 ) ;
module_param ( clock , int , 0444 ) ;
2007-05-08 19:22:00 +04:00
/*
* MAX 6650 / 6651 registers
*/
# define MAX6650_REG_SPEED 0x00
# define MAX6650_REG_CONFIG 0x02
# define MAX6650_REG_GPIO_DEF 0x04
# define MAX6650_REG_DAC 0x06
# define MAX6650_REG_ALARM_EN 0x08
# define MAX6650_REG_ALARM 0x0A
# define MAX6650_REG_TACH0 0x0C
# define MAX6650_REG_TACH1 0x0E
# define MAX6650_REG_TACH2 0x10
# define MAX6650_REG_TACH3 0x12
# define MAX6650_REG_GPIO_STAT 0x14
# define MAX6650_REG_COUNT 0x16
/*
* Config register bits
*/
# define MAX6650_CFG_V12 0x08
# define MAX6650_CFG_PRESCALER_MASK 0x07
# define MAX6650_CFG_PRESCALER_2 0x01
# define MAX6650_CFG_PRESCALER_4 0x02
# define MAX6650_CFG_PRESCALER_8 0x03
# define MAX6650_CFG_PRESCALER_16 0x04
# define MAX6650_CFG_MODE_MASK 0x30
# define MAX6650_CFG_MODE_ON 0x00
# define MAX6650_CFG_MODE_OFF 0x10
# define MAX6650_CFG_MODE_CLOSED_LOOP 0x20
# define MAX6650_CFG_MODE_OPEN_LOOP 0x30
# define MAX6650_COUNT_MASK 0x03
2009-06-15 20:39:52 +04:00
/*
* Alarm status register bits
*/
# define MAX6650_ALRM_MAX 0x01
# define MAX6650_ALRM_MIN 0x02
# define MAX6650_ALRM_TACH 0x04
# define MAX6650_ALRM_GPIO1 0x08
# define MAX6650_ALRM_GPIO2 0x10
2007-05-08 19:22:00 +04:00
/* Minimum and maximum values of the FAN-RPM */
# define FAN_RPM_MIN 240
# define FAN_RPM_MAX 30000
2019-06-07 20:23:17 +03:00
# define DIV_FROM_REG(reg) (1 << ((reg) & 7))
# define DAC_LIMIT(v12) ((v12) ? 180 : 76)
2007-05-08 19:22:00 +04:00
/*
* Client data ( each client gets its own )
*/
2012-01-15 09:32:21 +04:00
struct max6650_data {
2014-02-12 10:37:01 +04:00
struct i2c_client * client ;
2019-06-07 20:23:25 +03:00
struct mutex update_lock ; /* protect alarm register updates */
2011-05-25 22:43:32 +04:00
int nr_fans ;
2019-06-07 20:23:19 +03:00
bool valid ; /* false until following fields are valid */
2007-05-08 19:22:00 +04:00
unsigned long last_updated ; /* in jiffies */
/* register values */
u8 speed ;
u8 config ;
u8 tach [ 4 ] ;
u8 count ;
u8 dac ;
2009-06-15 20:39:52 +04:00
u8 alarm ;
2019-06-07 20:23:20 +03:00
u8 alarm_en ;
2019-04-19 03:57:22 +03:00
unsigned long cooling_dev_state ;
2007-05-08 19:22:00 +04:00
} ;
2014-02-12 10:26:12 +04:00
static const u8 tach_reg [ ] = {
MAX6650_REG_TACH0 ,
MAX6650_REG_TACH1 ,
MAX6650_REG_TACH2 ,
MAX6650_REG_TACH3 ,
} ;
2019-04-04 16:44:14 +03:00
static const struct of_device_id __maybe_unused max6650_dt_match [ ] = {
2016-08-22 09:47:51 +03:00
{
. compatible = " maxim,max6650 " ,
. data = ( void * ) 1
} ,
{
. compatible = " maxim,max6651 " ,
. data = ( void * ) 4
} ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , max6650_dt_match ) ;
2019-06-07 20:23:17 +03:00
static int dac_to_pwm ( int dac , bool v12 )
{
/*
* Useful range for dac is 0 - 180 for 12 V fans and 0 - 76 for 5 V fans .
* Lower DAC values mean higher speeds .
*/
return clamp_val ( 255 - ( 255 * dac ) / DAC_LIMIT ( v12 ) , 0 , 255 ) ;
}
static u8 pwm_to_dac ( unsigned int pwm , bool v12 )
{
int limit = DAC_LIMIT ( v12 ) ;
return limit - ( limit * pwm ) / 255 ;
}
2014-02-12 10:26:12 +04:00
static struct max6650_data * max6650_update_device ( struct device * dev )
{
2014-02-12 10:37:01 +04:00
struct max6650_data * data = dev_get_drvdata ( dev ) ;
struct i2c_client * client = data - > client ;
2019-06-07 20:23:24 +03:00
int reg , err = 0 ;
2014-02-12 10:26:12 +04:00
int i ;
mutex_lock ( & data - > update_lock ) ;
if ( time_after ( jiffies , data - > last_updated + HZ ) | | ! data - > valid ) {
for ( i = 0 ; i < data - > nr_fans ; i + + ) {
2019-06-07 20:23:24 +03:00
reg = i2c_smbus_read_byte_data ( client , tach_reg [ i ] ) ;
if ( reg < 0 ) {
err = reg ;
goto error ;
}
data - > tach [ i ] = reg ;
2014-02-12 10:26:12 +04:00
}
/*
* Alarms are cleared on read in case the condition that
* caused the alarm is removed . Keep the value latched here
* for providing the register through different alarm files .
*/
2019-06-07 20:23:24 +03:00
reg = i2c_smbus_read_byte_data ( client , MAX6650_REG_ALARM ) ;
if ( reg < 0 ) {
err = reg ;
goto error ;
}
data - > alarm | = reg ;
2014-02-12 10:26:12 +04:00
data - > last_updated = jiffies ;
2019-06-07 20:23:19 +03:00
data - > valid = true ;
2014-02-12 10:26:12 +04:00
}
2019-06-07 20:23:24 +03:00
error :
2014-02-12 10:26:12 +04:00
mutex_unlock ( & data - > update_lock ) ;
2019-06-07 20:23:24 +03:00
if ( err )
data = ERR_PTR ( err ) ;
2014-02-12 10:26:12 +04:00
return data ;
}
2016-08-24 11:13:26 +03:00
/*
* Change the operating mode of the chip ( if needed ) .
* mode is one of the MAX6650_CFG_MODE_ * values .
*/
static int max6650_set_operating_mode ( struct max6650_data * data , u8 mode )
{
int result ;
u8 config = data - > config ;
if ( mode = = ( config & MAX6650_CFG_MODE_MASK ) )
return 0 ;
config = ( config & ~ MAX6650_CFG_MODE_MASK ) | mode ;
result = i2c_smbus_write_byte_data ( data - > client , MAX6650_REG_CONFIG ,
config ) ;
if ( result < 0 )
return result ;
data - > config = config ;
return 0 ;
}
2007-05-08 19:22:00 +04:00
/*
* Set the fan speed to the specified RPM ( or read back the RPM setting ) .
* This works in closed loop mode only . Use pwm1 for open loop speed setting .
*
* The MAX6650 / 1 will automatically control fan speed when in closed loop
* mode .
*
* Assumptions :
*
* 1 ) The MAX6650 / 1 internal 254 kHz clock frequency is set correctly . Use
* the clock module parameter if you need to fine tune this .
*
* 2 ) The prescaler ( low three bits of the config register ) has already
* been set to an appropriate value . Use the prescaler module parameter
* if your BIOS doesn ' t initialize the chip properly .
*
* The relevant equations are given on pages 21 and 22 of the datasheet .
*
* From the datasheet , the relevant equation when in regulation is :
*
* [ fCLK / ( 128 x ( KTACH + 1 ) ) ] = 2 x FanSpeed / KSCALE
*
* where :
*
* fCLK is the oscillator frequency ( either the 254 kHz internal
* oscillator or the externally applied clock )
*
* KTACH is the value in the speed register
*
* FanSpeed is the speed of the fan in rps
*
* KSCALE is the prescaler value ( 1 , 2 , 4 , 8 , or 16 )
*
* When reading , we need to solve for FanSpeed . When writing , we need to
* solve for KTACH .
*
* Note : this tachometer is completely separate from the tachometers
* used to measure the fan speeds . Only one fan ' s speed ( fan1 ) is
* controlled .
*/
2016-08-24 11:13:26 +03:00
static int max6650_set_target ( struct max6650_data * data , unsigned long rpm )
2007-05-08 19:22:00 +04:00
{
int kscale , ktach ;
2012-01-15 09:32:21 +04:00
2016-08-24 11:13:26 +03:00
if ( rpm = = 0 )
return max6650_set_operating_mode ( data , MAX6650_CFG_MODE_OFF ) ;
2007-05-08 19:22:00 +04:00
2013-01-09 20:09:34 +04:00
rpm = clamp_val ( rpm , FAN_RPM_MIN , FAN_RPM_MAX ) ;
2007-05-08 19:22:00 +04:00
/*
2012-01-19 23:02:22 +04:00
* Divide the required speed by 60 to get from rpm to rps , then
* use the datasheet equation :
*
* KTACH = [ ( fCLK x KSCALE ) / ( 256 x FanSpeed ) ] - 1
*/
2007-05-08 19:22:00 +04:00
kscale = DIV_FROM_REG ( data - > config ) ;
ktach = ( ( clock * kscale ) / ( 256 * rpm / 60 ) ) - 1 ;
if ( ktach < 0 )
ktach = 0 ;
if ( ktach > 255 )
ktach = 255 ;
data - > speed = ktach ;
2016-08-24 11:13:26 +03:00
return i2c_smbus_write_byte_data ( data - > client , MAX6650_REG_SPEED ,
data - > speed ) ;
}
2007-05-08 19:22:00 +04:00
/*
2019-06-07 20:23:22 +03:00
* Get gpio alarm status :
2009-06-15 20:39:52 +04:00
* Possible values :
* 0 = no alarm
* 1 = alarm
*/
2018-12-06 21:46:16 +03:00
static ssize_t alarm_show ( struct device * dev ,
struct device_attribute * devattr , char * buf )
2009-06-15 20:39:52 +04:00
{
struct sensor_device_attribute * attr = to_sensor_dev_attr ( devattr ) ;
struct max6650_data * data = max6650_update_device ( dev ) ;
2019-06-07 20:23:24 +03:00
bool alarm ;
2009-06-15 20:39:52 +04:00
2019-06-07 20:23:24 +03:00
if ( IS_ERR ( data ) )
return PTR_ERR ( data ) ;
alarm = data - > alarm & attr - > index ;
2019-06-07 20:23:21 +03:00
if ( alarm ) {
2009-06-15 20:39:52 +04:00
mutex_lock ( & data - > update_lock ) ;
data - > alarm & = ~ attr - > index ;
2019-06-07 20:23:21 +03:00
data - > valid = false ;
2009-06-15 20:39:52 +04:00
mutex_unlock ( & data - > update_lock ) ;
}
return sprintf ( buf , " %d \n " , alarm ) ;
}
2018-12-06 21:46:16 +03:00
static SENSOR_DEVICE_ATTR_RO ( gpio1_alarm , alarm , MAX6650_ALRM_GPIO1 ) ;
static SENSOR_DEVICE_ATTR_RO ( gpio2_alarm , alarm , MAX6650_ALRM_GPIO2 ) ;
2009-06-15 20:39:52 +04:00
2011-07-24 07:11:19 +04:00
static umode_t max6650_attrs_visible ( struct kobject * kobj , struct attribute * a ,
2019-06-07 20:23:25 +03:00
int n )
2009-06-15 20:39:52 +04:00
{
2020-12-31 04:03:41 +03:00
struct device * dev = kobj_to_dev ( kobj ) ;
2014-02-12 10:37:01 +04:00
struct max6650_data * data = dev_get_drvdata ( dev ) ;
2009-06-15 20:39:52 +04:00
struct device_attribute * devattr ;
2007-05-08 19:22:00 +04:00
2009-06-15 20:39:52 +04:00
/*
* Hide the alarms that have not been enabled by the firmware
*/
devattr = container_of ( a , struct device_attribute , attr ) ;
2019-06-07 20:23:22 +03:00
if ( devattr = = & sensor_dev_attr_gpio1_alarm . dev_attr | |
devattr = = & sensor_dev_attr_gpio2_alarm . dev_attr ) {
2019-06-07 20:23:20 +03:00
if ( ! ( data - > alarm_en & to_sensor_dev_attr ( devattr ) - > index ) )
2009-06-15 20:39:52 +04:00
return 0 ;
}
return a - > mode ;
}
2007-05-08 19:22:00 +04:00
static struct attribute * max6650_attrs [ ] = {
2009-06-15 20:39:52 +04:00
& sensor_dev_attr_gpio1_alarm . dev_attr . attr ,
& sensor_dev_attr_gpio2_alarm . dev_attr . attr ,
2007-05-08 19:22:00 +04:00
NULL
} ;
2014-02-12 10:37:01 +04:00
static const struct attribute_group max6650_group = {
2007-05-08 19:22:00 +04:00
. attrs = max6650_attrs ,
2009-06-15 20:39:52 +04:00
. is_visible = max6650_attrs_visible ,
2007-05-08 19:22:00 +04:00
} ;
2019-06-07 20:23:22 +03:00
static const struct attribute_group * max6650_groups [ ] = {
& max6650_group ,
2011-05-25 22:43:32 +04:00
NULL
} ;
2014-02-12 10:37:01 +04:00
static int max6650_init_client ( struct max6650_data * data ,
struct i2c_client * client )
2007-05-08 19:22:00 +04:00
{
2014-02-12 10:43:54 +04:00
struct device * dev = & client - > dev ;
2019-06-07 20:23:18 +03:00
int reg ;
int err ;
2016-08-22 09:47:51 +03:00
u32 voltage ;
u32 prescale ;
2016-08-24 11:13:26 +03:00
u32 target_rpm ;
2016-08-22 09:47:51 +03:00
if ( of_property_read_u32 ( dev - > of_node , " maxim,fan-microvolt " ,
& voltage ) )
voltage = fan_voltage ;
else
voltage / = 1000000 ; /* Microvolts to volts */
if ( of_property_read_u32 ( dev - > of_node , " maxim,fan-prescale " ,
& prescale ) )
prescale = prescaler ;
2007-05-08 19:22:00 +04:00
2019-06-07 20:23:18 +03:00
reg = i2c_smbus_read_byte_data ( client , MAX6650_REG_CONFIG ) ;
if ( reg < 0 ) {
dev_err ( dev , " Error reading config register, aborting. \n " ) ;
return reg ;
2007-05-08 19:22:00 +04:00
}
2016-08-22 09:47:51 +03:00
switch ( voltage ) {
2012-01-15 09:32:21 +04:00
case 0 :
break ;
case 5 :
2019-06-07 20:23:18 +03:00
reg & = ~ MAX6650_CFG_V12 ;
2012-01-15 09:32:21 +04:00
break ;
case 12 :
2019-06-07 20:23:18 +03:00
reg | = MAX6650_CFG_V12 ;
2012-01-15 09:32:21 +04:00
break ;
default :
2016-08-22 09:47:51 +03:00
dev_err ( dev , " illegal value for fan_voltage (%d) \n " , voltage ) ;
2007-05-08 19:22:00 +04:00
}
2016-08-22 09:47:51 +03:00
switch ( prescale ) {
2012-01-15 09:32:21 +04:00
case 0 :
break ;
case 1 :
2019-06-07 20:23:18 +03:00
reg & = ~ MAX6650_CFG_PRESCALER_MASK ;
2012-01-15 09:32:21 +04:00
break ;
case 2 :
2019-06-07 20:23:18 +03:00
reg = ( reg & ~ MAX6650_CFG_PRESCALER_MASK )
2012-01-15 09:32:21 +04:00
| MAX6650_CFG_PRESCALER_2 ;
break ;
case 4 :
2019-06-07 20:23:18 +03:00
reg = ( reg & ~ MAX6650_CFG_PRESCALER_MASK )
2012-01-15 09:32:21 +04:00
| MAX6650_CFG_PRESCALER_4 ;
break ;
case 8 :
2019-06-07 20:23:18 +03:00
reg = ( reg & ~ MAX6650_CFG_PRESCALER_MASK )
2012-01-15 09:32:21 +04:00
| MAX6650_CFG_PRESCALER_8 ;
break ;
case 16 :
2019-06-07 20:23:18 +03:00
reg = ( reg & ~ MAX6650_CFG_PRESCALER_MASK )
2012-01-15 09:32:21 +04:00
| MAX6650_CFG_PRESCALER_16 ;
break ;
default :
2016-08-22 09:47:51 +03:00
dev_err ( dev , " illegal value for prescaler (%d) \n " , prescale ) ;
2007-05-08 19:22:00 +04:00
}
2016-08-22 09:47:51 +03:00
dev_info ( dev , " Fan voltage: %dV, prescaler: %d. \n " ,
2019-06-07 20:23:18 +03:00
( reg & MAX6650_CFG_V12 ) ? 12 : 5 ,
1 < < ( reg & MAX6650_CFG_PRESCALER_MASK ) ) ;
2007-05-08 19:22:00 +04:00
2019-06-07 20:23:18 +03:00
err = i2c_smbus_write_byte_data ( client , MAX6650_REG_CONFIG , reg ) ;
if ( err ) {
2014-02-12 10:43:54 +04:00
dev_err ( dev , " Config write error, aborting. \n " ) ;
2007-05-08 19:22:00 +04:00
return err ;
}
2019-06-07 20:23:18 +03:00
data - > config = reg ;
2019-06-07 20:23:23 +03:00
reg = i2c_smbus_read_byte_data ( client , MAX6650_REG_SPEED ) ;
if ( reg < 0 ) {
dev_err ( dev , " Failed to read speed register, aborting. \n " ) ;
return reg ;
}
data - > speed = reg ;
reg = i2c_smbus_read_byte_data ( client , MAX6650_REG_DAC ) ;
if ( reg < 0 ) {
dev_err ( dev , " Failed to read DAC register, aborting. \n " ) ;
return reg ;
}
data - > dac = reg ;
2019-06-07 20:23:18 +03:00
reg = i2c_smbus_read_byte_data ( client , MAX6650_REG_COUNT ) ;
if ( reg < 0 ) {
dev_err ( dev , " Failed to read count register, aborting. \n " ) ;
return reg ;
}
data - > count = reg ;
2007-05-08 19:22:00 +04:00
2019-06-07 20:23:20 +03:00
reg = i2c_smbus_read_byte_data ( client , MAX6650_REG_ALARM_EN ) ;
if ( reg < 0 ) {
dev_err ( dev , " Failed to read alarm configuration, aborting. \n " ) ;
return reg ;
}
data - > alarm_en = reg ;
2016-08-24 11:13:26 +03:00
if ( ! of_property_read_u32 ( client - > dev . of_node , " maxim,fan-target-rpm " ,
& target_rpm ) ) {
max6650_set_target ( data , target_rpm ) ;
max6650_set_operating_mode ( data , MAX6650_CFG_MODE_CLOSED_LOOP ) ;
}
2007-05-08 19:22:00 +04:00
return 0 ;
}
2019-04-19 03:57:22 +03:00
static int max6650_get_max_state ( struct thermal_cooling_device * cdev ,
unsigned long * state )
{
* state = 255 ;
return 0 ;
}
static int max6650_get_cur_state ( struct thermal_cooling_device * cdev ,
unsigned long * state )
{
struct max6650_data * data = cdev - > devdata ;
* state = data - > cooling_dev_state ;
return 0 ;
}
static int max6650_set_cur_state ( struct thermal_cooling_device * cdev ,
unsigned long state )
{
struct max6650_data * data = cdev - > devdata ;
struct i2c_client * client = data - > client ;
int err ;
state = clamp_val ( state , 0 , 255 ) ;
mutex_lock ( & data - > update_lock ) ;
2019-06-07 20:23:17 +03:00
data - > dac = pwm_to_dac ( state , data - > config & MAX6650_CFG_V12 ) ;
2019-04-19 03:57:22 +03:00
err = i2c_smbus_write_byte_data ( client , MAX6650_REG_DAC , data - > dac ) ;
if ( ! err ) {
max6650_set_operating_mode ( data , state ?
2019-06-07 20:23:25 +03:00
MAX6650_CFG_MODE_OPEN_LOOP :
MAX6650_CFG_MODE_OFF ) ;
2019-04-19 03:57:22 +03:00
data - > cooling_dev_state = state ;
}
mutex_unlock ( & data - > update_lock ) ;
2019-06-07 20:23:17 +03:00
return err ;
2019-04-19 03:57:22 +03:00
}
static const struct thermal_cooling_device_ops max6650_cooling_ops = {
. get_max_state = max6650_get_max_state ,
. get_cur_state = max6650_get_cur_state ,
. set_cur_state = max6650_set_cur_state ,
} ;
2019-06-07 20:23:22 +03:00
static int max6650_read ( struct device * dev , enum hwmon_sensor_types type ,
u32 attr , int channel , long * val )
{
struct max6650_data * data = max6650_update_device ( dev ) ;
int mode ;
2019-06-07 20:23:24 +03:00
if ( IS_ERR ( data ) )
return PTR_ERR ( data ) ;
2019-06-07 20:23:22 +03:00
switch ( type ) {
case hwmon_pwm :
switch ( attr ) {
case hwmon_pwm_input :
* val = dac_to_pwm ( data - > dac ,
data - > config & MAX6650_CFG_V12 ) ;
break ;
case hwmon_pwm_enable :
/*
* Possible values :
* 0 = Fan always on
* 1 = Open loop , Voltage is set according to speed ,
* not regulated .
* 2 = Closed loop , RPM for all fans regulated by fan1
* tachometer
* 3 = Fan off
*/
mode = ( data - > config & MAX6650_CFG_MODE_MASK ) > > 4 ;
* val = ( 4 - mode ) & 3 ; /* {0 1 2 3} -> {0 3 2 1} */
break ;
default :
return - EOPNOTSUPP ;
}
break ;
case hwmon_fan :
switch ( attr ) {
case hwmon_fan_input :
/*
* Calculation details :
*
* Each tachometer counts over an interval given by the
* " count " register ( 0.25 , 0.5 , 1 or 2 seconds ) .
* The driver assumes that the fans produce two pulses
* per revolution ( this seems to be the most common ) .
*/
* val = DIV_ROUND_CLOSEST ( data - > tach [ channel ] * 120 ,
DIV_FROM_REG ( data - > count ) ) ;
break ;
case hwmon_fan_div :
* val = DIV_FROM_REG ( data - > count ) ;
break ;
case hwmon_fan_target :
/*
* Use the datasheet equation :
* FanSpeed = KSCALE x fCLK / [ 256 x ( KTACH + 1 ) ]
* then multiply by 60 to give rpm .
*/
* val = 60 * DIV_FROM_REG ( data - > config ) * clock /
( 256 * ( data - > speed + 1 ) ) ;
break ;
case hwmon_fan_min_alarm :
* val = ! ! ( data - > alarm & MAX6650_ALRM_MIN ) ;
data - > alarm & = ~ MAX6650_ALRM_MIN ;
data - > valid = false ;
break ;
case hwmon_fan_max_alarm :
* val = ! ! ( data - > alarm & MAX6650_ALRM_MAX ) ;
data - > alarm & = ~ MAX6650_ALRM_MAX ;
data - > valid = false ;
break ;
case hwmon_fan_fault :
* val = ! ! ( data - > alarm & MAX6650_ALRM_TACH ) ;
data - > alarm & = ~ MAX6650_ALRM_TACH ;
data - > valid = false ;
break ;
default :
return - EOPNOTSUPP ;
}
break ;
default :
return - EOPNOTSUPP ;
}
return 0 ;
}
static const u8 max6650_pwm_modes [ ] = {
MAX6650_CFG_MODE_ON ,
MAX6650_CFG_MODE_OPEN_LOOP ,
MAX6650_CFG_MODE_CLOSED_LOOP ,
MAX6650_CFG_MODE_OFF ,
} ;
static int max6650_write ( struct device * dev , enum hwmon_sensor_types type ,
u32 attr , int channel , long val )
{
struct max6650_data * data = dev_get_drvdata ( dev ) ;
int ret = 0 ;
u8 reg ;
mutex_lock ( & data - > update_lock ) ;
switch ( type ) {
case hwmon_pwm :
switch ( attr ) {
case hwmon_pwm_input :
reg = pwm_to_dac ( clamp_val ( val , 0 , 255 ) ,
data - > config & MAX6650_CFG_V12 ) ;
ret = i2c_smbus_write_byte_data ( data - > client ,
MAX6650_REG_DAC , reg ) ;
if ( ret )
break ;
data - > dac = reg ;
break ;
case hwmon_pwm_enable :
if ( val < 0 | | val > = ARRAY_SIZE ( max6650_pwm_modes ) ) {
ret = - EINVAL ;
break ;
}
ret = max6650_set_operating_mode ( data ,
max6650_pwm_modes [ val ] ) ;
break ;
default :
ret = - EOPNOTSUPP ;
break ;
}
break ;
case hwmon_fan :
switch ( attr ) {
case hwmon_fan_div :
switch ( val ) {
case 1 :
reg = 0 ;
break ;
case 2 :
reg = 1 ;
break ;
case 4 :
reg = 2 ;
break ;
case 8 :
reg = 3 ;
break ;
default :
ret = - EINVAL ;
goto error ;
}
ret = i2c_smbus_write_byte_data ( data - > client ,
MAX6650_REG_COUNT , reg ) ;
if ( ret )
break ;
data - > count = reg ;
break ;
case hwmon_fan_target :
if ( val < 0 ) {
ret = - EINVAL ;
break ;
}
ret = max6650_set_target ( data , val ) ;
break ;
default :
ret = - EOPNOTSUPP ;
break ;
}
break ;
default :
ret = - EOPNOTSUPP ;
break ;
}
error :
mutex_unlock ( & data - > update_lock ) ;
return ret ;
}
static umode_t max6650_is_visible ( const void * _data ,
enum hwmon_sensor_types type , u32 attr ,
int channel )
{
const struct max6650_data * data = _data ;
if ( channel & & ( channel > = data - > nr_fans | | type ! = hwmon_fan ) )
return 0 ;
switch ( type ) {
case hwmon_fan :
switch ( attr ) {
case hwmon_fan_input :
return 0444 ;
case hwmon_fan_target :
case hwmon_fan_div :
return 0644 ;
case hwmon_fan_min_alarm :
if ( data - > alarm_en & MAX6650_ALRM_MIN )
return 0444 ;
break ;
case hwmon_fan_max_alarm :
if ( data - > alarm_en & MAX6650_ALRM_MAX )
return 0444 ;
break ;
case hwmon_fan_fault :
if ( data - > alarm_en & MAX6650_ALRM_TACH )
return 0444 ;
break ;
default :
break ;
}
break ;
case hwmon_pwm :
switch ( attr ) {
case hwmon_pwm_input :
case hwmon_pwm_enable :
return 0644 ;
default :
break ;
}
break ;
default :
break ;
}
return 0 ;
}
static const struct hwmon_channel_info * max6650_info [ ] = {
HWMON_CHANNEL_INFO ( fan , HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_DIV |
HWMON_F_MIN_ALARM | HWMON_F_MAX_ALARM |
HWMON_F_FAULT ,
HWMON_F_INPUT , HWMON_F_INPUT , HWMON_F_INPUT ) ,
HWMON_CHANNEL_INFO ( pwm , HWMON_PWM_INPUT | HWMON_PWM_ENABLE ) ,
NULL
} ;
static const struct hwmon_ops max6650_hwmon_ops = {
. read = max6650_read ,
. write = max6650_write ,
. is_visible = max6650_is_visible ,
} ;
static const struct hwmon_chip_info max6650_chip_info = {
. ops = & max6650_hwmon_ops ,
. info = max6650_info ,
} ;
2020-08-13 19:02:22 +03:00
static const struct i2c_device_id max6650_id [ ] ;
static int max6650_probe ( struct i2c_client * client )
2007-05-08 19:22:00 +04:00
{
2019-06-07 20:23:16 +03:00
struct thermal_cooling_device * cooling_dev ;
2014-02-12 10:43:54 +04:00
struct device * dev = & client - > dev ;
2016-08-22 09:47:51 +03:00
const struct of_device_id * of_id =
of_match_device ( of_match_ptr ( max6650_dt_match ) , dev ) ;
2014-02-12 10:26:12 +04:00
struct max6650_data * data ;
2014-02-12 10:37:01 +04:00
struct device * hwmon_dev ;
2014-02-12 10:26:12 +04:00
int err ;
2007-05-08 19:22:00 +04:00
2014-02-12 10:43:54 +04:00
data = devm_kzalloc ( dev , sizeof ( struct max6650_data ) , GFP_KERNEL ) ;
2014-02-12 10:40:33 +04:00
if ( ! data )
2014-02-12 10:26:12 +04:00
return - ENOMEM ;
2007-05-08 19:22:00 +04:00
2014-02-12 10:37:01 +04:00
data - > client = client ;
2019-04-19 03:57:22 +03:00
i2c_set_clientdata ( client , data ) ;
2014-02-12 10:26:12 +04:00
mutex_init ( & data - > update_lock ) ;
2020-08-13 19:02:22 +03:00
data - > nr_fans = of_id ? ( int ) ( uintptr_t ) of_id - > data :
i2c_match_id ( max6650_id , client ) - > driver_data ;
2007-05-08 19:22:00 +04:00
2014-02-12 10:26:12 +04:00
/*
* Initialize the max6650 chip
*/
2014-02-12 10:37:01 +04:00
err = max6650_init_client ( data , client ) ;
2014-02-12 10:26:12 +04:00
if ( err )
return err ;
2009-06-15 20:39:52 +04:00
2019-06-07 20:23:22 +03:00
hwmon_dev = devm_hwmon_device_register_with_info ( dev ,
client - > name , data ,
& max6650_chip_info ,
max6650_groups ) ;
2019-04-19 03:57:22 +03:00
err = PTR_ERR_OR_ZERO ( hwmon_dev ) ;
if ( err )
return err ;
2019-06-17 15:34:30 +03:00
if ( IS_ENABLED ( CONFIG_THERMAL ) ) {
cooling_dev = devm_thermal_of_cooling_device_register ( dev ,
dev - > of_node , client - > name ,
data , & max6650_cooling_ops ) ;
if ( IS_ERR ( cooling_dev ) ) {
dev_warn ( dev , " thermal cooling device register failed: %ld \n " ,
PTR_ERR ( cooling_dev ) ) ;
}
2019-06-07 20:23:16 +03:00
}
2019-06-17 15:34:30 +03:00
2019-04-19 03:57:22 +03:00
return 0 ;
}
2014-02-12 10:26:12 +04:00
static const struct i2c_device_id max6650_id [ ] = {
{ " max6650 " , 1 } ,
{ " max6651 " , 4 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , max6650_id ) ;
static struct i2c_driver max6650_driver = {
. driver = {
. name = " max6650 " ,
2016-08-22 09:47:51 +03:00
. of_match_table = of_match_ptr ( max6650_dt_match ) ,
2014-02-12 10:26:12 +04:00
} ,
2020-08-13 19:02:22 +03:00
. probe_new = max6650_probe ,
2014-02-12 10:26:12 +04:00
. id_table = max6650_id ,
} ;
2012-01-20 11:38:18 +04:00
module_i2c_driver ( max6650_driver ) ;
2007-05-08 19:22:00 +04:00
MODULE_AUTHOR ( " Hans J. Koch " ) ;
MODULE_DESCRIPTION ( " MAX6650 sensor driver " ) ;
MODULE_LICENSE ( " GPL " ) ;