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>
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'
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.
* 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)
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.
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
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.
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.
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>,
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
eeprom Raw EEPROM data in binary form.
Read only.
+
+pec Enable or disable PEC (SMBus only)
+ Read/Write
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.
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.
Supported adapters:
* Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH)
+ * Intel 82845G (GMCH)
Authors:
Frodo Looijaard <frodol@dds.nl>,
* 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
-----------------
-----------
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.
--- /dev/null
+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
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
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.
.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.
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
=================
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. */
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;
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;
}
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,
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
# Files to ignore in find ... statements
-RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg \) -prune -o
-export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg
+RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o
+export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git
# ===========================================================================
# Rules shared between *config targets and build targets
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 */
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);
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. */
.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;
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);
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;
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;
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);
}
}
-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;
}
}
-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;
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;
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;
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);
#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>
#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
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)
+/*** sysfs accessors ***/
+
+/* temperature */
+static ssize_t show_temp(struct device *dev, struct device_attribute *dummy,
+ char *buf)
{
- return i2c_smbus_read_byte_data(client, reg);
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp * 500); /* 9-bit value */
}
-static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
+static ssize_t show_max(struct device *dev, struct device_attribute *devattr,
+ char *buf)
{
- return i2c_smbus_write_byte_data(client, reg, value);
+ 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);
}
-/*** sysfs accessors ***/
+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;
+}
-/* 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; \
-}
-
-set_temp(temp_high, ADM9240_REG_TEMP_HIGH);
-set_temp(temp_hyst, ADM9240_REG_TEMP_HYST);
-
-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);
-
-show_in_offset(0);
-show_in_offset(1);
-show_in_offset(2);
-show_in_offset(3);
-show_in_offset(4);
-show_in_offset(5);
+#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);
+
+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 */
{
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
* - 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);
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);
-
-show_fan_offset(1);
-show_fan_offset(2);
+#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);
+
+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);
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));
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);
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;
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);
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);
}
/* 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) {
}
/* 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);
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);
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 */
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);
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 */
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;
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);
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);
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);
};
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);
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;
/* 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);
/* 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. */
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;
* 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);
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);
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);
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
/* 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);
}
/* 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;
}
/* 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;
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)
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;
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. */
/* 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);
/* 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);
}
/* 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;
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)
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);
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;
/* 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);
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. */
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 ;
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);
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);
}
-int lm85_read_value(struct i2c_client *client, u8 reg)
+static int lm85_read_value(struct i2c_client *client, u8 reg)
{
int res;
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 ;
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);
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. */
* 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.
*
* 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
* 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 };
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))
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. */
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
}
} 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;
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) {
&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:
*/
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 */
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
* 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);
-
- 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_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;
+
+ 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;
| 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 */
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. */
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);
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;
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);
superio_enter();
id = superio_inb(SUPERIO_REG_DEVID);
- if (id != 0x6f) {
+ if ((id != 0x6f) && (id != 0x81)) {
superio_exit();
return -ENODEV;
}
*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;
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>
* 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");
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;
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);
/* 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");
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,
}
/* 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)
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 !=
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 */
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);
return 0;
}
-/* Called when we have found a new VIA686A. Set limits, etc. */
static void via686a_init_client(struct i2c_client *client)
{
u8 reg;
* 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
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);
exit_free:
kfree(data);
exit_release:
- release_region(address, REGION_LENGTH);
+ release_region(address + REGION_OFFSET, REGION_LENGTH);
exit:
return err;
}
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;
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;
#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
#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 */
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;
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;
}
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);
ERROR2:
kfree(data);
ERROR1:
- release_region(address, WINB_EXTENT);
+ release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE);
ERROR0:
return err;
}
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;
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);
}
}
- 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);
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);
}
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) {
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);
return 0;
}
-/* Called when we have found a new W83781D. It should set limits, etc. */
static void
w83781d_init_client(struct i2c_client *client)
{
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;
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);
return 0;
}
-/* Called when we have found a new W83792D. It should set limits, etc. */
static void
w83792d_init_client(struct i2c_client *client)
{
#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 */
* 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
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
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. */
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)))
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;
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;
#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)
/* 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,
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.
/* -> 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);
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;
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id ali1535_ids[] = {
}
static struct pci_driver ali1535_driver = {
+ .owner = THIS_MODULE,
.name = "ali1535_smbus",
.id_table = ali1535_ids,
.probe = ali1535_probe,
#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)
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;
}
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),
/* 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)
{
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);
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id ali15x3_ids[] = {
}
static struct pci_driver ali15x3_driver = {
+ .owner = THIS_MODULE,
.name = "ali15x3_smbus",
.id_table = ali15x3_ids,
.probe = ali15x3_probe,
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;
#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
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
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;
}
static struct pci_driver amd756_driver = {
+ .owner = THIS_MODULE,
.name = "amd756_smbus",
.id_table = amd756_ids,
.probe = amd756_probe,
int size;
};
+static struct pci_driver amd8111_driver;
+
/*
* AMD PCI control registers definitions.
*/
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);
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;
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;
}
static struct pci_driver amd8111_driver = {
+ .owner = THIS_MODULE,
.name = "amd8111_smbus2",
.id_table = amd8111_ids,
.probe = amd8111_probe,
/* 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>
#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 */
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);
}
{
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);
.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);
/* 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;
}
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;
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;
}
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>");
static struct pci_driver hydra_driver = {
+ .owner = THIS_MODULE,
.name = "hydra_smbus",
.id_table = hydra_ids,
.probe = hydra_probe,
#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)
"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;
}
}
- 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;
/* 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;
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 {
}
outb_p(temp, SMBHSTSTS);
}
-#endif
result = 0;
END:
if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
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:
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);
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;
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 = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id i801_ids[] = {
}
static struct pci_driver i801_driver = {
+ .owner = THIS_MODULE,
.name = "i801_smbus",
.id_table = i801_ids,
.probe = i801_probe,
i810AB 7123
i810E 7125
i815 1132
+ i845G 2562
*/
#include <linux/kernel.h>
}
static struct pci_driver i810_driver = {
+ .owner = THIS_MODULE,
.name = "i810_smbus",
.id_table = i810_ids,
.probe = i810_probe,
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);
#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)
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) {
static struct device_driver iop3xx_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "IOP3xx-I2C",
.bus = &platform_bus_type,
.probe = iop3xx_i2c_probe,
/* 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;
#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;
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;
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;
}
static struct device_driver ixp2000_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "IXP2000-I2C",
.bus = &platform_bus_type,
.probe = ixp2000_i2c_probe,
#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;
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;
/*
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;
}
static struct device_driver ixp4xx_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "IXP4XX-I2C",
.bus = &platform_bus_type,
.probe = ixp4xx_i2c_probe,
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);
static struct macio_driver i2c_keywest_macio_driver =
{
+ .owner = THIS_MODULE,
.name = "i2c-keywest",
.match_table = i2c_keywest_match,
.probe = create_iface_macio,
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,
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;
/* 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,
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;
}
static struct device_driver mv64xxx_i2c_driver = {
+ .owner = THIS_MODULE,
.name = MV64XXX_I2C_CTLR_NAME,
.bus = &platform_bus_type,
.probe = mv64xxx_i2c_probe,
#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,
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
/* Return -1 on error. See smbus.h for more information */
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;
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;
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 */
}
static struct pci_driver nforce2_driver = {
+ .owner = THIS_MODULE,
.name = "nForce2_smbus",
.id_table = nforce2_ids,
.probe = nforce2_probe,
{
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",
}
}
-static struct parport_driver i2c_driver = {
+static struct parport_driver i2c_parport_driver = {
.name = "i2c-parport",
.attach = i2c_parport_attach,
.detach = i2c_parport_detach,
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>");
/* 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. "
/* 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[] = {
}
}
- 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;
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id piix4_ids[] = {
}
static struct pci_driver piix4_driver = {
+ .owner = THIS_MODULE,
.name = "piix4_smbus",
.id_table = piix4_ids,
.probe = piix4_probe,
}
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;
/*
* 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)
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);
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,
/* 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,
};
static struct device_driver s3c2440_i2c_driver = {
+ .owner = THIS_MODULE,
.name = "s3c2440-i2c",
.bus = &platform_bus_type,
.probe = s3c24xx_i2c_probe,
}
static struct pci_driver savage4_driver = {
+ .owner = THIS_MODULE,
.name = "savage4_smbus",
.id_table = savage4_ids,
.probe = savage4_probe,
/* 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)
{
/* 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;
static struct i2c_adapter sis5595_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
- .name = "unset",
.algo = &smbus_algorithm,
};
}
static struct pci_driver sis5595_driver = {
+ .owner = THIS_MODULE,
.name = "sis5595_smbus",
.id_table = sis5595_ids,
.probe = sis5595_probe,
#define SIS630_PCALL 0x04
#define SIS630_BLOCK_DATA 0x05
+static struct pci_driver sis630_driver;
+
/* insmod parameters */
static int high_clock;
static int force;
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[] = {
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;
static struct i2c_adapter sis630_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
- .name = "unset",
.algo = &smbus_algorithm,
};
static struct pci_driver sis630_driver = {
+ .owner = THIS_MODULE,
.name = "sis630_smbus",
.id_table = sis630_ids,
.probe = sis630_probe,
#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)
{
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
static struct pci_device_id sis96x_ids[] = {
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);
}
static struct pci_driver sis96x_driver = {
+ .owner = THIS_MODULE,
.name = "sis96x_smbus",
.id_table = sis96x_ids,
.probe = sis96x_probe,
/* 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
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;
}
static struct pci_driver vt586b_driver = {
+ .owner = THIS_MODULE,
.name = "vt586b_smbus",
.id_table = vt586b_ids,
.probe = vt586b_probe,
/*
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
*/
/*
- 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.
*/
#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>
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*/
-
-static unsigned short smb_cf_hstcfg = 0xD2;
+ We try to select the better one */
-#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
"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);
/* 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);
}
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))
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 = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
- .name = "unset",
};
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;
}
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 "
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;
}
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 "
}
}
- 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);
*/
return -ENODEV;
- release_region:
+release_region:
release_region(vt596_smba, 8);
return error;
}
{ 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,
}
static struct pci_driver voodoo3_driver = {
+ .owner = THIS_MODULE,
.name = "voodoo3_smbus",
.id_table = voodoo3_ids,
.probe = voodoo3_probe,
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);
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
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
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
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)
{
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;
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)) {
}
/* 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;
| 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);
}
struct device_driver omap_otg_driver = {
+ .owner = THIS_MODULE,
.name = "omap_otg",
.bus = &platform_bus_type,
.probe = otg_probe,
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;
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;
/* 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);
}
/* 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;
/* 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);
}
/* 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;
/* 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);
{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;
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;
--- /dev/null
+/*
+ * 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);
/* 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>
}
struct device_driver i2c_adapter_driver = {
+ .owner = THIS_MODULE,
.name = "i2c_adapter",
.bus = &i2c_bus_type,
.probe = i2c_device_probe,
}
struct class i2c_adapter_class = {
+ .owner = THIS_MODULE,
.name = "i2c-adapter",
.release = &i2c_adapter_class_dev_release,
};
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;
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) {
}
}
+ /* 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) {
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);
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)
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) {
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");
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]);
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:
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;
}
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);
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;
}
/* 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>
{
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]) {
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:
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);
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);
if (res)
goto out_unreg_class;
- devfs_mk_dir("i2c");
-
return 0;
out_unreg_class:
{
i2c_del_driver(&i2cdev_driver);
class_unregister(&i2c_dev_class);
- devfs_remove("i2c");
unregister_chrdev(I2C_MAJOR,"i2c");
}
readb(socket->base + 0x800 + reg + 1);
}
+static ssize_t show_yenta_registers(struct device *yentadev, struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *dev = to_pci_dev(yentadev);
+ struct yenta_socket *socket = pci_get_drvdata(dev);
+ int offset = 0, i;
+
+ offset = snprintf(buf, PAGE_SIZE, "CB registers:");
+ for (i = 0; i < 0x24; i += 4) {
+ unsigned val;
+ if (!(i & 15))
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i);
+ val = cb_readl(socket, i);
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, " %08x", val);
+ }
+
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n\nExCA registers:");
+ for (i = 0; i < 0x45; i++) {
+ unsigned char val;
+ if (!(i & 7)) {
+ if (i & 8) {
+ memcpy(buf + offset, " -", 2);
+ offset += 2;
+ } else
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i);
+ }
+ val = exca_readb(socket, i);
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, " %02x", val);
+ }
+ buf[offset++] = '\n';
+ return offset;
+}
+
+static DEVICE_ATTR(yenta_registers, S_IRUSR, show_yenta_registers, NULL);
+
/*
* Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
* on what kind of card is inserted..
{
struct yenta_socket *sock = pci_get_drvdata(dev);
+ /* Remove the register attributes */
+ device_remove_file(&dev->dev, &dev_attr_yenta_registers);
+
/* we don't want a dying socket registered */
pcmcia_unregister_socket(&sock->socket);
/* Register it with the pcmcia layer.. */
ret = pcmcia_register_socket(&socket->socket);
- if (ret == 0)
+ if (ret == 0) {
+ /* Add the yenta register attributes */
+ device_create_file(&dev->dev, &dev_attr_yenta_registers);
goto out;
+ }
unmap:
iounmap(socket->base);
kfree(rsv);
}
-static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
+static inline void ext3_show_quota_options(struct seq_file *seq, struct super_block *sb)
{
- struct super_block *sb = vfs->mnt_sb;
+#if defined(CONFIG_QUOTA)
struct ext3_sb_info *sbi = EXT3_SB(sb);
- if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
- seq_puts(seq, ",data=journal");
- else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA)
- seq_puts(seq, ",data=ordered");
- else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
- seq_puts(seq, ",data=writeback");
-
-#if defined(CONFIG_QUOTA)
if (sbi->s_jquota_fmt)
seq_printf(seq, ",jqfmt=%s",
(sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0");
if (sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)
seq_puts(seq, ",grpquota");
#endif
+}
+
+static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+ struct super_block *sb = vfs->mnt_sb;
+
+ if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
+ seq_puts(seq, ",data=journal");
+ else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA)
+ seq_puts(seq, ",data=ordered");
+ else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
+ seq_puts(seq, ",data=writeback");
+
+ ext3_show_quota_options(seq, sb);
return 0;
}
/* 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
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 *);
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 *);
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c-algo-pcf.h,v 1.8 2003/01/21 08:08:16 kmalkki Exp $ */
-
#ifndef _LINUX_I2C_ALGO_PCF_H
#define _LINUX_I2C_ALGO_PCF_H
int timeout;
};
-#define I2C_PCF_ADAP_MAX 16
-
int i2c_pcf_add_bus(struct i2c_adapter *);
int i2c_pcf_del_bus(struct i2c_adapter *);
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: i2c-dev.h,v 1.13 2003/01/21 08:08:16 kmalkki Exp $ */
-
#ifndef _LINUX_I2C_DEV_H
#define _LINUX_I2C_DEV_H
/* --- Bit algorithm adapters */
#define I2C_HW_B_LP 0x010000 /* Parallel port Philips style */
-#define I2C_HW_B_LPC 0x010001 /* Parallel port control reg. */
#define I2C_HW_B_SER 0x010002 /* Serial line interface */
-#define I2C_HW_B_ELV 0x010003 /* ELV Card */
-#define I2C_HW_B_VELLE 0x010004 /* Vellemann K8000 */
#define I2C_HW_B_BT848 0x010005 /* BT848 video boards */
#define I2C_HW_B_WNV 0x010006 /* Winnov Videums */
#define I2C_HW_B_VIA 0x010007 /* Via vt82c586b */
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c.h,v 1.68 2003/01/21 08:08:16 kmalkki Exp $ */
-
#ifndef _LINUX_I2C_H
#define _LINUX_I2C_H
#include <linux/module.h>
#include <linux/types.h>
#include <linux/i2c-id.h>
+#include <linux/mod_devicetable.h>
#include <linux/device.h> /* for struct device */
#include <asm/semaphore.h>
extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
u8 command, u16 value);
-/* Returns the number of bytes transferred */
extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
u8 command, u8 length,
u8 *values);
+/* Returns the number of read bytes */
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
u8 command, u8 *values);
#define I2C_FUNC_10BIT_ADDR 0x00000002
#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */
#define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC 0x00000800 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_PROC_CALL_PEC 0x00002000 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_QUICK 0x00010000
#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */
-#define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
I2C_FUNC_SMBUS_WRITE_BYTE)
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
#define I2C_FUNC_SMBUS_I2C_BLOCK_2 (I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2)
-#define I2C_FUNC_SMBUS_BLOCK_DATA_PEC (I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \
- I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC)
-#define I2C_FUNC_SMBUS_WORD_DATA_PEC (I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \
- I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC)
-
-#define I2C_FUNC_SMBUS_READ_BYTE_PEC I2C_FUNC_SMBUS_READ_BYTE_DATA
-#define I2C_FUNC_SMBUS_WRITE_BYTE_PEC I2C_FUNC_SMBUS_WRITE_BYTE_DATA
-#define I2C_FUNC_SMBUS_READ_BYTE_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA
-#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA_PEC I2C_FUNC_SMBUS_WRITE_WORD_DATA
-#define I2C_FUNC_SMBUS_BYTE_PEC I2C_FUNC_SMBUS_BYTE_DATA
-#define I2C_FUNC_SMBUS_BYTE_DATA_PEC I2C_FUNC_SMBUS_WORD_DATA
#define I2C_FUNC_SMBUS_EMUL (I2C_FUNC_SMBUS_QUICK | \
I2C_FUNC_SMBUS_BYTE | \
I2C_FUNC_SMBUS_WORD_DATA | \
I2C_FUNC_SMBUS_PROC_CALL | \
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
- I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \
I2C_FUNC_SMBUS_I2C_BLOCK)
/*
* Data for SMBus Messages
*/
#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
-#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */
union i2c_smbus_data {
__u8 byte;
__u16 word;
- __u8 block[I2C_SMBUS_BLOCK_MAX + 3]; /* block[0] is used for length */
- /* one more for read length in block process call */
- /* and one more for PEC */
+ __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
+ /* and one more for user-space compatibility */
};
/* smbus_access read or write markers */
#define I2C_SMBUS_BLOCK_DATA 5
#define I2C_SMBUS_I2C_BLOCK_DATA 6
#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
-#define I2C_SMBUS_BLOCK_DATA_PEC 8 /* SMBus 2.0 */
-#define I2C_SMBUS_PROC_CALL_PEC 9 /* SMBus 2.0 */
-#define I2C_SMBUS_BLOCK_PROC_CALL_PEC 10 /* SMBus 2.0 */
-#define I2C_SMBUS_WORD_DATA_PEC 11 /* SMBus 2.0 */
/* ----- commands for the ioctl like i2c_command call:
#define I2C_SMBUS 0x0720 /* SMBus-level access */
-/* ... algo-bit.c recognizes */
-#define I2C_UDELAY 0x0705 /* set delay in microsecs between each */
- /* written byte (except address) */
-#define I2C_MDELAY 0x0706 /* millisec delay between written bytes */
-
/* ----- I2C-DEV: char device interface stuff ------------------------- */
#define I2C_MAJOR 89 /* Device major number */
#define PCMCIA_DEV_ID_MATCH_FAKE_CIS 0x0200
#define PCMCIA_DEV_ID_MATCH_ANONYMOUS 0x0400
+/* I2C */
+struct i2c_device_id {
+ __u16 id;
+};
+
#endif /* LINUX_MOD_DEVICETABLE_H */
--- /dev/null
+/*
+ * x1205.h - defines for drivers/i2c/chips/x1205.c
+ * Copyright 2004 Karen Spearel
+ * Copyright 2005 Alessandro Zummo
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_X1205_H__
+#define __LINUX_X1205_H__
+
+/* commands */
+
+#define X1205_CMD_GETDATETIME 0
+#define X1205_CMD_SETTIME 1
+#define X1205_CMD_SETDATETIME 2
+#define X1205_CMD_GETALARM 3
+#define X1205_CMD_SETALARM 4
+#define X1205_CMD_GETDTRIM 5
+#define X1205_CMD_SETDTRIM 6
+#define X1205_CMD_GETATRIM 7
+#define X1205_CMD_SETATRIM 8
+
+extern int x1205_do_command(unsigned int cmd, void *arg);
+extern int x1205_direct_attach(int adapter_id,
+ struct i2c_client_address_data *address_data);
+
+#endif /* __LINUX_X1205_H__ */
#include <linux/videodev.h>
#include <linux/i2c.h>
-/* Remove these once they are officially defined */
-#ifndef I2C_DRIVERID_OVCAMCHIP
- #define I2C_DRIVERID_OVCAMCHIP 0xf00f
-#endif
-#ifndef I2C_HW_SMBUS_OV511
- #define I2C_HW_SMBUS_OV511 0xfe
-#endif
-#ifndef I2C_HW_SMBUS_OV518
- #define I2C_HW_SMBUS_OV518 0xff
-#endif
-#ifndef I2C_HW_SMBUS_OVFX2
- #define I2C_HW_SMBUS_OVFX2 0xfd
-#endif
-
/* --------------------------------- */
/* ENUMERATIONS */
/* --------------------------------- */
return 1;
}
+static int do_i2c_entry(const char *filename, struct i2c_device_id *i2c, char *alias)
+{
+ strcpy(alias, "i2c:");
+ ADD(alias, "id", 1, i2c->id);
+ return 1;
+}
+
/* Ignore any prefix, eg. v850 prepends _ */
static inline int sym_is(const char *symbol, const char *name)
{
else if (sym_is(symname, "__mod_vio_device_table"))
do_table(symval, sym->st_size, sizeof(struct vio_device_id),
do_vio_entry, mod);
+ else if (sym_is(symname, "__mod_i2c_device_table"))
+ do_table(symval, sym->st_size, sizeof(struct i2c_device_id),
+ do_i2c_entry, mod);
}