diff options
author | Guenter Roeck <linux@roeck-us.net> | 2012-12-19 16:17:02 -0500 |
---|---|---|
committer | Jean Delvare <khali@endymion.delvare> | 2012-12-19 16:17:02 -0500 |
commit | 483db43e81f4958e3cd11a990112e8082a6a5261 (patch) | |
tree | 4f1f0081a8dedbb2ec9c2f264d40f03ae3772be7 /drivers/hwmon | |
parent | c4458db3688a603a4cb4b1d01ca10ff0d58bc8eb (diff) |
hwmon: (it87) Manage device specific features with table
This simplifies the code, improves runtime performance, reduces
code size (about 280 bytes on x86_64), and makes it easier
to add support for new devices.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/it87.c | 155 |
1 files changed, 81 insertions, 74 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 59c147b9b976..e8fdc438df0a 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -228,6 +228,63 @@ static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 }; | |||
228 | #define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i)) | 228 | #define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i)) |
229 | #define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i)) | 229 | #define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i)) |
230 | 230 | ||
231 | struct it87_devices { | ||
232 | const char *name; | ||
233 | u16 features; | ||
234 | }; | ||
235 | |||
236 | #define FEAT_12MV_ADC (1 << 0) | ||
237 | #define FEAT_NEWER_AUTOPWM (1 << 1) | ||
238 | #define FEAT_OLD_AUTOPWM (1 << 2) | ||
239 | #define FEAT_16BIT_FANS (1 << 3) | ||
240 | #define FEAT_TEMP_OFFSET (1 << 4) | ||
241 | |||
242 | static const struct it87_devices it87_devices[] = { | ||
243 | [it87] = { | ||
244 | .name = "it87", | ||
245 | .features = FEAT_OLD_AUTOPWM, /* may need to overwrite */ | ||
246 | }, | ||
247 | [it8712] = { | ||
248 | .name = "it8712", | ||
249 | .features = FEAT_OLD_AUTOPWM, /* may need to overwrite */ | ||
250 | }, | ||
251 | [it8716] = { | ||
252 | .name = "it8716", | ||
253 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET, | ||
254 | }, | ||
255 | [it8718] = { | ||
256 | .name = "it8718", | ||
257 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET, | ||
258 | }, | ||
259 | [it8720] = { | ||
260 | .name = "it8720", | ||
261 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET, | ||
262 | }, | ||
263 | [it8721] = { | ||
264 | .name = "it8721", | ||
265 | .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | ||
266 | | FEAT_TEMP_OFFSET, | ||
267 | }, | ||
268 | [it8728] = { | ||
269 | .name = "it8728", | ||
270 | .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | ||
271 | | FEAT_TEMP_OFFSET, | ||
272 | }, | ||
273 | [it8782] = { | ||
274 | .name = "it8782", | ||
275 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET, | ||
276 | }, | ||
277 | [it8783] = { | ||
278 | .name = "it8783", | ||
279 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET, | ||
280 | }, | ||
281 | }; | ||
282 | |||
283 | #define has_16bit_fans(data) ((data)->features & FEAT_16BIT_FANS) | ||
284 | #define has_12mv_adc(data) ((data)->features & FEAT_12MV_ADC) | ||
285 | #define has_newer_autopwm(data) ((data)->features & FEAT_NEWER_AUTOPWM) | ||
286 | #define has_old_autopwm(data) ((data)->features & FEAT_OLD_AUTOPWM) | ||
287 | #define has_temp_offset(data) ((data)->features & FEAT_TEMP_OFFSET) | ||
231 | 288 | ||
232 | struct it87_sio_data { | 289 | struct it87_sio_data { |
233 | enum chips type; | 290 | enum chips type; |
@@ -251,7 +308,7 @@ struct it87_sio_data { | |||
251 | struct it87_data { | 308 | struct it87_data { |
252 | struct device *hwmon_dev; | 309 | struct device *hwmon_dev; |
253 | enum chips type; | 310 | enum chips type; |
254 | u8 revision; | 311 | u16 features; |
255 | 312 | ||
256 | unsigned short addr; | 313 | unsigned short addr; |
257 | const char *name; | 314 | const char *name; |
@@ -293,37 +350,6 @@ struct it87_data { | |||
293 | s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ | 350 | s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ |
294 | }; | 351 | }; |
295 | 352 | ||
296 | static inline int has_12mv_adc(const struct it87_data *data) | ||
297 | { | ||
298 | /* | ||
299 | * IT8721F and later have a 12 mV ADC, also with internal scaling | ||
300 | * on selected inputs. | ||
301 | */ | ||
302 | return data->type == it8721 | ||
303 | || data->type == it8728; | ||
304 | } | ||
305 | |||
306 | static inline int has_newer_autopwm(const struct it87_data *data) | ||
307 | { | ||
308 | /* | ||
309 | * IT8721F and later have separate registers for the temperature | ||
310 | * mapping and the manual duty cycle. | ||
311 | */ | ||
312 | return data->type == it8721 | ||
313 | || data->type == it8728; | ||
314 | } | ||
315 | |||
316 | static inline int has_temp_offset(const struct it87_data *data) | ||
317 | { | ||
318 | return data->type == it8716 | ||
319 | || data->type == it8718 | ||
320 | || data->type == it8720 | ||
321 | || data->type == it8721 | ||
322 | || data->type == it8728 | ||
323 | || data->type == it8782 | ||
324 | || data->type == it8783; | ||
325 | } | ||
326 | |||
327 | static int adc_lsb(const struct it87_data *data, int nr) | 353 | static int adc_lsb(const struct it87_data *data, int nr) |
328 | { | 354 | { |
329 | int lsb = has_12mv_adc(data) ? 12 : 16; | 355 | int lsb = has_12mv_adc(data) ? 12 : 16; |
@@ -406,35 +432,6 @@ static const unsigned int pwm_freq[8] = { | |||
406 | 750000 / 128, | 432 | 750000 / 128, |
407 | }; | 433 | }; |
408 | 434 | ||
409 | static inline int has_16bit_fans(const struct it87_data *data) | ||
410 | { | ||
411 | /* | ||
412 | * IT8705F Datasheet 0.4.1, 3h == Version G. | ||
413 | * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. | ||
414 | * These are the first revisions with 16-bit tachometer support. | ||
415 | */ | ||
416 | return (data->type == it87 && data->revision >= 0x03) | ||
417 | || (data->type == it8712 && data->revision >= 0x08) | ||
418 | || data->type == it8716 | ||
419 | || data->type == it8718 | ||
420 | || data->type == it8720 | ||
421 | || data->type == it8721 | ||
422 | || data->type == it8728 | ||
423 | || data->type == it8782 | ||
424 | || data->type == it8783; | ||
425 | } | ||
426 | |||
427 | static inline int has_old_autopwm(const struct it87_data *data) | ||
428 | { | ||
429 | /* | ||
430 | * The old automatic fan speed control interface is implemented | ||
431 | * by IT8705F chips up to revision F and IT8712F chips up to | ||
432 | * revision G. | ||
433 | */ | ||
434 | return (data->type == it87 && data->revision < 0x03) | ||
435 | || (data->type == it8712 && data->revision < 0x08); | ||
436 | } | ||
437 | |||
438 | static int it87_probe(struct platform_device *pdev); | 435 | static int it87_probe(struct platform_device *pdev); |
439 | static int it87_remove(struct platform_device *pdev); | 436 | static int it87_remove(struct platform_device *pdev); |
440 | 437 | ||
@@ -1952,17 +1949,6 @@ static int it87_probe(struct platform_device *pdev) | |||
1952 | int err = 0, i; | 1949 | int err = 0, i; |
1953 | int enable_pwm_interface; | 1950 | int enable_pwm_interface; |
1954 | int fan_beep_need_rw; | 1951 | int fan_beep_need_rw; |
1955 | static const char * const names[] = { | ||
1956 | "it87", | ||
1957 | "it8712", | ||
1958 | "it8716", | ||
1959 | "it8718", | ||
1960 | "it8720", | ||
1961 | "it8721", | ||
1962 | "it8728", | ||
1963 | "it8782", | ||
1964 | "it8783", | ||
1965 | }; | ||
1966 | 1952 | ||
1967 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1953 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
1968 | if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, | 1954 | if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, |
@@ -1979,8 +1965,29 @@ static int it87_probe(struct platform_device *pdev) | |||
1979 | 1965 | ||
1980 | data->addr = res->start; | 1966 | data->addr = res->start; |
1981 | data->type = sio_data->type; | 1967 | data->type = sio_data->type; |
1982 | data->revision = sio_data->revision; | 1968 | data->features = it87_devices[sio_data->type].features; |
1983 | data->name = names[sio_data->type]; | 1969 | data->name = it87_devices[sio_data->type].name; |
1970 | /* | ||
1971 | * IT8705F Datasheet 0.4.1, 3h == Version G. | ||
1972 | * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. | ||
1973 | * These are the first revisions with 16-bit tachometer support. | ||
1974 | */ | ||
1975 | switch (data->type) { | ||
1976 | case it87: | ||
1977 | if (sio_data->revision >= 0x03) { | ||
1978 | data->features &= ~FEAT_OLD_AUTOPWM; | ||
1979 | data->features |= FEAT_16BIT_FANS; | ||
1980 | } | ||
1981 | break; | ||
1982 | case it8712: | ||
1983 | if (sio_data->revision >= 0x08) { | ||
1984 | data->features &= ~FEAT_OLD_AUTOPWM; | ||
1985 | data->features |= FEAT_16BIT_FANS; | ||
1986 | } | ||
1987 | break; | ||
1988 | default: | ||
1989 | break; | ||
1990 | } | ||
1984 | 1991 | ||
1985 | /* Now, we do the remaining detection. */ | 1992 | /* Now, we do the remaining detection. */ |
1986 | if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) | 1993 | if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) |