aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/w83795.c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2010-10-28 14:31:46 -0400
committerJean Delvare <khali@endymion.delvare>2010-10-28 14:31:46 -0400
commit0e256018b0f35d1b22ca37e1d0e207f7ba3d0076 (patch)
tree029db8e2bd87afb27c9d4211ff724958bade47b4 /drivers/hwmon/w83795.c
parent6c82b2f3fb31e43a9b898769afd2151ca64986a4 (diff)
hwmon: (w83795) Add support for dynamic in0-2 limits
The W83795G can be configured to set the in0, in1 and/or in2 voltage limits dynamically based on VID input pins. Switch the respective sysfs attributes to read-only. Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/w83795.c')
-rw-r--r--drivers/hwmon/w83795.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c
index 24e44245e548..458fb297f696 100644
--- a/drivers/hwmon/w83795.c
+++ b/drivers/hwmon/w83795.c
@@ -316,6 +316,7 @@ struct w83795_data {
316 u8 bank; 316 u8 bank;
317 317
318 u32 has_in; /* Enable monitor VIN or not */ 318 u32 has_in; /* Enable monitor VIN or not */
319 u8 has_dyn_in; /* Only in2-0 can have this */
319 u16 in[21][3]; /* Register value, read/high/low */ 320 u16 in[21][3]; /* Register value, read/high/low */
320 u8 in_lsb[10][3]; /* LSB Register value, high/low */ 321 u8 in_lsb[10][3]; /* LSB Register value, high/low */
321 u8 has_gain; /* has gain: in17-20 * 8 */ 322 u8 has_gain; /* has gain: in17-20 * 8 */
@@ -450,6 +451,23 @@ static struct w83795_data *w83795_update_device(struct device *dev)
450 data->in[i][IN_READ] = tmp; 451 data->in[i][IN_READ] = tmp;
451 } 452 }
452 453
454 /* in0-2 can have dynamic limits (W83795G only) */
455 if (data->has_dyn_in) {
456 u8 lsb_max = w83795_read(client, IN_LSB_REG(0, IN_MAX));
457 u8 lsb_low = w83795_read(client, IN_LSB_REG(0, IN_LOW));
458
459 for (i = 0; i < 3; i++) {
460 if (!(data->has_dyn_in & (1 << i)))
461 continue;
462 data->in[i][IN_MAX] =
463 w83795_read(client, W83795_REG_IN[i][IN_MAX]);
464 data->in[i][IN_LOW] =
465 w83795_read(client, W83795_REG_IN[i][IN_LOW]);
466 data->in_lsb[i][IN_MAX] = (lsb_max >> (2 * i)) & 0x03;
467 data->in_lsb[i][IN_LOW] = (lsb_low >> (2 * i)) & 0x03;
468 }
469 }
470
453 /* Update fan */ 471 /* Update fan */
454 for (i = 0; i < ARRAY_SIZE(data->fan); i++) { 472 for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
455 if (!(data->has_fan & (1 << i))) 473 if (!(data->has_fan & (1 << i)))
@@ -1450,6 +1468,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
1450 1468
1451#define NOT_USED -1 1469#define NOT_USED -1
1452 1470
1471/* Don't change the attribute order, _max and _min are accessed by index
1472 * somewhere else in the code */
1453#define SENSOR_ATTR_IN(index) { \ 1473#define SENSOR_ATTR_IN(index) { \
1454 SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL, \ 1474 SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL, \
1455 IN_READ, index), \ 1475 IN_READ, index), \
@@ -1844,6 +1864,39 @@ static int device_remove_file_wrapper(struct device *dev,
1844 return 0; 1864 return 0;
1845} 1865}
1846 1866
1867static void w83795_check_dynamic_in_limits(struct i2c_client *client)
1868{
1869 struct w83795_data *data = i2c_get_clientdata(client);
1870 u8 vid_ctl;
1871 int i, err_max, err_min;
1872
1873 vid_ctl = w83795_read(client, W83795_REG_VID_CTRL);
1874
1875 /* Return immediately if VRM isn't configured */
1876 if ((vid_ctl & 0x07) == 0x00 || (vid_ctl & 0x07) == 0x07)
1877 return;
1878
1879 data->has_dyn_in = (vid_ctl >> 3) & 0x07;
1880 for (i = 0; i < 2; i++) {
1881 if (!(data->has_dyn_in & (1 << i)))
1882 continue;
1883
1884 /* Voltage limits in dynamic mode, switch to read-only */
1885 err_max = sysfs_chmod_file(&client->dev.kobj,
1886 &w83795_in[i][2].dev_attr.attr,
1887 S_IRUGO);
1888 err_min = sysfs_chmod_file(&client->dev.kobj,
1889 &w83795_in[i][3].dev_attr.attr,
1890 S_IRUGO);
1891 if (err_max || err_min)
1892 dev_warn(&client->dev, "Failed to set in%d limits "
1893 "read-only (%d, %d)\n", i, err_max, err_min);
1894 else
1895 dev_info(&client->dev, "in%d limits set dynamically "
1896 "from VID\n", i);
1897 }
1898}
1899
1847/* Check pins that can be used for either temperature or voltage monitoring */ 1900/* Check pins that can be used for either temperature or voltage monitoring */
1848static void w83795_apply_temp_config(struct w83795_data *data, u8 config, 1901static void w83795_apply_temp_config(struct w83795_data *data, u8 config,
1849 int temp_chan, int in_chan) 1902 int temp_chan, int in_chan)
@@ -2049,6 +2102,9 @@ static int w83795_probe(struct i2c_client *client,
2049 if (err) 2102 if (err)
2050 goto exit_remove; 2103 goto exit_remove;
2051 2104
2105 if (data->chip_type == w83795g)
2106 w83795_check_dynamic_in_limits(client);
2107
2052 data->hwmon_dev = hwmon_device_register(dev); 2108 data->hwmon_dev = hwmon_device_register(dev);
2053 if (IS_ERR(data->hwmon_dev)) { 2109 if (IS_ERR(data->hwmon_dev)) {
2054 err = PTR_ERR(data->hwmon_dev); 2110 err = PTR_ERR(data->hwmon_dev);