aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/w83627hf.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drivers/hwmon/w83627hf.c1600
1 files changed, 802 insertions, 798 deletions
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 9be277156ed2..b638d672ac45 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -389,14 +389,184 @@ struct w83627hf_data {
#endif
};
-static int w83627hf_probe(struct platform_device *pdev);
-static int w83627hf_remove(struct platform_device *pdev);
+/* Registers 0x50-0x5f are banked */
+static inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg)
+{
+ if ((reg & 0x00f0) == 0x50) {
+ outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
+ outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET);
+ }
+}
+
+/* Not strictly necessary, but play it safe for now */
+static inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg)
+{
+ if (reg & 0xff00) {
+ outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
+ outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
+ }
+}
+
+static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
+{
+ int res, word_sized;
+
+ mutex_lock(&data->lock);
+ word_sized = (((reg & 0xff00) == 0x100)
+ || ((reg & 0xff00) == 0x200))
+ && (((reg & 0x00ff) == 0x50)
+ || ((reg & 0x00ff) == 0x53)
+ || ((reg & 0x00ff) == 0x55));
+ w83627hf_set_bank(data, reg);
+ outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
+ res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
+ if (word_sized) {
+ outb_p((reg & 0xff) + 1,
+ data->addr + W83781D_ADDR_REG_OFFSET);
+ res =
+ (res << 8) + inb_p(data->addr +
+ W83781D_DATA_REG_OFFSET);
+ }
+ w83627hf_reset_bank(data, reg);
+ mutex_unlock(&data->lock);
+ return res;
+}
+
+static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
+{
+ int word_sized;
+
+ mutex_lock(&data->lock);
+ word_sized = (((reg & 0xff00) == 0x100)
+ || ((reg & 0xff00) == 0x200))
+ && (((reg & 0x00ff) == 0x53)
+ || ((reg & 0x00ff) == 0x55));
+ w83627hf_set_bank(data, reg);
+ outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
+ if (word_sized) {
+ outb_p(value >> 8,
+ data->addr + W83781D_DATA_REG_OFFSET);
+ outb_p((reg & 0xff) + 1,
+ data->addr + W83781D_ADDR_REG_OFFSET);
+ }
+ outb_p(value & 0xff,
+ data->addr + W83781D_DATA_REG_OFFSET);
+ w83627hf_reset_bank(data, reg);
+ mutex_unlock(&data->lock);
+ return 0;
+}
+
+static void w83627hf_update_fan_div(struct w83627hf_data *data)
+{
+ int reg;
+
+ reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
+ data->fan_div[0] = (reg >> 4) & 0x03;
+ data->fan_div[1] = (reg >> 6) & 0x03;
+ if (data->type != w83697hf) {
+ data->fan_div[2] = (w83627hf_read_value(data,
+ W83781D_REG_PIN) >> 6) & 0x03;
+ }
+ reg = w83627hf_read_value(data, W83781D_REG_VBAT);
+ data->fan_div[0] |= (reg >> 3) & 0x04;
+ data->fan_div[1] |= (reg >> 4) & 0x04;
+ if (data->type != w83697hf)
+ data->fan_div[2] |= (reg >> 5) & 0x04;
+}
-static int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
-static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
-static void w83627hf_update_fan_div(struct w83627hf_data *data);
-static struct w83627hf_data *w83627hf_update_device(struct device *dev);
-static void w83627hf_init_device(struct platform_device *pdev);
+static struct w83627hf_data *w83627hf_update_device(struct device *dev)
+{
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ int i, num_temps = (data->type == w83697hf) ? 2 : 3;
+ int num_pwms = (data->type == w83697hf) ? 2 : 3;
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
+ for (i = 0; i <= 8; i++) {
+ /* skip missing sensors */
+ if (((data->type == w83697hf) && (i == 1)) ||
+ ((data->type != w83627hf && data->type != w83697hf)
+ && (i == 5 || i == 6)))
+ continue;
+ data->in[i] =
+ w83627hf_read_value(data, W83781D_REG_IN(i));
+ data->in_min[i] =
+ w83627hf_read_value(data,
+ W83781D_REG_IN_MIN(i));
+ data->in_max[i] =
+ w83627hf_read_value(data,
+ W83781D_REG_IN_MAX(i));
+ }
+ for (i = 0; i <= 2; i++) {
+ data->fan[i] =
+ w83627hf_read_value(data, W83627HF_REG_FAN(i));
+ data->fan_min[i] =
+ w83627hf_read_value(data,
+ W83627HF_REG_FAN_MIN(i));
+ }
+ for (i = 0; i <= 2; i++) {
+ u8 tmp = w83627hf_read_value(data,
+ W836X7HF_REG_PWM(data->type, i));
+ /* bits 0-3 are reserved in 627THF */
+ if (data->type == w83627thf)
+ tmp &= 0xf0;
+ data->pwm[i] = tmp;
+ if (i == 1 &&
+ (data->type == w83627hf || data->type == w83697hf))
+ break;
+ }
+ if (data->type == w83627hf) {
+ u8 tmp = w83627hf_read_value(data,
+ W83627HF_REG_PWM_FREQ);
+ data->pwm_freq[0] = tmp & 0x07;
+ data->pwm_freq[1] = (tmp >> 4) & 0x07;
+ } else if (data->type != w83627thf) {
+ for (i = 1; i <= 3; i++) {
+ data->pwm_freq[i - 1] =
+ w83627hf_read_value(data,
+ W83637HF_REG_PWM_FREQ[i - 1]);
+ if (i == 2 && (data->type == w83697hf))
+ break;
+ }
+ }
+ if (data->type != w83627hf) {
+ for (i = 0; i < num_pwms; i++) {
+ u8 tmp = w83627hf_read_value(data,
+ W83627THF_REG_PWM_ENABLE[i]);
+ data->pwm_enable[i] =
+ ((tmp >> W83627THF_PWM_ENABLE_SHIFT[i])
+ & 0x03) + 1;
+ }
+ }
+ for (i = 0; i < num_temps; i++) {
+ data->temp[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp[i]);
+ data->temp_max[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp_over[i]);
+ data->temp_max_hyst[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp_hyst[i]);
+ }
+
+ w83627hf_update_fan_div(data);
+
+ data->alarms =
+ w83627hf_read_value(data, W83781D_REG_ALARM1) |
+ (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
+ (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
+ i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
+ data->beep_mask = (i << 8) |
+ w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
+ w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
+ data->last_updated = jiffies;
+ data->valid = true;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
#ifdef CONFIG_PM
static int w83627hf_suspend(struct device *dev)
@@ -464,99 +634,171 @@ static const struct dev_pm_ops w83627hf_dev_pm_ops = {
#define W83627HF_DEV_PM_OPS NULL
#endif /* CONFIG_PM */
-static struct platform_driver w83627hf_driver = {
- .driver = {
- .name = DRVNAME,
- .pm = W83627HF_DEV_PM_OPS,
- },
- .probe = w83627hf_probe,
- .remove = w83627hf_remove,
-};
-
-static ssize_t
-in_input_show(struct device *dev, struct device_attribute *devattr, char *buf)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = w83627hf_update_device(dev);
- return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in[nr]));
-}
-static ssize_t
-in_min_show(struct device *dev, struct device_attribute *devattr, char *buf)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = w83627hf_update_device(dev);
- return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_min[nr]));
-}
-static ssize_t
-in_max_show(struct device *dev, struct device_attribute *devattr, char *buf)
+static int w83627thf_read_gpio5(struct platform_device *pdev)
{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = w83627hf_update_device(dev);
- return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_max[nr]));
+ struct w83627hf_sio_data *sio_data = dev_get_platdata(&pdev->dev);
+ int res = 0xff, sel;
+
+ if (superio_enter(sio_data)) {
+ /*
+ * Some other driver reserved the address space for itself.
+ * We don't want to fail driver instantiation because of that,
+ * so display a warning and keep going.
+ */
+ dev_warn(&pdev->dev,
+ "Can not read VID data: Failed to enable SuperIO access\n");
+ return res;
+ }
+
+ superio_select(sio_data, W83627HF_LD_GPIO5);
+
+ res = 0xff;
+
+ /* Make sure these GPIO pins are enabled */
+ if (!(superio_inb(sio_data, W83627THF_GPIO5_EN) & (1<<3))) {
+ dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n");
+ goto exit;
+ }
+
+ /*
+ * Make sure the pins are configured for input
+ * There must be at least five (VRM 9), and possibly 6 (VRM 10)
+ */
+ sel = superio_inb(sio_data, W83627THF_GPIO5_IOSR) & 0x3f;
+ if ((sel & 0x1f) != 0x1f) {
+ dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
+ "function\n");
+ goto exit;
+ }
+
+ dev_info(&pdev->dev, "Reading VID from GPIO5\n");
+ res = superio_inb(sio_data, W83627THF_GPIO5_DR) & sel;
+
+exit:
+ superio_exit(sio_data);
+ return res;
}
-static ssize_t
-in_min_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+
+static int w83687thf_read_vid(struct platform_device *pdev)
{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = dev_get_drvdata(dev);
- long val;
- int err;
+ struct w83627hf_sio_data *sio_data = dev_get_platdata(&pdev->dev);
+ int res = 0xff;
- err = kstrtol(buf, 10, &val);
- if (err)
- return err;
+ if (superio_enter(sio_data)) {
+ /*
+ * Some other driver reserved the address space for itself.
+ * We don't want to fail driver instantiation because of that,
+ * so display a warning and keep going.
+ */
+ dev_warn(&pdev->dev,
+ "Can not read VID data: Failed to enable SuperIO access\n");
+ return res;
+ }
- mutex_lock(&data->update_lock);
- data->in_min[nr] = IN_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]);
- mutex_unlock(&data->update_lock);
- return count;
+ superio_select(sio_data, W83627HF_LD_HWM);
+
+ /* Make sure these GPIO pins are enabled */
+ if (!(superio_inb(sio_data, W83687THF_VID_EN) & (1 << 2))) {
+ dev_dbg(&pdev->dev, "VID disabled, no VID function\n");
+ goto exit;
+ }
+
+ /* Make sure the pins are configured for input */
+ if (!(superio_inb(sio_data, W83687THF_VID_CFG) & (1 << 4))) {
+ dev_dbg(&pdev->dev, "VID configured as output, "
+ "no VID function\n");
+ goto exit;
+ }
+
+ res = superio_inb(sio_data, W83687THF_VID_DATA) & 0x3f;
+
+exit:
+ superio_exit(sio_data);
+ return res;
}
-static ssize_t
-in_max_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+
+static void w83627hf_init_device(struct platform_device *pdev)
{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = dev_get_drvdata(dev);
- long val;
- int err;
+ struct w83627hf_data *data = platform_get_drvdata(pdev);
+ int i;
+ enum chips type = data->type;
+ u8 tmp;
- err = kstrtol(buf, 10, &val);
- if (err)
- return err;
+ /* Minimize conflicts with other winbond i2c-only clients... */
+ /* disable i2c subclients... how to disable main i2c client?? */
+ /* force i2c address to relatively uncommon address */
+ if (type == w83627hf) {
+ w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
+ w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
+ }
- mutex_lock(&data->update_lock);
- data->in_max[nr] = IN_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]);
- mutex_unlock(&data->update_lock);
- return count;
-}
+ /* Read VID only once */
+ if (type == w83627hf || type == w83637hf) {
+ int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
+ int hi = w83627hf_read_value(data, W83781D_REG_CHIPID);
+ data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
+ } else if (type == w83627thf) {
+ data->vid = w83627thf_read_gpio5(pdev);
+ } else if (type == w83687thf) {
+ data->vid = w83687thf_read_vid(pdev);
+ }
-static SENSOR_DEVICE_ATTR_RO(in1_input, in_input, 1);
-static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1);
-static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1);
-static SENSOR_DEVICE_ATTR_RO(in2_input, in_input, 2);
-static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2);
-static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2);
-static SENSOR_DEVICE_ATTR_RO(in3_input, in_input, 3);
-static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3);
-static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3);
-static SENSOR_DEVICE_ATTR_RO(in4_input, in_input, 4);
-static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4);
-static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4);
-static SENSOR_DEVICE_ATTR_RO(in5_input, in_input, 5);
-static SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 5);
-static SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 5);
-static SENSOR_DEVICE_ATTR_RO(in6_input, in_input, 6);
-static SENSOR_DEVICE_ATTR_RW(in6_min, in_min, 6);
-static SENSOR_DEVICE_ATTR_RW(in6_max, in_max, 6);
-static SENSOR_DEVICE_ATTR_RO(in7_input, in_input, 7);
-static SENSOR_DEVICE_ATTR_RW(in7_min, in_min, 7);
-static SENSOR_DEVICE_ATTR_RW(in7_max, in_max, 7);
-static SENSOR_DEVICE_ATTR_RO(in8_input, in_input, 8);
-static SENSOR_DEVICE_ATTR_RW(in8_min, in_min, 8);
-static SENSOR_DEVICE_ATTR_RW(in8_max, in_max, 8);
+ /* Read VRM & OVT Config only once */
+ if (type == w83627thf || type == w83637hf || type == w83687thf) {
+ data->vrm_ovt =
+ w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG);
+ }
+
+ tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
+ for (i = 1; i <= 3; i++) {
+ if (!(tmp & BIT_SCFG1[i - 1])) {
+ data->sens[i - 1] = 4;
+ } else {
+ if (w83627hf_read_value
+ (data,
+ W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
+ data->sens[i - 1] = 1;
+ else
+ data->sens[i - 1] = 2;
+ }
+ if ((type == w83697hf) && (i == 2))
+ break;
+ }
+
+ if(init) {
+ /* Enable temp2 */
+ tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
+ if (tmp & 0x01) {
+ dev_warn(&pdev->dev, "Enabling temp2, readings "
+ "might not make sense\n");
+ w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
+ tmp & 0xfe);
+ }
+
+ /* Enable temp3 */
+ if (type != w83697hf) {
+ tmp = w83627hf_read_value(data,
+ W83627HF_REG_TEMP3_CONFIG);
+ if (tmp & 0x01) {
+ dev_warn(&pdev->dev, "Enabling temp3, "
+ "readings might not make sense\n");
+ w83627hf_write_value(data,
+ W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
+ }
+ }
+ }
+
+ /* Start monitoring */
+ w83627hf_write_value(data, W83781D_REG_CONFIG,
+ (w83627hf_read_value(data,
+ W83781D_REG_CONFIG) & 0xf7)
+ | 0x01);
+
+ /* Enable VBAT monitoring if needed */
+ tmp = w83627hf_read_value(data, W83781D_REG_VBAT);
+ if (!(tmp & 0x01))
+ w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01);
+}
/* use a different set of functions for in0 */
static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
@@ -582,6 +824,7 @@ static ssize_t in0_input_show(struct device *dev,
struct w83627hf_data *data = w83627hf_update_device(dev);
return show_in_0(data, buf, data->in[0]);
}
+static DEVICE_ATTR_RO(in0_input);
static ssize_t in0_min_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -590,13 +833,6 @@ static ssize_t in0_min_show(struct device *dev, struct device_attribute *attr,
return show_in_0(data, buf, data->in_min[0]);
}
-static ssize_t in0_max_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct w83627hf_data *data = w83627hf_update_device(dev);
- return show_in_0(data, buf, data->in_max[0]);
-}
-
static ssize_t in0_min_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
@@ -627,6 +863,15 @@ static ssize_t in0_min_store(struct device *dev,
return count;
}
+static DEVICE_ATTR_RW(in0_min);
+
+static ssize_t in0_max_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return show_in_0(data, buf, data->in_max[0]);
+}
+
static ssize_t in0_max_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
@@ -657,193 +902,16 @@ static ssize_t in0_max_store(struct device *dev,
return count;
}
-static DEVICE_ATTR_RO(in0_input);
-static DEVICE_ATTR_RW(in0_min);
static DEVICE_ATTR_RW(in0_max);
static ssize_t
-fan_input_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = w83627hf_update_device(dev);
- return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan[nr],
- (long)DIV_FROM_REG(data->fan_div[nr])));
-}
-static ssize_t
-fan_min_show(struct device *dev, struct device_attribute *devattr, char *buf)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = w83627hf_update_device(dev);
- return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan_min[nr],
- (long)DIV_FROM_REG(data->fan_div[nr])));
-}
-static ssize_t
-fan_min_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = dev_get_drvdata(dev);
- unsigned long val;
- int err;
-
- err = kstrtoul(buf, 10, &val);
- if (err)
- return err;
-
- mutex_lock(&data->update_lock);
- data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
- w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
- data->fan_min[nr]);
-
- mutex_unlock(&data->update_lock);
- return count;
-}
-
-static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0);
-static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
-static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1);
-static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
-static SENSOR_DEVICE_ATTR_RO(fan3_input, fan_input, 2);
-static SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2);
-
-static ssize_t
-temp_show(struct device *dev, struct device_attribute *devattr, char *buf)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = w83627hf_update_device(dev);
-
- u16 tmp = data->temp[nr];
- return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
- : (long) TEMP_FROM_REG(tmp));
-}
-
-static ssize_t
-temp_max_show(struct device *dev, struct device_attribute *devattr, char *buf)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = w83627hf_update_device(dev);
-
- u16 tmp = data->temp_max[nr];
- return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
- : (long) TEMP_FROM_REG(tmp));
-}
-
-static ssize_t
-temp_max_hyst_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = w83627hf_update_device(dev);
-
- u16 tmp = data->temp_max_hyst[nr];
- return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
- : (long) TEMP_FROM_REG(tmp));
-}
-
-static ssize_t
-temp_max_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = dev_get_drvdata(dev);
- u16 tmp;
- long val;
- int err;
-
- err = kstrtol(buf, 10, &val);
- if (err)
- return err;
-
- tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
- mutex_lock(&data->update_lock);
- data->temp_max[nr] = tmp;
- w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
- mutex_unlock(&data->update_lock);
- return count;
-}
-
-static ssize_t
-temp_max_hyst_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = dev_get_drvdata(dev);
- u16 tmp;
- long val;
- int err;
-
- err = kstrtol(buf, 10, &val);
- if (err)
- return err;
-
- tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
- mutex_lock(&data->update_lock);
- data->temp_max_hyst[nr] = tmp;
- w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
- mutex_unlock(&data->update_lock);
- return count;
-}
-
-static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
-static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
-static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp_max_hyst, 0);
-static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
-static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
-static SENSOR_DEVICE_ATTR_RW(temp2_max_hyst, temp_max_hyst, 1);
-static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
-static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2);
-static SENSOR_DEVICE_ATTR_RW(temp3_max_hyst, temp_max_hyst, 2);
-
-static ssize_t
-cpu0_vid_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w83627hf_data *data = w83627hf_update_device(dev);
- return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
-}
-static DEVICE_ATTR_RO(cpu0_vid);
-
-static ssize_t
-vrm_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w83627hf_data *data = dev_get_drvdata(dev);
- return sprintf(buf, "%ld\n", (long) data->vrm);
-}
-static ssize_t
-vrm_store(struct device *dev, struct device_attribute *attr, const char *buf,
- size_t count)
-{
- struct w83627hf_data *data = dev_get_drvdata(dev);
- unsigned long val;
- int err;
-
- err = kstrtoul(buf, 10, &val);
- if (err)
- return err;
-
- if (val > 255)
- return -EINVAL;
- data->vrm = val;
-
- return count;
-}
-static DEVICE_ATTR_RW(vrm);
-
-static ssize_t
-alarms_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w83627hf_data *data = w83627hf_update_device(dev);
- return sprintf(buf, "%ld\n", (long) data->alarms);
-}
-static DEVICE_ATTR_RO(alarms);
-
-static ssize_t
alarm_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
int bitnr = to_sensor_dev_attr(attr)->index;
return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
}
+
static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0);
static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1);
static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2);
@@ -861,44 +929,6 @@ static SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, 5);
static SENSOR_DEVICE_ATTR_RO(temp3_alarm, alarm, 13);
static ssize_t
-beep_mask_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct w83627hf_data *data = w83627hf_update_device(dev);
- return sprintf(buf, "%ld\n",
- (long)BEEP_MASK_FROM_REG(data->beep_mask));
-}
-
-static ssize_t
-beep_mask_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct w83627hf_data *data = dev_get_drvdata(dev);
- unsigned long val;
- int err;
-
- err = kstrtoul(buf, 10, &val);
- if (err)
- return err;
-
- mutex_lock(&data->update_lock);
-
- /* preserve beep enable */
- data->beep_mask = (data->beep_mask & 0x8000)
- | BEEP_MASK_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
- data->beep_mask & 0xff);
- w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
- ((data->beep_mask) >> 16) & 0xff);
- w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
- (data->beep_mask >> 8) & 0xff);
-
- mutex_unlock(&data->update_lock);
- return count;
-}
-
-static DEVICE_ATTR_RW(beep_mask);
-
-static ssize_t
beep_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
@@ -974,6 +1004,143 @@ static SENSOR_DEVICE_ATTR_RW(temp3_beep, beep, 13);
static SENSOR_DEVICE_ATTR_RW(beep_enable, beep, 15);
static ssize_t
+in_input_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in[nr]));
+}
+
+static ssize_t
+in_min_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_min[nr]));
+}
+
+static ssize_t
+in_min_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ long val;
+ int err;
+
+ err = kstrtol(buf, 10, &val);
+ if (err)
+ return err;
+
+ mutex_lock(&data->update_lock);
+ data->in_min[nr] = IN_TO_REG(val);
+ w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t
+in_max_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_max[nr]));
+}
+
+static ssize_t
+in_max_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ long val;
+ int err;
+
+ err = kstrtol(buf, 10, &val);
+ if (err)
+ return err;
+
+ mutex_lock(&data->update_lock);
+ data->in_max[nr] = IN_TO_REG(val);
+ w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR_RO(in1_input, in_input, 1);
+static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1);
+static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1);
+static SENSOR_DEVICE_ATTR_RO(in2_input, in_input, 2);
+static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2);
+static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2);
+static SENSOR_DEVICE_ATTR_RO(in3_input, in_input, 3);
+static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3);
+static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3);
+static SENSOR_DEVICE_ATTR_RO(in4_input, in_input, 4);
+static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4);
+static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4);
+static SENSOR_DEVICE_ATTR_RO(in5_input, in_input, 5);
+static SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 5);
+static SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 5);
+static SENSOR_DEVICE_ATTR_RO(in6_input, in_input, 6);
+static SENSOR_DEVICE_ATTR_RW(in6_min, in_min, 6);
+static SENSOR_DEVICE_ATTR_RW(in6_max, in_max, 6);
+static SENSOR_DEVICE_ATTR_RO(in7_input, in_input, 7);
+static SENSOR_DEVICE_ATTR_RW(in7_min, in_min, 7);
+static SENSOR_DEVICE_ATTR_RW(in7_max, in_max, 7);
+static SENSOR_DEVICE_ATTR_RO(in8_input, in_input, 8);
+static SENSOR_DEVICE_ATTR_RW(in8_min, in_min, 8);
+static SENSOR_DEVICE_ATTR_RW(in8_max, in_max, 8);
+
+static ssize_t
+fan_input_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan[nr],
+ (long)DIV_FROM_REG(data->fan_div[nr])));
+}
+
+static ssize_t
+fan_min_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan_min[nr],
+ (long)DIV_FROM_REG(data->fan_div[nr])));
+}
+
+static ssize_t
+fan_min_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int err;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err)
+ return err;
+
+ mutex_lock(&data->update_lock);
+ data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+ w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
+ data->fan_min[nr]);
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0);
+static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
+static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1);
+static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
+static SENSOR_DEVICE_ATTR_RO(fan3_input, fan_input, 2);
+static SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2);
+
+static ssize_t
fan_div_show(struct device *dev, struct device_attribute *devattr, char *buf)
{
int nr = to_sensor_dev_attr(devattr)->index;
@@ -981,6 +1148,7 @@ fan_div_show(struct device *dev, struct device_attribute *devattr, char *buf)
return sprintf(buf, "%ld\n",
(long) DIV_FROM_REG(data->fan_div[nr]));
}
+
/*
* Note: we save and restore the fan minimum here, because its value is
* determined in part by the fan divisor. This follows the principle of
@@ -1033,138 +1201,92 @@ static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
static SENSOR_DEVICE_ATTR_RW(fan3_div, fan_div, 2);
static ssize_t
-pwm_show(struct device *dev, struct device_attribute *devattr, char *buf)
+temp_show(struct device *dev, struct device_attribute *devattr, char *buf)
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- return sprintf(buf, "%ld\n", (long) data->pwm[nr]);
-}
-static ssize_t
-pwm_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- int nr = to_sensor_dev_attr(devattr)->index;
- struct w83627hf_data *data = dev_get_drvdata(dev);
- unsigned long val;
- int err;
-
- err = kstrtoul(buf, 10, &val);
- if (err)
- return err;
-
- mutex_lock(&data->update_lock);
-
- if (data->type == w83627thf) {
- /* bits 0-3 are reserved in 627THF */
- data->pwm[nr] = PWM_TO_REG(val) & 0xf0;
- w83627hf_write_value(data,
- W836X7HF_REG_PWM(data->type, nr),
- data->pwm[nr] |
- (w83627hf_read_value(data,
- W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
- } else {
- data->pwm[nr] = PWM_TO_REG(val);
- w83627hf_write_value(data,
- W836X7HF_REG_PWM(data->type, nr),
- data->pwm[nr]);
- }
-
- mutex_unlock(&data->update_lock);
- return count;
+ u16 tmp = data->temp[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
-static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
-static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
-static SENSOR_DEVICE_ATTR_RW(pwm3, pwm, 2);
-
static ssize_t
-pwm_enable_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
+temp_max_show(struct device *dev, struct device_attribute *devattr, char *buf)
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- return sprintf(buf, "%d\n", data->pwm_enable[nr]);
+
+ u16 tmp = data->temp_max[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
-pwm_enable_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+temp_max_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = dev_get_drvdata(dev);
- u8 reg;
- unsigned long val;
+ u16 tmp;
+ long val;
int err;
- err = kstrtoul(buf, 10, &val);
+ err = kstrtol(buf, 10, &val);
if (err)
return err;
- if (!val || val > 3) /* modes 1, 2 and 3 are supported */
- return -EINVAL;
+ tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
mutex_lock(&data->update_lock);
- data->pwm_enable[nr] = val;
- reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]);
- reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]);
- reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr];
- w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg);
+ data->temp_max[nr] = tmp;
+ w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
mutex_unlock(&data->update_lock);
return count;
}
-static SENSOR_DEVICE_ATTR_RW(pwm1_enable, pwm_enable, 0);
-static SENSOR_DEVICE_ATTR_RW(pwm2_enable, pwm_enable, 1);
-static SENSOR_DEVICE_ATTR_RW(pwm3_enable, pwm_enable, 2);
-
static ssize_t
-pwm_freq_show(struct device *dev, struct device_attribute *devattr, char *buf)
+temp_max_hyst_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- if (data->type == w83627hf)
- return sprintf(buf, "%ld\n",
- pwm_freq_from_reg_627hf(data->pwm_freq[nr]));
- else
- return sprintf(buf, "%ld\n",
- pwm_freq_from_reg(data->pwm_freq[nr]));
+
+ u16 tmp = data->temp_max_hyst[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
-pwm_freq_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+temp_max_hyst_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = dev_get_drvdata(dev);
- static const u8 mask[]={0xF8, 0x8F};
- unsigned long val;
+ u16 tmp;
+ long val;
int err;
- err = kstrtoul(buf, 10, &val);
+ err = kstrtol(buf, 10, &val);
if (err)
return err;
+ tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
mutex_lock(&data->update_lock);
-
- if (data->type == w83627hf) {
- data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val);
- w83627hf_write_value(data, W83627HF_REG_PWM_FREQ,
- (data->pwm_freq[nr] << (nr*4)) |
- (w83627hf_read_value(data,
- W83627HF_REG_PWM_FREQ) & mask[nr]));
- } else {
- data->pwm_freq[nr] = pwm_freq_to_reg(val);
- w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr],
- data->pwm_freq[nr]);
- }
-
+ data->temp_max_hyst[nr] = tmp;
+ w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
mutex_unlock(&data->update_lock);
return count;
}
-static SENSOR_DEVICE_ATTR_RW(pwm1_freq, pwm_freq, 0);
-static SENSOR_DEVICE_ATTR_RW(pwm2_freq, pwm_freq, 1);
-static SENSOR_DEVICE_ATTR_RW(pwm3_freq, pwm_freq, 2);
+static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
+static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
+static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp_max_hyst, 0);
+static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
+static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
+static SENSOR_DEVICE_ATTR_RW(temp2_max_hyst, temp_max_hyst, 1);
+static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
+static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2);
+static SENSOR_DEVICE_ATTR_RW(temp3_max_hyst, temp_max_hyst, 2);
static ssize_t
temp_type_show(struct device *dev, struct device_attribute *devattr,
@@ -1236,81 +1358,12 @@ static SENSOR_DEVICE_ATTR_RW(temp2_type, temp_type, 1);
static SENSOR_DEVICE_ATTR_RW(temp3_type, temp_type, 2);
static ssize_t
-name_show(struct device *dev, struct device_attribute *devattr, char *buf)
-{
- struct w83627hf_data *data = dev_get_drvdata(dev);
-
- return sprintf(buf, "%s\n", data->name);
-}
-static DEVICE_ATTR_RO(name);
-
-static int __init w83627hf_find(int sioaddr, unsigned short *addr,
- struct w83627hf_sio_data *sio_data)
+alarms_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- int err;
- u16 val;
-
- static __initconst char *const names[] = {
- "W83627HF",
- "W83627THF",
- "W83697HF",
- "W83637HF",
- "W83687THF",
- };
-
- sio_data->sioaddr = sioaddr;
- err = superio_enter(sio_data);
- if (err)
- return err;
-
- err = -ENODEV;
- val = force_id ? force_id : superio_inb(sio_data, DEVID);
- switch (val) {
- case W627_DEVID:
- sio_data->type = w83627hf;
- break;
- case W627THF_DEVID:
- sio_data->type = w83627thf;
- break;
- case W697_DEVID:
- sio_data->type = w83697hf;
- break;
- case W637_DEVID:
- sio_data->type = w83637hf;
- break;
- case W687THF_DEVID:
- sio_data->type = w83687thf;
- break;
- case 0xff: /* No device at all */
- goto exit;
- default:
- pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val);
- goto exit;
- }
-
- superio_select(sio_data, W83627HF_LD_HWM);
- val = (superio_inb(sio_data, WINB_BASE_REG) << 8) |
- superio_inb(sio_data, WINB_BASE_REG + 1);
- *addr = val & WINB_ALIGNMENT;
- if (*addr == 0) {
- pr_warn("Base address not set, skipping\n");
- goto exit;
- }
-
- val = superio_inb(sio_data, WINB_ACT_REG);
- if (!(val & 0x01)) {
- pr_warn("Enabling HWM logical device\n");
- superio_outb(sio_data, WINB_ACT_REG, val | 0x01);
- }
-
- err = 0;
- pr_info(DRVNAME ": Found %s chip at %#x\n",
- names[sio_data->type], *addr);
-
- exit:
- superio_exit(sio_data);
- return err;
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%ld\n", (long) data->alarms);
}
+static DEVICE_ATTR_RO(alarms);
#define VIN_UNIT_ATTRS(_X_) \
&sensor_dev_attr_in##_X_##_input.dev_attr.attr, \
@@ -1334,6 +1387,100 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,
&sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr, \
&sensor_dev_attr_temp##_X_##_beep.dev_attr.attr
+static ssize_t
+beep_mask_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%ld\n",
+ (long)BEEP_MASK_FROM_REG(data->beep_mask));
+}
+
+static ssize_t
+beep_mask_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int err;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err)
+ return err;
+
+ mutex_lock(&data->update_lock);
+
+ /* preserve beep enable */
+ data->beep_mask = (data->beep_mask & 0x8000)
+ | BEEP_MASK_TO_REG(val);
+ w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
+ data->beep_mask & 0xff);
+ w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
+ ((data->beep_mask) >> 16) & 0xff);
+ w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
+ (data->beep_mask >> 8) & 0xff);
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static DEVICE_ATTR_RW(beep_mask);
+
+static ssize_t
+pwm_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%ld\n", (long) data->pwm[nr]);
+}
+
+static ssize_t
+pwm_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int err;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err)
+ return err;
+
+ mutex_lock(&data->update_lock);
+
+ if (data->type == w83627thf) {
+ /* bits 0-3 are reserved in 627THF */
+ data->pwm[nr] = PWM_TO_REG(val) & 0xf0;
+ w83627hf_write_value(data,
+ W836X7HF_REG_PWM(data->type, nr),
+ data->pwm[nr] |
+ (w83627hf_read_value(data,
+ W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
+ } else {
+ data->pwm[nr] = PWM_TO_REG(val);
+ w83627hf_write_value(data,
+ W836X7HF_REG_PWM(data->type, nr),
+ data->pwm[nr]);
+ }
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm3, pwm, 2);
+
+static ssize_t
+name_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", data->name);
+}
+
+static DEVICE_ATTR_RO(name);
+
static struct attribute *w83627hf_attributes[] = {
&dev_attr_in0_input.attr,
&dev_attr_in0_min.attr,
@@ -1366,6 +1513,131 @@ static const struct attribute_group w83627hf_group = {
.attrs = w83627hf_attributes,
};
+static ssize_t
+pwm_freq_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ if (data->type == w83627hf)
+ return sprintf(buf, "%ld\n",
+ pwm_freq_from_reg_627hf(data->pwm_freq[nr]));
+ else
+ return sprintf(buf, "%ld\n",
+ pwm_freq_from_reg(data->pwm_freq[nr]));
+}
+
+static ssize_t
+pwm_freq_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ static const u8 mask[]={0xF8, 0x8F};
+ unsigned long val;
+ int err;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err)
+ return err;
+
+ mutex_lock(&data->update_lock);
+
+ if (data->type == w83627hf) {
+ data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val);
+ w83627hf_write_value(data, W83627HF_REG_PWM_FREQ,
+ (data->pwm_freq[nr] << (nr*4)) |
+ (w83627hf_read_value(data,
+ W83627HF_REG_PWM_FREQ) & mask[nr]));
+ } else {
+ data->pwm_freq[nr] = pwm_freq_to_reg(val);
+ w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr],
+ data->pwm_freq[nr]);
+ }
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR_RW(pwm1_freq, pwm_freq, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2_freq, pwm_freq, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm3_freq, pwm_freq, 2);
+
+static ssize_t
+cpu0_vid_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+}
+
+static DEVICE_ATTR_RO(cpu0_vid);
+
+static ssize_t
+vrm_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%ld\n", (long) data->vrm);
+}
+
+static ssize_t
+vrm_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int err;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err)
+ return err;
+
+ if (val > 255)
+ return -EINVAL;
+ data->vrm = val;
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(vrm);
+
+static ssize_t
+pwm_enable_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = w83627hf_update_device(dev);
+ return sprintf(buf, "%d\n", data->pwm_enable[nr]);
+}
+
+static ssize_t
+pwm_enable_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(devattr)->index;
+ struct w83627hf_data *data = dev_get_drvdata(dev);
+ u8 reg;
+ unsigned long val;
+ int err;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err)
+ return err;
+
+ if (!val || val > 3) /* modes 1, 2 and 3 are supported */
+ return -EINVAL;
+ mutex_lock(&data->update_lock);
+ data->pwm_enable[nr] = val;
+ reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]);
+ reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]);
+ reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr];
+ w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR_RW(pwm1_enable, pwm_enable, 0);
+static SENSOR_DEVICE_ATTR_RW(pwm2_enable, pwm_enable, 1);
+static SENSOR_DEVICE_ATTR_RW(pwm3_enable, pwm_enable, 2);
+
static struct attribute *w83627hf_attributes_opt[] = {
VIN_UNIT_ATTRS(1),
VIN_UNIT_ATTRS(5),
@@ -1568,349 +1840,81 @@ static int w83627hf_remove(struct platform_device *pdev)
return 0;
}
-/* Registers 0x50-0x5f are banked */
-static inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg)
-{
- if ((reg & 0x00f0) == 0x50) {
- outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
- outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET);
- }
-}
-
-/* Not strictly necessary, but play it safe for now */
-static inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg)
-{
- if (reg & 0xff00) {
- outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
- outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
- }
-}
-
-static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
-{
- int res, word_sized;
-
- mutex_lock(&data->lock);
- word_sized = (((reg & 0xff00) == 0x100)
- || ((reg & 0xff00) == 0x200))
- && (((reg & 0x00ff) == 0x50)
- || ((reg & 0x00ff) == 0x53)
- || ((reg & 0x00ff) == 0x55));
- w83627hf_set_bank(data, reg);
- outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
- res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
- if (word_sized) {
- outb_p((reg & 0xff) + 1,
- data->addr + W83781D_ADDR_REG_OFFSET);
- res =
- (res << 8) + inb_p(data->addr +
- W83781D_DATA_REG_OFFSET);
- }
- w83627hf_reset_bank(data, reg);
- mutex_unlock(&data->lock);
- return res;
-}
+static struct platform_driver w83627hf_driver = {
+ .driver = {
+ .name = DRVNAME,
+ .pm = W83627HF_DEV_PM_OPS,
+ },
+ .probe = w83627hf_probe,
+ .remove = w83627hf_remove,
+};
-static int w83627thf_read_gpio5(struct platform_device *pdev)
+static int __init w83627hf_find(int sioaddr, unsigned short *addr,
+ struct w83627hf_sio_data *sio_data)
{
- struct w83627hf_sio_data *sio_data = dev_get_platdata(&pdev->dev);
- int res = 0xff, sel;
-
- if (superio_enter(sio_data)) {
- /*
- * Some other driver reserved the address space for itself.
- * We don't want to fail driver instantiation because of that,
- * so display a warning and keep going.
- */
- dev_warn(&pdev->dev,
- "Can not read VID data: Failed to enable SuperIO access\n");
- return res;
- }
+ int err;
+ u16 val;
- superio_select(sio_data, W83627HF_LD_GPIO5);
+ static __initconst char *const names[] = {
+ "W83627HF",
+ "W83627THF",
+ "W83697HF",
+ "W83637HF",
+ "W83687THF",
+ };
- res = 0xff;
+ sio_data->sioaddr = sioaddr;
+ err = superio_enter(sio_data);
+ if (err)
+ return err;
- /* Make sure these GPIO pins are enabled */
- if (!(superio_inb(sio_data, W83627THF_GPIO5_EN) & (1<<3))) {
- dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n");
+ err = -ENODEV;
+ val = force_id ? force_id : superio_inb(sio_data, DEVID);
+ switch (val) {
+ case W627_DEVID:
+ sio_data->type = w83627hf;
+ break;
+ case W627THF_DEVID:
+ sio_data->type = w83627thf;
+ break;
+ case W697_DEVID:
+ sio_data->type = w83697hf;
+ break;
+ case W637_DEVID:
+ sio_data->type = w83637hf;
+ break;
+ case W687THF_DEVID:
+ sio_data->type = w83687thf;
+ break;
+ case 0xff: /* No device at all */
goto exit;
- }
-
- /*
- * Make sure the pins are configured for input
- * There must be at least five (VRM 9), and possibly 6 (VRM 10)
- */
- sel = superio_inb(sio_data, W83627THF_GPIO5_IOSR) & 0x3f;
- if ((sel & 0x1f) != 0x1f) {
- dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
- "function\n");
+ default:
+ pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val);
goto exit;
}
- dev_info(&pdev->dev, "Reading VID from GPIO5\n");
- res = superio_inb(sio_data, W83627THF_GPIO5_DR) & sel;
-
-exit:
- superio_exit(sio_data);
- return res;
-}
-
-static int w83687thf_read_vid(struct platform_device *pdev)
-{
- struct w83627hf_sio_data *sio_data = dev_get_platdata(&pdev->dev);
- int res = 0xff;
-
- if (superio_enter(sio_data)) {
- /*
- * Some other driver reserved the address space for itself.
- * We don't want to fail driver instantiation because of that,
- * so display a warning and keep going.
- */
- dev_warn(&pdev->dev,
- "Can not read VID data: Failed to enable SuperIO access\n");
- return res;
- }
-
superio_select(sio_data, W83627HF_LD_HWM);
-
- /* Make sure these GPIO pins are enabled */
- if (!(superio_inb(sio_data, W83687THF_VID_EN) & (1 << 2))) {
- dev_dbg(&pdev->dev, "VID disabled, no VID function\n");
+ val = (superio_inb(sio_data, WINB_BASE_REG) << 8) |
+ superio_inb(sio_data, WINB_BASE_REG + 1);
+ *addr = val & WINB_ALIGNMENT;
+ if (*addr == 0) {
+ pr_warn("Base address not set, skipping\n");
goto exit;
}
- /* Make sure the pins are configured for input */
- if (!(superio_inb(sio_data, W83687THF_VID_CFG) & (1 << 4))) {
- dev_dbg(&pdev->dev, "VID configured as output, "
- "no VID function\n");
- goto exit;
+ val = superio_inb(sio_data, WINB_ACT_REG);
+ if (!(val & 0x01)) {
+ pr_warn("Enabling HWM logical device\n");
+ superio_outb(sio_data, WINB_ACT_REG, val | 0x01);
}
- res = superio_inb(sio_data, W83687THF_VID_DATA) & 0x3f;
+ err = 0;
+ pr_info(DRVNAME ": Found %s chip at %#x\n",
+ names[sio_data->type], *addr);
-exit:
+ exit:
superio_exit(sio_data);
- return res;
-}
-
-static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
-{
- int word_sized;
-
- mutex_lock(&data->lock);
- word_sized = (((reg & 0xff00) == 0x100)
- || ((reg & 0xff00) == 0x200))
- && (((reg & 0x00ff) == 0x53)
- || ((reg & 0x00ff) == 0x55));
- w83627hf_set_bank(data, reg);
- outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
- if (word_sized) {
- outb_p(value >> 8,
- data->addr + W83781D_DATA_REG_OFFSET);
- outb_p((reg & 0xff) + 1,
- data->addr + W83781D_ADDR_REG_OFFSET);
- }
- outb_p(value & 0xff,
- data->addr + W83781D_DATA_REG_OFFSET);
- w83627hf_reset_bank(data, reg);
- mutex_unlock(&data->lock);
- return 0;
-}
-
-static void w83627hf_init_device(struct platform_device *pdev)
-{
- struct w83627hf_data *data = platform_get_drvdata(pdev);
- int i;
- enum chips type = data->type;
- u8 tmp;
-
- /* Minimize conflicts with other winbond i2c-only clients... */
- /* disable i2c subclients... how to disable main i2c client?? */
- /* force i2c address to relatively uncommon address */
- if (type == w83627hf) {
- w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
- w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
- }
-
- /* Read VID only once */
- if (type == w83627hf || type == w83637hf) {
- int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
- int hi = w83627hf_read_value(data, W83781D_REG_CHIPID);
- data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
- } else if (type == w83627thf) {
- data->vid = w83627thf_read_gpio5(pdev);
- } else if (type == w83687thf) {
- data->vid = w83687thf_read_vid(pdev);
- }
-
- /* Read VRM & OVT Config only once */
- if (type == w83627thf || type == w83637hf || type == w83687thf) {
- data->vrm_ovt =
- w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG);
- }
-
- tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
- for (i = 1; i <= 3; i++) {
- if (!(tmp & BIT_SCFG1[i - 1])) {
- data->sens[i - 1] = 4;
- } else {
- if (w83627hf_read_value
- (data,
- W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
- data->sens[i - 1] = 1;
- else
- data->sens[i - 1] = 2;
- }
- if ((type == w83697hf) && (i == 2))
- break;
- }
-
- if(init) {
- /* Enable temp2 */
- tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
- if (tmp & 0x01) {
- dev_warn(&pdev->dev, "Enabling temp2, readings "
- "might not make sense\n");
- w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
- tmp & 0xfe);
- }
-
- /* Enable temp3 */
- if (type != w83697hf) {
- tmp = w83627hf_read_value(data,
- W83627HF_REG_TEMP3_CONFIG);
- if (tmp & 0x01) {
- dev_warn(&pdev->dev, "Enabling temp3, "
- "readings might not make sense\n");
- w83627hf_write_value(data,
- W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
- }
- }
- }
-
- /* Start monitoring */
- w83627hf_write_value(data, W83781D_REG_CONFIG,
- (w83627hf_read_value(data,
- W83781D_REG_CONFIG) & 0xf7)
- | 0x01);
-
- /* Enable VBAT monitoring if needed */
- tmp = w83627hf_read_value(data, W83781D_REG_VBAT);
- if (!(tmp & 0x01))
- w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01);
-}
-
-static void w83627hf_update_fan_div(struct w83627hf_data *data)
-{
- int reg;
-
- reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
- data->fan_div[0] = (reg >> 4) & 0x03;
- data->fan_div[1] = (reg >> 6) & 0x03;
- if (data->type != w83697hf) {
- data->fan_div[2] = (w83627hf_read_value(data,
- W83781D_REG_PIN) >> 6) & 0x03;
- }
- reg = w83627hf_read_value(data, W83781D_REG_VBAT);
- data->fan_div[0] |= (reg >> 3) & 0x04;
- data->fan_div[1] |= (reg >> 4) & 0x04;
- if (data->type != w83697hf)
- data->fan_div[2] |= (reg >> 5) & 0x04;
-}
-
-static struct w83627hf_data *w83627hf_update_device(struct device *dev)
-{
- struct w83627hf_data *data = dev_get_drvdata(dev);
- int i, num_temps = (data->type == w83697hf) ? 2 : 3;
- int num_pwms = (data->type == w83697hf) ? 2 : 3;
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
- || !data->valid) {
- for (i = 0; i <= 8; i++) {
- /* skip missing sensors */
- if (((data->type == w83697hf) && (i == 1)) ||
- ((data->type != w83627hf && data->type != w83697hf)
- && (i == 5 || i == 6)))
- continue;
- data->in[i] =
- w83627hf_read_value(data, W83781D_REG_IN(i));
- data->in_min[i] =
- w83627hf_read_value(data,
- W83781D_REG_IN_MIN(i));
- data->in_max[i] =
- w83627hf_read_value(data,
- W83781D_REG_IN_MAX(i));
- }
- for (i = 0; i <= 2; i++) {
- data->fan[i] =
- w83627hf_read_value(data, W83627HF_REG_FAN(i));
- data->fan_min[i] =
- w83627hf_read_value(data,
- W83627HF_REG_FAN_MIN(i));
- }
- for (i = 0; i <= 2; i++) {
- u8 tmp = w83627hf_read_value(data,
- W836X7HF_REG_PWM(data->type, i));
- /* bits 0-3 are reserved in 627THF */
- if (data->type == w83627thf)
- tmp &= 0xf0;
- data->pwm[i] = tmp;
- if (i == 1 &&
- (data->type == w83627hf || data->type == w83697hf))
- break;
- }
- if (data->type == w83627hf) {
- u8 tmp = w83627hf_read_value(data,
- W83627HF_REG_PWM_FREQ);
- data->pwm_freq[0] = tmp & 0x07;
- data->pwm_freq[1] = (tmp >> 4) & 0x07;
- } else if (data->type != w83627thf) {
- for (i = 1; i <= 3; i++) {
- data->pwm_freq[i - 1] =
- w83627hf_read_value(data,
- W83637HF_REG_PWM_FREQ[i - 1]);
- if (i == 2 && (data->type == w83697hf))
- break;
- }
- }
- if (data->type != w83627hf) {
- for (i = 0; i < num_pwms; i++) {
- u8 tmp = w83627hf_read_value(data,
- W83627THF_REG_PWM_ENABLE[i]);
- data->pwm_enable[i] =
- ((tmp >> W83627THF_PWM_ENABLE_SHIFT[i])
- & 0x03) + 1;
- }
- }
- for (i = 0; i < num_temps; i++) {
- data->temp[i] = w83627hf_read_value(
- data, w83627hf_reg_temp[i]);
- data->temp_max[i] = w83627hf_read_value(
- data, w83627hf_reg_temp_over[i]);
- data->temp_max_hyst[i] = w83627hf_read_value(
- data, w83627hf_reg_temp_hyst[i]);
- }
-
- w83627hf_update_fan_div(data);
-
- data->alarms =
- w83627hf_read_value(data, W83781D_REG_ALARM1) |
- (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
- (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
- i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
- data->beep_mask = (i << 8) |
- w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
- w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
- data->last_updated = jiffies;
- data->valid = true;
- }
-
- mutex_unlock(&data->update_lock);
-
- return data;
+ return err;
}
static int __init w83627hf_device_add(unsigned short address,