Commit c27b73b3 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/i2c-2.6

into ppc970.osdl.org:/home/torvalds/v2.5/linux
parents 387f6b76 60d8593b
......@@ -3,22 +3,44 @@ Naming and data format standards for sysfs files
The libsensors library offers an interface to the raw sensors data
through the sysfs interface. See libsensors documentation and source for
more further information.
more further information. As of writing this document, libsensors
(from lm_sensors 2.8.3) is heavily chip-dependant. Adding or updating
support for any given chip requires modifying the library's code.
This is because libsensors was written for the procfs interface
older kernel modules were using, which wasn't standardized enough.
Recent versions of libsensors (from lm_sensors 2.8.2 and later) have
support for the sysfs interface, though.
The new sysfs interface was designed to be as chip-independant as
possible.
Note that motherboards vary widely in the connections to sensor chips.
There is no standard that ensures, for example, that the second
temperature sensor is connected to the CPU, or that the second fan is on
the CPU. Also, some values reported by the chips need some computation
before they make full sense. For example, most chips can only measure
voltages between 0 and +4V. Other voltages are scaled back into that
range using external resistors. Since the values of these resistors
can change from motherboard to motherboard, the conversions cannot be
hard coded into the driver and have to be done in user space.
For this reason, even if we aim at a chip-independant libsensors, it will
still require a configuration file (e.g. /etc/sensors.conf) for proper
values conversion, labeling of inputs and hiding of unused inputs.
An alternative method that some programs use is to access the sysfs
files directly. This document briefly describes the standards that the
drivers follow, so that an application program can scan for entries and
access this data in a simple and consistent way.
access this data in a simple and consistent way. That said, such programs
will have to implement conversion, labeling and hiding of inputs. For
this reason, it is still not recommended to bypass the library.
If you are developing a userspace application please send us feedback on
this standard.
Note that motherboards vary widely in the connections to sensor chips.
There is no standard that ensures, for example, that the second
temperature sensor is connected to the CPU, or that the second fan is on
the CPU. Therefore, programs must provide a facility for the user to
label or bind /proc entries for display. Sensor chips often have unused
inputs that should be ignored by user programs.
Note that this standard isn't completely established yet, so it is subject
to changes, even important ones. One more reason to use the library instead
of accessing sysfs files directly.
Each chip gets its own directory in the sysfs /sys/devices tree. To
find all sensor chips, it is easier to follow the symlinks from
......@@ -28,6 +50,15 @@ All sysfs values are fixed point numbers. To get the true value of some
of the values, you should divide by the specified value.
There is only one value per file, unlike the older /proc specification.
The common scheme for files naming is: <type><number>_<item>. Usual
types for sensor chips are "in" (voltage), "temp" (temperature) and
"fan" (fan). Usual items are "input" (measured value), "max" (high
threshold, "min" (low threshold). Numbering usually starts from 1,
except for voltages which start from 0 (because most data sheets use
this). A number is always used for elements that can be present more
than once, even if there is a single element of the given type on the
specific chip. Other files do not refer to a specific element, so
they have a simple name, and no number.
Alarms are direct indications read from the chips. The drivers do NOT
make comparisons of readings to thresholds. This allows violations
......@@ -38,71 +69,21 @@ to cause an alarm) is chip-dependent.
-------------------------------------------------------------------------
sysfs entries are as follows:
Entry Function
----- --------
alarms Alarm bitmask.
Read only.
Integer representation of one to four bytes.
A '1' bit means an alarm.
Chips should be programmed for 'comparator' mode so that
the alarm will 'come back' after you read the register
if it is still valid.
Generally a direct representation of a chip's internal
alarm registers; there is no standard for the position
of individual bits.
Bits are defined in kernel/include/sensors.h.
beep_enable Beep/interrupt enable
0 to disable.
1 to enable.
Read/Write
beep_mask Bitmask for beep.
Same format as 'alarms' with the same bit locations.
Read only.
************
* Voltages *
************
curr_max[1-n] Current max value
Fixed point XXXXX, divide by 1000 to get Amps.
Read/Write.
curr_min[1-n] Current min value.
Fixed point XXXXX, divide by 1000 to get Amps.
Read/Write.
curr_input[1-n] Current input value
Fixed point XXXXX, divide by 1000 to get Amps.
Read only.
eeprom Raw EEPROM data in binary form.
Read only.
fan_min[1-3] Fan minimum value
Integer value indicating RPM
Read/Write.
fan_input[1-3] Fan input value.
Integer value indicating RPM
Read only.
fan_div[1-3] Fan divisor.
Integers in powers of two (1,2,4,8,16,32,64,128).
Some chips only support values 1,2,4,8.
See doc/fan-divisors for details.
in_min[0-8] Voltage min value.
in[0-8]_min Voltage min value.
Fixed point value in form XXXX. Divide by 1000 to get
Volts.
Read/Write
in_max[0-8] Voltage max value.
in[0-8]_max Voltage max value.
Fixed point value in form XXXX. Divide by 1000 to get
Volts.
Read/Write
in_input[0-8] Voltage input value.
in[0-8]_input Voltage input value.
Fixed point value in form XXXX. Divide by 1000 to get
Volts.
Read only
......@@ -116,76 +97,156 @@ in_input[0-8] Voltage input value.
These drivers will output the actual voltage.
First two values are read/write and third is read only.
Typical usage:
in_*0 CPU #1 voltage (not scaled)
in_*1 CPU #1 voltage (not scaled)
in_*2 3.3V nominal (not scaled)
in_*3 5.0V nominal (scaled)
in_*4 12.0V nominal (scaled)
in_*5 -12.0V nominal (scaled)
in_*6 -5.0V nominal (scaled)
in_*7 varies
in_*8 varies
pwm[1-3] Pulse width modulation fan control.
in0_* CPU #1 voltage (not scaled)
in1_* CPU #1 voltage (not scaled)
in2_* 3.3V nominal (not scaled)
in3_* 5.0V nominal (scaled)
in4_* 12.0V nominal (scaled)
in5_* -12.0V nominal (scaled)
in6_* -5.0V nominal (scaled)
in7_* varies
in8_* varies
in0_ref CPU core reference voltage.
Read only.
Fixed point value in form XXXX corresponding to CPU core
voltage as told to the sensor chip. Divide by 1000 to
get Volts. Not always correct.
vrm Voltage Regulator Module version number.
Read only.
Two digit number (XX), first is major version, second is
minor version.
Affects the way the driver calculates the core voltage from
the vid pins. See doc/vid for details.
********
* Fans *
********
fan[1-3]_min Fan minimum value
Integer value indicating RPM
Read/Write.
fan[1-3]_input Fan input value.
Integer value indicating RPM
Read only.
fan[1-3]_div Fan divisor.
Integers in powers of two (1,2,4,8,16,32,64,128).
Some chips only support values 1,2,4,8.
See doc/fan-divisors for details.
fan[1-3]_pwm Pulse width modulation fan control.
Integer 0 - 255
Read/Write
255 is max or 100%.
Corresponds to the fans 1-3.
pwm_enable[1-3] pwm enable
not always present even if pwm* is.
fan[1-3]_pwm_enable
Switch PWM on and off.
Not always present even if fan*_pwm is.
0 to turn off
1 to turn on
Read/Write
sensor[1-3] Sensor type selection.
****************
* Temperatures *
****************
temp[1-3]_type Sensor type selection.
Integers 1,2,3, or thermistor Beta value (3435)
Read/Write.
temp_max[1-4] Temperature max value.
temp[1-4]_max Temperature max value.
Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius.
Read/Write value.
temp_min[1-3] Temperature min value.
temp[1-3]_min Temperature min value.
Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius.
Read/Write value.
temp_hyst[1-3] Temperature hysteresis value.
temp[1-3]_max_hyst
Temperature hysteresis value for max limit.
Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius. Must be reported as an
absolute temperature, NOT a delta from the max value.
Read/Write value.
temp_input[1-4] Temperature input value.
temp[1-4]_input Temperature input value.
Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius.
Read only value.
temp_crit Temperature critical value, typically greater than all
temp_max values.
temp[1-4]_crit Temperature critical value, typically greater than
corresponding temp_max values.
Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius.
Common to all temperature channels.
Read/Write value.
If there are multiple temperature sensors, temp_*1 is
temp[1-2]_crit_hyst
Temperature hysteresis value for critical limit.
Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius. Must be reported as an
absolute temperature, NOT a delta from the critical value.
Read/Write value.
If there are multiple temperature sensors, temp1_* is
generally the sensor inside the chip itself, generally
reported as "motherboard temperature". temp_*2 to
temp_*4 are generally sensors external to the chip
reported as "motherboard temperature". temp2_* to
temp4_* are generally sensors external to the chip
itself, for example the thermal diode inside the CPU or
a thermistor nearby.
vid CPU core voltage.
************
* Currents *
************
Note that no known chip provides current measurements as of writing,
so this part is theoretical, so to say.
curr[1-n]_max Current max value
Fixed point XXXXX, divide by 1000 to get Amps.
Read/Write.
curr[1-n]_min Current min value.
Fixed point XXXXX, divide by 1000 to get Amps.
Read/Write.
curr[1-n]_input Current input value
Fixed point XXXXX, divide by 1000 to get Amps.
Read only.
Fixed point value in form XXXX corresponding to CPU core
voltage as told to the sensor chip. Divide by 1000 to
get Volts. Not always correct.
vrm Voltage Regulator Module version number.
*********
* Other *
*********
alarms Alarm bitmask.
Read only.
Integer representation of one to four bytes.
A '1' bit means an alarm.
Chips should be programmed for 'comparator' mode so that
the alarm will 'come back' after you read the register
if it is still valid.
Generally a direct representation of a chip's internal
alarm registers; there is no standard for the position
of individual bits.
Bits are defined in kernel/include/sensors.h.
beep_enable Beep/interrupt enable
0 to disable.
1 to enable.
Read/Write
beep_mask Bitmask for beep.
Same format as 'alarms' with the same bit locations.
Read only.
eeprom Raw EEPROM data in binary form.
Read only.
Two digit number (XX), first is major version, second is
minor version.
Affects the way the driver calculates the core voltage from
the vid pins. See doc/vid for details.
......@@ -15,9 +15,6 @@ config I2C
Both I2C and SMBus are supported here. You will need this for
hardware sensors support, and also for Video For Linux support.
Specifically, if you want to use a BT848 based frame grabber/overlay
boards under Linux, say Y here and also to "I2C bit-banging
interfaces", below.
If you want I2C support, you should say Y here and also to the
specific driver for your bus adapter(s) below.
......@@ -49,6 +46,15 @@ config I2C_DEBUG_CORE
messages to the system log. Select this if you are having a
problem with I2C support and want to see more of what is going on.
config I2C_DEBUG_ALGO
bool "I2C Algorithm debugging messages"
depends on I2C
help
Say Y here if you want the I2C algorithm drivers to produce a bunch
of debug messages to the system log. Select this if you are having
a problem with I2C support and want to see more of what is going
on.
config I2C_DEBUG_BUS
bool "I2C Bus debugging messages"
depends on I2C
......
......@@ -6,3 +6,7 @@ obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o
obj-y += busses/ chips/ algos/
ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
EXTRA_CFLAGS += -DDEBUG
endif
......@@ -5,3 +5,7 @@
obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o
ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
EXTRA_CFLAGS += -DDEBUG
endif
......@@ -21,8 +21,6 @@
/* With some changes from Frodo Looijaard <frodol@dds.nl>, Kysti Mlkki
<kmalkki@cc.hut.fi> and Jean Delvare <khali@linux-fr.org> */
/* #define DEBUG 1 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
......
......@@ -27,8 +27,6 @@
messages, proper stop/repstart signaling during receive,
added detect code */
/* #define DEBUG 1 */ /* to pick up dev_dbg calls */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
......
......@@ -58,17 +58,6 @@ config I2C_ELEKTOR
This support is also available as a module. If so, the module
will be called i2c-elektor.
config I2C_ELV
tristate "ELV adapter"
depends on I2C
select I2C_ALGOBIT
help
This supports parallel-port I2C adapters called ELV. Say Y if you
own such an adapter.
This support is also available as a module. If so, the module
will be called i2c-elv.
config I2C_HYDRA
tristate "CHRP Apple Hydra Mac I/O I2C interface"
depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL
......@@ -144,6 +133,17 @@ config I2C_ITE
This support is also available as a module. If so, the module
will be called i2c-ite.
config I2C_IXP42X
tristate "IXP42x GPIO-Based I2C Interface"
depends on I2C && ARCH_IXP425
select I2C_ALGOBIT
help
Say Y here if you have an Intel IXP42x(420,421,422,425) based
system and are using GPIO lines for an I2C bus.
This support is also available as a module. If so, the module
will be called i2c-ixp42x.
config I2C_KEYWEST
tristate "Powermac Keywest I2C interface"
depends on I2C && PPC_PMAC
......@@ -164,16 +164,6 @@ config I2C_NFORCE2
This driver can also be built as a module. If so, the module
will be called i2c-nforce2.
config I2C_PHILIPSPAR
tristate "Philips style parallel port adapter"
depends on I2C && PARPORT
select I2C_ALGOBIT
help
This supports parallel-port I2C adapters made by Philips.
This support is also available as a module. If so, the module
will be called i2c-philips-par.
config I2C_PARPORT
tristate "Parallel port adapter"
depends on I2C && PARPORT
......@@ -343,17 +333,6 @@ config I2C_SIS96X
This driver can also be built as a module. If so, the module
will be called i2c-sis96x.
config I2C_VELLEMAN
tristate "Velleman K8000 adapter"
depends on I2C
select I2C_ALGOBIT
help
This supports the Velleman K8000 parallel-port I2C adapter. Say Y
if you own such an adapter.
This support is also available as a module. If so, the module
will be called i2c-velleman.
config I2C_VIA
tristate "VIA 82C586B"
depends on I2C && PCI && EXPERIMENTAL
......
......@@ -7,7 +7,6 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_ELV) += i2c-elv.o
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
obj-$(CONFIG_I2C_I801) += i2c-i801.o
obj-$(CONFIG_I2C_I810) += i2c-i810.o
......@@ -15,9 +14,9 @@ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_ISA) += i2c-isa.o
obj-$(CONFIG_I2C_ITE) += i2c-ite.o
obj-$(CONFIG_I2C_IXP42X) += i2c-ixp42x.o
obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o
obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
obj-$(CONFIG_I2C_PHILIPSPAR) += i2c-philips-par.o
obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
......@@ -27,9 +26,12 @@ obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o
obj-$(CONFIG_I2C_VIA) += i2c-via.o
obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
EXTRA_CFLAGS += -DDEBUG
endif
......@@ -54,10 +54,6 @@
/* Note: we assume there can only be one ALI1535, with one SMBus interface */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
......@@ -484,6 +480,7 @@ static struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali1535_adapter = {
.owner = THIS_MODULE,
.class = I2C_ADAP_CLASS_SMBUS,
.algo = &smbus_algorithm,
.name = "unset",
};
......@@ -517,6 +514,7 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_
static void __devexit ali1535_remove(struct pci_dev *dev)
{
i2c_del_adapter(&ali1535_adapter);
release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
}
static struct pci_driver ali1535_driver = {
......@@ -534,7 +532,6 @@ static int __init i2c_ali1535_init(void)
static void __exit i2c_ali1535_exit(void)
{
pci_unregister_driver(&ali1535_driver);
release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
......
......@@ -61,10 +61,6 @@
/* Note: we assume there can only be one ALI15X3, with one SMBus interface */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
......
......@@ -38,10 +38,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
......
......@@ -9,10 +9,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
......
......@@ -26,10 +26,6 @@
for Alpha Processor Inc. UP-2000(+) boards */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/module.h>
......
/* ------------------------------------------------------------------------- */
/* i2c-elv.c i2c-hw access for philips style parallel port adapters */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-2000 Simon G. Vogl
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
/* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <asm/io.h>
#define DEFAULT_BASE 0x378
static long base=0;
static unsigned char port_data = 0;
/* --- Convenience defines for the parallel port: */
#define BASE (unsigned long)(data)
#define DATA BASE /* Centronics data port */
#define STAT (BASE+1) /* Centronics status port */
#define CTRL (BASE+2) /* Centronics control port */
/* ----- local functions ---------------------------------------------- */
static void bit_elv_setscl(void *data, int state)
{
if (state) {
port_data &= 0xfe;
} else {
port_data |=1;
}
outb(port_data, DATA);
}
static void bit_elv_setsda(void *data, int state)
{
if (state) {
port_data &=0xfd;
} else {
port_data |=2;
}
outb(port_data, DATA);
}
static int bit_elv_getscl(void *data)
{
return ( 0 == ( (inb_p(STAT)) & 0x08 ) );
}
static int bit_elv_getsda(void *data)
{
return ( 0 == ( (inb_p(STAT)) & 0x40 ) );
}
static int bit_elv_init(void)
{
if (!request_region(base, (base == 0x3bc) ? 3 : 8,
"i2c (ELV adapter)"))
return -ENODEV;
if (inb(base+1) & 0x80) { /* BUSY should be high */
pr_debug("i2c-elv: Busy was low.\n");
goto fail;
}
outb(0x0c,base+2); /* SLCT auf low */
udelay(400);
if (!(inb(base+1) && 0x10)) {
outb(0x04,base+2);
pr_debug("i2c-elv: Select was high.\n");
goto fail;
}
port_data = 0;
bit_elv_setsda((void*)base,1);
bit_elv_setscl((void*)base,1);
return 0;
fail:
release_region(base , (base == 0x3bc) ? 3 : 8);
return -ENODEV;
}
/* ------------------------------------------------------------------------
* Encapsulate the above functions in the correct operations structure.
* This is only done when more than one hardware adapter is supported.
*/
static struct i2c_algo_bit_data bit_elv_data = {
.setsda = bit_elv_setsda,
.setscl = bit_elv_setscl,
.getsda = bit_elv_getsda,
.getscl = bit_elv_getscl,
.udelay = 80,
.mdelay = 80,
.timeout = HZ
};
static struct i2c_adapter bit_elv_ops = {
.owner = THIS_MODULE,
.algo_data = &bit_elv_data,
.name = "ELV Parallel port adaptor",
};
static int __init i2c_bitelv_init(void)
{
printk(KERN_INFO "i2c ELV parallel port adapter driver\n");
if (base==0) {
/* probe some values */
base=DEFAULT_BASE;
bit_elv_data.data=(void*)DEFAULT_BASE;
if (bit_elv_init()==0) {
if(i2c_bit_add_bus(&bit_elv_ops) < 0)
return -ENODEV;
} else {
return -ENODEV;
}
} else {
i2c_set_adapdata(&bit_elv_ops, (void *)base);
if (bit_elv_init()==0) {
if(i2c_bit_add_bus(&bit_elv_ops) < 0)
return -ENODEV;
} else {
return -ENODEV;
}
}
pr_debug("i2c-elv: found device at %#lx.\n",base);
return 0;
}
static void __exit i2c_bitelv_exit(void)
{
i2c_bit_del_bus(&bit_elv_ops);
release_region(base , (base == 0x3bc) ? 3 : 8);
}
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter");
MODULE_LICENSE("GPL");
MODULE_PARM(base, "i");
module_init(i2c_bitelv_init);
module_exit(i2c_bitelv_exit);
......@@ -13,10 +13,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
......
......@@ -39,10 +39,6 @@
/* Note: we assume there can only be one I801, with one SMBus interface */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
......@@ -608,6 +604,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
static void __devexit i801_remove(struct pci_dev *dev)
{
i2c_del_adapter(&i801_adapter);
release_region(i801_smba, (isich4 ? 16 : 8));
}
static struct pci_driver i801_driver = {
......@@ -625,7 +622,6 @@ static int __init i2c_i801_init(void)
static void __exit i2c_i801_exit(void)
{
pci_unregister_driver(&i801_driver);
release_region(i801_smba, (isich4 ? 16 : 8));
}
MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
......
......@@ -35,10 +35,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
......
......@@ -29,10 +29,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
......
......@@ -32,10 +32,6 @@
---------------------------------------------------------------------------*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
......@@ -129,7 +125,7 @@ static void iop3xx_adap_final_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
* NB: the handler has to clear the source of the interrupt!
* Then it passes the SR flags of interest to BH via adap data
*/
static void iop3xx_i2c_handler(int this_irq,
static irqreturn_t iop3xx_i2c_handler(int this_irq,
void *dev_id,
struct pt_regs *regs)
{
......@@ -142,6 +138,7 @@ static void iop3xx_i2c_handler(int this_irq,
iop3xx_adap->biu->SR_received |= sr;
wake_up_interruptible(&iop3xx_adap->waitq);
}
return IRQ_HANDLED;
}
/* check all error conditions, clear them , report most important */
......@@ -185,7 +182,7 @@ static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
unsigned sr = 0;
int interrupted;
int done;
int rc;
int rc = 0;
do {
interrupted = wait_event_interruptible_timeout (
......@@ -198,13 +195,13 @@ static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
return rc;
}else if (!interrupted) {
*status = sr;
return rc = -ETIMEDOUT;
return -ETIMEDOUT;
}
} while(!done);
*status = sr;
return rc = 0;
return 0;
}
/*
......@@ -284,7 +281,7 @@ static int iop3xx_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char
{
unsigned cr = *iop3xx_adap->biu->CR;
int status;
int rc;
int rc = 0;
*iop3xx_adap->biu->DBR = byte;
cr &= ~IOP321_ICR_MSTART;
......@@ -304,7 +301,7 @@ static int iop3xx_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap,
{
unsigned cr = *iop3xx_adap->biu->CR;
int status;
int rc;
int rc = 0;
cr &= ~IOP321_ICR_MSTART;
......@@ -386,13 +383,16 @@ static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[
iop3xx_adap_reset(iop3xx_adap);
iop3xx_adap_enable(iop3xx_adap);
for (im = 0; ret == 0 && im != num; ++im) {
for (im = 0; ret == 0 && im != num; im++) {
ret = iop3xx_handle_msg(i2c_adap, &msgs[im]);
}
iop3xx_adap_transaction_cleanup(iop3xx_adap);
if(ret)
return ret;
return im;
}
static int algo_control(struct i2c_adapter *adapter, unsigned int cmd,
......
......@@ -25,10 +25,6 @@
of this. */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
......
......@@ -34,10 +34,6 @@
Frodo Looijaard <frodol@dds.nl> */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/module.h>
......
/*
* drivers/i2c/i2c-adap-ixp42x.c
*
* Intel's IXP42x XScale NPU chipsets (IXP420, 421, 422, 425) do not have
* an on board I2C controller but provide 16 GPIO pins that are often
* used to create an I2C bus. This driver provides an i2c_adapter
* interface that plugs in under algo_bit and drives the GPIO pins
* as instructed by the alogorithm driver.
*
* Author: Deepak Saxena <dsaxena@plexity.net>
*
* Copyright (c) 2003-2004 MontaVista Software Inc.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*
* NOTE: Since different platforms will use different GPIO pins for
* I2C, this driver uses an IXP42x-specific platform_data
* pointer to pass the GPIO numbers to the driver. This
* allows us to support all the different IXP42x platforms
* w/o having to put #ifdefs in this driver.
*
* See arch/arm/mach-ixp42x/ixdp425.c for an example of building a
* device list and filling in the ixp42x_i2c_pins data structure
* that is passed as the platform_data to this driver.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <asm/hardware.h> /* Pick up IXP42x-specific bits */
static inline int ixp42x_scl_pin(void *data)
{
return ((struct ixp42x_i2c_pins*)data)->scl_pin;
}
static inline int ixp42x_sda_pin(void *data)
{
return ((struct ixp42x_i2c_pins*)data)->sda_pin;
}
static void ixp42x_bit_setscl(void *data, int val)
{
gpio_line_set(ixp42x_scl_pin(data), 0);
gpio_line_config(ixp42x_scl_pin(data),
val ? IXP425_GPIO_IN : IXP425_GPIO_OUT );
}
static void ixp42x_bit_setsda(void *data, int val)
{
gpio_line_set(ixp42x_sda_pin(data), 0);
gpio_line_config(ixp42x_sda_pin(data),
val ? IXP425_GPIO_IN : IXP425_GPIO_OUT );
}
static int ixp42x_bit_getscl(void *data)
{
int scl;
gpio_line_config(ixp42x_scl_pin(data), IXP425_GPIO_IN );
gpio_line_get(ixp42x_scl_pin(data), &scl);
return scl;
}
static int ixp42x_bit_getsda(void *data)
{
int sda;
gpio_line_config(ixp42x_sda_pin(data), IXP425_GPIO_IN );
gpio_line_get(ixp42x_sda_pin(data), &sda);
return sda;
}
struct ixp42x_i2c_data {
struct ixp42x_i2c_pins *gpio_pins;
struct i2c_adapter adapter;
struct i2c_algo_bit_data algo_data;
};
static int ixp42x_i2c_remove(struct device *dev)
{
struct platform_device *plat_dev = to_platform_device(dev);
struct ixp42x_i2c_data *drv_data = dev_get_drvdata(&plat_dev->dev);
dev_set_drvdata(&plat_dev->dev, NULL);
i2c_bit_del_bus(&drv_data->adapter);
kfree(drv_data);
return 0;
}
static int ixp42x_i2c_probe(struct device *dev)
{
int err;
struct platform_device *plat_dev = to_platform_device(dev);
struct ixp42x_i2c_pins *gpio = plat_dev->dev.platform_data;
struct ixp42x_i2c_data *drv_data =
kmalloc(sizeof(struct ixp42x_i2c_data), GFP_KERNEL);
if(!drv_data)
return -ENOMEM;
memzero(drv_data, sizeof(struct ixp42x_i2c_data));
drv_data->gpio_pins = gpio;
/*
* We could make a lot of these structures static, but
* certain platforms may have multiple GPIO-based I2C
* buses for various device domains, so we need per-device
* algo_data->data.
*/
drv_data->algo_data.data = gpio;
drv_data->algo_data.setsda = ixp42x_bit_setsda;
drv_data->algo_data.setscl = ixp42x_bit_setscl;
drv_data->algo_data.getsda = ixp42x_bit_getsda;
drv_data->algo_data.getscl = ixp42x_bit_getscl;
drv_data->algo_data.udelay = 10;
drv_data->algo_data.mdelay = 10;
drv_data->algo_data.timeout = 100;
drv_data->adapter.id = I2C_HW_B_IXP425,
drv_data->adapter.algo_data = &drv_data->algo_data,
drv_data->adapter.dev.parent = &plat_dev->dev;
gpio_line_config(gpio->scl_pin, IXP425_GPIO_IN);
gpio_line_config(gpio->sda_pin, IXP425_GPIO_IN);
gpio_line_set(gpio->scl_pin, 0);
gpio_line_set(gpio->sda_pin, 0);
if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) {
printk(KERN_ERR "ERROR: Could not install %s\n", dev->bus_id);
kfree(drv_data);
return err;
}
dev_set_drvdata(&plat_dev->dev, drv_data);
return 0;
}
static struct device_driver ixp42x_i2c_driver = {
.name = "IXP42X-I2C",
.bus = &platform_bus_type,
.probe = ixp42x_i2c_probe,
.remove = ixp42x_i2c_remove,
};
static int __init ixp42x_i2c_init(void)
{
return driver_register(&ixp42x_i2c_driver);
}
static void __exit ixp42x_i2c_exit(void)
{
driver_unregister(&ixp42x_i2c_driver);
}
module_init(ixp42x_i2c_init);
module_exit(ixp42x_i2c_exit);
MODULE_DESCRIPTION("GPIO-based I2C driver for IXP42x systems");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
......@@ -47,10 +47,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/config.h>
#include <linux/kernel.h>
......
......@@ -33,10 +33,6 @@
/* Note: we assume there can only be one nForce2, with two SMBus interfaces */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
......
......@@ -25,10 +25,6 @@
* ------------------------------------------------------------------------ */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
......
......@@ -25,10 +25,6 @@
* ------------------------------------------------------------------------ */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
......
/* ------------------------------------------------------------------------- */
/* i2c-philips-par.c i2c-hw access for philips style parallel port adapters */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-2000 Simon G. Vogl
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
/* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/parport.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
static int type;
struct i2c_par
{
struct pardevice *pdev;
struct i2c_adapter adapter;
struct i2c_algo_bit_data bit_lp_data;
struct i2c_par *next;
};
static struct i2c_par *adapter_list;
/* ----- printer port defines ------------------------------------------*/
/* Pin Port Inverted name */
#define I2C_ON 0x20 /* 12 status N paper */
/* ... only for phil. not used */
#define I2C_SDA 0x80 /* 9 data N data7 */
#define I2C_SCL 0x08 /* 17 ctrl N dsel */
#define I2C_SDAIN 0x80 /* 11 stat Y busy */
#define I2C_SCLIN 0x08 /* 15 stat Y enable */
#define I2C_DMASK 0x7f
#define I2C_CMASK 0xf7
/* ----- local functions ---------------------------------------------- */
static void bit_lp_setscl(void *data, int state)
{
/*be cautious about state of the control register -
touch only the one bit needed*/
if (state) {
parport_write_control((struct parport *) data,
parport_read_control((struct parport *) data)|I2C_SCL);
} else {
parport_write_control((struct parport *) data,
parport_read_control((struct parport *) data)&I2C_CMASK);
}
}
static void bit_lp_setsda(void *data, int state)
{
if (state) {
parport_write_data((struct parport *) data, I2C_DMASK);
} else {
parport_write_data((struct parport *) data, I2C_SDA);
}
}
static int bit_lp_getscl(void *data)
{
return parport_read_status((struct parport *) data) & I2C_SCLIN;
}
static int bit_lp_getsda(void *data)
{
return parport_read_status((struct parport *) data) & I2C_SDAIN;
}
static void bit_lp_setscl2(void *data, int state)
{
if (state) {
parport_write_data((struct parport *) data,
parport_read_data((struct parport *) data)|0x1);
} else {
parport_write_data((struct parport *) data,
parport_read_data((struct parport *) data)&0xfe);
}
}
static void bit_lp_setsda2(void *data, int state)
{
if (state) {
parport_write_data((struct parport *) data,
parport_read_data((struct parport *) data)|0x2);
} else {
parport_write_data((struct parport *) data,
parport_read_data((struct parport *) data)&0xfd);
}
}
static int bit_lp_getsda2(void *data)
{
return (parport_read_status((struct parport *) data) &
PARPORT_STATUS_BUSY) ? 0 : 1;
}
/* ------------------------------------------------------------------------
* Encapsulate the above functions in the correct operations structure.
* This is only done when more than one hardware adapter is supported.
*/
static struct i2c_algo_bit_data bit_lp_data = {
.setsda = bit_lp_setsda,
.setscl = bit_lp_setscl,
.getsda = bit_lp_getsda,
.getscl = bit_lp_getscl,
.udelay = 80,
.mdelay = 80,
.timeout = HZ
};
static struct i2c_algo_bit_data bit_lp_data2 = {
.setsda = bit_lp_setsda2,
.setscl = bit_lp_setscl2,
.getsda = bit_lp_getsda2,
.udelay = 80,
.mdelay = 80,
.timeout = HZ
};
static struct i2c_adapter bit_lp_ops = {
.owner = THIS_MODULE,
.id = I2C_HW_B_LP,
.name = "Philips Parallel port adapter",
};
static void i2c_parport_attach (struct parport *port)
{
struct i2c_par *adapter = kmalloc(sizeof(struct i2c_par),
GFP_KERNEL);
if (!adapter) {
printk(KERN_ERR "i2c-philips-par: Unable to malloc.\n");
return;
}
memset (adapter, 0x00, sizeof(struct i2c_par));
/* pr_debug("i2c-philips-par: attaching to %s\n", port->name); */
adapter->pdev = parport_register_device(port, "i2c-philips-par",
NULL, NULL, NULL,
PARPORT_FLAG_EXCL,
NULL);
if (!adapter->pdev) {
printk(KERN_ERR "i2c-philips-par: Unable to register with parport.\n");
kfree(adapter);
return;
}
adapter->adapter = bit_lp_ops;
adapter->adapter.algo_data = &adapter->bit_lp_data;
adapter->bit_lp_data = type ? bit_lp_data2 : bit_lp_data;
adapter->bit_lp_data.data = port;
if (parport_claim_or_block(adapter->pdev) < 0 ) {
printk(KERN_ERR "i2c-philips-par: Could not claim parallel port.\n");
kfree(adapter);
return;
}
/* reset hardware to sane state */
adapter->bit_lp_data.setsda(port, 1);
adapter->bit_lp_data.setscl(port, 1);
parport_release(adapter->pdev);
if (i2c_bit_add_bus(&adapter->adapter) < 0) {
printk(KERN_ERR "i2c-philips-par: Unable to register with I2C.\n");
parport_unregister_device(adapter->pdev);
kfree(adapter);
return; /* No good */
}
adapter->next = adapter_list;
adapter_list = adapter;
}
static void i2c_parport_detach (struct parport *port)
{
struct i2c_par *adapter, *prev = NULL;
for (adapter = adapter_list; adapter; adapter = adapter->next) {
if (adapter->pdev->port == port) {
parport_unregister_device(adapter->pdev);
i2c_bit_del_bus(&adapter->adapter);
if (prev)
prev->next = adapter->next;
else
adapter_list = adapter->next;
kfree(adapter);
return;
}
prev = adapter;
}
}
static struct parport_driver i2c_driver = {
.name = "i2c-philips-par",
.attach = i2c_parport_attach,
.detach = i2c_parport_detach,
};
int __init i2c_bitlp_init(void)
{
printk(KERN_INFO "i2c Philips parallel port adapter driver\n");
return parport_register_driver(&i2c_driver);
}
void __exit i2c_bitlp_exit(void)
{
parport_unregister_driver(&i2c_driver);
}
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for Philips parallel port adapter");
MODULE_LICENSE("GPL");
MODULE_PARM(type, "i");
module_init(i2c_bitlp_init);
module_exit(i2c_bitlp_exit);
......@@ -29,10 +29,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/config.h>
......
......@@ -55,10 +55,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
......@@ -216,7 +212,7 @@ static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, u8 *mmvga,
/*
* Cleanup stuff
*/
static void __devexit prosavage_remove(struct pci_dev *dev)
static void prosavage_remove(struct pci_dev *dev)
{
struct s_i2c_chip *chip;
int i, ret;
......@@ -321,7 +317,7 @@ static struct pci_driver prosavage_driver = {
.name = "prosavage-smbus",
.id_table = prosavage_pci_tbl,
.probe = prosavage_probe,
.remove = __devexit_p(prosavage_remove),
.remove = prosavage_remove,
};
static int __init i2c_prosavage_init(void)
......
......@@ -12,10 +12,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
......
......@@ -30,10 +30,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
......
......@@ -56,10 +56,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
......@@ -364,6 +360,7 @@ static struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis5595_adapter = {
.owner = THIS_MODULE,
.class = I2C_ADAP_CLASS_SMBUS,
.name = "unset",
.algo = &smbus_algorithm,
};
......@@ -391,6 +388,7 @@ static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_
static void __devexit sis5595_remove(struct pci_dev *dev)
{
i2c_del_adapter(&sis5595_adapter);
release_region(sis5595_base + SMB_INDEX, 2);
}
static struct pci_driver sis5595_driver = {
......@@ -408,7 +406,6 @@ static int __init i2c_sis5595_init(void)
static void __exit i2c_sis5595_exit(void)
{
pci_unregister_driver(&sis5595_driver);
release_region(sis5595_base + SMB_INDEX, 2);
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
......
......@@ -49,10 +49,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
......
......@@ -33,10 +33,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
......
/* ------------------------------------------------------------------------- */
/* i2c-velleman.c i2c-hw access for Velleman K8000 adapters */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-96, 2000 Simon G. Vogl
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <asm/io.h>
/* Pin Port Inverted name */
#define I2C_SDA 0x02 /* ctrl bit 1 (inv) */
#define I2C_SCL 0x08 /* ctrl bit 3 (inv) */
#define I2C_SDAIN 0x10 /* stat bit 4 */
#define I2C_SCLIN 0x08 /* ctrl bit 3 (inv)(reads own output)*/
#define I2C_DMASK 0xfd
#define I2C_CMASK 0xf7
/* --- Convenience defines for the parallel port: */
#define BASE (unsigned long)(data)
#define DATA BASE /* Centronics data port */
#define STAT (BASE+1) /* Centronics status port */
#define CTRL (BASE+2) /* Centronics control port */
#define DEFAULT_BASE 0x378
static long base=0;
/* ----- local functions --------------------------------------------------- */
static void bit_velle_setscl(void *data, int state)
{
if (state) {
outb(inb(CTRL) & I2C_CMASK, CTRL);
} else {
outb(inb(CTRL) | I2C_SCL, CTRL);
}
}
static void bit_velle_setsda(void *data, int state)
{
if (state) {
outb(inb(CTRL) & I2C_DMASK , CTRL);
} else {
outb(inb(CTRL) | I2C_SDA, CTRL);
}
}
static int bit_velle_getscl(void *data)
{
return ( 0 == ( (inb(CTRL)) & I2C_SCLIN ) );
}
static int bit_velle_getsda(void *data)
{
return ( 0 != ( (inb(STAT)) & I2C_SDAIN ) );
}
static int bit_velle_init(void)
{
if (!request_region(base, (base == 0x3bc) ? 3 : 8,
"i2c (Vellemann adapter)"))
return -ENODEV;
bit_velle_setsda((void*)base,1);
bit_velle_setscl((void*)base,1);
return 0;
}
/* ------------------------------------------------------------------------
* Encapsulate the above functions in the correct operations structure.
* This is only done when more than one hardware adapter is supported.
*/
static struct i2c_algo_bit_data bit_velle_data = {
.setsda = bit_velle_setsda,
.setscl = bit_velle_setscl,
.getsda = bit_velle_getsda,
.getscl = bit_velle_getscl,
.udelay = 10,
.mdelay = 10,
.timeout = HZ
};
static struct i2c_adapter bit_velle_ops = {
.owner = THIS_MODULE,
.algo_data = &bit_velle_data,
.name = "Velleman K8000",
};
static int __init i2c_bitvelle_init(void)
{
printk(KERN_INFO "i2c-velleman: i2c Velleman K8000 driver\n");
if (base==0) {
/* probe some values */
base=DEFAULT_BASE;
bit_velle_data.data=(void*)DEFAULT_BASE;
if (bit_velle_init()==0) {
if(i2c_bit_add_bus(&bit_velle_ops) < 0)
return -ENODEV;
} else {
return -ENODEV;
}
} else {
bit_velle_data.data=(void*)base;
if (bit_velle_init()==0) {
if(i2c_bit_add_bus(&bit_velle_ops) < 0)
return -ENODEV;
} else {
return -ENODEV;
}
}
pr_debug("i2c-velleman: found device at %#lx.\n",base);
return 0;
}
static void __exit i2c_bitvelle_exit(void)
{
i2c_bit_del_bus(&bit_velle_ops);
release_region(base, (base == 0x3bc) ? 3 : 8);
}
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K8000 adapter");
MODULE_LICENSE("GPL");
MODULE_PARM(base, "i");
module_init(i2c_bitvelle_init);
module_exit(i2c_bitvelle_exit);
......@@ -22,10 +22,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
......@@ -92,6 +88,7 @@ static struct i2c_algo_bit_data bit_data = {
static struct i2c_adapter vt586b_adapter = {
.owner = THIS_MODULE,
.class = I2C_ADAP_CLASS_SMBUS,
.name = "VIA i2c",
.algo_data = &bit_data,
};
......
......@@ -34,10 +34,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
......
......@@ -28,10 +28,6 @@
the BT869 and possibly other I2C devices. */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
......@@ -171,6 +167,7 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = {
static struct i2c_adapter voodoo3_i2c_adapter = {
.owner = THIS_MODULE,
.class = I2C_ADAP_CLASS_TV_ANALOG,
.name = "I2C Voodoo3/Banshee adapter",
.algo_data = &voo_i2c_bit_data,
};
......@@ -187,6 +184,7 @@ static struct i2c_algo_bit_data voo_ddc_bit_data = {
static struct i2c_adapter voodoo3_ddc_adapter = {
.owner = THIS_MODULE,
.class = I2C_ADAP_CLASS_DDC,
.name = "DDC Voodoo3/Banshee adapter",
.algo_data = &voo_ddc_bit_data,
};
......
......@@ -25,10 +25,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
......
......@@ -22,10 +22,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_BUS
#define DEBUG 1
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
......
......@@ -2,7 +2,7 @@
# I2C Sensor device configuration
#
menu "I2C Hardware Sensors Chip support"
menu "Hardware Sensors Chip support"
depends on I2C
config I2C_SENSOR
......@@ -33,17 +33,16 @@ config SENSORS_ASB100
This driver can also be built as a module. If so, the module
will be called asb100.
config SENSORS_EEPROM
tristate "EEPROM (DIMM) reader"
config SENSORS_DS1621
tristate "Dallas Semiconductor DS1621 and DS1625"
depends on I2C && EXPERIMENTAL
select I2C_SENSOR
help
If you say yes here you get read-only access to the EEPROM data
available on modern memory DIMMs, and which could theoretically
also be available on other devices.
If you say yes here you get support for Dallas Semiconductor
DS1621 and DS1625 sensor chips.
This driver can also be built as a module. If so, the module
will be called eeprom.
will be called ds1621.
config SENSORS_FSCHER
tristate "FSC Hermes"
......@@ -102,6 +101,17 @@ config SENSORS_LM78
This driver can also be built as a module. If so, the module
will be called lm78.
config SENSORS_LM80
tristate "National Semiconductor LM80"
depends on I2C && EXPERIMENTAL
select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor
LM80 sensor chips.
This driver can also be built as a module. If so, the module
will be called lm80.
config SENSORS_LM83
tristate "National Semiconductor LM83"
depends on I2C && EXPERIMENTAL
......@@ -171,4 +181,32 @@ config SENSORS_W83L785TS
This driver can also be built as a module. If so, the module
will be called w83l785ts.
config SENSORS_W83627HF
tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF"
depends on I2C && EXPERIMENTAL
select I2C_SENSOR
help
If you say yes here you get support for the Winbond W836X7 series
of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF
This driver can also be built as a module. If so, the module
will be called w83627hf.
endmenu
menu "Other I2C Chip support"
depends on I2C
config SENSORS_EEPROM
tristate "EEPROM reader"
depends on I2C && EXPERIMENTAL
select I2C_SENSOR
help
If you say yes here you get read-only access to the EEPROM data
available on modern memory DIMMs and Sony Vaio laptops. Such
EEPROMs could theoretically be available on other devices as well.
This driver can also be built as a module. If so, the module
will be called eeprom.
endmenu
......@@ -4,17 +4,24 @@
# asb100, then w83781d go first, as they can override other drivers' addresses.
obj-$(CONFIG_SENSORS_ASB100) += asb100.o
obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
obj-$(CONFIG_SENSORS_LM78) += lm78.o
obj-$(CONFIG_SENSORS_LM80) += lm80.o
obj-$(CONFIG_SENSORS_LM83) += lm83.o
obj-$(CONFIG_SENSORS_LM85) += lm85.o
obj-$(CONFIG_SENSORS_LM90) += lm90.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
endif
......@@ -20,10 +20,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -139,7 +135,7 @@ static int adm1021_detach_client(struct i2c_client *client);
static int adm1021_read_value(struct i2c_client *client, u8 reg);
static int adm1021_write_value(struct i2c_client *client, u8 reg,
u16 value);
static void adm1021_update_client(struct i2c_client *client);
static struct adm1021_data *adm1021_update_device(struct device *dev);
/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
static int read_only = 0;
......@@ -148,7 +144,7 @@ static int read_only = 0;
/* This is the driver that will be inserted */
static struct i2c_driver adm1021_driver = {
.owner = THIS_MODULE,
.name = "ADM1021-MAX1617",
.name = "adm1021",
.id = I2C_DRIVERID_ADM1021,
.flags = I2C_DF_NOTIFY,
.attach_adapter = adm1021_attach_adapter,
......@@ -163,13 +159,8 @@ static int adm1021_id = 0;
#define show(value) \
static ssize_t show_##value(struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct adm1021_data *data = i2c_get_clientdata(client); \
int temp; \
\
adm1021_update_client(client); \
temp = TEMP_FROM_REG(data->value); \
return sprintf(buf, "%d\n", temp); \
struct adm1021_data *data = adm1021_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
}
show(temp_max);
show(temp_hyst);
......@@ -181,10 +172,7 @@ show(remote_temp_input);
#define show2(value) \
static ssize_t show_##value(struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct adm1021_data *data = i2c_get_clientdata(client); \
\
adm1021_update_client(client); \
struct adm1021_data *data = adm1021_update_device(dev); \
return sprintf(buf, "%d\n", data->value); \
}
show2(alarms);
......@@ -206,12 +194,12 @@ set(temp_hyst, ADM1021_REG_THYST_W);
set(remote_temp_max, ADM1021_REG_REMOTE_TOS_W);
set(remote_temp_hyst, ADM1021_REG_REMOTE_THYST_W);
static DEVICE_ATTR(temp_max1, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
static DEVICE_ATTR(temp_min1, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input, NULL);
static DEVICE_ATTR(temp_max2, S_IWUSR | S_IRUGO, show_remote_temp_max, set_remote_temp_max);
static DEVICE_ATTR(temp_min2, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst);
static DEVICE_ATTR(temp_input2, S_IRUGO, show_remote_temp_input, NULL);
static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL);
static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_remote_temp_max, set_remote_temp_max);
static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst);
static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote_temp_input, NULL);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
static DEVICE_ATTR(die_code, S_IRUGO, show_die_code, NULL);
......@@ -309,10 +297,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
type_name = "gl523sm";
} else if (kind == mc1066) {
type_name = "mc1066";
} else {
dev_err(&adapter->dev, "Internal error: unknown kind (%d)?!?",
kind);
goto error1;
}
/* Fill in the remaining client fields and put it into the global list */
......@@ -331,12 +315,12 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
adm1021_init_client(new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_min1);
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_max2);
device_create_file(&new_client->dev, &dev_attr_temp_min2);
device_create_file(&new_client->dev, &dev_attr_temp_input2);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp2_max);
device_create_file(&new_client->dev, &dev_attr_temp2_min);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_alarms);
if (data->type == adm1021)
device_create_file(&new_client->dev, &dev_attr_die_code);
......@@ -393,8 +377,9 @@ static int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value)
return 0;
}
static void adm1021_update_client(struct i2c_client *client)
static struct adm1021_data *adm1021_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct adm1021_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
......@@ -424,6 +409,8 @@ static void adm1021_update_client(struct i2c_client *client)
}
up(&data->update_lock);
return data;
}
static int __init sensors_adm1021_init(void)
......
......@@ -37,10 +37,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
......@@ -274,7 +270,7 @@ static ssize_t \
{ \
return show_in(dev, buf, 0x##offset); \
} \
static DEVICE_ATTR(in_input##offset, S_IRUGO, \
static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
show_in##offset, NULL) \
static ssize_t \
show_in##offset##_min (struct device *dev, char *buf) \
......@@ -296,9 +292,9 @@ static ssize_t set_in##offset##_max (struct device *dev, \
{ \
return set_in_max(dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
show_in##offset##_min, set_in##offset##_min) \
static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
show_in##offset##_max, set_in##offset##_max)
sysfs_in(0)
......@@ -310,9 +306,9 @@ sysfs_in(5)
sysfs_in(6)
#define device_create_file_in(client, offset) do { \
device_create_file(&client->dev, &dev_attr_in_input##offset); \
device_create_file(&client->dev, &dev_attr_in_min##offset); \
device_create_file(&client->dev, &dev_attr_in_max##offset); \
device_create_file(&client->dev, &dev_attr_in##offset##_input); \
device_create_file(&client->dev, &dev_attr_in##offset##_min); \
device_create_file(&client->dev, &dev_attr_in##offset##_max); \
} while (0)
/* 3 Fans */
......@@ -412,11 +408,11 @@ static ssize_t set_fan##offset##_div(struct device *dev, const char *buf, \
{ \
return set_fan_div(dev, buf, count, offset - 1); \
} \
static DEVICE_ATTR(fan_input##offset, S_IRUGO, \
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
show_fan##offset, NULL) \
static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
show_fan##offset##_min, set_fan##offset##_min) \
static DEVICE_ATTR(fan_div##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
show_fan##offset##_div, set_fan##offset##_div)
sysfs_fan(1)
......@@ -424,9 +420,9 @@ sysfs_fan(2)
sysfs_fan(3)
#define device_create_file_fan(client, offset) do { \
device_create_file(&client->dev, &dev_attr_fan_input##offset); \
device_create_file(&client->dev, &dev_attr_fan_min##offset); \
device_create_file(&client->dev, &dev_attr_fan_div##offset); \
device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
} while (0)
/* 4 Temp. Sensors */
......@@ -484,7 +480,7 @@ static ssize_t show_temp##num(struct device *dev, char *buf) \
{ \
return show_temp(dev, buf, num-1); \
} \
static DEVICE_ATTR(temp_input##num, S_IRUGO, show_temp##num, NULL) \
static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL) \
static ssize_t show_temp_max##num(struct device *dev, char *buf) \
{ \
return show_temp_max(dev, buf, num-1); \
......@@ -494,7 +490,7 @@ static ssize_t set_temp_max##num(struct device *dev, const char *buf, \
{ \
return set_temp_max(dev, buf, count, num-1); \
} \
static DEVICE_ATTR(temp_max##num, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \
show_temp_max##num, set_temp_max##num) \
static ssize_t show_temp_hyst##num(struct device *dev, char *buf) \
{ \
......@@ -505,7 +501,7 @@ static ssize_t set_temp_hyst##num(struct device *dev, const char *buf, \
{ \
return set_temp_hyst(dev, buf, count, num-1); \
} \
static DEVICE_ATTR(temp_hyst##num, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(temp##num##_max_hyst, S_IRUGO | S_IWUSR, \
show_temp_hyst##num, set_temp_hyst##num)
sysfs_temp(1)
......@@ -515,9 +511,9 @@ sysfs_temp(4)
/* VID */
#define device_create_file_temp(client, num) do { \
device_create_file(&client->dev, &dev_attr_temp_input##num); \
device_create_file(&client->dev, &dev_attr_temp_max##num); \
device_create_file(&client->dev, &dev_attr_temp_hyst##num); \
device_create_file(&client->dev, &dev_attr_temp##num##_input); \
device_create_file(&client->dev, &dev_attr_temp##num##_max); \
device_create_file(&client->dev, &dev_attr_temp##num##_max_hyst); \
} while (0)
static ssize_t show_vid(struct device *dev, char *buf)
......@@ -526,9 +522,9 @@ static ssize_t show_vid(struct device *dev, char *buf)
return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
}
static DEVICE_ATTR(vid, S_IRUGO, show_vid, NULL)
static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL)
#define device_create_file_vid(client) \
device_create_file(&client->dev, &dev_attr_vid)
device_create_file(&client->dev, &dev_attr_in0_ref)
/* VRM */
static ssize_t show_vrm(struct device *dev, char *buf)
......@@ -597,12 +593,12 @@ static ssize_t set_pwm_enable1(struct device *dev, const char *buf,
return count;
}
static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1)
static DEVICE_ATTR(pwm_enable1, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(fan1_pwm, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1)
static DEVICE_ATTR(fan1_pwm_enable, S_IRUGO | S_IWUSR,
show_pwm_enable1, set_pwm_enable1)
#define device_create_file_pwm1(client) do { \
device_create_file(&new_client->dev, &dev_attr_pwm1); \
device_create_file(&new_client->dev, &dev_attr_pwm_enable1); \
device_create_file(&new_client->dev, &dev_attr_fan1_pwm); \
device_create_file(&new_client->dev, &dev_attr_fan1_pwm_enable); \
} while (0)
/* This function is called when:
......
/*
ds1621.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Christian W. Zuckschwerdt <zany@triq.net> 2000-11-23
based on lm75.c by Frodo Looijaard <frodol@dds.nl>
Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
the help of Jean Delvare <khali@linux-fr.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include "lm75.h"
/* Addresses to scan */
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { 0x48, 0x4f, I2C_CLIENT_END };
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
SENSORS_INSMOD_1(ds1621);
static int polarity = -1;
MODULE_PARM(polarity, "i");
MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low");
/* Many DS1621 constants specified below */
/* Config register used for detection */
/* 7 6 5 4 3 2 1 0 */
/* |Done|THF |TLF |NVB | 1 | 0 |POL |1SHOT| */
#define DS1621_REG_CONFIG_MASK 0x0C
#define DS1621_REG_CONFIG_VAL 0x08
#define DS1621_REG_CONFIG_POLARITY 0x02
#define DS1621_REG_CONFIG_1SHOT 0x01
#define DS1621_REG_CONFIG_DONE 0x80
/* The DS1621 registers */
#define DS1621_REG_TEMP 0xAA /* word, RO */
#define DS1621_REG_TEMP_MIN 0xA1 /* word, RW */
#define DS1621_REG_TEMP_MAX 0xA2 /* word, RW */
#define DS1621_REG_CONF 0xAC /* byte, RW */
#define DS1621_COM_START 0xEE /* no data */
/* The DS1621 configuration register */
#define DS1621_ALARM_TEMP_HIGH 0x40
#define DS1621_ALARM_TEMP_LOW 0x20
/* Conversions. Rounding and limit checking is only done on the TO_REG
variants. Note that you should be a bit careful with which arguments
these macros are called: arguments may be evaluated more than once.
Fixing this is just not worth it. */
#define ALARMS_FROM_REG(val) ((val) & \
(DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW))
/* Each client has this additional data */
struct ds1621_data {
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
u16 temp, temp_min, temp_max; /* Register values, word */
u8 conf; /* Register encoding, combined */
};
static int ds1621_attach_adapter(struct i2c_adapter *adapter);
static int ds1621_detect(struct i2c_adapter *adapter, int address,
int kind);
static void ds1621_init_client(struct i2c_client *client);
static int ds1621_detach_client(struct i2c_client *client);
static struct ds1621_data *ds1621_update_client(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver ds1621_driver = {
.owner = THIS_MODULE,
.name = "ds1621",
.id = I2C_DRIVERID_DS1621,
.flags = I2C_DF_NOTIFY,
.attach_adapter = ds1621_attach_adapter,
.detach_client = ds1621_detach_client,
};
static int ds1621_id = 0;
static u16 swap_bytes(u16 val)
{
return (val >> 8) | (val << 8);
}
/* All registers are word-sized, except for the configuration register.
DS1621 uses a high-byte first convention, which is exactly opposite to
the usual practice. */
static int ds1621_read_value(struct i2c_client *client, u8 reg)
{
if (reg == DS1621_REG_CONF)
return i2c_smbus_read_byte_data(client, reg);
else
return swap_bytes(i2c_smbus_read_word_data(client, reg));
}
/* All registers are word-sized, except for the configuration register.
DS1621 uses a high-byte first convention, which is exactly opposite to
the usual practice. */
static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value)
{
if (reg == DS1621_REG_CONF)
return i2c_smbus_write_byte_data(client, reg, value);
else
return i2c_smbus_write_word_data(client, reg,
swap_bytes(value));
}
static void ds1621_init_client(struct i2c_client *client)
{
int reg = ds1621_read_value(client, DS1621_REG_CONF);
/* switch to continous conversion mode */
reg &= ~ DS1621_REG_CONFIG_1SHOT;
/* setup output polarity */
if (polarity == 0)
reg &= ~DS1621_REG_CONFIG_POLARITY;
else if (polarity == 1)
reg |= DS1621_REG_CONFIG_POLARITY;
ds1621_write_value(client, DS1621_REG_CONF, reg);
/* start conversion */
i2c_smbus_write_byte(client, DS1621_COM_START);
}
#define show(value) \
static ssize_t show_##value(struct device *dev, char *buf) \
{ \
struct ds1621_data *data = ds1621_update_client(dev); \
return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value)); \
}
show(temp);
show(temp_min);
show(temp_max);
#define set_temp(suffix, value, reg) \
static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct ds1621_data *data = ds1621_update_client(dev); \
data->value = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \
ds1621_write_value(client, reg, data->value); \
return count; \
}
set_temp(min, temp_min, DS1621_REG_TEMP_MIN);
set_temp(max, temp_max, DS1621_REG_TEMP_MAX);
static ssize_t show_alarms(struct device *dev, char *buf)
{
struct ds1621_data *data = ds1621_update_client(dev);
return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->conf));
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
static DEVICE_ATTR(temp1_input, S_IRUGO , show_temp, NULL);
static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min);
static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
static int ds1621_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_detect(adapter, &addr_data, ds1621_detect);
}
/* This function is called by i2c_detect */
int ds1621_detect(struct i2c_adapter *adapter, int address,
int kind)
{
int conf, temp;
struct i2c_client *new_client;
struct ds1621_data *data;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_WORD_DATA
| I2C_FUNC_SMBUS_WRITE_BYTE))
goto exit;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access ds1621_{read,write}_value. */
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
sizeof(struct ds1621_data),
GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
memset(new_client, 0, sizeof(struct i2c_client) +
sizeof(struct ds1621_data));
data = (struct ds1621_data *) (new_client + 1);
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &ds1621_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. It is lousy. */
if (kind < 0) {
conf = ds1621_read_value(new_client, DS1621_REG_CONF);
if ((conf & DS1621_REG_CONFIG_MASK) != DS1621_REG_CONFIG_VAL)
goto exit_free;
temp = ds1621_read_value(new_client, DS1621_REG_TEMP);
if (temp & 0x007f)
goto exit_free;
temp = ds1621_read_value(new_client, DS1621_REG_TEMP_MIN);
if (temp & 0x007f)
goto exit_free;
temp = ds1621_read_value(new_client, DS1621_REG_TEMP_MAX);
if (temp & 0x007f)
goto exit_free;
}
/* Determine the chip type - only one kind supported! */
if (kind <= 0)
kind = ds1621;
/* Fill in remaining client fields and put it into the global list */
strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE);
new_client->id = ds1621_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* Initialize the DS1621 chip */
ds1621_init_client(new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_alarms);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
return 0;
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
exit_free:
kfree(new_client);
exit:
return err;
}
static int ds1621_detach_client(struct i2c_client *client)
{
int err;
if ((err = i2c_detach_client(client))) {
dev_err(&client->dev,
"ds1621.o: Client deregistration failed, client not detached.\n");
return err;
}
kfree(client);
return 0;
}
static struct ds1621_data *ds1621_update_client(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct ds1621_data *data = i2c_get_clientdata(client);
u8 new_conf;
down(&data->update_lock);
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
(jiffies < data->last_updated) || !data->valid) {
dev_dbg(&client->dev, "Starting ds1621 update\n");
data->conf = ds1621_read_value(client, DS1621_REG_CONF);
data->temp = ds1621_read_value(client, DS1621_REG_TEMP);
data->temp_min = ds1621_read_value(client,
DS1621_REG_TEMP_MIN);
data->temp_max = ds1621_read_value(client,
DS1621_REG_TEMP_MAX);
/* reset alarms if neccessary */
new_conf = data->conf;
if (data->temp < data->temp_min)
new_conf &= ~DS1621_ALARM_TEMP_LOW;
if (data->temp > data->temp_max)
new_conf &= ~DS1621_ALARM_TEMP_HIGH;
if (data->conf != new_conf)
ds1621_write_value(client, DS1621_REG_CONF,
new_conf);
data->last_updated = jiffies;
data->valid = 1;
}
up(&data->update_lock);
return data;
}
static int __init ds1621_init(void)
{
return i2c_add_driver(&ds1621_driver);
}
static void __exit ds1621_exit(void)
{
i2c_del_driver(&ds1621_driver);
}
MODULE_AUTHOR("Christian W. Zuckschwerdt <zany@triq.net>");
MODULE_DESCRIPTION("DS1621 driver");
MODULE_LICENSE("GPL");
module_init(ds1621_init);
module_exit(ds1621_exit);
......@@ -27,10 +27,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
......
......@@ -26,6 +26,7 @@
* and Philip Edelbrock <phil@netroedge.com>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -108,7 +109,7 @@ SENSORS_INSMOD_1(fscher);
static int fscher_attach_adapter(struct i2c_adapter *adapter);
static int fscher_detect(struct i2c_adapter *adapter, int address, int kind);
static int fscher_detach_client(struct i2c_client *client);
static void fscher_update_client(struct i2c_client *client);
static struct fscher_data *fscher_update_device(struct device *dev);
static void fscher_init_client(struct i2c_client *client);
static int fscher_read_value(struct i2c_client *client, u8 reg);
......@@ -160,71 +161,69 @@ static int fscher_id = 0;
* Sysfs stuff
*/
#define sysfs_r(kind, offset, reg) \
static ssize_t show_##kind (struct fscher_data *, char *, int); \
static ssize_t show_##kind##offset (struct device *, char *); \
static ssize_t show_##kind##offset (struct device *dev, char *buf) \
#define sysfs_r(kind, sub, offset, reg) \
static ssize_t show_##kind##sub (struct fscher_data *, char *, int); \
static ssize_t show_##kind##offset##sub (struct device *, char *); \
static ssize_t show_##kind##offset##sub (struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct fscher_data *data = i2c_get_clientdata(client); \
fscher_update_client(client); \
return show_##kind(data, buf, (offset)); \
struct fscher_data *data = fscher_update_device(dev); \
return show_##kind##sub(data, buf, (offset)); \
}
#define sysfs_w(kind, offset, reg) \
static ssize_t set_##kind (struct i2c_client *, struct fscher_data *, const char *, size_t, int, int); \
static ssize_t set_##kind##offset (struct device *, const char *, size_t); \
static ssize_t set_##kind##offset (struct device *dev, const char *buf, size_t count) \
#define sysfs_w(kind, sub, offset, reg) \
static ssize_t set_##kind##sub (struct i2c_client *, struct fscher_data *, const char *, size_t, int, int); \
static ssize_t set_##kind##offset##sub (struct device *, const char *, size_t); \
static ssize_t set_##kind##offset##sub (struct device *dev, const char *buf, size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct fscher_data *data = i2c_get_clientdata(client); \
return set_##kind(client, data, buf, count, (offset), reg); \
return set_##kind##sub(client, data, buf, count, (offset), reg); \
}
#define sysfs_rw_n(kind, offset, reg) \
sysfs_r(kind, offset, reg) \
sysfs_w(kind, offset, reg) \
static DEVICE_ATTR(kind##offset, S_IRUGO | S_IWUSR, show_##kind##offset, set_##kind##offset);
#define sysfs_rw_n(kind, sub, offset, reg) \
sysfs_r(kind, sub, offset, reg) \
sysfs_w(kind, sub, offset, reg) \
static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, show_##kind##offset##sub, set_##kind##offset##sub);
#define sysfs_rw(kind, reg) \
sysfs_r(kind, 0, reg) \
sysfs_w(kind, 0, reg) \
static DEVICE_ATTR(kind, S_IRUGO | S_IWUSR, show_##kind##0, set_##kind##0);
#define sysfs_rw(kind, sub, reg) \
sysfs_r(kind, sub, 0, reg) \
sysfs_w(kind, sub, 0, reg) \
static DEVICE_ATTR(kind##sub, S_IRUGO | S_IWUSR, show_##kind##0##sub, set_##kind##0##sub);
#define sysfs_ro_n(kind, offset, reg) \
sysfs_r(kind, offset, reg) \
static DEVICE_ATTR(kind##offset, S_IRUGO, show_##kind##offset, NULL);
#define sysfs_ro_n(kind, sub, offset, reg) \
sysfs_r(kind, sub, offset, reg) \
static DEVICE_ATTR(kind##offset##sub, S_IRUGO, show_##kind##offset##sub, NULL);
#define sysfs_ro(kind, reg) \
sysfs_r(kind, 0, reg) \
static DEVICE_ATTR(kind, S_IRUGO, show_##kind##0, NULL);
#define sysfs_ro(kind, sub, reg) \
sysfs_r(kind, sub, 0, reg) \
static DEVICE_ATTR(kind, S_IRUGO, show_##kind##0##sub, NULL);
#define sysfs_fan(offset, reg_status, reg_min, reg_ripple, reg_act) \
sysfs_rw_n(pwm , offset, reg_min) \
sysfs_rw_n(fan_status, offset, reg_status) \
sysfs_rw_n(fan_div , offset, reg_ripple) \
sysfs_ro_n(fan_input , offset, reg_act)
sysfs_rw_n(fan, _pwm , offset, reg_min) \
sysfs_rw_n(fan, _status, offset, reg_status) \
sysfs_rw_n(fan, _div , offset, reg_ripple) \
sysfs_ro_n(fan, _input , offset, reg_act)
#define sysfs_temp(offset, reg_status, reg_act) \
sysfs_rw_n(temp_status, offset, reg_status) \
sysfs_ro_n(temp_input , offset, reg_act)
sysfs_rw_n(temp, _status, offset, reg_status) \
sysfs_ro_n(temp, _input , offset, reg_act)
#define sysfs_in(offset, reg_act) \
sysfs_ro_n(in_input, offset, reg_act)
sysfs_ro_n(in, _input, offset, reg_act)
#define sysfs_revision(reg_revision) \
sysfs_ro(revision, reg_revision)
sysfs_ro(revision, , reg_revision)
#define sysfs_alarms(reg_events) \
sysfs_ro(alarms, reg_events)
sysfs_ro(alarms, , reg_events)
#define sysfs_control(reg_control) \
sysfs_rw(control, reg_control)
sysfs_rw(control, , reg_control)
#define sysfs_watchdog(reg_control, reg_status, reg_preset) \
sysfs_rw(watchdog_control, reg_control) \
sysfs_rw(watchdog_status , reg_status) \
sysfs_rw(watchdog_preset , reg_preset)
sysfs_rw(watchdog, _control, reg_control) \
sysfs_rw(watchdog, _status , reg_status) \
sysfs_rw(watchdog, _preset , reg_preset)
sysfs_fan(1, FSCHER_REG_FAN0_STATE, FSCHER_REG_FAN0_MIN,
FSCHER_REG_FAN0_RIPPLE, FSCHER_REG_FAN0_ACT)
......@@ -248,21 +247,21 @@ sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_P
#define device_create_file_fan(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_fan_status##offset); \
device_create_file(&client->dev, &dev_attr_pwm##offset); \
device_create_file(&client->dev, &dev_attr_fan_div##offset); \
device_create_file(&client->dev, &dev_attr_fan_input##offset); \
device_create_file(&client->dev, &dev_attr_fan##offset##_status); \
device_create_file(&client->dev, &dev_attr_fan##offset##_pwm); \
device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
} while (0)
#define device_create_file_temp(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_temp_status##offset); \
device_create_file(&client->dev, &dev_attr_temp_input##offset); \
device_create_file(&client->dev, &dev_attr_temp##offset##_status); \
device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
} while (0)
#define device_create_file_in(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_in_input##offset); \
device_create_file(&client->dev, &dev_attr_in##offset##_input); \
} while (0)
#define device_create_file_revision(client) \
......@@ -415,8 +414,9 @@ static void fscher_init_client(struct i2c_client *client)
data->revision = fscher_read_value(client, FSCHER_REG_REVISION);
}
static void fscher_update_client(struct i2c_client *client)
static struct fscher_data *fscher_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct fscher_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
......@@ -461,6 +461,8 @@ static void fscher_update_client(struct i2c_client *client)
}
up(&data->update_lock);
return data;
}
......@@ -484,7 +486,7 @@ static ssize_t show_fan_status(struct fscher_data *data, char *buf, int nr)
return sprintf(buf, "%u\n", data->fan_status[FAN_INDEX_FROM_NUM(nr)] & 0x04);
}
static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data,
static ssize_t set_fan_pwm(struct i2c_client *client, struct fscher_data *data,
const char *buf, size_t count, int nr, int reg)
{
data->fan_min[FAN_INDEX_FROM_NUM(nr)] = simple_strtoul(buf, NULL, 10) & 0xff;
......@@ -493,7 +495,7 @@ static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data,
return count;
}
static ssize_t show_pwm (struct fscher_data *data, char *buf, int nr)
static ssize_t show_fan_pwm (struct fscher_data *data, char *buf, int nr)
{
return sprintf(buf, "%u\n", data->fan_min[FAN_INDEX_FROM_NUM(nr)]);
}
......
......@@ -37,10 +37,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -151,7 +147,7 @@ static void gl518_init_client(struct i2c_client *client);
static int gl518_detach_client(struct i2c_client *client);
static int gl518_read_value(struct i2c_client *client, u8 reg);
static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value);
static void gl518_update_client(struct i2c_client *client);
static struct gl518_data *gl518_update_device(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver gl518_driver = {
......@@ -176,18 +172,14 @@ static int gl518_id = 0;
#define show(type, suffix, value) \
static ssize_t show_##suffix(struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct gl518_data *data = i2c_get_clientdata(client); \
gl518_update_client(client); \
struct gl518_data *data = gl518_update_device(dev); \
return sprintf(buf, "%d\n", type##_FROM_REG(data->value)); \
}
#define show_fan(suffix, value, index) \
static ssize_t show_##suffix(struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct gl518_data *data = i2c_get_clientdata(client); \
gl518_update_client(client); \
struct gl518_data *data = gl518_update_device(dev); \
return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[index], \
DIV_FROM_REG(data->fan_div[index]))); \
}
......@@ -307,29 +299,29 @@ static ssize_t set_fan_min2(struct device *dev, const char *buf, size_t count)
return count;
}
static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input1, NULL);
static DEVICE_ATTR(temp_max1, S_IWUSR|S_IRUGO, show_temp_max1, set_temp_max1);
static DEVICE_ATTR(temp_hyst1, S_IWUSR|S_IRUGO,
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
static DEVICE_ATTR(temp1_max, S_IWUSR|S_IRUGO, show_temp_max1, set_temp_max1);
static DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO,
show_temp_hyst1, set_temp_hyst1);
static DEVICE_ATTR(fan_auto1, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1);
static DEVICE_ATTR(fan_input1, S_IRUGO, show_fan_input1, NULL);
static DEVICE_ATTR(fan_input2, S_IRUGO, show_fan_input2, NULL);
static DEVICE_ATTR(fan_min1, S_IWUSR|S_IRUGO, show_fan_min1, set_fan_min1);
static DEVICE_ATTR(fan_min2, S_IWUSR|S_IRUGO, show_fan_min2, set_fan_min2);
static DEVICE_ATTR(fan_div1, S_IWUSR|S_IRUGO, show_fan_div1, set_fan_div1);
static DEVICE_ATTR(fan_div2, S_IWUSR|S_IRUGO, show_fan_div2, set_fan_div2);
static DEVICE_ATTR(in_input0, S_IRUGO, show_in_input0, NULL);
static DEVICE_ATTR(in_input1, S_IRUGO, show_in_input1, NULL);
static DEVICE_ATTR(in_input2, S_IRUGO, show_in_input2, NULL);
static DEVICE_ATTR(in_input3, S_IRUGO, show_in_input3, NULL);
static DEVICE_ATTR(in_min0, S_IWUSR|S_IRUGO, show_in_min0, set_in_min0);
static DEVICE_ATTR(in_min1, S_IWUSR|S_IRUGO, show_in_min1, set_in_min1);
static DEVICE_ATTR(in_min2, S_IWUSR|S_IRUGO, show_in_min2, set_in_min2);
static DEVICE_ATTR(in_min3, S_IWUSR|S_IRUGO, show_in_min3, set_in_min3);
static DEVICE_ATTR(in_max0, S_IWUSR|S_IRUGO, show_in_max0, set_in_max0);
static DEVICE_ATTR(in_max1, S_IWUSR|S_IRUGO, show_in_max1, set_in_max1);
static DEVICE_ATTR(in_max2, S_IWUSR|S_IRUGO, show_in_max2, set_in_max2);
static DEVICE_ATTR(in_max3, S_IWUSR|S_IRUGO, show_in_max3, set_in_max3);
static DEVICE_ATTR(fan1_auto, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1);
static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input1, NULL);
static DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input2, NULL);
static DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO, show_fan_min1, set_fan_min1);
static DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO, show_fan_min2, set_fan_min2);
static DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO, show_fan_div1, set_fan_div1);
static DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO, show_fan_div2, set_fan_div2);
static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL);
static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL);
static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL);
static DEVICE_ATTR(in3_input, S_IRUGO, show_in_input3, NULL);
static DEVICE_ATTR(in0_min, S_IWUSR|S_IRUGO, show_in_min0, set_in_min0);
static DEVICE_ATTR(in1_min, S_IWUSR|S_IRUGO, show_in_min1, set_in_min1);
static DEVICE_ATTR(in2_min, S_IWUSR|S_IRUGO, show_in_min2, set_in_min2);
static DEVICE_ATTR(in3_min, S_IWUSR|S_IRUGO, show_in_min3, set_in_min3);
static DEVICE_ATTR(in0_max, S_IWUSR|S_IRUGO, show_in_max0, set_in_max0);
static DEVICE_ATTR(in1_max, S_IWUSR|S_IRUGO, show_in_max1, set_in_max1);
static DEVICE_ATTR(in2_max, S_IWUSR|S_IRUGO, show_in_max2, set_in_max2);
static DEVICE_ATTR(in3_max, S_IWUSR|S_IRUGO, show_in_max3, set_in_max3);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
static DEVICE_ATTR(beep_enable, S_IWUSR|S_IRUGO,
show_beep_enable, set_beep_enable);
......@@ -353,7 +345,6 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
struct i2c_client *new_client;
struct gl518_data *data;
int err = 0;
const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
......@@ -393,10 +384,8 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
i = gl518_read_value(new_client, GL518_REG_REVISION);
if (i == 0x00) {
kind = gl518sm_r00;
name = "gl518sm";
} else if (i == 0x80) {
kind = gl518sm_r80;
name = "gl518sm";
} else {
if (kind <= 0)
dev_info(&adapter->dev,
......@@ -408,7 +397,7 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* Fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE);
new_client->id = gl518_id++;
data->type = kind;
data->valid = 0;
......@@ -424,28 +413,28 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
gl518_init_client((struct i2c_client *) new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_in_input0);
device_create_file(&new_client->dev, &dev_attr_in_input1);
device_create_file(&new_client->dev, &dev_attr_in_input2);
device_create_file(&new_client->dev, &dev_attr_in_input3);
device_create_file(&new_client->dev, &dev_attr_in_min0);
device_create_file(&new_client->dev, &dev_attr_in_min1);
device_create_file(&new_client->dev, &dev_attr_in_min2);
device_create_file(&new_client->dev, &dev_attr_in_min3);
device_create_file(&new_client->dev, &dev_attr_in_max0);
device_create_file(&new_client->dev, &dev_attr_in_max1);
device_create_file(&new_client->dev, &dev_attr_in_max2);
device_create_file(&new_client->dev, &dev_attr_in_max3);
device_create_file(&new_client->dev, &dev_attr_fan_auto1);
device_create_file(&new_client->dev, &dev_attr_fan_input1);
device_create_file(&new_client->dev, &dev_attr_fan_input2);
device_create_file(&new_client->dev, &dev_attr_fan_min1);
device_create_file(&new_client->dev, &dev_attr_fan_min2);
device_create_file(&new_client->dev, &dev_attr_fan_div1);
device_create_file(&new_client->dev, &dev_attr_fan_div2);
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_hyst1);
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
device_create_file(&new_client->dev, &dev_attr_in3_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in2_min);
device_create_file(&new_client->dev, &dev_attr_in3_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
device_create_file(&new_client->dev, &dev_attr_in1_max);
device_create_file(&new_client->dev, &dev_attr_in2_max);
device_create_file(&new_client->dev, &dev_attr_in3_max);
device_create_file(&new_client->dev, &dev_attr_fan1_auto);
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan2_input);
device_create_file(&new_client->dev, &dev_attr_fan1_min);
device_create_file(&new_client->dev, &dev_attr_fan2_min);
device_create_file(&new_client->dev, &dev_attr_fan1_div);
device_create_file(&new_client->dev, &dev_attr_fan2_div);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
device_create_file(&new_client->dev, &dev_attr_alarms);
device_create_file(&new_client->dev, &dev_attr_beep_enable);
device_create_file(&new_client->dev, &dev_attr_beep_mask);
......@@ -523,8 +512,9 @@ static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
return i2c_smbus_write_byte_data(client, reg, value);
}
static void gl518_update_client(struct i2c_client *client)
static struct gl518_data *gl518_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct gl518_data *data = i2c_get_clientdata(client);
int val;
......@@ -590,6 +580,8 @@ static void gl518_update_client(struct i2c_client *client)
}
up(&data->update_lock);
return data;
}
static int __init sensors_gl518sm_init(void)
......
......@@ -6,7 +6,7 @@
IT8712F Super I/O chip w/LPC interface & SMbus
Sis950 A clone of the IT8705F
Copyright (c) 2001 Chris Gauthron <chrisg@0-in.com>
Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com>
Largely inspired by lm78.c of the same package
This program is free software; you can redistribute it and/or modify
......@@ -32,10 +32,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -51,17 +47,14 @@ static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
SENSORS_INSMOD_4(it87, it8705, it8712, sis950);
SENSORS_INSMOD_1(it87);
/* Update battery voltage after every reading if true */
static int update_vbat = 0;
static int update_vbat;
/* Enable Temp1 as thermal resistor */
/* Enable Temp2 as thermal diode */
/* Enable Temp3 as thermal resistor */
static int temp_type = 0x2a;
/* Reset the registers on init if true */
static int reset;
/* Many IT87 constants specified below */
......@@ -135,61 +128,6 @@ static int DIV_TO_REG(int val)
}
#define DIV_FROM_REG(val) (1 << (val))
/* Initial limits. Use the config file to set better limits. */
#define IT87_INIT_IN_0 170
#define IT87_INIT_IN_1 250
#define IT87_INIT_IN_2 (330 / 2)
#define IT87_INIT_IN_3 (((500) * 100)/168)
#define IT87_INIT_IN_4 (((1200) * 10)/38)
#define IT87_INIT_IN_5 (((1200) * 10)/72)
#define IT87_INIT_IN_6 (((500) * 10)/56)
#define IT87_INIT_IN_7 (((500) * 100)/168)
#define IT87_INIT_IN_PERCENTAGE 10
#define IT87_INIT_IN_MIN_0 \
(IT87_INIT_IN_0 - IT87_INIT_IN_0 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MAX_0 \
(IT87_INIT_IN_0 + IT87_INIT_IN_0 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MIN_1 \
(IT87_INIT_IN_1 - IT87_INIT_IN_1 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MAX_1 \
(IT87_INIT_IN_1 + IT87_INIT_IN_1 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MIN_2 \
(IT87_INIT_IN_2 - IT87_INIT_IN_2 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MAX_2 \
(IT87_INIT_IN_2 + IT87_INIT_IN_2 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MIN_3 \
(IT87_INIT_IN_3 - IT87_INIT_IN_3 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MAX_3 \
(IT87_INIT_IN_3 + IT87_INIT_IN_3 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MIN_4 \
(IT87_INIT_IN_4 - IT87_INIT_IN_4 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MAX_4 \
(IT87_INIT_IN_4 + IT87_INIT_IN_4 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MIN_5 \
(IT87_INIT_IN_5 - IT87_INIT_IN_5 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MAX_5 \
(IT87_INIT_IN_5 + IT87_INIT_IN_5 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MIN_6 \
(IT87_INIT_IN_6 - IT87_INIT_IN_6 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MAX_6 \
(IT87_INIT_IN_6 + IT87_INIT_IN_6 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MIN_7 \
(IT87_INIT_IN_7 - IT87_INIT_IN_7 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_IN_MAX_7 \
(IT87_INIT_IN_7 + IT87_INIT_IN_7 * IT87_INIT_IN_PERCENTAGE / 100)
#define IT87_INIT_FAN_MIN_1 3000
#define IT87_INIT_FAN_MIN_2 3000
#define IT87_INIT_FAN_MIN_3 3000
#define IT87_INIT_TEMP_HIGH_1 600
#define IT87_INIT_TEMP_LOW_1 200
#define IT87_INIT_TEMP_HIGH_2 600
#define IT87_INIT_TEMP_LOW_2 200
#define IT87_INIT_TEMP_HIGH_3 600
#define IT87_INIT_TEMP_LOW_3 200
/* For each registered IT87, we need to keep some data in memory. That
data is pointed to by it87_list[NR]->data. The structure itself is
......@@ -225,13 +163,13 @@ static int it87_detach_client(struct i2c_client *client);
static int it87_read_value(struct i2c_client *client, u8 register);
static int it87_write_value(struct i2c_client *client, u8 register,
u8 value);
static void it87_update_client(struct i2c_client *client);
static struct it87_data *it87_update_device(struct device *dev);
static void it87_init_client(struct i2c_client *client, struct it87_data *data);
static struct i2c_driver it87_driver = {
.owner = THIS_MODULE,
.name = "IT87xx",
.name = "it87",
.id = I2C_DRIVERID_IT87,
.flags = I2C_DF_NOTIFY,
.attach_adapter = it87_attach_adapter,
......@@ -242,25 +180,19 @@ static int it87_id = 0;
static ssize_t show_in(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])*10 );
}
static ssize_t show_in_min(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])*10 );
}
static ssize_t show_in_max(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])*10 );
}
......@@ -293,7 +225,7 @@ static ssize_t \
{ \
return show_in(dev, buf, 0x##offset); \
} \
static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in##offset, NULL)
static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL)
#define limit_in_offset(offset) \
static ssize_t \
......@@ -316,9 +248,9 @@ static ssize_t set_in##offset##_max (struct device *dev, \
{ \
return set_in_max(dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
show_in##offset##_min, set_in##offset##_min) \
static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
show_in##offset##_max, set_in##offset##_max)
show_in_offset(0);
......@@ -342,23 +274,17 @@ show_in_offset(8);
/* 3 temperatures */
static ssize_t show_temp(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*100 );
}
static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*100);
}
static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])*100);
}
static ssize_t set_temp_max(struct device *dev, const char *buf,
......@@ -406,10 +332,10 @@ static ssize_t set_temp_##offset##_min (struct device *dev, \
{ \
return set_temp_min(dev, buf, count, 0x##offset - 1); \
} \
static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_temp_##offset, NULL) \
static DEVICE_ATTR(temp_max##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL) \
static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
show_temp_##offset##_max, set_temp_##offset##_max) \
static DEVICE_ATTR(temp_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
show_temp_##offset##_min, set_temp_##offset##_min)
show_temp_offset(1);
......@@ -418,14 +344,12 @@ show_temp_offset(3);
static ssize_t show_sensor(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
if (data->sensor & (1 << nr))
return sprintf(buf, "1\n");
return sprintf(buf, "3\n"); /* thermal diode */
if (data->sensor & (8 << nr))
return sprintf(buf, "2\n");
return sprintf(buf, "0\n");
return sprintf(buf, "2\n"); /* thermistor */
return sprintf(buf, "0\n"); /* disabled */
}
static ssize_t set_sensor(struct device *dev, const char *buf,
size_t count, int nr)
......@@ -436,10 +360,13 @@ static ssize_t set_sensor(struct device *dev, const char *buf,
data->sensor &= ~(1 << nr);
data->sensor &= ~(8 << nr);
if (val == 1)
/* 3 = thermal diode; 2 = thermistor; 0 = disabled */
if (val == 3)
data->sensor |= 1 << nr;
else if (val == 2)
data->sensor |= 8 << nr;
else if (val != 0)
return -1;
it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor);
return count;
}
......@@ -453,7 +380,7 @@ static ssize_t set_sensor_##offset (struct device *dev, \
{ \
return set_sensor(dev, buf, count, 0x##offset - 1); \
} \
static DEVICE_ATTR(sensor##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
show_sensor_##offset, set_sensor_##offset)
show_sensor_offset(1);
......@@ -463,25 +390,19 @@ show_sensor_offset(3);
/* 3 Fans */
static ssize_t show_fan(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
DIV_FROM_REG(data->fan_div[nr])) );
}
static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
return sprintf(buf,"%d\n",
FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
}
static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
return sprintf(buf,"%d\n", DIV_FROM_REG(data->fan_div[nr]) );
}
static ssize_t set_fan_min(struct device *dev, const char *buf,
......@@ -554,10 +475,10 @@ static ssize_t set_fan_##offset##_div (struct device *dev, \
{ \
return set_fan_div(dev, buf, count, 0x##offset - 1); \
} \
static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_fan_##offset, NULL) \
static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
show_fan_##offset##_min, set_fan_##offset##_min) \
static DEVICE_ATTR(fan_div##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
show_fan_##offset##_div, set_fan_##offset##_div)
show_fan_offset(1);
......@@ -567,9 +488,7 @@ show_fan_offset(3);
/* Alarms */
static ssize_t show_alarms(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
struct it87_data *data = it87_update_device(dev);
return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));
}
static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL);
......@@ -681,12 +600,6 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind == it87) {
name = "it87";
} /* else if (kind == it8712) {
name = "it8712";
} */ else {
dev_dbg(&adapter->dev, "Internal error: unknown kind (%d)?!?",
kind);
goto ERROR1;
}
/* Fill in the remaining client fields and put it into the global list */
......@@ -706,52 +619,52 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
it87_init_client(new_client, data);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_in_input0);
device_create_file(&new_client->dev, &dev_attr_in_input1);
device_create_file(&new_client->dev, &dev_attr_in_input2);
device_create_file(&new_client->dev, &dev_attr_in_input3);
device_create_file(&new_client->dev, &dev_attr_in_input4);
device_create_file(&new_client->dev, &dev_attr_in_input5);
device_create_file(&new_client->dev, &dev_attr_in_input6);
device_create_file(&new_client->dev, &dev_attr_in_input7);
device_create_file(&new_client->dev, &dev_attr_in_input8);
device_create_file(&new_client->dev, &dev_attr_in_min0);
device_create_file(&new_client->dev, &dev_attr_in_min1);
device_create_file(&new_client->dev, &dev_attr_in_min2);
device_create_file(&new_client->dev, &dev_attr_in_min3);
device_create_file(&new_client->dev, &dev_attr_in_min4);
device_create_file(&new_client->dev, &dev_attr_in_min5);
device_create_file(&new_client->dev, &dev_attr_in_min6);
device_create_file(&new_client->dev, &dev_attr_in_min7);
device_create_file(&new_client->dev, &dev_attr_in_max0);
device_create_file(&new_client->dev, &dev_attr_in_max1);
device_create_file(&new_client->dev, &dev_attr_in_max2);
device_create_file(&new_client->dev, &dev_attr_in_max3);
device_create_file(&new_client->dev, &dev_attr_in_max4);
device_create_file(&new_client->dev, &dev_attr_in_max5);
device_create_file(&new_client->dev, &dev_attr_in_max6);
device_create_file(&new_client->dev, &dev_attr_in_max7);
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_input2);
device_create_file(&new_client->dev, &dev_attr_temp_input3);
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_max2);
device_create_file(&new_client->dev, &dev_attr_temp_max3);
device_create_file(&new_client->dev, &dev_attr_temp_min1);
device_create_file(&new_client->dev, &dev_attr_temp_min2);
device_create_file(&new_client->dev, &dev_attr_temp_min3);
device_create_file(&new_client->dev, &dev_attr_sensor1);
device_create_file(&new_client->dev, &dev_attr_sensor2);
device_create_file(&new_client->dev, &dev_attr_sensor3);
device_create_file(&new_client->dev, &dev_attr_fan_input1);
device_create_file(&new_client->dev, &dev_attr_fan_input2);
device_create_file(&new_client->dev, &dev_attr_fan_input3);
device_create_file(&new_client->dev, &dev_attr_fan_min1);
device_create_file(&new_client->dev, &dev_attr_fan_min2);
device_create_file(&new_client->dev, &dev_attr_fan_min3);
device_create_file(&new_client->dev, &dev_attr_fan_div1);
device_create_file(&new_client->dev, &dev_attr_fan_div2);
device_create_file(&new_client->dev, &dev_attr_fan_div3);
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
device_create_file(&new_client->dev, &dev_attr_in3_input);
device_create_file(&new_client->dev, &dev_attr_in4_input);
device_create_file(&new_client->dev, &dev_attr_in5_input);
device_create_file(&new_client->dev, &dev_attr_in6_input);
device_create_file(&new_client->dev, &dev_attr_in7_input);
device_create_file(&new_client->dev, &dev_attr_in8_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in2_min);
device_create_file(&new_client->dev, &dev_attr_in3_min);
device_create_file(&new_client->dev, &dev_attr_in4_min);
device_create_file(&new_client->dev, &dev_attr_in5_min);
device_create_file(&new_client->dev, &dev_attr_in6_min);
device_create_file(&new_client->dev, &dev_attr_in7_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
device_create_file(&new_client->dev, &dev_attr_in1_max);
device_create_file(&new_client->dev, &dev_attr_in2_max);
device_create_file(&new_client->dev, &dev_attr_in3_max);
device_create_file(&new_client->dev, &dev_attr_in4_max);
device_create_file(&new_client->dev, &dev_attr_in5_max);
device_create_file(&new_client->dev, &dev_attr_in6_max);
device_create_file(&new_client->dev, &dev_attr_in7_max);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_temp3_input);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp2_max);
device_create_file(&new_client->dev, &dev_attr_temp3_max);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
device_create_file(&new_client->dev, &dev_attr_temp2_min);
device_create_file(&new_client->dev, &dev_attr_temp3_min);
device_create_file(&new_client->dev, &dev_attr_temp1_type);
device_create_file(&new_client->dev, &dev_attr_temp2_type);
device_create_file(&new_client->dev, &dev_attr_temp3_type);
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan2_input);
device_create_file(&new_client->dev, &dev_attr_fan3_input);
device_create_file(&new_client->dev, &dev_attr_fan1_min);
device_create_file(&new_client->dev, &dev_attr_fan2_min);
device_create_file(&new_client->dev, &dev_attr_fan3_min);
device_create_file(&new_client->dev, &dev_attr_fan1_div);
device_create_file(&new_client->dev, &dev_attr_fan2_div);
device_create_file(&new_client->dev, &dev_attr_fan3_div);
device_create_file(&new_client->dev, &dev_attr_alarms);
return 0;
......@@ -825,85 +738,50 @@ static int it87_write_value(struct i2c_client *client, u8 reg, u8 value)
return i2c_smbus_write_byte_data(client, reg, value);
}
/* Called when we have found a new IT87. It should set limits, etc. */
/* Called when we have found a new IT87. */
static void it87_init_client(struct i2c_client *client, struct it87_data *data)
{
int tmp;
if (reset) {
/* Reset all except Watchdog values and last conversion values
This sets fan-divs to 2, among others */
it87_write_value(client, IT87_REG_CONFIG, 0x80);
it87_write_value(client, IT87_REG_VIN_MIN(0),
IN_TO_REG(IT87_INIT_IN_MIN_0));
it87_write_value(client, IT87_REG_VIN_MAX(0),
IN_TO_REG(IT87_INIT_IN_MAX_0));
it87_write_value(client, IT87_REG_VIN_MIN(1),
IN_TO_REG(IT87_INIT_IN_MIN_1));
it87_write_value(client, IT87_REG_VIN_MAX(1),
IN_TO_REG(IT87_INIT_IN_MAX_1));
it87_write_value(client, IT87_REG_VIN_MIN(2),
IN_TO_REG(IT87_INIT_IN_MIN_2));
it87_write_value(client, IT87_REG_VIN_MAX(2),
IN_TO_REG(IT87_INIT_IN_MAX_2));
it87_write_value(client, IT87_REG_VIN_MIN(3),
IN_TO_REG(IT87_INIT_IN_MIN_3));
it87_write_value(client, IT87_REG_VIN_MAX(3),
IN_TO_REG(IT87_INIT_IN_MAX_3));
it87_write_value(client, IT87_REG_VIN_MIN(4),
IN_TO_REG(IT87_INIT_IN_MIN_4));
it87_write_value(client, IT87_REG_VIN_MAX(4),
IN_TO_REG(IT87_INIT_IN_MAX_4));
it87_write_value(client, IT87_REG_VIN_MIN(5),
IN_TO_REG(IT87_INIT_IN_MIN_5));
it87_write_value(client, IT87_REG_VIN_MAX(5),
IN_TO_REG(IT87_INIT_IN_MAX_5));
it87_write_value(client, IT87_REG_VIN_MIN(6),
IN_TO_REG(IT87_INIT_IN_MIN_6));
it87_write_value(client, IT87_REG_VIN_MAX(6),
IN_TO_REG(IT87_INIT_IN_MAX_6));
it87_write_value(client, IT87_REG_VIN_MIN(7),
IN_TO_REG(IT87_INIT_IN_MIN_7));
it87_write_value(client, IT87_REG_VIN_MAX(7),
IN_TO_REG(IT87_INIT_IN_MAX_7));
/* Note: Battery voltage does not have limit registers */
it87_write_value(client, IT87_REG_FAN_MIN(0),
FAN_TO_REG(IT87_INIT_FAN_MIN_1, 2));
it87_write_value(client, IT87_REG_FAN_MIN(1),
FAN_TO_REG(IT87_INIT_FAN_MIN_2, 2));
it87_write_value(client, IT87_REG_FAN_MIN(2),
FAN_TO_REG(IT87_INIT_FAN_MIN_3, 2));
it87_write_value(client, IT87_REG_TEMP_HIGH(0),
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_1));
it87_write_value(client, IT87_REG_TEMP_LOW(0),
TEMP_TO_REG(IT87_INIT_TEMP_LOW_1));
it87_write_value(client, IT87_REG_TEMP_HIGH(1),
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_2));
it87_write_value(client, IT87_REG_TEMP_LOW(1),
TEMP_TO_REG(IT87_INIT_TEMP_LOW_2));
it87_write_value(client, IT87_REG_TEMP_HIGH(2),
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_3));
it87_write_value(client, IT87_REG_TEMP_LOW(2),
TEMP_TO_REG(IT87_INIT_TEMP_LOW_3));
/* Enable voltage monitors */
it87_write_value(client, IT87_REG_VIN_ENABLE, 0xff);
}
/* Enable Temp1-Temp3 */
data->sensor = (it87_read_value(client, IT87_REG_TEMP_ENABLE) & 0xc0);
data->sensor |= temp_type & 0x3f;
it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor);
/* Check if temperature channnels are reset manually or by some reason */
tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE);
if ((tmp & 0x3f) == 0) {
/* Temp1,Temp3=thermistor; Temp2=thermal diode */
tmp = (tmp & 0xc0) | 0x2a;
it87_write_value(client, IT87_REG_TEMP_ENABLE, tmp);
}
data->sensor = tmp;
/* Enable fans */
it87_write_value(client, IT87_REG_FAN_CTRL,
(it87_read_value(client, IT87_REG_FAN_CTRL) & 0x8f)
| 0x70);
/* Check if voltage monitors are reset manually or by some reason */
tmp = it87_read_value(client, IT87_REG_VIN_ENABLE);
if ((tmp & 0xff) == 0) {
/* Enable all voltage monitors */
it87_write_value(client, IT87_REG_VIN_ENABLE, 0xff);
}
/* Check if tachometers are reset manually or by some reason */
tmp = it87_read_value(client, IT87_REG_FAN_CTRL);
if ((tmp & 0x70) == 0) {
/* Enable all fan tachometers */
tmp = (tmp & 0x8f) | 0x70;
it87_write_value(client, IT87_REG_FAN_CTRL, tmp);
}
/* Start monitoring */
it87_write_value(client, IT87_REG_CONFIG,
(it87_read_value(client, IT87_REG_CONFIG) & 0xb7)
(it87_read_value(client, IT87_REG_CONFIG) & 0x36)
| (update_vbat ? 0x41 : 0x01));
}
static void it87_update_client(struct i2c_client *client)
static struct it87_data *it87_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int i;
......@@ -949,13 +827,7 @@ static void it87_update_client(struct i2c_client *client)
}
/* The 8705 does not have VID capability */
/*if (data->type == it8712) {
data->vid = it87_read_value(client, IT87_REG_VID);
data->vid &= 0x1f;
}
else */ {
data->vid = 0x1f;
}
i = it87_read_value(client, IT87_REG_FAN_DIV);
data->fan_div[0] = i & 0x07;
......@@ -967,11 +839,15 @@ static void it87_update_client(struct i2c_client *client)
(it87_read_value(client, IT87_REG_ALARM2) << 8) |
(it87_read_value(client, IT87_REG_ALARM3) << 16);
data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE);
data->last_updated = jiffies;
data->valid = 1;
}
up(&data->update_lock);
return data;
}
static int __init sm_it87_init(void)
......@@ -989,8 +865,8 @@ MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>");
MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver");
MODULE_PARM(update_vbat, "i");
MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
MODULE_PARM(temp_type, "i");
MODULE_PARM_DESC(temp_type, "Temperature sensor type, normally leave unset");
MODULE_PARM(reset, "i");
MODULE_PARM_DESC(reset, "Reset the chip's registers, default no");
MODULE_LICENSE("GPL");
module_init(sm_it87_init);
......
......@@ -19,10 +19,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -64,7 +60,7 @@ static void lm75_init_client(struct i2c_client *client);
static int lm75_detach_client(struct i2c_client *client);
static int lm75_read_value(struct i2c_client *client, u8 reg);
static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value);
static void lm75_update_client(struct i2c_client *client);
static struct lm75_data *lm75_update_device(struct device *dev);
/* This is the driver that will be inserted */
......@@ -82,9 +78,7 @@ static int lm75_id = 0;
#define show(value) \
static ssize_t show_##value(struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm75_data *data = i2c_get_clientdata(client); \
lm75_update_client(client); \
struct lm75_data *data = lm75_update_device(dev); \
return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value)); \
}
show(temp_max);
......@@ -104,9 +98,9 @@ static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \
set(temp_max, LM75_REG_TEMP_OS);
set(temp_hyst, LM75_REG_TEMP_HYST);
static DEVICE_ATTR(temp_max1, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
static DEVICE_ATTR(temp_hyst1, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input, NULL);
static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL);
static int lm75_attach_adapter(struct i2c_adapter *adapter)
{
......@@ -122,7 +116,7 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
struct i2c_client *new_client;
struct lm75_data *data;
int err = 0;
const char *name;
const char *name = "";
/* Make sure we aren't probing the ISA bus!! This is just a safety check
at this moment; i2c_detect really won't call us. */
......@@ -176,10 +170,6 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind == lm75) {
name = "lm75";
} else {
dev_dbg(&adapter->dev, "Internal error: unknown kind (%d)?!?",
kind);
goto exit_free;
}
/* Fill in the remaining client fields and put it into the global list */
......@@ -197,9 +187,9 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
lm75_init_client(new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_hyst1);
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
return 0;
......@@ -250,8 +240,9 @@ static void lm75_init_client(struct i2c_client *client)
lm75_write_value(client, LM75_REG_CONF, 0);
}
static void lm75_update_client(struct i2c_client *client)
static struct lm75_data *lm75_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm75_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
......@@ -268,6 +259,8 @@ static void lm75_update_client(struct i2c_client *client)
}
up(&data->update_lock);
return data;
}
static int __init sensors_lm75_init(void)
......
......@@ -19,10 +19,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -223,7 +219,7 @@ static int lm78_detach_client(struct i2c_client *client);
static int lm78_read_value(struct i2c_client *client, u8 register);
static int lm78_write_value(struct i2c_client *client, u8 register, u8 value);
static void lm78_update_client(struct i2c_client *client);
static struct lm78_data *lm78_update_device(struct device *dev);
static void lm78_init_client(struct i2c_client *client);
......@@ -239,25 +235,19 @@ static struct i2c_driver lm78_driver = {
/* 7 Voltages */
static ssize_t show_in(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
}
static ssize_t show_in_min(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
}
static ssize_t show_in_max(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
}
......@@ -289,7 +279,7 @@ static ssize_t \
{ \
return show_in(dev, buf, 0x##offset); \
} \
static DEVICE_ATTR(in_input##offset, S_IRUGO, \
static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
show_in##offset, NULL) \
static ssize_t \
show_in##offset##_min (struct device *dev, char *buf) \
......@@ -311,9 +301,9 @@ static ssize_t set_in##offset##_max (struct device *dev, \
{ \
return set_in_max(dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
show_in##offset##_min, set_in##offset##_min) \
static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
show_in##offset##_max, set_in##offset##_max)
show_in_offset(0);
......@@ -327,17 +317,13 @@ show_in_offset(6);
/* Temperature */
static ssize_t show_temp(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
}
static ssize_t show_temp_over(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
}
......@@ -353,9 +339,7 @@ static ssize_t set_temp_over(struct device *dev, const char *buf, size_t count)
static ssize_t show_temp_hyst(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
}
......@@ -369,27 +353,23 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count)
return count;
}
static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp, NULL)
static DEVICE_ATTR(temp_max1, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL)
static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
show_temp_over, set_temp_over)
static DEVICE_ATTR(temp_hyst1, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
show_temp_hyst, set_temp_hyst)
/* 3 Fans */
static ssize_t show_fan(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
DIV_FROM_REG(data->fan_div[nr])) );
}
static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
DIV_FROM_REG(data->fan_div[nr])) );
}
......@@ -407,9 +387,7 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
}
......@@ -460,8 +438,8 @@ static ssize_t set_fan_##offset##_min (struct device *dev, \
{ \
return set_fan_min(dev, buf, count, 0x##offset - 1); \
} \
static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_fan_##offset, NULL) \
static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
show_fan_##offset##_min, set_fan_##offset##_min)
static ssize_t set_fan_1_div(struct device *dev, const char *buf,
......@@ -481,28 +459,24 @@ show_fan_offset(2);
show_fan_offset(3);
/* Fan 3 divisor is locked in H/W */
static DEVICE_ATTR(fan_div1, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
show_fan_1_div, set_fan_1_div)
static DEVICE_ATTR(fan_div2, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
show_fan_2_div, set_fan_2_div)
static DEVICE_ATTR(fan_div3, S_IRUGO, show_fan_3_div, NULL)
static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL)
/* VID */
static ssize_t show_vid(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
}
static DEVICE_ATTR(vid, S_IRUGO, show_vid, NULL);
static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL);
/* Alarms */
static ssize_t show_alarms(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
lm78_update_client(client);
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
......@@ -635,11 +609,6 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
client_name = "lm78-j";
} else if (kind == lm79) {
client_name = "lm79";
} else {
dev_dbg(&adapter->dev, "Internal error: unknown kind (%d)?!?",
kind);
err = -ENODEV;
goto ERROR2;
}
/* Fill in the remaining client fields and put into the global list */
......@@ -657,41 +626,41 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
lm78_init_client(new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_in_input0);
device_create_file(&new_client->dev, &dev_attr_in_min0);
device_create_file(&new_client->dev, &dev_attr_in_max0);
device_create_file(&new_client->dev, &dev_attr_in_input1);
device_create_file(&new_client->dev, &dev_attr_in_min1);
device_create_file(&new_client->dev, &dev_attr_in_max1);
device_create_file(&new_client->dev, &dev_attr_in_input2);
device_create_file(&new_client->dev, &dev_attr_in_min2);
device_create_file(&new_client->dev, &dev_attr_in_max2);
device_create_file(&new_client->dev, &dev_attr_in_input3);
device_create_file(&new_client->dev, &dev_attr_in_min3);
device_create_file(&new_client->dev, &dev_attr_in_max3);
device_create_file(&new_client->dev, &dev_attr_in_input4);
device_create_file(&new_client->dev, &dev_attr_in_min4);
device_create_file(&new_client->dev, &dev_attr_in_max4);
device_create_file(&new_client->dev, &dev_attr_in_input5);
device_create_file(&new_client->dev, &dev_attr_in_min5);
device_create_file(&new_client->dev, &dev_attr_in_max5);
device_create_file(&new_client->dev, &dev_attr_in_input6);
device_create_file(&new_client->dev, &dev_attr_in_min6);
device_create_file(&new_client->dev, &dev_attr_in_max6);
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_hyst1);
device_create_file(&new_client->dev, &dev_attr_fan_input1);
device_create_file(&new_client->dev, &dev_attr_fan_min1);
device_create_file(&new_client->dev, &dev_attr_fan_div1);
device_create_file(&new_client->dev, &dev_attr_fan_input2);
device_create_file(&new_client->dev, &dev_attr_fan_min2);
device_create_file(&new_client->dev, &dev_attr_fan_div2);
device_create_file(&new_client->dev, &dev_attr_fan_input3);
device_create_file(&new_client->dev, &dev_attr_fan_min3);
device_create_file(&new_client->dev, &dev_attr_fan_div3);
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in1_max);
device_create_file(&new_client->dev, &dev_attr_in2_input);
device_create_file(&new_client->dev, &dev_attr_in2_min);
device_create_file(&new_client->dev, &dev_attr_in2_max);
device_create_file(&new_client->dev, &dev_attr_in3_input);
device_create_file(&new_client->dev, &dev_attr_in3_min);
device_create_file(&new_client->dev, &dev_attr_in3_max);
device_create_file(&new_client->dev, &dev_attr_in4_input);
device_create_file(&new_client->dev, &dev_attr_in4_min);
device_create_file(&new_client->dev, &dev_attr_in4_max);
device_create_file(&new_client->dev, &dev_attr_in5_input);
device_create_file(&new_client->dev, &dev_attr_in5_min);
device_create_file(&new_client->dev, &dev_attr_in5_max);
device_create_file(&new_client->dev, &dev_attr_in6_input);
device_create_file(&new_client->dev, &dev_attr_in6_min);
device_create_file(&new_client->dev, &dev_attr_in6_max);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan1_min);
device_create_file(&new_client->dev, &dev_attr_fan1_div);
device_create_file(&new_client->dev, &dev_attr_fan2_input);
device_create_file(&new_client->dev, &dev_attr_fan2_min);
device_create_file(&new_client->dev, &dev_attr_fan2_div);
device_create_file(&new_client->dev, &dev_attr_fan3_input);
device_create_file(&new_client->dev, &dev_attr_fan3_min);
device_create_file(&new_client->dev, &dev_attr_fan3_div);
device_create_file(&new_client->dev, &dev_attr_alarms);
device_create_file(&new_client->dev, &dev_attr_vid);
device_create_file(&new_client->dev, &dev_attr_in0_ref);
return 0;
......@@ -829,8 +798,9 @@ static void lm78_init_client(struct i2c_client *client)
}
static void lm78_update_client(struct i2c_client *client)
static struct lm78_data *lm78_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
int i;
......@@ -879,6 +849,8 @@ static void lm78_update_client(struct i2c_client *client)
}
up(&data->update_lock);
return data;
}
static int __init sm_lm78_init(void)
......
/*
* lm80.c - From lm_sensors, Linux kernel modules for hardware
* monitoring
* Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
* and Philip Edelbrock <phil@netroedge.com>
*
* Ported to Linux 2.6 by Tiago Sousa <mirage@kaotik.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { 0x28, 0x2f, I2C_CLIENT_END };
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
SENSORS_INSMOD_1(lm80);
/* Many LM80 constants specified below */
/* The LM80 registers */
#define LM80_REG_IN_MAX(nr) (0x2a + (nr) * 2)
#define LM80_REG_IN_MIN(nr) (0x2b + (nr) * 2)
#define LM80_REG_IN(nr) (0x20 + (nr))
#define LM80_REG_FAN1_MIN 0x3c
#define LM80_REG_FAN2_MIN 0x3d
#define LM80_REG_FAN1 0x28
#define LM80_REG_FAN2 0x29
#define LM80_REG_TEMP 0x27
#define LM80_REG_TEMP_HOT_MAX 0x38
#define LM80_REG_TEMP_HOT_HYST 0x39
#define LM80_REG_TEMP_OS_MAX 0x3a
#define LM80_REG_TEMP_OS_HYST 0x3b
#define LM80_REG_CONFIG 0x00
#define LM80_REG_ALARM1 0x01
#define LM80_REG_ALARM2 0x02
#define LM80_REG_MASK1 0x03
#define LM80_REG_MASK2 0x04
#define LM80_REG_FANDIV 0x05
#define LM80_REG_RES 0x06
/* Conversions. Rounding and limit checking is only done on the TO_REG
variants. Note that you should be a bit careful with which arguments
these macros are called: arguments may be evaluated more than once.
Fixing this is just not worth it. */
#define IN_TO_REG(val) (SENSORS_LIMIT((val)/10,0,255))
#define IN_FROM_REG(val) ((val)*10)
static inline unsigned char FAN_TO_REG(unsigned rpm, unsigned div)
{
if (rpm == 0)
return 255;
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
return SENSORS_LIMIT((1350000 + rpm*div / 2) / (rpm*div), 1, 254);
}
#define FAN_FROM_REG(val,div) ((val)==0?-1:\
(val)==255?0:1350000/((div)*(val)))
static inline long TEMP_FROM_REG(u16 temp)
{
long res;
temp >>= 4;
if (temp < 0x0800)
res = 625 * (long) temp;
else
res = ((long) temp - 0x01000) * 625;
return res / 10;
}
#define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000)
#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT((val)<0?\
((val)-500)/1000:((val)+500)/1000,0,255)
#define ALARMS_FROM_REG(val) (val)
#define DIV_FROM_REG(val) (1 << (val))
#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
/*
* Client data (each client gets its own)
*/
struct lm80_data {
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
u8 in[7]; /* Register value */
u8 in_max[7]; /* Register value */
u8 in_min[7]; /* Register value */
u8 fan[2]; /* Register value */
u8 fan_min[2]; /* Register value */
u8 fan_div[2]; /* Register encoding, shifted right */
u16 temp; /* Register values, shifted right */
u8 temp_hot_max; /* Register value */
u8 temp_hot_hyst; /* Register value */
u8 temp_os_max; /* Register value */
u8 temp_os_hyst; /* Register value */
u16 alarms; /* Register encoding, combined */
};
/*
* Functions declaration
*/
static int lm80_attach_adapter(struct i2c_adapter *adapter);
static int lm80_detect(struct i2c_adapter *adapter, int address, int kind);
static void lm80_init_client(struct i2c_client *client);
static int lm80_detach_client(struct i2c_client *client);
static struct lm80_data *lm80_update_device(struct device *dev);
static int lm80_read_value(struct i2c_client *client, u8 reg);
static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
/*
* Internal variables
*/
static int lm80_id = 0;
/*
* Driver data (common to all clients)
*/
static struct i2c_driver lm80_driver = {
.owner = THIS_MODULE,
.name = "lm80",
.id = I2C_DRIVERID_LM80,
.flags = I2C_DF_NOTIFY,
.attach_adapter = lm80_attach_adapter,
.detach_client = lm80_detach_client,
};
/*
* Sysfs stuff
*/
#define show_in(suffix, value) \
static ssize_t show_in_##suffix(struct device *dev, char *buf) \
{ \
struct lm80_data *data = lm80_update_device(dev); \
return sprintf(buf, "%d\n", IN_FROM_REG(data->value)); \
}
show_in(min0, in_min[0]);
show_in(min1, in_min[1]);
show_in(min2, in_min[2]);
show_in(min3, in_min[3]);
show_in(min4, in_min[4]);
show_in(min5, in_min[5]);
show_in(min6, in_min[6]);
show_in(max0, in_max[0]);
show_in(max1, in_max[1]);
show_in(max2, in_max[2]);
show_in(max3, in_max[3]);
show_in(max4, in_max[4]);
show_in(max5, in_max[5]);
show_in(max6, in_max[6]);
show_in(input0, in[0]);
show_in(input1, in[1]);
show_in(input2, in[2]);
show_in(input3, in[3]);
show_in(input4, in[4]);
show_in(input5, in[5]);
show_in(input6, in[6]);
#define set_in(suffix, value, reg) \
static ssize_t set_in_##suffix(struct device *dev, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm80_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \
data->value = IN_TO_REG(val); \
lm80_write_value(client, reg, data->value); \
return count; \
}
set_in(min0, in_min[0], LM80_REG_IN_MIN(0));
set_in(min1, in_min[1], LM80_REG_IN_MIN(1));
set_in(min2, in_min[2], LM80_REG_IN_MIN(2));
set_in(min3, in_min[3], LM80_REG_IN_MIN(3));
set_in(min4, in_min[4], LM80_REG_IN_MIN(4));
set_in(min5, in_min[5], LM80_REG_IN_MIN(5));
set_in(min6, in_min[6], LM80_REG_IN_MIN(6));
set_in(max0, in_max[0], LM80_REG_IN_MAX(0));
set_in(max1, in_max[1], LM80_REG_IN_MAX(1));
set_in(max2, in_max[2], LM80_REG_IN_MAX(2));
set_in(max3, in_max[3], LM80_REG_IN_MAX(3));
set_in(max4, in_max[4], LM80_REG_IN_MAX(4));
set_in(max5, in_max[5], LM80_REG_IN_MAX(5));
set_in(max6, in_max[6], LM80_REG_IN_MAX(6));
#define show_fan(suffix, value, div) \
static ssize_t show_fan_##suffix(struct device *dev, char *buf) \
{ \
struct lm80_data *data = lm80_update_device(dev); \
return sprintf(buf, "%d\n", FAN_FROM_REG(data->value, \
DIV_FROM_REG(data->div))); \
}
show_fan(min1, fan_min[0], fan_div[0]);
show_fan(min2, fan_min[1], fan_div[1]);
show_fan(input1, fan[0], fan_div[0]);
show_fan(input2, fan[1], fan_div[1]);
#define show_fan_div(suffix, value) \
static ssize_t show_fan_div##suffix(struct device *dev, char *buf) \
{ \
struct lm80_data *data = lm80_update_device(dev); \
return sprintf(buf, "%d\n", DIV_FROM_REG(data->value)); \
}
show_fan_div(1, fan_div[0]);
show_fan_div(2, fan_div[1]);
#define set_fan(suffix, value, reg, div) \
static ssize_t set_fan_##suffix(struct device *dev, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm80_data *data = i2c_get_clientdata(client); \
long val = simple_strtoul(buf, NULL, 10); \
data->value = FAN_TO_REG(val, DIV_FROM_REG(data->div)); \
lm80_write_value(client, reg, data->value); \
return count; \
}
set_fan(min1, fan_min[0], LM80_REG_FAN1_MIN, fan_div[0]);
set_fan(min2, fan_min[1], LM80_REG_FAN2_MIN, fan_div[1]);
static ssize_t show_temp_input1(struct device *dev, char *buf)
{
struct lm80_data *data = lm80_update_device(dev);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp));
}
#define show_temp(suffix, value) \
static ssize_t show_temp_##suffix(struct device *dev, char *buf) \
{ \
struct lm80_data *data = lm80_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \
}
show_temp(hot_max, temp_hot_max);
show_temp(hot_hyst, temp_hot_hyst);
show_temp(os_max, temp_os_max);
show_temp(os_hyst, temp_os_hyst);
#define set_temp(suffix, value, reg) \
static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm80_data *data = i2c_get_clientdata(client); \
long val = simple_strtoul(buf, NULL, 10); \
data->value = TEMP_LIMIT_TO_REG(val); \
lm80_write_value(client, reg, data->value); \
return count; \
}
set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX);
set_temp(hot_hyst, temp_hot_hyst, LM80_REG_TEMP_HOT_HYST);
set_temp(os_max, temp_os_max, LM80_REG_TEMP_OS_MAX);
set_temp(os_hyst, temp_os_hyst, LM80_REG_TEMP_OS_HYST);
static ssize_t show_alarms(struct device *dev, char *buf)
{
struct lm80_data *data = lm80_update_device(dev);
return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
}
static DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min0, set_in_min0);
static DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min1, set_in_min1);
static DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min2, set_in_min2);
static DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min3, set_in_min3);
static DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min4, set_in_min4);
static DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min5, set_in_min5);
static DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min6, set_in_min6);
static DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max0, set_in_max0);
static DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max1, set_in_max1);
static DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max2, set_in_max2);
static DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max3, set_in_max3);
static DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max4, set_in_max4);
static DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max5, set_in_max5);
static DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max6, set_in_max6);
static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL);
static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL);
static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL);
static DEVICE_ATTR(in3_input, S_IRUGO, show_in_input3, NULL);
static DEVICE_ATTR(in4_input, S_IRUGO, show_in_input4, NULL);
static DEVICE_ATTR(in5_input, S_IRUGO, show_in_input5, NULL);
static DEVICE_ATTR(in6_input, S_IRUGO, show_in_input6, NULL);
static DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min1,
set_fan_min1);
static DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min2,
set_fan_min2);
static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input1, NULL);
static DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input2, NULL);
static DEVICE_ATTR(fan1_div, S_IRUGO, show_fan_div1, NULL);
static DEVICE_ATTR(fan2_div, S_IRUGO, show_fan_div2, NULL);
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_hot_max,
set_temp_hot_max);
static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hot_hyst,
set_temp_hot_hyst);
static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_os_max,
set_temp_os_max);
static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_os_hyst,
set_temp_os_hyst);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/*
* Real code
*/
static int lm80_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
return 0;
return i2c_detect(adapter, &addr_data, lm80_detect);
}
int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i, cur;
struct i2c_client *new_client;
struct lm80_data *data;
int err = 0;
const char *name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access lm80_{read,write}_value. */
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
sizeof(struct lm80_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
memset(new_client, 0x00, sizeof(struct i2c_client) +
sizeof(struct lm80_data));
data = (struct lm80_data *) (new_client + 1);
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &lm80_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. It is lousy. */
if (lm80_read_value(new_client, LM80_REG_ALARM2) & 0xc0)
goto error_free;
for (i = 0x2a; i <= 0x3d; i++) {
cur = i2c_smbus_read_byte_data(new_client, i);
if ((i2c_smbus_read_byte_data(new_client, i + 0x40) != cur)
|| (i2c_smbus_read_byte_data(new_client, i + 0x80) != cur)
|| (i2c_smbus_read_byte_data(new_client, i + 0xc0) != cur))
goto error_free;
}
/* Determine the chip type - only one kind supported! */
kind = lm80;
name = "lm80";
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
new_client->id = lm80_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto error_free;
/* Initialize the LM80 chip */
lm80_init_client(new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in2_min);
device_create_file(&new_client->dev, &dev_attr_in3_min);
device_create_file(&new_client->dev, &dev_attr_in4_min);
device_create_file(&new_client->dev, &dev_attr_in5_min);
device_create_file(&new_client->dev, &dev_attr_in6_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
device_create_file(&new_client->dev, &dev_attr_in1_max);
device_create_file(&new_client->dev, &dev_attr_in2_max);
device_create_file(&new_client->dev, &dev_attr_in3_max);
device_create_file(&new_client->dev, &dev_attr_in4_max);
device_create_file(&new_client->dev, &dev_attr_in5_max);
device_create_file(&new_client->dev, &dev_attr_in6_max);
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
device_create_file(&new_client->dev, &dev_attr_in3_input);
device_create_file(&new_client->dev, &dev_attr_in4_input);
device_create_file(&new_client->dev, &dev_attr_in5_input);
device_create_file(&new_client->dev, &dev_attr_in6_input);
device_create_file(&new_client->dev, &dev_attr_fan1_min);
device_create_file(&new_client->dev, &dev_attr_fan2_min);
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan2_input);
device_create_file(&new_client->dev, &dev_attr_fan1_div);
device_create_file(&new_client->dev, &dev_attr_fan2_div);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
device_create_file(&new_client->dev, &dev_attr_temp1_crit);
device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
device_create_file(&new_client->dev, &dev_attr_alarms);
return 0;
error_free:
kfree(new_client);
exit:
return err;
}
static int lm80_detach_client(struct i2c_client *client)
{
int err;
if ((err = i2c_detach_client(client))) {
dev_err(&client->dev, "Client deregistration failed, "
"client not detached.\n");
return err;
}
kfree(client);
return 0;
}
static int lm80_read_value(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value)
{
return i2c_smbus_write_byte_data(client, reg, value);
}
/* Called when we have found a new LM80. */
static void lm80_init_client(struct i2c_client *client)
{
/* Reset all except Watchdog values and last conversion values
This sets fan-divs to 2, among others. This makes most other
initializations unnecessary */
lm80_write_value(client, LM80_REG_CONFIG, 0x80);
/* Set 11-bit temperature resolution */
lm80_write_value(client, LM80_REG_RES, 0x08);
/* Start monitoring */
lm80_write_value(client, LM80_REG_CONFIG, 0x01);
}
static struct lm80_data *lm80_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm80_data *data = i2c_get_clientdata(client);
int i;
down(&data->update_lock);
if ((jiffies - data->last_updated > 2 * HZ) ||
(jiffies < data->last_updated) || !data->valid) {
dev_dbg(&client->dev, "Starting lm80 update\n");
for (i = 0; i <= 6; i++) {
data->in[i] =
lm80_read_value(client, LM80_REG_IN(i));
data->in_min[i] =
lm80_read_value(client, LM80_REG_IN_MIN(i));
data->in_max[i] =
lm80_read_value(client, LM80_REG_IN_MAX(i));
}
data->fan[0] = lm80_read_value(client, LM80_REG_FAN1);
data->fan_min[0] =
lm80_read_value(client, LM80_REG_FAN1_MIN);
data->fan[1] = lm80_read_value(client, LM80_REG_FAN2);
data->fan_min[1] =
lm80_read_value(client, LM80_REG_FAN2_MIN);
data->temp =
(lm80_read_value(client, LM80_REG_TEMP) << 8) |
(lm80_read_value(client, LM80_REG_RES) & 0xf0);
data->temp_os_max =
lm80_read_value(client, LM80_REG_TEMP_OS_MAX);
data->temp_os_hyst =
lm80_read_value(client, LM80_REG_TEMP_OS_HYST);
data->temp_hot_max =
lm80_read_value(client, LM80_REG_TEMP_HOT_MAX);
data->temp_hot_hyst =
lm80_read_value(client, LM80_REG_TEMP_HOT_HYST);
i = lm80_read_value(client, LM80_REG_FANDIV);
data->fan_div[0] = (i >> 2) & 0x03;
data->fan_div[1] = (i >> 4) & 0x03;
data->alarms = lm80_read_value(client, LM80_REG_ALARM1) +
(lm80_read_value(client, LM80_REG_ALARM2) << 8);
data->last_updated = jiffies;
data->valid = 1;
}
up(&data->update_lock);
return data;
}
static int __init sensors_lm80_init(void)
{
return i2c_add_driver(&lm80_driver);
}
static void __exit sensors_lm80_exit(void)
{
i2c_del_driver(&lm80_driver);
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
"Philip Edelbrock <phil@netroedge.com>");
MODULE_DESCRIPTION("LM80 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm80_init);
module_exit(sensors_lm80_exit);
......@@ -28,10 +28,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -118,7 +114,7 @@ static const u8 LM83_REG_W_HIGH[] = {
static int lm83_attach_adapter(struct i2c_adapter *adapter);
static int lm83_detect(struct i2c_adapter *adapter, int address, int kind);
static int lm83_detach_client(struct i2c_client *client);
static void lm83_update_client(struct i2c_client *client);
static struct lm83_data *lm83_update_device(struct device *dev);
/*
* Driver data (common to all clients)
......@@ -162,9 +158,7 @@ static int lm83_id = 0;
#define show_temp(suffix, value) \
static ssize_t show_temp_##suffix(struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm83_data *data = i2c_get_clientdata(client); \
lm83_update_client(client); \
struct lm83_data *data = lm83_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
}
show_temp(input1, temp_input[0]);
......@@ -195,23 +189,21 @@ set_temp(crit, temp_crit, LM83_REG_W_TCRIT);
static ssize_t show_alarms(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm83_data *data = i2c_get_clientdata(client);
lm83_update_client(client);
struct lm83_data *data = lm83_update_device(dev);
return sprintf(buf, "%d\n", data->alarms);
}
static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input1, NULL);
static DEVICE_ATTR(temp_input2, S_IRUGO, show_temp_input2, NULL);
static DEVICE_ATTR(temp_input3, S_IRUGO, show_temp_input3, NULL);
static DEVICE_ATTR(temp_input4, S_IRUGO, show_temp_input4, NULL);
static DEVICE_ATTR(temp_max1, S_IWUSR | S_IRUGO, show_temp_high1,
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL);
static DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input3, NULL);
static DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input4, NULL);
static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_high1,
set_temp_high1);
static DEVICE_ATTR(temp_max2, S_IWUSR | S_IRUGO, show_temp_high2,
static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_high2,
set_temp_high2);
static DEVICE_ATTR(temp_max3, S_IWUSR | S_IRUGO, show_temp_high3,
static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_high3,
set_temp_high3);
static DEVICE_ATTR(temp_max4, S_IWUSR | S_IRUGO, show_temp_high4,
static DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_high4,
set_temp_high4);
static DEVICE_ATTR(temp_crit, S_IWUSR | S_IRUGO, show_temp_crit,
set_temp_crit);
......@@ -292,7 +284,6 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
if (man_id == 0x01) { /* National Semiconductor */
if (chip_id == 0x03) {
kind = lm83;
name = "lm83";
}
}
......@@ -304,6 +295,10 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
}
}
if (kind == lm83) {
name = "lm83";
}
/* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
new_client->id = lm83_id++;
......@@ -320,14 +315,14 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
*/
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_input2);
device_create_file(&new_client->dev, &dev_attr_temp_input3);
device_create_file(&new_client->dev, &dev_attr_temp_input4);
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_max2);
device_create_file(&new_client->dev, &dev_attr_temp_max3);
device_create_file(&new_client->dev, &dev_attr_temp_max4);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_temp3_input);
device_create_file(&new_client->dev, &dev_attr_temp4_input);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp2_max);
device_create_file(&new_client->dev, &dev_attr_temp3_max);
device_create_file(&new_client->dev, &dev_attr_temp4_max);
device_create_file(&new_client->dev, &dev_attr_temp_crit);
device_create_file(&new_client->dev, &dev_attr_alarms);
......@@ -353,8 +348,9 @@ static int lm83_detach_client(struct i2c_client *client)
return 0;
}
static void lm83_update_client(struct i2c_client *client)
static struct lm83_data *lm83_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm83_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
......@@ -385,6 +381,8 @@ static void lm83_update_client(struct i2c_client *client)
}
up(&data->update_lock);
return data;
}
static int __init sensors_lm83_init(void)
......
......@@ -23,10 +23,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -397,7 +393,7 @@ static int lm85_detach_client(struct i2c_client *client);
static int lm85_read_value(struct i2c_client *client, u8 register);
static int lm85_write_value(struct i2c_client *client, u8 register, int value);
static void lm85_update_client(struct i2c_client *client);
static struct lm85_data *lm85_update_device(struct device *dev);
static void lm85_init_client(struct i2c_client *client);
......@@ -417,18 +413,12 @@ static int lm85_id = 0;
/* 4 Fans */
static ssize_t show_fan(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr]) );
}
static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr]) );
}
static ssize_t set_fan_min(struct device *dev, const char *buf,
......@@ -460,8 +450,8 @@ static ssize_t set_fan_##offset##_min (struct device *dev, \
{ \
return set_fan_min(dev, buf, count, 0x##offset - 1); \
} \
static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_fan_##offset, NULL) \
static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
show_fan_##offset##_min, set_fan_##offset##_min)
show_fan_offset(1);
......@@ -473,21 +463,15 @@ show_fan_offset(4);
static ssize_t show_vid_reg(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
}
static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL)
static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL)
static ssize_t show_vrm_reg(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->vrm);
}
......@@ -506,10 +490,7 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg)
static ssize_t show_alarms_reg(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
}
......@@ -519,10 +500,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
static ssize_t show_pwm(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm[nr]) );
}
static ssize_t set_pwm(struct device *dev, const char *buf,
......@@ -541,11 +519,9 @@ static ssize_t set_pwm(struct device *dev, const char *buf,
}
static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
struct lm85_data *data = lm85_update_device(dev);
int pwm_zone;
lm85_update_client(client);
pwm_zone = ZONE_FROM_REG(data->autofan[nr].config);
return sprintf(buf,"%d\n", (pwm_zone != 0 && pwm_zone != -1) );
}
......@@ -564,9 +540,9 @@ static ssize_t show_pwm_enable##offset (struct device *dev, char *buf) \
{ \
return show_pwm_enable(dev, buf, 0x##offset - 1); \
} \
static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, \
show_pwm_##offset, set_pwm_##offset) \
static DEVICE_ATTR(pwm_enable##offset, S_IRUGO, show_pwm_enable##offset, NULL)
static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO, show_pwm_enable##offset, NULL)
show_pwm_reg(1);
show_pwm_reg(2);
......@@ -576,18 +552,12 @@ show_pwm_reg(3);
static ssize_t show_in(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]) );
}
static ssize_t show_in_min(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]) );
}
static ssize_t set_in_min(struct device *dev, const char *buf,
......@@ -606,10 +576,7 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
}
static ssize_t show_in_max(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]) );
}
static ssize_t set_in_max(struct device *dev, const char *buf,
......@@ -649,10 +616,10 @@ static ssize_t set_in_##offset##_max (struct device *dev, \
{ \
return set_in_max(dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in_##offset, NULL) \
static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in_##offset, NULL) \
static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
show_in_##offset##_min, set_in_##offset##_min) \
static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
show_in_##offset##_max, set_in_##offset##_max)
show_in_reg(0);
......@@ -665,18 +632,12 @@ show_in_reg(4);
static ssize_t show_temp(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]) );
}
static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]) );
}
static ssize_t set_temp_min(struct device *dev, const char *buf,
......@@ -695,10 +656,7 @@ static ssize_t set_temp_min(struct device *dev, const char *buf,
}
static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
lm85_update_client(client);
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]) );
}
static ssize_t set_temp_max(struct device *dev, const char *buf,
......@@ -738,10 +696,10 @@ static ssize_t set_temp_##offset##_max (struct device *dev, \
{ \
return set_temp_max(dev, buf, count, 0x##offset - 1); \
} \
static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_temp_##offset, NULL) \
static DEVICE_ATTR(temp_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL) \
static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
show_temp_##offset##_min, set_temp_##offset##_min) \
static DEVICE_ATTR(temp_max##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
show_temp_##offset##_max, set_temp_##offset##_max)
show_temp_reg(1);
......@@ -857,10 +815,6 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
type_name = "adm1027";
} else if ( kind == adt7463 ) {
type_name = "adt7463";
} else {
dev_dbg(&adapter->dev, "Internal error, invalid kind (%d)!", kind);
err = -EFAULT ;
goto ERROR1;
}
strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
......@@ -886,46 +840,46 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
lm85_init_client(new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_fan_input1);
device_create_file(&new_client->dev, &dev_attr_fan_input2);
device_create_file(&new_client->dev, &dev_attr_fan_input3);
device_create_file(&new_client->dev, &dev_attr_fan_input4);
device_create_file(&new_client->dev, &dev_attr_fan_min1);
device_create_file(&new_client->dev, &dev_attr_fan_min2);
device_create_file(&new_client->dev, &dev_attr_fan_min3);
device_create_file(&new_client->dev, &dev_attr_fan_min4);
device_create_file(&new_client->dev, &dev_attr_pwm1);
device_create_file(&new_client->dev, &dev_attr_pwm2);
device_create_file(&new_client->dev, &dev_attr_pwm3);
device_create_file(&new_client->dev, &dev_attr_pwm_enable1);
device_create_file(&new_client->dev, &dev_attr_pwm_enable2);
device_create_file(&new_client->dev, &dev_attr_pwm_enable3);
device_create_file(&new_client->dev, &dev_attr_in_input0);
device_create_file(&new_client->dev, &dev_attr_in_input1);
device_create_file(&new_client->dev, &dev_attr_in_input2);
device_create_file(&new_client->dev, &dev_attr_in_input3);
device_create_file(&new_client->dev, &dev_attr_in_input4);
device_create_file(&new_client->dev, &dev_attr_in_min0);
device_create_file(&new_client->dev, &dev_attr_in_min1);
device_create_file(&new_client->dev, &dev_attr_in_min2);
device_create_file(&new_client->dev, &dev_attr_in_min3);
device_create_file(&new_client->dev, &dev_attr_in_min4);
device_create_file(&new_client->dev, &dev_attr_in_max0);
device_create_file(&new_client->dev, &dev_attr_in_max1);
device_create_file(&new_client->dev, &dev_attr_in_max2);
device_create_file(&new_client->dev, &dev_attr_in_max3);
device_create_file(&new_client->dev, &dev_attr_in_max4);
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_input2);
device_create_file(&new_client->dev, &dev_attr_temp_input3);
device_create_file(&new_client->dev, &dev_attr_temp_min1);
device_create_file(&new_client->dev, &dev_attr_temp_min2);
device_create_file(&new_client->dev, &dev_attr_temp_min3);
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_max2);
device_create_file(&new_client->dev, &dev_attr_temp_max3);
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan2_input);
device_create_file(&new_client->dev, &dev_attr_fan3_input);
device_create_file(&new_client->dev, &dev_attr_fan4_input);
device_create_file(&new_client->dev, &dev_attr_fan1_min);
device_create_file(&new_client->dev, &dev_attr_fan2_min);
device_create_file(&new_client->dev, &dev_attr_fan3_min);
device_create_file(&new_client->dev, &dev_attr_fan4_min);
device_create_file(&new_client->dev, &dev_attr_fan1_pwm);
device_create_file(&new_client->dev, &dev_attr_fan2_pwm);
device_create_file(&new_client->dev, &dev_attr_fan3_pwm);
device_create_file(&new_client->dev, &dev_attr_fan1_pwm_enable);
device_create_file(&new_client->dev, &dev_attr_fan2_pwm_enable);
device_create_file(&new_client->dev, &dev_attr_fan3_pwm_enable);
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
device_create_file(&new_client->dev, &dev_attr_in3_input);
device_create_file(&new_client->dev, &dev_attr_in4_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in2_min);
device_create_file(&new_client->dev, &dev_attr_in3_min);
device_create_file(&new_client->dev, &dev_attr_in4_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
device_create_file(&new_client->dev, &dev_attr_in1_max);
device_create_file(&new_client->dev, &dev_attr_in2_max);
device_create_file(&new_client->dev, &dev_attr_in3_max);
device_create_file(&new_client->dev, &dev_attr_in4_max);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_temp3_input);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
device_create_file(&new_client->dev, &dev_attr_temp2_min);
device_create_file(&new_client->dev, &dev_attr_temp3_min);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp2_max);
device_create_file(&new_client->dev, &dev_attr_temp3_max);
device_create_file(&new_client->dev, &dev_attr_vrm);
device_create_file(&new_client->dev, &dev_attr_vid);
device_create_file(&new_client->dev, &dev_attr_in0_ref);
device_create_file(&new_client->dev, &dev_attr_alarms);
return 0;
......@@ -1047,8 +1001,9 @@ void lm85_init_client(struct i2c_client *client)
lm85_write_value(client, LM85_REG_CONFIG, value);
}
void lm85_update_client(struct i2c_client *client)
static struct lm85_data *lm85_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
int i;
......@@ -1189,6 +1144,8 @@ void lm85_update_client(struct i2c_client *client)
data->valid = 1;
up(&data->update_lock);
return data;
}
......
......@@ -36,10 +36,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -126,7 +122,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address,
int kind);
static void lm90_init_client(struct i2c_client *client);
static int lm90_detach_client(struct i2c_client *client);
static void lm90_update_client(struct i2c_client *client);
static struct lm90_data *lm90_update_device(struct device *dev);
/*
* Driver data (common to all clients)
......@@ -171,9 +167,7 @@ static int lm90_id = 0;
#define show_temp(value, converter) \
static ssize_t show_##value(struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm90_data *data = i2c_get_clientdata(client); \
lm90_update_client(client); \
struct lm90_data *data = lm90_update_device(dev); \
return sprintf(buf, "%d\n", converter(data->value)); \
}
show_temp(temp_input1, TEMP1_FROM_REG);
......@@ -216,9 +210,7 @@ set_temp1(temp_crit2, LM90_REG_W_REMOTE_CRIT);
#define show_temp_hyst(value, basereg) \
static ssize_t show_##value(struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm90_data *data = i2c_get_clientdata(client); \
lm90_update_client(client); \
struct lm90_data *data = lm90_update_device(dev); \
return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->basereg) \
- HYST_FROM_REG(data->temp_hyst)); \
}
......@@ -239,29 +231,27 @@ static ssize_t set_temp_hyst1(struct device *dev, const char *buf,
static ssize_t show_alarms(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm90_data *data = i2c_get_clientdata(client);
lm90_update_client(client);
struct lm90_data *data = lm90_update_device(dev);
return sprintf(buf, "%d\n", data->alarms);
}
static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input1, NULL);
static DEVICE_ATTR(temp_input2, S_IRUGO, show_temp_input2, NULL);
static DEVICE_ATTR(temp_min1, S_IWUSR | S_IRUGO, show_temp_low1,
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL);
static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_low1,
set_temp_low1);
static DEVICE_ATTR(temp_min2, S_IWUSR | S_IRUGO, show_temp_low2,
static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_low2,
set_temp_low2);
static DEVICE_ATTR(temp_max1, S_IWUSR | S_IRUGO, show_temp_high1,
static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_high1,
set_temp_high1);
static DEVICE_ATTR(temp_max2, S_IWUSR | S_IRUGO, show_temp_high2,
static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_high2,
set_temp_high2);
static DEVICE_ATTR(temp_crit1, S_IWUSR | S_IRUGO, show_temp_crit1,
static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit1,
set_temp_crit1);
static DEVICE_ATTR(temp_crit2, S_IWUSR | S_IRUGO, show_temp_crit2,
static DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit2,
set_temp_crit2);
static DEVICE_ATTR(temp_hyst1, S_IWUSR | S_IRUGO, show_temp_hyst1,
static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst1,
set_temp_hyst1);
static DEVICE_ATTR(temp_hyst2, S_IRUGO, show_temp_hyst2, NULL);
static DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_hyst2, NULL);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/*
......@@ -347,7 +337,6 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
LM90_REG_R_CONFIG2) & 0xF8) == 0x00
&& reg_convrate <= 0x09))) {
kind = lm90;
name = "lm90";
}
}
else if (man_id == 0x41) { /* Analog Devices */
......@@ -355,7 +344,6 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
&& (kind == 0 /* skip detection */
|| (reg_config1 & 0x3F) == 0x00)) {
kind = adm1032;
name = "adm1032";
}
}
......@@ -367,6 +355,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
}
}
if (kind == lm90) {
name = "lm90";
} else if (kind == adm1032) {
name = "adm1032";
}
/* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
new_client->id = lm90_id++;
......@@ -381,16 +375,16 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
lm90_init_client(new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_input2);
device_create_file(&new_client->dev, &dev_attr_temp_min1);
device_create_file(&new_client->dev, &dev_attr_temp_min2);
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_max2);
device_create_file(&new_client->dev, &dev_attr_temp_crit1);
device_create_file(&new_client->dev, &dev_attr_temp_crit2);
device_create_file(&new_client->dev, &dev_attr_temp_hyst1);
device_create_file(&new_client->dev, &dev_attr_temp_hyst2);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_temp1_min);
device_create_file(&new_client->dev, &dev_attr_temp2_min);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp2_max);
device_create_file(&new_client->dev, &dev_attr_temp1_crit);
device_create_file(&new_client->dev, &dev_attr_temp2_crit);
device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
device_create_file(&new_client->dev, &dev_attr_alarms);
return 0;
......@@ -430,8 +424,9 @@ static int lm90_detach_client(struct i2c_client *client)
return 0;
}
static void lm90_update_client(struct i2c_client *client)
static struct lm90_data *lm90_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm90_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
......@@ -505,6 +500,8 @@ static void lm90_update_client(struct i2c_client *client)
}
up(&data->update_lock);
return data;
}
static int __init sensors_lm90_init(void)
......
......@@ -32,10 +32,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
......@@ -409,30 +405,24 @@ static inline void via686a_write_value(struct i2c_client *client, u8 reg,
outb_p(value, client->addr + reg);
}
static void via686a_update_client(struct i2c_client *client);
static struct via686a_data *via686a_update_device(struct device *dev);
static void via686a_init_client(struct i2c_client *client);
/* following are the sysfs callback functions */
/* 7 voltage sensors */
static ssize_t show_in(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client);
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)*10 );
}
static ssize_t show_in_min(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client);
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)*10 );
}
static ssize_t show_in_max(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client);
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)*10 );
}
......@@ -482,10 +472,10 @@ static ssize_t set_in##offset##_max (struct device *dev, \
{ \
return set_in_max(dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in##offset, NULL) \
static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL) \
static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
show_in##offset##_min, set_in##offset##_min) \
static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
show_in##offset##_max, set_in##offset##_max)
show_in_offset(0);
......@@ -496,21 +486,15 @@ show_in_offset(4);
/* 3 temperatures */
static ssize_t show_temp(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client);
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])*100 );
}
static ssize_t show_temp_over(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client);
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])*100);
}
static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client);
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])*100);
}
static ssize_t set_temp_over(struct device *dev, const char *buf,
......@@ -556,10 +540,10 @@ static ssize_t set_temp_##offset##_hyst (struct device *dev, \
{ \
return set_temp_hyst(dev, buf, count, 0x##offset - 1); \
} \
static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_temp_##offset, NULL) \
static DEVICE_ATTR(temp_max##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL) \
static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
show_temp_##offset##_over, set_temp_##offset##_over) \
static DEVICE_ATTR(temp_hyst##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
show_temp_##offset##_hyst, set_temp_##offset##_hyst)
show_temp_offset(1);
......@@ -568,23 +552,17 @@ show_temp_offset(3);
/* 2 Fans */
static ssize_t show_fan(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client);
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
DIV_FROM_REG(data->fan_div[nr])) );
}
static ssize_t show_fan_min(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client);
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf,"%d\n",
FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
}
static ssize_t show_fan_div(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client);
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf,"%d\n", DIV_FROM_REG(data->fan_div[nr]) );
}
static ssize_t set_fan_min(struct device *dev, const char *buf,
......@@ -631,10 +609,10 @@ static ssize_t set_fan_##offset##_div (struct device *dev, \
{ \
return set_fan_div(dev, buf, count, 0x##offset - 1); \
} \
static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_fan_##offset, NULL) \
static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL) \
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
show_fan_##offset##_min, set_fan_##offset##_min) \
static DEVICE_ATTR(fan_div##offset, S_IRUGO | S_IWUSR, \
static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
show_fan_##offset##_div, set_fan_##offset##_div)
show_fan_offset(1);
......@@ -642,9 +620,7 @@ show_fan_offset(2);
/* Alarms */
static ssize_t show_alarms(struct device *dev, char *buf) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client);
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));
}
static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL);
......@@ -653,7 +629,7 @@ static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL);
smbus_driver and isa_driver, and clients could be of either kind */
static struct i2c_driver via686a_driver = {
.owner = THIS_MODULE,
.name = "VIA686A",
.name = "via686a",
.id = I2C_DRIVERID_VIA686A,
.flags = I2C_DF_NOTIFY,
.attach_adapter = via686a_attach_adapter,
......@@ -742,36 +718,36 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
via686a_init_client(new_client);
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_in_input0);
device_create_file(&new_client->dev, &dev_attr_in_input1);
device_create_file(&new_client->dev, &dev_attr_in_input2);
device_create_file(&new_client->dev, &dev_attr_in_input3);
device_create_file(&new_client->dev, &dev_attr_in_input4);
device_create_file(&new_client->dev, &dev_attr_in_min0);
device_create_file(&new_client->dev, &dev_attr_in_min1);
device_create_file(&new_client->dev, &dev_attr_in_min2);
device_create_file(&new_client->dev, &dev_attr_in_min3);
device_create_file(&new_client->dev, &dev_attr_in_min4);
device_create_file(&new_client->dev, &dev_attr_in_max0);
device_create_file(&new_client->dev, &dev_attr_in_max1);
device_create_file(&new_client->dev, &dev_attr_in_max2);
device_create_file(&new_client->dev, &dev_attr_in_max3);
device_create_file(&new_client->dev, &dev_attr_in_max4);
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_input2);
device_create_file(&new_client->dev, &dev_attr_temp_input3);
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_max2);
device_create_file(&new_client->dev, &dev_attr_temp_max3);
device_create_file(&new_client->dev, &dev_attr_temp_hyst1);
device_create_file(&new_client->dev, &dev_attr_temp_hyst2);
device_create_file(&new_client->dev, &dev_attr_temp_hyst3);
device_create_file(&new_client->dev, &dev_attr_fan_input1);
device_create_file(&new_client->dev, &dev_attr_fan_input2);
device_create_file(&new_client->dev, &dev_attr_fan_min1);
device_create_file(&new_client->dev, &dev_attr_fan_min2);
device_create_file(&new_client->dev, &dev_attr_fan_div1);
device_create_file(&new_client->dev, &dev_attr_fan_div2);
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
device_create_file(&new_client->dev, &dev_attr_in3_input);
device_create_file(&new_client->dev, &dev_attr_in4_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in2_min);
device_create_file(&new_client->dev, &dev_attr_in3_min);
device_create_file(&new_client->dev, &dev_attr_in4_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
device_create_file(&new_client->dev, &dev_attr_in1_max);
device_create_file(&new_client->dev, &dev_attr_in2_max);
device_create_file(&new_client->dev, &dev_attr_in3_max);
device_create_file(&new_client->dev, &dev_attr_in4_max);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_temp3_input);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp2_max);
device_create_file(&new_client->dev, &dev_attr_temp3_max);
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
device_create_file(&new_client->dev, &dev_attr_temp2_max_hyst);
device_create_file(&new_client->dev, &dev_attr_temp3_max_hyst);
device_create_file(&new_client->dev, &dev_attr_fan1_input);
device_create_file(&new_client->dev, &dev_attr_fan2_input);
device_create_file(&new_client->dev, &dev_attr_fan1_min);
device_create_file(&new_client->dev, &dev_attr_fan2_min);
device_create_file(&new_client->dev, &dev_attr_fan1_div);
device_create_file(&new_client->dev, &dev_attr_fan2_div);
device_create_file(&new_client->dev, &dev_attr_alarms);
return 0;
......@@ -854,8 +830,9 @@ static void via686a_init_client(struct i2c_client *client)
!(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
}
static void via686a_update_client(struct i2c_client *client)
static struct via686a_data *via686a_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
int i;
......@@ -916,6 +893,8 @@ static void via686a_update_client(struct i2c_client *client)
}
up(&data->update_lock);
return data;
}
static struct pci_device_id via686a_pci_ids[] = {
......
/*
w83627hf.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998 - 2003 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>,
and Mark Studebaker <mdsxyz123@yahoo.com>
Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
Supports following chips:
Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC)
w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC)
w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC)
w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC)
For other winbond chips, and for i2c support in the above chips,
use w83781d.c.
Note: automatic ("cruise") fan control for 697, 637 & 627thf not
supported yet.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
#include <asm/io.h>
#include "lm75.h"
static int force_addr;
MODULE_PARM(force_addr, "i");
MODULE_PARM_DESC(force_addr,
"Initialize the base address of the sensors");
static int force_i2c = 0x1f;
MODULE_PARM(force_i2c, "i");
MODULE_PARM_DESC(force_i2c,
"Initialize the i2c address of the sensors");
/* Addresses to scan */
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
static int init = 1;
MODULE_PARM(init, "i");
MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
/* modified from kernel/include/traps.c */
#define REG 0x2e /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */
#define VAL 0x2f /* The value to read/write */
/* logical device numbers for superio_select (below) */
#define W83627HF_LD_FDC 0x00
#define W83627HF_LD_PRT 0x01
#define W83627HF_LD_UART1 0x02
#define W83627HF_LD_UART2 0x03
#define W83627HF_LD_KBC 0x05
#define W83627HF_LD_CIR 0x06 /* w83627hf only */
#define W83627HF_LD_GAME 0x07
#define W83627HF_LD_MIDI 0x07
#define W83627HF_LD_GPIO1 0x07
#define W83627HF_LD_GPIO5 0x07 /* w83627thf only */
#define W83627HF_LD_GPIO2 0x08
#define W83627HF_LD_GPIO3 0x09
#define W83627HF_LD_GPIO4 0x09 /* w83627thf only */
#define W83627HF_LD_ACPI 0x0a
#define W83627HF_LD_HWM 0x0b
#define DEVID 0x20 /* Register: Device ID */
#define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */
#define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */
#define W83627THF_GPIO5_INVR 0xf5 /* w83627thf only */
static inline void
superio_outb(int reg, int val)
{
outb(reg, REG);
outb(val, VAL);
}
static inline int
superio_inb(int reg)
{
outb(reg, REG);
return inb(VAL);
}
static inline void
superio_select(int ld)
{
outb(DEV, REG);
outb(ld, VAL);
}
static inline void
superio_enter(void)
{
outb(0x87, REG);
outb(0x87, REG);
}
static inline void
superio_exit(void)
{
outb(0xAA, REG);
}
#define W627_DEVID 0x52
#define W627THF_DEVID 0x82
#define W697_DEVID 0x60
#define W637_DEVID 0x70
#define WINB_ACT_REG 0x30
#define WINB_BASE_REG 0x60
/* Constants specified below */
/* Length of ISA address segment */
#define WINB_EXTENT 8
/* Where are the ISA address/data registers relative to the base address */
#define W83781D_ADDR_REG_OFFSET 5
#define W83781D_DATA_REG_OFFSET 6
/* The W83781D registers */
/* The W83782D registers for nr=7,8 are in bank 5 */
#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
(0x554 + (((nr) - 7) * 2)))
#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
(0x555 + (((nr) - 7) * 2)))
#define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
(0x550 + (nr) - 7))
#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
#define W83781D_REG_FAN(nr) (0x27 + (nr))
#define W83781D_REG_TEMP2_CONFIG 0x152
#define W83781D_REG_TEMP3_CONFIG 0x252
#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \
((nr == 2) ? (0x0150) : \
(0x27)))
#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \
((nr == 2) ? (0x153) : \
(0x3A)))
#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \
((nr == 2) ? (0x155) : \
(0x39)))
#define W83781D_REG_BANK 0x4E
#define W83781D_REG_CONFIG 0x40
#define W83781D_REG_ALARM1 0x41
#define W83781D_REG_ALARM2 0x42
#define W83781D_REG_ALARM3 0x450
#define W83781D_REG_IRQ 0x4C
#define W83781D_REG_BEEP_CONFIG 0x4D
#define W83781D_REG_BEEP_INTS1 0x56
#define W83781D_REG_BEEP_INTS2 0x57
#define W83781D_REG_BEEP_INTS3 0x453
#define W83781D_REG_VID_FANDIV 0x47
#define W83781D_REG_CHIPID 0x49
#define W83781D_REG_WCHIPID 0x58
#define W83781D_REG_CHIPMAN 0x4F
#define W83781D_REG_PIN 0x4B
#define W83781D_REG_VBAT 0x5D
#define W83627HF_REG_PWM1 0x5A
#define W83627HF_REG_PWM2 0x5B
#define W83627HF_REG_PWMCLK12 0x5C
#define W83627THF_REG_PWM1 0x01 /* 697HF and 637HF too */
#define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */
#define W83627THF_REG_PWM3 0x11 /* 637HF too */
#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF too, unused yet */
static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 };
static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
W83627THF_REG_PWM3 };
#define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \
regpwm_627hf[(nr) - 1] : regpwm[(nr) - 1])
#define W83781D_REG_I2C_ADDR 0x48
#define W83781D_REG_I2C_SUBADDR 0x4A
/* Sensor selection */
#define W83781D_REG_SCFG1 0x5D
static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
#define W83781D_REG_SCFG2 0x59
static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
#define W83781D_DEFAULT_BETA 3435
/* Conversions. Limit checking is only done on the TO_REG
variants. Note that you should be a bit careful with which arguments
these macros are called: arguments may be evaluated more than once.
Fixing this is just not worth it. */
#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255))
#define IN_FROM_REG(val) ((val) * 16 + 5)
static inline u8 FAN_TO_REG(long rpm, int div)
{
if (rpm == 0)
return 255;
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
254);
}
#define TEMP_MIN (-128000)
#define TEMP_MAX ( 127000)
/* TEMP: 0.001C/bit (-128C to +127C)
REG: 1C/bit, two's complement */
static u8 TEMP_TO_REG(int temp)
{
int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX);
ntemp += (ntemp<0 ? -500 : 500);
return (u8)(ntemp / 1000);
}
static int TEMP_FROM_REG(u8 reg)
{
return (s8)reg * 1000;
}
#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
#define BEEP_MASK_FROM_REG(val) (val)
#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff)
#define BEEP_ENABLE_TO_REG(val) ((val)?1:0)
#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0)
#define DIV_FROM_REG(val) (1 << (val))
static inline u8 DIV_TO_REG(long val)
{
int i;
val = SENSORS_LIMIT(val, 1, 128) >> 1;
for (i = 0; i < 6; i++) {
if (val == 0)
break;
val >>= 1;
}
return ((u8) i);
}
/* For each registered chip, we need to keep some data in memory. That
data is pointed to by w83627hf_list[NR]->data. The structure itself is
dynamically allocated, at the same time when a new client is allocated. */
struct w83627hf_data {
struct semaphore lock;
enum chips type;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
struct i2c_client *lm75; /* for secondary I2C addresses */
/* pointer to array of 2 subclients */
u8 in[9]; /* Register value */
u8 in_max[9]; /* Register value */
u8 in_min[9]; /* Register value */
u8 fan[3]; /* Register value */
u8 fan_min[3]; /* Register value */
u8 temp;
u8 temp_max; /* Register value */
u8 temp_max_hyst; /* Register value */
u16 temp_add[2]; /* Register value */
u16 temp_max_add[2]; /* Register value */
u16 temp_max_hyst_add[2]; /* Register value */
u8 fan_div[3]; /* Register encoding, shifted right */
u8 vid; /* Register encoding, combined */
u32 alarms; /* Register encoding, combined */
u32 beep_mask; /* Register encoding, combined */
u8 beep_enable; /* Boolean */
u8 pwm[3]; /* Register value */
u8 pwmenable[3]; /* bool */
u16 sens[3]; /* 782D/783S only.
1 = pentium diode; 2 = 3904 diode;
3000-5000 = thermistor beta.
Default = 3435.
Other Betas unimplemented */
u8 vrm;
};
static int w83627hf_attach_adapter(struct i2c_adapter *adapter);
static int w83627hf_detect(struct i2c_adapter *adapter, int address,
int kind);
static int w83627hf_detach_client(struct i2c_client *client);
static int w83627hf_read_value(struct i2c_client *client, u16 register);
static int w83627hf_write_value(struct i2c_client *client, u16 register,
u16 value);
static struct w83627hf_data *w83627hf_update_device(struct device *dev);
static void w83627hf_init_client(struct i2c_client *client);
static struct i2c_driver w83627hf_driver = {
.owner = THIS_MODULE,
.name = "w83627hf",
.id = I2C_DRIVERID_W83627HF,
.flags = I2C_DF_NOTIFY,
.attach_adapter = w83627hf_attach_adapter,
.detach_client = w83627hf_detach_client,
};
/* following are the sysfs callback functions */
#define show_in_reg(reg) \
static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
{ \
struct w83627hf_data *data = w83627hf_update_device(dev); \
return sprintf(buf,"%ld\n", (long)IN_FROM_REG(data->reg[nr])); \
}
show_in_reg(in)
show_in_reg(in_min)
show_in_reg(in_max)
#define store_in_reg(REG, reg) \
static ssize_t \
store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct w83627hf_data *data = i2c_get_clientdata(client); \
u32 val; \
\
val = simple_strtoul(buf, NULL, 10); \
data->in_##reg[nr] = IN_TO_REG(val); \
w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \
data->in_##reg[nr]); \
\
return count; \
}
store_in_reg(MIN, min)
store_in_reg(MAX, max)
#define sysfs_in_offset(offset) \
static ssize_t \
show_regs_in_##offset (struct device *dev, char *buf) \
{ \
return show_in(dev, buf, 0x##offset); \
} \
static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL)
#define sysfs_in_reg_offset(reg, offset) \
static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \
{ \
return show_in_##reg (dev, buf, 0x##offset); \
} \
static ssize_t \
store_regs_in_##reg##offset (struct device *dev, \
const char *buf, size_t count) \
{ \
return store_in_##reg (dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, \
show_regs_in_##reg##offset, store_regs_in_##reg##offset)
#define sysfs_in_offsets(offset) \
sysfs_in_offset(offset) \
sysfs_in_reg_offset(min, offset) \
sysfs_in_reg_offset(max, offset)
sysfs_in_offsets(0)
sysfs_in_offsets(1)
sysfs_in_offsets(2)
sysfs_in_offsets(3)
sysfs_in_offsets(4)
sysfs_in_offsets(5)
sysfs_in_offsets(6)
sysfs_in_offsets(7)
sysfs_in_offsets(8)
#define device_create_file_in(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_in##offset##_input); \
device_create_file(&client->dev, &dev_attr_in##offset##_min); \
device_create_file(&client->dev, &dev_attr_in##offset##_max); \
} while (0)
#define show_fan_reg(reg) \
static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
{ \
struct w83627hf_data *data = w83627hf_update_device(dev); \
return sprintf(buf,"%ld\n", \
FAN_FROM_REG(data->reg[nr-1], \
(long)DIV_FROM_REG(data->fan_div[nr-1]))); \
}
show_fan_reg(fan)
show_fan_reg(fan_min)
static ssize_t
store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83627hf_data *data = i2c_get_clientdata(client);
u32 val;
val = simple_strtoul(buf, NULL, 10);
data->fan_min[nr - 1] =
FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1]));
w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr),
data->fan_min[nr - 1]);
return count;
}
#define sysfs_fan_offset(offset) \
static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \
{ \
return show_fan(dev, buf, 0x##offset); \
} \
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL)
#define sysfs_fan_min_offset(offset) \
static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \
{ \
return show_fan_min(dev, buf, 0x##offset); \
} \
static ssize_t \
store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \
{ \
return store_fan_min(dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
show_regs_fan_min##offset, store_regs_fan_min##offset)
sysfs_fan_offset(1)
sysfs_fan_min_offset(1)
sysfs_fan_offset(2)
sysfs_fan_min_offset(2)
sysfs_fan_offset(3)
sysfs_fan_min_offset(3)
#define device_create_file_fan(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
} while (0)
#define show_temp_reg(reg) \
static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
{ \
struct w83627hf_data *data = w83627hf_update_device(dev); \
if (nr >= 2) { /* TEMP2 and TEMP3 */ \
return sprintf(buf,"%ld\n", \
(long)LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \
} else { /* TEMP1 */ \
return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \
} \
}
show_temp_reg(temp)
show_temp_reg(temp_max)
show_temp_reg(temp_max_hyst)
#define store_temp_reg(REG, reg) \
static ssize_t \
store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct w83627hf_data *data = i2c_get_clientdata(client); \
u32 val; \
\
val = simple_strtoul(buf, NULL, 10); \
\
if (nr >= 2) { /* TEMP2 and TEMP3 */ \
data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \
data->temp_##reg##_add[nr-2]); \
} else { /* TEMP1 */ \
data->temp_##reg = TEMP_TO_REG(val); \
w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \
data->temp_##reg); \
} \
\
return count; \
}
store_temp_reg(OVER, max)
store_temp_reg(HYST, max_hyst)
#define sysfs_temp_offset(offset) \
static ssize_t \
show_regs_temp_##offset (struct device *dev, char *buf) \
{ \
return show_temp(dev, buf, 0x##offset); \
} \
static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL)
#define sysfs_temp_reg_offset(reg, offset) \
static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \
{ \
return show_temp_##reg (dev, buf, 0x##offset); \
} \
static ssize_t \
store_regs_temp_##reg##offset (struct device *dev, \
const char *buf, size_t count) \
{ \
return store_temp_##reg (dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \
show_regs_temp_##reg##offset, store_regs_temp_##reg##offset)
#define sysfs_temp_offsets(offset) \
sysfs_temp_offset(offset) \
sysfs_temp_reg_offset(max, offset) \
sysfs_temp_reg_offset(max_hyst, offset)
sysfs_temp_offsets(1)
sysfs_temp_offsets(2)
sysfs_temp_offsets(3)
#define device_create_file_temp(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
device_create_file(&client->dev, &dev_attr_temp##offset##_max); \
device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \
} while (0)
static ssize_t
show_vid_reg(struct device *dev, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
}
static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL)
#define device_create_file_vid(client) \
device_create_file(&client->dev, &dev_attr_in0_ref)
static ssize_t
show_vrm_reg(struct device *dev, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->vrm);
}
static ssize_t
store_vrm_reg(struct device *dev, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83627hf_data *data = i2c_get_clientdata(client);
u32 val;
val = simple_strtoul(buf, NULL, 10);
data->vrm = val;
return count;
}
static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg)
#define device_create_file_vrm(client) \
device_create_file(&client->dev, &dev_attr_vrm)
static ssize_t
show_alarms_reg(struct device *dev, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->alarms);
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
#define device_create_file_alarms(client) \
device_create_file(&client->dev, &dev_attr_alarms)
#define show_beep_reg(REG, reg) \
static ssize_t show_beep_##reg (struct device *dev, char *buf) \
{ \
struct w83627hf_data *data = w83627hf_update_device(dev); \
return sprintf(buf,"%ld\n", \
(long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \
}
show_beep_reg(ENABLE, enable)
show_beep_reg(MASK, mask)
#define BEEP_ENABLE 0 /* Store beep_enable */
#define BEEP_MASK 1 /* Store beep_mask */
static ssize_t
store_beep_reg(struct device *dev, const char *buf, size_t count,
int update_mask)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83627hf_data *data = i2c_get_clientdata(client);
u32 val, val2;
val = simple_strtoul(buf, NULL, 10);
if (update_mask == BEEP_MASK) { /* We are storing beep_mask */
data->beep_mask = BEEP_MASK_TO_REG(val);
w83627hf_write_value(client, W83781D_REG_BEEP_INTS1,
data->beep_mask & 0xff);
w83627hf_write_value(client, W83781D_REG_BEEP_INTS3,
((data->beep_mask) >> 16) & 0xff);
val2 = (data->beep_mask >> 8) & 0x7f;
} else { /* We are storing beep_enable */
val2 =
w83627hf_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f;
data->beep_enable = BEEP_ENABLE_TO_REG(val);
}
w83627hf_write_value(client, W83781D_REG_BEEP_INTS2,
val2 | data->beep_enable << 7);
return count;
}
#define sysfs_beep(REG, reg) \
static ssize_t show_regs_beep_##reg (struct device *dev, char *buf) \
{ \
return show_beep_##reg(dev, buf); \
} \
static ssize_t \
store_regs_beep_##reg (struct device *dev, const char *buf, size_t count) \
{ \
return store_beep_reg(dev, buf, count, BEEP_##REG); \
} \
static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \
show_regs_beep_##reg, store_regs_beep_##reg)
sysfs_beep(ENABLE, enable)
sysfs_beep(MASK, mask)
#define device_create_file_beep(client) \
do { \
device_create_file(&client->dev, &dev_attr_beep_enable); \
device_create_file(&client->dev, &dev_attr_beep_mask); \
} while (0)
static ssize_t
show_fan_div_reg(struct device *dev, char *buf, int nr)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return sprintf(buf, "%ld\n",
(long) DIV_FROM_REG(data->fan_div[nr - 1]));
}
static ssize_t
store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83627hf_data *data = i2c_get_clientdata(client);
u32 val, old, old2, old3 = 0;
val = simple_strtoul(buf, NULL, 10);
old = w83627hf_read_value(client, W83781D_REG_VID_FANDIV);
old3 = w83627hf_read_value(client, W83781D_REG_VBAT);
data->fan_div[nr - 1] = DIV_TO_REG(val);
if (nr >= 3 && data->type != w83697hf) {
old2 = w83627hf_read_value(client, W83781D_REG_PIN);
old2 = (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6);
w83627hf_write_value(client, W83781D_REG_PIN, old2);
old3 = (old3 & 0x7f) | ((data->fan_div[2] & 0x04) << 5);
}
if (nr >= 2) {
old = (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
old3 = (old3 & 0xbf) | ((data->fan_div[1] & 0x04) << 4);
}
if (nr >= 1) {
old = (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
w83627hf_write_value(client, W83781D_REG_VID_FANDIV, old);
old3 = (old3 & 0xdf) | ((data->fan_div[0] & 0x04) << 3);
w83627hf_write_value(client, W83781D_REG_VBAT, old3);
}
return count;
}
#define sysfs_fan_div(offset) \
static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \
{ \
return show_fan_div_reg(dev, buf, offset); \
} \
static ssize_t \
store_regs_fan_div_##offset (struct device *dev, \
const char *buf, size_t count) \
{ \
return store_fan_div_reg(dev, buf, count, offset); \
} \
static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
show_regs_fan_div_##offset, store_regs_fan_div_##offset)
sysfs_fan_div(1)
sysfs_fan_div(2)
sysfs_fan_div(3)
#define device_create_file_fan_div(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
} while (0)
static ssize_t
show_pwm_reg(struct device *dev, char *buf, int nr)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->pwm[nr - 1]);
}
static ssize_t
store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83627hf_data *data = i2c_get_clientdata(client);
u32 val;
val = simple_strtoul(buf, NULL, 10);
if (data->type == w83627thf) {
/* bits 0-3 are reserved in 627THF */
data->pwm[nr - 1] = PWM_TO_REG(val) & 0xf0;
w83627hf_write_value(client,
W836X7HF_REG_PWM(data->type, nr),
data->pwm[nr - 1] |
(w83627hf_read_value(client,
W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
} else {
data->pwm[nr - 1] = PWM_TO_REG(val);
w83627hf_write_value(client,
W836X7HF_REG_PWM(data->type, nr),
data->pwm[nr - 1]);
}
return count;
}
#define sysfs_pwm(offset) \
static ssize_t show_regs_pwm_##offset (struct device *dev, char *buf) \
{ \
return show_pwm_reg(dev, buf, offset); \
} \
static ssize_t \
store_regs_pwm_##offset (struct device *dev, const char *buf, size_t count) \
{ \
return store_pwm_reg(dev, buf, count, offset); \
} \
static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, \
show_regs_pwm_##offset, store_regs_pwm_##offset)
sysfs_pwm(1)
sysfs_pwm(2)
sysfs_pwm(3)
#define device_create_file_pwm(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_fan##offset##_pwm); \
} while (0)
static ssize_t
show_sensor_reg(struct device *dev, char *buf, int nr)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->sens[nr - 1]);
}
static ssize_t
store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83627hf_data *data = i2c_get_clientdata(client);
u32 val, tmp;
val = simple_strtoul(buf, NULL, 10);
switch (val) {
case 1: /* PII/Celeron diode */
tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
w83627hf_write_value(client, W83781D_REG_SCFG1,
tmp | BIT_SCFG1[nr - 1]);
tmp = w83627hf_read_value(client, W83781D_REG_SCFG2);
w83627hf_write_value(client, W83781D_REG_SCFG2,
tmp | BIT_SCFG2[nr - 1]);
data->sens[nr - 1] = val;
break;
case 2: /* 3904 */
tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
w83627hf_write_value(client, W83781D_REG_SCFG1,
tmp | BIT_SCFG1[nr - 1]);
tmp = w83627hf_read_value(client, W83781D_REG_SCFG2);
w83627hf_write_value(client, W83781D_REG_SCFG2,
tmp & ~BIT_SCFG2[nr - 1]);
data->sens[nr - 1] = val;
break;
case W83781D_DEFAULT_BETA: /* thermistor */
tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
w83627hf_write_value(client, W83781D_REG_SCFG1,
tmp & ~BIT_SCFG1[nr - 1]);
data->sens[nr - 1] = val;
break;
default:
dev_err(&client->dev,
"Invalid sensor type %ld; must be 1, 2, or %d\n",
(long) val, W83781D_DEFAULT_BETA);
break;
}
return count;
}
#define sysfs_sensor(offset) \
static ssize_t show_regs_sensor_##offset (struct device *dev, char *buf) \
{ \
return show_sensor_reg(dev, buf, offset); \
} \
static ssize_t \
store_regs_sensor_##offset (struct device *dev, const char *buf, size_t count) \
{ \
return store_sensor_reg(dev, buf, count, offset); \
} \
static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
show_regs_sensor_##offset, store_regs_sensor_##offset)
sysfs_sensor(1)
sysfs_sensor(2)
sysfs_sensor(3)
#define device_create_file_sensor(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
} while (0)
/* This function is called when:
* w83627hf_driver is inserted (when this module is loaded), for each
available adapter
* when a new adapter is inserted (and w83627hf_driver is still present) */
static int w83627hf_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_detect(adapter, &addr_data, w83627hf_detect);
}
static int w83627hf_find(int *address)
{
u16 val;
superio_enter();
val= superio_inb(DEVID);
if(val != W627_DEVID &&
val != W627THF_DEVID &&
val != W697_DEVID &&
val != W637_DEVID) {
superio_exit();
return -ENODEV;
}
superio_select(W83627HF_LD_HWM);
val = (superio_inb(WINB_BASE_REG) << 8) |
superio_inb(WINB_BASE_REG + 1);
*address = val & ~(WINB_EXTENT - 1);
if (*address == 0 && force_addr == 0) {
superio_exit();
return -ENODEV;
}
if (force_addr)
*address = force_addr; /* so detect will get called */
superio_exit();
return 0;
}
int w83627hf_detect(struct i2c_adapter *adapter, int address,
int kind)
{
int val;
struct i2c_client *new_client;
struct w83627hf_data *data;
int err = 0;
const char *client_name = "";
if (!i2c_is_isa_adapter(adapter)) {
err = -ENODEV;
goto ERROR0;
}
if(force_addr)
address = force_addr & ~(WINB_EXTENT - 1);
if (!request_region(address, WINB_EXTENT, "w83627hf")) {
err = -EBUSY;
goto ERROR0;
}
if(force_addr) {
printk("w83627hf.o: forcing ISA address 0x%04X\n", address);
superio_enter();
superio_select(W83627HF_LD_HWM);
superio_outb(WINB_BASE_REG, address >> 8);
superio_outb(WINB_BASE_REG+1, address & 0xff);
superio_exit();
}
superio_enter();
val= superio_inb(DEVID);
if(val == W627_DEVID)
kind = w83627hf;
else if(val == W697_DEVID)
kind = w83697hf;
else if(val == W627THF_DEVID)
kind = w83627thf;
else if(val == W637_DEVID)
kind = w83637hf;
else {
dev_info(&adapter->dev,
"Unsupported chip (dev_id=0x%02X).\n", val);
goto ERROR1;
}
superio_select(W83627HF_LD_HWM);
if((val = 0x01 & superio_inb(WINB_ACT_REG)) == 0)
superio_outb(WINB_ACT_REG, 1);
superio_exit();
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access w83627hf_{read,write}_value. */
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
sizeof(struct w83627hf_data),
GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR1;
}
memset(new_client, 0x00, sizeof (struct i2c_client) +
sizeof (struct w83627hf_data));
data = (struct w83627hf_data *) (new_client + 1);
i2c_set_clientdata(new_client, data);
new_client->addr = address;
init_MUTEX(&data->lock);
new_client->adapter = adapter;
new_client->driver = &w83627hf_driver;
new_client->flags = 0;
if (kind == w83627hf) {
client_name = "w83627hf";
} else if (kind == w83627thf) {
client_name = "w83627thf";
} else if (kind == w83697hf) {
client_name = "w83697hf";
} else if (kind == w83637hf) {
client_name = "w83637hf";
}
/* Fill in the remaining client fields and put into the global list */
strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
data->type = kind;
data->valid = 0;
init_MUTEX(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto ERROR2;
data->lm75 = NULL;
/* Initialize the chip */
w83627hf_init_client(new_client);
/* Register sysfs hooks */
device_create_file_in(new_client, 0);
if (kind != w83697hf)
device_create_file_in(new_client, 1);
device_create_file_in(new_client, 2);
device_create_file_in(new_client, 3);
device_create_file_in(new_client, 4);
if (kind != w83627thf && kind != w83637hf) {
device_create_file_in(new_client, 5);
device_create_file_in(new_client, 6);
}
device_create_file_in(new_client, 7);
device_create_file_in(new_client, 8);
device_create_file_fan(new_client, 1);
device_create_file_fan(new_client, 2);
if (kind != w83697hf)
device_create_file_fan(new_client, 3);
device_create_file_temp(new_client, 1);
device_create_file_temp(new_client, 2);
if (kind != w83697hf)
device_create_file_temp(new_client, 3);
if (kind != w83697hf)
device_create_file_vid(new_client);
if (kind != w83697hf)
device_create_file_vrm(new_client);
device_create_file_fan_div(new_client, 1);
device_create_file_fan_div(new_client, 2);
if (kind != w83697hf)
device_create_file_fan_div(new_client, 3);
device_create_file_alarms(new_client);
device_create_file_beep(new_client);
device_create_file_pwm(new_client, 1);
device_create_file_pwm(new_client, 2);
if (kind == w83627thf || kind == w83637hf)
device_create_file_pwm(new_client, 3);
device_create_file_sensor(new_client, 1);
device_create_file_sensor(new_client, 2);
if (kind != w83697hf)
device_create_file_sensor(new_client, 3);
return 0;
ERROR2:
kfree(new_client);
ERROR1:
release_region(address, WINB_EXTENT);
ERROR0:
return err;
}
static int w83627hf_detach_client(struct i2c_client *client)
{
int err;
if ((err = i2c_detach_client(client))) {
dev_err(&client->dev,
"Client deregistration failed, client not detached.\n");
return err;
}
release_region(client->addr, WINB_EXTENT);
kfree(client);
return 0;
}
/*
ISA access must always be locked explicitly!
We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
would slow down the W83781D access and should not be necessary.
There are some ugly typecasts here, but the good news is - they should
nowhere else be necessary! */
static int w83627hf_read_value(struct i2c_client *client, u16 reg)
{
struct w83627hf_data *data = i2c_get_clientdata(client);
int res, word_sized;
down(&data->lock);
word_sized = (((reg & 0xff00) == 0x100)
|| ((reg & 0xff00) == 0x200))
&& (((reg & 0x00ff) == 0x50)
|| ((reg & 0x00ff) == 0x53)
|| ((reg & 0x00ff) == 0x55));
if (reg & 0xff00) {
outb_p(W83781D_REG_BANK,
client->addr + W83781D_ADDR_REG_OFFSET);
outb_p(reg >> 8,
client->addr + W83781D_DATA_REG_OFFSET);
}
outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
if (word_sized) {
outb_p((reg & 0xff) + 1,
client->addr + W83781D_ADDR_REG_OFFSET);
res =
(res << 8) + inb_p(client->addr +
W83781D_DATA_REG_OFFSET);
}
if (reg & 0xff00) {
outb_p(W83781D_REG_BANK,
client->addr + W83781D_ADDR_REG_OFFSET);
outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
}
up(&data->lock);
return res;
}
static int w83627thf_read_gpio5(struct i2c_client *client)
{
struct w83627hf_data *data = i2c_get_clientdata(client);
int res, inv;
down(&data->lock);
superio_enter();
superio_select(W83627HF_LD_GPIO5);
res = superio_inb(W83627THF_GPIO5_DR);
inv = superio_inb(W83627THF_GPIO5_INVR);
superio_exit();
up(&data->lock);
return res;
}
static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
{
struct w83627hf_data *data = i2c_get_clientdata(client);
int word_sized;
down(&data->lock);
word_sized = (((reg & 0xff00) == 0x100)
|| ((reg & 0xff00) == 0x200))
&& (((reg & 0x00ff) == 0x53)
|| ((reg & 0x00ff) == 0x55));
if (reg & 0xff00) {
outb_p(W83781D_REG_BANK,
client->addr + W83781D_ADDR_REG_OFFSET);
outb_p(reg >> 8,
client->addr + W83781D_DATA_REG_OFFSET);
}
outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
if (word_sized) {
outb_p(value >> 8,
client->addr + W83781D_DATA_REG_OFFSET);
outb_p((reg & 0xff) + 1,
client->addr + W83781D_ADDR_REG_OFFSET);
}
outb_p(value & 0xff,
client->addr + W83781D_DATA_REG_OFFSET);
if (reg & 0xff00) {
outb_p(W83781D_REG_BANK,
client->addr + W83781D_ADDR_REG_OFFSET);
outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
}
up(&data->lock);
return 0;
}
/* Called when we have found a new W83781D. It should set limits, etc. */
static void w83627hf_init_client(struct i2c_client *client)
{
struct w83627hf_data *data = i2c_get_clientdata(client);
int vid = 0, i;
int type = data->type;
u8 tmp;
if(init) {
/* save this register */
i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG);
/* Reset all except Watchdog values and last conversion values
This sets fan-divs to 2, among others */
w83627hf_write_value(client, W83781D_REG_CONFIG, 0x80);
/* Restore the register and disable power-on abnormal beep.
This saves FAN 1/2/3 input/output values set by BIOS. */
w83627hf_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80);
/* Disable master beep-enable (reset turns it on).
Individual beeps should be reset to off but for some reason
disabling this bit helps some people not get beeped */
w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, 0);
}
/* Minimize conflicts with other winbond i2c-only clients... */
/* disable i2c subclients... how to disable main i2c client?? */
/* force i2c address to relatively uncommon address */
w83627hf_write_value(client, W83781D_REG_I2C_SUBADDR, 0x89);
w83627hf_write_value(client, W83781D_REG_I2C_ADDR, force_i2c);
/* Read VID only once */
if (w83627hf == data->type || w83637hf == data->type) {
int lo = w83627hf_read_value(client, W83781D_REG_VID_FANDIV);
int hi = w83627hf_read_value(client, W83781D_REG_CHIPID);
data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
} else if (w83627thf == data->type) {
data->vid = w83627thf_read_gpio5(client) & 0x1f;
}
/* Convert VID to voltage based on default VRM */
data->vrm = DEFAULT_VRM;
if (type != w83697hf)
vid = vid_from_reg(vid, data->vrm);
tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
for (i = 1; i <= 3; i++) {
if (!(tmp & BIT_SCFG1[i - 1])) {
data->sens[i - 1] = W83781D_DEFAULT_BETA;
} else {
if (w83627hf_read_value
(client,
W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
data->sens[i - 1] = 1;
else
data->sens[i - 1] = 2;
}
if ((type == w83697hf) && (i == 2))
break;
}
data->pwmenable[0] = 1;
data->pwmenable[1] = 1;
data->pwmenable[2] = 1;
if(init) {
if (type == w83627hf) {
/* enable PWM2 control (can't hurt since PWM reg
should have been reset to 0xff) */
w83627hf_write_value(client, W83627HF_REG_PWMCLK12,
0x19);
}
/* enable comparator mode for temp2 and temp3 so
alarm indication will work correctly */
i = w83627hf_read_value(client, W83781D_REG_IRQ);
if (!(i & 0x40))
w83627hf_write_value(client, W83781D_REG_IRQ,
i | 0x40);
}
/* Start monitoring */
w83627hf_write_value(client, W83781D_REG_CONFIG,
(w83627hf_read_value(client,
W83781D_REG_CONFIG) & 0xf7)
| 0x01);
}
static struct w83627hf_data *w83627hf_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83627hf_data *data = i2c_get_clientdata(client);
int i;
down(&data->update_lock);
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
(jiffies < data->last_updated) || !data->valid) {
for (i = 0; i <= 8; i++) {
/* skip missing sensors */
if (((data->type == w83697hf) && (i == 1)) ||
((data->type == w83627thf || data->type == w83637hf)
&& (i == 4 || i == 5)))
continue;
data->in[i] =
w83627hf_read_value(client, W83781D_REG_IN(i));
data->in_min[i] =
w83627hf_read_value(client,
W83781D_REG_IN_MIN(i));
data->in_max[i] =
w83627hf_read_value(client,
W83781D_REG_IN_MAX(i));
}
for (i = 1; i <= 3; i++) {
data->fan[i - 1] =
w83627hf_read_value(client, W83781D_REG_FAN(i));
data->fan_min[i - 1] =
w83627hf_read_value(client,
W83781D_REG_FAN_MIN(i));
}
for (i = 1; i <= 3; i++) {
u8 tmp = w83627hf_read_value(client,
W836X7HF_REG_PWM(data->type, i));
/* bits 0-3 are reserved in 627THF */
if (data->type == w83627thf)
tmp &= 0xf0;
data->pwm[i - 1] = tmp;
if(i == 2 &&
(data->type == w83627hf || data->type == w83697hf))
break;
}
data->temp = w83627hf_read_value(client, W83781D_REG_TEMP(1));
data->temp_max =
w83627hf_read_value(client, W83781D_REG_TEMP_OVER(1));
data->temp_max_hyst =
w83627hf_read_value(client, W83781D_REG_TEMP_HYST(1));
data->temp_add[0] =
w83627hf_read_value(client, W83781D_REG_TEMP(2));
data->temp_max_add[0] =
w83627hf_read_value(client, W83781D_REG_TEMP_OVER(2));
data->temp_max_hyst_add[0] =
w83627hf_read_value(client, W83781D_REG_TEMP_HYST(2));
if (data->type != w83697hf) {
data->temp_add[1] =
w83627hf_read_value(client, W83781D_REG_TEMP(3));
data->temp_max_add[1] =
w83627hf_read_value(client, W83781D_REG_TEMP_OVER(3));
data->temp_max_hyst_add[1] =
w83627hf_read_value(client, W83781D_REG_TEMP_HYST(3));
}
i = w83627hf_read_value(client, W83781D_REG_VID_FANDIV);
data->fan_div[0] = (i >> 4) & 0x03;
data->fan_div[1] = (i >> 6) & 0x03;
if (data->type != w83697hf) {
data->fan_div[2] = (w83627hf_read_value(client,
W83781D_REG_PIN) >> 6) & 0x03;
}
i = w83627hf_read_value(client, W83781D_REG_VBAT);
data->fan_div[0] |= (i >> 3) & 0x04;
data->fan_div[1] |= (i >> 4) & 0x04;
if (data->type != w83697hf)
data->fan_div[2] |= (i >> 5) & 0x04;
data->alarms =
w83627hf_read_value(client, W83781D_REG_ALARM1) |
(w83627hf_read_value(client, W83781D_REG_ALARM2) << 8) |
(w83627hf_read_value(client, W83781D_REG_ALARM3) << 16);
i = w83627hf_read_value(client, W83781D_REG_BEEP_INTS2);
data->beep_enable = i >> 7;
data->beep_mask = ((i & 0x7f) << 8) |
w83627hf_read_value(client, W83781D_REG_BEEP_INTS1) |
w83627hf_read_value(client, W83781D_REG_BEEP_INTS3) << 16;
data->last_updated = jiffies;
data->valid = 1;
}
up(&data->update_lock);
return data;
}
static int __init sensors_w83627hf_init(void)
{
int addr;
if (w83627hf_find(&addr)) {
return -ENODEV;
}
normal_isa[0] = addr;
return i2c_add_driver(&w83627hf_driver);
}
static void __exit sensors_w83627hf_exit(void)
{
i2c_del_driver(&w83627hf_driver);
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
"Philip Edelbrock <phil@netroedge.com>, "
"and Mark Studebaker <mdsxyz123@yahoo.com>");
MODULE_DESCRIPTION("W83627HF driver");
MODULE_LICENSE("GPL");
module_init(sensors_w83627hf_init);
module_exit(sensors_w83627hf_exit);
......@@ -25,8 +25,7 @@
Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
as99127f 7 3 1? 3 0x31 0x12c3 yes no
as99127f rev.2 (type_name = 1299127f) 0x31 0x5ca3 yes no
asb100 "bach" (type_name = as99127f) 0x31 0x0694 yes no
as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no
w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes
w83627hf 9 3 2 3 0x21 0x5ca3 yes yes(LPC)
w83627thf 9 3 2 3 0x90 0x5ca3 no yes(LPC)
......@@ -37,10 +36,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -248,10 +243,10 @@ struct w83781d_data {
u8 fan_min[3]; /* Register value */
u8 temp;
u8 temp_max; /* Register value */
u8 temp_hyst; /* Register value */
u8 temp_max_hyst; /* Register value */
u16 temp_add[2]; /* Register value */
u16 temp_max_add[2]; /* Register value */
u16 temp_hyst_add[2]; /* Register value */
u16 temp_max_hyst_add[2]; /* Register value */
u8 fan_div[3]; /* Register encoding, shifted right */
u8 vid; /* Register encoding, combined */
u32 alarms; /* Register encoding, combined */
......@@ -277,7 +272,7 @@ static int w83781d_detach_client(struct i2c_client *client);
static int w83781d_read_value(struct i2c_client *client, u16 register);
static int w83781d_write_value(struct i2c_client *client, u16 register,
u16 value);
static void w83781d_update_client(struct i2c_client *client);
static struct w83781d_data *w83781d_update_device(struct device *dev);
static void w83781d_init_client(struct i2c_client *client);
static inline u16 swap_bytes(u16 val)
......@@ -298,11 +293,7 @@ static struct i2c_driver w83781d_driver = {
#define show_in_reg(reg) \
static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct w83781d_data *data = i2c_get_clientdata(client); \
\
w83781d_update_client(client); \
\
struct w83781d_data *data = w83781d_update_device(dev); \
return sprintf(buf,"%ld\n", (long)IN_FROM_REG(data->reg[nr] * 10)); \
}
show_in_reg(in);
......@@ -331,7 +322,7 @@ show_regs_in_##offset (struct device *dev, char *buf) \
{ \
return show_in(dev, buf, 0x##offset); \
} \
static DEVICE_ATTR(in_input##offset, S_IRUGO, show_regs_in_##offset, NULL)
static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL)
#define sysfs_in_reg_offset(reg, offset) \
static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \
......@@ -342,7 +333,7 @@ static ssize_t store_regs_in_##reg##offset (struct device *dev, const char *buf,
{ \
return store_in_##reg (dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(in_##reg##offset, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset)
static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset)
#define sysfs_in_offsets(offset) \
sysfs_in_offset(offset); \
......@@ -361,19 +352,15 @@ sysfs_in_offsets(8);
#define device_create_file_in(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_in_input##offset); \
device_create_file(&client->dev, &dev_attr_in_min##offset); \
device_create_file(&client->dev, &dev_attr_in_max##offset); \
device_create_file(&client->dev, &dev_attr_in##offset##_input); \
device_create_file(&client->dev, &dev_attr_in##offset##_min); \
device_create_file(&client->dev, &dev_attr_in##offset##_max); \
} while (0)
#define show_fan_reg(reg) \
static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct w83781d_data *data = i2c_get_clientdata(client); \
\
w83781d_update_client(client); \
\
struct w83781d_data *data = w83781d_update_device(dev); \
return sprintf(buf,"%ld\n", \
FAN_FROM_REG(data->reg[nr-1], (long)DIV_FROM_REG(data->fan_div[nr-1]))); \
}
......@@ -401,7 +388,7 @@ static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \
{ \
return show_fan(dev, buf, 0x##offset); \
} \
static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_regs_fan_##offset, NULL)
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL)
#define sysfs_fan_min_offset(offset) \
static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \
......@@ -412,7 +399,7 @@ static ssize_t store_regs_fan_min##offset (struct device *dev, const char *buf,
{ \
return store_fan_min(dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset)
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset)
sysfs_fan_offset(1);
sysfs_fan_min_offset(1);
......@@ -423,18 +410,14 @@ sysfs_fan_min_offset(3);
#define device_create_file_fan(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_fan_input##offset); \
device_create_file(&client->dev, &dev_attr_fan_min##offset); \
device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
} while (0)
#define show_temp_reg(reg) \
static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct w83781d_data *data = i2c_get_clientdata(client); \
\
w83781d_update_client(client); \
\
struct w83781d_data *data = w83781d_update_device(dev); \
if (nr >= 2) { /* TEMP2 and TEMP3 */ \
if (data->type == as99127f) { \
return sprintf(buf,"%ld\n", \
......@@ -449,7 +432,7 @@ static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
}
show_temp_reg(temp);
show_temp_reg(temp_max);
show_temp_reg(temp_hyst);
show_temp_reg(temp_max_hyst);
#define store_temp_reg(REG, reg) \
static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
......@@ -477,7 +460,7 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou
return count; \
}
store_temp_reg(OVER, max);
store_temp_reg(HYST, hyst);
store_temp_reg(HYST, max_hyst);
#define sysfs_temp_offset(offset) \
static ssize_t \
......@@ -485,7 +468,7 @@ show_regs_temp_##offset (struct device *dev, char *buf) \
{ \
return show_temp(dev, buf, 0x##offset); \
} \
static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_regs_temp_##offset, NULL)
static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL)
#define sysfs_temp_reg_offset(reg, offset) \
static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \
......@@ -496,12 +479,12 @@ static ssize_t store_regs_temp_##reg##offset (struct device *dev, const char *bu
{ \
return store_temp_##reg (dev, buf, count, 0x##offset); \
} \
static DEVICE_ATTR(temp_##reg##offset, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset)
static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset)
#define sysfs_temp_offsets(offset) \
sysfs_temp_offset(offset); \
sysfs_temp_reg_offset(max, offset); \
sysfs_temp_reg_offset(hyst, offset);
sysfs_temp_reg_offset(max_hyst, offset);
sysfs_temp_offsets(1);
sysfs_temp_offsets(2);
......@@ -509,34 +492,26 @@ sysfs_temp_offsets(3);
#define device_create_file_temp(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_temp_input##offset); \
device_create_file(&client->dev, &dev_attr_temp_max##offset); \
device_create_file(&client->dev, &dev_attr_temp_hyst##offset); \
device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
device_create_file(&client->dev, &dev_attr_temp##offset##_max); \
device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \
} while (0)
static ssize_t
show_vid_reg(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
w83781d_update_client(client);
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
}
static
DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL)
DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL)
#define device_create_file_vid(client) \
device_create_file(&client->dev, &dev_attr_vid);
device_create_file(&client->dev, &dev_attr_in0_ref);
static ssize_t
show_vrm_reg(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
w83781d_update_client(client);
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->vrm);
}
......@@ -560,11 +535,7 @@ device_create_file(&client->dev, &dev_attr_vrm);
static ssize_t
show_alarms_reg(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
w83781d_update_client(client);
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
}
......@@ -575,11 +546,7 @@ device_create_file(&client->dev, &dev_attr_alarms);
#define show_beep_reg(REG, reg) \
static ssize_t show_beep_##reg (struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct w83781d_data *data = i2c_get_clientdata(client); \
\
w83781d_update_client(client); \
\
struct w83781d_data *data = w83781d_update_device(dev); \
return sprintf(buf,"%ld\n", (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \
}
show_beep_reg(ENABLE, enable);
......@@ -640,62 +607,114 @@ device_create_file(&client->dev, &dev_attr_beep_enable); \
device_create_file(&client->dev, &dev_attr_beep_mask); \
} while (0)
/* w83697hf only has two fans */
static ssize_t
show_fan_div_reg(struct device *dev, char *buf, int nr)
{
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n",
(long) DIV_FROM_REG(data->fan_div[nr - 1]));
}
/* Note: we save and restore the fan minimum here, because its value is
determined in part by the fan divisor. This follows the principle of
least suprise; the user doesn't expect the fan minimum to change just
because the divisor changed. */
static ssize_t
store_regs_fan_div_1(struct device *dev, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
unsigned long min;
u8 reg;
w83781d_update_client(client);
/* Save fan_min */
min = FAN_FROM_REG(data->fan_min[0],
DIV_FROM_REG(data->fan_div[0]));
return sprintf(buf, "%ld\n",
(long) DIV_FROM_REG(data->fan_div[nr - 1]));
data->fan_div[0] = DIV_TO_REG(simple_strtoul(buf, NULL, 10),
data->type);
reg = w83781d_read_value(client, W83781D_REG_VID_FANDIV) & 0xcf;
reg |= (data->fan_div[0] & 0x03) << 4;
w83781d_write_value(client, W83781D_REG_VID_FANDIV, reg);
/* w83781d and as99127f don't have extended divisor bits */
if (data->type != w83781d && data->type != as99127f) {
reg = w83781d_read_value(client, W83781D_REG_VBAT) & 0xdf;
reg |= (data->fan_div[0] & 0x04) << 3;
w83781d_write_value(client, W83781D_REG_VBAT, reg);
}
/* Restore fan_min */
data->fan_min[0] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[0]));
w83781d_write_value(client, W83781D_REG_FAN_MIN(1), data->fan_min[0]);
return count;
}
/* w83697hf only has two fans */
static ssize_t
store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
store_regs_fan_div_2(struct device *dev, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
u32 val, old, old2, old3 = 0;
unsigned long min;
u8 reg;
val = simple_strtoul(buf, NULL, 10);
old = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
/* Save fan_min */
min = FAN_FROM_REG(data->fan_min[1],
DIV_FROM_REG(data->fan_div[1]));
data->fan_div[nr - 1] = DIV_TO_REG(val, data->type);
data->fan_div[1] = DIV_TO_REG(simple_strtoul(buf, NULL, 10),
data->type);
reg = w83781d_read_value(client, W83781D_REG_VID_FANDIV) & 0x3f;
reg |= (data->fan_div[1] & 0x03) << 6;
w83781d_write_value(client, W83781D_REG_VID_FANDIV, reg);
/* w83781d and as99127f don't have extended divisor bits */
if ((data->type != w83781d) && data->type != as99127f) {
old3 = w83781d_read_value(client, W83781D_REG_VBAT);
if (data->type != w83781d && data->type != as99127f) {
reg = w83781d_read_value(client, W83781D_REG_VBAT) & 0xbf;
reg |= (data->fan_div[1] & 0x04) << 4;
w83781d_write_value(client, W83781D_REG_VBAT, reg);
}
if (nr >= 3 && data->type != w83697hf) {
old2 = w83781d_read_value(client, W83781D_REG_PIN);
old2 = (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6);
w83781d_write_value(client, W83781D_REG_PIN, old2);
if ((data->type != w83781d) && (data->type != as99127f)) {
old3 = (old3 & 0x7f) | ((data->fan_div[2] & 0x04) << 5);
}
}
if (nr >= 2) {
old = (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
/* Restore fan_min */
data->fan_min[1] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[1]));
w83781d_write_value(client, W83781D_REG_FAN_MIN(2), data->fan_min[1]);
if ((data->type != w83781d) && (data->type != as99127f)) {
old3 = (old3 & 0xbf) | ((data->fan_div[1] & 0x04) << 4);
}
}
if (nr >= 1) {
old = (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
w83781d_write_value(client, W83781D_REG_VID_FANDIV, old);
return count;
}
if ((data->type != w83781d) && (data->type != as99127f)) {
old3 = (old3 & 0xdf) | ((data->fan_div[0] & 0x04) << 3);
w83781d_write_value(client, W83781D_REG_VBAT, old3);
}
static ssize_t
store_regs_fan_div_3(struct device *dev, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
unsigned long min;
u8 reg;
/* Save fan_min */
min = FAN_FROM_REG(data->fan_min[2],
DIV_FROM_REG(data->fan_div[2]));
data->fan_div[2] = DIV_TO_REG(simple_strtoul(buf, NULL, 10),
data->type);
reg = w83781d_read_value(client, W83781D_REG_PIN) & 0x3f;
reg |= (data->fan_div[2] & 0x03) << 6;
w83781d_write_value(client, W83781D_REG_PIN, reg);
/* w83781d and as99127f don't have extended divisor bits */
if (data->type != w83781d && data->type != as99127f) {
reg = w83781d_read_value(client, W83781D_REG_VBAT) & 0x7f;
reg |= (data->fan_div[2] & 0x04) << 5;
w83781d_write_value(client, W83781D_REG_VBAT, reg);
}
/* Restore fan_min */
data->fan_min[2] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[2]));
w83781d_write_value(client, W83781D_REG_FAN_MIN(3), data->fan_min[2]);
return count;
}
......@@ -704,11 +723,7 @@ static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \
{ \
return show_fan_div_reg(dev, buf, offset); \
} \
static ssize_t store_regs_fan_div_##offset (struct device *dev, const char *buf, size_t count) \
{ \
return store_fan_div_reg(dev, buf, count, offset); \
} \
static DEVICE_ATTR(fan_div##offset, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset)
static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset)
sysfs_fan_div(1);
sysfs_fan_div(2);
......@@ -716,18 +731,14 @@ sysfs_fan_div(3);
#define device_create_file_fan_div(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_fan_div##offset); \
device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
} while (0)
/* w83697hf only has two fans */
static ssize_t
show_pwm_reg(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
w83781d_update_client(client);
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr - 1]));
}
......@@ -735,11 +746,7 @@ show_pwm_reg(struct device *dev, char *buf, int nr)
static ssize_t
show_pwmenable_reg(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
w83781d_update_client(client);
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->pwmenable[nr - 1]);
}
......@@ -809,7 +816,7 @@ static ssize_t store_regs_pwm_##offset (struct device *dev, const char *buf, siz
{ \
return store_pwm_reg(dev, buf, count, offset); \
} \
static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, show_regs_pwm_##offset, store_regs_pwm_##offset)
static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, show_regs_pwm_##offset, store_regs_pwm_##offset)
#define sysfs_pwmenable(offset) \
static ssize_t show_regs_pwmenable_##offset (struct device *dev, char *buf) \
......@@ -820,7 +827,7 @@ static ssize_t store_regs_pwmenable_##offset (struct device *dev, const char *bu
{ \
return store_pwmenable_reg(dev, buf, count, offset); \
} \
static DEVICE_ATTR(pwm_enable##offset, S_IRUGO | S_IWUSR, show_regs_pwmenable_##offset, store_regs_pwmenable_##offset)
static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO | S_IWUSR, show_regs_pwmenable_##offset, store_regs_pwmenable_##offset)
sysfs_pwm(1);
sysfs_pwm(2);
......@@ -830,22 +837,18 @@ sysfs_pwm(4);
#define device_create_file_pwm(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_pwm##offset); \
device_create_file(&client->dev, &dev_attr_fan##offset##_pwm); \
} while (0)
#define device_create_file_pwmenable(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_pwm_enable##offset); \
device_create_file(&client->dev, &dev_attr_fan##offset##_pwm_enable); \
} while (0)
static ssize_t
show_sensor_reg(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
w83781d_update_client(client);
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->sens[nr - 1]);
}
......@@ -902,7 +905,7 @@ static ssize_t store_regs_sensor_##offset (struct device *dev, const char *buf,
{ \
return store_sensor_reg(dev, buf, count, offset); \
} \
static DEVICE_ATTR(sensor##offset, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset)
static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset)
sysfs_sensor(1);
sysfs_sensor(2);
......@@ -910,19 +913,16 @@ sysfs_sensor(3);
#define device_create_file_sensor(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_sensor##offset); \
device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
} while (0)
#ifdef W83781D_RT
static ssize_t
show_rt_reg(struct device *dev, char *buf, int nr)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
struct w83781d_data *data = w83781d_update_device(dev);
int i, j = 0;
w83781d_update_client(client);
for (i = 0; i < 32; i++) {
if (i > 0)
j += sprintf(buf, " %ld", (long) data->rt[nr - 1][i]);
......@@ -997,7 +997,7 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
{
int i, val1 = 0, id;
int err;
const char *client_name;
const char *client_name = "";
struct w83781d_data *data = i2c_get_clientdata(new_client);
data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
......@@ -1063,8 +1063,6 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
client_name = "w83627hf subclient";
else if (kind == as99127f)
client_name = "as99127f subclient";
else
client_name = "unknown subclient?";
for (i = 0; i <= 1; i++) {
/* store all data in w83781d */
......@@ -1118,6 +1116,23 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
goto ERROR0;
}
/* Prevent users from forcing a kind for a bus it isn't supposed
to possibly be on */
if (is_isa && (kind == as99127f || kind == w83783s)) {
dev_err(&adapter->dev,
"Cannot force I2C-only chip for ISA address 0x%02x.\n",
address);
err = -EINVAL;
goto ERROR0;
}
if (!is_isa && kind == w83697hf) {
dev_err(&adapter->dev,
"Cannot force ISA-only chip for I2C address 0x%02x.\n",
address);
err = -EINVAL;
goto ERROR0;
}
if (is_isa)
if (!request_region(address, W83781D_EXTENT, "w83781d")) {
err = -EBUSY;
......@@ -1194,10 +1209,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
/* Check for Winbond or Asus ID if in bank 0 */
if ((!(val1 & 0x07)) &&
(((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)
&& (val2 != 0x94))
|| ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)
&& (val2 != 0x06)))) {
(((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
|| ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
err = -ENODEV;
goto ERROR2;
}
......@@ -1226,7 +1239,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
if (val2 == 0x5c)
vendid = winbond;
else if ((val2 == 0x12) || (val2 == 0x06))
else if (val2 == 0x12)
vendid = asus;
else {
err = -ENODEV;
......@@ -1273,11 +1286,6 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
client_name = "as99127f";
} else if (kind == w83697hf) {
client_name = "w83697hf";
} else {
dev_err(&new_client->dev, "Internal error: unknown "
"kind (%d)?!?", kind);
err = -ENODEV;
goto ERROR2;
}
/* Fill in the remaining client fields and put into the global list */
......@@ -1632,7 +1640,11 @@ w83781d_init_client(struct i2c_client *client)
if (type != w83781d) {
/* enable comparator mode for temp2 and temp3 so
alarm indication will work correctly */
w83781d_write_value(client, W83781D_REG_IRQ, 0x41);
i = w83781d_read_value(client, W83781D_REG_IRQ);
if (!(i & 0x40))
w83781d_write_value(client, W83781D_REG_IRQ,
i | 0x40);
for (i = 0; i < 3; i++)
data->pwmenable[i] = 1;
}
......@@ -1645,9 +1657,9 @@ w83781d_init_client(struct i2c_client *client)
| 0x01);
}
static void
w83781d_update_client(struct i2c_client *client)
static struct w83781d_data *w83781d_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
int i;
......@@ -1697,13 +1709,13 @@ w83781d_update_client(struct i2c_client *client)
data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1));
data->temp_max =
w83781d_read_value(client, W83781D_REG_TEMP_OVER(1));
data->temp_hyst =
data->temp_max_hyst =
w83781d_read_value(client, W83781D_REG_TEMP_HYST(1));
data->temp_add[0] =
w83781d_read_value(client, W83781D_REG_TEMP(2));
data->temp_max_add[0] =
w83781d_read_value(client, W83781D_REG_TEMP_OVER(2));
data->temp_hyst_add[0] =
data->temp_max_hyst_add[0] =
w83781d_read_value(client, W83781D_REG_TEMP_HYST(2));
if (data->type != w83783s && data->type != w83697hf) {
data->temp_add[1] =
......@@ -1711,7 +1723,7 @@ w83781d_update_client(struct i2c_client *client)
data->temp_max_add[1] =
w83781d_read_value(client,
W83781D_REG_TEMP_OVER(3));
data->temp_hyst_add[1] =
data->temp_max_hyst_add[1] =
w83781d_read_value(client,
W83781D_REG_TEMP_HYST(3));
}
......@@ -1760,6 +1772,8 @@ w83781d_update_client(struct i2c_client *client)
}
up(&data->update_lock);
return data;
}
static int __init
......
......@@ -12,6 +12,9 @@
* Ported to Linux 2.6 by Wolfgang Ziegler <nuppla@gmx.at> and Jean Delvare
* <khali@linux-fr.org>.
*
* Thanks to James Bolt <james@evilpenguin.com> for benchmarking the read
* error handling mechanism.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
......@@ -28,10 +31,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CHIP
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -86,7 +85,7 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address,
int kind);
static int w83l785ts_detach_client(struct i2c_client *client);
static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval);
static void w83l785ts_update_client(struct i2c_client *client);
static struct w83l785ts_data *w83l785ts_update_device(struct device *dev);
/*
* Driver data (common to all clients)
......@@ -127,22 +126,18 @@ static int w83l785ts_id = 0;
static ssize_t show_temp(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83l785ts_data *data = i2c_get_clientdata(client);
w83l785ts_update_client(client);
struct w83l785ts_data *data = w83l785ts_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
}
static ssize_t show_temp_over(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83l785ts_data *data = i2c_get_clientdata(client);
w83l785ts_update_client(client);
struct w83l785ts_data *data = w83l785ts_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
}
static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp, NULL)
static DEVICE_ATTR(temp_max1, S_IRUGO, show_temp_over, NULL)
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL)
static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_over, NULL)
/*
* Real code
......@@ -164,7 +159,6 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
struct i2c_client *new_client;
struct w83l785ts_data *data;
int err = 0;
const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
......@@ -225,7 +219,6 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
if (man_id == 0x5CA3) { /* Winbond */
if (chip_id == 0x70) { /* W83L785TS-S */
kind = w83l785ts;
name = "w83l785ts";
}
}
......@@ -238,7 +231,7 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* We can fill in the remaining client fields. */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE);
new_client->id = w83l785ts_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
......@@ -256,8 +249,8 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
*/
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp1_max);
return 0;
......@@ -301,8 +294,9 @@ static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval)
return defval;
}
static void w83l785ts_update_client(struct i2c_client *client)
static struct w83l785ts_data *w83l785ts_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83l785ts_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
......@@ -321,6 +315,8 @@ static void w83l785ts_update_client(struct i2c_client *client)
}
up(&data->update_lock);
return data;
}
static int __init sensors_w83l785ts_init(void)
......
......@@ -22,10 +22,6 @@
SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CORE
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
......@@ -175,7 +171,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
driver = list_entry(item, struct i2c_driver, list);
if (driver->detach_adapter)
if ((res = driver->detach_adapter(adap))) {
dev_warn(&adap->dev, "can't detach adapter"
dev_warn(&adap->dev, "can't detach adapter "
"while detaching driver %s: driver not "
"detached!", driver->name);
goto out_unlock;
......@@ -437,8 +433,11 @@ static void i2c_dec_use_client(struct i2c_client *client)
int i2c_use_client(struct i2c_client *client)
{
if (!i2c_inc_use_client(client))
return -ENODEV;
int ret;
ret = i2c_inc_use_client(client);
if (ret)
return ret;
if (client->flags & I2C_CLIENT_ALLOW_USE) {
if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
......@@ -618,7 +617,7 @@ int i2c_control(struct i2c_client *client,
int ret = 0;
struct i2c_adapter *adap = client->adapter;
dev_dbg(&client->dev, "i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg);
dev_dbg(&client->adapter->dev, "i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg);
switch (cmd) {
case I2C_RETRIES:
adap->retries = arg;
......
......@@ -30,10 +30,6 @@
<pmhahn@titan.lahn.de> */
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CORE
#define DEBUG 1
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
......@@ -72,24 +68,18 @@ struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev = NULL;
int i;
spin_lock(&i2c_dev_array_lock);
for (i = 0; i < I2C_MINORS; ++i) {
if ((i2c_dev_array[i]) &&
(i2c_dev_array[i]->adap == adap)) {
i2c_dev = i2c_dev_array[i];
break;
}
}
if ((i2c_dev_array[adap->nr]) &&
(i2c_dev_array[adap->nr]->adap == adap))
i2c_dev = i2c_dev_array[adap->nr];
spin_unlock(&i2c_dev_array_lock);
return i2c_dev;
}
static struct i2c_dev *get_free_i2c_dev(void)
static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev;
unsigned int i;
i2c_dev = kmalloc(sizeof(*i2c_dev), GFP_KERNEL);
if (!i2c_dev)
......@@ -97,15 +87,16 @@ static struct i2c_dev *get_free_i2c_dev(void)
memset(i2c_dev, 0x00, sizeof(*i2c_dev));
spin_lock(&i2c_dev_array_lock);
for (i = 0; i < I2C_MINORS; ++i) {
if (i2c_dev_array[i])
continue;
i2c_dev->minor = i;
i2c_dev_array[i] = i2c_dev;
if (i2c_dev_array[adap->nr]) {
spin_unlock(&i2c_dev_array_lock);
return i2c_dev;
dev_err(&adap->dev, "i2c-dev already has a device assigned to this adapter\n");
goto error;
}
i2c_dev->minor = adap->nr;
i2c_dev_array[adap->nr] = i2c_dev;
spin_unlock(&i2c_dev_array_lock);
return i2c_dev;
error:
kfree(i2c_dev);
return ERR_PTR(-ENODEV);
}
......@@ -124,6 +115,13 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
}
static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
{
struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
return sprintf(buf, "%s\n", i2c_dev->adap->name);
}
static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
loff_t *offset)
{
......@@ -187,7 +185,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
int i,datasize,res;
unsigned long funcs;
dev_dbg(&client->dev, "i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
dev_dbg(&client->adapter->dev, "i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
iminor(inode),cmd, arg);
switch ( cmd ) {
......@@ -308,7 +306,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
(data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
dev_dbg(&client->dev,
dev_dbg(&client->adapter->dev,
"size out of range (%x) in ioctl I2C_SMBUS.\n",
data_arg.size);
return -EINVAL;
......@@ -317,7 +315,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
so the check is valid if size==I2C_SMBUS_QUICK too. */
if ((data_arg.read_write != I2C_SMBUS_READ) &&
(data_arg.read_write != I2C_SMBUS_WRITE)) {
dev_dbg(&client->dev,
dev_dbg(&client->adapter->dev,
"read_write out of range (%x) in ioctl I2C_SMBUS.\n",
data_arg.read_write);
return -EINVAL;
......@@ -336,7 +334,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
data_arg.size, NULL);
if (data_arg.data == NULL) {
dev_dbg(&client->dev,
dev_dbg(&client->adapter->dev,
"data is NULL pointer in ioctl I2C_SMBUS.\n");
return -EINVAL;
}
......@@ -439,7 +437,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
struct i2c_dev *i2c_dev;
int retval;
i2c_dev = get_free_i2c_dev();
i2c_dev = get_free_i2c_dev(adap);
if (IS_ERR(i2c_dev))
return PTR_ERR(i2c_dev);
......@@ -459,6 +457,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
if (retval)
goto error;
class_device_create_file(&i2c_dev->class_dev, &class_device_attr_dev);
class_device_create_file(&i2c_dev->class_dev, &class_device_attr_name);
return 0;
error:
return_i2c_dev(i2c_dev);
......
......@@ -20,10 +20,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_I2C_DEBUG_CORE
#define DEBUG 1
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
......
......@@ -760,7 +760,7 @@ static int __devinitdata sis_96x_compatible = 0;
#define SIS_DETECT_REGISTER 0x40
static void __init quirk_sis_503_smbus(struct pci_dev *dev)
static void __init quirk_sis_503(struct pci_dev *dev)
{
u8 reg;
u16 devid;
......@@ -768,7 +768,7 @@ static void __init quirk_sis_503_smbus(struct pci_dev *dev)
pci_read_config_byte(dev, SIS_DETECT_REGISTER, &reg);
pci_write_config_byte(dev, SIS_DETECT_REGISTER, reg | (1 << 6));
pci_read_config_word(dev, PCI_DEVICE_ID, &devid);
if ((devid & 0xfff0) != 0x0960) {
if (((devid & 0xfff0) != 0x0960) && (devid != 0x0018)) {
pci_write_config_byte(dev, SIS_DETECT_REGISTER, reg);
return;
}
......@@ -905,12 +905,14 @@ static struct pci_fixup pci_fixups[] __devinitdata = {
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503_smbus },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_645, quirk_sis_96x_compatible },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_646, quirk_sis_96x_compatible },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_648, quirk_sis_96x_compatible },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650, quirk_sis_96x_compatible },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_compatible },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus },
......
......@@ -569,6 +569,7 @@
#define PCI_DEVICE_ID_SI_6202 0x0002
#define PCI_DEVICE_ID_SI_503 0x0008
#define PCI_DEVICE_ID_SI_ACPI 0x0009
#define PCI_DEVICE_ID_SI_LPC 0x0018
#define PCI_DEVICE_ID_SI_5597_VGA 0x0200
#define PCI_DEVICE_ID_SI_6205 0x0205
#define PCI_DEVICE_ID_SI_501 0x0406
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment