/*
* adt7475 - Thermal sensor driver for the ADT7475 chip and derivatives
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h>
#include <linux/err.h>
/* Indexes for the sysfs hooks */
#define INPUT 0
#define MIN 1
#define MAX 2
#define CONTROL 3
#define OFFSET 3
#define AUTOMIN 4
#define THERM 5
#define HYSTERSIS 6
/* These are unique identifiers for the sysfs functions - unlike the
numbers above, these are not also indexes into an array
*/
#define ALARM 9
#define FAULT 10
/* 7475 Common Registers */
#define REG_DEVREV2 0x12 /* ADT7490 only */
#define REG_VTT 0x1E /* ADT7490 only */
#define REG_EXTEND3 0x1F /* ADT7490 only */
#define REG_VOLTAGE_BASE 0x20
#define REG_TEMP_BASE 0x25
#define REG_TACH_BASE 0x28
#define REG_PWM_BASE 0x30
#define REG_PWM_MAX_BASE 0x38
#define REG_DEVID 0x3D
#define REG_VENDID 0x3E
#define REG_DEVID2 0x3F
#define REG_STATUS1 0x41
#define REG_STATUS2 0x42
#define REG_VID 0x43 /* ADT7476 only */
#define REG_VOLTAGE_MIN_BASE 0x44
#define REG_VOLTAGE_MAX_BASE 0x45
#define REG_TEMP_MIN_BASE 0x4E
#define REG_TEMP_MAX_BASE 0x4F
#define REG_TACH_MIN_BASE 0x54
#define REG_PWM_CONFIG_BASE 0x5C
#define REG_TEMP_TRANGE_BASE 0x5F
#define REG_PWM_MIN_BASE 0x64
#define REG_TEMP_TMIN_BASE 0x67
#define REG_TEMP_THERM_BASE 0x6A
#define REG_REMOTE1_HYSTERSIS 0x6D
#define REG_REMOTE2_HYSTERSIS 0x6E
#define REG_TEMP_OFFSET_BASE 0x70
#define REG_CONFIG2 0x73
#define REG_EXTEND1 0x76
#define REG_EXTEND2 0x77
#define REG_CONFIG3 0x78
#define REG_CONFIG5 0x7C
#define REG_CONFIG4 0x7D
#define REG_STATUS4 0x81 /* ADT7490 only */
#define REG_VTT_MIN 0x84 /* ADT7490 only */
#define REG_VTT_MAX 0x86 /* ADT7490 only */
#define VID_VIDSEL 0x80 /* ADT7476 only */
#define CONFIG2_ATTN 0x20
#define CONFIG3_SMBALERT 0x01
#define CONFIG3_THERM 0x02
#define CONFIG4_PINFUNC 0x03
#define CONFIG4_MAXDUTY 0x08
#define CONFIG4_ATTN_IN10 0x30
#define CONFIG4_ATTN_IN43 0xC0
#define CONFIG5_TWOSCOMP 0x01
#define CONFIG5_TEMPOFFSET 0x02
#define CONFIG5_VIDGPIO 0x10 /* ADT7476 only */
/* ADT7475 Settings */
#define ADT7475_VOLTAGE_COUNT 5 /* Not counting Vtt */
#define ADT7475_TEMP_COUNT 3
#define ADT7475_TACH_COUNT 4
#define ADT7475_PWM_COUNT 3
/* Macro to read the registers */
#define adt7475_read(reg) i2c_smbus_read_byte_data(client, (reg))
/* Macros to easily index the registers */
#define TACH_REG(idx) (REG_TACH_BASE + ((idx) * 2))
#define TACH_MIN_REG(idx) (REG_TACH_MIN_BASE + ((idx) * 2))
#define PWM_REG(idx) (REG_PWM_BASE + (idx))
#define PWM_MAX_REG(idx) (REG_PWM_MAX_BASE + (idx))
#define PWM_MIN_REG(idx) (REG_PWM_MIN_BASE + (idx))
#define PWM_CONFIG_REG(idx) (REG_PWM_CONFIG_BASE + (idx))
#define VOLTAGE_REG(idx) (REG_VOLTAGE_BASE + (idx))
#define VOLTAGE_MIN_REG(idx) (REG_VOLTAGE_MIN_BASE + ((idx) * 2))
#define VOLTAGE_MAX_REG(idx) (REG_VOLTAGE_MAX_BASE + ((idx) * 2))
#define TEMP_REG(idx) (REG_TEMP_BASE + (idx))
#define TEMP_MIN_REG(idx) (REG_TEMP_MIN_BASE + ((idx) * 2))
#define TEMP_MAX_REG(idx) (REG_TEMP_MAX_BASE + ((idx) * 2))
#define TEMP_TMIN_REG(idx) (REG_TEMP_TMIN_BASE + (idx))
#define TEMP_THERM_REG(idx) (REG_TEMP_THERM_BASE + (idx))
#define TEMP_OFFSET_REG(idx) (REG_TEMP_OFFSET_BASE + (idx))
#define TEMP_TRANGE_REG(idx) (REG_TEMP_TRANGE_BASE + (idx))
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
enum chips { adt7473, adt7475, adt7476, adt7490 };
static const struct i2c_device_id adt7475_id[] = {
{ "adt7473", adt7473 },
{ "adt7475", adt7475 },
{ "adt7476", adt7476 },
{ "adt7490", adt7490 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adt7475_id);
struct adt7475_data {
struct device *hwmon_dev;
struct mutex lock;
unsigned long measure_updated;
unsigned long limits_updated;
char valid;
u8 config4;
u8 config5;
u8 has_voltage;
u8 bypass_attn; /* Bypass voltage attenuator */
u8 has_pwm2:1;
u8 has_fan4:1;
u8 has_vid:1;
u32 alarms;
u16 voltage[3][6];
u16 temp[7][3];
u16 tach[2][4];
u8 pwm[4][3];
u8 range[3];
u8 pwmctl[3];
u8 pwmchan[3];
u8 vid;
u8 vrm;
};
static struct i2c_driver adt7475_driver;
static struct adt7475_data *adt7475_update_device(struct device *dev);
static void adt7475_read_hystersis(struct i2c_client *client);
static void adt7475_read_pwm(struct i2c_client *client, int index);
/* Given a temp value, convert it to register value */
static inline u16 temp2reg(struct adt7475_data *data, long val)
{
u16 ret;
if (!(data->config5 & CONFIG5_TWOSCOMP)) {
val = SENSORS_LIMIT(val, -64000, 191000);
ret = (val + 64500) / 1000;
} else {
val = SENSORS_LIMIT(val, -128000, 127000);
if (val < -500)
ret = (256500 + val) / 1000;
else
ret = (val + 500) / 1000;
}
return ret << 2;
}
/* Given a register value, convert it to a real temp value */
static inline int reg2temp(struct adt7475_data *data, u16 reg)
{
if (data->config5 & CONFIG5_TWOSCOMP) {
if (reg >= 512)
return (reg - 1024) * 250;
else
return reg * 250;
} else
return (reg - 256) * 250;
}
static inline int tach2rpm(u16 tach)
{
if (tach == 0 || tach == 0xFFFF)
return 0;
return (90000 * 60) / tach;
}
static inline u16 rpm2tach(unsigned long rpm)
{
if (rpm == 0)
return 0;
return SENSORS_LIMIT((90000 * 60) / rpm, 1, 0xFFFF);
}
/* Scaling factors for voltage inputs, taken from the ADT7490 datasheet */
static const int adt7473_in_scaling[ADT7475_VOLTAGE_COUNT + 1][2] = {
{ 45, 94 }, /* +2.5V */
{ 175, 525 }, /* Vccp */
{ 68, 71 }, /* Vcc */
{ 93, 47 }, /* +5V */
{ 120, 20 }, /* +12V */
{ 45, 45 }, /* Vtt */
};
static inline int reg2volt(int channel, u16 reg, u8 bypass_attn)
{
const int *r = adt7473_in_scaling[channel];
if (bypass_attn & (1 << channel))
return DIV_ROUND_CLOSEST(reg * 2250, 1024);
return DIV_ROUND_CLOSEST(reg * (r[0] + r[1]) * 2250, r[1] * 1024);
}
static inline u16 volt2reg(int channel, long volt, u8 bypass_attn)
{
const int *r = adt7473_in_scaling[channel];
long reg;
if (bypass_attn & (1 << channel))
reg = (volt * 1024) / 2250;
else
reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250);
return SENSORS_LIMIT(reg, 0, 1023) & (0xff << 2);
}
static u16 adt7475_read_word(struct i2c_client *client, int reg)
{
u16 val;
val = i2c_smbus_read_byte_data(client, reg);
val |= (i2c_smbus_read_byte_data(client, reg + 1) << 8);
return val;
}
static void adt7475_write_word(struct i2c_client *client, int reg, u16 val)
{
i2c_smbus_write_byte_data(client, reg + 1, val >> 8);
i2c_smbus_write_byte_data(client, reg, val & 0xFF);
}
/* Find the nearest value in a table - used for pwm frequency and
auto temp range */
static int find_nearest(long val, const int *array, int size)
{
int i;
if (val < array[0])
return 0;
if (val > array[size - 1])
return size - 1;
for (i = 0; i < size - 1; i++) {
int a, b;
if (val > array[i + 1])
continue;
a = val - array[i];
b = array[i + 1] - val;
return (a <= b) ? i : i + 1;
}
return 0;
}
static ssize_t show_voltage(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct adt7475_data *data = adt7475_update_device(dev);
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
unsigned short val;
switch (sattr->nr) {
case ALARM:
return sprintf(buf, "%d\n",
(data->alarms >> sattr->index) & 1);
default:
val = data->voltage[sattr->nr][sattr->index];
return sprintf(buf, "%d\n",
reg2volt(sattr->index, val, data->bypass_attn));
}
}
static ssize_t set_voltage(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
struct i2c_client *client = to_i2c_client(dev);
struct adt7475_data *data = i2c_get_clientdata(client);
unsigned char reg;
long val;
if (strict_strtol(buf, 10, &val))
return -EINVAL;
mutex_lock(&data->lock);
d