mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
2255893444
Commit10a0575ea0
("hwmon: (nct6775-i2c) Use i2c_get_match_data()") introduced calling i2c_get_match_data() to the nct6775 driver. As part of that commit, enum kinds was changed to start with 1, based on Adjust the 'kinds' enum to not use 0, so that no match data can be distinguished from a valid enum value. The patch had to be fixed later with commit2792fc8f8c
("hwmon: (nct6775-core) Explicitly initialize nct6775_device_names indexes") and commitefe86092ab
("hwmon: (nct6775-platform) Explicitly initialize nct6775_sio_names indexes"). Various patches submitted later show that the change from 0 to 1 is not really necessary. As it turns out, it is perfectly fine as long as there is an i2c_device_id array with the same data as in the of_device_id array. This data is used as fallback if the data pointer in struct of_device_id is NULL (0). Let enum chips start with 0 to avoid confusion against other drivers where the enum starts with 0 and i2c_get_match_data() is used as well. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
272 lines
7.2 KiB
C
272 lines
7.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
#ifndef __HWMON_NCT6775_H__
|
|
#define __HWMON_NCT6775_H__
|
|
|
|
#include <linux/types.h>
|
|
|
|
enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792,
|
|
nct6793, nct6795, nct6796, nct6797, nct6798, nct6799 };
|
|
enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
|
|
|
|
#define NUM_TEMP 12 /* Max number of temp attribute sets w/ limits*/
|
|
#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
|
|
#define NUM_TSI_TEMP 8 /* Max number of TSI temp register pairs */
|
|
|
|
#define NUM_REG_ALARM 7 /* Max number of alarm registers */
|
|
#define NUM_REG_BEEP 5 /* Max number of beep registers */
|
|
|
|
#define NUM_FAN 7
|
|
#define NUM_IN 18
|
|
|
|
struct nct6775_data {
|
|
int addr; /* IO base of hw monitor block */
|
|
int sioreg; /* SIO register address */
|
|
enum kinds kind;
|
|
const char *name;
|
|
|
|
const struct attribute_group *groups[7];
|
|
u8 num_groups;
|
|
|
|
u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
|
|
* 3=temp_crit, 4=temp_lcrit
|
|
*/
|
|
u8 temp_src[NUM_TEMP];
|
|
u16 reg_temp_config[NUM_TEMP];
|
|
const char * const *temp_label;
|
|
u32 temp_mask;
|
|
u32 virt_temp_mask;
|
|
|
|
u16 REG_CONFIG;
|
|
u16 REG_VBAT;
|
|
u16 REG_DIODE;
|
|
u8 DIODE_MASK;
|
|
|
|
const s8 *ALARM_BITS;
|
|
const s8 *BEEP_BITS;
|
|
|
|
const u16 *REG_VIN;
|
|
const u16 *REG_IN_MINMAX[2];
|
|
|
|
const u16 *REG_TARGET;
|
|
const u16 *REG_FAN;
|
|
const u16 *REG_FAN_MODE;
|
|
const u16 *REG_FAN_MIN;
|
|
const u16 *REG_FAN_PULSES;
|
|
const u16 *FAN_PULSE_SHIFT;
|
|
const u16 *REG_FAN_TIME[3];
|
|
|
|
const u16 *REG_TOLERANCE_H;
|
|
|
|
const u8 *REG_PWM_MODE;
|
|
const u8 *PWM_MODE_MASK;
|
|
|
|
const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
|
|
* [3]=pwm_max, [4]=pwm_step,
|
|
* [5]=weight_duty_step, [6]=weight_duty_base
|
|
*/
|
|
const u16 *REG_PWM_READ;
|
|
|
|
const u16 *REG_CRITICAL_PWM_ENABLE;
|
|
u8 CRITICAL_PWM_ENABLE_MASK;
|
|
const u16 *REG_CRITICAL_PWM;
|
|
|
|
const u16 *REG_AUTO_TEMP;
|
|
const u16 *REG_AUTO_PWM;
|
|
|
|
const u16 *REG_CRITICAL_TEMP;
|
|
const u16 *REG_CRITICAL_TEMP_TOLERANCE;
|
|
|
|
const u16 *REG_TEMP_SOURCE; /* temp register sources */
|
|
const u16 *REG_TEMP_SEL;
|
|
const u16 *REG_WEIGHT_TEMP_SEL;
|
|
const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
|
|
|
|
const u16 *REG_TEMP_OFFSET;
|
|
|
|
const u16 *REG_ALARM;
|
|
const u16 *REG_BEEP;
|
|
|
|
const u16 *REG_TSI_TEMP;
|
|
|
|
unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
|
|
unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
|
|
|
|
struct mutex update_lock;
|
|
bool valid; /* true if following fields are valid */
|
|
unsigned long last_updated; /* In jiffies */
|
|
|
|
/* Register values */
|
|
u8 bank; /* current register bank */
|
|
u8 in_num; /* number of in inputs we have */
|
|
u8 in[NUM_IN][3]; /* [0]=in, [1]=in_max, [2]=in_min */
|
|
const u16 *scale_in; /* internal scaling factors */
|
|
unsigned int rpm[NUM_FAN];
|
|
u16 fan_min[NUM_FAN];
|
|
u8 fan_pulses[NUM_FAN];
|
|
u8 fan_div[NUM_FAN];
|
|
u8 has_pwm;
|
|
u8 has_fan; /* some fan inputs can be disabled */
|
|
u8 has_fan_min; /* some fans don't have min register */
|
|
bool has_fan_div;
|
|
|
|
u8 num_temp_alarms; /* 2, 3, or 6 */
|
|
u8 num_temp_beeps; /* 2, 3, or 6 */
|
|
u8 temp_fixed_num; /* 3 or 6 */
|
|
u8 temp_type[NUM_TEMP_FIXED];
|
|
s8 temp_offset[NUM_TEMP_FIXED];
|
|
s16 temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
|
|
* 3=temp_crit, 4=temp_lcrit
|
|
*/
|
|
s16 tsi_temp[NUM_TSI_TEMP];
|
|
u64 alarms;
|
|
u64 beeps;
|
|
|
|
u8 pwm_num; /* number of pwm */
|
|
u8 pwm_mode[NUM_FAN]; /* 0->DC variable voltage,
|
|
* 1->PWM variable duty cycle
|
|
*/
|
|
enum pwm_enable pwm_enable[NUM_FAN];
|
|
/* 0->off
|
|
* 1->manual
|
|
* 2->thermal cruise mode (also called SmartFan I)
|
|
* 3->fan speed cruise mode
|
|
* 4->SmartFan III
|
|
* 5->enhanced variable thermal cruise (SmartFan IV)
|
|
*/
|
|
u8 pwm[7][NUM_FAN]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
|
|
* [3]=pwm_max, [4]=pwm_step,
|
|
* [5]=weight_duty_step, [6]=weight_duty_base
|
|
*/
|
|
|
|
u8 target_temp[NUM_FAN];
|
|
u8 target_temp_mask;
|
|
u32 target_speed[NUM_FAN];
|
|
u32 target_speed_tolerance[NUM_FAN];
|
|
u8 speed_tolerance_limit;
|
|
|
|
u8 temp_tolerance[2][NUM_FAN];
|
|
u8 tolerance_mask;
|
|
|
|
u8 fan_time[3][NUM_FAN]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
|
|
|
|
/* Automatic fan speed control registers */
|
|
int auto_pwm_num;
|
|
u8 auto_pwm[NUM_FAN][7];
|
|
u8 auto_temp[NUM_FAN][7];
|
|
u8 pwm_temp_sel[NUM_FAN];
|
|
u8 pwm_weight_temp_sel[NUM_FAN];
|
|
u8 weight_temp[3][NUM_FAN]; /* 0->temp_step, 1->temp_step_tol,
|
|
* 2->temp_base
|
|
*/
|
|
|
|
u8 vid;
|
|
u8 vrm;
|
|
|
|
bool have_vid;
|
|
|
|
u16 have_temp;
|
|
u16 have_temp_fixed;
|
|
u16 have_tsi_temp;
|
|
u32 have_in;
|
|
|
|
/* Remember extra register values over suspend/resume */
|
|
u8 vbat;
|
|
u8 fandiv1;
|
|
u8 fandiv2;
|
|
u8 sio_reg_enable;
|
|
|
|
struct regmap *regmap;
|
|
bool read_only;
|
|
|
|
/* driver-specific (platform, i2c) initialization hook and data */
|
|
int (*driver_init)(struct nct6775_data *data);
|
|
void *driver_data;
|
|
};
|
|
|
|
static inline int nct6775_read_value(struct nct6775_data *data, u16 reg, u16 *value)
|
|
{
|
|
unsigned int tmp;
|
|
int ret = regmap_read(data->regmap, reg, &tmp);
|
|
|
|
if (!ret)
|
|
*value = tmp;
|
|
return ret;
|
|
}
|
|
|
|
static inline int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
|
|
{
|
|
return regmap_write(data->regmap, reg, value);
|
|
}
|
|
|
|
struct nct6775_data *nct6775_update_device(struct device *dev);
|
|
|
|
bool nct6775_reg_is_word_sized(struct nct6775_data *data, u16 reg);
|
|
int nct6775_probe(struct device *dev, struct nct6775_data *data,
|
|
const struct regmap_config *regmapcfg);
|
|
|
|
ssize_t nct6775_show_alarm(struct device *dev, struct device_attribute *attr, char *buf);
|
|
ssize_t nct6775_show_beep(struct device *dev, struct device_attribute *attr, char *buf);
|
|
ssize_t nct6775_store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
|
|
size_t count);
|
|
|
|
static inline int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
|
|
{
|
|
if (!nct6775_reg_is_word_sized(data, reg))
|
|
value >>= 8;
|
|
return nct6775_write_value(data, reg, value);
|
|
}
|
|
|
|
static inline umode_t nct6775_attr_mode(struct nct6775_data *data, struct attribute *attr)
|
|
{
|
|
return data->read_only ? (attr->mode & ~0222) : attr->mode;
|
|
}
|
|
|
|
static inline int
|
|
nct6775_add_attr_group(struct nct6775_data *data, const struct attribute_group *group)
|
|
{
|
|
/* Need to leave a NULL terminator at the end of data->groups */
|
|
if (data->num_groups == ARRAY_SIZE(data->groups) - 1)
|
|
return -ENOBUFS;
|
|
|
|
data->groups[data->num_groups++] = group;
|
|
return 0;
|
|
}
|
|
|
|
#define NCT6775_REG_BANK 0x4E
|
|
#define NCT6775_REG_CONFIG 0x40
|
|
|
|
#define NCT6775_REG_FANDIV1 0x506
|
|
#define NCT6775_REG_FANDIV2 0x507
|
|
|
|
#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
|
|
|
|
/*
|
|
* ALARM_BITS and BEEP_BITS store bit-index for the mask of the registers
|
|
* loaded into data->alarm and data->beep.
|
|
*
|
|
* Every input register (IN/TEMP/FAN) must have a corresponding
|
|
* ALARM/BEEP bit at the same index BITS[BASE + index]
|
|
* Set value to -1 to disable the visibility of that '*_alarm' attribute and
|
|
* to pad the bits until the next BASE
|
|
*
|
|
* Beep has an additional GLOBAL_BEEP_ENABLE bit
|
|
*/
|
|
#define VIN_ALARM_BASE 0
|
|
#define FAN_ALARM_BASE 24
|
|
#define TEMP_ALARM_BASE 36
|
|
#define INTRUSION_ALARM_BASE 48
|
|
#define BEEP_ENABLE_BASE 50
|
|
|
|
#define NUM_ALARM_BITS (INTRUSION_ALARM_BASE + 4)
|
|
#define NUM_BEEP_BITS (BEEP_ENABLE_BASE + 1)
|
|
|
|
/*
|
|
* Not currently used:
|
|
* REG_MAN_ID has the value 0x5ca3 for all supported chips.
|
|
* REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
|
|
* REG_MAN_ID is at port 0x4f
|
|
* REG_CHIP_ID is at port 0x58
|
|
*/
|
|
|
|
#endif /* __HWMON_NCT6775_H__ */
|