blob: 869822785b4f6b021dd60f2b88ec86770a68db82 [file] [log] [blame]
Jean Delvareba224e22006-12-12 18:18:29 +01001/*
2 * pc87427.c - hardware monitoring driver for the
3 * National Semiconductor PC87427 Super-I/O chip
Jean Delvare4e7d99e2010-08-14 21:08:56 +02004 * Copyright (C) 2006, 2008 Jean Delvare <khali@linux-fr.org>
Jean Delvareba224e22006-12-12 18:18:29 +01005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * Supports the following chips:
16 *
17 * Chip #vin #fan #pwm #temp devid
Jean Delvare328716b2010-08-14 21:08:58 +020018 * PC87427 - 8 4 - 0xF2
Jean Delvareba224e22006-12-12 18:18:29 +010019 *
20 * This driver assumes that no more than one chip is present.
Jean Delvare328716b2010-08-14 21:08:58 +020021 * Only fans are supported so far, although the chip can do much more.
Jean Delvareba224e22006-12-12 18:18:29 +010022 */
23
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/slab.h>
27#include <linux/jiffies.h>
28#include <linux/platform_device.h>
29#include <linux/hwmon.h>
30#include <linux/hwmon-sysfs.h>
31#include <linux/err.h>
32#include <linux/mutex.h>
33#include <linux/sysfs.h>
Jean Delvarece7ee4e2007-05-08 17:21:59 +020034#include <linux/ioport.h>
Jean Delvareb9acb642009-01-07 16:37:35 +010035#include <linux/acpi.h>
H Hartley Sweeten6055fae2009-09-15 17:18:13 +020036#include <linux/io.h>
Jean Delvareba224e22006-12-12 18:18:29 +010037
Jean Delvare67b671b2007-12-06 23:13:42 +010038static unsigned short force_id;
39module_param(force_id, ushort, 0);
40MODULE_PARM_DESC(force_id, "Override the detected device ID");
41
Jean Delvareba224e22006-12-12 18:18:29 +010042static struct platform_device *pdev;
43
44#define DRVNAME "pc87427"
45
46/* The lock mutex protects both the I/O accesses (needed because the
47 device is using banked registers) and the register cache (needed to keep
48 the data in the registers and the cache in sync at any time). */
49struct pc87427_data {
Tony Jones1beeffe2007-08-20 13:46:20 -070050 struct device *hwmon_dev;
Jean Delvareba224e22006-12-12 18:18:29 +010051 struct mutex lock;
52 int address[2];
53 const char *name;
54
55 unsigned long last_updated; /* in jiffies */
56 u8 fan_enabled; /* bit vector */
57 u16 fan[8]; /* register values */
58 u16 fan_min[8]; /* register values */
59 u8 fan_status[8]; /* register values */
Jean Delvare328716b2010-08-14 21:08:58 +020060
61 u8 pwm_enabled; /* bit vector */
62 u8 pwm_auto_ok; /* bit vector */
63 u8 pwm_enable[4]; /* register values */
64 u8 pwm[4]; /* register values */
Jean Delvareba224e22006-12-12 18:18:29 +010065};
66
Jean Delvare4e7d99e2010-08-14 21:08:56 +020067struct pc87427_sio_data {
68 u8 has_fanin;
Jean Delvare328716b2010-08-14 21:08:58 +020069 u8 has_fanout;
Jean Delvare4e7d99e2010-08-14 21:08:56 +020070};
71
Jean Delvareba224e22006-12-12 18:18:29 +010072/*
73 * Super-I/O registers and operations
74 */
75
76#define SIOREG_LDSEL 0x07 /* Logical device select */
77#define SIOREG_DEVID 0x20 /* Device ID */
Jean Delvare4e7d99e2010-08-14 21:08:56 +020078#define SIOREG_CF2 0x22 /* Configuration 2 */
79#define SIOREG_CF3 0x23 /* Configuration 3 */
80#define SIOREG_CF4 0x24 /* Configuration 4 */
Jean Delvare328716b2010-08-14 21:08:58 +020081#define SIOREG_CF5 0x25 /* Configuration 5 */
Jean Delvare4e7d99e2010-08-14 21:08:56 +020082#define SIOREG_CFB 0x2B /* Configuration B */
Jean Delvare328716b2010-08-14 21:08:58 +020083#define SIOREG_CFC 0x2C /* Configuration C */
Jean Delvare4e7d99e2010-08-14 21:08:56 +020084#define SIOREG_CFD 0x2D /* Configuration D */
Jean Delvareba224e22006-12-12 18:18:29 +010085#define SIOREG_ACT 0x30 /* Device activation */
86#define SIOREG_MAP 0x50 /* I/O or memory mapping */
87#define SIOREG_IOBASE 0x60 /* I/O base address */
88
89static const u8 logdev[2] = { 0x09, 0x14 };
90static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" };
91#define LD_FAN 0
92#define LD_IN 1
93#define LD_TEMP 1
94
95static inline void superio_outb(int sioaddr, int reg, int val)
96{
97 outb(reg, sioaddr);
98 outb(val, sioaddr + 1);
99}
100
101static inline int superio_inb(int sioaddr, int reg)
102{
103 outb(reg, sioaddr);
104 return inb(sioaddr + 1);
105}
106
107static inline void superio_exit(int sioaddr)
108{
109 outb(0x02, sioaddr);
110 outb(0x02, sioaddr + 1);
111}
112
113/*
114 * Logical devices
115 */
116
117#define REGION_LENGTH 32
118#define PC87427_REG_BANK 0x0f
119#define BANK_FM(nr) (nr)
120#define BANK_FT(nr) (0x08 + (nr))
121#define BANK_FC(nr) (0x10 + (nr) * 2)
122
123/*
124 * I/O access functions
125 */
126
127/* ldi is the logical device index */
128static inline int pc87427_read8(struct pc87427_data *data, u8 ldi, u8 reg)
129{
130 return inb(data->address[ldi] + reg);
131}
132
133/* Must be called with data->lock held, except during init */
134static inline int pc87427_read8_bank(struct pc87427_data *data, u8 ldi,
135 u8 bank, u8 reg)
136{
137 outb(bank, data->address[ldi] + PC87427_REG_BANK);
138 return inb(data->address[ldi] + reg);
139}
140
141/* Must be called with data->lock held, except during init */
142static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi,
143 u8 bank, u8 reg, u8 value)
144{
145 outb(bank, data->address[ldi] + PC87427_REG_BANK);
146 outb(value, data->address[ldi] + reg);
147}
148
149/*
150 * Fan registers and conversions
151 */
152
153/* fan data registers are 16-bit wide */
154#define PC87427_REG_FAN 0x12
155#define PC87427_REG_FAN_MIN 0x14
156#define PC87427_REG_FAN_STATUS 0x10
157
158#define FAN_STATUS_STALL (1 << 3)
159#define FAN_STATUS_LOSPD (1 << 1)
160#define FAN_STATUS_MONEN (1 << 0)
161
162/* Dedicated function to read all registers related to a given fan input.
163 This saves us quite a few locks and bank selections.
164 Must be called with data->lock held.
165 nr is from 0 to 7 */
166static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
167{
168 int iobase = data->address[LD_FAN];
169
170 outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
171 data->fan[nr] = inw(iobase + PC87427_REG_FAN);
172 data->fan_min[nr] = inw(iobase + PC87427_REG_FAN_MIN);
173 data->fan_status[nr] = inb(iobase + PC87427_REG_FAN_STATUS);
174 /* Clear fan alarm bits */
175 outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS);
176}
177
178/* The 2 LSB of fan speed registers are used for something different.
179 The actual 2 LSB of the measurements are not available. */
180static inline unsigned long fan_from_reg(u16 reg)
181{
182 reg &= 0xfffc;
183 if (reg == 0x0000 || reg == 0xfffc)
184 return 0;
185 return 5400000UL / reg;
186}
187
188/* The 2 LSB of the fan speed limit registers are not significant. */
189static inline u16 fan_to_reg(unsigned long val)
190{
191 if (val < 83UL)
192 return 0xffff;
193 if (val >= 1350000UL)
194 return 0x0004;
195 return ((1350000UL + val / 2) / val) << 2;
196}
197
198/*
Jean Delvare328716b2010-08-14 21:08:58 +0200199 * PWM registers and conversions
200 */
201
202#define PC87427_REG_PWM_ENABLE 0x10
203#define PC87427_REG_PWM_DUTY 0x12
204
205#define PWM_ENABLE_MODE_MASK (7 << 4)
206#define PWM_ENABLE_CTLEN (1 << 0)
207
208#define PWM_MODE_MANUAL (0 << 4)
209#define PWM_MODE_AUTO (1 << 4)
210#define PWM_MODE_OFF (2 << 4)
211#define PWM_MODE_ON (7 << 4)
212
213/* Dedicated function to read all registers related to a given PWM output.
214 This saves us quite a few locks and bank selections.
215 Must be called with data->lock held.
216 nr is from 0 to 3 */
217static void pc87427_readall_pwm(struct pc87427_data *data, u8 nr)
218{
219 int iobase = data->address[LD_FAN];
220
221 outb(BANK_FC(nr), iobase + PC87427_REG_BANK);
222 data->pwm_enable[nr] = inb(iobase + PC87427_REG_PWM_ENABLE);
223 data->pwm[nr] = inb(iobase + PC87427_REG_PWM_DUTY);
224}
225
226static inline int pwm_enable_from_reg(u8 reg)
227{
228 switch (reg & PWM_ENABLE_MODE_MASK) {
229 case PWM_MODE_ON:
230 return 0;
231 case PWM_MODE_MANUAL:
232 case PWM_MODE_OFF:
233 return 1;
234 case PWM_MODE_AUTO:
235 return 2;
236 default:
237 return -EPROTO;
238 }
239}
240
241static inline u8 pwm_enable_to_reg(unsigned long val, u8 pwmval)
242{
243 switch (val) {
244 default:
245 return PWM_MODE_ON;
246 case 1:
247 return pwmval ? PWM_MODE_MANUAL : PWM_MODE_OFF;
248 case 2:
249 return PWM_MODE_AUTO;
250 }
251}
252
253/*
Jean Delvareba224e22006-12-12 18:18:29 +0100254 * Data interface
255 */
256
257static struct pc87427_data *pc87427_update_device(struct device *dev)
258{
259 struct pc87427_data *data = dev_get_drvdata(dev);
260 int i;
261
262 mutex_lock(&data->lock);
263 if (!time_after(jiffies, data->last_updated + HZ)
264 && data->last_updated)
265 goto done;
266
267 /* Fans */
268 for (i = 0; i < 8; i++) {
269 if (!(data->fan_enabled & (1 << i)))
270 continue;
271 pc87427_readall_fan(data, i);
272 }
Jean Delvare328716b2010-08-14 21:08:58 +0200273
274 /* PWM outputs */
275 for (i = 0; i < 4; i++) {
276 if (!(data->pwm_enabled & (1 << i)))
277 continue;
278 pc87427_readall_pwm(data, i);
279 }
280
Jean Delvareba224e22006-12-12 18:18:29 +0100281 data->last_updated = jiffies;
282
283done:
284 mutex_unlock(&data->lock);
285 return data;
286}
287
288static ssize_t show_fan_input(struct device *dev, struct device_attribute
289 *devattr, char *buf)
290{
Jean Delvareba224e22006-12-12 18:18:29 +0100291 struct pc87427_data *data = pc87427_update_device(dev);
Jean Delvare0d22d582010-08-14 21:08:57 +0200292 int nr = to_sensor_dev_attr(devattr)->index;
Jean Delvareba224e22006-12-12 18:18:29 +0100293
294 return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
295}
296
297static ssize_t show_fan_min(struct device *dev, struct device_attribute
298 *devattr, char *buf)
299{
Jean Delvareba224e22006-12-12 18:18:29 +0100300 struct pc87427_data *data = pc87427_update_device(dev);
Jean Delvare0d22d582010-08-14 21:08:57 +0200301 int nr = to_sensor_dev_attr(devattr)->index;
Jean Delvareba224e22006-12-12 18:18:29 +0100302
303 return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
304}
305
306static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
307 *devattr, char *buf)
308{
Jean Delvareba224e22006-12-12 18:18:29 +0100309 struct pc87427_data *data = pc87427_update_device(dev);
Jean Delvare0d22d582010-08-14 21:08:57 +0200310 int nr = to_sensor_dev_attr(devattr)->index;
Jean Delvareba224e22006-12-12 18:18:29 +0100311
312 return sprintf(buf, "%d\n", !!(data->fan_status[nr]
313 & FAN_STATUS_LOSPD));
314}
315
316static ssize_t show_fan_fault(struct device *dev, struct device_attribute
317 *devattr, char *buf)
318{
Jean Delvareba224e22006-12-12 18:18:29 +0100319 struct pc87427_data *data = pc87427_update_device(dev);
Jean Delvare0d22d582010-08-14 21:08:57 +0200320 int nr = to_sensor_dev_attr(devattr)->index;
Jean Delvareba224e22006-12-12 18:18:29 +0100321
322 return sprintf(buf, "%d\n", !!(data->fan_status[nr]
323 & FAN_STATUS_STALL));
324}
325
326static ssize_t set_fan_min(struct device *dev, struct device_attribute
327 *devattr, const char *buf, size_t count)
328{
329 struct pc87427_data *data = dev_get_drvdata(dev);
Jean Delvare0d22d582010-08-14 21:08:57 +0200330 int nr = to_sensor_dev_attr(devattr)->index;
331 unsigned long val;
Jean Delvareba224e22006-12-12 18:18:29 +0100332 int iobase = data->address[LD_FAN];
333
Jean Delvare0d22d582010-08-14 21:08:57 +0200334 if (strict_strtoul(buf, 10, &val) < 0)
335 return -EINVAL;
336
Jean Delvareba224e22006-12-12 18:18:29 +0100337 mutex_lock(&data->lock);
338 outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
339 /* The low speed limit registers are read-only while monitoring
340 is enabled, so we have to disable monitoring, then change the
341 limit, and finally enable monitoring again. */
342 outb(0, iobase + PC87427_REG_FAN_STATUS);
343 data->fan_min[nr] = fan_to_reg(val);
344 outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN);
345 outb(FAN_STATUS_MONEN, iobase + PC87427_REG_FAN_STATUS);
346 mutex_unlock(&data->lock);
347
348 return count;
349}
350
351static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
352static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
353static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
354static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
355static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4);
356static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5);
357static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6);
358static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7);
359
360static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
361 show_fan_min, set_fan_min, 0);
362static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
363 show_fan_min, set_fan_min, 1);
364static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
365 show_fan_min, set_fan_min, 2);
366static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
367 show_fan_min, set_fan_min, 3);
368static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
369 show_fan_min, set_fan_min, 4);
370static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
371 show_fan_min, set_fan_min, 5);
372static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
373 show_fan_min, set_fan_min, 6);
374static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO,
375 show_fan_min, set_fan_min, 7);
376
377static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
378static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
379static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2);
380static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3);
381static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4);
382static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5);
383static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6);
384static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7);
385
386static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
387static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
388static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
389static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
390static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4);
391static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5);
392static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6);
393static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7);
394
395static struct attribute *pc87427_attributes_fan[8][5] = {
396 {
397 &sensor_dev_attr_fan1_input.dev_attr.attr,
398 &sensor_dev_attr_fan1_min.dev_attr.attr,
399 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
400 &sensor_dev_attr_fan1_fault.dev_attr.attr,
401 NULL
402 }, {
403 &sensor_dev_attr_fan2_input.dev_attr.attr,
404 &sensor_dev_attr_fan2_min.dev_attr.attr,
405 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
406 &sensor_dev_attr_fan2_fault.dev_attr.attr,
407 NULL
408 }, {
409 &sensor_dev_attr_fan3_input.dev_attr.attr,
410 &sensor_dev_attr_fan3_min.dev_attr.attr,
411 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
412 &sensor_dev_attr_fan3_fault.dev_attr.attr,
413 NULL
414 }, {
415 &sensor_dev_attr_fan4_input.dev_attr.attr,
416 &sensor_dev_attr_fan4_min.dev_attr.attr,
417 &sensor_dev_attr_fan4_alarm.dev_attr.attr,
418 &sensor_dev_attr_fan4_fault.dev_attr.attr,
419 NULL
420 }, {
421 &sensor_dev_attr_fan5_input.dev_attr.attr,
422 &sensor_dev_attr_fan5_min.dev_attr.attr,
423 &sensor_dev_attr_fan5_alarm.dev_attr.attr,
424 &sensor_dev_attr_fan5_fault.dev_attr.attr,
425 NULL
426 }, {
427 &sensor_dev_attr_fan6_input.dev_attr.attr,
428 &sensor_dev_attr_fan6_min.dev_attr.attr,
429 &sensor_dev_attr_fan6_alarm.dev_attr.attr,
430 &sensor_dev_attr_fan6_fault.dev_attr.attr,
431 NULL
432 }, {
433 &sensor_dev_attr_fan7_input.dev_attr.attr,
434 &sensor_dev_attr_fan7_min.dev_attr.attr,
435 &sensor_dev_attr_fan7_alarm.dev_attr.attr,
436 &sensor_dev_attr_fan7_fault.dev_attr.attr,
437 NULL
438 }, {
439 &sensor_dev_attr_fan8_input.dev_attr.attr,
440 &sensor_dev_attr_fan8_min.dev_attr.attr,
441 &sensor_dev_attr_fan8_alarm.dev_attr.attr,
442 &sensor_dev_attr_fan8_fault.dev_attr.attr,
443 NULL
444 }
445};
446
447static const struct attribute_group pc87427_group_fan[8] = {
448 { .attrs = pc87427_attributes_fan[0] },
449 { .attrs = pc87427_attributes_fan[1] },
450 { .attrs = pc87427_attributes_fan[2] },
451 { .attrs = pc87427_attributes_fan[3] },
452 { .attrs = pc87427_attributes_fan[4] },
453 { .attrs = pc87427_attributes_fan[5] },
454 { .attrs = pc87427_attributes_fan[6] },
455 { .attrs = pc87427_attributes_fan[7] },
456};
457
Jean Delvare328716b2010-08-14 21:08:58 +0200458/* Must be called with data->lock held and pc87427_readall_pwm() freshly
459 called */
460static void update_pwm_enable(struct pc87427_data *data, int nr, u8 mode)
461{
462 int iobase = data->address[LD_FAN];
463 data->pwm_enable[nr] &= ~PWM_ENABLE_MODE_MASK;
464 data->pwm_enable[nr] |= mode;
465 outb(data->pwm_enable[nr], iobase + PC87427_REG_PWM_ENABLE);
466}
467
468static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
469 *devattr, char *buf)
470{
471 struct pc87427_data *data = pc87427_update_device(dev);
472 int nr = to_sensor_dev_attr(devattr)->index;
473 int pwm_enable;
474
475 pwm_enable = pwm_enable_from_reg(data->pwm_enable[nr]);
476 if (pwm_enable < 0)
477 return pwm_enable;
478 return sprintf(buf, "%d\n", pwm_enable);
479}
480
481static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
482 *devattr, const char *buf, size_t count)
483{
484 struct pc87427_data *data = dev_get_drvdata(dev);
485 int nr = to_sensor_dev_attr(devattr)->index;
486 unsigned long val;
487
488 if (strict_strtoul(buf, 10, &val) < 0 || val > 2)
489 return -EINVAL;
490 /* Can't go to automatic mode if it isn't configured */
491 if (val == 2 && !(data->pwm_auto_ok & (1 << nr)))
492 return -EINVAL;
493
494 mutex_lock(&data->lock);
495 pc87427_readall_pwm(data, nr);
496 update_pwm_enable(data, nr, pwm_enable_to_reg(val, data->pwm[nr]));
497 mutex_unlock(&data->lock);
498
499 return count;
500}
501
502static ssize_t show_pwm(struct device *dev, struct device_attribute
503 *devattr, char *buf)
504{
505 struct pc87427_data *data = pc87427_update_device(dev);
506 int nr = to_sensor_dev_attr(devattr)->index;
507
508 return sprintf(buf, "%d\n", (int)data->pwm[nr]);
509}
510
511static ssize_t set_pwm(struct device *dev, struct device_attribute
512 *devattr, const char *buf, size_t count)
513{
514 struct pc87427_data *data = dev_get_drvdata(dev);
515 int nr = to_sensor_dev_attr(devattr)->index;
516 unsigned long val;
517 int iobase = data->address[LD_FAN];
518 u8 mode;
519
520 if (strict_strtoul(buf, 10, &val) < 0 || val > 0xff)
521 return -EINVAL;
522
523 mutex_lock(&data->lock);
524 pc87427_readall_pwm(data, nr);
525 mode = data->pwm_enable[nr] & PWM_ENABLE_MODE_MASK;
526 if (mode != PWM_MODE_MANUAL && mode != PWM_MODE_OFF) {
527 dev_notice(dev, "Can't set PWM%d duty cycle while not in "
528 "manual mode\n", nr + 1);
529 mutex_unlock(&data->lock);
530 return -EPERM;
531 }
532
533 /* We may have to change the mode */
534 if (mode == PWM_MODE_MANUAL && val == 0) {
535 /* Transition from Manual to Off */
536 update_pwm_enable(data, nr, PWM_MODE_OFF);
537 mode = PWM_MODE_OFF;
538 dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1,
539 "manual", "off");
540 } else if (mode == PWM_MODE_OFF && val != 0) {
541 /* Transition from Off to Manual */
542 update_pwm_enable(data, nr, PWM_MODE_MANUAL);
543 mode = PWM_MODE_MANUAL;
544 dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1,
545 "off", "manual");
546 }
547
548 data->pwm[nr] = val;
549 if (mode == PWM_MODE_MANUAL)
550 outb(val, iobase + PC87427_REG_PWM_DUTY);
551 mutex_unlock(&data->lock);
552
553 return count;
554}
555
556static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
557 show_pwm_enable, set_pwm_enable, 0);
558static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
559 show_pwm_enable, set_pwm_enable, 1);
560static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
561 show_pwm_enable, set_pwm_enable, 2);
562static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO,
563 show_pwm_enable, set_pwm_enable, 3);
564
565static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
566static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
567static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2);
568static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3);
569
570static struct attribute *pc87427_attributes_pwm[4][3] = {
571 {
572 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
573 &sensor_dev_attr_pwm1.dev_attr.attr,
574 NULL
575 }, {
576 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
577 &sensor_dev_attr_pwm2.dev_attr.attr,
578 NULL
579 }, {
580 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
581 &sensor_dev_attr_pwm3.dev_attr.attr,
582 NULL
583 }, {
584 &sensor_dev_attr_pwm4_enable.dev_attr.attr,
585 &sensor_dev_attr_pwm4.dev_attr.attr,
586 NULL
587 }
588};
589
590static const struct attribute_group pc87427_group_pwm[4] = {
591 { .attrs = pc87427_attributes_pwm[0] },
592 { .attrs = pc87427_attributes_pwm[1] },
593 { .attrs = pc87427_attributes_pwm[2] },
594 { .attrs = pc87427_attributes_pwm[3] },
595};
596
Jean Delvareba224e22006-12-12 18:18:29 +0100597static ssize_t show_name(struct device *dev, struct device_attribute
598 *devattr, char *buf)
599{
600 struct pc87427_data *data = dev_get_drvdata(dev);
601
602 return sprintf(buf, "%s\n", data->name);
603}
604static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
605
606
607/*
608 * Device detection, attach and detach
609 */
610
611static void __devinit pc87427_init_device(struct device *dev)
612{
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200613 struct pc87427_sio_data *sio_data = dev->platform_data;
Jean Delvareba224e22006-12-12 18:18:29 +0100614 struct pc87427_data *data = dev_get_drvdata(dev);
615 int i;
616 u8 reg;
617
618 /* The FMC module should be ready */
619 reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
620 if (!(reg & 0x80))
621 dev_warn(dev, "FMC module not ready!\n");
622
623 /* Check which fans are enabled */
624 for (i = 0; i < 8; i++) {
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200625 if (!(sio_data->has_fanin & (1 << i))) /* Not wired */
626 continue;
Jean Delvareba224e22006-12-12 18:18:29 +0100627 reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
628 PC87427_REG_FAN_STATUS);
629 if (reg & FAN_STATUS_MONEN)
630 data->fan_enabled |= (1 << i);
631 }
632
633 if (!data->fan_enabled) {
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200634 dev_dbg(dev, "Enabling monitoring of all fans\n");
635 for (i = 0; i < 8; i++) {
636 if (!(sio_data->has_fanin & (1 << i))) /* Not wired */
637 continue;
Jean Delvareba224e22006-12-12 18:18:29 +0100638 pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
639 PC87427_REG_FAN_STATUS,
640 FAN_STATUS_MONEN);
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200641 }
642 data->fan_enabled = sio_data->has_fanin;
Jean Delvareba224e22006-12-12 18:18:29 +0100643 }
Jean Delvare328716b2010-08-14 21:08:58 +0200644
645 /* Check which PWM outputs are enabled */
646 for (i = 0; i < 4; i++) {
647 if (!(sio_data->has_fanout & (1 << i))) /* Not wired */
648 continue;
649 reg = pc87427_read8_bank(data, LD_FAN, BANK_FC(i),
650 PC87427_REG_PWM_ENABLE);
651 if (reg & PWM_ENABLE_CTLEN)
652 data->pwm_enabled |= (1 << i);
653
654 /* We don't expose an interface to reconfigure the automatic
655 fan control mode, so only allow to return to this mode if
656 it was originally set. */
657 if ((reg & PWM_ENABLE_MODE_MASK) == PWM_MODE_AUTO) {
658 dev_dbg(dev, "PWM%d is in automatic control mode\n",
659 i + 1);
660 data->pwm_auto_ok |= (1 << i);
661 }
662 }
Jean Delvareba224e22006-12-12 18:18:29 +0100663}
664
665static int __devinit pc87427_probe(struct platform_device *pdev)
666{
667 struct pc87427_data *data;
668 struct resource *res;
669 int i, err;
670
Jean Delvare0d22d582010-08-14 21:08:57 +0200671 data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL);
672 if (!data) {
Jean Delvareba224e22006-12-12 18:18:29 +0100673 err = -ENOMEM;
674 printk(KERN_ERR DRVNAME ": Out of memory\n");
675 goto exit;
676 }
677
678 /* This will need to be revisited when we add support for
679 temperature and voltage monitoring. */
680 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
Julia Lawall86855b02009-09-15 17:18:13 +0200681 if (!request_region(res->start, resource_size(res), DRVNAME)) {
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200682 err = -EBUSY;
683 dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
684 (unsigned long)res->start, (unsigned long)res->end);
685 goto exit_kfree;
686 }
Jean Delvareba224e22006-12-12 18:18:29 +0100687 data->address[0] = res->start;
688
689 mutex_init(&data->lock);
690 data->name = "pc87427";
691 platform_set_drvdata(pdev, data);
692 pc87427_init_device(&pdev->dev);
693
694 /* Register sysfs hooks */
Jean Delvare0d22d582010-08-14 21:08:57 +0200695 err = device_create_file(&pdev->dev, &dev_attr_name);
696 if (err)
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200697 goto exit_release_region;
Jean Delvareba224e22006-12-12 18:18:29 +0100698 for (i = 0; i < 8; i++) {
699 if (!(data->fan_enabled & (1 << i)))
700 continue;
Jean Delvare0d22d582010-08-14 21:08:57 +0200701 err = sysfs_create_group(&pdev->dev.kobj,
702 &pc87427_group_fan[i]);
703 if (err)
Jean Delvareba224e22006-12-12 18:18:29 +0100704 goto exit_remove_files;
705 }
Jean Delvare328716b2010-08-14 21:08:58 +0200706 for (i = 0; i < 4; i++) {
707 if (!(data->pwm_enabled & (1 << i)))
708 continue;
709 err = sysfs_create_group(&pdev->dev.kobj,
710 &pc87427_group_pwm[i]);
711 if (err)
712 goto exit_remove_files;
713 }
Jean Delvareba224e22006-12-12 18:18:29 +0100714
Tony Jones1beeffe2007-08-20 13:46:20 -0700715 data->hwmon_dev = hwmon_device_register(&pdev->dev);
716 if (IS_ERR(data->hwmon_dev)) {
717 err = PTR_ERR(data->hwmon_dev);
Jean Delvareba224e22006-12-12 18:18:29 +0100718 dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
719 goto exit_remove_files;
720 }
721
722 return 0;
723
724exit_remove_files:
725 for (i = 0; i < 8; i++) {
726 if (!(data->fan_enabled & (1 << i)))
727 continue;
728 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
729 }
Jean Delvare328716b2010-08-14 21:08:58 +0200730 for (i = 0; i < 4; i++) {
731 if (!(data->pwm_enabled & (1 << i)))
732 continue;
733 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_pwm[i]);
734 }
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200735exit_release_region:
Julia Lawall86855b02009-09-15 17:18:13 +0200736 release_region(res->start, resource_size(res));
Jean Delvareba224e22006-12-12 18:18:29 +0100737exit_kfree:
738 platform_set_drvdata(pdev, NULL);
739 kfree(data);
740exit:
741 return err;
742}
743
744static int __devexit pc87427_remove(struct platform_device *pdev)
745{
746 struct pc87427_data *data = platform_get_drvdata(pdev);
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200747 struct resource *res;
Jean Delvareba224e22006-12-12 18:18:29 +0100748 int i;
749
Tony Jones1beeffe2007-08-20 13:46:20 -0700750 hwmon_device_unregister(data->hwmon_dev);
Jean Delvareba224e22006-12-12 18:18:29 +0100751 device_remove_file(&pdev->dev, &dev_attr_name);
752 for (i = 0; i < 8; i++) {
753 if (!(data->fan_enabled & (1 << i)))
754 continue;
755 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
756 }
Jean Delvare328716b2010-08-14 21:08:58 +0200757 for (i = 0; i < 4; i++) {
758 if (!(data->pwm_enabled & (1 << i)))
759 continue;
760 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_pwm[i]);
761 }
Jean Delvare04a62172007-06-12 13:57:19 +0200762 platform_set_drvdata(pdev, NULL);
Jean Delvareba224e22006-12-12 18:18:29 +0100763 kfree(data);
764
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200765 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
Julia Lawall86855b02009-09-15 17:18:13 +0200766 release_region(res->start, resource_size(res));
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200767
Jean Delvareba224e22006-12-12 18:18:29 +0100768 return 0;
769}
770
771
772static struct platform_driver pc87427_driver = {
773 .driver = {
774 .owner = THIS_MODULE,
775 .name = DRVNAME,
776 },
777 .probe = pc87427_probe,
778 .remove = __devexit_p(pc87427_remove),
779};
780
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200781static int __init pc87427_device_add(unsigned short address,
782 const struct pc87427_sio_data *sio_data)
Jean Delvareba224e22006-12-12 18:18:29 +0100783{
784 struct resource res = {
785 .start = address,
786 .end = address + REGION_LENGTH - 1,
787 .name = logdev_str[0],
788 .flags = IORESOURCE_IO,
789 };
790 int err;
791
Jean Delvareb9acb642009-01-07 16:37:35 +0100792 err = acpi_check_resource_conflict(&res);
793 if (err)
794 goto exit;
795
Jean Delvareba224e22006-12-12 18:18:29 +0100796 pdev = platform_device_alloc(DRVNAME, address);
797 if (!pdev) {
798 err = -ENOMEM;
799 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
800 goto exit;
801 }
802
803 err = platform_device_add_resources(pdev, &res, 1);
804 if (err) {
805 printk(KERN_ERR DRVNAME ": Device resource addition failed "
806 "(%d)\n", err);
807 goto exit_device_put;
808 }
809
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200810 err = platform_device_add_data(pdev, sio_data,
811 sizeof(struct pc87427_sio_data));
812 if (err) {
813 printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
814 goto exit_device_put;
815 }
816
Jean Delvareba224e22006-12-12 18:18:29 +0100817 err = platform_device_add(pdev);
818 if (err) {
819 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
820 err);
821 goto exit_device_put;
822 }
823
824 return 0;
825
826exit_device_put:
827 platform_device_put(pdev);
828exit:
829 return err;
830}
831
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200832static int __init pc87427_find(int sioaddr, unsigned short *address,
833 struct pc87427_sio_data *sio_data)
Jean Delvareba224e22006-12-12 18:18:29 +0100834{
835 u16 val;
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200836 u8 cfg, cfg_b;
Jean Delvareba224e22006-12-12 18:18:29 +0100837 int i, err = 0;
838
839 /* Identify device */
Jean Delvare67b671b2007-12-06 23:13:42 +0100840 val = force_id ? force_id : superio_inb(sioaddr, SIOREG_DEVID);
Jean Delvareba224e22006-12-12 18:18:29 +0100841 if (val != 0xf2) { /* PC87427 */
842 err = -ENODEV;
843 goto exit;
844 }
845
846 for (i = 0; i < 2; i++) {
847 address[i] = 0;
848 /* Select logical device */
849 superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);
850
851 val = superio_inb(sioaddr, SIOREG_ACT);
852 if (!(val & 0x01)) {
853 printk(KERN_INFO DRVNAME ": Logical device 0x%02x "
854 "not activated\n", logdev[i]);
855 continue;
856 }
857
858 val = superio_inb(sioaddr, SIOREG_MAP);
859 if (val & 0x01) {
860 printk(KERN_WARNING DRVNAME ": Logical device 0x%02x "
861 "is memory-mapped, can't use\n", logdev[i]);
862 continue;
863 }
864
865 val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
866 | superio_inb(sioaddr, SIOREG_IOBASE + 1);
867 if (!val) {
868 printk(KERN_INFO DRVNAME ": I/O base address not set "
869 "for logical device 0x%02x\n", logdev[i]);
870 continue;
871 }
872 address[i] = val;
873 }
874
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200875 /* Check which fan inputs are wired */
876 sio_data->has_fanin = (1 << 2) | (1 << 3); /* FANIN2, FANIN3 */
877
878 cfg = superio_inb(sioaddr, SIOREG_CF2);
879 if (!(cfg & (1 << 3)))
880 sio_data->has_fanin |= (1 << 0); /* FANIN0 */
881 if (!(cfg & (1 << 2)))
882 sio_data->has_fanin |= (1 << 4); /* FANIN4 */
883
884 cfg = superio_inb(sioaddr, SIOREG_CFD);
885 if (!(cfg & (1 << 0)))
886 sio_data->has_fanin |= (1 << 1); /* FANIN1 */
887
888 cfg = superio_inb(sioaddr, SIOREG_CF4);
889 if (!(cfg & (1 << 0)))
890 sio_data->has_fanin |= (1 << 7); /* FANIN7 */
891 cfg_b = superio_inb(sioaddr, SIOREG_CFB);
892 if (!(cfg & (1 << 1)) && (cfg_b & (1 << 3)))
893 sio_data->has_fanin |= (1 << 5); /* FANIN5 */
894 cfg = superio_inb(sioaddr, SIOREG_CF3);
895 if ((cfg & (1 << 3)) && !(cfg_b & (1 << 5)))
896 sio_data->has_fanin |= (1 << 6); /* FANIN6 */
897
Jean Delvare328716b2010-08-14 21:08:58 +0200898 /* Check which fan outputs are wired */
899 sio_data->has_fanout = (1 << 0); /* FANOUT0 */
900 if (cfg_b & (1 << 0))
901 sio_data->has_fanout |= (1 << 3); /* FANOUT3 */
902
903 cfg = superio_inb(sioaddr, SIOREG_CFC);
904 if (!(cfg & (1 << 4))) {
905 if (cfg_b & (1 << 1))
906 sio_data->has_fanout |= (1 << 1); /* FANOUT1 */
907 if (cfg_b & (1 << 2))
908 sio_data->has_fanout |= (1 << 2); /* FANOUT2 */
909 }
910
911 /* FANOUT1 and FANOUT2 can each be routed to 2 different pins */
912 cfg = superio_inb(sioaddr, SIOREG_CF5);
913 if (cfg & (1 << 6))
914 sio_data->has_fanout |= (1 << 1); /* FANOUT1 */
915 if (cfg & (1 << 5))
916 sio_data->has_fanout |= (1 << 2); /* FANOUT2 */
917
Jean Delvareba224e22006-12-12 18:18:29 +0100918exit:
919 superio_exit(sioaddr);
920 return err;
921}
922
923static int __init pc87427_init(void)
924{
925 int err;
926 unsigned short address[2];
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200927 struct pc87427_sio_data sio_data;
Jean Delvareba224e22006-12-12 18:18:29 +0100928
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200929 if (pc87427_find(0x2e, address, &sio_data)
930 && pc87427_find(0x4e, address, &sio_data))
Jean Delvareba224e22006-12-12 18:18:29 +0100931 return -ENODEV;
932
933 /* For now the driver only handles fans so we only care about the
934 first address. */
935 if (!address[0])
936 return -ENODEV;
937
938 err = platform_driver_register(&pc87427_driver);
939 if (err)
940 goto exit;
941
942 /* Sets global pdev as a side effect */
Jean Delvare4e7d99e2010-08-14 21:08:56 +0200943 err = pc87427_device_add(address[0], &sio_data);
Jean Delvareba224e22006-12-12 18:18:29 +0100944 if (err)
945 goto exit_driver;
946
947 return 0;
948
949exit_driver:
950 platform_driver_unregister(&pc87427_driver);
951exit:
952 return err;
953}
954
955static void __exit pc87427_exit(void)
956{
957 platform_device_unregister(pdev);
958 platform_driver_unregister(&pc87427_driver);
959}
960
961MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
962MODULE_DESCRIPTION("PC87427 hardware monitoring driver");
963MODULE_LICENSE("GPL");
964
965module_init(pc87427_init);
966module_exit(pc87427_exit);