diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 15:07:28 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 15:07:28 -0400 |
| commit | 36f021b579d195cdc5fa6f3e2bab198b4bf70643 (patch) | |
| tree | 96d3c97f5e5214d2aa7151c12a22a7eb345dbaa1 | |
| parent | 215d06780d13fd7de629b02b61b7b7bf88ce5039 (diff) | |
| parent | 1d72acf91abb327e25137ad2e371c1a788b34e45 (diff) | |
Merge branch 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
* 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6: (32 commits)
Use menuconfig objects - hwmon
hwmon/smsc47b397: Use dynamic sysfs callbacks
hwmon/smsc47b397: Convert to a platform driver
hwmon/w83781d: Deprecate W83627HF support
hwmon/w83781d: Use dynamic sysfs callbacks
hwmon/w83781d: Be less i2c_client-centric
hwmon/w83781d: Clean up conversion macros
hwmon/w83781d: No longer use i2c-isa
hwmon/ams: Do not print error on systems without apple motion sensor
hwmon/ams: Fix I2C read retry logic
hwmon: New AD7416, AD7417 and AD7418 driver
hwmon/coretemp: Add documentation
hwmon: New coretemp driver
i386: Use functions from library in msr driver
i386: Add safe variants of rdmsr_on_cpu and wrmsr_on_cpu
hwmon/lm75: Use dynamic sysfs callbacks
hwmon/lm78: Use dynamic sysfs callbacks
hwmon/lm78: Be less i2c_client-centric
hwmon/lm78: No longer use i2c-isa
hwmon: New max6650 driver
...
29 files changed, 3777 insertions, 1692 deletions
diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp new file mode 100644 index 000000000000..870cda9416e9 --- /dev/null +++ b/Documentation/hwmon/coretemp | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | Kernel driver coretemp | ||
| 2 | ====================== | ||
| 3 | |||
| 4 | Supported chips: | ||
| 5 | * All Intel Core family | ||
| 6 | Prefix: 'coretemp' | ||
| 7 | CPUID: family 0x6, models 0xe, 0xf | ||
| 8 | Datasheet: Intel 64 and IA-32 Architectures Software Developer's Manual | ||
| 9 | Volume 3A: System Programming Guide | ||
| 10 | |||
| 11 | Author: Rudolf Marek | ||
| 12 | |||
| 13 | Description | ||
| 14 | ----------- | ||
| 15 | |||
| 16 | This driver permits reading temperature sensor embedded inside Intel Core CPU. | ||
| 17 | Temperature is measured in degrees Celsius and measurement resolution is | ||
| 18 | 1 degree C. Valid temperatures are from 0 to TjMax degrees C, because | ||
| 19 | the actual value of temperature register is in fact a delta from TjMax. | ||
| 20 | |||
| 21 | Temperature known as TjMax is the maximum junction temperature of processor. | ||
| 22 | Intel defines this temperature as 85C or 100C. At this temperature, protection | ||
| 23 | mechanism will perform actions to forcibly cool down the processor. Alarm | ||
| 24 | may be raised, if the temperature grows enough (more than TjMax) to trigger | ||
| 25 | the Out-Of-Spec bit. Following table summarizes the exported sysfs files: | ||
| 26 | |||
| 27 | temp1_input - Core temperature (in millidegrees Celsius). | ||
| 28 | temp1_crit - Maximum junction temperature (in millidegrees Celsius). | ||
| 29 | temp1_crit_alarm - Set when Out-of-spec bit is set, never clears. | ||
| 30 | Correct CPU operation is no longer guaranteed. | ||
| 31 | temp1_label - Contains string "Core X", where X is processor | ||
| 32 | number. | ||
| 33 | |||
| 34 | The TjMax temperature is set to 85 degrees C if undocumented model specific | ||
| 35 | register (UMSR) 0xee has bit 30 set. If not the TjMax is 100 degrees C as | ||
| 36 | (sometimes) documented in processor datasheet. | ||
diff --git a/Documentation/hwmon/max6650 b/Documentation/hwmon/max6650 new file mode 100644 index 000000000000..8be7beb9e3e8 --- /dev/null +++ b/Documentation/hwmon/max6650 | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | Kernel driver max6650 | ||
| 2 | ===================== | ||
| 3 | |||
| 4 | Supported chips: | ||
| 5 | * Maxim 6650 / 6651 | ||
| 6 | Prefix: 'max6650' | ||
| 7 | Addresses scanned: I2C 0x1b, 0x1f, 0x48, 0x4b | ||
| 8 | Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf | ||
| 9 | |||
| 10 | Authors: | ||
| 11 | Hans J. Koch <hjk@linutronix.de> | ||
| 12 | John Morris <john.morris@spirentcom.com> | ||
| 13 | Claus Gindhart <claus.gindhart@kontron.com> | ||
| 14 | |||
| 15 | Description | ||
| 16 | ----------- | ||
| 17 | |||
| 18 | This driver implements support for the Maxim 6650/6651 | ||
| 19 | |||
| 20 | The 2 devices are very similar, but the Maxim 6550 has a reduced feature | ||
| 21 | set, e.g. only one fan-input, instead of 4 for the 6651. | ||
| 22 | |||
| 23 | The driver is not able to distinguish between the 2 devices. | ||
| 24 | |||
| 25 | The driver provides the following sensor accesses in sysfs: | ||
| 26 | |||
| 27 | fan1_input ro fan tachometer speed in RPM | ||
| 28 | fan2_input ro " | ||
| 29 | fan3_input ro " | ||
| 30 | fan4_input ro " | ||
| 31 | fan1_target rw desired fan speed in RPM (closed loop mode only) | ||
| 32 | pwm1_enable rw regulator mode, 0=full on, 1=open loop, 2=closed loop | ||
| 33 | pwm1 rw relative speed (0-255), 255=max. speed. | ||
| 34 | Used in open loop mode only. | ||
| 35 | fan1_div rw sets the speed range the inputs can handle. Legal | ||
| 36 | values are 1, 2, 4, and 8. Use lower values for | ||
| 37 | faster fans. | ||
| 38 | |||
| 39 | Module parameters | ||
| 40 | ----------------- | ||
| 41 | |||
| 42 | If your board has a BIOS that initializes the MAX6650/6651 correctly, you can | ||
| 43 | simply load your module without parameters. It won't touch the configuration | ||
| 44 | registers then. If your board BIOS doesn't initialize the chip, or you want | ||
| 45 | different settings, you can set the following parameters: | ||
| 46 | |||
| 47 | voltage_12V: 5=5V fan, 12=12V fan, 0=don't change | ||
| 48 | prescaler: Possible values are 1,2,4,8,16, or 0 for don't change | ||
| 49 | clock: The clock frequency in Hz of the chip the driver should assume [254000] | ||
| 50 | |||
| 51 | Please have a look at the MAX6650/6651 data sheet and make sure that you fully | ||
| 52 | understand the meaning of these parameters before you attempt to change them. | ||
| 53 | |||
diff --git a/Documentation/hwmon/smsc47m1 b/Documentation/hwmon/smsc47m1 index 04a11124f667..42c8431b3c9d 100644 --- a/Documentation/hwmon/smsc47m1 +++ b/Documentation/hwmon/smsc47m1 | |||
| @@ -14,6 +14,10 @@ Supported chips: | |||
| 14 | http://www.smsc.com/main/datasheets/47m14x.pdf | 14 | http://www.smsc.com/main/datasheets/47m14x.pdf |
| 15 | http://www.smsc.com/main/tools/discontinued/47m15x.pdf | 15 | http://www.smsc.com/main/tools/discontinued/47m15x.pdf |
| 16 | http://www.smsc.com/main/datasheets/47m192.pdf | 16 | http://www.smsc.com/main/datasheets/47m192.pdf |
| 17 | * SMSC LPC47M292 | ||
| 18 | Addresses scanned: none, address read from Super I/O config space | ||
| 19 | Prefix: 'smsc47m2' | ||
| 20 | Datasheet: Not public | ||
| 17 | * SMSC LPC47M997 | 21 | * SMSC LPC47M997 |
| 18 | Addresses scanned: none, address read from Super I/O config space | 22 | Addresses scanned: none, address read from Super I/O config space |
| 19 | Prefix: 'smsc47m1' | 23 | Prefix: 'smsc47m1' |
| @@ -32,9 +36,10 @@ Description | |||
| 32 | The Standard Microsystems Corporation (SMSC) 47M1xx Super I/O chips | 36 | The Standard Microsystems Corporation (SMSC) 47M1xx Super I/O chips |
| 33 | contain monitoring and PWM control circuitry for two fans. | 37 | contain monitoring and PWM control circuitry for two fans. |
| 34 | 38 | ||
| 35 | The 47M15x and 47M192 chips contain a full 'hardware monitoring block' | 39 | The LPC47M15x, LPC47M192 and LPC47M292 chips contain a full 'hardware |
| 36 | in addition to the fan monitoring and control. The hardware monitoring | 40 | monitoring block' in addition to the fan monitoring and control. The |
| 37 | block is not supported by the driver. | 41 | hardware monitoring block is not supported by this driver, use the |
| 42 | smsc47m192 driver for that. | ||
| 38 | 43 | ||
| 39 | No documentation is available for the 47M997, but it has the same device | 44 | No documentation is available for the 47M997, but it has the same device |
| 40 | ID as the 47M15x and 47M192 chips and seems to be compatible. | 45 | ID as the 47M15x and 47M192 chips and seems to be compatible. |
diff --git a/Documentation/hwmon/smsc47m192 b/Documentation/hwmon/smsc47m192 index 45d6453cd435..6d54ecb7b3f8 100644 --- a/Documentation/hwmon/smsc47m192 +++ b/Documentation/hwmon/smsc47m192 | |||
| @@ -2,12 +2,13 @@ Kernel driver smsc47m192 | |||
| 2 | ======================== | 2 | ======================== |
| 3 | 3 | ||
| 4 | Supported chips: | 4 | Supported chips: |
| 5 | * SMSC LPC47M192 and LPC47M997 | 5 | * SMSC LPC47M192, LPC47M15x, LPC47M292 and LPC47M997 |
| 6 | Prefix: 'smsc47m192' | 6 | Prefix: 'smsc47m192' |
| 7 | Addresses scanned: I2C 0x2c - 0x2d | 7 | Addresses scanned: I2C 0x2c - 0x2d |
| 8 | Datasheet: The datasheet for LPC47M192 is publicly available from | 8 | Datasheet: The datasheet for LPC47M192 is publicly available from |
| 9 | http://www.smsc.com/ | 9 | http://www.smsc.com/ |
| 10 | The LPC47M997 is compatible for hardware monitoring. | 10 | The LPC47M15x, LPC47M292 and LPC47M997 are compatible for |
| 11 | hardware monitoring. | ||
| 11 | 12 | ||
| 12 | Author: Hartmut Rick <linux@rick.claranet.de> | 13 | Author: Hartmut Rick <linux@rick.claranet.de> |
| 13 | Special thanks to Jean Delvare for careful checking | 14 | Special thanks to Jean Delvare for careful checking |
| @@ -18,7 +19,7 @@ Description | |||
| 18 | ----------- | 19 | ----------- |
| 19 | 20 | ||
| 20 | This driver implements support for the hardware sensor capabilities | 21 | This driver implements support for the hardware sensor capabilities |
| 21 | of the SMSC LPC47M192 and LPC47M997 Super-I/O chips. | 22 | of the SMSC LPC47M192 and compatible Super-I/O chips. |
| 22 | 23 | ||
| 23 | These chips support 3 temperature channels and 8 voltage inputs | 24 | These chips support 3 temperature channels and 8 voltage inputs |
| 24 | as well as CPU voltage VID input. | 25 | as well as CPU voltage VID input. |
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index d73d2e8c7534..a9a18ad0d17a 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface | |||
| @@ -152,6 +152,13 @@ fan[1-*]_div Fan divisor. | |||
| 152 | Note that this is actually an internal clock divisor, which | 152 | Note that this is actually an internal clock divisor, which |
| 153 | affects the measurable speed range, not the read value. | 153 | affects the measurable speed range, not the read value. |
| 154 | 154 | ||
| 155 | fan[1-*]_target | ||
| 156 | Desired fan speed | ||
| 157 | Unit: revolution/min (RPM) | ||
| 158 | RW | ||
| 159 | Only makes sense if the chip supports closed-loop fan speed | ||
| 160 | control based on the measured fan speed. | ||
| 161 | |||
| 155 | Also see the Alarms section for status flags associated with fans. | 162 | Also see the Alarms section for status flags associated with fans. |
| 156 | 163 | ||
| 157 | 164 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 69f3f66091b4..41a4b477c576 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -1040,6 +1040,12 @@ P: Simon Arlott | |||
| 1040 | M: cxacru@fire.lp0.eu | 1040 | M: cxacru@fire.lp0.eu |
| 1041 | S: Maintained | 1041 | S: Maintained |
| 1042 | 1042 | ||
| 1043 | CORETEMP HARDWARE MONITORING DRIVER | ||
| 1044 | P: Rudolf Marek | ||
| 1045 | M: r.marek@assembler.cz | ||
| 1046 | L: lm-sensors@lm-sensors.org | ||
| 1047 | S: Maintained | ||
| 1048 | |||
| 1043 | COSA/SRP SYNC SERIAL DRIVER | 1049 | COSA/SRP SYNC SERIAL DRIVER |
| 1044 | P: Jan "Yenya" Kasprzak | 1050 | P: Jan "Yenya" Kasprzak |
| 1045 | M: kas@fi.muni.cz | 1051 | M: kas@fi.muni.cz |
| @@ -2314,6 +2320,12 @@ M: vandrove@vc.cvut.cz | |||
| 2314 | L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) | 2320 | L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) |
| 2315 | S: Maintained | 2321 | S: Maintained |
| 2316 | 2322 | ||
| 2323 | MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER | ||
| 2324 | P: Hans J. Koch | ||
| 2325 | M: hjk@linutronix.de | ||
| 2326 | L: lm-sensors@lm-sensors.org | ||
| 2327 | S: Maintained | ||
| 2328 | |||
| 2317 | MEGARAID SCSI DRIVERS | 2329 | MEGARAID SCSI DRIVERS |
| 2318 | P: Neela Syam Kolli | 2330 | P: Neela Syam Kolli |
| 2319 | M: Neela.Kolli@engenio.com | 2331 | M: Neela.Kolli@engenio.com |
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c index bcaa6e9b6197..8cd0a91ce107 100644 --- a/arch/i386/kernel/msr.c +++ b/arch/i386/kernel/msr.c | |||
| @@ -45,104 +45,6 @@ | |||
| 45 | 45 | ||
| 46 | static struct class *msr_class; | 46 | static struct class *msr_class; |
| 47 | 47 | ||
| 48 | static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx) | ||
| 49 | { | ||
| 50 | int err; | ||
| 51 | |||
| 52 | err = wrmsr_safe(reg, eax, edx); | ||
| 53 | if (err) | ||
| 54 | err = -EIO; | ||
| 55 | return err; | ||
| 56 | } | ||
| 57 | |||
| 58 | static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx) | ||
| 59 | { | ||
| 60 | int err; | ||
| 61 | |||
| 62 | err = rdmsr_safe(reg, eax, edx); | ||
| 63 | if (err) | ||
| 64 | err = -EIO; | ||
| 65 | return err; | ||
| 66 | } | ||
| 67 | |||
| 68 | #ifdef CONFIG_SMP | ||
| 69 | |||
| 70 | struct msr_command { | ||
| 71 | int err; | ||
| 72 | u32 reg; | ||
| 73 | u32 data[2]; | ||
| 74 | }; | ||
| 75 | |||
| 76 | static void msr_smp_wrmsr(void *cmd_block) | ||
| 77 | { | ||
| 78 | struct msr_command *cmd = (struct msr_command *)cmd_block; | ||
| 79 | |||
| 80 | cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]); | ||
| 81 | } | ||
| 82 | |||
| 83 | static void msr_smp_rdmsr(void *cmd_block) | ||
| 84 | { | ||
| 85 | struct msr_command *cmd = (struct msr_command *)cmd_block; | ||
| 86 | |||
| 87 | cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]); | ||
| 88 | } | ||
| 89 | |||
| 90 | static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) | ||
| 91 | { | ||
| 92 | struct msr_command cmd; | ||
| 93 | int ret; | ||
| 94 | |||
| 95 | preempt_disable(); | ||
| 96 | if (cpu == smp_processor_id()) { | ||
| 97 | ret = wrmsr_eio(reg, eax, edx); | ||
| 98 | } else { | ||
| 99 | cmd.reg = reg; | ||
| 100 | cmd.data[0] = eax; | ||
| 101 | cmd.data[1] = edx; | ||
| 102 | |||
| 103 | smp_call_function_single(cpu, msr_smp_wrmsr, &cmd, 1, 1); | ||
| 104 | ret = cmd.err; | ||
| 105 | } | ||
| 106 | preempt_enable(); | ||
| 107 | return ret; | ||
| 108 | } | ||
| 109 | |||
| 110 | static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx) | ||
| 111 | { | ||
| 112 | struct msr_command cmd; | ||
| 113 | int ret; | ||
| 114 | |||
| 115 | preempt_disable(); | ||
| 116 | if (cpu == smp_processor_id()) { | ||
| 117 | ret = rdmsr_eio(reg, eax, edx); | ||
| 118 | } else { | ||
| 119 | cmd.reg = reg; | ||
| 120 | |||
| 121 | smp_call_function_single(cpu, msr_smp_rdmsr, &cmd, 1, 1); | ||
| 122 | |||
| 123 | *eax = cmd.data[0]; | ||
| 124 | *edx = cmd.data[1]; | ||
| 125 | |||
| 126 | ret = cmd.err; | ||
| 127 | } | ||
| 128 | preempt_enable(); | ||
| 129 | return ret; | ||
| 130 | } | ||
| 131 | |||
| 132 | #else /* ! CONFIG_SMP */ | ||
| 133 | |||
| 134 | static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) | ||
| 135 | { | ||
| 136 | return wrmsr_eio(reg, eax, edx); | ||
| 137 | } | ||
| 138 | |||
| 139 | static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) | ||
| 140 | { | ||
| 141 | return rdmsr_eio(reg, eax, edx); | ||
| 142 | } | ||
| 143 | |||
| 144 | #endif /* ! CONFIG_SMP */ | ||
| 145 | |||
| 146 | static loff_t msr_seek(struct file *file, loff_t offset, int orig) | 48 | static loff_t msr_seek(struct file *file, loff_t offset, int orig) |
| 147 | { | 49 | { |
| 148 | loff_t ret = -EINVAL; | 50 | loff_t ret = -EINVAL; |
| @@ -174,9 +76,9 @@ static ssize_t msr_read(struct file *file, char __user * buf, | |||
| 174 | return -EINVAL; /* Invalid chunk size */ | 76 | return -EINVAL; /* Invalid chunk size */ |
| 175 | 77 | ||
| 176 | for (; count; count -= 8) { | 78 | for (; count; count -= 8) { |
| 177 | err = do_rdmsr(cpu, reg, &data[0], &data[1]); | 79 | err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]); |
| 178 | if (err) | 80 | if (err) |
| 179 | return err; | 81 | return -EIO; |
| 180 | if (copy_to_user(tmp, &data, 8)) | 82 | if (copy_to_user(tmp, &data, 8)) |
| 181 | return -EFAULT; | 83 | return -EFAULT; |
| 182 | tmp += 2; | 84 | tmp += 2; |
| @@ -200,9 +102,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf, | |||
| 200 | for (; count; count -= 8) { | 102 | for (; count; count -= 8) { |
| 201 | if (copy_from_user(&data, tmp, 8)) | 103 | if (copy_from_user(&data, tmp, 8)) |
| 202 | return -EFAULT; | 104 | return -EFAULT; |
| 203 | err = do_wrmsr(cpu, reg, data[0], data[1]); | 105 | err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]); |
| 204 | if (err) | 106 | if (err) |
| 205 | return err; | 107 | return -EIO; |
| 206 | tmp += 2; | 108 | tmp += 2; |
| 207 | } | 109 | } |
| 208 | 110 | ||
diff --git a/arch/i386/lib/msr-on-cpu.c b/arch/i386/lib/msr-on-cpu.c index 1c46bda409ff..7767962f25d3 100644 --- a/arch/i386/lib/msr-on-cpu.c +++ b/arch/i386/lib/msr-on-cpu.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | struct msr_info { | 6 | struct msr_info { |
| 7 | u32 msr_no; | 7 | u32 msr_no; |
| 8 | u32 l, h; | 8 | u32 l, h; |
| 9 | int err; | ||
| 9 | }; | 10 | }; |
| 10 | 11 | ||
| 11 | static void __rdmsr_on_cpu(void *info) | 12 | static void __rdmsr_on_cpu(void *info) |
| @@ -15,20 +16,38 @@ static void __rdmsr_on_cpu(void *info) | |||
| 15 | rdmsr(rv->msr_no, rv->l, rv->h); | 16 | rdmsr(rv->msr_no, rv->l, rv->h); |
| 16 | } | 17 | } |
| 17 | 18 | ||
| 18 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | 19 | static void __rdmsr_safe_on_cpu(void *info) |
| 19 | { | 20 | { |
| 21 | struct msr_info *rv = info; | ||
| 22 | |||
| 23 | rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h); | ||
| 24 | } | ||
| 25 | |||
| 26 | static int _rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h, int safe) | ||
| 27 | { | ||
| 28 | int err = 0; | ||
| 20 | preempt_disable(); | 29 | preempt_disable(); |
| 21 | if (smp_processor_id() == cpu) | 30 | if (smp_processor_id() == cpu) |
| 22 | rdmsr(msr_no, *l, *h); | 31 | if (safe) |
| 32 | err = rdmsr_safe(msr_no, l, h); | ||
| 33 | else | ||
| 34 | rdmsr(msr_no, *l, *h); | ||
| 23 | else { | 35 | else { |
| 24 | struct msr_info rv; | 36 | struct msr_info rv; |
| 25 | 37 | ||
| 26 | rv.msr_no = msr_no; | 38 | rv.msr_no = msr_no; |
| 27 | smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1); | 39 | if (safe) { |
| 40 | smp_call_function_single(cpu, __rdmsr_safe_on_cpu, | ||
| 41 | &rv, 0, 1); | ||
| 42 | err = rv.err; | ||
| 43 | } else { | ||
| 44 | smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1); | ||
| 45 | } | ||
| 28 | *l = rv.l; | 46 | *l = rv.l; |
| 29 | *h = rv.h; | 47 | *h = rv.h; |
| 30 | } | 48 | } |
| 31 | preempt_enable(); | 49 | preempt_enable(); |
| 50 | return err; | ||
| 32 | } | 51 | } |
| 33 | 52 | ||
| 34 | static void __wrmsr_on_cpu(void *info) | 53 | static void __wrmsr_on_cpu(void *info) |
| @@ -38,21 +57,63 @@ static void __wrmsr_on_cpu(void *info) | |||
| 38 | wrmsr(rv->msr_no, rv->l, rv->h); | 57 | wrmsr(rv->msr_no, rv->l, rv->h); |
| 39 | } | 58 | } |
| 40 | 59 | ||
| 41 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | 60 | static void __wrmsr_safe_on_cpu(void *info) |
| 42 | { | 61 | { |
| 62 | struct msr_info *rv = info; | ||
| 63 | |||
| 64 | rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h); | ||
| 65 | } | ||
| 66 | |||
| 67 | static int _wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h, int safe) | ||
| 68 | { | ||
| 69 | int err = 0; | ||
| 43 | preempt_disable(); | 70 | preempt_disable(); |
| 44 | if (smp_processor_id() == cpu) | 71 | if (smp_processor_id() == cpu) |
| 45 | wrmsr(msr_no, l, h); | 72 | if (safe) |
| 73 | err = wrmsr_safe(msr_no, l, h); | ||
| 74 | else | ||
| 75 | wrmsr(msr_no, l, h); | ||
| 46 | else { | 76 | else { |
| 47 | struct msr_info rv; | 77 | struct msr_info rv; |
| 48 | 78 | ||
| 49 | rv.msr_no = msr_no; | 79 | rv.msr_no = msr_no; |
| 50 | rv.l = l; | 80 | rv.l = l; |
| 51 | rv.h = h; | 81 | rv.h = h; |
| 52 | smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1); | 82 | if (safe) { |
| 83 | smp_call_function_single(cpu, __wrmsr_safe_on_cpu, | ||
| 84 | &rv, 0, 1); | ||
| 85 | err = rv.err; | ||
| 86 | } else { | ||
| 87 | smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1); | ||
| 88 | } | ||
| 53 | } | 89 | } |
| 54 | preempt_enable(); | 90 | preempt_enable(); |
| 91 | return err; | ||
| 92 | } | ||
| 93 | |||
| 94 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | ||
| 95 | { | ||
| 96 | _wrmsr_on_cpu(cpu, msr_no, l, h, 0); | ||
| 97 | } | ||
| 98 | |||
| 99 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | ||
| 100 | { | ||
| 101 | _rdmsr_on_cpu(cpu, msr_no, l, h, 0); | ||
| 102 | } | ||
| 103 | |||
| 104 | /* These "safe" variants are slower and should be used when the target MSR | ||
| 105 | may not actually exist. */ | ||
| 106 | int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | ||
| 107 | { | ||
| 108 | return _wrmsr_on_cpu(cpu, msr_no, l, h, 1); | ||
| 109 | } | ||
| 110 | |||
| 111 | int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | ||
| 112 | { | ||
| 113 | return _rdmsr_on_cpu(cpu, msr_no, l, h, 1); | ||
| 55 | } | 114 | } |
| 56 | 115 | ||
| 57 | EXPORT_SYMBOL(rdmsr_on_cpu); | 116 | EXPORT_SYMBOL(rdmsr_on_cpu); |
| 58 | EXPORT_SYMBOL(wrmsr_on_cpu); | 117 | EXPORT_SYMBOL(wrmsr_on_cpu); |
| 118 | EXPORT_SYMBOL(rdmsr_safe_on_cpu); | ||
| 119 | EXPORT_SYMBOL(wrmsr_safe_on_cpu); | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 25b72a491702..3ba3a5221c41 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -2,9 +2,7 @@ | |||
| 2 | # Hardware monitoring chip drivers configuration | 2 | # Hardware monitoring chip drivers configuration |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | menu "Hardware Monitoring support" | 5 | menuconfig HWMON |
| 6 | |||
| 7 | config HWMON | ||
| 8 | tristate "Hardware Monitoring support" | 6 | tristate "Hardware Monitoring support" |
| 9 | default y | 7 | default y |
| 10 | help | 8 | help |
| @@ -23,13 +21,15 @@ config HWMON | |||
| 23 | This support can also be built as a module. If so, the module | 21 | This support can also be built as a module. If so, the module |
| 24 | will be called hwmon. | 22 | will be called hwmon. |
| 25 | 23 | ||
| 24 | if HWMON | ||
| 25 | |||
| 26 | config HWMON_VID | 26 | config HWMON_VID |
| 27 | tristate | 27 | tristate |
| 28 | default n | 28 | default n |
| 29 | 29 | ||
| 30 | config SENSORS_ABITUGURU | 30 | config SENSORS_ABITUGURU |
| 31 | tristate "Abit uGuru" | 31 | tristate "Abit uGuru" |
| 32 | depends on HWMON && EXPERIMENTAL | 32 | depends on EXPERIMENTAL |
| 33 | help | 33 | help |
| 34 | If you say yes here you get support for the Abit uGuru chips | 34 | If you say yes here you get support for the Abit uGuru chips |
| 35 | sensor part. The voltage and frequency control parts of the Abit | 35 | sensor part. The voltage and frequency control parts of the Abit |
| @@ -39,9 +39,19 @@ config SENSORS_ABITUGURU | |||
| 39 | This driver can also be built as a module. If so, the module | 39 | This driver can also be built as a module. If so, the module |
| 40 | will be called abituguru. | 40 | will be called abituguru. |
| 41 | 41 | ||
| 42 | config SENSORS_AD7418 | ||
| 43 | tristate "Analog Devices AD7416, AD7417 and AD7418" | ||
| 44 | depends on I2C && EXPERIMENTAL | ||
| 45 | help | ||
| 46 | If you say yes here you get support for the Analog Devices | ||
| 47 | AD7416, AD7417 and AD7418 temperature monitoring chips. | ||
| 48 | |||
| 49 | This driver can also be built as a module. If so, the module | ||
| 50 | will be called ad7418. | ||
| 51 | |||
| 42 | config SENSORS_ADM1021 | 52 | config SENSORS_ADM1021 |
| 43 | tristate "Analog Devices ADM1021 and compatibles" | 53 | tristate "Analog Devices ADM1021 and compatibles" |
| 44 | depends on HWMON && I2C | 54 | depends on I2C |
| 45 | help | 55 | help |
| 46 | If you say yes here you get support for Analog Devices ADM1021 | 56 | If you say yes here you get support for Analog Devices ADM1021 |
| 47 | and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A, | 57 | and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A, |
| @@ -53,7 +63,7 @@ config SENSORS_ADM1021 | |||
| 53 | 63 | ||
| 54 | config SENSORS_ADM1025 | 64 | config SENSORS_ADM1025 |
| 55 | tristate "Analog Devices ADM1025 and compatibles" | 65 | tristate "Analog Devices ADM1025 and compatibles" |
| 56 | depends on HWMON && I2C | 66 | depends on I2C |
| 57 | select HWMON_VID | 67 | select HWMON_VID |
| 58 | help | 68 | help |
| 59 | If you say yes here you get support for Analog Devices ADM1025 | 69 | If you say yes here you get support for Analog Devices ADM1025 |
| @@ -64,7 +74,7 @@ config SENSORS_ADM1025 | |||
| 64 | 74 | ||
| 65 | config SENSORS_ADM1026 | 75 | config SENSORS_ADM1026 |
| 66 | tristate "Analog Devices ADM1026 and compatibles" | 76 | tristate "Analog Devices ADM1026 and compatibles" |
| 67 | depends on HWMON && I2C && EXPERIMENTAL | 77 | depends on I2C && EXPERIMENTAL |
| 68 | select HWMON_VID | 78 | select HWMON_VID |
| 69 | help | 79 | help |
| 70 | If you say yes here you get support for Analog Devices ADM1026 | 80 | If you say yes here you get support for Analog Devices ADM1026 |
| @@ -75,7 +85,7 @@ config SENSORS_ADM1026 | |||
| 75 | 85 | ||
| 76 | config SENSORS_ADM1029 | 86 | config SENSORS_ADM1029 |
| 77 | tristate "Analog Devices ADM1029" | 87 | tristate "Analog Devices ADM1029" |
| 78 | depends on HWMON && I2C && EXPERIMENTAL | 88 | depends on I2C && EXPERIMENTAL |
| 79 | help | 89 | help |
| 80 | If you say yes here you get support for Analog Devices ADM1029 | 90 | If you say yes here you get support for Analog Devices ADM1029 |
| 81 | sensor chip. | 91 | sensor chip. |
| @@ -86,7 +96,7 @@ config SENSORS_ADM1029 | |||
| 86 | 96 | ||
| 87 | config SENSORS_ADM1031 | 97 | config SENSORS_ADM1031 |
| 88 | tristate "Analog Devices ADM1031 and compatibles" | 98 | tristate "Analog Devices ADM1031 and compatibles" |
| 89 | depends on HWMON && I2C && EXPERIMENTAL | 99 | depends on I2C && EXPERIMENTAL |
| 90 | help | 100 | help |
| 91 | If you say yes here you get support for Analog Devices ADM1031 | 101 | If you say yes here you get support for Analog Devices ADM1031 |
| 92 | and ADM1030 sensor chips. | 102 | and ADM1030 sensor chips. |
| @@ -96,7 +106,7 @@ config SENSORS_ADM1031 | |||
| 96 | 106 | ||
| 97 | config SENSORS_ADM9240 | 107 | config SENSORS_ADM9240 |
| 98 | tristate "Analog Devices ADM9240 and compatibles" | 108 | tristate "Analog Devices ADM9240 and compatibles" |
| 99 | depends on HWMON && I2C && EXPERIMENTAL | 109 | depends on I2C && EXPERIMENTAL |
| 100 | select HWMON_VID | 110 | select HWMON_VID |
| 101 | help | 111 | help |
| 102 | If you say yes here you get support for Analog Devices ADM9240, | 112 | If you say yes here you get support for Analog Devices ADM9240, |
| @@ -107,7 +117,7 @@ config SENSORS_ADM9240 | |||
| 107 | 117 | ||
| 108 | config SENSORS_K8TEMP | 118 | config SENSORS_K8TEMP |
| 109 | tristate "AMD Athlon64/FX or Opteron temperature sensor" | 119 | tristate "AMD Athlon64/FX or Opteron temperature sensor" |
| 110 | depends on HWMON && X86 && PCI && EXPERIMENTAL | 120 | depends on X86 && PCI && EXPERIMENTAL |
| 111 | help | 121 | help |
| 112 | If you say yes here you get support for the temperature | 122 | If you say yes here you get support for the temperature |
| 113 | sensor(s) inside your CPU. Supported is whole AMD K8 | 123 | sensor(s) inside your CPU. Supported is whole AMD K8 |
| @@ -119,7 +129,7 @@ config SENSORS_K8TEMP | |||
| 119 | 129 | ||
| 120 | config SENSORS_AMS | 130 | config SENSORS_AMS |
| 121 | tristate "Apple Motion Sensor driver" | 131 | tristate "Apple Motion Sensor driver" |
| 122 | depends on HWMON && PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL | 132 | depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL |
| 123 | help | 133 | help |
| 124 | Support for the motion sensor included in PowerBooks. Includes | 134 | Support for the motion sensor included in PowerBooks. Includes |
| 125 | implementations for PMU and I2C. | 135 | implementations for PMU and I2C. |
| @@ -144,7 +154,7 @@ config SENSORS_AMS_I2C | |||
| 144 | 154 | ||
| 145 | config SENSORS_ASB100 | 155 | config SENSORS_ASB100 |
| 146 | tristate "Asus ASB100 Bach" | 156 | tristate "Asus ASB100 Bach" |
| 147 | depends on HWMON && I2C && EXPERIMENTAL | 157 | depends on I2C && EXPERIMENTAL |
| 148 | select HWMON_VID | 158 | select HWMON_VID |
| 149 | help | 159 | help |
| 150 | If you say yes here you get support for the ASB100 Bach sensor | 160 | If you say yes here you get support for the ASB100 Bach sensor |
| @@ -155,7 +165,7 @@ config SENSORS_ASB100 | |||
| 155 | 165 | ||
| 156 | config SENSORS_ATXP1 | 166 | config SENSORS_ATXP1 |
| 157 | tristate "Attansic ATXP1 VID controller" | 167 | tristate "Attansic ATXP1 VID controller" |
| 158 | depends on HWMON && I2C && EXPERIMENTAL | 168 | depends on I2C && EXPERIMENTAL |
| 159 | select HWMON_VID | 169 | select HWMON_VID |
| 160 | help | 170 | help |
| 161 | If you say yes here you get support for the Attansic ATXP1 VID | 171 | If you say yes here you get support for the Attansic ATXP1 VID |
| @@ -169,7 +179,7 @@ config SENSORS_ATXP1 | |||
| 169 | 179 | ||
| 170 | config SENSORS_DS1621 | 180 | config SENSORS_DS1621 |
| 171 | tristate "Dallas Semiconductor DS1621 and DS1625" | 181 | tristate "Dallas Semiconductor DS1621 and DS1625" |
| 172 | depends on HWMON && I2C | 182 | depends on I2C |
| 173 | help | 183 | help |
| 174 | If you say yes here you get support for Dallas Semiconductor | 184 | If you say yes here you get support for Dallas Semiconductor |
| 175 | DS1621 and DS1625 sensor chips. | 185 | DS1621 and DS1625 sensor chips. |
| @@ -179,7 +189,7 @@ config SENSORS_DS1621 | |||
| 179 | 189 | ||
| 180 | config SENSORS_F71805F | 190 | config SENSORS_F71805F |
| 181 | tristate "Fintek F71805F/FG and F71872F/FG" | 191 | tristate "Fintek F71805F/FG and F71872F/FG" |
| 182 | depends on HWMON && EXPERIMENTAL | 192 | depends on EXPERIMENTAL |
| 183 | help | 193 | help |
| 184 | If you say yes here you get support for hardware monitoring | 194 | If you say yes here you get support for hardware monitoring |
| 185 | features of the Fintek F71805F/FG and F71872F/FG Super-I/O | 195 | features of the Fintek F71805F/FG and F71872F/FG Super-I/O |
| @@ -190,7 +200,7 @@ config SENSORS_F71805F | |||
| 190 | 200 | ||
| 191 | config SENSORS_FSCHER | 201 | config SENSORS_FSCHER |
| 192 | tristate "FSC Hermes" | 202 | tristate "FSC Hermes" |
| 193 | depends on HWMON && I2C | 203 | depends on I2C |
| 194 | help | 204 | help |
| 195 | If you say yes here you get support for Fujitsu Siemens | 205 | If you say yes here you get support for Fujitsu Siemens |
| 196 | Computers Hermes sensor chips. | 206 | Computers Hermes sensor chips. |
| @@ -200,7 +210,7 @@ config SENSORS_FSCHER | |||
| 200 | 210 | ||
| 201 | config SENSORS_FSCPOS | 211 | config SENSORS_FSCPOS |
| 202 | tristate "FSC Poseidon" | 212 | tristate "FSC Poseidon" |
| 203 | depends on HWMON && I2C | 213 | depends on I2C |
| 204 | help | 214 | help |
| 205 | If you say yes here you get support for Fujitsu Siemens | 215 | If you say yes here you get support for Fujitsu Siemens |
| 206 | Computers Poseidon sensor chips. | 216 | Computers Poseidon sensor chips. |
| @@ -210,7 +220,7 @@ config SENSORS_FSCPOS | |||
| 210 | 220 | ||
| 211 | config SENSORS_GL518SM | 221 | config SENSORS_GL518SM |
| 212 | tristate "Genesys Logic GL518SM" | 222 | tristate "Genesys Logic GL518SM" |
| 213 | depends on HWMON && I2C | 223 | depends on I2C |
| 214 | help | 224 | help |
| 215 | If you say yes here you get support for Genesys Logic GL518SM | 225 | If you say yes here you get support for Genesys Logic GL518SM |
| 216 | sensor chips. | 226 | sensor chips. |
| @@ -220,7 +230,7 @@ config SENSORS_GL518SM | |||
| 220 | 230 | ||
| 221 | config SENSORS_GL520SM | 231 | config SENSORS_GL520SM |
| 222 | tristate "Genesys Logic GL520SM" | 232 | tristate "Genesys Logic GL520SM" |
| 223 | depends on HWMON && I2C | 233 | depends on I2C |
| 224 | select HWMON_VID | 234 | select HWMON_VID |
| 225 | help | 235 | help |
| 226 | If you say yes here you get support for Genesys Logic GL520SM | 236 | If you say yes here you get support for Genesys Logic GL520SM |
| @@ -229,9 +239,17 @@ config SENSORS_GL520SM | |||
| 229 | This driver can also be built as a module. If so, the module | 239 | This driver can also be built as a module. If so, the module |
| 230 | will be called gl520sm. | 240 | will be called gl520sm. |
| 231 | 241 | ||
| 242 | config SENSORS_CORETEMP | ||
| 243 | tristate "Intel Core (2) Duo/Solo temperature sensor" | ||
| 244 | depends on X86 && EXPERIMENTAL | ||
| 245 | help | ||
| 246 | If you say yes here you get support for the temperature | ||
| 247 | sensor inside your CPU. Supported all are all known variants | ||
| 248 | of Intel Core family. | ||
| 249 | |||
| 232 | config SENSORS_IT87 | 250 | config SENSORS_IT87 |
| 233 | tristate "ITE IT87xx and compatibles" | 251 | tristate "ITE IT87xx and compatibles" |
| 234 | depends on HWMON && I2C | 252 | depends on I2C |
| 235 | select I2C_ISA | 253 | select I2C_ISA |
| 236 | select HWMON_VID | 254 | select HWMON_VID |
| 237 | help | 255 | help |
| @@ -243,7 +261,7 @@ config SENSORS_IT87 | |||
| 243 | 261 | ||
| 244 | config SENSORS_LM63 | 262 | config SENSORS_LM63 |
| 245 | tristate "National Semiconductor LM63" | 263 | tristate "National Semiconductor LM63" |
| 246 | depends on HWMON && I2C | 264 | depends on I2C |
| 247 | help | 265 | help |
| 248 | If you say yes here you get support for the National Semiconductor | 266 | If you say yes here you get support for the National Semiconductor |
| 249 | LM63 remote diode digital temperature sensor with integrated fan | 267 | LM63 remote diode digital temperature sensor with integrated fan |
| @@ -255,7 +273,7 @@ config SENSORS_LM63 | |||
| 255 | 273 | ||
| 256 | config SENSORS_LM70 | 274 | config SENSORS_LM70 |
| 257 | tristate "National Semiconductor LM70" | 275 | tristate "National Semiconductor LM70" |
| 258 | depends on HWMON && SPI_MASTER && EXPERIMENTAL | 276 | depends on SPI_MASTER && EXPERIMENTAL |
| 259 | help | 277 | help |
| 260 | If you say yes here you get support for the National Semiconductor | 278 | If you say yes here you get support for the National Semiconductor |
| 261 | LM70 digital temperature sensor chip. | 279 | LM70 digital temperature sensor chip. |
| @@ -265,7 +283,7 @@ config SENSORS_LM70 | |||
| 265 | 283 | ||
| 266 | config SENSORS_LM75 | 284 | config SENSORS_LM75 |
| 267 | tristate "National Semiconductor LM75 and compatibles" | 285 | tristate "National Semiconductor LM75 and compatibles" |
| 268 | depends on HWMON && I2C | 286 | depends on I2C |
| 269 | help | 287 | help |
| 270 | If you say yes here you get support for National Semiconductor LM75 | 288 | If you say yes here you get support for National Semiconductor LM75 |
| 271 | sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in | 289 | sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in |
| @@ -280,7 +298,7 @@ config SENSORS_LM75 | |||
| 280 | 298 | ||
| 281 | config SENSORS_LM77 | 299 | config SENSORS_LM77 |
| 282 | tristate "National Semiconductor LM77" | 300 | tristate "National Semiconductor LM77" |
| 283 | depends on HWMON && I2C | 301 | depends on I2C |
| 284 | help | 302 | help |
| 285 | If you say yes here you get support for National Semiconductor LM77 | 303 | If you say yes here you get support for National Semiconductor LM77 |
| 286 | sensor chips. | 304 | sensor chips. |
| @@ -290,8 +308,7 @@ config SENSORS_LM77 | |||
| 290 | 308 | ||
| 291 | config SENSORS_LM78 | 309 | config SENSORS_LM78 |
| 292 | tristate "National Semiconductor LM78 and compatibles" | 310 | tristate "National Semiconductor LM78 and compatibles" |
| 293 | depends on HWMON && I2C | 311 | depends on I2C |
| 294 | select I2C_ISA | ||
| 295 | select HWMON_VID | 312 | select HWMON_VID |
| 296 | help | 313 | help |
| 297 | If you say yes here you get support for National Semiconductor LM78, | 314 | If you say yes here you get support for National Semiconductor LM78, |
| @@ -302,7 +319,7 @@ config SENSORS_LM78 | |||
| 302 | 319 | ||
| 303 | config SENSORS_LM80 | 320 | config SENSORS_LM80 |
| 304 | tristate "National Semiconductor LM80" | 321 | tristate "National Semiconductor LM80" |
| 305 | depends on HWMON && I2C && EXPERIMENTAL | 322 | depends on I2C && EXPERIMENTAL |
| 306 | help | 323 | help |
| 307 | If you say yes here you get support for National Semiconductor | 324 | If you say yes here you get support for National Semiconductor |
| 308 | LM80 sensor chips. | 325 | LM80 sensor chips. |
| @@ -312,7 +329,7 @@ config SENSORS_LM80 | |||
| 312 | 329 | ||
| 313 | config SENSORS_LM83 | 330 | config SENSORS_LM83 |
| 314 | tristate "National Semiconductor LM83 and compatibles" | 331 | tristate "National Semiconductor LM83 and compatibles" |
| 315 | depends on HWMON && I2C | 332 | depends on I2C |
| 316 | help | 333 | help |
| 317 | If you say yes here you get support for National Semiconductor | 334 | If you say yes here you get support for National Semiconductor |
| 318 | LM82 and LM83 sensor chips. | 335 | LM82 and LM83 sensor chips. |
| @@ -322,7 +339,7 @@ config SENSORS_LM83 | |||
| 322 | 339 | ||
| 323 | config SENSORS_LM85 | 340 | config SENSORS_LM85 |
| 324 | tristate "National Semiconductor LM85 and compatibles" | 341 | tristate "National Semiconductor LM85 and compatibles" |
| 325 | depends on HWMON && I2C && EXPERIMENTAL | 342 | depends on I2C && EXPERIMENTAL |
| 326 | select HWMON_VID | 343 | select HWMON_VID |
| 327 | help | 344 | help |
| 328 | If you say yes here you get support for National Semiconductor LM85 | 345 | If you say yes here you get support for National Semiconductor LM85 |
| @@ -333,7 +350,7 @@ config SENSORS_LM85 | |||
| 333 | 350 | ||
| 334 | config SENSORS_LM87 | 351 | config SENSORS_LM87 |
| 335 | tristate "National Semiconductor LM87" | 352 | tristate "National Semiconductor LM87" |
| 336 | depends on HWMON && I2C | 353 | depends on I2C |
| 337 | select HWMON_VID | 354 | select HWMON_VID |
| 338 | help | 355 | help |
| 339 | If you say yes here you get support for National Semiconductor LM87 | 356 | If you say yes here you get support for National Semiconductor LM87 |
| @@ -344,7 +361,7 @@ config SENSORS_LM87 | |||
| 344 | 361 | ||
| 345 | config SENSORS_LM90 | 362 | config SENSORS_LM90 |
| 346 | tristate "National Semiconductor LM90 and compatibles" | 363 | tristate "National Semiconductor LM90 and compatibles" |
| 347 | depends on HWMON && I2C | 364 | depends on I2C |
| 348 | help | 365 | help |
| 349 | If you say yes here you get support for National Semiconductor LM90, | 366 | If you say yes here you get support for National Semiconductor LM90, |
| 350 | LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and | 367 | LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and |
| @@ -358,7 +375,7 @@ config SENSORS_LM90 | |||
| 358 | 375 | ||
| 359 | config SENSORS_LM92 | 376 | config SENSORS_LM92 |
| 360 | tristate "National Semiconductor LM92 and compatibles" | 377 | tristate "National Semiconductor LM92 and compatibles" |
| 361 | depends on HWMON && I2C | 378 | depends on I2C |
| 362 | help | 379 | help |
| 363 | If you say yes here you get support for National Semiconductor LM92 | 380 | If you say yes here you get support for National Semiconductor LM92 |
| 364 | and Maxim MAX6635 sensor chips. | 381 | and Maxim MAX6635 sensor chips. |
| @@ -368,16 +385,26 @@ config SENSORS_LM92 | |||
| 368 | 385 | ||
| 369 | config SENSORS_MAX1619 | 386 | config SENSORS_MAX1619 |
| 370 | tristate "Maxim MAX1619 sensor chip" | 387 | tristate "Maxim MAX1619 sensor chip" |
| 371 | depends on HWMON && I2C | 388 | depends on I2C |
| 372 | help | 389 | help |
| 373 | If you say yes here you get support for MAX1619 sensor chip. | 390 | If you say yes here you get support for MAX1619 sensor chip. |
| 374 | 391 | ||
| 375 | This driver can also be built as a module. If so, the module | 392 | This driver can also be built as a module. If so, the module |
| 376 | will be called max1619. | 393 | will be called max1619. |
| 377 | 394 | ||
| 395 | config SENSORS_MAX6650 | ||
| 396 | tristate "Maxim MAX6650 sensor chip" | ||
| 397 | depends on I2C && EXPERIMENTAL | ||
| 398 | help | ||
| 399 | If you say yes here you get support for the MAX6650 / MAX6651 | ||
| 400 | sensor chips. | ||
| 401 | |||
| 402 | This driver can also be built as a module. If so, the module | ||
| 403 | will be called max6650. | ||
| 404 | |||
| 378 | config SENSORS_PC87360 | 405 | config SENSORS_PC87360 |
| 379 | tristate "National Semiconductor PC87360 family" | 406 | tristate "National Semiconductor PC87360 family" |
| 380 | depends on HWMON && I2C && EXPERIMENTAL | 407 | depends on I2C && EXPERIMENTAL |
| 381 | select I2C_ISA | 408 | select I2C_ISA |
| 382 | select HWMON_VID | 409 | select HWMON_VID |
| 383 | help | 410 | help |
| @@ -392,7 +419,7 @@ config SENSORS_PC87360 | |||
| 392 | 419 | ||
| 393 | config SENSORS_PC87427 | 420 | config SENSORS_PC87427 |
| 394 | tristate "National Semiconductor PC87427" | 421 | tristate "National Semiconductor PC87427" |
| 395 | depends on HWMON && EXPERIMENTAL | 422 | depends on EXPERIMENTAL |
| 396 | help | 423 | help |
| 397 | If you say yes here you get access to the hardware monitoring | 424 | If you say yes here you get access to the hardware monitoring |
| 398 | functions of the National Semiconductor PC87427 Super-I/O chip. | 425 | functions of the National Semiconductor PC87427 Super-I/O chip. |
| @@ -405,7 +432,7 @@ config SENSORS_PC87427 | |||
| 405 | 432 | ||
| 406 | config SENSORS_SIS5595 | 433 | config SENSORS_SIS5595 |
| 407 | tristate "Silicon Integrated Systems Corp. SiS5595" | 434 | tristate "Silicon Integrated Systems Corp. SiS5595" |
| 408 | depends on HWMON && I2C && PCI && EXPERIMENTAL | 435 | depends on I2C && PCI && EXPERIMENTAL |
| 409 | select I2C_ISA | 436 | select I2C_ISA |
| 410 | help | 437 | help |
| 411 | If you say yes here you get support for the integrated sensors in | 438 | If you say yes here you get support for the integrated sensors in |
| @@ -416,28 +443,28 @@ config SENSORS_SIS5595 | |||
| 416 | 443 | ||
| 417 | config SENSORS_SMSC47M1 | 444 | config SENSORS_SMSC47M1 |
| 418 | tristate "SMSC LPC47M10x and compatibles" | 445 | tristate "SMSC LPC47M10x and compatibles" |
| 419 | depends on HWMON && I2C | ||
| 420 | select I2C_ISA | ||
| 421 | help | 446 | help |
| 422 | If you say yes here you get support for the integrated fan | 447 | If you say yes here you get support for the integrated fan |
| 423 | monitoring and control capabilities of the SMSC LPC47B27x, | 448 | monitoring and control capabilities of the SMSC LPC47B27x, |
| 424 | LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x, | 449 | LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x, |
| 425 | LPC47M192 and LPC47M997 chips. | 450 | LPC47M192, LPC47M292 and LPC47M997 chips. |
| 426 | 451 | ||
| 427 | The temperature and voltage sensor features of the LPC47M192 | 452 | The temperature and voltage sensor features of the LPC47M15x, |
| 428 | and LPC47M997 are supported by another driver, select also | 453 | LPC47M192, LPC47M292 and LPC47M997 are supported by another |
| 429 | "SMSC LPC47M192 and compatibles" below for those. | 454 | driver, select also "SMSC LPC47M192 and compatibles" below for |
| 455 | those. | ||
| 430 | 456 | ||
| 431 | This driver can also be built as a module. If so, the module | 457 | This driver can also be built as a module. If so, the module |
| 432 | will be called smsc47m1. | 458 | will be called smsc47m1. |
| 433 | 459 | ||
| 434 | config SENSORS_SMSC47M192 | 460 | config SENSORS_SMSC47M192 |
| 435 | tristate "SMSC LPC47M192 and compatibles" | 461 | tristate "SMSC LPC47M192 and compatibles" |
| 436 | depends on HWMON && I2C && EXPERIMENTAL | 462 | depends on I2C && EXPERIMENTAL |
| 437 | select HWMON_VID | 463 | select HWMON_VID |
| 438 | help | 464 | help |
| 439 | If you say yes here you get support for the temperature and | 465 | If you say yes here you get support for the temperature and |
| 440 | voltage sensors of the SMSC LPC47M192 and LPC47M997 chips. | 466 | voltage sensors of the SMSC LPC47M192, LPC47M15x, LPC47M292 |
| 467 | and LPC47M997 chips. | ||
| 441 | 468 | ||
| 442 | The fan monitoring and control capabilities of these chips | 469 | The fan monitoring and control capabilities of these chips |
| 443 | are supported by another driver, select | 470 | are supported by another driver, select |
| @@ -449,8 +476,7 @@ config SENSORS_SMSC47M192 | |||
| 449 | 476 | ||
| 450 | config SENSORS_SMSC47B397 | 477 | config SENSORS_SMSC47B397 |
| 451 | tristate "SMSC LPC47B397-NC" | 478 | tristate "SMSC LPC47B397-NC" |
| 452 | depends on HWMON && I2C && EXPERIMENTAL | 479 | depends on EXPERIMENTAL |
| 453 | select I2C_ISA | ||
| 454 | help | 480 | help |
| 455 | If you say yes here you get support for the SMSC LPC47B397-NC | 481 | If you say yes here you get support for the SMSC LPC47B397-NC |
| 456 | sensor chip. | 482 | sensor chip. |
| @@ -460,7 +486,7 @@ config SENSORS_SMSC47B397 | |||
| 460 | 486 | ||
| 461 | config SENSORS_VIA686A | 487 | config SENSORS_VIA686A |
| 462 | tristate "VIA686A" | 488 | tristate "VIA686A" |
| 463 | depends on HWMON && I2C && PCI | 489 | depends on I2C && PCI |
| 464 | select I2C_ISA | 490 | select I2C_ISA |
| 465 | help | 491 | help |
| 466 | If you say yes here you get support for the integrated sensors in | 492 | If you say yes here you get support for the integrated sensors in |
| @@ -471,7 +497,7 @@ config SENSORS_VIA686A | |||
| 471 | 497 | ||
| 472 | config SENSORS_VT1211 | 498 | config SENSORS_VT1211 |
| 473 | tristate "VIA VT1211" | 499 | tristate "VIA VT1211" |
| 474 | depends on HWMON && EXPERIMENTAL | 500 | depends on EXPERIMENTAL |
| 475 | select HWMON_VID | 501 | select HWMON_VID |
| 476 | help | 502 | help |
| 477 | If you say yes here then you get support for hardware monitoring | 503 | If you say yes here then you get support for hardware monitoring |
| @@ -482,7 +508,7 @@ config SENSORS_VT1211 | |||
| 482 | 508 | ||
| 483 | config SENSORS_VT8231 | 509 | config SENSORS_VT8231 |
| 484 | tristate "VIA VT8231" | 510 | tristate "VIA VT8231" |
| 485 | depends on HWMON && I2C && PCI && EXPERIMENTAL | 511 | depends on I2C && PCI && EXPERIMENTAL |
| 486 | select HWMON_VID | 512 | select HWMON_VID |
| 487 | select I2C_ISA | 513 | select I2C_ISA |
| 488 | help | 514 | help |
| @@ -494,8 +520,7 @@ config SENSORS_VT8231 | |||
| 494 | 520 | ||
| 495 | config SENSORS_W83781D | 521 | config SENSORS_W83781D |
| 496 | tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F" | 522 | tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F" |
| 497 | depends on HWMON && I2C | 523 | depends on I2C |
| 498 | select I2C_ISA | ||
| 499 | select HWMON_VID | 524 | select HWMON_VID |
| 500 | help | 525 | help |
| 501 | If you say yes here you get support for the Winbond W8378x series | 526 | If you say yes here you get support for the Winbond W8378x series |
| @@ -507,7 +532,7 @@ config SENSORS_W83781D | |||
| 507 | 532 | ||
| 508 | config SENSORS_W83791D | 533 | config SENSORS_W83791D |
| 509 | tristate "Winbond W83791D" | 534 | tristate "Winbond W83791D" |
| 510 | depends on HWMON && I2C && EXPERIMENTAL | 535 | depends on I2C && EXPERIMENTAL |
| 511 | select HWMON_VID | 536 | select HWMON_VID |
| 512 | help | 537 | help |
| 513 | If you say yes here you get support for the Winbond W83791D chip. | 538 | If you say yes here you get support for the Winbond W83791D chip. |
| @@ -517,7 +542,7 @@ config SENSORS_W83791D | |||
| 517 | 542 | ||
| 518 | config SENSORS_W83792D | 543 | config SENSORS_W83792D |
| 519 | tristate "Winbond W83792D" | 544 | tristate "Winbond W83792D" |
| 520 | depends on HWMON && I2C && EXPERIMENTAL | 545 | depends on I2C && EXPERIMENTAL |
| 521 | help | 546 | help |
| 522 | If you say yes here you get support for the Winbond W83792D chip. | 547 | If you say yes here you get support for the Winbond W83792D chip. |
| 523 | 548 | ||
| @@ -526,7 +551,7 @@ config SENSORS_W83792D | |||
| 526 | 551 | ||
| 527 | config SENSORS_W83793 | 552 | config SENSORS_W83793 |
| 528 | tristate "Winbond W83793" | 553 | tristate "Winbond W83793" |
| 529 | depends on HWMON && I2C && EXPERIMENTAL | 554 | depends on I2C && EXPERIMENTAL |
| 530 | select HWMON_VID | 555 | select HWMON_VID |
| 531 | help | 556 | help |
| 532 | If you say yes here you get support for the Winbond W83793 | 557 | If you say yes here you get support for the Winbond W83793 |
| @@ -537,7 +562,7 @@ config SENSORS_W83793 | |||
| 537 | 562 | ||
| 538 | config SENSORS_W83L785TS | 563 | config SENSORS_W83L785TS |
| 539 | tristate "Winbond W83L785TS-S" | 564 | tristate "Winbond W83L785TS-S" |
| 540 | depends on HWMON && I2C && EXPERIMENTAL | 565 | depends on I2C && EXPERIMENTAL |
| 541 | help | 566 | help |
| 542 | If you say yes here you get support for the Winbond W83L785TS-S | 567 | If you say yes here you get support for the Winbond W83L785TS-S |
| 543 | sensor chip, which is used on the Asus A7N8X, among other | 568 | sensor chip, which is used on the Asus A7N8X, among other |
| @@ -548,8 +573,6 @@ config SENSORS_W83L785TS | |||
| 548 | 573 | ||
| 549 | config SENSORS_W83627HF | 574 | config SENSORS_W83627HF |
| 550 | tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" | 575 | tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" |
| 551 | depends on HWMON && I2C | ||
| 552 | select I2C_ISA | ||
| 553 | select HWMON_VID | 576 | select HWMON_VID |
| 554 | help | 577 | help |
| 555 | If you say yes here you get support for the Winbond W836X7 series | 578 | If you say yes here you get support for the Winbond W836X7 series |
| @@ -561,7 +584,7 @@ config SENSORS_W83627HF | |||
| 561 | 584 | ||
| 562 | config SENSORS_W83627EHF | 585 | config SENSORS_W83627EHF |
| 563 | tristate "Winbond W83627EHF" | 586 | tristate "Winbond W83627EHF" |
| 564 | depends on HWMON && I2C && EXPERIMENTAL | 587 | depends on I2C && EXPERIMENTAL |
| 565 | select I2C_ISA | 588 | select I2C_ISA |
| 566 | help | 589 | help |
| 567 | If you say yes here you get preliminary support for the hardware | 590 | If you say yes here you get preliminary support for the hardware |
| @@ -577,7 +600,7 @@ config SENSORS_W83627EHF | |||
| 577 | 600 | ||
| 578 | config SENSORS_HDAPS | 601 | config SENSORS_HDAPS |
| 579 | tristate "IBM Hard Drive Active Protection System (hdaps)" | 602 | tristate "IBM Hard Drive Active Protection System (hdaps)" |
| 580 | depends on HWMON && INPUT && X86 | 603 | depends on INPUT && X86 |
| 581 | default n | 604 | default n |
| 582 | help | 605 | help |
| 583 | This driver provides support for the IBM Hard Drive Active Protection | 606 | This driver provides support for the IBM Hard Drive Active Protection |
| @@ -620,7 +643,6 @@ config SENSORS_APPLESMC | |||
| 620 | 643 | ||
| 621 | config HWMON_DEBUG_CHIP | 644 | config HWMON_DEBUG_CHIP |
| 622 | bool "Hardware Monitoring Chip debugging messages" | 645 | bool "Hardware Monitoring Chip debugging messages" |
| 623 | depends on HWMON | ||
| 624 | default n | 646 | default n |
| 625 | help | 647 | help |
| 626 | Say Y here if you want the I2C chip drivers to produce a bunch of | 648 | Say Y here if you want the I2C chip drivers to produce a bunch of |
| @@ -628,4 +650,4 @@ config HWMON_DEBUG_CHIP | |||
| 628 | a problem with I2C support and want to see more of what is going | 650 | a problem with I2C support and want to see more of what is going |
| 629 | on. | 651 | on. |
| 630 | 652 | ||
| 631 | endmenu | 653 | endif # HWMON |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 544f8d8dff4e..cfaf338919dd 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
| @@ -14,6 +14,7 @@ obj-$(CONFIG_SENSORS_W83781D) += w83781d.o | |||
| 14 | obj-$(CONFIG_SENSORS_W83791D) += w83791d.o | 14 | obj-$(CONFIG_SENSORS_W83791D) += w83791d.o |
| 15 | 15 | ||
| 16 | obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o | 16 | obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o |
| 17 | obj-$(CONFIG_SENSORS_AD7418) += ad7418.o | ||
| 17 | obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o | 18 | obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o |
| 18 | obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o | 19 | obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o |
| 19 | obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o | 20 | obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o |
| @@ -23,6 +24,7 @@ obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o | |||
| 23 | obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o | 24 | obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o |
| 24 | obj-$(CONFIG_SENSORS_AMS) += ams/ | 25 | obj-$(CONFIG_SENSORS_AMS) += ams/ |
| 25 | obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o | 26 | obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o |
| 27 | obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o | ||
| 26 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o | 28 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o |
| 27 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o | 29 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o |
| 28 | obj-$(CONFIG_SENSORS_FSCHER) += fscher.o | 30 | obj-$(CONFIG_SENSORS_FSCHER) += fscher.o |
| @@ -44,6 +46,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o | |||
| 44 | obj-$(CONFIG_SENSORS_LM90) += lm90.o | 46 | obj-$(CONFIG_SENSORS_LM90) += lm90.o |
| 45 | obj-$(CONFIG_SENSORS_LM92) += lm92.o | 47 | obj-$(CONFIG_SENSORS_LM92) += lm92.o |
| 46 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o | 48 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o |
| 49 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o | ||
| 47 | obj-$(CONFIG_SENSORS_PC87360) += pc87360.o | 50 | obj-$(CONFIG_SENSORS_PC87360) += pc87360.o |
| 48 | obj-$(CONFIG_SENSORS_PC87427) += pc87427.o | 51 | obj-$(CONFIG_SENSORS_PC87427) += pc87427.o |
| 49 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o | 52 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o |
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c new file mode 100644 index 000000000000..cc8b624a1e51 --- /dev/null +++ b/drivers/hwmon/ad7418.c | |||
| @@ -0,0 +1,373 @@ | |||
| 1 | /* | ||
| 2 | * An hwmon driver for the Analog Devices AD7416/17/18 | ||
| 3 | * Copyright (C) 2006-07 Tower Technologies | ||
| 4 | * | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * Based on lm75.c | ||
| 8 | * Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License, | ||
| 12 | * as published by the Free Software Foundation - version 2. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/jiffies.h> | ||
| 17 | #include <linux/i2c.h> | ||
| 18 | #include <linux/hwmon.h> | ||
| 19 | #include <linux/hwmon-sysfs.h> | ||
| 20 | #include <linux/err.h> | ||
| 21 | #include <linux/mutex.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | |||
| 24 | #include "lm75.h" | ||
| 25 | |||
| 26 | #define DRV_VERSION "0.3" | ||
| 27 | |||
| 28 | /* Addresses to scan */ | ||
| 29 | static unsigned short normal_i2c[] = { 0x28, I2C_CLIENT_END }; | ||
| 30 | /* Insmod parameters */ | ||
| 31 | I2C_CLIENT_INSMOD_3(ad7416, ad7417, ad7418); | ||
| 32 | |||
| 33 | /* AD7418 registers */ | ||
| 34 | #define AD7418_REG_TEMP_IN 0x00 | ||
| 35 | #define AD7418_REG_CONF 0x01 | ||
| 36 | #define AD7418_REG_TEMP_HYST 0x02 | ||
| 37 | #define AD7418_REG_TEMP_OS 0x03 | ||
| 38 | #define AD7418_REG_ADC 0x04 | ||
| 39 | #define AD7418_REG_CONF2 0x05 | ||
| 40 | |||
| 41 | #define AD7418_REG_ADC_CH(x) ((x) << 5) | ||
| 42 | #define AD7418_CH_TEMP AD7418_REG_ADC_CH(0) | ||
| 43 | |||
| 44 | static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN, | ||
| 45 | AD7418_REG_TEMP_HYST, | ||
| 46 | AD7418_REG_TEMP_OS }; | ||
| 47 | |||
| 48 | struct ad7418_data { | ||
| 49 | struct i2c_client client; | ||
| 50 | struct class_device *class_dev; | ||
| 51 | struct attribute_group attrs; | ||
| 52 | enum chips type; | ||
| 53 | struct mutex lock; | ||
| 54 | int adc_max; /* number of ADC channels */ | ||
| 55 | char valid; | ||
| 56 | unsigned long last_updated; /* In jiffies */ | ||
| 57 | s16 temp[3]; /* Register values */ | ||
| 58 | u16 in[4]; | ||
| 59 | }; | ||
| 60 | |||
| 61 | static int ad7418_attach_adapter(struct i2c_adapter *adapter); | ||
| 62 | static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind); | ||
| 63 | static int ad7418_detach_client(struct i2c_client *client); | ||
| 64 | |||
| 65 | static struct i2c_driver ad7418_driver = { | ||
| 66 | .driver = { | ||
| 67 | .name = "ad7418", | ||
| 68 | }, | ||
| 69 | .attach_adapter = ad7418_attach_adapter, | ||
| 70 | .detach_client = ad7418_detach_client, | ||
| 71 | }; | ||
| 72 | |||
| 73 | /* All registers are word-sized, except for the configuration registers. | ||
| 74 | * AD7418 uses a high-byte first convention. Do NOT use those functions to | ||
| 75 | * access the configuration registers CONF and CONF2, as they are byte-sized. | ||
| 76 | */ | ||
| 77 | static inline int ad7418_read(struct i2c_client *client, u8 reg) | ||
| 78 | { | ||
| 79 | return swab16(i2c_smbus_read_word_data(client, reg)); | ||
| 80 | } | ||
| 81 | |||
| 82 | static inline int ad7418_write(struct i2c_client *client, u8 reg, u16 value) | ||
| 83 | { | ||
| 84 | return i2c_smbus_write_word_data(client, reg, swab16(value)); | ||
| 85 | } | ||
| 86 | |||
| 87 | static void ad7418_init_client(struct i2c_client *client) | ||
| 88 | { | ||
| 89 | struct ad7418_data *data = i2c_get_clientdata(client); | ||
| 90 | |||
| 91 | int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); | ||
| 92 | if (reg < 0) { | ||
| 93 | dev_err(&client->dev, "cannot read configuration register\n"); | ||
| 94 | } else { | ||
| 95 | dev_info(&client->dev, "configuring for mode 1\n"); | ||
| 96 | i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe); | ||
| 97 | |||
| 98 | if (data->type == ad7417 || data->type == ad7418) | ||
| 99 | i2c_smbus_write_byte_data(client, | ||
| 100 | AD7418_REG_CONF2, 0x00); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | static struct ad7418_data *ad7418_update_device(struct device *dev) | ||
| 105 | { | ||
| 106 | struct i2c_client *client = to_i2c_client(dev); | ||
| 107 | struct ad7418_data *data = i2c_get_clientdata(client); | ||
| 108 | |||
| 109 | mutex_lock(&data->lock); | ||
| 110 | |||
| 111 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | ||
| 112 | || !data->valid) { | ||
| 113 | u8 cfg; | ||
| 114 | int i, ch; | ||
| 115 | |||
| 116 | /* read config register and clear channel bits */ | ||
| 117 | cfg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); | ||
| 118 | cfg &= 0x1F; | ||
| 119 | |||
| 120 | i2c_smbus_write_byte_data(client, AD7418_REG_CONF, | ||
| 121 | cfg | AD7418_CH_TEMP); | ||
| 122 | udelay(30); | ||
| 123 | |||
| 124 | for (i = 0; i < 3; i++) { | ||
| 125 | data->temp[i] = ad7418_read(client, AD7418_REG_TEMP[i]); | ||
| 126 | } | ||
| 127 | |||
| 128 | for (i = 0, ch = 4; i < data->adc_max; i++, ch--) { | ||
| 129 | i2c_smbus_write_byte_data(client, | ||
| 130 | AD7418_REG_CONF, | ||
| 131 | cfg | AD7418_REG_ADC_CH(ch)); | ||
| 132 | |||
| 133 | udelay(15); | ||
| 134 | data->in[data->adc_max - 1 - i] = | ||
| 135 | ad7418_read(client, AD7418_REG_ADC); | ||
| 136 | } | ||
| 137 | |||
| 138 | /* restore old configuration value */ | ||
| 139 | ad7418_write(client, AD7418_REG_CONF, cfg); | ||
| 140 | |||
| 141 | data->last_updated = jiffies; | ||
| 142 | data->valid = 1; | ||
| 143 | } | ||
| 144 | |||
| 145 | mutex_unlock(&data->lock); | ||
| 146 | |||
| 147 | return data; | ||
| 148 | } | ||
| 149 | |||
| 150 | static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, | ||
| 151 | char *buf) | ||
| 152 | { | ||
| 153 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 154 | struct ad7418_data *data = ad7418_update_device(dev); | ||
| 155 | return sprintf(buf, "%d\n", | ||
| 156 | LM75_TEMP_FROM_REG(data->temp[attr->index])); | ||
| 157 | } | ||
| 158 | |||
| 159 | static ssize_t show_adc(struct device *dev, struct device_attribute *devattr, | ||
| 160 | char *buf) | ||
| 161 | { | ||
| 162 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 163 | struct ad7418_data *data = ad7418_update_device(dev); | ||
| 164 | |||
| 165 | return sprintf(buf, "%d\n", | ||
| 166 | ((data->in[attr->index] >> 6) * 2500 + 512) / 1024); | ||
| 167 | } | ||
| 168 | |||
| 169 | static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, | ||
| 170 | const char *buf, size_t count) | ||
| 171 | { | ||
| 172 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 173 | struct i2c_client *client = to_i2c_client(dev); | ||
| 174 | struct ad7418_data *data = i2c_get_clientdata(client); | ||
| 175 | int temp = simple_strtol(buf, NULL, 10); | ||
| 176 | |||
| 177 | mutex_lock(&data->lock); | ||
| 178 | data->temp[attr->index] = LM75_TEMP_TO_REG(temp); | ||
| 179 | ad7418_write(client, AD7418_REG_TEMP[attr->index], data->temp[attr->index]); | ||
| 180 | mutex_unlock(&data->lock); | ||
| 181 | return count; | ||
| 182 | } | ||
| 183 | |||
| 184 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
| 185 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, | ||
| 186 | show_temp, set_temp, 1); | ||
| 187 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, | ||
| 188 | show_temp, set_temp, 2); | ||
| 189 | |||
| 190 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_adc, NULL, 0); | ||
| 191 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 1); | ||
| 192 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2); | ||
| 193 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3); | ||
| 194 | |||
| 195 | static int ad7418_attach_adapter(struct i2c_adapter *adapter) | ||
| 196 | { | ||
| 197 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
| 198 | return 0; | ||
| 199 | return i2c_probe(adapter, &addr_data, ad7418_detect); | ||
| 200 | } | ||
| 201 | |||
| 202 | static struct attribute *ad7416_attributes[] = { | ||
| 203 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
| 204 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
| 205 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
| 206 | NULL | ||
| 207 | }; | ||
| 208 | |||
| 209 | static struct attribute *ad7417_attributes[] = { | ||
| 210 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
| 211 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
| 212 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
| 213 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
| 214 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
| 215 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
| 216 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
| 217 | NULL | ||
| 218 | }; | ||
| 219 | |||
| 220 | static struct attribute *ad7418_attributes[] = { | ||
| 221 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
| 222 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
| 223 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
| 224 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
| 225 | NULL | ||
| 226 | }; | ||
| 227 | |||
| 228 | static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind) | ||
| 229 | { | ||
| 230 | struct i2c_client *client; | ||
| 231 | struct ad7418_data *data; | ||
| 232 | int err = 0; | ||
| 233 | |||
| 234 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | | ||
| 235 | I2C_FUNC_SMBUS_WORD_DATA)) | ||
| 236 | goto exit; | ||
| 237 | |||
| 238 | if (!(data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL))) { | ||
| 239 | err = -ENOMEM; | ||
| 240 | goto exit; | ||
| 241 | } | ||
| 242 | |||
| 243 | client = &data->client; | ||
| 244 | client->addr = address; | ||
| 245 | client->adapter = adapter; | ||
| 246 | client->driver = &ad7418_driver; | ||
| 247 | |||
| 248 | i2c_set_clientdata(client, data); | ||
| 249 | |||
| 250 | mutex_init(&data->lock); | ||
| 251 | |||
| 252 | /* AD7418 has a curious behaviour on registers 6 and 7. They | ||
| 253 | * both always read 0xC071 and are not documented on the datasheet. | ||
| 254 | * We use them to detect the chip. | ||
| 255 | */ | ||
| 256 | if (kind <= 0) { | ||
| 257 | int reg, reg6, reg7; | ||
| 258 | |||
| 259 | /* the AD7416 lies within this address range, but I have | ||
| 260 | * no means to check. | ||
| 261 | */ | ||
| 262 | if (address >= 0x48 && address <= 0x4f) { | ||
| 263 | /* XXX add tests for AD7416 here */ | ||
| 264 | /* data->type = ad7416; */ | ||
| 265 | } | ||
| 266 | /* here we might have AD7417 or AD7418 */ | ||
| 267 | else if (address >= 0x28 && address <= 0x2f) { | ||
| 268 | reg6 = i2c_smbus_read_word_data(client, 0x06); | ||
| 269 | reg7 = i2c_smbus_read_word_data(client, 0x07); | ||
| 270 | |||
| 271 | if (address == 0x28 && reg6 == 0xC071 && reg7 == 0xC071) | ||
| 272 | data->type = ad7418; | ||
| 273 | |||
| 274 | /* XXX add tests for AD7417 here */ | ||
| 275 | |||
| 276 | |||
| 277 | /* both AD7417 and AD7418 have bits 0-5 of | ||
| 278 | * the CONF2 register at 0 | ||
| 279 | */ | ||
| 280 | reg = i2c_smbus_read_byte_data(client, | ||
| 281 | AD7418_REG_CONF2); | ||
| 282 | if (reg & 0x3F) | ||
| 283 | data->type = any_chip; /* detection failed */ | ||
| 284 | } | ||
| 285 | } else { | ||
| 286 | dev_dbg(&adapter->dev, "detection forced\n"); | ||
| 287 | } | ||
| 288 | |||
| 289 | if (kind > 0) | ||
| 290 | data->type = kind; | ||
| 291 | else if (kind < 0 && data->type == any_chip) { | ||
| 292 | err = -ENODEV; | ||
| 293 | goto exit_free; | ||
| 294 | } | ||
| 295 | |||
| 296 | switch (data->type) { | ||
| 297 | case any_chip: | ||
| 298 | case ad7416: | ||
| 299 | data->adc_max = 0; | ||
| 300 | data->attrs.attrs = ad7416_attributes; | ||
| 301 | strlcpy(client->name, "ad7416", I2C_NAME_SIZE); | ||
| 302 | break; | ||
| 303 | |||
| 304 | case ad7417: | ||
| 305 | data->adc_max = 4; | ||
| 306 | data->attrs.attrs = ad7417_attributes; | ||
| 307 | strlcpy(client->name, "ad7417", I2C_NAME_SIZE); | ||
| 308 | break; | ||
| 309 | |||
| 310 | case ad7418: | ||
| 311 | data->adc_max = 1; | ||
| 312 | data->attrs.attrs = ad7418_attributes; | ||
| 313 | strlcpy(client->name, "ad7418", I2C_NAME_SIZE); | ||
| 314 | break; | ||
| 315 | } | ||
| 316 | |||
| 317 | if ((err = i2c_attach_client(client))) | ||
| 318 | goto exit_free; | ||
| 319 | |||
| 320 | dev_info(&client->dev, "%s chip found\n", client->name); | ||
| 321 | |||
| 322 | /* Initialize the AD7418 chip */ | ||
| 323 | ad7418_init_client(client); | ||
| 324 | |||
| 325 | /* Register sysfs hooks */ | ||
| 326 | if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) | ||
| 327 | goto exit_detach; | ||
| 328 | |||
| 329 | data->class_dev = hwmon_device_register(&client->dev); | ||
| 330 | if (IS_ERR(data->class_dev)) { | ||
| 331 | err = PTR_ERR(data->class_dev); | ||
| 332 | goto exit_remove; | ||
| 333 | } | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | |||
| 337 | exit_remove: | ||
| 338 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
| 339 | exit_detach: | ||
| 340 | i2c_detach_client(client); | ||
| 341 | exit_free: | ||
| 342 | kfree(data); | ||
| 343 | exit: | ||
| 344 | return err; | ||
| 345 | } | ||
| 346 | |||
| 347 | static int ad7418_detach_client(struct i2c_client *client) | ||
| 348 | { | ||
| 349 | struct ad7418_data *data = i2c_get_clientdata(client); | ||
| 350 | hwmon_device_unregister(data->class_dev); | ||
| 351 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
| 352 | i2c_detach_client(client); | ||
| 353 | kfree(data); | ||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | static int __init ad7418_init(void) | ||
| 358 | { | ||
| 359 | return i2c_add_driver(&ad7418_driver); | ||
| 360 | } | ||
| 361 | |||
| 362 | static void __exit ad7418_exit(void) | ||
| 363 | { | ||
| 364 | i2c_del_driver(&ad7418_driver); | ||
| 365 | } | ||
| 366 | |||
| 367 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 368 | MODULE_DESCRIPTION("AD7416/17/18 driver"); | ||
| 369 | MODULE_LICENSE("GPL"); | ||
| 370 | MODULE_VERSION(DRV_VERSION); | ||
| 371 | |||
| 372 | module_init(ad7418_init); | ||
| 373 | module_exit(ad7418_exit); | ||
diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c index dbe6a32c064e..6db973739725 100644 --- a/drivers/hwmon/ams/ams-core.c +++ b/drivers/hwmon/ams/ams-core.c | |||
| @@ -219,9 +219,6 @@ int __init ams_init(void) | |||
| 219 | /* Found PMU motion sensor */ | 219 | /* Found PMU motion sensor */ |
| 220 | return ams_pmu_init(np); | 220 | return ams_pmu_init(np); |
| 221 | #endif | 221 | #endif |
| 222 | |||
| 223 | printk(KERN_ERR "ams: No motion sensor found.\n"); | ||
| 224 | |||
| 225 | return -ENODEV; | 222 | return -ENODEV; |
| 226 | } | 223 | } |
| 227 | 224 | ||
diff --git a/drivers/hwmon/ams/ams-i2c.c b/drivers/hwmon/ams/ams-i2c.c index ccd5cefae90e..957760536a4c 100644 --- a/drivers/hwmon/ams/ams-i2c.c +++ b/drivers/hwmon/ams/ams-i2c.c | |||
| @@ -85,17 +85,17 @@ static int ams_i2c_write(u8 reg, u8 value) | |||
| 85 | static int ams_i2c_cmd(enum ams_i2c_cmd cmd) | 85 | static int ams_i2c_cmd(enum ams_i2c_cmd cmd) |
| 86 | { | 86 | { |
| 87 | s32 result; | 87 | s32 result; |
| 88 | int remaining = HZ / 20; | 88 | int count = 3; |
| 89 | 89 | ||
| 90 | ams_i2c_write(AMS_COMMAND, cmd); | 90 | ams_i2c_write(AMS_COMMAND, cmd); |
| 91 | mdelay(5); | 91 | msleep(5); |
| 92 | 92 | ||
| 93 | while (remaining) { | 93 | while (count--) { |
| 94 | result = ams_i2c_read(AMS_COMMAND); | 94 | result = ams_i2c_read(AMS_COMMAND); |
| 95 | if (result == 0 || result & 0x80) | 95 | if (result == 0 || result & 0x80) |
| 96 | return 0; | 96 | return 0; |
| 97 | 97 | ||
| 98 | remaining = schedule_timeout(remaining); | 98 | schedule_timeout_uninterruptible(HZ / 20); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | return -1; | 101 | return -1; |
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c new file mode 100644 index 000000000000..03b1f650d1c4 --- /dev/null +++ b/drivers/hwmon/coretemp.c | |||
| @@ -0,0 +1,406 @@ | |||
| 1 | /* | ||
| 2 | * coretemp.c - Linux kernel module for hardware monitoring | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz> | ||
| 5 | * | ||
| 6 | * Inspired from many hwmon drivers | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; version 2 of the License. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 20 | * 02110-1301 USA. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/delay.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | #include <linux/jiffies.h> | ||
| 28 | #include <linux/hwmon.h> | ||
| 29 | #include <linux/sysfs.h> | ||
| 30 | #include <linux/hwmon-sysfs.h> | ||
| 31 | #include <linux/err.h> | ||
| 32 | #include <linux/mutex.h> | ||
| 33 | #include <linux/list.h> | ||
| 34 | #include <linux/platform_device.h> | ||
| 35 | #include <linux/cpu.h> | ||
| 36 | #include <asm/msr.h> | ||
| 37 | #include <asm/processor.h> | ||
| 38 | |||
| 39 | #define DRVNAME "coretemp" | ||
| 40 | |||
| 41 | typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_LABEL, SHOW_NAME } SHOW; | ||
| 42 | |||
| 43 | /* | ||
| 44 | * Functions declaration | ||
| 45 | */ | ||
| 46 | |||
| 47 | static struct coretemp_data *coretemp_update_device(struct device *dev); | ||
| 48 | |||
| 49 | struct coretemp_data { | ||
| 50 | struct class_device *class_dev; | ||
| 51 | struct mutex update_lock; | ||
| 52 | const char *name; | ||
| 53 | u32 id; | ||
| 54 | char valid; /* zero until following fields are valid */ | ||
| 55 | unsigned long last_updated; /* in jiffies */ | ||
| 56 | int temp; | ||
| 57 | int tjmax; | ||
| 58 | u8 alarm; | ||
| 59 | }; | ||
| 60 | |||
| 61 | static struct coretemp_data *coretemp_update_device(struct device *dev); | ||
| 62 | |||
| 63 | /* | ||
| 64 | * Sysfs stuff | ||
| 65 | */ | ||
| 66 | |||
| 67 | static ssize_t show_name(struct device *dev, struct device_attribute | ||
| 68 | *devattr, char *buf) | ||
| 69 | { | ||
| 70 | int ret; | ||
| 71 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 72 | struct coretemp_data *data = dev_get_drvdata(dev); | ||
| 73 | |||
| 74 | if (attr->index == SHOW_NAME) | ||
| 75 | ret = sprintf(buf, "%s\n", data->name); | ||
| 76 | else /* show label */ | ||
| 77 | ret = sprintf(buf, "Core %d\n", data->id); | ||
| 78 | return ret; | ||
| 79 | } | ||
| 80 | |||
| 81 | static ssize_t show_alarm(struct device *dev, struct device_attribute | ||
| 82 | *devattr, char *buf) | ||
| 83 | { | ||
| 84 | struct coretemp_data *data = coretemp_update_device(dev); | ||
| 85 | /* read the Out-of-spec log, never clear */ | ||
| 86 | return sprintf(buf, "%d\n", data->alarm); | ||
| 87 | } | ||
| 88 | |||
| 89 | static ssize_t show_temp(struct device *dev, | ||
| 90 | struct device_attribute *devattr, char *buf) | ||
| 91 | { | ||
| 92 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 93 | struct coretemp_data *data = coretemp_update_device(dev); | ||
| 94 | int err; | ||
| 95 | |||
| 96 | if (attr->index == SHOW_TEMP) | ||
| 97 | err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN; | ||
| 98 | else | ||
| 99 | err = sprintf(buf, "%d\n", data->tjmax); | ||
| 100 | |||
| 101 | return err; | ||
| 102 | } | ||
| 103 | |||
| 104 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, | ||
| 105 | SHOW_TEMP); | ||
| 106 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, | ||
| 107 | SHOW_TJMAX); | ||
| 108 | static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL); | ||
| 109 | static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL); | ||
| 110 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME); | ||
| 111 | |||
| 112 | static struct attribute *coretemp_attributes[] = { | ||
| 113 | &sensor_dev_attr_name.dev_attr.attr, | ||
| 114 | &sensor_dev_attr_temp1_label.dev_attr.attr, | ||
| 115 | &dev_attr_temp1_crit_alarm.attr, | ||
| 116 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
| 117 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
| 118 | NULL | ||
| 119 | }; | ||
| 120 | |||
| 121 | static const struct attribute_group coretemp_group = { | ||
| 122 | .attrs = coretemp_attributes, | ||
| 123 | }; | ||
| 124 | |||
| 125 | static struct coretemp_data *coretemp_update_device(struct device *dev) | ||
| 126 | { | ||
| 127 | struct coretemp_data *data = dev_get_drvdata(dev); | ||
| 128 | |||
| 129 | mutex_lock(&data->update_lock); | ||
| 130 | |||
| 131 | if (!data->valid || time_after(jiffies, data->last_updated + HZ)) { | ||
| 132 | u32 eax, edx; | ||
| 133 | |||
| 134 | data->valid = 0; | ||
| 135 | rdmsr_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx); | ||
| 136 | data->alarm = (eax >> 5) & 1; | ||
| 137 | /* update only if data has been valid */ | ||
| 138 | if (eax & 0x80000000) { | ||
| 139 | data->temp = data->tjmax - (((eax >> 16) | ||
| 140 | & 0x7f) * 1000); | ||
| 141 | data->valid = 1; | ||
| 142 | } else { | ||
| 143 | dev_dbg(dev, "Temperature data invalid (0x%x)\n", eax); | ||
| 144 | } | ||
| 145 | data->last_updated = jiffies; | ||
| 146 | } | ||
| 147 | |||
| 148 | mutex_unlock(&data->update_lock); | ||
| 149 | return data; | ||
| 150 | } | ||
| 151 | |||
| 152 | static int __devinit coretemp_probe(struct platform_device *pdev) | ||
| 153 | { | ||
| 154 | struct coretemp_data *data; | ||
| 155 | struct cpuinfo_x86 *c = &(cpu_data)[pdev->id]; | ||
| 156 | int err; | ||
| 157 | u32 eax, edx; | ||
| 158 | |||
| 159 | if (!(data = kzalloc(sizeof(struct coretemp_data), GFP_KERNEL))) { | ||
| 160 | err = -ENOMEM; | ||
| 161 | dev_err(&pdev->dev, "Out of memory\n"); | ||
| 162 | goto exit; | ||
| 163 | } | ||
| 164 | |||
| 165 | data->id = pdev->id; | ||
| 166 | data->name = "coretemp"; | ||
| 167 | mutex_init(&data->update_lock); | ||
| 168 | /* Tjmax default is 100 degrees C */ | ||
| 169 | data->tjmax = 100000; | ||
| 170 | |||
| 171 | /* test if we can access the THERM_STATUS MSR */ | ||
| 172 | err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx); | ||
| 173 | if (err) { | ||
| 174 | dev_err(&pdev->dev, | ||
| 175 | "Unable to access THERM_STATUS MSR, giving up\n"); | ||
| 176 | goto exit_free; | ||
| 177 | } | ||
| 178 | |||
| 179 | /* Some processors have Tjmax 85 following magic should detect it | ||
| 180 | Intel won't disclose the information without signed NDA, but | ||
| 181 | individuals cannot sign it. Catch(ed) 22. | ||
| 182 | */ | ||
| 183 | |||
| 184 | if (((c->x86_model == 0xf) && (c->x86_mask > 3)) || | ||
| 185 | (c->x86_model == 0xe)) { | ||
| 186 | err = rdmsr_safe_on_cpu(data->id, 0xee, &eax, &edx); | ||
| 187 | if (err) { | ||
| 188 | dev_warn(&pdev->dev, | ||
| 189 | "Unable to access MSR 0xEE, Tjmax left at %d " | ||
| 190 | "degrees C\n", data->tjmax/1000); | ||
| 191 | } else if (eax & 0x40000000) { | ||
| 192 | data->tjmax = 85000; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | platform_set_drvdata(pdev, data); | ||
| 197 | |||
| 198 | if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group))) | ||
| 199 | goto exit_free; | ||
| 200 | |||
| 201 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
| 202 | if (IS_ERR(data->class_dev)) { | ||
| 203 | err = PTR_ERR(data->class_dev); | ||
| 204 | dev_err(&pdev->dev, "Class registration failed (%d)\n", | ||
| 205 | err); | ||
| 206 | goto exit_class; | ||
| 207 | } | ||
| 208 | |||
| 209 | return 0; | ||
| 210 | |||
| 211 | exit_class: | ||
| 212 | sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); | ||
| 213 | exit_free: | ||
| 214 | kfree(data); | ||
| 215 | exit: | ||
| 216 | return err; | ||
| 217 | } | ||
| 218 | |||
| 219 | static int __devexit coretemp_remove(struct platform_device *pdev) | ||
| 220 | { | ||
| 221 | struct coretemp_data *data = platform_get_drvdata(pdev); | ||
| 222 | |||
| 223 | hwmon_device_unregister(data->class_dev); | ||
| 224 | sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); | ||
| 225 | platform_set_drvdata(pdev, NULL); | ||
| 226 | kfree(data); | ||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | static struct platform_driver coretemp_driver = { | ||
| 231 | .driver = { | ||
| 232 | .owner = THIS_MODULE, | ||
| 233 | .name = DRVNAME, | ||
| 234 | }, | ||
| 235 | .probe = coretemp_probe, | ||
| 236 | .remove = __devexit_p(coretemp_remove), | ||
| 237 | }; | ||
| 238 | |||
| 239 | struct pdev_entry { | ||
| 240 | struct list_head list; | ||
| 241 | struct platform_device *pdev; | ||
| 242 | unsigned int cpu; | ||
| 243 | }; | ||
| 244 | |||
| 245 | static LIST_HEAD(pdev_list); | ||
| 246 | static DEFINE_MUTEX(pdev_list_mutex); | ||
| 247 | |||
| 248 | static int __cpuinit coretemp_device_add(unsigned int cpu) | ||
| 249 | { | ||
| 250 | int err; | ||
| 251 | struct platform_device *pdev; | ||
| 252 | struct pdev_entry *pdev_entry; | ||
| 253 | |||
| 254 | pdev = platform_device_alloc(DRVNAME, cpu); | ||
| 255 | if (!pdev) { | ||
| 256 | err = -ENOMEM; | ||
| 257 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | ||
| 258 | goto exit; | ||
| 259 | } | ||
| 260 | |||
| 261 | pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL); | ||
| 262 | if (!pdev_entry) { | ||
| 263 | err = -ENOMEM; | ||
| 264 | goto exit_device_put; | ||
| 265 | } | ||
| 266 | |||
| 267 | err = platform_device_add(pdev); | ||
| 268 | if (err) { | ||
| 269 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
| 270 | err); | ||
| 271 | goto exit_device_free; | ||
| 272 | } | ||
| 273 | |||
| 274 | pdev_entry->pdev = pdev; | ||
| 275 | pdev_entry->cpu = cpu; | ||
| 276 | mutex_lock(&pdev_list_mutex); | ||
| 277 | list_add_tail(&pdev_entry->list, &pdev_list); | ||
| 278 | mutex_unlock(&pdev_list_mutex); | ||
| 279 | |||
| 280 | return 0; | ||
| 281 | |||
| 282 | exit_device_free: | ||
| 283 | kfree(pdev_entry); | ||
| 284 | exit_device_put: | ||
| 285 | platform_device_put(pdev); | ||
| 286 | exit: | ||
| 287 | return err; | ||
| 288 | } | ||
| 289 | |||
| 290 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 291 | void coretemp_device_remove(unsigned int cpu) | ||
| 292 | { | ||
| 293 | struct pdev_entry *p, *n; | ||
| 294 | mutex_lock(&pdev_list_mutex); | ||
| 295 | list_for_each_entry_safe(p, n, &pdev_list, list) { | ||
| 296 | if (p->cpu == cpu) { | ||
| 297 | platform_device_unregister(p->pdev); | ||
| 298 | list_del(&p->list); | ||
| 299 | kfree(p); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | mutex_unlock(&pdev_list_mutex); | ||
| 303 | } | ||
| 304 | |||
| 305 | static int coretemp_cpu_callback(struct notifier_block *nfb, | ||
| 306 | unsigned long action, void *hcpu) | ||
| 307 | { | ||
| 308 | unsigned int cpu = (unsigned long) hcpu; | ||
| 309 | |||
| 310 | switch (action) { | ||
| 311 | case CPU_ONLINE: | ||
| 312 | coretemp_device_add(cpu); | ||
| 313 | break; | ||
| 314 | case CPU_DEAD: | ||
| 315 | coretemp_device_remove(cpu); | ||
| 316 | break; | ||
| 317 | } | ||
| 318 | return NOTIFY_OK; | ||
| 319 | } | ||
| 320 | |||
| 321 | static struct notifier_block __cpuinitdata coretemp_cpu_notifier = { | ||
| 322 | .notifier_call = coretemp_cpu_callback, | ||
| 323 | }; | ||
| 324 | #endif /* !CONFIG_HOTPLUG_CPU */ | ||
| 325 | |||
| 326 | static int __init coretemp_init(void) | ||
| 327 | { | ||
| 328 | int i, err = -ENODEV; | ||
| 329 | struct pdev_entry *p, *n; | ||
| 330 | |||
| 331 | printk(KERN_NOTICE DRVNAME ": This driver uses undocumented features " | ||
| 332 | "of Core CPU. Temperature might be wrong!\n"); | ||
| 333 | |||
| 334 | /* quick check if we run Intel */ | ||
| 335 | if (cpu_data[0].x86_vendor != X86_VENDOR_INTEL) | ||
| 336 | goto exit; | ||
| 337 | |||
| 338 | err = platform_driver_register(&coretemp_driver); | ||
| 339 | if (err) | ||
| 340 | goto exit; | ||
| 341 | |||
| 342 | for_each_online_cpu(i) { | ||
| 343 | struct cpuinfo_x86 *c = &(cpu_data)[i]; | ||
| 344 | |||
| 345 | /* check if family 6, models e, f */ | ||
| 346 | if ((c->cpuid_level < 0) || (c->x86 != 0x6) || | ||
| 347 | !((c->x86_model == 0xe) || (c->x86_model == 0xf))) { | ||
| 348 | |||
| 349 | /* supported CPU not found, but report the unknown | ||
| 350 | family 6 CPU */ | ||
| 351 | if ((c->x86 == 0x6) && (c->x86_model > 0xf)) | ||
| 352 | printk(KERN_WARNING DRVNAME ": Unknown CPU " | ||
| 353 | "model %x\n", c->x86_model); | ||
| 354 | continue; | ||
| 355 | } | ||
| 356 | |||
| 357 | err = coretemp_device_add(i); | ||
| 358 | if (err) | ||
| 359 | goto exit_devices_unreg; | ||
| 360 | } | ||
| 361 | if (list_empty(&pdev_list)) { | ||
| 362 | err = -ENODEV; | ||
| 363 | goto exit_driver_unreg; | ||
| 364 | } | ||
| 365 | |||
| 366 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 367 | register_hotcpu_notifier(&coretemp_cpu_notifier); | ||
| 368 | #endif | ||
| 369 | return 0; | ||
| 370 | |||
| 371 | exit_devices_unreg: | ||
| 372 | mutex_lock(&pdev_list_mutex); | ||
| 373 | list_for_each_entry_safe(p, n, &pdev_list, list) { | ||
| 374 | platform_device_unregister(p->pdev); | ||
| 375 | list_del(&p->list); | ||
| 376 | kfree(p); | ||
| 377 | } | ||
| 378 | mutex_unlock(&pdev_list_mutex); | ||
| 379 | exit_driver_unreg: | ||
| 380 | platform_driver_unregister(&coretemp_driver); | ||
| 381 | exit: | ||
| 382 | return err; | ||
| 383 | } | ||
| 384 | |||
| 385 | static void __exit coretemp_exit(void) | ||
| 386 | { | ||
| 387 | struct pdev_entry *p, *n; | ||
| 388 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 389 | unregister_hotcpu_notifier(&coretemp_cpu_notifier); | ||
| 390 | #endif | ||
| 391 | mutex_lock(&pdev_list_mutex); | ||
| 392 | list_for_each_entry_safe(p, n, &pdev_list, list) { | ||
| 393 | platform_device_unregister(p->pdev); | ||
| 394 | list_del(&p->list); | ||
| 395 | kfree(p); | ||
| 396 | } | ||
| 397 | mutex_unlock(&pdev_list_mutex); | ||
| 398 | platform_driver_unregister(&coretemp_driver); | ||
| 399 | } | ||
| 400 | |||
| 401 | MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>"); | ||
| 402 | MODULE_DESCRIPTION("Intel Core temperature monitor"); | ||
| 403 | MODULE_LICENSE("GPL"); | ||
| 404 | |||
| 405 | module_init(coretemp_init) | ||
| 406 | module_exit(coretemp_exit) | ||
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 7c2973487122..cdbe309b8fc4 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/err.h> | 35 | #include <linux/err.h> |
| 36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
| 37 | #include <linux/sysfs.h> | 37 | #include <linux/sysfs.h> |
| 38 | #include <linux/ioport.h> | ||
| 38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
| 39 | 40 | ||
| 40 | static struct platform_device *pdev; | 41 | static struct platform_device *pdev; |
| @@ -1140,6 +1141,13 @@ static int __devinit f71805f_probe(struct platform_device *pdev) | |||
| 1140 | } | 1141 | } |
| 1141 | 1142 | ||
| 1142 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1143 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
| 1144 | if (!request_region(res->start + ADDR_REG_OFFSET, 2, DRVNAME)) { | ||
| 1145 | err = -EBUSY; | ||
| 1146 | dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n", | ||
| 1147 | (unsigned long)(res->start + ADDR_REG_OFFSET), | ||
| 1148 | (unsigned long)(res->start + ADDR_REG_OFFSET + 1)); | ||
| 1149 | goto exit_free; | ||
| 1150 | } | ||
| 1143 | data->addr = res->start; | 1151 | data->addr = res->start; |
| 1144 | data->name = names[sio_data->kind]; | 1152 | data->name = names[sio_data->kind]; |
| 1145 | mutex_init(&data->update_lock); | 1153 | mutex_init(&data->update_lock); |
| @@ -1165,7 +1173,7 @@ static int __devinit f71805f_probe(struct platform_device *pdev) | |||
| 1165 | 1173 | ||
| 1166 | /* Register sysfs interface files */ | 1174 | /* Register sysfs interface files */ |
| 1167 | if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group))) | 1175 | if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group))) |
| 1168 | goto exit_free; | 1176 | goto exit_release_region; |
| 1169 | if (data->has_in & (1 << 4)) { /* in4 */ | 1177 | if (data->has_in & (1 << 4)) { /* in4 */ |
| 1170 | if ((err = sysfs_create_group(&pdev->dev.kobj, | 1178 | if ((err = sysfs_create_group(&pdev->dev.kobj, |
| 1171 | &f71805f_group_optin[0]))) | 1179 | &f71805f_group_optin[0]))) |
| @@ -1219,6 +1227,8 @@ exit_remove_files: | |||
| 1219 | for (i = 0; i < 4; i++) | 1227 | for (i = 0; i < 4; i++) |
| 1220 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); | 1228 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); |
| 1221 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); | 1229 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); |
| 1230 | exit_release_region: | ||
| 1231 | release_region(res->start + ADDR_REG_OFFSET, 2); | ||
| 1222 | exit_free: | 1232 | exit_free: |
| 1223 | platform_set_drvdata(pdev, NULL); | 1233 | platform_set_drvdata(pdev, NULL); |
| 1224 | kfree(data); | 1234 | kfree(data); |
| @@ -1229,6 +1239,7 @@ exit: | |||
| 1229 | static int __devexit f71805f_remove(struct platform_device *pdev) | 1239 | static int __devexit f71805f_remove(struct platform_device *pdev) |
| 1230 | { | 1240 | { |
| 1231 | struct f71805f_data *data = platform_get_drvdata(pdev); | 1241 | struct f71805f_data *data = platform_get_drvdata(pdev); |
| 1242 | struct resource *res; | ||
| 1232 | int i; | 1243 | int i; |
| 1233 | 1244 | ||
| 1234 | platform_set_drvdata(pdev, NULL); | 1245 | platform_set_drvdata(pdev, NULL); |
| @@ -1239,6 +1250,9 @@ static int __devexit f71805f_remove(struct platform_device *pdev) | |||
| 1239 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); | 1250 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); |
| 1240 | kfree(data); | 1251 | kfree(data); |
| 1241 | 1252 | ||
| 1253 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 1254 | release_region(res->start + ADDR_REG_OFFSET, 2); | ||
| 1255 | |||
| 1242 | return 0; | 1256 | return 0; |
| 1243 | } | 1257 | } |
| 1244 | 1258 | ||
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index b80f6ed5acfc..5aab23b93e24 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c | |||
| @@ -166,16 +166,16 @@ static struct vrm_model vrm_models[] = { | |||
| 166 | {X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14}, /* Intel Core (65 nm) */ | 166 | {X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14}, /* Intel Core (65 nm) */ |
| 167 | {X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110}, /* Intel Conroe */ | 167 | {X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110}, /* Intel Conroe */ |
| 168 | {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ | 168 | {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ |
| 169 | {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */ | ||
| 170 | {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ | 169 | {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ |
| 171 | {X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90}, /* P4 Willamette */ | 170 | {X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90}, /* P4 Willamette */ |
| 172 | {X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90}, /* P4 Northwood */ | 171 | {X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90}, /* P4 Northwood */ |
| 173 | {X86_VENDOR_INTEL, 0xF, ANY, ANY, 100}, /* Prescott and above assume VRD 10 */ | 172 | {X86_VENDOR_INTEL, 0xF, ANY, ANY, 100}, /* Prescott and above assume VRD 10 */ |
| 174 | {X86_VENDOR_INTEL, 0x10, ANY, ANY, 0}, /* Itanium 2 */ | ||
| 175 | {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */ | 173 | {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */ |
| 176 | {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */ | 174 | {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */ |
| 177 | {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */ | 175 | {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */ |
| 178 | {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M */ | 176 | {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M, Eden-N */ |
| 177 | {X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0}, /* No information */ | ||
| 178 | {X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13}, /* C7, Esther */ | ||
| 179 | {X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */ | 179 | {X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */ |
| 180 | }; | 180 | }; |
| 181 | 181 | ||
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 7c65b8bb6d72..a40166ffad12 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/jiffies.h> | 24 | #include <linux/jiffies.h> |
| 25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
| 26 | #include <linux/hwmon.h> | 26 | #include <linux/hwmon.h> |
| 27 | #include <linux/hwmon-sysfs.h> | ||
| 27 | #include <linux/err.h> | 28 | #include <linux/err.h> |
| 28 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
| 29 | #include "lm75.h" | 30 | #include "lm75.h" |
| @@ -39,10 +40,12 @@ I2C_CLIENT_INSMOD_1(lm75); | |||
| 39 | /* Many LM75 constants specified below */ | 40 | /* Many LM75 constants specified below */ |
| 40 | 41 | ||
| 41 | /* The LM75 registers */ | 42 | /* The LM75 registers */ |
| 42 | #define LM75_REG_TEMP 0x00 | ||
| 43 | #define LM75_REG_CONF 0x01 | 43 | #define LM75_REG_CONF 0x01 |
| 44 | #define LM75_REG_TEMP_HYST 0x02 | 44 | static const u8 LM75_REG_TEMP[3] = { |
| 45 | #define LM75_REG_TEMP_OS 0x03 | 45 | 0x00, /* input */ |
| 46 | 0x03, /* max */ | ||
| 47 | 0x02, /* hyst */ | ||
| 48 | }; | ||
| 46 | 49 | ||
| 47 | /* Each client has this additional data */ | 50 | /* Each client has this additional data */ |
| 48 | struct lm75_data { | 51 | struct lm75_data { |
| @@ -51,9 +54,10 @@ struct lm75_data { | |||
| 51 | struct mutex update_lock; | 54 | struct mutex update_lock; |
| 52 | char valid; /* !=0 if following fields are valid */ | 55 | char valid; /* !=0 if following fields are valid */ |
| 53 | unsigned long last_updated; /* In jiffies */ | 56 | unsigned long last_updated; /* In jiffies */ |
| 54 | u16 temp_input; /* Register values */ | 57 | u16 temp[3]; /* Register values, |
| 55 | u16 temp_max; | 58 | 0 = input |
| 56 | u16 temp_hyst; | 59 | 1 = max |
| 60 | 2 = hyst */ | ||
| 57 | }; | 61 | }; |
| 58 | 62 | ||
| 59 | static int lm75_attach_adapter(struct i2c_adapter *adapter); | 63 | static int lm75_attach_adapter(struct i2c_adapter *adapter); |
| @@ -75,35 +79,36 @@ static struct i2c_driver lm75_driver = { | |||
| 75 | .detach_client = lm75_detach_client, | 79 | .detach_client = lm75_detach_client, |
| 76 | }; | 80 | }; |
| 77 | 81 | ||
| 78 | #define show(value) \ | 82 | static ssize_t show_temp(struct device *dev, struct device_attribute *da, |
| 79 | static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 83 | char *buf) |
| 80 | { \ | 84 | { |
| 81 | struct lm75_data *data = lm75_update_device(dev); \ | 85 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 82 | return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value)); \ | 86 | struct lm75_data *data = lm75_update_device(dev); |
| 87 | return sprintf(buf, "%d\n", | ||
| 88 | LM75_TEMP_FROM_REG(data->temp[attr->index])); | ||
| 83 | } | 89 | } |
| 84 | show(temp_max); | 90 | |
| 85 | show(temp_hyst); | 91 | static ssize_t set_temp(struct device *dev, struct device_attribute *da, |
| 86 | show(temp_input); | 92 | const char *buf, size_t count) |
| 87 | 93 | { | |
| 88 | #define set(value, reg) \ | 94 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 89 | static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 95 | struct i2c_client *client = to_i2c_client(dev); |
| 90 | { \ | 96 | struct lm75_data *data = i2c_get_clientdata(client); |
| 91 | struct i2c_client *client = to_i2c_client(dev); \ | 97 | int nr = attr->index; |
| 92 | struct lm75_data *data = i2c_get_clientdata(client); \ | 98 | unsigned long temp = simple_strtoul(buf, NULL, 10); |
| 93 | int temp = simple_strtoul(buf, NULL, 10); \ | 99 | |
| 94 | \ | 100 | mutex_lock(&data->update_lock); |
| 95 | mutex_lock(&data->update_lock); \ | 101 | data->temp[nr] = LM75_TEMP_TO_REG(temp); |
| 96 | data->value = LM75_TEMP_TO_REG(temp); \ | 102 | lm75_write_value(client, LM75_REG_TEMP[nr], data->temp[nr]); |
| 97 | lm75_write_value(client, reg, data->value); \ | 103 | mutex_unlock(&data->update_lock); |
| 98 | mutex_unlock(&data->update_lock); \ | 104 | return count; |
| 99 | return count; \ | ||
| 100 | } | 105 | } |
| 101 | set(temp_max, LM75_REG_TEMP_OS); | ||
| 102 | set(temp_hyst, LM75_REG_TEMP_HYST); | ||
| 103 | 106 | ||
| 104 | static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); | 107 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, |
| 105 | static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); | 108 | show_temp, set_temp, 1); |
| 106 | static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL); | 109 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, |
| 110 | show_temp, set_temp, 2); | ||
| 111 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
| 107 | 112 | ||
| 108 | static int lm75_attach_adapter(struct i2c_adapter *adapter) | 113 | static int lm75_attach_adapter(struct i2c_adapter *adapter) |
| 109 | { | 114 | { |
| @@ -113,9 +118,9 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter) | |||
| 113 | } | 118 | } |
| 114 | 119 | ||
| 115 | static struct attribute *lm75_attributes[] = { | 120 | static struct attribute *lm75_attributes[] = { |
| 116 | &dev_attr_temp1_input.attr, | 121 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
| 117 | &dev_attr_temp1_max.attr, | 122 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
| 118 | &dev_attr_temp1_max_hyst.attr, | 123 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, |
| 119 | 124 | ||
| 120 | NULL | 125 | NULL |
| 121 | }; | 126 | }; |
| @@ -283,11 +288,12 @@ static struct lm75_data *lm75_update_device(struct device *dev) | |||
| 283 | 288 | ||
| 284 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 289 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) |
| 285 | || !data->valid) { | 290 | || !data->valid) { |
| 291 | int i; | ||
| 286 | dev_dbg(&client->dev, "Starting lm75 update\n"); | 292 | dev_dbg(&client->dev, "Starting lm75 update\n"); |
| 287 | 293 | ||
| 288 | data->temp_input = lm75_read_value(client, LM75_REG_TEMP); | 294 | for (i = 0; i < ARRAY_SIZE(data->temp); i++) |
| 289 | data->temp_max = lm75_read_value(client, LM75_REG_TEMP_OS); | 295 | data->temp[i] = lm75_read_value(client, |
| 290 | data->temp_hyst = lm75_read_value(client, LM75_REG_TEMP_HYST); | 296 | LM75_REG_TEMP[i]); |
| 291 | data->last_updated = jiffies; | 297 | data->last_updated = jiffies; |
| 292 | data->valid = 1; | 298 | data->valid = 1; |
| 293 | } | 299 | } |
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 886786c33916..9fb572f03ba5 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | lm78.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | lm78.c - Part of lm_sensors, Linux kernel modules for hardware |
| 3 | monitoring | 3 | monitoring |
| 4 | Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> | 4 | Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> |
| 5 | Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> | ||
| 5 | 6 | ||
| 6 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by | 8 | it under the terms of the GNU General Public License as published by |
| @@ -23,13 +24,18 @@ | |||
| 23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 24 | #include <linux/jiffies.h> | 25 | #include <linux/jiffies.h> |
| 25 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
| 26 | #include <linux/i2c-isa.h> | 27 | #include <linux/platform_device.h> |
| 28 | #include <linux/ioport.h> | ||
| 27 | #include <linux/hwmon.h> | 29 | #include <linux/hwmon.h> |
| 28 | #include <linux/hwmon-vid.h> | 30 | #include <linux/hwmon-vid.h> |
| 31 | #include <linux/hwmon-sysfs.h> | ||
| 29 | #include <linux/err.h> | 32 | #include <linux/err.h> |
| 30 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
| 31 | #include <asm/io.h> | 34 | #include <asm/io.h> |
| 32 | 35 | ||
| 36 | /* ISA device, if found */ | ||
| 37 | static struct platform_device *pdev; | ||
| 38 | |||
| 33 | /* Addresses to scan */ | 39 | /* Addresses to scan */ |
| 34 | static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, | 40 | static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, |
| 35 | 0x25, 0x26, 0x27, 0x28, 0x29, | 41 | 0x25, 0x26, 0x27, 0x28, 0x29, |
| @@ -121,12 +127,8 @@ static inline int TEMP_FROM_REG(s8 val) | |||
| 121 | a bit - except if there could be more than one SMBus. Groan. No solution | 127 | a bit - except if there could be more than one SMBus. Groan. No solution |
| 122 | for this yet. */ | 128 | for this yet. */ |
| 123 | 129 | ||
| 124 | /* This module may seem overly long and complicated. In fact, it is not so | 130 | /* For ISA chips, we abuse the i2c_client addr and name fields. We also use |
| 125 | bad. Quite a lot of bookkeeping is done. A real driver can often cut | 131 | the driver field to differentiate between I2C and ISA chips. */ |
| 126 | some corners. */ | ||
| 127 | |||
| 128 | /* For each registered chip, we need to keep some data in memory. | ||
| 129 | The structure is dynamically allocated. */ | ||
| 130 | struct lm78_data { | 132 | struct lm78_data { |
| 131 | struct i2c_client client; | 133 | struct i2c_client client; |
| 132 | struct class_device *class_dev; | 134 | struct class_device *class_dev; |
| @@ -152,14 +154,16 @@ struct lm78_data { | |||
| 152 | 154 | ||
| 153 | 155 | ||
| 154 | static int lm78_attach_adapter(struct i2c_adapter *adapter); | 156 | static int lm78_attach_adapter(struct i2c_adapter *adapter); |
| 155 | static int lm78_isa_attach_adapter(struct i2c_adapter *adapter); | ||
| 156 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); | 157 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); |
| 157 | static int lm78_detach_client(struct i2c_client *client); | 158 | static int lm78_detach_client(struct i2c_client *client); |
| 158 | 159 | ||
| 159 | static int lm78_read_value(struct i2c_client *client, u8 reg); | 160 | static int __devinit lm78_isa_probe(struct platform_device *pdev); |
| 160 | static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value); | 161 | static int __devexit lm78_isa_remove(struct platform_device *pdev); |
| 162 | |||
| 163 | static int lm78_read_value(struct lm78_data *data, u8 reg); | ||
| 164 | static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value); | ||
| 161 | static struct lm78_data *lm78_update_device(struct device *dev); | 165 | static struct lm78_data *lm78_update_device(struct device *dev); |
| 162 | static void lm78_init_client(struct i2c_client *client); | 166 | static void lm78_init_device(struct lm78_data *data); |
| 163 | 167 | ||
| 164 | 168 | ||
| 165 | static struct i2c_driver lm78_driver = { | 169 | static struct i2c_driver lm78_driver = { |
| @@ -171,95 +175,78 @@ static struct i2c_driver lm78_driver = { | |||
| 171 | .detach_client = lm78_detach_client, | 175 | .detach_client = lm78_detach_client, |
| 172 | }; | 176 | }; |
| 173 | 177 | ||
| 174 | static struct i2c_driver lm78_isa_driver = { | 178 | static struct platform_driver lm78_isa_driver = { |
| 175 | .driver = { | 179 | .driver = { |
| 176 | .owner = THIS_MODULE, | 180 | .owner = THIS_MODULE, |
| 177 | .name = "lm78-isa", | 181 | .name = "lm78", |
| 178 | }, | 182 | }, |
| 179 | .attach_adapter = lm78_isa_attach_adapter, | 183 | .probe = lm78_isa_probe, |
| 180 | .detach_client = lm78_detach_client, | 184 | .remove = lm78_isa_remove, |
| 181 | }; | 185 | }; |
| 182 | 186 | ||
| 183 | 187 | ||
| 184 | /* 7 Voltages */ | 188 | /* 7 Voltages */ |
| 185 | static ssize_t show_in(struct device *dev, char *buf, int nr) | 189 | static ssize_t show_in(struct device *dev, struct device_attribute *da, |
| 190 | char *buf) | ||
| 186 | { | 191 | { |
| 192 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 187 | struct lm78_data *data = lm78_update_device(dev); | 193 | struct lm78_data *data = lm78_update_device(dev); |
| 188 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])); | 194 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index])); |
| 189 | } | 195 | } |
| 190 | 196 | ||
| 191 | static ssize_t show_in_min(struct device *dev, char *buf, int nr) | 197 | static ssize_t show_in_min(struct device *dev, struct device_attribute *da, |
| 198 | char *buf) | ||
| 192 | { | 199 | { |
| 200 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 193 | struct lm78_data *data = lm78_update_device(dev); | 201 | struct lm78_data *data = lm78_update_device(dev); |
| 194 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])); | 202 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index])); |
| 195 | } | 203 | } |
| 196 | 204 | ||
| 197 | static ssize_t show_in_max(struct device *dev, char *buf, int nr) | 205 | static ssize_t show_in_max(struct device *dev, struct device_attribute *da, |
| 206 | char *buf) | ||
| 198 | { | 207 | { |
| 208 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 199 | struct lm78_data *data = lm78_update_device(dev); | 209 | struct lm78_data *data = lm78_update_device(dev); |
| 200 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])); | 210 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index])); |
| 201 | } | 211 | } |
| 202 | 212 | ||
| 203 | static ssize_t set_in_min(struct device *dev, const char *buf, | 213 | static ssize_t set_in_min(struct device *dev, struct device_attribute *da, |
| 204 | size_t count, int nr) | 214 | const char *buf, size_t count) |
| 205 | { | 215 | { |
| 206 | struct i2c_client *client = to_i2c_client(dev); | 216 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 207 | struct lm78_data *data = i2c_get_clientdata(client); | 217 | struct lm78_data *data = dev_get_drvdata(dev); |
| 208 | unsigned long val = simple_strtoul(buf, NULL, 10); | 218 | unsigned long val = simple_strtoul(buf, NULL, 10); |
| 219 | int nr = attr->index; | ||
| 209 | 220 | ||
| 210 | mutex_lock(&data->update_lock); | 221 | mutex_lock(&data->update_lock); |
| 211 | data->in_min[nr] = IN_TO_REG(val); | 222 | data->in_min[nr] = IN_TO_REG(val); |
| 212 | lm78_write_value(client, LM78_REG_IN_MIN(nr), data->in_min[nr]); | 223 | lm78_write_value(data, LM78_REG_IN_MIN(nr), data->in_min[nr]); |
| 213 | mutex_unlock(&data->update_lock); | 224 | mutex_unlock(&data->update_lock); |
| 214 | return count; | 225 | return count; |
| 215 | } | 226 | } |
| 216 | 227 | ||
| 217 | static ssize_t set_in_max(struct device *dev, const char *buf, | 228 | static ssize_t set_in_max(struct device *dev, struct device_attribute *da, |
| 218 | size_t count, int nr) | 229 | const char *buf, size_t count) |
| 219 | { | 230 | { |
| 220 | struct i2c_client *client = to_i2c_client(dev); | 231 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 221 | struct lm78_data *data = i2c_get_clientdata(client); | 232 | struct lm78_data *data = dev_get_drvdata(dev); |
| 222 | unsigned long val = simple_strtoul(buf, NULL, 10); | 233 | unsigned long val = simple_strtoul(buf, NULL, 10); |
| 234 | int nr = attr->index; | ||
| 223 | 235 | ||
| 224 | mutex_lock(&data->update_lock); | 236 | mutex_lock(&data->update_lock); |
| 225 | data->in_max[nr] = IN_TO_REG(val); | 237 | data->in_max[nr] = IN_TO_REG(val); |
| 226 | lm78_write_value(client, LM78_REG_IN_MAX(nr), data->in_max[nr]); | 238 | lm78_write_value(data, LM78_REG_IN_MAX(nr), data->in_max[nr]); |
| 227 | mutex_unlock(&data->update_lock); | 239 | mutex_unlock(&data->update_lock); |
| 228 | return count; | 240 | return count; |
| 229 | } | 241 | } |
| 230 | 242 | ||
| 231 | #define show_in_offset(offset) \ | 243 | #define show_in_offset(offset) \ |
| 232 | static ssize_t \ | 244 | static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ |
| 233 | show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 245 | show_in, NULL, offset); \ |
| 234 | { \ | 246 | static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ |
| 235 | return show_in(dev, buf, offset); \ | 247 | show_in_min, set_in_min, offset); \ |
| 236 | } \ | 248 | static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ |
| 237 | static DEVICE_ATTR(in##offset##_input, S_IRUGO, \ | 249 | show_in_max, set_in_max, offset); |
| 238 | show_in##offset, NULL); \ | ||
| 239 | static ssize_t \ | ||
| 240 | show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 241 | { \ | ||
| 242 | return show_in_min(dev, buf, offset); \ | ||
| 243 | } \ | ||
| 244 | static ssize_t \ | ||
| 245 | show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 246 | { \ | ||
| 247 | return show_in_max(dev, buf, offset); \ | ||
| 248 | } \ | ||
| 249 | static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \ | ||
| 250 | const char *buf, size_t count) \ | ||
| 251 | { \ | ||
| 252 | return set_in_min(dev, buf, count, offset); \ | ||
| 253 | } \ | ||
| 254 | static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \ | ||
| 255 | const char *buf, size_t count) \ | ||
| 256 | { \ | ||
| 257 | return set_in_max(dev, buf, count, offset); \ | ||
| 258 | } \ | ||
| 259 | static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ | ||
| 260 | show_in##offset##_min, set_in##offset##_min); \ | ||
| 261 | static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ | ||
| 262 | show_in##offset##_max, set_in##offset##_max); | ||
| 263 | 250 | ||
| 264 | show_in_offset(0); | 251 | show_in_offset(0); |
| 265 | show_in_offset(1); | 252 | show_in_offset(1); |
| @@ -270,46 +257,49 @@ show_in_offset(5); | |||
| 270 | show_in_offset(6); | 257 | show_in_offset(6); |
| 271 | 258 | ||
| 272 | /* Temperature */ | 259 | /* Temperature */ |
| 273 | static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf) | 260 | static ssize_t show_temp(struct device *dev, struct device_attribute *da, |
| 261 | char *buf) | ||
| 274 | { | 262 | { |
| 275 | struct lm78_data *data = lm78_update_device(dev); | 263 | struct lm78_data *data = lm78_update_device(dev); |
| 276 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp)); | 264 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp)); |
| 277 | } | 265 | } |
| 278 | 266 | ||
| 279 | static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf) | 267 | static ssize_t show_temp_over(struct device *dev, struct device_attribute *da, |
| 268 | char *buf) | ||
| 280 | { | 269 | { |
| 281 | struct lm78_data *data = lm78_update_device(dev); | 270 | struct lm78_data *data = lm78_update_device(dev); |
| 282 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over)); | 271 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over)); |
| 283 | } | 272 | } |
| 284 | 273 | ||
| 285 | static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 274 | static ssize_t set_temp_over(struct device *dev, struct device_attribute *da, |
| 275 | const char *buf, size_t count) | ||
| 286 | { | 276 | { |
| 287 | struct i2c_client *client = to_i2c_client(dev); | 277 | struct lm78_data *data = dev_get_drvdata(dev); |
| 288 | struct lm78_data *data = i2c_get_clientdata(client); | ||
| 289 | long val = simple_strtol(buf, NULL, 10); | 278 | long val = simple_strtol(buf, NULL, 10); |
| 290 | 279 | ||
| 291 | mutex_lock(&data->update_lock); | 280 | mutex_lock(&data->update_lock); |
| 292 | data->temp_over = TEMP_TO_REG(val); | 281 | data->temp_over = TEMP_TO_REG(val); |
| 293 | lm78_write_value(client, LM78_REG_TEMP_OVER, data->temp_over); | 282 | lm78_write_value(data, LM78_REG_TEMP_OVER, data->temp_over); |
| 294 | mutex_unlock(&data->update_lock); | 283 | mutex_unlock(&data->update_lock); |
| 295 | return count; | 284 | return count; |
| 296 | } | 285 | } |
| 297 | 286 | ||
| 298 | static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf) | 287 | static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da, |
| 288 | char *buf) | ||
| 299 | { | 289 | { |
| 300 | struct lm78_data *data = lm78_update_device(dev); | 290 | struct lm78_data *data = lm78_update_device(dev); |
| 301 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst)); | 291 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst)); |
| 302 | } | 292 | } |
| 303 | 293 | ||
| 304 | static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 294 | static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da, |
| 295 | const char *buf, size_t count) | ||
| 305 | { | 296 | { |
| 306 | struct i2c_client *client = to_i2c_client(dev); | 297 | struct lm78_data *data = dev_get_drvdata(dev); |
| 307 | struct lm78_data *data = i2c_get_clientdata(client); | ||
| 308 | long val = simple_strtol(buf, NULL, 10); | 298 | long val = simple_strtol(buf, NULL, 10); |
| 309 | 299 | ||
| 310 | mutex_lock(&data->update_lock); | 300 | mutex_lock(&data->update_lock); |
| 311 | data->temp_hyst = TEMP_TO_REG(val); | 301 | data->temp_hyst = TEMP_TO_REG(val); |
| 312 | lm78_write_value(client, LM78_REG_TEMP_HYST, data->temp_hyst); | 302 | lm78_write_value(data, LM78_REG_TEMP_HYST, data->temp_hyst); |
| 313 | mutex_unlock(&data->update_lock); | 303 | mutex_unlock(&data->update_lock); |
| 314 | return count; | 304 | return count; |
| 315 | } | 305 | } |
| @@ -321,49 +311,59 @@ static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, | |||
| 321 | show_temp_hyst, set_temp_hyst); | 311 | show_temp_hyst, set_temp_hyst); |
| 322 | 312 | ||
| 323 | /* 3 Fans */ | 313 | /* 3 Fans */ |
| 324 | static ssize_t show_fan(struct device *dev, char *buf, int nr) | 314 | static ssize_t show_fan(struct device *dev, struct device_attribute *da, |
| 315 | char *buf) | ||
| 325 | { | 316 | { |
| 317 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 326 | struct lm78_data *data = lm78_update_device(dev); | 318 | struct lm78_data *data = lm78_update_device(dev); |
| 319 | int nr = attr->index; | ||
| 327 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], | 320 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], |
| 328 | DIV_FROM_REG(data->fan_div[nr])) ); | 321 | DIV_FROM_REG(data->fan_div[nr])) ); |
| 329 | } | 322 | } |
| 330 | 323 | ||
| 331 | static ssize_t show_fan_min(struct device *dev, char *buf, int nr) | 324 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, |
| 325 | char *buf) | ||
| 332 | { | 326 | { |
| 327 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 333 | struct lm78_data *data = lm78_update_device(dev); | 328 | struct lm78_data *data = lm78_update_device(dev); |
| 329 | int nr = attr->index; | ||
| 334 | return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr], | 330 | return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr], |
| 335 | DIV_FROM_REG(data->fan_div[nr])) ); | 331 | DIV_FROM_REG(data->fan_div[nr])) ); |
| 336 | } | 332 | } |
| 337 | 333 | ||
| 338 | static ssize_t set_fan_min(struct device *dev, const char *buf, | 334 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, |
| 339 | size_t count, int nr) | 335 | const char *buf, size_t count) |
| 340 | { | 336 | { |
| 341 | struct i2c_client *client = to_i2c_client(dev); | 337 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 342 | struct lm78_data *data = i2c_get_clientdata(client); | 338 | struct lm78_data *data = dev_get_drvdata(dev); |
| 339 | int nr = attr->index; | ||
| 343 | unsigned long val = simple_strtoul(buf, NULL, 10); | 340 | unsigned long val = simple_strtoul(buf, NULL, 10); |
| 344 | 341 | ||
| 345 | mutex_lock(&data->update_lock); | 342 | mutex_lock(&data->update_lock); |
| 346 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | 343 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
| 347 | lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); | 344 | lm78_write_value(data, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); |
| 348 | mutex_unlock(&data->update_lock); | 345 | mutex_unlock(&data->update_lock); |
| 349 | return count; | 346 | return count; |
| 350 | } | 347 | } |
| 351 | 348 | ||
| 352 | static ssize_t show_fan_div(struct device *dev, char *buf, int nr) | 349 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *da, |
| 350 | char *buf) | ||
| 353 | { | 351 | { |
| 352 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 354 | struct lm78_data *data = lm78_update_device(dev); | 353 | struct lm78_data *data = lm78_update_device(dev); |
| 355 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) ); | 354 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); |
| 356 | } | 355 | } |
| 357 | 356 | ||
| 358 | /* Note: we save and restore the fan minimum here, because its value is | 357 | /* Note: we save and restore the fan minimum here, because its value is |
| 359 | determined in part by the fan divisor. This follows the principle of | 358 | determined in part by the fan divisor. This follows the principle of |
| 360 | least surprise; the user doesn't expect the fan minimum to change just | 359 | least surprise; the user doesn't expect the fan minimum to change just |
| 361 | because the divisor changed. */ | 360 | because the divisor changed. */ |
| 362 | static ssize_t set_fan_div(struct device *dev, const char *buf, | 361 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, |
| 363 | size_t count, int nr) | 362 | const char *buf, size_t count) |
| 364 | { | 363 | { |
| 365 | struct i2c_client *client = to_i2c_client(dev); | 364 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 366 | struct lm78_data *data = i2c_get_clientdata(client); | 365 | struct lm78_data *data = dev_get_drvdata(dev); |
| 366 | int nr = attr->index; | ||
| 367 | unsigned long val = simple_strtoul(buf, NULL, 10); | 367 | unsigned long val = simple_strtoul(buf, NULL, 10); |
| 368 | unsigned long min; | 368 | unsigned long min; |
| 369 | u8 reg; | 369 | u8 reg; |
| @@ -378,13 +378,13 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, | |||
| 378 | case 4: data->fan_div[nr] = 2; break; | 378 | case 4: data->fan_div[nr] = 2; break; |
| 379 | case 8: data->fan_div[nr] = 3; break; | 379 | case 8: data->fan_div[nr] = 3; break; |
| 380 | default: | 380 | default: |
| 381 | dev_err(&client->dev, "fan_div value %ld not " | 381 | dev_err(dev, "fan_div value %ld not " |
| 382 | "supported. Choose one of 1, 2, 4 or 8!\n", val); | 382 | "supported. Choose one of 1, 2, 4 or 8!\n", val); |
| 383 | mutex_unlock(&data->update_lock); | 383 | mutex_unlock(&data->update_lock); |
| 384 | return -EINVAL; | 384 | return -EINVAL; |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | reg = lm78_read_value(client, LM78_REG_VID_FANDIV); | 387 | reg = lm78_read_value(data, LM78_REG_VID_FANDIV); |
| 388 | switch (nr) { | 388 | switch (nr) { |
| 389 | case 0: | 389 | case 0: |
| 390 | reg = (reg & 0xcf) | (data->fan_div[nr] << 4); | 390 | reg = (reg & 0xcf) | (data->fan_div[nr] << 4); |
| @@ -393,63 +393,36 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, | |||
| 393 | reg = (reg & 0x3f) | (data->fan_div[nr] << 6); | 393 | reg = (reg & 0x3f) | (data->fan_div[nr] << 6); |
| 394 | break; | 394 | break; |
| 395 | } | 395 | } |
| 396 | lm78_write_value(client, LM78_REG_VID_FANDIV, reg); | 396 | lm78_write_value(data, LM78_REG_VID_FANDIV, reg); |
| 397 | 397 | ||
| 398 | data->fan_min[nr] = | 398 | data->fan_min[nr] = |
| 399 | FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); | 399 | FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); |
| 400 | lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); | 400 | lm78_write_value(data, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); |
| 401 | mutex_unlock(&data->update_lock); | 401 | mutex_unlock(&data->update_lock); |
| 402 | 402 | ||
| 403 | return count; | 403 | return count; |
| 404 | } | 404 | } |
| 405 | 405 | ||
| 406 | #define show_fan_offset(offset) \ | 406 | #define show_fan_offset(offset) \ |
| 407 | static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 407 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ |
| 408 | { \ | 408 | show_fan, NULL, offset - 1); \ |
| 409 | return show_fan(dev, buf, offset - 1); \ | 409 | static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ |
| 410 | } \ | 410 | show_fan_min, set_fan_min, offset - 1); |
| 411 | static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 412 | { \ | ||
| 413 | return show_fan_min(dev, buf, offset - 1); \ | ||
| 414 | } \ | ||
| 415 | static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 416 | { \ | ||
| 417 | return show_fan_div(dev, buf, offset - 1); \ | ||
| 418 | } \ | ||
| 419 | static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \ | ||
| 420 | const char *buf, size_t count) \ | ||
| 421 | { \ | ||
| 422 | return set_fan_min(dev, buf, count, offset - 1); \ | ||
| 423 | } \ | ||
| 424 | static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ | ||
| 425 | static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
| 426 | show_fan_##offset##_min, set_fan_##offset##_min); | ||
| 427 | |||
| 428 | static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf, | ||
| 429 | size_t count) | ||
| 430 | { | ||
| 431 | return set_fan_div(dev, buf, count, 0) ; | ||
| 432 | } | ||
| 433 | |||
| 434 | static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf, | ||
| 435 | size_t count) | ||
| 436 | { | ||
| 437 | return set_fan_div(dev, buf, count, 1) ; | ||
| 438 | } | ||
| 439 | 411 | ||
| 440 | show_fan_offset(1); | 412 | show_fan_offset(1); |
| 441 | show_fan_offset(2); | 413 | show_fan_offset(2); |
| 442 | show_fan_offset(3); | 414 | show_fan_offset(3); |
| 443 | 415 | ||
| 444 | /* Fan 3 divisor is locked in H/W */ | 416 | /* Fan 3 divisor is locked in H/W */ |
| 445 | static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, | 417 | static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, |
| 446 | show_fan_1_div, set_fan_1_div); | 418 | show_fan_div, set_fan_div, 0); |
| 447 | static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, | 419 | static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, |
| 448 | show_fan_2_div, set_fan_2_div); | 420 | show_fan_div, set_fan_div, 1); |
| 449 | static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL); | 421 | static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2); |
| 450 | 422 | ||
| 451 | /* VID */ | 423 | /* VID */ |
| 452 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) | 424 | static ssize_t show_vid(struct device *dev, struct device_attribute *da, |
| 425 | char *buf) | ||
| 453 | { | 426 | { |
| 454 | struct lm78_data *data = lm78_update_device(dev); | 427 | struct lm78_data *data = lm78_update_device(dev); |
| 455 | return sprintf(buf, "%d\n", vid_from_reg(data->vid, 82)); | 428 | return sprintf(buf, "%d\n", vid_from_reg(data->vid, 82)); |
| @@ -457,7 +430,8 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char | |||
| 457 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); | 430 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); |
| 458 | 431 | ||
| 459 | /* Alarms */ | 432 | /* Alarms */ |
| 460 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 433 | static ssize_t show_alarms(struct device *dev, struct device_attribute *da, |
| 434 | char *buf) | ||
| 461 | { | 435 | { |
| 462 | struct lm78_data *data = lm78_update_device(dev); | 436 | struct lm78_data *data = lm78_update_device(dev); |
| 463 | return sprintf(buf, "%u\n", data->alarms); | 437 | return sprintf(buf, "%u\n", data->alarms); |
| @@ -475,45 +449,40 @@ static int lm78_attach_adapter(struct i2c_adapter *adapter) | |||
| 475 | return i2c_probe(adapter, &addr_data, lm78_detect); | 449 | return i2c_probe(adapter, &addr_data, lm78_detect); |
| 476 | } | 450 | } |
| 477 | 451 | ||
| 478 | static int lm78_isa_attach_adapter(struct i2c_adapter *adapter) | ||
| 479 | { | ||
| 480 | return lm78_detect(adapter, isa_address, -1); | ||
| 481 | } | ||
| 482 | |||
| 483 | static struct attribute *lm78_attributes[] = { | 452 | static struct attribute *lm78_attributes[] = { |
| 484 | &dev_attr_in0_input.attr, | 453 | &sensor_dev_attr_in0_input.dev_attr.attr, |
| 485 | &dev_attr_in0_min.attr, | 454 | &sensor_dev_attr_in0_min.dev_attr.attr, |
| 486 | &dev_attr_in0_max.attr, | 455 | &sensor_dev_attr_in0_max.dev_attr.attr, |
| 487 | &dev_attr_in1_input.attr, | 456 | &sensor_dev_attr_in1_input.dev_attr.attr, |
| 488 | &dev_attr_in1_min.attr, | 457 | &sensor_dev_attr_in1_min.dev_attr.attr, |
| 489 | &dev_attr_in1_max.attr, | 458 | &sensor_dev_attr_in1_max.dev_attr.attr, |
| 490 | &dev_attr_in2_input.attr, | 459 | &sensor_dev_attr_in2_input.dev_attr.attr, |
| 491 | &dev_attr_in2_min.attr, | 460 | &sensor_dev_attr_in2_min.dev_attr.attr, |
| 492 | &dev_attr_in2_max.attr, | 461 | &sensor_dev_attr_in2_max.dev_attr.attr, |
| 493 | &dev_attr_in3_input.attr, | 462 | &sensor_dev_attr_in3_input.dev_attr.attr, |
| 494 | &dev_attr_in3_min.attr, | 463 | &sensor_dev_attr_in3_min.dev_attr.attr, |
| 495 | &dev_attr_in3_max.attr, | 464 | &sensor_dev_attr_in3_max.dev_attr.attr, |
| 496 | &dev_attr_in4_input.attr, | 465 | &sensor_dev_attr_in4_input.dev_attr.attr, |
| 497 | &dev_attr_in4_min.attr, | 466 | &sensor_dev_attr_in4_min.dev_attr.attr, |
| 498 | &dev_attr_in4_max.attr, | 467 | &sensor_dev_attr_in4_max.dev_attr.attr, |
| 499 | &dev_attr_in5_input.attr, | 468 | &sensor_dev_attr_in5_input.dev_attr.attr, |
| 500 | &dev_attr_in5_min.attr, | 469 | &sensor_dev_attr_in5_min.dev_attr.attr, |
| 501 | &dev_attr_in5_max.attr, | 470 | &sensor_dev_attr_in5_max.dev_attr.attr, |
| 502 | &dev_attr_in6_input.attr, | 471 | &sensor_dev_attr_in6_input.dev_attr.attr, |
| 503 | &dev_attr_in6_min.attr, | 472 | &sensor_dev_attr_in6_min.dev_attr.attr, |
| 504 | &dev_attr_in6_max.attr, | 473 | &sensor_dev_attr_in6_max.dev_attr.attr, |
| 505 | &dev_attr_temp1_input.attr, | 474 | &dev_attr_temp1_input.attr, |
| 506 | &dev_attr_temp1_max.attr, | 475 | &dev_attr_temp1_max.attr, |
| 507 | &dev_attr_temp1_max_hyst.attr, | 476 | &dev_attr_temp1_max_hyst.attr, |
| 508 | &dev_attr_fan1_input.attr, | 477 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
| 509 | &dev_attr_fan1_min.attr, | 478 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
| 510 | &dev_attr_fan1_div.attr, | 479 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
| 511 | &dev_attr_fan2_input.attr, | 480 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
| 512 | &dev_attr_fan2_min.attr, | 481 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
| 513 | &dev_attr_fan2_div.attr, | 482 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
| 514 | &dev_attr_fan3_input.attr, | 483 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
| 515 | &dev_attr_fan3_min.attr, | 484 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
| 516 | &dev_attr_fan3_div.attr, | 485 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
| 517 | &dev_attr_alarms.attr, | 486 | &dev_attr_alarms.attr, |
| 518 | &dev_attr_cpu0_vid.attr, | 487 | &dev_attr_cpu0_vid.attr, |
| 519 | 488 | ||
| @@ -524,6 +493,17 @@ static const struct attribute_group lm78_group = { | |||
| 524 | .attrs = lm78_attributes, | 493 | .attrs = lm78_attributes, |
| 525 | }; | 494 | }; |
| 526 | 495 | ||
| 496 | /* I2C devices get this name attribute automatically, but for ISA devices | ||
| 497 | we must create it by ourselves. */ | ||
| 498 | static ssize_t show_name(struct device *dev, struct device_attribute | ||
| 499 | *devattr, char *buf) | ||
| 500 | { | ||
| 501 | struct lm78_data *data = dev_get_drvdata(dev); | ||
| 502 | |||
| 503 | return sprintf(buf, "%s\n", data->client.name); | ||
| 504 | } | ||
| 505 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
| 506 | |||
| 527 | /* This function is called by i2c_probe */ | 507 | /* This function is called by i2c_probe */ |
| 528 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | 508 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) |
| 529 | { | 509 | { |
| @@ -531,54 +511,10 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 531 | struct i2c_client *new_client; | 511 | struct i2c_client *new_client; |
| 532 | struct lm78_data *data; | 512 | struct lm78_data *data; |
| 533 | const char *client_name = ""; | 513 | const char *client_name = ""; |
| 534 | int is_isa = i2c_is_isa_adapter(adapter); | ||
| 535 | 514 | ||
| 536 | if (!is_isa && | 515 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
| 537 | !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
| 538 | err = -ENODEV; | 516 | err = -ENODEV; |
| 539 | goto ERROR0; | 517 | goto ERROR1; |
| 540 | } | ||
| 541 | |||
| 542 | /* Reserve the ISA region */ | ||
| 543 | if (is_isa) | ||
| 544 | if (!request_region(address, LM78_EXTENT, | ||
| 545 | lm78_isa_driver.driver.name)) { | ||
| 546 | err = -EBUSY; | ||
| 547 | goto ERROR0; | ||
| 548 | } | ||
| 549 | |||
| 550 | /* Probe whether there is anything available on this address. Already | ||
| 551 | done for SMBus clients */ | ||
| 552 | if (kind < 0) { | ||
| 553 | if (is_isa) { | ||
| 554 | |||
| 555 | #define REALLY_SLOW_IO | ||
| 556 | /* We need the timeouts for at least some LM78-like | ||
| 557 | chips. But only if we read 'undefined' registers. */ | ||
| 558 | i = inb_p(address + 1); | ||
| 559 | if (inb_p(address + 2) != i) { | ||
| 560 | err = -ENODEV; | ||
| 561 | goto ERROR1; | ||
| 562 | } | ||
| 563 | if (inb_p(address + 3) != i) { | ||
| 564 | err = -ENODEV; | ||
| 565 | goto ERROR1; | ||
| 566 | } | ||
| 567 | if (inb_p(address + 7) != i) { | ||
| 568 | err = -ENODEV; | ||
| 569 | goto ERROR1; | ||
| 570 | } | ||
| 571 | #undef REALLY_SLOW_IO | ||
| 572 | |||
| 573 | /* Let's just hope nothing breaks here */ | ||
| 574 | i = inb_p(address + 5) & 0x7f; | ||
| 575 | outb_p(~i & 0x7f, address + 5); | ||
| 576 | if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) { | ||
| 577 | outb_p(i, address + 5); | ||
| 578 | err = -ENODEV; | ||
| 579 | goto ERROR1; | ||
| 580 | } | ||
| 581 | } | ||
| 582 | } | 518 | } |
| 583 | 519 | ||
| 584 | /* OK. For now, we presume we have a valid client. We now create the | 520 | /* OK. For now, we presume we have a valid client. We now create the |
| @@ -591,22 +527,19 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 591 | } | 527 | } |
| 592 | 528 | ||
| 593 | new_client = &data->client; | 529 | new_client = &data->client; |
| 594 | if (is_isa) | ||
| 595 | mutex_init(&data->lock); | ||
| 596 | i2c_set_clientdata(new_client, data); | 530 | i2c_set_clientdata(new_client, data); |
| 597 | new_client->addr = address; | 531 | new_client->addr = address; |
| 598 | new_client->adapter = adapter; | 532 | new_client->adapter = adapter; |
| 599 | new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver; | 533 | new_client->driver = &lm78_driver; |
| 600 | new_client->flags = 0; | ||
| 601 | 534 | ||
| 602 | /* Now, we do the remaining detection. */ | 535 | /* Now, we do the remaining detection. */ |
| 603 | if (kind < 0) { | 536 | if (kind < 0) { |
| 604 | if (lm78_read_value(new_client, LM78_REG_CONFIG) & 0x80) { | 537 | if (lm78_read_value(data, LM78_REG_CONFIG) & 0x80) { |
| 605 | err = -ENODEV; | 538 | err = -ENODEV; |
| 606 | goto ERROR2; | 539 | goto ERROR2; |
| 607 | } | 540 | } |
| 608 | if (!is_isa && (lm78_read_value( | 541 | if (lm78_read_value(data, LM78_REG_I2C_ADDR) != |
| 609 | new_client, LM78_REG_I2C_ADDR) != address)) { | 542 | address) { |
| 610 | err = -ENODEV; | 543 | err = -ENODEV; |
| 611 | goto ERROR2; | 544 | goto ERROR2; |
| 612 | } | 545 | } |
| @@ -614,7 +547,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 614 | 547 | ||
| 615 | /* Determine the chip type. */ | 548 | /* Determine the chip type. */ |
| 616 | if (kind <= 0) { | 549 | if (kind <= 0) { |
| 617 | i = lm78_read_value(new_client, LM78_REG_CHIPID); | 550 | i = lm78_read_value(data, LM78_REG_CHIPID); |
| 618 | if (i == 0x00 || i == 0x20 /* LM78 */ | 551 | if (i == 0x00 || i == 0x20 /* LM78 */ |
| 619 | || i == 0x40) /* LM78-J */ | 552 | || i == 0x40) /* LM78-J */ |
| 620 | kind = lm78; | 553 | kind = lm78; |
| @@ -641,21 +574,12 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 641 | strlcpy(new_client->name, client_name, I2C_NAME_SIZE); | 574 | strlcpy(new_client->name, client_name, I2C_NAME_SIZE); |
| 642 | data->type = kind; | 575 | data->type = kind; |
| 643 | 576 | ||
| 644 | data->valid = 0; | ||
| 645 | mutex_init(&data->update_lock); | ||
| 646 | |||
| 647 | /* Tell the I2C layer a new client has arrived */ | 577 | /* Tell the I2C layer a new client has arrived */ |
| 648 | if ((err = i2c_attach_client(new_client))) | 578 | if ((err = i2c_attach_client(new_client))) |
| 649 | goto ERROR2; | 579 | goto ERROR2; |
| 650 | 580 | ||
| 651 | /* Initialize the LM78 chip */ | 581 | /* Initialize the LM78 chip */ |
| 652 | lm78_init_client(new_client); | 582 | lm78_init_device(data); |
| 653 | |||
| 654 | /* A few vars need to be filled upon startup */ | ||
| 655 | for (i = 0; i < 3; i++) { | ||
| 656 | data->fan_min[i] = lm78_read_value(new_client, | ||
| 657 | LM78_REG_FAN_MIN(i)); | ||
| 658 | } | ||
| 659 | 583 | ||
| 660 | /* Register sysfs hooks */ | 584 | /* Register sysfs hooks */ |
| 661 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group))) | 585 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group))) |
| @@ -676,9 +600,6 @@ ERROR3: | |||
| 676 | ERROR2: | 600 | ERROR2: |
| 677 | kfree(data); | 601 | kfree(data); |
| 678 | ERROR1: | 602 | ERROR1: |
| 679 | if (is_isa) | ||
| 680 | release_region(address, LM78_EXTENT); | ||
| 681 | ERROR0: | ||
| 682 | return err; | 603 | return err; |
| 683 | } | 604 | } |
| 684 | 605 | ||
| @@ -693,9 +614,77 @@ static int lm78_detach_client(struct i2c_client *client) | |||
| 693 | if ((err = i2c_detach_client(client))) | 614 | if ((err = i2c_detach_client(client))) |
| 694 | return err; | 615 | return err; |
| 695 | 616 | ||
| 696 | if(i2c_is_isa_client(client)) | 617 | kfree(data); |
| 697 | release_region(client->addr, LM78_EXTENT); | 618 | |
| 619 | return 0; | ||
| 620 | } | ||
| 621 | |||
| 622 | static int __devinit lm78_isa_probe(struct platform_device *pdev) | ||
| 623 | { | ||
| 624 | int err; | ||
| 625 | struct lm78_data *data; | ||
| 626 | struct resource *res; | ||
| 627 | const char *name; | ||
| 628 | |||
| 629 | /* Reserve the ISA region */ | ||
| 630 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 631 | if (!request_region(res->start, LM78_EXTENT, "lm78")) { | ||
| 632 | err = -EBUSY; | ||
| 633 | goto exit; | ||
| 634 | } | ||
| 635 | |||
| 636 | if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) { | ||
| 637 | err = -ENOMEM; | ||
| 638 | goto exit_release_region; | ||
| 639 | } | ||
| 640 | mutex_init(&data->lock); | ||
| 641 | data->client.addr = res->start; | ||
| 642 | i2c_set_clientdata(&data->client, data); | ||
| 643 | platform_set_drvdata(pdev, data); | ||
| 644 | |||
| 645 | if (lm78_read_value(data, LM78_REG_CHIPID) & 0x80) { | ||
| 646 | data->type = lm79; | ||
| 647 | name = "lm79"; | ||
| 648 | } else { | ||
| 649 | data->type = lm78; | ||
| 650 | name = "lm78"; | ||
| 651 | } | ||
| 652 | strlcpy(data->client.name, name, I2C_NAME_SIZE); | ||
| 653 | |||
| 654 | /* Initialize the LM78 chip */ | ||
| 655 | lm78_init_device(data); | ||
| 656 | |||
| 657 | /* Register sysfs hooks */ | ||
| 658 | if ((err = sysfs_create_group(&pdev->dev.kobj, &lm78_group)) | ||
| 659 | || (err = device_create_file(&pdev->dev, &dev_attr_name))) | ||
| 660 | goto exit_remove_files; | ||
| 661 | |||
| 662 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
| 663 | if (IS_ERR(data->class_dev)) { | ||
| 664 | err = PTR_ERR(data->class_dev); | ||
| 665 | goto exit_remove_files; | ||
| 666 | } | ||
| 667 | |||
| 668 | return 0; | ||
| 669 | |||
| 670 | exit_remove_files: | ||
| 671 | sysfs_remove_group(&pdev->dev.kobj, &lm78_group); | ||
| 672 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
| 673 | kfree(data); | ||
| 674 | exit_release_region: | ||
| 675 | release_region(res->start, LM78_EXTENT); | ||
| 676 | exit: | ||
| 677 | return err; | ||
| 678 | } | ||
| 679 | |||
| 680 | static int __devexit lm78_isa_remove(struct platform_device *pdev) | ||
| 681 | { | ||
| 682 | struct lm78_data *data = platform_get_drvdata(pdev); | ||
| 698 | 683 | ||
| 684 | hwmon_device_unregister(data->class_dev); | ||
| 685 | sysfs_remove_group(&pdev->dev.kobj, &lm78_group); | ||
| 686 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
| 687 | release_region(data->client.addr, LM78_EXTENT); | ||
| 699 | kfree(data); | 688 | kfree(data); |
| 700 | 689 | ||
| 701 | return 0; | 690 | return 0; |
| @@ -706,11 +695,12 @@ static int lm78_detach_client(struct i2c_client *client) | |||
| 706 | separately. | 695 | separately. |
| 707 | We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks, | 696 | We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks, |
| 708 | would slow down the LM78 access and should not be necessary. */ | 697 | would slow down the LM78 access and should not be necessary. */ |
| 709 | static int lm78_read_value(struct i2c_client *client, u8 reg) | 698 | static int lm78_read_value(struct lm78_data *data, u8 reg) |
| 710 | { | 699 | { |
| 711 | int res; | 700 | struct i2c_client *client = &data->client; |
| 712 | if (i2c_is_isa_client(client)) { | 701 | |
| 713 | struct lm78_data *data = i2c_get_clientdata(client); | 702 | if (!client->driver) { /* ISA device */ |
| 703 | int res; | ||
| 714 | mutex_lock(&data->lock); | 704 | mutex_lock(&data->lock); |
| 715 | outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); | 705 | outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); |
| 716 | res = inb_p(client->addr + LM78_DATA_REG_OFFSET); | 706 | res = inb_p(client->addr + LM78_DATA_REG_OFFSET); |
| @@ -727,10 +717,11 @@ static int lm78_read_value(struct i2c_client *client, u8 reg) | |||
| 727 | would slow down the LM78 access and should not be necessary. | 717 | would slow down the LM78 access and should not be necessary. |
| 728 | There are some ugly typecasts here, but the good new is - they should | 718 | There are some ugly typecasts here, but the good new is - they should |
| 729 | nowhere else be necessary! */ | 719 | nowhere else be necessary! */ |
| 730 | static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value) | 720 | static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value) |
| 731 | { | 721 | { |
| 732 | if (i2c_is_isa_client(client)) { | 722 | struct i2c_client *client = &data->client; |
| 733 | struct lm78_data *data = i2c_get_clientdata(client); | 723 | |
| 724 | if (!client->driver) { /* ISA device */ | ||
| 734 | mutex_lock(&data->lock); | 725 | mutex_lock(&data->lock); |
| 735 | outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); | 726 | outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); |
| 736 | outb_p(value, client->addr + LM78_DATA_REG_OFFSET); | 727 | outb_p(value, client->addr + LM78_DATA_REG_OFFSET); |
| @@ -740,20 +731,29 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value) | |||
| 740 | return i2c_smbus_write_byte_data(client, reg, value); | 731 | return i2c_smbus_write_byte_data(client, reg, value); |
| 741 | } | 732 | } |
| 742 | 733 | ||
| 743 | static void lm78_init_client(struct i2c_client *client) | 734 | static void lm78_init_device(struct lm78_data *data) |
| 744 | { | 735 | { |
| 745 | u8 config = lm78_read_value(client, LM78_REG_CONFIG); | 736 | u8 config; |
| 737 | int i; | ||
| 746 | 738 | ||
| 747 | /* Start monitoring */ | 739 | /* Start monitoring */ |
| 748 | if (!(config & 0x01)) | 740 | config = lm78_read_value(data, LM78_REG_CONFIG); |
| 749 | lm78_write_value(client, LM78_REG_CONFIG, | 741 | if ((config & 0x09) != 0x01) |
| 742 | lm78_write_value(data, LM78_REG_CONFIG, | ||
| 750 | (config & 0xf7) | 0x01); | 743 | (config & 0xf7) | 0x01); |
| 744 | |||
| 745 | /* A few vars need to be filled upon startup */ | ||
| 746 | for (i = 0; i < 3; i++) { | ||
| 747 | data->fan_min[i] = lm78_read_value(data, | ||
| 748 | LM78_REG_FAN_MIN(i)); | ||
| 749 | } | ||
| 750 | |||
| 751 | mutex_init(&data->update_lock); | ||
| 751 | } | 752 | } |
| 752 | 753 | ||
| 753 | static struct lm78_data *lm78_update_device(struct device *dev) | 754 | static struct lm78_data *lm78_update_device(struct device *dev) |
| 754 | { | 755 | { |
| 755 | struct i2c_client *client = to_i2c_client(dev); | 756 | struct lm78_data *data = dev_get_drvdata(dev); |
| 756 | struct lm78_data *data = i2c_get_clientdata(client); | ||
| 757 | int i; | 757 | int i; |
| 758 | 758 | ||
| 759 | mutex_lock(&data->update_lock); | 759 | mutex_lock(&data->update_lock); |
| @@ -761,39 +761,39 @@ static struct lm78_data *lm78_update_device(struct device *dev) | |||
| 761 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 761 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) |
| 762 | || !data->valid) { | 762 | || !data->valid) { |
| 763 | 763 | ||
| 764 | dev_dbg(&client->dev, "Starting lm78 update\n"); | 764 | dev_dbg(dev, "Starting lm78 update\n"); |
| 765 | 765 | ||
| 766 | for (i = 0; i <= 6; i++) { | 766 | for (i = 0; i <= 6; i++) { |
| 767 | data->in[i] = | 767 | data->in[i] = |
| 768 | lm78_read_value(client, LM78_REG_IN(i)); | 768 | lm78_read_value(data, LM78_REG_IN(i)); |
| 769 | data->in_min[i] = | 769 | data->in_min[i] = |
| 770 | lm78_read_value(client, LM78_REG_IN_MIN(i)); | 770 | lm78_read_value(data, LM78_REG_IN_MIN(i)); |
| 771 | data->in_max[i] = | 771 | data->in_max[i] = |
| 772 | lm78_read_value(client, LM78_REG_IN_MAX(i)); | 772 | lm78_read_value(data, LM78_REG_IN_MAX(i)); |
| 773 | } | 773 | } |
| 774 | for (i = 0; i < 3; i++) { | 774 | for (i = 0; i < 3; i++) { |
| 775 | data->fan[i] = | 775 | data->fan[i] = |
| 776 | lm78_read_value(client, LM78_REG_FAN(i)); | 776 | lm78_read_value(data, LM78_REG_FAN(i)); |
| 777 | data->fan_min[i] = | 777 | data->fan_min[i] = |
| 778 | lm78_read_value(client, LM78_REG_FAN_MIN(i)); | 778 | lm78_read_value(data, LM78_REG_FAN_MIN(i)); |
| 779 | } | 779 | } |
| 780 | data->temp = lm78_read_value(client, LM78_REG_TEMP); | 780 | data->temp = lm78_read_value(data, LM78_REG_TEMP); |
| 781 | data->temp_over = | 781 | data->temp_over = |
| 782 | lm78_read_value(client, LM78_REG_TEMP_OVER); | 782 | lm78_read_value(data, LM78_REG_TEMP_OVER); |
| 783 | data->temp_hyst = | 783 | data->temp_hyst = |
| 784 | lm78_read_value(client, LM78_REG_TEMP_HYST); | 784 | lm78_read_value(data, LM78_REG_TEMP_HYST); |
| 785 | i = lm78_read_value(client, LM78_REG_VID_FANDIV); | 785 | i = lm78_read_value(data, LM78_REG_VID_FANDIV); |
| 786 | data->vid = i & 0x0f; | 786 | data->vid = i & 0x0f; |
| 787 | if (data->type == lm79) | 787 | if (data->type == lm79) |
| 788 | data->vid |= | 788 | data->vid |= |
| 789 | (lm78_read_value(client, LM78_REG_CHIPID) & | 789 | (lm78_read_value(data, LM78_REG_CHIPID) & |
| 790 | 0x01) << 4; | 790 | 0x01) << 4; |
| 791 | else | 791 | else |
| 792 | data->vid |= 0x10; | 792 | data->vid |= 0x10; |
| 793 | data->fan_div[0] = (i >> 4) & 0x03; | 793 | data->fan_div[0] = (i >> 4) & 0x03; |
| 794 | data->fan_div[1] = i >> 6; | 794 | data->fan_div[1] = i >> 6; |
| 795 | data->alarms = lm78_read_value(client, LM78_REG_ALARM1) + | 795 | data->alarms = lm78_read_value(data, LM78_REG_ALARM1) + |
| 796 | (lm78_read_value(client, LM78_REG_ALARM2) << 8); | 796 | (lm78_read_value(data, LM78_REG_ALARM2) << 8); |
| 797 | data->last_updated = jiffies; | 797 | data->last_updated = jiffies; |
| 798 | data->valid = 1; | 798 | data->valid = 1; |
| 799 | 799 | ||
| @@ -805,26 +805,154 @@ static struct lm78_data *lm78_update_device(struct device *dev) | |||
| 805 | return data; | 805 | return data; |
| 806 | } | 806 | } |
| 807 | 807 | ||
| 808 | /* return 1 if a supported chip is found, 0 otherwise */ | ||
| 809 | static int __init lm78_isa_found(unsigned short address) | ||
| 810 | { | ||
| 811 | int val, save, found = 0; | ||
| 812 | |||
| 813 | if (!request_region(address, LM78_EXTENT, "lm78")) | ||
| 814 | return 0; | ||
| 815 | |||
| 816 | #define REALLY_SLOW_IO | ||
| 817 | /* We need the timeouts for at least some LM78-like | ||
| 818 | chips. But only if we read 'undefined' registers. */ | ||
| 819 | val = inb_p(address + 1); | ||
| 820 | if (inb_p(address + 2) != val | ||
| 821 | || inb_p(address + 3) != val | ||
| 822 | || inb_p(address + 7) != val) | ||
| 823 | goto release; | ||
| 824 | #undef REALLY_SLOW_IO | ||
| 825 | |||
| 826 | /* We should be able to change the 7 LSB of the address port. The | ||
| 827 | MSB (busy flag) should be clear initially, set after the write. */ | ||
| 828 | save = inb_p(address + LM78_ADDR_REG_OFFSET); | ||
| 829 | if (save & 0x80) | ||
| 830 | goto release; | ||
| 831 | val = ~save & 0x7f; | ||
| 832 | outb_p(val, address + LM78_ADDR_REG_OFFSET); | ||
| 833 | if (inb_p(address + LM78_ADDR_REG_OFFSET) != (val | 0x80)) { | ||
| 834 | outb_p(save, address + LM78_ADDR_REG_OFFSET); | ||
| 835 | goto release; | ||
| 836 | } | ||
| 837 | |||
| 838 | /* We found a device, now see if it could be an LM78 */ | ||
| 839 | outb_p(LM78_REG_CONFIG, address + LM78_ADDR_REG_OFFSET); | ||
| 840 | val = inb_p(address + LM78_DATA_REG_OFFSET); | ||
| 841 | if (val & 0x80) | ||
| 842 | goto release; | ||
| 843 | outb_p(LM78_REG_I2C_ADDR, address + LM78_ADDR_REG_OFFSET); | ||
| 844 | val = inb_p(address + LM78_DATA_REG_OFFSET); | ||
| 845 | if (val < 0x03 || val > 0x77) /* Not a valid I2C address */ | ||
| 846 | goto release; | ||
| 847 | |||
| 848 | /* The busy flag should be clear again */ | ||
| 849 | if (inb_p(address + LM78_ADDR_REG_OFFSET) & 0x80) | ||
| 850 | goto release; | ||
| 851 | |||
| 852 | /* Explicitly prevent the misdetection of Winbond chips */ | ||
| 853 | outb_p(0x4f, address + LM78_ADDR_REG_OFFSET); | ||
| 854 | val = inb_p(address + LM78_DATA_REG_OFFSET); | ||
| 855 | if (val == 0xa3 || val == 0x5c) | ||
| 856 | goto release; | ||
| 857 | |||
| 858 | /* Explicitly prevent the misdetection of ITE chips */ | ||
| 859 | outb_p(0x58, address + LM78_ADDR_REG_OFFSET); | ||
| 860 | val = inb_p(address + LM78_DATA_REG_OFFSET); | ||
| 861 | if (val == 0x90) | ||
| 862 | goto release; | ||
| 863 | |||
| 864 | /* Determine the chip type */ | ||
| 865 | outb_p(LM78_REG_CHIPID, address + LM78_ADDR_REG_OFFSET); | ||
| 866 | val = inb_p(address + LM78_DATA_REG_OFFSET); | ||
| 867 | if (val == 0x00 /* LM78 */ | ||
| 868 | || val == 0x40 /* LM78-J */ | ||
| 869 | || (val & 0xfe) == 0xc0) /* LM79 */ | ||
| 870 | found = 1; | ||
| 871 | |||
| 872 | if (found) | ||
| 873 | pr_info("lm78: Found an %s chip at %#x\n", | ||
| 874 | val & 0x80 ? "LM79" : "LM78", (int)address); | ||
| 875 | |||
| 876 | release: | ||
| 877 | release_region(address, LM78_EXTENT); | ||
| 878 | return found; | ||
| 879 | } | ||
| 880 | |||
| 881 | static int __init lm78_isa_device_add(unsigned short address) | ||
| 882 | { | ||
| 883 | struct resource res = { | ||
| 884 | .start = address, | ||
| 885 | .end = address + LM78_EXTENT, | ||
| 886 | .name = "lm78", | ||
| 887 | .flags = IORESOURCE_IO, | ||
| 888 | }; | ||
| 889 | int err; | ||
| 890 | |||
| 891 | pdev = platform_device_alloc("lm78", address); | ||
| 892 | if (!pdev) { | ||
| 893 | err = -ENOMEM; | ||
| 894 | printk(KERN_ERR "lm78: Device allocation failed\n"); | ||
| 895 | goto exit; | ||
| 896 | } | ||
| 897 | |||
| 898 | err = platform_device_add_resources(pdev, &res, 1); | ||
| 899 | if (err) { | ||
| 900 | printk(KERN_ERR "lm78: Device resource addition failed " | ||
| 901 | "(%d)\n", err); | ||
| 902 | goto exit_device_put; | ||
| 903 | } | ||
| 904 | |||
| 905 | err = platform_device_add(pdev); | ||
| 906 | if (err) { | ||
| 907 | printk(KERN_ERR "lm78: Device addition failed (%d)\n", | ||
| 908 | err); | ||
| 909 | goto exit_device_put; | ||
| 910 | } | ||
| 911 | |||
| 912 | return 0; | ||
| 913 | |||
| 914 | exit_device_put: | ||
| 915 | platform_device_put(pdev); | ||
| 916 | exit: | ||
| 917 | pdev = NULL; | ||
| 918 | return err; | ||
| 919 | } | ||
| 920 | |||
| 808 | static int __init sm_lm78_init(void) | 921 | static int __init sm_lm78_init(void) |
| 809 | { | 922 | { |
| 810 | int res; | 923 | int res; |
| 811 | 924 | ||
| 812 | res = i2c_add_driver(&lm78_driver); | 925 | res = i2c_add_driver(&lm78_driver); |
| 813 | if (res) | 926 | if (res) |
| 814 | return res; | 927 | goto exit; |
| 815 | 928 | ||
| 816 | /* Don't exit if this one fails, we still want the I2C variants | 929 | if (lm78_isa_found(isa_address)) { |
| 817 | to work! */ | 930 | res = platform_driver_register(&lm78_isa_driver); |
| 818 | if (i2c_isa_add_driver(&lm78_isa_driver)) | 931 | if (res) |
| 819 | isa_address = 0; | 932 | goto exit_unreg_i2c_driver; |
| 933 | |||
| 934 | /* Sets global pdev as a side effect */ | ||
| 935 | res = lm78_isa_device_add(isa_address); | ||
| 936 | if (res) | ||
| 937 | goto exit_unreg_isa_driver; | ||
| 938 | } | ||
| 820 | 939 | ||
| 821 | return 0; | 940 | return 0; |
| 941 | |||
| 942 | exit_unreg_isa_driver: | ||
| 943 | platform_driver_unregister(&lm78_isa_driver); | ||
| 944 | exit_unreg_i2c_driver: | ||
| 945 | i2c_del_driver(&lm78_driver); | ||
| 946 | exit: | ||
| 947 | return res; | ||
| 822 | } | 948 | } |
| 823 | 949 | ||
| 824 | static void __exit sm_lm78_exit(void) | 950 | static void __exit sm_lm78_exit(void) |
| 825 | { | 951 | { |
| 826 | if (isa_address) | 952 | if (pdev) { |
| 827 | i2c_isa_del_driver(&lm78_isa_driver); | 953 | platform_device_unregister(pdev); |
| 954 | platform_driver_unregister(&lm78_isa_driver); | ||
| 955 | } | ||
| 828 | i2c_del_driver(&lm78_driver); | 956 | i2c_del_driver(&lm78_driver); |
| 829 | } | 957 | } |
| 830 | 958 | ||
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 3ce825489e34..988ae1c4aada 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c | |||
| @@ -747,6 +747,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 747 | } | 747 | } |
| 748 | 748 | ||
| 749 | if (!(data->channel & CHAN_NO_VID)) { | 749 | if (!(data->channel & CHAN_NO_VID)) { |
| 750 | data->vrm = vid_which_vrm(); | ||
| 750 | if ((err = device_create_file(&new_client->dev, | 751 | if ((err = device_create_file(&new_client->dev, |
| 751 | &dev_attr_cpu0_vid)) | 752 | &dev_attr_cpu0_vid)) |
| 752 | || (err = device_create_file(&new_client->dev, | 753 | || (err = device_create_file(&new_client->dev, |
| @@ -779,7 +780,6 @@ static void lm87_init_client(struct i2c_client *client) | |||
| 779 | u8 config; | 780 | u8 config; |
| 780 | 781 | ||
| 781 | data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE); | 782 | data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE); |
| 782 | data->vrm = vid_which_vrm(); | ||
| 783 | 783 | ||
| 784 | config = lm87_read_value(client, LM87_REG_CONFIG); | 784 | config = lm87_read_value(client, LM87_REG_CONFIG); |
| 785 | if (!(config & 0x01)) { | 785 | if (!(config & 0x01)) { |
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c new file mode 100644 index 000000000000..8415664f33c2 --- /dev/null +++ b/drivers/hwmon/max6650.c | |||
| @@ -0,0 +1,693 @@ | |||
| 1 | /* | ||
| 2 | * max6650.c - Part of lm_sensors, Linux kernel modules for hardware | ||
| 3 | * monitoring. | ||
| 4 | * | ||
| 5 | * (C) 2007 by Hans J. Koch <hjk@linutronix.de> | ||
| 6 | * | ||
| 7 | * based on code written by John Morris <john.morris@spirentcom.com> | ||
| 8 | * Copyright (c) 2003 Spirent Communications | ||
| 9 | * and Claus Gindhart <claus.gindhart@kontron.com> | ||
| 10 | * | ||
| 11 | * This module has only been tested with the MAX6650 chip. It should | ||
| 12 | * also work with the MAX6651. It does not distinguish max6650 and max6651 | ||
| 13 | * chips. | ||
| 14 | * | ||
| 15 | * Tha datasheet was last seen at: | ||
| 16 | * | ||
| 17 | * http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf | ||
| 18 | * | ||
| 19 | * This program is free software; you can redistribute it and/or modify | ||
| 20 | * it under the terms of the GNU General Public License as published by | ||
| 21 | * the Free Software Foundation; either version 2 of the License, or | ||
| 22 | * (at your option) any later version. | ||
| 23 | * | ||
| 24 | * This program is distributed in the hope that it will be useful, | ||
| 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 27 | * GNU General Public License for more details. | ||
| 28 | * | ||
| 29 | * You should have received a copy of the GNU General Public License | ||
| 30 | * along with this program; if not, write to the Free Software | ||
| 31 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include <linux/module.h> | ||
| 35 | #include <linux/init.h> | ||
| 36 | #include <linux/slab.h> | ||
| 37 | #include <linux/jiffies.h> | ||
| 38 | #include <linux/i2c.h> | ||
| 39 | #include <linux/hwmon.h> | ||
| 40 | #include <linux/hwmon-sysfs.h> | ||
| 41 | #include <linux/err.h> | ||
| 42 | |||
| 43 | /* | ||
| 44 | * Addresses to scan. There are four disjoint possibilities, by pin config. | ||
| 45 | */ | ||
| 46 | |||
| 47 | static unsigned short normal_i2c[] = {0x1b, 0x1f, 0x48, 0x4b, I2C_CLIENT_END}; | ||
| 48 | |||
| 49 | /* | ||
| 50 | * Insmod parameters | ||
| 51 | */ | ||
| 52 | |||
| 53 | /* fan_voltage: 5=5V fan, 12=12V fan, 0=don't change */ | ||
| 54 | static int fan_voltage; | ||
| 55 | /* prescaler: Possible values are 1, 2, 4, 8, 16 or 0 for don't change */ | ||
| 56 | static int prescaler; | ||
| 57 | /* clock: The clock frequency of the chip the driver should assume */ | ||
| 58 | static int clock = 254000; | ||
| 59 | |||
| 60 | module_param(fan_voltage, int, S_IRUGO); | ||
| 61 | module_param(prescaler, int, S_IRUGO); | ||
| 62 | module_param(clock, int, S_IRUGO); | ||
| 63 | |||
| 64 | I2C_CLIENT_INSMOD_1(max6650); | ||
| 65 | |||
| 66 | /* | ||
| 67 | * MAX 6650/6651 registers | ||
| 68 | */ | ||
| 69 | |||
| 70 | #define MAX6650_REG_SPEED 0x00 | ||
| 71 | #define MAX6650_REG_CONFIG 0x02 | ||
| 72 | #define MAX6650_REG_GPIO_DEF 0x04 | ||
| 73 | #define MAX6650_REG_DAC 0x06 | ||
| 74 | #define MAX6650_REG_ALARM_EN 0x08 | ||
| 75 | #define MAX6650_REG_ALARM 0x0A | ||
| 76 | #define MAX6650_REG_TACH0 0x0C | ||
| 77 | #define MAX6650_REG_TACH1 0x0E | ||
| 78 | #define MAX6650_REG_TACH2 0x10 | ||
| 79 | #define MAX6650_REG_TACH3 0x12 | ||
| 80 | #define MAX6650_REG_GPIO_STAT 0x14 | ||
| 81 | #define MAX6650_REG_COUNT 0x16 | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Config register bits | ||
| 85 | */ | ||
| 86 | |||
| 87 | #define MAX6650_CFG_V12 0x08 | ||
| 88 | #define MAX6650_CFG_PRESCALER_MASK 0x07 | ||
| 89 | #define MAX6650_CFG_PRESCALER_2 0x01 | ||
| 90 | #define MAX6650_CFG_PRESCALER_4 0x02 | ||
| 91 | #define MAX6650_CFG_PRESCALER_8 0x03 | ||
| 92 | #define MAX6650_CFG_PRESCALER_16 0x04 | ||
| 93 | #define MAX6650_CFG_MODE_MASK 0x30 | ||
| 94 | #define MAX6650_CFG_MODE_ON 0x00 | ||
| 95 | #define MAX6650_CFG_MODE_OFF 0x10 | ||
| 96 | #define MAX6650_CFG_MODE_CLOSED_LOOP 0x20 | ||
| 97 | #define MAX6650_CFG_MODE_OPEN_LOOP 0x30 | ||
| 98 | #define MAX6650_COUNT_MASK 0x03 | ||
| 99 | |||
| 100 | /* Minimum and maximum values of the FAN-RPM */ | ||
| 101 | #define FAN_RPM_MIN 240 | ||
| 102 | #define FAN_RPM_MAX 30000 | ||
| 103 | |||
| 104 | #define DIV_FROM_REG(reg) (1 << (reg & 7)) | ||
| 105 | |||
| 106 | static int max6650_attach_adapter(struct i2c_adapter *adapter); | ||
| 107 | static int max6650_detect(struct i2c_adapter *adapter, int address, int kind); | ||
| 108 | static int max6650_init_client(struct i2c_client *client); | ||
| 109 | static int max6650_detach_client(struct i2c_client *client); | ||
| 110 | static struct max6650_data *max6650_update_device(struct device *dev); | ||
| 111 | |||
| 112 | /* | ||
| 113 | * Driver data (common to all clients) | ||
| 114 | */ | ||
| 115 | |||
| 116 | static struct i2c_driver max6650_driver = { | ||
| 117 | .driver = { | ||
| 118 | .name = "max6650", | ||
| 119 | }, | ||
| 120 | .attach_adapter = max6650_attach_adapter, | ||
| 121 | .detach_client = max6650_detach_client, | ||
| 122 | }; | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Client data (each client gets its own) | ||
| 126 | */ | ||
| 127 | |||
| 128 | struct max6650_data | ||
| 129 | { | ||
| 130 | struct i2c_client client; | ||
| 131 | struct class_device *class_dev; | ||
| 132 | struct mutex update_lock; | ||
| 133 | char valid; /* zero until following fields are valid */ | ||
| 134 | unsigned long last_updated; /* in jiffies */ | ||
| 135 | |||
| 136 | /* register values */ | ||
| 137 | u8 speed; | ||
| 138 | u8 config; | ||
| 139 | u8 tach[4]; | ||
| 140 | u8 count; | ||
| 141 | u8 dac; | ||
| 142 | }; | ||
| 143 | |||
| 144 | static ssize_t get_fan(struct device *dev, struct device_attribute *devattr, | ||
| 145 | char *buf) | ||
| 146 | { | ||
| 147 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 148 | struct max6650_data *data = max6650_update_device(dev); | ||
| 149 | int rpm; | ||
| 150 | |||
| 151 | /* | ||
| 152 | * Calculation details: | ||
| 153 | * | ||
| 154 | * Each tachometer counts over an interval given by the "count" | ||
| 155 | * register (0.25, 0.5, 1 or 2 seconds). This module assumes | ||
| 156 | * that the fans produce two pulses per revolution (this seems | ||
| 157 | * to be the most common). | ||
| 158 | */ | ||
| 159 | |||
| 160 | rpm = ((data->tach[attr->index] * 120) / DIV_FROM_REG(data->count)); | ||
| 161 | return sprintf(buf, "%d\n", rpm); | ||
| 162 | } | ||
| 163 | |||
| 164 | /* | ||
| 165 | * Set the fan speed to the specified RPM (or read back the RPM setting). | ||
| 166 | * This works in closed loop mode only. Use pwm1 for open loop speed setting. | ||
| 167 | * | ||
| 168 | * The MAX6650/1 will automatically control fan speed when in closed loop | ||
| 169 | * mode. | ||
| 170 | * | ||
| 171 | * Assumptions: | ||
| 172 | * | ||
| 173 | * 1) The MAX6650/1 internal 254kHz clock frequency is set correctly. Use | ||
| 174 | * the clock module parameter if you need to fine tune this. | ||
| 175 | * | ||
| 176 | * 2) The prescaler (low three bits of the config register) has already | ||
| 177 | * been set to an appropriate value. Use the prescaler module parameter | ||
| 178 | * if your BIOS doesn't initialize the chip properly. | ||
| 179 | * | ||
| 180 | * The relevant equations are given on pages 21 and 22 of the datasheet. | ||
| 181 | * | ||
| 182 | * From the datasheet, the relevant equation when in regulation is: | ||
| 183 | * | ||
| 184 | * [fCLK / (128 x (KTACH + 1))] = 2 x FanSpeed / KSCALE | ||
| 185 | * | ||
| 186 | * where: | ||
| 187 | * | ||
| 188 | * fCLK is the oscillator frequency (either the 254kHz internal | ||
| 189 | * oscillator or the externally applied clock) | ||
| 190 | * | ||
| 191 | * KTACH is the value in the speed register | ||
| 192 | * | ||
| 193 | * FanSpeed is the speed of the fan in rps | ||
| 194 | * | ||
| 195 | * KSCALE is the prescaler value (1, 2, 4, 8, or 16) | ||
| 196 | * | ||
| 197 | * When reading, we need to solve for FanSpeed. When writing, we need to | ||
| 198 | * solve for KTACH. | ||
| 199 | * | ||
| 200 | * Note: this tachometer is completely separate from the tachometers | ||
| 201 | * used to measure the fan speeds. Only one fan's speed (fan1) is | ||
| 202 | * controlled. | ||
| 203 | */ | ||
| 204 | |||
| 205 | static ssize_t get_target(struct device *dev, struct device_attribute *devattr, | ||
| 206 | char *buf) | ||
| 207 | { | ||
| 208 | struct max6650_data *data = max6650_update_device(dev); | ||
| 209 | int kscale, ktach, rpm; | ||
| 210 | |||
| 211 | /* | ||
| 212 | * Use the datasheet equation: | ||
| 213 | * | ||
| 214 | * FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)] | ||
| 215 | * | ||
| 216 | * then multiply by 60 to give rpm. | ||
| 217 | */ | ||
| 218 | |||
| 219 | kscale = DIV_FROM_REG(data->config); | ||
| 220 | ktach = data->speed; | ||
| 221 | rpm = 60 * kscale * clock / (256 * (ktach + 1)); | ||
| 222 | return sprintf(buf, "%d\n", rpm); | ||
| 223 | } | ||
| 224 | |||
| 225 | static ssize_t set_target(struct device *dev, struct device_attribute *devattr, | ||
| 226 | const char *buf, size_t count) | ||
| 227 | { | ||
| 228 | struct i2c_client *client = to_i2c_client(dev); | ||
| 229 | struct max6650_data *data = i2c_get_clientdata(client); | ||
| 230 | int rpm = simple_strtoul(buf, NULL, 10); | ||
| 231 | int kscale, ktach; | ||
| 232 | |||
| 233 | rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX); | ||
| 234 | |||
| 235 | /* | ||
| 236 | * Divide the required speed by 60 to get from rpm to rps, then | ||
| 237 | * use the datasheet equation: | ||
| 238 | * | ||
| 239 | * KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1 | ||
| 240 | */ | ||
| 241 | |||
| 242 | mutex_lock(&data->update_lock); | ||
| 243 | |||
| 244 | kscale = DIV_FROM_REG(data->config); | ||
| 245 | ktach = ((clock * kscale) / (256 * rpm / 60)) - 1; | ||
| 246 | if (ktach < 0) | ||
| 247 | ktach = 0; | ||
| 248 | if (ktach > 255) | ||
| 249 | ktach = 255; | ||
| 250 | data->speed = ktach; | ||
| 251 | |||
| 252 | i2c_smbus_write_byte_data(client, MAX6650_REG_SPEED, data->speed); | ||
| 253 | |||
| 254 | mutex_unlock(&data->update_lock); | ||
| 255 | |||
| 256 | return count; | ||
| 257 | } | ||
| 258 | |||
| 259 | /* | ||
| 260 | * Get/set the fan speed in open loop mode using pwm1 sysfs file. | ||
| 261 | * Speed is given as a relative value from 0 to 255, where 255 is maximum | ||
| 262 | * speed. Note that this is done by writing directly to the chip's DAC, | ||
| 263 | * it won't change the closed loop speed set by fan1_target. | ||
| 264 | * Also note that due to rounding errors it is possible that you don't read | ||
| 265 | * back exactly the value you have set. | ||
| 266 | */ | ||
| 267 | |||
| 268 | static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr, | ||
| 269 | char *buf) | ||
| 270 | { | ||
| 271 | int pwm; | ||
| 272 | struct max6650_data *data = max6650_update_device(dev); | ||
| 273 | |||
| 274 | /* Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans. | ||
| 275 | Lower DAC values mean higher speeds. */ | ||
| 276 | if (data->config & MAX6650_CFG_V12) | ||
| 277 | pwm = 255 - (255 * (int)data->dac)/180; | ||
| 278 | else | ||
| 279 | pwm = 255 - (255 * (int)data->dac)/76; | ||
| 280 | |||
| 281 | if (pwm < 0) | ||
| 282 | pwm = 0; | ||
| 283 | |||
| 284 | return sprintf(buf, "%d\n", pwm); | ||
| 285 | } | ||
| 286 | |||
| 287 | static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | ||
| 288 | const char *buf, size_t count) | ||
| 289 | { | ||
| 290 | struct i2c_client *client = to_i2c_client(dev); | ||
| 291 | struct max6650_data *data = i2c_get_clientdata(client); | ||
| 292 | int pwm = simple_strtoul(buf, NULL, 10); | ||
| 293 | |||
| 294 | pwm = SENSORS_LIMIT(pwm, 0, 255); | ||
| 295 | |||
| 296 | mutex_lock(&data->update_lock); | ||
| 297 | |||
| 298 | if (data->config & MAX6650_CFG_V12) | ||
| 299 | data->dac = 180 - (180 * pwm)/255; | ||
| 300 | else | ||
| 301 | data->dac = 76 - (76 * pwm)/255; | ||
| 302 | |||
| 303 | i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, data->dac); | ||
| 304 | |||
| 305 | mutex_unlock(&data->update_lock); | ||
| 306 | |||
| 307 | return count; | ||
| 308 | } | ||
| 309 | |||
| 310 | /* | ||
| 311 | * Get/Set controller mode: | ||
| 312 | * Possible values: | ||
| 313 | * 0 = Fan always on | ||
| 314 | * 1 = Open loop, Voltage is set according to speed, not regulated. | ||
| 315 | * 2 = Closed loop, RPM for all fans regulated by fan1 tachometer | ||
| 316 | */ | ||
| 317 | |||
| 318 | static ssize_t get_enable(struct device *dev, struct device_attribute *devattr, | ||
| 319 | char *buf) | ||
| 320 | { | ||
| 321 | struct max6650_data *data = max6650_update_device(dev); | ||
| 322 | int mode = (data->config & MAX6650_CFG_MODE_MASK) >> 4; | ||
| 323 | int sysfs_modes[4] = {0, 1, 2, 1}; | ||
| 324 | |||
| 325 | return sprintf(buf, "%d\n", sysfs_modes[mode]); | ||
| 326 | } | ||
| 327 | |||
| 328 | static ssize_t set_enable(struct device *dev, struct device_attribute *devattr, | ||
| 329 | const char *buf, size_t count) | ||
| 330 | { | ||
| 331 | struct i2c_client *client = to_i2c_client(dev); | ||
| 332 | struct max6650_data *data = i2c_get_clientdata(client); | ||
| 333 | int mode = simple_strtoul(buf, NULL, 10); | ||
| 334 | int max6650_modes[3] = {0, 3, 2}; | ||
| 335 | |||
| 336 | if ((mode < 0)||(mode > 2)) { | ||
| 337 | dev_err(&client->dev, | ||
| 338 | "illegal value for pwm1_enable (%d)\n", mode); | ||
| 339 | return -EINVAL; | ||
| 340 | } | ||
| 341 | |||
| 342 | mutex_lock(&data->update_lock); | ||
| 343 | |||
| 344 | data->config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG); | ||
| 345 | data->config = (data->config & ~MAX6650_CFG_MODE_MASK) | ||
| 346 | | (max6650_modes[mode] << 4); | ||
| 347 | |||
| 348 | i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, data->config); | ||
| 349 | |||
| 350 | mutex_unlock(&data->update_lock); | ||
| 351 | |||
| 352 | return count; | ||
| 353 | } | ||
| 354 | |||
| 355 | /* | ||
| 356 | * Read/write functions for fan1_div sysfs file. The MAX6650 has no such | ||
| 357 | * divider. We handle this by converting between divider and counttime: | ||
| 358 | * | ||
| 359 | * (counttime == k) <==> (divider == 2^k), k = 0, 1, 2, or 3 | ||
| 360 | * | ||
| 361 | * Lower values of k allow to connect a faster fan without the risk of | ||
| 362 | * counter overflow. The price is lower resolution. You can also set counttime | ||
| 363 | * using the module parameter. Note that the module parameter "prescaler" also | ||
| 364 | * influences the behaviour. Unfortunately, there's no sysfs attribute | ||
| 365 | * defined for that. See the data sheet for details. | ||
| 366 | */ | ||
| 367 | |||
| 368 | static ssize_t get_div(struct device *dev, struct device_attribute *devattr, | ||
| 369 | char *buf) | ||
| 370 | { | ||
| 371 | struct max6650_data *data = max6650_update_device(dev); | ||
| 372 | |||
| 373 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->count)); | ||
| 374 | } | ||
| 375 | |||
| 376 | static ssize_t set_div(struct device *dev, struct device_attribute *devattr, | ||
| 377 | const char *buf, size_t count) | ||
| 378 | { | ||
| 379 | struct i2c_client *client = to_i2c_client(dev); | ||
| 380 | struct max6650_data *data = i2c_get_clientdata(client); | ||
| 381 | int div = simple_strtoul(buf, NULL, 10); | ||
| 382 | |||
| 383 | mutex_lock(&data->update_lock); | ||
| 384 | switch (div) { | ||
| 385 | case 1: | ||
| 386 | data->count = 0; | ||
| 387 | break; | ||
| 388 | case 2: | ||
| 389 | data->count = 1; | ||
| 390 | break; | ||
| 391 | case 4: | ||
| 392 | data->count = 2; | ||
| 393 | break; | ||
| 394 | case 8: | ||
| 395 | data->count = 3; | ||
| 396 | break; | ||
| 397 | default: | ||
| 398 | dev_err(&client->dev, | ||
| 399 | "illegal value for fan divider (%d)\n", div); | ||
| 400 | return -EINVAL; | ||
| 401 | } | ||
| 402 | |||
| 403 | i2c_smbus_write_byte_data(client, MAX6650_REG_COUNT, data->count); | ||
| 404 | mutex_unlock(&data->update_lock); | ||
| 405 | |||
| 406 | return count; | ||
| 407 | } | ||
| 408 | |||
| 409 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0); | ||
| 410 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1); | ||
| 411 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2); | ||
| 412 | static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, get_fan, NULL, 3); | ||
| 413 | static DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, get_target, set_target); | ||
| 414 | static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, get_div, set_div); | ||
| 415 | static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, get_enable, set_enable); | ||
| 416 | static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm); | ||
| 417 | |||
| 418 | |||
| 419 | static struct attribute *max6650_attrs[] = { | ||
| 420 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
| 421 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
| 422 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
| 423 | &sensor_dev_attr_fan4_input.dev_attr.attr, | ||
| 424 | &dev_attr_fan1_target.attr, | ||
| 425 | &dev_attr_fan1_div.attr, | ||
| 426 | &dev_attr_pwm1_enable.attr, | ||
| 427 | &dev_attr_pwm1.attr, | ||
| 428 | NULL | ||
| 429 | }; | ||
| 430 | |||
| 431 | static struct attribute_group max6650_attr_grp = { | ||
| 432 | .attrs = max6650_attrs, | ||
| 433 | }; | ||
| 434 | |||
| 435 | /* | ||
| 436 | * Real code | ||
| 437 | */ | ||
| 438 | |||
| 439 | static int max6650_attach_adapter(struct i2c_adapter *adapter) | ||
| 440 | { | ||
| 441 | if (!(adapter->class & I2C_CLASS_HWMON)) { | ||
| 442 | dev_dbg(&adapter->dev, | ||
| 443 | "FATAL: max6650_attach_adapter class HWMON not set\n"); | ||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | |||
| 447 | return i2c_probe(adapter, &addr_data, max6650_detect); | ||
| 448 | } | ||
| 449 | |||
| 450 | /* | ||
| 451 | * The following function does more than just detection. If detection | ||
| 452 | * succeeds, it also registers the new chip. | ||
| 453 | */ | ||
| 454 | |||
| 455 | static int max6650_detect(struct i2c_adapter *adapter, int address, int kind) | ||
| 456 | { | ||
| 457 | struct i2c_client *client; | ||
| 458 | struct max6650_data *data; | ||
| 459 | int err = -ENODEV; | ||
| 460 | |||
| 461 | dev_dbg(&adapter->dev, "max6650_detect called, kind = %d\n", kind); | ||
| 462 | |||
| 463 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
| 464 | dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support " | ||
| 465 | "byte read mode, skipping.\n"); | ||
| 466 | return 0; | ||
| 467 | } | ||
| 468 | |||
| 469 | if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) { | ||
| 470 | dev_err(&adapter->dev, "max6650: out of memory.\n"); | ||
| 471 | return -ENOMEM; | ||
| 472 | } | ||
| 473 | |||
| 474 | client = &data->client; | ||
| 475 | i2c_set_clientdata(client, data); | ||
| 476 | client->addr = address; | ||
| 477 | client->adapter = adapter; | ||
| 478 | client->driver = &max6650_driver; | ||
| 479 | |||
| 480 | /* | ||
| 481 | * Now we do the remaining detection. A negative kind means that | ||
| 482 | * the driver was loaded with no force parameter (default), so we | ||
| 483 | * must both detect and identify the chip (actually there is only | ||
| 484 | * one possible kind of chip for now, max6650). A zero kind means that | ||
| 485 | * the driver was loaded with the force parameter, the detection | ||
| 486 | * step shall be skipped. A positive kind means that the driver | ||
| 487 | * was loaded with the force parameter and a given kind of chip is | ||
| 488 | * requested, so both the detection and the identification steps | ||
| 489 | * are skipped. | ||
| 490 | * | ||
| 491 | * Currently I can find no way to distinguish between a MAX6650 and | ||
| 492 | * a MAX6651. This driver has only been tried on the former. | ||
| 493 | */ | ||
| 494 | |||
| 495 | if ((kind < 0) && | ||
| 496 | ( (i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG) & 0xC0) | ||
| 497 | ||(i2c_smbus_read_byte_data(client, MAX6650_REG_GPIO_STAT) & 0xE0) | ||
| 498 | ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN) & 0xE0) | ||
| 499 | ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM) & 0xE0) | ||
| 500 | ||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) { | ||
| 501 | dev_dbg(&adapter->dev, | ||
| 502 | "max6650: detection failed at 0x%02x.\n", address); | ||
| 503 | goto err_free; | ||
| 504 | } | ||
| 505 | |||
| 506 | dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address); | ||
| 507 | |||
| 508 | strlcpy(client->name, "max6650", I2C_NAME_SIZE); | ||
| 509 | mutex_init(&data->update_lock); | ||
| 510 | |||
| 511 | if ((err = i2c_attach_client(client))) { | ||
| 512 | dev_err(&adapter->dev, "max6650: failed to attach client.\n"); | ||
| 513 | goto err_free; | ||
| 514 | } | ||
| 515 | |||
| 516 | /* | ||
| 517 | * Initialize the max6650 chip | ||
| 518 | */ | ||
| 519 | if (max6650_init_client(client)) | ||
| 520 | goto err_detach; | ||
| 521 | |||
| 522 | err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp); | ||
| 523 | if (err) | ||
| 524 | goto err_detach; | ||
| 525 | |||
| 526 | data->class_dev = hwmon_device_register(&client->dev); | ||
| 527 | if (!IS_ERR(data->class_dev)) | ||
| 528 | return 0; | ||
| 529 | |||
| 530 | err = PTR_ERR(data->class_dev); | ||
| 531 | dev_err(&client->dev, "error registering hwmon device.\n"); | ||
| 532 | sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); | ||
| 533 | err_detach: | ||
| 534 | i2c_detach_client(client); | ||
| 535 | err_free: | ||
| 536 | kfree(data); | ||
| 537 | return err; | ||
| 538 | } | ||
| 539 | |||
| 540 | static int max6650_detach_client(struct i2c_client *client) | ||
| 541 | { | ||
| 542 | struct max6650_data *data = i2c_get_clientdata(client); | ||
| 543 | int err; | ||
| 544 | |||
| 545 | sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); | ||
| 546 | hwmon_device_unregister(data->class_dev); | ||
| 547 | err = i2c_detach_client(client); | ||
| 548 | if (!err) | ||
| 549 | kfree(data); | ||
| 550 | return err; | ||
| 551 | } | ||
| 552 | |||
| 553 | static int max6650_init_client(struct i2c_client *client) | ||
| 554 | { | ||
| 555 | struct max6650_data *data = i2c_get_clientdata(client); | ||
| 556 | int config; | ||
| 557 | int err = -EIO; | ||
| 558 | |||
| 559 | config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG); | ||
| 560 | |||
| 561 | if (config < 0) { | ||
| 562 | dev_err(&client->dev, "Error reading config, aborting.\n"); | ||
| 563 | return err; | ||
| 564 | } | ||
| 565 | |||
| 566 | switch (fan_voltage) { | ||
| 567 | case 0: | ||
| 568 | break; | ||
| 569 | case 5: | ||
| 570 | config &= ~MAX6650_CFG_V12; | ||
| 571 | break; | ||
| 572 | case 12: | ||
| 573 | config |= MAX6650_CFG_V12; | ||
| 574 | break; | ||
| 575 | default: | ||
| 576 | dev_err(&client->dev, | ||
| 577 | "illegal value for fan_voltage (%d)\n", | ||
| 578 | fan_voltage); | ||
| 579 | } | ||
| 580 | |||
| 581 | dev_info(&client->dev, "Fan voltage is set to %dV.\n", | ||
| 582 | (config & MAX6650_CFG_V12) ? 12 : 5); | ||
| 583 | |||
| 584 | switch (prescaler) { | ||
| 585 | case 0: | ||
| 586 | break; | ||
| 587 | case 1: | ||
| 588 | config &= ~MAX6650_CFG_PRESCALER_MASK; | ||
| 589 | break; | ||
| 590 | case 2: | ||
| 591 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | ||
| 592 | | MAX6650_CFG_PRESCALER_2; | ||
| 593 | break; | ||
| 594 | case 4: | ||
| 595 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | ||
| 596 | | MAX6650_CFG_PRESCALER_4; | ||
| 597 | break; | ||
| 598 | case 8: | ||
| 599 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | ||
| 600 | | MAX6650_CFG_PRESCALER_8; | ||
| 601 | break; | ||
| 602 | case 16: | ||
| 603 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | ||
| 604 | | MAX6650_CFG_PRESCALER_16; | ||
| 605 | break; | ||
| 606 | default: | ||
| 607 | dev_err(&client->dev, | ||
| 608 | "illegal value for prescaler (%d)\n", | ||
| 609 | prescaler); | ||
| 610 | } | ||
| 611 | |||
| 612 | dev_info(&client->dev, "Prescaler is set to %d.\n", | ||
| 613 | 1 << (config & MAX6650_CFG_PRESCALER_MASK)); | ||
| 614 | |||
| 615 | /* If mode is set to "full off", we change it to "open loop" and | ||
| 616 | * set DAC to 255, which has the same effect. We do this because | ||
| 617 | * there's no "full off" mode defined in hwmon specifcations. | ||
| 618 | */ | ||
| 619 | |||
| 620 | if ((config & MAX6650_CFG_MODE_MASK) == MAX6650_CFG_MODE_OFF) { | ||
| 621 | dev_dbg(&client->dev, "Change mode to open loop, full off.\n"); | ||
| 622 | config = (config & ~MAX6650_CFG_MODE_MASK) | ||
| 623 | | MAX6650_CFG_MODE_OPEN_LOOP; | ||
| 624 | if (i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, 255)) { | ||
| 625 | dev_err(&client->dev, "DAC write error, aborting.\n"); | ||
| 626 | return err; | ||
| 627 | } | ||
| 628 | } | ||
| 629 | |||
| 630 | if (i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, config)) { | ||
| 631 | dev_err(&client->dev, "Config write error, aborting.\n"); | ||
| 632 | return err; | ||
| 633 | } | ||
| 634 | |||
| 635 | data->config = config; | ||
| 636 | data->count = i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT); | ||
| 637 | |||
| 638 | return 0; | ||
| 639 | } | ||
| 640 | |||
| 641 | static const u8 tach_reg[] = { | ||
| 642 | MAX6650_REG_TACH0, | ||
| 643 | MAX6650_REG_TACH1, | ||
| 644 | MAX6650_REG_TACH2, | ||
| 645 | MAX6650_REG_TACH3, | ||
| 646 | }; | ||
| 647 | |||
| 648 | static struct max6650_data *max6650_update_device(struct device *dev) | ||
| 649 | { | ||
| 650 | int i; | ||
| 651 | struct i2c_client *client = to_i2c_client(dev); | ||
| 652 | struct max6650_data *data = i2c_get_clientdata(client); | ||
| 653 | |||
| 654 | mutex_lock(&data->update_lock); | ||
| 655 | |||
| 656 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | ||
| 657 | data->speed = i2c_smbus_read_byte_data(client, | ||
| 658 | MAX6650_REG_SPEED); | ||
| 659 | data->config = i2c_smbus_read_byte_data(client, | ||
| 660 | MAX6650_REG_CONFIG); | ||
| 661 | for (i = 0; i < 4; i++) { | ||
| 662 | data->tach[i] = i2c_smbus_read_byte_data(client, | ||
| 663 | tach_reg[i]); | ||
| 664 | } | ||
| 665 | data->count = i2c_smbus_read_byte_data(client, | ||
| 666 | MAX6650_REG_COUNT); | ||
| 667 | data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC); | ||
| 668 | |||
| 669 | data->last_updated = jiffies; | ||
| 670 | data->valid = 1; | ||
| 671 | } | ||
| 672 | |||
| 673 | mutex_unlock(&data->update_lock); | ||
| 674 | |||
| 675 | return data; | ||
| 676 | } | ||
| 677 | |||
| 678 | static int __init sensors_max6650_init(void) | ||
| 679 | { | ||
| 680 | return i2c_add_driver(&max6650_driver); | ||
| 681 | } | ||
| 682 | |||
| 683 | static void __exit sensors_max6650_exit(void) | ||
| 684 | { | ||
| 685 | i2c_del_driver(&max6650_driver); | ||
| 686 | } | ||
| 687 | |||
| 688 | MODULE_AUTHOR("Hans J. Koch"); | ||
| 689 | MODULE_DESCRIPTION("MAX6650 sensor driver"); | ||
| 690 | MODULE_LICENSE("GPL"); | ||
| 691 | |||
| 692 | module_init(sensors_max6650_init); | ||
| 693 | module_exit(sensors_max6650_exit); | ||
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index affa21a5ccfd..29354fa26f81 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/err.h> | 31 | #include <linux/err.h> |
| 32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
| 33 | #include <linux/sysfs.h> | 33 | #include <linux/sysfs.h> |
| 34 | #include <linux/ioport.h> | ||
| 34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
| 35 | 36 | ||
| 36 | static struct platform_device *pdev; | 37 | static struct platform_device *pdev; |
| @@ -429,6 +430,12 @@ static int __devinit pc87427_probe(struct platform_device *pdev) | |||
| 429 | /* This will need to be revisited when we add support for | 430 | /* This will need to be revisited when we add support for |
| 430 | temperature and voltage monitoring. */ | 431 | temperature and voltage monitoring. */ |
| 431 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 432 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
| 433 | if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) { | ||
| 434 | err = -EBUSY; | ||
| 435 | dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n", | ||
| 436 | (unsigned long)res->start, (unsigned long)res->end); | ||
| 437 | goto exit_kfree; | ||
| 438 | } | ||
| 432 | data->address[0] = res->start; | 439 | data->address[0] = res->start; |
| 433 | 440 | ||
| 434 | mutex_init(&data->lock); | 441 | mutex_init(&data->lock); |
| @@ -438,7 +445,7 @@ static int __devinit pc87427_probe(struct platform_device *pdev) | |||
| 438 | 445 | ||
| 439 | /* Register sysfs hooks */ | 446 | /* Register sysfs hooks */ |
| 440 | if ((err = device_create_file(&pdev->dev, &dev_attr_name))) | 447 | if ((err = device_create_file(&pdev->dev, &dev_attr_name))) |
| 441 | goto exit_kfree; | 448 | goto exit_release_region; |
| 442 | for (i = 0; i < 8; i++) { | 449 | for (i = 0; i < 8; i++) { |
| 443 | if (!(data->fan_enabled & (1 << i))) | 450 | if (!(data->fan_enabled & (1 << i))) |
| 444 | continue; | 451 | continue; |
| @@ -462,6 +469,8 @@ exit_remove_files: | |||
| 462 | continue; | 469 | continue; |
| 463 | sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]); | 470 | sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]); |
| 464 | } | 471 | } |
| 472 | exit_release_region: | ||
| 473 | release_region(res->start, res->end - res->start + 1); | ||
| 465 | exit_kfree: | 474 | exit_kfree: |
| 466 | platform_set_drvdata(pdev, NULL); | 475 | platform_set_drvdata(pdev, NULL); |
| 467 | kfree(data); | 476 | kfree(data); |
| @@ -472,6 +481,7 @@ exit: | |||
| 472 | static int __devexit pc87427_remove(struct platform_device *pdev) | 481 | static int __devexit pc87427_remove(struct platform_device *pdev) |
| 473 | { | 482 | { |
| 474 | struct pc87427_data *data = platform_get_drvdata(pdev); | 483 | struct pc87427_data *data = platform_get_drvdata(pdev); |
| 484 | struct resource *res; | ||
| 475 | int i; | 485 | int i; |
| 476 | 486 | ||
| 477 | platform_set_drvdata(pdev, NULL); | 487 | platform_set_drvdata(pdev, NULL); |
| @@ -484,6 +494,9 @@ static int __devexit pc87427_remove(struct platform_device *pdev) | |||
| 484 | } | 494 | } |
| 485 | kfree(data); | 495 | kfree(data); |
| 486 | 496 | ||
| 497 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 498 | release_region(res->start, res->end - res->start + 1); | ||
| 499 | |||
| 487 | return 0; | 500 | return 0; |
| 488 | } | 501 | } |
| 489 | 502 | ||
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index 72b0e2d8650c..943abbd95ab5 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c | |||
| @@ -30,16 +30,17 @@ | |||
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
| 32 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
| 33 | #include <linux/i2c.h> | 33 | #include <linux/platform_device.h> |
| 34 | #include <linux/i2c-isa.h> | ||
| 35 | #include <linux/hwmon.h> | 34 | #include <linux/hwmon.h> |
| 35 | #include <linux/hwmon-sysfs.h> | ||
| 36 | #include <linux/err.h> | 36 | #include <linux/err.h> |
| 37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
| 38 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
| 39 | #include <asm/io.h> | 39 | #include <asm/io.h> |
| 40 | 40 | ||
| 41 | /* Address is autodetected, there is no default value */ | 41 | static struct platform_device *pdev; |
| 42 | static unsigned short address; | 42 | |
| 43 | #define DRVNAME "smsc47b397" | ||
| 43 | 44 | ||
| 44 | /* Super-I/0 registers and commands */ | 45 | /* Super-I/0 registers and commands */ |
| 45 | 46 | ||
| @@ -91,7 +92,8 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80}; | |||
| 91 | #define SMSC47B397_REG_FAN_MSB(nr) (0x29 + 2 * (nr)) | 92 | #define SMSC47B397_REG_FAN_MSB(nr) (0x29 + 2 * (nr)) |
| 92 | 93 | ||
| 93 | struct smsc47b397_data { | 94 | struct smsc47b397_data { |
| 94 | struct i2c_client client; | 95 | unsigned short addr; |
| 96 | const char *name; | ||
| 95 | struct class_device *class_dev; | 97 | struct class_device *class_dev; |
| 96 | struct mutex lock; | 98 | struct mutex lock; |
| 97 | 99 | ||
| @@ -104,45 +106,43 @@ struct smsc47b397_data { | |||
| 104 | u8 temp[4]; | 106 | u8 temp[4]; |
| 105 | }; | 107 | }; |
| 106 | 108 | ||
| 107 | static int smsc47b397_read_value(struct i2c_client *client, u8 reg) | 109 | static int smsc47b397_read_value(struct smsc47b397_data* data, u8 reg) |
| 108 | { | 110 | { |
| 109 | struct smsc47b397_data *data = i2c_get_clientdata(client); | ||
| 110 | int res; | 111 | int res; |
| 111 | 112 | ||
| 112 | mutex_lock(&data->lock); | 113 | mutex_lock(&data->lock); |
| 113 | outb(reg, client->addr); | 114 | outb(reg, data->addr); |
| 114 | res = inb_p(client->addr + 1); | 115 | res = inb_p(data->addr + 1); |
| 115 | mutex_unlock(&data->lock); | 116 | mutex_unlock(&data->lock); |
| 116 | return res; | 117 | return res; |
| 117 | } | 118 | } |
| 118 | 119 | ||
| 119 | static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) | 120 | static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) |
| 120 | { | 121 | { |
| 121 | struct i2c_client *client = to_i2c_client(dev); | 122 | struct smsc47b397_data *data = dev_get_drvdata(dev); |
| 122 | struct smsc47b397_data *data = i2c_get_clientdata(client); | ||
| 123 | int i; | 123 | int i; |
| 124 | 124 | ||
| 125 | mutex_lock(&data->update_lock); | 125 | mutex_lock(&data->update_lock); |
| 126 | 126 | ||
| 127 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | 127 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { |
| 128 | dev_dbg(&client->dev, "starting device update...\n"); | 128 | dev_dbg(dev, "starting device update...\n"); |
| 129 | 129 | ||
| 130 | /* 4 temperature inputs, 4 fan inputs */ | 130 | /* 4 temperature inputs, 4 fan inputs */ |
| 131 | for (i = 0; i < 4; i++) { | 131 | for (i = 0; i < 4; i++) { |
| 132 | data->temp[i] = smsc47b397_read_value(client, | 132 | data->temp[i] = smsc47b397_read_value(data, |
| 133 | SMSC47B397_REG_TEMP(i)); | 133 | SMSC47B397_REG_TEMP(i)); |
| 134 | 134 | ||
| 135 | /* must read LSB first */ | 135 | /* must read LSB first */ |
| 136 | data->fan[i] = smsc47b397_read_value(client, | 136 | data->fan[i] = smsc47b397_read_value(data, |
| 137 | SMSC47B397_REG_FAN_LSB(i)); | 137 | SMSC47B397_REG_FAN_LSB(i)); |
| 138 | data->fan[i] |= smsc47b397_read_value(client, | 138 | data->fan[i] |= smsc47b397_read_value(data, |
| 139 | SMSC47B397_REG_FAN_MSB(i)) << 8; | 139 | SMSC47B397_REG_FAN_MSB(i)) << 8; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | data->last_updated = jiffies; | 142 | data->last_updated = jiffies; |
| 143 | data->valid = 1; | 143 | data->valid = 1; |
| 144 | 144 | ||
| 145 | dev_dbg(&client->dev, "... device update complete\n"); | 145 | dev_dbg(dev, "... device update complete\n"); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | mutex_unlock(&data->update_lock); | 148 | mutex_unlock(&data->update_lock); |
| @@ -157,24 +157,18 @@ static int temp_from_reg(u8 reg) | |||
| 157 | return (s8)reg * 1000; | 157 | return (s8)reg * 1000; |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | /* 0 <= nr <= 3 */ | 160 | static ssize_t show_temp(struct device *dev, struct device_attribute |
| 161 | static ssize_t show_temp(struct device *dev, char *buf, int nr) | 161 | *devattr, char *buf) |
| 162 | { | 162 | { |
| 163 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 163 | struct smsc47b397_data *data = smsc47b397_update_device(dev); | 164 | struct smsc47b397_data *data = smsc47b397_update_device(dev); |
| 164 | return sprintf(buf, "%d\n", temp_from_reg(data->temp[nr])); | 165 | return sprintf(buf, "%d\n", temp_from_reg(data->temp[attr->index])); |
| 165 | } | 166 | } |
| 166 | 167 | ||
| 167 | #define sysfs_temp(num) \ | 168 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); |
| 168 | static ssize_t show_temp##num(struct device *dev, struct device_attribute *attr, char *buf) \ | 169 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); |
| 169 | { \ | 170 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); |
| 170 | return show_temp(dev, buf, num-1); \ | 171 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); |
| 171 | } \ | ||
| 172 | static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL) | ||
| 173 | |||
| 174 | sysfs_temp(1); | ||
| 175 | sysfs_temp(2); | ||
| 176 | sysfs_temp(3); | ||
| 177 | sysfs_temp(4); | ||
| 178 | 172 | ||
| 179 | /* FAN: 1 RPM/bit | 173 | /* FAN: 1 RPM/bit |
| 180 | REG: count of 90kHz pulses / revolution */ | 174 | REG: count of 90kHz pulses / revolution */ |
| @@ -183,35 +177,37 @@ static int fan_from_reg(u16 reg) | |||
| 183 | return 90000 * 60 / reg; | 177 | return 90000 * 60 / reg; |
| 184 | } | 178 | } |
| 185 | 179 | ||
| 186 | /* 0 <= nr <= 3 */ | 180 | static ssize_t show_fan(struct device *dev, struct device_attribute |
| 187 | static ssize_t show_fan(struct device *dev, char *buf, int nr) | 181 | *devattr, char *buf) |
| 188 | { | 182 | { |
| 189 | struct smsc47b397_data *data = smsc47b397_update_device(dev); | 183 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 190 | return sprintf(buf, "%d\n", fan_from_reg(data->fan[nr])); | 184 | struct smsc47b397_data *data = smsc47b397_update_device(dev); |
| 185 | return sprintf(buf, "%d\n", fan_from_reg(data->fan[attr->index])); | ||
| 191 | } | 186 | } |
| 187 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); | ||
| 188 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); | ||
| 189 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); | ||
| 190 | static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); | ||
| 192 | 191 | ||
| 193 | #define sysfs_fan(num) \ | 192 | static ssize_t show_name(struct device *dev, struct device_attribute |
| 194 | static ssize_t show_fan##num(struct device *dev, struct device_attribute *attr, char *buf) \ | 193 | *devattr, char *buf) |
| 195 | { \ | 194 | { |
| 196 | return show_fan(dev, buf, num-1); \ | 195 | struct smsc47b397_data *data = dev_get_drvdata(dev); |
| 197 | } \ | 196 | return sprintf(buf, "%s\n", data->name); |
| 198 | static DEVICE_ATTR(fan##num##_input, S_IRUGO, show_fan##num, NULL) | 197 | } |
| 199 | 198 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | |
| 200 | sysfs_fan(1); | ||
| 201 | sysfs_fan(2); | ||
| 202 | sysfs_fan(3); | ||
| 203 | sysfs_fan(4); | ||
| 204 | 199 | ||
| 205 | static struct attribute *smsc47b397_attributes[] = { | 200 | static struct attribute *smsc47b397_attributes[] = { |
| 206 | &dev_attr_temp1_input.attr, | 201 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
| 207 | &dev_attr_temp2_input.attr, | 202 | &sensor_dev_attr_temp2_input.dev_attr.attr, |
| 208 | &dev_attr_temp3_input.attr, | 203 | &sensor_dev_attr_temp3_input.dev_attr.attr, |
| 209 | &dev_attr_temp4_input.attr, | 204 | &sensor_dev_attr_temp4_input.dev_attr.attr, |
| 210 | &dev_attr_fan1_input.attr, | 205 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
| 211 | &dev_attr_fan2_input.attr, | 206 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
| 212 | &dev_attr_fan3_input.attr, | 207 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
| 213 | &dev_attr_fan4_input.attr, | 208 | &sensor_dev_attr_fan4_input.dev_attr.attr, |
| 214 | 209 | ||
| 210 | &dev_attr_name.attr, | ||
| 215 | NULL | 211 | NULL |
| 216 | }; | 212 | }; |
| 217 | 213 | ||
| @@ -219,44 +215,44 @@ static const struct attribute_group smsc47b397_group = { | |||
| 219 | .attrs = smsc47b397_attributes, | 215 | .attrs = smsc47b397_attributes, |
| 220 | }; | 216 | }; |
| 221 | 217 | ||
| 222 | static int smsc47b397_detach_client(struct i2c_client *client) | 218 | static int __devexit smsc47b397_remove(struct platform_device *pdev) |
| 223 | { | 219 | { |
| 224 | struct smsc47b397_data *data = i2c_get_clientdata(client); | 220 | struct smsc47b397_data *data = platform_get_drvdata(pdev); |
| 225 | int err; | 221 | struct resource *res; |
| 226 | 222 | ||
| 227 | hwmon_device_unregister(data->class_dev); | 223 | hwmon_device_unregister(data->class_dev); |
| 228 | sysfs_remove_group(&client->dev.kobj, &smsc47b397_group); | 224 | sysfs_remove_group(&pdev->dev.kobj, &smsc47b397_group); |
| 229 | 225 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | |
| 230 | if ((err = i2c_detach_client(client))) | 226 | release_region(res->start, SMSC_EXTENT); |
| 231 | return err; | ||
| 232 | |||
| 233 | release_region(client->addr, SMSC_EXTENT); | ||
| 234 | kfree(data); | 227 | kfree(data); |
| 235 | 228 | ||
| 236 | return 0; | 229 | return 0; |
| 237 | } | 230 | } |
| 238 | 231 | ||
| 239 | static int smsc47b397_detect(struct i2c_adapter *adapter); | 232 | static int smsc47b397_probe(struct platform_device *pdev); |
| 240 | 233 | ||
| 241 | static struct i2c_driver smsc47b397_driver = { | 234 | static struct platform_driver smsc47b397_driver = { |
| 242 | .driver = { | 235 | .driver = { |
| 243 | .owner = THIS_MODULE, | 236 | .owner = THIS_MODULE, |
| 244 | .name = "smsc47b397", | 237 | .name = DRVNAME, |
| 245 | }, | 238 | }, |
| 246 | .attach_adapter = smsc47b397_detect, | 239 | .probe = smsc47b397_probe, |
| 247 | .detach_client = smsc47b397_detach_client, | 240 | .remove = __devexit_p(smsc47b397_remove), |
| 248 | }; | 241 | }; |
| 249 | 242 | ||
| 250 | static int smsc47b397_detect(struct i2c_adapter *adapter) | 243 | static int __devinit smsc47b397_probe(struct platform_device *pdev) |
| 251 | { | 244 | { |
| 252 | struct i2c_client *new_client; | 245 | struct device *dev = &pdev->dev; |
| 253 | struct smsc47b397_data *data; | 246 | struct smsc47b397_data *data; |
| 247 | struct resource *res; | ||
| 254 | int err = 0; | 248 | int err = 0; |
| 255 | 249 | ||
| 256 | if (!request_region(address, SMSC_EXTENT, | 250 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
| 251 | if (!request_region(res->start, SMSC_EXTENT, | ||
| 257 | smsc47b397_driver.driver.name)) { | 252 | smsc47b397_driver.driver.name)) { |
| 258 | dev_err(&adapter->dev, "Region 0x%x already in use!\n", | 253 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", |
| 259 | address); | 254 | (unsigned long)res->start, |
| 255 | (unsigned long)res->start + SMSC_EXTENT - 1); | ||
| 260 | return -EBUSY; | 256 | return -EBUSY; |
| 261 | } | 257 | } |
| 262 | 258 | ||
| @@ -265,25 +261,16 @@ static int smsc47b397_detect(struct i2c_adapter *adapter) | |||
| 265 | goto error_release; | 261 | goto error_release; |
| 266 | } | 262 | } |
| 267 | 263 | ||
| 268 | new_client = &data->client; | 264 | data->addr = res->start; |
| 269 | i2c_set_clientdata(new_client, data); | 265 | data->name = "smsc47b397"; |
| 270 | new_client->addr = address; | ||
| 271 | mutex_init(&data->lock); | 266 | mutex_init(&data->lock); |
| 272 | new_client->adapter = adapter; | ||
| 273 | new_client->driver = &smsc47b397_driver; | ||
| 274 | new_client->flags = 0; | ||
| 275 | |||
| 276 | strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE); | ||
| 277 | |||
| 278 | mutex_init(&data->update_lock); | 267 | mutex_init(&data->update_lock); |
| 268 | platform_set_drvdata(pdev, data); | ||
| 279 | 269 | ||
| 280 | if ((err = i2c_attach_client(new_client))) | 270 | if ((err = sysfs_create_group(&dev->kobj, &smsc47b397_group))) |
| 281 | goto error_free; | 271 | goto error_free; |
| 282 | 272 | ||
| 283 | if ((err = sysfs_create_group(&new_client->dev.kobj, &smsc47b397_group))) | 273 | data->class_dev = hwmon_device_register(dev); |
| 284 | goto error_detach; | ||
| 285 | |||
| 286 | data->class_dev = hwmon_device_register(&new_client->dev); | ||
| 287 | if (IS_ERR(data->class_dev)) { | 274 | if (IS_ERR(data->class_dev)) { |
| 288 | err = PTR_ERR(data->class_dev); | 275 | err = PTR_ERR(data->class_dev); |
| 289 | goto error_remove; | 276 | goto error_remove; |
| @@ -292,13 +279,50 @@ static int smsc47b397_detect(struct i2c_adapter *adapter) | |||
| 292 | return 0; | 279 | return 0; |
| 293 | 280 | ||
| 294 | error_remove: | 281 | error_remove: |
| 295 | sysfs_remove_group(&new_client->dev.kobj, &smsc47b397_group); | 282 | sysfs_remove_group(&dev->kobj, &smsc47b397_group); |
| 296 | error_detach: | ||
| 297 | i2c_detach_client(new_client); | ||
| 298 | error_free: | 283 | error_free: |
| 299 | kfree(data); | 284 | kfree(data); |
| 300 | error_release: | 285 | error_release: |
| 301 | release_region(address, SMSC_EXTENT); | 286 | release_region(res->start, SMSC_EXTENT); |
| 287 | return err; | ||
| 288 | } | ||
| 289 | |||
| 290 | static int __init smsc47b397_device_add(unsigned short address) | ||
| 291 | { | ||
| 292 | struct resource res = { | ||
| 293 | .start = address, | ||
| 294 | .end = address + SMSC_EXTENT - 1, | ||
| 295 | .name = DRVNAME, | ||
| 296 | .flags = IORESOURCE_IO, | ||
| 297 | }; | ||
| 298 | int err; | ||
| 299 | |||
| 300 | pdev = platform_device_alloc(DRVNAME, address); | ||
| 301 | if (!pdev) { | ||
| 302 | err = -ENOMEM; | ||
| 303 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | ||
| 304 | goto exit; | ||
| 305 | } | ||
| 306 | |||
| 307 | err = platform_device_add_resources(pdev, &res, 1); | ||
| 308 | if (err) { | ||
| 309 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | ||
| 310 | "(%d)\n", err); | ||
| 311 | goto exit_device_put; | ||
| 312 | } | ||
| 313 | |||
| 314 | err = platform_device_add(pdev); | ||
| 315 | if (err) { | ||
| 316 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
| 317 | err); | ||
| 318 | goto exit_device_put; | ||
| 319 | } | ||
| 320 | |||
| 321 | return 0; | ||
| 322 | |||
| 323 | exit_device_put: | ||
| 324 | platform_device_put(pdev); | ||
| 325 | exit: | ||
| 302 | return err; | 326 | return err; |
| 303 | } | 327 | } |
| 304 | 328 | ||
| @@ -320,7 +344,7 @@ static int __init smsc47b397_find(unsigned short *addr) | |||
| 320 | *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8) | 344 | *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8) |
| 321 | | superio_inb(SUPERIO_REG_BASE_LSB); | 345 | | superio_inb(SUPERIO_REG_BASE_LSB); |
| 322 | 346 | ||
| 323 | printk(KERN_INFO "smsc47b397: found SMSC %s " | 347 | printk(KERN_INFO DRVNAME ": found SMSC %s " |
| 324 | "(base address 0x%04x, revision %u)\n", | 348 | "(base address 0x%04x, revision %u)\n", |
| 325 | id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev); | 349 | id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev); |
| 326 | 350 | ||
| @@ -330,17 +354,33 @@ static int __init smsc47b397_find(unsigned short *addr) | |||
| 330 | 354 | ||
| 331 | static int __init smsc47b397_init(void) | 355 | static int __init smsc47b397_init(void) |
| 332 | { | 356 | { |
| 357 | unsigned short address; | ||
| 333 | int ret; | 358 | int ret; |
| 334 | 359 | ||
| 335 | if ((ret = smsc47b397_find(&address))) | 360 | if ((ret = smsc47b397_find(&address))) |
| 336 | return ret; | 361 | return ret; |
| 337 | 362 | ||
| 338 | return i2c_isa_add_driver(&smsc47b397_driver); | 363 | ret = platform_driver_register(&smsc47b397_driver); |
| 364 | if (ret) | ||
| 365 | goto exit; | ||
| 366 | |||
| 367 | /* Sets global pdev as a side effect */ | ||
| 368 | ret = smsc47b397_device_add(address); | ||
| 369 | if (ret) | ||
| 370 | goto exit_driver; | ||
| 371 | |||
| 372 | return 0; | ||
| 373 | |||
| 374 | exit_driver: | ||
| 375 | platform_driver_unregister(&smsc47b397_driver); | ||
| 376 | exit: | ||
| 377 | return ret; | ||
| 339 | } | 378 | } |
| 340 | 379 | ||
| 341 | static void __exit smsc47b397_exit(void) | 380 | static void __exit smsc47b397_exit(void) |
| 342 | { | 381 | { |
| 343 | i2c_isa_del_driver(&smsc47b397_driver); | 382 | platform_device_unregister(pdev); |
| 383 | platform_driver_unregister(&smsc47b397_driver); | ||
| 344 | } | 384 | } |
| 345 | 385 | ||
| 346 | MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); | 386 | MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); |
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index beb881c4b2e8..1e21c8cc948f 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c | |||
| @@ -3,10 +3,11 @@ | |||
| 3 | for hardware monitoring | 3 | for hardware monitoring |
| 4 | 4 | ||
| 5 | Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x, | 5 | Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x, |
| 6 | LPC47M14x, LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips. | 6 | LPC47M14x, LPC47M15x, LPC47M192, LPC47M292 and LPC47M997 |
| 7 | Super-I/O chips. | ||
| 7 | 8 | ||
| 8 | Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> | 9 | Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> |
| 9 | Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> | 10 | Copyright (C) 2004-2007 Jean Delvare <khali@linux-fr.org> |
| 10 | Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com> | 11 | Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com> |
| 11 | and Jean Delvare | 12 | and Jean Delvare |
| 12 | 13 | ||
| @@ -29,17 +30,19 @@ | |||
| 29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 30 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
| 31 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
| 32 | #include <linux/i2c.h> | 33 | #include <linux/platform_device.h> |
| 33 | #include <linux/i2c-isa.h> | ||
| 34 | #include <linux/hwmon.h> | 34 | #include <linux/hwmon.h> |
| 35 | #include <linux/hwmon-sysfs.h> | ||
| 35 | #include <linux/err.h> | 36 | #include <linux/err.h> |
| 36 | #include <linux/init.h> | 37 | #include <linux/init.h> |
| 37 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
| 38 | #include <linux/sysfs.h> | 39 | #include <linux/sysfs.h> |
| 39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
| 40 | 41 | ||
| 41 | /* Address is autodetected, there is no default value */ | 42 | static struct platform_device *pdev; |
| 42 | static unsigned short address; | 43 | |
| 44 | #define DRVNAME "smsc47m1" | ||
| 45 | enum chips { smsc47m1, smsc47m2 }; | ||
| 43 | 46 | ||
| 44 | /* Super-I/0 registers and commands */ | 47 | /* Super-I/0 registers and commands */ |
| 45 | 48 | ||
| @@ -87,10 +90,18 @@ superio_exit(void) | |||
| 87 | #define SMSC47M1_REG_ALARM 0x04 | 90 | #define SMSC47M1_REG_ALARM 0x04 |
| 88 | #define SMSC47M1_REG_TPIN(nr) (0x34 - (nr)) | 91 | #define SMSC47M1_REG_TPIN(nr) (0x34 - (nr)) |
| 89 | #define SMSC47M1_REG_PPIN(nr) (0x36 - (nr)) | 92 | #define SMSC47M1_REG_PPIN(nr) (0x36 - (nr)) |
| 90 | #define SMSC47M1_REG_PWM(nr) (0x56 + (nr)) | ||
| 91 | #define SMSC47M1_REG_FANDIV 0x58 | 93 | #define SMSC47M1_REG_FANDIV 0x58 |
| 92 | #define SMSC47M1_REG_FAN(nr) (0x59 + (nr)) | 94 | |
| 93 | #define SMSC47M1_REG_FAN_PRELOAD(nr) (0x5B + (nr)) | 95 | static const u8 SMSC47M1_REG_FAN[3] = { 0x59, 0x5a, 0x6b }; |
| 96 | static const u8 SMSC47M1_REG_FAN_PRELOAD[3] = { 0x5b, 0x5c, 0x6c }; | ||
| 97 | static const u8 SMSC47M1_REG_PWM[3] = { 0x56, 0x57, 0x69 }; | ||
| 98 | |||
| 99 | #define SMSC47M2_REG_ALARM6 0x09 | ||
| 100 | #define SMSC47M2_REG_TPIN1 0x38 | ||
| 101 | #define SMSC47M2_REG_TPIN2 0x37 | ||
| 102 | #define SMSC47M2_REG_TPIN3 0x2d | ||
| 103 | #define SMSC47M2_REG_PPIN3 0x2c | ||
| 104 | #define SMSC47M2_REG_FANDIV3 0x6a | ||
| 94 | 105 | ||
| 95 | #define MIN_FROM_REG(reg,div) ((reg)>=192 ? 0 : \ | 106 | #define MIN_FROM_REG(reg,div) ((reg)>=192 ? 0 : \ |
| 96 | 983040/((192-(reg))*(div))) | 107 | 983040/((192-(reg))*(div))) |
| @@ -102,45 +113,57 @@ superio_exit(void) | |||
| 102 | #define PWM_TO_REG(reg) (((reg) >> 1) & 0x7E) | 113 | #define PWM_TO_REG(reg) (((reg) >> 1) & 0x7E) |
| 103 | 114 | ||
| 104 | struct smsc47m1_data { | 115 | struct smsc47m1_data { |
| 105 | struct i2c_client client; | 116 | unsigned short addr; |
| 117 | const char *name; | ||
| 118 | enum chips type; | ||
| 106 | struct class_device *class_dev; | 119 | struct class_device *class_dev; |
| 107 | struct mutex lock; | ||
| 108 | 120 | ||
| 109 | struct mutex update_lock; | 121 | struct mutex update_lock; |
| 110 | unsigned long last_updated; /* In jiffies */ | 122 | unsigned long last_updated; /* In jiffies */ |
| 111 | 123 | ||
| 112 | u8 fan[2]; /* Register value */ | 124 | u8 fan[3]; /* Register value */ |
| 113 | u8 fan_preload[2]; /* Register value */ | 125 | u8 fan_preload[3]; /* Register value */ |
| 114 | u8 fan_div[2]; /* Register encoding, shifted right */ | 126 | u8 fan_div[3]; /* Register encoding, shifted right */ |
| 115 | u8 alarms; /* Register encoding */ | 127 | u8 alarms; /* Register encoding */ |
| 116 | u8 pwm[2]; /* Register value (bit 7 is enable) */ | 128 | u8 pwm[3]; /* Register value (bit 0 is disable) */ |
| 117 | }; | 129 | }; |
| 118 | 130 | ||
| 131 | struct smsc47m1_sio_data { | ||
| 132 | enum chips type; | ||
| 133 | }; | ||
| 119 | 134 | ||
| 120 | static int smsc47m1_detect(struct i2c_adapter *adapter); | ||
| 121 | static int smsc47m1_detach_client(struct i2c_client *client); | ||
| 122 | |||
| 123 | static int smsc47m1_read_value(struct i2c_client *client, u8 reg); | ||
| 124 | static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value); | ||
| 125 | 135 | ||
| 136 | static int smsc47m1_probe(struct platform_device *pdev); | ||
| 137 | static int smsc47m1_remove(struct platform_device *pdev); | ||
| 126 | static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, | 138 | static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, |
| 127 | int init); | 139 | int init); |
| 128 | 140 | ||
| 141 | static inline int smsc47m1_read_value(struct smsc47m1_data *data, u8 reg) | ||
| 142 | { | ||
| 143 | return inb_p(data->addr + reg); | ||
| 144 | } | ||
| 129 | 145 | ||
| 130 | static struct i2c_driver smsc47m1_driver = { | 146 | static inline void smsc47m1_write_value(struct smsc47m1_data *data, u8 reg, |
| 147 | u8 value) | ||
| 148 | { | ||
| 149 | outb_p(value, data->addr + reg); | ||
| 150 | } | ||
| 151 | |||
| 152 | static struct platform_driver smsc47m1_driver = { | ||
| 131 | .driver = { | 153 | .driver = { |
| 132 | .owner = THIS_MODULE, | 154 | .owner = THIS_MODULE, |
| 133 | .name = "smsc47m1", | 155 | .name = DRVNAME, |
| 134 | }, | 156 | }, |
| 135 | .attach_adapter = smsc47m1_detect, | 157 | .probe = smsc47m1_probe, |
| 136 | .detach_client = smsc47m1_detach_client, | 158 | .remove = __devexit_p(smsc47m1_remove), |
| 137 | }; | 159 | }; |
| 138 | 160 | ||
| 139 | /* nr is 0 or 1 in the callback functions below */ | 161 | static ssize_t get_fan(struct device *dev, struct device_attribute |
| 140 | 162 | *devattr, char *buf) | |
| 141 | static ssize_t get_fan(struct device *dev, char *buf, int nr) | ||
| 142 | { | 163 | { |
| 164 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 143 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 165 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
| 166 | int nr = attr->index; | ||
| 144 | /* This chip (stupidly) stops monitoring fan speed if PWM is | 167 | /* This chip (stupidly) stops monitoring fan speed if PWM is |
| 145 | enabled and duty cycle is 0%. This is fine if the monitoring | 168 | enabled and duty cycle is 0%. This is fine if the monitoring |
| 146 | and control concern the same fan, but troublesome if they are | 169 | and control concern the same fan, but troublesome if they are |
| @@ -152,43 +175,54 @@ static ssize_t get_fan(struct device *dev, char *buf, int nr) | |||
| 152 | return sprintf(buf, "%d\n", rpm); | 175 | return sprintf(buf, "%d\n", rpm); |
| 153 | } | 176 | } |
| 154 | 177 | ||
| 155 | static ssize_t get_fan_min(struct device *dev, char *buf, int nr) | 178 | static ssize_t get_fan_min(struct device *dev, struct device_attribute |
| 179 | *devattr, char *buf) | ||
| 156 | { | 180 | { |
| 181 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 157 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 182 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
| 183 | int nr = attr->index; | ||
| 158 | int rpm = MIN_FROM_REG(data->fan_preload[nr], | 184 | int rpm = MIN_FROM_REG(data->fan_preload[nr], |
| 159 | DIV_FROM_REG(data->fan_div[nr])); | 185 | DIV_FROM_REG(data->fan_div[nr])); |
| 160 | return sprintf(buf, "%d\n", rpm); | 186 | return sprintf(buf, "%d\n", rpm); |
| 161 | } | 187 | } |
| 162 | 188 | ||
| 163 | static ssize_t get_fan_div(struct device *dev, char *buf, int nr) | 189 | static ssize_t get_fan_div(struct device *dev, struct device_attribute |
| 190 | *devattr, char *buf) | ||
| 164 | { | 191 | { |
| 192 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 165 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 193 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
| 166 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); | 194 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); |
| 167 | } | 195 | } |
| 168 | 196 | ||
| 169 | static ssize_t get_pwm(struct device *dev, char *buf, int nr) | 197 | static ssize_t get_pwm(struct device *dev, struct device_attribute |
| 198 | *devattr, char *buf) | ||
| 170 | { | 199 | { |
| 200 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 171 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 201 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
| 172 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); | 202 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[attr->index])); |
| 173 | } | 203 | } |
| 174 | 204 | ||
| 175 | static ssize_t get_pwm_en(struct device *dev, char *buf, int nr) | 205 | static ssize_t get_pwm_en(struct device *dev, struct device_attribute |
| 206 | *devattr, char *buf) | ||
| 176 | { | 207 | { |
| 208 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 177 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 209 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
| 178 | return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[nr])); | 210 | return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[attr->index])); |
| 179 | } | 211 | } |
| 180 | 212 | ||
| 181 | static ssize_t get_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 213 | static ssize_t get_alarms(struct device *dev, struct device_attribute |
| 214 | *devattr, char *buf) | ||
| 182 | { | 215 | { |
| 183 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 216 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
| 184 | return sprintf(buf, "%d\n", data->alarms); | 217 | return sprintf(buf, "%d\n", data->alarms); |
| 185 | } | 218 | } |
| 186 | 219 | ||
| 187 | static ssize_t set_fan_min(struct device *dev, const char *buf, | 220 | static ssize_t set_fan_min(struct device *dev, struct device_attribute |
| 188 | size_t count, int nr) | 221 | *devattr, const char *buf, size_t count) |
| 189 | { | 222 | { |
| 190 | struct i2c_client *client = to_i2c_client(dev); | 223 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 191 | struct smsc47m1_data *data = i2c_get_clientdata(client); | 224 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
| 225 | int nr = attr->index; | ||
| 192 | long rpmdiv, val = simple_strtol(buf, NULL, 10); | 226 | long rpmdiv, val = simple_strtol(buf, NULL, 10); |
| 193 | 227 | ||
| 194 | mutex_lock(&data->update_lock); | 228 | mutex_lock(&data->update_lock); |
| @@ -200,7 +234,7 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, | |||
| 200 | } | 234 | } |
| 201 | 235 | ||
| 202 | data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); | 236 | data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); |
| 203 | smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), | 237 | smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr], |
| 204 | data->fan_preload[nr]); | 238 | data->fan_preload[nr]); |
| 205 | mutex_unlock(&data->update_lock); | 239 | mutex_unlock(&data->update_lock); |
| 206 | 240 | ||
| @@ -211,12 +245,12 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, | |||
| 211 | determined in part by the fan clock divider. This follows the principle | 245 | determined in part by the fan clock divider. This follows the principle |
| 212 | of least surprise; the user doesn't expect the fan minimum to change just | 246 | of least surprise; the user doesn't expect the fan minimum to change just |
| 213 | because the divider changed. */ | 247 | because the divider changed. */ |
| 214 | static ssize_t set_fan_div(struct device *dev, const char *buf, | 248 | static ssize_t set_fan_div(struct device *dev, struct device_attribute |
| 215 | size_t count, int nr) | 249 | *devattr, const char *buf, size_t count) |
| 216 | { | 250 | { |
| 217 | struct i2c_client *client = to_i2c_client(dev); | 251 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 218 | struct smsc47m1_data *data = i2c_get_clientdata(client); | 252 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
| 219 | 253 | int nr = attr->index; | |
| 220 | long new_div = simple_strtol(buf, NULL, 10), tmp; | 254 | long new_div = simple_strtol(buf, NULL, 10), tmp; |
| 221 | u8 old_div = DIV_FROM_REG(data->fan_div[nr]); | 255 | u8 old_div = DIV_FROM_REG(data->fan_div[nr]); |
| 222 | 256 | ||
| @@ -234,27 +268,38 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, | |||
| 234 | return -EINVAL; | 268 | return -EINVAL; |
| 235 | } | 269 | } |
| 236 | 270 | ||
| 237 | tmp = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV) & 0x0F; | 271 | switch (nr) { |
| 238 | tmp |= (data->fan_div[0] << 4) | (data->fan_div[1] << 6); | 272 | case 0: |
| 239 | smsc47m1_write_value(client, SMSC47M1_REG_FANDIV, tmp); | 273 | case 1: |
| 274 | tmp = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV) | ||
| 275 | & ~(0x03 << (4 + 2 * nr)); | ||
| 276 | tmp |= data->fan_div[nr] << (4 + 2 * nr); | ||
| 277 | smsc47m1_write_value(data, SMSC47M1_REG_FANDIV, tmp); | ||
| 278 | break; | ||
| 279 | case 2: | ||
| 280 | tmp = smsc47m1_read_value(data, SMSC47M2_REG_FANDIV3) & 0xCF; | ||
| 281 | tmp |= data->fan_div[2] << 4; | ||
| 282 | smsc47m1_write_value(data, SMSC47M2_REG_FANDIV3, tmp); | ||
| 283 | break; | ||
| 284 | } | ||
| 240 | 285 | ||
| 241 | /* Preserve fan min */ | 286 | /* Preserve fan min */ |
| 242 | tmp = 192 - (old_div * (192 - data->fan_preload[nr]) | 287 | tmp = 192 - (old_div * (192 - data->fan_preload[nr]) |
| 243 | + new_div / 2) / new_div; | 288 | + new_div / 2) / new_div; |
| 244 | data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); | 289 | data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); |
| 245 | smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), | 290 | smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr], |
| 246 | data->fan_preload[nr]); | 291 | data->fan_preload[nr]); |
| 247 | mutex_unlock(&data->update_lock); | 292 | mutex_unlock(&data->update_lock); |
| 248 | 293 | ||
| 249 | return count; | 294 | return count; |
| 250 | } | 295 | } |
| 251 | 296 | ||
| 252 | static ssize_t set_pwm(struct device *dev, const char *buf, | 297 | static ssize_t set_pwm(struct device *dev, struct device_attribute |
| 253 | size_t count, int nr) | 298 | *devattr, const char *buf, size_t count) |
| 254 | { | 299 | { |
| 255 | struct i2c_client *client = to_i2c_client(dev); | 300 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 256 | struct smsc47m1_data *data = i2c_get_clientdata(client); | 301 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
| 257 | 302 | int nr = attr->index; | |
| 258 | long val = simple_strtol(buf, NULL, 10); | 303 | long val = simple_strtol(buf, NULL, 10); |
| 259 | 304 | ||
| 260 | if (val < 0 || val > 255) | 305 | if (val < 0 || val > 255) |
| @@ -263,19 +308,19 @@ static ssize_t set_pwm(struct device *dev, const char *buf, | |||
| 263 | mutex_lock(&data->update_lock); | 308 | mutex_lock(&data->update_lock); |
| 264 | data->pwm[nr] &= 0x81; /* Preserve additional bits */ | 309 | data->pwm[nr] &= 0x81; /* Preserve additional bits */ |
| 265 | data->pwm[nr] |= PWM_TO_REG(val); | 310 | data->pwm[nr] |= PWM_TO_REG(val); |
| 266 | smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), | 311 | smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr], |
| 267 | data->pwm[nr]); | 312 | data->pwm[nr]); |
| 268 | mutex_unlock(&data->update_lock); | 313 | mutex_unlock(&data->update_lock); |
| 269 | 314 | ||
| 270 | return count; | 315 | return count; |
| 271 | } | 316 | } |
| 272 | 317 | ||
| 273 | static ssize_t set_pwm_en(struct device *dev, const char *buf, | 318 | static ssize_t set_pwm_en(struct device *dev, struct device_attribute |
| 274 | size_t count, int nr) | 319 | *devattr, const char *buf, size_t count) |
| 275 | { | 320 | { |
| 276 | struct i2c_client *client = to_i2c_client(dev); | 321 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 277 | struct smsc47m1_data *data = i2c_get_clientdata(client); | 322 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
| 278 | 323 | int nr = attr->index; | |
| 279 | long val = simple_strtol(buf, NULL, 10); | 324 | long val = simple_strtol(buf, NULL, 10); |
| 280 | 325 | ||
| 281 | if (val != 0 && val != 1) | 326 | if (val != 0 && val != 1) |
| @@ -284,7 +329,7 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf, | |||
| 284 | mutex_lock(&data->update_lock); | 329 | mutex_lock(&data->update_lock); |
| 285 | data->pwm[nr] &= 0xFE; /* preserve the other bits */ | 330 | data->pwm[nr] &= 0xFE; /* preserve the other bits */ |
| 286 | data->pwm[nr] |= !val; | 331 | data->pwm[nr] |= !val; |
| 287 | smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), | 332 | smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr], |
| 288 | data->pwm[nr]); | 333 | data->pwm[nr]); |
| 289 | mutex_unlock(&data->update_lock); | 334 | mutex_unlock(&data->update_lock); |
| 290 | 335 | ||
| @@ -292,79 +337,55 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf, | |||
| 292 | } | 337 | } |
| 293 | 338 | ||
| 294 | #define fan_present(offset) \ | 339 | #define fan_present(offset) \ |
| 295 | static ssize_t get_fan##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 340 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan, \ |
| 296 | { \ | 341 | NULL, offset - 1); \ |
| 297 | return get_fan(dev, buf, offset - 1); \ | 342 | static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ |
| 298 | } \ | 343 | get_fan_min, set_fan_min, offset - 1); \ |
| 299 | static ssize_t get_fan##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ | 344 | static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ |
| 300 | { \ | 345 | get_fan_div, set_fan_div, offset - 1); \ |
| 301 | return get_fan_min(dev, buf, offset - 1); \ | 346 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ |
| 302 | } \ | 347 | get_pwm, set_pwm, offset - 1); \ |
| 303 | static ssize_t set_fan##offset##_min (struct device *dev, struct device_attribute *attr, \ | 348 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ |
| 304 | const char *buf, size_t count) \ | 349 | get_pwm_en, set_pwm_en, offset - 1) |
| 305 | { \ | ||
| 306 | return set_fan_min(dev, buf, count, offset - 1); \ | ||
| 307 | } \ | ||
| 308 | static ssize_t get_fan##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 309 | { \ | ||
| 310 | return get_fan_div(dev, buf, offset - 1); \ | ||
| 311 | } \ | ||
| 312 | static ssize_t set_fan##offset##_div (struct device *dev, struct device_attribute *attr, \ | ||
| 313 | const char *buf, size_t count) \ | ||
| 314 | { \ | ||
| 315 | return set_fan_div(dev, buf, count, offset - 1); \ | ||
| 316 | } \ | ||
| 317 | static ssize_t get_pwm##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 318 | { \ | ||
| 319 | return get_pwm(dev, buf, offset - 1); \ | ||
| 320 | } \ | ||
| 321 | static ssize_t set_pwm##offset (struct device *dev, struct device_attribute *attr, \ | ||
| 322 | const char *buf, size_t count) \ | ||
| 323 | { \ | ||
| 324 | return set_pwm(dev, buf, count, offset - 1); \ | ||
| 325 | } \ | ||
| 326 | static ssize_t get_pwm##offset##_en (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 327 | { \ | ||
| 328 | return get_pwm_en(dev, buf, offset - 1); \ | ||
| 329 | } \ | ||
| 330 | static ssize_t set_pwm##offset##_en (struct device *dev, struct device_attribute *attr, \ | ||
| 331 | const char *buf, size_t count) \ | ||
| 332 | { \ | ||
| 333 | return set_pwm_en(dev, buf, count, offset - 1); \ | ||
| 334 | } \ | ||
| 335 | static DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan##offset, \ | ||
| 336 | NULL); \ | ||
| 337 | static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
| 338 | get_fan##offset##_min, set_fan##offset##_min); \ | ||
| 339 | static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ | ||
| 340 | get_fan##offset##_div, set_fan##offset##_div); \ | ||
| 341 | static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | ||
| 342 | get_pwm##offset, set_pwm##offset); \ | ||
| 343 | static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ | ||
| 344 | get_pwm##offset##_en, set_pwm##offset##_en); | ||
| 345 | 350 | ||
| 346 | fan_present(1); | 351 | fan_present(1); |
| 347 | fan_present(2); | 352 | fan_present(2); |
| 353 | fan_present(3); | ||
| 348 | 354 | ||
| 349 | static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); | 355 | static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); |
| 350 | 356 | ||
| 357 | static ssize_t show_name(struct device *dev, struct device_attribute | ||
| 358 | *devattr, char *buf) | ||
| 359 | { | ||
| 360 | struct smsc47m1_data *data = dev_get_drvdata(dev); | ||
| 361 | |||
| 362 | return sprintf(buf, "%s\n", data->name); | ||
| 363 | } | ||
| 364 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
| 365 | |||
| 351 | /* Almost all sysfs files may or may not be created depending on the chip | 366 | /* Almost all sysfs files may or may not be created depending on the chip |
| 352 | setup so we create them individually. It is still convenient to define a | 367 | setup so we create them individually. It is still convenient to define a |
| 353 | group to remove them all at once. */ | 368 | group to remove them all at once. */ |
| 354 | static struct attribute *smsc47m1_attributes[] = { | 369 | static struct attribute *smsc47m1_attributes[] = { |
| 355 | &dev_attr_fan1_input.attr, | 370 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
| 356 | &dev_attr_fan1_min.attr, | 371 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
| 357 | &dev_attr_fan1_div.attr, | 372 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
| 358 | &dev_attr_fan2_input.attr, | 373 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
| 359 | &dev_attr_fan2_min.attr, | 374 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
| 360 | &dev_attr_fan2_div.attr, | 375 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
| 361 | 376 | &sensor_dev_attr_fan3_input.dev_attr.attr, | |
| 362 | &dev_attr_pwm1.attr, | 377 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
| 363 | &dev_attr_pwm1_enable.attr, | 378 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
| 364 | &dev_attr_pwm2.attr, | 379 | |
| 365 | &dev_attr_pwm2_enable.attr, | 380 | &sensor_dev_attr_pwm1.dev_attr.attr, |
| 381 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
| 382 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
| 383 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
| 384 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
| 385 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
| 366 | 386 | ||
| 367 | &dev_attr_alarms.attr, | 387 | &dev_attr_alarms.attr, |
| 388 | &dev_attr_name.attr, | ||
| 368 | NULL | 389 | NULL |
| 369 | }; | 390 | }; |
| 370 | 391 | ||
| @@ -372,7 +393,8 @@ static const struct attribute_group smsc47m1_group = { | |||
| 372 | .attrs = smsc47m1_attributes, | 393 | .attrs = smsc47m1_attributes, |
| 373 | }; | 394 | }; |
| 374 | 395 | ||
| 375 | static int __init smsc47m1_find(unsigned short *addr) | 396 | static int __init smsc47m1_find(unsigned short *addr, |
| 397 | struct smsc47m1_sio_data *sio_data) | ||
| 376 | { | 398 | { |
| 377 | u8 val; | 399 | u8 val; |
| 378 | 400 | ||
| @@ -386,18 +408,32 @@ static int __init smsc47m1_find(unsigned short *addr) | |||
| 386 | * can do much more besides (device id 0x60). | 408 | * can do much more besides (device id 0x60). |
| 387 | * The LPC47M997 is undocumented, but seems to be compatible with | 409 | * The LPC47M997 is undocumented, but seems to be compatible with |
| 388 | * the LPC47M192, and has the same device id. | 410 | * the LPC47M192, and has the same device id. |
| 411 | * The LPC47M292 (device id 0x6B) is somewhat compatible, but it | ||
| 412 | * supports a 3rd fan, and the pin configuration registers are | ||
| 413 | * unfortunately different. | ||
| 389 | */ | 414 | */ |
| 390 | if (val == 0x51) | 415 | switch (val) { |
| 391 | printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n"); | 416 | case 0x51: |
| 392 | else if (val == 0x59) | 417 | pr_info(DRVNAME ": Found SMSC LPC47B27x\n"); |
| 393 | printk(KERN_INFO "smsc47m1: Found SMSC " | 418 | sio_data->type = smsc47m1; |
| 394 | "LPC47M10x/LPC47M112/LPC47M13x\n"); | 419 | break; |
| 395 | else if (val == 0x5F) | 420 | case 0x59: |
| 396 | printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n"); | 421 | pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n"); |
| 397 | else if (val == 0x60) | 422 | sio_data->type = smsc47m1; |
| 398 | printk(KERN_INFO "smsc47m1: Found SMSC " | 423 | break; |
| 399 | "LPC47M15x/LPC47M192/LPC47M997\n"); | 424 | case 0x5F: |
| 400 | else { | 425 | pr_info(DRVNAME ": Found SMSC LPC47M14x\n"); |
| 426 | sio_data->type = smsc47m1; | ||
| 427 | break; | ||
| 428 | case 0x60: | ||
| 429 | pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n"); | ||
| 430 | sio_data->type = smsc47m1; | ||
| 431 | break; | ||
| 432 | case 0x6B: | ||
| 433 | pr_info(DRVNAME ": Found SMSC LPC47M292\n"); | ||
| 434 | sio_data->type = smsc47m2; | ||
| 435 | break; | ||
| 436 | default: | ||
| 401 | superio_exit(); | 437 | superio_exit(); |
| 402 | return -ENODEV; | 438 | return -ENODEV; |
| 403 | } | 439 | } |
| @@ -407,7 +443,7 @@ static int __init smsc47m1_find(unsigned short *addr) | |||
| 407 | | superio_inb(SUPERIO_REG_BASE + 1); | 443 | | superio_inb(SUPERIO_REG_BASE + 1); |
| 408 | val = superio_inb(SUPERIO_REG_ACT); | 444 | val = superio_inb(SUPERIO_REG_ACT); |
| 409 | if (*addr == 0 || (val & 0x01) == 0) { | 445 | if (*addr == 0 || (val & 0x01) == 0) { |
| 410 | printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n"); | 446 | pr_info(DRVNAME ": Device is disabled, will not use\n"); |
| 411 | superio_exit(); | 447 | superio_exit(); |
| 412 | return -ENODEV; | 448 | return -ENODEV; |
| 413 | } | 449 | } |
| @@ -416,15 +452,25 @@ static int __init smsc47m1_find(unsigned short *addr) | |||
| 416 | return 0; | 452 | return 0; |
| 417 | } | 453 | } |
| 418 | 454 | ||
| 419 | static int smsc47m1_detect(struct i2c_adapter *adapter) | 455 | static int __devinit smsc47m1_probe(struct platform_device *pdev) |
| 420 | { | 456 | { |
| 421 | struct i2c_client *new_client; | 457 | struct device *dev = &pdev->dev; |
| 458 | struct smsc47m1_sio_data *sio_data = dev->platform_data; | ||
| 422 | struct smsc47m1_data *data; | 459 | struct smsc47m1_data *data; |
| 460 | struct resource *res; | ||
| 423 | int err = 0; | 461 | int err = 0; |
| 424 | int fan1, fan2, pwm1, pwm2; | 462 | int fan1, fan2, fan3, pwm1, pwm2, pwm3; |
| 425 | 463 | ||
| 426 | if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.driver.name)) { | 464 | static const char *names[] = { |
| 427 | dev_err(&adapter->dev, "Region 0x%x already in use!\n", address); | 465 | "smsc47m1", |
| 466 | "smsc47m2", | ||
| 467 | }; | ||
| 468 | |||
| 469 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 470 | if (!request_region(res->start, SMSC_EXTENT, DRVNAME)) { | ||
| 471 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
| 472 | (unsigned long)res->start, | ||
| 473 | (unsigned long)res->end); | ||
| 428 | return -EBUSY; | 474 | return -EBUSY; |
| 429 | } | 475 | } |
| 430 | 476 | ||
| @@ -433,93 +479,114 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) | |||
| 433 | goto error_release; | 479 | goto error_release; |
| 434 | } | 480 | } |
| 435 | 481 | ||
| 436 | new_client = &data->client; | 482 | data->addr = res->start; |
| 437 | i2c_set_clientdata(new_client, data); | 483 | data->type = sio_data->type; |
| 438 | new_client->addr = address; | 484 | data->name = names[sio_data->type]; |
| 439 | mutex_init(&data->lock); | ||
| 440 | new_client->adapter = adapter; | ||
| 441 | new_client->driver = &smsc47m1_driver; | ||
| 442 | new_client->flags = 0; | ||
| 443 | |||
| 444 | strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE); | ||
| 445 | mutex_init(&data->update_lock); | 485 | mutex_init(&data->update_lock); |
| 486 | platform_set_drvdata(pdev, data); | ||
| 446 | 487 | ||
| 447 | /* If no function is properly configured, there's no point in | 488 | /* If no function is properly configured, there's no point in |
| 448 | actually registering the chip. */ | 489 | actually registering the chip. */ |
| 449 | fan1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0)) & 0x05) | 490 | pwm1 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(0)) & 0x05) |
| 450 | == 0x05; | ||
| 451 | fan2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1)) & 0x05) | ||
| 452 | == 0x05; | ||
| 453 | pwm1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05) | ||
| 454 | == 0x04; | 491 | == 0x04; |
| 455 | pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05) | 492 | pwm2 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(1)) & 0x05) |
| 456 | == 0x04; | 493 | == 0x04; |
| 457 | if (!(fan1 || fan2 || pwm1 || pwm2)) { | 494 | if (data->type == smsc47m2) { |
| 458 | dev_warn(&adapter->dev, "Device at 0x%x is not configured, " | 495 | fan1 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN1) |
| 459 | "will not use\n", new_client->addr); | 496 | & 0x0d) == 0x09; |
| 497 | fan2 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN2) | ||
| 498 | & 0x0d) == 0x09; | ||
| 499 | fan3 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN3) | ||
| 500 | & 0x0d) == 0x0d; | ||
| 501 | pwm3 = (smsc47m1_read_value(data, SMSC47M2_REG_PPIN3) | ||
| 502 | & 0x0d) == 0x08; | ||
| 503 | } else { | ||
| 504 | fan1 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(0)) | ||
| 505 | & 0x05) == 0x05; | ||
| 506 | fan2 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(1)) | ||
| 507 | & 0x05) == 0x05; | ||
| 508 | fan3 = 0; | ||
| 509 | pwm3 = 0; | ||
| 510 | } | ||
| 511 | if (!(fan1 || fan2 || fan3 || pwm1 || pwm2 || pwm3)) { | ||
| 512 | dev_warn(dev, "Device not configured, will not use\n"); | ||
| 460 | err = -ENODEV; | 513 | err = -ENODEV; |
| 461 | goto error_free; | 514 | goto error_free; |
| 462 | } | 515 | } |
| 463 | 516 | ||
| 464 | if ((err = i2c_attach_client(new_client))) | ||
| 465 | goto error_free; | ||
| 466 | |||
| 467 | /* Some values (fan min, clock dividers, pwm registers) may be | 517 | /* Some values (fan min, clock dividers, pwm registers) may be |
| 468 | needed before any update is triggered, so we better read them | 518 | needed before any update is triggered, so we better read them |
| 469 | at least once here. We don't usually do it that way, but in | 519 | at least once here. We don't usually do it that way, but in |
| 470 | this particular case, manually reading 5 registers out of 8 | 520 | this particular case, manually reading 5 registers out of 8 |
| 471 | doesn't make much sense and we're better using the existing | 521 | doesn't make much sense and we're better using the existing |
| 472 | function. */ | 522 | function. */ |
| 473 | smsc47m1_update_device(&new_client->dev, 1); | 523 | smsc47m1_update_device(dev, 1); |
| 474 | 524 | ||
| 475 | /* Register sysfs hooks */ | 525 | /* Register sysfs hooks */ |
| 476 | if (fan1) { | 526 | if (fan1) { |
| 477 | if ((err = device_create_file(&new_client->dev, | 527 | if ((err = device_create_file(dev, |
| 478 | &dev_attr_fan1_input)) | 528 | &sensor_dev_attr_fan1_input.dev_attr)) |
| 479 | || (err = device_create_file(&new_client->dev, | 529 | || (err = device_create_file(dev, |
| 480 | &dev_attr_fan1_min)) | 530 | &sensor_dev_attr_fan1_min.dev_attr)) |
| 481 | || (err = device_create_file(&new_client->dev, | 531 | || (err = device_create_file(dev, |
| 482 | &dev_attr_fan1_div))) | 532 | &sensor_dev_attr_fan1_div.dev_attr))) |
| 483 | goto error_remove_files; | 533 | goto error_remove_files; |
| 484 | } else | 534 | } else |
| 485 | dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, " | 535 | dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n"); |
| 486 | "skipping\n"); | ||
| 487 | 536 | ||
| 488 | if (fan2) { | 537 | if (fan2) { |
| 489 | if ((err = device_create_file(&new_client->dev, | 538 | if ((err = device_create_file(dev, |
| 490 | &dev_attr_fan2_input)) | 539 | &sensor_dev_attr_fan2_input.dev_attr)) |
| 491 | || (err = device_create_file(&new_client->dev, | 540 | || (err = device_create_file(dev, |
| 492 | &dev_attr_fan2_min)) | 541 | &sensor_dev_attr_fan2_min.dev_attr)) |
| 493 | || (err = device_create_file(&new_client->dev, | 542 | || (err = device_create_file(dev, |
| 494 | &dev_attr_fan2_div))) | 543 | &sensor_dev_attr_fan2_div.dev_attr))) |
| 495 | goto error_remove_files; | 544 | goto error_remove_files; |
| 496 | } else | 545 | } else |
| 497 | dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, " | 546 | dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n"); |
| 498 | "skipping\n"); | 547 | |
| 548 | if (fan3) { | ||
| 549 | if ((err = device_create_file(dev, | ||
| 550 | &sensor_dev_attr_fan3_input.dev_attr)) | ||
| 551 | || (err = device_create_file(dev, | ||
| 552 | &sensor_dev_attr_fan3_min.dev_attr)) | ||
| 553 | || (err = device_create_file(dev, | ||
| 554 | &sensor_dev_attr_fan3_div.dev_attr))) | ||
| 555 | goto error_remove_files; | ||
| 556 | } else | ||
| 557 | dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n"); | ||
| 499 | 558 | ||
| 500 | if (pwm1) { | 559 | if (pwm1) { |
| 501 | if ((err = device_create_file(&new_client->dev, | 560 | if ((err = device_create_file(dev, |
| 502 | &dev_attr_pwm1)) | 561 | &sensor_dev_attr_pwm1.dev_attr)) |
| 503 | || (err = device_create_file(&new_client->dev, | 562 | || (err = device_create_file(dev, |
| 504 | &dev_attr_pwm1_enable))) | 563 | &sensor_dev_attr_pwm1_enable.dev_attr))) |
| 505 | goto error_remove_files; | 564 | goto error_remove_files; |
| 506 | } else | 565 | } else |
| 507 | dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, " | 566 | dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n"); |
| 508 | "skipping\n"); | 567 | |
| 509 | if (pwm2) { | 568 | if (pwm2) { |
| 510 | if ((err = device_create_file(&new_client->dev, | 569 | if ((err = device_create_file(dev, |
| 511 | &dev_attr_pwm2)) | 570 | &sensor_dev_attr_pwm2.dev_attr)) |
| 512 | || (err = device_create_file(&new_client->dev, | 571 | || (err = device_create_file(dev, |
| 513 | &dev_attr_pwm2_enable))) | 572 | &sensor_dev_attr_pwm2_enable.dev_attr))) |
| 573 | goto error_remove_files; | ||
| 574 | } else | ||
| 575 | dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n"); | ||
| 576 | |||
| 577 | if (pwm3) { | ||
| 578 | if ((err = device_create_file(dev, | ||
| 579 | &sensor_dev_attr_pwm3.dev_attr)) | ||
| 580 | || (err = device_create_file(dev, | ||
| 581 | &sensor_dev_attr_pwm3_enable.dev_attr))) | ||
| 514 | goto error_remove_files; | 582 | goto error_remove_files; |
| 515 | } else | 583 | } else |
| 516 | dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, " | 584 | dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n"); |
| 517 | "skipping\n"); | ||
| 518 | 585 | ||
| 519 | if ((err = device_create_file(&new_client->dev, &dev_attr_alarms))) | 586 | if ((err = device_create_file(dev, &dev_attr_alarms))) |
| 520 | goto error_remove_files; | 587 | goto error_remove_files; |
| 521 | 588 | ||
| 522 | data->class_dev = hwmon_device_register(&new_client->dev); | 589 | data->class_dev = hwmon_device_register(dev); |
| 523 | if (IS_ERR(data->class_dev)) { | 590 | if (IS_ERR(data->class_dev)) { |
| 524 | err = PTR_ERR(data->class_dev); | 591 | err = PTR_ERR(data->class_dev); |
| 525 | goto error_remove_files; | 592 | goto error_remove_files; |
| @@ -528,78 +595,71 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) | |||
| 528 | return 0; | 595 | return 0; |
| 529 | 596 | ||
| 530 | error_remove_files: | 597 | error_remove_files: |
| 531 | sysfs_remove_group(&new_client->dev.kobj, &smsc47m1_group); | 598 | sysfs_remove_group(&dev->kobj, &smsc47m1_group); |
| 532 | i2c_detach_client(new_client); | ||
| 533 | error_free: | 599 | error_free: |
| 534 | kfree(data); | 600 | kfree(data); |
| 535 | error_release: | 601 | error_release: |
| 536 | release_region(address, SMSC_EXTENT); | 602 | release_region(res->start, SMSC_EXTENT); |
| 537 | return err; | 603 | return err; |
| 538 | } | 604 | } |
| 539 | 605 | ||
| 540 | static int smsc47m1_detach_client(struct i2c_client *client) | 606 | static int __devexit smsc47m1_remove(struct platform_device *pdev) |
| 541 | { | 607 | { |
| 542 | struct smsc47m1_data *data = i2c_get_clientdata(client); | 608 | struct smsc47m1_data *data = platform_get_drvdata(pdev); |
| 543 | int err; | 609 | struct resource *res; |
| 544 | 610 | ||
| 611 | platform_set_drvdata(pdev, NULL); | ||
| 545 | hwmon_device_unregister(data->class_dev); | 612 | hwmon_device_unregister(data->class_dev); |
| 546 | sysfs_remove_group(&client->dev.kobj, &smsc47m1_group); | 613 | sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group); |
| 547 | |||
| 548 | if ((err = i2c_detach_client(client))) | ||
| 549 | return err; | ||
| 550 | 614 | ||
| 551 | release_region(client->addr, SMSC_EXTENT); | 615 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
| 616 | release_region(res->start, SMSC_EXTENT); | ||
| 552 | kfree(data); | 617 | kfree(data); |
| 553 | 618 | ||
| 554 | return 0; | 619 | return 0; |
| 555 | } | 620 | } |
| 556 | 621 | ||
| 557 | static int smsc47m1_read_value(struct i2c_client *client, u8 reg) | ||
| 558 | { | ||
| 559 | int res; | ||
| 560 | |||
| 561 | mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); | ||
| 562 | res = inb_p(client->addr + reg); | ||
| 563 | mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); | ||
| 564 | return res; | ||
| 565 | } | ||
| 566 | |||
| 567 | static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value) | ||
| 568 | { | ||
| 569 | mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); | ||
| 570 | outb_p(value, client->addr + reg); | ||
| 571 | mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); | ||
| 572 | } | ||
| 573 | |||
| 574 | static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, | 622 | static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, |
| 575 | int init) | 623 | int init) |
| 576 | { | 624 | { |
| 577 | struct i2c_client *client = to_i2c_client(dev); | 625 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
| 578 | struct smsc47m1_data *data = i2c_get_clientdata(client); | ||
| 579 | 626 | ||
| 580 | mutex_lock(&data->update_lock); | 627 | mutex_lock(&data->update_lock); |
| 581 | 628 | ||
| 582 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { | 629 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { |
| 583 | int i; | 630 | int i, fan_nr; |
| 584 | 631 | fan_nr = data->type == smsc47m2 ? 3 : 2; | |
| 585 | for (i = 0; i < 2; i++) { | 632 | |
| 586 | data->fan[i] = smsc47m1_read_value(client, | 633 | for (i = 0; i < fan_nr; i++) { |
| 587 | SMSC47M1_REG_FAN(i)); | 634 | data->fan[i] = smsc47m1_read_value(data, |
| 588 | data->fan_preload[i] = smsc47m1_read_value(client, | 635 | SMSC47M1_REG_FAN[i]); |
| 589 | SMSC47M1_REG_FAN_PRELOAD(i)); | 636 | data->fan_preload[i] = smsc47m1_read_value(data, |
| 590 | data->pwm[i] = smsc47m1_read_value(client, | 637 | SMSC47M1_REG_FAN_PRELOAD[i]); |
| 591 | SMSC47M1_REG_PWM(i)); | 638 | data->pwm[i] = smsc47m1_read_value(data, |
| 639 | SMSC47M1_REG_PWM[i]); | ||
| 592 | } | 640 | } |
| 593 | 641 | ||
| 594 | i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV); | 642 | i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV); |
| 595 | data->fan_div[0] = (i >> 4) & 0x03; | 643 | data->fan_div[0] = (i >> 4) & 0x03; |
| 596 | data->fan_div[1] = i >> 6; | 644 | data->fan_div[1] = i >> 6; |
| 597 | 645 | ||
| 598 | data->alarms = smsc47m1_read_value(client, | 646 | data->alarms = smsc47m1_read_value(data, |
| 599 | SMSC47M1_REG_ALARM) >> 6; | 647 | SMSC47M1_REG_ALARM) >> 6; |
| 600 | /* Clear alarms if needed */ | 648 | /* Clear alarms if needed */ |
| 601 | if (data->alarms) | 649 | if (data->alarms) |
| 602 | smsc47m1_write_value(client, SMSC47M1_REG_ALARM, 0xC0); | 650 | smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0); |
| 651 | |||
| 652 | if (fan_nr >= 3) { | ||
| 653 | data->fan_div[2] = (smsc47m1_read_value(data, | ||
| 654 | SMSC47M2_REG_FANDIV3) >> 4) & 0x03; | ||
| 655 | data->alarms |= (smsc47m1_read_value(data, | ||
| 656 | SMSC47M2_REG_ALARM6) & 0x40) >> 4; | ||
| 657 | /* Clear alarm if needed */ | ||
| 658 | if (data->alarms & 0x04) | ||
| 659 | smsc47m1_write_value(data, | ||
| 660 | SMSC47M2_REG_ALARM6, | ||
| 661 | 0x40); | ||
| 662 | } | ||
| 603 | 663 | ||
| 604 | data->last_updated = jiffies; | 664 | data->last_updated = jiffies; |
| 605 | } | 665 | } |
| @@ -608,18 +668,86 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, | |||
| 608 | return data; | 668 | return data; |
| 609 | } | 669 | } |
| 610 | 670 | ||
| 671 | static int __init smsc47m1_device_add(unsigned short address, | ||
| 672 | const struct smsc47m1_sio_data *sio_data) | ||
| 673 | { | ||
| 674 | struct resource res = { | ||
| 675 | .start = address, | ||
| 676 | .end = address + SMSC_EXTENT - 1, | ||
| 677 | .name = DRVNAME, | ||
| 678 | .flags = IORESOURCE_IO, | ||
| 679 | }; | ||
| 680 | int err; | ||
| 681 | |||
| 682 | pdev = platform_device_alloc(DRVNAME, address); | ||
| 683 | if (!pdev) { | ||
| 684 | err = -ENOMEM; | ||
| 685 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | ||
| 686 | goto exit; | ||
| 687 | } | ||
| 688 | |||
| 689 | err = platform_device_add_resources(pdev, &res, 1); | ||
| 690 | if (err) { | ||
| 691 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | ||
| 692 | "(%d)\n", err); | ||
| 693 | goto exit_device_put; | ||
| 694 | } | ||
| 695 | |||
| 696 | pdev->dev.platform_data = kmalloc(sizeof(struct smsc47m1_sio_data), | ||
| 697 | GFP_KERNEL); | ||
| 698 | if (!pdev->dev.platform_data) { | ||
| 699 | err = -ENOMEM; | ||
| 700 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | ||
| 701 | goto exit_device_put; | ||
| 702 | } | ||
| 703 | memcpy(pdev->dev.platform_data, sio_data, | ||
| 704 | sizeof(struct smsc47m1_sio_data)); | ||
| 705 | |||
| 706 | err = platform_device_add(pdev); | ||
| 707 | if (err) { | ||
| 708 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
| 709 | err); | ||
| 710 | goto exit_device_put; | ||
| 711 | } | ||
| 712 | |||
| 713 | return 0; | ||
| 714 | |||
| 715 | exit_device_put: | ||
| 716 | platform_device_put(pdev); | ||
| 717 | exit: | ||
| 718 | return err; | ||
| 719 | } | ||
| 720 | |||
| 611 | static int __init sm_smsc47m1_init(void) | 721 | static int __init sm_smsc47m1_init(void) |
| 612 | { | 722 | { |
| 613 | if (smsc47m1_find(&address)) { | 723 | int err; |
| 724 | unsigned short address; | ||
| 725 | struct smsc47m1_sio_data sio_data; | ||
| 726 | |||
| 727 | if (smsc47m1_find(&address, &sio_data)) | ||
| 614 | return -ENODEV; | 728 | return -ENODEV; |
| 615 | } | ||
| 616 | 729 | ||
| 617 | return i2c_isa_add_driver(&smsc47m1_driver); | 730 | err = platform_driver_register(&smsc47m1_driver); |
| 731 | if (err) | ||
| 732 | goto exit; | ||
| 733 | |||
| 734 | /* Sets global pdev as a side effect */ | ||
| 735 | err = smsc47m1_device_add(address, &sio_data); | ||
| 736 | if (err) | ||
| 737 | goto exit_driver; | ||
| 738 | |||
| 739 | return 0; | ||
| 740 | |||
| 741 | exit_driver: | ||
| 742 | platform_driver_unregister(&smsc47m1_driver); | ||
| 743 | exit: | ||
| 744 | return err; | ||
| 618 | } | 745 | } |
| 619 | 746 | ||
| 620 | static void __exit sm_smsc47m1_exit(void) | 747 | static void __exit sm_smsc47m1_exit(void) |
| 621 | { | 748 | { |
| 622 | i2c_isa_del_driver(&smsc47m1_driver); | 749 | platform_device_unregister(pdev); |
| 750 | platform_driver_unregister(&smsc47m1_driver); | ||
| 623 | } | 751 | } |
| 624 | 752 | ||
| 625 | MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>"); | 753 | MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>"); |
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index a6833f437395..a012f396f354 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | smsc47m192.c - Support for hardware monitoring block of | 2 | smsc47m192.c - Support for hardware monitoring block of |
| 3 | SMSC LPC47M192 and LPC47M997 Super I/O chips | 3 | SMSC LPC47M192 and compatible Super I/O chips |
| 4 | 4 | ||
| 5 | Copyright (C) 2006 Hartmut Rick <linux@rick.claranet.de> | 5 | Copyright (C) 2006 Hartmut Rick <linux@rick.claranet.de> |
| 6 | 6 | ||
| @@ -518,7 +518,7 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address, | |||
| 518 | && (i2c_smbus_read_byte_data(client, | 518 | && (i2c_smbus_read_byte_data(client, |
| 519 | SMSC47M192_REG_VID4) & 0xfe) == 0x80) { | 519 | SMSC47M192_REG_VID4) & 0xfe) == 0x80) { |
| 520 | dev_info(&adapter->dev, | 520 | dev_info(&adapter->dev, |
| 521 | "found SMSC47M192 or SMSC47M997, " | 521 | "found SMSC47M192 or compatible, " |
| 522 | "version 2, stepping A%d\n", version & 0x0f); | 522 | "version 2, stepping A%d\n", version & 0x0f); |
| 523 | } else { | 523 | } else { |
| 524 | dev_dbg(&adapter->dev, | 524 | dev_dbg(&adapter->dev, |
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 89c23d6add7b..9f3e332c5b7f 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/hwmon-vid.h> | 31 | #include <linux/hwmon-vid.h> |
| 32 | #include <linux/err.h> | 32 | #include <linux/err.h> |
| 33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
| 34 | #include <linux/ioport.h> | ||
| 34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
| 35 | 36 | ||
| 36 | static int uch_config = -1; | 37 | static int uch_config = -1; |
| @@ -1130,6 +1131,12 @@ static int __devinit vt1211_probe(struct platform_device *pdev) | |||
| 1130 | } | 1131 | } |
| 1131 | 1132 | ||
| 1132 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1133 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
| 1134 | if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) { | ||
| 1135 | err = -EBUSY; | ||
| 1136 | dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", | ||
| 1137 | (unsigned long)res->start, (unsigned long)res->end); | ||
| 1138 | goto EXIT_KFREE; | ||
| 1139 | } | ||
| 1133 | data->addr = res->start; | 1140 | data->addr = res->start; |
| 1134 | data->name = DRVNAME; | 1141 | data->name = DRVNAME; |
| 1135 | mutex_init(&data->update_lock); | 1142 | mutex_init(&data->update_lock); |
| @@ -1197,6 +1204,8 @@ EXIT_DEV_REMOVE: | |||
| 1197 | dev_err(dev, "Sysfs interface creation failed (%d)\n", err); | 1204 | dev_err(dev, "Sysfs interface creation failed (%d)\n", err); |
| 1198 | EXIT_DEV_REMOVE_SILENT: | 1205 | EXIT_DEV_REMOVE_SILENT: |
| 1199 | vt1211_remove_sysfs(pdev); | 1206 | vt1211_remove_sysfs(pdev); |
| 1207 | release_region(res->start, res->end - res->start + 1); | ||
| 1208 | EXIT_KFREE: | ||
| 1200 | platform_set_drvdata(pdev, NULL); | 1209 | platform_set_drvdata(pdev, NULL); |
| 1201 | kfree(data); | 1210 | kfree(data); |
| 1202 | EXIT: | 1211 | EXIT: |
| @@ -1206,12 +1215,16 @@ EXIT: | |||
| 1206 | static int __devexit vt1211_remove(struct platform_device *pdev) | 1215 | static int __devexit vt1211_remove(struct platform_device *pdev) |
| 1207 | { | 1216 | { |
| 1208 | struct vt1211_data *data = platform_get_drvdata(pdev); | 1217 | struct vt1211_data *data = platform_get_drvdata(pdev); |
| 1218 | struct resource *res; | ||
| 1209 | 1219 | ||
| 1210 | hwmon_device_unregister(data->class_dev); | 1220 | hwmon_device_unregister(data->class_dev); |
| 1211 | vt1211_remove_sysfs(pdev); | 1221 | vt1211_remove_sysfs(pdev); |
| 1212 | platform_set_drvdata(pdev, NULL); | 1222 | platform_set_drvdata(pdev, NULL); |
| 1213 | kfree(data); | 1223 | kfree(data); |
| 1214 | 1224 | ||
| 1225 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 1226 | release_region(res->start, res->end - res->start + 1); | ||
| 1227 | |||
| 1215 | return 0; | 1228 | return 0; |
| 1216 | } | 1229 | } |
| 1217 | 1230 | ||
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index d7e240635b3b..a5b774b07cbd 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | Philip Edelbrock <phil@netroedge.com>, | 5 | Philip Edelbrock <phil@netroedge.com>, |
| 6 | and Mark Studebaker <mdsxyz123@yahoo.com> | 6 | and Mark Studebaker <mdsxyz123@yahoo.com> |
| 7 | Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org> | 7 | Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org> |
| 8 | Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> | ||
| 8 | 9 | ||
| 9 | This program is free software; you can redistribute it and/or modify | 10 | This program is free software; you can redistribute it and/or modify |
| 10 | it under the terms of the GNU General Public License as published by | 11 | it under the terms of the GNU General Public License as published by |
| @@ -42,15 +43,20 @@ | |||
| 42 | #include <linux/init.h> | 43 | #include <linux/init.h> |
| 43 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
| 44 | #include <linux/jiffies.h> | 45 | #include <linux/jiffies.h> |
| 45 | #include <linux/i2c.h> | 46 | #include <linux/platform_device.h> |
| 46 | #include <linux/i2c-isa.h> | ||
| 47 | #include <linux/hwmon.h> | 47 | #include <linux/hwmon.h> |
| 48 | #include <linux/hwmon-vid.h> | 48 | #include <linux/hwmon-vid.h> |
| 49 | #include <linux/err.h> | 49 | #include <linux/err.h> |
| 50 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
| 51 | #include <linux/ioport.h> | ||
| 51 | #include <asm/io.h> | 52 | #include <asm/io.h> |
| 52 | #include "lm75.h" | 53 | #include "lm75.h" |
| 53 | 54 | ||
| 55 | static struct platform_device *pdev; | ||
| 56 | |||
| 57 | #define DRVNAME "w83627hf" | ||
| 58 | enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; | ||
| 59 | |||
| 54 | static u16 force_addr; | 60 | static u16 force_addr; |
| 55 | module_param(force_addr, ushort, 0); | 61 | module_param(force_addr, ushort, 0); |
| 56 | MODULE_PARM_DESC(force_addr, | 62 | MODULE_PARM_DESC(force_addr, |
| @@ -60,12 +66,6 @@ module_param(force_i2c, byte, 0); | |||
| 60 | MODULE_PARM_DESC(force_i2c, | 66 | MODULE_PARM_DESC(force_i2c, |
| 61 | "Initialize the i2c address of the sensors"); | 67 | "Initialize the i2c address of the sensors"); |
| 62 | 68 | ||
| 63 | /* The actual ISA address is read from Super-I/O configuration space */ | ||
| 64 | static unsigned short address; | ||
| 65 | |||
| 66 | /* Insmod parameters */ | ||
| 67 | enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; | ||
| 68 | |||
| 69 | static int reset; | 69 | static int reset; |
| 70 | module_param(reset, bool, 0); | 70 | module_param(reset, bool, 0); |
| 71 | MODULE_PARM_DESC(reset, "Set to one to reset chip on load"); | 71 | MODULE_PARM_DESC(reset, "Set to one to reset chip on load"); |
| @@ -156,9 +156,9 @@ superio_exit(void) | |||
| 156 | #define WINB_REGION_OFFSET 5 | 156 | #define WINB_REGION_OFFSET 5 |
| 157 | #define WINB_REGION_SIZE 2 | 157 | #define WINB_REGION_SIZE 2 |
| 158 | 158 | ||
| 159 | /* Where are the sensors address/data registers relative to the base address */ | 159 | /* Where are the sensors address/data registers relative to the region offset */ |
| 160 | #define W83781D_ADDR_REG_OFFSET 5 | 160 | #define W83781D_ADDR_REG_OFFSET 0 |
| 161 | #define W83781D_DATA_REG_OFFSET 6 | 161 | #define W83781D_DATA_REG_OFFSET 1 |
| 162 | 162 | ||
| 163 | /* The W83781D registers */ | 163 | /* The W83781D registers */ |
| 164 | /* The W83782D registers for nr=7,8 are in bank 5 */ | 164 | /* The W83782D registers for nr=7,8 are in bank 5 */ |
| @@ -289,7 +289,8 @@ static inline u8 DIV_TO_REG(long val) | |||
| 289 | /* For each registered chip, we need to keep some data in memory. | 289 | /* For each registered chip, we need to keep some data in memory. |
| 290 | The structure is dynamically allocated. */ | 290 | The structure is dynamically allocated. */ |
| 291 | struct w83627hf_data { | 291 | struct w83627hf_data { |
| 292 | struct i2c_client client; | 292 | unsigned short addr; |
| 293 | const char *name; | ||
| 293 | struct class_device *class_dev; | 294 | struct class_device *class_dev; |
| 294 | struct mutex lock; | 295 | struct mutex lock; |
| 295 | enum chips type; | 296 | enum chips type; |
| @@ -298,9 +299,6 @@ struct w83627hf_data { | |||
| 298 | char valid; /* !=0 if following fields are valid */ | 299 | char valid; /* !=0 if following fields are valid */ |
| 299 | unsigned long last_updated; /* In jiffies */ | 300 | unsigned long last_updated; /* In jiffies */ |
| 300 | 301 | ||
| 301 | struct i2c_client *lm75; /* for secondary I2C addresses */ | ||
| 302 | /* pointer to array of 2 subclients */ | ||
| 303 | |||
| 304 | u8 in[9]; /* Register value */ | 302 | u8 in[9]; /* Register value */ |
| 305 | u8 in_max[9]; /* Register value */ | 303 | u8 in_max[9]; /* Register value */ |
| 306 | u8 in_min[9]; /* Register value */ | 304 | u8 in_min[9]; /* Register value */ |
| @@ -327,22 +325,26 @@ struct w83627hf_data { | |||
| 327 | u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ | 325 | u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ |
| 328 | }; | 326 | }; |
| 329 | 327 | ||
| 328 | struct w83627hf_sio_data { | ||
| 329 | enum chips type; | ||
| 330 | }; | ||
| 331 | |||
| 330 | 332 | ||
| 331 | static int w83627hf_detect(struct i2c_adapter *adapter); | 333 | static int w83627hf_probe(struct platform_device *pdev); |
| 332 | static int w83627hf_detach_client(struct i2c_client *client); | 334 | static int w83627hf_remove(struct platform_device *pdev); |
| 333 | 335 | ||
| 334 | static int w83627hf_read_value(struct i2c_client *client, u16 reg); | 336 | static int w83627hf_read_value(struct w83627hf_data *data, u16 reg); |
| 335 | static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value); | 337 | static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value); |
| 336 | static struct w83627hf_data *w83627hf_update_device(struct device *dev); | 338 | static struct w83627hf_data *w83627hf_update_device(struct device *dev); |
| 337 | static void w83627hf_init_client(struct i2c_client *client); | 339 | static void w83627hf_init_device(struct platform_device *pdev); |
| 338 | 340 | ||
| 339 | static struct i2c_driver w83627hf_driver = { | 341 | static struct platform_driver w83627hf_driver = { |
| 340 | .driver = { | 342 | .driver = { |
| 341 | .owner = THIS_MODULE, | 343 | .owner = THIS_MODULE, |
| 342 | .name = "w83627hf", | 344 | .name = DRVNAME, |
| 343 | }, | 345 | }, |
| 344 | .attach_adapter = w83627hf_detect, | 346 | .probe = w83627hf_probe, |
| 345 | .detach_client = w83627hf_detach_client, | 347 | .remove = __devexit_p(w83627hf_remove), |
| 346 | }; | 348 | }; |
| 347 | 349 | ||
| 348 | /* following are the sysfs callback functions */ | 350 | /* following are the sysfs callback functions */ |
| @@ -360,15 +362,14 @@ show_in_reg(in_max) | |||
| 360 | static ssize_t \ | 362 | static ssize_t \ |
| 361 | store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | 363 | store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ |
| 362 | { \ | 364 | { \ |
| 363 | struct i2c_client *client = to_i2c_client(dev); \ | 365 | struct w83627hf_data *data = dev_get_drvdata(dev); \ |
| 364 | struct w83627hf_data *data = i2c_get_clientdata(client); \ | ||
| 365 | u32 val; \ | 366 | u32 val; \ |
| 366 | \ | 367 | \ |
| 367 | val = simple_strtoul(buf, NULL, 10); \ | 368 | val = simple_strtoul(buf, NULL, 10); \ |
| 368 | \ | 369 | \ |
| 369 | mutex_lock(&data->update_lock); \ | 370 | mutex_lock(&data->update_lock); \ |
| 370 | data->in_##reg[nr] = IN_TO_REG(val); \ | 371 | data->in_##reg[nr] = IN_TO_REG(val); \ |
| 371 | w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \ | 372 | w83627hf_write_value(data, W83781D_REG_IN_##REG(nr), \ |
| 372 | data->in_##reg[nr]); \ | 373 | data->in_##reg[nr]); \ |
| 373 | \ | 374 | \ |
| 374 | mutex_unlock(&data->update_lock); \ | 375 | mutex_unlock(&data->update_lock); \ |
| @@ -452,8 +453,7 @@ static ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *at | |||
| 452 | static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr, | 453 | static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr, |
| 453 | const char *buf, size_t count) | 454 | const char *buf, size_t count) |
| 454 | { | 455 | { |
| 455 | struct i2c_client *client = to_i2c_client(dev); | 456 | struct w83627hf_data *data = dev_get_drvdata(dev); |
| 456 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 457 | u32 val; | 457 | u32 val; |
| 458 | 458 | ||
| 459 | val = simple_strtoul(buf, NULL, 10); | 459 | val = simple_strtoul(buf, NULL, 10); |
| @@ -472,7 +472,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a | |||
| 472 | /* use VRM8 (standard) calculation */ | 472 | /* use VRM8 (standard) calculation */ |
| 473 | data->in_min[0] = IN_TO_REG(val); | 473 | data->in_min[0] = IN_TO_REG(val); |
| 474 | 474 | ||
| 475 | w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]); | 475 | w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]); |
| 476 | mutex_unlock(&data->update_lock); | 476 | mutex_unlock(&data->update_lock); |
| 477 | return count; | 477 | return count; |
| 478 | } | 478 | } |
| @@ -480,8 +480,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a | |||
| 480 | static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr, | 480 | static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr, |
| 481 | const char *buf, size_t count) | 481 | const char *buf, size_t count) |
| 482 | { | 482 | { |
| 483 | struct i2c_client *client = to_i2c_client(dev); | 483 | struct w83627hf_data *data = dev_get_drvdata(dev); |
| 484 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 485 | u32 val; | 484 | u32 val; |
| 486 | 485 | ||
| 487 | val = simple_strtoul(buf, NULL, 10); | 486 | val = simple_strtoul(buf, NULL, 10); |
| @@ -500,7 +499,7 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a | |||
| 500 | /* use VRM8 (standard) calculation */ | 499 | /* use VRM8 (standard) calculation */ |
| 501 | data->in_max[0] = IN_TO_REG(val); | 500 | data->in_max[0] = IN_TO_REG(val); |
| 502 | 501 | ||
| 503 | w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]); | 502 | w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]); |
| 504 | mutex_unlock(&data->update_lock); | 503 | mutex_unlock(&data->update_lock); |
| 505 | return count; | 504 | return count; |
| 506 | } | 505 | } |
| @@ -525,8 +524,7 @@ show_fan_reg(fan_min); | |||
| 525 | static ssize_t | 524 | static ssize_t |
| 526 | store_fan_min(struct device *dev, const char *buf, size_t count, int nr) | 525 | store_fan_min(struct device *dev, const char *buf, size_t count, int nr) |
| 527 | { | 526 | { |
| 528 | struct i2c_client *client = to_i2c_client(dev); | 527 | struct w83627hf_data *data = dev_get_drvdata(dev); |
| 529 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 530 | u32 val; | 528 | u32 val; |
| 531 | 529 | ||
| 532 | val = simple_strtoul(buf, NULL, 10); | 530 | val = simple_strtoul(buf, NULL, 10); |
| @@ -534,7 +532,7 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) | |||
| 534 | mutex_lock(&data->update_lock); | 532 | mutex_lock(&data->update_lock); |
| 535 | data->fan_min[nr - 1] = | 533 | data->fan_min[nr - 1] = |
| 536 | FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); | 534 | FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); |
| 537 | w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr), | 535 | w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr), |
| 538 | data->fan_min[nr - 1]); | 536 | data->fan_min[nr - 1]); |
| 539 | 537 | ||
| 540 | mutex_unlock(&data->update_lock); | 538 | mutex_unlock(&data->update_lock); |
| @@ -587,8 +585,7 @@ show_temp_reg(temp_max_hyst); | |||
| 587 | static ssize_t \ | 585 | static ssize_t \ |
| 588 | store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | 586 | store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ |
| 589 | { \ | 587 | { \ |
| 590 | struct i2c_client *client = to_i2c_client(dev); \ | 588 | struct w83627hf_data *data = dev_get_drvdata(dev); \ |
| 591 | struct w83627hf_data *data = i2c_get_clientdata(client); \ | ||
| 592 | u32 val; \ | 589 | u32 val; \ |
| 593 | \ | 590 | \ |
| 594 | val = simple_strtoul(buf, NULL, 10); \ | 591 | val = simple_strtoul(buf, NULL, 10); \ |
| @@ -597,11 +594,11 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | |||
| 597 | \ | 594 | \ |
| 598 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ | 595 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ |
| 599 | data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ | 596 | data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ |
| 600 | w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \ | 597 | w83627hf_write_value(data, W83781D_REG_TEMP_##REG(nr), \ |
| 601 | data->temp_##reg##_add[nr-2]); \ | 598 | data->temp_##reg##_add[nr-2]); \ |
| 602 | } else { /* TEMP1 */ \ | 599 | } else { /* TEMP1 */ \ |
| 603 | data->temp_##reg = TEMP_TO_REG(val); \ | 600 | data->temp_##reg = TEMP_TO_REG(val); \ |
| 604 | w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \ | 601 | w83627hf_write_value(data, W83781D_REG_TEMP_##REG(nr), \ |
| 605 | data->temp_##reg); \ | 602 | data->temp_##reg); \ |
| 606 | } \ | 603 | } \ |
| 607 | \ | 604 | \ |
| @@ -659,8 +656,7 @@ show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
| 659 | static ssize_t | 656 | static ssize_t |
| 660 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 657 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
| 661 | { | 658 | { |
| 662 | struct i2c_client *client = to_i2c_client(dev); | 659 | struct w83627hf_data *data = dev_get_drvdata(dev); |
| 663 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 664 | u32 val; | 660 | u32 val; |
| 665 | 661 | ||
| 666 | val = simple_strtoul(buf, NULL, 10); | 662 | val = simple_strtoul(buf, NULL, 10); |
| @@ -695,8 +691,7 @@ static ssize_t | |||
| 695 | store_beep_reg(struct device *dev, const char *buf, size_t count, | 691 | store_beep_reg(struct device *dev, const char *buf, size_t count, |
| 696 | int update_mask) | 692 | int update_mask) |
| 697 | { | 693 | { |
| 698 | struct i2c_client *client = to_i2c_client(dev); | 694 | struct w83627hf_data *data = dev_get_drvdata(dev); |
| 699 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 700 | u32 val, val2; | 695 | u32 val, val2; |
| 701 | 696 | ||
| 702 | val = simple_strtoul(buf, NULL, 10); | 697 | val = simple_strtoul(buf, NULL, 10); |
| @@ -705,18 +700,18 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, | |||
| 705 | 700 | ||
| 706 | if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ | 701 | if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ |
| 707 | data->beep_mask = BEEP_MASK_TO_REG(val); | 702 | data->beep_mask = BEEP_MASK_TO_REG(val); |
| 708 | w83627hf_write_value(client, W83781D_REG_BEEP_INTS1, | 703 | w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, |
| 709 | data->beep_mask & 0xff); | 704 | data->beep_mask & 0xff); |
| 710 | w83627hf_write_value(client, W83781D_REG_BEEP_INTS3, | 705 | w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, |
| 711 | ((data->beep_mask) >> 16) & 0xff); | 706 | ((data->beep_mask) >> 16) & 0xff); |
| 712 | val2 = (data->beep_mask >> 8) & 0x7f; | 707 | val2 = (data->beep_mask >> 8) & 0x7f; |
| 713 | } else { /* We are storing beep_enable */ | 708 | } else { /* We are storing beep_enable */ |
| 714 | val2 = | 709 | val2 = |
| 715 | w83627hf_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f; | 710 | w83627hf_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f; |
| 716 | data->beep_enable = BEEP_ENABLE_TO_REG(val); | 711 | data->beep_enable = BEEP_ENABLE_TO_REG(val); |
| 717 | } | 712 | } |
| 718 | 713 | ||
| 719 | w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, | 714 | w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, |
| 720 | val2 | data->beep_enable << 7); | 715 | val2 | data->beep_enable << 7); |
| 721 | 716 | ||
| 722 | mutex_unlock(&data->update_lock); | 717 | mutex_unlock(&data->update_lock); |
| @@ -754,8 +749,7 @@ show_fan_div_reg(struct device *dev, char *buf, int nr) | |||
| 754 | static ssize_t | 749 | static ssize_t |
| 755 | store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) | 750 | store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) |
| 756 | { | 751 | { |
| 757 | struct i2c_client *client = to_i2c_client(dev); | 752 | struct w83627hf_data *data = dev_get_drvdata(dev); |
| 758 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 759 | unsigned long min; | 753 | unsigned long min; |
| 760 | u8 reg; | 754 | u8 reg; |
| 761 | unsigned long val = simple_strtoul(buf, NULL, 10); | 755 | unsigned long val = simple_strtoul(buf, NULL, 10); |
| @@ -768,19 +762,19 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
| 768 | 762 | ||
| 769 | data->fan_div[nr] = DIV_TO_REG(val); | 763 | data->fan_div[nr] = DIV_TO_REG(val); |
| 770 | 764 | ||
| 771 | reg = (w83627hf_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) | 765 | reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) |
| 772 | & (nr==0 ? 0xcf : 0x3f)) | 766 | & (nr==0 ? 0xcf : 0x3f)) |
| 773 | | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); | 767 | | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); |
| 774 | w83627hf_write_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); | 768 | w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); |
| 775 | 769 | ||
| 776 | reg = (w83627hf_read_value(client, W83781D_REG_VBAT) | 770 | reg = (w83627hf_read_value(data, W83781D_REG_VBAT) |
| 777 | & ~(1 << (5 + nr))) | 771 | & ~(1 << (5 + nr))) |
| 778 | | ((data->fan_div[nr] & 0x04) << (3 + nr)); | 772 | | ((data->fan_div[nr] & 0x04) << (3 + nr)); |
| 779 | w83627hf_write_value(client, W83781D_REG_VBAT, reg); | 773 | w83627hf_write_value(data, W83781D_REG_VBAT, reg); |
| 780 | 774 | ||
| 781 | /* Restore fan_min */ | 775 | /* Restore fan_min */ |
| 782 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); | 776 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); |
| 783 | w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); | 777 | w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); |
| 784 | 778 | ||
| 785 | mutex_unlock(&data->update_lock); | 779 | mutex_unlock(&data->update_lock); |
| 786 | return count; | 780 | return count; |
| @@ -814,8 +808,7 @@ show_pwm_reg(struct device *dev, char *buf, int nr) | |||
| 814 | static ssize_t | 808 | static ssize_t |
| 815 | store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) | 809 | store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) |
| 816 | { | 810 | { |
| 817 | struct i2c_client *client = to_i2c_client(dev); | 811 | struct w83627hf_data *data = dev_get_drvdata(dev); |
| 818 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 819 | u32 val; | 812 | u32 val; |
| 820 | 813 | ||
| 821 | val = simple_strtoul(buf, NULL, 10); | 814 | val = simple_strtoul(buf, NULL, 10); |
| @@ -825,14 +818,14 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
| 825 | if (data->type == w83627thf) { | 818 | if (data->type == w83627thf) { |
| 826 | /* bits 0-3 are reserved in 627THF */ | 819 | /* bits 0-3 are reserved in 627THF */ |
| 827 | data->pwm[nr - 1] = PWM_TO_REG(val) & 0xf0; | 820 | data->pwm[nr - 1] = PWM_TO_REG(val) & 0xf0; |
| 828 | w83627hf_write_value(client, | 821 | w83627hf_write_value(data, |
| 829 | W836X7HF_REG_PWM(data->type, nr), | 822 | W836X7HF_REG_PWM(data->type, nr), |
| 830 | data->pwm[nr - 1] | | 823 | data->pwm[nr - 1] | |
| 831 | (w83627hf_read_value(client, | 824 | (w83627hf_read_value(data, |
| 832 | W836X7HF_REG_PWM(data->type, nr)) & 0x0f)); | 825 | W836X7HF_REG_PWM(data->type, nr)) & 0x0f)); |
| 833 | } else { | 826 | } else { |
| 834 | data->pwm[nr - 1] = PWM_TO_REG(val); | 827 | data->pwm[nr - 1] = PWM_TO_REG(val); |
| 835 | w83627hf_write_value(client, | 828 | w83627hf_write_value(data, |
| 836 | W836X7HF_REG_PWM(data->type, nr), | 829 | W836X7HF_REG_PWM(data->type, nr), |
| 837 | data->pwm[nr - 1]); | 830 | data->pwm[nr - 1]); |
| 838 | } | 831 | } |
| @@ -868,8 +861,7 @@ show_sensor_reg(struct device *dev, char *buf, int nr) | |||
| 868 | static ssize_t | 861 | static ssize_t |
| 869 | store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | 862 | store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) |
| 870 | { | 863 | { |
| 871 | struct i2c_client *client = to_i2c_client(dev); | 864 | struct w83627hf_data *data = dev_get_drvdata(dev); |
| 872 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 873 | u32 val, tmp; | 865 | u32 val, tmp; |
| 874 | 866 | ||
| 875 | val = simple_strtoul(buf, NULL, 10); | 867 | val = simple_strtoul(buf, NULL, 10); |
| @@ -878,31 +870,31 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
| 878 | 870 | ||
| 879 | switch (val) { | 871 | switch (val) { |
| 880 | case 1: /* PII/Celeron diode */ | 872 | case 1: /* PII/Celeron diode */ |
| 881 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); | 873 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); |
| 882 | w83627hf_write_value(client, W83781D_REG_SCFG1, | 874 | w83627hf_write_value(data, W83781D_REG_SCFG1, |
| 883 | tmp | BIT_SCFG1[nr - 1]); | 875 | tmp | BIT_SCFG1[nr - 1]); |
| 884 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG2); | 876 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); |
| 885 | w83627hf_write_value(client, W83781D_REG_SCFG2, | 877 | w83627hf_write_value(data, W83781D_REG_SCFG2, |
| 886 | tmp | BIT_SCFG2[nr - 1]); | 878 | tmp | BIT_SCFG2[nr - 1]); |
| 887 | data->sens[nr - 1] = val; | 879 | data->sens[nr - 1] = val; |
| 888 | break; | 880 | break; |
| 889 | case 2: /* 3904 */ | 881 | case 2: /* 3904 */ |
| 890 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); | 882 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); |
| 891 | w83627hf_write_value(client, W83781D_REG_SCFG1, | 883 | w83627hf_write_value(data, W83781D_REG_SCFG1, |
| 892 | tmp | BIT_SCFG1[nr - 1]); | 884 | tmp | BIT_SCFG1[nr - 1]); |
| 893 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG2); | 885 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); |
| 894 | w83627hf_write_value(client, W83781D_REG_SCFG2, | 886 | w83627hf_write_value(data, W83781D_REG_SCFG2, |
| 895 | tmp & ~BIT_SCFG2[nr - 1]); | 887 | tmp & ~BIT_SCFG2[nr - 1]); |
| 896 | data->sens[nr - 1] = val; | 888 | data->sens[nr - 1] = val; |
| 897 | break; | 889 | break; |
| 898 | case W83781D_DEFAULT_BETA: /* thermistor */ | 890 | case W83781D_DEFAULT_BETA: /* thermistor */ |
| 899 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); | 891 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); |
| 900 | w83627hf_write_value(client, W83781D_REG_SCFG1, | 892 | w83627hf_write_value(data, W83781D_REG_SCFG1, |
| 901 | tmp & ~BIT_SCFG1[nr - 1]); | 893 | tmp & ~BIT_SCFG1[nr - 1]); |
| 902 | data->sens[nr - 1] = val; | 894 | data->sens[nr - 1] = val; |
| 903 | break; | 895 | break; |
| 904 | default: | 896 | default: |
| 905 | dev_err(&client->dev, | 897 | dev_err(dev, |
| 906 | "Invalid sensor type %ld; must be 1, 2, or %d\n", | 898 | "Invalid sensor type %ld; must be 1, 2, or %d\n", |
| 907 | (long) val, W83781D_DEFAULT_BETA); | 899 | (long) val, W83781D_DEFAULT_BETA); |
| 908 | break; | 900 | break; |
| @@ -929,35 +921,85 @@ sysfs_sensor(1); | |||
| 929 | sysfs_sensor(2); | 921 | sysfs_sensor(2); |
| 930 | sysfs_sensor(3); | 922 | sysfs_sensor(3); |
| 931 | 923 | ||
| 932 | static int __init w83627hf_find(int sioaddr, unsigned short *addr) | 924 | static ssize_t show_name(struct device *dev, struct device_attribute |
| 925 | *devattr, char *buf) | ||
| 926 | { | ||
| 927 | struct w83627hf_data *data = dev_get_drvdata(dev); | ||
| 928 | |||
| 929 | return sprintf(buf, "%s\n", data->name); | ||
| 930 | } | ||
| 931 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
| 932 | |||
| 933 | static int __init w83627hf_find(int sioaddr, unsigned short *addr, | ||
| 934 | struct w83627hf_sio_data *sio_data) | ||
| 933 | { | 935 | { |
| 936 | int err = -ENODEV; | ||
| 934 | u16 val; | 937 | u16 val; |
| 935 | 938 | ||
| 939 | static const __initdata char *names[] = { | ||
| 940 | "W83627HF", | ||
| 941 | "W83627THF", | ||
| 942 | "W83697HF", | ||
| 943 | "W83637HF", | ||
| 944 | "W83687THF", | ||
| 945 | }; | ||
| 946 | |||
| 936 | REG = sioaddr; | 947 | REG = sioaddr; |
| 937 | VAL = sioaddr + 1; | 948 | VAL = sioaddr + 1; |
| 938 | 949 | ||
| 939 | superio_enter(); | 950 | superio_enter(); |
| 940 | val= superio_inb(DEVID); | 951 | val= superio_inb(DEVID); |
| 941 | if(val != W627_DEVID && | 952 | switch (val) { |
| 942 | val != W627THF_DEVID && | 953 | case W627_DEVID: |
| 943 | val != W697_DEVID && | 954 | sio_data->type = w83627hf; |
| 944 | val != W637_DEVID && | 955 | break; |
| 945 | val != W687THF_DEVID) { | 956 | case W627THF_DEVID: |
| 946 | superio_exit(); | 957 | sio_data->type = w83627thf; |
| 947 | return -ENODEV; | 958 | break; |
| 959 | case W697_DEVID: | ||
| 960 | sio_data->type = w83697hf; | ||
| 961 | break; | ||
| 962 | case W637_DEVID: | ||
| 963 | sio_data->type = w83637hf; | ||
| 964 | break; | ||
| 965 | case W687THF_DEVID: | ||
| 966 | sio_data->type = w83687thf; | ||
| 967 | break; | ||
| 968 | default: | ||
| 969 | pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n", val); | ||
| 970 | goto exit; | ||
| 948 | } | 971 | } |
| 949 | 972 | ||
| 950 | superio_select(W83627HF_LD_HWM); | 973 | superio_select(W83627HF_LD_HWM); |
| 974 | force_addr &= WINB_ALIGNMENT; | ||
| 975 | if (force_addr) { | ||
| 976 | printk(KERN_WARNING DRVNAME ": Forcing address 0x%x\n", | ||
| 977 | force_addr); | ||
| 978 | superio_outb(WINB_BASE_REG, force_addr >> 8); | ||
| 979 | superio_outb(WINB_BASE_REG + 1, force_addr & 0xff); | ||
| 980 | } | ||
| 951 | val = (superio_inb(WINB_BASE_REG) << 8) | | 981 | val = (superio_inb(WINB_BASE_REG) << 8) | |
| 952 | superio_inb(WINB_BASE_REG + 1); | 982 | superio_inb(WINB_BASE_REG + 1); |
| 953 | *addr = val & WINB_ALIGNMENT; | 983 | *addr = val & WINB_ALIGNMENT; |
| 954 | if (*addr == 0 && force_addr == 0) { | 984 | if (*addr == 0) { |
| 955 | superio_exit(); | 985 | printk(KERN_WARNING DRVNAME ": Base address not set, " |
| 956 | return -ENODEV; | 986 | "skipping\n"); |
| 987 | goto exit; | ||
| 957 | } | 988 | } |
| 958 | 989 | ||
| 990 | val = superio_inb(WINB_ACT_REG); | ||
| 991 | if (!(val & 0x01)) { | ||
| 992 | printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n"); | ||
| 993 | superio_outb(WINB_ACT_REG, val | 0x01); | ||
| 994 | } | ||
| 995 | |||
| 996 | err = 0; | ||
| 997 | pr_info(DRVNAME ": Found %s chip at %#x\n", | ||
| 998 | names[sio_data->type], *addr); | ||
| 999 | |||
| 1000 | exit: | ||
| 959 | superio_exit(); | 1001 | superio_exit(); |
| 960 | return 0; | 1002 | return err; |
| 961 | } | 1003 | } |
| 962 | 1004 | ||
| 963 | static struct attribute *w83627hf_attributes[] = { | 1005 | static struct attribute *w83627hf_attributes[] = { |
| @@ -1003,6 +1045,7 @@ static struct attribute *w83627hf_attributes[] = { | |||
| 1003 | &dev_attr_pwm1.attr, | 1045 | &dev_attr_pwm1.attr, |
| 1004 | &dev_attr_pwm2.attr, | 1046 | &dev_attr_pwm2.attr, |
| 1005 | 1047 | ||
| 1048 | &dev_attr_name.attr, | ||
| 1006 | NULL | 1049 | NULL |
| 1007 | }; | 1050 | }; |
| 1008 | 1051 | ||
| @@ -1039,161 +1082,92 @@ static const struct attribute_group w83627hf_group_opt = { | |||
| 1039 | .attrs = w83627hf_attributes_opt, | 1082 | .attrs = w83627hf_attributes_opt, |
| 1040 | }; | 1083 | }; |
| 1041 | 1084 | ||
| 1042 | static int w83627hf_detect(struct i2c_adapter *adapter) | 1085 | static int __devinit w83627hf_probe(struct platform_device *pdev) |
| 1043 | { | 1086 | { |
| 1044 | int val, kind; | 1087 | struct device *dev = &pdev->dev; |
| 1045 | struct i2c_client *new_client; | 1088 | struct w83627hf_sio_data *sio_data = dev->platform_data; |
| 1046 | struct w83627hf_data *data; | 1089 | struct w83627hf_data *data; |
| 1047 | int err = 0; | 1090 | struct resource *res; |
| 1048 | const char *client_name = ""; | 1091 | int err; |
| 1049 | |||
| 1050 | if(force_addr) | ||
| 1051 | address = force_addr & WINB_ALIGNMENT; | ||
| 1052 | 1092 | ||
| 1053 | if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE, | 1093 | static const char *names[] = { |
| 1054 | w83627hf_driver.driver.name)) { | 1094 | "w83627hf", |
| 1095 | "w83627thf", | ||
| 1096 | "w83697hf", | ||
| 1097 | "w83637hf", | ||
| 1098 | "w83687thf", | ||
| 1099 | }; | ||
| 1100 | |||
| 1101 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 1102 | if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) { | ||
| 1103 | dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", | ||
| 1104 | (unsigned long)res->start, | ||
| 1105 | (unsigned long)(res->start + WINB_REGION_SIZE - 1)); | ||
| 1055 | err = -EBUSY; | 1106 | err = -EBUSY; |
| 1056 | goto ERROR0; | 1107 | goto ERROR0; |
| 1057 | } | 1108 | } |
| 1058 | 1109 | ||
| 1059 | if(force_addr) { | ||
| 1060 | printk("w83627hf.o: forcing ISA address 0x%04X\n", address); | ||
| 1061 | superio_enter(); | ||
| 1062 | superio_select(W83627HF_LD_HWM); | ||
| 1063 | superio_outb(WINB_BASE_REG, address >> 8); | ||
| 1064 | superio_outb(WINB_BASE_REG+1, address & 0xff); | ||
| 1065 | superio_exit(); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | superio_enter(); | ||
| 1069 | val= superio_inb(DEVID); | ||
| 1070 | if(val == W627_DEVID) | ||
| 1071 | kind = w83627hf; | ||
| 1072 | else if(val == W697_DEVID) | ||
| 1073 | kind = w83697hf; | ||
| 1074 | else if(val == W627THF_DEVID) | ||
| 1075 | kind = w83627thf; | ||
| 1076 | else if(val == W637_DEVID) | ||
| 1077 | kind = w83637hf; | ||
| 1078 | else if (val == W687THF_DEVID) | ||
| 1079 | kind = w83687thf; | ||
| 1080 | else { | ||
| 1081 | dev_info(&adapter->dev, | ||
| 1082 | "Unsupported chip (dev_id=0x%02X).\n", val); | ||
| 1083 | goto ERROR1; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | superio_select(W83627HF_LD_HWM); | ||
| 1087 | if((val = 0x01 & superio_inb(WINB_ACT_REG)) == 0) | ||
| 1088 | superio_outb(WINB_ACT_REG, 1); | ||
| 1089 | superio_exit(); | ||
| 1090 | |||
| 1091 | /* OK. For now, we presume we have a valid client. We now create the | ||
| 1092 | client structure, even though we cannot fill it completely yet. | ||
| 1093 | But it allows us to access w83627hf_{read,write}_value. */ | ||
| 1094 | |||
| 1095 | if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) { | 1110 | if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) { |
| 1096 | err = -ENOMEM; | 1111 | err = -ENOMEM; |
| 1097 | goto ERROR1; | 1112 | goto ERROR1; |
| 1098 | } | 1113 | } |
| 1099 | 1114 | data->addr = res->start; | |
| 1100 | new_client = &data->client; | 1115 | data->type = sio_data->type; |
| 1101 | i2c_set_clientdata(new_client, data); | 1116 | data->name = names[sio_data->type]; |
| 1102 | new_client->addr = address; | ||
| 1103 | mutex_init(&data->lock); | 1117 | mutex_init(&data->lock); |
| 1104 | new_client->adapter = adapter; | ||
| 1105 | new_client->driver = &w83627hf_driver; | ||
| 1106 | new_client->flags = 0; | ||
| 1107 | |||
| 1108 | |||
| 1109 | if (kind == w83627hf) { | ||
| 1110 | client_name = "w83627hf"; | ||
| 1111 | } else if (kind == w83627thf) { | ||
| 1112 | client_name = "w83627thf"; | ||
| 1113 | } else if (kind == w83697hf) { | ||
| 1114 | client_name = "w83697hf"; | ||
| 1115 | } else if (kind == w83637hf) { | ||
| 1116 | client_name = "w83637hf"; | ||
| 1117 | } else if (kind == w83687thf) { | ||
| 1118 | client_name = "w83687thf"; | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | /* Fill in the remaining client fields and put into the global list */ | ||
| 1122 | strlcpy(new_client->name, client_name, I2C_NAME_SIZE); | ||
| 1123 | data->type = kind; | ||
| 1124 | data->valid = 0; | ||
| 1125 | mutex_init(&data->update_lock); | 1118 | mutex_init(&data->update_lock); |
| 1126 | 1119 | platform_set_drvdata(pdev, data); | |
| 1127 | /* Tell the I2C layer a new client has arrived */ | ||
| 1128 | if ((err = i2c_attach_client(new_client))) | ||
| 1129 | goto ERROR2; | ||
| 1130 | |||
| 1131 | data->lm75 = NULL; | ||
| 1132 | 1120 | ||
| 1133 | /* Initialize the chip */ | 1121 | /* Initialize the chip */ |
| 1134 | w83627hf_init_client(new_client); | 1122 | w83627hf_init_device(pdev); |
| 1135 | 1123 | ||
| 1136 | /* A few vars need to be filled upon startup */ | 1124 | /* A few vars need to be filled upon startup */ |
| 1137 | data->fan_min[0] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(1)); | 1125 | data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1)); |
| 1138 | data->fan_min[1] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(2)); | 1126 | data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2)); |
| 1139 | data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3)); | 1127 | data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3)); |
| 1140 | 1128 | ||
| 1141 | /* Register common device attributes */ | 1129 | /* Register common device attributes */ |
| 1142 | if ((err = sysfs_create_group(&new_client->dev.kobj, &w83627hf_group))) | 1130 | if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group))) |
| 1143 | goto ERROR3; | 1131 | goto ERROR3; |
| 1144 | 1132 | ||
| 1145 | /* Register chip-specific device attributes */ | 1133 | /* Register chip-specific device attributes */ |
| 1146 | if (kind == w83627hf || kind == w83697hf) | 1134 | if (data->type == w83627hf || data->type == w83697hf) |
| 1147 | if ((err = device_create_file(&new_client->dev, | 1135 | if ((err = device_create_file(dev, &dev_attr_in5_input)) |
| 1148 | &dev_attr_in5_input)) | 1136 | || (err = device_create_file(dev, &dev_attr_in5_min)) |
| 1149 | || (err = device_create_file(&new_client->dev, | 1137 | || (err = device_create_file(dev, &dev_attr_in5_max)) |
| 1150 | &dev_attr_in5_min)) | 1138 | || (err = device_create_file(dev, &dev_attr_in6_input)) |
| 1151 | || (err = device_create_file(&new_client->dev, | 1139 | || (err = device_create_file(dev, &dev_attr_in6_min)) |
| 1152 | &dev_attr_in5_max)) | 1140 | || (err = device_create_file(dev, &dev_attr_in6_max))) |
| 1153 | || (err = device_create_file(&new_client->dev, | ||
| 1154 | &dev_attr_in6_input)) | ||
| 1155 | || (err = device_create_file(&new_client->dev, | ||
| 1156 | &dev_attr_in6_min)) | ||
| 1157 | || (err = device_create_file(&new_client->dev, | ||
| 1158 | &dev_attr_in6_max))) | ||
| 1159 | goto ERROR4; | 1141 | goto ERROR4; |
| 1160 | 1142 | ||
| 1161 | if (kind != w83697hf) | 1143 | if (data->type != w83697hf) |
| 1162 | if ((err = device_create_file(&new_client->dev, | 1144 | if ((err = device_create_file(dev, &dev_attr_in1_input)) |
| 1163 | &dev_attr_in1_input)) | 1145 | || (err = device_create_file(dev, &dev_attr_in1_min)) |
| 1164 | || (err = device_create_file(&new_client->dev, | 1146 | || (err = device_create_file(dev, &dev_attr_in1_max)) |
| 1165 | &dev_attr_in1_min)) | 1147 | || (err = device_create_file(dev, &dev_attr_fan3_input)) |
| 1166 | || (err = device_create_file(&new_client->dev, | 1148 | || (err = device_create_file(dev, &dev_attr_fan3_min)) |
| 1167 | &dev_attr_in1_max)) | 1149 | || (err = device_create_file(dev, &dev_attr_fan3_div)) |
| 1168 | || (err = device_create_file(&new_client->dev, | 1150 | || (err = device_create_file(dev, &dev_attr_temp3_input)) |
| 1169 | &dev_attr_fan3_input)) | 1151 | || (err = device_create_file(dev, &dev_attr_temp3_max)) |
| 1170 | || (err = device_create_file(&new_client->dev, | 1152 | || (err = device_create_file(dev, &dev_attr_temp3_max_hyst)) |
| 1171 | &dev_attr_fan3_min)) | 1153 | || (err = device_create_file(dev, &dev_attr_temp3_type))) |
| 1172 | || (err = device_create_file(&new_client->dev, | ||
| 1173 | &dev_attr_fan3_div)) | ||
| 1174 | || (err = device_create_file(&new_client->dev, | ||
| 1175 | &dev_attr_temp3_input)) | ||
| 1176 | || (err = device_create_file(&new_client->dev, | ||
| 1177 | &dev_attr_temp3_max)) | ||
| 1178 | || (err = device_create_file(&new_client->dev, | ||
| 1179 | &dev_attr_temp3_max_hyst)) | ||
| 1180 | || (err = device_create_file(&new_client->dev, | ||
| 1181 | &dev_attr_temp3_type))) | ||
| 1182 | goto ERROR4; | 1154 | goto ERROR4; |
| 1183 | 1155 | ||
| 1184 | if (kind != w83697hf && data->vid != 0xff) | 1156 | if (data->type != w83697hf && data->vid != 0xff) { |
| 1185 | if ((err = device_create_file(&new_client->dev, | 1157 | /* Convert VID to voltage based on VRM */ |
| 1186 | &dev_attr_cpu0_vid)) | 1158 | data->vrm = vid_which_vrm(); |
| 1187 | || (err = device_create_file(&new_client->dev, | 1159 | |
| 1188 | &dev_attr_vrm))) | 1160 | if ((err = device_create_file(dev, &dev_attr_cpu0_vid)) |
| 1161 | || (err = device_create_file(dev, &dev_attr_vrm))) | ||
| 1189 | goto ERROR4; | 1162 | goto ERROR4; |
| 1163 | } | ||
| 1190 | 1164 | ||
| 1191 | if (kind == w83627thf || kind == w83637hf || kind == w83687thf) | 1165 | if (data->type == w83627thf || data->type == w83637hf |
| 1192 | if ((err = device_create_file(&new_client->dev, | 1166 | || data->type == w83687thf) |
| 1193 | &dev_attr_pwm3))) | 1167 | if ((err = device_create_file(dev, &dev_attr_pwm3))) |
| 1194 | goto ERROR4; | 1168 | goto ERROR4; |
| 1195 | 1169 | ||
| 1196 | data->class_dev = hwmon_device_register(&new_client->dev); | 1170 | data->class_dev = hwmon_device_register(dev); |
| 1197 | if (IS_ERR(data->class_dev)) { | 1171 | if (IS_ERR(data->class_dev)) { |
| 1198 | err = PTR_ERR(data->class_dev); | 1172 | err = PTR_ERR(data->class_dev); |
| 1199 | goto ERROR4; | 1173 | goto ERROR4; |
| @@ -1202,47 +1176,37 @@ static int w83627hf_detect(struct i2c_adapter *adapter) | |||
| 1202 | return 0; | 1176 | return 0; |
| 1203 | 1177 | ||
| 1204 | ERROR4: | 1178 | ERROR4: |
| 1205 | sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group); | 1179 | sysfs_remove_group(&dev->kobj, &w83627hf_group); |
| 1206 | sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group_opt); | 1180 | sysfs_remove_group(&dev->kobj, &w83627hf_group_opt); |
| 1207 | ERROR3: | 1181 | ERROR3: |
| 1208 | i2c_detach_client(new_client); | ||
| 1209 | ERROR2: | ||
| 1210 | kfree(data); | 1182 | kfree(data); |
| 1211 | ERROR1: | 1183 | ERROR1: |
| 1212 | release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE); | 1184 | release_region(res->start, WINB_REGION_SIZE); |
| 1213 | ERROR0: | 1185 | ERROR0: |
| 1214 | return err; | 1186 | return err; |
| 1215 | } | 1187 | } |
| 1216 | 1188 | ||
| 1217 | static int w83627hf_detach_client(struct i2c_client *client) | 1189 | static int __devexit w83627hf_remove(struct platform_device *pdev) |
| 1218 | { | 1190 | { |
| 1219 | struct w83627hf_data *data = i2c_get_clientdata(client); | 1191 | struct w83627hf_data *data = platform_get_drvdata(pdev); |
| 1220 | int err; | 1192 | struct resource *res; |
| 1221 | 1193 | ||
| 1194 | platform_set_drvdata(pdev, NULL); | ||
| 1222 | hwmon_device_unregister(data->class_dev); | 1195 | hwmon_device_unregister(data->class_dev); |
| 1223 | 1196 | ||
| 1224 | sysfs_remove_group(&client->dev.kobj, &w83627hf_group); | 1197 | sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group); |
| 1225 | sysfs_remove_group(&client->dev.kobj, &w83627hf_group_opt); | 1198 | sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt); |
| 1226 | |||
| 1227 | if ((err = i2c_detach_client(client))) | ||
| 1228 | return err; | ||
| 1229 | |||
| 1230 | release_region(client->addr + WINB_REGION_OFFSET, WINB_REGION_SIZE); | ||
| 1231 | kfree(data); | 1199 | kfree(data); |
| 1232 | 1200 | ||
| 1201 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 1202 | release_region(res->start, WINB_REGION_SIZE); | ||
| 1203 | |||
| 1233 | return 0; | 1204 | return 0; |
| 1234 | } | 1205 | } |
| 1235 | 1206 | ||
| 1236 | 1207 | ||
| 1237 | /* | 1208 | static int w83627hf_read_value(struct w83627hf_data *data, u16 reg) |
| 1238 | ISA access must always be locked explicitly! | ||
| 1239 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, | ||
| 1240 | would slow down the W83781D access and should not be necessary. | ||
| 1241 | There are some ugly typecasts here, but the good news is - they should | ||
| 1242 | nowhere else be necessary! */ | ||
| 1243 | static int w83627hf_read_value(struct i2c_client *client, u16 reg) | ||
| 1244 | { | 1209 | { |
| 1245 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 1246 | int res, word_sized; | 1210 | int res, word_sized; |
| 1247 | 1211 | ||
| 1248 | mutex_lock(&data->lock); | 1212 | mutex_lock(&data->lock); |
| @@ -1253,29 +1217,29 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg) | |||
| 1253 | || ((reg & 0x00ff) == 0x55)); | 1217 | || ((reg & 0x00ff) == 0x55)); |
| 1254 | if (reg & 0xff00) { | 1218 | if (reg & 0xff00) { |
| 1255 | outb_p(W83781D_REG_BANK, | 1219 | outb_p(W83781D_REG_BANK, |
| 1256 | client->addr + W83781D_ADDR_REG_OFFSET); | 1220 | data->addr + W83781D_ADDR_REG_OFFSET); |
| 1257 | outb_p(reg >> 8, | 1221 | outb_p(reg >> 8, |
| 1258 | client->addr + W83781D_DATA_REG_OFFSET); | 1222 | data->addr + W83781D_DATA_REG_OFFSET); |
| 1259 | } | 1223 | } |
| 1260 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); | 1224 | outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); |
| 1261 | res = inb_p(client->addr + W83781D_DATA_REG_OFFSET); | 1225 | res = inb_p(data->addr + W83781D_DATA_REG_OFFSET); |
| 1262 | if (word_sized) { | 1226 | if (word_sized) { |
| 1263 | outb_p((reg & 0xff) + 1, | 1227 | outb_p((reg & 0xff) + 1, |
| 1264 | client->addr + W83781D_ADDR_REG_OFFSET); | 1228 | data->addr + W83781D_ADDR_REG_OFFSET); |
| 1265 | res = | 1229 | res = |
| 1266 | (res << 8) + inb_p(client->addr + | 1230 | (res << 8) + inb_p(data->addr + |
| 1267 | W83781D_DATA_REG_OFFSET); | 1231 | W83781D_DATA_REG_OFFSET); |
| 1268 | } | 1232 | } |
| 1269 | if (reg & 0xff00) { | 1233 | if (reg & 0xff00) { |
| 1270 | outb_p(W83781D_REG_BANK, | 1234 | outb_p(W83781D_REG_BANK, |
| 1271 | client->addr + W83781D_ADDR_REG_OFFSET); | 1235 | data->addr + W83781D_ADDR_REG_OFFSET); |
| 1272 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); | 1236 | outb_p(0, data->addr + W83781D_DATA_REG_OFFSET); |
| 1273 | } | 1237 | } |
| 1274 | mutex_unlock(&data->lock); | 1238 | mutex_unlock(&data->lock); |
| 1275 | return res; | 1239 | return res; |
| 1276 | } | 1240 | } |
| 1277 | 1241 | ||
| 1278 | static int w83627thf_read_gpio5(struct i2c_client *client) | 1242 | static int __devinit w83627thf_read_gpio5(struct platform_device *pdev) |
| 1279 | { | 1243 | { |
| 1280 | int res = 0xff, sel; | 1244 | int res = 0xff, sel; |
| 1281 | 1245 | ||
| @@ -1284,7 +1248,7 @@ static int w83627thf_read_gpio5(struct i2c_client *client) | |||
| 1284 | 1248 | ||
| 1285 | /* Make sure these GPIO pins are enabled */ | 1249 | /* Make sure these GPIO pins are enabled */ |
| 1286 | if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) { | 1250 | if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) { |
| 1287 | dev_dbg(&client->dev, "GPIO5 disabled, no VID function\n"); | 1251 | dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n"); |
| 1288 | goto exit; | 1252 | goto exit; |
| 1289 | } | 1253 | } |
| 1290 | 1254 | ||
| @@ -1292,12 +1256,12 @@ static int w83627thf_read_gpio5(struct i2c_client *client) | |||
| 1292 | There must be at least five (VRM 9), and possibly 6 (VRM 10) */ | 1256 | There must be at least five (VRM 9), and possibly 6 (VRM 10) */ |
| 1293 | sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f; | 1257 | sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f; |
| 1294 | if ((sel & 0x1f) != 0x1f) { | 1258 | if ((sel & 0x1f) != 0x1f) { |
| 1295 | dev_dbg(&client->dev, "GPIO5 not configured for VID " | 1259 | dev_dbg(&pdev->dev, "GPIO5 not configured for VID " |
| 1296 | "function\n"); | 1260 | "function\n"); |
| 1297 | goto exit; | 1261 | goto exit; |
| 1298 | } | 1262 | } |
| 1299 | 1263 | ||
| 1300 | dev_info(&client->dev, "Reading VID from GPIO5\n"); | 1264 | dev_info(&pdev->dev, "Reading VID from GPIO5\n"); |
| 1301 | res = superio_inb(W83627THF_GPIO5_DR) & sel; | 1265 | res = superio_inb(W83627THF_GPIO5_DR) & sel; |
| 1302 | 1266 | ||
| 1303 | exit: | 1267 | exit: |
| @@ -1305,7 +1269,7 @@ exit: | |||
| 1305 | return res; | 1269 | return res; |
| 1306 | } | 1270 | } |
| 1307 | 1271 | ||
| 1308 | static int w83687thf_read_vid(struct i2c_client *client) | 1272 | static int __devinit w83687thf_read_vid(struct platform_device *pdev) |
| 1309 | { | 1273 | { |
| 1310 | int res = 0xff; | 1274 | int res = 0xff; |
| 1311 | 1275 | ||
| @@ -1314,13 +1278,13 @@ static int w83687thf_read_vid(struct i2c_client *client) | |||
| 1314 | 1278 | ||
| 1315 | /* Make sure these GPIO pins are enabled */ | 1279 | /* Make sure these GPIO pins are enabled */ |
| 1316 | if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { | 1280 | if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { |
| 1317 | dev_dbg(&client->dev, "VID disabled, no VID function\n"); | 1281 | dev_dbg(&pdev->dev, "VID disabled, no VID function\n"); |
| 1318 | goto exit; | 1282 | goto exit; |
| 1319 | } | 1283 | } |
| 1320 | 1284 | ||
| 1321 | /* Make sure the pins are configured for input */ | 1285 | /* Make sure the pins are configured for input */ |
| 1322 | if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { | 1286 | if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { |
| 1323 | dev_dbg(&client->dev, "VID configured as output, " | 1287 | dev_dbg(&pdev->dev, "VID configured as output, " |
| 1324 | "no VID function\n"); | 1288 | "no VID function\n"); |
| 1325 | goto exit; | 1289 | goto exit; |
| 1326 | } | 1290 | } |
| @@ -1332,9 +1296,8 @@ exit: | |||
| 1332 | return res; | 1296 | return res; |
| 1333 | } | 1297 | } |
| 1334 | 1298 | ||
| 1335 | static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) | 1299 | static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value) |
| 1336 | { | 1300 | { |
| 1337 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 1338 | int word_sized; | 1301 | int word_sized; |
| 1339 | 1302 | ||
| 1340 | mutex_lock(&data->lock); | 1303 | mutex_lock(&data->lock); |
| @@ -1344,33 +1307,33 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) | |||
| 1344 | || ((reg & 0x00ff) == 0x55)); | 1307 | || ((reg & 0x00ff) == 0x55)); |
| 1345 | if (reg & 0xff00) { | 1308 | if (reg & 0xff00) { |
| 1346 | outb_p(W83781D_REG_BANK, | 1309 | outb_p(W83781D_REG_BANK, |
| 1347 | client->addr + W83781D_ADDR_REG_OFFSET); | 1310 | data->addr + W83781D_ADDR_REG_OFFSET); |
| 1348 | outb_p(reg >> 8, | 1311 | outb_p(reg >> 8, |
| 1349 | client->addr + W83781D_DATA_REG_OFFSET); | 1312 | data->addr + W83781D_DATA_REG_OFFSET); |
| 1350 | } | 1313 | } |
| 1351 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); | 1314 | outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); |
| 1352 | if (word_sized) { | 1315 | if (word_sized) { |
| 1353 | outb_p(value >> 8, | 1316 | outb_p(value >> 8, |
| 1354 | client->addr + W83781D_DATA_REG_OFFSET); | 1317 | data->addr + W83781D_DATA_REG_OFFSET); |
| 1355 | outb_p((reg & 0xff) + 1, | 1318 | outb_p((reg & 0xff) + 1, |
| 1356 | client->addr + W83781D_ADDR_REG_OFFSET); | 1319 | data->addr + W83781D_ADDR_REG_OFFSET); |
| 1357 | } | 1320 | } |
| 1358 | outb_p(value & 0xff, | 1321 | outb_p(value & 0xff, |
| 1359 | client->addr + W83781D_DATA_REG_OFFSET); | 1322 | data->addr + W83781D_DATA_REG_OFFSET); |
| 1360 | if (reg & 0xff00) { | 1323 | if (reg & 0xff00) { |
| 1361 | outb_p(W83781D_REG_BANK, | 1324 | outb_p(W83781D_REG_BANK, |
| 1362 | client->addr + W83781D_ADDR_REG_OFFSET); | 1325 | data->addr + W83781D_ADDR_REG_OFFSET); |
| 1363 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); | 1326 | outb_p(0, data->addr + W83781D_DATA_REG_OFFSET); |
| 1364 | } | 1327 | } |
| 1365 | mutex_unlock(&data->lock); | 1328 | mutex_unlock(&data->lock); |
| 1366 | return 0; | 1329 | return 0; |
| 1367 | } | 1330 | } |
| 1368 | 1331 | ||
| 1369 | static void w83627hf_init_client(struct i2c_client *client) | 1332 | static void __devinit w83627hf_init_device(struct platform_device *pdev) |
| 1370 | { | 1333 | { |
| 1371 | struct w83627hf_data *data = i2c_get_clientdata(client); | 1334 | struct w83627hf_data *data = platform_get_drvdata(pdev); |
| 1372 | int i; | 1335 | int i; |
| 1373 | int type = data->type; | 1336 | enum chips type = data->type; |
| 1374 | u8 tmp; | 1337 | u8 tmp; |
| 1375 | 1338 | ||
| 1376 | if (reset) { | 1339 | if (reset) { |
| @@ -1379,57 +1342,53 @@ static void w83627hf_init_client(struct i2c_client *client) | |||
| 1379 | speed...) so it is now optional. It might even go away if | 1342 | speed...) so it is now optional. It might even go away if |
| 1380 | nobody reports it as being useful, as I see very little | 1343 | nobody reports it as being useful, as I see very little |
| 1381 | reason why this would be needed at all. */ | 1344 | reason why this would be needed at all. */ |
| 1382 | dev_info(&client->dev, "If reset=1 solved a problem you were " | 1345 | dev_info(&pdev->dev, "If reset=1 solved a problem you were " |
| 1383 | "having, please report!\n"); | 1346 | "having, please report!\n"); |
| 1384 | 1347 | ||
| 1385 | /* save this register */ | 1348 | /* save this register */ |
| 1386 | i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG); | 1349 | i = w83627hf_read_value(data, W83781D_REG_BEEP_CONFIG); |
| 1387 | /* Reset all except Watchdog values and last conversion values | 1350 | /* Reset all except Watchdog values and last conversion values |
| 1388 | This sets fan-divs to 2, among others */ | 1351 | This sets fan-divs to 2, among others */ |
| 1389 | w83627hf_write_value(client, W83781D_REG_CONFIG, 0x80); | 1352 | w83627hf_write_value(data, W83781D_REG_CONFIG, 0x80); |
| 1390 | /* Restore the register and disable power-on abnormal beep. | 1353 | /* Restore the register and disable power-on abnormal beep. |
| 1391 | This saves FAN 1/2/3 input/output values set by BIOS. */ | 1354 | This saves FAN 1/2/3 input/output values set by BIOS. */ |
| 1392 | w83627hf_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); | 1355 | w83627hf_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80); |
| 1393 | /* Disable master beep-enable (reset turns it on). | 1356 | /* Disable master beep-enable (reset turns it on). |
| 1394 | Individual beeps should be reset to off but for some reason | 1357 | Individual beeps should be reset to off but for some reason |
| 1395 | disabling this bit helps some people not get beeped */ | 1358 | disabling this bit helps some people not get beeped */ |
| 1396 | w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, 0); | 1359 | w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, 0); |
| 1397 | } | 1360 | } |
| 1398 | 1361 | ||
| 1399 | /* Minimize conflicts with other winbond i2c-only clients... */ | 1362 | /* Minimize conflicts with other winbond i2c-only clients... */ |
| 1400 | /* disable i2c subclients... how to disable main i2c client?? */ | 1363 | /* disable i2c subclients... how to disable main i2c client?? */ |
| 1401 | /* force i2c address to relatively uncommon address */ | 1364 | /* force i2c address to relatively uncommon address */ |
| 1402 | w83627hf_write_value(client, W83781D_REG_I2C_SUBADDR, 0x89); | 1365 | w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89); |
| 1403 | w83627hf_write_value(client, W83781D_REG_I2C_ADDR, force_i2c); | 1366 | w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c); |
| 1404 | 1367 | ||
| 1405 | /* Read VID only once */ | 1368 | /* Read VID only once */ |
| 1406 | if (w83627hf == data->type || w83637hf == data->type) { | 1369 | if (type == w83627hf || type == w83637hf) { |
| 1407 | int lo = w83627hf_read_value(client, W83781D_REG_VID_FANDIV); | 1370 | int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV); |
| 1408 | int hi = w83627hf_read_value(client, W83781D_REG_CHIPID); | 1371 | int hi = w83627hf_read_value(data, W83781D_REG_CHIPID); |
| 1409 | data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); | 1372 | data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); |
| 1410 | } else if (w83627thf == data->type) { | 1373 | } else if (type == w83627thf) { |
| 1411 | data->vid = w83627thf_read_gpio5(client); | 1374 | data->vid = w83627thf_read_gpio5(pdev); |
| 1412 | } else if (w83687thf == data->type) { | 1375 | } else if (type == w83687thf) { |
| 1413 | data->vid = w83687thf_read_vid(client); | 1376 | data->vid = w83687thf_read_vid(pdev); |
| 1414 | } | 1377 | } |
| 1415 | 1378 | ||
| 1416 | /* Read VRM & OVT Config only once */ | 1379 | /* Read VRM & OVT Config only once */ |
| 1417 | if (w83627thf == data->type || w83637hf == data->type | 1380 | if (type == w83627thf || type == w83637hf || type == w83687thf) { |
| 1418 | || w83687thf == data->type) { | ||
| 1419 | data->vrm_ovt = | 1381 | data->vrm_ovt = |
| 1420 | w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); | 1382 | w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG); |
| 1421 | } | 1383 | } |
| 1422 | 1384 | ||
| 1423 | /* Convert VID to voltage based on VRM */ | 1385 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); |
| 1424 | data->vrm = vid_which_vrm(); | ||
| 1425 | |||
| 1426 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); | ||
| 1427 | for (i = 1; i <= 3; i++) { | 1386 | for (i = 1; i <= 3; i++) { |
| 1428 | if (!(tmp & BIT_SCFG1[i - 1])) { | 1387 | if (!(tmp & BIT_SCFG1[i - 1])) { |
| 1429 | data->sens[i - 1] = W83781D_DEFAULT_BETA; | 1388 | data->sens[i - 1] = W83781D_DEFAULT_BETA; |
| 1430 | } else { | 1389 | } else { |
| 1431 | if (w83627hf_read_value | 1390 | if (w83627hf_read_value |
| 1432 | (client, | 1391 | (data, |
| 1433 | W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) | 1392 | W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) |
| 1434 | data->sens[i - 1] = 1; | 1393 | data->sens[i - 1] = 1; |
| 1435 | else | 1394 | else |
| @@ -1441,38 +1400,37 @@ static void w83627hf_init_client(struct i2c_client *client) | |||
| 1441 | 1400 | ||
| 1442 | if(init) { | 1401 | if(init) { |
| 1443 | /* Enable temp2 */ | 1402 | /* Enable temp2 */ |
| 1444 | tmp = w83627hf_read_value(client, W83781D_REG_TEMP2_CONFIG); | 1403 | tmp = w83627hf_read_value(data, W83781D_REG_TEMP2_CONFIG); |
| 1445 | if (tmp & 0x01) { | 1404 | if (tmp & 0x01) { |
| 1446 | dev_warn(&client->dev, "Enabling temp2, readings " | 1405 | dev_warn(&pdev->dev, "Enabling temp2, readings " |
| 1447 | "might not make sense\n"); | 1406 | "might not make sense\n"); |
| 1448 | w83627hf_write_value(client, W83781D_REG_TEMP2_CONFIG, | 1407 | w83627hf_write_value(data, W83781D_REG_TEMP2_CONFIG, |
| 1449 | tmp & 0xfe); | 1408 | tmp & 0xfe); |
| 1450 | } | 1409 | } |
| 1451 | 1410 | ||
| 1452 | /* Enable temp3 */ | 1411 | /* Enable temp3 */ |
| 1453 | if (type != w83697hf) { | 1412 | if (type != w83697hf) { |
| 1454 | tmp = w83627hf_read_value(client, | 1413 | tmp = w83627hf_read_value(data, |
| 1455 | W83781D_REG_TEMP3_CONFIG); | 1414 | W83781D_REG_TEMP3_CONFIG); |
| 1456 | if (tmp & 0x01) { | 1415 | if (tmp & 0x01) { |
| 1457 | dev_warn(&client->dev, "Enabling temp3, " | 1416 | dev_warn(&pdev->dev, "Enabling temp3, " |
| 1458 | "readings might not make sense\n"); | 1417 | "readings might not make sense\n"); |
| 1459 | w83627hf_write_value(client, | 1418 | w83627hf_write_value(data, |
| 1460 | W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); | 1419 | W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); |
| 1461 | } | 1420 | } |
| 1462 | } | 1421 | } |
| 1463 | } | 1422 | } |
| 1464 | 1423 | ||
| 1465 | /* Start monitoring */ | 1424 | /* Start monitoring */ |
| 1466 | w83627hf_write_value(client, W83781D_REG_CONFIG, | 1425 | w83627hf_write_value(data, W83781D_REG_CONFIG, |
| 1467 | (w83627hf_read_value(client, | 1426 | (w83627hf_read_value(data, |
| 1468 | W83781D_REG_CONFIG) & 0xf7) | 1427 | W83781D_REG_CONFIG) & 0xf7) |
| 1469 | | 0x01); | 1428 | | 0x01); |
| 1470 | } | 1429 | } |
| 1471 | 1430 | ||
| 1472 | static struct w83627hf_data *w83627hf_update_device(struct device *dev) | 1431 | static struct w83627hf_data *w83627hf_update_device(struct device *dev) |
| 1473 | { | 1432 | { |
| 1474 | struct i2c_client *client = to_i2c_client(dev); | 1433 | struct w83627hf_data *data = dev_get_drvdata(dev); |
| 1475 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
| 1476 | int i; | 1434 | int i; |
| 1477 | 1435 | ||
| 1478 | mutex_lock(&data->update_lock); | 1436 | mutex_lock(&data->update_lock); |
| @@ -1486,23 +1444,23 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) | |||
| 1486 | && (i == 5 || i == 6))) | 1444 | && (i == 5 || i == 6))) |
| 1487 | continue; | 1445 | continue; |
| 1488 | data->in[i] = | 1446 | data->in[i] = |
| 1489 | w83627hf_read_value(client, W83781D_REG_IN(i)); | 1447 | w83627hf_read_value(data, W83781D_REG_IN(i)); |
| 1490 | data->in_min[i] = | 1448 | data->in_min[i] = |
| 1491 | w83627hf_read_value(client, | 1449 | w83627hf_read_value(data, |
| 1492 | W83781D_REG_IN_MIN(i)); | 1450 | W83781D_REG_IN_MIN(i)); |
| 1493 | data->in_max[i] = | 1451 | data->in_max[i] = |
| 1494 | w83627hf_read_value(client, | 1452 | w83627hf_read_value(data, |
| 1495 | W83781D_REG_IN_MAX(i)); | 1453 | W83781D_REG_IN_MAX(i)); |
| 1496 | } | 1454 | } |
| 1497 | for (i = 1; i <= 3; i++) { | 1455 | for (i = 1; i <= 3; i++) { |
| 1498 | data->fan[i - 1] = | 1456 | data->fan[i - 1] = |
| 1499 | w83627hf_read_value(client, W83781D_REG_FAN(i)); | 1457 | w83627hf_read_value(data, W83781D_REG_FAN(i)); |
| 1500 | data->fan_min[i - 1] = | 1458 | data->fan_min[i - 1] = |
| 1501 | w83627hf_read_value(client, | 1459 | w83627hf_read_value(data, |
| 1502 | W83781D_REG_FAN_MIN(i)); | 1460 | W83781D_REG_FAN_MIN(i)); |
| 1503 | } | 1461 | } |
| 1504 | for (i = 1; i <= 3; i++) { | 1462 | for (i = 1; i <= 3; i++) { |
| 1505 | u8 tmp = w83627hf_read_value(client, | 1463 | u8 tmp = w83627hf_read_value(data, |
| 1506 | W836X7HF_REG_PWM(data->type, i)); | 1464 | W836X7HF_REG_PWM(data->type, i)); |
| 1507 | /* bits 0-3 are reserved in 627THF */ | 1465 | /* bits 0-3 are reserved in 627THF */ |
| 1508 | if (data->type == w83627thf) | 1466 | if (data->type == w83627thf) |
| @@ -1513,47 +1471,47 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) | |||
| 1513 | break; | 1471 | break; |
| 1514 | } | 1472 | } |
| 1515 | 1473 | ||
| 1516 | data->temp = w83627hf_read_value(client, W83781D_REG_TEMP(1)); | 1474 | data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1)); |
| 1517 | data->temp_max = | 1475 | data->temp_max = |
| 1518 | w83627hf_read_value(client, W83781D_REG_TEMP_OVER(1)); | 1476 | w83627hf_read_value(data, W83781D_REG_TEMP_OVER(1)); |
| 1519 | data->temp_max_hyst = | 1477 | data->temp_max_hyst = |
| 1520 | w83627hf_read_value(client, W83781D_REG_TEMP_HYST(1)); | 1478 | w83627hf_read_value(data, W83781D_REG_TEMP_HYST(1)); |
| 1521 | data->temp_add[0] = | 1479 | data->temp_add[0] = |
| 1522 | w83627hf_read_value(client, W83781D_REG_TEMP(2)); | 1480 | w83627hf_read_value(data, W83781D_REG_TEMP(2)); |
| 1523 | data->temp_max_add[0] = | 1481 | data->temp_max_add[0] = |
| 1524 | w83627hf_read_value(client, W83781D_REG_TEMP_OVER(2)); | 1482 | w83627hf_read_value(data, W83781D_REG_TEMP_OVER(2)); |
| 1525 | data->temp_max_hyst_add[0] = | 1483 | data->temp_max_hyst_add[0] = |
| 1526 | w83627hf_read_value(client, W83781D_REG_TEMP_HYST(2)); | 1484 | w83627hf_read_value(data, W83781D_REG_TEMP_HYST(2)); |
| 1527 | if (data->type != w83697hf) { | 1485 | if (data->type != w83697hf) { |
| 1528 | data->temp_add[1] = | 1486 | data->temp_add[1] = |
| 1529 | w83627hf_read_value(client, W83781D_REG_TEMP(3)); | 1487 | w83627hf_read_value(data, W83781D_REG_TEMP(3)); |
| 1530 | data->temp_max_add[1] = | 1488 | data->temp_max_add[1] = |
| 1531 | w83627hf_read_value(client, W83781D_REG_TEMP_OVER(3)); | 1489 | w83627hf_read_value(data, W83781D_REG_TEMP_OVER(3)); |
| 1532 | data->temp_max_hyst_add[1] = | 1490 | data->temp_max_hyst_add[1] = |
| 1533 | w83627hf_read_value(client, W83781D_REG_TEMP_HYST(3)); | 1491 | w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3)); |
| 1534 | } | 1492 | } |
| 1535 | 1493 | ||
| 1536 | i = w83627hf_read_value(client, W83781D_REG_VID_FANDIV); | 1494 | i = w83627hf_read_value(data, W83781D_REG_VID_FANDIV); |
| 1537 | data->fan_div[0] = (i >> 4) & 0x03; | 1495 | data->fan_div[0] = (i >> 4) & 0x03; |
| 1538 | data->fan_div[1] = (i >> 6) & 0x03; | 1496 | data->fan_div[1] = (i >> 6) & 0x03; |
| 1539 | if (data->type != w83697hf) { | 1497 | if (data->type != w83697hf) { |
| 1540 | data->fan_div[2] = (w83627hf_read_value(client, | 1498 | data->fan_div[2] = (w83627hf_read_value(data, |
| 1541 | W83781D_REG_PIN) >> 6) & 0x03; | 1499 | W83781D_REG_PIN) >> 6) & 0x03; |
| 1542 | } | 1500 | } |
| 1543 | i = w83627hf_read_value(client, W83781D_REG_VBAT); | 1501 | i = w83627hf_read_value(data, W83781D_REG_VBAT); |
| 1544 | data->fan_div[0] |= (i >> 3) & 0x04; | 1502 | data->fan_div[0] |= (i >> 3) & 0x04; |
| 1545 | data->fan_div[1] |= (i >> 4) & 0x04; | 1503 | data->fan_div[1] |= (i >> 4) & 0x04; |
| 1546 | if (data->type != w83697hf) | 1504 | if (data->type != w83697hf) |
| 1547 | data->fan_div[2] |= (i >> 5) & 0x04; | 1505 | data->fan_div[2] |= (i >> 5) & 0x04; |
| 1548 | data->alarms = | 1506 | data->alarms = |
| 1549 | w83627hf_read_value(client, W83781D_REG_ALARM1) | | 1507 | w83627hf_read_value(data, W83781D_REG_ALARM1) | |
| 1550 | (w83627hf_read_value(client, W83781D_REG_ALARM2) << 8) | | 1508 | (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) | |
| 1551 | (w83627hf_read_value(client, W83781D_REG_ALARM3) << 16); | 1509 | (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16); |
| 1552 | i = w83627hf_read_value(client, W83781D_REG_BEEP_INTS2); | 1510 | i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2); |
| 1553 | data->beep_enable = i >> 7; | 1511 | data->beep_enable = i >> 7; |
| 1554 | data->beep_mask = ((i & 0x7f) << 8) | | 1512 | data->beep_mask = ((i & 0x7f) << 8) | |
| 1555 | w83627hf_read_value(client, W83781D_REG_BEEP_INTS1) | | 1513 | w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) | |
| 1556 | w83627hf_read_value(client, W83781D_REG_BEEP_INTS3) << 16; | 1514 | w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16; |
| 1557 | data->last_updated = jiffies; | 1515 | data->last_updated = jiffies; |
| 1558 | data->valid = 1; | 1516 | data->valid = 1; |
| 1559 | } | 1517 | } |
| @@ -1563,19 +1521,87 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) | |||
| 1563 | return data; | 1521 | return data; |
| 1564 | } | 1522 | } |
| 1565 | 1523 | ||
| 1524 | static int __init w83627hf_device_add(unsigned short address, | ||
| 1525 | const struct w83627hf_sio_data *sio_data) | ||
| 1526 | { | ||
| 1527 | struct resource res = { | ||
| 1528 | .start = address + WINB_REGION_OFFSET, | ||
| 1529 | .end = address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1, | ||
| 1530 | .name = DRVNAME, | ||
| 1531 | .flags = IORESOURCE_IO, | ||
| 1532 | }; | ||
| 1533 | int err; | ||
| 1534 | |||
| 1535 | pdev = platform_device_alloc(DRVNAME, address); | ||
| 1536 | if (!pdev) { | ||
| 1537 | err = -ENOMEM; | ||
| 1538 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | ||
| 1539 | goto exit; | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | err = platform_device_add_resources(pdev, &res, 1); | ||
| 1543 | if (err) { | ||
| 1544 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | ||
| 1545 | "(%d)\n", err); | ||
| 1546 | goto exit_device_put; | ||
| 1547 | } | ||
| 1548 | |||
| 1549 | pdev->dev.platform_data = kmalloc(sizeof(struct w83627hf_sio_data), | ||
| 1550 | GFP_KERNEL); | ||
| 1551 | if (!pdev->dev.platform_data) { | ||
| 1552 | err = -ENOMEM; | ||
| 1553 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | ||
| 1554 | goto exit_device_put; | ||
| 1555 | } | ||
| 1556 | memcpy(pdev->dev.platform_data, sio_data, | ||
| 1557 | sizeof(struct w83627hf_sio_data)); | ||
| 1558 | |||
| 1559 | err = platform_device_add(pdev); | ||
| 1560 | if (err) { | ||
| 1561 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
| 1562 | err); | ||
| 1563 | goto exit_device_put; | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | return 0; | ||
| 1567 | |||
| 1568 | exit_device_put: | ||
| 1569 | platform_device_put(pdev); | ||
| 1570 | exit: | ||
| 1571 | return err; | ||
| 1572 | } | ||
| 1573 | |||
| 1566 | static int __init sensors_w83627hf_init(void) | 1574 | static int __init sensors_w83627hf_init(void) |
| 1567 | { | 1575 | { |
| 1568 | if (w83627hf_find(0x2e, &address) | 1576 | int err; |
| 1569 | && w83627hf_find(0x4e, &address)) { | 1577 | unsigned short address; |
| 1578 | struct w83627hf_sio_data sio_data; | ||
| 1579 | |||
| 1580 | if (w83627hf_find(0x2e, &address, &sio_data) | ||
| 1581 | && w83627hf_find(0x4e, &address, &sio_data)) | ||
| 1570 | return -ENODEV; | 1582 | return -ENODEV; |
| 1571 | } | ||
| 1572 | 1583 | ||
| 1573 | return i2c_isa_add_driver(&w83627hf_driver); | 1584 | err = platform_driver_register(&w83627hf_driver); |
| 1585 | if (err) | ||
| 1586 | goto exit; | ||
| 1587 | |||
| 1588 | /* Sets global pdev as a side effect */ | ||
| 1589 | err = w83627hf_device_add(address, &sio_data); | ||
| 1590 | if (err) | ||
| 1591 | goto exit_driver; | ||
| 1592 | |||
| 1593 | return 0; | ||
| 1594 | |||
| 1595 | exit_driver: | ||
| 1596 | platform_driver_unregister(&w83627hf_driver); | ||
| 1597 | exit: | ||
| 1598 | return err; | ||
| 1574 | } | 1599 | } |
| 1575 | 1600 | ||
| 1576 | static void __exit sensors_w83627hf_exit(void) | 1601 | static void __exit sensors_w83627hf_exit(void) |
| 1577 | { | 1602 | { |
| 1578 | i2c_isa_del_driver(&w83627hf_driver); | 1603 | platform_device_unregister(pdev); |
| 1604 | platform_driver_unregister(&w83627hf_driver); | ||
| 1579 | } | 1605 | } |
| 1580 | 1606 | ||
| 1581 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " | 1607 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " |
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index a47da3ec5472..f85b48fea1c4 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
| @@ -2,8 +2,9 @@ | |||
| 2 | w83781d.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | w83781d.c - Part of lm_sensors, Linux kernel modules for hardware |
| 3 | monitoring | 3 | monitoring |
| 4 | Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>, | 4 | Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>, |
| 5 | Philip Edelbrock <phil@netroedge.com>, | 5 | Philip Edelbrock <phil@netroedge.com>, |
| 6 | and Mark Studebaker <mdsxyz123@yahoo.com> | 6 | and Mark Studebaker <mdsxyz123@yahoo.com> |
| 7 | Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> | ||
| 7 | 8 | ||
| 8 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
| 9 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by |
| @@ -38,15 +39,20 @@ | |||
| 38 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
| 39 | #include <linux/jiffies.h> | 40 | #include <linux/jiffies.h> |
| 40 | #include <linux/i2c.h> | 41 | #include <linux/i2c.h> |
| 41 | #include <linux/i2c-isa.h> | 42 | #include <linux/platform_device.h> |
| 43 | #include <linux/ioport.h> | ||
| 42 | #include <linux/hwmon.h> | 44 | #include <linux/hwmon.h> |
| 43 | #include <linux/hwmon-vid.h> | 45 | #include <linux/hwmon-vid.h> |
| 46 | #include <linux/hwmon-sysfs.h> | ||
| 44 | #include <linux/sysfs.h> | 47 | #include <linux/sysfs.h> |
| 45 | #include <linux/err.h> | 48 | #include <linux/err.h> |
| 46 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
| 47 | #include <asm/io.h> | 50 | #include <asm/io.h> |
| 48 | #include "lm75.h" | 51 | #include "lm75.h" |
| 49 | 52 | ||
| 53 | /* ISA device, if found */ | ||
| 54 | static struct platform_device *pdev; | ||
| 55 | |||
| 50 | /* Addresses to scan */ | 56 | /* Addresses to scan */ |
| 51 | static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, | 57 | static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, |
| 52 | 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, | 58 | 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, |
| @@ -75,8 +81,8 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); | |||
| 75 | #define W83781D_ADDR_REG_OFFSET 5 | 81 | #define W83781D_ADDR_REG_OFFSET 5 |
| 76 | #define W83781D_DATA_REG_OFFSET 6 | 82 | #define W83781D_DATA_REG_OFFSET 6 |
| 77 | 83 | ||
| 78 | /* The W83781D registers */ | 84 | /* The device registers */ |
| 79 | /* The W83782D registers for nr=7,8 are in bank 5 */ | 85 | /* in nr from 0 to 8 */ |
| 80 | #define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ | 86 | #define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ |
| 81 | (0x554 + (((nr) - 7) * 2))) | 87 | (0x554 + (((nr) - 7) * 2))) |
| 82 | #define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ | 88 | #define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ |
| @@ -84,12 +90,14 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); | |||
| 84 | #define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ | 90 | #define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ |
| 85 | (0x550 + (nr) - 7)) | 91 | (0x550 + (nr) - 7)) |
| 86 | 92 | ||
| 87 | #define W83781D_REG_FAN_MIN(nr) (0x3a + (nr)) | 93 | /* fan nr from 0 to 2 */ |
| 88 | #define W83781D_REG_FAN(nr) (0x27 + (nr)) | 94 | #define W83781D_REG_FAN_MIN(nr) (0x3b + (nr)) |
| 95 | #define W83781D_REG_FAN(nr) (0x28 + (nr)) | ||
| 89 | 96 | ||
| 90 | #define W83781D_REG_BANK 0x4E | 97 | #define W83781D_REG_BANK 0x4E |
| 91 | #define W83781D_REG_TEMP2_CONFIG 0x152 | 98 | #define W83781D_REG_TEMP2_CONFIG 0x152 |
| 92 | #define W83781D_REG_TEMP3_CONFIG 0x252 | 99 | #define W83781D_REG_TEMP3_CONFIG 0x252 |
| 100 | /* temp nr from 1 to 3 */ | ||
| 93 | #define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \ | 101 | #define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \ |
| 94 | ((nr == 2) ? (0x0150) : \ | 102 | ((nr == 2) ? (0x0150) : \ |
| 95 | (0x27))) | 103 | (0x27))) |
| @@ -127,19 +135,9 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); | |||
| 127 | #define W83781D_REG_VBAT 0x5D | 135 | #define W83781D_REG_VBAT 0x5D |
| 128 | 136 | ||
| 129 | /* PWM 782D (1-4) and 783S (1-2) only */ | 137 | /* PWM 782D (1-4) and 783S (1-2) only */ |
| 130 | #define W83781D_REG_PWM1 0x5B /* 782d and 783s/627hf datasheets disagree */ | 138 | static const u8 W83781D_REG_PWM[] = { 0x5B, 0x5A, 0x5E, 0x5F }; |
| 131 | /* on which is which; */ | ||
| 132 | #define W83781D_REG_PWM2 0x5A /* We follow the 782d convention here, */ | ||
| 133 | /* However 782d is probably wrong. */ | ||
| 134 | #define W83781D_REG_PWM3 0x5E | ||
| 135 | #define W83781D_REG_PWM4 0x5F | ||
| 136 | #define W83781D_REG_PWMCLK12 0x5C | 139 | #define W83781D_REG_PWMCLK12 0x5C |
| 137 | #define W83781D_REG_PWMCLK34 0x45C | 140 | #define W83781D_REG_PWMCLK34 0x45C |
| 138 | static const u8 regpwm[] = { W83781D_REG_PWM1, W83781D_REG_PWM2, | ||
| 139 | W83781D_REG_PWM3, W83781D_REG_PWM4 | ||
| 140 | }; | ||
| 141 | |||
| 142 | #define W83781D_REG_PWM(nr) (regpwm[(nr) - 1]) | ||
| 143 | 141 | ||
| 144 | #define W83781D_REG_I2C_ADDR 0x48 | 142 | #define W83781D_REG_I2C_ADDR 0x48 |
| 145 | #define W83781D_REG_I2C_SUBADDR 0x4A | 143 | #define W83781D_REG_I2C_SUBADDR 0x4A |
| @@ -159,12 +157,9 @@ static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 }; | |||
| 159 | #define W83781D_REG_RT_IDX 0x50 | 157 | #define W83781D_REG_RT_IDX 0x50 |
| 160 | #define W83781D_REG_RT_VAL 0x51 | 158 | #define W83781D_REG_RT_VAL 0x51 |
| 161 | 159 | ||
| 162 | /* Conversions. Rounding and limit checking is only done on the TO_REG | 160 | /* Conversions */ |
| 163 | variants. Note that you should be a bit careful with which arguments | 161 | #define IN_TO_REG(val) SENSORS_LIMIT(((val) + 8) / 16, 0, 255) |
| 164 | these macros are called: arguments may be evaluated more than once. | 162 | #define IN_FROM_REG(val) ((val) * 16) |
| 165 | Fixing this is just not worth it. */ | ||
| 166 | #define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255)) | ||
| 167 | #define IN_FROM_REG(val) (((val) * 16) / 10) | ||
| 168 | 163 | ||
| 169 | static inline u8 | 164 | static inline u8 |
| 170 | FAN_TO_REG(long rpm, int div) | 165 | FAN_TO_REG(long rpm, int div) |
| @@ -175,24 +170,24 @@ FAN_TO_REG(long rpm, int div) | |||
| 175 | return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); | 170 | return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); |
| 176 | } | 171 | } |
| 177 | 172 | ||
| 178 | #define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \ | 173 | static inline long |
| 179 | ((val) == 255 ? 0 : \ | 174 | FAN_FROM_REG(u8 val, int div) |
| 180 | 1350000 / ((val) * (div)))) | 175 | { |
| 176 | if (val == 0) | ||
| 177 | return -1; | ||
| 178 | if (val == 255) | ||
| 179 | return 0; | ||
| 180 | return 1350000 / (val * div); | ||
| 181 | } | ||
| 181 | 182 | ||
| 182 | #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \ | 183 | #define TEMP_TO_REG(val) SENSORS_LIMIT((val) / 1000, -127, 128) |
| 183 | : (val)) / 1000, 0, 0xff)) | 184 | #define TEMP_FROM_REG(val) ((val) * 1000) |
| 184 | #define TEMP_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000) | ||
| 185 | 185 | ||
| 186 | #define PWM_FROM_REG(val) (val) | ||
| 187 | #define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) | ||
| 188 | #define BEEP_MASK_FROM_REG(val,type) ((type) == as99127f ? \ | 186 | #define BEEP_MASK_FROM_REG(val,type) ((type) == as99127f ? \ |
| 189 | (val) ^ 0x7fff : (val)) | 187 | (val) ^ 0x7fff : (val)) |
| 190 | #define BEEP_MASK_TO_REG(val,type) ((type) == as99127f ? \ | 188 | #define BEEP_MASK_TO_REG(val,type) ((type) == as99127f ? \ |
| 191 | (~(val)) & 0x7fff : (val) & 0xffffff) | 189 | (~(val)) & 0x7fff : (val) & 0xffffff) |
| 192 | 190 | ||
| 193 | #define BEEP_ENABLE_TO_REG(val) ((val) ? 1 : 0) | ||
| 194 | #define BEEP_ENABLE_FROM_REG(val) ((val) ? 1 : 0) | ||
| 195 | |||
| 196 | #define DIV_FROM_REG(val) (1 << (val)) | 191 | #define DIV_FROM_REG(val) (1 << (val)) |
| 197 | 192 | ||
| 198 | static inline u8 | 193 | static inline u8 |
| @@ -207,7 +202,7 @@ DIV_TO_REG(long val, enum chips type) | |||
| 207 | break; | 202 | break; |
| 208 | val >>= 1; | 203 | val >>= 1; |
| 209 | } | 204 | } |
| 210 | return ((u8) i); | 205 | return i; |
| 211 | } | 206 | } |
| 212 | 207 | ||
| 213 | /* There are some complications in a module like this. First off, W83781D chips | 208 | /* There are some complications in a module like this. First off, W83781D chips |
| @@ -221,8 +216,8 @@ DIV_TO_REG(long val, enum chips type) | |||
| 221 | a bit - except if there could be more than one SMBus. Groan. No solution | 216 | a bit - except if there could be more than one SMBus. Groan. No solution |
| 222 | for this yet. */ | 217 | for this yet. */ |
| 223 | 218 | ||
| 224 | /* For each registered chip, we need to keep some data in memory. | 219 | /* For ISA chips, we abuse the i2c_client addr and name fields. We also use |
| 225 | The structure is dynamically allocated. */ | 220 | the driver field to differentiate between I2C and ISA chips. */ |
| 226 | struct w83781d_data { | 221 | struct w83781d_data { |
| 227 | struct i2c_client client; | 222 | struct i2c_client client; |
| 228 | struct class_device *class_dev; | 223 | struct class_device *class_dev; |
| @@ -241,9 +236,9 @@ struct w83781d_data { | |||
| 241 | u8 in_min[9]; /* Register value - 8 & 9 for 782D only */ | 236 | u8 in_min[9]; /* Register value - 8 & 9 for 782D only */ |
| 242 | u8 fan[3]; /* Register value */ | 237 | u8 fan[3]; /* Register value */ |
| 243 | u8 fan_min[3]; /* Register value */ | 238 | u8 fan_min[3]; /* Register value */ |
| 244 | u8 temp; | 239 | s8 temp; /* Register value */ |
| 245 | u8 temp_max; /* Register value */ | 240 | s8 temp_max; /* Register value */ |
| 246 | u8 temp_max_hyst; /* Register value */ | 241 | s8 temp_max_hyst; /* Register value */ |
| 247 | u16 temp_add[2]; /* Register value */ | 242 | u16 temp_add[2]; /* Register value */ |
| 248 | u16 temp_max_add[2]; /* Register value */ | 243 | u16 temp_max_add[2]; /* Register value */ |
| 249 | u16 temp_max_hyst_add[2]; /* Register value */ | 244 | u16 temp_max_hyst_add[2]; /* Register value */ |
| @@ -253,7 +248,7 @@ struct w83781d_data { | |||
| 253 | u32 beep_mask; /* Register encoding, combined */ | 248 | u32 beep_mask; /* Register encoding, combined */ |
| 254 | u8 beep_enable; /* Boolean */ | 249 | u8 beep_enable; /* Boolean */ |
| 255 | u8 pwm[4]; /* Register value */ | 250 | u8 pwm[4]; /* Register value */ |
| 256 | u8 pwmenable[4]; /* Boolean */ | 251 | u8 pwm2_enable; /* Boolean */ |
| 257 | u16 sens[3]; /* 782D/783S only. | 252 | u16 sens[3]; /* 782D/783S only. |
| 258 | 1 = pentium diode; 2 = 3904 diode; | 253 | 1 = pentium diode; 2 = 3904 diode; |
| 259 | 3000-5000 = thermistor beta. | 254 | 3000-5000 = thermistor beta. |
| @@ -263,14 +258,16 @@ struct w83781d_data { | |||
| 263 | }; | 258 | }; |
| 264 | 259 | ||
| 265 | static int w83781d_attach_adapter(struct i2c_adapter *adapter); | 260 | static int w83781d_attach_adapter(struct i2c_adapter *adapter); |
| 266 | static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter); | ||
| 267 | static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); | 261 | static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); |
| 268 | static int w83781d_detach_client(struct i2c_client *client); | 262 | static int w83781d_detach_client(struct i2c_client *client); |
| 269 | 263 | ||
| 270 | static int w83781d_read_value(struct i2c_client *client, u16 reg); | 264 | static int __devinit w83781d_isa_probe(struct platform_device *pdev); |
| 271 | static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value); | 265 | static int __devexit w83781d_isa_remove(struct platform_device *pdev); |
| 266 | |||
| 267 | static int w83781d_read_value(struct w83781d_data *data, u16 reg); | ||
| 268 | static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value); | ||
| 272 | static struct w83781d_data *w83781d_update_device(struct device *dev); | 269 | static struct w83781d_data *w83781d_update_device(struct device *dev); |
| 273 | static void w83781d_init_client(struct i2c_client *client); | 270 | static void w83781d_init_device(struct device *dev); |
| 274 | 271 | ||
| 275 | static struct i2c_driver w83781d_driver = { | 272 | static struct i2c_driver w83781d_driver = { |
| 276 | .driver = { | 273 | .driver = { |
| @@ -281,39 +278,44 @@ static struct i2c_driver w83781d_driver = { | |||
| 281 | .detach_client = w83781d_detach_client, | 278 | .detach_client = w83781d_detach_client, |
| 282 | }; | 279 | }; |
| 283 | 280 | ||
| 284 | static struct i2c_driver w83781d_isa_driver = { | 281 | static struct platform_driver w83781d_isa_driver = { |
| 285 | .driver = { | 282 | .driver = { |
| 286 | .owner = THIS_MODULE, | 283 | .owner = THIS_MODULE, |
| 287 | .name = "w83781d-isa", | 284 | .name = "w83781d", |
| 288 | }, | 285 | }, |
| 289 | .attach_adapter = w83781d_isa_attach_adapter, | 286 | .probe = w83781d_isa_probe, |
| 290 | .detach_client = w83781d_detach_client, | 287 | .remove = w83781d_isa_remove, |
| 291 | }; | 288 | }; |
| 292 | 289 | ||
| 293 | 290 | ||
| 294 | /* following are the sysfs callback functions */ | 291 | /* following are the sysfs callback functions */ |
| 295 | #define show_in_reg(reg) \ | 292 | #define show_in_reg(reg) \ |
| 296 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ | 293 | static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \ |
| 294 | char *buf) \ | ||
| 297 | { \ | 295 | { \ |
| 296 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ | ||
| 298 | struct w83781d_data *data = w83781d_update_device(dev); \ | 297 | struct w83781d_data *data = w83781d_update_device(dev); \ |
| 299 | return sprintf(buf,"%ld\n", (long)IN_FROM_REG(data->reg[nr] * 10)); \ | 298 | return sprintf(buf, "%ld\n", \ |
| 299 | (long)IN_FROM_REG(data->reg[attr->index])); \ | ||
| 300 | } | 300 | } |
| 301 | show_in_reg(in); | 301 | show_in_reg(in); |
| 302 | show_in_reg(in_min); | 302 | show_in_reg(in_min); |
| 303 | show_in_reg(in_max); | 303 | show_in_reg(in_max); |
| 304 | 304 | ||
| 305 | #define store_in_reg(REG, reg) \ | 305 | #define store_in_reg(REG, reg) \ |
| 306 | static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | 306 | static ssize_t store_in_##reg (struct device *dev, struct device_attribute \ |
| 307 | *da, const char *buf, size_t count) \ | ||
| 307 | { \ | 308 | { \ |
| 308 | struct i2c_client *client = to_i2c_client(dev); \ | 309 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ |
| 309 | struct w83781d_data *data = i2c_get_clientdata(client); \ | 310 | struct w83781d_data *data = dev_get_drvdata(dev); \ |
| 311 | int nr = attr->index; \ | ||
| 310 | u32 val; \ | 312 | u32 val; \ |
| 311 | \ | 313 | \ |
| 312 | val = simple_strtoul(buf, NULL, 10) / 10; \ | 314 | val = simple_strtoul(buf, NULL, 10); \ |
| 313 | \ | 315 | \ |
| 314 | mutex_lock(&data->update_lock); \ | 316 | mutex_lock(&data->update_lock); \ |
| 315 | data->in_##reg[nr] = IN_TO_REG(val); \ | 317 | data->in_##reg[nr] = IN_TO_REG(val); \ |
| 316 | w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ | 318 | w83781d_write_value(data, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ |
| 317 | \ | 319 | \ |
| 318 | mutex_unlock(&data->update_lock); \ | 320 | mutex_unlock(&data->update_lock); \ |
| 319 | return count; \ | 321 | return count; \ |
| @@ -321,29 +323,13 @@ static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count | |||
| 321 | store_in_reg(MIN, min); | 323 | store_in_reg(MIN, min); |
| 322 | store_in_reg(MAX, max); | 324 | store_in_reg(MAX, max); |
| 323 | 325 | ||
| 324 | #define sysfs_in_offset(offset) \ | ||
| 325 | static ssize_t \ | ||
| 326 | show_regs_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 327 | { \ | ||
| 328 | return show_in(dev, buf, offset); \ | ||
| 329 | } \ | ||
| 330 | static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL); | ||
| 331 | |||
| 332 | #define sysfs_in_reg_offset(reg, offset) \ | ||
| 333 | static ssize_t show_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 334 | { \ | ||
| 335 | return show_in_##reg (dev, buf, offset); \ | ||
| 336 | } \ | ||
| 337 | static ssize_t store_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | ||
| 338 | { \ | ||
| 339 | return store_in_##reg (dev, buf, count, offset); \ | ||
| 340 | } \ | ||
| 341 | static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset); | ||
| 342 | |||
| 343 | #define sysfs_in_offsets(offset) \ | 326 | #define sysfs_in_offsets(offset) \ |
| 344 | sysfs_in_offset(offset); \ | 327 | static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ |
| 345 | sysfs_in_reg_offset(min, offset); \ | 328 | show_in, NULL, offset); \ |
| 346 | sysfs_in_reg_offset(max, offset); | 329 | static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ |
| 330 | show_in_min, store_in_min, offset); \ | ||
| 331 | static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ | ||
| 332 | show_in_max, store_in_max, offset) | ||
| 347 | 333 | ||
| 348 | sysfs_in_offsets(0); | 334 | sysfs_in_offsets(0); |
| 349 | sysfs_in_offsets(1); | 335 | sysfs_in_offsets(1); |
| @@ -356,63 +342,56 @@ sysfs_in_offsets(7); | |||
| 356 | sysfs_in_offsets(8); | 342 | sysfs_in_offsets(8); |
| 357 | 343 | ||
| 358 | #define show_fan_reg(reg) \ | 344 | #define show_fan_reg(reg) \ |
| 359 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ | 345 | static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \ |
| 346 | char *buf) \ | ||
| 360 | { \ | 347 | { \ |
| 348 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ | ||
| 361 | struct w83781d_data *data = w83781d_update_device(dev); \ | 349 | struct w83781d_data *data = w83781d_update_device(dev); \ |
| 362 | return sprintf(buf,"%ld\n", \ | 350 | return sprintf(buf,"%ld\n", \ |
| 363 | FAN_FROM_REG(data->reg[nr-1], (long)DIV_FROM_REG(data->fan_div[nr-1]))); \ | 351 | FAN_FROM_REG(data->reg[attr->index], \ |
| 352 | DIV_FROM_REG(data->fan_div[attr->index]))); \ | ||
| 364 | } | 353 | } |
| 365 | show_fan_reg(fan); | 354 | show_fan_reg(fan); |
| 366 | show_fan_reg(fan_min); | 355 | show_fan_reg(fan_min); |
| 367 | 356 | ||
| 368 | static ssize_t | 357 | static ssize_t |
| 369 | store_fan_min(struct device *dev, const char *buf, size_t count, int nr) | 358 | store_fan_min(struct device *dev, struct device_attribute *da, |
| 359 | const char *buf, size_t count) | ||
| 370 | { | 360 | { |
| 371 | struct i2c_client *client = to_i2c_client(dev); | 361 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 372 | struct w83781d_data *data = i2c_get_clientdata(client); | 362 | struct w83781d_data *data = dev_get_drvdata(dev); |
| 363 | int nr = attr->index; | ||
| 373 | u32 val; | 364 | u32 val; |
| 374 | 365 | ||
| 375 | val = simple_strtoul(buf, NULL, 10); | 366 | val = simple_strtoul(buf, NULL, 10); |
| 376 | 367 | ||
| 377 | mutex_lock(&data->update_lock); | 368 | mutex_lock(&data->update_lock); |
| 378 | data->fan_min[nr - 1] = | 369 | data->fan_min[nr] = |
| 379 | FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); | 370 | FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
| 380 | w83781d_write_value(client, W83781D_REG_FAN_MIN(nr), | 371 | w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), |
| 381 | data->fan_min[nr - 1]); | 372 | data->fan_min[nr]); |
| 382 | 373 | ||
| 383 | mutex_unlock(&data->update_lock); | 374 | mutex_unlock(&data->update_lock); |
| 384 | return count; | 375 | return count; |
| 385 | } | 376 | } |
| 386 | 377 | ||
| 387 | #define sysfs_fan_offset(offset) \ | 378 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); |
| 388 | static ssize_t show_regs_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 379 | static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, |
| 389 | { \ | 380 | show_fan_min, store_fan_min, 0); |
| 390 | return show_fan(dev, buf, offset); \ | 381 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); |
| 391 | } \ | 382 | static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, |
| 392 | static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL); | 383 | show_fan_min, store_fan_min, 1); |
| 393 | 384 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); | |
| 394 | #define sysfs_fan_min_offset(offset) \ | 385 | static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR, |
| 395 | static ssize_t show_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 386 | show_fan_min, store_fan_min, 2); |
| 396 | { \ | ||
| 397 | return show_fan_min(dev, buf, offset); \ | ||
| 398 | } \ | ||
| 399 | static ssize_t store_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | ||
| 400 | { \ | ||
| 401 | return store_fan_min(dev, buf, count, offset); \ | ||
| 402 | } \ | ||
| 403 | static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset); | ||
| 404 | |||
| 405 | sysfs_fan_offset(1); | ||
| 406 | sysfs_fan_min_offset(1); | ||
| 407 | sysfs_fan_offset(2); | ||
| 408 | sysfs_fan_min_offset(2); | ||
| 409 | sysfs_fan_offset(3); | ||
| 410 | sysfs_fan_min_offset(3); | ||
| 411 | 387 | ||
| 412 | #define show_temp_reg(reg) \ | 388 | #define show_temp_reg(reg) \ |
| 413 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ | 389 | static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \ |
| 390 | char *buf) \ | ||
| 414 | { \ | 391 | { \ |
| 392 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ | ||
| 415 | struct w83781d_data *data = w83781d_update_device(dev); \ | 393 | struct w83781d_data *data = w83781d_update_device(dev); \ |
| 394 | int nr = attr->index; \ | ||
| 416 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ | 395 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ |
| 417 | return sprintf(buf,"%d\n", \ | 396 | return sprintf(buf,"%d\n", \ |
| 418 | LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \ | 397 | LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \ |
| @@ -425,10 +404,12 @@ show_temp_reg(temp_max); | |||
| 425 | show_temp_reg(temp_max_hyst); | 404 | show_temp_reg(temp_max_hyst); |
| 426 | 405 | ||
| 427 | #define store_temp_reg(REG, reg) \ | 406 | #define store_temp_reg(REG, reg) \ |
| 428 | static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | 407 | static ssize_t store_temp_##reg (struct device *dev, \ |
| 408 | struct device_attribute *da, const char *buf, size_t count) \ | ||
| 429 | { \ | 409 | { \ |
| 430 | struct i2c_client *client = to_i2c_client(dev); \ | 410 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ |
| 431 | struct w83781d_data *data = i2c_get_clientdata(client); \ | 411 | struct w83781d_data *data = dev_get_drvdata(dev); \ |
| 412 | int nr = attr->index; \ | ||
| 432 | s32 val; \ | 413 | s32 val; \ |
| 433 | \ | 414 | \ |
| 434 | val = simple_strtol(buf, NULL, 10); \ | 415 | val = simple_strtol(buf, NULL, 10); \ |
| @@ -437,11 +418,11 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou | |||
| 437 | \ | 418 | \ |
| 438 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ | 419 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ |
| 439 | data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ | 420 | data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ |
| 440 | w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \ | 421 | w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \ |
| 441 | data->temp_##reg##_add[nr-2]); \ | 422 | data->temp_##reg##_add[nr-2]); \ |
| 442 | } else { /* TEMP1 */ \ | 423 | } else { /* TEMP1 */ \ |
| 443 | data->temp_##reg = TEMP_TO_REG(val); \ | 424 | data->temp_##reg = TEMP_TO_REG(val); \ |
| 444 | w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \ | 425 | w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \ |
| 445 | data->temp_##reg); \ | 426 | data->temp_##reg); \ |
| 446 | } \ | 427 | } \ |
| 447 | \ | 428 | \ |
| @@ -451,29 +432,13 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou | |||
| 451 | store_temp_reg(OVER, max); | 432 | store_temp_reg(OVER, max); |
| 452 | store_temp_reg(HYST, max_hyst); | 433 | store_temp_reg(HYST, max_hyst); |
| 453 | 434 | ||
| 454 | #define sysfs_temp_offset(offset) \ | ||
| 455 | static ssize_t \ | ||
| 456 | show_regs_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 457 | { \ | ||
| 458 | return show_temp(dev, buf, offset); \ | ||
| 459 | } \ | ||
| 460 | static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL); | ||
| 461 | |||
| 462 | #define sysfs_temp_reg_offset(reg, offset) \ | ||
| 463 | static ssize_t show_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 464 | { \ | ||
| 465 | return show_temp_##reg (dev, buf, offset); \ | ||
| 466 | } \ | ||
| 467 | static ssize_t store_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | ||
| 468 | { \ | ||
| 469 | return store_temp_##reg (dev, buf, count, offset); \ | ||
| 470 | } \ | ||
| 471 | static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset); | ||
| 472 | |||
| 473 | #define sysfs_temp_offsets(offset) \ | 435 | #define sysfs_temp_offsets(offset) \ |
| 474 | sysfs_temp_offset(offset); \ | 436 | static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ |
| 475 | sysfs_temp_reg_offset(max, offset); \ | 437 | show_temp, NULL, offset); \ |
| 476 | sysfs_temp_reg_offset(max_hyst, offset); | 438 | static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ |
| 439 | show_temp_max, store_temp_max, offset); \ | ||
| 440 | static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ | ||
| 441 | show_temp_max_hyst, store_temp_max_hyst, offset); | ||
| 477 | 442 | ||
| 478 | sysfs_temp_offsets(1); | 443 | sysfs_temp_offsets(1); |
| 479 | sysfs_temp_offsets(2); | 444 | sysfs_temp_offsets(2); |
| @@ -498,8 +463,7 @@ show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
| 498 | static ssize_t | 463 | static ssize_t |
| 499 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 464 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
| 500 | { | 465 | { |
| 501 | struct i2c_client *client = to_i2c_client(dev); | 466 | struct w83781d_data *data = dev_get_drvdata(dev); |
| 502 | struct w83781d_data *data = i2c_get_clientdata(client); | ||
| 503 | u32 val; | 467 | u32 val; |
| 504 | 468 | ||
| 505 | val = simple_strtoul(buf, NULL, 10); | 469 | val = simple_strtoul(buf, NULL, 10); |
| @@ -528,68 +492,67 @@ static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr | |||
| 528 | static ssize_t show_beep_enable (struct device *dev, struct device_attribute *attr, char *buf) | 492 | static ssize_t show_beep_enable (struct device *dev, struct device_attribute *attr, char *buf) |
| 529 | { | 493 | { |
| 530 | struct w83781d_data *data = w83781d_update_device(dev); | 494 | struct w83781d_data *data = w83781d_update_device(dev); |
| 531 | return sprintf(buf, "%ld\n", | 495 | return sprintf(buf, "%ld\n", (long)data->beep_enable); |
| 532 | (long)BEEP_ENABLE_FROM_REG(data->beep_enable)); | ||
| 533 | } | 496 | } |
| 534 | 497 | ||
| 535 | #define BEEP_ENABLE 0 /* Store beep_enable */ | ||
| 536 | #define BEEP_MASK 1 /* Store beep_mask */ | ||
| 537 | |||
| 538 | static ssize_t | 498 | static ssize_t |
| 539 | store_beep_reg(struct device *dev, const char *buf, size_t count, | 499 | store_beep_mask(struct device *dev, struct device_attribute *attr, |
| 540 | int update_mask) | 500 | const char *buf, size_t count) |
| 541 | { | 501 | { |
| 542 | struct i2c_client *client = to_i2c_client(dev); | 502 | struct w83781d_data *data = dev_get_drvdata(dev); |
| 543 | struct w83781d_data *data = i2c_get_clientdata(client); | 503 | u32 val; |
| 544 | u32 val, val2; | ||
| 545 | 504 | ||
| 546 | val = simple_strtoul(buf, NULL, 10); | 505 | val = simple_strtoul(buf, NULL, 10); |
| 547 | 506 | ||
| 548 | mutex_lock(&data->update_lock); | 507 | mutex_lock(&data->update_lock); |
| 508 | data->beep_mask = BEEP_MASK_TO_REG(val, data->type); | ||
| 509 | w83781d_write_value(data, W83781D_REG_BEEP_INTS1, | ||
| 510 | data->beep_mask & 0xff); | ||
| 511 | w83781d_write_value(data, W83781D_REG_BEEP_INTS2, | ||
| 512 | ((data->beep_mask >> 8) & 0x7f) | ||
| 513 | | data->beep_enable << 7); | ||
| 514 | if (data->type != w83781d && data->type != as99127f) { | ||
| 515 | w83781d_write_value(data, W83781D_REG_BEEP_INTS3, | ||
| 516 | ((data->beep_mask) >> 16) & 0xff); | ||
| 517 | } | ||
| 518 | mutex_unlock(&data->update_lock); | ||
| 549 | 519 | ||
| 550 | if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ | 520 | return count; |
| 551 | data->beep_mask = BEEP_MASK_TO_REG(val, data->type); | 521 | } |
| 552 | w83781d_write_value(client, W83781D_REG_BEEP_INTS1, | ||
| 553 | data->beep_mask & 0xff); | ||
| 554 | |||
| 555 | if ((data->type != w83781d) && (data->type != as99127f)) { | ||
| 556 | w83781d_write_value(client, W83781D_REG_BEEP_INTS3, | ||
| 557 | ((data->beep_mask) >> 16) & 0xff); | ||
| 558 | } | ||
| 559 | 522 | ||
| 560 | val2 = (data->beep_mask >> 8) & 0x7f; | 523 | static ssize_t |
| 561 | } else { /* We are storing beep_enable */ | 524 | store_beep_enable(struct device *dev, struct device_attribute *attr, |
| 562 | val2 = w83781d_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f; | 525 | const char *buf, size_t count) |
| 563 | data->beep_enable = BEEP_ENABLE_TO_REG(val); | 526 | { |
| 564 | } | 527 | struct w83781d_data *data = dev_get_drvdata(dev); |
| 528 | u32 val; | ||
| 565 | 529 | ||
| 566 | w83781d_write_value(client, W83781D_REG_BEEP_INTS2, | 530 | val = simple_strtoul(buf, NULL, 10); |
| 567 | val2 | data->beep_enable << 7); | 531 | if (val != 0 && val != 1) |
| 532 | return -EINVAL; | ||
| 568 | 533 | ||
| 534 | mutex_lock(&data->update_lock); | ||
| 535 | data->beep_enable = val; | ||
| 536 | val = w83781d_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f; | ||
| 537 | val |= data->beep_enable << 7; | ||
| 538 | w83781d_write_value(data, W83781D_REG_BEEP_INTS2, val); | ||
| 569 | mutex_unlock(&data->update_lock); | 539 | mutex_unlock(&data->update_lock); |
| 540 | |||
| 570 | return count; | 541 | return count; |
| 571 | } | 542 | } |
| 572 | 543 | ||
| 573 | #define sysfs_beep(REG, reg) \ | 544 | static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, |
| 574 | static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ | 545 | show_beep_mask, store_beep_mask); |
| 575 | { \ | 546 | static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, |
| 576 | return show_beep_##reg(dev, attr, buf); \ | 547 | show_beep_enable, store_beep_enable); |
| 577 | } \ | ||
| 578 | static ssize_t store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | ||
| 579 | { \ | ||
| 580 | return store_beep_reg(dev, buf, count, BEEP_##REG); \ | ||
| 581 | } \ | ||
| 582 | static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg); | ||
| 583 | |||
| 584 | sysfs_beep(ENABLE, enable); | ||
| 585 | sysfs_beep(MASK, mask); | ||
| 586 | 548 | ||
| 587 | static ssize_t | 549 | static ssize_t |
| 588 | show_fan_div_reg(struct device *dev, char *buf, int nr) | 550 | show_fan_div(struct device *dev, struct device_attribute *da, char *buf) |
| 589 | { | 551 | { |
| 552 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 590 | struct w83781d_data *data = w83781d_update_device(dev); | 553 | struct w83781d_data *data = w83781d_update_device(dev); |
| 591 | return sprintf(buf, "%ld\n", | 554 | return sprintf(buf, "%ld\n", |
| 592 | (long) DIV_FROM_REG(data->fan_div[nr - 1])); | 555 | (long) DIV_FROM_REG(data->fan_div[attr->index])); |
| 593 | } | 556 | } |
| 594 | 557 | ||
| 595 | /* Note: we save and restore the fan minimum here, because its value is | 558 | /* Note: we save and restore the fan minimum here, because its value is |
| @@ -597,11 +560,13 @@ show_fan_div_reg(struct device *dev, char *buf, int nr) | |||
| 597 | least surprise; the user doesn't expect the fan minimum to change just | 560 | least surprise; the user doesn't expect the fan minimum to change just |
| 598 | because the divisor changed. */ | 561 | because the divisor changed. */ |
| 599 | static ssize_t | 562 | static ssize_t |
| 600 | store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) | 563 | store_fan_div(struct device *dev, struct device_attribute *da, |
| 564 | const char *buf, size_t count) | ||
| 601 | { | 565 | { |
| 602 | struct i2c_client *client = to_i2c_client(dev); | 566 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 603 | struct w83781d_data *data = i2c_get_clientdata(client); | 567 | struct w83781d_data *data = dev_get_drvdata(dev); |
| 604 | unsigned long min; | 568 | unsigned long min; |
| 569 | int nr = attr->index; | ||
| 605 | u8 reg; | 570 | u8 reg; |
| 606 | unsigned long val = simple_strtoul(buf, NULL, 10); | 571 | unsigned long val = simple_strtoul(buf, NULL, 10); |
| 607 | 572 | ||
| @@ -613,77 +578,72 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
| 613 | 578 | ||
| 614 | data->fan_div[nr] = DIV_TO_REG(val, data->type); | 579 | data->fan_div[nr] = DIV_TO_REG(val, data->type); |
| 615 | 580 | ||
| 616 | reg = (w83781d_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) | 581 | reg = (w83781d_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) |
| 617 | & (nr==0 ? 0xcf : 0x3f)) | 582 | & (nr==0 ? 0xcf : 0x3f)) |
| 618 | | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); | 583 | | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); |
| 619 | w83781d_write_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); | 584 | w83781d_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); |
| 620 | 585 | ||
| 621 | /* w83781d and as99127f don't have extended divisor bits */ | 586 | /* w83781d and as99127f don't have extended divisor bits */ |
| 622 | if (data->type != w83781d && data->type != as99127f) { | 587 | if (data->type != w83781d && data->type != as99127f) { |
| 623 | reg = (w83781d_read_value(client, W83781D_REG_VBAT) | 588 | reg = (w83781d_read_value(data, W83781D_REG_VBAT) |
| 624 | & ~(1 << (5 + nr))) | 589 | & ~(1 << (5 + nr))) |
| 625 | | ((data->fan_div[nr] & 0x04) << (3 + nr)); | 590 | | ((data->fan_div[nr] & 0x04) << (3 + nr)); |
| 626 | w83781d_write_value(client, W83781D_REG_VBAT, reg); | 591 | w83781d_write_value(data, W83781D_REG_VBAT, reg); |
| 627 | } | 592 | } |
| 628 | 593 | ||
| 629 | /* Restore fan_min */ | 594 | /* Restore fan_min */ |
| 630 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); | 595 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); |
| 631 | w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); | 596 | w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), data->fan_min[nr]); |
| 632 | 597 | ||
| 633 | mutex_unlock(&data->update_lock); | 598 | mutex_unlock(&data->update_lock); |
| 634 | return count; | 599 | return count; |
| 635 | } | 600 | } |
| 636 | 601 | ||
| 637 | #define sysfs_fan_div(offset) \ | 602 | static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, |
| 638 | static ssize_t show_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 603 | show_fan_div, store_fan_div, 0); |
| 639 | { \ | 604 | static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, |
| 640 | return show_fan_div_reg(dev, buf, offset); \ | 605 | show_fan_div, store_fan_div, 1); |
| 641 | } \ | 606 | static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR, |
| 642 | static ssize_t store_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 607 | show_fan_div, store_fan_div, 2); |
| 643 | { \ | ||
| 644 | return store_fan_div_reg(dev, buf, count, offset - 1); \ | ||
| 645 | } \ | ||
| 646 | static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset); | ||
| 647 | |||
| 648 | sysfs_fan_div(1); | ||
| 649 | sysfs_fan_div(2); | ||
| 650 | sysfs_fan_div(3); | ||
| 651 | 608 | ||
| 652 | static ssize_t | 609 | static ssize_t |
| 653 | show_pwm_reg(struct device *dev, char *buf, int nr) | 610 | show_pwm(struct device *dev, struct device_attribute *da, char *buf) |
| 654 | { | 611 | { |
| 612 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 655 | struct w83781d_data *data = w83781d_update_device(dev); | 613 | struct w83781d_data *data = w83781d_update_device(dev); |
| 656 | return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr - 1])); | 614 | return sprintf(buf, "%d\n", (int)data->pwm[attr->index]); |
| 657 | } | 615 | } |
| 658 | 616 | ||
| 659 | static ssize_t | 617 | static ssize_t |
| 660 | show_pwmenable_reg(struct device *dev, char *buf, int nr) | 618 | show_pwm2_enable(struct device *dev, struct device_attribute *da, char *buf) |
| 661 | { | 619 | { |
| 662 | struct w83781d_data *data = w83781d_update_device(dev); | 620 | struct w83781d_data *data = w83781d_update_device(dev); |
| 663 | return sprintf(buf, "%ld\n", (long) data->pwmenable[nr - 1]); | 621 | return sprintf(buf, "%d\n", (int)data->pwm2_enable); |
| 664 | } | 622 | } |
| 665 | 623 | ||
| 666 | static ssize_t | 624 | static ssize_t |
| 667 | store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) | 625 | store_pwm(struct device *dev, struct device_attribute *da, const char *buf, |
| 626 | size_t count) | ||
| 668 | { | 627 | { |
| 669 | struct i2c_client *client = to_i2c_client(dev); | 628 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 670 | struct w83781d_data *data = i2c_get_clientdata(client); | 629 | struct w83781d_data *data = dev_get_drvdata(dev); |
| 630 | int nr = attr->index; | ||
| 671 | u32 val; | 631 | u32 val; |
| 672 | 632 | ||
| 673 | val = simple_strtoul(buf, NULL, 10); | 633 | val = simple_strtoul(buf, NULL, 10); |
| 674 | 634 | ||
| 675 | mutex_lock(&data->update_lock); | 635 | mutex_lock(&data->update_lock); |
| 676 | data->pwm[nr - 1] = PWM_TO_REG(val); | 636 | data->pwm[nr] = SENSORS_LIMIT(val, 0, 255); |
| 677 | w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]); | 637 | w83781d_write_value(data, W83781D_REG_PWM[nr], data->pwm[nr]); |
| 678 | mutex_unlock(&data->update_lock); | 638 | mutex_unlock(&data->update_lock); |
| 679 | return count; | 639 | return count; |
| 680 | } | 640 | } |
| 681 | 641 | ||
| 682 | static ssize_t | 642 | static ssize_t |
| 683 | store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) | 643 | store_pwm2_enable(struct device *dev, struct device_attribute *da, |
| 644 | const char *buf, size_t count) | ||
| 684 | { | 645 | { |
| 685 | struct i2c_client *client = to_i2c_client(dev); | 646 | struct w83781d_data *data = dev_get_drvdata(dev); |
| 686 | struct w83781d_data *data = i2c_get_clientdata(client); | ||
| 687 | u32 val, reg; | 647 | u32 val, reg; |
| 688 | 648 | ||
| 689 | val = simple_strtoul(buf, NULL, 10); | 649 | val = simple_strtoul(buf, NULL, 10); |
| @@ -693,15 +653,15 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
| 693 | switch (val) { | 653 | switch (val) { |
| 694 | case 0: | 654 | case 0: |
| 695 | case 1: | 655 | case 1: |
| 696 | reg = w83781d_read_value(client, W83781D_REG_PWMCLK12); | 656 | reg = w83781d_read_value(data, W83781D_REG_PWMCLK12); |
| 697 | w83781d_write_value(client, W83781D_REG_PWMCLK12, | 657 | w83781d_write_value(data, W83781D_REG_PWMCLK12, |
| 698 | (reg & 0xf7) | (val << 3)); | 658 | (reg & 0xf7) | (val << 3)); |
| 699 | 659 | ||
| 700 | reg = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); | 660 | reg = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); |
| 701 | w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, | 661 | w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, |
| 702 | (reg & 0xef) | (!val << 4)); | 662 | (reg & 0xef) | (!val << 4)); |
| 703 | 663 | ||
| 704 | data->pwmenable[nr - 1] = val; | 664 | data->pwm2_enable = val; |
| 705 | break; | 665 | break; |
| 706 | 666 | ||
| 707 | default: | 667 | default: |
| @@ -713,50 +673,29 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
| 713 | return count; | 673 | return count; |
| 714 | } | 674 | } |
| 715 | 675 | ||
| 716 | #define sysfs_pwm(offset) \ | 676 | static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 0); |
| 717 | static ssize_t show_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 677 | static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 1); |
| 718 | { \ | 678 | static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 2); |
| 719 | return show_pwm_reg(dev, buf, offset); \ | 679 | static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 3); |
| 720 | } \ | 680 | /* only PWM2 can be enabled/disabled */ |
| 721 | static ssize_t store_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, \ | 681 | static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, |
| 722 | const char *buf, size_t count) \ | 682 | show_pwm2_enable, store_pwm2_enable); |
| 723 | { \ | ||
| 724 | return store_pwm_reg(dev, buf, count, offset); \ | ||
| 725 | } \ | ||
| 726 | static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | ||
| 727 | show_regs_pwm_##offset, store_regs_pwm_##offset); | ||
| 728 | |||
| 729 | #define sysfs_pwmenable(offset) \ | ||
| 730 | static ssize_t show_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 731 | { \ | ||
| 732 | return show_pwmenable_reg(dev, buf, offset); \ | ||
| 733 | } \ | ||
| 734 | static ssize_t store_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, \ | ||
| 735 | const char *buf, size_t count) \ | ||
| 736 | { \ | ||
| 737 | return store_pwmenable_reg(dev, buf, count, offset); \ | ||
| 738 | } \ | ||
| 739 | static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ | ||
| 740 | show_regs_pwmenable_##offset, store_regs_pwmenable_##offset); | ||
| 741 | |||
| 742 | sysfs_pwm(1); | ||
| 743 | sysfs_pwm(2); | ||
| 744 | sysfs_pwmenable(2); /* only PWM2 can be enabled/disabled */ | ||
| 745 | sysfs_pwm(3); | ||
| 746 | sysfs_pwm(4); | ||
| 747 | 683 | ||
| 748 | static ssize_t | 684 | static ssize_t |
| 749 | show_sensor_reg(struct device *dev, char *buf, int nr) | 685 | show_sensor(struct device *dev, struct device_attribute *da, char *buf) |
| 750 | { | 686 | { |
| 687 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 751 | struct w83781d_data *data = w83781d_update_device(dev); | 688 | struct w83781d_data *data = w83781d_update_device(dev); |
| 752 | return sprintf(buf, "%ld\n", (long) data->sens[nr - 1]); | 689 | return sprintf(buf, "%d\n", (int)data->sens[attr->index]); |
| 753 | } | 690 | } |
| 754 | 691 | ||
| 755 | static ssize_t | 692 | static ssize_t |
| 756 | store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | 693 | store_sensor(struct device *dev, struct device_attribute *da, |
| 694 | const char *buf, size_t count) | ||
| 757 | { | 695 | { |
| 758 | struct i2c_client *client = to_i2c_client(dev); | 696 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 759 | struct w83781d_data *data = i2c_get_clientdata(client); | 697 | struct w83781d_data *data = dev_get_drvdata(dev); |
| 698 | int nr = attr->index; | ||
| 760 | u32 val, tmp; | 699 | u32 val, tmp; |
| 761 | 700 | ||
| 762 | val = simple_strtoul(buf, NULL, 10); | 701 | val = simple_strtoul(buf, NULL, 10); |
| @@ -765,28 +704,28 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
| 765 | 704 | ||
| 766 | switch (val) { | 705 | switch (val) { |
| 767 | case 1: /* PII/Celeron diode */ | 706 | case 1: /* PII/Celeron diode */ |
| 768 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); | 707 | tmp = w83781d_read_value(data, W83781D_REG_SCFG1); |
| 769 | w83781d_write_value(client, W83781D_REG_SCFG1, | 708 | w83781d_write_value(data, W83781D_REG_SCFG1, |
| 770 | tmp | BIT_SCFG1[nr - 1]); | 709 | tmp | BIT_SCFG1[nr]); |
| 771 | tmp = w83781d_read_value(client, W83781D_REG_SCFG2); | 710 | tmp = w83781d_read_value(data, W83781D_REG_SCFG2); |
| 772 | w83781d_write_value(client, W83781D_REG_SCFG2, | 711 | w83781d_write_value(data, W83781D_REG_SCFG2, |
| 773 | tmp | BIT_SCFG2[nr - 1]); | 712 | tmp | BIT_SCFG2[nr]); |
| 774 | data->sens[nr - 1] = val; | 713 | data->sens[nr] = val; |
| 775 | break; | 714 | break; |
| 776 | case 2: /* 3904 */ | 715 | case 2: /* 3904 */ |
| 777 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); | 716 | tmp = w83781d_read_value(data, W83781D_REG_SCFG1); |
| 778 | w83781d_write_value(client, W83781D_REG_SCFG1, | 717 | w83781d_write_value(data, W83781D_REG_SCFG1, |
| 779 | tmp | BIT_SCFG1[nr - 1]); | 718 | tmp | BIT_SCFG1[nr]); |
| 780 | tmp = w83781d_read_value(client, W83781D_REG_SCFG2); | 719 | tmp = w83781d_read_value(data, W83781D_REG_SCFG2); |
| 781 | w83781d_write_value(client, W83781D_REG_SCFG2, | 720 | w83781d_write_value(data, W83781D_REG_SCFG2, |
| 782 | tmp & ~BIT_SCFG2[nr - 1]); | 721 | tmp & ~BIT_SCFG2[nr]); |
| 783 | data->sens[nr - 1] = val; | 722 | data->sens[nr] = val; |
| 784 | break; | 723 | break; |
| 785 | case W83781D_DEFAULT_BETA: /* thermistor */ | 724 | case W83781D_DEFAULT_BETA: /* thermistor */ |
| 786 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); | 725 | tmp = w83781d_read_value(data, W83781D_REG_SCFG1); |
| 787 | w83781d_write_value(client, W83781D_REG_SCFG1, | 726 | w83781d_write_value(data, W83781D_REG_SCFG1, |
| 788 | tmp & ~BIT_SCFG1[nr - 1]); | 727 | tmp & ~BIT_SCFG1[nr]); |
| 789 | data->sens[nr - 1] = val; | 728 | data->sens[nr] = val; |
| 790 | break; | 729 | break; |
| 791 | default: | 730 | default: |
| 792 | dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n", | 731 | dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n", |
| @@ -798,20 +737,22 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
| 798 | return count; | 737 | return count; |
| 799 | } | 738 | } |
| 800 | 739 | ||
| 801 | #define sysfs_sensor(offset) \ | 740 | static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR, |
| 802 | static ssize_t show_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 741 | show_sensor, store_sensor, 0); |
| 803 | { \ | 742 | static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, |
| 804 | return show_sensor_reg(dev, buf, offset); \ | 743 | show_sensor, store_sensor, 0); |
| 805 | } \ | 744 | static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, |
| 806 | static ssize_t store_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 745 | show_sensor, store_sensor, 0); |
| 807 | { \ | ||
| 808 | return store_sensor_reg(dev, buf, count, offset); \ | ||
| 809 | } \ | ||
| 810 | static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset); | ||
| 811 | 746 | ||
| 812 | sysfs_sensor(1); | 747 | /* I2C devices get this name attribute automatically, but for ISA devices |
| 813 | sysfs_sensor(2); | 748 | we must create it by ourselves. */ |
| 814 | sysfs_sensor(3); | 749 | static ssize_t |
| 750 | show_name(struct device *dev, struct device_attribute *devattr, char *buf) | ||
| 751 | { | ||
| 752 | struct w83781d_data *data = dev_get_drvdata(dev); | ||
| 753 | return sprintf(buf, "%s\n", data->client.name); | ||
| 754 | } | ||
| 755 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
| 815 | 756 | ||
| 816 | /* This function is called when: | 757 | /* This function is called when: |
| 817 | * w83781d_driver is inserted (when this module is loaded), for each | 758 | * w83781d_driver is inserted (when this module is loaded), for each |
| @@ -825,12 +766,6 @@ w83781d_attach_adapter(struct i2c_adapter *adapter) | |||
| 825 | return i2c_probe(adapter, &addr_data, w83781d_detect); | 766 | return i2c_probe(adapter, &addr_data, w83781d_detect); |
| 826 | } | 767 | } |
| 827 | 768 | ||
| 828 | static int | ||
| 829 | w83781d_isa_attach_adapter(struct i2c_adapter *adapter) | ||
| 830 | { | ||
| 831 | return w83781d_detect(adapter, isa_address, -1); | ||
| 832 | } | ||
| 833 | |||
| 834 | /* Assumes that adapter is of I2C, not ISA variety. | 769 | /* Assumes that adapter is of I2C, not ISA variety. |
| 835 | * OTHERWISE DON'T CALL THIS | 770 | * OTHERWISE DON'T CALL THIS |
| 836 | */ | 771 | */ |
| @@ -862,12 +797,12 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, | |||
| 862 | goto ERROR_SC_1; | 797 | goto ERROR_SC_1; |
| 863 | } | 798 | } |
| 864 | } | 799 | } |
| 865 | w83781d_write_value(new_client, W83781D_REG_I2C_SUBADDR, | 800 | w83781d_write_value(data, W83781D_REG_I2C_SUBADDR, |
| 866 | (force_subclients[2] & 0x07) | | 801 | (force_subclients[2] & 0x07) | |
| 867 | ((force_subclients[3] & 0x07) << 4)); | 802 | ((force_subclients[3] & 0x07) << 4)); |
| 868 | data->lm75[0]->addr = force_subclients[2]; | 803 | data->lm75[0]->addr = force_subclients[2]; |
| 869 | } else { | 804 | } else { |
| 870 | val1 = w83781d_read_value(new_client, W83781D_REG_I2C_SUBADDR); | 805 | val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR); |
| 871 | data->lm75[0]->addr = 0x48 + (val1 & 0x07); | 806 | data->lm75[0]->addr = 0x48 + (val1 & 0x07); |
| 872 | } | 807 | } |
| 873 | 808 | ||
| @@ -937,20 +872,20 @@ ERROR_SC_0: | |||
| 937 | return err; | 872 | return err; |
| 938 | } | 873 | } |
| 939 | 874 | ||
| 940 | #define IN_UNIT_ATTRS(X) \ | 875 | #define IN_UNIT_ATTRS(X) \ |
| 941 | &dev_attr_in##X##_input.attr, \ | 876 | &sensor_dev_attr_in##X##_input.dev_attr.attr, \ |
| 942 | &dev_attr_in##X##_min.attr, \ | 877 | &sensor_dev_attr_in##X##_min.dev_attr.attr, \ |
| 943 | &dev_attr_in##X##_max.attr | 878 | &sensor_dev_attr_in##X##_max.dev_attr.attr |
| 944 | 879 | ||
| 945 | #define FAN_UNIT_ATTRS(X) \ | 880 | #define FAN_UNIT_ATTRS(X) \ |
| 946 | &dev_attr_fan##X##_input.attr, \ | 881 | &sensor_dev_attr_fan##X##_input.dev_attr.attr, \ |
| 947 | &dev_attr_fan##X##_min.attr, \ | 882 | &sensor_dev_attr_fan##X##_min.dev_attr.attr, \ |
| 948 | &dev_attr_fan##X##_div.attr | 883 | &sensor_dev_attr_fan##X##_div.dev_attr.attr |
| 949 | 884 | ||
| 950 | #define TEMP_UNIT_ATTRS(X) \ | 885 | #define TEMP_UNIT_ATTRS(X) \ |
| 951 | &dev_attr_temp##X##_input.attr, \ | 886 | &sensor_dev_attr_temp##X##_input.dev_attr.attr, \ |
| 952 | &dev_attr_temp##X##_max.attr, \ | 887 | &sensor_dev_attr_temp##X##_max.dev_attr.attr, \ |
| 953 | &dev_attr_temp##X##_max_hyst.attr | 888 | &sensor_dev_attr_temp##X##_max_hyst.dev_attr.attr |
| 954 | 889 | ||
| 955 | static struct attribute* w83781d_attributes[] = { | 890 | static struct attribute* w83781d_attributes[] = { |
| 956 | IN_UNIT_ATTRS(0), | 891 | IN_UNIT_ATTRS(0), |
| @@ -980,91 +915,115 @@ static struct attribute *w83781d_attributes_opt[] = { | |||
| 980 | IN_UNIT_ATTRS(7), | 915 | IN_UNIT_ATTRS(7), |
| 981 | IN_UNIT_ATTRS(8), | 916 | IN_UNIT_ATTRS(8), |
| 982 | TEMP_UNIT_ATTRS(3), | 917 | TEMP_UNIT_ATTRS(3), |
| 983 | &dev_attr_pwm1.attr, | 918 | &sensor_dev_attr_pwm1.dev_attr.attr, |
| 984 | &dev_attr_pwm2.attr, | 919 | &sensor_dev_attr_pwm2.dev_attr.attr, |
| 920 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
| 921 | &sensor_dev_attr_pwm4.dev_attr.attr, | ||
| 985 | &dev_attr_pwm2_enable.attr, | 922 | &dev_attr_pwm2_enable.attr, |
| 986 | &dev_attr_pwm3.attr, | 923 | &sensor_dev_attr_temp1_type.dev_attr.attr, |
| 987 | &dev_attr_pwm4.attr, | 924 | &sensor_dev_attr_temp2_type.dev_attr.attr, |
| 988 | &dev_attr_temp1_type.attr, | 925 | &sensor_dev_attr_temp3_type.dev_attr.attr, |
| 989 | &dev_attr_temp2_type.attr, | ||
| 990 | &dev_attr_temp3_type.attr, | ||
| 991 | NULL | 926 | NULL |
| 992 | }; | 927 | }; |
| 993 | static const struct attribute_group w83781d_group_opt = { | 928 | static const struct attribute_group w83781d_group_opt = { |
| 994 | .attrs = w83781d_attributes_opt, | 929 | .attrs = w83781d_attributes_opt, |
| 995 | }; | 930 | }; |
| 996 | 931 | ||
| 932 | /* No clean up is done on error, it's up to the caller */ | ||
| 997 | static int | 933 | static int |
| 998 | w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | 934 | w83781d_create_files(struct device *dev, int kind, int is_isa) |
| 999 | { | 935 | { |
| 1000 | int i = 0, val1 = 0, val2; | ||
| 1001 | struct i2c_client *client; | ||
| 1002 | struct device *dev; | ||
| 1003 | struct w83781d_data *data; | ||
| 1004 | int err; | 936 | int err; |
| 1005 | const char *client_name = ""; | ||
| 1006 | int is_isa = i2c_is_isa_adapter(adapter); | ||
| 1007 | enum vendor { winbond, asus } vendid; | ||
| 1008 | 937 | ||
| 1009 | if (!is_isa | 938 | if ((err = sysfs_create_group(&dev->kobj, &w83781d_group))) |
| 1010 | && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 939 | return err; |
| 1011 | err = -EINVAL; | 940 | |
| 1012 | goto ERROR0; | 941 | if (kind != w83783s) { |
| 942 | if ((err = device_create_file(dev, | ||
| 943 | &sensor_dev_attr_in1_input.dev_attr)) | ||
| 944 | || (err = device_create_file(dev, | ||
| 945 | &sensor_dev_attr_in1_min.dev_attr)) | ||
| 946 | || (err = device_create_file(dev, | ||
| 947 | &sensor_dev_attr_in1_max.dev_attr))) | ||
| 948 | return err; | ||
| 949 | } | ||
| 950 | if (kind != as99127f && kind != w83781d && kind != w83783s) { | ||
| 951 | if ((err = device_create_file(dev, | ||
| 952 | &sensor_dev_attr_in7_input.dev_attr)) | ||
| 953 | || (err = device_create_file(dev, | ||
| 954 | &sensor_dev_attr_in7_min.dev_attr)) | ||
| 955 | || (err = device_create_file(dev, | ||
| 956 | &sensor_dev_attr_in7_max.dev_attr)) | ||
| 957 | || (err = device_create_file(dev, | ||
| 958 | &sensor_dev_attr_in8_input.dev_attr)) | ||
| 959 | || (err = device_create_file(dev, | ||
| 960 | &sensor_dev_attr_in8_min.dev_attr)) | ||
| 961 | || (err = device_create_file(dev, | ||
| 962 | &sensor_dev_attr_in8_max.dev_attr))) | ||
| 963 | return err; | ||
| 964 | } | ||
| 965 | if (kind != w83783s) { | ||
| 966 | if ((err = device_create_file(dev, | ||
| 967 | &sensor_dev_attr_temp3_input.dev_attr)) | ||
| 968 | || (err = device_create_file(dev, | ||
| 969 | &sensor_dev_attr_temp3_max.dev_attr)) | ||
| 970 | || (err = device_create_file(dev, | ||
| 971 | &sensor_dev_attr_temp3_max_hyst.dev_attr))) | ||
| 972 | return err; | ||
| 1013 | } | 973 | } |
| 1014 | 974 | ||
| 1015 | /* Prevent users from forcing a kind for a bus it isn't supposed | 975 | if (kind != w83781d && kind != as99127f) { |
| 1016 | to possibly be on */ | 976 | if ((err = device_create_file(dev, |
| 1017 | if (is_isa && (kind == as99127f || kind == w83783s)) { | 977 | &sensor_dev_attr_pwm1.dev_attr)) |
| 1018 | dev_err(&adapter->dev, | 978 | || (err = device_create_file(dev, |
| 1019 | "Cannot force I2C-only chip for ISA address 0x%02x.\n", | 979 | &sensor_dev_attr_pwm2.dev_attr)) |
| 1020 | address); | 980 | || (err = device_create_file(dev, &dev_attr_pwm2_enable))) |
| 1021 | err = -EINVAL; | 981 | return err; |
| 1022 | goto ERROR0; | ||
| 1023 | } | 982 | } |
| 1024 | 983 | if (kind == w83782d && !is_isa) { | |
| 1025 | if (is_isa) | 984 | if ((err = device_create_file(dev, |
| 1026 | if (!request_region(address, W83781D_EXTENT, | 985 | &sensor_dev_attr_pwm3.dev_attr)) |
| 1027 | w83781d_isa_driver.driver.name)) { | 986 | || (err = device_create_file(dev, |
| 1028 | dev_dbg(&adapter->dev, "Request of region " | 987 | &sensor_dev_attr_pwm4.dev_attr))) |
| 1029 | "0x%x-0x%x for w83781d failed\n", address, | 988 | return err; |
| 1030 | address + W83781D_EXTENT - 1); | 989 | } |
| 1031 | err = -EBUSY; | 990 | |
| 1032 | goto ERROR0; | 991 | if (kind != as99127f && kind != w83781d) { |
| 992 | if ((err = device_create_file(dev, | ||
| 993 | &sensor_dev_attr_temp1_type.dev_attr)) | ||
| 994 | || (err = device_create_file(dev, | ||
| 995 | &sensor_dev_attr_temp2_type.dev_attr))) | ||
| 996 | return err; | ||
| 997 | if (kind != w83783s) { | ||
| 998 | if ((err = device_create_file(dev, | ||
| 999 | &sensor_dev_attr_temp3_type.dev_attr))) | ||
| 1000 | return err; | ||
| 1033 | } | 1001 | } |
| 1002 | } | ||
| 1034 | 1003 | ||
| 1035 | /* Probe whether there is anything available on this address. Already | 1004 | if (is_isa) { |
| 1036 | done for SMBus clients */ | 1005 | err = device_create_file(&pdev->dev, &dev_attr_name); |
| 1037 | if (kind < 0) { | 1006 | if (err) |
| 1038 | if (is_isa) { | 1007 | return err; |
| 1008 | } | ||
| 1039 | 1009 | ||
| 1040 | #define REALLY_SLOW_IO | 1010 | return 0; |
| 1041 | /* We need the timeouts for at least some LM78-like | 1011 | } |
| 1042 | chips. But only if we read 'undefined' registers. */ | ||
| 1043 | i = inb_p(address + 1); | ||
| 1044 | if (inb_p(address + 2) != i | ||
| 1045 | || inb_p(address + 3) != i | ||
| 1046 | || inb_p(address + 7) != i) { | ||
| 1047 | dev_dbg(&adapter->dev, "Detection of w83781d " | ||
| 1048 | "chip failed at step 1\n"); | ||
| 1049 | err = -ENODEV; | ||
| 1050 | goto ERROR1; | ||
| 1051 | } | ||
| 1052 | #undef REALLY_SLOW_IO | ||
| 1053 | 1012 | ||
| 1054 | /* Let's just hope nothing breaks here */ | 1013 | static int |
| 1055 | i = inb_p(address + 5) & 0x7f; | 1014 | w83781d_detect(struct i2c_adapter *adapter, int address, int kind) |
| 1056 | outb_p(~i & 0x7f, address + 5); | 1015 | { |
| 1057 | val2 = inb_p(address + 5) & 0x7f; | 1016 | int val1 = 0, val2; |
| 1058 | if (val2 != (~i & 0x7f)) { | 1017 | struct i2c_client *client; |
| 1059 | outb_p(i, address + 5); | 1018 | struct device *dev; |
| 1060 | dev_dbg(&adapter->dev, "Detection of w83781d " | 1019 | struct w83781d_data *data; |
| 1061 | "chip failed at step 2 (0x%x != " | 1020 | int err; |
| 1062 | "0x%x at 0x%x)\n", val2, ~i & 0x7f, | 1021 | const char *client_name = ""; |
| 1063 | address + 5); | 1022 | enum vendor { winbond, asus } vendid; |
| 1064 | err = -ENODEV; | 1023 | |
| 1065 | goto ERROR1; | 1024 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
| 1066 | } | 1025 | err = -EINVAL; |
| 1067 | } | 1026 | goto ERROR1; |
| 1068 | } | 1027 | } |
| 1069 | 1028 | ||
| 1070 | /* OK. For now, we presume we have a valid client. We now create the | 1029 | /* OK. For now, we presume we have a valid client. We now create the |
| @@ -1081,8 +1040,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 1081 | client->addr = address; | 1040 | client->addr = address; |
| 1082 | mutex_init(&data->lock); | 1041 | mutex_init(&data->lock); |
| 1083 | client->adapter = adapter; | 1042 | client->adapter = adapter; |
| 1084 | client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver; | 1043 | client->driver = &w83781d_driver; |
| 1085 | client->flags = 0; | ||
| 1086 | dev = &client->dev; | 1044 | dev = &client->dev; |
| 1087 | 1045 | ||
| 1088 | /* Now, we do the remaining detection. */ | 1046 | /* Now, we do the remaining detection. */ |
| @@ -1092,14 +1050,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 1092 | force_*=... parameter, and the Winbond will be reset to the right | 1050 | force_*=... parameter, and the Winbond will be reset to the right |
| 1093 | bank. */ | 1051 | bank. */ |
| 1094 | if (kind < 0) { | 1052 | if (kind < 0) { |
| 1095 | if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) { | 1053 | if (w83781d_read_value(data, W83781D_REG_CONFIG) & 0x80) { |
| 1096 | dev_dbg(&adapter->dev, "Detection of w83781d chip " | 1054 | dev_dbg(&adapter->dev, "Detection of w83781d chip " |
| 1097 | "failed at step 3\n"); | 1055 | "failed at step 3\n"); |
| 1098 | err = -ENODEV; | 1056 | err = -ENODEV; |
| 1099 | goto ERROR2; | 1057 | goto ERROR2; |
| 1100 | } | 1058 | } |
| 1101 | val1 = w83781d_read_value(client, W83781D_REG_BANK); | 1059 | val1 = w83781d_read_value(data, W83781D_REG_BANK); |
| 1102 | val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN); | 1060 | val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN); |
| 1103 | /* Check for Winbond or Asus ID if in bank 0 */ | 1061 | /* Check for Winbond or Asus ID if in bank 0 */ |
| 1104 | if ((!(val1 & 0x07)) && | 1062 | if ((!(val1 & 0x07)) && |
| 1105 | (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)) | 1063 | (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)) |
| @@ -1111,10 +1069,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 1111 | } | 1069 | } |
| 1112 | /* If Winbond SMBus, check address at 0x48. | 1070 | /* If Winbond SMBus, check address at 0x48. |
| 1113 | Asus doesn't support, except for as99127f rev.2 */ | 1071 | Asus doesn't support, except for as99127f rev.2 */ |
| 1114 | if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) || | 1072 | if ((!(val1 & 0x80) && (val2 == 0xa3)) || |
| 1115 | ((val1 & 0x80) && (val2 == 0x5c)))) { | 1073 | ((val1 & 0x80) && (val2 == 0x5c))) { |
| 1116 | if (w83781d_read_value | 1074 | if (w83781d_read_value |
| 1117 | (client, W83781D_REG_I2C_ADDR) != address) { | 1075 | (data, W83781D_REG_I2C_ADDR) != address) { |
| 1118 | dev_dbg(&adapter->dev, "Detection of w83781d " | 1076 | dev_dbg(&adapter->dev, "Detection of w83781d " |
| 1119 | "chip failed at step 5\n"); | 1077 | "chip failed at step 5\n"); |
| 1120 | err = -ENODEV; | 1078 | err = -ENODEV; |
| @@ -1125,14 +1083,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 1125 | 1083 | ||
| 1126 | /* We have either had a force parameter, or we have already detected the | 1084 | /* We have either had a force parameter, or we have already detected the |
| 1127 | Winbond. Put it now into bank 0 and Vendor ID High Byte */ | 1085 | Winbond. Put it now into bank 0 and Vendor ID High Byte */ |
| 1128 | w83781d_write_value(client, W83781D_REG_BANK, | 1086 | w83781d_write_value(data, W83781D_REG_BANK, |
| 1129 | (w83781d_read_value(client, W83781D_REG_BANK) | 1087 | (w83781d_read_value(data, W83781D_REG_BANK) |
| 1130 | & 0x78) | 0x80); | 1088 | & 0x78) | 0x80); |
| 1131 | 1089 | ||
| 1132 | /* Determine the chip type. */ | 1090 | /* Determine the chip type. */ |
| 1133 | if (kind <= 0) { | 1091 | if (kind <= 0) { |
| 1134 | /* get vendor ID */ | 1092 | /* get vendor ID */ |
| 1135 | val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN); | 1093 | val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN); |
| 1136 | if (val2 == 0x5c) | 1094 | if (val2 == 0x5c) |
| 1137 | vendid = winbond; | 1095 | vendid = winbond; |
| 1138 | else if (val2 == 0x12) | 1096 | else if (val2 == 0x12) |
| @@ -1144,17 +1102,16 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 1144 | goto ERROR2; | 1102 | goto ERROR2; |
| 1145 | } | 1103 | } |
| 1146 | 1104 | ||
| 1147 | val1 = w83781d_read_value(client, W83781D_REG_WCHIPID); | 1105 | val1 = w83781d_read_value(data, W83781D_REG_WCHIPID); |
| 1148 | if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond) | 1106 | if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond) |
| 1149 | kind = w83781d; | 1107 | kind = w83781d; |
| 1150 | else if (val1 == 0x30 && vendid == winbond) | 1108 | else if (val1 == 0x30 && vendid == winbond) |
| 1151 | kind = w83782d; | 1109 | kind = w83782d; |
| 1152 | else if (val1 == 0x40 && vendid == winbond && !is_isa | 1110 | else if (val1 == 0x40 && vendid == winbond && address == 0x2d) |
| 1153 | && address == 0x2d) | ||
| 1154 | kind = w83783s; | 1111 | kind = w83783s; |
| 1155 | else if (val1 == 0x21 && vendid == winbond) | 1112 | else if (val1 == 0x21 && vendid == winbond) |
| 1156 | kind = w83627hf; | 1113 | kind = w83627hf; |
| 1157 | else if (val1 == 0x31 && !is_isa && address >= 0x28) | 1114 | else if (val1 == 0x31 && address >= 0x28) |
| 1158 | kind = as99127f; | 1115 | kind = as99127f; |
| 1159 | else { | 1116 | else { |
| 1160 | if (kind == 0) | 1117 | if (kind == 0) |
| @@ -1182,86 +1139,23 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 1182 | strlcpy(client->name, client_name, I2C_NAME_SIZE); | 1139 | strlcpy(client->name, client_name, I2C_NAME_SIZE); |
| 1183 | data->type = kind; | 1140 | data->type = kind; |
| 1184 | 1141 | ||
| 1185 | data->valid = 0; | ||
| 1186 | mutex_init(&data->update_lock); | ||
| 1187 | |||
| 1188 | /* Tell the I2C layer a new client has arrived */ | 1142 | /* Tell the I2C layer a new client has arrived */ |
| 1189 | if ((err = i2c_attach_client(client))) | 1143 | if ((err = i2c_attach_client(client))) |
| 1190 | goto ERROR2; | 1144 | goto ERROR2; |
| 1191 | 1145 | ||
| 1192 | /* attach secondary i2c lm75-like clients */ | 1146 | /* attach secondary i2c lm75-like clients */ |
| 1193 | if (!is_isa) { | 1147 | if ((err = w83781d_detect_subclients(adapter, address, |
| 1194 | if ((err = w83781d_detect_subclients(adapter, address, | 1148 | kind, client))) |
| 1195 | kind, client))) | 1149 | goto ERROR3; |
| 1196 | goto ERROR3; | ||
| 1197 | } else { | ||
| 1198 | data->lm75[0] = NULL; | ||
| 1199 | data->lm75[1] = NULL; | ||
| 1200 | } | ||
| 1201 | 1150 | ||
| 1202 | /* Initialize the chip */ | 1151 | /* Initialize the chip */ |
| 1203 | w83781d_init_client(client); | 1152 | w83781d_init_device(dev); |
| 1204 | |||
| 1205 | /* A few vars need to be filled upon startup */ | ||
| 1206 | for (i = 1; i <= 3; i++) { | ||
| 1207 | data->fan_min[i - 1] = w83781d_read_value(client, | ||
| 1208 | W83781D_REG_FAN_MIN(i)); | ||
| 1209 | } | ||
| 1210 | if (kind != w83781d && kind != as99127f) | ||
| 1211 | for (i = 0; i < 4; i++) | ||
| 1212 | data->pwmenable[i] = 1; | ||
| 1213 | 1153 | ||
| 1214 | /* Register sysfs hooks */ | 1154 | /* Register sysfs hooks */ |
| 1215 | if ((err = sysfs_create_group(&dev->kobj, &w83781d_group))) | 1155 | err = w83781d_create_files(dev, kind, 0); |
| 1156 | if (err) | ||
| 1216 | goto ERROR4; | 1157 | goto ERROR4; |
| 1217 | 1158 | ||
| 1218 | if (kind != w83783s) { | ||
| 1219 | if ((err = device_create_file(dev, &dev_attr_in1_input)) | ||
| 1220 | || (err = device_create_file(dev, &dev_attr_in1_min)) | ||
| 1221 | || (err = device_create_file(dev, &dev_attr_in1_max))) | ||
| 1222 | goto ERROR4; | ||
| 1223 | } | ||
| 1224 | if (kind != as99127f && kind != w83781d && kind != w83783s) { | ||
| 1225 | if ((err = device_create_file(dev, &dev_attr_in7_input)) | ||
| 1226 | || (err = device_create_file(dev, &dev_attr_in7_min)) | ||
| 1227 | || (err = device_create_file(dev, &dev_attr_in7_max)) | ||
| 1228 | || (err = device_create_file(dev, &dev_attr_in8_input)) | ||
| 1229 | || (err = device_create_file(dev, &dev_attr_in8_min)) | ||
| 1230 | || (err = device_create_file(dev, &dev_attr_in8_max))) | ||
| 1231 | goto ERROR4; | ||
| 1232 | } | ||
| 1233 | if (kind != w83783s) { | ||
| 1234 | if ((err = device_create_file(dev, &dev_attr_temp3_input)) | ||
| 1235 | || (err = device_create_file(dev, &dev_attr_temp3_max)) | ||
| 1236 | || (err = device_create_file(dev, | ||
| 1237 | &dev_attr_temp3_max_hyst))) | ||
| 1238 | goto ERROR4; | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | if (kind != w83781d && kind != as99127f) { | ||
| 1242 | if ((err = device_create_file(dev, &dev_attr_pwm1)) | ||
| 1243 | || (err = device_create_file(dev, &dev_attr_pwm2)) | ||
| 1244 | || (err = device_create_file(dev, &dev_attr_pwm2_enable))) | ||
| 1245 | goto ERROR4; | ||
| 1246 | } | ||
| 1247 | if (kind == w83782d && !is_isa) { | ||
| 1248 | if ((err = device_create_file(dev, &dev_attr_pwm3)) | ||
| 1249 | || (err = device_create_file(dev, &dev_attr_pwm4))) | ||
| 1250 | goto ERROR4; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | if (kind != as99127f && kind != w83781d) { | ||
| 1254 | if ((err = device_create_file(dev, &dev_attr_temp1_type)) | ||
| 1255 | || (err = device_create_file(dev, | ||
| 1256 | &dev_attr_temp2_type))) | ||
| 1257 | goto ERROR4; | ||
| 1258 | if (kind != w83783s) { | ||
| 1259 | if ((err = device_create_file(dev, | ||
| 1260 | &dev_attr_temp3_type))) | ||
| 1261 | goto ERROR4; | ||
| 1262 | } | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | data->class_dev = hwmon_device_register(dev); | 1159 | data->class_dev = hwmon_device_register(dev); |
| 1266 | if (IS_ERR(data->class_dev)) { | 1160 | if (IS_ERR(data->class_dev)) { |
| 1267 | err = PTR_ERR(data->class_dev); | 1161 | err = PTR_ERR(data->class_dev); |
| @@ -1287,9 +1181,6 @@ ERROR3: | |||
| 1287 | ERROR2: | 1181 | ERROR2: |
| 1288 | kfree(data); | 1182 | kfree(data); |
| 1289 | ERROR1: | 1183 | ERROR1: |
| 1290 | if (is_isa) | ||
| 1291 | release_region(address, W83781D_EXTENT); | ||
| 1292 | ERROR0: | ||
| 1293 | return err; | 1184 | return err; |
| 1294 | } | 1185 | } |
| 1295 | 1186 | ||
| @@ -1305,8 +1196,6 @@ w83781d_detach_client(struct i2c_client *client) | |||
| 1305 | sysfs_remove_group(&client->dev.kobj, &w83781d_group); | 1196 | sysfs_remove_group(&client->dev.kobj, &w83781d_group); |
| 1306 | sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt); | 1197 | sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt); |
| 1307 | } | 1198 | } |
| 1308 | if (i2c_is_isa_client(client)) | ||
| 1309 | release_region(client->addr, W83781D_EXTENT); | ||
| 1310 | 1199 | ||
| 1311 | if ((err = i2c_detach_client(client))) | 1200 | if ((err = i2c_detach_client(client))) |
| 1312 | return err; | 1201 | return err; |
| @@ -1322,6 +1211,88 @@ w83781d_detach_client(struct i2c_client *client) | |||
| 1322 | return 0; | 1211 | return 0; |
| 1323 | } | 1212 | } |
| 1324 | 1213 | ||
| 1214 | static int __devinit | ||
| 1215 | w83781d_isa_probe(struct platform_device *pdev) | ||
| 1216 | { | ||
| 1217 | int err, reg; | ||
| 1218 | struct w83781d_data *data; | ||
| 1219 | struct resource *res; | ||
| 1220 | const char *name; | ||
| 1221 | |||
| 1222 | /* Reserve the ISA region */ | ||
| 1223 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 1224 | if (!request_region(res->start, W83781D_EXTENT, "w83781d")) { | ||
| 1225 | err = -EBUSY; | ||
| 1226 | goto exit; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) { | ||
| 1230 | err = -ENOMEM; | ||
| 1231 | goto exit_release_region; | ||
| 1232 | } | ||
| 1233 | mutex_init(&data->lock); | ||
| 1234 | data->client.addr = res->start; | ||
| 1235 | i2c_set_clientdata(&data->client, data); | ||
| 1236 | platform_set_drvdata(pdev, data); | ||
| 1237 | |||
| 1238 | reg = w83781d_read_value(data, W83781D_REG_WCHIPID); | ||
| 1239 | switch (reg) { | ||
| 1240 | case 0x21: | ||
| 1241 | data->type = w83627hf; | ||
| 1242 | name = "w83627hf"; | ||
| 1243 | break; | ||
| 1244 | case 0x30: | ||
| 1245 | data->type = w83782d; | ||
| 1246 | name = "w83782d"; | ||
| 1247 | break; | ||
| 1248 | default: | ||
| 1249 | data->type = w83781d; | ||
| 1250 | name = "w83781d"; | ||
| 1251 | } | ||
| 1252 | strlcpy(data->client.name, name, I2C_NAME_SIZE); | ||
| 1253 | |||
| 1254 | /* Initialize the W83781D chip */ | ||
| 1255 | w83781d_init_device(&pdev->dev); | ||
| 1256 | |||
| 1257 | /* Register sysfs hooks */ | ||
| 1258 | err = w83781d_create_files(&pdev->dev, data->type, 1); | ||
| 1259 | if (err) | ||
| 1260 | goto exit_remove_files; | ||
| 1261 | |||
| 1262 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
| 1263 | if (IS_ERR(data->class_dev)) { | ||
| 1264 | err = PTR_ERR(data->class_dev); | ||
| 1265 | goto exit_remove_files; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | return 0; | ||
| 1269 | |||
| 1270 | exit_remove_files: | ||
| 1271 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | ||
| 1272 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | ||
| 1273 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
| 1274 | kfree(data); | ||
| 1275 | exit_release_region: | ||
| 1276 | release_region(res->start, W83781D_EXTENT); | ||
| 1277 | exit: | ||
| 1278 | return err; | ||
| 1279 | } | ||
| 1280 | |||
| 1281 | static int __devexit | ||
| 1282 | w83781d_isa_remove(struct platform_device *pdev) | ||
| 1283 | { | ||
| 1284 | struct w83781d_data *data = platform_get_drvdata(pdev); | ||
| 1285 | |||
| 1286 | hwmon_device_unregister(data->class_dev); | ||
| 1287 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | ||
| 1288 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | ||
| 1289 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
| 1290 | release_region(data->client.addr, W83781D_EXTENT); | ||
| 1291 | kfree(data); | ||
| 1292 | |||
| 1293 | return 0; | ||
| 1294 | } | ||
| 1295 | |||
| 1325 | /* The SMBus locks itself, usually, but nothing may access the Winbond between | 1296 | /* The SMBus locks itself, usually, but nothing may access the Winbond between |
| 1326 | bank switches. ISA access must always be locked explicitly! | 1297 | bank switches. ISA access must always be locked explicitly! |
| 1327 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, | 1298 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, |
| @@ -1329,14 +1300,14 @@ w83781d_detach_client(struct i2c_client *client) | |||
| 1329 | There are some ugly typecasts here, but the good news is - they should | 1300 | There are some ugly typecasts here, but the good news is - they should |
| 1330 | nowhere else be necessary! */ | 1301 | nowhere else be necessary! */ |
| 1331 | static int | 1302 | static int |
| 1332 | w83781d_read_value(struct i2c_client *client, u16 reg) | 1303 | w83781d_read_value(struct w83781d_data *data, u16 reg) |
| 1333 | { | 1304 | { |
| 1334 | struct w83781d_data *data = i2c_get_clientdata(client); | 1305 | struct i2c_client *client = &data->client; |
| 1335 | int res, word_sized, bank; | 1306 | int res, word_sized, bank; |
| 1336 | struct i2c_client *cl; | 1307 | struct i2c_client *cl; |
| 1337 | 1308 | ||
| 1338 | mutex_lock(&data->lock); | 1309 | mutex_lock(&data->lock); |
| 1339 | if (i2c_is_isa_client(client)) { | 1310 | if (!client->driver) { /* ISA device */ |
| 1340 | word_sized = (((reg & 0xff00) == 0x100) | 1311 | word_sized = (((reg & 0xff00) == 0x100) |
| 1341 | || ((reg & 0xff00) == 0x200)) | 1312 | || ((reg & 0xff00) == 0x200)) |
| 1342 | && (((reg & 0x00ff) == 0x50) | 1313 | && (((reg & 0x00ff) == 0x50) |
| @@ -1398,14 +1369,14 @@ w83781d_read_value(struct i2c_client *client, u16 reg) | |||
| 1398 | } | 1369 | } |
| 1399 | 1370 | ||
| 1400 | static int | 1371 | static int |
| 1401 | w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) | 1372 | w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value) |
| 1402 | { | 1373 | { |
| 1403 | struct w83781d_data *data = i2c_get_clientdata(client); | 1374 | struct i2c_client *client = &data->client; |
| 1404 | int word_sized, bank; | 1375 | int word_sized, bank; |
| 1405 | struct i2c_client *cl; | 1376 | struct i2c_client *cl; |
| 1406 | 1377 | ||
| 1407 | mutex_lock(&data->lock); | 1378 | mutex_lock(&data->lock); |
| 1408 | if (i2c_is_isa_client(client)) { | 1379 | if (!client->driver) { /* ISA device */ |
| 1409 | word_sized = (((reg & 0xff00) == 0x100) | 1380 | word_sized = (((reg & 0xff00) == 0x100) |
| 1410 | || ((reg & 0xff00) == 0x200)) | 1381 | || ((reg & 0xff00) == 0x200)) |
| 1411 | && (((reg & 0x00ff) == 0x53) | 1382 | && (((reg & 0x00ff) == 0x53) |
| @@ -1462,13 +1433,18 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) | |||
| 1462 | } | 1433 | } |
| 1463 | 1434 | ||
| 1464 | static void | 1435 | static void |
| 1465 | w83781d_init_client(struct i2c_client *client) | 1436 | w83781d_init_device(struct device *dev) |
| 1466 | { | 1437 | { |
| 1467 | struct w83781d_data *data = i2c_get_clientdata(client); | 1438 | struct w83781d_data *data = dev_get_drvdata(dev); |
| 1468 | int i, p; | 1439 | int i, p; |
| 1469 | int type = data->type; | 1440 | int type = data->type; |
| 1470 | u8 tmp; | 1441 | u8 tmp; |
| 1471 | 1442 | ||
| 1443 | if (type == w83627hf) | ||
| 1444 | dev_info(dev, "The W83627HF chip is better supported by the " | ||
| 1445 | "w83627hf driver, support will be dropped from the " | ||
| 1446 | "w83781d driver soon\n"); | ||
| 1447 | |||
| 1472 | if (reset && type != as99127f) { /* this resets registers we don't have | 1448 | if (reset && type != as99127f) { /* this resets registers we don't have |
| 1473 | documentation for on the as99127f */ | 1449 | documentation for on the as99127f */ |
| 1474 | /* Resetting the chip has been the default for a long time, | 1450 | /* Resetting the chip has been the default for a long time, |
| @@ -1477,42 +1453,42 @@ w83781d_init_client(struct i2c_client *client) | |||
| 1477 | It might even go away if nobody reports it as being useful, | 1453 | It might even go away if nobody reports it as being useful, |
| 1478 | as I see very little reason why this would be needed at | 1454 | as I see very little reason why this would be needed at |
| 1479 | all. */ | 1455 | all. */ |
| 1480 | dev_info(&client->dev, "If reset=1 solved a problem you were " | 1456 | dev_info(dev, "If reset=1 solved a problem you were " |
| 1481 | "having, please report!\n"); | 1457 | "having, please report!\n"); |
| 1482 | 1458 | ||
| 1483 | /* save these registers */ | 1459 | /* save these registers */ |
| 1484 | i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); | 1460 | i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); |
| 1485 | p = w83781d_read_value(client, W83781D_REG_PWMCLK12); | 1461 | p = w83781d_read_value(data, W83781D_REG_PWMCLK12); |
| 1486 | /* Reset all except Watchdog values and last conversion values | 1462 | /* Reset all except Watchdog values and last conversion values |
| 1487 | This sets fan-divs to 2, among others */ | 1463 | This sets fan-divs to 2, among others */ |
| 1488 | w83781d_write_value(client, W83781D_REG_CONFIG, 0x80); | 1464 | w83781d_write_value(data, W83781D_REG_CONFIG, 0x80); |
| 1489 | /* Restore the registers and disable power-on abnormal beep. | 1465 | /* Restore the registers and disable power-on abnormal beep. |
| 1490 | This saves FAN 1/2/3 input/output values set by BIOS. */ | 1466 | This saves FAN 1/2/3 input/output values set by BIOS. */ |
| 1491 | w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); | 1467 | w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80); |
| 1492 | w83781d_write_value(client, W83781D_REG_PWMCLK12, p); | 1468 | w83781d_write_value(data, W83781D_REG_PWMCLK12, p); |
| 1493 | /* Disable master beep-enable (reset turns it on). | 1469 | /* Disable master beep-enable (reset turns it on). |
| 1494 | Individual beep_mask should be reset to off but for some reason | 1470 | Individual beep_mask should be reset to off but for some reason |
| 1495 | disabling this bit helps some people not get beeped */ | 1471 | disabling this bit helps some people not get beeped */ |
| 1496 | w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0); | 1472 | w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 0); |
| 1497 | } | 1473 | } |
| 1498 | 1474 | ||
| 1499 | /* Disable power-on abnormal beep, as advised by the datasheet. | 1475 | /* Disable power-on abnormal beep, as advised by the datasheet. |
| 1500 | Already done if reset=1. */ | 1476 | Already done if reset=1. */ |
| 1501 | if (init && !reset && type != as99127f) { | 1477 | if (init && !reset && type != as99127f) { |
| 1502 | i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); | 1478 | i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); |
| 1503 | w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); | 1479 | w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80); |
| 1504 | } | 1480 | } |
| 1505 | 1481 | ||
| 1506 | data->vrm = vid_which_vrm(); | 1482 | data->vrm = vid_which_vrm(); |
| 1507 | 1483 | ||
| 1508 | if ((type != w83781d) && (type != as99127f)) { | 1484 | if ((type != w83781d) && (type != as99127f)) { |
| 1509 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); | 1485 | tmp = w83781d_read_value(data, W83781D_REG_SCFG1); |
| 1510 | for (i = 1; i <= 3; i++) { | 1486 | for (i = 1; i <= 3; i++) { |
| 1511 | if (!(tmp & BIT_SCFG1[i - 1])) { | 1487 | if (!(tmp & BIT_SCFG1[i - 1])) { |
| 1512 | data->sens[i - 1] = W83781D_DEFAULT_BETA; | 1488 | data->sens[i - 1] = W83781D_DEFAULT_BETA; |
| 1513 | } else { | 1489 | } else { |
| 1514 | if (w83781d_read_value | 1490 | if (w83781d_read_value |
| 1515 | (client, | 1491 | (data, |
| 1516 | W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) | 1492 | W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) |
| 1517 | data->sens[i - 1] = 1; | 1493 | data->sens[i - 1] = 1; |
| 1518 | else | 1494 | else |
| @@ -1525,38 +1501,46 @@ w83781d_init_client(struct i2c_client *client) | |||
| 1525 | 1501 | ||
| 1526 | if (init && type != as99127f) { | 1502 | if (init && type != as99127f) { |
| 1527 | /* Enable temp2 */ | 1503 | /* Enable temp2 */ |
| 1528 | tmp = w83781d_read_value(client, W83781D_REG_TEMP2_CONFIG); | 1504 | tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG); |
| 1529 | if (tmp & 0x01) { | 1505 | if (tmp & 0x01) { |
| 1530 | dev_warn(&client->dev, "Enabling temp2, readings " | 1506 | dev_warn(dev, "Enabling temp2, readings " |
| 1531 | "might not make sense\n"); | 1507 | "might not make sense\n"); |
| 1532 | w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG, | 1508 | w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG, |
| 1533 | tmp & 0xfe); | 1509 | tmp & 0xfe); |
| 1534 | } | 1510 | } |
| 1535 | 1511 | ||
| 1536 | /* Enable temp3 */ | 1512 | /* Enable temp3 */ |
| 1537 | if (type != w83783s) { | 1513 | if (type != w83783s) { |
| 1538 | tmp = w83781d_read_value(client, | 1514 | tmp = w83781d_read_value(data, |
| 1539 | W83781D_REG_TEMP3_CONFIG); | 1515 | W83781D_REG_TEMP3_CONFIG); |
| 1540 | if (tmp & 0x01) { | 1516 | if (tmp & 0x01) { |
| 1541 | dev_warn(&client->dev, "Enabling temp3, " | 1517 | dev_warn(dev, "Enabling temp3, " |
| 1542 | "readings might not make sense\n"); | 1518 | "readings might not make sense\n"); |
| 1543 | w83781d_write_value(client, | 1519 | w83781d_write_value(data, |
| 1544 | W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); | 1520 | W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); |
| 1545 | } | 1521 | } |
| 1546 | } | 1522 | } |
| 1547 | } | 1523 | } |
| 1548 | 1524 | ||
| 1549 | /* Start monitoring */ | 1525 | /* Start monitoring */ |
| 1550 | w83781d_write_value(client, W83781D_REG_CONFIG, | 1526 | w83781d_write_value(data, W83781D_REG_CONFIG, |
| 1551 | (w83781d_read_value(client, | 1527 | (w83781d_read_value(data, |
| 1552 | W83781D_REG_CONFIG) & 0xf7) | 1528 | W83781D_REG_CONFIG) & 0xf7) |
| 1553 | | 0x01); | 1529 | | 0x01); |
| 1530 | |||
| 1531 | /* A few vars need to be filled upon startup */ | ||
| 1532 | for (i = 0; i < 3; i++) { | ||
| 1533 | data->fan_min[i] = w83781d_read_value(data, | ||
| 1534 | W83781D_REG_FAN_MIN(i)); | ||
| 1535 | } | ||
| 1536 | |||
| 1537 | mutex_init(&data->update_lock); | ||
| 1554 | } | 1538 | } |
| 1555 | 1539 | ||
| 1556 | static struct w83781d_data *w83781d_update_device(struct device *dev) | 1540 | static struct w83781d_data *w83781d_update_device(struct device *dev) |
| 1557 | { | 1541 | { |
| 1558 | struct i2c_client *client = to_i2c_client(dev); | 1542 | struct w83781d_data *data = dev_get_drvdata(dev); |
| 1559 | struct w83781d_data *data = i2c_get_clientdata(client); | 1543 | struct i2c_client *client = &data->client; |
| 1560 | int i; | 1544 | int i; |
| 1561 | 1545 | ||
| 1562 | mutex_lock(&data->update_lock); | 1546 | mutex_lock(&data->update_lock); |
| @@ -1569,98 +1553,97 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) | |||
| 1569 | if (data->type == w83783s && i == 1) | 1553 | if (data->type == w83783s && i == 1) |
| 1570 | continue; /* 783S has no in1 */ | 1554 | continue; /* 783S has no in1 */ |
| 1571 | data->in[i] = | 1555 | data->in[i] = |
| 1572 | w83781d_read_value(client, W83781D_REG_IN(i)); | 1556 | w83781d_read_value(data, W83781D_REG_IN(i)); |
| 1573 | data->in_min[i] = | 1557 | data->in_min[i] = |
| 1574 | w83781d_read_value(client, W83781D_REG_IN_MIN(i)); | 1558 | w83781d_read_value(data, W83781D_REG_IN_MIN(i)); |
| 1575 | data->in_max[i] = | 1559 | data->in_max[i] = |
| 1576 | w83781d_read_value(client, W83781D_REG_IN_MAX(i)); | 1560 | w83781d_read_value(data, W83781D_REG_IN_MAX(i)); |
| 1577 | if ((data->type != w83782d) | 1561 | if ((data->type != w83782d) |
| 1578 | && (data->type != w83627hf) && (i == 6)) | 1562 | && (data->type != w83627hf) && (i == 6)) |
| 1579 | break; | 1563 | break; |
| 1580 | } | 1564 | } |
| 1581 | for (i = 1; i <= 3; i++) { | 1565 | for (i = 0; i < 3; i++) { |
| 1582 | data->fan[i - 1] = | 1566 | data->fan[i] = |
| 1583 | w83781d_read_value(client, W83781D_REG_FAN(i)); | 1567 | w83781d_read_value(data, W83781D_REG_FAN(i)); |
| 1584 | data->fan_min[i - 1] = | 1568 | data->fan_min[i] = |
| 1585 | w83781d_read_value(client, W83781D_REG_FAN_MIN(i)); | 1569 | w83781d_read_value(data, W83781D_REG_FAN_MIN(i)); |
| 1586 | } | 1570 | } |
| 1587 | if (data->type != w83781d && data->type != as99127f) { | 1571 | if (data->type != w83781d && data->type != as99127f) { |
| 1588 | for (i = 1; i <= 4; i++) { | 1572 | for (i = 0; i < 4; i++) { |
| 1589 | data->pwm[i - 1] = | 1573 | data->pwm[i] = |
| 1590 | w83781d_read_value(client, | 1574 | w83781d_read_value(data, |
| 1591 | W83781D_REG_PWM(i)); | 1575 | W83781D_REG_PWM[i]); |
| 1592 | if ((data->type != w83782d | 1576 | if ((data->type != w83782d || !client->driver) |
| 1593 | || i2c_is_isa_client(client)) | 1577 | && i == 1) |
| 1594 | && i == 2) | ||
| 1595 | break; | 1578 | break; |
| 1596 | } | 1579 | } |
| 1597 | /* Only PWM2 can be disabled */ | 1580 | /* Only PWM2 can be disabled */ |
| 1598 | data->pwmenable[1] = (w83781d_read_value(client, | 1581 | data->pwm2_enable = (w83781d_read_value(data, |
| 1599 | W83781D_REG_PWMCLK12) & 0x08) >> 3; | 1582 | W83781D_REG_PWMCLK12) & 0x08) >> 3; |
| 1600 | } | 1583 | } |
| 1601 | 1584 | ||
| 1602 | data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1)); | 1585 | data->temp = w83781d_read_value(data, W83781D_REG_TEMP(1)); |
| 1603 | data->temp_max = | 1586 | data->temp_max = |
| 1604 | w83781d_read_value(client, W83781D_REG_TEMP_OVER(1)); | 1587 | w83781d_read_value(data, W83781D_REG_TEMP_OVER(1)); |
| 1605 | data->temp_max_hyst = | 1588 | data->temp_max_hyst = |
| 1606 | w83781d_read_value(client, W83781D_REG_TEMP_HYST(1)); | 1589 | w83781d_read_value(data, W83781D_REG_TEMP_HYST(1)); |
| 1607 | data->temp_add[0] = | 1590 | data->temp_add[0] = |
| 1608 | w83781d_read_value(client, W83781D_REG_TEMP(2)); | 1591 | w83781d_read_value(data, W83781D_REG_TEMP(2)); |
| 1609 | data->temp_max_add[0] = | 1592 | data->temp_max_add[0] = |
| 1610 | w83781d_read_value(client, W83781D_REG_TEMP_OVER(2)); | 1593 | w83781d_read_value(data, W83781D_REG_TEMP_OVER(2)); |
| 1611 | data->temp_max_hyst_add[0] = | 1594 | data->temp_max_hyst_add[0] = |
| 1612 | w83781d_read_value(client, W83781D_REG_TEMP_HYST(2)); | 1595 | w83781d_read_value(data, W83781D_REG_TEMP_HYST(2)); |
| 1613 | if (data->type != w83783s) { | 1596 | if (data->type != w83783s) { |
| 1614 | data->temp_add[1] = | 1597 | data->temp_add[1] = |
| 1615 | w83781d_read_value(client, W83781D_REG_TEMP(3)); | 1598 | w83781d_read_value(data, W83781D_REG_TEMP(3)); |
| 1616 | data->temp_max_add[1] = | 1599 | data->temp_max_add[1] = |
| 1617 | w83781d_read_value(client, | 1600 | w83781d_read_value(data, |
| 1618 | W83781D_REG_TEMP_OVER(3)); | 1601 | W83781D_REG_TEMP_OVER(3)); |
| 1619 | data->temp_max_hyst_add[1] = | 1602 | data->temp_max_hyst_add[1] = |
| 1620 | w83781d_read_value(client, | 1603 | w83781d_read_value(data, |
| 1621 | W83781D_REG_TEMP_HYST(3)); | 1604 | W83781D_REG_TEMP_HYST(3)); |
| 1622 | } | 1605 | } |
| 1623 | i = w83781d_read_value(client, W83781D_REG_VID_FANDIV); | 1606 | i = w83781d_read_value(data, W83781D_REG_VID_FANDIV); |
| 1624 | data->vid = i & 0x0f; | 1607 | data->vid = i & 0x0f; |
| 1625 | data->vid |= (w83781d_read_value(client, | 1608 | data->vid |= (w83781d_read_value(data, |
| 1626 | W83781D_REG_CHIPID) & 0x01) << 4; | 1609 | W83781D_REG_CHIPID) & 0x01) << 4; |
| 1627 | data->fan_div[0] = (i >> 4) & 0x03; | 1610 | data->fan_div[0] = (i >> 4) & 0x03; |
| 1628 | data->fan_div[1] = (i >> 6) & 0x03; | 1611 | data->fan_div[1] = (i >> 6) & 0x03; |
| 1629 | data->fan_div[2] = (w83781d_read_value(client, | 1612 | data->fan_div[2] = (w83781d_read_value(data, |
| 1630 | W83781D_REG_PIN) >> 6) & 0x03; | 1613 | W83781D_REG_PIN) >> 6) & 0x03; |
| 1631 | if ((data->type != w83781d) && (data->type != as99127f)) { | 1614 | if ((data->type != w83781d) && (data->type != as99127f)) { |
| 1632 | i = w83781d_read_value(client, W83781D_REG_VBAT); | 1615 | i = w83781d_read_value(data, W83781D_REG_VBAT); |
| 1633 | data->fan_div[0] |= (i >> 3) & 0x04; | 1616 | data->fan_div[0] |= (i >> 3) & 0x04; |
| 1634 | data->fan_div[1] |= (i >> 4) & 0x04; | 1617 | data->fan_div[1] |= (i >> 4) & 0x04; |
| 1635 | data->fan_div[2] |= (i >> 5) & 0x04; | 1618 | data->fan_div[2] |= (i >> 5) & 0x04; |
| 1636 | } | 1619 | } |
| 1637 | if ((data->type == w83782d) || (data->type == w83627hf)) { | 1620 | if ((data->type == w83782d) || (data->type == w83627hf)) { |
| 1638 | data->alarms = w83781d_read_value(client, | 1621 | data->alarms = w83781d_read_value(data, |
| 1639 | W83782D_REG_ALARM1) | 1622 | W83782D_REG_ALARM1) |
| 1640 | | (w83781d_read_value(client, | 1623 | | (w83781d_read_value(data, |
| 1641 | W83782D_REG_ALARM2) << 8) | 1624 | W83782D_REG_ALARM2) << 8) |
| 1642 | | (w83781d_read_value(client, | 1625 | | (w83781d_read_value(data, |
| 1643 | W83782D_REG_ALARM3) << 16); | 1626 | W83782D_REG_ALARM3) << 16); |
| 1644 | } else if (data->type == w83783s) { | 1627 | } else if (data->type == w83783s) { |
| 1645 | data->alarms = w83781d_read_value(client, | 1628 | data->alarms = w83781d_read_value(data, |
| 1646 | W83782D_REG_ALARM1) | 1629 | W83782D_REG_ALARM1) |
| 1647 | | (w83781d_read_value(client, | 1630 | | (w83781d_read_value(data, |
| 1648 | W83782D_REG_ALARM2) << 8); | 1631 | W83782D_REG_ALARM2) << 8); |
| 1649 | } else { | 1632 | } else { |
| 1650 | /* No real-time status registers, fall back to | 1633 | /* No real-time status registers, fall back to |
| 1651 | interrupt status registers */ | 1634 | interrupt status registers */ |
| 1652 | data->alarms = w83781d_read_value(client, | 1635 | data->alarms = w83781d_read_value(data, |
| 1653 | W83781D_REG_ALARM1) | 1636 | W83781D_REG_ALARM1) |
| 1654 | | (w83781d_read_value(client, | 1637 | | (w83781d_read_value(data, |
| 1655 | W83781D_REG_ALARM2) << 8); | 1638 | W83781D_REG_ALARM2) << 8); |
| 1656 | } | 1639 | } |
| 1657 | i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2); | 1640 | i = w83781d_read_value(data, W83781D_REG_BEEP_INTS2); |
| 1658 | data->beep_enable = i >> 7; | 1641 | data->beep_enable = i >> 7; |
| 1659 | data->beep_mask = ((i & 0x7f) << 8) + | 1642 | data->beep_mask = ((i & 0x7f) << 8) + |
| 1660 | w83781d_read_value(client, W83781D_REG_BEEP_INTS1); | 1643 | w83781d_read_value(data, W83781D_REG_BEEP_INTS1); |
| 1661 | if ((data->type != w83781d) && (data->type != as99127f)) { | 1644 | if ((data->type != w83781d) && (data->type != as99127f)) { |
| 1662 | data->beep_mask |= | 1645 | data->beep_mask |= |
| 1663 | w83781d_read_value(client, | 1646 | w83781d_read_value(data, |
| 1664 | W83781D_REG_BEEP_INTS3) << 16; | 1647 | W83781D_REG_BEEP_INTS3) << 16; |
| 1665 | } | 1648 | } |
| 1666 | data->last_updated = jiffies; | 1649 | data->last_updated = jiffies; |
| @@ -1672,6 +1655,133 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) | |||
| 1672 | return data; | 1655 | return data; |
| 1673 | } | 1656 | } |
| 1674 | 1657 | ||
| 1658 | /* return 1 if a supported chip is found, 0 otherwise */ | ||
| 1659 | static int __init | ||
| 1660 | w83781d_isa_found(unsigned short address) | ||
| 1661 | { | ||
| 1662 | int val, save, found = 0; | ||
| 1663 | |||
| 1664 | if (!request_region(address, W83781D_EXTENT, "w83781d")) | ||
| 1665 | return 0; | ||
| 1666 | |||
| 1667 | #define REALLY_SLOW_IO | ||
| 1668 | /* We need the timeouts for at least some W83781D-like | ||
| 1669 | chips. But only if we read 'undefined' registers. */ | ||
| 1670 | val = inb_p(address + 1); | ||
| 1671 | if (inb_p(address + 2) != val | ||
| 1672 | || inb_p(address + 3) != val | ||
| 1673 | || inb_p(address + 7) != val) { | ||
| 1674 | pr_debug("w83781d: Detection failed at step 1\n"); | ||
| 1675 | goto release; | ||
| 1676 | } | ||
| 1677 | #undef REALLY_SLOW_IO | ||
| 1678 | |||
| 1679 | /* We should be able to change the 7 LSB of the address port. The | ||
| 1680 | MSB (busy flag) should be clear initially, set after the write. */ | ||
| 1681 | save = inb_p(address + W83781D_ADDR_REG_OFFSET); | ||
| 1682 | if (save & 0x80) { | ||
| 1683 | pr_debug("w83781d: Detection failed at step 2\n"); | ||
| 1684 | goto release; | ||
| 1685 | } | ||
| 1686 | val = ~save & 0x7f; | ||
| 1687 | outb_p(val, address + W83781D_ADDR_REG_OFFSET); | ||
| 1688 | if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) { | ||
| 1689 | outb_p(save, address + W83781D_ADDR_REG_OFFSET); | ||
| 1690 | pr_debug("w83781d: Detection failed at step 3\n"); | ||
| 1691 | goto release; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | /* We found a device, now see if it could be a W83781D */ | ||
| 1695 | outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET); | ||
| 1696 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
| 1697 | if (val & 0x80) { | ||
| 1698 | pr_debug("w83781d: Detection failed at step 4\n"); | ||
| 1699 | goto release; | ||
| 1700 | } | ||
| 1701 | outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); | ||
| 1702 | save = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
| 1703 | outb_p(W83781D_REG_CHIPMAN, address + W83781D_ADDR_REG_OFFSET); | ||
| 1704 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
| 1705 | if ((!(save & 0x80) && (val != 0xa3)) | ||
| 1706 | || ((save & 0x80) && (val != 0x5c))) { | ||
| 1707 | pr_debug("w83781d: Detection failed at step 5\n"); | ||
| 1708 | goto release; | ||
| 1709 | } | ||
| 1710 | outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET); | ||
| 1711 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
| 1712 | if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */ | ||
| 1713 | pr_debug("w83781d: Detection failed at step 6\n"); | ||
| 1714 | goto release; | ||
| 1715 | } | ||
| 1716 | |||
| 1717 | /* The busy flag should be clear again */ | ||
| 1718 | if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) { | ||
| 1719 | pr_debug("w83781d: Detection failed at step 7\n"); | ||
| 1720 | goto release; | ||
| 1721 | } | ||
| 1722 | |||
| 1723 | /* Determine the chip type */ | ||
| 1724 | outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); | ||
| 1725 | save = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
| 1726 | outb_p(save & 0xf8, address + W83781D_DATA_REG_OFFSET); | ||
| 1727 | outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET); | ||
| 1728 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
| 1729 | if ((val & 0xfe) == 0x10 /* W83781D */ | ||
| 1730 | || val == 0x30 /* W83782D */ | ||
| 1731 | || val == 0x21) /* W83627HF */ | ||
| 1732 | found = 1; | ||
| 1733 | |||
| 1734 | if (found) | ||
| 1735 | pr_info("w83781d: Found a %s chip at %#x\n", | ||
| 1736 | val == 0x21 ? "W83627HF" : | ||
| 1737 | val == 0x30 ? "W83782D" : "W83781D", (int)address); | ||
| 1738 | |||
| 1739 | release: | ||
| 1740 | release_region(address, W83781D_EXTENT); | ||
| 1741 | return found; | ||
| 1742 | } | ||
| 1743 | |||
| 1744 | static int __init | ||
| 1745 | w83781d_isa_device_add(unsigned short address) | ||
| 1746 | { | ||
| 1747 | struct resource res = { | ||
| 1748 | .start = address, | ||
| 1749 | .end = address + W83781D_EXTENT, | ||
| 1750 | .name = "w83781d", | ||
| 1751 | .flags = IORESOURCE_IO, | ||
| 1752 | }; | ||
| 1753 | int err; | ||
| 1754 | |||
| 1755 | pdev = platform_device_alloc("w83781d", address); | ||
| 1756 | if (!pdev) { | ||
| 1757 | err = -ENOMEM; | ||
| 1758 | printk(KERN_ERR "w83781d: Device allocation failed\n"); | ||
| 1759 | goto exit; | ||
| 1760 | } | ||
| 1761 | |||
| 1762 | err = platform_device_add_resources(pdev, &res, 1); | ||
| 1763 | if (err) { | ||
| 1764 | printk(KERN_ERR "w83781d: Device resource addition failed " | ||
| 1765 | "(%d)\n", err); | ||
| 1766 | goto exit_device_put; | ||
| 1767 | } | ||
| 1768 | |||
| 1769 | err = platform_device_add(pdev); | ||
| 1770 | if (err) { | ||
| 1771 | printk(KERN_ERR "w83781d: Device addition failed (%d)\n", | ||
| 1772 | err); | ||
| 1773 | goto exit_device_put; | ||
| 1774 | } | ||
| 1775 | |||
| 1776 | return 0; | ||
| 1777 | |||
| 1778 | exit_device_put: | ||
| 1779 | platform_device_put(pdev); | ||
| 1780 | exit: | ||
| 1781 | pdev = NULL; | ||
| 1782 | return err; | ||
| 1783 | } | ||
| 1784 | |||
| 1675 | static int __init | 1785 | static int __init |
| 1676 | sensors_w83781d_init(void) | 1786 | sensors_w83781d_init(void) |
| 1677 | { | 1787 | { |
| @@ -1679,21 +1789,36 @@ sensors_w83781d_init(void) | |||
| 1679 | 1789 | ||
| 1680 | res = i2c_add_driver(&w83781d_driver); | 1790 | res = i2c_add_driver(&w83781d_driver); |
| 1681 | if (res) | 1791 | if (res) |
| 1682 | return res; | 1792 | goto exit; |
| 1793 | |||
| 1794 | if (w83781d_isa_found(isa_address)) { | ||
| 1795 | res = platform_driver_register(&w83781d_isa_driver); | ||
| 1796 | if (res) | ||
| 1797 | goto exit_unreg_i2c_driver; | ||
| 1683 | 1798 | ||
| 1684 | /* Don't exit if this one fails, we still want the I2C variants | 1799 | /* Sets global pdev as a side effect */ |
| 1685 | to work! */ | 1800 | res = w83781d_isa_device_add(isa_address); |
| 1686 | if (i2c_isa_add_driver(&w83781d_isa_driver)) | 1801 | if (res) |
| 1687 | isa_address = 0; | 1802 | goto exit_unreg_isa_driver; |
| 1803 | } | ||
| 1688 | 1804 | ||
| 1689 | return 0; | 1805 | return 0; |
| 1806 | |||
| 1807 | exit_unreg_isa_driver: | ||
| 1808 | platform_driver_unregister(&w83781d_isa_driver); | ||
| 1809 | exit_unreg_i2c_driver: | ||
| 1810 | i2c_del_driver(&w83781d_driver); | ||
| 1811 | exit: | ||
| 1812 | return res; | ||
| 1690 | } | 1813 | } |
| 1691 | 1814 | ||
| 1692 | static void __exit | 1815 | static void __exit |
| 1693 | sensors_w83781d_exit(void) | 1816 | sensors_w83781d_exit(void) |
| 1694 | { | 1817 | { |
| 1695 | if (isa_address) | 1818 | if (pdev) { |
| 1696 | i2c_isa_del_driver(&w83781d_isa_driver); | 1819 | platform_device_unregister(pdev); |
| 1820 | platform_driver_unregister(&w83781d_isa_driver); | ||
| 1821 | } | ||
| 1697 | i2c_del_driver(&w83781d_driver); | 1822 | i2c_del_driver(&w83781d_driver); |
| 1698 | } | 1823 | } |
| 1699 | 1824 | ||
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h index 9559894c7658..26861df52cc4 100644 --- a/include/asm-i386/msr.h +++ b/include/asm-i386/msr.h | |||
| @@ -77,7 +77,7 @@ static inline unsigned long long native_read_pmc(void) | |||
| 77 | #ifdef CONFIG_PARAVIRT | 77 | #ifdef CONFIG_PARAVIRT |
| 78 | #include <asm/paravirt.h> | 78 | #include <asm/paravirt.h> |
| 79 | #else | 79 | #else |
| 80 | 80 | #include <linux/errno.h> | |
| 81 | /* | 81 | /* |
| 82 | * Access to machine-specific registers (available on 586 and better only) | 82 | * Access to machine-specific registers (available on 586 and better only) |
| 83 | * Note: the rd* operations modify the parameters directly (without using | 83 | * Note: the rd* operations modify the parameters directly (without using |
| @@ -148,6 +148,8 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val) | |||
| 148 | #ifdef CONFIG_SMP | 148 | #ifdef CONFIG_SMP |
| 149 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | 149 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); |
| 150 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | 150 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); |
| 151 | int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | ||
| 152 | int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | ||
| 151 | #else /* CONFIG_SMP */ | 153 | #else /* CONFIG_SMP */ |
| 152 | static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | 154 | static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) |
| 153 | { | 155 | { |
| @@ -157,6 +159,14 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | |||
| 157 | { | 159 | { |
| 158 | wrmsr(msr_no, l, h); | 160 | wrmsr(msr_no, l, h); |
| 159 | } | 161 | } |
| 162 | static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | ||
| 163 | { | ||
| 164 | return rdmsr_safe(msr_no, l, h); | ||
| 165 | } | ||
| 166 | static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | ||
| 167 | { | ||
| 168 | return wrmsr_safe(msr_no, l, h); | ||
| 169 | } | ||
| 160 | #endif /* CONFIG_SMP */ | 170 | #endif /* CONFIG_SMP */ |
| 161 | #endif | 171 | #endif |
| 162 | #endif | 172 | #endif |
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h index a524f0325673..d5c55b80da54 100644 --- a/include/asm-x86_64/msr.h +++ b/include/asm-x86_64/msr.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <asm/msr-index.h> | 4 | #include <asm/msr-index.h> |
| 5 | 5 | ||
| 6 | #ifndef __ASSEMBLY__ | 6 | #ifndef __ASSEMBLY__ |
| 7 | #include <linux/errno.h> | ||
| 7 | /* | 8 | /* |
| 8 | * Access to machine-specific registers (available on 586 and better only) | 9 | * Access to machine-specific registers (available on 586 and better only) |
| 9 | * Note: the rd* operations modify the parameters directly (without using | 10 | * Note: the rd* operations modify the parameters directly (without using |
| @@ -162,6 +163,8 @@ static inline unsigned int cpuid_edx(unsigned int op) | |||
| 162 | #ifdef CONFIG_SMP | 163 | #ifdef CONFIG_SMP |
| 163 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | 164 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); |
| 164 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | 165 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); |
| 166 | int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | ||
| 167 | int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | ||
| 165 | #else /* CONFIG_SMP */ | 168 | #else /* CONFIG_SMP */ |
| 166 | static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | 169 | static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) |
| 167 | { | 170 | { |
| @@ -171,6 +174,14 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | |||
| 171 | { | 174 | { |
| 172 | wrmsr(msr_no, l, h); | 175 | wrmsr(msr_no, l, h); |
| 173 | } | 176 | } |
| 177 | static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | ||
| 178 | { | ||
| 179 | return rdmsr_safe(msr_no, l, h); | ||
| 180 | } | ||
| 181 | static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | ||
| 182 | { | ||
| 183 | return wrmsr_safe(msr_no, l, h); | ||
| 184 | } | ||
| 174 | #endif /* CONFIG_SMP */ | 185 | #endif /* CONFIG_SMP */ |
| 175 | #endif /* __ASSEMBLY__ */ | 186 | #endif /* __ASSEMBLY__ */ |
| 176 | #endif /* X86_64_MSR_H */ | 187 | #endif /* X86_64_MSR_H */ |
