diff options
author | Guenter Roeck <linux@roeck-us.net> | 2014-05-12 13:44:48 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2014-05-21 19:02:23 -0400 |
commit | 4cab259f866ed33571c5f9e3f4bc2799ab64ba45 (patch) | |
tree | 0c17eba6c39de840a50070ac09b063d1d702b0ac /drivers/hwmon | |
parent | 57d60b1b7e0d0d32602587fd032d56d7ed9e1556 (diff) |
hwmon: (emc1403) Convert to use regmap
Convert to regmap to be able to use its register caching mechanism.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/emc1403.c | 117 |
1 files changed, 63 insertions, 54 deletions
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 0bb0bab60163..3c9a8a94753f 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c | |||
@@ -18,9 +18,6 @@ | |||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | 18 | * with this program; if not, write to the Free Software Foundation, Inc., |
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
21 | * | ||
22 | * TODO | ||
23 | * - cache alarm and critical limit registers | ||
24 | */ | 21 | */ |
25 | 22 | ||
26 | #include <linux/module.h> | 23 | #include <linux/module.h> |
@@ -32,7 +29,7 @@ | |||
32 | #include <linux/err.h> | 29 | #include <linux/err.h> |
33 | #include <linux/sysfs.h> | 30 | #include <linux/sysfs.h> |
34 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
35 | #include <linux/jiffies.h> | 32 | #include <linux/regmap.h> |
36 | 33 | ||
37 | #define THERMAL_PID_REG 0xfd | 34 | #define THERMAL_PID_REG 0xfd |
38 | #define THERMAL_SMSC_ID_REG 0xfe | 35 | #define THERMAL_SMSC_ID_REG 0xfe |
@@ -41,15 +38,9 @@ | |||
41 | enum emc1403_chip { emc1402, emc1403, emc1404 }; | 38 | enum emc1403_chip { emc1402, emc1403, emc1404 }; |
42 | 39 | ||
43 | struct thermal_data { | 40 | struct thermal_data { |
44 | struct i2c_client *client; | 41 | struct regmap *regmap; |
45 | const struct attribute_group *groups[4]; | ||
46 | struct mutex mutex; | 42 | struct mutex mutex; |
47 | /* | 43 | const struct attribute_group *groups[4]; |
48 | * Cache the hyst value so we don't keep re-reading it. In theory | ||
49 | * we could cache it forever as nobody else should be writing it. | ||
50 | */ | ||
51 | u8 cached_hyst; | ||
52 | unsigned long hyst_valid; | ||
53 | }; | 44 | }; |
54 | 45 | ||
55 | static ssize_t show_temp(struct device *dev, | 46 | static ssize_t show_temp(struct device *dev, |
@@ -57,12 +48,13 @@ static ssize_t show_temp(struct device *dev, | |||
57 | { | 48 | { |
58 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | 49 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); |
59 | struct thermal_data *data = dev_get_drvdata(dev); | 50 | struct thermal_data *data = dev_get_drvdata(dev); |
51 | unsigned int val; | ||
60 | int retval; | 52 | int retval; |
61 | 53 | ||
62 | retval = i2c_smbus_read_byte_data(data->client, sda->index); | 54 | retval = regmap_read(data->regmap, sda->index, &val); |
63 | if (retval < 0) | 55 | if (retval < 0) |
64 | return retval; | 56 | return retval; |
65 | return sprintf(buf, "%d000\n", retval); | 57 | return sprintf(buf, "%d000\n", val); |
66 | } | 58 | } |
67 | 59 | ||
68 | static ssize_t show_bit(struct device *dev, | 60 | static ssize_t show_bit(struct device *dev, |
@@ -70,12 +62,13 @@ static ssize_t show_bit(struct device *dev, | |||
70 | { | 62 | { |
71 | struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); | 63 | struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); |
72 | struct thermal_data *data = dev_get_drvdata(dev); | 64 | struct thermal_data *data = dev_get_drvdata(dev); |
65 | unsigned int val; | ||
73 | int retval; | 66 | int retval; |
74 | 67 | ||
75 | retval = i2c_smbus_read_byte_data(data->client, sda->nr); | 68 | retval = regmap_read(data->regmap, sda->nr, &val); |
76 | if (retval < 0) | 69 | if (retval < 0) |
77 | return retval; | 70 | return retval; |
78 | return sprintf(buf, "%d\n", !!(retval & sda->index)); | 71 | return sprintf(buf, "%d\n", !!(val & sda->index)); |
79 | } | 72 | } |
80 | 73 | ||
81 | static ssize_t store_temp(struct device *dev, | 74 | static ssize_t store_temp(struct device *dev, |
@@ -88,8 +81,8 @@ static ssize_t store_temp(struct device *dev, | |||
88 | 81 | ||
89 | if (kstrtoul(buf, 10, &val)) | 82 | if (kstrtoul(buf, 10, &val)) |
90 | return -EINVAL; | 83 | return -EINVAL; |
91 | retval = i2c_smbus_write_byte_data(data->client, sda->index, | 84 | retval = regmap_write(data->regmap, sda->index, |
92 | DIV_ROUND_CLOSEST(val, 1000)); | 85 | DIV_ROUND_CLOSEST(val, 1000)); |
93 | if (retval < 0) | 86 | if (retval < 0) |
94 | return retval; | 87 | return retval; |
95 | return count; | 88 | return count; |
@@ -100,28 +93,17 @@ static ssize_t store_bit(struct device *dev, | |||
100 | { | 93 | { |
101 | struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); | 94 | struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); |
102 | struct thermal_data *data = dev_get_drvdata(dev); | 95 | struct thermal_data *data = dev_get_drvdata(dev); |
103 | struct i2c_client *client = data->client; | ||
104 | unsigned long val; | 96 | unsigned long val; |
105 | int retval; | 97 | int retval; |
106 | 98 | ||
107 | if (kstrtoul(buf, 10, &val)) | 99 | if (kstrtoul(buf, 10, &val)) |
108 | return -EINVAL; | 100 | return -EINVAL; |
109 | 101 | ||
110 | mutex_lock(&data->mutex); | 102 | retval = regmap_update_bits(data->regmap, sda->nr, sda->index, |
111 | retval = i2c_smbus_read_byte_data(client, sda->nr); | 103 | val ? sda->index : 0); |
112 | if (retval < 0) | 104 | if (retval < 0) |
113 | goto fail; | 105 | return retval; |
114 | 106 | return count; | |
115 | retval &= ~sda->index; | ||
116 | if (val) | ||
117 | retval |= sda->index; | ||
118 | |||
119 | retval = i2c_smbus_write_byte_data(client, sda->index, retval); | ||
120 | if (retval == 0) | ||
121 | retval = count; | ||
122 | fail: | ||
123 | mutex_unlock(&data->mutex); | ||
124 | return retval; | ||
125 | } | 107 | } |
126 | 108 | ||
127 | static ssize_t show_hyst(struct device *dev, | 109 | static ssize_t show_hyst(struct device *dev, |
@@ -129,22 +111,20 @@ static ssize_t show_hyst(struct device *dev, | |||
129 | { | 111 | { |
130 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | 112 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); |
131 | struct thermal_data *data = dev_get_drvdata(dev); | 113 | struct thermal_data *data = dev_get_drvdata(dev); |
132 | struct i2c_client *client = data->client; | 114 | struct regmap *regmap = data->regmap; |
115 | unsigned int limit; | ||
116 | unsigned int hyst; | ||
133 | int retval; | 117 | int retval; |
134 | int hyst; | ||
135 | 118 | ||
136 | retval = i2c_smbus_read_byte_data(client, sda->index); | 119 | retval = regmap_read(regmap, sda->index, &limit); |
137 | if (retval < 0) | 120 | if (retval < 0) |
138 | return retval; | 121 | return retval; |
139 | 122 | ||
140 | if (time_after(jiffies, data->hyst_valid)) { | 123 | retval = regmap_read(regmap, 0x21, &hyst); |
141 | hyst = i2c_smbus_read_byte_data(client, 0x21); | 124 | if (retval < 0) |
142 | if (hyst < 0) | 125 | return retval; |
143 | return retval; | 126 | |
144 | data->cached_hyst = hyst; | 127 | return sprintf(buf, "%d000\n", limit - hyst); |
145 | data->hyst_valid = jiffies + HZ; | ||
146 | } | ||
147 | return sprintf(buf, "%d000\n", retval - data->cached_hyst); | ||
148 | } | 128 | } |
149 | 129 | ||
150 | static ssize_t store_hyst(struct device *dev, | 130 | static ssize_t store_hyst(struct device *dev, |
@@ -152,7 +132,8 @@ static ssize_t store_hyst(struct device *dev, | |||
152 | { | 132 | { |
153 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | 133 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); |
154 | struct thermal_data *data = dev_get_drvdata(dev); | 134 | struct thermal_data *data = dev_get_drvdata(dev); |
155 | struct i2c_client *client = data->client; | 135 | struct regmap *regmap = data->regmap; |
136 | unsigned int limit; | ||
156 | int retval; | 137 | int retval; |
157 | int hyst; | 138 | int hyst; |
158 | unsigned long val; | 139 | unsigned long val; |
@@ -161,23 +142,20 @@ static ssize_t store_hyst(struct device *dev, | |||
161 | return -EINVAL; | 142 | return -EINVAL; |
162 | 143 | ||
163 | mutex_lock(&data->mutex); | 144 | mutex_lock(&data->mutex); |
164 | retval = i2c_smbus_read_byte_data(client, sda->index); | 145 | retval = regmap_read(regmap, sda->index, &limit); |
165 | if (retval < 0) | 146 | if (retval < 0) |
166 | goto fail; | 147 | goto fail; |
167 | 148 | ||
168 | hyst = retval * 1000 - val; | 149 | hyst = limit * 1000 - val; |
169 | hyst = DIV_ROUND_CLOSEST(hyst, 1000); | 150 | hyst = DIV_ROUND_CLOSEST(hyst, 1000); |
170 | if (hyst < 0 || hyst > 255) { | 151 | if (hyst < 0 || hyst > 255) { |
171 | retval = -ERANGE; | 152 | retval = -ERANGE; |
172 | goto fail; | 153 | goto fail; |
173 | } | 154 | } |
174 | 155 | ||
175 | retval = i2c_smbus_write_byte_data(client, 0x21, hyst); | 156 | retval = regmap_write(regmap, 0x21, hyst); |
176 | if (retval == 0) { | 157 | if (retval == 0) |
177 | retval = count; | 158 | retval = count; |
178 | data->cached_hyst = hyst; | ||
179 | data->hyst_valid = jiffies + HZ; | ||
180 | } | ||
181 | fail: | 159 | fail: |
182 | mutex_unlock(&data->mutex); | 160 | mutex_unlock(&data->mutex); |
183 | return retval; | 161 | return retval; |
@@ -356,6 +334,35 @@ static int emc1403_detect(struct i2c_client *client, | |||
356 | return 0; | 334 | return 0; |
357 | } | 335 | } |
358 | 336 | ||
337 | static bool emc1403_regmap_is_volatile(struct device *dev, unsigned int reg) | ||
338 | { | ||
339 | switch (reg) { | ||
340 | case 0x00: /* internal diode high byte */ | ||
341 | case 0x01: /* external diode 1 high byte */ | ||
342 | case 0x02: /* status */ | ||
343 | case 0x10: /* external diode 1 low byte */ | ||
344 | case 0x1b: /* external diode fault */ | ||
345 | case 0x23: /* external diode 2 high byte */ | ||
346 | case 0x24: /* external diode 2 low byte */ | ||
347 | case 0x29: /* internal diode low byte */ | ||
348 | case 0x2a: /* externl diode 3 high byte */ | ||
349 | case 0x2b: /* external diode 3 low byte */ | ||
350 | case 0x35: /* high limit status */ | ||
351 | case 0x36: /* low limit status */ | ||
352 | case 0x37: /* therm limit status */ | ||
353 | return true; | ||
354 | default: | ||
355 | return false; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | static struct regmap_config emc1403_regmap_config = { | ||
360 | .reg_bits = 8, | ||
361 | .val_bits = 8, | ||
362 | .cache_type = REGCACHE_RBTREE, | ||
363 | .volatile_reg = emc1403_regmap_is_volatile, | ||
364 | }; | ||
365 | |||
359 | static int emc1403_probe(struct i2c_client *client, | 366 | static int emc1403_probe(struct i2c_client *client, |
360 | const struct i2c_device_id *id) | 367 | const struct i2c_device_id *id) |
361 | { | 368 | { |
@@ -367,9 +374,11 @@ static int emc1403_probe(struct i2c_client *client, | |||
367 | if (data == NULL) | 374 | if (data == NULL) |
368 | return -ENOMEM; | 375 | return -ENOMEM; |
369 | 376 | ||
370 | data->client = client; | 377 | data->regmap = devm_regmap_init_i2c(client, &emc1403_regmap_config); |
378 | if (IS_ERR(data->regmap)) | ||
379 | return PTR_ERR(data->regmap); | ||
380 | |||
371 | mutex_init(&data->mutex); | 381 | mutex_init(&data->mutex); |
372 | data->hyst_valid = jiffies - 1; /* Expired */ | ||
373 | 382 | ||
374 | switch (id->driver_data) { | 383 | switch (id->driver_data) { |
375 | case emc1404: | 384 | case emc1404: |