Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6
This commit is contained in:
commit
20731945ae
108 changed files with 1813 additions and 1081 deletions
|
@ -4,18 +4,18 @@ Kernel driver it87
|
|||
Supported chips:
|
||||
* IT8705F
|
||||
Prefix: 'it87'
|
||||
Addresses scanned: from Super I/O config space, or default ISA 0x290 (8 I/O ports)
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
Datasheet: Publicly available at the ITE website
|
||||
http://www.ite.com.tw/
|
||||
* IT8712F
|
||||
Prefix: 'it8712'
|
||||
Addresses scanned: I2C 0x28 - 0x2f
|
||||
from Super I/O config space, or default ISA 0x290 (8 I/O ports)
|
||||
from Super I/O config space (8 I/O ports)
|
||||
Datasheet: Publicly available at the ITE website
|
||||
http://www.ite.com.tw/
|
||||
* SiS950 [clone of IT8705F]
|
||||
Prefix: 'sis950'
|
||||
Addresses scanned: from Super I/O config space, or default ISA 0x290 (8 I/O ports)
|
||||
Prefix: 'it87'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
Datasheet: No longer be available
|
||||
|
||||
Author: Christophe Gauthron <chrisg@0-in.com>
|
||||
|
|
|
@ -24,14 +24,14 @@ Supported chips:
|
|||
http://www.national.com/pf/LM/LM86.html
|
||||
* Analog Devices ADM1032
|
||||
Prefix: 'adm1032'
|
||||
Addresses scanned: I2C 0x4c
|
||||
Addresses scanned: I2C 0x4c and 0x4d
|
||||
Datasheet: Publicly available at the Analog Devices website
|
||||
http://products.analog.com/products/info.asp?product=ADM1032
|
||||
http://www.analog.com/en/prod/0,2877,ADM1032,00.html
|
||||
* Analog Devices ADT7461
|
||||
Prefix: 'adt7461'
|
||||
Addresses scanned: I2C 0x4c
|
||||
Addresses scanned: I2C 0x4c and 0x4d
|
||||
Datasheet: Publicly available at the Analog Devices website
|
||||
http://products.analog.com/products/info.asp?product=ADT7461
|
||||
http://www.analog.com/en/prod/0,2877,ADT7461,00.html
|
||||
Note: Only if in ADM1032 compatibility mode
|
||||
* Maxim MAX6657
|
||||
Prefix: 'max6657'
|
||||
|
@ -71,8 +71,8 @@ increased resolution of the remote temperature measurement.
|
|||
|
||||
The different chipsets of the family are not strictly identical, although
|
||||
very similar. This driver doesn't handle any specific feature for now,
|
||||
but could if there ever was a need for it. For reference, here comes a
|
||||
non-exhaustive list of specific features:
|
||||
with the exception of SMBus PEC. For reference, here comes a non-exhaustive
|
||||
list of specific features:
|
||||
|
||||
LM90:
|
||||
* Filter and alert configuration register at 0xBF.
|
||||
|
@ -91,6 +91,7 @@ ADM1032:
|
|||
* Conversion averaging.
|
||||
* Up to 64 conversions/s.
|
||||
* ALERT is triggered by open remote sensor.
|
||||
* SMBus PEC support for Write Byte and Receive Byte transactions.
|
||||
|
||||
ADT7461
|
||||
* Extended temperature range (breaks compatibility)
|
||||
|
@ -119,3 +120,37 @@ The lm90 driver will not update its values more frequently than every
|
|||
other second; reading them more often will do no harm, but will return
|
||||
'old' values.
|
||||
|
||||
PEC Support
|
||||
-----------
|
||||
|
||||
The ADM1032 is the only chip of the family which supports PEC. It does
|
||||
not support PEC on all transactions though, so some care must be taken.
|
||||
|
||||
When reading a register value, the PEC byte is computed and sent by the
|
||||
ADM1032 chip. However, in the case of a combined transaction (SMBus Read
|
||||
Byte), the ADM1032 computes the CRC value over only the second half of
|
||||
the message rather than its entirety, because it thinks the first half
|
||||
of the message belongs to a different transaction. As a result, the CRC
|
||||
value differs from what the SMBus master expects, and all reads fail.
|
||||
|
||||
For this reason, the lm90 driver will enable PEC for the ADM1032 only if
|
||||
the bus supports the SMBus Send Byte and Receive Byte transaction types.
|
||||
These transactions will be used to read register values, instead of
|
||||
SMBus Read Byte, and PEC will work properly.
|
||||
|
||||
Additionally, the ADM1032 doesn't support SMBus Send Byte with PEC.
|
||||
Instead, it will try to write the PEC value to the register (because the
|
||||
SMBus Send Byte transaction with PEC is similar to a Write Byte transaction
|
||||
without PEC), which is not what we want. Thus, PEC is explicitely disabled
|
||||
on SMBus Send Byte transactions in the lm90 driver.
|
||||
|
||||
PEC on byte data transactions represents a significant increase in bandwidth
|
||||
usage (+33% for writes, +25% for reads) in normal conditions. With the need
|
||||
to use two SMBus transaction for reads, this overhead jumps to +50%. Worse,
|
||||
two transactions will typically mean twice as much delay waiting for
|
||||
transaction completion, effectively doubling the register cache refresh time.
|
||||
I guess reliability comes at a price, but it's quite expensive this time.
|
||||
|
||||
So, as not everyone might enjoy the slowdown, PEC can be disabled through
|
||||
sysfs. Just write 0 to the "pec" file and PEC will be disabled. Write 1
|
||||
to that file to enable PEC again.
|
||||
|
|
|
@ -3,6 +3,7 @@ Kernel driver smsc47b397
|
|||
|
||||
Supported chips:
|
||||
* SMSC LPC47B397-NC
|
||||
* SMSC SCH5307-NS
|
||||
Prefix: 'smsc47b397'
|
||||
Addresses scanned: none, address read from Super I/O config space
|
||||
Datasheet: In this file
|
||||
|
@ -12,11 +13,14 @@ Authors: Mark M. Hoffman <mhoffman@lightlink.com>
|
|||
|
||||
November 23, 2004
|
||||
|
||||
The following specification describes the SMSC LPC47B397-NC sensor chip
|
||||
The following specification describes the SMSC LPC47B397-NC[1] sensor chip
|
||||
(for which there is no public datasheet available). This document was
|
||||
provided by Craig Kelly (In-Store Broadcast Network) and edited/corrected
|
||||
by Mark M. Hoffman <mhoffman@lightlink.com>.
|
||||
|
||||
[1] And SMSC SCH5307-NS, which has a different device ID but is otherwise
|
||||
compatible.
|
||||
|
||||
* * * * *
|
||||
|
||||
Methods for detecting the HP SIO and reading the thermal data on a dc7100.
|
||||
|
@ -127,7 +131,7 @@ OUT DX,AL
|
|||
The registers of interest for identifying the SIO on the dc7100 are Device ID
|
||||
(0x20) and Device Rev (0x21).
|
||||
|
||||
The Device ID will read 0X6F
|
||||
The Device ID will read 0x6F (for SCH5307-NS, 0x81)
|
||||
The Device Rev currently reads 0x01
|
||||
|
||||
Obtaining the HWM Base Address.
|
||||
|
|
|
@ -12,6 +12,10 @@ Supported chips:
|
|||
http://www.smsc.com/main/datasheets/47m14x.pdf
|
||||
http://www.smsc.com/main/tools/discontinued/47m15x.pdf
|
||||
http://www.smsc.com/main/datasheets/47m192.pdf
|
||||
* SMSC LPC47M997
|
||||
Addresses scanned: none, address read from Super I/O config space
|
||||
Prefix: 'smsc47m1'
|
||||
Datasheet: none
|
||||
|
||||
Authors:
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>,
|
||||
|
@ -30,6 +34,9 @@ The 47M15x and 47M192 chips contain a full 'hardware monitoring block'
|
|||
in addition to the fan monitoring and control. The hardware monitoring
|
||||
block is not supported by the driver.
|
||||
|
||||
No documentation is available for the 47M997, but it has the same device
|
||||
ID as the 47M15x and 47M192 chips and seems to be compatible.
|
||||
|
||||
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 or 8) to give
|
||||
|
|
|
@ -272,3 +272,6 @@ beep_mask Bitmask for beep.
|
|||
|
||||
eeprom Raw EEPROM data in binary form.
|
||||
Read only.
|
||||
|
||||
pec Enable or disable PEC (SMBus only)
|
||||
Read/Write
|
||||
|
|
|
@ -18,8 +18,9 @@ Authors:
|
|||
Module Parameters
|
||||
-----------------
|
||||
|
||||
force_addr=0xaddr Set the I/O base address. Useful for Asus A7V boards
|
||||
that don't set the address in the BIOS. Does not do a
|
||||
force_addr=0xaddr Set the I/O base address. Useful for boards that
|
||||
don't set the address in the BIOS. Look for a BIOS
|
||||
upgrade before resorting to this. Does not do a
|
||||
PCI force; the via686a must still be present in lspci.
|
||||
Don't use this unless the driver complains that the
|
||||
base address is not set.
|
||||
|
@ -63,3 +64,15 @@ miss once-only alarms.
|
|||
|
||||
The driver only updates its values each 1.5 seconds; reading it more often
|
||||
will do no harm, but will return 'old' values.
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
This driver handles sensors integrated in some VIA south bridges. It is
|
||||
possible that a motherboard maker used a VT82C686A/B chip as part of a
|
||||
product design but was not interested in its hardware monitoring features,
|
||||
in which case the sensor inputs will not be wired. This is the case of
|
||||
the Asus K7V, A7V and A7V133 motherboards, to name only a few of them.
|
||||
So, if you need the force_addr parameter, and end up with values which
|
||||
don't seem to make any sense, don't look any further: your chip is simply
|
||||
not wired for hardware monitoring.
|
||||
|
|
|
@ -2,6 +2,7 @@ Kernel driver i2c-i810
|
|||
|
||||
Supported adapters:
|
||||
* Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH)
|
||||
* Intel 82845G (GMCH)
|
||||
|
||||
Authors:
|
||||
Frodo Looijaard <frodol@dds.nl>,
|
||||
|
|
|
@ -4,17 +4,18 @@ Supported adapters:
|
|||
* VIA Technologies, Inc. VT82C596A/B
|
||||
Datasheet: Sometimes available at the VIA website
|
||||
|
||||
* VIA Technologies, Inc. VT82C686A/B
|
||||
* VIA Technologies, Inc. VT82C686A/B
|
||||
Datasheet: Sometimes available at the VIA website
|
||||
|
||||
* VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237
|
||||
Datasheet: available on request from Via
|
||||
|
||||
Authors:
|
||||
Frodo Looijaard <frodol@dds.nl>,
|
||||
Philip Edelbrock <phil@netroedge.com>,
|
||||
Kyösti Mälkki <kmalkki@cc.hut.fi>,
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
Frodo Looijaard <frodol@dds.nl>,
|
||||
Philip Edelbrock <phil@netroedge.com>,
|
||||
Kyösti Mälkki <kmalkki@cc.hut.fi>,
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>,
|
||||
Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
Module Parameters
|
||||
-----------------
|
||||
|
@ -28,20 +29,22 @@ Description
|
|||
-----------
|
||||
|
||||
i2c-viapro is a true SMBus host driver for motherboards with one of the
|
||||
supported VIA southbridges.
|
||||
supported VIA south bridges.
|
||||
|
||||
Your lspci -n listing must show one of these :
|
||||
|
||||
device 1106:3050 (VT82C596 function 3)
|
||||
device 1106:3051 (VT82C596 function 3)
|
||||
device 1106:3050 (VT82C596A function 3)
|
||||
device 1106:3051 (VT82C596B function 3)
|
||||
device 1106:3057 (VT82C686 function 4)
|
||||
device 1106:3074 (VT8233)
|
||||
device 1106:3147 (VT8233A)
|
||||
device 1106:8235 (VT8231)
|
||||
devide 1106:3177 (VT8235)
|
||||
devide 1106:3227 (VT8237)
|
||||
device 1106:8235 (VT8231 function 4)
|
||||
device 1106:3177 (VT8235)
|
||||
device 1106:3227 (VT8237R)
|
||||
|
||||
If none of these show up, you should look in the BIOS for settings like
|
||||
enable ACPI / SMBus or even USB.
|
||||
|
||||
|
||||
Except for the oldest chips (VT82C596A/B, VT82C686A and most probably
|
||||
VT8231), this driver supports I2C block transactions. Such transactions
|
||||
are mainly useful to read from and write to EEPROMs.
|
||||
|
|
38
Documentation/i2c/chips/x1205
Normal file
38
Documentation/i2c/chips/x1205
Normal file
|
@ -0,0 +1,38 @@
|
|||
Kernel driver x1205
|
||||
===================
|
||||
|
||||
Supported chips:
|
||||
* Xicor X1205 RTC
|
||||
Prefix: 'x1205'
|
||||
Addresses scanned: none
|
||||
Datasheet: http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
|
||||
|
||||
Authors:
|
||||
Karen Spearel <kas11@tampabay.rr.com>,
|
||||
Alessandro Zummo <a.zummo@towertech.it>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This module aims to provide complete access to the Xicor X1205 RTC.
|
||||
Recently Xicor has merged with Intersil, but the chip is
|
||||
still sold under the Xicor brand.
|
||||
|
||||
This chip is located at address 0x6f and uses a 2-byte register addressing.
|
||||
Two bytes need to be written to read a single register, while most
|
||||
other chips just require one and take the second one as the data
|
||||
to be written. To prevent corrupting unknown chips, the user must
|
||||
explicitely set the probe parameter.
|
||||
|
||||
example:
|
||||
|
||||
modprobe x1205 probe=0,0x6f
|
||||
|
||||
The module supports one more option, hctosys, which is used to set the
|
||||
software clock from the x1205. On systems where the x1205 is the
|
||||
only hardware rtc, this parameter could be used to achieve a correct
|
||||
date/time earlier in the system boot sequence.
|
||||
|
||||
example:
|
||||
|
||||
modprobe x1205 probe=0,0x6f hctosys=1
|
|
@ -17,9 +17,10 @@ For the most up-to-date list of functionality constants, please check
|
|||
I2C_FUNC_I2C Plain i2c-level commands (Pure SMBus
|
||||
adapters typically can not do these)
|
||||
I2C_FUNC_10BIT_ADDR Handles the 10-bit address extensions
|
||||
I2C_FUNC_PROTOCOL_MANGLING Knows about the I2C_M_REV_DIR_ADDR,
|
||||
I2C_M_REV_DIR_ADDR and I2C_M_REV_DIR_NOSTART
|
||||
flags (which modify the i2c protocol!)
|
||||
I2C_FUNC_PROTOCOL_MANGLING Knows about the I2C_M_IGNORE_NAK,
|
||||
I2C_M_REV_DIR_ADDR, I2C_M_NOSTART and
|
||||
I2C_M_NO_RD_ACK flags (which modify the
|
||||
I2C protocol!)
|
||||
I2C_FUNC_SMBUS_QUICK Handles the SMBus write_quick command
|
||||
I2C_FUNC_SMBUS_READ_BYTE Handles the SMBus read_byte command
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE Handles the SMBus write_byte command
|
||||
|
|
|
@ -82,7 +82,7 @@ Technical changes:
|
|||
exit and exit_free. For i2c+isa drivers, labels should be named
|
||||
ERROR0, ERROR1 and ERROR2. Don't forget to properly set err before
|
||||
jumping to error labels. By the way, labels should be left-aligned.
|
||||
Use memset to fill the client and data area with 0x00.
|
||||
Use kzalloc instead of kmalloc.
|
||||
Use i2c_set_clientdata to set the client data (as opposed to
|
||||
a direct access to client->data).
|
||||
Use strlcpy instead of strcpy to copy the client name.
|
||||
|
|
|
@ -33,8 +33,8 @@ static struct i2c_driver foo_driver = {
|
|||
.command = &foo_command /* may be NULL */
|
||||
}
|
||||
|
||||
The name can be chosen freely, and may be upto 40 characters long. Please
|
||||
use something descriptive here.
|
||||
The name field must match the driver name, including the case. It must not
|
||||
contain spaces, and may be up to 31 characters long.
|
||||
|
||||
Don't worry about the flags field; just put I2C_DF_NOTIFY into it. This
|
||||
means that your driver will be notified when new adapters are found.
|
||||
|
@ -43,9 +43,6 @@ This is almost always what you want.
|
|||
All other fields are for call-back functions which will be explained
|
||||
below.
|
||||
|
||||
There use to be two additional fields in this structure, inc_use et dec_use,
|
||||
for module usage count, but these fields were obsoleted and removed.
|
||||
|
||||
|
||||
Extra client data
|
||||
=================
|
||||
|
@ -58,6 +55,7 @@ be very useful.
|
|||
An example structure is below.
|
||||
|
||||
struct foo_data {
|
||||
struct i2c_client client;
|
||||
struct semaphore lock; /* For ISA access in `sensors' drivers. */
|
||||
int sysctl_id; /* To keep the /proc directory entry for
|
||||
`sensors' drivers. */
|
||||
|
@ -310,22 +308,15 @@ For now, you can ignore the `flags' parameter. It is there for future use.
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access several i2c functions safely */
|
||||
|
||||
/* Note that we reserve some space for foo_data too. If you don't
|
||||
need it, remove it. We do it here to help to lessen memory
|
||||
fragmentation. */
|
||||
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct foo_data),
|
||||
GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct foo_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
||||
/* This is tricky, but it will set the data to the right value. */
|
||||
client->data = new_client + 1;
|
||||
data = (struct foo_data *) (client->data);
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &foo_driver;
|
||||
new_client->flags = 0;
|
||||
|
@ -451,7 +442,7 @@ much simpler than the attachment code, fortunately!
|
|||
release_region(client->addr,LM78_EXTENT);
|
||||
/* HYBRID SENSORS CHIP ONLY END */
|
||||
|
||||
kfree(client); /* Frees client data too, if allocated at the same time */
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -576,12 +567,12 @@ SMBus communication
|
|||
extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
|
||||
u8 command, u8 length,
|
||||
u8 *values);
|
||||
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
|
||||
u8 command, u8 *values);
|
||||
|
||||
These ones were removed in Linux 2.6.10 because they had no users, but could
|
||||
be added back later if needed:
|
||||
|
||||
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
|
||||
u8 command, u8 *values);
|
||||
extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
|
||||
u8 command, u8 *values);
|
||||
extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
|
||||
|
|
|
@ -2736,6 +2736,12 @@ P: Roger Luethi
|
|||
M: rl@hellgate.ch
|
||||
S: Maintained
|
||||
|
||||
VIAPRO SMBUS DRIVER
|
||||
P: Jean Delvare
|
||||
M: khali@linux-fr.org
|
||||
L: lm-sensors@lm-sensors.org
|
||||
S: Maintained
|
||||
|
||||
UCLINUX (AND M68KNOMMU)
|
||||
P: Greg Ungerer
|
||||
M: gerg@uclinux.org
|
||||
|
|
|
@ -121,7 +121,7 @@ static int adm1021_write_value(struct i2c_client *client, u8 reg,
|
|||
static struct adm1021_data *adm1021_update_device(struct device *dev);
|
||||
|
||||
/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
|
||||
static int read_only = 0;
|
||||
static int read_only;
|
||||
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
|
@ -204,11 +204,10 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access adm1021_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto error0;
|
||||
}
|
||||
memset(data, 0, sizeof(struct adm1021_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -331,11 +331,10 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct adm1025_data));
|
||||
|
||||
/* The common I2C client data is placed right before the
|
||||
ADM1025-specific data. */
|
||||
|
|
|
@ -315,7 +315,7 @@ static struct i2c_driver adm1026_driver = {
|
|||
.detach_client = adm1026_detach_client,
|
||||
};
|
||||
|
||||
int adm1026_attach_adapter(struct i2c_adapter *adapter)
|
||||
static int adm1026_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON)) {
|
||||
return 0;
|
||||
|
@ -323,7 +323,7 @@ int adm1026_attach_adapter(struct i2c_adapter *adapter)
|
|||
return i2c_probe(adapter, &addr_data, adm1026_detect);
|
||||
}
|
||||
|
||||
int adm1026_detach_client(struct i2c_client *client)
|
||||
static int adm1026_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct adm1026_data *data = i2c_get_clientdata(client);
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
@ -332,7 +332,7 @@ int adm1026_detach_client(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int adm1026_read_value(struct i2c_client *client, u8 reg)
|
||||
static int adm1026_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
@ -346,7 +346,7 @@ int adm1026_read_value(struct i2c_client *client, u8 reg)
|
|||
return res;
|
||||
}
|
||||
|
||||
int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
|
||||
static int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
@ -360,7 +360,7 @@ int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
|
|||
return res;
|
||||
}
|
||||
|
||||
void adm1026_init_client(struct i2c_client *client)
|
||||
static void adm1026_init_client(struct i2c_client *client)
|
||||
{
|
||||
int value, i;
|
||||
struct adm1026_data *data = i2c_get_clientdata(client);
|
||||
|
@ -460,7 +460,7 @@ void adm1026_init_client(struct i2c_client *client)
|
|||
}
|
||||
}
|
||||
|
||||
void adm1026_print_gpio(struct i2c_client *client)
|
||||
static void adm1026_print_gpio(struct i2c_client *client)
|
||||
{
|
||||
struct adm1026_data *data = i2c_get_clientdata(client);
|
||||
int i;
|
||||
|
@ -492,7 +492,7 @@ void adm1026_print_gpio(struct i2c_client *client)
|
|||
}
|
||||
}
|
||||
|
||||
void adm1026_fixup_gpio(struct i2c_client *client)
|
||||
static void adm1026_fixup_gpio(struct i2c_client *client)
|
||||
{
|
||||
struct adm1026_data *data = i2c_get_clientdata(client);
|
||||
int i;
|
||||
|
@ -1452,8 +1452,8 @@ static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
|
|||
static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
|
||||
static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
|
||||
|
||||
int adm1026_detect(struct i2c_adapter *adapter, int address,
|
||||
int kind)
|
||||
static int adm1026_detect(struct i2c_adapter *adapter, int address,
|
||||
int kind)
|
||||
{
|
||||
int company, verstep;
|
||||
struct i2c_client *new_client;
|
||||
|
@ -1470,13 +1470,11 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access adm1026_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(data, 0, sizeof(struct adm1026_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
new_client->addr = address;
|
||||
|
|
|
@ -740,11 +740,10 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct adm1031_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
|
@ -69,8 +70,7 @@ I2C_CLIENT_INSMOD_3(adm9240, ds1780, lm81);
|
|||
#define ADM9240_REG_INT(nr) (0x41 + (nr))
|
||||
#define ADM9240_REG_INT_MASK(nr) (0x43 + (nr))
|
||||
#define ADM9240_REG_TEMP 0x27
|
||||
#define ADM9240_REG_TEMP_HIGH 0x39
|
||||
#define ADM9240_REG_TEMP_HYST 0x3a
|
||||
#define ADM9240_REG_TEMP_MAX(nr) (0x39 + (nr)) /* 0, 1 = high, hyst */
|
||||
#define ADM9240_REG_ANALOG_OUT 0x19
|
||||
#define ADM9240_REG_CHASSIS_CLEAR 0x46
|
||||
#define ADM9240_REG_VID_FAN_DIV 0x47
|
||||
|
@ -162,177 +162,155 @@ struct adm9240_data {
|
|||
u8 fan_min[2]; /* rw fan1_min */
|
||||
u8 fan_div[2]; /* rw fan1_div, read-only accessor */
|
||||
s16 temp; /* ro temp1_input, 9-bit sign-extended */
|
||||
s8 temp_high; /* rw temp1_max */
|
||||
s8 temp_hyst; /* rw temp1_max_hyst */
|
||||
s8 temp_max[2]; /* rw 0 -> temp_max, 1 -> temp_max_hyst */
|
||||
u16 alarms; /* ro alarms */
|
||||
u8 aout; /* rw aout_output */
|
||||
u8 vid; /* ro vid */
|
||||
u8 vrm; /* -- vrm set on startup, no accessor */
|
||||
};
|
||||
|
||||
/* i2c byte read/write interface */
|
||||
static int adm9240_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
return i2c_smbus_read_byte_data(client, reg);
|
||||
}
|
||||
|
||||
static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
|
||||
{
|
||||
return i2c_smbus_write_byte_data(client, reg, value);
|
||||
}
|
||||
|
||||
/*** sysfs accessors ***/
|
||||
|
||||
/* temperature */
|
||||
#define show_temp(value, scale) \
|
||||
static ssize_t show_##value(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct adm9240_data *data = adm9240_update_device(dev); \
|
||||
return sprintf(buf, "%d\n", data->value * scale); \
|
||||
}
|
||||
show_temp(temp_high, 1000);
|
||||
show_temp(temp_hyst, 1000);
|
||||
show_temp(temp, 500); /* 0.5'C per bit */
|
||||
|
||||
#define set_temp(value, reg) \
|
||||
static ssize_t set_##value(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count) \
|
||||
{ \
|
||||
struct i2c_client *client = to_i2c_client(dev); \
|
||||
struct adm9240_data *data = adm9240_update_device(dev); \
|
||||
long temp = simple_strtoul(buf, NULL, 10); \
|
||||
\
|
||||
down(&data->update_lock); \
|
||||
data->value = TEMP_TO_REG(temp); \
|
||||
adm9240_write_value(client, reg, data->value); \
|
||||
up(&data->update_lock); \
|
||||
return count; \
|
||||
static ssize_t show_temp(struct device *dev, struct device_attribute *dummy,
|
||||
char *buf)
|
||||
{
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%d\n", data->temp * 500); /* 9-bit value */
|
||||
}
|
||||
|
||||
set_temp(temp_high, ADM9240_REG_TEMP_HIGH);
|
||||
set_temp(temp_hyst, ADM9240_REG_TEMP_HYST);
|
||||
static ssize_t show_max(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%d\n", data->temp_max[attr->index] * 1000);
|
||||
}
|
||||
|
||||
static ssize_t set_max(struct device *dev, struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct adm9240_data *data = i2c_get_clientdata(client);
|
||||
long val = simple_strtol(buf, NULL, 10);
|
||||
|
||||
down(&data->update_lock);
|
||||
data->temp_max[attr->index] = TEMP_TO_REG(val);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index),
|
||||
data->temp_max[attr->index]);
|
||||
up(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
|
||||
show_temp_high, set_temp_high);
|
||||
static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
|
||||
show_temp_hyst, set_temp_hyst);
|
||||
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
|
||||
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
|
||||
show_max, set_max, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
|
||||
show_max, set_max, 1);
|
||||
|
||||
/* voltage */
|
||||
static ssize_t show_in(struct device *dev, char *buf, int nr)
|
||||
static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
|
||||
return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index],
|
||||
attr->index));
|
||||
}
|
||||
|
||||
static ssize_t show_in_min(struct device *dev, char *buf, int nr)
|
||||
static ssize_t show_in_min(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
|
||||
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index],
|
||||
attr->index));
|
||||
}
|
||||
|
||||
static ssize_t show_in_max(struct device *dev, char *buf, int nr)
|
||||
static ssize_t show_in_max(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
|
||||
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index],
|
||||
attr->index));
|
||||
}
|
||||
|
||||
static ssize_t set_in_min(struct device *dev, const char *buf,
|
||||
size_t count, int nr)
|
||||
static ssize_t set_in_min(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct adm9240_data *data = i2c_get_clientdata(client);
|
||||
unsigned long val = simple_strtoul(buf, NULL, 10);
|
||||
|
||||
down(&data->update_lock);
|
||||
data->in_min[nr] = IN_TO_REG(val, nr);
|
||||
adm9240_write_value(client, ADM9240_REG_IN_MIN(nr), data->in_min[nr]);
|
||||
data->in_min[attr->index] = IN_TO_REG(val, attr->index);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index),
|
||||
data->in_min[attr->index]);
|
||||
up(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t set_in_max(struct device *dev, const char *buf,
|
||||
size_t count, int nr)
|
||||
static ssize_t set_in_max(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct adm9240_data *data = i2c_get_clientdata(client);
|
||||
unsigned long val = simple_strtoul(buf, NULL, 10);
|
||||
|
||||
down(&data->update_lock);
|
||||
data->in_max[nr] = IN_TO_REG(val, nr);
|
||||
adm9240_write_value(client, ADM9240_REG_IN_MAX(nr), data->in_max[nr]);
|
||||
data->in_max[attr->index] = IN_TO_REG(val, attr->index);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index),
|
||||
data->in_max[attr->index]);
|
||||
up(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
#define show_in_offset(offset) \
|
||||
static ssize_t show_in##offset(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return show_in(dev, buf, offset); \
|
||||
} \
|
||||
static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); \
|
||||
static ssize_t show_in##offset##_min(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return show_in_min(dev, buf, offset); \
|
||||
} \
|
||||
static ssize_t show_in##offset##_max(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return show_in_max(dev, buf, offset); \
|
||||
} \
|
||||
static ssize_t \
|
||||
set_in##offset##_min(struct device *dev, \
|
||||
struct device_attribute *attr, const char *buf, \
|
||||
size_t count) \
|
||||
{ \
|
||||
return set_in_min(dev, buf, count, offset); \
|
||||
} \
|
||||
static ssize_t \
|
||||
set_in##offset##_max(struct device *dev, \
|
||||
struct device_attribute *attr, const char *buf, \
|
||||
size_t count) \
|
||||
{ \
|
||||
return set_in_max(dev, buf, count, offset); \
|
||||
} \
|
||||
static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
|
||||
show_in##offset##_min, set_in##offset##_min); \
|
||||
static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
|
||||
show_in##offset##_max, set_in##offset##_max);
|
||||
#define vin(nr) \
|
||||
static SENSOR_DEVICE_ATTR(in##nr##_input, S_IRUGO, \
|
||||
show_in, NULL, nr); \
|
||||
static SENSOR_DEVICE_ATTR(in##nr##_min, S_IRUGO | S_IWUSR, \
|
||||
show_in_min, set_in_min, nr); \
|
||||
static SENSOR_DEVICE_ATTR(in##nr##_max, S_IRUGO | S_IWUSR, \
|
||||
show_in_max, set_in_max, nr);
|
||||
|
||||
show_in_offset(0);
|
||||
show_in_offset(1);
|
||||
show_in_offset(2);
|
||||
show_in_offset(3);
|
||||
show_in_offset(4);
|
||||
show_in_offset(5);
|
||||
vin(0);
|
||||
vin(1);
|
||||
vin(2);
|
||||
vin(3);
|
||||
vin(4);
|
||||
vin(5);
|
||||
|
||||
/* fans */
|
||||
static ssize_t show_fan(struct device *dev, char *buf, int nr)
|
||||
static ssize_t show_fan(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
|
||||
1 << data->fan_div[nr]));
|
||||
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index],
|
||||
1 << data->fan_div[attr->index]));
|
||||
}
|
||||
|
||||
static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
|
||||
static ssize_t show_fan_min(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
|
||||
1 << data->fan_div[nr]));
|
||||
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[attr->index],
|
||||
1 << data->fan_div[attr->index]));
|
||||
}
|
||||
|
||||
static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
|
||||
static ssize_t show_fan_div(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%d\n", 1 << data->fan_div[nr]);
|
||||
return sprintf(buf, "%d\n", 1 << data->fan_div[attr->index]);
|
||||
}
|
||||
|
||||
/* write new fan div, callers must hold data->update_lock */
|
||||
|
@ -341,16 +319,16 @@ static void adm9240_write_fan_div(struct i2c_client *client, int nr,
|
|||
{
|
||||
u8 reg, old, shift = (nr + 2) * 2;
|
||||
|
||||
reg = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
|
||||
reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
|
||||
old = (reg >> shift) & 3;
|
||||
reg &= ~(3 << shift);
|
||||
reg |= (fan_div << shift);
|
||||
adm9240_write_value(client, ADM9240_REG_VID_FAN_DIV, reg);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
|
||||
dev_dbg(&client->dev, "fan%d clock divider changed from %u "
|
||||
"to %u\n", nr + 1, 1 << old, 1 << fan_div);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* set fan speed low limit:
|
||||
*
|
||||
* - value is zero: disable fan speed low limit alarm
|
||||
|
@ -361,12 +339,15 @@ static void adm9240_write_fan_div(struct i2c_client *client, int nr,
|
|||
* - otherwise: select fan clock divider to suit fan speed low limit,
|
||||
* measurement code may adjust registers to ensure fan speed reading
|
||||
*/
|
||||
static ssize_t set_fan_min(struct device *dev, const char *buf,
|
||||
size_t count, int nr)
|
||||
static ssize_t set_fan_min(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct adm9240_data *data = i2c_get_clientdata(client);
|
||||
unsigned long val = simple_strtoul(buf, NULL, 10);
|
||||
int nr = attr->index;
|
||||
u8 new_div;
|
||||
|
||||
down(&data->update_lock);
|
||||
|
@ -406,50 +387,27 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
|
|||
data->fan_div[nr] = new_div;
|
||||
adm9240_write_fan_div(client, nr, new_div);
|
||||
}
|
||||
adm9240_write_value(client, ADM9240_REG_FAN_MIN(nr),
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr),
|
||||
data->fan_min[nr]);
|
||||
|
||||
up(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
#define show_fan_offset(offset) \
|
||||
static ssize_t show_fan_##offset (struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return show_fan(dev, buf, offset - 1); \
|
||||
} \
|
||||
static ssize_t show_fan_##offset##_div (struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return show_fan_div(dev, buf, offset - 1); \
|
||||
} \
|
||||
static ssize_t show_fan_##offset##_min (struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return show_fan_min(dev, buf, offset - 1); \
|
||||
} \
|
||||
static ssize_t set_fan_##offset##_min (struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count) \
|
||||
{ \
|
||||
return set_fan_min(dev, buf, count, offset - 1); \
|
||||
} \
|
||||
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
|
||||
show_fan_##offset, NULL); \
|
||||
static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
|
||||
show_fan_##offset##_div, NULL); \
|
||||
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
|
||||
show_fan_##offset##_min, set_fan_##offset##_min);
|
||||
#define fan(nr) \
|
||||
static SENSOR_DEVICE_ATTR(fan##nr##_input, S_IRUGO, \
|
||||
show_fan, NULL, nr - 1); \
|
||||
static SENSOR_DEVICE_ATTR(fan##nr##_div, S_IRUGO, \
|
||||
show_fan_div, NULL, nr - 1); \
|
||||
static SENSOR_DEVICE_ATTR(fan##nr##_min, S_IRUGO | S_IWUSR, \
|
||||
show_fan_min, set_fan_min, nr - 1);
|
||||
|
||||
show_fan_offset(1);
|
||||
show_fan_offset(2);
|
||||
fan(1);
|
||||
fan(2);
|
||||
|
||||
/* alarms */
|
||||
static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t show_alarms(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%u\n", data->alarms);
|
||||
|
@ -457,7 +415,8 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
|
|||
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
|
||||
|
||||
/* vid */
|
||||
static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t show_vid(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
|
||||
|
@ -465,13 +424,16 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char
|
|||
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
|
||||
|
||||
/* analog output */
|
||||
static ssize_t show_aout(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t show_aout(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
|
||||
}
|
||||
|
||||
static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
||||
static ssize_t set_aout(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct adm9240_data *data = i2c_get_clientdata(client);
|
||||
|
@ -479,20 +441,23 @@ static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const
|
|||
|
||||
down(&data->update_lock);
|
||||
data->aout = AOUT_TO_REG(val);
|
||||
adm9240_write_value(client, ADM9240_REG_ANALOG_OUT, data->aout);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout);
|
||||
up(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
|
||||
|
||||
/* chassis_clear */
|
||||
static ssize_t chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
||||
static ssize_t chassis_clear(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
unsigned long val = simple_strtol(buf, NULL, 10);
|
||||
|
||||
if (val == 1) {
|
||||
adm9240_write_value(client, ADM9240_REG_CHASSIS_CLEAR, 0x80);
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_CHASSIS_CLEAR, 0x80);
|
||||
dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
|
||||
}
|
||||
return count;
|
||||
|
@ -513,11 +478,10 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct adm9240_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
@ -533,7 +497,7 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (kind < 0) {
|
||||
|
||||
/* verify chip: reg address should match i2c address */
|
||||
if (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR)
|
||||
if (i2c_smbus_read_byte_data(new_client, ADM9240_REG_I2C_ADDR)
|
||||
!= address) {
|
||||
dev_err(&adapter->dev, "detect fail: address match, "
|
||||
"0x%02x\n", address);
|
||||
|
@ -541,8 +505,8 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
}
|
||||
|
||||
/* check known chip manufacturer */
|
||||
man_id = adm9240_read_value(new_client, ADM9240_REG_MAN_ID);
|
||||
|
||||
man_id = i2c_smbus_read_byte_data(new_client,
|
||||
ADM9240_REG_MAN_ID);
|
||||
if (man_id == 0x23) {
|
||||
kind = adm9240;
|
||||
} else if (man_id == 0xda) {
|
||||
|
@ -556,7 +520,8 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
}
|
||||
|
||||
/* successful detect, print chip info */
|
||||
die_rev = adm9240_read_value(new_client, ADM9240_REG_DIE_REV);
|
||||
die_rev = i2c_smbus_read_byte_data(new_client,
|
||||
ADM9240_REG_DIE_REV);
|
||||
dev_info(&adapter->dev, "found %s revision %u\n",
|
||||
man_id == 0x23 ? "ADM9240" :
|
||||
man_id == 0xda ? "DS1780" : "LM81", die_rev);
|
||||
|
@ -588,33 +553,59 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
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);
|
||||
device_create_file(&new_client->dev, &dev_attr_in1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in1_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in1_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_in2_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in2_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in2_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_in3_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in3_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in3_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_in4_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in4_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in4_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_in5_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in5_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in5_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in0_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in0_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in0_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in1_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in1_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in1_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in2_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in2_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in2_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in3_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in3_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in3_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in4_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in4_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in4_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in5_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in5_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in5_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
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);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan2_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan2_div);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan2_min);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_max_hyst.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan1_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan1_div.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan1_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan2_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan2_div.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan2_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &dev_attr_alarms);
|
||||
device_create_file(&new_client->dev, &dev_attr_aout_output);
|
||||
device_create_file(&new_client->dev, &dev_attr_chassis_clear);
|
||||
|
@ -654,8 +645,8 @@ static int adm9240_detach_client(struct i2c_client *client)
|
|||
static void adm9240_init_client(struct i2c_client *client)
|
||||
{
|
||||
struct adm9240_data *data = i2c_get_clientdata(client);
|
||||
u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
|
||||
u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
|
||||
u8 conf = i2c_smbus_read_byte_data(client, ADM9240_REG_CONFIG);
|
||||
u8 mode = i2c_smbus_read_byte_data(client, ADM9240_REG_TEMP_CONF) & 3;
|
||||
|
||||
data->vrm = vid_which_vrm(); /* need this to report vid as mV */
|
||||
|
||||
|
@ -672,18 +663,22 @@ static void adm9240_init_client(struct i2c_client *client)
|
|||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
adm9240_write_value(client,
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_IN_MIN(i), 0);
|
||||
adm9240_write_value(client,
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_IN_MAX(i), 255);
|
||||
}
|
||||
adm9240_write_value(client, ADM9240_REG_FAN_MIN(0), 255);
|
||||
adm9240_write_value(client, ADM9240_REG_FAN_MIN(1), 255);
|
||||
adm9240_write_value(client, ADM9240_REG_TEMP_HIGH, 127);
|
||||
adm9240_write_value(client, ADM9240_REG_TEMP_HYST, 127);
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_FAN_MIN(0), 255);
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_FAN_MIN(1), 255);
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_TEMP_MAX(0), 127);
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_TEMP_MAX(1), 127);
|
||||
|
||||
/* start measurement cycle */
|
||||
adm9240_write_value(client, ADM9240_REG_CONFIG, 1);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_CONFIG, 1);
|
||||
|
||||
dev_info(&client->dev, "cold start: config was 0x%02x "
|
||||
"mode %u\n", conf, mode);
|
||||
|
@ -704,25 +699,25 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
|
|||
|
||||
for (i = 0; i < 6; i++) /* read voltages */
|
||||
{
|
||||
data->in[i] = adm9240_read_value(client,
|
||||
data->in[i] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_IN(i));
|
||||
}
|
||||
data->alarms = adm9240_read_value(client,
|
||||
data->alarms = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_INT(0)) |
|
||||
adm9240_read_value(client,
|
||||
i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_INT(1)) << 8;
|
||||
|
||||
/* read temperature: assume temperature changes less than
|
||||
* 0.5'C per two measurement cycles thus ignore possible
|
||||
* but unlikely aliasing error on lsb reading. --Grant */
|
||||
data->temp = ((adm9240_read_value(client,
|
||||
data->temp = ((i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_TEMP) << 8) |
|
||||
adm9240_read_value(client,
|
||||
i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_TEMP_CONF)) / 128;
|
||||
|
||||
for (i = 0; i < 2; i++) /* read fans */
|
||||
{
|
||||
data->fan[i] = adm9240_read_value(client,
|
||||
data->fan[i] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_FAN(i));
|
||||
|
||||
/* adjust fan clock divider on overflow */
|
||||
|
@ -747,30 +742,30 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
|
|||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
data->in_min[i] = adm9240_read_value(client,
|
||||
data->in_min[i] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_IN_MIN(i));
|
||||
data->in_max[i] = adm9240_read_value(client,
|
||||
data->in_max[i] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_IN_MAX(i));
|
||||
}
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
data->fan_min[i] = adm9240_read_value(client,
|
||||
data->fan_min[i] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_FAN_MIN(i));
|
||||
}
|
||||
data->temp_high = adm9240_read_value(client,
|
||||
ADM9240_REG_TEMP_HIGH);
|
||||
data->temp_hyst = adm9240_read_value(client,
|
||||
ADM9240_REG_TEMP_HYST);
|
||||
data->temp_max[0] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_TEMP_MAX(0));
|
||||
data->temp_max[1] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_TEMP_MAX(1));
|
||||
|
||||
/* read fan divs and 5-bit VID */
|
||||
i = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
|
||||
i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
|
||||
data->fan_div[0] = (i >> 4) & 3;
|
||||
data->fan_div[1] = (i >> 6) & 3;
|
||||
data->vid = i & 0x0f;
|
||||
data->vid |= (adm9240_read_value(client,
|
||||
data->vid |= (i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_VID4) & 1) << 4;
|
||||
/* read analog out */
|
||||
data->aout = adm9240_read_value(client,
|
||||
data->aout = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_ANALOG_OUT);
|
||||
|
||||
data->last_updated_config = jiffies;
|
||||
|
|
|
@ -629,19 +629,17 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
|
|||
int i, id, err;
|
||||
struct asb100_data *data = i2c_get_clientdata(new_client);
|
||||
|
||||
data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
if (!(data->lm75[0])) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR_SC_0;
|
||||
}
|
||||
memset(data->lm75[0], 0x00, sizeof(struct i2c_client));
|
||||
|
||||
data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
if (!(data->lm75[1])) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR_SC_1;
|
||||
}
|
||||
memset(data->lm75[1], 0x00, sizeof(struct i2c_client));
|
||||
|
||||
id = i2c_adapter_id(adapter);
|
||||
|
||||
|
@ -724,12 +722,11 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access asb100_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
|
||||
pr_debug("asb100.o: detect failed, kmalloc failed!\n");
|
||||
if (!(data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
|
||||
pr_debug("asb100.o: detect failed, kzalloc failed!\n");
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
memset(data, 0, sizeof(struct asb100_data));
|
||||
|
||||
new_client = &data->client;
|
||||
init_MUTEX(&data->lock);
|
||||
|
|
|
@ -253,6 +253,8 @@ static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
|
|||
|
||||
static int atxp1_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_probe(adapter, &addr_data, &atxp1_detect);
|
||||
};
|
||||
|
||||
|
@ -266,12 +268,11 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(data, 0, sizeof(struct atxp1_data));
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
||||
|
|
|
@ -180,12 +180,14 @@ static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
|
|||
|
||||
static int ds1621_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_probe(adapter, &addr_data, ds1621_detect);
|
||||
}
|
||||
|
||||
/* This function is called by i2c_probe */
|
||||
int ds1621_detect(struct i2c_adapter *adapter, int address,
|
||||
int kind)
|
||||
static int ds1621_detect(struct i2c_adapter *adapter, int address,
|
||||
int kind)
|
||||
{
|
||||
int conf, temp;
|
||||
struct i2c_client *new_client;
|
||||
|
@ -200,11 +202,10 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
|
|||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access ds1621_{read,write}_value. */
|
||||
if (!(data = kmalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct ds1621_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -303,11 +303,10 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
/* 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 i2c_smbus_read_byte_data. */
|
||||
if (!(data = kmalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct fscher_data));
|
||||
|
||||
/* The common I2C client data is placed right before the
|
||||
* Hermes-specific data. */
|
||||
|
|
|
@ -438,7 +438,7 @@ static int fscpos_attach_adapter(struct i2c_adapter *adapter)
|
|||
return i2c_probe(adapter, &addr_data, fscpos_detect);
|
||||
}
|
||||
|
||||
int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
struct fscpos_data *data;
|
||||
|
@ -453,11 +453,10 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
* But it allows us to access fscpos_{read,write}_value.
|
||||
*/
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct fscpos_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -365,11 +365,10 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access gl518_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct gl518_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -536,11 +536,10 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access gl520_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct gl520_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
it87.c - Part of lm_sensors, Linux kernel modules for hardware
|
||||
monitoring.
|
||||
|
||||
Supports: IT8705F Super I/O chip w/LPC interface & SMBus
|
||||
Supports: IT8705F Super I/O chip w/LPC interface
|
||||
IT8712F Super I/O chip w/LPC interface & SMBus
|
||||
Sis950 A clone of the IT8705F
|
||||
|
||||
|
@ -47,7 +47,7 @@
|
|||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
|
||||
0x2e, 0x2f, I2C_CLIENT_END };
|
||||
static unsigned short isa_address = 0x290;
|
||||
static unsigned short isa_address;
|
||||
|
||||
/* Insmod parameters */
|
||||
I2C_CLIENT_INSMOD_2(it87, it8712);
|
||||
|
@ -706,7 +706,7 @@ static int it87_isa_attach_adapter(struct i2c_adapter *adapter)
|
|||
}
|
||||
|
||||
/* SuperIO detection - will change isa_address if a chip is found */
|
||||
static int __init it87_find(int *address)
|
||||
static int __init it87_find(unsigned short *address)
|
||||
{
|
||||
int err = -ENODEV;
|
||||
|
||||
|
@ -738,7 +738,7 @@ static int __init it87_find(int *address)
|
|||
}
|
||||
|
||||
/* This function is called by i2c_probe */
|
||||
int it87_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
int i;
|
||||
struct i2c_client *new_client;
|
||||
|
@ -757,42 +757,14 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!request_region(address, IT87_EXTENT, it87_isa_driver.name))
|
||||
goto ERROR0;
|
||||
|
||||
/* Probe whether there is anything available on this address. Already
|
||||
done for SMBus and Super-I/O clients */
|
||||
if (kind < 0) {
|
||||
if (is_isa && !chip_type) {
|
||||
#define REALLY_SLOW_IO
|
||||
/* We need the timeouts for at least some IT87-like chips. But only
|
||||
if we read 'undefined' registers. */
|
||||
i = inb_p(address + 1);
|
||||
if (inb_p(address + 2) != i
|
||||
|| inb_p(address + 3) != i
|
||||
|| inb_p(address + 7) != i) {
|
||||
err = -ENODEV;
|
||||
goto ERROR1;
|
||||
}
|
||||
#undef REALLY_SLOW_IO
|
||||
|
||||
/* Let's just hope nothing breaks here */
|
||||
i = inb_p(address + 5) & 0x7f;
|
||||
outb_p(~i & 0x7f, address + 5);
|
||||
if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
|
||||
outb_p(i, address + 5);
|
||||
err = -ENODEV;
|
||||
goto ERROR1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
/* For now, we presume we have a valid client. We create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access it87_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct it87_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR1;
|
||||
}
|
||||
memset(data, 0, sizeof(struct it87_data));
|
||||
|
||||
new_client = &data->client;
|
||||
if (is_isa)
|
||||
|
@ -1182,20 +1154,18 @@ static struct it87_data *it87_update_device(struct device *dev)
|
|||
|
||||
static int __init sm_it87_init(void)
|
||||
{
|
||||
int addr, res;
|
||||
|
||||
if (!it87_find(&addr)) {
|
||||
isa_address = addr;
|
||||
}
|
||||
int res;
|
||||
|
||||
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;
|
||||
if (!it87_find(&isa_address)) {
|
||||
res = i2c_isa_add_driver(&it87_isa_driver);
|
||||
if (res) {
|
||||
i2c_del_driver(&it87_driver);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -375,11 +375,10 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct lm63_data));
|
||||
|
||||
/* The common I2C client data is placed right before the
|
||||
LM63-specific data. */
|
||||
|
|
|
@ -127,11 +127,10 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
/* 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 lm75_{read,write}_value. */
|
||||
if (!(data = kmalloc(sizeof(struct lm75_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct lm75_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct lm75_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -226,11 +226,10 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
/* 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 lm77_{read,write}_value. */
|
||||
if (!(data = kmalloc(sizeof(struct lm77_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct lm77_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -480,7 +480,7 @@ static int lm78_isa_attach_adapter(struct i2c_adapter *adapter)
|
|||
}
|
||||
|
||||
/* This function is called by i2c_probe */
|
||||
int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
int i, err;
|
||||
struct i2c_client *new_client;
|
||||
|
@ -540,11 +540,10 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access lm78_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR1;
|
||||
}
|
||||
memset(data, 0, sizeof(struct lm78_data));
|
||||
|
||||
new_client = &data->client;
|
||||
if (is_isa)
|
||||
|
@ -726,7 +725,6 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
|
|||
return i2c_smbus_write_byte_data(client, reg, value);
|
||||
}
|
||||
|
||||
/* Called when we have found a new LM78. It should set limits, etc. */
|
||||
static void lm78_init_client(struct i2c_client *client)
|
||||
{
|
||||
u8 config = lm78_read_value(client, LM78_REG_CONFIG);
|
||||
|
|
|
@ -393,7 +393,7 @@ static int lm80_attach_adapter(struct i2c_adapter *adapter)
|
|||
return i2c_probe(adapter, &addr_data, lm80_detect);
|
||||
}
|
||||
|
||||
int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
int i, cur;
|
||||
struct i2c_client *new_client;
|
||||
|
@ -407,11 +407,10 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access lm80_{read,write}_value. */
|
||||
if (!(data = kmalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct lm80_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -230,11 +230,10 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct lm83_data));
|
||||
|
||||
/* The common I2C client data is placed right after the
|
||||
* LM83-specific data. */
|
||||
|
|
|
@ -1007,14 +1007,14 @@ temp_auto(1);
|
|||
temp_auto(2);
|
||||
temp_auto(3);
|
||||
|
||||
int lm85_attach_adapter(struct i2c_adapter *adapter)
|
||||
static int lm85_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
return i2c_probe(adapter, &addr_data, lm85_detect);
|
||||
}
|
||||
|
||||
int lm85_detect(struct i2c_adapter *adapter, int address,
|
||||
static int lm85_detect(struct i2c_adapter *adapter, int address,
|
||||
int kind)
|
||||
{
|
||||
int company, verstep ;
|
||||
|
@ -1033,11 +1033,10 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access lm85_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
memset(data, 0, sizeof(struct lm85_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
@ -1236,7 +1235,7 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
|
|||
return err;
|
||||
}
|
||||
|
||||
int lm85_detach_client(struct i2c_client *client)
|
||||
static int lm85_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm85_data *data = i2c_get_clientdata(client);
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
|
@ -1246,7 +1245,7 @@ int lm85_detach_client(struct i2c_client *client)
|
|||
}
|
||||
|
||||
|
||||
int lm85_read_value(struct i2c_client *client, u8 reg)
|
||||
static int lm85_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
@ -1276,7 +1275,7 @@ int lm85_read_value(struct i2c_client *client, u8 reg)
|
|||
return res ;
|
||||
}
|
||||
|
||||
int lm85_write_value(struct i2c_client *client, u8 reg, int value)
|
||||
static int lm85_write_value(struct i2c_client *client, u8 reg, int value)
|
||||
{
|
||||
int res ;
|
||||
|
||||
|
@ -1305,7 +1304,7 @@ int lm85_write_value(struct i2c_client *client, u8 reg, int value)
|
|||
return res ;
|
||||
}
|
||||
|
||||
void lm85_init_client(struct i2c_client *client)
|
||||
static void lm85_init_client(struct i2c_client *client)
|
||||
{
|
||||
int value;
|
||||
struct lm85_data *data = i2c_get_clientdata(client);
|
||||
|
|
|
@ -554,11 +554,10 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct lm87_data));
|
||||
|
||||
/* The common I2C client data is placed right before the
|
||||
LM87-specific data. */
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
* Devices. That chip is similar to the LM90, with a few differences
|
||||
* that are not handled by this driver. Complete datasheet can be
|
||||
* obtained from Analog's website at:
|
||||
* http://products.analog.com/products/info.asp?product=ADM1032
|
||||
* http://www.analog.com/en/prod/0,2877,ADM1032,00.html
|
||||
* Among others, it has a higher accuracy than the LM90, much like the
|
||||
* LM86 does.
|
||||
*
|
||||
|
@ -49,7 +49,7 @@
|
|||
* register values are decoded differently) it is ignored by this
|
||||
* driver. Complete datasheet can be obtained from Analog's website
|
||||
* at:
|
||||
* http://products.analog.com/products/info.asp?product=ADT7461
|
||||
* http://www.analog.com/en/prod/0,2877,ADT7461,00.html
|
||||
*
|
||||
* Since the LM90 was the first chipset supported by this driver, most
|
||||
* comments will refer to this chipset, but are actually general and
|
||||
|
@ -83,10 +83,10 @@
|
|||
* Addresses to scan
|
||||
* Address is fully defined internally and cannot be changed except for
|
||||
* MAX6659.
|
||||
* LM86, LM89, LM90, LM99, ADM1032, MAX6657 and MAX6658 have address 0x4c.
|
||||
* LM89-1, and LM99-1 have address 0x4d.
|
||||
* LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6657 and MAX6658
|
||||
* have address 0x4c.
|
||||
* ADM1032-2, ADT7461-2, LM89-1, and LM99-1 have address 0x4d.
|
||||
* MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
|
||||
* ADT7461 always has address 0x4c.
|
||||
*/
|
||||
|
||||
static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
|
||||
|
@ -345,10 +345,74 @@ static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
|
|||
static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
|
||||
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
|
||||
|
||||
/* pec used for ADM1032 only */
|
||||
static ssize_t show_pec(struct device *dev, struct device_attribute *dummy,
|
||||
char *buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
return sprintf(buf, "%d\n", !!(client->flags & I2C_CLIENT_PEC));
|
||||
}
|
||||
|
||||
static ssize_t set_pec(struct device *dev, struct device_attribute *dummy,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
long val = simple_strtol(buf, NULL, 10);
|
||||
|
||||
switch (val) {
|
||||
case 0:
|
||||
client->flags &= ~I2C_CLIENT_PEC;
|
||||
break;
|
||||
case 1:
|
||||
client->flags |= I2C_CLIENT_PEC;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec);
|
||||
|
||||
/*
|
||||
* Real code
|
||||
*/
|
||||
|
||||
/* The ADM1032 supports PEC but not on write byte transactions, so we need
|
||||
to explicitely ask for a transaction without PEC. */
|
||||
static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value)
|
||||
{
|
||||
return i2c_smbus_xfer(client->adapter, client->addr,
|
||||
client->flags & ~I2C_CLIENT_PEC,
|
||||
I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
|
||||
}
|
||||
|
||||
/* It is assumed that client->update_lock is held (unless we are in
|
||||
detection or initialization steps). This matters when PEC is enabled,
|
||||
because we don't want the address pointer to change between the write
|
||||
byte and the read byte transactions. */
|
||||
static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (client->flags & I2C_CLIENT_PEC) {
|
||||
err = adm1032_write_byte(client, reg);
|
||||
if (err >= 0)
|
||||
err = i2c_smbus_read_byte(client);
|
||||
} else
|
||||
err = i2c_smbus_read_byte_data(client, reg);
|
||||
|
||||
if (err < 0) {
|
||||
dev_warn(&client->dev, "Register %#02x read failed (%d)\n",
|
||||
reg, err);
|
||||
return err;
|
||||
}
|
||||
*value = err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm90_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
|
@ -370,11 +434,10 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct lm90_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct lm90_data));
|
||||
|
||||
/* The common I2C client data is placed right before the
|
||||
LM90-specific data. */
|
||||
|
@ -403,20 +466,22 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (kind < 0) { /* detection and identification */
|
||||
u8 man_id, chip_id, reg_config1, reg_convrate;
|
||||
|
||||
man_id = i2c_smbus_read_byte_data(new_client,
|
||||
LM90_REG_R_MAN_ID);
|
||||
chip_id = i2c_smbus_read_byte_data(new_client,
|
||||
LM90_REG_R_CHIP_ID);
|
||||
reg_config1 = i2c_smbus_read_byte_data(new_client,
|
||||
LM90_REG_R_CONFIG1);
|
||||
reg_convrate = i2c_smbus_read_byte_data(new_client,
|
||||
LM90_REG_R_CONVRATE);
|
||||
if (lm90_read_reg(new_client, LM90_REG_R_MAN_ID,
|
||||
&man_id) < 0
|
||||
|| lm90_read_reg(new_client, LM90_REG_R_CHIP_ID,
|
||||
&chip_id) < 0
|
||||
|| lm90_read_reg(new_client, LM90_REG_R_CONFIG1,
|
||||
®_config1) < 0
|
||||
|| lm90_read_reg(new_client, LM90_REG_R_CONVRATE,
|
||||
®_convrate) < 0)
|
||||
goto exit_free;
|
||||
|
||||
if (man_id == 0x01) { /* National Semiconductor */
|
||||
u8 reg_config2;
|
||||
|
||||
reg_config2 = i2c_smbus_read_byte_data(new_client,
|
||||
LM90_REG_R_CONFIG2);
|
||||
if (lm90_read_reg(new_client, LM90_REG_R_CONFIG2,
|
||||
®_config2) < 0)
|
||||
goto exit_free;
|
||||
|
||||
if ((reg_config1 & 0x2A) == 0x00
|
||||
&& (reg_config2 & 0xF8) == 0x00
|
||||
|
@ -435,14 +500,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
}
|
||||
} else
|
||||
if (man_id == 0x41) { /* Analog Devices */
|
||||
if (address == 0x4C
|
||||
&& (chip_id & 0xF0) == 0x40 /* ADM1032 */
|
||||
if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
|
||||
&& (reg_config1 & 0x3F) == 0x00
|
||||
&& reg_convrate <= 0x0A) {
|
||||
kind = adm1032;
|
||||
} else
|
||||
if (address == 0x4c
|
||||
&& chip_id == 0x51 /* ADT7461 */
|
||||
if (chip_id == 0x51 /* ADT7461 */
|
||||
&& (reg_config1 & 0x1F) == 0x00 /* check compat mode */
|
||||
&& reg_convrate <= 0x0A) {
|
||||
kind = adt7461;
|
||||
|
@ -477,6 +540,10 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
name = "lm90";
|
||||
} else if (kind == adm1032) {
|
||||
name = "adm1032";
|
||||
/* The ADM1032 supports PEC, but only if combined
|
||||
transactions are not used. */
|
||||
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
|
||||
new_client->flags |= I2C_CLIENT_PEC;
|
||||
} else if (kind == lm99) {
|
||||
name = "lm99";
|
||||
} else if (kind == lm86) {
|
||||
|
@ -529,6 +596,9 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
&sensor_dev_attr_temp2_crit_hyst.dev_attr);
|
||||
device_create_file(&new_client->dev, &dev_attr_alarms);
|
||||
|
||||
if (new_client->flags & I2C_CLIENT_PEC)
|
||||
device_create_file(&new_client->dev, &dev_attr_pec);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
|
@ -548,7 +618,10 @@ static void lm90_init_client(struct i2c_client *client)
|
|||
*/
|
||||
i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
|
||||
5); /* 2 Hz */
|
||||
config = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG1);
|
||||
if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) {
|
||||
dev_warn(&client->dev, "Initialization failed!\n");
|
||||
return;
|
||||
}
|
||||
if (config & 0x40)
|
||||
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
|
||||
config & 0xBF); /* run */
|
||||
|
@ -576,21 +649,15 @@ static struct lm90_data *lm90_update_device(struct device *dev)
|
|||
down(&data->update_lock);
|
||||
|
||||
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
|
||||
u8 oldh, newh;
|
||||
u8 oldh, newh, l;
|
||||
|
||||
dev_dbg(&client->dev, "Updating lm90 data.\n");
|
||||
data->temp8[0] = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_LOCAL_TEMP);
|
||||
data->temp8[1] = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_LOCAL_LOW);
|
||||
data->temp8[2] = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_LOCAL_HIGH);
|
||||
data->temp8[3] = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_LOCAL_CRIT);
|
||||
data->temp8[4] = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_REMOTE_CRIT);
|
||||
data->temp_hyst = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_TCRIT_HYST);
|
||||
lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, &data->temp8[0]);
|
||||
lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[1]);
|
||||
lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[2]);
|
||||
lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[3]);
|
||||
lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[4]);
|
||||
lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
|
||||
|
||||
/*
|
||||
* There is a trick here. We have to read two registers to
|
||||
|
@ -606,36 +673,20 @@ static struct lm90_data *lm90_update_device(struct device *dev)
|
|||
* then we have a valid reading. Else we have to read the low
|
||||
* byte again, and now we believe we have a correct reading.
|
||||
*/
|
||||
oldh = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_REMOTE_TEMPH);
|
||||
data->temp11[0] = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_REMOTE_TEMPL);
|
||||
newh = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_REMOTE_TEMPH);
|
||||
if (newh != oldh) {
|
||||
data->temp11[0] = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_REMOTE_TEMPL);
|
||||
#ifdef DEBUG
|
||||
oldh = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_REMOTE_TEMPH);
|
||||
/* oldh is actually newer */
|
||||
if (newh != oldh)
|
||||
dev_warn(&client->dev, "Remote temperature may be "
|
||||
"wrong.\n");
|
||||
#endif
|
||||
}
|
||||
data->temp11[0] |= (newh << 8);
|
||||
if (lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPH, &oldh) == 0
|
||||
&& lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPL, &l) == 0
|
||||
&& lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPH, &newh) == 0
|
||||
&& (newh == oldh
|
||||
|| lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPL, &l) == 0))
|
||||
data->temp11[0] = (newh << 8) | l;
|
||||
|
||||
data->temp11[1] = (i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_REMOTE_LOWH) << 8) +
|
||||
i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_REMOTE_LOWL);
|
||||
data->temp11[2] = (i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_REMOTE_HIGHH) << 8) +
|
||||
i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_REMOTE_HIGHL);
|
||||
data->alarms = i2c_smbus_read_byte_data(client,
|
||||
LM90_REG_R_STATUS);
|
||||
if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &newh) == 0
|
||||
&& lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL, &l) == 0)
|
||||
data->temp11[1] = (newh << 8) | l;
|
||||
if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &newh) == 0
|
||||
&& lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, &l) == 0)
|
||||
data->temp11[2] = (newh << 8) | l;
|
||||
lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
|
|
|
@ -300,11 +300,10 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
| I2C_FUNC_SMBUS_WORD_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct lm92_data));
|
||||
|
||||
/* Fill in enough client fields so that we can read from the chip,
|
||||
which is required for identication */
|
||||
|
|
|
@ -197,11 +197,10 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct max1619_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct max1619_data));
|
||||
|
||||
/* The common I2C client data is placed right before the
|
||||
MAX1619-specific data. */
|
||||
|
|
|
@ -754,9 +754,8 @@ static int pc87360_detect(struct i2c_adapter *adapter)
|
|||
const char *name = "pc87360";
|
||||
int use_thermistors = 0;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
|
||||
if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
memset(data, 0x00, sizeof(struct pc87360_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -518,11 +518,10 @@ static int sis5595_detect(struct i2c_adapter *adapter)
|
|||
goto exit_release;
|
||||
}
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit_release;
|
||||
}
|
||||
memset(data, 0, sizeof(struct sis5595_data));
|
||||
|
||||
new_client = &data->client;
|
||||
new_client->addr = address;
|
||||
|
|
|
@ -244,11 +244,10 @@ static int smsc47b397_detect(struct i2c_adapter *adapter)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto error_release;
|
||||
}
|
||||
memset(data, 0x00, sizeof(struct smsc47b397_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
@ -299,7 +298,7 @@ static int __init smsc47b397_find(unsigned short *addr)
|
|||
superio_enter();
|
||||
id = superio_inb(SUPERIO_REG_DEVID);
|
||||
|
||||
if (id != 0x6f) {
|
||||
if ((id != 0x6f) && (id != 0x81)) {
|
||||
superio_exit();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -310,8 +309,9 @@ static int __init smsc47b397_find(unsigned short *addr)
|
|||
*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
|
||||
| superio_inb(SUPERIO_REG_BASE_LSB);
|
||||
|
||||
printk(KERN_INFO "smsc47b397: found SMSC LPC47B397-NC "
|
||||
"(base address 0x%04x, revision %u)\n", *addr, rev);
|
||||
printk(KERN_INFO "smsc47b397: found SMSC %s "
|
||||
"(base address 0x%04x, revision %u)\n",
|
||||
id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev);
|
||||
|
||||
superio_exit();
|
||||
return 0;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
for hardware monitoring
|
||||
|
||||
Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x,
|
||||
LPC47M15x and LPC47M192 Super-I/O chips.
|
||||
LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips.
|
||||
|
||||
Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
|
||||
|
@ -356,6 +356,8 @@ static int __init smsc47m1_find(unsigned short *addr)
|
|||
* 0x5F) and LPC47B27x (device id 0x51) have fan control.
|
||||
* The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
|
||||
* can do much more besides (device id 0x60).
|
||||
* The LPC47M997 is undocumented, but seems to be compatible with
|
||||
* the LPC47M192, and has the same device id.
|
||||
*/
|
||||
if (val == 0x51)
|
||||
printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
|
||||
|
@ -364,7 +366,8 @@ static int __init smsc47m1_find(unsigned short *addr)
|
|||
else if (val == 0x5F)
|
||||
printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
|
||||
else if (val == 0x60)
|
||||
printk(KERN_INFO "smsc47m1: Found SMSC LPC47M15x/LPC47M192\n");
|
||||
printk(KERN_INFO "smsc47m1: Found SMSC "
|
||||
"LPC47M15x/LPC47M192/LPC47M997\n");
|
||||
else {
|
||||
superio_exit();
|
||||
return -ENODEV;
|
||||
|
@ -396,11 +399,10 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto error_release;
|
||||
}
|
||||
memset(data, 0x00, sizeof(struct smsc47m1_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
/* If force_addr is set to anything different from 0, we forcibly enable
|
||||
the device at the given address. */
|
||||
static unsigned short force_addr = 0;
|
||||
static unsigned short force_addr;
|
||||
module_param(force_addr, ushort, 0);
|
||||
MODULE_PARM_DESC(force_addr,
|
||||
"Initialize the base address of the sensors");
|
||||
|
@ -198,7 +198,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
|||
but the function is very linear in the useful range (0-80 deg C), so
|
||||
we'll just use linear interpolation for 10-bit readings.) So, tempLUT
|
||||
is the temp at via register values 0-255: */
|
||||
static const long tempLUT[] =
|
||||
static const s16 tempLUT[] =
|
||||
{ -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
|
||||
-503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
|
||||
-362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
|
||||
|
@ -270,7 +270,7 @@ static inline u8 TEMP_TO_REG(long val)
|
|||
}
|
||||
|
||||
/* for 8-bit temperature hyst and over registers */
|
||||
#define TEMP_FROM_REG(val) (tempLUT[(val)] * 100)
|
||||
#define TEMP_FROM_REG(val) ((long)tempLUT[val] * 100)
|
||||
|
||||
/* for 10-bit temperature readings */
|
||||
static inline long TEMP_FROM_REG10(u16 val)
|
||||
|
@ -589,10 +589,8 @@ static int via686a_detect(struct i2c_adapter *adapter)
|
|||
u16 val;
|
||||
|
||||
/* 8231 requires multiple of 256, we enforce that on 686 as well */
|
||||
if (force_addr)
|
||||
address = force_addr & 0xFF00;
|
||||
|
||||
if (force_addr) {
|
||||
address = force_addr & 0xFF00;
|
||||
dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
|
||||
address);
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
|
@ -603,11 +601,17 @@ static int via686a_detect(struct i2c_adapter *adapter)
|
|||
pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
|
||||
return -ENODEV;
|
||||
if (!(val & 0x0001)) {
|
||||
dev_warn(&adapter->dev, "enabling sensors\n");
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
|
||||
val | 0x0001))
|
||||
if (force_addr) {
|
||||
dev_info(&adapter->dev, "enabling sensors\n");
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
|
||||
val | 0x0001))
|
||||
return -ENODEV;
|
||||
} else {
|
||||
dev_warn(&adapter->dev, "sensors disabled - enable "
|
||||
"with force_addr=0x%x\n", address);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reserve the ISA region */
|
||||
|
@ -617,11 +621,10 @@ static int via686a_detect(struct i2c_adapter *adapter)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit_release;
|
||||
}
|
||||
memset(data, 0, sizeof(struct via686a_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
@ -708,7 +711,6 @@ static int via686a_detach_client(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Called when we have found a new VIA686A. Set limits, etc. */
|
||||
static void via686a_init_client(struct i2c_client *client)
|
||||
{
|
||||
u8 reg;
|
||||
|
|
|
@ -105,7 +105,9 @@ superio_exit(void)
|
|||
* ISA constants
|
||||
*/
|
||||
|
||||
#define REGION_LENGTH 8
|
||||
#define REGION_ALIGNMENT ~7
|
||||
#define REGION_OFFSET 5
|
||||
#define REGION_LENGTH 2
|
||||
#define ADDR_REG_OFFSET 5
|
||||
#define DATA_REG_OFFSET 6
|
||||
|
||||
|
@ -673,16 +675,16 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
|
|||
struct w83627ehf_data *data;
|
||||
int i, err = 0;
|
||||
|
||||
if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
|
||||
if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
|
||||
w83627ehf_driver.name)) {
|
||||
err = -EBUSY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit_release;
|
||||
}
|
||||
memset(data, 0, sizeof(struct w83627ehf_data));
|
||||
|
||||
client = &data->client;
|
||||
i2c_set_clientdata(client, data);
|
||||
|
@ -762,7 +764,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
|
|||
exit_free:
|
||||
kfree(data);
|
||||
exit_release:
|
||||
release_region(address, REGION_LENGTH);
|
||||
release_region(address + REGION_OFFSET, REGION_LENGTH);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
@ -776,7 +778,7 @@ static int w83627ehf_detach_client(struct i2c_client *client)
|
|||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
release_region(client->addr, REGION_LENGTH);
|
||||
release_region(client->addr + REGION_OFFSET, REGION_LENGTH);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
|
@ -807,7 +809,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
|
|||
superio_select(W83627EHF_LD_HWM);
|
||||
val = (superio_inb(SIO_REG_ADDR) << 8)
|
||||
| superio_inb(SIO_REG_ADDR + 1);
|
||||
*addr = val & ~(REGION_LENGTH - 1);
|
||||
*addr = val & REGION_ALIGNMENT;
|
||||
if (*addr == 0) {
|
||||
superio_exit();
|
||||
return -ENODEV;
|
||||
|
|
|
@ -142,10 +142,14 @@ superio_exit(void)
|
|||
#define WINB_BASE_REG 0x60
|
||||
/* Constants specified below */
|
||||
|
||||
/* Length of ISA address segment */
|
||||
#define WINB_EXTENT 8
|
||||
/* Alignment of the base address */
|
||||
#define WINB_ALIGNMENT ~7
|
||||
|
||||
/* Where are the ISA address/data registers relative to the base address */
|
||||
/* Offset & size of I/O region we are interested in */
|
||||
#define WINB_REGION_OFFSET 5
|
||||
#define WINB_REGION_SIZE 2
|
||||
|
||||
/* Where are the sensors address/data registers relative to the base address */
|
||||
#define W83781D_ADDR_REG_OFFSET 5
|
||||
#define W83781D_DATA_REG_OFFSET 6
|
||||
|
||||
|
@ -197,7 +201,6 @@ superio_exit(void)
|
|||
|
||||
#define W83627HF_REG_PWM1 0x5A
|
||||
#define W83627HF_REG_PWM2 0x5B
|
||||
#define W83627HF_REG_PWMCLK12 0x5C
|
||||
|
||||
#define W83627THF_REG_PWM1 0x01 /* 697HF and 637HF too */
|
||||
#define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */
|
||||
|
@ -981,7 +984,7 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr)
|
|||
superio_select(W83627HF_LD_HWM);
|
||||
val = (superio_inb(WINB_BASE_REG) << 8) |
|
||||
superio_inb(WINB_BASE_REG + 1);
|
||||
*addr = val & ~(WINB_EXTENT - 1);
|
||||
*addr = val & WINB_ALIGNMENT;
|
||||
if (*addr == 0 && force_addr == 0) {
|
||||
superio_exit();
|
||||
return -ENODEV;
|
||||
|
@ -1000,9 +1003,10 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
|
|||
const char *client_name = "";
|
||||
|
||||
if(force_addr)
|
||||
address = force_addr & ~(WINB_EXTENT - 1);
|
||||
address = force_addr & WINB_ALIGNMENT;
|
||||
|
||||
if (!request_region(address, WINB_EXTENT, w83627hf_driver.name)) {
|
||||
if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE,
|
||||
w83627hf_driver.name)) {
|
||||
err = -EBUSY;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
@ -1041,11 +1045,10 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access w83627hf_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR1;
|
||||
}
|
||||
memset(data, 0, sizeof(struct w83627hf_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
@ -1148,7 +1151,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
|
|||
ERROR2:
|
||||
kfree(data);
|
||||
ERROR1:
|
||||
release_region(address, WINB_EXTENT);
|
||||
release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE);
|
||||
ERROR0:
|
||||
return err;
|
||||
}
|
||||
|
@ -1163,7 +1166,7 @@ static int w83627hf_detach_client(struct i2c_client *client)
|
|||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
release_region(client->addr, WINB_EXTENT);
|
||||
release_region(client->addr + WINB_REGION_OFFSET, WINB_REGION_SIZE);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
|
@ -1275,7 +1278,6 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Called when we have found a new W83781D. It should set limits, etc. */
|
||||
static void w83627hf_init_client(struct i2c_client *client)
|
||||
{
|
||||
struct w83627hf_data *data = i2c_get_clientdata(client);
|
||||
|
@ -1369,12 +1371,6 @@ static void w83627hf_init_client(struct i2c_client *client)
|
|||
}
|
||||
}
|
||||
|
||||
if (type == w83627hf) {
|
||||
/* enable PWM2 control (can't hurt since PWM reg
|
||||
should have been reset to 0xff) */
|
||||
w83627hf_write_value(client, W83627HF_REG_PWMCLK12,
|
||||
0x19);
|
||||
}
|
||||
/* enable comparator mode for temp2 and temp3 so
|
||||
alarm indication will work correctly */
|
||||
i = w83627hf_read_value(client, W83781D_REG_IRQ);
|
||||
|
|
|
@ -889,12 +889,11 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
|
|||
const char *client_name = "";
|
||||
struct w83781d_data *data = i2c_get_clientdata(new_client);
|
||||
|
||||
data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
if (!(data->lm75[0])) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR_SC_0;
|
||||
}
|
||||
memset(data->lm75[0], 0x00, sizeof (struct i2c_client));
|
||||
|
||||
id = i2c_adapter_id(adapter);
|
||||
|
||||
|
@ -919,13 +918,11 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
|
|||
}
|
||||
|
||||
if (kind != w83783s) {
|
||||
|
||||
data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
if (!(data->lm75[1])) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR_SC_1;
|
||||
}
|
||||
memset(data->lm75[1], 0x0, sizeof(struct i2c_client));
|
||||
|
||||
if (force_subclients[0] == id &&
|
||||
force_subclients[1] == address) {
|
||||
|
@ -1064,11 +1061,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access w83781d_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR1;
|
||||
}
|
||||
memset(data, 0, sizeof(struct w83781d_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
@ -1451,7 +1447,6 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Called when we have found a new W83781D. It should set limits, etc. */
|
||||
static void
|
||||
w83781d_init_client(struct i2c_client *client)
|
||||
{
|
||||
|
|
|
@ -1086,11 +1086,10 @@ w83792d_create_subclient(struct i2c_adapter *adapter,
|
|||
int err;
|
||||
struct i2c_client *sub_client;
|
||||
|
||||
(*sub_cli) = sub_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
(*sub_cli) = sub_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
if (!(sub_client)) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(sub_client, 0x00, sizeof(struct i2c_client));
|
||||
sub_client->addr = 0x48 + addr;
|
||||
i2c_set_clientdata(sub_client, NULL);
|
||||
sub_client->adapter = adapter;
|
||||
|
@ -1184,11 +1183,10 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access w83792d_{read,write}_value. */
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
memset(data, 0, sizeof(struct w83792d_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
@ -1429,7 +1427,6 @@ w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Called when we have found a new W83792D. It should set limits, etc. */
|
||||
static void
|
||||
w83792d_init_client(struct i2c_client *client)
|
||||
{
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* How many retries on register read error */
|
||||
|
@ -73,7 +74,7 @@ I2C_CLIENT_INSMOD_1(w83l785ts);
|
|||
* The W83L785TS-S uses signed 8-bit values.
|
||||
*/
|
||||
|
||||
#define TEMP_FROM_REG(val) ((val & 0x80 ? val-0x100 : val) * 1000)
|
||||
#define TEMP_FROM_REG(val) ((val) * 1000)
|
||||
|
||||
/*
|
||||
* Functions declaration
|
||||
|
@ -111,27 +112,24 @@ struct w83l785ts_data {
|
|||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
/* registers values */
|
||||
u8 temp, temp_over;
|
||||
s8 temp[2]; /* 0: input
|
||||
1: critical limit */
|
||||
};
|
||||
|
||||
/*
|
||||
* Sysfs stuff
|
||||
*/
|
||||
|
||||
static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct w83l785ts_data *data = w83l785ts_update_device(dev);
|
||||
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
|
||||
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
|
||||
}
|
||||
|
||||
static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct w83l785ts_data *data = w83l785ts_update_device(dev);
|
||||
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
|
||||
static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_over, NULL);
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1);
|
||||
|
||||
/*
|
||||
* Real code
|
||||
|
@ -158,12 +156,10 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct w83l785ts_data));
|
||||
|
||||
|
||||
/* The common I2C client data is placed right before the
|
||||
* W83L785TS-specific data. */
|
||||
|
@ -228,7 +224,7 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Default values in case the first read fails (unlikely). */
|
||||
data->temp_over = data->temp = 0;
|
||||
data->temp[1] = data->temp[0] = 0;
|
||||
|
||||
/* Tell the I2C layer a new client has arrived. */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
|
@ -246,8 +242,10 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_max);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_max.dev_attr);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -305,10 +303,10 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev)
|
|||
|
||||
if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) {
|
||||
dev_dbg(&client->dev, "Updating w83l785ts data.\n");
|
||||
data->temp = w83l785ts_read_value(client,
|
||||
W83L785TS_REG_TEMP, data->temp);
|
||||
data->temp_over = w83l785ts_read_value(client,
|
||||
W83L785TS_REG_TEMP_OVER, data->temp_over);
|
||||
data->temp[0] = w83l785ts_read_value(client,
|
||||
W83L785TS_REG_TEMP, data->temp[0]);
|
||||
data->temp[1] = w83l785ts_read_value(client,
|
||||
W83L785TS_REG_TEMP_OVER, data->temp[1]);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
|
||||
#define DEB3(fmt, args...) do { if (i2c_debug>=3) printk(fmt, ## args); } while(0)
|
||||
|
||||
static int i2c_debug=0;
|
||||
static int i2c_debug;
|
||||
|
||||
#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
|
||||
#define pca_inw(adap, reg) adap->read_byte(adap, reg)
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
/* module parameters:
|
||||
*/
|
||||
static int bit_scan=0; /* have a look at what's hanging 'round */
|
||||
static int bit_scan; /* have a look at what's hanging 'round */
|
||||
|
||||
|
||||
static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
|
||||
|
|
|
@ -135,11 +135,12 @@ config I2C_I810
|
|||
help
|
||||
If you say yes to this option, support will be included for the Intel
|
||||
810/815 family of mainboard I2C interfaces. Specifically, the
|
||||
following versions of the chipset is supported:
|
||||
following versions of the chipset are supported:
|
||||
i810AA
|
||||
i810AB
|
||||
i810E
|
||||
i815
|
||||
i845G
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called i2c-i810.
|
||||
|
|
|
@ -134,7 +134,7 @@
|
|||
/* -> Read = 1 */
|
||||
#define ALI1535_SMBIO_EN 0x04 /* SMB I/O Space enable */
|
||||
|
||||
|
||||
static struct pci_driver ali1535_driver;
|
||||
static unsigned short ali1535_smba;
|
||||
static DECLARE_MUTEX(i2c_ali1535_sem);
|
||||
|
||||
|
@ -162,7 +162,8 @@ static int ali1535_setup(struct pci_dev *dev)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE, "ali1535-smb")) {
|
||||
if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE,
|
||||
ali1535_driver.name)) {
|
||||
dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n",
|
||||
ali1535_smba);
|
||||
goto exit;
|
||||
|
@ -480,7 +481,6 @@ static struct i2c_adapter ali1535_adapter = {
|
|||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
.name = "unset",
|
||||
};
|
||||
|
||||
static struct pci_device_id ali1535_ids[] = {
|
||||
|
@ -513,6 +513,7 @@ static void __devexit ali1535_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver ali1535_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ali1535_smbus",
|
||||
.id_table = ali1535_ids,
|
||||
.probe = ali1535_probe,
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
|
||||
#define HST_CNTL2_SIZEMASK 0x38
|
||||
|
||||
static struct pci_driver ali1563_pci_driver;
|
||||
static unsigned short ali1563_smba;
|
||||
|
||||
static int ali1563_transaction(struct i2c_adapter * a, int size)
|
||||
|
@ -350,7 +351,8 @@ static int __devinit ali1563_setup(struct pci_dev * dev)
|
|||
dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
|
||||
goto Err;
|
||||
}
|
||||
if (!request_region(ali1563_smba,ALI1563_SMB_IOSIZE,"i2c-ali1563")) {
|
||||
if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
|
||||
ali1563_pci_driver.name)) {
|
||||
dev_warn(&dev->dev,"Could not allocate I/O space");
|
||||
goto Err;
|
||||
}
|
||||
|
@ -406,7 +408,8 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = {
|
|||
MODULE_DEVICE_TABLE (pci, ali1563_id_table);
|
||||
|
||||
static struct pci_driver ali1563_pci_driver = {
|
||||
.name = "ali1563_i2c",
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ali1563_smbus",
|
||||
.id_table = ali1563_id_table,
|
||||
.probe = ali1563_probe,
|
||||
.remove = __devexit_p(ali1563_remove),
|
||||
|
|
|
@ -125,12 +125,13 @@
|
|||
|
||||
/* If force_addr is set to anything different from 0, we forcibly enable
|
||||
the device at the given address. */
|
||||
static u16 force_addr = 0;
|
||||
static u16 force_addr;
|
||||
module_param(force_addr, ushort, 0);
|
||||
MODULE_PARM_DESC(force_addr,
|
||||
"Initialize the base address of the i2c controller");
|
||||
|
||||
static unsigned short ali15x3_smba = 0;
|
||||
static struct pci_driver ali15x3_driver;
|
||||
static unsigned short ali15x3_smba;
|
||||
|
||||
static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
|
||||
{
|
||||
|
@ -166,7 +167,8 @@ static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
|
|||
if(force_addr)
|
||||
ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
|
||||
|
||||
if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb")) {
|
||||
if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
|
||||
ali15x3_driver.name)) {
|
||||
dev_err(&ALI15X3_dev->dev,
|
||||
"ALI15X3_smb region 0x%x already in use!\n",
|
||||
ali15x3_smba);
|
||||
|
@ -470,7 +472,6 @@ static struct i2c_adapter ali15x3_adapter = {
|
|||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
.name = "unset",
|
||||
};
|
||||
|
||||
static struct pci_device_id ali15x3_ids[] = {
|
||||
|
@ -503,6 +504,7 @@ static void __devexit ali15x3_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver ali15x3_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ali15x3_smbus",
|
||||
.id_table = ali15x3_ids,
|
||||
.probe = ali15x3_probe,
|
||||
|
|
|
@ -169,12 +169,12 @@ static int __init amd756_s4882_init(void)
|
|||
init_MUTEX(&amd756_lock);
|
||||
|
||||
/* Define the 5 virtual adapters and algorithms structures */
|
||||
if (!(s4882_adapter = kmalloc(5 * sizeof(struct i2c_adapter),
|
||||
if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter),
|
||||
GFP_KERNEL))) {
|
||||
error = -ENOMEM;
|
||||
goto ERROR1;
|
||||
}
|
||||
if (!(s4882_algo = kmalloc(5 * sizeof(struct i2c_algorithm),
|
||||
if (!(s4882_algo = kzalloc(5 * sizeof(struct i2c_algorithm),
|
||||
GFP_KERNEL))) {
|
||||
error = -ENOMEM;
|
||||
goto ERROR2;
|
||||
|
|
|
@ -85,8 +85,8 @@
|
|||
#define AMD756_PROCESS_CALL 0x04
|
||||
#define AMD756_BLOCK_DATA 0x05
|
||||
|
||||
|
||||
static unsigned short amd756_ioport = 0;
|
||||
static struct pci_driver amd756_driver;
|
||||
static unsigned short amd756_ioport;
|
||||
|
||||
/*
|
||||
SMBUS event = I/O 28-29 bit 11
|
||||
|
@ -303,7 +303,6 @@ struct i2c_adapter amd756_smbus = {
|
|||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
.name = "unset",
|
||||
};
|
||||
|
||||
enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
|
||||
|
@ -365,7 +364,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
|
|||
amd756_ioport += SMB_ADDR_OFFSET;
|
||||
}
|
||||
|
||||
if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) {
|
||||
if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
|
||||
dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
|
||||
amd756_ioport);
|
||||
return -ENODEV;
|
||||
|
@ -402,6 +401,7 @@ static void __devexit amd756_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver amd756_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "amd756_smbus",
|
||||
.id_table = amd756_ids,
|
||||
.probe = amd756_probe,
|
||||
|
|
|
@ -30,6 +30,8 @@ struct amd_smbus {
|
|||
int size;
|
||||
};
|
||||
|
||||
static struct pci_driver amd8111_driver;
|
||||
|
||||
/*
|
||||
* AMD PCI control registers definitions.
|
||||
*/
|
||||
|
@ -242,7 +244,6 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
|
|||
break;
|
||||
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL:
|
||||
protocol |= pec;
|
||||
len = min_t(u8, data->block[0], 31);
|
||||
amd_ec_write(smbus, AMD_SMB_CMD, command);
|
||||
amd_ec_write(smbus, AMD_SMB_BCNT, len);
|
||||
|
@ -252,13 +253,6 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
|
|||
read_write = I2C_SMBUS_READ;
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_WORD_DATA_PEC:
|
||||
case I2C_SMBUS_BLOCK_DATA_PEC:
|
||||
case I2C_SMBUS_PROC_CALL_PEC:
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
|
||||
dev_warn(&adap->dev, "Unexpected software PEC transaction %d\n.", size);
|
||||
return -1;
|
||||
|
||||
default:
|
||||
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
|
||||
return -1;
|
||||
|
@ -343,16 +337,15 @@ static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_
|
|||
if (~pci_resource_flags(dev, 0) & IORESOURCE_IO)
|
||||
return -ENODEV;
|
||||
|
||||
smbus = kmalloc(sizeof(struct amd_smbus), GFP_KERNEL);
|
||||
smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL);
|
||||
if (!smbus)
|
||||
return -ENOMEM;
|
||||
memset(smbus, 0, sizeof(struct amd_smbus));
|
||||
|
||||
smbus->dev = dev;
|
||||
smbus->base = pci_resource_start(dev, 0);
|
||||
smbus->size = pci_resource_len(dev, 0);
|
||||
|
||||
if (!request_region(smbus->base, smbus->size, "amd8111 SMBus 2.0"))
|
||||
if (!request_region(smbus->base, smbus->size, amd8111_driver.name))
|
||||
goto out_kfree;
|
||||
|
||||
smbus->adapter.owner = THIS_MODULE;
|
||||
|
@ -391,6 +384,7 @@ static void __devexit amd8111_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver amd8111_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "amd8111_smbus2",
|
||||
.id_table = amd8111_ids,
|
||||
.probe = amd8111_probe,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
|
||||
Frodo Looijaard <frodol@dds.nl> */
|
||||
|
||||
/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
|
||||
/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
|
||||
for Alpha Processor Inc. UP-2000(+) boards */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -46,12 +46,14 @@
|
|||
#define DEFAULT_BASE 0x330
|
||||
|
||||
static int base;
|
||||
static u8 __iomem *base_iomem;
|
||||
|
||||
static int irq;
|
||||
static int clock = 0x1c;
|
||||
static int own = 0x55;
|
||||
static int mmapped;
|
||||
|
||||
/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
|
||||
/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
|
||||
this module in real supports only one device, due to missing arguments
|
||||
in some functions, called from the algo-pcf module. Sometimes it's
|
||||
need to be rewriten - but for now just remove this for simpler reading */
|
||||
|
@ -60,40 +62,33 @@ static wait_queue_head_t pcf_wait;
|
|||
static int pcf_pending;
|
||||
static spinlock_t lock;
|
||||
|
||||
static struct i2c_adapter pcf_isa_ops;
|
||||
|
||||
/* ----- local functions ---------------------------------------------- */
|
||||
|
||||
static void pcf_isa_setbyte(void *data, int ctl, int val)
|
||||
{
|
||||
int address = ctl ? (base + 1) : base;
|
||||
u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
|
||||
|
||||
/* enable irq if any specified for serial operation */
|
||||
if (ctl && irq && (val & I2C_PCF_ESO)) {
|
||||
val |= I2C_PCF_ENI;
|
||||
}
|
||||
|
||||
pr_debug("i2c-elektor: Write 0x%X 0x%02X\n", address, val & 255);
|
||||
|
||||
switch (mmapped) {
|
||||
case 0: /* regular I/O */
|
||||
outb(val, address);
|
||||
break;
|
||||
case 2: /* double mapped I/O needed for UP2000 board,
|
||||
I don't know why this... */
|
||||
writeb(val, (void *)address);
|
||||
/* fall */
|
||||
case 1: /* memory mapped I/O */
|
||||
writeb(val, (void *)address);
|
||||
break;
|
||||
}
|
||||
pr_debug("%s: Write %p 0x%02X\n", pcf_isa_ops.name, address, val);
|
||||
iowrite8(val, address);
|
||||
#ifdef __alpha__
|
||||
/* API UP2000 needs some hardware fudging to make the write stick */
|
||||
iowrite8(val, address);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int pcf_isa_getbyte(void *data, int ctl)
|
||||
{
|
||||
int address = ctl ? (base + 1) : base;
|
||||
int val = mmapped ? readb((void *)address) : inb(address);
|
||||
|
||||
pr_debug("i2c-elektor: Read 0x%X 0x%02X\n", address, val);
|
||||
u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
|
||||
int val = ioread8(address);
|
||||
|
||||
pr_debug("%s: Read %p 0x%02X\n", pcf_isa_ops.name, address, val);
|
||||
return (val);
|
||||
}
|
||||
|
||||
|
@ -149,16 +144,40 @@ static int pcf_isa_init(void)
|
|||
{
|
||||
spin_lock_init(&lock);
|
||||
if (!mmapped) {
|
||||
if (!request_region(base, 2, "i2c (isa bus adapter)")) {
|
||||
printk(KERN_ERR
|
||||
"i2c-elektor: requested I/O region (0x%X:2) "
|
||||
"is in use.\n", base);
|
||||
if (!request_region(base, 2, pcf_isa_ops.name)) {
|
||||
printk(KERN_ERR "%s: requested I/O region (%#x:2) is "
|
||||
"in use\n", pcf_isa_ops.name, base);
|
||||
return -ENODEV;
|
||||
}
|
||||
base_iomem = ioport_map(base, 2);
|
||||
if (!base_iomem) {
|
||||
printk(KERN_ERR "%s: remap of I/O region %#x failed\n",
|
||||
pcf_isa_ops.name, base);
|
||||
release_region(base, 2);
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
if (!request_mem_region(base, 2, pcf_isa_ops.name)) {
|
||||
printk(KERN_ERR "%s: requested memory region (%#x:2) "
|
||||
"is in use\n", pcf_isa_ops.name, base);
|
||||
return -ENODEV;
|
||||
}
|
||||
base_iomem = ioremap(base, 2);
|
||||
if (base_iomem == NULL) {
|
||||
printk(KERN_ERR "%s: remap of memory region %#x "
|
||||
"failed\n", pcf_isa_ops.name, base);
|
||||
release_mem_region(base, 2);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
pr_debug("%s: registers %#x remapped to %p\n", pcf_isa_ops.name, base,
|
||||
base_iomem);
|
||||
|
||||
if (irq > 0) {
|
||||
if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", NULL) < 0) {
|
||||
printk(KERN_ERR "i2c-elektor: Request irq%d failed\n", irq);
|
||||
if (request_irq(irq, pcf_isa_handler, 0, pcf_isa_ops.name,
|
||||
NULL) < 0) {
|
||||
printk(KERN_ERR "%s: Request irq%d failed\n",
|
||||
pcf_isa_ops.name, irq);
|
||||
irq = 0;
|
||||
} else
|
||||
enable_irq(irq);
|
||||
|
@ -186,47 +205,49 @@ static struct i2c_adapter pcf_isa_ops = {
|
|||
.class = I2C_CLASS_HWMON,
|
||||
.id = I2C_HW_P_ELEK,
|
||||
.algo_data = &pcf_isa_data,
|
||||
.name = "PCF8584 ISA adapter",
|
||||
.name = "i2c-elektor",
|
||||
};
|
||||
|
||||
static int __init i2c_pcfisa_init(void)
|
||||
static int __init i2c_pcfisa_init(void)
|
||||
{
|
||||
#ifdef __alpha__
|
||||
/* check to see we have memory mapped PCF8584 connected to the
|
||||
/* check to see we have memory mapped PCF8584 connected to the
|
||||
Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
|
||||
if (base == 0) {
|
||||
struct pci_dev *cy693_dev;
|
||||
|
||||
cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ,
|
||||
|
||||
cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ,
|
||||
PCI_DEVICE_ID_CONTAQ_82C693, NULL);
|
||||
if (cy693_dev) {
|
||||
char config;
|
||||
unsigned char config;
|
||||
/* yeap, we've found cypress, let's check config */
|
||||
if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
|
||||
|
||||
pr_debug("i2c-elektor: found cy82c693, config register 0x47 = 0x%02x.\n", config);
|
||||
|
||||
pr_debug("%s: found cy82c693, config "
|
||||
"register 0x47 = 0x%02x\n",
|
||||
pcf_isa_ops.name, config);
|
||||
|
||||
/* UP2000 board has this register set to 0xe1,
|
||||
but the most significant bit as seems can be
|
||||
but the most significant bit as seems can be
|
||||
reset during the proper initialisation
|
||||
sequence if guys from API decides to do that
|
||||
(so, we can even enable Tsunami Pchip
|
||||
window for the upper 1 Gb) */
|
||||
sequence if guys from API decides to do that
|
||||
(so, we can even enable Tsunami Pchip
|
||||
window for the upper 1 Gb) */
|
||||
|
||||
/* so just check for ROMCS at 0xe0000,
|
||||
ROMCS enabled for writes
|
||||
ROMCS enabled for writes
|
||||
and external XD Bus buffer in use. */
|
||||
if ((config & 0x7f) == 0x61) {
|
||||
/* seems to be UP2000 like board */
|
||||
base = 0xe0000;
|
||||
/* I don't know why we need to
|
||||
write twice */
|
||||
mmapped = 2;
|
||||
/* UP2000 drives ISA with
|
||||
mmapped = 1;
|
||||
/* UP2000 drives ISA with
|
||||
8.25 MHz (PCI/4) clock
|
||||
(this can be read from cypress) */
|
||||
clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
|
||||
printk(KERN_INFO "i2c-elektor: found API UP2000 like board, will probe PCF8584 later.\n");
|
||||
pr_info("%s: found API UP2000 like "
|
||||
"board, will probe PCF8584 "
|
||||
"later\n", pcf_isa_ops.name);
|
||||
}
|
||||
}
|
||||
pci_dev_put(cy693_dev);
|
||||
|
@ -236,12 +257,11 @@ static int __init i2c_pcfisa_init(void)
|
|||
|
||||
/* sanity checks for mmapped I/O */
|
||||
if (mmapped && base < 0xc8000) {
|
||||
printk(KERN_ERR "i2c-elektor: incorrect base address (0x%0X) specified for mmapped I/O.\n", base);
|
||||
printk(KERN_ERR "%s: incorrect base address (%#x) specified "
|
||||
"for mmapped I/O\n", pcf_isa_ops.name, base);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "i2c-elektor: i2c pcf8584-isa adapter driver\n");
|
||||
|
||||
if (base == 0) {
|
||||
base = DEFAULT_BASE;
|
||||
}
|
||||
|
@ -251,8 +271,8 @@ static int __init i2c_pcfisa_init(void)
|
|||
return -ENODEV;
|
||||
if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
|
||||
goto fail;
|
||||
|
||||
printk(KERN_ERR "i2c-elektor: found device at %#x.\n", base);
|
||||
|
||||
dev_info(&pcf_isa_ops.dev, "found device at %#x\n", base);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -262,8 +282,13 @@ static int __init i2c_pcfisa_init(void)
|
|||
free_irq(irq, NULL);
|
||||
}
|
||||
|
||||
if (!mmapped)
|
||||
release_region(base , 2);
|
||||
if (!mmapped) {
|
||||
ioport_unmap(base_iomem);
|
||||
release_region(base, 2);
|
||||
} else {
|
||||
iounmap(base_iomem);
|
||||
release_mem_region(base, 2);
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -276,8 +301,13 @@ static void i2c_pcfisa_exit(void)
|
|||
free_irq(irq, NULL);
|
||||
}
|
||||
|
||||
if (!mmapped)
|
||||
release_region(base , 2);
|
||||
if (!mmapped) {
|
||||
ioport_unmap(base_iomem);
|
||||
release_region(base, 2);
|
||||
} else {
|
||||
iounmap(base_iomem);
|
||||
release_mem_region(base, 2);
|
||||
}
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
|
||||
|
|
|
@ -155,6 +155,7 @@ static void __devexit hydra_remove(struct pci_dev *dev)
|
|||
|
||||
|
||||
static struct pci_driver hydra_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "hydra_smbus",
|
||||
.id_table = hydra_ids,
|
||||
.probe = hydra_probe,
|
||||
|
|
|
@ -52,10 +52,6 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
|
||||
#define HAVE_PEC
|
||||
#endif
|
||||
|
||||
/* I801 SMBus address offsets */
|
||||
#define SMBHSTSTS (0 + i801_smba)
|
||||
#define SMBHSTCNT (2 + i801_smba)
|
||||
|
@ -106,10 +102,11 @@ MODULE_PARM_DESC(force_addr,
|
|||
"EXTREMELY DANGEROUS!");
|
||||
|
||||
static int i801_transaction(void);
|
||||
static int i801_block_transaction(union i2c_smbus_data *data,
|
||||
char read_write, int command);
|
||||
static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
|
||||
int command, int hwpec);
|
||||
|
||||
static unsigned short i801_smba;
|
||||
static struct pci_driver i801_driver;
|
||||
static struct pci_dev *I801_dev;
|
||||
static int isich4;
|
||||
|
||||
|
@ -143,7 +140,7 @@ static int i801_setup(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (!request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus")) {
|
||||
if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) {
|
||||
dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n",
|
||||
i801_smba);
|
||||
error_return = -EBUSY;
|
||||
|
@ -252,7 +249,7 @@ static int i801_transaction(void)
|
|||
|
||||
/* All-inclusive block transaction function */
|
||||
static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
|
||||
int command)
|
||||
int command, int hwpec)
|
||||
{
|
||||
int i, len;
|
||||
int smbcmd;
|
||||
|
@ -391,8 +388,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
|
|||
goto END;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PEC
|
||||
if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
|
||||
if (hwpec) {
|
||||
/* wait for INTR bit as advised by Intel */
|
||||
timeout = 0;
|
||||
do {
|
||||
|
@ -406,7 +402,6 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
|
|||
}
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
}
|
||||
#endif
|
||||
result = 0;
|
||||
END:
|
||||
if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
|
||||
|
@ -421,14 +416,13 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
|
|||
unsigned short flags, char read_write, u8 command,
|
||||
int size, union i2c_smbus_data * data)
|
||||
{
|
||||
int hwpec = 0;
|
||||
int hwpec;
|
||||
int block = 0;
|
||||
int ret, xact = 0;
|
||||
|
||||
#ifdef HAVE_PEC
|
||||
if(isich4)
|
||||
hwpec = (flags & I2C_CLIENT_PEC) != 0;
|
||||
#endif
|
||||
hwpec = isich4 && (flags & I2C_CLIENT_PEC)
|
||||
&& size != I2C_SMBUS_QUICK
|
||||
&& size != I2C_SMBUS_I2C_BLOCK_DATA;
|
||||
|
||||
switch (size) {
|
||||
case I2C_SMBUS_QUICK:
|
||||
|
@ -463,11 +457,6 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
|
|||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
#ifdef HAVE_PEC
|
||||
case I2C_SMBUS_BLOCK_DATA_PEC:
|
||||
if(hwpec && size == I2C_SMBUS_BLOCK_DATA)
|
||||
size = I2C_SMBUS_BLOCK_DATA_PEC;
|
||||
#endif
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
|
@ -479,27 +468,18 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PEC
|
||||
if(isich4 && hwpec) {
|
||||
if(size != I2C_SMBUS_QUICK &&
|
||||
size != I2C_SMBUS_I2C_BLOCK_DATA)
|
||||
outb_p(1, SMBAUXCTL); /* enable HW PEC */
|
||||
}
|
||||
#endif
|
||||
if (hwpec)
|
||||
outb_p(1, SMBAUXCTL); /* enable hardware PEC */
|
||||
|
||||
if(block)
|
||||
ret = i801_block_transaction(data, read_write, size);
|
||||
ret = i801_block_transaction(data, read_write, size, hwpec);
|
||||
else {
|
||||
outb_p(xact | ENABLE_INT9, SMBHSTCNT);
|
||||
ret = i801_transaction();
|
||||
}
|
||||
|
||||
#ifdef HAVE_PEC
|
||||
if(isich4 && hwpec) {
|
||||
if(size != I2C_SMBUS_QUICK &&
|
||||
size != I2C_SMBUS_I2C_BLOCK_DATA)
|
||||
outb_p(0, SMBAUXCTL);
|
||||
}
|
||||
#endif
|
||||
if (hwpec)
|
||||
outb_p(0, SMBAUXCTL); /* disable hardware PEC */
|
||||
|
||||
if(block)
|
||||
return ret;
|
||||
|
@ -526,12 +506,7 @@ static u32 i801_func(struct i2c_adapter *adapter)
|
|||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
|
||||
#ifdef HAVE_PEC
|
||||
| (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
|
||||
I2C_FUNC_SMBUS_HWPEC_CALC
|
||||
: 0)
|
||||
#endif
|
||||
;
|
||||
| (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
|
@ -543,7 +518,6 @@ static struct i2c_adapter i801_adapter = {
|
|||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
.name = "unset",
|
||||
};
|
||||
|
||||
static struct pci_device_id i801_ids[] = {
|
||||
|
@ -586,6 +560,7 @@ static void __devexit i801_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver i801_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i801_smbus",
|
||||
.id_table = i801_ids,
|
||||
.probe = i801_probe,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
i810AB 7123
|
||||
i810E 7125
|
||||
i815 1132
|
||||
i845G 2562
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -232,6 +233,7 @@ static void __devexit i810_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver i810_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i810_smbus",
|
||||
.id_table = i810_ids,
|
||||
.probe = i810_probe,
|
||||
|
|
|
@ -672,13 +672,12 @@ static int __devinit iic_probe(struct ocp_device *ocp){
|
|||
printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
|
||||
ocp->def->index);
|
||||
|
||||
if (!(dev = kmalloc(sizeof(*dev), GFP_KERNEL))){
|
||||
if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
|
||||
printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n",
|
||||
ocp->def->index);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->idx = ocp->def->index;
|
||||
ocp_set_drvdata(ocp, dev);
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "i2c-iop3xx.h"
|
||||
|
||||
/* global unit counter */
|
||||
static int i2c_id = 0;
|
||||
static int i2c_id;
|
||||
|
||||
static inline unsigned char
|
||||
iic_cook_addr(struct i2c_msg *msg)
|
||||
|
@ -440,19 +440,17 @@ iop3xx_i2c_probe(struct device *dev)
|
|||
struct i2c_adapter *new_adapter;
|
||||
struct i2c_algo_iop3xx_data *adapter_data;
|
||||
|
||||
new_adapter = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
|
||||
new_adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
|
||||
if (!new_adapter) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memset((void*)new_adapter, 0, sizeof(*new_adapter));
|
||||
|
||||
adapter_data = kmalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
|
||||
adapter_data = kzalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
|
||||
if (!adapter_data) {
|
||||
ret = -ENOMEM;
|
||||
goto free_adapter;
|
||||
}
|
||||
memset((void*)adapter_data, 0, sizeof(*adapter_data));
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
|
@ -525,6 +523,7 @@ iop3xx_i2c_probe(struct device *dev)
|
|||
|
||||
|
||||
static struct device_driver iop3xx_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "IOP3xx-I2C",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = iop3xx_i2c_probe,
|
||||
|
|
|
@ -92,6 +92,7 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
|
|||
|
||||
/* Add the driver to the list of i2c drivers in the driver core */
|
||||
driver->driver.name = driver->name;
|
||||
driver->driver.owner = driver->owner;
|
||||
driver->driver.bus = &i2c_bus_type;
|
||||
driver->driver.probe = i2c_isa_device_probe;
|
||||
driver->driver.remove = i2c_isa_device_remove;
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
#include <asm/hardware.h> /* Pick up IXP2000-specific bits */
|
||||
#include <asm/arch/gpio.h>
|
||||
|
||||
static struct device_driver ixp2000_i2c_driver;
|
||||
|
||||
static inline int ixp2000_scl_pin(void *data)
|
||||
{
|
||||
return ((struct ixp2000_i2c_pins*)data)->scl_pin;
|
||||
|
@ -104,11 +106,10 @@ static int ixp2000_i2c_probe(struct device *dev)
|
|||
struct platform_device *plat_dev = to_platform_device(dev);
|
||||
struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data;
|
||||
struct ixp2000_i2c_data *drv_data =
|
||||
kmalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
|
||||
kzalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
|
||||
|
||||
if (!drv_data)
|
||||
return -ENOMEM;
|
||||
memzero(drv_data, sizeof(*drv_data));
|
||||
drv_data->gpio_pins = gpio;
|
||||
|
||||
drv_data->algo_data.data = gpio;
|
||||
|
@ -121,6 +122,8 @@ static int ixp2000_i2c_probe(struct device *dev)
|
|||
drv_data->algo_data.timeout = 100;
|
||||
|
||||
drv_data->adapter.id = I2C_HW_B_IXP2000,
|
||||
strlcpy(drv_data->adapter.name, ixp2000_i2c_driver.name,
|
||||
I2C_NAME_SIZE);
|
||||
drv_data->adapter.algo_data = &drv_data->algo_data,
|
||||
|
||||
drv_data->adapter.dev.parent = &plat_dev->dev;
|
||||
|
@ -142,6 +145,7 @@ static int ixp2000_i2c_probe(struct device *dev)
|
|||
}
|
||||
|
||||
static struct device_driver ixp2000_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "IXP2000-I2C",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = ixp2000_i2c_probe,
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
#include <asm/hardware.h> /* Pick up IXP4xx-specific bits */
|
||||
|
||||
static struct device_driver ixp4xx_i2c_driver;
|
||||
|
||||
static inline int ixp4xx_scl_pin(void *data)
|
||||
{
|
||||
return ((struct ixp4xx_i2c_pins*)data)->scl_pin;
|
||||
|
@ -105,12 +107,11 @@ static int ixp4xx_i2c_probe(struct device *dev)
|
|||
struct platform_device *plat_dev = to_platform_device(dev);
|
||||
struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data;
|
||||
struct ixp4xx_i2c_data *drv_data =
|
||||
kmalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
|
||||
kzalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
|
||||
|
||||
if(!drv_data)
|
||||
return -ENOMEM;
|
||||
|
||||
memzero(drv_data, sizeof(struct ixp4xx_i2c_data));
|
||||
drv_data->gpio_pins = gpio;
|
||||
|
||||
/*
|
||||
|
@ -129,6 +130,8 @@ static int ixp4xx_i2c_probe(struct device *dev)
|
|||
drv_data->algo_data.timeout = 100;
|
||||
|
||||
drv_data->adapter.id = I2C_HW_B_IXP4XX;
|
||||
strlcpy(drv_data->adapter.name, ixp4xx_i2c_driver.name,
|
||||
I2C_NAME_SIZE);
|
||||
drv_data->adapter.algo_data = &drv_data->algo_data;
|
||||
|
||||
drv_data->adapter.dev.parent = &plat_dev->dev;
|
||||
|
@ -151,6 +154,7 @@ static int ixp4xx_i2c_probe(struct device *dev)
|
|||
}
|
||||
|
||||
static struct device_driver ixp4xx_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "IXP4XX-I2C",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = ixp4xx_i2c_probe,
|
||||
|
|
|
@ -535,13 +535,12 @@ create_iface(struct device_node *np, struct device *dev)
|
|||
|
||||
tsize = sizeof(struct keywest_iface) +
|
||||
(sizeof(struct keywest_chan) + 4) * nchan;
|
||||
iface = (struct keywest_iface *) kmalloc(tsize, GFP_KERNEL);
|
||||
iface = kzalloc(tsize, GFP_KERNEL);
|
||||
if (iface == NULL) {
|
||||
printk(KERN_ERR "i2c-keywest: can't allocate inteface !\n");
|
||||
pmac_low_i2c_unlock(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(iface, 0, tsize);
|
||||
spin_lock_init(&iface->lock);
|
||||
init_completion(&iface->complete);
|
||||
iface->node = of_node_get(np);
|
||||
|
@ -716,6 +715,7 @@ static struct of_device_id i2c_keywest_match[] =
|
|||
|
||||
static struct macio_driver i2c_keywest_macio_driver =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i2c-keywest",
|
||||
.match_table = i2c_keywest_match,
|
||||
.probe = create_iface_macio,
|
||||
|
@ -724,6 +724,7 @@ static struct macio_driver i2c_keywest_macio_driver =
|
|||
|
||||
static struct of_platform_driver i2c_keywest_of_platform_driver =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i2c-keywest",
|
||||
.match_table = i2c_keywest_match,
|
||||
.probe = create_iface_of_platform,
|
||||
|
|
|
@ -296,10 +296,9 @@ static int fsl_i2c_probe(struct device *device)
|
|||
|
||||
pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
|
||||
|
||||
if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
|
||||
if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(i2c, 0, sizeof(*i2c));
|
||||
|
||||
i2c->irq = platform_get_irq(pdev, 0);
|
||||
i2c->flags = pdata->device_flags;
|
||||
|
@ -361,6 +360,7 @@ static int fsl_i2c_remove(struct device *device)
|
|||
|
||||
/* Structure for a device driver */
|
||||
static struct device_driver fsl_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "fsl-i2c",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = fsl_i2c_probe,
|
||||
|
|
|
@ -500,13 +500,10 @@ mv64xxx_i2c_probe(struct device *dev)
|
|||
if ((pd->id != 0) || !pdata)
|
||||
return -ENODEV;
|
||||
|
||||
drv_data = kmalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
|
||||
|
||||
drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
|
||||
if (!drv_data)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(drv_data, 0, sizeof(struct mv64xxx_i2c_data));
|
||||
|
||||
if (mv64xxx_i2c_map_regs(pd, drv_data)) {
|
||||
rc = -ENODEV;
|
||||
goto exit_kfree;
|
||||
|
@ -570,6 +567,7 @@ mv64xxx_i2c_remove(struct device *dev)
|
|||
}
|
||||
|
||||
static struct device_driver mv64xxx_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = MV64XXX_I2C_CTLR_NAME,
|
||||
.bus = &platform_bus_type,
|
||||
.probe = mv64xxx_i2c_probe,
|
||||
|
|
|
@ -97,6 +97,7 @@ struct nforce2_smbus {
|
|||
#define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
|
||||
#define NVIDIA_SMB_PRTCL_PEC 0x80
|
||||
|
||||
static struct pci_driver nforce2_driver;
|
||||
|
||||
static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
|
@ -113,7 +114,6 @@ static struct i2c_adapter nforce2_adapter = {
|
|||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
.name = "unset",
|
||||
};
|
||||
|
||||
/* Return -1 on error. See smbus.h for more information */
|
||||
|
@ -188,13 +188,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
|
|||
dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
|
||||
case I2C_SMBUS_WORD_DATA_PEC:
|
||||
case I2C_SMBUS_BLOCK_DATA_PEC:
|
||||
case I2C_SMBUS_PROC_CALL_PEC:
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
|
||||
dev_err(&adap->dev, "Unexpected software PEC transaction %d\n.", size);
|
||||
return -1;
|
||||
|
||||
default:
|
||||
dev_err(&adap->dev, "Unsupported transaction %d\n", size);
|
||||
return -1;
|
||||
|
@ -285,7 +278,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg,
|
|||
smbus->base = iobase & 0xfffc;
|
||||
smbus->size = 8;
|
||||
|
||||
if (!request_region(smbus->base, smbus->size, "nForce2 SMBus")) {
|
||||
if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
|
||||
dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
|
||||
smbus->base, smbus->base+smbus->size-1, name);
|
||||
return -1;
|
||||
|
@ -313,10 +306,8 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
|
|||
int res1, res2;
|
||||
|
||||
/* we support 2 SMBus adapters */
|
||||
if (!(smbuses = (void *)kmalloc(2*sizeof(struct nforce2_smbus),
|
||||
GFP_KERNEL)))
|
||||
if (!(smbuses = kzalloc(2*sizeof(struct nforce2_smbus), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
memset (smbuses, 0, 2*sizeof(struct nforce2_smbus));
|
||||
pci_set_drvdata(dev, smbuses);
|
||||
|
||||
/* SMBus adapter 1 */
|
||||
|
@ -356,6 +347,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver nforce2_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "nForce2_smbus",
|
||||
.id_table = nforce2_ids,
|
||||
.probe = nforce2_probe,
|
||||
|
|
|
@ -155,12 +155,11 @@ static void i2c_parport_attach (struct parport *port)
|
|||
{
|
||||
struct i2c_par *adapter;
|
||||
|
||||
adapter = kmalloc(sizeof(struct i2c_par), GFP_KERNEL);
|
||||
adapter = kzalloc(sizeof(struct i2c_par), GFP_KERNEL);
|
||||
if (adapter == NULL) {
|
||||
printk(KERN_ERR "i2c-parport: Failed to kmalloc\n");
|
||||
printk(KERN_ERR "i2c-parport: Failed to kzalloc\n");
|
||||
return;
|
||||
}
|
||||
memset(adapter, 0x00, sizeof(struct i2c_par));
|
||||
|
||||
pr_debug("i2c-parport: attaching to %s\n", port->name);
|
||||
adapter->pdev = parport_register_device(port, "i2c-parport",
|
||||
|
@ -232,7 +231,7 @@ static void i2c_parport_detach (struct parport *port)
|
|||
}
|
||||
}
|
||||
|
||||
static struct parport_driver i2c_driver = {
|
||||
static struct parport_driver i2c_parport_driver = {
|
||||
.name = "i2c-parport",
|
||||
.attach = i2c_parport_attach,
|
||||
.detach = i2c_parport_detach,
|
||||
|
@ -250,12 +249,12 @@ static int __init i2c_parport_init(void)
|
|||
type = 0;
|
||||
}
|
||||
|
||||
return parport_register_driver(&i2c_driver);
|
||||
return parport_register_driver(&i2c_parport_driver);
|
||||
}
|
||||
|
||||
static void __exit i2c_parport_exit(void)
|
||||
{
|
||||
parport_unregister_driver(&i2c_driver);
|
||||
parport_unregister_driver(&i2c_parport_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
|
||||
|
|
|
@ -90,13 +90,13 @@ struct sd {
|
|||
|
||||
/* If force is set to anything different from 0, we forcibly enable the
|
||||
PIIX4. DANGEROUS! */
|
||||
static int force = 0;
|
||||
static int force;
|
||||
module_param (force, int, 0);
|
||||
MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
|
||||
|
||||
/* If force_addr is set to anything different from 0, we forcibly enable
|
||||
the PIIX4 at the given address. VERY DANGEROUS! */
|
||||
static int force_addr = 0;
|
||||
static int force_addr;
|
||||
module_param (force_addr, int, 0);
|
||||
MODULE_PARM_DESC(force_addr,
|
||||
"Forcibly enable the PIIX4 at the given address. "
|
||||
|
@ -104,14 +104,15 @@ MODULE_PARM_DESC(force_addr,
|
|||
|
||||
/* If fix_hstcfg is set to anything different from 0, we reset one of the
|
||||
registers to be a valid value. */
|
||||
static int fix_hstcfg = 0;
|
||||
static int fix_hstcfg;
|
||||
module_param (fix_hstcfg, int, 0);
|
||||
MODULE_PARM_DESC(fix_hstcfg,
|
||||
"Fix config register. Needed on some boards (Force CPCI735).");
|
||||
|
||||
static int piix4_transaction(void);
|
||||
|
||||
static unsigned short piix4_smba = 0;
|
||||
static unsigned short piix4_smba;
|
||||
static struct pci_driver piix4_driver;
|
||||
static struct i2c_adapter piix4_adapter;
|
||||
|
||||
static struct dmi_system_id __devinitdata piix4_dmi_table[] = {
|
||||
|
@ -157,7 +158,7 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
|
|||
}
|
||||
}
|
||||
|
||||
if (!request_region(piix4_smba, SMBIOSIZE, "piix4-smbus")) {
|
||||
if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
|
||||
dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n",
|
||||
piix4_smba);
|
||||
return -ENODEV;
|
||||
|
@ -407,7 +408,6 @@ static struct i2c_adapter piix4_adapter = {
|
|||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
.name = "unset",
|
||||
};
|
||||
|
||||
static struct pci_device_id piix4_ids[] = {
|
||||
|
@ -462,6 +462,7 @@ static void __devexit piix4_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver piix4_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "piix4_smbus",
|
||||
.id_table = piix4_ids,
|
||||
.probe = piix4_probe,
|
||||
|
|
|
@ -211,12 +211,11 @@ static int create_iface(struct device_node *np, struct device *dev)
|
|||
}
|
||||
busid = *reg;
|
||||
|
||||
iface = kmalloc(sizeof(struct smu_iface), GFP_KERNEL);
|
||||
iface = kzalloc(sizeof(struct smu_iface), GFP_KERNEL);
|
||||
if (iface == NULL) {
|
||||
printk(KERN_ERR "i2c-pmac-smu: can't allocate inteface !\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(iface, 0, sizeof(struct smu_iface));
|
||||
init_completion(&iface->complete);
|
||||
iface->busid = busid;
|
||||
|
||||
|
|
|
@ -83,11 +83,6 @@ struct s_i2c_chip {
|
|||
/*
|
||||
* i2c configuration
|
||||
*/
|
||||
#ifndef I2C_HW_B_S3VIA
|
||||
#define I2C_HW_B_S3VIA 0x18 /* S3VIA ProSavage adapter */
|
||||
#endif
|
||||
|
||||
/* delays */
|
||||
#define CYCLE_DELAY 10
|
||||
#define TIMEOUT (HZ / 2)
|
||||
|
||||
|
@ -241,14 +236,12 @@ static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_devic
|
|||
struct s_i2c_chip *chip;
|
||||
struct s_i2c_bus *bus;
|
||||
|
||||
pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
|
||||
pci_set_drvdata(dev, kzalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
|
||||
chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
|
||||
if (chip == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(chip, 0, sizeof(struct s_i2c_chip));
|
||||
|
||||
base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
|
||||
len = dev->resource[0].end - base + 1;
|
||||
chip->mmio = ioremap_nocache(base, len);
|
||||
|
@ -308,6 +301,7 @@ static struct pci_device_id prosavage_pci_tbl[] = {
|
|||
MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
|
||||
|
||||
static struct pci_driver prosavage_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "prosavage_smbus",
|
||||
.id_table = prosavage_pci_tbl,
|
||||
.probe = prosavage_probe,
|
||||
|
|
|
@ -896,6 +896,7 @@ static int s3c24xx_i2c_resume(struct device *dev)
|
|||
/* device driver for platform bus bits */
|
||||
|
||||
static struct device_driver s3c2410_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "s3c2410-i2c",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = s3c24xx_i2c_probe,
|
||||
|
@ -904,6 +905,7 @@ static struct device_driver s3c2410_i2c_driver = {
|
|||
};
|
||||
|
||||
static struct device_driver s3c2440_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "s3c2440-i2c",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = s3c24xx_i2c_probe,
|
||||
|
|
|
@ -179,6 +179,7 @@ static void __devexit savage4_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver savage4_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "savage4_smbus",
|
||||
.id_table = savage4_ids,
|
||||
.probe = savage4_probe,
|
||||
|
|
|
@ -123,11 +123,12 @@ static int blacklist[] = {
|
|||
|
||||
/* If force_addr is set to anything different from 0, we forcibly enable
|
||||
the device at the given address. */
|
||||
static u16 force_addr = 0;
|
||||
static u16 force_addr;
|
||||
module_param(force_addr, ushort, 0);
|
||||
MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
|
||||
|
||||
static unsigned short sis5595_base = 0;
|
||||
static struct pci_driver sis5595_driver;
|
||||
static unsigned short sis5595_base;
|
||||
|
||||
static u8 sis5595_read(u8 reg)
|
||||
{
|
||||
|
@ -172,7 +173,8 @@ static int sis5595_setup(struct pci_dev *SIS5595_dev)
|
|||
|
||||
/* NB: We grab just the two SMBus registers here, but this may still
|
||||
* interfere with ACPI :-( */
|
||||
if (!request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus")) {
|
||||
if (!request_region(sis5595_base + SMB_INDEX, 2,
|
||||
sis5595_driver.name)) {
|
||||
dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n",
|
||||
sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1);
|
||||
return -ENODEV;
|
||||
|
@ -364,7 +366,6 @@ static struct i2c_algorithm smbus_algorithm = {
|
|||
static struct i2c_adapter sis5595_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.name = "unset",
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
|
@ -397,6 +398,7 @@ static void __devexit sis5595_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver sis5595_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "sis5595_smbus",
|
||||
.id_table = sis5595_ids,
|
||||
.probe = sis5595_probe,
|
||||
|
|
|
@ -92,6 +92,8 @@
|
|||
#define SIS630_PCALL 0x04
|
||||
#define SIS630_BLOCK_DATA 0x05
|
||||
|
||||
static struct pci_driver sis630_driver;
|
||||
|
||||
/* insmod parameters */
|
||||
static int high_clock;
|
||||
static int force;
|
||||
|
@ -101,7 +103,7 @@ module_param(force, bool, 0);
|
|||
MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
|
||||
|
||||
/* acpi base address */
|
||||
static unsigned short acpi_base = 0;
|
||||
static unsigned short acpi_base;
|
||||
|
||||
/* supported chips */
|
||||
static int supported[] = {
|
||||
|
@ -432,7 +434,8 @@ static int sis630_setup(struct pci_dev *sis630_dev)
|
|||
dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
|
||||
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, "sis630-smbus")) {
|
||||
if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
|
||||
sis630_driver.name)) {
|
||||
dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
|
||||
"in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
|
||||
goto exit;
|
||||
|
@ -455,7 +458,6 @@ static struct i2c_algorithm smbus_algorithm = {
|
|||
static struct i2c_adapter sis630_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.name = "unset",
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
|
@ -494,6 +496,7 @@ static void __devexit sis630_remove(struct pci_dev *dev)
|
|||
|
||||
|
||||
static struct pci_driver sis630_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "sis630_smbus",
|
||||
.id_table = sis630_ids,
|
||||
.probe = sis630_probe,
|
||||
|
|
|
@ -82,8 +82,9 @@
|
|||
#define SIS96x_PROC_CALL 0x04
|
||||
#define SIS96x_BLOCK_DATA 0x05
|
||||
|
||||
static struct pci_driver sis96x_driver;
|
||||
static struct i2c_adapter sis96x_adapter;
|
||||
static u16 sis96x_smbus_base = 0;
|
||||
static u16 sis96x_smbus_base;
|
||||
|
||||
static inline u8 sis96x_read(u8 reg)
|
||||
{
|
||||
|
@ -257,7 +258,6 @@ static struct i2c_adapter sis96x_adapter = {
|
|||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
.name = "unset",
|
||||
};
|
||||
|
||||
static struct pci_device_id sis96x_ids[] = {
|
||||
|
@ -294,7 +294,8 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
|
|||
sis96x_smbus_base);
|
||||
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
if (!request_region(sis96x_smbus_base, SMB_IOSIZE, "sis96x-smbus")) {
|
||||
if (!request_region(sis96x_smbus_base, SMB_IOSIZE,
|
||||
sis96x_driver.name)) {
|
||||
dev_err(&dev->dev, "SMBus registers 0x%04x-0x%04x "
|
||||
"already in use!\n", sis96x_smbus_base,
|
||||
sis96x_smbus_base + SMB_IOSIZE - 1);
|
||||
|
@ -328,6 +329,7 @@ static void __devexit sis96x_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver sis96x_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "sis96x_smbus",
|
||||
.id_table = sis96x_ids,
|
||||
.probe = sis96x_probe,
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
|
||||
/* io-region reservation */
|
||||
#define IOSPACE 0x06
|
||||
#define IOTEXT "via-i2c"
|
||||
|
||||
static u16 pm_io_base = 0;
|
||||
static struct pci_driver vt586b_driver;
|
||||
static u16 pm_io_base;
|
||||
|
||||
/*
|
||||
It does not appear from the datasheet that the GPIO pins are
|
||||
|
@ -130,7 +130,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i
|
|||
pci_read_config_word(dev, base, &pm_io_base);
|
||||
pm_io_base &= (0xff << 8);
|
||||
|
||||
if (!request_region(I2C_DIR, IOSPACE, IOTEXT)) {
|
||||
if (!request_region(I2C_DIR, IOSPACE, vt586b_driver.name)) {
|
||||
dev_err(&dev->dev, "IO 0x%x-0x%x already in use\n", I2C_DIR, I2C_DIR + IOSPACE);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -159,6 +159,7 @@ static void __devexit vt586b_remove(struct pci_dev *dev)
|
|||
|
||||
|
||||
static struct pci_driver vt586b_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "vt586b_smbus",
|
||||
.id_table = vt586b_ids,
|
||||
.probe = vt586b_probe,
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
/*
|
||||
i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
|
||||
monitoring
|
||||
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
|
||||
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
|
||||
Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -21,15 +22,19 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
Supports Via devices:
|
||||
82C596A/B (0x3050)
|
||||
82C596B (0x3051)
|
||||
82C686A/B
|
||||
8231
|
||||
8233
|
||||
8233A (0x3147 and 0x3177)
|
||||
8235
|
||||
8237
|
||||
Supports the following VIA south bridges:
|
||||
|
||||
Chip name PCI ID REV I2C block
|
||||
VT82C596A 0x3050 no
|
||||
VT82C596B 0x3051 no
|
||||
VT82C686A 0x3057 0x30 no
|
||||
VT82C686B 0x3057 0x40 yes
|
||||
VT8231 0x8235 no?
|
||||
VT8233 0x3074 yes
|
||||
VT8233A 0x3147 yes?
|
||||
VT8235 0x3177 yes
|
||||
VT8237R 0x3227 yes
|
||||
|
||||
Note: we assume there can only be one device, with one SMBus interface.
|
||||
*/
|
||||
|
||||
|
@ -38,7 +43,6 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -46,48 +50,37 @@
|
|||
|
||||
static struct pci_dev *vt596_pdev;
|
||||
|
||||
#define SMBBA1 0x90
|
||||
#define SMBBA2 0x80
|
||||
#define SMBBA3 0xD0
|
||||
#define SMBBA1 0x90
|
||||
#define SMBBA2 0x80
|
||||
#define SMBBA3 0xD0
|
||||
|
||||
/* SMBus address offsets */
|
||||
static unsigned short vt596_smba;
|
||||
#define SMBHSTSTS (vt596_smba + 0)
|
||||
#define SMBHSLVSTS (vt596_smba + 1)
|
||||
#define SMBHSTCNT (vt596_smba + 2)
|
||||
#define SMBHSTCMD (vt596_smba + 3)
|
||||
#define SMBHSTADD (vt596_smba + 4)
|
||||
#define SMBHSTDAT0 (vt596_smba + 5)
|
||||
#define SMBHSTDAT1 (vt596_smba + 6)
|
||||
#define SMBBLKDAT (vt596_smba + 7)
|
||||
#define SMBSLVCNT (vt596_smba + 8)
|
||||
#define SMBSHDWCMD (vt596_smba + 9)
|
||||
#define SMBSLVEVT (vt596_smba + 0xA)
|
||||
#define SMBSLVDAT (vt596_smba + 0xC)
|
||||
|
||||
/* PCI Address Constants */
|
||||
|
||||
/* SMBus data in configuration space can be found in two places,
|
||||
We try to select the better one*/
|
||||
We try to select the better one */
|
||||
|
||||
static unsigned short smb_cf_hstcfg = 0xD2;
|
||||
|
||||
#define SMBHSTCFG (smb_cf_hstcfg)
|
||||
#define SMBSLVC (smb_cf_hstcfg + 1)
|
||||
#define SMBSHDW1 (smb_cf_hstcfg + 2)
|
||||
#define SMBSHDW2 (smb_cf_hstcfg + 3)
|
||||
#define SMBREV (smb_cf_hstcfg + 4)
|
||||
static unsigned short SMBHSTCFG = 0xD2;
|
||||
|
||||
/* Other settings */
|
||||
#define MAX_TIMEOUT 500
|
||||
#define ENABLE_INT9 0
|
||||
|
||||
/* VT82C596 constants */
|
||||
#define VT596_QUICK 0x00
|
||||
#define VT596_BYTE 0x04
|
||||
#define VT596_BYTE_DATA 0x08
|
||||
#define VT596_WORD_DATA 0x0C
|
||||
#define VT596_BLOCK_DATA 0x14
|
||||
#define VT596_QUICK 0x00
|
||||
#define VT596_BYTE 0x04
|
||||
#define VT596_BYTE_DATA 0x08
|
||||
#define VT596_WORD_DATA 0x0C
|
||||
#define VT596_BLOCK_DATA 0x14
|
||||
#define VT596_I2C_BLOCK_DATA 0x34
|
||||
|
||||
|
||||
/* If force is set to anything different from 0, we forcibly enable the
|
||||
|
@ -105,40 +98,65 @@ MODULE_PARM_DESC(force_addr,
|
|||
"EXTREMELY DANGEROUS!");
|
||||
|
||||
|
||||
static struct pci_driver vt596_driver;
|
||||
static struct i2c_adapter vt596_adapter;
|
||||
|
||||
/* Another internally used function */
|
||||
static int vt596_transaction(void)
|
||||
#define FEATURE_I2CBLOCK (1<<0)
|
||||
static unsigned int vt596_features;
|
||||
|
||||
#ifdef DEBUG
|
||||
static void vt596_dump_regs(const char *msg, u8 size)
|
||||
{
|
||||
dev_dbg(&vt596_adapter.dev, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x "
|
||||
"DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
|
||||
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
|
||||
if (size == VT596_BLOCK_DATA
|
||||
|| size == VT596_I2C_BLOCK_DATA) {
|
||||
int i;
|
||||
|
||||
dev_dbg(&vt596_adapter.dev, "BLK=");
|
||||
for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++)
|
||||
printk("%02x,", inb_p(SMBBLKDAT));
|
||||
printk("\n");
|
||||
dev_dbg(&vt596_adapter.dev, " ");
|
||||
for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++)
|
||||
printk("%02x,", inb_p(SMBBLKDAT));
|
||||
printk("%02x\n", inb_p(SMBBLKDAT));
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline void vt596_dump_regs(const char *msg, u8 size) { }
|
||||
#endif
|
||||
|
||||
/* Return -1 on error, 0 on success */
|
||||
static int vt596_transaction(u8 size)
|
||||
{
|
||||
int temp;
|
||||
int result = 0;
|
||||
int timeout = 0;
|
||||
|
||||
dev_dbg(&vt596_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
|
||||
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
|
||||
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
vt596_dump_regs("Transaction (pre)", size);
|
||||
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
|
||||
dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
|
||||
"Resetting...\n", temp);
|
||||
|
||||
"Resetting... ", temp);
|
||||
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
|
||||
dev_dbg(&vt596_adapter.dev, "Failed! (0x%02x)\n", temp);
|
||||
|
||||
printk("Failed! (0x%02x)\n", temp);
|
||||
return -1;
|
||||
} else {
|
||||
dev_dbg(&vt596_adapter.dev, "Successfull!\n");
|
||||
printk("Successful!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* start the transaction by setting bit 6 */
|
||||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||
/* Start the transaction by setting bit 6 */
|
||||
outb_p(0x40 | (size & 0x3C), SMBHSTCNT);
|
||||
|
||||
/* We will always wait for a fraction of a second!
|
||||
I don't know if VIA needs this, Intel did */
|
||||
/* We will always wait for a fraction of a second */
|
||||
do {
|
||||
msleep(1);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
|
@ -147,77 +165,61 @@ static int vt596_transaction(void)
|
|||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
result = -1;
|
||||
dev_dbg(&vt596_adapter.dev, "SMBus Timeout!\n");
|
||||
dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
|
||||
}
|
||||
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
dev_dbg(&vt596_adapter.dev, "Error: Failed bus transaction\n");
|
||||
dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
|
||||
inb_p(SMBHSTCNT) & 0x3C);
|
||||
}
|
||||
|
||||
if (temp & 0x08) {
|
||||
result = -1;
|
||||
dev_info(&vt596_adapter.dev, "Bus collision! SMBus may be "
|
||||
"locked until next hard\nreset. (sorry!)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
dev_err(&vt596_adapter.dev, "SMBus collision!\n");
|
||||
}
|
||||
|
||||
if (temp & 0x04) {
|
||||
result = -1;
|
||||
dev_dbg(&vt596_adapter.dev, "Error: no response!\n");
|
||||
/* Quick commands are used to probe for chips, so
|
||||
errors are expected, and we don't want to frighten the
|
||||
user. */
|
||||
if ((inb_p(SMBHSTCNT) & 0x3C) != VT596_QUICK)
|
||||
dev_err(&vt596_adapter.dev, "Transaction error!\n");
|
||||
}
|
||||
|
||||
if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
|
||||
/* Resetting status register */
|
||||
if (temp & 0x1F)
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
|
||||
dev_warn(&vt596_adapter.dev, "Failed reset at end "
|
||||
"of transaction (%02x)\n", temp);
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
|
||||
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
|
||||
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
|
||||
vt596_dump_regs("Transaction (post)", size);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return -1 on error. */
|
||||
/* Return -1 on error, 0 on success */
|
||||
static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write, u8 command,
|
||||
int size, union i2c_smbus_data *data)
|
||||
unsigned short flags, char read_write, u8 command,
|
||||
int size, union i2c_smbus_data *data)
|
||||
{
|
||||
int i, len;
|
||||
int i;
|
||||
|
||||
switch (size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
dev_info(&vt596_adapter.dev,
|
||||
"I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
size = VT596_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(command, SMBHSTCMD);
|
||||
size = VT596_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->byte, SMBHSTDAT0);
|
||||
size = VT596_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
outb_p(data->word & 0xff, SMBHSTDAT0);
|
||||
|
@ -225,28 +227,33 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
|
|||
}
|
||||
size = VT596_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
if (!(vt596_features & FEATURE_I2CBLOCK))
|
||||
goto exit_unsupported;
|
||||
if (read_write == I2C_SMBUS_READ)
|
||||
outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
|
||||
/* Fall through */
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
u8 len = data->block[0];
|
||||
if (len > I2C_SMBUS_BLOCK_MAX)
|
||||
len = I2C_SMBUS_BLOCK_MAX;
|
||||
outb_p(len, SMBHSTDAT0);
|
||||
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= len; i++)
|
||||
outb_p(data->block[i], SMBBLKDAT);
|
||||
}
|
||||
size = VT596_BLOCK_DATA;
|
||||
size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ?
|
||||
VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA;
|
||||
break;
|
||||
default:
|
||||
goto exit_unsupported;
|
||||
}
|
||||
|
||||
outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
|
||||
outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
|
||||
|
||||
if (vt596_transaction()) /* Error in transaction */
|
||||
if (vt596_transaction(size)) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
|
||||
|
@ -254,35 +261,39 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
|
|||
|
||||
switch (size) {
|
||||
case VT596_BYTE:
|
||||
/* Where is the result put? I assume here it is in
|
||||
* SMBHSTDAT0 but it might just as well be in the
|
||||
* SMBHSTCMD. No clue in the docs
|
||||
*/
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case VT596_BYTE_DATA:
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case VT596_WORD_DATA:
|
||||
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
case VT596_I2C_BLOCK_DATA:
|
||||
case VT596_BLOCK_DATA:
|
||||
data->block[0] = inb_p(SMBHSTDAT0);
|
||||
if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
|
||||
data->block[0] = I2C_SMBUS_BLOCK_MAX;
|
||||
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= data->block[0]; i++)
|
||||
data->block[i] = inb_p(SMBBLKDAT);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
exit_unsupported:
|
||||
dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
|
||||
size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static u32 vt596_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
|
||||
if (vt596_features & FEATURE_I2CBLOCK)
|
||||
func |= I2C_FUNC_SMBUS_I2C_BLOCK;
|
||||
return func;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
|
@ -294,7 +305,6 @@ static struct i2c_adapter vt596_adapter = {
|
|||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
.name = "unset",
|
||||
};
|
||||
|
||||
static int __devinit vt596_probe(struct pci_dev *pdev,
|
||||
|
@ -302,7 +312,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
|
|||
{
|
||||
unsigned char temp;
|
||||
int error = -ENODEV;
|
||||
|
||||
|
||||
/* Determine the address of the SMBus areas */
|
||||
if (force_addr) {
|
||||
vt596_smba = force_addr & 0xfff0;
|
||||
|
@ -311,12 +321,12 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
|
||||
!(vt596_smba & 0x1)) {
|
||||
!(vt596_smba & 0x0001)) {
|
||||
/* try 2nd address and config reg. for 596 */
|
||||
if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
|
||||
!pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
|
||||
(vt596_smba & 0x1)) {
|
||||
smb_cf_hstcfg = 0x84;
|
||||
(vt596_smba & 0x0001)) {
|
||||
SMBHSTCFG = 0x84;
|
||||
} else {
|
||||
/* no matches at all */
|
||||
dev_err(&pdev->dev, "Cannot configure "
|
||||
|
@ -333,10 +343,10 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
found:
|
||||
if (!request_region(vt596_smba, 8, "viapro-smbus")) {
|
||||
found:
|
||||
if (!request_region(vt596_smba, 8, vt596_driver.name)) {
|
||||
dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
|
||||
vt596_smba);
|
||||
vt596_smba);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -348,16 +358,16 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
|
|||
pci_write_config_word(pdev, id->driver_data, vt596_smba);
|
||||
pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
|
||||
dev_warn(&pdev->dev, "WARNING: SMBus interface set to new "
|
||||
"address 0x%04x!\n", vt596_smba);
|
||||
} else if ((temp & 1) == 0) {
|
||||
"address 0x%04x!\n", vt596_smba);
|
||||
} else if (!(temp & 0x01)) {
|
||||
if (force) {
|
||||
/* NOTE: This assumes I/O space and other allocations
|
||||
* WERE done by the Bios! Don't complain if your
|
||||
* hardware does weird things after enabling this.
|
||||
* :') Check for Bios updates before resorting to
|
||||
/* NOTE: This assumes I/O space and other allocations
|
||||
* WERE done by the Bios! Don't complain if your
|
||||
* hardware does weird things after enabling this.
|
||||
* :') Check for Bios updates before resorting to
|
||||
* this.
|
||||
*/
|
||||
pci_write_config_byte(pdev, SMBHSTCFG, temp | 1);
|
||||
pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
|
||||
dev_info(&pdev->dev, "Enabling SMBus device\n");
|
||||
} else {
|
||||
dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
|
||||
|
@ -367,22 +377,28 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
|
|||
}
|
||||
}
|
||||
|
||||
if ((temp & 0x0E) == 8)
|
||||
dev_dbg(&pdev->dev, "using Interrupt 9 for SMBus.\n");
|
||||
else if ((temp & 0x0E) == 0)
|
||||
dev_dbg(&pdev->dev, "using Interrupt SMI# for SMBus.\n");
|
||||
else
|
||||
dev_dbg(&pdev->dev, "Illegal Interrupt configuration "
|
||||
"(or code out of date)!\n");
|
||||
|
||||
pci_read_config_byte(pdev, SMBREV, &temp);
|
||||
dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp);
|
||||
dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
|
||||
|
||||
switch (pdev->device) {
|
||||
case PCI_DEVICE_ID_VIA_8237:
|
||||
case PCI_DEVICE_ID_VIA_8235:
|
||||
case PCI_DEVICE_ID_VIA_8233A:
|
||||
case PCI_DEVICE_ID_VIA_8233_0:
|
||||
vt596_features |= FEATURE_I2CBLOCK;
|
||||
break;
|
||||
case PCI_DEVICE_ID_VIA_82C686_4:
|
||||
/* The VT82C686B (rev 0x40) does support I2C block
|
||||
transactions, but the VT82C686A (rev 0x30) doesn't */
|
||||
if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
|
||||
&& temp >= 0x40)
|
||||
vt596_features |= FEATURE_I2CBLOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
vt596_adapter.dev.parent = &pdev->dev;
|
||||
snprintf(vt596_adapter.name, I2C_NAME_SIZE,
|
||||
"SMBus Via Pro adapter at %04x", vt596_smba);
|
||||
|
||||
"SMBus Via Pro adapter at %04x", vt596_smba);
|
||||
|
||||
vt596_pdev = pci_dev_get(pdev);
|
||||
if (i2c_add_adapter(&vt596_adapter)) {
|
||||
pci_dev_put(vt596_pdev);
|
||||
|
@ -395,7 +411,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
|
|||
*/
|
||||
return -ENODEV;
|
||||
|
||||
release_region:
|
||||
release_region:
|
||||
release_region(vt596_smba, 8);
|
||||
return error;
|
||||
}
|
||||
|
@ -420,9 +436,10 @@ static struct pci_device_id vt596_ids[] = {
|
|||
{ 0, }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE (pci, vt596_ids);
|
||||
MODULE_DEVICE_TABLE(pci, vt596_ids);
|
||||
|
||||
static struct pci_driver vt596_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "vt596_smbus",
|
||||
.id_table = vt596_ids,
|
||||
.probe = vt596_probe,
|
||||
|
|
|
@ -225,6 +225,7 @@ static void __devexit voodoo3_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver voodoo3_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "voodoo3_smbus",
|
||||
.id_table = voodoo3_ids,
|
||||
.probe = voodoo3_probe,
|
||||
|
|
|
@ -442,14 +442,13 @@ static int __init scx200_acb_create(int base, int index)
|
|||
int rc = 0;
|
||||
char description[64];
|
||||
|
||||
iface = kmalloc(sizeof(*iface), GFP_KERNEL);
|
||||
iface = kzalloc(sizeof(*iface), GFP_KERNEL);
|
||||
if (!iface) {
|
||||
printk(KERN_ERR NAME ": can't allocate memory\n");
|
||||
rc = -ENOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
memset(iface, 0, sizeof(*iface));
|
||||
adapter = &iface->adapter;
|
||||
i2c_set_adapdata(adapter, iface);
|
||||
snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index);
|
||||
|
|
|
@ -126,4 +126,13 @@ config SENSORS_MAX6875
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called max6875.
|
||||
|
||||
config RTC_X1205_I2C
|
||||
tristate "Xicor X1205 RTC chip"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get support for the Xicor X1205 RTC chip.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called x1205.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
|
|||
obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
|
||||
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
|
||||
obj-$(CONFIG_TPS65010) += tps65010.o
|
||||
obj-$(CONFIG_RTC_X1205_I2C) += x1205.o
|
||||
|
||||
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
|
|
|
@ -243,11 +243,10 @@ static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
I2C_FUNC_I2C))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct ds1337_data));
|
||||
INIT_LIST_HEAD(&data->list);
|
||||
|
||||
/* The common I2C client data is placed right before the
|
||||
|
|
|
@ -167,7 +167,8 @@ static void ds1374_set_tlet(ulong arg)
|
|||
|
||||
static ulong new_time;
|
||||
|
||||
DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet, (ulong) & new_time);
|
||||
static DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet,
|
||||
(ulong) & new_time);
|
||||
|
||||
int ds1374_set_rtc_time(ulong nowtime)
|
||||
{
|
||||
|
@ -193,13 +194,11 @@ static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
|
|||
struct i2c_client *client;
|
||||
int rc;
|
||||
|
||||
client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(client, 0, sizeof(struct i2c_client));
|
||||
strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE);
|
||||
client->flags = I2C_DF_NOTIFY;
|
||||
client->addr = addr;
|
||||
client->adapter = adap;
|
||||
client->driver = &ds1374_driver;
|
||||
|
|
|
@ -88,8 +88,8 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
|
|||
dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
|
||||
|
||||
if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
|
||||
for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_I2C_BLOCK_MAX)
|
||||
if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_I2C_BLOCK_MAX)
|
||||
for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_BLOCK_MAX)
|
||||
if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_BLOCK_MAX)
|
||||
goto exit;
|
||||
} else {
|
||||
if (i2c_smbus_write_byte(client, slice << 5)) {
|
||||
|
@ -155,7 +155,7 @@ static int eeprom_attach_adapter(struct i2c_adapter *adapter)
|
|||
}
|
||||
|
||||
/* This function is called by i2c_probe */
|
||||
int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
struct eeprom_data *data;
|
||||
|
@ -171,11 +171,10 @@ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
| I2C_FUNC_SMBUS_BYTE))
|
||||
goto exit;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct eeprom_data));
|
||||
|
||||
new_client = &data->client;
|
||||
memset(data->data, 0xff, EEPROM_SIZE);
|
||||
|
|
|
@ -888,6 +888,7 @@ static int otg_remove(struct device *dev)
|
|||
}
|
||||
|
||||
struct device_driver omap_otg_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "omap_otg",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = otg_probe,
|
||||
|
|
|
@ -174,13 +174,11 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
|
|||
struct i2c_client *client;
|
||||
int rc;
|
||||
|
||||
client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(client, 0, sizeof(struct i2c_client));
|
||||
strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE);
|
||||
client->flags = I2C_DF_NOTIFY;
|
||||
client->addr = addr;
|
||||
client->adapter = adap;
|
||||
client->driver = &m41t00_driver;
|
||||
|
|
|
@ -179,16 +179,14 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
if (address & 1)
|
||||
return 0;
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL)))
|
||||
if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
memset(data, 0, sizeof(struct max6875_data));
|
||||
|
||||
/* A fake client is created on the odd address */
|
||||
if (!(fake_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
|
||||
if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit_kfree1;
|
||||
}
|
||||
memset(fake_client, 0, sizeof(struct i2c_client));
|
||||
|
||||
/* Init real i2c_client */
|
||||
real_client = &data->client;
|
||||
|
|
|
@ -122,11 +122,10 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet. */
|
||||
if (!(data = kmalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct pca9539_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -115,7 +115,7 @@ static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
|
|||
}
|
||||
|
||||
/* This function is called by i2c_probe */
|
||||
int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
struct pcf8574_data *data;
|
||||
|
@ -127,11 +127,10 @@ int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet. */
|
||||
if (!(data = kmalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct pcf8574_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -166,7 +166,7 @@ static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
|
|||
}
|
||||
|
||||
/* This function is called by i2c_probe */
|
||||
int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *new_client;
|
||||
struct pcf8591_data *data;
|
||||
|
@ -178,11 +178,10 @@ int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
|
|||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet. */
|
||||
if (!(data = kmalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
|
||||
if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memset(data, 0, sizeof(struct pcf8591_data));
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
|
|
|
@ -148,17 +148,16 @@ static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
|
|||
{addr, I2C_M_RD, 2, data}
|
||||
};
|
||||
|
||||
d = kmalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
|
||||
d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
|
||||
if (!d) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
memset(d, 0, sizeof(struct rtc8564_data));
|
||||
new_client = &d->client;
|
||||
|
||||
strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
|
||||
i2c_set_clientdata(new_client, d);
|
||||
new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY;
|
||||
new_client->flags = I2C_CLIENT_ALLOW_USE;
|
||||
new_client->addr = addr;
|
||||
new_client->adapter = adap;
|
||||
new_client->driver = &rtc8564_driver;
|
||||
|
|
|
@ -500,11 +500,10 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
|
|||
return 0;
|
||||
}
|
||||
|
||||
tps = kmalloc(sizeof *tps, GFP_KERNEL);
|
||||
tps = kzalloc(sizeof *tps, GFP_KERNEL);
|
||||
if (!tps)
|
||||
return 0;
|
||||
|
||||
memset(tps, 0, sizeof *tps);
|
||||
init_MUTEX(&tps->lock);
|
||||
INIT_WORK(&tps->work, tps65010_work, tps);
|
||||
tps->irq = -1;
|
||||
|
|
698
drivers/i2c/chips/x1205.c
Normal file
698
drivers/i2c/chips/x1205.c
Normal file
|
@ -0,0 +1,698 @@
|
|||
/*
|
||||
* x1205.c - An i2c driver for the Xicor X1205 RTC
|
||||
* Copyright 2004 Karen Spearel
|
||||
* Copyright 2005 Alessandro Zummo
|
||||
*
|
||||
* please send all reports to:
|
||||
* kas11 at tampabay dot rr dot com
|
||||
* a dot zummo at towertech dot it
|
||||
*
|
||||
* based on the other drivers in this same directory.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <linux/x1205.h>
|
||||
|
||||
#define DRV_VERSION "0.9.9"
|
||||
|
||||
/* Addresses to scan: none. This chip is located at
|
||||
* 0x6f and uses a two bytes register addressing.
|
||||
* Two bytes need to be written to read a single register,
|
||||
* while most other chips just require one and take the second
|
||||
* one as the data to be written. To prevent corrupting
|
||||
* unknown chips, the user must explicitely set the probe parameter.
|
||||
*/
|
||||
|
||||
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
I2C_CLIENT_INSMOD;
|
||||
I2C_CLIENT_MODULE_PARM(hctosys,
|
||||
"Set the system time from the hardware clock upon initialization");
|
||||
|
||||
/* offsets into CCR area */
|
||||
|
||||
#define CCR_SEC 0
|
||||
#define CCR_MIN 1
|
||||
#define CCR_HOUR 2
|
||||
#define CCR_MDAY 3
|
||||
#define CCR_MONTH 4
|
||||
#define CCR_YEAR 5
|
||||
#define CCR_WDAY 6
|
||||
#define CCR_Y2K 7
|
||||
|
||||
#define X1205_REG_SR 0x3F /* status register */
|
||||
#define X1205_REG_Y2K 0x37
|
||||
#define X1205_REG_DW 0x36
|
||||
#define X1205_REG_YR 0x35
|
||||
#define X1205_REG_MO 0x34
|
||||
#define X1205_REG_DT 0x33
|
||||
#define X1205_REG_HR 0x32
|
||||
#define X1205_REG_MN 0x31
|
||||
#define X1205_REG_SC 0x30
|
||||
#define X1205_REG_DTR 0x13
|
||||
#define X1205_REG_ATR 0x12
|
||||
#define X1205_REG_INT 0x11
|
||||
#define X1205_REG_0 0x10
|
||||
#define X1205_REG_Y2K1 0x0F
|
||||
#define X1205_REG_DWA1 0x0E
|
||||
#define X1205_REG_YRA1 0x0D
|
||||
#define X1205_REG_MOA1 0x0C
|
||||
#define X1205_REG_DTA1 0x0B
|
||||
#define X1205_REG_HRA1 0x0A
|
||||
#define X1205_REG_MNA1 0x09
|
||||
#define X1205_REG_SCA1 0x08
|
||||
#define X1205_REG_Y2K0 0x07
|
||||
#define X1205_REG_DWA0 0x06
|
||||
#define X1205_REG_YRA0 0x05
|
||||
#define X1205_REG_MOA0 0x04
|
||||
#define X1205_REG_DTA0 0x03
|
||||
#define X1205_REG_HRA0 0x02
|
||||
#define X1205_REG_MNA0 0x01
|
||||
#define X1205_REG_SCA0 0x00
|
||||
|
||||
#define X1205_CCR_BASE 0x30 /* Base address of CCR */
|
||||
#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */
|
||||
|
||||
#define X1205_SR_RTCF 0x01 /* Clock failure */
|
||||
#define X1205_SR_WEL 0x02 /* Write Enable Latch */
|
||||
#define X1205_SR_RWEL 0x04 /* Register Write Enable */
|
||||
|
||||
#define X1205_DTR_DTR0 0x01
|
||||
#define X1205_DTR_DTR1 0x02
|
||||
#define X1205_DTR_DTR2 0x04
|
||||
|
||||
#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
|
||||
|
||||
/* Prototypes */
|
||||
static int x1205_attach(struct i2c_adapter *adapter);
|
||||
static int x1205_detach(struct i2c_client *client);
|
||||
static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
|
||||
static int x1205_command(struct i2c_client *client, unsigned int cmd,
|
||||
void *arg);
|
||||
|
||||
static struct i2c_driver x1205_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "x1205",
|
||||
.flags = I2C_DF_NOTIFY,
|
||||
.attach_adapter = &x1205_attach,
|
||||
.detach_client = &x1205_detach,
|
||||
};
|
||||
|
||||
struct x1205_data {
|
||||
struct i2c_client client;
|
||||
struct list_head list;
|
||||
unsigned int epoch;
|
||||
};
|
||||
|
||||
static const unsigned char days_in_mo[] =
|
||||
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
static LIST_HEAD(x1205_clients);
|
||||
|
||||
/* Workaround until the I2C subsytem will allow to send
|
||||
* commands to a specific client. This function will send the command
|
||||
* to the first client.
|
||||
*/
|
||||
int x1205_do_command(unsigned int cmd, void *arg)
|
||||
{
|
||||
struct list_head *walk;
|
||||
struct list_head *tmp;
|
||||
struct x1205_data *data;
|
||||
|
||||
list_for_each_safe(walk, tmp, &x1205_clients) {
|
||||
data = list_entry(walk, struct x1205_data, list);
|
||||
return x1205_command(&data->client, cmd, arg);
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#define is_leap(year) \
|
||||
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
|
||||
|
||||
/* make sure the rtc_time values are in bounds */
|
||||
static int x1205_validate_tm(struct rtc_time *tm)
|
||||
{
|
||||
int year = tm->tm_year + 1900;
|
||||
|
||||
if ((tm->tm_year < 70) || (tm->tm_year > 255))
|
||||
return -EINVAL;
|
||||
|
||||
if ((tm->tm_mon > 11) || (tm->tm_mday == 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (tm->tm_mday > days_in_mo[tm->tm_mon]
|
||||
+ ((tm->tm_mon == 1) && is_leap(year)))
|
||||
return -EINVAL;
|
||||
|
||||
if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the routines that deal directly with the x1205 hardware, we use
|
||||
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
|
||||
* Epoch is initialized as 2000. Time is set to UTC.
|
||||
*/
|
||||
static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
|
||||
u8 reg_base)
|
||||
{
|
||||
unsigned char dt_addr[2] = { 0, reg_base };
|
||||
static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
|
||||
|
||||
unsigned char buf[8], sr;
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{ client->addr, 0, 2, sr_addr }, /* setup read ptr */
|
||||
{ client->addr, I2C_M_RD, 1, &sr }, /* read status */
|
||||
{ client->addr, 0, 2, dt_addr }, /* setup read ptr */
|
||||
{ client->addr, I2C_M_RD, 8, buf }, /* read date */
|
||||
};
|
||||
|
||||
struct x1205_data *data = i2c_get_clientdata(client);
|
||||
|
||||
/* read status register */
|
||||
if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
|
||||
dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* check for battery failure */
|
||||
if (sr & X1205_SR_RTCF) {
|
||||
dev_warn(&client->dev,
|
||||
"Clock had a power failure, you must set the date.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* read date registers */
|
||||
if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) {
|
||||
dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dev_dbg(&client->dev,
|
||||
"%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
|
||||
"mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
|
||||
__FUNCTION__,
|
||||
buf[0], buf[1], buf[2], buf[3],
|
||||
buf[4], buf[5], buf[6], buf[7]);
|
||||
|
||||
tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
|
||||
tm->tm_min = BCD2BIN(buf[CCR_MIN]);
|
||||
tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
|
||||
tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
|
||||
tm->tm_mon = BCD2BIN(buf[CCR_MONTH]);
|
||||
data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100;
|
||||
tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900;
|
||||
tm->tm_wday = buf[CCR_WDAY];
|
||||
|
||||
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
|
||||
"mday=%d, mon=%d, year=%d, wday=%d\n",
|
||||
__FUNCTION__,
|
||||
tm->tm_sec, tm->tm_min, tm->tm_hour,
|
||||
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
|
||||
int datetoo, u8 reg_base)
|
||||
{
|
||||
int i, err, xfer;
|
||||
|
||||
unsigned char buf[8];
|
||||
|
||||
static const unsigned char wel[3] = { 0, X1205_REG_SR,
|
||||
X1205_SR_WEL };
|
||||
|
||||
static const unsigned char rwel[3] = { 0, X1205_REG_SR,
|
||||
X1205_SR_WEL | X1205_SR_RWEL };
|
||||
|
||||
static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
|
||||
|
||||
struct x1205_data *data = i2c_get_clientdata(client);
|
||||
|
||||
/* check if all values in the tm struct are correct */
|
||||
if ((err = x1205_validate_tm(tm)) < 0)
|
||||
return err;
|
||||
|
||||
dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
|
||||
"mday=%d, mon=%d, year=%d, wday=%d\n",
|
||||
__FUNCTION__,
|
||||
tm->tm_sec, tm->tm_min, tm->tm_hour,
|
||||
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
|
||||
|
||||
buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
|
||||
buf[CCR_MIN] = BIN2BCD(tm->tm_min);
|
||||
|
||||
/* set hour and 24hr bit */
|
||||
buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
|
||||
|
||||
/* should we also set the date? */
|
||||
if (datetoo) {
|
||||
buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
|
||||
|
||||
/* month, 0 - 11 */
|
||||
buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);
|
||||
|
||||
/* year, since 1900 */
|
||||
buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch);
|
||||
buf[CCR_WDAY] = tm->tm_wday & 0x07;
|
||||
buf[CCR_Y2K] = BIN2BCD(data->epoch / 100);
|
||||
}
|
||||
|
||||
/* this sequence is required to unlock the chip */
|
||||
xfer = i2c_master_send(client, wel, 3);
|
||||
if (xfer != 3) {
|
||||
dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
xfer = i2c_master_send(client, rwel, 3);
|
||||
if (xfer != 3) {
|
||||
dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* write register's data */
|
||||
for (i = 0; i < (datetoo ? 8 : 3); i++) {
|
||||
unsigned char rdata[3] = { 0, reg_base + i, buf[i] };
|
||||
|
||||
xfer = i2c_master_send(client, rdata, 3);
|
||||
if (xfer != 3) {
|
||||
dev_err(&client->dev,
|
||||
"%s: xfer=%d addr=%02x, data=%02x\n",
|
||||
__FUNCTION__,
|
||||
xfer, rdata[1], rdata[2]);
|
||||
return -EIO;
|
||||
}
|
||||
};
|
||||
|
||||
/* disable further writes */
|
||||
xfer = i2c_master_send(client, diswe, 3);
|
||||
if (xfer != 3) {
|
||||
dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int x1205_get_dtrim(struct i2c_client *client, int *trim)
|
||||
{
|
||||
unsigned char dtr;
|
||||
static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR };
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{ client->addr, 0, 2, dtr_addr }, /* setup read ptr */
|
||||
{ client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */
|
||||
};
|
||||
|
||||
/* read dtr register */
|
||||
if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
|
||||
dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr);
|
||||
|
||||
*trim = 0;
|
||||
|
||||
if (dtr & X1205_DTR_DTR0)
|
||||
*trim += 20;
|
||||
|
||||
if (dtr & X1205_DTR_DTR1)
|
||||
*trim += 10;
|
||||
|
||||
if (dtr & X1205_DTR_DTR2)
|
||||
*trim = -*trim;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int x1205_get_atrim(struct i2c_client *client, int *trim)
|
||||
{
|
||||
s8 atr;
|
||||
static unsigned char atr_addr[2] = { 0, X1205_REG_ATR };
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{ client->addr, 0, 2, atr_addr }, /* setup read ptr */
|
||||
{ client->addr, I2C_M_RD, 1, &atr }, /* read atr */
|
||||
};
|
||||
|
||||
/* read atr register */
|
||||
if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
|
||||
dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr);
|
||||
|
||||
/* atr is a two's complement value on 6 bits,
|
||||
* perform sign extension. The formula is
|
||||
* Catr = (atr * 0.25pF) + 11.00pF.
|
||||
*/
|
||||
if (atr & 0x20)
|
||||
atr |= 0xC0;
|
||||
|
||||
dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr);
|
||||
|
||||
*trim = (atr * 250) + 11000;
|
||||
|
||||
dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int x1205_hctosys(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
|
||||
struct rtc_time tm;
|
||||
struct timespec tv;
|
||||
|
||||
err = x1205_command(client, X1205_CMD_GETDATETIME, &tm);
|
||||
|
||||
if (err) {
|
||||
dev_err(&client->dev,
|
||||
"Unable to set the system clock\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
|
||||
* whether it stores the most close value or the value with partial
|
||||
* seconds truncated. However, it is important that we use it to store
|
||||
* the truncated value. This is because otherwise it is necessary,
|
||||
* in an rtc sync function, to read both xtime.tv_sec and
|
||||
* xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
|
||||
* of >32bits is not possible. So storing the most close value would
|
||||
* slow down the sync API. So here we have the truncated value and
|
||||
* the best guess is to add 0.5s.
|
||||
*/
|
||||
|
||||
tv.tv_nsec = NSEC_PER_SEC >> 1;
|
||||
|
||||
/* WARNING: this is not the C library 'mktime' call, it is a built in
|
||||
* inline function from include/linux/time.h. It expects (requires)
|
||||
* the month to be in the range 1-12
|
||||
*/
|
||||
|
||||
tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1,
|
||||
tm.tm_mday, tm.tm_hour,
|
||||
tm.tm_min, tm.tm_sec);
|
||||
|
||||
do_settimeofday(&tv);
|
||||
|
||||
dev_info(&client->dev,
|
||||
"setting the system clock to %d-%d-%d %d:%d:%d\n",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1,
|
||||
tm.tm_mday, tm.tm_hour, tm.tm_min,
|
||||
tm.tm_sec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct x1205_limit
|
||||
{
|
||||
unsigned char reg;
|
||||
unsigned char mask;
|
||||
unsigned char min;
|
||||
unsigned char max;
|
||||
};
|
||||
|
||||
static int x1205_validate_client(struct i2c_client *client)
|
||||
{
|
||||
int i, xfer;
|
||||
|
||||
/* Probe array. We will read the register at the specified
|
||||
* address and check if the given bits are zero.
|
||||
*/
|
||||
static const unsigned char probe_zero_pattern[] = {
|
||||
/* register, mask */
|
||||
X1205_REG_SR, 0x18,
|
||||
X1205_REG_DTR, 0xF8,
|
||||
X1205_REG_ATR, 0xC0,
|
||||
X1205_REG_INT, 0x18,
|
||||
X1205_REG_0, 0xFF,
|
||||
};
|
||||
|
||||
static const struct x1205_limit probe_limits_pattern[] = {
|
||||
/* register, mask, min, max */
|
||||
{ X1205_REG_Y2K, 0xFF, 19, 20 },
|
||||
{ X1205_REG_DW, 0xFF, 0, 6 },
|
||||
{ X1205_REG_YR, 0xFF, 0, 99 },
|
||||
{ X1205_REG_MO, 0xFF, 0, 12 },
|
||||
{ X1205_REG_DT, 0xFF, 0, 31 },
|
||||
{ X1205_REG_HR, 0x7F, 0, 23 },
|
||||
{ X1205_REG_MN, 0xFF, 0, 59 },
|
||||
{ X1205_REG_SC, 0xFF, 0, 59 },
|
||||
{ X1205_REG_Y2K1, 0xFF, 19, 20 },
|
||||
{ X1205_REG_Y2K0, 0xFF, 19, 20 },
|
||||
};
|
||||
|
||||
/* check that registers have bits a 0 where expected */
|
||||
for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) {
|
||||
unsigned char buf;
|
||||
|
||||
unsigned char addr[2] = { 0, probe_zero_pattern[i] };
|
||||
|
||||
struct i2c_msg msgs[2] = {
|
||||
{ client->addr, 0, 2, addr },
|
||||
{ client->addr, I2C_M_RD, 1, &buf },
|
||||
};
|
||||
|
||||
xfer = i2c_transfer(client->adapter, msgs, 2);
|
||||
if (xfer != 2) {
|
||||
dev_err(&client->adapter->dev,
|
||||
"%s: could not read register %x\n",
|
||||
__FUNCTION__, addr[1]);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((buf & probe_zero_pattern[i+1]) != 0) {
|
||||
dev_err(&client->adapter->dev,
|
||||
"%s: register=%02x, zero pattern=%d, value=%x\n",
|
||||
__FUNCTION__, addr[1], i, buf);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
/* check limits (only registers with bcd values) */
|
||||
for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) {
|
||||
unsigned char reg, value;
|
||||
|
||||
unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
|
||||
|
||||
struct i2c_msg msgs[2] = {
|
||||
{ client->addr, 0, 2, addr },
|
||||
{ client->addr, I2C_M_RD, 1, ® },
|
||||
};
|
||||
|
||||
xfer = i2c_transfer(client->adapter, msgs, 2);
|
||||
|
||||
if (xfer != 2) {
|
||||
dev_err(&client->adapter->dev,
|
||||
"%s: could not read register %x\n",
|
||||
__FUNCTION__, addr[1]);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
value = BCD2BIN(reg & probe_limits_pattern[i].mask);
|
||||
|
||||
if (value > probe_limits_pattern[i].max ||
|
||||
value < probe_limits_pattern[i].min) {
|
||||
dev_dbg(&client->adapter->dev,
|
||||
"%s: register=%x, lim pattern=%d, value=%d\n",
|
||||
__FUNCTION__, addr[1], i, value);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int x1205_attach(struct i2c_adapter *adapter)
|
||||
{
|
||||
dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
|
||||
|
||||
return i2c_probe(adapter, &addr_data, x1205_probe);
|
||||
}
|
||||
|
||||
int x1205_direct_attach(int adapter_id,
|
||||
struct i2c_client_address_data *address_data)
|
||||
{
|
||||
int err;
|
||||
struct i2c_adapter *adapter = i2c_get_adapter(adapter_id);
|
||||
|
||||
if (adapter) {
|
||||
err = i2c_probe(adapter,
|
||||
address_data, x1205_probe);
|
||||
|
||||
i2c_put_adapter(adapter);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
struct i2c_client *client;
|
||||
struct x1205_data *data;
|
||||
|
||||
int err = 0;
|
||||
|
||||
dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
|
||||
err = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize our structures */
|
||||
data->epoch = 2000;
|
||||
|
||||
client = &data->client;
|
||||
client->addr = address;
|
||||
client->driver = &x1205_driver;
|
||||
client->adapter = adapter;
|
||||
|
||||
strlcpy(client->name, "x1205", I2C_NAME_SIZE);
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
/* Verify the chip is really an X1205 */
|
||||
if (kind < 0) {
|
||||
if (x1205_validate_client(client) < 0) {
|
||||
err = -ENODEV;
|
||||
goto exit_kfree;
|
||||
}
|
||||
}
|
||||
|
||||
/* Inform the i2c layer */
|
||||
if ((err = i2c_attach_client(client)))
|
||||
goto exit_kfree;
|
||||
|
||||
list_add(&data->list, &x1205_clients);
|
||||
|
||||
dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
|
||||
|
||||
/* If requested, set the system time */
|
||||
if (hctosys)
|
||||
x1205_hctosys(client);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_kfree:
|
||||
kfree(data);
|
||||
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int x1205_detach(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
struct x1205_data *data = i2c_get_clientdata(client);
|
||||
|
||||
dev_dbg(&client->dev, "%s\n", __FUNCTION__);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
list_del(&data->list);
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int x1205_command(struct i2c_client *client, unsigned int cmd,
|
||||
void *param)
|
||||
{
|
||||
if (param == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (!capable(CAP_SYS_TIME))
|
||||
return -EACCES;
|
||||
|
||||
dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case X1205_CMD_GETDATETIME:
|
||||
return x1205_get_datetime(client, param, X1205_CCR_BASE);
|
||||
|
||||
case X1205_CMD_SETTIME:
|
||||
return x1205_set_datetime(client, param, 0,
|
||||
X1205_CCR_BASE);
|
||||
|
||||
case X1205_CMD_SETDATETIME:
|
||||
return x1205_set_datetime(client, param, 1,
|
||||
X1205_CCR_BASE);
|
||||
|
||||
case X1205_CMD_GETALARM:
|
||||
return x1205_get_datetime(client, param, X1205_ALM0_BASE);
|
||||
|
||||
case X1205_CMD_SETALARM:
|
||||
return x1205_set_datetime(client, param, 1,
|
||||
X1205_ALM0_BASE);
|
||||
|
||||
case X1205_CMD_GETDTRIM:
|
||||
return x1205_get_dtrim(client, param);
|
||||
|
||||
case X1205_CMD_GETATRIM:
|
||||
return x1205_get_atrim(client, param);
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int __init x1205_init(void)
|
||||
{
|
||||
return i2c_add_driver(&x1205_driver);
|
||||
}
|
||||
|
||||
static void __exit x1205_exit(void)
|
||||
{
|
||||
i2c_del_driver(&x1205_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR(
|
||||
"Karen Spearel <kas11@tampabay.rr.com>, "
|
||||
"Alessandro Zummo <a.zummo@towertech.it>");
|
||||
MODULE_DESCRIPTION("Xicor X1205 RTC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
EXPORT_SYMBOL_GPL(x1205_do_command);
|
||||
EXPORT_SYMBOL_GPL(x1205_direct_attach);
|
||||
|
||||
module_init(x1205_init);
|
||||
module_exit(x1205_exit);
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
|
||||
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
|
||||
SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> */
|
||||
SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and
|
||||
Jean Delvare <khali@linux-fr.org> */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -85,6 +86,7 @@ void i2c_adapter_dev_release(struct device *dev)
|
|||
}
|
||||
|
||||
struct device_driver i2c_adapter_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i2c_adapter",
|
||||
.bus = &i2c_bus_type,
|
||||
.probe = i2c_device_probe,
|
||||
|
@ -98,6 +100,7 @@ static void i2c_adapter_class_dev_release(struct class_device *dev)
|
|||
}
|
||||
|
||||
struct class i2c_adapter_class = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i2c-adapter",
|
||||
.release = &i2c_adapter_class_dev_release,
|
||||
};
|
||||
|
@ -291,6 +294,7 @@ int i2c_add_driver(struct i2c_driver *driver)
|
|||
down(&core_lists);
|
||||
|
||||
/* add the driver to the list of i2c drivers in the driver core */
|
||||
driver->driver.owner = driver->owner;
|
||||
driver->driver.name = driver->name;
|
||||
driver->driver.bus = &i2c_bus_type;
|
||||
driver->driver.probe = i2c_device_probe;
|
||||
|
@ -706,10 +710,6 @@ int i2c_probe(struct i2c_adapter *adapter,
|
|||
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;
|
||||
|
||||
/* Force entries are done first, and are not affected by ignore
|
||||
entries */
|
||||
if (address_data->forces) {
|
||||
|
@ -736,6 +736,17 @@ int i2c_probe(struct i2c_adapter *adapter,
|
|||
}
|
||||
}
|
||||
|
||||
/* Stop here if we can't use SMBUS_QUICK */
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
|
||||
if (address_data->probe[0] == I2C_CLIENT_END
|
||||
&& address_data->normal_i2c[0] == I2C_CLIENT_END)
|
||||
return 0;
|
||||
|
||||
dev_warn(&adapter->dev, "SMBus Quick command not supported, "
|
||||
"can't probe for chips\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
|
@ -820,101 +831,44 @@ crc8(u16 data)
|
|||
return (u8)(data >> 8);
|
||||
}
|
||||
|
||||
/* CRC over count bytes in the first array plus the bytes in the rest
|
||||
array if it is non-null. rest[0] is the (length of rest) - 1
|
||||
and is included. */
|
||||
static u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
|
||||
/* Incremental CRC8 over count bytes in the array pointed to by p */
|
||||
static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < count; i++)
|
||||
crc = crc8((crc ^ first[i]) << 8);
|
||||
if(rest != NULL)
|
||||
for(i = 0; i <= rest[0]; i++)
|
||||
crc = crc8((crc ^ rest[i]) << 8);
|
||||
crc = crc8((crc ^ p[i]) << 8);
|
||||
return crc;
|
||||
}
|
||||
|
||||
static u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
|
||||
/* Assume a 7-bit address, which is reasonable for SMBus */
|
||||
static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg)
|
||||
{
|
||||
return i2c_smbus_partial_pec(0, count, first, rest);
|
||||
/* The address will be sent first */
|
||||
u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD);
|
||||
pec = i2c_smbus_pec(pec, &addr, 1);
|
||||
|
||||
/* The data buffer follows */
|
||||
return i2c_smbus_pec(pec, msg->buf, msg->len);
|
||||
}
|
||||
|
||||
/* Returns new "size" (transaction type)
|
||||
Note that we convert byte to byte_data and byte_data to word_data
|
||||
rather than invent new xxx_PEC transactions. */
|
||||
static int i2c_smbus_add_pec(u16 addr, u8 command, int size,
|
||||
union i2c_smbus_data *data)
|
||||
/* Used for write only transactions */
|
||||
static inline void i2c_smbus_add_pec(struct i2c_msg *msg)
|
||||
{
|
||||
u8 buf[3];
|
||||
|
||||
buf[0] = addr << 1;
|
||||
buf[1] = command;
|
||||
switch(size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
data->byte = i2c_smbus_pec(2, buf, NULL);
|
||||
size = I2C_SMBUS_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
buf[2] = data->byte;
|
||||
data->word = buf[2] ||
|
||||
(i2c_smbus_pec(3, buf, NULL) << 8);
|
||||
size = I2C_SMBUS_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
/* unsupported */
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
data->block[data->block[0] + 1] =
|
||||
i2c_smbus_pec(2, buf, data->block);
|
||||
size = I2C_SMBUS_BLOCK_DATA_PEC;
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg);
|
||||
msg->len++;
|
||||
}
|
||||
|
||||
static int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
|
||||
union i2c_smbus_data *data)
|
||||
/* Return <0 on CRC error
|
||||
If there was a write before this read (most cases) we need to take the
|
||||
partial CRC from the write part into account.
|
||||
Note that this function does modify the message (we need to decrease the
|
||||
message length to hide the CRC byte from the caller). */
|
||||
static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
|
||||
{
|
||||
u8 buf[3], rpec, cpec;
|
||||
u8 rpec = msg->buf[--msg->len];
|
||||
cpec = i2c_smbus_msg_pec(cpec, msg);
|
||||
|
||||
buf[1] = command;
|
||||
switch(size) {
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
buf[0] = (addr << 1) | 1;
|
||||
cpec = i2c_smbus_pec(2, buf, NULL);
|
||||
rpec = data->byte;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
buf[0] = (addr << 1) | 1;
|
||||
buf[2] = data->word & 0xff;
|
||||
cpec = i2c_smbus_pec(3, buf, NULL);
|
||||
rpec = data->word >> 8;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA_PEC:
|
||||
/* unsupported */
|
||||
cpec = rpec = 0;
|
||||
break;
|
||||
case I2C_SMBUS_PROC_CALL_PEC:
|
||||
/* unsupported */
|
||||
cpec = rpec = 0;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA_PEC:
|
||||
buf[0] = (addr << 1);
|
||||
buf[2] = (addr << 1) | 1;
|
||||
cpec = i2c_smbus_pec(3, buf, data->block);
|
||||
rpec = data->block[data->block[0] + 1];
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
|
||||
buf[0] = (addr << 1) | 1;
|
||||
rpec = i2c_smbus_partial_pec(partial, 1,
|
||||
buf, data->block);
|
||||
cpec = data->block[data->block[0] + 1];
|
||||
break;
|
||||
default:
|
||||
cpec = rpec = 0;
|
||||
break;
|
||||
}
|
||||
if (rpec != cpec) {
|
||||
pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n",
|
||||
rpec, cpec);
|
||||
|
@ -941,9 +895,8 @@ s32 i2c_smbus_read_byte(struct i2c_client *client)
|
|||
|
||||
s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
|
||||
{
|
||||
union i2c_smbus_data data; /* only for PEC */
|
||||
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
|
||||
I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
|
||||
I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
|
||||
}
|
||||
|
||||
s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
|
||||
|
@ -1026,13 +979,14 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
|
|||
need to use only one message; when reading, we need two. We initialize
|
||||
most things with sane defaults, to keep the code below somewhat
|
||||
simpler. */
|
||||
unsigned char msgbuf0[34];
|
||||
unsigned char msgbuf1[34];
|
||||
unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
|
||||
unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
|
||||
int num = read_write == I2C_SMBUS_READ?2:1;
|
||||
struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
|
||||
{ addr, flags | I2C_M_RD, 0, msgbuf1 }
|
||||
};
|
||||
int i;
|
||||
u8 partial_pec = 0;
|
||||
|
||||
msgbuf0[0] = command;
|
||||
switch(size) {
|
||||
|
@ -1075,7 +1029,6 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
|
|||
msgbuf0[2] = (data->word >> 8) & 0xff;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
case I2C_SMBUS_BLOCK_DATA_PEC:
|
||||
if (read_write == I2C_SMBUS_READ) {
|
||||
dev_err(&adapter->dev, "Block read not supported "
|
||||
"under I2C emulation!\n");
|
||||
|
@ -1088,23 +1041,20 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
|
|||
data->block[0]);
|
||||
return -1;
|
||||
}
|
||||
if(size == I2C_SMBUS_BLOCK_DATA_PEC)
|
||||
(msg[0].len)++;
|
||||
for (i = 1; i <= msg[0].len; i++)
|
||||
for (i = 1; i < msg[0].len; i++)
|
||||
msgbuf0[i] = data->block[i-1];
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL:
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
|
||||
dev_dbg(&adapter->dev, "Block process call not supported "
|
||||
"under I2C emulation!\n");
|
||||
return -1;
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
if (read_write == I2C_SMBUS_READ) {
|
||||
msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;
|
||||
msg[1].len = I2C_SMBUS_BLOCK_MAX;
|
||||
} else {
|
||||
msg[0].len = data->block[0] + 1;
|
||||
if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 1) {
|
||||
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
|
||||
dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with "
|
||||
"invalid block write size (%d)\n",
|
||||
data->block[0]);
|
||||
|
@ -1120,9 +1070,30 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
|
|||
return -1;
|
||||
}
|
||||
|
||||
i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
|
||||
&& size != I2C_SMBUS_I2C_BLOCK_DATA);
|
||||
if (i) {
|
||||
/* Compute PEC if first message is a write */
|
||||
if (!(msg[0].flags & I2C_M_RD)) {
|
||||
if (num == 1) /* Write only */
|
||||
i2c_smbus_add_pec(&msg[0]);
|
||||
else /* Write followed by read */
|
||||
partial_pec = i2c_smbus_msg_pec(0, &msg[0]);
|
||||
}
|
||||
/* Ask for PEC if last message is a read */
|
||||
if (msg[num-1].flags & I2C_M_RD)
|
||||
msg[num-1].len++;
|
||||
}
|
||||
|
||||
if (i2c_transfer(adapter, msg, num) < 0)
|
||||
return -1;
|
||||
|
||||
/* Check PEC if last message is a read */
|
||||
if (i && (msg[num-1].flags & I2C_M_RD)) {
|
||||
if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read_write == I2C_SMBUS_READ)
|
||||
switch(size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
|
@ -1137,8 +1108,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
|
|||
break;
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
/* fixed at 32 for now */
|
||||
data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;
|
||||
for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++)
|
||||
data->block[0] = I2C_SMBUS_BLOCK_MAX;
|
||||
for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
|
||||
data->block[i+1] = msgbuf1[i];
|
||||
break;
|
||||
}
|
||||
|
@ -1151,28 +1122,8 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
|
|||
union i2c_smbus_data * data)
|
||||
{
|
||||
s32 res;
|
||||
int swpec = 0;
|
||||
u8 partial = 0;
|
||||
|
||||
flags &= I2C_M_TEN | I2C_CLIENT_PEC;
|
||||
if((flags & I2C_CLIENT_PEC) &&
|
||||
!(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) {
|
||||
swpec = 1;
|
||||
if(read_write == I2C_SMBUS_READ &&
|
||||
size == I2C_SMBUS_BLOCK_DATA)
|
||||
size = I2C_SMBUS_BLOCK_DATA_PEC;
|
||||
else if(size == I2C_SMBUS_PROC_CALL)
|
||||
size = I2C_SMBUS_PROC_CALL_PEC;
|
||||
else if(size == I2C_SMBUS_BLOCK_PROC_CALL) {
|
||||
i2c_smbus_add_pec(addr, command,
|
||||
I2C_SMBUS_BLOCK_DATA, data);
|
||||
partial = data->block[data->block[0] + 1];
|
||||
size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;
|
||||
} else if(read_write == I2C_SMBUS_WRITE &&
|
||||
size != I2C_SMBUS_QUICK &&
|
||||
size != I2C_SMBUS_I2C_BLOCK_DATA)
|
||||
size = i2c_smbus_add_pec(addr, command, size, data);
|
||||
}
|
||||
|
||||
if (adapter->algo->smbus_xfer) {
|
||||
down(&adapter->bus_lock);
|
||||
|
@ -1183,13 +1134,6 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
|
|||
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
|
||||
command,size,data);
|
||||
|
||||
if(res >= 0 && swpec &&
|
||||
size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA &&
|
||||
(read_write == I2C_SMBUS_READ || size == I2C_SMBUS_PROC_CALL_PEC ||
|
||||
size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
|
||||
if(i2c_smbus_check_pec(addr, command, size, partial, data))
|
||||
return -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,15 +26,11 @@
|
|||
|
||||
/* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
|
||||
|
||||
/* The devfs code is contributed by Philipp Matthias Hahn
|
||||
<pmhahn@titan.lahn.de> */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
|
@ -80,10 +76,9 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
|
|||
{
|
||||
struct i2c_dev *i2c_dev;
|
||||
|
||||
i2c_dev = kmalloc(sizeof(*i2c_dev), GFP_KERNEL);
|
||||
i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
|
||||
if (!i2c_dev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
memset(i2c_dev, 0x00, sizeof(*i2c_dev));
|
||||
|
||||
spin_lock(&i2c_dev_array_lock);
|
||||
if (i2c_dev_array[adap->nr]) {
|
||||
|
@ -177,8 +172,8 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
|
|||
int i,datasize,res;
|
||||
unsigned long funcs;
|
||||
|
||||
dev_dbg(&client->adapter->dev, "i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
|
||||
iminor(inode),cmd, arg);
|
||||
dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
|
||||
cmd, arg);
|
||||
|
||||
switch ( cmd ) {
|
||||
case I2C_SLAVE:
|
||||
|
@ -432,8 +427,6 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
|
|||
if (IS_ERR(i2c_dev))
|
||||
return PTR_ERR(i2c_dev);
|
||||
|
||||
devfs_mk_cdev(MKDEV(I2C_MAJOR, i2c_dev->minor),
|
||||
S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i2c_dev->minor);
|
||||
pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
|
||||
adap->name, i2c_dev->minor);
|
||||
|
||||
|
@ -466,7 +459,6 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
|
|||
return -ENODEV;
|
||||
|
||||
init_completion(&i2c_dev->released);
|
||||
devfs_remove("i2c/%d", i2c_dev->minor);
|
||||
return_i2c_dev(i2c_dev);
|
||||
class_device_unregister(&i2c_dev->class_dev);
|
||||
wait_for_completion(&i2c_dev->released);
|
||||
|
@ -522,8 +514,6 @@ static int __init i2c_dev_init(void)
|
|||
if (res)
|
||||
goto out_unreg_class;
|
||||
|
||||
devfs_mk_dir("i2c");
|
||||
|
||||
return 0;
|
||||
|
||||
out_unreg_class:
|
||||
|
@ -539,7 +529,6 @@ static void __exit i2c_dev_exit(void)
|
|||
{
|
||||
i2c_del_driver(&i2cdev_driver);
|
||||
class_unregister(&i2c_dev_class);
|
||||
devfs_remove("i2c");
|
||||
unregister_chrdev(I2C_MAJOR,"i2c");
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
|
||||
Frodo Looijaard <frodol@dds.nl> */
|
||||
|
||||
/* $Id: i2c-algo-bit.h,v 1.10 2003/01/21 08:08:16 kmalkki Exp $ */
|
||||
|
||||
#ifndef _LINUX_I2C_ALGO_BIT_H
|
||||
#define _LINUX_I2C_ALGO_BIT_H
|
||||
|
||||
|
@ -46,8 +44,6 @@ struct i2c_algo_bit_data {
|
|||
int timeout; /* in jiffies */
|
||||
};
|
||||
|
||||
#define I2C_BIT_ADAP_MAX 16
|
||||
|
||||
int i2c_bit_add_bus(struct i2c_adapter *);
|
||||
int i2c_bit_del_bus(struct i2c_adapter *);
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ struct i2c_algo_pca_data {
|
|||
int (*wait_for_interrupt) (struct i2c_algo_pca_data *adap);
|
||||
};
|
||||
|
||||
#define I2C_PCA_ADAP_MAX 16
|
||||
|
||||
int i2c_pca_add_bus(struct i2c_adapter *);
|
||||
int i2c_pca_del_bus(struct i2c_adapter *);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue