mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 13:34:10 +08:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6
This commit is contained in:
commit
8566cfc9fe
@ -2,16 +2,11 @@ Kernel driver lm78
|
||||
==================
|
||||
|
||||
Supported chips:
|
||||
* National Semiconductor LM78
|
||||
* National Semiconductor LM78 / LM78-J
|
||||
Prefix: 'lm78'
|
||||
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
||||
Datasheet: Publicly available at the National Semiconductor website
|
||||
http://www.national.com/
|
||||
* National Semiconductor LM78-J
|
||||
Prefix: 'lm78-j'
|
||||
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
||||
Datasheet: Publicly available at the National Semiconductor website
|
||||
http://www.national.com/
|
||||
* National Semiconductor LM79
|
||||
Prefix: 'lm79'
|
||||
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
||||
|
174
Documentation/hwmon/w83792d
Normal file
174
Documentation/hwmon/w83792d
Normal file
@ -0,0 +1,174 @@
|
||||
Kernel driver w83792d
|
||||
=====================
|
||||
|
||||
Supported chips:
|
||||
* Winbond W83792D
|
||||
Prefix: 'w83792d'
|
||||
Addresses scanned: I2C 0x2c - 0x2f
|
||||
Datasheet: http://www.winbond.com.tw/E-WINBONDHTM/partner/PDFresult.asp?Pname=1035
|
||||
|
||||
Author: Chunhao Huang
|
||||
Contact: DZShen <DZShen@Winbond.com.tw>
|
||||
|
||||
|
||||
Module Parameters
|
||||
-----------------
|
||||
|
||||
* init int
|
||||
(default 1)
|
||||
Use 'init=0' to bypass initializing the chip.
|
||||
Try this if your computer crashes when you load the module.
|
||||
|
||||
* force_subclients=bus,caddr,saddr,saddr
|
||||
This is used to force the i2c addresses for subclients of
|
||||
a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b'
|
||||
to force the subclients of chip 0x2f on bus 0 to i2c addresses
|
||||
0x4a and 0x4b.
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for the Winbond W83792AD/D.
|
||||
|
||||
Detection of the chip can sometimes be foiled because it can be in an
|
||||
internal state that allows no clean access (Bank with ID register is not
|
||||
currently selected). If you know the address of the chip, use a 'force'
|
||||
parameter; this will put it into a more well-behaved state first.
|
||||
|
||||
The driver implements three temperature sensors, seven fan rotation speed
|
||||
sensors, nine voltage sensors, and two automatic fan regulation
|
||||
strategies called: Smart Fan I (Thermal Cruise mode) and Smart Fan II.
|
||||
Automatic fan control mode is possible only for fan1-fan3. Fan4-fan7 can run
|
||||
synchronized with selected fan (fan1-fan3). This functionality and manual PWM
|
||||
control for fan4-fan7 is not yet implemented.
|
||||
|
||||
Temperatures are measured in degrees Celsius and measurement resolution is 1
|
||||
degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
|
||||
the temperature gets higher than the Overtemperature Shutdown value; it stays
|
||||
on until the temperature falls below the Hysteresis value.
|
||||
|
||||
Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
|
||||
triggered if the rotation speed has dropped below a programmable limit. Fan
|
||||
readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or
|
||||
128) to give the readings more range or accuracy.
|
||||
|
||||
Voltage sensors (also known as IN sensors) report their values in millivolts.
|
||||
An alarm is triggered if the voltage has crossed a programmable minimum
|
||||
or maximum limit.
|
||||
|
||||
Alarms are provided as output from "realtime status register". Following bits
|
||||
are defined:
|
||||
|
||||
bit - alarm on:
|
||||
0 - in0
|
||||
1 - in1
|
||||
2 - temp1
|
||||
3 - temp2
|
||||
4 - temp3
|
||||
5 - fan1
|
||||
6 - fan2
|
||||
7 - fan3
|
||||
8 - in2
|
||||
9 - in3
|
||||
10 - in4
|
||||
11 - in5
|
||||
12 - in6
|
||||
13 - VID change
|
||||
14 - chassis
|
||||
15 - fan7
|
||||
16 - tart1
|
||||
17 - tart2
|
||||
18 - tart3
|
||||
19 - in7
|
||||
20 - in8
|
||||
21 - fan4
|
||||
22 - fan5
|
||||
23 - fan6
|
||||
|
||||
Tart will be asserted while target temperature cannot be achieved after 3 minutes
|
||||
of full speed rotation of corresponding fan.
|
||||
|
||||
In addition to the alarms described above, there is a CHAS alarm on the chips
|
||||
which triggers if your computer case is open (This one is latched, contrary
|
||||
to realtime alarms).
|
||||
|
||||
The chips only update values each 3 seconds; reading them more often will
|
||||
do no harm, but will return 'old' values.
|
||||
|
||||
|
||||
W83792D PROBLEMS
|
||||
----------------
|
||||
Known problems:
|
||||
- This driver is only for Winbond W83792D C version device, there
|
||||
are also some motherboards with B version W83792D device. The
|
||||
calculation method to in6-in7(measured value, limits) is a little
|
||||
different between C and B version. C or B version can be identified
|
||||
by CR[0x49h].
|
||||
- The function of vid and vrm has not been finished, because I'm NOT
|
||||
very familiar with them. Adding support is welcome.
|
||||
- The function of chassis open detection needs more tests.
|
||||
- If you have ASUS server board and chip was not found: Then you will
|
||||
need to upgrade to latest (or beta) BIOS. If it does not help please
|
||||
contact us.
|
||||
|
||||
Fan control
|
||||
-----------
|
||||
|
||||
Manual mode
|
||||
-----------
|
||||
|
||||
Works as expected. You just need to specify desired PWM/DC value (fan speed)
|
||||
in appropriate pwm# file.
|
||||
|
||||
Thermal cruise
|
||||
--------------
|
||||
|
||||
In this mode, W83792D provides the Smart Fan system to automatically control
|
||||
fan speed to keep the temperatures of CPU and the system within specific
|
||||
range. At first a wanted temperature and interval must be set. This is done
|
||||
via thermal_cruise# file. The tolerance# file serves to create T +- tolerance
|
||||
interval. The fan speed will be lowered as long as the current temperature
|
||||
remains below the thermal_cruise# +- tolerance# value. Once the temperature
|
||||
exceeds the high limit (T+tolerance), the fan will be turned on with a
|
||||
specific speed set by pwm# and automatically controlled its PWM duty cycle
|
||||
with the temperature varying. Three conditions may occur:
|
||||
|
||||
(1) If the temperature still exceeds the high limit, PWM duty
|
||||
cycle will increase slowly.
|
||||
|
||||
(2) If the temperature goes below the high limit, but still above the low
|
||||
limit (T-tolerance), the fan speed will be fixed at the current speed because
|
||||
the temperature is in the target range.
|
||||
|
||||
(3) If the temperature goes below the low limit, PWM duty cycle will decrease
|
||||
slowly to 0 or a preset stop value until the temperature exceeds the low
|
||||
limit. (The preset stop value handling is not yet implemented in driver)
|
||||
|
||||
Smart Fan II
|
||||
------------
|
||||
|
||||
W83792D also provides a special mode for fan. Four temperature points are
|
||||
available. When related temperature sensors detects the temperature in preset
|
||||
temperature region (sf2_point@_fan# +- tolerance#) it will cause fans to run
|
||||
on programmed value from sf2_level@_fan#. You need to set four temperatures
|
||||
for each fan.
|
||||
|
||||
|
||||
/sys files
|
||||
----------
|
||||
|
||||
pwm[1-3] - this file stores PWM duty cycle or DC value (fan speed) in range:
|
||||
0 (stop) to 255 (full)
|
||||
pwm[1-3]_enable - this file controls mode of fan/temperature control:
|
||||
* 0 Disabled
|
||||
* 1 Manual mode
|
||||
* 2 Smart Fan II
|
||||
* 3 Thermal Cruise
|
||||
pwm[1-3]_mode - Select PWM of DC mode
|
||||
* 0 DC
|
||||
* 1 PWM
|
||||
thermal_cruise[1-3] - Selects the desired temperature for cruise (degC)
|
||||
tolerance[1-3] - Value in degrees of Celsius (degC) for +- T
|
||||
sf2_point[1-4]_fan[1-3] - four temperature points for each fan for Smart Fan II
|
||||
sf2_level[1-3]_fan[1-3] - three PWM/DC levels for each fan for Smart Fan II
|
@ -4,22 +4,13 @@ Kernel driver max6875
|
||||
Supported chips:
|
||||
* Maxim MAX6874, MAX6875
|
||||
Prefix: 'max6875'
|
||||
Addresses scanned: 0x50, 0x52
|
||||
Addresses scanned: None (see below)
|
||||
Datasheet:
|
||||
http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
|
||||
|
||||
Author: Ben Gardner <bgardner@wabtec.com>
|
||||
|
||||
|
||||
Module Parameters
|
||||
-----------------
|
||||
|
||||
* allow_write int
|
||||
Set to non-zero to enable write permission:
|
||||
*0: Read only
|
||||
1: Read and write
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
@ -33,34 +24,85 @@ registers.
|
||||
|
||||
The Maxim MAX6874 is a similar, mostly compatible device, with more intputs
|
||||
and outputs:
|
||||
|
||||
vin gpi vout
|
||||
MAX6874 6 4 8
|
||||
MAX6875 4 3 5
|
||||
|
||||
MAX6874 chips can have four different addresses (as opposed to only two for
|
||||
the MAX6875). The additional addresses (0x54 and 0x56) are not probed by
|
||||
this driver by default, but the probe module parameter can be used if
|
||||
needed.
|
||||
|
||||
See the datasheet for details on how to program the EEPROM.
|
||||
See the datasheet for more information.
|
||||
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
eeprom_user - 512 bytes of user-defined EEPROM space. Only writable if
|
||||
allow_write was set and register 0x43 is 0.
|
||||
|
||||
eeprom_config - 70 bytes of config EEPROM. Note that changes will not get
|
||||
loaded into register space until a power cycle or device reset.
|
||||
|
||||
reg_config - 70 bytes of register space. Any changes take affect immediately.
|
||||
eeprom - 512 bytes of user-defined EEPROM space.
|
||||
|
||||
|
||||
General Remarks
|
||||
---------------
|
||||
|
||||
A typical application will require that the EEPROMs be programmed once and
|
||||
never altered afterwards.
|
||||
Valid addresses for the MAX6875 are 0x50 and 0x52.
|
||||
Valid addresses for the MAX6874 are 0x50, 0x52, 0x54 and 0x56.
|
||||
The driver does not probe any address, so you must force the address.
|
||||
|
||||
Example:
|
||||
$ modprobe max6875 force=0,0x50
|
||||
|
||||
The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple
|
||||
addresses. For example, for address 0x50, it also reserves 0x51.
|
||||
The even-address instance is called 'max6875', the odd one is 'max6875 subclient'.
|
||||
|
||||
|
||||
Programming the chip using i2c-dev
|
||||
----------------------------------
|
||||
|
||||
Use the i2c-dev interface to access and program the chips.
|
||||
Reads and writes are performed differently depending on the address range.
|
||||
|
||||
The configuration registers are at addresses 0x00 - 0x45.
|
||||
Use i2c_smbus_write_byte_data() to write a register and
|
||||
i2c_smbus_read_byte_data() to read a register.
|
||||
The command is the register number.
|
||||
|
||||
Examples:
|
||||
To write a 1 to register 0x45:
|
||||
i2c_smbus_write_byte_data(fd, 0x45, 1);
|
||||
|
||||
To read register 0x45:
|
||||
value = i2c_smbus_read_byte_data(fd, 0x45);
|
||||
|
||||
|
||||
The configuration EEPROM is at addresses 0x8000 - 0x8045.
|
||||
The user EEPROM is at addresses 0x8100 - 0x82ff.
|
||||
|
||||
Use i2c_smbus_write_word_data() to write a byte to EEPROM.
|
||||
|
||||
The command is the upper byte of the address: 0x80, 0x81, or 0x82.
|
||||
The data word is the lower part of the address or'd with data << 8.
|
||||
cmd = address >> 8;
|
||||
val = (address & 0xff) | (data << 8);
|
||||
|
||||
Example:
|
||||
To write 0x5a to address 0x8003:
|
||||
i2c_smbus_write_word_data(fd, 0x80, 0x5a03);
|
||||
|
||||
|
||||
Reading data from the EEPROM is a little more complicated.
|
||||
Use i2c_smbus_write_byte_data() to set the read address and then
|
||||
i2c_smbus_read_byte() or i2c_smbus_read_i2c_block_data() to read the data.
|
||||
|
||||
Example:
|
||||
To read data starting at offset 0x8100, first set the address:
|
||||
i2c_smbus_write_byte_data(fd, 0x81, 0x00);
|
||||
|
||||
And then read the data
|
||||
value = i2c_smbus_read_byte(fd);
|
||||
|
||||
or
|
||||
|
||||
count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer);
|
||||
|
||||
The block read should read 16 bytes.
|
||||
0x84 is the block read command.
|
||||
|
||||
See the datasheet for more details.
|
||||
|
||||
|
@ -115,7 +115,7 @@ CHECKING THROUGH /DEV
|
||||
If you try to access an adapter from a userspace program, you will have
|
||||
to use the /dev interface. You will still have to check whether the
|
||||
functionality you need is supported, of course. This is done using
|
||||
the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2c_detect
|
||||
the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect
|
||||
program, is below:
|
||||
|
||||
int file;
|
||||
|
@ -1,4 +1,4 @@
|
||||
Revision 4, 2004-03-30
|
||||
Revision 5, 2005-07-29
|
||||
Jean Delvare <khali@linux-fr.org>
|
||||
Greg KH <greg@kroah.com>
|
||||
|
||||
@ -17,20 +17,22 @@ yours for best results.
|
||||
|
||||
Technical changes:
|
||||
|
||||
* [Includes] Get rid of "version.h". Replace <linux/i2c-proc.h> with
|
||||
<linux/i2c-sensor.h>. Includes typically look like that:
|
||||
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
|
||||
Includes typically look like that:
|
||||
#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> /* if you need VRM support */
|
||||
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon-vid.h> /* if you need VRM support */
|
||||
#include <asm/io.h> /* if you have I/O operations */
|
||||
Please respect this inclusion order. Some extra headers may be
|
||||
required for a given driver (e.g. "lm75.h").
|
||||
|
||||
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, SENSORS_ISA_END
|
||||
becomes I2C_CLIENT_ISA_END.
|
||||
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, ISA addresses
|
||||
are no more handled by the i2c core.
|
||||
SENSORS_INSMOD_<n> becomes I2C_CLIENT_INSMOD_<n>.
|
||||
|
||||
* [Client data] Get rid of sysctl_id. Try using standard names for
|
||||
register values (for example, temp_os becomes temp_max). You're
|
||||
@ -66,13 +68,15 @@ Technical changes:
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
ISA-only drivers of course don't need this.
|
||||
Call i2c_probe() instead of i2c_detect().
|
||||
|
||||
* [Detect] As mentioned earlier, the flags parameter is gone.
|
||||
The type_name and client_name strings are replaced by a single
|
||||
name string, which will be filled with a lowercase, short string
|
||||
(typically the driver name, e.g. "lm75").
|
||||
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
|
||||
useless.
|
||||
useless. Same for isa-only drivers, as the test would always be
|
||||
true. Only hybrid drivers (which are quite rare) still need it.
|
||||
The errorN labels are reduced to the number needed. If that number
|
||||
is 2 (i2c-only drivers), it is advised that the labels are named
|
||||
exit and exit_free. For i2c+isa drivers, labels should be named
|
||||
@ -86,6 +90,8 @@ Technical changes:
|
||||
device_create_file. Move the driver initialization before any
|
||||
sysfs file creation.
|
||||
Drop client->id.
|
||||
Drop any 24RF08 corruption prevention you find, as this is now done
|
||||
at the i2c-core level, and doing it twice voids it.
|
||||
|
||||
* [Init] Limits must not be set by the driver (can be done later in
|
||||
user-space). Chip should not be reset default (although a module
|
||||
@ -93,7 +99,8 @@ Technical changes:
|
||||
limited to the strictly necessary steps.
|
||||
|
||||
* [Detach] Get rid of data, remove the call to
|
||||
i2c_deregister_entry.
|
||||
i2c_deregister_entry. Do not log an error message if
|
||||
i2c_detach_client fails, as i2c-core will now do it for you.
|
||||
|
||||
* [Update] Don't access client->data directly, use
|
||||
i2c_get_clientdata(client) instead.
|
||||
|
@ -148,15 +148,15 @@ are defined in i2c.h to help you support them, as well as a generic
|
||||
detection algorithm.
|
||||
|
||||
You do not have to use this parameter interface; but don't try to use
|
||||
function i2c_probe() (or i2c_detect()) if you don't.
|
||||
function i2c_probe() if you don't.
|
||||
|
||||
NOTE: If you want to write a `sensors' driver, the interface is slightly
|
||||
different! See below.
|
||||
|
||||
|
||||
|
||||
Probing classes (i2c)
|
||||
---------------------
|
||||
Probing classes
|
||||
---------------
|
||||
|
||||
All parameters are given as lists of unsigned 16-bit integers. Lists are
|
||||
terminated by I2C_CLIENT_END.
|
||||
@ -171,12 +171,18 @@ The following lists are used internally:
|
||||
ignore: insmod parameter.
|
||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
||||
the second is the I2C address. These addresses are never probed.
|
||||
This parameter overrules 'normal' and 'probe', but not the 'force' lists.
|
||||
This parameter overrules the 'normal_i2c' list only.
|
||||
force: insmod parameter.
|
||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
||||
the second is the I2C address. A device is blindly assumed to be on
|
||||
the given address, no probing is done.
|
||||
|
||||
Additionally, kind-specific force lists may optionally be defined if
|
||||
the driver supports several chip kinds. They are grouped in a
|
||||
NULL-terminated list of pointers named forces, those first element if the
|
||||
generic force list mentioned above. Each additional list correspond to an
|
||||
insmod parameter of the form force_<kind>.
|
||||
|
||||
Fortunately, as a module writer, you just have to define the `normal_i2c'
|
||||
parameter. The complete declaration could look like this:
|
||||
|
||||
@ -186,66 +192,17 @@ parameter. The complete declaration could look like this:
|
||||
|
||||
/* Magic definition of all other variables and things */
|
||||
I2C_CLIENT_INSMOD;
|
||||
/* Or, if your driver supports, say, 2 kind of devices: */
|
||||
I2C_CLIENT_INSMOD_2(foo, bar);
|
||||
|
||||
If you use the multi-kind form, an enum will be defined for you:
|
||||
enum chips { any_chip, foo, bar, ... }
|
||||
You can then (and certainly should) use it in the driver code.
|
||||
|
||||
Note that you *have* to call the defined variable `normal_i2c',
|
||||
without any prefix!
|
||||
|
||||
|
||||
Probing classes (sensors)
|
||||
-------------------------
|
||||
|
||||
If you write a `sensors' driver, you use a slightly different interface.
|
||||
As well as I2C addresses, we have to cope with ISA addresses. Also, we
|
||||
use a enum of chip types. Don't forget to include `sensors.h'.
|
||||
|
||||
The following lists are used internally. They are all lists of integers.
|
||||
|
||||
normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
|
||||
A list of I2C addresses which should normally be examined.
|
||||
normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
|
||||
A list of ISA addresses which should normally be examined.
|
||||
probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
|
||||
A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
|
||||
the ISA bus, -1 for any I2C bus), the second is the address. These
|
||||
addresses are also probed, as if they were in the 'normal' list.
|
||||
ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
|
||||
A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
|
||||
the ISA bus, -1 for any I2C bus), the second is the I2C address. These
|
||||
addresses are never probed. This parameter overrules 'normal' and
|
||||
'probe', but not the 'force' lists.
|
||||
|
||||
Also used is a list of pointers to sensors_force_data structures:
|
||||
force_data: insmod parameters. A list, ending with an element of which
|
||||
the force field is NULL.
|
||||
Each element contains the type of chip and a list of pairs.
|
||||
The first value is a bus number (SENSORS_ISA_BUS for the ISA bus,
|
||||
-1 for any I2C bus), the second is the address.
|
||||
These are automatically translated to insmod variables of the form
|
||||
force_foo.
|
||||
|
||||
So we have a generic insmod variabled `force', and chip-specific variables
|
||||
`force_CHIPNAME'.
|
||||
|
||||
Fortunately, as a module writer, you just have to define the `normal_i2c'
|
||||
and `normal_isa' parameters, and define what chip names are used.
|
||||
The complete declaration could look like this:
|
||||
/* Scan i2c addresses 0x37, and 0x48 to 0x4f */
|
||||
static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
|
||||
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
|
||||
/* Scan ISA address 0x290 */
|
||||
static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
|
||||
|
||||
/* Define chips foo and bar, as well as all module parameters and things */
|
||||
SENSORS_INSMOD_2(foo,bar);
|
||||
|
||||
If you have one chip, you use macro SENSORS_INSMOD_1(chip), if you have 2
|
||||
you use macro SENSORS_INSMOD_2(chip1,chip2), etc. If you do not want to
|
||||
bother with chip types, you can use SENSORS_INSMOD_0.
|
||||
|
||||
A enum is automatically defined as follows:
|
||||
enum chips { any_chip, chip1, chip2, ... }
|
||||
|
||||
|
||||
Attaching to an adapter
|
||||
-----------------------
|
||||
|
||||
@ -264,17 +221,10 @@ detected at a specific address, another callback is called.
|
||||
return i2c_probe(adapter,&addr_data,&foo_detect_client);
|
||||
}
|
||||
|
||||
For `sensors' drivers, use the i2c_detect function instead:
|
||||
|
||||
int foo_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_detect(adapter,&addr_data,&foo_detect_client);
|
||||
}
|
||||
|
||||
Remember, structure `addr_data' is defined by the macros explained above,
|
||||
so you do not have to define it yourself.
|
||||
|
||||
The i2c_probe or i2c_detect function will call the foo_detect_client
|
||||
The i2c_probe function will call the foo_detect_client
|
||||
function only for those i2c addresses that actually have a device on
|
||||
them (unless a `force' parameter was used). In addition, addresses that
|
||||
are already in use (by some other registered client) are skipped.
|
||||
@ -283,19 +233,18 @@ are already in use (by some other registered client) are skipped.
|
||||
The detect client function
|
||||
--------------------------
|
||||
|
||||
The detect client function is called by i2c_probe or i2c_detect.
|
||||
The `kind' parameter contains 0 if this call is due to a `force'
|
||||
parameter, and -1 otherwise (for i2c_detect, it contains 0 if
|
||||
this call is due to the generic `force' parameter, and the chip type
|
||||
number if it is due to a specific `force' parameter).
|
||||
The detect client function is called by i2c_probe. The `kind' parameter
|
||||
contains -1 for a probed detection, 0 for a forced detection, or a positive
|
||||
number for a forced detection with a chip type forced.
|
||||
|
||||
Below, some things are only needed if this is a `sensors' driver. Those
|
||||
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
|
||||
markers.
|
||||
|
||||
This function should only return an error (any value != 0) if there is
|
||||
some reason why no more detection should be done anymore. If the
|
||||
detection just fails for this address, return 0.
|
||||
Returning an error different from -ENODEV in a detect function will cause
|
||||
the detection to stop: other addresses and adapters won't be scanned.
|
||||
This should only be done on fatal or internal errors, such as a memory
|
||||
shortage or i2c_attach_client failing.
|
||||
|
||||
For now, you can ignore the `flags' parameter. It is there for future use.
|
||||
|
||||
@ -320,11 +269,10 @@ For now, you can ignore the `flags' parameter. It is there for future use.
|
||||
const char *type_name = "";
|
||||
int is_isa = i2c_is_isa_adapter(adapter);
|
||||
|
||||
if (is_isa) {
|
||||
/* Do this only if the chip can additionally be found on the ISA bus
|
||||
(hybrid chip). */
|
||||
|
||||
/* If this client can't be on the ISA bus at all, we can stop now
|
||||
(call `goto ERROR0'). But for kicks, we will assume it is all
|
||||
right. */
|
||||
if (is_isa) {
|
||||
|
||||
/* Discard immediately if this ISA range is already used */
|
||||
if (check_region(address,FOO_EXTENT))
|
||||
@ -495,15 +443,13 @@ much simpler than the attachment code, fortunately!
|
||||
/* SENSORS ONLY END */
|
||||
|
||||
/* Try to detach the client from i2c space */
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk("foo.o: Client deregistration failed, client not detached.\n");
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
/* SENSORS ONLY START */
|
||||
/* HYBRID SENSORS CHIP ONLY START */
|
||||
if i2c_is_isa_client(client)
|
||||
release_region(client->addr,LM78_EXTENT);
|
||||
/* SENSORS ONLY END */
|
||||
/* HYBRID SENSORS CHIP ONLY END */
|
||||
|
||||
kfree(client); /* Frees client data too, if allocated at the same time */
|
||||
return 0;
|
||||
|
@ -933,6 +933,13 @@ M: khc@pm.waw.pl
|
||||
W: http://www.kernel.org/pub/linux/utils/net/hdlc/
|
||||
S: Maintained
|
||||
|
||||
HARDWARE MONITORING
|
||||
P: Jean Delvare
|
||||
M: khali@linux-fr.org
|
||||
L: lm-sensors@lm-sensors.org
|
||||
W: http://www.lm-sensors.nu/
|
||||
S: Maintained
|
||||
|
||||
HARMONY SOUND DRIVER
|
||||
P: Kyle McMartin
|
||||
M: kyle@parisc-linux.org
|
||||
@ -1014,7 +1021,7 @@ P: William Irwin
|
||||
M: wli@holomorphy.com
|
||||
S: Maintained
|
||||
|
||||
I2C AND SENSORS DRIVERS
|
||||
I2C SUBSYSTEM
|
||||
P: Greg Kroah-Hartman
|
||||
M: greg@kroah.com
|
||||
P: Jean Delvare
|
||||
|
@ -12,12 +12,20 @@ config HWMON
|
||||
of a system. Most modern motherboards include such a device. It
|
||||
can include temperature sensors, voltage sensors, fan speed
|
||||
sensors and various additional features such as the ability to
|
||||
control the speed of the fans.
|
||||
control the speed of the fans. If you want this support you
|
||||
should say Y here and also to the specific driver(s) for your
|
||||
sensors chip(s) below.
|
||||
|
||||
This support can also be built as a module. If so, the module
|
||||
will be called hwmon.
|
||||
|
||||
config HWMON_VID
|
||||
tristate
|
||||
default n
|
||||
|
||||
config SENSORS_ADM1021
|
||||
tristate "Analog Devices ADM1021 and compatibles"
|
||||
depends on HWMON && I2C
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for Analog Devices ADM1021
|
||||
and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
|
||||
@ -30,7 +38,7 @@ config SENSORS_ADM1021
|
||||
config SENSORS_ADM1025
|
||||
tristate "Analog Devices ADM1025 and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for Analog Devices ADM1025
|
||||
and Philips NE1619 sensor chips.
|
||||
@ -41,7 +49,7 @@ config SENSORS_ADM1025
|
||||
config SENSORS_ADM1026
|
||||
tristate "Analog Devices ADM1026 and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for Analog Devices ADM1026
|
||||
sensor chip.
|
||||
@ -52,7 +60,6 @@ config SENSORS_ADM1026
|
||||
config SENSORS_ADM1031
|
||||
tristate "Analog Devices ADM1031 and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for Analog Devices ADM1031
|
||||
and ADM1030 sensor chips.
|
||||
@ -63,7 +70,7 @@ config SENSORS_ADM1031
|
||||
config SENSORS_ADM9240
|
||||
tristate "Analog Devices ADM9240 and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for Analog Devices ADM9240,
|
||||
Dallas DS1780, National Semiconductor LM81 sensor chips.
|
||||
@ -74,7 +81,7 @@ config SENSORS_ADM9240
|
||||
config SENSORS_ASB100
|
||||
tristate "Asus ASB100 Bach"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for the ASB100 Bach sensor
|
||||
chip found on some Asus mainboards.
|
||||
@ -85,7 +92,7 @@ config SENSORS_ASB100
|
||||
config SENSORS_ATXP1
|
||||
tristate "Attansic ATXP1 VID controller"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for the Attansic ATXP1 VID
|
||||
controller.
|
||||
@ -99,7 +106,6 @@ config SENSORS_ATXP1
|
||||
config SENSORS_DS1621
|
||||
tristate "Dallas Semiconductor DS1621 and DS1625"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for Dallas Semiconductor
|
||||
DS1621 and DS1625 sensor chips.
|
||||
@ -110,7 +116,6 @@ config SENSORS_DS1621
|
||||
config SENSORS_FSCHER
|
||||
tristate "FSC Hermes"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for Fujitsu Siemens
|
||||
Computers Hermes sensor chips.
|
||||
@ -121,7 +126,6 @@ config SENSORS_FSCHER
|
||||
config SENSORS_FSCPOS
|
||||
tristate "FSC Poseidon"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for Fujitsu Siemens
|
||||
Computers Poseidon sensor chips.
|
||||
@ -132,7 +136,6 @@ config SENSORS_FSCPOS
|
||||
config SENSORS_GL518SM
|
||||
tristate "Genesys Logic GL518SM"
|
||||
depends on HWMON && I2C
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for Genesys Logic GL518SM
|
||||
sensor chips.
|
||||
@ -143,7 +146,7 @@ config SENSORS_GL518SM
|
||||
config SENSORS_GL520SM
|
||||
tristate "Genesys Logic GL520SM"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for Genesys Logic GL520SM
|
||||
sensor chips.
|
||||
@ -154,7 +157,8 @@ config SENSORS_GL520SM
|
||||
config SENSORS_IT87
|
||||
tristate "ITE IT87xx and compatibles"
|
||||
depends on HWMON && I2C
|
||||
select I2C_SENSOR
|
||||
select I2C_ISA
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for ITE IT87xx sensor chips
|
||||
and clones: SiS960.
|
||||
@ -165,7 +169,6 @@ config SENSORS_IT87
|
||||
config SENSORS_LM63
|
||||
tristate "National Semiconductor LM63"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for the National Semiconductor
|
||||
LM63 remote diode digital temperature sensor with integrated fan
|
||||
@ -178,7 +181,6 @@ config SENSORS_LM63
|
||||
config SENSORS_LM75
|
||||
tristate "National Semiconductor LM75 and compatibles"
|
||||
depends on HWMON && I2C
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor LM75
|
||||
sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in
|
||||
@ -194,7 +196,6 @@ config SENSORS_LM75
|
||||
config SENSORS_LM77
|
||||
tristate "National Semiconductor LM77"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor LM77
|
||||
sensor chips.
|
||||
@ -205,7 +206,8 @@ config SENSORS_LM77
|
||||
config SENSORS_LM78
|
||||
tristate "National Semiconductor LM78 and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select I2C_ISA
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor LM78,
|
||||
LM78-J and LM79.
|
||||
@ -216,7 +218,6 @@ config SENSORS_LM78
|
||||
config SENSORS_LM80
|
||||
tristate "National Semiconductor LM80"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor
|
||||
LM80 sensor chips.
|
||||
@ -227,7 +228,6 @@ config SENSORS_LM80
|
||||
config SENSORS_LM83
|
||||
tristate "National Semiconductor LM83"
|
||||
depends on HWMON && I2C
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor
|
||||
LM83 sensor chips.
|
||||
@ -238,7 +238,7 @@ config SENSORS_LM83
|
||||
config SENSORS_LM85
|
||||
tristate "National Semiconductor LM85 and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor LM85
|
||||
sensor chips and clones: ADT7463, EMC6D100, EMC6D102 and ADM1027.
|
||||
@ -249,7 +249,7 @@ config SENSORS_LM85
|
||||
config SENSORS_LM87
|
||||
tristate "National Semiconductor LM87"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor LM87
|
||||
sensor chips.
|
||||
@ -260,7 +260,6 @@ config SENSORS_LM87
|
||||
config SENSORS_LM90
|
||||
tristate "National Semiconductor LM90 and compatibles"
|
||||
depends on HWMON && I2C
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor LM90,
|
||||
LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and
|
||||
@ -275,7 +274,6 @@ config SENSORS_LM90
|
||||
config SENSORS_LM92
|
||||
tristate "National Semiconductor LM92 and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor LM92
|
||||
and Maxim MAX6635 sensor chips.
|
||||
@ -286,7 +284,6 @@ config SENSORS_LM92
|
||||
config SENSORS_MAX1619
|
||||
tristate "Maxim MAX1619 sensor chip"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for MAX1619 sensor chip.
|
||||
|
||||
@ -296,8 +293,8 @@ config SENSORS_MAX1619
|
||||
config SENSORS_PC87360
|
||||
tristate "National Semiconductor PC87360 family"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select I2C_ISA
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get access to the hardware monitoring
|
||||
functions of the National Semiconductor PC8736x Super-I/O chips.
|
||||
@ -311,7 +308,6 @@ config SENSORS_PC87360
|
||||
config SENSORS_SIS5595
|
||||
tristate "Silicon Integrated Systems Corp. SiS5595"
|
||||
depends on HWMON && I2C && PCI && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select I2C_ISA
|
||||
help
|
||||
If you say yes here you get support for the integrated sensors in
|
||||
@ -323,7 +319,6 @@ config SENSORS_SIS5595
|
||||
config SENSORS_SMSC47M1
|
||||
tristate "SMSC LPC47M10x and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select I2C_ISA
|
||||
help
|
||||
If you say yes here you get support for the integrated fan
|
||||
@ -336,7 +331,6 @@ config SENSORS_SMSC47M1
|
||||
config SENSORS_SMSC47B397
|
||||
tristate "SMSC LPC47B397-NC"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select I2C_ISA
|
||||
help
|
||||
If you say yes here you get support for the SMSC LPC47B397-NC
|
||||
@ -348,7 +342,6 @@ config SENSORS_SMSC47B397
|
||||
config SENSORS_VIA686A
|
||||
tristate "VIA686A"
|
||||
depends on HWMON && I2C && PCI
|
||||
select I2C_SENSOR
|
||||
select I2C_ISA
|
||||
help
|
||||
If you say yes here you get support for the integrated sensors in
|
||||
@ -360,7 +353,8 @@ config SENSORS_VIA686A
|
||||
config SENSORS_W83781D
|
||||
tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
|
||||
depends on HWMON && I2C
|
||||
select I2C_SENSOR
|
||||
select I2C_ISA
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for the Winbond W8378x series
|
||||
of sensor chips: the W83781D, W83782D, W83783S and W83627HF,
|
||||
@ -369,10 +363,18 @@ config SENSORS_W83781D
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called w83781d.
|
||||
|
||||
config SENSORS_W83792D
|
||||
tristate "Winbond W83792D"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get support for the Winbond W83792D chip.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called w83792d.
|
||||
|
||||
config SENSORS_W83L785TS
|
||||
tristate "Winbond W83L785TS-S"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for the Winbond W83L785TS-S
|
||||
sensor chip, which is used on the Asus A7N8X, among other
|
||||
@ -384,8 +386,8 @@ config SENSORS_W83L785TS
|
||||
config SENSORS_W83627HF
|
||||
tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select I2C_ISA
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for the Winbond W836X7 series
|
||||
of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF
|
||||
@ -396,7 +398,6 @@ config SENSORS_W83627HF
|
||||
config SENSORS_W83627EHF
|
||||
tristate "Winbond W83627EHF"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
select I2C_ISA
|
||||
help
|
||||
If you say yes here you get preliminary support for the hardware
|
||||
@ -404,6 +405,9 @@ config SENSORS_W83627EHF
|
||||
Only fan and temperature inputs are supported at the moment, while
|
||||
the chip does much more than that.
|
||||
|
||||
This driver also supports the W83627EHG, which is the lead-free
|
||||
version of the W83627EHF.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called w83627ehf.
|
||||
|
||||
|
@ -2,9 +2,13 @@
|
||||
# Makefile for sensor chip drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_HWMON) += hwmon.o
|
||||
obj-$(CONFIG_HWMON_VID) += hwmon-vid.o
|
||||
|
||||
# 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_W83792D) += w83792d.o
|
||||
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
|
||||
|
||||
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
|
||||
|
@ -24,7 +24,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
|
||||
/* Addresses to scan */
|
||||
@ -32,10 +33,9 @@ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
|
||||
0x29, 0x2a, 0x2b,
|
||||
0x4c, 0x4d, 0x4e,
|
||||
I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
|
||||
I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
|
||||
|
||||
/* adm1021 constants specified below */
|
||||
|
||||
@ -89,6 +89,7 @@ clearing it. Weird, ey? --Phil */
|
||||
/* Each client has this additional data */
|
||||
struct adm1021_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
enum chips type;
|
||||
|
||||
struct semaphore update_lock;
|
||||
@ -185,7 +186,7 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, adm1021_detect);
|
||||
return i2c_probe(adapter, &addr_data, adm1021_detect);
|
||||
}
|
||||
|
||||
static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
@ -196,15 +197,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
int err = 0;
|
||||
const char *type_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. */
|
||||
#ifdef DEBUG
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
dev_dbg(&adapter->dev, "adm1021_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto error0;
|
||||
|
||||
@ -295,6 +287,12 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
adm1021_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto error2;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -305,6 +303,8 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
error2:
|
||||
i2c_detach_client(new_client);
|
||||
error1:
|
||||
kfree(data);
|
||||
error0:
|
||||
@ -322,14 +322,15 @@ static void adm1021_init_client(struct i2c_client *client)
|
||||
|
||||
static int adm1021_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct adm1021_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,9 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* Addresses to scan
|
||||
@ -60,13 +61,12 @@
|
||||
*/
|
||||
|
||||
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/*
|
||||
* Insmod parameters
|
||||
*/
|
||||
|
||||
SENSORS_INSMOD_2(adm1025, ne1619);
|
||||
I2C_CLIENT_INSMOD_2(adm1025, ne1619);
|
||||
|
||||
/*
|
||||
* The ADM1025 registers
|
||||
@ -132,6 +132,7 @@ static struct i2c_driver adm1025_driver = {
|
||||
|
||||
struct adm1025_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
@ -312,7 +313,7 @@ static int adm1025_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, adm1025_detect);
|
||||
return i2c_probe(adapter, &addr_data, adm1025_detect);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -416,6 +417,12 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
adm1025_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -452,6 +459,8 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -464,7 +473,7 @@ static void adm1025_init_client(struct i2c_client *client)
|
||||
struct adm1025_data *data = i2c_get_clientdata(client);
|
||||
int i;
|
||||
|
||||
data->vrm = i2c_which_vrm();
|
||||
data->vrm = vid_which_vrm();
|
||||
|
||||
/*
|
||||
* Set high limits
|
||||
@ -502,15 +511,15 @@ static void adm1025_init_client(struct i2c_client *client)
|
||||
|
||||
static int adm1025_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct adm1025_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -28,16 +28,16 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(adm1026);
|
||||
I2C_CLIENT_INSMOD_1(adm1026);
|
||||
|
||||
static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1 };
|
||||
@ -259,6 +259,7 @@ struct pwm_data {
|
||||
|
||||
struct adm1026_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
enum chips type;
|
||||
|
||||
@ -319,13 +320,15 @@ int adm1026_attach_adapter(struct i2c_adapter *adapter)
|
||||
if (!(adapter->class & I2C_CLASS_HWMON)) {
|
||||
return 0;
|
||||
}
|
||||
return i2c_detect(adapter, &addr_data, adm1026_detect);
|
||||
return i2c_probe(adapter, &addr_data, adm1026_detect);
|
||||
}
|
||||
|
||||
int adm1026_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct adm1026_data *data = i2c_get_clientdata(client);
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
i2c_detach_client(client);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1549,12 +1552,18 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
|
||||
goto exitfree;
|
||||
|
||||
/* Set the VRM version */
|
||||
data->vrm = i2c_which_vrm();
|
||||
data->vrm = vid_which_vrm();
|
||||
|
||||
/* Initialize the ADM1026 chip */
|
||||
adm1026_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exitdetach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
|
||||
@ -1690,6 +1699,8 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
|
||||
return 0;
|
||||
|
||||
/* Error out and cleanup code */
|
||||
exitdetach:
|
||||
i2c_detach_client(new_client);
|
||||
exitfree:
|
||||
kfree(data);
|
||||
exit:
|
||||
|
@ -26,7 +26,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* Following macros takes channel parameter starting from 0 to 2 */
|
||||
#define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr))
|
||||
@ -59,16 +60,16 @@
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_2(adm1030, adm1031);
|
||||
I2C_CLIENT_INSMOD_2(adm1030, adm1031);
|
||||
|
||||
typedef u8 auto_chan_table_t[8][2];
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct adm1031_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
int chip_type;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
@ -725,10 +726,10 @@ static int adm1031_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, adm1031_detect);
|
||||
return i2c_probe(adapter, &addr_data, adm1031_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
/* This function is called by i2c_probe */
|
||||
static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
@ -788,6 +789,12 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
adm1031_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_div);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_min);
|
||||
@ -833,6 +840,8 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -841,11 +850,14 @@ exit:
|
||||
|
||||
static int adm1031_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct adm1031_data *data = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
if ((ret = i2c_detach_client(client)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -45,17 +45,16 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
I2C_CLIENT_END };
|
||||
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_3(adm9240, ds1780, lm81);
|
||||
I2C_CLIENT_INSMOD_3(adm9240, ds1780, lm81);
|
||||
|
||||
/* ADM9240 registers */
|
||||
#define ADM9240_REG_MAN_ID 0x3e
|
||||
@ -150,6 +149,7 @@ static struct i2c_driver adm9240_driver = {
|
||||
struct adm9240_data {
|
||||
enum chips type;
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid;
|
||||
unsigned long last_updated_measure;
|
||||
@ -582,6 +582,12 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
adm9240_init_client(new_client);
|
||||
|
||||
/* populate sysfs filesystem */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -615,6 +621,9 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -625,20 +634,20 @@ static int adm9240_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, adm9240_detect);
|
||||
return i2c_probe(adapter, &addr_data, adm9240_detect);
|
||||
}
|
||||
|
||||
static int adm9240_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct adm9240_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -648,7 +657,7 @@ static void adm9240_init_client(struct i2c_client *client)
|
||||
u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
|
||||
u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
|
||||
|
||||
data->vrm = i2c_which_vrm(); /* need this to report vid as mV */
|
||||
data->vrm = vid_which_vrm(); /* need this to report vid as mV */
|
||||
|
||||
dev_info(&client->dev, "Using VRM: %d.%d\n", data->vrm / 10,
|
||||
data->vrm % 10);
|
||||
|
@ -39,8 +39,9 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include "lm75.h"
|
||||
@ -54,11 +55,8 @@
|
||||
/* I2C addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
|
||||
|
||||
/* ISA addresses to scan (none) */
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(asb100);
|
||||
I2C_CLIENT_INSMOD_1(asb100);
|
||||
I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
|
||||
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
|
||||
|
||||
@ -183,6 +181,7 @@ static u8 DIV_TO_REG(long val)
|
||||
dynamically allocated, at the same time the client itself is allocated. */
|
||||
struct asb100_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
enum chips type;
|
||||
|
||||
@ -621,7 +620,7 @@ static int asb100_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, asb100_detect);
|
||||
return i2c_probe(adapter, &addr_data, asb100_detect);
|
||||
}
|
||||
|
||||
static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
|
||||
@ -714,14 +713,6 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
struct i2c_client *new_client;
|
||||
struct asb100_data *data;
|
||||
|
||||
/* asb100 is SMBus only */
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
pr_debug("asb100.o: detect failed, "
|
||||
"cannot attach to legacy adapter!\n");
|
||||
err = -ENODEV;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
||||
pr_debug("asb100.o: detect failed, "
|
||||
"smbus byte data not supported!\n");
|
||||
@ -821,6 +812,12 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2));
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto ERROR3;
|
||||
}
|
||||
|
||||
device_create_file_in(new_client, 0);
|
||||
device_create_file_in(new_client, 1);
|
||||
device_create_file_in(new_client, 2);
|
||||
@ -847,6 +844,11 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR3:
|
||||
i2c_detach_client(data->lm75[1]);
|
||||
i2c_detach_client(data->lm75[0]);
|
||||
kfree(data->lm75[1]);
|
||||
kfree(data->lm75[0]);
|
||||
ERROR2:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR1:
|
||||
@ -857,21 +859,23 @@ ERROR0:
|
||||
|
||||
static int asb100_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct asb100_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "client deregistration failed; "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
/* main client */
|
||||
if (data)
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if (i2c_get_clientdata(client)==NULL) {
|
||||
/* subclients */
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
/* main client */
|
||||
if (data)
|
||||
kfree(data);
|
||||
|
||||
/* subclient */
|
||||
else
|
||||
kfree(client);
|
||||
} else {
|
||||
/* main client */
|
||||
kfree(i2c_get_clientdata(client));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -969,7 +973,7 @@ static void asb100_init_client(struct i2c_client *client)
|
||||
|
||||
vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f;
|
||||
vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4;
|
||||
data->vrm = i2c_which_vrm();
|
||||
data->vrm = vid_which_vrm();
|
||||
vid = vid_from_reg(vid, data->vrm);
|
||||
|
||||
/* Start monitoring */
|
||||
|
@ -23,8 +23,9 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
|
||||
@ -40,9 +41,8 @@ MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
|
||||
#define ATXP1_GPIO1MASK 0x0f
|
||||
|
||||
static unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
SENSORS_INSMOD_1(atxp1);
|
||||
I2C_CLIENT_INSMOD_1(atxp1);
|
||||
|
||||
static int atxp1_attach_adapter(struct i2c_adapter * adapter);
|
||||
static int atxp1_detach_client(struct i2c_client * client);
|
||||
@ -59,6 +59,7 @@ static struct i2c_driver atxp1_driver = {
|
||||
|
||||
struct atxp1_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
unsigned long last_updated;
|
||||
u8 valid;
|
||||
@ -252,7 +253,7 @@ static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
|
||||
|
||||
static int atxp1_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_detect(adapter, &addr_data, &atxp1_detect);
|
||||
return i2c_probe(adapter, &addr_data, &atxp1_detect);
|
||||
};
|
||||
|
||||
static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
@ -295,7 +296,7 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
}
|
||||
|
||||
/* Get VRM */
|
||||
data->vrm = i2c_which_vrm();
|
||||
data->vrm = vid_which_vrm();
|
||||
|
||||
if ((data->vrm != 90) && (data->vrm != 91)) {
|
||||
dev_err(&new_client->dev, "Not supporting VRM %d.%d\n",
|
||||
@ -317,6 +318,12 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_gpio1);
|
||||
device_create_file(&new_client->dev, &dev_attr_gpio2);
|
||||
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
|
||||
@ -326,6 +333,8 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -334,14 +343,17 @@ exit:
|
||||
|
||||
static int atxp1_detach_client(struct i2c_client * client)
|
||||
{
|
||||
struct atxp1_data * data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
err = i2c_detach_client(client);
|
||||
|
||||
if (err)
|
||||
dev_err(&client->dev, "Failed to detach client.\n");
|
||||
else
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
|
||||
return err;
|
||||
};
|
||||
|
@ -26,16 +26,16 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include "lm75.h"
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
|
||||
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(ds1621);
|
||||
I2C_CLIENT_INSMOD_1(ds1621);
|
||||
static int polarity = -1;
|
||||
module_param(polarity, int, 0);
|
||||
MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low");
|
||||
@ -71,6 +71,7 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low")
|
||||
/* Each client has this additional data */
|
||||
struct ds1621_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
@ -179,10 +180,10 @@ 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);
|
||||
return i2c_probe(adapter, &addr_data, ds1621_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
/* This function is called by i2c_probe */
|
||||
int ds1621_detect(struct i2c_adapter *adapter, int address,
|
||||
int kind)
|
||||
{
|
||||
@ -250,6 +251,12 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
|
||||
ds1621_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -259,6 +266,8 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -267,15 +276,15 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
|
||||
|
||||
static int ds1621_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct ds1621_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -31,20 +31,20 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* Addresses to scan
|
||||
*/
|
||||
|
||||
static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/*
|
||||
* Insmod parameters
|
||||
*/
|
||||
|
||||
SENSORS_INSMOD_1(fscher);
|
||||
I2C_CLIENT_INSMOD_1(fscher);
|
||||
|
||||
/*
|
||||
* The FSCHER registers
|
||||
@ -132,6 +132,7 @@ static struct i2c_driver fscher_driver = {
|
||||
|
||||
struct fscher_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
@ -287,7 +288,7 @@ static int fscher_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, fscher_detect);
|
||||
return i2c_probe(adapter, &addr_data, fscher_detect);
|
||||
}
|
||||
|
||||
static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
@ -341,6 +342,12 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
fscher_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file_revision(new_client);
|
||||
device_create_file_alarms(new_client);
|
||||
device_create_file_control(new_client);
|
||||
@ -360,6 +367,8 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -368,15 +377,15 @@ exit:
|
||||
|
||||
static int fscher_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct fscher_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -34,19 +34,19 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* Addresses to scan
|
||||
*/
|
||||
static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/*
|
||||
* Insmod parameters
|
||||
*/
|
||||
SENSORS_INSMOD_1(fscpos);
|
||||
I2C_CLIENT_INSMOD_1(fscpos);
|
||||
|
||||
/*
|
||||
* The FSCPOS registers
|
||||
@ -113,6 +113,7 @@ static struct i2c_driver fscpos_driver = {
|
||||
*/
|
||||
struct fscpos_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* 0 until following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
@ -434,7 +435,7 @@ static int fscpos_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, fscpos_detect);
|
||||
return i2c_probe(adapter, &addr_data, fscpos_detect);
|
||||
}
|
||||
|
||||
int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
@ -496,6 +497,12 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_event);
|
||||
device_create_file(&new_client->dev, &dev_attr_in0_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in1_input);
|
||||
@ -526,6 +533,8 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -534,14 +543,14 @@ exit:
|
||||
|
||||
static int fscpos_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct fscpos_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, client"
|
||||
" not detached.\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -41,14 +41,14 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_2(gl518sm_r00, gl518sm_r80);
|
||||
I2C_CLIENT_INSMOD_2(gl518sm_r00, gl518sm_r80);
|
||||
|
||||
/* Many GL518 constants specified below */
|
||||
|
||||
@ -117,6 +117,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
/* Each client has this additional data */
|
||||
struct gl518_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
enum chips type;
|
||||
|
||||
struct semaphore update_lock;
|
||||
@ -346,7 +347,7 @@ static int gl518_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, gl518_detect);
|
||||
return i2c_probe(adapter, &addr_data, gl518_detect);
|
||||
}
|
||||
|
||||
static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
@ -419,6 +420,12 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
gl518_init_client((struct i2c_client *) new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -450,6 +457,8 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -477,16 +486,15 @@ static void gl518_init_client(struct i2c_client *client)
|
||||
|
||||
static int gl518_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct gl518_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,9 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* Type of the extra sensor */
|
||||
static unsigned short extra_sensor_type;
|
||||
@ -36,10 +37,9 @@ MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=tempe
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(gl520sm);
|
||||
I2C_CLIENT_INSMOD_1(gl520sm);
|
||||
|
||||
/* Many GL520 constants specified below
|
||||
One of the inputs can be configured as either temp or voltage.
|
||||
@ -120,6 +120,7 @@ static struct i2c_driver gl520_driver = {
|
||||
/* Client data */
|
||||
struct gl520_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* zero until the following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
@ -518,7 +519,7 @@ static int gl520_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, gl520_detect);
|
||||
return i2c_probe(adapter, &addr_data, gl520_detect);
|
||||
}
|
||||
|
||||
static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
@ -571,6 +572,12 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
gl520_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file_vid(new_client, 0);
|
||||
|
||||
device_create_file_in(new_client, 0);
|
||||
@ -592,6 +599,8 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -608,7 +617,7 @@ static void gl520_init_client(struct i2c_client *client)
|
||||
conf = oldconf = gl520_read_value(client, GL520_REG_CONF);
|
||||
|
||||
data->alarm_mask = 0xff;
|
||||
data->vrm = i2c_which_vrm();
|
||||
data->vrm = vid_which_vrm();
|
||||
|
||||
if (extra_sensor_type == 1)
|
||||
conf &= ~0x10;
|
||||
@ -639,15 +648,15 @@ static void gl520_init_client(struct i2c_client *client)
|
||||
|
||||
static int gl520_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct gl520_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
189
drivers/hwmon/hwmon-vid.c
Normal file
189
drivers/hwmon/hwmon-vid.c
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
hwmon-vid.c - VID/VRM/VRD voltage conversions
|
||||
|
||||
Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
|
||||
|
||||
Partly imported from i2c-vid.h of the lm_sensors project
|
||||
Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
With assistance from Trent Piepho <xyzzy@speakeasy.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/kernel.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
|
||||
/*
|
||||
Common code for decoding VID pins.
|
||||
|
||||
References:
|
||||
|
||||
For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines",
|
||||
available at http://developer.intel.com/.
|
||||
|
||||
For VRD 10.0 and up, "VRD x.y Design Guide",
|
||||
available at http://developer.intel.com/.
|
||||
|
||||
AMD Opteron processors don't follow the Intel specifications.
|
||||
I'm going to "make up" 2.4 as the spec number for the Opterons.
|
||||
No good reason just a mnemonic for the 24x Opteron processor
|
||||
series.
|
||||
|
||||
Opteron VID encoding is:
|
||||
00000 = 1.550 V
|
||||
00001 = 1.525 V
|
||||
. . . .
|
||||
11110 = 0.800 V
|
||||
11111 = 0.000 V (off)
|
||||
*/
|
||||
|
||||
/* vrm is the VRM/VRD document version multiplied by 10.
|
||||
val is the 4-, 5- or 6-bit VID code.
|
||||
Returned value is in mV to avoid floating point in the kernel. */
|
||||
int vid_from_reg(int val, int vrm)
|
||||
{
|
||||
int vid;
|
||||
|
||||
switch(vrm) {
|
||||
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case 100: /* VRD 10.0 */
|
||||
if((val & 0x1f) == 0x1f)
|
||||
return 0;
|
||||
if((val & 0x1f) <= 0x09 || val == 0x0a)
|
||||
vid = 10875 - (val & 0x1f) * 250;
|
||||
else
|
||||
vid = 18625 - (val & 0x1f) * 250;
|
||||
if(val & 0x20)
|
||||
vid -= 125;
|
||||
vid /= 10; /* only return 3 dec. places for now */
|
||||
return vid;
|
||||
|
||||
case 24: /* Opteron processor */
|
||||
return(val == 0x1f ? 0 : 1550 - val * 25);
|
||||
|
||||
case 91: /* VRM 9.1 */
|
||||
case 90: /* VRM 9.0 */
|
||||
return(val == 0x1f ? 0 :
|
||||
1850 - val * 25);
|
||||
|
||||
case 85: /* VRM 8.5 */
|
||||
return((val & 0x10 ? 25 : 0) +
|
||||
((val & 0x0f) > 0x04 ? 2050 : 1250) -
|
||||
((val & 0x0f) * 50));
|
||||
|
||||
case 84: /* VRM 8.4 */
|
||||
val &= 0x0f;
|
||||
/* fall through */
|
||||
default: /* VRM 8.2 */
|
||||
return(val == 0x1f ? 0 :
|
||||
val & 0x10 ? 5100 - (val) * 100 :
|
||||
2050 - (val) * 50);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
After this point is the code to automatically determine which
|
||||
VRM/VRD specification should be used depending on the CPU.
|
||||
*/
|
||||
|
||||
struct vrm_model {
|
||||
u8 vendor;
|
||||
u8 eff_family;
|
||||
u8 eff_model;
|
||||
int vrm_type;
|
||||
};
|
||||
|
||||
#define ANY 0xFF
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
|
||||
static struct vrm_model vrm_models[] = {
|
||||
{X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */
|
||||
{X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */
|
||||
{X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */
|
||||
{X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* Tualatin */
|
||||
{X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */
|
||||
{X86_VENDOR_INTEL, 0x7, ANY, 0}, /* Itanium */
|
||||
{X86_VENDOR_INTEL, 0xF, 0x0, 90}, /* P4 */
|
||||
{X86_VENDOR_INTEL, 0xF, 0x1, 90}, /* P4 Willamette */
|
||||
{X86_VENDOR_INTEL, 0xF, 0x2, 90}, /* P4 Northwood */
|
||||
{X86_VENDOR_INTEL, 0xF, 0x3, 100}, /* P4 Prescott */
|
||||
{X86_VENDOR_INTEL, 0xF, 0x4, 100}, /* P4 Prescott */
|
||||
{X86_VENDOR_INTEL, 0x10,ANY, 0}, /* Itanium 2 */
|
||||
{X86_VENDOR_UNKNOWN, ANY, ANY, 0} /* stop here */
|
||||
};
|
||||
|
||||
static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
|
||||
if (vrm_models[i].vendor==vendor)
|
||||
if ((vrm_models[i].eff_family==eff_family)
|
||||
&& ((vrm_models[i].eff_model==eff_model) ||
|
||||
(vrm_models[i].eff_model==ANY)))
|
||||
return vrm_models[i].vrm_type;
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vid_which_vrm(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = cpu_data;
|
||||
u32 eax;
|
||||
u8 eff_family, eff_model;
|
||||
int vrm_ret;
|
||||
|
||||
if (c->x86 < 6) /* Any CPU with family lower than 6 */
|
||||
return 0; /* doesn't have VID and/or CPUID */
|
||||
|
||||
eax = cpuid_eax(1);
|
||||
eff_family = ((eax & 0x00000F00)>>8);
|
||||
eff_model = ((eax & 0x000000F0)>>4);
|
||||
if (eff_family == 0xF) { /* use extended model & family */
|
||||
eff_family += ((eax & 0x00F00000)>>20);
|
||||
eff_model += ((eax & 0x000F0000)>>16)<<4;
|
||||
}
|
||||
vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
|
||||
if (vrm_ret == 0)
|
||||
printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
|
||||
"x86 CPU\n");
|
||||
return vrm_ret;
|
||||
}
|
||||
|
||||
/* and now something completely different for the non-x86 world */
|
||||
#else
|
||||
int vid_which_vrm(void)
|
||||
{
|
||||
printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(vid_from_reg);
|
||||
EXPORT_SYMBOL(vid_which_vrm);
|
||||
|
||||
MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
|
||||
|
||||
MODULE_DESCRIPTION("hwmon-vid driver");
|
||||
MODULE_LICENSE("GPL");
|
98
drivers/hwmon/hwmon.c
Normal file
98
drivers/hwmon/hwmon.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
|
||||
|
||||
This file defines the sysfs class "hwmon", for use by sensors drivers.
|
||||
|
||||
Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
|
||||
|
||||
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; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/hwmon.h>
|
||||
|
||||
#define HWMON_ID_PREFIX "hwmon"
|
||||
#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
|
||||
|
||||
static struct class *hwmon_class;
|
||||
|
||||
static DEFINE_IDR(hwmon_idr);
|
||||
|
||||
/**
|
||||
* hwmon_device_register - register w/ hwmon sysfs class
|
||||
* @dev: the device to register
|
||||
*
|
||||
* hwmon_device_unregister() must be called when the class device is no
|
||||
* longer needed.
|
||||
*
|
||||
* Returns the pointer to the new struct class device.
|
||||
*/
|
||||
struct class_device *hwmon_device_register(struct device *dev)
|
||||
{
|
||||
struct class_device *cdev;
|
||||
int id;
|
||||
|
||||
if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (idr_get_new(&hwmon_idr, NULL, &id) < 0)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
id = id & MAX_ID_MASK;
|
||||
cdev = class_device_create(hwmon_class, MKDEV(0,0), dev,
|
||||
HWMON_ID_FORMAT, id);
|
||||
|
||||
if (IS_ERR(cdev))
|
||||
idr_remove(&hwmon_idr, id);
|
||||
|
||||
return cdev;
|
||||
}
|
||||
|
||||
/**
|
||||
* hwmon_device_unregister - removes the previously registered class device
|
||||
*
|
||||
* @cdev: the class device to destroy
|
||||
*/
|
||||
void hwmon_device_unregister(struct class_device *cdev)
|
||||
{
|
||||
int id;
|
||||
|
||||
if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) {
|
||||
class_device_unregister(cdev);
|
||||
idr_remove(&hwmon_idr, id);
|
||||
} else
|
||||
dev_dbg(cdev->dev,
|
||||
"hwmon_device_unregister() failed: bad class ID!\n");
|
||||
}
|
||||
|
||||
static int __init hwmon_init(void)
|
||||
{
|
||||
hwmon_class = class_create(THIS_MODULE, "hwmon");
|
||||
if (IS_ERR(hwmon_class)) {
|
||||
printk(KERN_ERR "hwmon.c: couldn't create sysfs class\n");
|
||||
return PTR_ERR(hwmon_class);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit hwmon_exit(void)
|
||||
{
|
||||
class_destroy(hwmon_class);
|
||||
}
|
||||
|
||||
module_init(hwmon_init);
|
||||
module_exit(hwmon_exit);
|
||||
|
||||
EXPORT_SYMBOL_GPL(hwmon_device_register);
|
||||
EXPORT_SYMBOL_GPL(hwmon_device_unregister);
|
||||
|
||||
MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
|
||||
MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -36,19 +36,21 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
|
||||
0x2e, 0x2f, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
|
||||
static unsigned short isa_address = 0x290;
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_2(it87, it8712);
|
||||
I2C_CLIENT_INSMOD_2(it87, it8712);
|
||||
|
||||
#define REG 0x2e /* The register to read/write */
|
||||
#define DEV 0x07 /* Register: Logical device select */
|
||||
@ -192,6 +194,7 @@ static int DIV_TO_REG(int val)
|
||||
allocated. */
|
||||
struct it87_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
enum chips type;
|
||||
|
||||
@ -218,7 +221,7 @@ struct it87_data {
|
||||
|
||||
|
||||
static int it87_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int it87_find(int *address);
|
||||
static int it87_isa_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int it87_detect(struct i2c_adapter *adapter, int address, int kind);
|
||||
static int it87_detach_client(struct i2c_client *client);
|
||||
|
||||
@ -239,6 +242,14 @@ static struct i2c_driver it87_driver = {
|
||||
.detach_client = it87_detach_client,
|
||||
};
|
||||
|
||||
static struct i2c_driver it87_isa_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "it87-isa",
|
||||
.attach_adapter = it87_isa_attach_adapter,
|
||||
.detach_client = it87_detach_client,
|
||||
};
|
||||
|
||||
|
||||
static ssize_t show_in(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
@ -686,11 +697,16 @@ static int it87_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, it87_detect);
|
||||
return i2c_probe(adapter, &addr_data, it87_detect);
|
||||
}
|
||||
|
||||
/* SuperIO detection - will change normal_isa[0] if a chip is found */
|
||||
static int it87_find(int *address)
|
||||
static int it87_isa_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return it87_detect(adapter, isa_address, -1);
|
||||
}
|
||||
|
||||
/* SuperIO detection - will change isa_address if a chip is found */
|
||||
static int __init it87_find(int *address)
|
||||
{
|
||||
int err = -ENODEV;
|
||||
|
||||
@ -721,7 +737,7 @@ exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
/* This function is called by i2c_probe */
|
||||
int it87_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
int i;
|
||||
@ -738,7 +754,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
/* Reserve the ISA region */
|
||||
if (is_isa)
|
||||
if (!request_region(address, IT87_EXTENT, it87_driver.name))
|
||||
if (!request_region(address, IT87_EXTENT, it87_isa_driver.name))
|
||||
goto ERROR0;
|
||||
|
||||
/* Probe whether there is anything available on this address. Already
|
||||
@ -784,7 +800,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
i2c_set_clientdata(new_client, data);
|
||||
new_client->addr = address;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &it87_driver;
|
||||
new_client->driver = is_isa ? &it87_isa_driver : &it87_driver;
|
||||
new_client->flags = 0;
|
||||
|
||||
/* Now, we do the remaining detection. */
|
||||
@ -840,6 +856,12 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
it87_init_client(new_client, data);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto ERROR3;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
|
||||
@ -897,13 +919,15 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
}
|
||||
|
||||
if (data->type == it8712) {
|
||||
data->vrm = i2c_which_vrm();
|
||||
data->vrm = vid_which_vrm();
|
||||
device_create_file_vrm(new_client);
|
||||
device_create_file_vid(new_client);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR3:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR2:
|
||||
kfree(data);
|
||||
ERROR1:
|
||||
@ -915,17 +939,17 @@ ERROR0:
|
||||
|
||||
static int it87_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct it87_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev,
|
||||
"Client deregistration failed, client not detached.\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
if(i2c_is_isa_client(client))
|
||||
release_region(client->addr, IT87_EXTENT);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1158,16 +1182,28 @@ static struct it87_data *it87_update_device(struct device *dev)
|
||||
|
||||
static int __init sm_it87_init(void)
|
||||
{
|
||||
int addr;
|
||||
int addr, res;
|
||||
|
||||
if (!it87_find(&addr)) {
|
||||
normal_isa[0] = addr;
|
||||
isa_address = addr;
|
||||
}
|
||||
return i2c_add_driver(&it87_driver);
|
||||
|
||||
res = i2c_add_driver(&it87_driver);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = i2c_isa_add_driver(&it87_isa_driver);
|
||||
if (res) {
|
||||
i2c_del_driver(&it87_driver);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit sm_it87_exit(void)
|
||||
{
|
||||
i2c_isa_del_driver(&it87_isa_driver);
|
||||
i2c_del_driver(&it87_driver);
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,9 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* Addresses to scan
|
||||
@ -51,13 +52,12 @@
|
||||
*/
|
||||
|
||||
static unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/*
|
||||
* Insmod parameters
|
||||
*/
|
||||
|
||||
SENSORS_INSMOD_1(lm63);
|
||||
I2C_CLIENT_INSMOD_1(lm63);
|
||||
|
||||
/*
|
||||
* The LM63 registers
|
||||
@ -152,6 +152,7 @@ static struct i2c_driver lm63_driver = {
|
||||
|
||||
struct lm63_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
@ -358,7 +359,7 @@ static int lm63_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, lm63_detect);
|
||||
return i2c_probe(adapter, &addr_data, lm63_detect);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -437,6 +438,12 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
lm63_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
if (data->config & 0x04) { /* tachometer enabled */
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan1_input.dev_attr);
|
||||
@ -462,6 +469,8 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -505,15 +514,15 @@ static void lm63_init_client(struct i2c_client *client)
|
||||
|
||||
static int lm63_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm63_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -23,17 +23,17 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include "lm75.h"
|
||||
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
|
||||
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(lm75);
|
||||
I2C_CLIENT_INSMOD_1(lm75);
|
||||
|
||||
/* Many LM75 constants specified below */
|
||||
|
||||
@ -46,6 +46,7 @@ SENSORS_INSMOD_1(lm75);
|
||||
/* Each client has this additional data */
|
||||
struct lm75_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
@ -107,10 +108,10 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, lm75_detect);
|
||||
return i2c_probe(adapter, &addr_data, lm75_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
/* This function is called by i2c_probe */
|
||||
static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
int i;
|
||||
@ -119,16 +120,6 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
int err = 0;
|
||||
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. */
|
||||
#ifdef DEBUG
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
dev_dbg(&adapter->dev,
|
||||
"lm75_detect called for an ISA bus adapter?!?\n");
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA))
|
||||
goto exit;
|
||||
@ -208,12 +199,20 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
lm75_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -222,8 +221,10 @@ exit:
|
||||
|
||||
static int lm75_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm75_data *data = i2c_get_clientdata(client);
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
i2c_detach_client(client);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -251,8 +252,12 @@ static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
|
||||
|
||||
static void lm75_init_client(struct i2c_client *client)
|
||||
{
|
||||
/* Initialize the LM75 chip */
|
||||
lm75_write_value(client, LM75_REG_CONF, 0);
|
||||
int reg;
|
||||
|
||||
/* Enable if in shutdown mode */
|
||||
reg = lm75_read_value(client, LM75_REG_CONF);
|
||||
if (reg >= 0 && (reg & 0x01))
|
||||
lm75_write_value(client, LM75_REG_CONF, reg & 0xfe);
|
||||
}
|
||||
|
||||
static struct lm75_data *lm75_update_device(struct device *dev)
|
||||
|
@ -25,7 +25,7 @@
|
||||
which contains this code, we don't worry about the wasted space.
|
||||
*/
|
||||
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon.h>
|
||||
|
||||
/* straight from the datasheet */
|
||||
#define LM75_TEMP_MIN (-55000)
|
||||
|
@ -30,15 +30,14 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(lm77);
|
||||
I2C_CLIENT_INSMOD_1(lm77);
|
||||
|
||||
/* The LM77 registers */
|
||||
#define LM77_REG_TEMP 0x00
|
||||
@ -51,6 +50,7 @@ SENSORS_INSMOD_1(lm77);
|
||||
/* Each client has this additional data */
|
||||
struct lm77_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid;
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
@ -208,10 +208,10 @@ static int lm77_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, lm77_detect);
|
||||
return i2c_probe(adapter, &addr_data, lm77_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
/* This function is called by i2c_probe */
|
||||
static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
@ -317,6 +317,12 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
lm77_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_crit);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_min);
|
||||
@ -327,6 +333,8 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
device_create_file(&new_client->dev, &dev_attr_alarms);
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -335,8 +343,10 @@ exit:
|
||||
|
||||
static int lm77_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm77_data *data = i2c_get_clientdata(client);
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
i2c_detach_client(client);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,10 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
@ -31,10 +34,10 @@ static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24,
|
||||
0x25, 0x26, 0x27, 0x28, 0x29,
|
||||
0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
|
||||
0x2f, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
|
||||
static unsigned short isa_address = 0x290;
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_3(lm78, lm78j, lm79);
|
||||
I2C_CLIENT_INSMOD_2(lm78, lm79);
|
||||
|
||||
/* Many LM78 constants specified below */
|
||||
|
||||
@ -104,13 +107,6 @@ static inline int TEMP_FROM_REG(s8 val)
|
||||
return val * 1000;
|
||||
}
|
||||
|
||||
/* VID: mV
|
||||
REG: (see doc/vid) */
|
||||
static inline int VID_FROM_REG(u8 val)
|
||||
{
|
||||
return val==0x1f ? 0 : val>=0x10 ? 5100-val*100 : 2050-val*50;
|
||||
}
|
||||
|
||||
#define DIV_FROM_REG(val) (1 << (val))
|
||||
|
||||
/* There are some complications in a module like this. First off, LM78 chips
|
||||
@ -134,6 +130,7 @@ static inline int VID_FROM_REG(u8 val)
|
||||
allocated. */
|
||||
struct lm78_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
enum chips type;
|
||||
|
||||
@ -156,6 +153,7 @@ struct lm78_data {
|
||||
|
||||
|
||||
static int lm78_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int lm78_isa_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
|
||||
static int lm78_detach_client(struct i2c_client *client);
|
||||
|
||||
@ -174,6 +172,14 @@ static struct i2c_driver lm78_driver = {
|
||||
.detach_client = lm78_detach_client,
|
||||
};
|
||||
|
||||
static struct i2c_driver lm78_isa_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "lm78-isa",
|
||||
.attach_adapter = lm78_isa_attach_adapter,
|
||||
.detach_client = lm78_detach_client,
|
||||
};
|
||||
|
||||
|
||||
/* 7 Voltages */
|
||||
static ssize_t show_in(struct device *dev, char *buf, int nr)
|
||||
{
|
||||
@ -445,7 +451,7 @@ static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL);
|
||||
static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct lm78_data *data = lm78_update_device(dev);
|
||||
return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
|
||||
return sprintf(buf, "%d\n", vid_from_reg(82, data->vid));
|
||||
}
|
||||
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
|
||||
|
||||
@ -465,10 +471,15 @@ static int lm78_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, lm78_detect);
|
||||
return i2c_probe(adapter, &addr_data, lm78_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
static int lm78_isa_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return lm78_detect(adapter, isa_address, -1);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_probe */
|
||||
int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
int i, err;
|
||||
@ -485,7 +496,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
/* Reserve the ISA region */
|
||||
if (is_isa)
|
||||
if (!request_region(address, LM78_EXTENT, lm78_driver.name)) {
|
||||
if (!request_region(address, LM78_EXTENT,
|
||||
lm78_isa_driver.name)) {
|
||||
err = -EBUSY;
|
||||
goto ERROR0;
|
||||
}
|
||||
@ -540,7 +552,7 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
i2c_set_clientdata(new_client, data);
|
||||
new_client->addr = address;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &lm78_driver;
|
||||
new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver;
|
||||
new_client->flags = 0;
|
||||
|
||||
/* Now, we do the remaining detection. */
|
||||
@ -559,10 +571,9 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
/* Determine the chip type. */
|
||||
if (kind <= 0) {
|
||||
i = lm78_read_value(new_client, LM78_REG_CHIPID);
|
||||
if (i == 0x00 || i == 0x20)
|
||||
if (i == 0x00 || i == 0x20 /* LM78 */
|
||||
|| i == 0x40) /* LM78-J */
|
||||
kind = lm78;
|
||||
else if (i == 0x40)
|
||||
kind = lm78j;
|
||||
else if ((i & 0xfe) == 0xc0)
|
||||
kind = lm79;
|
||||
else {
|
||||
@ -578,8 +589,6 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
if (kind == lm78) {
|
||||
client_name = "lm78";
|
||||
} else if (kind == lm78j) {
|
||||
client_name = "lm78-j";
|
||||
} else if (kind == lm79) {
|
||||
client_name = "lm79";
|
||||
}
|
||||
@ -605,6 +614,12 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
}
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto ERROR3;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -643,6 +658,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR3:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR2:
|
||||
kfree(data);
|
||||
ERROR1:
|
||||
@ -654,18 +671,18 @@ ERROR0:
|
||||
|
||||
static int lm78_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm78_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev,
|
||||
"Client deregistration failed, client not detached.\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
if(i2c_is_isa_client(client))
|
||||
release_region(client->addr, LM78_EXTENT);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -777,18 +794,31 @@ static struct lm78_data *lm78_update_device(struct device *dev)
|
||||
|
||||
static int __init sm_lm78_init(void)
|
||||
{
|
||||
return i2c_add_driver(&lm78_driver);
|
||||
int res;
|
||||
|
||||
res = i2c_add_driver(&lm78_driver);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = i2c_isa_add_driver(&lm78_isa_driver);
|
||||
if (res) {
|
||||
i2c_del_driver(&lm78_driver);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit sm_lm78_exit(void)
|
||||
{
|
||||
i2c_isa_del_driver(&lm78_isa_driver);
|
||||
i2c_del_driver(&lm78_driver);
|
||||
}
|
||||
|
||||
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
|
||||
MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver");
|
||||
MODULE_DESCRIPTION("LM78/LM79 driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(sm_lm78_init);
|
||||
|
@ -26,15 +26,15 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c,
|
||||
0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(lm80);
|
||||
I2C_CLIENT_INSMOD_1(lm80);
|
||||
|
||||
/* Many LM80 constants specified below */
|
||||
|
||||
@ -107,6 +107,7 @@ static inline long TEMP_FROM_REG(u16 temp)
|
||||
|
||||
struct lm80_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
@ -389,7 +390,7 @@ static int lm80_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, lm80_detect);
|
||||
return i2c_probe(adapter, &addr_data, lm80_detect);
|
||||
}
|
||||
|
||||
int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
@ -451,6 +452,12 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2));
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto error_detach;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -487,6 +494,8 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
error_detach:
|
||||
i2c_detach_client(new_client);
|
||||
error_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -495,15 +504,15 @@ exit:
|
||||
|
||||
static int lm80_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm80_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -32,8 +32,9 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* Addresses to scan
|
||||
@ -45,13 +46,12 @@ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
|
||||
0x29, 0x2a, 0x2b,
|
||||
0x4c, 0x4d, 0x4e,
|
||||
I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/*
|
||||
* Insmod parameters
|
||||
*/
|
||||
|
||||
SENSORS_INSMOD_1(lm83);
|
||||
I2C_CLIENT_INSMOD_1(lm83);
|
||||
|
||||
/*
|
||||
* The LM83 registers
|
||||
@ -138,6 +138,7 @@ static struct i2c_driver lm83_driver = {
|
||||
|
||||
struct lm83_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
@ -212,7 +213,7 @@ static int lm83_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, lm83_detect);
|
||||
return i2c_probe(adapter, &addr_data, lm83_detect);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -312,6 +313,12 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
*/
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
@ -340,6 +347,8 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -348,15 +357,15 @@ exit:
|
||||
|
||||
static int lm83_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm83_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev,
|
||||
"Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -28,15 +28,15 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
|
||||
I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
|
||||
|
||||
/* The LM85 registers */
|
||||
|
||||
@ -281,15 +281,6 @@ static int ZONE_TO_REG( int zone )
|
||||
#define PPR_TO_REG(val,fan) (SENSORS_LIMIT((val)-1,0,3)<<(fan *2))
|
||||
#define PPR_FROM_REG(val,fan) ((((val)>>(fan * 2))&0x03)+1)
|
||||
|
||||
/* i2c-vid.h defines vid_from_reg() */
|
||||
#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
|
||||
|
||||
/* Unlike some other drivers we DO NOT set initial limits. Use
|
||||
* the config file to set limits. Some users have reported
|
||||
* motherboards shutting down when we set limits in a previous
|
||||
* version of the driver.
|
||||
*/
|
||||
|
||||
/* Chip sampling rates
|
||||
*
|
||||
* Some sensors are not updated more frequently than once per second
|
||||
@ -339,6 +330,7 @@ struct lm85_autofan {
|
||||
|
||||
struct lm85_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
enum chips type;
|
||||
|
||||
@ -1019,7 +1011,7 @@ int lm85_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, lm85_detect);
|
||||
return i2c_probe(adapter, &addr_data, lm85_detect);
|
||||
}
|
||||
|
||||
int lm85_detect(struct i2c_adapter *adapter, int address,
|
||||
@ -1031,11 +1023,6 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
|
||||
int err = 0;
|
||||
const char *type_name = "";
|
||||
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
/* This chip has no ISA interface */
|
||||
goto ERROR0 ;
|
||||
};
|
||||
|
||||
if (!i2c_check_functionality(adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA)) {
|
||||
/* We need to be able to do byte I/O */
|
||||
@ -1160,12 +1147,18 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
|
||||
goto ERROR1;
|
||||
|
||||
/* Set the VRM version */
|
||||
data->vrm = i2c_which_vrm();
|
||||
data->vrm = vid_which_vrm();
|
||||
|
||||
/* Initialize the LM85 chip */
|
||||
lm85_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto ERROR2;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -1235,6 +1228,8 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
|
||||
return 0;
|
||||
|
||||
/* Error out and cleanup code */
|
||||
ERROR2:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR1:
|
||||
kfree(data);
|
||||
ERROR0:
|
||||
@ -1243,8 +1238,10 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
|
||||
|
||||
int lm85_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm85_data *data = i2c_get_clientdata(client);
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
i2c_detach_client(client);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -57,8 +57,9 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* Addresses to scan
|
||||
@ -66,13 +67,12 @@
|
||||
*/
|
||||
|
||||
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/*
|
||||
* Insmod parameters
|
||||
*/
|
||||
|
||||
SENSORS_INSMOD_1(lm87);
|
||||
I2C_CLIENT_INSMOD_1(lm87);
|
||||
|
||||
/*
|
||||
* The LM87 registers
|
||||
@ -175,6 +175,7 @@ static struct i2c_driver lm87_driver = {
|
||||
|
||||
struct lm87_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
@ -537,7 +538,7 @@ static int lm87_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, lm87_detect);
|
||||
return i2c_probe(adapter, &addr_data, lm87_detect);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -608,6 +609,12 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
data->in_scale[7] = 1875;
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -673,6 +680,8 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -685,7 +694,7 @@ static void lm87_init_client(struct i2c_client *client)
|
||||
u8 config;
|
||||
|
||||
data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE);
|
||||
data->vrm = i2c_which_vrm();
|
||||
data->vrm = vid_which_vrm();
|
||||
|
||||
config = lm87_read_value(client, LM87_REG_CONFIG);
|
||||
if (!(config & 0x01)) {
|
||||
@ -719,15 +728,15 @@ static void lm87_init_client(struct i2c_client *client)
|
||||
|
||||
static int lm87_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm87_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -75,8 +75,9 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* Addresses to scan
|
||||
@ -89,13 +90,12 @@
|
||||
*/
|
||||
|
||||
static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/*
|
||||
* Insmod parameters
|
||||
*/
|
||||
|
||||
SENSORS_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
|
||||
I2C_CLIENT_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
|
||||
|
||||
/*
|
||||
* The LM90 registers
|
||||
@ -200,6 +200,7 @@ static struct i2c_driver lm90_driver = {
|
||||
|
||||
struct lm90_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
@ -352,7 +353,7 @@ static int lm90_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, lm90_detect);
|
||||
return i2c_probe(adapter, &addr_data, lm90_detect);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -500,6 +501,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
lm90_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
@ -524,6 +531,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -547,15 +556,15 @@ static void lm90_init_client(struct i2c_client *client)
|
||||
|
||||
static int lm90_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm90_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -44,17 +44,16 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* The LM92 and MAX6635 have 2 two-state pins for address selection,
|
||||
resulting in 4 possible addresses. */
|
||||
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
|
||||
I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(lm92);
|
||||
I2C_CLIENT_INSMOD_1(lm92);
|
||||
|
||||
/* The LM92 registers */
|
||||
#define LM92_REG_CONFIG 0x01 /* 8-bit, RW */
|
||||
@ -96,6 +95,7 @@ static struct i2c_driver lm92_driver;
|
||||
/* Client data (each client gets its own) */
|
||||
struct lm92_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
@ -359,6 +359,12 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
lm92_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_crit);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
|
||||
@ -370,6 +376,8 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -380,20 +388,20 @@ static int lm92_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, lm92_detect);
|
||||
return i2c_probe(adapter, &addr_data, lm92_detect);
|
||||
}
|
||||
|
||||
static int lm92_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm92_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -31,20 +31,19 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
|
||||
0x29, 0x2a, 0x2b,
|
||||
0x4c, 0x4d, 0x4e,
|
||||
I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/*
|
||||
* Insmod parameters
|
||||
*/
|
||||
|
||||
SENSORS_INSMOD_1(max1619);
|
||||
I2C_CLIENT_INSMOD_1(max1619);
|
||||
|
||||
/*
|
||||
* The MAX1619 registers
|
||||
@ -104,6 +103,7 @@ static struct i2c_driver max1619_driver = {
|
||||
|
||||
struct max1619_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
@ -179,7 +179,7 @@ static int max1619_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, max1619_detect);
|
||||
return i2c_probe(adapter, &addr_data, max1619_detect);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -275,6 +275,12 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
max1619_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
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_temp2_min);
|
||||
@ -285,6 +291,8 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -308,15 +316,15 @@ static void max1619_init_client(struct i2c_client *client)
|
||||
|
||||
static int max1619_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct max1619_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -55,7 +55,9 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <asm/io.h>
|
||||
@ -68,14 +70,10 @@ module_param(force_addr, ushort, 0);
|
||||
MODULE_PARM_DESC(force_addr,
|
||||
"Initialize the base address of the sensors");
|
||||
|
||||
/* Addresses to scan.
|
||||
/* Device address
|
||||
Note that we can't determine the ISA address until we have initialized
|
||||
our module */
|
||||
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(sis5595);
|
||||
static unsigned short address;
|
||||
|
||||
/* Many SIS5595 constants specified below */
|
||||
|
||||
@ -168,6 +166,7 @@ static inline u8 DIV_TO_REG(int val)
|
||||
allocated. */
|
||||
struct sis5595_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
|
||||
struct semaphore update_lock;
|
||||
@ -190,8 +189,7 @@ struct sis5595_data {
|
||||
|
||||
static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */
|
||||
|
||||
static int sis5595_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int sis5595_detect(struct i2c_adapter *adapter, int address, int kind);
|
||||
static int sis5595_detect(struct i2c_adapter *adapter);
|
||||
static int sis5595_detach_client(struct i2c_client *client);
|
||||
|
||||
static int sis5595_read_value(struct i2c_client *client, u8 register);
|
||||
@ -202,9 +200,7 @@ static void sis5595_init_client(struct i2c_client *client);
|
||||
static struct i2c_driver sis5595_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "sis5595",
|
||||
.id = I2C_DRIVERID_SIS5595,
|
||||
.flags = I2C_DF_NOTIFY,
|
||||
.attach_adapter = sis5595_attach_adapter,
|
||||
.attach_adapter = sis5595_detect,
|
||||
.detach_client = sis5595_detach_client,
|
||||
};
|
||||
|
||||
@ -476,14 +472,7 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
|
||||
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
|
||||
|
||||
/* This is called when the module is loaded */
|
||||
static int sis5595_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, sis5595_detect);
|
||||
}
|
||||
|
||||
int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int sis5595_detect(struct i2c_adapter *adapter)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
@ -492,10 +481,6 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
char val;
|
||||
u16 a;
|
||||
|
||||
/* Make sure we are probing the ISA bus!! */
|
||||
if (!i2c_is_isa_adapter(adapter))
|
||||
goto exit;
|
||||
|
||||
if (force_addr)
|
||||
address = force_addr & ~(SIS5595_EXTENT - 1);
|
||||
/* Reserve the ISA region */
|
||||
@ -578,6 +563,12 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
}
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -608,7 +599,9 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit_release:
|
||||
@ -619,18 +612,17 @@ exit:
|
||||
|
||||
static int sis5595_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct sis5595_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev,
|
||||
"Client deregistration failed, client not detached.\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
if (i2c_is_isa_client(client))
|
||||
release_region(client->addr, SIS5595_EXTENT);
|
||||
release_region(client->addr, SIS5595_EXTENT);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -745,7 +737,6 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
|
||||
{
|
||||
u16 val;
|
||||
int *i;
|
||||
int addr = 0;
|
||||
|
||||
for (i = blacklist; *i != 0; i++) {
|
||||
struct pci_dev *dev;
|
||||
@ -761,22 +752,19 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
|
||||
pci_read_config_word(dev, SIS5595_BASE_REG, &val))
|
||||
return -ENODEV;
|
||||
|
||||
addr = val & ~(SIS5595_EXTENT - 1);
|
||||
if (addr == 0 && force_addr == 0) {
|
||||
address = val & ~(SIS5595_EXTENT - 1);
|
||||
if (address == 0 && force_addr == 0) {
|
||||
dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (force_addr)
|
||||
addr = force_addr; /* so detect will get called */
|
||||
|
||||
if (!addr) {
|
||||
if (!address) {
|
||||
dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
normal_isa[0] = addr;
|
||||
|
||||
s_bridge = pci_dev_get(dev);
|
||||
if (i2c_add_driver(&sis5595_driver)) {
|
||||
if (i2c_isa_add_driver(&sis5595_driver)) {
|
||||
pci_dev_put(s_bridge);
|
||||
s_bridge = NULL;
|
||||
}
|
||||
@ -803,7 +791,7 @@ static void __exit sm_sis5595_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&sis5595_pci_driver);
|
||||
if (s_bridge != NULL) {
|
||||
i2c_del_driver(&sis5595_driver);
|
||||
i2c_isa_del_driver(&sis5595_driver);
|
||||
pci_dev_put(s_bridge);
|
||||
s_bridge = NULL;
|
||||
}
|
||||
|
@ -31,23 +31,14 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||
/* Address is autodetected, there is no default value */
|
||||
static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
|
||||
static struct i2c_force_data forces[] = {{NULL}};
|
||||
|
||||
enum chips { any_chip, smsc47b397 };
|
||||
static struct i2c_address_data addr_data = {
|
||||
.normal_i2c = normal_i2c,
|
||||
.normal_isa = normal_isa,
|
||||
.probe = normal_i2c, /* cheat */
|
||||
.ignore = normal_i2c, /* cheat */
|
||||
.forces = forces,
|
||||
};
|
||||
static unsigned short address;
|
||||
|
||||
/* Super-I/0 registers and commands */
|
||||
|
||||
@ -100,6 +91,7 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
|
||||
|
||||
struct smsc47b397_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
|
||||
struct semaphore update_lock;
|
||||
@ -215,52 +207,40 @@ sysfs_fan(4);
|
||||
#define device_create_file_fan(client, num) \
|
||||
device_create_file(&client->dev, &dev_attr_fan##num##_input)
|
||||
|
||||
static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind);
|
||||
|
||||
static int smsc47b397_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, smsc47b397_detect);
|
||||
}
|
||||
|
||||
static int smsc47b397_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct smsc47b397_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
release_region(client->addr, SMSC_EXTENT);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smsc47b397_detect(struct i2c_adapter *adapter);
|
||||
|
||||
static struct i2c_driver smsc47b397_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "smsc47b397",
|
||||
.id = I2C_DRIVERID_SMSC47B397,
|
||||
.flags = I2C_DF_NOTIFY,
|
||||
.attach_adapter = smsc47b397_attach_adapter,
|
||||
.attach_adapter = smsc47b397_detect,
|
||||
.detach_client = smsc47b397_detach_client,
|
||||
};
|
||||
|
||||
static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
|
||||
static int smsc47b397_detect(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
struct smsc47b397_data *data;
|
||||
int err = 0;
|
||||
|
||||
if (!i2c_is_isa_adapter(adapter)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!request_region(addr, SMSC_EXTENT, smsc47b397_driver.name)) {
|
||||
dev_err(&adapter->dev, "Region 0x%x already in use!\n", addr);
|
||||
if (!request_region(address, SMSC_EXTENT, smsc47b397_driver.name)) {
|
||||
dev_err(&adapter->dev, "Region 0x%x already in use!\n",
|
||||
address);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -272,7 +252,7 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
new_client->addr = addr;
|
||||
new_client->addr = address;
|
||||
init_MUTEX(&data->lock);
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &smsc47b397_driver;
|
||||
@ -285,6 +265,12 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto error_free;
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto error_detach;
|
||||
}
|
||||
|
||||
device_create_file_temp(new_client, 1);
|
||||
device_create_file_temp(new_client, 2);
|
||||
device_create_file_temp(new_client, 3);
|
||||
@ -297,14 +283,16 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
error_detach:
|
||||
i2c_detach_client(new_client);
|
||||
error_free:
|
||||
kfree(data);
|
||||
error_release:
|
||||
release_region(addr, SMSC_EXTENT);
|
||||
release_region(address, SMSC_EXTENT);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __init smsc47b397_find(unsigned int *addr)
|
||||
static int __init smsc47b397_find(unsigned short *addr)
|
||||
{
|
||||
u8 id, rev;
|
||||
|
||||
@ -333,15 +321,15 @@ static int __init smsc47b397_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = smsc47b397_find(normal_isa)))
|
||||
if ((ret = smsc47b397_find(&address)))
|
||||
return ret;
|
||||
|
||||
return i2c_add_driver(&smsc47b397_driver);
|
||||
return i2c_isa_add_driver(&smsc47b397_driver);
|
||||
}
|
||||
|
||||
static void __exit smsc47b397_exit(void)
|
||||
{
|
||||
i2c_del_driver(&smsc47b397_driver);
|
||||
i2c_isa_del_driver(&smsc47b397_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
|
||||
|
@ -30,21 +30,14 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||
/* Address is autodetected, there is no default value */
|
||||
static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
|
||||
static struct i2c_force_data forces[] = {{NULL}};
|
||||
|
||||
enum chips { any_chip, smsc47m1 };
|
||||
static struct i2c_address_data addr_data = {
|
||||
.normal_i2c = normal_i2c,
|
||||
.normal_isa = normal_isa,
|
||||
.forces = forces,
|
||||
};
|
||||
static unsigned short address;
|
||||
|
||||
/* Super-I/0 registers and commands */
|
||||
|
||||
@ -108,6 +101,7 @@ superio_exit(void)
|
||||
|
||||
struct smsc47m1_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
|
||||
struct semaphore update_lock;
|
||||
@ -121,9 +115,7 @@ struct smsc47m1_data {
|
||||
};
|
||||
|
||||
|
||||
static int smsc47m1_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int smsc47m1_find(int *address);
|
||||
static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind);
|
||||
static int smsc47m1_detect(struct i2c_adapter *adapter);
|
||||
static int smsc47m1_detach_client(struct i2c_client *client);
|
||||
|
||||
static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
|
||||
@ -136,9 +128,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
|
||||
static struct i2c_driver smsc47m1_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "smsc47m1",
|
||||
.id = I2C_DRIVERID_SMSC47M1,
|
||||
.flags = I2C_DF_NOTIFY,
|
||||
.attach_adapter = smsc47m1_attach_adapter,
|
||||
.attach_adapter = smsc47m1_detect,
|
||||
.detach_client = smsc47m1_detach_client,
|
||||
};
|
||||
|
||||
@ -354,14 +344,7 @@ fan_present(2);
|
||||
|
||||
static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
|
||||
|
||||
static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, smsc47m1_detect);
|
||||
}
|
||||
|
||||
static int smsc47m1_find(int *address)
|
||||
static int __init smsc47m1_find(unsigned short *addr)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
@ -388,10 +371,10 @@ static int smsc47m1_find(int *address)
|
||||
}
|
||||
|
||||
superio_select();
|
||||
*address = (superio_inb(SUPERIO_REG_BASE) << 8)
|
||||
| superio_inb(SUPERIO_REG_BASE + 1);
|
||||
*addr = (superio_inb(SUPERIO_REG_BASE) << 8)
|
||||
| superio_inb(SUPERIO_REG_BASE + 1);
|
||||
val = superio_inb(SUPERIO_REG_ACT);
|
||||
if (*address == 0 || (val & 0x01) == 0) {
|
||||
if (*addr == 0 || (val & 0x01) == 0) {
|
||||
printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
|
||||
superio_exit();
|
||||
return -ENODEV;
|
||||
@ -401,17 +384,13 @@ static int smsc47m1_find(int *address)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int smsc47m1_detect(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
struct smsc47m1_data *data;
|
||||
int err = 0;
|
||||
int fan1, fan2, pwm1, pwm2;
|
||||
|
||||
if (!i2c_is_isa_adapter(adapter)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
|
||||
dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
|
||||
return -EBUSY;
|
||||
@ -461,6 +440,13 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
function. */
|
||||
smsc47m1_update_device(&new_client->dev, 1);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto error_detach;
|
||||
}
|
||||
|
||||
if (fan1) {
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_min);
|
||||
@ -494,6 +480,8 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
error_detach:
|
||||
i2c_detach_client(new_client);
|
||||
error_free:
|
||||
kfree(data);
|
||||
error_release:
|
||||
@ -503,16 +491,16 @@ error_release:
|
||||
|
||||
static int smsc47m1_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct smsc47m1_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
release_region(client->addr, SMSC_EXTENT);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -573,16 +561,16 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
|
||||
|
||||
static int __init sm_smsc47m1_init(void)
|
||||
{
|
||||
if (smsc47m1_find(normal_isa)) {
|
||||
if (smsc47m1_find(&address)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return i2c_add_driver(&smsc47m1_driver);
|
||||
return i2c_isa_add_driver(&smsc47m1_driver);
|
||||
}
|
||||
|
||||
static void __exit sm_smsc47m1_exit(void)
|
||||
{
|
||||
i2c_del_driver(&smsc47m1_driver);
|
||||
i2c_isa_del_driver(&smsc47m1_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
|
||||
|
@ -35,7 +35,9 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
@ -47,14 +49,10 @@ module_param(force_addr, ushort, 0);
|
||||
MODULE_PARM_DESC(force_addr,
|
||||
"Initialize the base address of the sensors");
|
||||
|
||||
/* Addresses to scan.
|
||||
/* Device address
|
||||
Note that we can't determine the ISA address until we have initialized
|
||||
our module */
|
||||
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(via686a);
|
||||
static unsigned short address;
|
||||
|
||||
/*
|
||||
The Via 686a southbridge has a LM78-like chip integrated on the same IC.
|
||||
@ -297,6 +295,7 @@ static inline long TEMP_FROM_REG10(u16 val)
|
||||
via686a client is allocated. */
|
||||
struct via686a_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
@ -315,8 +314,7 @@ struct via686a_data {
|
||||
|
||||
static struct pci_dev *s_bridge; /* pointer to the (only) via686a */
|
||||
|
||||
static int via686a_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int via686a_detect(struct i2c_adapter *adapter, int address, int kind);
|
||||
static int via686a_detect(struct i2c_adapter *adapter);
|
||||
static int via686a_detach_client(struct i2c_client *client);
|
||||
|
||||
static inline int via686a_read_value(struct i2c_client *client, u8 reg)
|
||||
@ -576,22 +574,13 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
|
||||
static struct i2c_driver via686a_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "via686a",
|
||||
.id = I2C_DRIVERID_VIA686A,
|
||||
.flags = I2C_DF_NOTIFY,
|
||||
.attach_adapter = via686a_attach_adapter,
|
||||
.attach_adapter = via686a_detect,
|
||||
.detach_client = via686a_detach_client,
|
||||
};
|
||||
|
||||
|
||||
/* This is called when the module is loaded */
|
||||
static int via686a_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, via686a_detect);
|
||||
}
|
||||
|
||||
static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int via686a_detect(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
struct via686a_data *data;
|
||||
@ -599,13 +588,6 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
const char client_name[] = "via686a";
|
||||
u16 val;
|
||||
|
||||
/* Make sure we are probing the ISA bus!! */
|
||||
if (!i2c_is_isa_adapter(adapter)) {
|
||||
dev_err(&adapter->dev,
|
||||
"via686a_detect called for an I2C bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 8231 requires multiple of 256, we enforce that on 686 as well */
|
||||
if (force_addr)
|
||||
address = force_addr & 0xFF00;
|
||||
@ -637,7 +619,7 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
goto exit_release;
|
||||
}
|
||||
memset(data, 0, sizeof(struct via686a_data));
|
||||
|
||||
@ -655,12 +637,18 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
init_MUTEX(&data->update_lock);
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
goto exit_free;
|
||||
|
||||
/* Initialize the VIA686A chip */
|
||||
via686a_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -695,25 +683,27 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR3:
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
ERROR0:
|
||||
exit_release:
|
||||
release_region(address, VIA686A_EXTENT);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int via686a_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct via686a_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev,
|
||||
"Client deregistration failed, client not detached.\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
release_region(client->addr, VIA686A_EXTENT);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -810,29 +800,25 @@ static int __devinit via686a_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
u16 val;
|
||||
int addr = 0;
|
||||
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_read_config_word(dev, VIA686A_BASE_REG, &val))
|
||||
return -ENODEV;
|
||||
|
||||
addr = val & ~(VIA686A_EXTENT - 1);
|
||||
if (addr == 0 && force_addr == 0) {
|
||||
address = val & ~(VIA686A_EXTENT - 1);
|
||||
if (address == 0 && force_addr == 0) {
|
||||
dev_err(&dev->dev, "base address not set - upgrade BIOS "
|
||||
"or use force_addr=0xaddr\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (force_addr)
|
||||
addr = force_addr; /* so detect will get called */
|
||||
|
||||
if (!addr) {
|
||||
if (!address) {
|
||||
dev_err(&dev->dev, "No Via 686A sensors found.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
normal_isa[0] = addr;
|
||||
|
||||
s_bridge = pci_dev_get(dev);
|
||||
if (i2c_add_driver(&via686a_driver)) {
|
||||
if (i2c_isa_add_driver(&via686a_driver)) {
|
||||
pci_dev_put(s_bridge);
|
||||
s_bridge = NULL;
|
||||
}
|
||||
@ -859,7 +845,7 @@ static void __exit sm_via686a_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&via686a_pci_driver);
|
||||
if (s_bridge != NULL) {
|
||||
i2c_del_driver(&via686a_driver);
|
||||
i2c_isa_del_driver(&via686a_driver);
|
||||
pci_dev_put(s_bridge);
|
||||
s_bridge = NULL;
|
||||
}
|
||||
|
@ -9,6 +9,9 @@
|
||||
Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
|
||||
in testing and debugging this driver.
|
||||
|
||||
This driver also supports the W83627EHG, which is the lead-free
|
||||
version of the W83627EHF.
|
||||
|
||||
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
|
||||
@ -37,17 +40,14 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/io.h>
|
||||
#include "lm75.h"
|
||||
|
||||
/* Addresses to scan
|
||||
The actual ISA address is read from Super-I/O configuration space */
|
||||
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(w83627ehf);
|
||||
/* The actual ISA address is read from Super-I/O configuration space */
|
||||
static unsigned short address;
|
||||
|
||||
/*
|
||||
* Super-I/O constants and functions
|
||||
@ -174,6 +174,7 @@ temp1_to_reg(int temp)
|
||||
|
||||
struct w83627ehf_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
|
||||
struct semaphore update_lock;
|
||||
@ -666,15 +667,12 @@ static void w83627ehf_init_client(struct i2c_client *client)
|
||||
}
|
||||
}
|
||||
|
||||
static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int w83627ehf_detect(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct i2c_client *client;
|
||||
struct w83627ehf_data *data;
|
||||
int i, err = 0;
|
||||
|
||||
if (!i2c_is_isa_adapter(adapter))
|
||||
return 0;
|
||||
|
||||
if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
|
||||
err = -EBUSY;
|
||||
goto exit;
|
||||
@ -720,6 +718,12 @@ static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
data->has_fan |= (1 << 4);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&client->dev, &dev_attr_fan1_input);
|
||||
device_create_file(&client->dev, &dev_attr_fan1_min);
|
||||
device_create_file(&client->dev, &dev_attr_fan1_div);
|
||||
@ -753,6 +757,8 @@ static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit_release:
|
||||
@ -761,24 +767,17 @@ exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int w83627ehf_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, w83627ehf_detect);
|
||||
}
|
||||
|
||||
static int w83627ehf_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct w83627ehf_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
release_region(client->addr, REGION_LENGTH);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -786,12 +785,11 @@ static int w83627ehf_detach_client(struct i2c_client *client)
|
||||
static struct i2c_driver w83627ehf_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "w83627ehf",
|
||||
.flags = I2C_DF_NOTIFY,
|
||||
.attach_adapter = w83627ehf_attach_adapter,
|
||||
.attach_adapter = w83627ehf_detect,
|
||||
.detach_client = w83627ehf_detach_client,
|
||||
};
|
||||
|
||||
static int __init w83627ehf_find(int sioaddr, int *address)
|
||||
static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
@ -809,8 +807,8 @@ static int __init w83627ehf_find(int sioaddr, int *address)
|
||||
superio_select(W83627EHF_LD_HWM);
|
||||
val = (superio_inb(SIO_REG_ADDR) << 8)
|
||||
| superio_inb(SIO_REG_ADDR + 1);
|
||||
*address = val & ~(REGION_LENGTH - 1);
|
||||
if (*address == 0) {
|
||||
*addr = val & ~(REGION_LENGTH - 1);
|
||||
if (*addr == 0) {
|
||||
superio_exit();
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -826,16 +824,16 @@ static int __init w83627ehf_find(int sioaddr, int *address)
|
||||
|
||||
static int __init sensors_w83627ehf_init(void)
|
||||
{
|
||||
if (w83627ehf_find(0x2e, &normal_isa[0])
|
||||
&& w83627ehf_find(0x4e, &normal_isa[0]))
|
||||
if (w83627ehf_find(0x2e, &address)
|
||||
&& w83627ehf_find(0x4e, &address))
|
||||
return -ENODEV;
|
||||
|
||||
return i2c_add_driver(&w83627ehf_driver);
|
||||
return i2c_isa_add_driver(&w83627ehf_driver);
|
||||
}
|
||||
|
||||
static void __exit sensors_w83627ehf_exit(void)
|
||||
{
|
||||
i2c_del_driver(&w83627ehf_driver);
|
||||
i2c_isa_del_driver(&w83627ehf_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
|
||||
|
@ -42,8 +42,10 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/io.h>
|
||||
#include "lm75.h"
|
||||
|
||||
@ -56,12 +58,11 @@ module_param(force_i2c, byte, 0);
|
||||
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 int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
|
||||
/* The actual ISA address is read from Super-I/O configuration space */
|
||||
static unsigned short address;
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
|
||||
enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf };
|
||||
|
||||
static int init = 1;
|
||||
module_param(init, bool, 0);
|
||||
@ -277,6 +278,7 @@ static inline u8 DIV_TO_REG(long val)
|
||||
dynamically allocated, at the same time when a new client is allocated. */
|
||||
struct w83627hf_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
enum chips type;
|
||||
|
||||
@ -314,9 +316,7 @@ struct w83627hf_data {
|
||||
};
|
||||
|
||||
|
||||
static int w83627hf_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int w83627hf_detect(struct i2c_adapter *adapter, int address,
|
||||
int kind);
|
||||
static int w83627hf_detect(struct i2c_adapter *adapter);
|
||||
static int w83627hf_detach_client(struct i2c_client *client);
|
||||
|
||||
static int w83627hf_read_value(struct i2c_client *client, u16 register);
|
||||
@ -328,9 +328,7 @@ 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,
|
||||
.attach_adapter = w83627hf_detect,
|
||||
.detach_client = w83627hf_detach_client,
|
||||
};
|
||||
|
||||
@ -959,16 +957,7 @@ 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 sioaddr, int *address)
|
||||
static int __init w83627hf_find(int sioaddr, unsigned short *addr)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
@ -988,32 +977,24 @@ static int w83627hf_find(int sioaddr, int *address)
|
||||
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) {
|
||||
*addr = val & ~(WINB_EXTENT - 1);
|
||||
if (*addr == 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)
|
||||
static int w83627hf_detect(struct i2c_adapter *adapter)
|
||||
{
|
||||
int val;
|
||||
int val, kind;
|
||||
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);
|
||||
|
||||
@ -1102,6 +1083,12 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
|
||||
data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3));
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto ERROR3;
|
||||
}
|
||||
|
||||
device_create_file_in(new_client, 0);
|
||||
if (kind != w83697hf)
|
||||
device_create_file_in(new_client, 1);
|
||||
@ -1152,6 +1139,8 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR3:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR2:
|
||||
kfree(data);
|
||||
ERROR1:
|
||||
@ -1162,16 +1151,16 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
|
||||
|
||||
static int w83627hf_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct w83627hf_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev,
|
||||
"Client deregistration failed, client not detached.\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
release_region(client->addr, WINB_EXTENT);
|
||||
kfree(i2c_get_clientdata(client));
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1327,7 +1316,7 @@ static void w83627hf_init_client(struct i2c_client *client)
|
||||
data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
|
||||
} else {
|
||||
/* Convert VID to voltage based on default VRM */
|
||||
data->vrm = i2c_which_vrm();
|
||||
data->vrm = vid_which_vrm();
|
||||
}
|
||||
|
||||
tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
|
||||
@ -1485,20 +1474,17 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
|
||||
|
||||
static int __init sensors_w83627hf_init(void)
|
||||
{
|
||||
int addr;
|
||||
|
||||
if (w83627hf_find(0x2e, &addr)
|
||||
&& w83627hf_find(0x4e, &addr)) {
|
||||
if (w83627hf_find(0x2e, &address)
|
||||
&& w83627hf_find(0x4e, &address)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
normal_isa[0] = addr;
|
||||
|
||||
return i2c_add_driver(&w83627hf_driver);
|
||||
return i2c_isa_add_driver(&w83627hf_driver);
|
||||
}
|
||||
|
||||
static void __exit sensors_w83627hf_exit(void)
|
||||
{
|
||||
i2c_del_driver(&w83627hf_driver);
|
||||
i2c_isa_del_driver(&w83627hf_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
|
||||
|
@ -38,8 +38,10 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/io.h>
|
||||
#include "lm75.h"
|
||||
|
||||
@ -47,10 +49,10 @@
|
||||
static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
|
||||
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
|
||||
0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
|
||||
static unsigned short isa_address = 0x290;
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
|
||||
I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
|
||||
I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
|
||||
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
|
||||
|
||||
@ -218,6 +220,7 @@ DIV_TO_REG(long val, enum chips type)
|
||||
allocated. */
|
||||
struct w83781d_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore lock;
|
||||
enum chips type;
|
||||
|
||||
@ -255,6 +258,7 @@ struct w83781d_data {
|
||||
};
|
||||
|
||||
static int w83781d_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
|
||||
static int w83781d_detach_client(struct i2c_client *client);
|
||||
|
||||
@ -273,6 +277,14 @@ static struct i2c_driver w83781d_driver = {
|
||||
.detach_client = w83781d_detach_client,
|
||||
};
|
||||
|
||||
static struct i2c_driver w83781d_isa_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "w83781d-isa",
|
||||
.attach_adapter = w83781d_isa_attach_adapter,
|
||||
.detach_client = w83781d_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) \
|
||||
@ -856,7 +868,13 @@ w83781d_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, w83781d_detect);
|
||||
return i2c_probe(adapter, &addr_data, w83781d_detect);
|
||||
}
|
||||
|
||||
static int
|
||||
w83781d_isa_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return w83781d_detect(adapter, isa_address, -1);
|
||||
}
|
||||
|
||||
/* Assumes that adapter is of I2C, not ISA variety.
|
||||
@ -961,10 +979,10 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
|
||||
ERROR_SC_3:
|
||||
i2c_detach_client(data->lm75[0]);
|
||||
ERROR_SC_2:
|
||||
if (NULL != data->lm75[1])
|
||||
if (data->lm75[1])
|
||||
kfree(data->lm75[1]);
|
||||
ERROR_SC_1:
|
||||
if (NULL != data->lm75[0])
|
||||
if (data->lm75[0])
|
||||
kfree(data->lm75[0]);
|
||||
ERROR_SC_0:
|
||||
return err;
|
||||
@ -999,7 +1017,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
if (is_isa)
|
||||
if (!request_region(address, W83781D_EXTENT,
|
||||
w83781d_driver.name)) {
|
||||
w83781d_isa_driver.name)) {
|
||||
dev_dbg(&adapter->dev, "Request of region "
|
||||
"0x%x-0x%x for w83781d failed\n", address,
|
||||
address + W83781D_EXTENT - 1);
|
||||
@ -1057,7 +1075,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
new_client->addr = address;
|
||||
init_MUTEX(&data->lock);
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &w83781d_driver;
|
||||
new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
|
||||
new_client->flags = 0;
|
||||
|
||||
/* Now, we do the remaining detection. */
|
||||
@ -1189,6 +1207,12 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
data->pwmenable[i] = 1;
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto ERROR4;
|
||||
}
|
||||
|
||||
device_create_file_in(new_client, 0);
|
||||
if (kind != w83783s)
|
||||
device_create_file_in(new_client, 1);
|
||||
@ -1241,6 +1265,15 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR4:
|
||||
if (data->lm75[1]) {
|
||||
i2c_detach_client(data->lm75[1]);
|
||||
kfree(data->lm75[1]);
|
||||
}
|
||||
if (data->lm75[0]) {
|
||||
i2c_detach_client(data->lm75[0]);
|
||||
kfree(data->lm75[0]);
|
||||
}
|
||||
ERROR3:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR2:
|
||||
@ -1255,24 +1288,26 @@ ERROR0:
|
||||
static int
|
||||
w83781d_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct w83781d_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
/* main client */
|
||||
if (data)
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
if (i2c_is_isa_client(client))
|
||||
release_region(client->addr, W83781D_EXTENT);
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev,
|
||||
"Client deregistration failed, client not detached.\n");
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
if (i2c_get_clientdata(client)==NULL) {
|
||||
/* subclients */
|
||||
/* main client */
|
||||
if (data)
|
||||
kfree(data);
|
||||
|
||||
/* subclient */
|
||||
else
|
||||
kfree(client);
|
||||
} else {
|
||||
/* main client */
|
||||
kfree(i2c_get_clientdata(client));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1443,7 +1478,7 @@ w83781d_init_client(struct i2c_client *client)
|
||||
w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
|
||||
}
|
||||
|
||||
data->vrm = i2c_which_vrm();
|
||||
data->vrm = vid_which_vrm();
|
||||
|
||||
if ((type != w83781d) && (type != as99127f)) {
|
||||
tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
|
||||
@ -1613,12 +1648,25 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
|
||||
static int __init
|
||||
sensors_w83781d_init(void)
|
||||
{
|
||||
return i2c_add_driver(&w83781d_driver);
|
||||
int res;
|
||||
|
||||
res = i2c_add_driver(&w83781d_driver);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = i2c_isa_add_driver(&w83781d_isa_driver);
|
||||
if (res) {
|
||||
i2c_del_driver(&w83781d_driver);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit
|
||||
sensors_w83781d_exit(void)
|
||||
{
|
||||
i2c_isa_del_driver(&w83781d_isa_driver);
|
||||
i2c_del_driver(&w83781d_driver);
|
||||
}
|
||||
|
||||
|
1649
drivers/hwmon/w83792d.c
Normal file
1649
drivers/hwmon/w83792d.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -36,7 +36,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* How many retries on register read error */
|
||||
#define MAX_RETRIES 5
|
||||
@ -47,13 +48,12 @@
|
||||
*/
|
||||
|
||||
static unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/*
|
||||
* Insmod parameters
|
||||
*/
|
||||
|
||||
SENSORS_INSMOD_1(w83l785ts);
|
||||
I2C_CLIENT_INSMOD_1(w83l785ts);
|
||||
|
||||
/*
|
||||
* The W83L785TS-S registers
|
||||
@ -105,6 +105,7 @@ static struct i2c_driver w83l785ts_driver = {
|
||||
|
||||
struct w83l785ts_data {
|
||||
struct i2c_client client;
|
||||
struct class_device *class_dev;
|
||||
struct semaphore update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
@ -140,7 +141,7 @@ static int w83l785ts_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_detect(adapter, &addr_data, w83l785ts_detect);
|
||||
return i2c_probe(adapter, &addr_data, w83l785ts_detect);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -239,11 +240,19 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
*/
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_max);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
@ -252,15 +261,15 @@ exit:
|
||||
|
||||
static int w83l785ts_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct w83l785ts_data *data = i2c_get_clientdata(client);
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4,12 +4,8 @@
|
||||
|
||||
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/
|
||||
|
||||
i2c-sensor-objs := i2c-sensor-detect.o i2c-sensor-vid.o
|
||||
|
||||
|
||||
ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
endif
|
||||
|
@ -519,8 +519,6 @@ static u32 bit_func(struct i2c_adapter *adap)
|
||||
/* -----exported algorithm data: ------------------------------------- */
|
||||
|
||||
static struct i2c_algorithm i2c_bit_algo = {
|
||||
.name = "Bit-shift algorithm",
|
||||
.id = I2C_ALGO_BIT,
|
||||
.master_xfer = bit_xfer,
|
||||
.functionality = bit_func,
|
||||
};
|
||||
@ -541,8 +539,6 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
|
||||
DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
|
||||
adap->id |= i2c_bit_algo.id;
|
||||
adap->algo = &i2c_bit_algo;
|
||||
|
||||
adap->timeout = 100; /* default values, should */
|
||||
|
@ -713,8 +713,6 @@ static u32 iic_func(struct i2c_adapter *adap)
|
||||
/* -----exported algorithm data: ------------------------------------- */
|
||||
|
||||
static struct i2c_algorithm iic_algo = {
|
||||
.name = "ITE IIC algorithm",
|
||||
.id = I2C_ALGO_IIC,
|
||||
.master_xfer = iic_xfer,
|
||||
.algo_control = algo_control, /* ioctl */
|
||||
.functionality = iic_func,
|
||||
@ -738,8 +736,6 @@ int i2c_iic_add_bus(struct i2c_adapter *adap)
|
||||
adap->name));
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
|
||||
adap->id |= iic_algo.id;
|
||||
adap->algo = &iic_algo;
|
||||
|
||||
adap->timeout = 100; /* default values, should */
|
||||
|
@ -187,12 +187,14 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
|
||||
int numbytes = 0;
|
||||
int state;
|
||||
int ret;
|
||||
int timeout = 100;
|
||||
|
||||
state = pca_status(adap);
|
||||
if ( state != 0xF8 ) {
|
||||
dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state );
|
||||
/* FIXME: what to do. Force stop ? */
|
||||
return -EREMOTEIO;
|
||||
while ((state = pca_status(adap)) != 0xf8 && timeout--) {
|
||||
msleep(10);
|
||||
}
|
||||
if (state != 0xf8) {
|
||||
dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
DEB1("{{{ XFER %d messages\n", num);
|
||||
@ -354,8 +356,6 @@ static int pca_init(struct i2c_algo_pca_data *adap)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm pca_algo = {
|
||||
.name = "PCA9564 algorithm",
|
||||
.id = I2C_ALGO_PCA,
|
||||
.master_xfer = pca_xfer,
|
||||
.functionality = pca_func,
|
||||
};
|
||||
@ -369,8 +369,6 @@ int i2c_pca_add_bus(struct i2c_adapter *adap)
|
||||
int rval;
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
|
||||
adap->id |= pca_algo.id;
|
||||
adap->algo = &pca_algo;
|
||||
|
||||
adap->timeout = 100; /* default values, should */
|
||||
|
@ -459,8 +459,6 @@ static u32 pcf_func(struct i2c_adapter *adap)
|
||||
/* -----exported algorithm data: ------------------------------------- */
|
||||
|
||||
static struct i2c_algorithm pcf_algo = {
|
||||
.name = "PCF8584 algorithm",
|
||||
.id = I2C_ALGO_PCF,
|
||||
.master_xfer = pcf_xfer,
|
||||
.functionality = pcf_func,
|
||||
};
|
||||
@ -476,8 +474,6 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
|
||||
DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
|
||||
adap->id |= pcf_algo.id;
|
||||
adap->algo = &pcf_algo;
|
||||
|
||||
adap->timeout = 100; /* default values, should */
|
||||
|
@ -149,7 +149,7 @@ static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
|
||||
err = i2c_write(adap, p->buf, p->len);
|
||||
}
|
||||
|
||||
return err;
|
||||
return (err < 0) ? err : i;
|
||||
}
|
||||
|
||||
static u32 sgi_func(struct i2c_adapter *adap)
|
||||
@ -158,8 +158,6 @@ static u32 sgi_func(struct i2c_adapter *adap)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm sgi_algo = {
|
||||
.name = "SGI algorithm",
|
||||
.id = I2C_ALGO_SGI,
|
||||
.master_xfer = sgi_xfer,
|
||||
.functionality = sgi_func,
|
||||
};
|
||||
@ -169,7 +167,6 @@ static struct i2c_algorithm sgi_algo = {
|
||||
*/
|
||||
int i2c_sgi_add_bus(struct i2c_adapter *adap)
|
||||
{
|
||||
adap->id |= sgi_algo.id;
|
||||
adap->algo = &sgi_algo;
|
||||
|
||||
return i2c_add_adapter(adap);
|
||||
|
@ -135,8 +135,6 @@ static u32 bit_func(struct i2c_adapter *adap)
|
||||
/* -----exported algorithm data: ------------------------------------- */
|
||||
|
||||
static struct i2c_algorithm i2c_sibyte_algo = {
|
||||
.name = "SiByte algorithm",
|
||||
.id = I2C_ALGO_SIBYTE,
|
||||
.smbus_xfer = smbus_xfer,
|
||||
.algo_control = algo_control, /* ioctl */
|
||||
.functionality = bit_func,
|
||||
@ -151,8 +149,6 @@ int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
|
||||
struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
|
||||
i2c_adap->id |= i2c_sibyte_algo.id;
|
||||
i2c_adap->algo = &i2c_sibyte_algo;
|
||||
|
||||
/* Set the frequency to 100 kHz */
|
||||
|
@ -182,14 +182,8 @@ config I2C_IOP3XX
|
||||
will be called i2c-iop3xx.
|
||||
|
||||
config I2C_ISA
|
||||
tristate "ISA Bus support"
|
||||
tristate
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes to this option, support will be included for i2c
|
||||
interfaces that are on the ISA bus.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called i2c-isa.
|
||||
|
||||
config I2C_ITE
|
||||
tristate "ITE I2C Adapter"
|
||||
|
@ -472,8 +472,6 @@ static u32 ali1535_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-i2c SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = ali1535_access,
|
||||
.functionality = ali1535_func,
|
||||
};
|
||||
|
@ -366,8 +366,6 @@ static void ali1563_shutdown(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm ali1563_algorithm = {
|
||||
.name = "Non-i2c SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = ali1563_access,
|
||||
.functionality = ali1563_func,
|
||||
};
|
||||
|
@ -462,8 +462,6 @@ static u32 ali15x3_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = ali15x3_access,
|
||||
.functionality = ali15x3_func,
|
||||
};
|
||||
|
@ -295,8 +295,6 @@ static u32 amd756_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = amd756_access,
|
||||
.functionality = amd756_func,
|
||||
};
|
||||
|
@ -323,8 +323,6 @@ static u32 amd8111_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus 2.0 adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = amd8111_access,
|
||||
.functionality = amd8111_func,
|
||||
};
|
||||
|
@ -283,8 +283,6 @@ au1550_func(struct i2c_adapter *adap)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm au1550_algo = {
|
||||
.name = "Au1550 algorithm",
|
||||
.id = I2C_ALGO_AU1550,
|
||||
.master_xfer = au1550_xfer,
|
||||
.functionality = au1550_func,
|
||||
};
|
||||
|
@ -535,8 +535,6 @@ static u32 i801_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = i801_access,
|
||||
.functionality = i801_func,
|
||||
};
|
||||
|
@ -627,8 +627,6 @@ static u32 iic_func(struct i2c_adapter *adap)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm iic_algo = {
|
||||
.name = "IBM IIC algorithm",
|
||||
.id = I2C_ALGO_OCP,
|
||||
.master_xfer = iic_xfer,
|
||||
.functionality = iic_func
|
||||
};
|
||||
@ -727,7 +725,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
|
||||
adap = &dev->adap;
|
||||
strcpy(adap->name, "IBM IIC");
|
||||
i2c_set_adapdata(adap, dev);
|
||||
adap->id = I2C_HW_OCP | iic_algo.id;
|
||||
adap->id = I2C_HW_OCP;
|
||||
adap->algo = &iic_algo;
|
||||
adap->client_register = NULL;
|
||||
adap->client_unregister = NULL;
|
||||
|
@ -399,8 +399,6 @@ iop3xx_i2c_func(struct i2c_adapter *adap)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm iop3xx_i2c_algo = {
|
||||
.name = "IOP3xx I2C algorithm",
|
||||
.id = I2C_ALGO_IOP3XX,
|
||||
.master_xfer = iop3xx_i2c_master_xfer,
|
||||
.algo_control = iop3xx_i2c_algo_control,
|
||||
.functionality = iop3xx_i2c_func,
|
||||
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
i2c-isa.c - Part of lm_sensors, Linux kernel modules for hardware
|
||||
monitoring
|
||||
i2c-isa.c - an i2c-core-like thing for ISA hardware monitoring chips
|
||||
Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
Based on the i2c-isa pseudo-adapter from the lm_sensors project
|
||||
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -18,30 +20,36 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* This implements an i2c algorithm/adapter for ISA bus. Not that this is
|
||||
on first sight very useful; almost no functionality is preserved.
|
||||
Except that it makes writing drivers for chips which can be on both
|
||||
the SMBus and the ISA bus very much easier. See lm78.c for an example
|
||||
of this. */
|
||||
/* This implements an i2c-core-like thing for ISA hardware monitoring
|
||||
chips. Such chips are linked to the i2c subsystem for historical
|
||||
reasons (because the early ISA hardware monitoring chips such as the
|
||||
LM78 had both an I2C and an ISA interface). They used to be
|
||||
registered with the main i2c-core, but as a first step in the
|
||||
direction of a clean separation between I2C and ISA chip drivers,
|
||||
we now have this separate core for ISA ones. It is significantly
|
||||
more simple than the real one, of course, because we don't have to
|
||||
handle multiple busses: there is only one (fake) ISA adapter.
|
||||
It is worth noting that we still rely on i2c-core for some things
|
||||
at the moment - but hopefully this won't last. */
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
|
||||
static u32 isa_func(struct i2c_adapter *adapter);
|
||||
|
||||
/* This is the actual algorithm we define */
|
||||
static struct i2c_algorithm isa_algorithm = {
|
||||
.name = "ISA bus algorithm",
|
||||
.id = I2C_ALGO_ISA,
|
||||
.functionality = isa_func,
|
||||
};
|
||||
|
||||
/* There can only be one... */
|
||||
static struct i2c_adapter isa_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_ISA,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &isa_algorithm,
|
||||
.name = "ISA main adapter",
|
||||
@ -53,17 +61,146 @@ static u32 isa_func(struct i2c_adapter *adapter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Copied from i2c-core */
|
||||
static ssize_t show_adapter_name(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
|
||||
return sprintf(buf, "%s\n", adap->name);
|
||||
}
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
|
||||
|
||||
static int i2c_isa_device_probe(struct device *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int i2c_isa_device_remove(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* We implement an interface which resembles i2c_{add,del}_driver,
|
||||
but for i2c-isa drivers. We don't have to remember and handle lists
|
||||
of drivers and adapters so this is much more simple, of course. */
|
||||
|
||||
int i2c_isa_add_driver(struct i2c_driver *driver)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Add the driver to the list of i2c drivers in the driver core */
|
||||
driver->driver.name = driver->name;
|
||||
driver->driver.bus = &i2c_bus_type;
|
||||
driver->driver.probe = i2c_isa_device_probe;
|
||||
driver->driver.remove = i2c_isa_device_remove;
|
||||
res = driver_register(&driver->driver);
|
||||
if (res)
|
||||
return res;
|
||||
dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->name);
|
||||
|
||||
/* Now look for clients */
|
||||
driver->attach_adapter(&isa_adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_isa_del_driver(struct i2c_driver *driver)
|
||||
{
|
||||
struct list_head *item, *_n;
|
||||
struct i2c_client *client;
|
||||
int res;
|
||||
|
||||
/* Detach all clients belonging to this one driver */
|
||||
list_for_each_safe(item, _n, &isa_adapter.clients) {
|
||||
client = list_entry(item, struct i2c_client, list);
|
||||
if (client->driver != driver)
|
||||
continue;
|
||||
dev_dbg(&isa_adapter.dev, "Detaching client %s at 0x%x\n",
|
||||
client->name, client->addr);
|
||||
if ((res = driver->detach_client(client))) {
|
||||
dev_err(&isa_adapter.dev, "Failed, driver "
|
||||
"%s not unregistered!\n",
|
||||
driver->name);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the driver off the core list */
|
||||
driver_unregister(&driver->driver);
|
||||
dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int __init i2c_isa_init(void)
|
||||
{
|
||||
return i2c_add_adapter(&isa_adapter);
|
||||
init_MUTEX(&isa_adapter.clist_lock);
|
||||
INIT_LIST_HEAD(&isa_adapter.clients);
|
||||
|
||||
isa_adapter.nr = ANY_I2C_ISA_BUS;
|
||||
isa_adapter.dev.parent = &platform_bus;
|
||||
sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
|
||||
isa_adapter.dev.driver = &i2c_adapter_driver;
|
||||
isa_adapter.dev.release = &i2c_adapter_dev_release;
|
||||
device_register(&isa_adapter.dev);
|
||||
device_create_file(&isa_adapter.dev, &dev_attr_name);
|
||||
|
||||
/* Add this adapter to the i2c_adapter class */
|
||||
memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
|
||||
isa_adapter.class_dev.dev = &isa_adapter.dev;
|
||||
isa_adapter.class_dev.class = &i2c_adapter_class;
|
||||
strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
|
||||
BUS_ID_SIZE);
|
||||
class_device_register(&isa_adapter.class_dev);
|
||||
|
||||
dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit i2c_isa_exit(void)
|
||||
{
|
||||
i2c_del_adapter(&isa_adapter);
|
||||
#ifdef DEBUG
|
||||
struct list_head *item, *_n;
|
||||
struct i2c_client *client = NULL;
|
||||
#endif
|
||||
|
||||
/* There should be no more active client */
|
||||
#ifdef DEBUG
|
||||
dev_dbg(&isa_adapter.dev, "Looking for clients\n");
|
||||
list_for_each_safe(item, _n, &isa_adapter.clients) {
|
||||
client = list_entry(item, struct i2c_client, list);
|
||||
dev_err(&isa_adapter.dev, "Driver %s still has an active "
|
||||
"ISA client at 0x%x\n", client->driver->name,
|
||||
client->addr);
|
||||
}
|
||||
if (client != NULL)
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Clean up the sysfs representation */
|
||||
dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
|
||||
init_completion(&isa_adapter.dev_released);
|
||||
init_completion(&isa_adapter.class_dev_released);
|
||||
class_device_unregister(&isa_adapter.class_dev);
|
||||
device_remove_file(&isa_adapter.dev, &dev_attr_name);
|
||||
device_unregister(&isa_adapter.dev);
|
||||
|
||||
/* Wait for sysfs to drop all references */
|
||||
dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
|
||||
wait_for_completion(&isa_adapter.dev_released);
|
||||
wait_for_completion(&isa_adapter.class_dev_released);
|
||||
|
||||
dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
|
||||
EXPORT_SYMBOL(i2c_isa_add_driver);
|
||||
EXPORT_SYMBOL(i2c_isa_del_driver);
|
||||
|
||||
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
|
||||
MODULE_DESCRIPTION("ISA bus access through i2c");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
@ -87,12 +87,9 @@ static const char *__kw_state_names[] = {
|
||||
};
|
||||
#endif /* DEBUG */
|
||||
|
||||
static int probe;
|
||||
|
||||
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
|
||||
MODULE_DESCRIPTION("I2C driver for Apple's Keywest");
|
||||
MODULE_LICENSE("GPL");
|
||||
module_param(probe, bool, 0);
|
||||
|
||||
#ifdef POLLED_MODE
|
||||
/* Don't schedule, the g5 fan controller is too
|
||||
@ -498,8 +495,6 @@ keywest_func(struct i2c_adapter * adapter)
|
||||
|
||||
/* For now, we only handle combined mode (smbus) */
|
||||
static struct i2c_algorithm keywest_algorithm = {
|
||||
.name = "Keywest i2c",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = keywest_smbus_xfer,
|
||||
.master_xfer = keywest_xfer,
|
||||
.functionality = keywest_func,
|
||||
@ -621,7 +616,6 @@ create_iface(struct device_node *np, struct device *dev)
|
||||
sprintf(chan->adapter.name, "%s %d", np->parent->name, i);
|
||||
chan->iface = iface;
|
||||
chan->chan_no = i;
|
||||
chan->adapter.id = I2C_ALGO_SMBUS;
|
||||
chan->adapter.algo = &keywest_algorithm;
|
||||
chan->adapter.algo_data = NULL;
|
||||
chan->adapter.client_register = NULL;
|
||||
@ -635,15 +629,6 @@ create_iface(struct device_node *np, struct device *dev)
|
||||
chan->adapter.name);
|
||||
i2c_set_adapdata(&chan->adapter, NULL);
|
||||
}
|
||||
if (probe) {
|
||||
printk("Probe: ");
|
||||
for (addr = 0x00; addr <= 0x7f; addr++) {
|
||||
if (i2c_smbus_xfer(&chan->adapter,addr,
|
||||
0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
|
||||
printk("%02x ", addr);
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n",
|
||||
|
@ -272,8 +272,6 @@ static u32 mpc_functionality(struct i2c_adapter *adap)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm mpc_algo = {
|
||||
.name = "MPC algorithm",
|
||||
.id = I2C_ALGO_MPC107,
|
||||
.master_xfer = mpc_xfer,
|
||||
.functionality = mpc_functionality,
|
||||
};
|
||||
@ -281,7 +279,7 @@ static struct i2c_algorithm mpc_algo = {
|
||||
static struct i2c_adapter mpc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "MPC adapter",
|
||||
.id = I2C_ALGO_MPC107 | I2C_HW_MPC107,
|
||||
.id = I2C_HW_MPC107,
|
||||
.algo = &mpc_algo,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.timeout = 1,
|
||||
|
@ -423,18 +423,16 @@ static int
|
||||
mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
{
|
||||
struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
|
||||
int i, rc = 0;
|
||||
int i, rc;
|
||||
|
||||
for (i=0; i<num; i++)
|
||||
if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) != 0)
|
||||
break;
|
||||
if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) < 0)
|
||||
return rc;
|
||||
|
||||
return rc;
|
||||
return num;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm mv64xxx_i2c_algo = {
|
||||
.name = MV64XXX_I2C_CTLR_NAME " algorithm",
|
||||
.id = I2C_ALGO_MV64XXX,
|
||||
.master_xfer = mv64xxx_i2c_xfer,
|
||||
.functionality = mv64xxx_i2c_functionality,
|
||||
};
|
||||
@ -523,7 +521,7 @@ mv64xxx_i2c_probe(struct device *dev)
|
||||
drv_data->freq_m = pdata->freq_m;
|
||||
drv_data->freq_n = pdata->freq_n;
|
||||
drv_data->irq = platform_get_irq(pd, 0);
|
||||
drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX;
|
||||
drv_data->adapter.id = I2C_HW_MV64XXX;
|
||||
drv_data->adapter.algo = &mv64xxx_i2c_algo;
|
||||
drv_data->adapter.owner = THIS_MODULE;
|
||||
drv_data->adapter.class = I2C_CLASS_HWMON;
|
||||
|
@ -110,8 +110,6 @@ static u32 nforce2_func(struct i2c_adapter *adapter);
|
||||
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = nforce2_access,
|
||||
.functionality = nforce2_func,
|
||||
};
|
||||
@ -131,7 +129,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
|
||||
struct nforce2_smbus *smbus = adap->algo_data;
|
||||
unsigned char protocol, pec, temp;
|
||||
unsigned char len = 0; /* to keep the compiler quiet */
|
||||
int timeout = 0;
|
||||
int i;
|
||||
|
||||
protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
|
||||
@ -191,29 +188,10 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
/*
|
||||
outb_p(command, NVIDIA_SMB_CMD);
|
||||
outb_p(data->word, NVIDIA_SMB_DATA);
|
||||
outb_p(data->word >> 8, NVIDIA_SMB_DATA + 1);
|
||||
protocol = NVIDIA_SMB_PRTCL_PROC_CALL | pec;
|
||||
read_write = I2C_SMBUS_READ;
|
||||
break;
|
||||
*/
|
||||
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL:
|
||||
dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
/*
|
||||
protocol |= pec;
|
||||
len = min_t(u8, data->block[0], 31);
|
||||
outb_p(command, NVIDIA_SMB_CMD);
|
||||
outb_p(len, NVIDIA_SMB_BCNT);
|
||||
for (i = 0; i < len; i++)
|
||||
outb_p(data->block[i + 1], NVIDIA_SMB_DATA + i);
|
||||
protocol = NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL | pec;
|
||||
read_write = I2C_SMBUS_READ;
|
||||
break;
|
||||
*/
|
||||
|
||||
case I2C_SMBUS_WORD_DATA_PEC:
|
||||
case I2C_SMBUS_BLOCK_DATA_PEC:
|
||||
@ -232,12 +210,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
|
||||
|
||||
temp = inb_p(NVIDIA_SMB_STS);
|
||||
|
||||
#if 0
|
||||
do {
|
||||
i2c_do_pause(1);
|
||||
temp = inb_p(NVIDIA_SMB_STS);
|
||||
} while (((temp & NVIDIA_SMB_STS_DONE) == 0) && (timeout++ < MAX_TIMEOUT));
|
||||
#endif
|
||||
if (~temp & NVIDIA_SMB_STS_DONE) {
|
||||
udelay(500);
|
||||
temp = inb_p(NVIDIA_SMB_STS);
|
||||
@ -247,9 +219,10 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
|
||||
temp = inb_p(NVIDIA_SMB_STS);
|
||||
}
|
||||
|
||||
if ((timeout >= MAX_TIMEOUT) || (~temp & NVIDIA_SMB_STS_DONE)
|
||||
|| (temp & NVIDIA_SMB_STS_STATUS))
|
||||
if ((~temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {
|
||||
dev_dbg(&adap->dev, "SMBus Timeout! (0x%02x)\n", temp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
return 0;
|
||||
|
@ -399,8 +399,6 @@ static u32 piix4_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = piix4_access,
|
||||
.functionality = piix4_func,
|
||||
};
|
||||
|
@ -568,7 +568,6 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
|
||||
/* i2c bus registration info */
|
||||
|
||||
static struct i2c_algorithm s3c24xx_i2c_algorithm = {
|
||||
.name = "S3C2410-I2C-Algorithm",
|
||||
.master_xfer = s3c24xx_i2c_xfer,
|
||||
.functionality = s3c24xx_i2c_func,
|
||||
};
|
||||
|
@ -357,8 +357,6 @@ static u32 sis5595_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = sis5595_access,
|
||||
.functionality = sis5595_func,
|
||||
};
|
||||
|
@ -448,8 +448,6 @@ exit:
|
||||
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = sis630_access,
|
||||
.functionality = sis630_func,
|
||||
};
|
||||
|
@ -249,8 +249,6 @@ static u32 sis96x_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = sis96x_access,
|
||||
.functionality = sis96x_func,
|
||||
};
|
||||
|
@ -109,8 +109,6 @@ static u32 stub_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.functionality = stub_func,
|
||||
.smbus_xfer = stub_xfer,
|
||||
};
|
||||
|
@ -286,8 +286,6 @@ static u32 vt596_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
.name = "Non-I2C SMBus adapter",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = vt596_access,
|
||||
.functionality = vt596_func,
|
||||
};
|
||||
|
@ -395,8 +395,6 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter)
|
||||
|
||||
/* For now, we only handle combined mode (smbus) */
|
||||
static struct i2c_algorithm scx200_acb_algorithm = {
|
||||
.name = "NatSemi SCx200 ACCESS.bus",
|
||||
.id = I2C_ALGO_SMBUS,
|
||||
.smbus_xfer = scx200_acb_smbus_xfer,
|
||||
.functionality = scx200_acb_func,
|
||||
};
|
||||
@ -456,7 +454,7 @@ static int __init scx200_acb_create(int base, int index)
|
||||
i2c_set_adapdata(adapter, iface);
|
||||
snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index);
|
||||
adapter->owner = THIS_MODULE;
|
||||
adapter->id = I2C_ALGO_SMBUS;
|
||||
adapter->id = I2C_HW_SMBUS_SCX200;
|
||||
adapter->algo = &scx200_acb_algorithm;
|
||||
adapter->class = I2C_CLASS_HWMON;
|
||||
|
||||
|
@ -2,17 +2,12 @@
|
||||
# Miscellaneous I2C chip drivers configuration
|
||||
#
|
||||
|
||||
config I2C_SENSOR
|
||||
tristate
|
||||
default n
|
||||
|
||||
menu "Miscellaneous I2C Chip support"
|
||||
depends on I2C
|
||||
|
||||
config SENSORS_DS1337
|
||||
tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for Dallas Semiconductor
|
||||
DS1337 and DS1339 real-time clock chips.
|
||||
@ -23,7 +18,6 @@ config SENSORS_DS1337
|
||||
config SENSORS_DS1374
|
||||
tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for Dallas Semiconductor
|
||||
DS1374 real-time clock chips.
|
||||
@ -34,7 +28,6 @@ config SENSORS_DS1374
|
||||
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
|
||||
@ -46,7 +39,6 @@ config SENSORS_EEPROM
|
||||
config SENSORS_PCF8574
|
||||
tristate "Philips PCF8574 and PCF8574A"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for Philips PCF8574 and
|
||||
PCF8574A chips.
|
||||
@ -67,7 +59,6 @@ config SENSORS_PCA9539
|
||||
config SENSORS_PCF8591
|
||||
tristate "Philips PCF8591"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for Philips PCF8591 chips.
|
||||
|
||||
@ -77,7 +68,6 @@ config SENSORS_PCF8591
|
||||
config SENSORS_RTC8564
|
||||
tristate "Epson 8564 RTC chip"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
select I2C_SENSOR
|
||||
help
|
||||
If you say yes here you get support for the Epson 8564 RTC chip.
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/rtc.h> /* get the user-level API */
|
||||
#include <linux/bcd.h>
|
||||
@ -39,9 +38,8 @@
|
||||
* Functions declaration
|
||||
*/
|
||||
static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
SENSORS_INSMOD_1(ds1337);
|
||||
I2C_CLIENT_INSMOD_1(ds1337);
|
||||
|
||||
static int ds1337_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind);
|
||||
@ -227,7 +225,7 @@ int ds1337_do_command(int bus, int cmd, void *arg)
|
||||
|
||||
static int ds1337_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_detect(adapter, &addr_data, ds1337_detect);
|
||||
return i2c_probe(adapter, &addr_data, ds1337_detect);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -354,11 +352,8 @@ static int ds1337_detach_client(struct i2c_client *client)
|
||||
int err;
|
||||
struct ds1337_data *data = i2c_get_clientdata(client);
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed, "
|
||||
"client not detached.\n");
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
list_del(&data->list);
|
||||
kfree(data);
|
||||
|
@ -53,7 +53,6 @@ static struct i2c_client_address_data addr_data = {
|
||||
.normal_i2c = normal_addr,
|
||||
.probe = ignore,
|
||||
.ignore = ignore,
|
||||
.force = ignore,
|
||||
};
|
||||
|
||||
static ulong ds1374_read_rtc(void)
|
||||
@ -166,7 +165,7 @@ static void ds1374_set_tlet(ulong arg)
|
||||
"can't confirm time set from rtc chip\n");
|
||||
}
|
||||
|
||||
ulong new_time;
|
||||
static ulong new_time;
|
||||
|
||||
DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet, (ulong) & new_time);
|
||||
|
||||
|
@ -33,15 +33,13 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
|
||||
0x55, 0x56, 0x57, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(eeprom);
|
||||
I2C_CLIENT_INSMOD_1(eeprom);
|
||||
|
||||
|
||||
/* Size of EEPROM in bytes */
|
||||
@ -153,21 +151,16 @@ static struct bin_attribute eeprom_attr = {
|
||||
|
||||
static int eeprom_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_detect(adapter, &addr_data, eeprom_detect);
|
||||
return i2c_probe(adapter, &addr_data, eeprom_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
/* This function is called by i2c_probe */
|
||||
int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
struct eeprom_data *data;
|
||||
int err = 0;
|
||||
|
||||
/* prevent 24RF08 corruption */
|
||||
if (kind < 0)
|
||||
i2c_smbus_xfer(adapter, address, 0, 0, 0,
|
||||
I2C_SMBUS_QUICK, NULL);
|
||||
|
||||
/* There are three ways we can read the EEPROM data:
|
||||
(1) I2C block reads (faster, but unsupported by most adapters)
|
||||
(2) Consecutive byte reads (100% overhead)
|
||||
@ -231,10 +224,8 @@ static int eeprom_detach_client(struct i2c_client *client)
|
||||
int err;
|
||||
|
||||
err = i2c_detach_client(client);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
|
||||
|
@ -42,7 +42,6 @@ static struct i2c_client_address_data addr_data = {
|
||||
.normal_i2c = normal_addr,
|
||||
.probe = ignore,
|
||||
.ignore = ignore,
|
||||
.force = ignore,
|
||||
};
|
||||
|
||||
ulong
|
||||
@ -145,7 +144,7 @@ m41t00_set_tlet(ulong arg)
|
||||
return;
|
||||
}
|
||||
|
||||
ulong new_time;
|
||||
static ulong new_time;
|
||||
|
||||
DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
|
||||
|
||||
|
@ -5,97 +5,60 @@
|
||||
|
||||
Based on i2c/chips/eeprom.c
|
||||
|
||||
The MAX6875 has two EEPROM sections: config and user.
|
||||
At reset, the config EEPROM is read into the registers.
|
||||
The MAX6875 has a bank of registers and two banks of EEPROM.
|
||||
Address ranges are defined as follows:
|
||||
* 0x0000 - 0x0046 = configuration registers
|
||||
* 0x8000 - 0x8046 = configuration EEPROM
|
||||
* 0x8100 - 0x82FF = user EEPROM
|
||||
|
||||
This driver make 3 binary files available in sysfs:
|
||||
reg_config - direct access to the registers
|
||||
eeprom_config - acesses configuration eeprom space
|
||||
eeprom_user - free for application use
|
||||
This driver makes the user EEPROM available for read.
|
||||
|
||||
In our application, we put device serial & model numbers in user eeprom.
|
||||
The registers & config EEPROM should be accessed via i2c-dev.
|
||||
|
||||
Notes:
|
||||
1) The datasheet says that register 0x44 / EEPROM 0x8044 should NOT
|
||||
be overwritten, so the driver explicitly prevents that.
|
||||
2) It's a good idea to keep the config (0x45) locked in config EEPROM.
|
||||
You can temporarily enable config writes by changing register 0x45.
|
||||
The MAX6875 ignores the lowest address bit, so each chip responds to
|
||||
two addresses - 0x50/0x51 and 0x52/0x53.
|
||||
|
||||
Note that the MAX6875 uses i2c_smbus_write_byte_data() to set the read
|
||||
address, so this driver is destructive if loaded for the wrong EEPROM chip.
|
||||
|
||||
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; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <asm/semaphore.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
/* No address scanned by default, as this could corrupt standard EEPROMS. */
|
||||
/* Do not scan - the MAX6875 access method will write to some EEPROM chips */
|
||||
static unsigned short normal_i2c[] = {I2C_CLIENT_END};
|
||||
static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(max6875);
|
||||
|
||||
/* this param will prevent 'accidental' writes to the eeprom */
|
||||
static int allow_write = 0;
|
||||
module_param(allow_write, int, 0);
|
||||
MODULE_PARM_DESC(allow_write,
|
||||
"Enable write access:\n"
|
||||
"*0: Read only\n"
|
||||
" 1: Read/Write access");
|
||||
I2C_CLIENT_INSMOD_1(max6875);
|
||||
|
||||
/* The MAX6875 can only read/write 16 bytes at a time */
|
||||
#define SLICE_SIZE 16
|
||||
#define SLICE_BITS 4
|
||||
|
||||
/* CONFIG EEPROM is at addresses 0x8000 - 0x8045, registers are at 0 - 0x45 */
|
||||
#define CONFIG_EEPROM_BASE 0x8000
|
||||
#define CONFIG_EEPROM_SIZE 0x0046
|
||||
#define CONFIG_EEPROM_SLICES 5
|
||||
|
||||
/* USER EEPROM is at addresses 0x8100 - 0x82FF */
|
||||
#define USER_EEPROM_BASE 0x8100
|
||||
#define USER_EEPROM_SIZE 0x0200
|
||||
#define USER_EEPROM_SLICES 32
|
||||
|
||||
/* MAX6875 commands */
|
||||
#define MAX6875_CMD_BLOCK_WRITE 0x83
|
||||
#define MAX6875_CMD_BLOCK_READ 0x84
|
||||
#define MAX6875_CMD_REBOOT 0x88
|
||||
|
||||
enum max6875_area_type {
|
||||
max6875_register_config=0,
|
||||
max6875_eeprom_config,
|
||||
max6875_eeprom_user,
|
||||
max6857_max
|
||||
};
|
||||
|
||||
struct eeprom_block {
|
||||
enum max6875_area_type type;
|
||||
u8 slices;
|
||||
u32 size;
|
||||
u32 valid;
|
||||
u32 base;
|
||||
unsigned long *updated;
|
||||
u8 *data;
|
||||
};
|
||||
#define MAX6875_CMD_BLK_READ 0x84
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct max6875_data {
|
||||
struct i2c_client client;
|
||||
struct semaphore update_lock;
|
||||
struct eeprom_block blocks[max6857_max];
|
||||
/* the above structs point into the arrays below */
|
||||
u8 data[USER_EEPROM_SIZE + (CONFIG_EEPROM_SIZE*2)];
|
||||
unsigned long last_updated[USER_EEPROM_SLICES + (CONFIG_EEPROM_SLICES*2)];
|
||||
|
||||
u32 valid;
|
||||
u8 data[USER_EEPROM_SIZE];
|
||||
unsigned long last_updated[USER_EEPROM_SLICES];
|
||||
};
|
||||
|
||||
static int max6875_attach_adapter(struct i2c_adapter *adapter);
|
||||
@ -111,337 +74,160 @@ static struct i2c_driver max6875_driver = {
|
||||
.detach_client = max6875_detach_client,
|
||||
};
|
||||
|
||||
static int max6875_update_slice(struct i2c_client *client,
|
||||
struct eeprom_block *blk,
|
||||
int slice)
|
||||
static void max6875_update_slice(struct i2c_client *client, int slice)
|
||||
{
|
||||
struct max6875_data *data = i2c_get_clientdata(client);
|
||||
int i, j, addr, count;
|
||||
u8 rdbuf[SLICE_SIZE];
|
||||
int retval = 0;
|
||||
int i, j, addr;
|
||||
u8 *buf;
|
||||
|
||||
if (slice >= blk->slices)
|
||||
return -1;
|
||||
if (slice >= USER_EEPROM_SLICES)
|
||||
return;
|
||||
|
||||
down(&data->update_lock);
|
||||
|
||||
if (!(blk->valid & (1 << slice)) ||
|
||||
(jiffies - blk->updated[slice] > 300 * HZ) ||
|
||||
(jiffies < blk->updated[slice])) {
|
||||
dev_dbg(&client->dev, "Starting eeprom update, slice %u, base %u\n",
|
||||
slice, blk->base);
|
||||
buf = &data->data[slice << SLICE_BITS];
|
||||
|
||||
addr = blk->base + (slice << SLICE_BITS);
|
||||
count = blk->size - (slice << SLICE_BITS);
|
||||
if (count > SLICE_SIZE) {
|
||||
count = SLICE_SIZE;
|
||||
if (!(data->valid & (1 << slice)) ||
|
||||
time_after(jiffies, data->last_updated[slice])) {
|
||||
|
||||
dev_dbg(&client->dev, "Starting update of slice %u\n", slice);
|
||||
|
||||
data->valid &= ~(1 << slice);
|
||||
|
||||
addr = USER_EEPROM_BASE + (slice << SLICE_BITS);
|
||||
|
||||
/* select the eeprom address */
|
||||
if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
|
||||
dev_err(&client->dev, "address set failed\n");
|
||||
goto exit_up;
|
||||
}
|
||||
|
||||
/* Preset the read address */
|
||||
if (addr < 0x100) {
|
||||
/* select the register */
|
||||
if (i2c_smbus_write_byte(client, addr & 0xFF)) {
|
||||
dev_dbg(&client->dev, "max6875 register select has failed!\n");
|
||||
retval = -1;
|
||||
goto exit;
|
||||
if (i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
|
||||
if (i2c_smbus_read_i2c_block_data(client,
|
||||
MAX6875_CMD_BLK_READ,
|
||||
buf) != SLICE_SIZE) {
|
||||
goto exit_up;
|
||||
}
|
||||
} else {
|
||||
/* select the eeprom */
|
||||
if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
|
||||
dev_dbg(&client->dev, "max6875 address set has failed!\n");
|
||||
retval = -1;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
|
||||
if (i2c_smbus_read_i2c_block_data(client, MAX6875_CMD_BLOCK_READ,
|
||||
rdbuf) != SLICE_SIZE)
|
||||
{
|
||||
retval = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(&blk->data[slice << SLICE_BITS], rdbuf, count);
|
||||
} else {
|
||||
for (i = 0; i < count; i++) {
|
||||
for (i = 0; i < SLICE_SIZE; i++) {
|
||||
j = i2c_smbus_read_byte(client);
|
||||
if (j < 0)
|
||||
{
|
||||
retval = -1;
|
||||
goto exit;
|
||||
if (j < 0) {
|
||||
goto exit_up;
|
||||
}
|
||||
blk->data[(slice << SLICE_BITS) + i] = (u8) j;
|
||||
buf[i] = j;
|
||||
}
|
||||
}
|
||||
blk->updated[slice] = jiffies;
|
||||
blk->valid |= (1 << slice);
|
||||
data->last_updated[slice] = jiffies;
|
||||
data->valid |= (1 << slice);
|
||||
}
|
||||
exit:
|
||||
exit_up:
|
||||
up(&data->update_lock);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, size_t count,
|
||||
enum max6875_area_type area_type)
|
||||
static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
|
||||
size_t count)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
|
||||
struct i2c_client *client = kobj_to_i2c_client(kobj);
|
||||
struct max6875_data *data = i2c_get_clientdata(client);
|
||||
struct eeprom_block *blk;
|
||||
int slice;
|
||||
int slice, max_slice;
|
||||
|
||||
blk = &data->blocks[area_type];
|
||||
|
||||
if (off > blk->size)
|
||||
if (off > USER_EEPROM_SIZE)
|
||||
return 0;
|
||||
if (off + count > blk->size)
|
||||
count = blk->size - off;
|
||||
|
||||
/* Only refresh slices which contain requested bytes */
|
||||
for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
|
||||
max6875_update_slice(client, blk, slice);
|
||||
if (off + count > USER_EEPROM_SIZE)
|
||||
count = USER_EEPROM_SIZE - off;
|
||||
|
||||
memcpy(buf, &blk->data[off], count);
|
||||
/* refresh slices which contain requested bytes */
|
||||
max_slice = (off + count - 1) >> SLICE_BITS;
|
||||
for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
|
||||
max6875_update_slice(client, slice);
|
||||
|
||||
memcpy(buf, &data->data[off], count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t max6875_user_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
{
|
||||
return max6875_read(kobj, buf, off, count, max6875_eeprom_user);
|
||||
}
|
||||
|
||||
static ssize_t max6875_config_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
{
|
||||
return max6875_read(kobj, buf, off, count, max6875_eeprom_config);
|
||||
}
|
||||
|
||||
static ssize_t max6875_cfgreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
{
|
||||
return max6875_read(kobj, buf, off, count, max6875_register_config);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t max6875_write(struct kobject *kobj, char *buf, loff_t off, size_t count,
|
||||
enum max6875_area_type area_type)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
|
||||
struct max6875_data *data = i2c_get_clientdata(client);
|
||||
struct eeprom_block *blk;
|
||||
int slice, addr, retval;
|
||||
ssize_t sent = 0;
|
||||
|
||||
blk = &data->blocks[area_type];
|
||||
|
||||
if (off > blk->size)
|
||||
return 0;
|
||||
if ((off + count) > blk->size)
|
||||
count = blk->size - off;
|
||||
|
||||
if (down_interruptible(&data->update_lock))
|
||||
return -EAGAIN;
|
||||
|
||||
/* writing to a register is done with i2c_smbus_write_byte_data() */
|
||||
if (blk->type == max6875_register_config) {
|
||||
for (sent = 0; sent < count; sent++) {
|
||||
addr = off + sent;
|
||||
if (addr == 0x44)
|
||||
continue;
|
||||
|
||||
retval = i2c_smbus_write_byte_data(client, addr, buf[sent]);
|
||||
}
|
||||
} else {
|
||||
int cmd, val;
|
||||
|
||||
/* We are writing to EEPROM */
|
||||
for (sent = 0; sent < count; sent++) {
|
||||
addr = blk->base + off + sent;
|
||||
cmd = addr >> 8;
|
||||
val = (addr & 0xff) | (buf[sent] << 8); // reversed
|
||||
|
||||
if (addr == 0x8044)
|
||||
continue;
|
||||
|
||||
retval = i2c_smbus_write_word_data(client, cmd, val);
|
||||
|
||||
if (retval) {
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* A write takes up to 11 ms */
|
||||
msleep(11);
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalidate the scratch buffer */
|
||||
for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
|
||||
blk->valid &= ~(1 << slice);
|
||||
|
||||
error_exit:
|
||||
up(&data->update_lock);
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
static ssize_t max6875_user_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
{
|
||||
return max6875_write(kobj, buf, off, count, max6875_eeprom_user);
|
||||
}
|
||||
|
||||
static ssize_t max6875_config_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
{
|
||||
return max6875_write(kobj, buf, off, count, max6875_eeprom_config);
|
||||
}
|
||||
|
||||
static ssize_t max6875_cfgreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
||||
{
|
||||
return max6875_write(kobj, buf, off, count, max6875_register_config);
|
||||
}
|
||||
|
||||
static struct bin_attribute user_eeprom_attr = {
|
||||
.attr = {
|
||||
.name = "eeprom_user",
|
||||
.mode = S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
.name = "eeprom",
|
||||
.mode = S_IRUGO,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.size = USER_EEPROM_SIZE,
|
||||
.read = max6875_user_read,
|
||||
.write = max6875_user_write,
|
||||
};
|
||||
|
||||
static struct bin_attribute config_eeprom_attr = {
|
||||
.attr = {
|
||||
.name = "eeprom_config",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.size = CONFIG_EEPROM_SIZE,
|
||||
.read = max6875_config_read,
|
||||
.write = max6875_config_write,
|
||||
};
|
||||
|
||||
static struct bin_attribute config_register_attr = {
|
||||
.attr = {
|
||||
.name = "reg_config",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.size = CONFIG_EEPROM_SIZE,
|
||||
.read = max6875_cfgreg_read,
|
||||
.write = max6875_cfgreg_write,
|
||||
.size = USER_EEPROM_SIZE,
|
||||
.read = max6875_read,
|
||||
};
|
||||
|
||||
static int max6875_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_detect(adapter, &addr_data, max6875_detect);
|
||||
return i2c_probe(adapter, &addr_data, max6875_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
/* This function is called by i2c_probe */
|
||||
static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
struct i2c_client *real_client;
|
||||
struct i2c_client *fake_client;
|
||||
struct max6875_data *data;
|
||||
int err = 0;
|
||||
|
||||
/* Prevent 24RF08 corruption (in case of user error) */
|
||||
if (kind < 0)
|
||||
i2c_smbus_xfer(adapter, address, 0, 0, 0,
|
||||
I2C_SMBUS_QUICK, NULL);
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
|
||||
| I2C_FUNC_SMBUS_READ_BYTE))
|
||||
return 0;
|
||||
|
||||
/* There are three ways we can read the EEPROM data:
|
||||
(1) I2C block reads (faster, but unsupported by most adapters)
|
||||
(2) Consecutive byte reads (100% overhead)
|
||||
(3) Regular byte data reads (200% overhead)
|
||||
The third method is not implemented by this driver because all
|
||||
known adapters support at least the second. */
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
|
||||
goto exit;
|
||||
/* Only check even addresses */
|
||||
if (address & 1)
|
||||
return 0;
|
||||
|
||||
/* 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 eeprom_{read,write}_value. */
|
||||
if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
memset(data, 0, sizeof(struct max6875_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
new_client->addr = address;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &max6875_driver;
|
||||
new_client->flags = 0;
|
||||
/* A fake client is created on the odd address */
|
||||
if (!(fake_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit_kfree1;
|
||||
}
|
||||
memset(fake_client, 0, sizeof(struct i2c_client));
|
||||
|
||||
/* Setup the user section */
|
||||
data->blocks[max6875_eeprom_user].type = max6875_eeprom_user;
|
||||
data->blocks[max6875_eeprom_user].slices = USER_EEPROM_SLICES;
|
||||
data->blocks[max6875_eeprom_user].size = USER_EEPROM_SIZE;
|
||||
data->blocks[max6875_eeprom_user].base = USER_EEPROM_BASE;
|
||||
data->blocks[max6875_eeprom_user].data = data->data;
|
||||
data->blocks[max6875_eeprom_user].updated = data->last_updated;
|
||||
|
||||
/* Setup the config section */
|
||||
data->blocks[max6875_eeprom_config].type = max6875_eeprom_config;
|
||||
data->blocks[max6875_eeprom_config].slices = CONFIG_EEPROM_SLICES;
|
||||
data->blocks[max6875_eeprom_config].size = CONFIG_EEPROM_SIZE;
|
||||
data->blocks[max6875_eeprom_config].base = CONFIG_EEPROM_BASE;
|
||||
data->blocks[max6875_eeprom_config].data = &data->data[USER_EEPROM_SIZE];
|
||||
data->blocks[max6875_eeprom_config].updated = &data->last_updated[USER_EEPROM_SLICES];
|
||||
|
||||
/* Setup the register section */
|
||||
data->blocks[max6875_register_config].type = max6875_register_config;
|
||||
data->blocks[max6875_register_config].slices = CONFIG_EEPROM_SLICES;
|
||||
data->blocks[max6875_register_config].size = CONFIG_EEPROM_SIZE;
|
||||
data->blocks[max6875_register_config].base = 0;
|
||||
data->blocks[max6875_register_config].data = &data->data[USER_EEPROM_SIZE+CONFIG_EEPROM_SIZE];
|
||||
data->blocks[max6875_register_config].updated = &data->last_updated[USER_EEPROM_SLICES+CONFIG_EEPROM_SLICES];
|
||||
|
||||
/* Init the data */
|
||||
memset(data->data, 0xff, sizeof(data->data));
|
||||
|
||||
/* Fill in the remaining client fields */
|
||||
strlcpy(new_client->name, "max6875", I2C_NAME_SIZE);
|
||||
/* Init real i2c_client */
|
||||
real_client = &data->client;
|
||||
i2c_set_clientdata(real_client, data);
|
||||
real_client->addr = address;
|
||||
real_client->adapter = adapter;
|
||||
real_client->driver = &max6875_driver;
|
||||
real_client->flags = 0;
|
||||
strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Verify that the chip is really what we think it is */
|
||||
if ((max6875_update_slice(new_client, &data->blocks[max6875_eeprom_config], 4) < 0) ||
|
||||
(max6875_update_slice(new_client, &data->blocks[max6875_register_config], 4) < 0))
|
||||
goto exit_kfree;
|
||||
/* Init fake client data */
|
||||
/* set the client data to the i2c_client so that it will get freed */
|
||||
i2c_set_clientdata(fake_client, fake_client);
|
||||
fake_client->addr = address | 1;
|
||||
fake_client->adapter = adapter;
|
||||
fake_client->driver = &max6875_driver;
|
||||
fake_client->flags = 0;
|
||||
strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE);
|
||||
|
||||
/* 0x41,0x42 must be zero and 0x40 must match in eeprom and registers */
|
||||
if ((data->blocks[max6875_eeprom_config].data[0x41] != 0) ||
|
||||
(data->blocks[max6875_eeprom_config].data[0x42] != 0) ||
|
||||
(data->blocks[max6875_register_config].data[0x41] != 0) ||
|
||||
(data->blocks[max6875_register_config].data[0x42] != 0) ||
|
||||
(data->blocks[max6875_eeprom_config].data[0x40] !=
|
||||
data->blocks[max6875_register_config].data[0x40]))
|
||||
goto exit_kfree;
|
||||
/* Prevent 24RF08 corruption (in case of user error) */
|
||||
i2c_smbus_write_quick(real_client, 0);
|
||||
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto exit_kfree;
|
||||
if ((err = i2c_attach_client(real_client)) != 0)
|
||||
goto exit_kfree2;
|
||||
|
||||
/* create the sysfs eeprom files with the correct permissions */
|
||||
if (allow_write == 0) {
|
||||
user_eeprom_attr.attr.mode &= ~S_IWUGO;
|
||||
user_eeprom_attr.write = NULL;
|
||||
config_eeprom_attr.attr.mode &= ~S_IWUGO;
|
||||
config_eeprom_attr.write = NULL;
|
||||
config_register_attr.attr.mode &= ~S_IWUGO;
|
||||
config_register_attr.write = NULL;
|
||||
}
|
||||
sysfs_create_bin_file(&new_client->dev.kobj, &user_eeprom_attr);
|
||||
sysfs_create_bin_file(&new_client->dev.kobj, &config_eeprom_attr);
|
||||
sysfs_create_bin_file(&new_client->dev.kobj, &config_register_attr);
|
||||
if ((err = i2c_attach_client(fake_client)) != 0)
|
||||
goto exit_detach;
|
||||
|
||||
sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_kfree:
|
||||
exit_detach:
|
||||
i2c_detach_client(real_client);
|
||||
exit_kfree2:
|
||||
kfree(fake_client);
|
||||
exit_kfree1:
|
||||
kfree(data);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -450,13 +236,9 @@ static int max6875_detach_client(struct i2c_client *client)
|
||||
int err;
|
||||
|
||||
err = i2c_detach_client(client);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -13,14 +13,12 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END};
|
||||
static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(pca9539);
|
||||
I2C_CLIENT_INSMOD_1(pca9539);
|
||||
|
||||
enum pca9539_cmd
|
||||
{
|
||||
@ -109,10 +107,10 @@ static struct attribute_group pca9539_defattr_group = {
|
||||
|
||||
static int pca9539_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_detect(adapter, &addr_data, pca9539_detect);
|
||||
return i2c_probe(adapter, &addr_data, pca9539_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
/* This function is called by i2c_probe */
|
||||
static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
@ -164,10 +162,8 @@ static int pca9539_detach_client(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
dev_err(&client->dev, "Client deregistration failed.\n");
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
|
@ -39,16 +39,14 @@
|
||||
#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[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_2(pcf8574, pcf8574a);
|
||||
I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a);
|
||||
|
||||
/* Initial values */
|
||||
#define PCF8574_INIT 255 /* All outputs on (input mode) */
|
||||
@ -113,10 +111,10 @@ static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
|
||||
|
||||
static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_detect(adapter, &addr_data, pcf8574_detect);
|
||||
return i2c_probe(adapter, &addr_data, pcf8574_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
/* This function is called by i2c_probe */
|
||||
int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
@ -186,11 +184,8 @@ static int pcf8574_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");
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
|
@ -24,15 +24,13 @@
|
||||
#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[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
|
||||
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
|
||||
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(pcf8591);
|
||||
I2C_CLIENT_INSMOD_1(pcf8591);
|
||||
|
||||
static int input_mode;
|
||||
module_param(input_mode, int, 0);
|
||||
@ -164,10 +162,10 @@ static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO,
|
||||
*/
|
||||
static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_detect(adapter, &addr_data, pcf8591_detect);
|
||||
return i2c_probe(adapter, &addr_data, pcf8591_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_detect */
|
||||
/* This function is called by i2c_probe */
|
||||
int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
@ -241,11 +239,8 @@ static int pcf8591_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");
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(i2c_get_clientdata(client));
|
||||
return 0;
|
||||
|
@ -67,7 +67,6 @@ static struct i2c_client_address_data addr_data = {
|
||||
.normal_i2c = normal_addr,
|
||||
.probe = ignore,
|
||||
.ignore = ignore,
|
||||
.force = ignore,
|
||||
};
|
||||
|
||||
static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
|
||||
|
@ -61,7 +61,7 @@ static int i2c_bus_resume(struct device * dev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct bus_type i2c_bus_type = {
|
||||
struct bus_type i2c_bus_type = {
|
||||
.name = "i2c",
|
||||
.match = i2c_device_match,
|
||||
.suspend = i2c_bus_suspend,
|
||||
@ -78,13 +78,13 @@ static int i2c_device_remove(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2c_adapter_dev_release(struct device *dev)
|
||||
void i2c_adapter_dev_release(struct device *dev)
|
||||
{
|
||||
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
|
||||
complete(&adap->dev_released);
|
||||
}
|
||||
|
||||
static struct device_driver i2c_adapter_driver = {
|
||||
struct device_driver i2c_adapter_driver = {
|
||||
.name = "i2c_adapter",
|
||||
.bus = &i2c_bus_type,
|
||||
.probe = i2c_device_probe,
|
||||
@ -97,7 +97,7 @@ static void i2c_adapter_class_dev_release(struct class_device *dev)
|
||||
complete(&adap->class_dev_released);
|
||||
}
|
||||
|
||||
static struct class i2c_adapter_class = {
|
||||
struct class i2c_adapter_class = {
|
||||
.name = "i2c-adapter",
|
||||
.release = &i2c_adapter_class_dev_release,
|
||||
};
|
||||
@ -188,6 +188,8 @@ int i2c_add_adapter(struct i2c_adapter *adap)
|
||||
strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
|
||||
class_device_register(&adap->class_dev);
|
||||
|
||||
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
|
||||
|
||||
/* inform drivers of new adapters */
|
||||
list_for_each(item,&drivers) {
|
||||
driver = list_entry(item, struct i2c_driver, list);
|
||||
@ -196,8 +198,6 @@ int i2c_add_adapter(struct i2c_adapter *adap)
|
||||
driver->attach_adapter(adap);
|
||||
}
|
||||
|
||||
dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr);
|
||||
|
||||
out_unlock:
|
||||
up(&core_lists);
|
||||
return res;
|
||||
@ -220,8 +220,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
|
||||
break;
|
||||
}
|
||||
if (adap_from_list != adap) {
|
||||
pr_debug("I2C: Attempting to delete an unregistered "
|
||||
"adapter\n");
|
||||
pr_debug("i2c-core: attempting to delete unregistered "
|
||||
"adapter [%s]\n", adap->name);
|
||||
res = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
@ -230,9 +230,8 @@ 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 "
|
||||
"while detaching driver %s: driver "
|
||||
"not detached!\n", driver->name);
|
||||
dev_err(&adap->dev, "detach_adapter failed "
|
||||
"for driver [%s]\n", driver->name);
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
@ -247,9 +246,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
|
||||
* must be deleted, as this would cause invalid states.
|
||||
*/
|
||||
if ((res=client->driver->detach_client(client))) {
|
||||
dev_err(&adap->dev, "adapter not "
|
||||
"unregistered, because client at "
|
||||
"address %02x can't be detached. ",
|
||||
dev_err(&adap->dev, "detach_client failed for client "
|
||||
"[%s] at address 0x%02x\n", client->name,
|
||||
client->addr);
|
||||
goto out_unlock;
|
||||
}
|
||||
@ -270,7 +268,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
|
||||
/* free dynamically allocated bus id */
|
||||
idr_remove(&i2c_adapter_idr, adap->nr);
|
||||
|
||||
dev_dbg(&adap->dev, "adapter unregistered\n");
|
||||
dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
|
||||
|
||||
out_unlock:
|
||||
up(&core_lists);
|
||||
@ -303,7 +301,7 @@ int i2c_add_driver(struct i2c_driver *driver)
|
||||
goto out_unlock;
|
||||
|
||||
list_add_tail(&driver->list,&drivers);
|
||||
pr_debug("i2c-core: driver %s registered.\n", driver->name);
|
||||
pr_debug("i2c-core: driver [%s] registered\n", driver->name);
|
||||
|
||||
/* now look for instances of driver on our adapters */
|
||||
if (driver->flags & I2C_DF_NOTIFY) {
|
||||
@ -331,21 +329,17 @@ int i2c_del_driver(struct i2c_driver *driver)
|
||||
/* Have a look at each adapter, if clients of this driver are still
|
||||
* attached. If so, detach them to be able to kill the driver
|
||||
* afterwards.
|
||||
*/
|
||||
pr_debug("i2c-core: unregister_driver - looking for clients.\n");
|
||||
/* removing clients does not depend on the notify flag, else
|
||||
*
|
||||
* Removing clients does not depend on the notify flag, else
|
||||
* invalid operation might (will!) result, when using stale client
|
||||
* pointers.
|
||||
*/
|
||||
list_for_each(item1,&adapters) {
|
||||
adap = list_entry(item1, struct i2c_adapter, list);
|
||||
dev_dbg(&adap->dev, "examining adapter\n");
|
||||
if (driver->detach_adapter) {
|
||||
if ((res = driver->detach_adapter(adap))) {
|
||||
dev_warn(&adap->dev, "while unregistering "
|
||||
"dummy driver %s, adapter could "
|
||||
"not be detached properly; driver "
|
||||
"not unloaded!",driver->name);
|
||||
dev_err(&adap->dev, "detach_adapter failed "
|
||||
"for driver [%s]\n", driver->name);
|
||||
goto out_unlock;
|
||||
}
|
||||
} else {
|
||||
@ -353,16 +347,13 @@ int i2c_del_driver(struct i2c_driver *driver)
|
||||
client = list_entry(item2, struct i2c_client, list);
|
||||
if (client->driver != driver)
|
||||
continue;
|
||||
pr_debug("i2c-core.o: detaching client %s:\n", client->name);
|
||||
dev_dbg(&adap->dev, "detaching client [%s] "
|
||||
"at 0x%02x\n", client->name,
|
||||
client->addr);
|
||||
if ((res = driver->detach_client(client))) {
|
||||
dev_err(&adap->dev, "while "
|
||||
"unregistering driver "
|
||||
"`%s', the client at "
|
||||
"address %02x of "
|
||||
"adapter could not "
|
||||
"be detached; driver "
|
||||
"not unloaded!",
|
||||
driver->name,
|
||||
dev_err(&adap->dev, "detach_client "
|
||||
"failed for client [%s] at "
|
||||
"0x%02x\n", client->name,
|
||||
client->addr);
|
||||
goto out_unlock;
|
||||
}
|
||||
@ -372,7 +363,7 @@ int i2c_del_driver(struct i2c_driver *driver)
|
||||
|
||||
driver_unregister(&driver->driver);
|
||||
list_del(&driver->list);
|
||||
pr_debug("i2c-core: driver unregistered: %s\n", driver->name);
|
||||
pr_debug("i2c-core: driver [%s] unregistered\n", driver->name);
|
||||
|
||||
out_unlock:
|
||||
up(&core_lists);
|
||||
@ -417,15 +408,12 @@ int i2c_attach_client(struct i2c_client *client)
|
||||
|
||||
if (adapter->client_register) {
|
||||
if (adapter->client_register(client)) {
|
||||
dev_warn(&adapter->dev, "warning: client_register "
|
||||
"seems to have failed for client %02x\n",
|
||||
client->addr);
|
||||
dev_dbg(&adapter->dev, "client_register "
|
||||
"failed for client [%s] at 0x%02x\n",
|
||||
client->name, client->addr);
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(&adapter->dev, "client [%s] registered to adapter\n",
|
||||
client->name);
|
||||
|
||||
if (client->flags & I2C_CLIENT_ALLOW_USE)
|
||||
client->usage_count = 0;
|
||||
|
||||
@ -436,7 +424,8 @@ int i2c_attach_client(struct i2c_client *client)
|
||||
|
||||
snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
|
||||
"%d-%04x", i2c_adapter_id(adapter), client->addr);
|
||||
pr_debug("registering %s\n", client->dev.bus_id);
|
||||
dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
|
||||
client->name, client->dev.bus_id);
|
||||
device_register(&client->dev);
|
||||
device_create_file(&client->dev, &dev_attr_client_name);
|
||||
|
||||
@ -449,8 +438,12 @@ int i2c_detach_client(struct i2c_client *client)
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
int res = 0;
|
||||
|
||||
if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0))
|
||||
if ((client->flags & I2C_CLIENT_ALLOW_USE)
|
||||
&& (client->usage_count > 0)) {
|
||||
dev_warn(&client->dev, "Client [%s] still busy, "
|
||||
"can't detach\n", client->name);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (adapter->client_unregister) {
|
||||
res = adapter->client_unregister(client);
|
||||
@ -669,98 +662,128 @@ int i2c_control(struct i2c_client *client,
|
||||
* Will not work for 10-bit addresses!
|
||||
* ----------------------------------------------------
|
||||
*/
|
||||
static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
|
||||
int (*found_proc) (struct i2c_adapter *, int, int))
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Make sure the address is valid */
|
||||
if (addr < 0x03 || addr > 0x77) {
|
||||
dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
|
||||
addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Skip if already in use */
|
||||
if (i2c_check_addr(adapter, addr))
|
||||
return 0;
|
||||
|
||||
/* Make sure there is something at this address, unless forced */
|
||||
if (kind < 0) {
|
||||
if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
|
||||
I2C_SMBUS_QUICK, NULL) < 0)
|
||||
return 0;
|
||||
|
||||
/* prevent 24RF08 corruption */
|
||||
if ((addr & ~0x0f) == 0x50)
|
||||
i2c_smbus_xfer(adapter, addr, 0, 0, 0,
|
||||
I2C_SMBUS_QUICK, NULL);
|
||||
}
|
||||
|
||||
/* Finally call the custom detection function */
|
||||
err = found_proc(adapter, addr, kind);
|
||||
|
||||
/* -ENODEV can be returned if there is a chip at the given address
|
||||
but it isn't supported by this chip driver. We catch it here as
|
||||
this isn't an error. */
|
||||
return (err == -ENODEV) ? 0 : err;
|
||||
}
|
||||
|
||||
int i2c_probe(struct i2c_adapter *adapter,
|
||||
struct i2c_client_address_data *address_data,
|
||||
int (*found_proc) (struct i2c_adapter *, int, int))
|
||||
{
|
||||
int addr,i,found,err;
|
||||
int i, err;
|
||||
int adap_id = i2c_adapter_id(adapter);
|
||||
|
||||
/* Forget it if we can't probe using SMBUS_QUICK */
|
||||
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
|
||||
return -1;
|
||||
|
||||
for (addr = 0x00; addr <= 0x7f; addr++) {
|
||||
/* Force entries are done first, and are not affected by ignore
|
||||
entries */
|
||||
if (address_data->forces) {
|
||||
unsigned short **forces = address_data->forces;
|
||||
int kind;
|
||||
|
||||
/* Skip if already in use */
|
||||
if (i2c_check_addr(adapter,addr))
|
||||
continue;
|
||||
|
||||
/* If it is in one of the force entries, we don't do any detection
|
||||
at all */
|
||||
found = 0;
|
||||
|
||||
for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 2) {
|
||||
if (((adap_id == address_data->force[i]) ||
|
||||
(address_data->force[i] == ANY_I2C_BUS)) &&
|
||||
(addr == address_data->force[i+1])) {
|
||||
dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n",
|
||||
adap_id, addr);
|
||||
if ((err = found_proc(adapter,addr,0)))
|
||||
return err;
|
||||
found = 1;
|
||||
for (kind = 0; forces[kind]; kind++) {
|
||||
for (i = 0; forces[kind][i] != I2C_CLIENT_END;
|
||||
i += 2) {
|
||||
if (forces[kind][i] == adap_id
|
||||
|| forces[kind][i] == ANY_I2C_BUS) {
|
||||
dev_dbg(&adapter->dev, "found force "
|
||||
"parameter for adapter %d, "
|
||||
"addr 0x%02x, kind %d\n",
|
||||
adap_id, forces[kind][i + 1],
|
||||
kind);
|
||||
err = i2c_probe_address(adapter,
|
||||
forces[kind][i + 1],
|
||||
kind, found_proc);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
/* If this address is in one of the ignores, we can forget about
|
||||
it right now */
|
||||
for (i = 0;
|
||||
!found && (address_data->ignore[i] != I2C_CLIENT_END);
|
||||
i += 2) {
|
||||
if (((adap_id == address_data->ignore[i]) ||
|
||||
((address_data->ignore[i] == ANY_I2C_BUS))) &&
|
||||
(addr == address_data->ignore[i+1])) {
|
||||
dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, "
|
||||
"addr %04x\n", adap_id ,addr);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
/* Now, we will do a detection, but only if it is in the normal or
|
||||
probe entries */
|
||||
for (i = 0;
|
||||
!found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
|
||||
i += 1) {
|
||||
if (addr == address_data->normal_i2c[i]) {
|
||||
found = 1;
|
||||
dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, "
|
||||
"addr %02x\n", adap_id, addr);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0;
|
||||
!found && (address_data->probe[i] != I2C_CLIENT_END);
|
||||
i += 2) {
|
||||
if (((adap_id == address_data->probe[i]) ||
|
||||
((address_data->probe[i] == ANY_I2C_BUS))) &&
|
||||
(addr == address_data->probe[i+1])) {
|
||||
found = 1;
|
||||
dev_dbg(&adapter->dev, "found probe parameter for adapter %d, "
|
||||
"addr %04x\n", adap_id,addr);
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
/* OK, so we really should examine this address. First check
|
||||
whether there is some client here at all! */
|
||||
if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
|
||||
if ((err = found_proc(adapter,addr,-1)))
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* return id number for a specific adapter
|
||||
*/
|
||||
int i2c_adapter_id(struct i2c_adapter *adap)
|
||||
{
|
||||
return adap->nr;
|
||||
/* Probe entries are done second, and are not affected by ignore
|
||||
entries either */
|
||||
for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
|
||||
if (address_data->probe[i] == adap_id
|
||||
|| address_data->probe[i] == ANY_I2C_BUS) {
|
||||
dev_dbg(&adapter->dev, "found probe parameter for "
|
||||
"adapter %d, addr 0x%02x\n", adap_id,
|
||||
address_data->probe[i + 1]);
|
||||
err = i2c_probe_address(adapter,
|
||||
address_data->probe[i + 1],
|
||||
-1, found_proc);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Normal entries are done last, unless shadowed by an ignore entry */
|
||||
for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
|
||||
int j, ignore;
|
||||
|
||||
ignore = 0;
|
||||
for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
|
||||
j += 2) {
|
||||
if ((address_data->ignore[j] == adap_id ||
|
||||
address_data->ignore[j] == ANY_I2C_BUS)
|
||||
&& address_data->ignore[j + 1]
|
||||
== address_data->normal_i2c[i]) {
|
||||
dev_dbg(&adapter->dev, "found ignore "
|
||||
"parameter for adapter %d, "
|
||||
"addr 0x%02x\n", adap_id,
|
||||
address_data->ignore[j + 1]);
|
||||
}
|
||||
ignore = 1;
|
||||
break;
|
||||
}
|
||||
if (ignore)
|
||||
continue;
|
||||
|
||||
dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
|
||||
"addr 0x%02x\n", adap_id,
|
||||
address_data->normal_i2c[i]);
|
||||
err = i2c_probe_address(adapter, address_data->normal_i2c[i],
|
||||
-1, found_proc);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct i2c_adapter* i2c_get_adapter(int id)
|
||||
@ -1171,6 +1194,12 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
|
||||
}
|
||||
|
||||
|
||||
/* Next four are needed by i2c-isa */
|
||||
EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);
|
||||
EXPORT_SYMBOL_GPL(i2c_adapter_driver);
|
||||
EXPORT_SYMBOL_GPL(i2c_adapter_class);
|
||||
EXPORT_SYMBOL_GPL(i2c_bus_type);
|
||||
|
||||
EXPORT_SYMBOL(i2c_add_adapter);
|
||||
EXPORT_SYMBOL(i2c_del_adapter);
|
||||
EXPORT_SYMBOL(i2c_add_driver);
|
||||
@ -1186,7 +1215,6 @@ EXPORT_SYMBOL(i2c_master_send);
|
||||
EXPORT_SYMBOL(i2c_master_recv);
|
||||
EXPORT_SYMBOL(i2c_control);
|
||||
EXPORT_SYMBOL(i2c_transfer);
|
||||
EXPORT_SYMBOL(i2c_adapter_id);
|
||||
EXPORT_SYMBOL(i2c_get_adapter);
|
||||
EXPORT_SYMBOL(i2c_put_adapter);
|
||||
EXPORT_SYMBOL(i2c_probe);
|
||||
|
@ -434,7 +434,8 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
|
||||
|
||||
devfs_mk_cdev(MKDEV(I2C_MAJOR, i2c_dev->minor),
|
||||
S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i2c_dev->minor);
|
||||
dev_dbg(&adap->dev, "Registered as minor %d\n", i2c_dev->minor);
|
||||
pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
|
||||
adap->name, i2c_dev->minor);
|
||||
|
||||
/* register this i2c device with the driver core */
|
||||
i2c_dev->adap = adap;
|
||||
@ -471,7 +472,7 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
|
||||
wait_for_completion(&i2c_dev->released);
|
||||
kfree(i2c_dev);
|
||||
|
||||
dev_dbg(&adap->dev, "Adapter unregistered\n");
|
||||
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
i2c-sensor-detect.c - Part of lm_sensors, Linux kernel modules for hardware
|
||||
monitoring
|
||||
Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
|
||||
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/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
|
||||
static unsigned short empty[] = {I2C_CLIENT_END};
|
||||
static unsigned int empty_isa[] = {I2C_CLIENT_ISA_END};
|
||||
|
||||
/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
|
||||
int i2c_detect(struct i2c_adapter *adapter,
|
||||
struct i2c_address_data *address_data,
|
||||
int (*found_proc) (struct i2c_adapter *, int, int))
|
||||
{
|
||||
int addr, i, found, j, err;
|
||||
struct i2c_force_data *this_force;
|
||||
int is_isa = i2c_is_isa_adapter(adapter);
|
||||
int adapter_id =
|
||||
is_isa ? ANY_I2C_ISA_BUS : i2c_adapter_id(adapter);
|
||||
unsigned short *normal_i2c;
|
||||
unsigned int *normal_isa;
|
||||
unsigned short *probe;
|
||||
unsigned short *ignore;
|
||||
|
||||
/* Forget it if we can't probe using SMBUS_QUICK */
|
||||
if ((!is_isa) &&
|
||||
!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
|
||||
return -1;
|
||||
|
||||
/* Use default "empty" list if the adapter doesn't specify any */
|
||||
normal_i2c = probe = ignore = empty;
|
||||
normal_isa = empty_isa;
|
||||
if (address_data->normal_i2c)
|
||||
normal_i2c = address_data->normal_i2c;
|
||||
if (address_data->normal_isa)
|
||||
normal_isa = address_data->normal_isa;
|
||||
if (address_data->probe)
|
||||
probe = address_data->probe;
|
||||
if (address_data->ignore)
|
||||
ignore = address_data->ignore;
|
||||
|
||||
for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
|
||||
if (!is_isa && i2c_check_addr(adapter, addr))
|
||||
continue;
|
||||
|
||||
/* If it is in one of the force entries, we don't do any
|
||||
detection at all */
|
||||
found = 0;
|
||||
for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
|
||||
for (j = 0; !found && (this_force->force[j] != I2C_CLIENT_END); j += 2) {
|
||||
if ( ((adapter_id == this_force->force[j]) ||
|
||||
((this_force->force[j] == ANY_I2C_BUS) && !is_isa)) &&
|
||||
(addr == this_force->force[j + 1]) ) {
|
||||
dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
|
||||
if ((err = found_proc(adapter, addr, this_force->kind)))
|
||||
return err;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
/* If this address is in one of the ignores, we can forget about it
|
||||
right now */
|
||||
for (i = 0; !found && (ignore[i] != I2C_CLIENT_END); i += 2) {
|
||||
if ( ((adapter_id == ignore[i]) ||
|
||||
((ignore[i] == ANY_I2C_BUS) &&
|
||||
!is_isa)) &&
|
||||
(addr == ignore[i + 1])) {
|
||||
dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
/* Now, we will do a detection, but only if it is in the normal or
|
||||
probe entries */
|
||||
if (is_isa) {
|
||||
for (i = 0; !found && (normal_isa[i] != I2C_CLIENT_ISA_END); i += 1) {
|
||||
if (addr == normal_isa[i]) {
|
||||
dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; !found && (normal_i2c[i] != I2C_CLIENT_END); i += 1) {
|
||||
if (addr == normal_i2c[i]) {
|
||||
found = 1;
|
||||
dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x\n", adapter_id, addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0;
|
||||
!found && (probe[i] != I2C_CLIENT_END);
|
||||
i += 2) {
|
||||
if (((adapter_id == probe[i]) ||
|
||||
((probe[i] == ANY_I2C_BUS) && !is_isa))
|
||||
&& (addr == probe[i + 1])) {
|
||||
dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
/* OK, so we really should examine this address. First check
|
||||
whether there is some client here at all! */
|
||||
if (is_isa ||
|
||||
(i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
|
||||
if ((err = found_proc(adapter, addr, -1)))
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(i2c_detect);
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
|
||||
"Rudolf Marek <r.marek@sh.cvut.cz>");
|
||||
|
||||
MODULE_DESCRIPTION("i2c-sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
i2c-sensor-vid.c - Part of lm_sensors, Linux kernel modules for hardware
|
||||
monitoring
|
||||
|
||||
Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
|
||||
|
||||
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/kernel.h>
|
||||
|
||||
struct vrm_model {
|
||||
u8 vendor;
|
||||
u8 eff_family;
|
||||
u8 eff_model;
|
||||
int vrm_type;
|
||||
};
|
||||
|
||||
#define ANY 0xFF
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
|
||||
static struct vrm_model vrm_models[] = {
|
||||
{X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */
|
||||
{X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */
|
||||
{X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */
|
||||
{X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* 0xB Tualatin */
|
||||
{X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */
|
||||
{X86_VENDOR_INTEL, 0x7, ANY, 0}, /* Itanium */
|
||||
{X86_VENDOR_INTEL, 0xF, 0x3, 100}, /* P4 Prescott */
|
||||
{X86_VENDOR_INTEL, 0xF, ANY, 90}, /* P4 before Prescott */
|
||||
{X86_VENDOR_INTEL, 0x10,ANY, 0}, /* Itanium 2 */
|
||||
{X86_VENDOR_UNKNOWN, ANY, ANY, 0} /* stop here */
|
||||
};
|
||||
|
||||
static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
|
||||
if (vrm_models[i].vendor==vendor)
|
||||
if ((vrm_models[i].eff_family==eff_family)&& \
|
||||
((vrm_models[i].eff_model==eff_model)|| \
|
||||
(vrm_models[i].eff_model==ANY)))
|
||||
return vrm_models[i].vrm_type;
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_which_vrm(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = cpu_data;
|
||||
u32 eax;
|
||||
u8 eff_family, eff_model;
|
||||
int vrm_ret;
|
||||
|
||||
if (c->x86 < 6) return 0; /* any CPU with familly lower than 6
|
||||
dont have VID and/or CPUID */
|
||||
eax = cpuid_eax(1);
|
||||
eff_family = ((eax & 0x00000F00)>>8);
|
||||
eff_model = ((eax & 0x000000F0)>>4);
|
||||
if (eff_family == 0xF) { /* use extended model & family */
|
||||
eff_family += ((eax & 0x00F00000)>>20);
|
||||
eff_model += ((eax & 0x000F0000)>>16)<<4;
|
||||
}
|
||||
vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
|
||||
if (vrm_ret == 0)
|
||||
printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your"
|
||||
" x86 CPU\n");
|
||||
return vrm_ret;
|
||||
}
|
||||
|
||||
/* and now for something completely different for Non-x86 world*/
|
||||
#else
|
||||
int i2c_which_vrm(void)
|
||||
{
|
||||
printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your CPU\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(i2c_which_vrm);
|
@ -1464,26 +1464,6 @@ static int __devinit add_card(struct pci_dev *dev,
|
||||
{ 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block }
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
|
||||
union i2c_smbus_data data;
|
||||
|
||||
if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE,NULL))
|
||||
PRINT(KERN_ERR, lynx->id,"eeprom read start has failed");
|
||||
else
|
||||
{
|
||||
u16 addr;
|
||||
for (addr=0x00; addr < 0x100; addr++) {
|
||||
if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE,& data)) {
|
||||
PRINT(KERN_ERR, lynx->id, "unable to read i2c %x", addr);
|
||||
break;
|
||||
}
|
||||
else
|
||||
PRINT(KERN_DEBUG, lynx->id,"got serial eeprom data at %x: %x",addr, data.byte);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we
|
||||
do it more efficiently in one transaction rather then using several reads */
|
||||
if (i2c_transfer(i2c_ad, msg, 2) < 0) {
|
||||
|
@ -387,8 +387,6 @@ static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, in
|
||||
|
||||
/* exported algorithm data */
|
||||
static struct i2c_algorithm saa7146_algo = {
|
||||
.name = "saa7146 i2c algorithm",
|
||||
.id = I2C_ALGO_SAA7146,
|
||||
.master_xfer = saa7146_i2c_xfer,
|
||||
.functionality = saa7146_i2c_func,
|
||||
};
|
||||
@ -412,7 +410,7 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c
|
||||
#endif
|
||||
i2c_adapter->algo = &saa7146_algo;
|
||||
i2c_adapter->algo_data = NULL;
|
||||
i2c_adapter->id = I2C_ALGO_SAA7146;
|
||||
i2c_adapter->id = I2C_HW_SAA7146;
|
||||
i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
|
||||
i2c_adapter->retries = SAA7146_I2C_RETRIES;
|
||||
}
|
||||
|
@ -172,8 +172,6 @@ static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm flexcop_algo = {
|
||||
.name = "FlexCop I2C algorithm",
|
||||
.id = I2C_ALGO_BIT,
|
||||
.master_xfer = flexcop_master_xfer,
|
||||
.functionality = flexcop_i2c_func,
|
||||
};
|
||||
@ -192,7 +190,6 @@ int flexcop_i2c_init(struct flexcop_device *fc)
|
||||
fc->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
|
||||
fc->i2c_adap.algo = &flexcop_algo;
|
||||
fc->i2c_adap.algo_data = NULL;
|
||||
fc->i2c_adap.id = I2C_ALGO_BIT;
|
||||
|
||||
if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
|
||||
return ret;
|
||||
|
@ -141,8 +141,6 @@ static u32 cxusb_i2c_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm cxusb_i2c_algo = {
|
||||
.name = "Conexant USB I2C algorithm",
|
||||
.id = I2C_ALGO_BIT,
|
||||
.master_xfer = cxusb_i2c_xfer,
|
||||
.functionality = cxusb_i2c_func,
|
||||
};
|
||||
|
@ -156,8 +156,6 @@ static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
struct i2c_algorithm dibusb_i2c_algo = {
|
||||
.name = "DiBcom USB I2C algorithm",
|
||||
.id = I2C_ALGO_BIT,
|
||||
.master_xfer = dibusb_i2c_xfer,
|
||||
.functionality = dibusb_i2c_func,
|
||||
};
|
||||
|
@ -77,8 +77,6 @@ static u32 digitv_i2c_func(struct i2c_adapter *adapter)
|
||||
}
|
||||
|
||||
static struct i2c_algorithm digitv_i2c_algo = {
|
||||
.name = "Nebula DigiTV USB I2C algorithm",
|
||||
.id = I2C_ALGO_BIT,
|
||||
.master_xfer = digitv_i2c_xfer,
|
||||
.functionality = digitv_i2c_func,
|
||||
};
|
||||
|
@ -27,7 +27,6 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
|
||||
#endif
|
||||
d->i2c_adap.algo = d->props.i2c_algo;
|
||||
d->i2c_adap.algo_data = NULL;
|
||||
d->i2c_adap.id = I2C_ALGO_BIT;
|
||||
|
||||
i2c_set_adapdata(&d->i2c_adap, d);
|
||||
|
||||
|
@ -633,7 +633,6 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
|
||||
i2c_set_adapdata(&pluto->i2c_adap, pluto);
|
||||
strcpy(pluto->i2c_adap.name, DRIVER_NAME);
|
||||
pluto->i2c_adap.owner = THIS_MODULE;
|
||||
pluto->i2c_adap.id = I2C_ALGO_BIT;
|
||||
pluto->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
|
||||
pluto->i2c_adap.dev.parent = &pdev->dev;
|
||||
pluto->i2c_adap.algo_data = &pluto->i2c_bit;
|
||||
|
@ -1472,8 +1472,6 @@ static void frontend_init(struct ttusb* ttusb)
|
||||
|
||||
|
||||
static struct i2c_algorithm ttusb_dec_algo = {
|
||||
.name = "ttusb dec i2c algorithm",
|
||||
.id = I2C_ALGO_BIT,
|
||||
.master_xfer = master_xfer,
|
||||
.functionality = functionality,
|
||||
};
|
||||
@ -1525,7 +1523,6 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
#endif
|
||||
ttusb->i2c_adap.algo = &ttusb_dec_algo;
|
||||
ttusb->i2c_adap.algo_data = NULL;
|
||||
ttusb->i2c_adap.id = I2C_ALGO_BIT;
|
||||
|
||||
result = i2c_add_adapter(&ttusb->i2c_adap);
|
||||
if (result) {
|
||||
|
@ -391,7 +391,6 @@ static struct i2c_client_address_data addr_data = {
|
||||
.normal_i2c = normal_i2c,
|
||||
.probe = &ignore,
|
||||
.ignore = &ignore,
|
||||
.force = &ignore,
|
||||
};
|
||||
|
||||
static struct i2c_driver i2c_driver_adv7170;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user