Hi,
Here are some i2c driver fixes and updates for 2.6.10. There are a few
new i2c drivers in here, and a number of bugfixes. Almost all of these
patches have been in the past few -mm releases.
Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.6
Individual patches will follow, sent to the sensors and linux-kernel
lists.
thanks,
greg k-h
Documentation/i2c/i2c-old-porting | 626 ---------------------------------
Documentation/i2c/chips/smsc47b397.txt | 146 +++++++
Documentation/i2c/i2c-stub | 9
Documentation/w1/w1.generic | 19 +
drivers/i2c/algos/Kconfig | 15
drivers/i2c/algos/Makefile | 2
drivers/i2c/algos/i2c-algo-bit.c | 4
drivers/i2c/algos/i2c-algo-pca.c | 4
drivers/i2c/algos/i2c-algo-pcf.c | 4
drivers/i2c/algos/i2c-algo-sgi.c | 189 +++++++++
drivers/i2c/algos/i2c-algo-sibyte.c | 231 ++++++++++++
drivers/i2c/busses/Kconfig | 16
drivers/i2c/busses/Makefile | 1
drivers/i2c/busses/i2c-ali1535.c | 7
drivers/i2c/busses/i2c-ali1563.c | 15
drivers/i2c/busses/i2c-ali15x3.c | 7
drivers/i2c/busses/i2c-amd756.c | 15
drivers/i2c/busses/i2c-amd8111.c | 2
drivers/i2c/busses/i2c-hydra.c | 7
drivers/i2c/busses/i2c-i801.c | 56 --
drivers/i2c/busses/i2c-iop3xx.c | 545 ++++++++++++++--------------
drivers/i2c/busses/i2c-iop3xx.h | 111 ++---
drivers/i2c/busses/i2c-nforce2.c | 15
drivers/i2c/busses/i2c-piix4.c | 54 --
drivers/i2c/busses/i2c-prosavage.c | 7
drivers/i2c/busses/i2c-sibyte.c | 71 +++
drivers/i2c/busses/i2c-sis96x.c | 12
drivers/i2c/busses/i2c-stub.c | 22 +
drivers/i2c/busses/i2c-viapro.c | 72 ---
drivers/i2c/chips/Kconfig | 12
drivers/i2c/chips/Makefile | 1
drivers/i2c/chips/asb100.c | 3
drivers/i2c/chips/eeprom.c | 19 -
drivers/i2c/chips/fscher.c | 11
drivers/i2c/chips/isp1301_omap.c | 9
drivers/i2c/chips/it87.c | 149 ++++++-
drivers/i2c/chips/lm78.c | 2
drivers/i2c/chips/lm90.c | 28 +
drivers/i2c/chips/pc87360.c | 3
drivers/i2c/chips/smsc47b397.c | 353 ++++++++++++++++++
drivers/i2c/chips/smsc47m1.c | 2
drivers/i2c/chips/via686a.c | 2
drivers/i2c/chips/w83627hf.c | 45 +-
drivers/i2c/chips/w83781d.c | 3
drivers/i2c/i2c-sensor-vid.c | 5
include/linux/i2c-algo-sgi.h | 27 +
include/linux/i2c-algo-sibyte.h | 33 +
include/linux/i2c-id.h | 16
include/linux/pci_ids.h | 16
49 files changed, 1772 insertions(+), 1251 deletions(-)
-----
<sjhill:realitydiluted.com>:
o I2C patch from MIPS tree
David Brownell:
o I2C: minor isp1301_omap tweaks
Deepak Saxena:
o Update IOP3xx I2C bus driver
Domen Puncer:
o it87: /proc/ioports fix
Evgeniy Polyakov:
o w1: Documentation bits for generic w1 behaviour
Ian Campbell:
o I2C: i2c-algo-bit should support I2C_FUNC_I2C
Jean Delvare:
o I2C: Update fscher pwm functionality
o I2C: Add byte commands to i2c-stub
o I2C: Fix MAX6657/8/9 detection in lm90
o I2C: Improve VID code for the W83627THF
o I2C: Add secondary Super-I/O address support to
o I2C: Remove checksum code in eeprom driver
o I2C: Use PCI_DEVICE in bus drivers
o I2C: Discard old driver porting documentation
o I2C: i2c-nforce2 supports the nForce3 250Gb
o I2C: i2c-algo-bit should support I2C_FUNC_I2C
o I2C: use chip driver name to request regions
Jonas Munsin:
o I2C: it87.c update
Ladislav Michl:
o I2C: let I2C_ALGO_SGI depend on MIPS
Mark M. Hoffman:
o I2C: add new sensors driver: SMSC LPC47B397-NC
o I2C: probe fewer addresses for asb100 (sensors) driver
Randy Dunlap:
o i2c-ali1563: fix init & exit section usage
Rudolf Marek:
o I2C: vid version detection fix
ChangeSet 1.1938.439.44, 2005/01/06 13:53:47-08:00, [email protected]
[PATCH] I2C: probe fewer addresses for asb100 (sensors) driver
This patch limits SMBus scanning for the asb100 sensor chip
to just one address - the only one we've ever seen in practice.
Signed-off-by Mark M. Hoffman <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/chips/asb100.c | 3 +--
1 files changed, 1 insertion(+), 2 deletions(-)
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c 2005-01-07 14:54:56 -08:00
+++ b/drivers/i2c/chips/asb100.c 2005-01-07 14:54:56 -08:00
@@ -56,8 +56,7 @@
#define ASB100_VERSION "1.0.0"
/* I2C addresses to scan */
-static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
- 0x2e, 0x2f, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
/* ISA addresses to scan (none) */
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
ChangeSet 1.1938.445.11, 2004/12/21 11:09:49-08:00, [email protected]
[PATCH] I2C: it87.c update
- adds manual PWM
- removes buggy "reset" module parameter
- fixes some whitespaces
Signed-off-by: Jonas Munsin <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/chips/it87.c | 147 +++++++++++++++++++++++++++++++++++++++++------
1 files changed, 130 insertions(+), 17 deletions(-)
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c 2005-01-07 14:55:04 -08:00
+++ b/drivers/i2c/chips/it87.c 2005-01-07 14:55:04 -08:00
@@ -96,9 +96,6 @@
/* Update battery voltage after every reading if true */
static int update_vbat;
-/* Reset the registers on init if true */
-static int reset;
-
/* Chip Type */
static u16 chip_type;
@@ -128,6 +125,8 @@
#define IT87_REG_FAN(nr) (0x0d + (nr))
#define IT87_REG_FAN_MIN(nr) (0x10 + (nr))
#define IT87_REG_FAN_MAIN_CTRL 0x13
+#define IT87_REG_FAN_CTL 0x14
+#define IT87_REG_PWM(nr) (0x15 + (nr))
#define IT87_REG_VIN(nr) (0x20 + (nr))
#define IT87_REG_TEMP(nr) (0x29 + (nr))
@@ -164,6 +163,9 @@
#define ALARMS_FROM_REG(val) (val)
+#define PWM_TO_REG(val) ((val) >> 1)
+#define PWM_FROM_REG(val) (((val)&0x7f) << 1)
+
static int DIV_TO_REG(int val)
{
int answer = 0;
@@ -200,6 +202,8 @@
u8 vid; /* Register encoding, combined */
int vrm;
u32 alarms; /* Register encoding, combined */
+ u8 fan_main_ctrl; /* Register value */
+ u8 manual_pwm_ctl[3]; /* manual PWM value set by user */
};
@@ -440,18 +444,28 @@
{
struct it87_data *data = it87_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
- DIV_FROM_REG(data->fan_div[nr])) );
+ DIV_FROM_REG(data->fan_div[nr])));
}
static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
{
struct it87_data *data = it87_update_device(dev);
return sprintf(buf,"%d\n",
- FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
+ FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])));
}
static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
{
struct it87_data *data = it87_update_device(dev);
- return sprintf(buf,"%d\n", DIV_FROM_REG(data->fan_div[nr]) );
+ return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
+}
+static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
+{
+ struct it87_data *data = it87_update_device(dev);
+ return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0);
+}
+static ssize_t show_pwm(struct device *dev, char *buf, int nr)
+{
+ struct it87_data *data = it87_update_device(dev);
+ return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]);
}
static ssize_t set_fan_min(struct device *dev, const char *buf,
size_t count, int nr)
@@ -499,6 +513,44 @@
}
return count;
}
+static ssize_t set_pwm_enable(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct it87_data *data = i2c_get_clientdata(client);
+ int val = simple_strtol(buf, NULL, 10);
+
+ if (val == 0) {
+ /* set on/off mode */
+ data->fan_main_ctrl &= ~(1 << nr);
+ it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
+ } else if (val == 1) {
+ /* set SmartGuardian mode */
+ data->fan_main_ctrl |= (1 << nr);
+ it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
+ /* set saved pwm value, clear FAN_CTLX PWM mode bit */
+ it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
+ } else
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t set_pwm(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct it87_data *data = i2c_get_clientdata(client);
+ int val = simple_strtol(buf, NULL, 10);
+
+ if (val < 0 || val > 255)
+ return -EINVAL;
+
+ data->manual_pwm_ctl[nr] = val;
+ if (data->fan_main_ctrl & (1 << nr))
+ it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
+
+ return count;
+}
#define show_fan_offset(offset) \
static ssize_t show_fan_##offset (struct device *dev, char *buf) \
@@ -533,6 +585,36 @@
show_fan_offset(2);
show_fan_offset(3);
+#define show_pwm_offset(offset) \
+static ssize_t show_pwm##offset##_enable (struct device *dev, \
+ char *buf) \
+{ \
+ return show_pwm_enable(dev, buf, offset - 1); \
+} \
+static ssize_t show_pwm##offset (struct device *dev, char *buf) \
+{ \
+ return show_pwm(dev, buf, offset - 1); \
+} \
+static ssize_t set_pwm##offset##_enable (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_pwm_enable(dev, buf, count, offset - 1); \
+} \
+static ssize_t set_pwm##offset (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_pwm(dev, buf, count, offset - 1); \
+} \
+static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
+ show_pwm##offset##_enable, \
+ set_pwm##offset##_enable); \
+static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
+ show_pwm##offset , set_pwm##offset );
+
+show_pwm_offset(1);
+show_pwm_offset(2);
+show_pwm_offset(3);
+
/* Alarms */
static ssize_t show_alarms(struct device *dev, char *buf)
{
@@ -774,6 +856,12 @@
device_create_file(&new_client->dev, &dev_attr_fan2_div);
device_create_file(&new_client->dev, &dev_attr_fan3_div);
device_create_file(&new_client->dev, &dev_attr_alarms);
+ device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
+ device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
+ device_create_file(&new_client->dev, &dev_attr_pwm3_enable);
+ device_create_file(&new_client->dev, &dev_attr_pwm1);
+ device_create_file(&new_client->dev, &dev_attr_pwm2);
+ device_create_file(&new_client->dev, &dev_attr_pwm3);
if (data->type == it8712) {
device_create_file_vrm(new_client);
@@ -851,12 +939,17 @@
/* Called when we have found a new IT87. */
static void it87_init_client(struct i2c_client *client, struct it87_data *data)
{
- int tmp;
+ int tmp, i;
- if (reset) {
- /* Reset all except Watchdog values and last conversion values
- This sets fan-divs to 2, among others */
- it87_write_value(client, IT87_REG_CONFIG, 0x80);
+ /* initialize to sane defaults:
+ * - if the chip is in manual pwm mode, this will be overwritten with
+ * the actual settings on the chip (so in this case, initialization
+ * is not needed)
+ * - if in automatic or on/off mode, we could switch to manual mode,
+ * read the registers and set manual_pwm_ctl accordingly, but currently
+ * this is not implemented, so we initialize to something sane */
+ for (i = 0; i < 3; i++) {
+ data->manual_pwm_ctl[i] = 0xff;
}
/* Check if temperature channnels are reset manually or by some reason */
@@ -876,13 +969,35 @@
}
/* Check if tachometers are reset manually or by some reason */
- tmp = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL);
- if ((tmp & 0x70) == 0) {
+ data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL);
+ if ((data->fan_main_ctrl & 0x70) == 0) {
/* Enable all fan tachometers */
- tmp = (tmp & 0x8f) | 0x70;
- it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, tmp);
+ data->fan_main_ctrl |= 0x70;
+ it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
}
+ /* Set current fan mode registers and the default settings for the
+ * other mode registers */
+ for (i = 0; i < 3; i++) {
+ if (data->fan_main_ctrl & (1 << i)) {
+ /* pwm mode */
+ tmp = it87_read_value(client, IT87_REG_PWM(i));
+ if (tmp & 0x80) {
+ /* automatic pwm - not yet implemented, but
+ * leave the settings made by the BIOS alone
+ * until a change is requested via the sysfs
+ * interface */
+ } else {
+ /* manual pwm */
+ data->manual_pwm_ctl[i] = PWM_FROM_REG(tmp);
+ }
+ }
+ }
+
+ /* make sure the fan is on when in on/off mode */
+ tmp = it87_read_value(client, IT87_REG_FAN_CTL);
+ it87_write_value(client, IT87_REG_FAN_CTL, tmp | 0x07);
+
/* Start monitoring */
it87_write_value(client, IT87_REG_CONFIG,
(it87_read_value(client, IT87_REG_CONFIG) & 0x36)
@@ -984,8 +1099,6 @@
MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver");
module_param(update_vbat, bool, 0);
MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
-module_param(reset, bool, 0);
-MODULE_PARM_DESC(reset, "Reset the chip's registers, default no");
MODULE_LICENSE("GPL");
module_init(sm_it87_init);
ChangeSet 1.1938.445.8, 2004/12/21 11:08:03-08:00, [email protected]
[PATCH] I2C: Use PCI_DEVICE in bus drivers
> Hint, the PCI_DEVICE() macro makes this a lot simpler :)
What about this cleanup patch then? It generalizes the use of
PCI_DEVICE() among i2c/busses drivers (with some pci ids cleanups for
free).
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/busses/i2c-ali1535.c | 7 ---
drivers/i2c/busses/i2c-ali1563.c | 7 ---
drivers/i2c/busses/i2c-ali15x3.c | 7 ---
drivers/i2c/busses/i2c-amd756.c | 15 +++++--
drivers/i2c/busses/i2c-amd8111.c | 2 -
drivers/i2c/busses/i2c-hydra.c | 7 ---
drivers/i2c/busses/i2c-i801.c | 56 ++++------------------------
drivers/i2c/busses/i2c-nforce2.c | 12 ++----
drivers/i2c/busses/i2c-piix4.c | 54 ++++++---------------------
drivers/i2c/busses/i2c-prosavage.c | 7 ---
drivers/i2c/busses/i2c-sis96x.c | 12 ------
drivers/i2c/busses/i2c-viapro.c | 72 ++++++++-----------------------------
include/linux/pci_ids.h | 6 +++
13 files changed, 62 insertions(+), 202 deletions(-)
diff -Nru a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
--- a/drivers/i2c/busses/i2c-ali1535.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-ali1535.c 2005-01-07 14:55:28 -08:00
@@ -487,12 +487,7 @@
};
static struct pci_device_id ali1535_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_AL,
- .device = PCI_DEVICE_ID_AL_M7101,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
{ },
};
diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
--- a/drivers/i2c/busses/i2c-ali1563.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-ali1563.c 2005-01-07 14:55:28 -08:00
@@ -385,12 +385,7 @@
}
static struct pci_device_id __devinitdata ali1563_id_table[] = {
- {
- .vendor = PCI_VENDOR_ID_AL,
- .device = PCI_DEVICE_ID_AL_M1563,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) },
{},
};
diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- a/drivers/i2c/busses/i2c-ali15x3.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-ali15x3.c 2005-01-07 14:55:28 -08:00
@@ -477,12 +477,7 @@
};
static struct pci_device_id ali15x3_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_AL,
- .device = PCI_DEVICE_ID_AL_M7101,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
{ 0, }
};
diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
--- a/drivers/i2c/busses/i2c-amd756.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-amd756.c 2005-01-07 14:55:28 -08:00
@@ -316,11 +316,16 @@
};
static struct pci_device_id amd756_ids[] = {
- {PCI_VENDOR_ID_AMD, 0x740B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD756 },
- {PCI_VENDOR_ID_AMD, 0x7413, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD766 },
- {PCI_VENDOR_ID_AMD, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768 },
- {PCI_VENDOR_ID_AMD, 0x746B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111 },
- {PCI_VENDOR_ID_NVIDIA, 0x01B4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B),
+ .driver_data = AMD756 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413),
+ .driver_data = AMD766 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443),
+ .driver_data = AMD768 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS),
+ .driver_data = AMD8111 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS),
+ .driver_data = NFORCE },
{ 0, }
};
diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
--- a/drivers/i2c/busses/i2c-amd8111.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-amd8111.c 2005-01-07 14:55:28 -08:00
@@ -332,7 +332,7 @@
static struct pci_device_id amd8111_ids[] = {
- { 0x1022, 0x746a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) },
{ 0, }
};
diff -Nru a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
--- a/drivers/i2c/busses/i2c-hydra.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-hydra.c 2005-01-07 14:55:28 -08:00
@@ -111,12 +111,7 @@
};
static struct pci_device_id hydra_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_APPLE,
- .device = PCI_DEVICE_ID_APPLE_HYDRA,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) },
{ 0, }
};
diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- a/drivers/i2c/busses/i2c-i801.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-i801.c 2005-01-07 14:55:28 -08:00
@@ -548,54 +548,14 @@
};
static struct pci_device_id i801_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801AA_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801AB_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801BA_2,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801CA_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801DB_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801EB_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_ESB_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_ICH6_16,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
{ 0, }
};
diff -Nru a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
--- a/drivers/i2c/busses/i2c-nforce2.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-nforce2.c 2005-01-07 14:55:28 -08:00
@@ -291,14 +291,10 @@
static struct pci_device_id nforce2_ids[] = {
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) },
{ 0 }
};
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-piix4.c 2005-01-07 14:55:28 -08:00
@@ -414,48 +414,18 @@
};
static struct pci_device_id piix4_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82371AB_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 3
- },
- {
- .vendor = PCI_VENDOR_ID_SERVERWORKS,
- .device = PCI_DEVICE_ID_SERVERWORKS_OSB4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 0,
- },
- {
- .vendor = PCI_VENDOR_ID_SERVERWORKS,
- .device = PCI_DEVICE_ID_SERVERWORKS_CSB5,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 0,
- },
- {
- .vendor = PCI_VENDOR_ID_SERVERWORKS,
- .device = PCI_DEVICE_ID_SERVERWORKS_CSB6,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 0,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82443MX_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 3,
- },
- {
- .vendor = PCI_VENDOR_ID_EFAR,
- .device = PCI_DEVICE_ID_EFAR_SLC90E66_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 0,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3),
+ .driver_data = 3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
+ .driver_data = 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
+ .driver_data = 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6),
+ .driver_data = 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3),
+ .driver_data = 3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3),
+ .driver_data = 0 },
{ 0, }
};
diff -Nru a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
--- a/drivers/i2c/busses/i2c-prosavage.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-prosavage.c 2005-01-07 14:55:28 -08:00
@@ -96,13 +96,6 @@
/*
* S3/VIA 8365/8375 registers
*/
-#ifndef PCI_DEVICE_ID_S3_SAVAGE4
-#define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25
-#endif
-#ifndef PCI_DEVICE_ID_S3_PROSAVAGE8
-#define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04
-#endif
-
#define VGA_CR_IX 0x3d4
#define VGA_CR_DATA 0x3d5
diff -Nru a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
--- a/drivers/i2c/busses/i2c-sis96x.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-sis96x.c 2005-01-07 14:55:28 -08:00
@@ -51,9 +51,6 @@
*/
#define SIS96x_VERSION "1.0.0"
-/* SiS96x SMBus PCI device ID */
-#define PCI_DEVICE_ID_SI_SMBUS 0x16
-
/* base address register in PCI config space */
#define SIS96x_BAR 0x04
@@ -267,14 +264,7 @@
};
static struct pci_device_id sis96x_ids[] = {
-
- {
- .vendor = PCI_VENDOR_ID_SI,
- .device = PCI_DEVICE_ID_SI_SMBUS,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
-
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) },
{ 0, }
};
diff -Nru a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
--- a/drivers/i2c/busses/i2c-viapro.c 2005-01-07 14:55:28 -08:00
+++ b/drivers/i2c/busses/i2c-viapro.c 2005-01-07 14:55:28 -08:00
@@ -395,62 +395,22 @@
}
static struct pci_device_id vt596_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_82C596_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_82C596B_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_82C686_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8233_0,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8233A,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8235,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8237,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8231_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3),
+ .driver_data = SMBBA1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3),
+ .driver_data = SMBBA1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4),
+ .driver_data = SMBBA1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
+ .driver_data = SMBBA1 },
{ 0, }
};
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h 2005-01-07 14:55:28 -08:00
+++ b/include/linux/pci_ids.h 2005-01-07 14:55:28 -08:00
@@ -496,6 +496,8 @@
# define PCI_DEVICE_ID_AMD_VIPER_7449 PCI_DEVICE_ID_AMD_OPUS_7449
#define PCI_DEVICE_ID_AMD_8111_LAN 0x7462
#define PCI_DEVICE_ID_AMD_8111_IDE 0x7469
+#define PCI_DEVICE_ID_AMD_8111_SMBUS2 0x746a
+#define PCI_DEVICE_ID_AMD_8111_SMBUS 0x746b
#define PCI_DEVICE_ID_AMD_8111_AUDIO 0x746d
#define PCI_DEVICE_ID_AMD_8151_0 0x7454
#define PCI_DEVICE_ID_AMD_8131_APIC 0x7450
@@ -585,6 +587,7 @@
#define PCI_DEVICE_ID_SI_6202 0x0002
#define PCI_DEVICE_ID_SI_503 0x0008
#define PCI_DEVICE_ID_SI_ACPI 0x0009
+#define PCI_DEVICE_ID_SI_SMBUS 0x0016
#define PCI_DEVICE_ID_SI_LPC 0x0018
#define PCI_DEVICE_ID_SI_5597_VGA 0x0200
#define PCI_DEVICE_ID_SI_6205 0x0205
@@ -1133,6 +1136,7 @@
#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2 0x01a0
#define PCI_DEVICE_ID_NVIDIA_NFORCE 0x01a4
#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01b4
#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE 0x01bc
#define PCI_DEVICE_ID_NVIDIA_NVENET_1 0x01c3
#define PCI_DEVICE_ID_NVIDIA_NFORCE2 0x01e0
@@ -2048,9 +2052,11 @@
#define PCI_DEVICE_ID_S3_PLATO_PXG 0x8902
#define PCI_DEVICE_ID_S3_ViRGE_DXGX 0x8a01
#define PCI_DEVICE_ID_S3_ViRGE_GX2 0x8a10
+#define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25
#define PCI_DEVICE_ID_S3_ViRGE_MX 0x8c01
#define PCI_DEVICE_ID_S3_ViRGE_MXP 0x8c02
#define PCI_DEVICE_ID_S3_ViRGE_MXPMV 0x8c03
+#define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04
#define PCI_DEVICE_ID_S3_SONICVIBES 0xca00
#define PCI_VENDOR_ID_DUNORD 0x5544
ChangeSet 1.1938.445.10, 2004/12/21 11:09:21-08:00, [email protected]
[PATCH] I2C: Remove checksum code in eeprom driver
As a follow-up to my earlier proposal to remove the checksum code from
the i2c eeprom driver, here is a patch that does just that. This shrinks
the driver size by around 5%, and paves the way for further fixes and
cleanups.
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/chips/eeprom.c | 19 -------------------
1 files changed, 19 deletions(-)
diff -Nru a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
--- a/drivers/i2c/chips/eeprom.c 2005-01-07 14:55:12 -08:00
+++ b/drivers/i2c/chips/eeprom.c 2005-01-07 14:55:12 -08:00
@@ -43,13 +43,6 @@
/* Insmod parameters */
SENSORS_INSMOD_1(eeprom);
-static int checksum = 0;
-module_param(checksum, bool, 0);
-MODULE_PARM_DESC(checksum, "Only accept eeproms whose checksum is correct");
-
-
-/* EEPROM registers */
-#define EEPROM_REG_CHECKSUM 0x3f
/* Size of EEPROM in bytes */
#define EEPROM_SIZE 256
@@ -168,7 +161,6 @@
/* This function is called by i2c_detect */
int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
{
- int i, cs;
struct i2c_client *new_client;
struct eeprom_data *data;
int err = 0;
@@ -204,17 +196,6 @@
/* prevent 24RF08 corruption */
i2c_smbus_write_quick(new_client, 0);
-
- /* Now, we do the remaining detection. It is not there, unless you force
- the checksum to work out. */
- if (checksum) {
- cs = 0;
- for (i = 0; i <= 0x3e; i++)
- cs += i2c_smbus_read_byte_data(new_client, i);
- cs &= 0xff;
- if (i2c_smbus_read_byte_data (new_client, EEPROM_REG_CHECKSUM) != cs)
- goto exit_kfree;
- }
data->nature = UNKNOWN;
/* Detect the Vaio nature of EEPROMs.
ChangeSet 1.1938.445.6, 2004/12/17 13:32:32-08:00, [email protected]
[PATCH] I2C: i2c-nforce2 supports the nForce3 250Gb
One more PCI ID for the i2c-nforce2 driver, this time for the nForce3
250Gb variant. Tested, works.
(Also cleans up a duplicate define in pci_ids.h.)
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/busses/i2c-nforce2.c | 3 +++
include/linux/pci_ids.h | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff -Nru a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
--- a/drivers/i2c/busses/i2c-nforce2.c 2005-01-07 14:55:43 -08:00
+++ b/drivers/i2c/busses/i2c-nforce2.c 2005-01-07 14:55:43 -08:00
@@ -28,6 +28,7 @@
nForce2 MCP 0064
nForce2 Ultra 400 MCP 0084
nForce3 Pro150 MCP 00D4
+ nForce3 250Gb MCP 00E4
This driver supports the 2 SMBuses that are included in the MCP2 of the
nForce2 chipset.
@@ -295,6 +296,8 @@
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0 }
};
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h 2005-01-07 14:55:43 -08:00
+++ b/include/linux/pci_ids.h 2005-01-07 14:55:43 -08:00
@@ -1097,7 +1097,6 @@
#define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0
#define PCI_DEVICE_ID_NVIDIA_NFORCE3 0x00d1
#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da
-#define PCI_DEVICE_ID_NVIDIA_NFORCE3S 0x00e1
#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS 0x00d4
#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE 0x00d5
#define PCI_DEVICE_ID_NVIDIA_NVENET_3 0x00d6
@@ -1105,6 +1104,7 @@
#define PCI_DEVICE_ID_NVIDIA_NVENET_7 0x00df
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S 0x00e1
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA 0x00e3
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS 0x00e4
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE 0x00e5
#define PCI_DEVICE_ID_NVIDIA_NVENET_6 0x00e6
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2 0x00ee
ChangeSet 1.1938.445.1, 2004/12/15 11:29:09-08:00, [email protected]
[PATCH] w1: Documentation bits for generic w1 behaviour.
Documentation bits for generic w1 behaviour.
Signed-off-by: Evgeniy Polyakov <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Documentation/w1/w1.generic | 19 +++++++++++++++++++
1 files changed, 19 insertions(+)
diff -Nru a/Documentation/w1/w1.generic b/Documentation/w1/w1.generic
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/Documentation/w1/w1.generic 2005-01-07 14:56:22 -08:00
@@ -0,0 +1,19 @@
+Any w1 device must be connected to w1 bus master device - for example
+ds9490 usb device or w1-over-GPIO or RS232 converter.
+Driver for w1 bus master must provide several functions(you can find
+them in struct w1_bus_master definition in w1.h) which then will be
+called by w1 core to send various commands over w1 bus(by default it is
+reset and search commands). When some device is found on the bus, w1 core
+checks if driver for it's family is loaded.
+If driver is loaded w1 core creates new w1_slave object and registers it
+in the system(creates some generic sysfs files(struct w1_family_ops in
+w1_family.h), notifies any registered listener and so on...).
+It is device driver's business to provide any communication method
+upstream.
+For example w1_therm driver(ds18?20 thermal sensor family driver)
+provides temperature reading function which is bound to ->rbin() method
+of the above w1_family_ops structure.
+w1_smem - driver for simple 64bit memory cell provides ID reading
+method.
+
+You can call above methods by reading appropriate sysfs files.
ChangeSet 1.1938.439.50, 2005/01/06 15:05:25-08:00, [email protected]
[PATCH] I2C: Update fscher pwm functionality
This is a small update to the fscher hardware monitoring chip driver.
More specifically it fixes two aspects of pwm:
1* Use the new sysfs names (e.g. pwm1 instead of fan1_pwm).
2* Better handling of out-of-range pwm values.
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/chips/fscher.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff -Nru a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
--- a/drivers/i2c/chips/fscher.c 2005-01-07 14:54:10 -08:00
+++ b/drivers/i2c/chips/fscher.c 2005-01-07 14:54:10 -08:00
@@ -198,7 +198,7 @@
static DEVICE_ATTR(kind, S_IRUGO, show_##kind##0##sub, NULL);
#define sysfs_fan(offset, reg_status, reg_min, reg_ripple, reg_act) \
-sysfs_rw_n(fan, _pwm , offset, reg_min) \
+sysfs_rw_n(pwm, , offset, reg_min) \
sysfs_rw_n(fan, _status, offset, reg_status) \
sysfs_rw_n(fan, _div , offset, reg_ripple) \
sysfs_ro_n(fan, _input , offset, reg_act)
@@ -247,7 +247,7 @@
#define device_create_file_fan(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_fan##offset##_status); \
- device_create_file(&client->dev, &dev_attr_fan##offset##_pwm); \
+ device_create_file(&client->dev, &dev_attr_pwm##offset); \
device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
} while (0)
@@ -483,16 +483,17 @@
return sprintf(buf, "%u\n", data->fan_status[FAN_INDEX_FROM_NUM(nr)] & 0x04);
}
-static ssize_t set_fan_pwm(struct i2c_client *client, struct fscher_data *data,
+static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data,
const char *buf, size_t count, int nr, int reg)
{
- data->fan_min[FAN_INDEX_FROM_NUM(nr)] = simple_strtoul(buf, NULL, 10) & 0xff;
+ unsigned long v = simple_strtoul(buf, NULL, 10);
+ data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v;
fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]);
return count;
}
-static ssize_t show_fan_pwm (struct fscher_data *data, char *buf, int nr)
+static ssize_t show_pwm(struct fscher_data *data, char *buf, int nr)
{
return sprintf(buf, "%u\n", data->fan_min[FAN_INDEX_FROM_NUM(nr)]);
}
ChangeSet 1.1938.439.45, 2005/01/06 13:54:20-08:00, [email protected]
[PATCH] I2C: Add secondary Super-I/O address support to
This patch adds support for the secondary Super-I/O address to the
w83627hf driver. Most manufacturer use the primary address but at least
the EPoX EP-9NDA3+ had a Winbond W83627THF at the secondary address.
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/chips/w83627hf.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
--- a/drivers/i2c/chips/w83627hf.c 2005-01-07 14:54:49 -08:00
+++ b/drivers/i2c/chips/w83627hf.c 2005-01-07 14:54:49 -08:00
@@ -67,9 +67,9 @@
MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
/* modified from kernel/include/traps.c */
-#define REG 0x2e /* The register to read/write */
+static int REG; /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */
-#define VAL 0x2f /* The value to read/write */
+static int VAL; /* The value to read/write */
/* logical device numbers for superio_select (below) */
#define W83627HF_LD_FDC 0x00
@@ -938,10 +938,13 @@
return i2c_detect(adapter, &addr_data, w83627hf_detect);
}
-static int w83627hf_find(int *address)
+static int w83627hf_find(int sioaddr, int *address)
{
u16 val;
+ REG = sioaddr;
+ VAL = sioaddr + 1;
+
superio_enter();
val= superio_inb(DEVID);
if(val != W627_DEVID &&
@@ -1422,7 +1425,8 @@
{
int addr;
- if (w83627hf_find(&addr)) {
+ if (w83627hf_find(0x2e, &addr)
+ && w83627hf_find(0x4e, &addr)) {
return -ENODEV;
}
normal_isa[0] = addr;
ChangeSet 1.1938.439.51, 2005/01/06 15:05:54-08:00, [email protected]
[PATCH] Update IOP3xx I2C bus driver
The following patch is a major cleanup of the IOP3xx I2C bus driver
that is found on Intel's IOP and IXP chipsets. The existing driver in
the 2.6 tree uses hardcoded I/O addresses based on board configuration
which is just going to get ugly as more chips use this unit. The update
switches to using the driver model and passing in the I/O addresses
via platform_device resources. The patch also updates the ID name to
more closely match the actual usage of the device.
I have tested this new driver on IXP46x systems and Dave Jiang has
tested it on both IOP321 and IOP331 systems. ARM-specific patches
to provide platform-level hooks will go upstream after this patch
is integrated.
An example of using the new driver (from IXP46x ARM code) follows:
static struct resource ixp46x_i2c_resources[] = {
[0] = {
.start = 0xc8011000,
.end = 0xc801101c,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IXP4XX_I2C,
.end = IRQ_IXP4XX_I2C,
.flags = IORESOURCE_IRQ
}
};
static struct platform_device ixp46x_i2c_controller = {
.name = "IOP3xx-I2C",
.id = 0,
.num_resources = 2,
.resource = &ixp46x_i2c_resources
};
static struct platform_device *ixp46x_devices[] __initdata = {
&ixp46x_i2c_controller
};
void __init ixp4xx_init(void)
{
if (cpu_is_ixp46x()) {
platform_add_devices(ixp46x_devices,
ARRAY_SIZE(ixp46x_devices));
}
}
Signed-off-by: Deepak Saxena <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/busses/Kconfig | 10
drivers/i2c/busses/i2c-iop3xx.c | 545 ++++++++++++++++++++--------------------
drivers/i2c/busses/i2c-iop3xx.h | 111 +++-----
include/linux/i2c-id.h | 4
4 files changed, 342 insertions(+), 328 deletions(-)
diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig 2005-01-07 14:54:03 -08:00
+++ b/drivers/i2c/busses/Kconfig 2005-01-07 14:54:03 -08:00
@@ -143,8 +143,14 @@
will be called i2c-ibm_iic.
config I2C_IOP3XX
- tristate "Intel XScale IOP3xx on-chip I2C interface"
- depends on ARCH_IOP3XX && I2C
+ tristate "Intel IOP3xx and IXP4xx on-chip I2C interface"
+ depends on (ARCH_IOP3XX || ARCH_IXP4XX) && I2C
+ help
+ Say Y here if you want to use the IIC bus controller on
+ the Intel IOP3xx I/O Processors or IXP4xx Network Processors.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-iop3xx.
config I2C_ISA
tristate "ISA Bus support"
diff -Nru a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
--- a/drivers/i2c/busses/i2c-iop3xx.c 2005-01-07 14:54:03 -08:00
+++ b/drivers/i2c/busses/i2c-iop3xx.c 2005-01-07 14:54:03 -08:00
@@ -1,35 +1,30 @@
/* ------------------------------------------------------------------------- */
-/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx */
+/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx & IXP46x */
/* ------------------------------------------------------------------------- */
-/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
- * <Peter dot Milne at D hyphen TACQ dot com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, version 2.
-
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* ------------------------------------------------------------------------- */
-/*
- With acknowledgements to i2c-algo-ibm_ocp.c by
- Ian DaSilva, MontaVista Software, Inc. [email protected]
-
- And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
-
- Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
-
- And which acknowledged Ky?sti M?lkki <[email protected]>,
- Frodo Looijaard <[email protected]>, Martin Bailey<[email protected]>
-
- ---------------------------------------------------------------------------*/
+/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
+ * <Peter dot Milne at D hyphen TACQ dot com>
+ *
+ * With acknowledgements to i2c-algo-ibm_ocp.c by
+ * Ian DaSilva, MontaVista Software, Inc. [email protected]
+ *
+ * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
+ *
+ * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
+ *
+ * And which acknowledged Ky?sti M?lkki <[email protected]>,
+ * Frodo Looijaard <[email protected]>, Martin Bailey<[email protected]>
+ *
+ * Major cleanup by Deepak Saxena <[email protected]>, 01/2005:
+ *
+ * - Use driver model to pass per-chip info instead of hardcoding and #ifdefs
+ * - Use ioremap/__raw_readl/__raw_writel instead of direct dereference
+ * - Make it work with IXP46x chips
+ * - Cleanup function names, coding style, etc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ */
#include <linux/config.h>
#include <linux/interrupt.h>
@@ -40,24 +35,18 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/sched.h>
+#include <linux/device.h>
#include <linux/i2c.h>
+#include <asm/io.h>
-#include <asm/arch-iop3xx/iop321.h>
-#include <asm/arch-iop3xx/iop321-irqs.h>
#include "i2c-iop3xx.h"
+/* global unit counter */
+static int i2c_id = 0;
-/* ----- global defines ----------------------------------------------- */
-#define PASSERT(x) do { if (!(x) ) \
- printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\
- } while (0)
-
-
-/* ----- global variables --------------------------------------------- */
-
-
-static inline unsigned char iic_cook_addr(struct i2c_msg *msg)
+static inline unsigned char
+iic_cook_addr(struct i2c_msg *msg)
{
unsigned char addr;
@@ -66,103 +55,110 @@
if (msg->flags & I2C_M_RD)
addr |= 1;
- /* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
+ /*
+ * Read or Write?
+ */
if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
return addr;
}
-
-static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
+static void
+iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
/* Follows devman 9.3 */
- *iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET;
- *iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS;
- *iop3xx_adap->biu->CR = 0;
+ __raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET);
+ __raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET);
+ __raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET);
}
-static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
+static void
+iop3xx_i2c_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
- *iop3xx_adap->biu->SAR = MYSAR;
+ __raw_writel(MYSAR, iop3xx_adap->ioaddr + SAR_OFFSET);
}
-static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
+static void
+iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
- u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE;
+ u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
+ /*
+ * Everytime unit enable is asserted, GPOD needs to be cleared
+ * on IOP321 to avoid data corruption on the bus.
+ */
+#ifdef CONFIG_ARCH_IOP321
+#define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */
+#define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */
+
+ *IOP321_GPOD &= (iop3xx_adap->id == 0) ? ~IOP321_GPOD_I2C0 :
+ ~IOP321_GPOD_I2C1;
+#endif
/* NB SR bits not same position as CR IE bits :-( */
- iop3xx_adap->biu->SR_enabled =
- IOP321_ISR_ALD | IOP321_ISR_BERRD |
- IOP321_ISR_RXFULL | IOP321_ISR_TXEMPTY;
+ iop3xx_adap->SR_enabled =
+ IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD |
+ IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY;
- cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
- IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE;
+ cr |= IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE |
+ IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE;
- *iop3xx_adap->biu->CR = cr;
+ __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
}
-static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
+static void
+iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
- unsigned cr = *iop3xx_adap->biu->CR;
+ unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
- cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE |
- IOP321_ICR_MSTOP | IOP321_ICR_SCLEN);
- *iop3xx_adap->biu->CR = cr;
-}
+ cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE |
+ IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN);
-static void iop3xx_adap_final_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
-{
- unsigned cr = *iop3xx_adap->biu->CR;
-
- cr &= ~(IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
- IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE);
- iop3xx_adap->biu->SR_enabled = 0;
- *iop3xx_adap->biu->CR = cr;
+ __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
}
/*
* NB: the handler has to clear the source of the interrupt!
* Then it passes the SR flags of interest to BH via adap data
*/
-static irqreturn_t iop3xx_i2c_handler(int this_irq,
- void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t
+iop3xx_i2c_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
+ u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET);
- u32 sr = *iop3xx_adap->biu->SR;
-
- if ((sr &= iop3xx_adap->biu->SR_enabled)) {
- *iop3xx_adap->biu->SR = sr;
- iop3xx_adap->biu->SR_received |= sr;
+ if ((sr &= iop3xx_adap->SR_enabled)) {
+ __raw_writel(sr, iop3xx_adap->ioaddr + SR_OFFSET);
+ iop3xx_adap->SR_received |= sr;
wake_up_interruptible(&iop3xx_adap->waitq);
}
return IRQ_HANDLED;
}
/* check all error conditions, clear them , report most important */
-static int iop3xx_adap_error(u32 sr)
+static int
+iop3xx_i2c_error(u32 sr)
{
int rc = 0;
- if ((sr&IOP321_ISR_BERRD)) {
+ if ((sr & IOP3XX_ISR_BERRD)) {
if ( !rc ) rc = -I2C_ERR_BERR;
}
- if ((sr&IOP321_ISR_ALD)) {
+ if ((sr & IOP3XX_ISR_ALD)) {
if ( !rc ) rc = -I2C_ERR_ALD;
}
return rc;
}
-static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
+static inline u32
+iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
unsigned long flags;
u32 sr;
spin_lock_irqsave(&iop3xx_adap->lock, flags);
- sr = iop3xx_adap->biu->SR_received;
- iop3xx_adap->biu->SR_received = 0;
+ sr = iop3xx_adap->SR_received;
+ iop3xx_adap->SR_received = 0;
spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
return sr;
@@ -175,9 +171,10 @@
typedef int (* compare_func)(unsigned test, unsigned mask);
/* returns 1 on correct comparison */
-static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
- unsigned flags, unsigned* status,
- compare_func compare)
+static int
+iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ unsigned flags, unsigned* status,
+ compare_func compare)
{
unsigned sr = 0;
int interrupted;
@@ -187,13 +184,13 @@
do {
interrupted = wait_event_interruptible_timeout (
iop3xx_adap->waitq,
- (done = compare( sr = get_srstat(iop3xx_adap),flags )),
- iop3xx_adap->timeout
+ (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )),
+ 1 * HZ;
);
- if ((rc = iop3xx_adap_error(sr)) < 0) {
+ if ((rc = iop3xx_i2c_error(sr)) < 0) {
*status = sr;
return rc;
- }else if (!interrupted) {
+ } else if (!interrupted) {
*status = sr;
return -ETIMEDOUT;
}
@@ -207,141 +204,131 @@
/*
* Concrete compare_funcs
*/
-static int all_bits_clear(unsigned test, unsigned mask)
+static int
+all_bits_clear(unsigned test, unsigned mask)
{
return (test & mask) == 0;
}
-static int any_bits_set(unsigned test, unsigned mask)
+
+static int
+any_bits_set(unsigned test, unsigned mask)
{
return (test & mask) != 0;
}
-static int iop3xx_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+static int
+iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
- return iop3xx_adap_wait_event(
+ return iop3xx_i2c_wait_event(
iop3xx_adap,
- IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD,
+ IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
status, any_bits_set);
}
-static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+static int
+iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
- return iop3xx_adap_wait_event(
+ return iop3xx_i2c_wait_event(
iop3xx_adap,
- IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD,
+ IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
status, any_bits_set);
}
-static int iop3xx_adap_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
-{
- return iop3xx_adap_wait_event(
- iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear);
-}
-
-/*
- * Description: This performs the IOP3xx initialization sequence
- * Valid for IOP321. Maybe valid for IOP310?.
- */
-static int iop3xx_adap_init (struct i2c_algo_iop3xx_data *iop3xx_adap)
+static int
+iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
- *IOP321_GPOD &= ~(iop3xx_adap->channel==0 ?
- IOP321_GPOD_I2C0:
- IOP321_GPOD_I2C1);
-
- iop3xx_adap_reset(iop3xx_adap);
- iop3xx_adap_set_slave_addr(iop3xx_adap);
- iop3xx_adap_enable(iop3xx_adap);
-
- return 0;
+ return iop3xx_i2c_wait_event(
+ iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear);
}
-static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
- struct i2c_msg* msg)
+static int
+iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ struct i2c_msg* msg)
{
- unsigned cr = *iop3xx_adap->biu->CR;
+ unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
int status;
int rc;
- *iop3xx_adap->biu->DBR = iic_cook_addr(msg);
+ __raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET);
- cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK);
- cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE;
+ cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
+ cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE;
+
+ __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
+ rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
- *iop3xx_adap->biu->CR = cr;
- rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
- /* this assert fires every time, contrary to IOP manual
- PASSERT((status&IOP321_ISR_UNITBUSY)!=0);
- */
- PASSERT((status&IOP321_ISR_RXREAD)==0);
-
return rc;
}
-static int iop3xx_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop)
+static int
+iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,
+ int stop)
{
- unsigned cr = *iop3xx_adap->biu->CR;
+ unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
int status;
int rc = 0;
- *iop3xx_adap->biu->DBR = byte;
- cr &= ~IOP321_ICR_MSTART;
+ __raw_writel(byte, iop3xx_adap->ioaddr + DBR_OFFSET);
+ cr &= ~IOP3XX_ICR_MSTART;
if (stop) {
- cr |= IOP321_ICR_MSTOP;
+ cr |= IOP3XX_ICR_MSTOP;
} else {
- cr &= ~IOP321_ICR_MSTOP;
+ cr &= ~IOP3XX_ICR_MSTOP;
}
- *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
- rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
+ cr |= IOP3XX_ICR_TBYTE;
+ __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
+ rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
return rc;
}
-static int iop3xx_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap,
- char* byte, int stop)
+static int
+iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,
+ int stop)
{
- unsigned cr = *iop3xx_adap->biu->CR;
+ unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
int status;
int rc = 0;
- cr &= ~IOP321_ICR_MSTART;
+ cr &= ~IOP3XX_ICR_MSTART;
if (stop) {
- cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;
+ cr |= IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK;
} else {
- cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
+ cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
}
- *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
+ cr |= IOP3XX_ICR_TBYTE;
+ __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
- rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status);
+ rc = iop3xx_i2c_wait_rx_done(iop3xx_adap, &status);
- *byte = *iop3xx_adap->biu->DBR;
+ *byte = __raw_readl(iop3xx_adap->ioaddr + DBR_OFFSET);
return rc;
}
-static int iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap,
- const char *buf, int count)
+static int
+iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
int ii;
int rc = 0;
- for (ii = 0; rc == 0 && ii != count; ++ii) {
- rc = iop3xx_adap_write_byte(iop3xx_adap, buf[ii], ii==count-1);
- }
+ for (ii = 0; rc == 0 && ii != count; ++ii)
+ rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1);
return rc;
}
-static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap,
- char *buf, int count)
+static int
+iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
int ii;
int rc = 0;
- for (ii = 0; rc == 0 && ii != count; ++ii) {
- rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
- }
+ for (ii = 0; rc == 0 && ii != count; ++ii)
+ rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
+
return rc;
}
@@ -352,12 +339,13 @@
* Each transfer (i.e. a read or a write) is separated by a repeated start
* condition.
*/
-static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
+static int
+iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
int rc;
- rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg);
+ rc = iop3xx_i2c_send_target_addr(iop3xx_adap, pmsg);
if (rc < 0) {
return rc;
}
@@ -372,22 +360,24 @@
/*
* master_xfer() - main read/write entry
*/
-static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+static int
+iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+ int num)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
int im = 0;
int ret = 0;
int status;
- iop3xx_adap_wait_idle(iop3xx_adap, &status);
- iop3xx_adap_reset(iop3xx_adap);
- iop3xx_adap_enable(iop3xx_adap);
+ iop3xx_i2c_wait_idle(iop3xx_adap, &status);
+ iop3xx_i2c_reset(iop3xx_adap);
+ iop3xx_i2c_enable(iop3xx_adap);
for (im = 0; ret == 0 && im != num; im++) {
- ret = iop3xx_handle_msg(i2c_adap, &msgs[im]);
+ ret = iop3xx_i2c_handle_msg(i2c_adap, &msgs[im]);
}
- iop3xx_adap_transaction_cleanup(iop3xx_adap);
+ iop3xx_i2c_transaction_cleanup(iop3xx_adap);
if(ret)
return ret;
@@ -395,136 +385,165 @@
return im;
}
-static int algo_control(struct i2c_adapter *adapter, unsigned int cmd,
+static int
+iop3xx_i2c_algo_control(struct i2c_adapter *adapter, unsigned int cmd,
unsigned long arg)
{
return 0;
}
-static u32 iic_func(struct i2c_adapter *adap)
+static u32
+iop3xx_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
-
-/* -----exported algorithm data: ------------------------------------- */
-
-static struct i2c_algorithm iic_algo = {
+static struct i2c_algorithm iop3xx_i2c_algo = {
.name = "IOP3xx I2C algorithm",
- .id = I2C_ALGO_OCP_IOP3XX,
- .master_xfer = iop3xx_master_xfer,
- .algo_control = algo_control,
- .functionality = iic_func,
+ .id = I2C_ALGO_IOP3XX,
+ .master_xfer = iop3xx_i2c_master_xfer,
+ .algo_control = iop3xx_i2c_algo_control,
+ .functionality = iop3xx_i2c_func,
};
-/*
- * registering functions to load algorithms at runtime
- */
-static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap)
+static int
+iop3xx_i2c_remove(struct device *device)
+{
+ struct platform_device *pdev = to_platform_device(device);
+ struct i2c_adapter *padapter = dev_get_drvdata(&pdev->dev);
+ struct i2c_algo_iop3xx_data *adapter_data =
+ (struct i2c_algo_iop3xx_data *)padapter->algo_data;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET);
+
+ /*
+ * Disable the actual HW unit
+ */
+ cr &= ~(IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE |
+ IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE);
+ __raw_writel(cr, adapter_data->ioaddr + CR_OFFSET);
+
+ iounmap((void __iomem*)adapter_data->ioaddr);
+ release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
+ kfree(adapter_data);
+ kfree(padapter);
+
+ dev_set_drvdata(&pdev->dev, NULL);
+
+ return 0;
+}
+
+static int
+iop3xx_i2c_probe(struct device *dev)
{
- struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *res;
+ int ret;
+ struct i2c_adapter *new_adapter;
+ struct i2c_algo_iop3xx_data *adapter_data;
- if (!request_region( REGION_START(iop3xx_adap),
- REGION_LENGTH(iop3xx_adap),
- iic_adap->name)) {
- return -ENODEV;
+ new_adapter = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+ if (!new_adapter) {
+ ret = -ENOMEM;
+ goto out;
}
+ memset((void*)new_adapter, 0, sizeof(*new_adapter));
- init_waitqueue_head(&iop3xx_adap->waitq);
- spin_lock_init(&iop3xx_adap->lock);
+ adapter_data = kmalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
+ if (!adapter_data) {
+ ret = -ENOMEM;
+ goto free_adapter;
+ }
+ memset((void*)adapter_data, 0, sizeof(*adapter_data));
- if (request_irq(
- iop3xx_adap->biu->irq,
- iop3xx_i2c_handler,
- /* SA_SAMPLE_RANDOM */ 0,
- iic_adap->name,
- iop3xx_adap)) {
- return -ENODEV;
- }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENODEV;
+ goto free_both;
+ }
- /* register new iic_adapter to i2c module... */
- iic_adap->id |= iic_algo.id;
- iic_adap->algo = &iic_algo;
+ if (!request_mem_region(res->start, IOP3XX_I2C_IO_SIZE, pdev->name)) {
+ ret = -EBUSY;
+ goto free_both;
+ }
- iic_adap->timeout = 100; /* default values, should */
- iic_adap->retries = 3; /* be replaced by defines */
+ /* set the adapter enumeration # */
+ adapter_data->id = i2c_id++;
- iop3xx_adap_init(iic_adap->algo_data);
- i2c_add_adapter(iic_adap);
- return 0;
-}
+ adapter_data->ioaddr = (u32)ioremap(res->start, IOP3XX_I2C_IO_SIZE);
+ if (!adapter_data->ioaddr) {
+ ret = -ENOMEM;
+ goto release_region;
+ }
-static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap)
-{
- struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+ res = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0,
+ pdev->name, adapter_data);
+ if (res) {
+ ret = -EIO;
+ goto unmap;
+ }
- iop3xx_adap_final_cleanup(iop3xx_adap);
- free_irq(iop3xx_adap->biu->irq, iop3xx_adap);
+ memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
+ new_adapter->id = I2C_HW_IOP3XX;
+ new_adapter->owner = THIS_MODULE;
+ new_adapter->dev.parent = &pdev->dev;
- release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
+ /*
+ * Default values...should these come in from board code?
+ */
+ new_adapter->timeout = 100;
+ new_adapter->retries = 3;
+ new_adapter->algo = &iop3xx_i2c_algo;
- return i2c_del_adapter(iic_adap);
-}
+ init_waitqueue_head(&adapter_data->waitq);
+ spin_lock_init(&adapter_data->lock);
-#ifdef CONFIG_ARCH_IOP321
+ iop3xx_i2c_reset(adapter_data);
+ iop3xx_i2c_set_slave_addr(adapter_data);
+ iop3xx_i2c_enable(adapter_data);
-static struct iop3xx_biu biu0 = {
- .CR = IOP321_ICR0,
- .SR = IOP321_ISR0,
- .SAR = IOP321_ISAR0,
- .DBR = IOP321_IDBR0,
- .BMR = IOP321_IBMR0,
- .irq = IRQ_IOP321_I2C_0,
-};
+ dev_set_drvdata(&pdev->dev, new_adapter);
+ new_adapter->algo_data = adapter_data;
-static struct iop3xx_biu biu1 = {
- .CR = IOP321_ICR1,
- .SR = IOP321_ISR1,
- .SAR = IOP321_ISAR1,
- .DBR = IOP321_IDBR1,
- .BMR = IOP321_IBMR1,
- .irq = IRQ_IOP321_I2C_1,
-};
+ i2c_add_adapter(new_adapter);
-#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "
-#else
-#error Please define the BIU struct iop3xx_biu for your processor arch
-#endif
+ return 0;
-static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = {
- .channel = 0,
- .biu = &biu0,
- .timeout = 1*HZ,
-};
-static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = {
- .channel = 1,
- .biu = &biu1,
- .timeout = 1*HZ,
-};
+unmap:
+ iounmap((void __iomem*)adapter_data->ioaddr);
-static struct i2c_adapter iop3xx_ops0 = {
- .owner = THIS_MODULE,
- .name = ADAPTER_NAME_ROOT "0",
- .id = I2C_HW_IOP321,
- .algo_data = &algo_iop3xx_data0,
-};
-static struct i2c_adapter iop3xx_ops1 = {
- .owner = THIS_MODULE,
- .name = ADAPTER_NAME_ROOT "1",
- .id = I2C_HW_IOP321,
- .algo_data = &algo_iop3xx_data1,
+release_region:
+ release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
+
+free_both:
+ kfree(adapter_data);
+
+free_adapter:
+ kfree(new_adapter);
+
+out:
+ return ret;
+}
+
+
+static struct device_driver iop3xx_i2c_driver = {
+ .name = "IOP3xx-I2C",
+ .bus = &platform_bus_type,
+ .probe = iop3xx_i2c_probe,
+ .remove = iop3xx_i2c_remove
};
-static int __init i2c_iop3xx_init (void)
+static int __init
+i2c_iop3xx_init (void)
{
- return i2c_iop3xx_add_bus(&iop3xx_ops0) ||
- i2c_iop3xx_add_bus(&iop3xx_ops1);
+ return driver_register(&iop3xx_i2c_driver);
}
-static void __exit i2c_iop3xx_exit (void)
+static void __exit
+i2c_iop3xx_exit (void)
{
- i2c_iop3xx_del_bus(&iop3xx_ops0);
- i2c_iop3xx_del_bus(&iop3xx_ops1);
+ driver_unregister(&iop3xx_i2c_driver);
+ return;
}
module_init (i2c_iop3xx_init);
diff -Nru a/drivers/i2c/busses/i2c-iop3xx.h b/drivers/i2c/busses/i2c-iop3xx.h
--- a/drivers/i2c/busses/i2c-iop3xx.h 2005-01-07 14:54:03 -08:00
+++ b/drivers/i2c/busses/i2c-iop3xx.h 2005-01-07 14:54:03 -08:00
@@ -25,20 +25,20 @@
/*
* iop321 hardware bit definitions
*/
-#define IOP321_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */
-#define IOP321_ICR_UNIT_RESET 0x4000 /* 1=RESET */
-#define IOP321_ICR_SADIE 0x2000 /* 1=Slave Detect Interrupt Enable */
-#define IOP321_ICR_ALDIE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */
-#define IOP321_ICR_SSDIE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */
-#define IOP321_ICR_BERRIE 0x0400 /* 1=Bus Error Interrupt Enable */
-#define IOP321_ICR_RXFULLIE 0x0200 /* 1=Receive Full Interrupt Enable */
-#define IOP321_ICR_TXEMPTYIE 0x0100 /* 1=Transmit Empty Interrupt Enable */
-#define IOP321_ICR_GCD 0x0080 /* 1=General Call Disable */
+#define IOP3XX_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */
+#define IOP3XX_ICR_UNIT_RESET 0x4000 /* 1=RESET */
+#define IOP3XX_ICR_SAD_IE 0x2000 /* 1=Slave Detect Interrupt Enable */
+#define IOP3XX_ICR_ALD_IE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */
+#define IOP3XX_ICR_SSD_IE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */
+#define IOP3XX_ICR_BERR_IE 0x0400 /* 1=Bus Error Interrupt Enable */
+#define IOP3XX_ICR_RXFULL_IE 0x0200 /* 1=Receive Full Interrupt Enable */
+#define IOP3XX_ICR_TXEMPTY_IE 0x0100 /* 1=Transmit Empty Interrupt Enable */
+#define IOP3XX_ICR_GCD 0x0080 /* 1=General Call Disable */
/*
- * IOP321_ICR_GCD: 1 disables response as slave. "This bit must be set
+ * IOP3XX_ICR_GCD: 1 disables response as slave. "This bit must be set
* when sending a master mode general call message from the I2C unit"
*/
-#define IOP321_ICR_UE 0x0040 /* 1=Unit Enable */
+#define IOP3XX_ICR_UE 0x0040 /* 1=Unit Enable */
/*
* "NOTE: To avoid I2C bus integrity problems,
* the user needs to ensure that the GPIO Output Data Register -
@@ -47,38 +47,38 @@
* The user prepares to enable I2C port 0 and
* I2C port 1 by clearing GPOD bits 7:6 and GPOD bits 5:4, respectively.
*/
-#define IOP321_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */
-#define IOP321_ICR_MABORT 0x0010 /* 1=Send a STOP with no data
+#define IOP3XX_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */
+#define IOP3XX_ICR_MABORT 0x0010 /* 1=Send a STOP with no data
* NB TBYTE must be clear */
-#define IOP321_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */
-#define IOP321_ICR_NACK 0x0004 /* 1=reply with NACK */
-#define IOP321_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */
-#define IOP321_ICR_MSTART 0x0001 /* 1=initiate a START */
-
-
-#define IOP321_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */
-#define IOP321_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */
-#define IOP321_ISR_GCAD 0x0100 /* 1=General Call Address Detected */
-#define IOP321_ISR_RXFULL 0x0080 /* 1=Receive Full */
-#define IOP321_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */
-#define IOP321_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */
-#define IOP321_ISR_SSD 0x0010 /* 1=Slave STOP Detected */
-#define IOP321_ISR_BBUSY 0x0008 /* 1=Bus BUSY */
-#define IOP321_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */
-#define IOP321_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */
-#define IOP321_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */
-
-#define IOP321_ISR_CLEARBITS 0x07f0
-
-#define IOP321_ISAR_SAMASK 0x007f
+#define IOP3XX_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */
+#define IOP3XX_ICR_NACK 0x0004 /* 1=reply with NACK */
+#define IOP3XX_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */
+#define IOP3XX_ICR_MSTART 0x0001 /* 1=initiate a START */
+
+
+#define IOP3XX_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */
+#define IOP3XX_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */
+#define IOP3XX_ISR_GCAD 0x0100 /* 1=General Call Address Detected */
+#define IOP3XX_ISR_RXFULL 0x0080 /* 1=Receive Full */
+#define IOP3XX_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */
+#define IOP3XX_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */
+#define IOP3XX_ISR_SSD 0x0010 /* 1=Slave STOP Detected */
+#define IOP3XX_ISR_BBUSY 0x0008 /* 1=Bus BUSY */
+#define IOP3XX_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */
+#define IOP3XX_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */
+#define IOP3XX_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */
+
+#define IOP3XX_ISR_CLEARBITS 0x07f0
+
+#define IOP3XX_ISAR_SAMASK 0x007f
-#define IOP321_IDBR_MASK 0x00ff
+#define IOP3XX_IDBR_MASK 0x00ff
-#define IOP321_IBMR_SCL 0x0002
-#define IOP321_IBMR_SDA 0x0001
+#define IOP3XX_IBMR_SCL 0x0002
+#define IOP3XX_IBMR_SDA 0x0001
-#define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */
-#define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */
+#define IOP3XX_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */
+#define IOP3XX_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */
#define MYSAR 0x02 /* SWAG a suitable slave address */
@@ -87,32 +87,21 @@
#define I2C_ERR_ALD (I2C_ERR+1)
-struct iop3xx_biu { /* Bus Interface Unit - the hardware */
-/* physical hardware defs - regs*/
- u32 *CR;
- u32 *SR;
- u32 *SAR;
- u32 *DBR;
- u32 *BMR;
-/* irq bit vector */
- u32 irq;
-/* stored flags */
- u32 SR_enabled, SR_received;
-};
+#define CR_OFFSET 0
+#define SR_OFFSET 0x4
+#define SAR_OFFSET 0x8
+#define DBR_OFFSET 0xc
+#define CCR_OFFSET 0x10
+#define BMR_OFFSET 0x14
-struct i2c_algo_iop3xx_data {
- int channel;
+#define IOP3XX_I2C_IO_SIZE 0x18
+struct i2c_algo_iop3xx_data {
+ u32 ioaddr;
wait_queue_head_t waitq;
spinlock_t lock;
- int timeout;
- struct iop3xx_biu* biu;
+ u32 SR_enabled, SR_received;
+ int id;
};
-
-#define REGION_START(adap) ((u32)((adap)->biu->CR))
-#define REGION_END(adap) ((u32)((adap)->biu->BMR+1))
-#define REGION_LENGTH(adap) (REGION_END(adap)-REGION_START(adap))
-
-#define IRQ_STATUS_MASK(adap) (1<<adap->biu->irq)
#endif /* I2C_IOP3XX_H */
diff -Nru a/include/linux/i2c-id.h b/include/linux/i2c-id.h
--- a/include/linux/i2c-id.h 2005-01-07 14:54:03 -08:00
+++ b/include/linux/i2c-id.h 2005-01-07 14:54:03 -08:00
@@ -194,7 +194,7 @@
#define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */
#define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
#define I2C_ALGO_BITHS 0x130000 /* enhanced bit style adapters */
-#define I2C_ALGO_OCP_IOP3XX 0x140000 /* XSCALE IOP3XX On-chip I2C alg */
+#define I2C_ALGO_IOP3XX 0x140000 /* XSCALE IOP3XX On-chip I2C alg */
#define I2C_ALGO_PCA 0x150000 /* PCA 9564 style adapters */
#define I2C_ALGO_SIBYTE 0x150000 /* Broadcom SiByte SOCs */
@@ -270,7 +270,7 @@
#define I2C_HW_SGI_MACE 0x01
/* --- XSCALE on-chip adapters */
-#define I2C_HW_IOP321 0x00
+#define I2C_HW_IOP3XX 0x00
/* --- SMBus only adapters */
#define I2C_HW_SMBUS_PIIX4 0x00
ChangeSet 1.1938.445.4, 2004/12/15 11:37:45-08:00, [email protected]
[PATCH] I2C: i2c-algo-bit should support I2C_FUNC_I2C
> Very few drivers seem to support the I2C_FUNC_I2C functionality, is
> there a reason for that?
Yes, most bus drivers are for SMBus, not I2C, masters. SMBus is a subset
of I2C. These SMBus master are fully I2C-capable, although in most cases
it doesn't matter. Most chip drivers are for SMBus clients as well.
Almost all hardware monitoring chips are SMBus devices. So it's not
surprising not to see I2C_FUNC_I2C widely used.
> I have an I2C bus on my platform constructed from a couple of GPIO lines
> using the i2c-algo-bit driver. The device on the bus is a DS1307 I2C RTC
> and the driver for that currently checks for
> I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_WRITE_BYTE
> however the datasheet suggests it is a simple i2c device with none of
> this smbus stuff, Russell King queried this here
> http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=2021/1
First, note that all SMBus commands are valid I2C transfers. In fact,
the SMBus specification doesn't do much except put names on specific I2C
transfers, and sometimes give meanings to the data being transfered. As
a result, "I2C" clients, although not specifically SMBus-compatible, may
enjoy SMBus commands such as SMBUS_READ_BYTE, SMBUS_READ_BYTE_DATA and
SMBUS_WRITE_BYTE_DATA. One typical example of that are EEPROMs and the
eeprom driver. It relies on i2c_smbus_write_byte and i2c_smbus_read_byte
(BTW I just noticed that it doesn't properly check for these
functionalities... have to fix that) because it's so much easier to call
these standard functions than rewrite I2C code manually. Also, this let
us access the EEPROMs on SMBus (non-I2C) busses.
Now, note that Russell is not quite correct in is assertion: "Do we
really require SMBUS functionality, or is i2c functionality sufficient?"
It's actually the other way around. SMBus puts restrictions on what a
valid I2C transfer is. "Do we need the full I2C functionality or is the
SMBus subset sufficient?" would make more sense.
As for the exact functionality you need to check, let's just see how you
access the bus. As far as I can see (providing that the code below
Russell's comments is still valid), you rely on:
* i2c_smbus_write_byte_data
* i2c_smbus_read_byte_data
* i2c_transfer
So yo *need* to check for the availability of I2C_FUNC_SMBUS_BYTE_DATA
on the adapter (which is part of I2C_FUNC_SMBUS_EMUL so any bus driver
using that, including any relying on i2c-algo-bit, will work with your
client driver) for the first two. And you also need to check for
I2C_FUNC_I2C for the third one.
Of course, any adapter with I2C_FUNC_I2C will be able to do SMBus byte
data transfers, but since you do not use i2c_transfer to do them, you
need to check the functionality separately (I think).
Also, I think that what you do with i2c_transfer is similar to
I2C_FUNC_SMBUS_READ_I2C_BLOCK, which is supported by some SMBus
(non-I2C) masters. If you convert your code to use
i2c_smbus_read_i2c_block_data, then you don't rely on the full I2C
capatbilities of the bus, which means that your chip driver will be
useable on more plateforms. That said, note that this feature is
unimplemented on most SMBus master drivers as of now, and broken on a
number of others (but I guess we would start paying more attention to
them if there were more users for this function).
> If I change it to a check for I2C_FUNC_I2C and change the algo-bit
> driver to declare I2C_FUNC_I2C then the driver continues to work fine.
You are right that i2c-algo-bit should declare itself I2C_FUNC_I2C
capable. I even think that every bus being I2C_FUNC_SMBUS_EMUL capable
is very likely to be I2C_FUNC_I2C capable. This means that other
algorithms (ite, pcf, maybe pca) could most probably be declared
I2C_FUNC_I2C capable as well. Can anyone confirm?
> Given the above, is the following patch appropriate, or is there
> something about the relationship between i2c and smbus that I don't
> understand.
I admit that the relationship between I2C and SMBus is somewhat tricky,
it took me some time to get it and even then I am sometimes not sure to
understand exactly what implies what ;) So we cannot blame you for not
getting it at first. I hope I helped make things a little clearer. If
not I welcome questions.
Whether or not you change your code to use SMBus only in your driver to
make it more widely useable, your patch to i2c-algo-bit is valid, I am
signing it too and will apply it to the 2.4 version of the driver as
well.
Signed-off-by: Ian Campbell <[email protected]>
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/algos/i2c-algo-bit.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff -Nru a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
--- a/drivers/i2c/algos/i2c-algo-bit.c 2005-01-07 14:55:58 -08:00
+++ b/drivers/i2c/algos/i2c-algo-bit.c 2005-01-07 14:55:58 -08:00
@@ -511,8 +511,8 @@
static u32 bit_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
- I2C_FUNC_PROTOCOL_MANGLING;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
}
ChangeSet 1.1938.439.53, 2005/01/07 11:14:41-08:00, [email protected]
[PATCH] I2C: add new sensors driver: SMSC LPC47B397-NC
This patch (3rd time's a charm) adds support for the SMSC LPC47B397-NC
sensor chip. It was sponsored by In-Store Broadcasting Network.
Signed-off-by: Craig Kelly (In-Store Broadcasting Network)
Signed-off-by: Glenn Ball (Utilitek Systems, Inc.)
Signed-off-by: Mark M. Hoffman <[email protected]>
Documentation/i2c/chips/smsc47b397.txt | 146 +++++++++++++
drivers/i2c/chips/Kconfig | 12 +
drivers/i2c/chips/Makefile | 1
drivers/i2c/chips/smsc47b397.c | 353 +++++++++++++++++++++++++++++++++
include/linux/i2c-id.h | 1
5 files changed, 513 insertions(+)
diff -Nru a/Documentation/i2c/chips/smsc47b397.txt b/Documentation/i2c/chips/smsc47b397.txt
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/Documentation/i2c/chips/smsc47b397.txt 2005-01-07 14:53:44 -08:00
@@ -0,0 +1,146 @@
+November 23, 2004
+
+The following specification describes the SMSC LPC47B397-NC 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 <[email protected]>.
+
+* * * * *
+
+Methods for detecting the HP SIO and reading the thermal data on a dc7100.
+
+The thermal information on the dc7100 is contained in the SIO Hardware Monitor
+(HWM). The information is accessed through an index/data pair. The index/data
+pair is located at the HWM Base Address + 0 and the HWM Base Address + 1. The
+HWM Base address can be obtained from Logical Device 8, registers 0x60 (MSB)
+and 0x61 (LSB). Currently we are using 0x480 for the HWM Base Address and
+0x480 and 0x481 for the index/data pair.
+
+Reading temperature information.
+The temperature information is located in the following registers:
+Temp1 0x25 (Currently, this reflects the CPU temp on all systems).
+Temp2 0x26
+Temp3 0x27
+Temp4 0x80
+
+Programming Example
+The following is an example of how to read the HWM temperature registers:
+MOV DX,480H
+MOV AX,25H
+OUT DX,AL
+MOV DX,481H
+IN AL,DX
+
+AL contains the data in hex, the temperature in Celsius is the decimal
+equivalent.
+
+Ex: If AL contains 0x2A, the temperature is 42 degrees C.
+
+Reading tach information.
+The fan speed information is located in the following registers:
+ LSB MSB
+Tach1 0x28 0x29 (Currently, this reflects the CPU
+ fan speed on all systems).
+Tach2 0x2A 0x2B
+Tach3 0x2C 0x2D
+Tach4 0x2E 0x2F
+
+Important!!!
+Reading the tach LSB locks the tach MSB.
+The LSB Must be read first.
+
+How to convert the tach reading to RPM.
+The tach reading (TCount) is given by: (Tach MSB * 256) + (Tach LSB)
+The SIO counts the number of 90kHz (11.111us) pulses per revolution.
+RPM = 60/(TCount * 11.111us)
+
+Example:
+Reg 0x28 = 0x9B
+Reg 0x29 = 0x08
+
+TCount = 0x89B = 2203
+
+RPM = 60 / (2203 * 11.11111 E-6) = 2451 RPM
+
+Obtaining the SIO version.
+
+CONFIGURATION SEQUENCE
+To program the configuration registers, the following sequence must be followed:
+1. Enter Configuration Mode
+2. Configure the Configuration Registers
+3. Exit Configuration Mode.
+
+Enter Configuration Mode
+To place the chip into the Configuration State The config key (0x55) is written
+to the CONFIG PORT (0x2E).
+
+Configuration Mode
+In configuration mode, the INDEX PORT is located at the CONFIG PORT address and
+the DATA PORT is at INDEX PORT address + 1.
+
+The desired configuration registers are accessed in two steps:
+a. Write the index of the Logical Device Number Configuration Register
+ (i.e., 0x07) to the INDEX PORT and then write the number of the
+ desired logical device to the DATA PORT.
+
+b. Write the address of the desired configuration register within the
+ logical device to the INDEX PORT and then write or read the config-
+ uration register through the DATA PORT.
+
+Note: If accessing the Global Configuration Registers, step (a) is not required.
+
+Exit Configuration Mode
+To exit the Configuration State the write 0xAA to the CONFIG PORT (0x2E).
+The chip returns to the RUN State. (This is important).
+
+Programming Example
+The following is an example of how to read the SIO Device ID located at 0x20
+
+; ENTER CONFIGURATION MODE
+MOV DX,02EH
+MOV AX,055H
+OUT DX,AL
+; GLOBAL CONFIGURATION REGISTER
+MOV DX,02EH
+MOV AL,20H
+OUT DX,AL
+; READ THE DATA
+MOV DX,02FH
+IN AL,DX
+; EXIT CONFIGURATION MODE
+MOV DX,02EH
+MOV AX,0AAH
+OUT DX,AL
+
+The registers of interest for identifying the SIO on the dc7100 are Device ID
+(0x20) and Device Rev (0x21).
+
+The Device ID will read 0X6F
+The Device Rev currently reads 0x01
+
+Obtaining the HWM Base Address.
+The following is an example of how to read the HWM Base Address located in
+Logical Device 8.
+
+; ENTER CONFIGURATION MODE
+MOV DX,02EH
+MOV AX,055H
+OUT DX,AL
+; CONFIGURE REGISTER CRE0,
+; LOGICAL DEVICE 8
+MOV DX,02EH
+MOV AL,07H
+OUT DX,AL ;Point to LD# Config Reg
+MOV DX,02FH
+MOV AL, 08H
+OUT DX,AL;Point to Logical Device 8
+;
+MOV DX,02EH
+MOV AL,60H
+OUT DX,AL ; Point to HWM Base Addr MSB
+MOV DX,02FH
+IN AL,DX ; Get MSB of HWM Base Addr
+; EXIT CONFIGURATION MODE
+MOV DX,02EH
+MOV AX,0AAH
+OUT DX,AL
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig 2005-01-07 14:53:44 -08:00
+++ b/drivers/i2c/chips/Kconfig 2005-01-07 14:53:44 -08:00
@@ -239,6 +239,18 @@
This driver can also be built as a module. If so, the module
will be called pc87360.
+config SENSORS_SMSC47B397
+ tristate "SMSC LPC47B397-NC"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ select I2C_ISA
+ help
+ If you say yes here you get support for the SMSC LPC47B397-NC
+ sensor chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called smsc47b397.
+
config SENSORS_SMSC47M1
tristate "SMSC LPC47M10x and compatibles"
depends on I2C && EXPERIMENTAL
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile 2005-01-07 14:53:44 -08:00
+++ b/drivers/i2c/chips/Makefile 2005-01-07 14:53:44 -08:00
@@ -30,6 +30,7 @@
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
+obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
diff -Nru a/drivers/i2c/chips/smsc47b397.c b/drivers/i2c/chips/smsc47b397.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/chips/smsc47b397.c 2005-01-07 14:53:44 -08:00
@@ -0,0 +1,353 @@
+/*
+ smsc47b397.c - Part of lm_sensors, Linux kernel modules
+ for hardware monitoring
+
+ Supports the SMSC LPC47B397-NC Super-I/O chip.
+
+ Author/Maintainer: Mark M. Hoffman <[email protected]>
+ Copyright (C) 2004 Utilitek Systems, Inc.
+
+ derived in part from smsc47m1.c:
+ Copyright (C) 2002 Mark D. Studebaker <[email protected]>
+ Copyright (C) 2004 Jean Delvare <[email protected]>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+/* Address is autodetected, there is no default value */
+static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
+static struct i2c_force_data forces[] = {{NULL}};
+
+enum chips { any_chip, smsc47b397 };
+static struct i2c_address_data addr_data = {
+ .normal_i2c = normal_i2c,
+ .normal_isa = normal_isa,
+ .probe = normal_i2c, /* cheat */
+ .ignore = normal_i2c, /* cheat */
+ .forces = forces,
+};
+
+/* Super-I/0 registers and commands */
+
+#define REG 0x2e /* The register to read/write */
+#define VAL 0x2f /* The value to read/write */
+
+static inline void superio_outb(int reg, int val)
+{
+ outb(reg, REG);
+ outb(val, VAL);
+}
+
+static inline int superio_inb(int reg)
+{
+ outb(reg, REG);
+ return inb(VAL);
+}
+
+/* select superio logical device */
+static inline void superio_select(int ld)
+{
+ superio_outb(0x07, ld);
+}
+
+static inline void superio_enter(void)
+{
+ outb(0x55, REG);
+}
+
+static inline void superio_exit(void)
+{
+ outb(0xAA, REG);
+}
+
+#define SUPERIO_REG_DEVID 0x20
+#define SUPERIO_REG_DEVREV 0x21
+#define SUPERIO_REG_BASE_MSB 0x60
+#define SUPERIO_REG_BASE_LSB 0x61
+#define SUPERIO_REG_LD8 0x08
+
+#define SMSC_EXTENT 0x02
+
+/* 0 <= nr <= 3 */
+static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
+#define SMSC47B397_REG_TEMP(nr) (smsc47b397_reg_temp[(nr)])
+
+/* 0 <= nr <= 3 */
+#define SMSC47B397_REG_FAN_LSB(nr) (0x28 + 2 * (nr))
+#define SMSC47B397_REG_FAN_MSB(nr) (0x29 + 2 * (nr))
+
+struct smsc47b397_data {
+ struct i2c_client client;
+ struct semaphore lock;
+
+ struct semaphore update_lock;
+ unsigned long last_updated; /* in jiffies */
+ int valid;
+
+ /* register values */
+ u16 fan[4];
+ u8 temp[4];
+};
+
+static int smsc47b397_read_value(struct i2c_client *client, u8 reg)
+{
+ struct smsc47b397_data *data = i2c_get_clientdata(client);
+ int res;
+
+ down(&data->lock);
+ outb(reg, client->addr);
+ res = inb_p(client->addr + 1);
+ up(&data->lock);
+ return res;
+}
+
+static struct smsc47b397_data *smsc47b397_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smsc47b397_data *data = i2c_get_clientdata(client);
+ int i;
+
+ down(&data->update_lock);
+
+ if (time_after(jiffies - data->last_updated, (unsigned long)HZ)
+ || time_before(jiffies, data->last_updated) || !data->valid) {
+
+ dev_dbg(&client->dev, "starting device update...\n");
+
+ /* 4 temperature inputs, 4 fan inputs */
+ for (i = 0; i < 4; i++) {
+ data->temp[i] = smsc47b397_read_value(client,
+ SMSC47B397_REG_TEMP(i));
+
+ /* must read LSB first */
+ data->fan[i] = smsc47b397_read_value(client,
+ SMSC47B397_REG_FAN_LSB(i));
+ data->fan[i] |= smsc47b397_read_value(client,
+ SMSC47B397_REG_FAN_MSB(i)) << 8;
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+
+ dev_dbg(&client->dev, "... device update complete\n");
+ }
+
+ up(&data->update_lock);
+
+ return data;
+}
+
+/* TEMP: 0.001C/bit (-128C to +127C)
+ REG: 1C/bit, two's complement */
+static int temp_from_reg(u8 reg)
+{
+ return (s8)reg * 1000;
+}
+
+/* 0 <= nr <= 3 */
+static ssize_t show_temp(struct device *dev, char *buf, int nr)
+{
+ struct smsc47b397_data *data = smsc47b397_update_device(dev);
+ return sprintf(buf, "%d\n", temp_from_reg(data->temp[nr]));
+}
+
+#define sysfs_temp(num) \
+static ssize_t show_temp##num(struct device *dev, char *buf) \
+{ \
+ return show_temp(dev, buf, num-1); \
+} \
+static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL)
+
+sysfs_temp(1);
+sysfs_temp(2);
+sysfs_temp(3);
+sysfs_temp(4);
+
+#define device_create_file_temp(client, num) \
+ device_create_file(&client->dev, &dev_attr_temp##num##_input)
+
+/* FAN: 1 RPM/bit
+ REG: count of 90kHz pulses / revolution */
+static int fan_from_reg(u16 reg)
+{
+ return 90000 * 60 / reg;
+}
+
+/* 0 <= nr <= 3 */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+ struct smsc47b397_data *data = smsc47b397_update_device(dev);
+ return sprintf(buf, "%d\n", fan_from_reg(data->fan[nr]));
+}
+
+#define sysfs_fan(num) \
+static ssize_t show_fan##num(struct device *dev, char *buf) \
+{ \
+ return show_fan(dev, buf, num-1); \
+} \
+static DEVICE_ATTR(fan##num##_input, S_IRUGO, show_fan##num, NULL)
+
+sysfs_fan(1);
+sysfs_fan(2);
+sysfs_fan(3);
+sysfs_fan(4);
+
+#define device_create_file_fan(client, num) \
+ device_create_file(&client->dev, &dev_attr_fan##num##_input)
+
+static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind);
+
+static int smsc47b397_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_detect(adapter, &addr_data, smsc47b397_detect);
+}
+
+static int smsc47b397_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed, "
+ "client not detached.\n");
+ return err;
+ }
+
+ release_region(client->addr, SMSC_EXTENT);
+ kfree(i2c_get_clientdata(client));
+
+ return 0;
+}
+
+static struct i2c_driver smsc47b397_driver = {
+ .owner = THIS_MODULE,
+ .name = "smsc47b397",
+ .id = I2C_DRIVERID_SMSC47B397,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = smsc47b397_attach_adapter,
+ .detach_client = smsc47b397_detach_client,
+};
+
+static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
+{
+ struct i2c_client *new_client;
+ struct smsc47b397_data *data;
+ int err = 0;
+
+ if (!i2c_is_isa_adapter(adapter)) {
+ return 0;
+ }
+
+ if (!request_region(addr, SMSC_EXTENT, smsc47b397_driver.name)) {
+ dev_err(&adapter->dev, "Region 0x%x already in use!\n", addr);
+ return -EBUSY;
+ }
+
+ if (!(data = kmalloc(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);
+ new_client->addr = addr;
+ init_MUTEX(&data->lock);
+ new_client->adapter = adapter;
+ new_client->driver = &smsc47b397_driver;
+ new_client->flags = 0;
+
+ strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE);
+
+ init_MUTEX(&data->update_lock);
+
+ if ((err = i2c_attach_client(new_client)))
+ goto error_free;
+
+ device_create_file_temp(new_client, 1);
+ device_create_file_temp(new_client, 2);
+ device_create_file_temp(new_client, 3);
+ device_create_file_temp(new_client, 4);
+
+ device_create_file_fan(new_client, 1);
+ device_create_file_fan(new_client, 2);
+ device_create_file_fan(new_client, 3);
+ device_create_file_fan(new_client, 4);
+
+ return 0;
+
+error_free:
+ kfree(new_client);
+error_release:
+ release_region(addr, SMSC_EXTENT);
+ return err;
+}
+
+static int __init smsc47b397_find(unsigned int *addr)
+{
+ u8 id, rev;
+
+ superio_enter();
+ id = superio_inb(SUPERIO_REG_DEVID);
+
+ if (id != 0x6f) {
+ superio_exit();
+ return -ENODEV;
+ }
+
+ rev = superio_inb(SUPERIO_REG_DEVREV);
+
+ superio_select(SUPERIO_REG_LD8);
+ *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);
+
+ superio_exit();
+ return 0;
+}
+
+static int __init smsc47b397_init(void)
+{
+ int ret;
+
+ if ((ret = smsc47b397_find(normal_isa)))
+ return ret;
+
+ return i2c_add_driver(&smsc47b397_driver);
+}
+
+static void __exit smsc47b397_exit(void)
+{
+ i2c_del_driver(&smsc47b397_driver);
+}
+
+MODULE_AUTHOR("Mark M. Hoffman <[email protected]>");
+MODULE_DESCRIPTION("SMSC LPC47B397 driver");
+MODULE_LICENSE("GPL");
+
+module_init(smsc47b397_init);
+module_exit(smsc47b397_exit);
diff -Nru a/include/linux/i2c-id.h b/include/linux/i2c-id.h
--- a/include/linux/i2c-id.h 2005-01-07 14:53:44 -08:00
+++ b/include/linux/i2c-id.h 2005-01-07 14:53:44 -08:00
@@ -167,6 +167,7 @@
#define I2C_DRIVERID_ASB100 1043
#define I2C_DRIVERID_FSCHER 1046
#define I2C_DRIVERID_W83L785TS 1047
+#define I2C_DRIVERID_SMSC47B397 1050
/*
* ---- Adapter types ----------------------------------------------------
ChangeSet 1.1938.445.5, 2004/12/15 11:43:29-08:00, [email protected]
[PATCH] it87: /proc/ioports fix
When request_region is called name is set to "", use module name.
Signed-off-by: Domen Puncer <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/chips/it87.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c 2005-01-07 14:55:51 -08:00
+++ b/drivers/i2c/chips/it87.c 2005-01-07 14:55:51 -08:00
@@ -624,7 +624,7 @@
/* Reserve the ISA region */
if (is_isa)
- if (!request_region(address, IT87_EXTENT, name))
+ if (!request_region(address, IT87_EXTENT, it87_driver.name))
goto ERROR0;
/* Probe whether there is anything available on this address. Already
ChangeSet 1.1938.445.9, 2004/12/21 11:08:43-08:00, [email protected]
[PATCH] I2C patch from MIPS tree...
Here is a newer i2c patch from the mainline Linux/MIPS kernel
tree. Some more changes came in since yesterday. Please apply
this for inclusion in the next Linux release. Thanks.
Signed-off-by: Steven J. Hill <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/algos/Kconfig | 13 ++
drivers/i2c/algos/Makefile | 2
drivers/i2c/algos/i2c-algo-sgi.c | 189 +++++++++++++++++++++++++++++
drivers/i2c/algos/i2c-algo-sibyte.c | 231 ++++++++++++++++++++++++++++++++++++
drivers/i2c/busses/Kconfig | 6
drivers/i2c/busses/Makefile | 1
drivers/i2c/busses/i2c-sibyte.c | 71 +++++++++++
include/linux/i2c-algo-sgi.h | 27 ++++
include/linux/i2c-algo-sibyte.h | 33 +++++
include/linux/i2c-id.h | 11 +
10 files changed, 584 insertions(+)
diff -Nru a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
--- a/drivers/i2c/algos/Kconfig 2005-01-07 14:55:20 -08:00
+++ b/drivers/i2c/algos/Kconfig 2005-01-07 14:55:20 -08:00
@@ -53,5 +53,18 @@
tristate "MPC8xx CPM I2C interface"
depends on 8xx && I2C
+config I2C_ALGO_SIBYTE
+ tristate "SiByte SMBus interface"
+ depends on SIBYTE_SB1xxx_SOC && I2C
+ help
+ Supports the SiByte SOC on-chip I2C interfaces (2 channels).
+
+config I2C_ALGO_SGI
+ tristate "I2C SGI interfaces"
+ depends on I2C
+ help
+ Supports the SGI interfaces like the ones found on SGI Indy VINO
+ or SGI O2 MACE.
+
endmenu
diff -Nru a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile
--- a/drivers/i2c/algos/Makefile 2005-01-07 14:55:20 -08:00
+++ b/drivers/i2c/algos/Makefile 2005-01-07 14:55:20 -08:00
@@ -6,6 +6,8 @@
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o
obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o
+obj-$(CONFIG_I2C_ALGO_SIBYTE) += i2c-algo-sibyte.o
+obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
EXTRA_CFLAGS += -DDEBUG
diff -Nru a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/algos/i2c-algo-sgi.c 2005-01-07 14:55:20 -08:00
@@ -0,0 +1,189 @@
+/*
+ * i2c-algo-sgi.c: i2c driver algorithms for SGI adapters.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * Copyright (C) 2003 Ladislav Michl <[email protected]>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-sgi.h>
+
+
+#define SGI_I2C_FORCE_IDLE (0 << 0)
+#define SGI_I2C_NOT_IDLE (1 << 0)
+#define SGI_I2C_WRITE (0 << 1)
+#define SGI_I2C_READ (1 << 1)
+#define SGI_I2C_RELEASE_BUS (0 << 2)
+#define SGI_I2C_HOLD_BUS (1 << 2)
+#define SGI_I2C_XFER_DONE (0 << 4)
+#define SGI_I2C_XFER_BUSY (1 << 4)
+#define SGI_I2C_ACK (0 << 5)
+#define SGI_I2C_NACK (1 << 5)
+#define SGI_I2C_BUS_OK (0 << 7)
+#define SGI_I2C_BUS_ERR (1 << 7)
+
+#define get_control() adap->getctrl(adap->data)
+#define set_control(val) adap->setctrl(adap->data, val)
+#define read_data() adap->rdata(adap->data)
+#define write_data(val) adap->wdata(adap->data, val)
+
+
+static int wait_xfer_done(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ for (i = 0; i < adap->xfer_timeout; i++) {
+ if ((get_control() & SGI_I2C_XFER_BUSY) == 0)
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int wait_ack(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ if (wait_xfer_done(adap))
+ return -ETIMEDOUT;
+ for (i = 0; i < adap->ack_timeout; i++) {
+ if ((get_control() & SGI_I2C_NACK) == 0)
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int force_idle(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ set_control(SGI_I2C_FORCE_IDLE);
+ for (i = 0; i < adap->xfer_timeout; i++) {
+ if ((get_control() & SGI_I2C_NOT_IDLE) == 0)
+ goto out;
+ udelay(1);
+ }
+ return -ETIMEDOUT;
+out:
+ if (get_control() & SGI_I2C_BUS_ERR)
+ return -EIO;
+ return 0;
+}
+
+static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr,
+ int rd)
+{
+ if (rd)
+ set_control(SGI_I2C_NOT_IDLE);
+ /* Check if bus is idle, eventually force it to do so */
+ if (get_control() & SGI_I2C_NOT_IDLE)
+ if (force_idle(adap))
+ return -EIO;
+ /* Write out the i2c chip address and specify operation */
+ set_control(SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE);
+ if (rd)
+ addr |= 1;
+ write_data(addr);
+ if (wait_ack(adap))
+ return -EIO;
+ return 0;
+}
+
+static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+ unsigned int len)
+{
+ int i;
+
+ set_control(SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE);
+ for (i = 0; i < len; i++) {
+ if (wait_xfer_done(adap))
+ return -EIO;
+ buf[i] = read_data();
+ }
+ set_control(SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE);
+
+ return 0;
+
+}
+
+static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+ unsigned int len)
+{
+ int i;
+
+ /* We are already in write state */
+ for (i = 0; i < len; i++) {
+ write_data(buf[i]);
+ if (wait_ack(adap))
+ return -EIO;
+ }
+ return 0;
+}
+
+static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+ int num)
+{
+ struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
+ struct i2c_msg *p;
+ int i, err = 0;
+
+ for (i = 0; !err && i < num; i++) {
+ p = &msgs[i];
+ err = do_address(adap, p->addr, p->flags & I2C_M_RD);
+ if (err || !p->len)
+ continue;
+ if (p->flags & I2C_M_RD)
+ err = i2c_read(adap, p->buf, p->len);
+ else
+ err = i2c_write(adap, p->buf, p->len);
+ }
+
+ return err;
+}
+
+static u32 sgi_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm sgi_algo = {
+ .name = "SGI algorithm",
+ .id = I2C_ALGO_SGI,
+ .master_xfer = sgi_xfer,
+ .functionality = sgi_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_sgi_add_bus(struct i2c_adapter *adap)
+{
+ adap->id |= sgi_algo.id;
+ adap->algo = &sgi_algo;
+
+ return i2c_add_adapter(adap);
+}
+
+
+int i2c_sgi_del_bus(struct i2c_adapter *adap)
+{
+ return i2c_del_adapter(adap);
+}
+
+EXPORT_SYMBOL(i2c_sgi_add_bus);
+EXPORT_SYMBOL(i2c_sgi_del_bus);
+
+MODULE_AUTHOR("Ladislav Michl <[email protected]>");
+MODULE_DESCRIPTION("I2C-Bus SGI algorithm");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c 2005-01-07 14:55:20 -08:00
@@ -0,0 +1,231 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-algo-sibyte.c i2c driver algorithms for bit-shift adapters */
+/* ------------------------------------------------------------------------- */
+/* Copyright (C) 2001,2002,2003 Broadcom Corporation
+ Copyright (C) 1995-2000 Simon G. Vogl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+/* ------------------------------------------------------------------------- */
+
+/* With some changes from Ky?sti M?lkki <[email protected]> and even
+ Frodo Looijaard <[email protected]>. */
+
+/* Ported for SiByte SOCs by Broadcom Corporation. */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_smbus.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-sibyte.h>
+
+/* ----- global defines ----------------------------------------------- */
+#define SMB_CSR(a,r) ((long)(a->reg_base + r))
+
+/* ----- global variables --------------------------------------------- */
+
+/* module parameters:
+ */
+static int bit_scan=0; /* have a look at what's hanging 'round */
+
+
+static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int size, union i2c_smbus_data * data)
+{
+ struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+ int data_bytes = 0;
+ int error;
+
+ while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ csr_out32((V_SMB_ADDR(addr) | (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
+ V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
+ break;
+ case I2C_SMBUS_BYTE:
+ if (read_write == I2C_SMBUS_READ) {
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ data_bytes = 1;
+ } else {
+ csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ }
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+ if (read_write == I2C_SMBUS_READ) {
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ data_bytes = 1;
+ } else {
+ csr_out32(V_SMB_LB(data->byte), SMB_CSR(adap, R_SMB_DATA));
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ }
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+ if (read_write == I2C_SMBUS_READ) {
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ data_bytes = 2;
+ } else {
+ csr_out32(V_SMB_LB(data->word & 0xff), SMB_CSR(adap, R_SMB_DATA));
+ csr_out32(V_SMB_MB(data->word >> 8), SMB_CSR(adap, R_SMB_DATA));
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ }
+ break;
+ default:
+ return -1; /* XXXKW better error code? */
+ }
+
+ while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
+ if (error & M_SMB_ERROR) {
+ /* Clear error bit by writing a 1 */
+ csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
+ return -1; /* XXXKW better error code? */
+ }
+
+ if (data_bytes == 1)
+ data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
+ if (data_bytes == 2)
+ data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
+
+ return 0;
+}
+
+static int algo_control(struct i2c_adapter *adapter,
+ unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+static u32 bit_func(struct i2c_adapter *adap)
+{
+ return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
+}
+
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static struct i2c_algorithm i2c_sibyte_algo = {
+ "SiByte algorithm",
+ I2C_ALGO_SIBYTE,
+ NULL, /* master_xfer */
+ smbus_xfer, /* smbus_xfer */
+ NULL, /* slave_xmit */
+ NULL, /* slave_recv */
+ algo_control, /* ioctl */
+ bit_func, /* functionality */
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
+{
+ int i;
+ struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+
+ /* register new adapter to i2c module... */
+
+ i2c_adap->id |= i2c_sibyte_algo.id;
+ i2c_adap->algo = &i2c_sibyte_algo;
+
+ /* Set the frequency to 100 kHz */
+ csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
+ csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
+
+ /* scan bus */
+ if (bit_scan) {
+ union i2c_smbus_data data;
+ int rc;
+ printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
+ i2c_adap->name);
+ for (i = 0x00; i < 0x7f; i++) {
+ /* XXXKW is this a realistic probe? */
+ rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
+ I2C_SMBUS_BYTE_DATA, &data);
+ if (!rc) {
+ printk("(%02x)",i);
+ } else
+ printk(".");
+ }
+ printk("\n");
+ }
+
+#ifdef MODULE
+ MOD_INC_USE_COUNT;
+#endif
+ i2c_add_adapter(i2c_adap);
+
+ return 0;
+}
+
+
+int i2c_sibyte_del_bus(struct i2c_adapter *adap)
+{
+ int res;
+
+ if ((res = i2c_del_adapter(adap)) < 0)
+ return res;
+
+#ifdef MODULE
+ MOD_DEC_USE_COUNT;
+#endif
+ return 0;
+}
+
+int __init i2c_algo_sibyte_init (void)
+{
+ printk("i2c-algo-sibyte.o: i2c SiByte algorithm module\n");
+ return 0;
+}
+
+
+EXPORT_SYMBOL(i2c_sibyte_add_bus);
+EXPORT_SYMBOL(i2c_sibyte_del_bus);
+
+#ifdef MODULE
+MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
+MODULE_DESCRIPTION("SiByte I2C-Bus algorithm");
+MODULE_PARM(bit_scan, "i");
+MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+ return i2c_algo_sibyte_init();
+}
+
+void cleanup_module(void)
+{
+}
+#endif
diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig 2005-01-07 14:55:20 -08:00
+++ b/drivers/i2c/busses/Kconfig 2005-01-07 14:55:20 -08:00
@@ -323,6 +323,12 @@
This driver can also be built as a module. If so, the module
will be called i2c-savage4.
+config I2C_SIBYTE
+ tristate "SiByte SMBus interface"
+ depends on SIBYTE_SB1xxx_SOC && I2C
+ help
+ Supports the SiByte SOC on-chip I2C interfaces (2 channels).
+
config SCx200_I2C
tristate "NatSemi SCx200 I2C using GPIO pins"
depends on SCx200_GPIO && I2C
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile 2005-01-07 14:55:20 -08:00
+++ b/drivers/i2c/busses/Makefile 2005-01-07 14:55:20 -08:00
@@ -29,6 +29,7 @@
obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
+obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
diff -Nru a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/busses/i2c-sibyte.c 2005-01-07 14:55:20 -08:00
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004 Steven J. Hill
+ * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/i2c-algo-sibyte.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_smbus.h>
+
+static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
+ { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) },
+ { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) }
+};
+
+static struct i2c_adapter sibyte_board_adapter[2] = {
+ {
+ .owner = THIS_MODULE,
+ .id = I2C_HW_SIBYTE,
+ .class = I2C_CLASS_HWMON,
+ .algo = NULL,
+ .algo_data = &sibyte_board_data[0],
+ .name = "SiByte SMBus 0",
+ },
+ {
+ .owner = THIS_MODULE,
+ .id = I2C_HW_SIBYTE,
+ .class = I2C_CLASS_HWMON,
+ .algo = NULL,
+ .algo_data = &sibyte_board_data[1],
+ .name = "SiByte SMBus 1",
+ },
+};
+
+static int __init i2c_sibyte_init(void)
+{
+ printk("i2c-swarm.o: i2c SMBus adapter module for SiByte board\n");
+ if (i2c_sibyte_add_bus(&sibyte_board_adapter[0], K_SMB_FREQ_100KHZ) < 0)
+ return -ENODEV;
+ if (i2c_sibyte_add_bus(&sibyte_board_adapter[1], K_SMB_FREQ_400KHZ) < 0)
+ return -ENODEV;
+ return 0;
+}
+
+static void __exit i2c_sibyte_exit(void)
+{
+ i2c_sibyte_del_bus(&sibyte_board_adapter[0]);
+ i2c_sibyte_del_bus(&sibyte_board_adapter[1]);
+}
+
+module_init(i2c_sibyte_init);
+module_exit(i2c_sibyte_exit);
+
+MODULE_AUTHOR("Kip Walker <[email protected]>, Steven J. Hill <[email protected]>");
+MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards");
+MODULE_LICENSE("GPL");
diff -Nru a/include/linux/i2c-algo-sgi.h b/include/linux/i2c-algo-sgi.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/include/linux/i2c-algo-sgi.h 2005-01-07 14:55:20 -08:00
@@ -0,0 +1,27 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * Copyright (C) 2003 Ladislav Michl <[email protected]>
+ */
+
+#ifndef I2C_ALGO_SGI_H
+#define I2C_ALGO_SGI_H 1
+
+#include <linux/i2c.h>
+
+struct i2c_algo_sgi_data {
+ void *data; /* private data for lowlevel routines */
+ unsigned (*getctrl)(void *data);
+ void (*setctrl)(void *data, unsigned val);
+ unsigned (*rdata)(void *data);
+ void (*wdata)(void *data, unsigned val);
+
+ int xfer_timeout;
+ int ack_timeout;
+};
+
+int i2c_sgi_add_bus(struct i2c_adapter *);
+int i2c_sgi_del_bus(struct i2c_adapter *);
+
+#endif /* I2C_ALGO_SGI_H */
diff -Nru a/include/linux/i2c-algo-sibyte.h b/include/linux/i2c-algo-sibyte.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/include/linux/i2c-algo-sibyte.h 2005-01-07 14:55:20 -08:00
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef I2C_ALGO_SIBYTE_H
+#define I2C_ALGO_SIBYTE_H 1
+
+#include <linux/i2c.h>
+
+struct i2c_algo_sibyte_data {
+ void *data; /* private data */
+ int bus; /* which bus */
+ void *reg_base; /* CSR base */
+};
+
+int i2c_sibyte_add_bus(struct i2c_adapter *, int speed);
+int i2c_sibyte_del_bus(struct i2c_adapter *);
+
+#endif /* I2C_ALGO_SIBYTE_H */
diff -Nru a/include/linux/i2c-id.h b/include/linux/i2c-id.h
--- a/include/linux/i2c-id.h 2005-01-07 14:55:20 -08:00
+++ b/include/linux/i2c-id.h 2005-01-07 14:55:20 -08:00
@@ -109,6 +109,7 @@
#define I2C_DRIVERID_OVCAMCHIP 61 /* OmniVision CMOS image sens. */
#define I2C_DRIVERID_TDA7313 62 /* TDA7313 audio processor */
#define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */
+#define I2C_DRIVERID_SAA7114H 64 /* video decoder */
#define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */
@@ -196,6 +197,9 @@
#define I2C_ALGO_OCP_IOP3XX 0x140000 /* XSCALE IOP3XX On-chip I2C alg */
#define I2C_ALGO_PCA 0x150000 /* PCA 9564 style adapters */
+#define I2C_ALGO_SIBYTE 0x150000 /* Broadcom SiByte SOCs */
+#define I2C_ALGO_SGI 0x160000 /* SGI algorithm */
+
#define I2C_ALGO_EXP 0x800000 /* experimental */
#define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */
@@ -257,6 +261,13 @@
/* --- PowerPC on-chip adapters */
#define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */
+
+/* --- Broadcom SiByte adapters */
+#define I2C_HW_SIBYTE 0x00
+
+/* --- SGI adapters */
+#define I2C_HW_SGI_VINO 0x00
+#define I2C_HW_SGI_MACE 0x01
/* --- XSCALE on-chip adapters */
#define I2C_HW_IOP321 0x00
ChangeSet 1.1938.439.49, 2005/01/06 15:04:58-08:00, [email protected]
[PATCH] I2C: minor isp1301_omap tweaks
Minor cleanups to the isp130_omap driver: enable the right
amount of VBUS current draw in non-OTG configurations; get rid
of a warning from GCC 2.95.3 ("int" function returns no value);
use kcalloc() not kmalloc+memset.
Signed-off-by: David Brownell <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/chips/isp1301_omap.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)
diff -Nru a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
--- a/drivers/i2c/chips/isp1301_omap.c 2005-01-07 14:54:18 -08:00
+++ b/drivers/i2c/chips/isp1301_omap.c 2005-01-07 14:54:18 -08:00
@@ -934,13 +934,14 @@
static void b_peripheral(struct isp1301 *isp)
{
- enable_vbus_draw(isp, 8);
OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
usb_gadget_vbus_connect(isp->otg.gadget);
#ifdef CONFIG_USB_OTG
+ enable_vbus_draw(isp, 8);
otg_update_isp(isp);
#else
+ enable_vbus_draw(isp, 100);
/* UDC driver just set OTG_BSESSVLD */
isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP);
isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN);
@@ -950,7 +951,7 @@
#endif
}
-static int isp_update_otg(struct isp1301 *isp, u8 stat)
+static void isp_update_otg(struct isp1301 *isp, u8 stat)
{
u8 isp_stat, isp_bstat;
enum usb_otg_state state = isp->otg.state;
@@ -1489,11 +1490,9 @@
if (the_transceiver)
return 0;
- isp = kmalloc(sizeof *isp, GFP_KERNEL);
+ isp = kcalloc(1, sizeof *isp, GFP_KERNEL);
if (!isp)
return 0;
-
- memset(isp, 0, sizeof *isp);
INIT_WORK(&isp->work, isp1301_work, isp);
init_timer(&isp->timer);
ChangeSet 1.1938.439.46, 2005/01/06 13:54:52-08:00, [email protected]
[PATCH] I2C: Improve VID code for the W83627THF
This patch cleans up and improves the VID pins value retrieval for the
W83627THF chip in the w83627hf driver. Tested successfully by Mark
Hoffman. The previous code was using an unrelated lock and reading
register values it didn't need. The new code supports 6-bit VID values
(as defined by Intel VRM 10), and also ensures that the GPIO pins are
possibly used as VID inputs.
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/chips/w83627hf.c | 31 +++++++++++++++++++++++--------
1 files changed, 23 insertions(+), 8 deletions(-)
diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
--- a/drivers/i2c/chips/w83627hf.c 2005-01-07 14:54:41 -08:00
+++ b/drivers/i2c/chips/w83627hf.c 2005-01-07 14:54:41 -08:00
@@ -90,9 +90,9 @@
#define DEVID 0x20 /* Register: Device ID */
+#define W83627THF_GPIO5_EN 0x30 /* w83627thf only */
#define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */
#define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */
-#define W83627THF_GPIO5_INVR 0xf5 /* w83627thf only */
static inline void
superio_outb(int reg, int val)
@@ -1190,16 +1190,31 @@
static int w83627thf_read_gpio5(struct i2c_client *client)
{
- struct w83627hf_data *data = i2c_get_clientdata(client);
- int res, inv;
+ int res = 0xff, sel;
- down(&data->lock);
superio_enter();
superio_select(W83627HF_LD_GPIO5);
- res = superio_inb(W83627THF_GPIO5_DR);
- inv = superio_inb(W83627THF_GPIO5_INVR);
+
+ /* Make sure these GPIO pins are enabled */
+ if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) {
+ dev_dbg(&client->dev, "GPIO5 disabled, no VID function\n");
+ goto exit;
+ }
+
+ /* Make sure the pins are configured for input
+ There must be at least five (VRM 9), and possibly 6 (VRM 10) */
+ sel = superio_inb(W83627THF_GPIO5_IOSR);
+ if ((sel & 0x1f) != 0x1f) {
+ dev_dbg(&client->dev, "GPIO5 not configured for VID "
+ "function\n");
+ goto exit;
+ }
+
+ dev_info(&client->dev, "Reading VID from GPIO5\n");
+ res = superio_inb(W83627THF_GPIO5_DR) & sel;
+
+exit:
superio_exit();
- up(&data->lock);
return res;
}
@@ -1272,7 +1287,7 @@
int hi = w83627hf_read_value(client, W83781D_REG_CHIPID);
data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
} else if (w83627thf == data->type) {
- data->vid = w83627thf_read_gpio5(client) & 0x1f;
+ data->vid = w83627thf_read_gpio5(client) & 0x3f;
}
/* Read VRM & OVT Config only once */
ChangeSet 1.1938.445.2, 2004/12/15 11:36:57-08:00, [email protected]
[PATCH] I2C: use chip driver name to request regions
> Trivial patch against 2.6.10-rc3-bk2.
> When request_region is called name is set to "", use module name.
Correct. I even think we should do the same for other chip drivers. For
now they all use an arbitrary string. Using the driver's name would be
both more consistent and more efficient (spares some bytes of memory).
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/chips/lm78.c | 2 +-
drivers/i2c/chips/pc87360.c | 3 ++-
drivers/i2c/chips/smsc47m1.c | 2 +-
drivers/i2c/chips/via686a.c | 2 +-
drivers/i2c/chips/w83627hf.c | 2 +-
drivers/i2c/chips/w83781d.c | 3 ++-
6 files changed, 8 insertions(+), 6 deletions(-)
diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
--- a/drivers/i2c/chips/lm78.c 2005-01-07 14:56:14 -08:00
+++ b/drivers/i2c/chips/lm78.c 2005-01-07 14:56:14 -08:00
@@ -462,7 +462,7 @@
/* Reserve the ISA region */
if (is_isa)
- if (!request_region(address, LM78_EXTENT, "lm78")) {
+ if (!request_region(address, LM78_EXTENT, lm78_driver.name)) {
err = -EBUSY;
goto ERROR0;
}
diff -Nru a/drivers/i2c/chips/pc87360.c b/drivers/i2c/chips/pc87360.c
--- a/drivers/i2c/chips/pc87360.c 2005-01-07 14:56:14 -08:00
+++ b/drivers/i2c/chips/pc87360.c 2005-01-07 14:56:14 -08:00
@@ -756,7 +756,8 @@
for (i = 0; i < 3; i++) {
if (((data->address[i] = extra_isa[i]))
- && !request_region(extra_isa[i], PC87360_EXTENT, "pc87360")) {
+ && !request_region(extra_isa[i], PC87360_EXTENT,
+ pc87360_driver.name)) {
dev_err(&new_client->dev, "Region 0x%x-0x%x already "
"in use!\n", extra_isa[i],
extra_isa[i]+PC87360_EXTENT-1);
diff -Nru a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c
--- a/drivers/i2c/chips/smsc47m1.c 2005-01-07 14:56:14 -08:00
+++ b/drivers/i2c/chips/smsc47m1.c 2005-01-07 14:56:14 -08:00
@@ -400,7 +400,7 @@
return 0;
}
- if (!request_region(address, SMSC_EXTENT, "smsc47m1")) {
+ if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
return -EBUSY;
}
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c 2005-01-07 14:56:14 -08:00
+++ b/drivers/i2c/chips/via686a.c 2005-01-07 14:56:14 -08:00
@@ -613,7 +613,7 @@
}
/* Reserve the ISA region */
- if (!request_region(address, VIA686A_EXTENT, "via686a-sensor")) {
+ if (!request_region(address, VIA686A_EXTENT, via686a_driver.name)) {
dev_err(&adapter->dev,"region 0x%x already in use!\n",
address);
return -ENODEV;
diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
--- a/drivers/i2c/chips/w83627hf.c 2005-01-07 14:56:14 -08:00
+++ b/drivers/i2c/chips/w83627hf.c 2005-01-07 14:56:14 -08:00
@@ -984,7 +984,7 @@
if(force_addr)
address = force_addr & ~(WINB_EXTENT - 1);
- if (!request_region(address, WINB_EXTENT, "w83627hf")) {
+ if (!request_region(address, WINB_EXTENT, w83627hf_driver.name)) {
err = -EBUSY;
goto ERROR0;
}
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c 2005-01-07 14:56:14 -08:00
+++ b/drivers/i2c/chips/w83781d.c 2005-01-07 14:56:14 -08:00
@@ -1065,7 +1065,8 @@
}
if (is_isa)
- if (!request_region(address, W83781D_EXTENT, "w83781d")) {
+ if (!request_region(address, W83781D_EXTENT,
+ w83781d_driver.name)) {
dev_dbg(&adapter->dev, "Request of region "
"0x%x-0x%x for w83781d failed\n", address,
address + W83781D_EXTENT - 1);
ChangeSet 1.1938.439.52, 2005/01/06 16:22:21-08:00, [email protected]
[PATCH] I2C: vid version detection fix
AMD 64 uses same VID table as Opteron.
Source:
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25112.PDF
Signed-off-by: Rudolf Marek <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/i2c-sensor-vid.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff -Nru a/drivers/i2c/i2c-sensor-vid.c b/drivers/i2c/i2c-sensor-vid.c
--- a/drivers/i2c/i2c-sensor-vid.c 2005-01-07 14:53:54 -08:00
+++ b/drivers/i2c/i2c-sensor-vid.c 2005-01-07 14:53:54 -08:00
@@ -36,8 +36,7 @@
static struct vrm_model vrm_models[] = {
{X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */
- {X86_VENDOR_AMD, 0xF, 0x4, 90}, /* Athlon 64 */
- {X86_VENDOR_AMD, 0xF, 0x5, 24}, /* Opteron */
+ {X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */
{X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */
{X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* 0xB Tualatin */
{X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */
@@ -87,7 +86,7 @@
return vrm_ret;
}
-/* and now something completely different for Non-x86 world*/
+/* and now for something completely different for Non-x86 world*/
#else
int i2c_which_vrm(void)
{
ChangeSet 1.1938.445.7, 2004/12/17 15:30:27-08:00, [email protected]
[PATCH] I2C: Discard old driver porting documentation
The Documentation/i2c/i2c-old-porting file is outdated. There are no
more drivers left to be ported from that old i2c model (from the times
of Linux 2.2). Let's simply delete that file.
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Documentation/i2c/i2c-old-porting | 626 --------------------------------------
1 files changed, 626 deletions(-)
diff -Nru a/Documentation/i2c/i2c-old-porting b/Documentation/i2c/i2c-old-porting
--- a/Documentation/i2c/i2c-old-porting 2005-01-07 14:55:35 -08:00
+++ /dev/null Wed Dec 31 16:00:00 196900
@@ -1,626 +0,0 @@
-I2C Conversion Guide for I2C-old to the current I2C API
-July 2002
-For Linux Kernel v2.5.x
-Frank Davis <[email protected]>
--------------------------------------------------------
-
-There exists several kernel drivers that are using an old version of the I2C
-API. These drivers need to be converted to the current (kernel 2.5.x) version.
-The following document provides a guideline to make the appropriate changes to
-the affected drivers. There maybe slight modifications to this guide that are
-specific to the driver you are working on. If you see {driver_name}, replace
-that with the respective name of the driver, such as saa7110.c , {driver_name}
-= saa7110.
-
--------------------------------------------------------
-
-Step 1: Include the right header file
-
-Perform the following change within the driver
-
-#include <linux/i2c-old.h> --> #include <linux/i2c.h>
-
-Step 2: Add and set the i2c modes
-
-Add the following code near the top of the driver
-
-static unsigned short normal_i2c[] = {34>>1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
-
-static struct i2c_client_address_data addr_data = {
- normal_i2c , normal_i2c_range,
- probe , probe_range,
- ignore , ignore_range,
- force
-};
-
-static struct i2c_client client_template;
-
-Step 3: Modify the driver info struct
-
-Within the struct for the driver , such as struct {driver_name} , make the
-following change ,
-struct i2c_bus *bus --> struct i2c_client *client
-
-Make changes where this change affects references within the file.
-
-Add a semaphore to the driver struct (as above)
-
-struct semaphore lock
-
-Step 5: Remove specific read and write functions
-
-Remove the driver specific write and read functions, usually in the form:
-{driver_name}_write , {driver_name}_read , {driver_name}_write_block , etc.
-
-Step 6: Update the write and read functions for the current I2C API
-
-Replace all references of {driver_name}_write with i2c_smbus_write_byte_data
-Replace all references of {driver_name}_read with i2c_smbus_read_byte_data or
-i2c_smbus_read_byte , depending on args passed in.
-
-** Ensure that these functions pass in the i2c_client *client , NOT the
-decoder/encoder that was passed in the driver specific write and read
-functions.
-
-Step 7: Modify the driver's attach function
-
-Change the driver attach function prototype :
-{driver_name}_attach(struct i2c_device *device) --> {driver_name}_attach(struct
-i2c_adapter *adap, int addr , unsigned short flags, int kind)
-
-Create a i2c_client client...
-Add the following (where "decoder" is a reference to a struct for the driver
-info:
-
-struct i2c_client *client;
-client = kmalloc(sizeof(*client), GFP_KERNEL);
-if(client == NULL)
- return -ENOMEM;
-client_template.adapter = adap;
-client_template.addr = addr;
-memcpy(client, &client_template, sizeof(*client));
-strcpy(client->name , "{driver_name}");
-decoder->client = client;
-client->data = decoder;
-decoder->addr = addr;
-
-Towards the end of the function, add:
-
-init_MUTEX(&decoder->lock);
-i2c_attach_client(client);
-
-
-Step 8: Modify the driver's detach function
-
-Change the driver detach function prototype :
-{driver_name}_detach(struct i2c_device *device) --> {driver_name}_detach(struct
-i2c_client *client)
-
-In the beginning of the detach function, add:
-i2c_detach_client(client);
-
-Towards the end of the detach function, add:
-kfree(client->data);
-kfree(client);
-
-Step 9: Modify the driver's command function
-
-Change the driver command function prototype :
-
-Step 10: Add the probe function after the driver's attach function.
-
-Add the following code:
-
-static int {driver_name}_probe(struct i2c_adapter *adap)
-{
- return i2c_probe(adap, &addr_data, {driver_name}_attach);
-
-}
-
-Step 11: Modify the driver's i2c_driver
-
-Find the i2c_driver , such as
-static struct i2c_driver i2c_driver_saa7110
-It is usually located towards the end of the driver
-Replace the values from I2C_DRIVERID_{something} to {driver_name}_attach, and
-add the following
-I2C_DRIVERID_{driver_name} , // verify by looking in include/linux/i2c-id.h
-I2C_DF_NOTIFY,
-{driver_name}_probe,
-....
-
-Step 12: Adding the i2c_client
-
-Add the i2c_client to the driver. Add the following code:
-
-static struct i2c_client client_template = {
- "{driver_name}_client",
- -1,
- 0,
- 0,
- NULL,
- {i2c_driver reference}
-};
-
-Step 13: Registering and Unregistering
-
-Replace i2c_register_driver with i2c_add_driver
-Replace i2c_unregister_driver with i2c_del_driver
-
--------------------------------------------------------
-
-Example:
-
-The following patch provides the i2c coversion patch for the saa7110 driver
-based on the above guide (for clarity).
-
-
---- drivers/media/video/saa7110.c.old Fri Jun 28 10:22:52 2002
-+++ drivers/media/video/saa7110.c Thu Jul 4 16:51:08 2002
-@@ -26,7 +26,7 @@
- #include <asm/io.h>
- #include <asm/uaccess.h>
-
--#include <linux/i2c-old.h>
-+#include <linux/i2c.h>
- #include <linux/videodev.h>
- #include "linux/video_decoder.h"
-
-@@ -37,13 +37,31 @@
-
- #define I2C_SAA7110 0x9C /* or 0x9E */
-
-+#define IF_NAME "saa7110"
- #define I2C_DELAY 10 /* 10 us or 100khz */
-
-+static unsigned short normal_i2c[] = {34>>1, I2C_CLIENT_END };
-+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-+static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-+static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-+static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-+static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-+static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-+
-+static struct i2c_client_address_data addr_data = {
-+ normal_i2c, normal_i2c_range,
-+ probe, probe_range,
-+ ignore, ignore_range,
-+ force
-+};
-+
-+static struct i2c_client client_template;
-+
- struct saa7110 {
-- struct i2c_bus *bus;
-+ struct i2c_client *client;
- int addr;
- unsigned char reg[36];
--
-+ struct semaphore lock;
- int norm;
- int input;
- int enable;
-@@ -54,67 +72,10 @@
- };
-
- /* ----------------------------------------------------------------------- */
--/* I2C support functions */
--/* ----------------------------------------------------------------------- */
--static
--int saa7110_write(struct saa7110 *decoder, unsigned char subaddr, unsigned char data)
--{
-- int ack;
--
-- LOCK_I2C_BUS(decoder->bus);
-- i2c_start(decoder->bus);
-- i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
-- i2c_sendbyte(decoder->bus, subaddr, I2C_DELAY);
-- ack = i2c_sendbyte(decoder->bus, data, I2C_DELAY);
-- i2c_stop(decoder->bus);
-- decoder->reg[subaddr] = data;
-- UNLOCK_I2C_BUS(decoder->bus);
-- return ack;
--}
--
--static
--int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len)
--{
-- unsigned subaddr = *data;
--
-- LOCK_I2C_BUS(decoder->bus);
-- i2c_start(decoder->bus);
-- i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY);
-- while (len-- > 0) {
-- if (i2c_sendbyte(decoder->bus,*data,0)) {
-- i2c_stop(decoder->bus);
-- UNLOCK_I2C_BUS(decoder->bus);
-- return -EAGAIN;
-- }
-- decoder->reg[subaddr++] = *data++;
-- }
-- i2c_stop(decoder->bus);
-- UNLOCK_I2C_BUS(decoder->bus);
--
-- return 0;
--}
--
--static
--int saa7110_read(struct saa7110* decoder)
--{
-- int data;
--
-- LOCK_I2C_BUS(decoder->bus);
-- i2c_start(decoder->bus);
-- i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
-- i2c_start(decoder->bus);
-- i2c_sendbyte(decoder->bus, decoder->addr | 1, I2C_DELAY);
-- data = i2c_readbyte(decoder->bus, 1);
-- i2c_stop(decoder->bus);
-- UNLOCK_I2C_BUS(decoder->bus);
-- return data;
--}
--
--/* ----------------------------------------------------------------------- */
- /* SAA7110 functions */
- /* ----------------------------------------------------------------------- */
- static
--int saa7110_selmux(struct i2c_device *device, int chan)
-+int saa7110_selmux(struct i2c_client *client, int chan)
- {
- static const unsigned char modes[9][8] = {
- /* mode 0 */ { 0x00, 0xD9, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 },
-@@ -126,61 +87,59 @@
- /* mode 6 */ { 0x80, 0x59, 0x17, 0x42, 0xA3, 0x44, 0x75, 0x12 },
- /* mode 7 */ { 0x80, 0x9A, 0x17, 0xB1, 0x13, 0x60, 0xB5, 0x14 },
- /* mode 8 */ { 0x80, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21 } };
-- struct saa7110* decoder = device->data;
- const unsigned char* ptr = modes[chan];
-
-- saa7110_write(decoder,0x06,ptr[0]); /* Luminance control */
-- saa7110_write(decoder,0x20,ptr[1]); /* Analog Control #1 */
-- saa7110_write(decoder,0x21,ptr[2]); /* Analog Control #2 */
-- saa7110_write(decoder,0x22,ptr[3]); /* Mixer Control #1 */
-- saa7110_write(decoder,0x2C,ptr[4]); /* Mixer Control #2 */
-- saa7110_write(decoder,0x30,ptr[5]); /* ADCs gain control */
-- saa7110_write(decoder,0x31,ptr[6]); /* Mixer Control #3 */
-- saa7110_write(decoder,0x21,ptr[7]); /* Analog Control #2 */
-+ i2c_smbus_write_byte_data(client,0x06,ptr[0]); /* Luminance control */
-+ i2c_smbus_write_byte_data(client,0x20,ptr[1]); /* Analog Control #1 */
-+ i2c_smbus_write_byte_data(client,0x21,ptr[2]); /* Analog Control #2 */
-+ i2c_smbus_write_byte_data(client,0x22,ptr[3]); /* Mixer Control #1 */
-+ i2c_smbus_write_byte_data(client,0x2C,ptr[4]); /* Mixer Control #2 */
-+ i2c_smbus_write_byte_data(client,0x30,ptr[5]); /* ADCs gain control */
-+ i2c_smbus_write_byte_data(client,0x31,ptr[6]); /* Mixer Control #3 */
-+ i2c_smbus_write_byte_data(client,0x21,ptr[7]); /* Analog Control #2 */
-
- return 0;
- }
-
- static
--int determine_norm(struct i2c_device* dev)
-+int determine_norm(struct i2c_client* client)
- {
-- struct saa7110* decoder = dev->data;
- int status;
-
- /* mode changed, start automatic detection */
-- status = saa7110_read(decoder);
-+ status = i2c_smbus_read_byte(client);
- if ((status & 3) == 0) {
-- saa7110_write(decoder,0x06,0x80);
-+ i2c_smbus_write_byte_data(client,0x06,0x80);
- if (status & 0x20) {
-- DEBUG(printk(KERN_INFO "%s: norm=bw60\n",dev->name));
-- saa7110_write(decoder,0x2E,0x81);
-+ DEBUG(printk(KERN_INFO "%s: norm=bw60\n",adp->name));
-+ i2c_smbus_write_byte_data(client,0x2E,0x81);
- return VIDEO_MODE_NTSC;
- }
-- DEBUG(printk(KERN_INFO "%s: norm=bw50\n",dev->name));
-- saa7110_write(decoder,0x2E,0x9A);
-+ DEBUG(printk(KERN_INFO "%s: norm=bw50\n",adp->name));
-+ i2c_smbus_write_byte_data(client,0x2E,0x9A);
- return VIDEO_MODE_PAL;
- }
-
-- saa7110_write(decoder,0x06,0x00);
-+ i2c_smbus_write_byte_data(client,0x06,0x00);
- if (status & 0x20) { /* 60Hz */
-- DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",dev->name));
-- saa7110_write(decoder,0x0D,0x06);
-- saa7110_write(decoder,0x11,0x2C);
-- saa7110_write(decoder,0x2E,0x81);
-+ DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",adp->name));
-+ i2c_smbus_write_byte_data(client,0x0D,0x06);
-+ i2c_smbus_write_byte_data(client,0x11,0x2C);
-+ i2c_smbus_write_byte_data(client,0x2E,0x81);
- return VIDEO_MODE_NTSC;
- }
-
- /* 50Hz -> PAL/SECAM */
-- saa7110_write(decoder,0x0D,0x06);
-- saa7110_write(decoder,0x11,0x59);
-- saa7110_write(decoder,0x2E,0x9A);
-+ i2c_smbus_write_byte_data(client,0x0D,0x06);
-+ i2c_smbus_write_byte_data(client,0x11,0x59);
-+ i2c_smbus_write_byte_data(client,0x2E,0x9A);
-
- mdelay(150); /* pause 150 ms */
-
-- status = saa7110_read(decoder);
-+ status = i2c_smbus_read_byte(client);
- if ((status & 0x03) == 0x01) {
- DEBUG(printk(KERN_INFO "%s: norm=secam\n",dev->name));
-- saa7110_write(decoder,0x0D,0x07);
-+ i2c_smbus_write_byte_data(client,0x0D,0x07);
- return VIDEO_MODE_SECAM;
- }
- DEBUG(printk(KERN_INFO "%s: norm=pal\n",dev->name));
-@@ -188,7 +147,7 @@
- }
-
- static
--int saa7110_attach(struct i2c_device *device)
-+int saa7110_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)
- {
- static const unsigned char initseq[] = {
- 0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF0, 0x00, 0x00,
-@@ -198,20 +157,28 @@
- 0xD9, 0x17, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
- 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x81, 0x03,
- 0x40, 0x75, 0x01, 0x8C, 0x03};
-- struct saa7110* decoder;
-+ struct saa7110 *decoder;
-+ struct i2c_client *client;
- int rv;
--
-- device->data = decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
-- if (device->data == 0)
-+ client=kmalloc(sizeof(*client), GFP_KERNEL);
-+ if(client == NULL)
- return -ENOMEM;
--
-+ client_template.adapter = adap;
-+ client_template.addr = addr;
-+ memcpy(client, &client_template, sizeof(*client));
-+
-+ decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
-+ if (decoder == NULL) {
-+ kfree(client);
-+ return -ENOMEM;
-+ }
-
- /* clear our private data */
-- memset(decoder, 0, sizeof(struct saa7110));
-- strcpy(device->name, "saa7110");
-- decoder->bus = device->bus;
-- decoder->addr = device->addr;
-+ memset(decoder, 0, sizeof(*decoder));
-+ strcpy(client->name, IF_NAME);
-+ decoder->client = client;
-+ client->data = decoder;
-+ decoder->addr = addr;
- decoder->norm = VIDEO_MODE_PAL;
- decoder->input = 0;
- decoder->enable = 1;
-@@ -220,40 +187,52 @@
- decoder->hue = 32768;
- decoder->sat = 32768;
-
-- rv = saa7110_write_block(decoder, initseq, sizeof(initseq));
-+ rv = i2c_master_send(client, initseq, sizeof(initseq));
- if (rv < 0)
-- printk(KERN_ERR "%s_attach: init status %d\n", device->name, rv);
-+ printk(KERN_ERR "%s_attach: init status %d\n", client->name, rv);
- else {
-- saa7110_write(decoder,0x21,0x16);
-- saa7110_write(decoder,0x0D,0x04);
-- DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7110_read(decoder)));
-- saa7110_write(decoder,0x0D,0x06);
-+ i2c_smbus_write_byte_data(client,0x21,0x16);
-+ i2c_smbus_write_byte_data(client,0x0D,0x04);
-+ DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", client->name, i2c_smbus_read_byte(client)));
-+ i2c_smbus_write_byte_data(client,0x0D,0x06);
- }
-
-+ init_MUTEX(&decoder->lock);
-+ i2c_attach_client(client);
- /* setup and implicit mode 0 select has been performed */
- return 0;
- }
-
-+static
-+int saa7110_probe(struct i2c_adapter *adap)
-+{
-+ return i2c_probe(adap, &addr_data, saa7110_attach);
-+}
-+
- static
--int saa7110_detach(struct i2c_device *device)
-+int saa7110_detach(struct i2c_client *client)
- {
-- struct saa7110* decoder = device->data;
-+ struct saa7110* decoder = client->data;
-
-- DEBUG(printk(KERN_INFO "%s_detach\n",device->name));
-+ i2c_detach_client(client);
-+
-+ DEBUG(printk(KERN_INFO "%s_detach\n",client->name));
-
- /* stop further output */
-- saa7110_write(decoder,0x0E,0x00);
-+ i2c_smbus_write_byte_data(client,0x0E,0x00);
-
-- kfree(device->data);
-+ kfree(decoder);
-+ kfree(client);
-
- return 0;
- }
-
- static
--int saa7110_command(struct i2c_device *device, unsigned int cmd, void *arg)
-+int saa7110_command(struct i2c_client *client, unsigned int cmd, void *arg)
- {
-- struct saa7110* decoder = device->data;
-+ struct saa7110* decoder = client->data;
- int v;
-
- switch (cmd) {
-@@ -272,11 +251,11 @@
-
- case DECODER_GET_STATUS:
- {
-- struct saa7110* decoder = device->data;
-+ struct saa7110* decoder = client->data;
- int status;
- int res = 0;
-
-- status = i2c_read(device->bus,device->addr|1);
-+ status = i2c_smbus_read_byte(client);
- if (status & 0x40)
- res |= DECODER_STATUS_GOOD;
- if (status & 0x03)
-@@ -301,26 +280,26 @@
- v = *(int*)arg;
- if (decoder->norm != v) {
- decoder->norm = v;
-- saa7110_write(decoder, 0x06, 0x00);
-+ i2c_smbus_write_byte_data(client, 0x06, 0x00);
- switch (v) {
- case VIDEO_MODE_NTSC:
-- saa7110_write(decoder, 0x0D, 0x06);
-- saa7110_write(decoder, 0x11, 0x2C);
-- saa7110_write(decoder, 0x30, 0x81);
-- saa7110_write(decoder, 0x2A, 0xDF);
-+ i2c_smbus_write_byte_data(client, 0x0D, 0x06);
-+ i2c_smbus_write_byte_data(client, 0x11, 0x2C);
-+ i2c_smbus_write_byte_data(client, 0x30, 0x81);
-+ i2c_smbus_write_byte_data(client, 0x2A, 0xDF);
- break;
- case VIDEO_MODE_PAL:
-- saa7110_write(decoder, 0x0D, 0x06);
-- saa7110_write(decoder, 0x11, 0x59);
-- saa7110_write(decoder, 0x2E, 0x9A);
-+ i2c_smbus_write_byte_data(client, 0x0D, 0x06);
-+ i2c_smbus_write_byte_data(client, 0x11, 0x59);
-+ i2c_smbus_write_byte_data(client, 0x2E, 0x9A);
- break;
- case VIDEO_MODE_SECAM:
-- saa7110_write(decoder, 0x0D, 0x07);
-- saa7110_write(decoder, 0x11, 0x59);
-- saa7110_write(decoder, 0x2E, 0x9A);
-+ i2c_smbus_write_byte_data(client, 0x0D, 0x07);
-+ i2c_smbus_write_byte_data(client, 0x11, 0x59);
-+ i2c_smbus_write_byte_data(client, 0x2E, 0x9A);
- break;
- case VIDEO_MODE_AUTO:
-- *(int*)arg = determine_norm(device);
-+ *(int*)arg = determine_norm(client);
- break;
- default:
- return -EPERM;
-@@ -334,7 +313,7 @@
- return -EINVAL;
- if (decoder->input != v) {
- decoder->input = v;
-- saa7110_selmux(device, v);
-+ saa7110_selmux(client, v);
- }
- break;
-
-@@ -349,7 +328,7 @@
- v = *(int*)arg;
- if (decoder->enable != v) {
- decoder->enable = v;
-- saa7110_write(decoder,0x0E, v ? 0x18 : 0x00);
-+ i2c_smbus_write_byte_data(client,0x0E, v ? 0x18 : 0x00);
- }
- break;
-
-@@ -360,22 +339,22 @@
- if (decoder->bright != pic->brightness) {
- /* We want 0 to 255 we get 0-65535 */
- decoder->bright = pic->brightness;
-- saa7110_write(decoder, 0x19, decoder->bright >> 8);
-+ i2c_smbus_write_byte_data(client, 0x19, decoder->bright >> 8);
- }
- if (decoder->contrast != pic->contrast) {
- /* We want 0 to 127 we get 0-65535 */
- decoder->contrast = pic->contrast;
-- saa7110_write(decoder, 0x13, decoder->contrast >> 9);
-+ i2c_smbus_write_byte_data(client, 0x13, decoder->contrast >> 9);
- }
- if (decoder->sat != pic->colour) {
- /* We want 0 to 127 we get 0-65535 */
- decoder->sat = pic->colour;
-- saa7110_write(decoder, 0x12, decoder->sat >> 9);
-+ i2c_smbus_write_byte_data(client, 0x12, decoder->sat >> 9);
- }
- if (decoder->hue != pic->hue) {
- /* We want -128 to 127 we get 0-65535 */
- decoder->hue = pic->hue;
-- saa7110_write(decoder, 0x07, (decoder->hue>>8)-128);
-+ i2c_smbus_write_byte_data(client, 0x07, (decoder->hue>>8)-128);
- }
- }
- break;
-@@ -383,7 +362,7 @@
- case DECODER_DUMP:
- for (v=0; v<34; v+=16) {
- int j;
-- DEBUG(printk(KERN_INFO "%s: %03x\n",device->name,v));
-+ DEBUG(printk(KERN_INFO "%s: %03x\n",client->name,v));
- for (j=0; j<16; j++) {
- DEBUG(printk(KERN_INFO " %02x",decoder->reg[v+j]));
- }
-@@ -402,24 +381,30 @@
-
- static struct i2c_driver i2c_driver_saa7110 =
- {
-- "saa7110", /* name */
--
-- I2C_DRIVERID_VIDEODECODER, /* in i2c.h */
-- I2C_SAA7110, I2C_SAA7110+1, /* Addr range */
--
-- saa7110_attach,
-- saa7110_detach,
-- saa7110_command
-+ .owner = THIS_MODULE,
-+ .name = IF_NAME,
-+ .id = I2C_DRIVERID_SAA7110,
-+ .flags = I2C_DF_NOTIFY,
-+ .attach_adapter = saa7110_probe,
-+ .detach_adapter = saa7110_detach,
-+ .command = saa7110_command,
- };
-+static struct i2c_client client_template = {
-+ "saa7110_client",
-+ -1,
-+ 0,
-+ 0,
-+ NULL,
-+ &i2c_driver_saa7110
-+};
-
- static int saa7110_init(void)
- {
-- return i2c_register_driver(&i2c_driver_saa7110);
-+ return i2c_add_driver(&i2c_driver_saa7110);
- }
-
- static void saa7110_exit(void)
- {
-- i2c_unregister_driver(&i2c_driver_saa7110);
-+ i2c_del_driver(&i2c_driver_saa7110);
- }
-
-
-
-
ChangeSet 1.1938.445.3, 2004/12/15 11:37:22-08:00, [email protected]
[PATCH] I2C: i2c-algo-bit should support I2C_FUNC_I2C
Signed-off-by: Ian Campbell <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/algos/i2c-algo-pca.c | 4 ++--
drivers/i2c/algos/i2c-algo-pcf.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff -Nru a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
--- a/drivers/i2c/algos/i2c-algo-pca.c 2005-01-07 14:56:06 -08:00
+++ b/drivers/i2c/algos/i2c-algo-pca.c 2005-01-07 14:56:06 -08:00
@@ -189,7 +189,7 @@
state = pca_status(adap);
if ( state != 0xF8 ) {
- printk(KERN_ERR DRIVER ": bus is not idle. status is %#04x\n", state );
+ dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state );
/* FIXME: what to do. Force stop ? */
return -EREMOTEIO;
}
@@ -328,7 +328,7 @@
static u32 pca_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static int pca_init(struct i2c_algo_pca_data *adap)
diff -Nru a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
--- a/drivers/i2c/algos/i2c-algo-pcf.c 2005-01-07 14:56:06 -08:00
+++ b/drivers/i2c/algos/i2c-algo-pcf.c 2005-01-07 14:56:06 -08:00
@@ -414,8 +414,8 @@
static u32 pcf_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
- I2C_FUNC_PROTOCOL_MANGLING;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
}
/* -----exported algorithm data: ------------------------------------- */
ChangeSet 1.1938.439.48, 2005/01/06 13:55:55-08:00, [email protected]
[PATCH] I2C: Add byte commands to i2c-stub
While working on EEPROMs, DDC/EDID and the like these last few days, I
wanted to use your i2c-stub driver to test my code. However, I noticed
that it wouldn't handle byte commands, while both i2cdetect and the
eeprom driver need it for proper operation. Thus I added this
functionality to the driver. What do you think about it?
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Documentation/i2c/i2c-stub | 9 +++++++--
drivers/i2c/busses/i2c-stub.c | 22 ++++++++++++++++++++--
2 files changed, 27 insertions(+), 4 deletions(-)
diff -Nru a/Documentation/i2c/i2c-stub b/Documentation/i2c/i2c-stub
--- a/Documentation/i2c/i2c-stub 2005-01-07 14:54:26 -08:00
+++ b/Documentation/i2c/i2c-stub 2005-01-07 14:54:26 -08:00
@@ -2,13 +2,18 @@
DESCRIPTION:
-This module is a very simple fake I2C/SMBus driver. It implements three
-types of SMBus commands: write quick, (r/w) byte data, and (r/w) word data.
+This module is a very simple fake I2C/SMBus driver. It implements four
+types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, and
+(r/w) word data.
No hardware is needed nor associated with this module. It will accept write
quick commands to all addresses; it will respond to the other commands (also
to all addresses) by reading from or writing to an array in memory. It will
also spam the kernel logs for every command it handles.
+
+A pointer register with auto-increment is implemented for all byte
+operations. This allows for continuous byte reads like those supported by
+EEPROMs, among others.
The typical use-case is like this:
1. load this module
diff -Nru a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
--- a/drivers/i2c/busses/i2c-stub.c 2005-01-07 14:54:26 -08:00
+++ b/drivers/i2c/busses/i2c-stub.c 2005-01-07 14:54:26 -08:00
@@ -28,6 +28,7 @@
#include <linux/errno.h>
#include <linux/i2c.h>
+static u8 stub_pointer;
static u8 stub_bytes[256];
static u16 stub_words[256];
@@ -44,6 +45,22 @@
ret = 0;
break;
+ case I2C_SMBUS_BYTE:
+ if (read_write == I2C_SMBUS_WRITE) {
+ stub_pointer = command;
+ dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
+ "wrote 0x%02x.\n",
+ addr, command);
+ } else {
+ data->byte = stub_bytes[stub_pointer++];
+ dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
+ "read 0x%02x.\n",
+ addr, data->byte);
+ }
+
+ ret = 0;
+ break;
+
case I2C_SMBUS_BYTE_DATA:
if (read_write == I2C_SMBUS_WRITE) {
stub_bytes[command] = data->byte;
@@ -56,6 +73,7 @@
"read 0x%02x at 0x%02x.\n",
addr, data->byte, command);
}
+ stub_pointer = command + 1;
ret = 0;
break;
@@ -87,8 +105,8 @@
static u32 stub_func(struct i2c_adapter *adapter)
{
- return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE_DATA |
- I2C_FUNC_SMBUS_WORD_DATA;
+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
}
static struct i2c_algorithm smbus_algorithm = {
Hi all:
* Greg KH <[email protected]> [2005-01-07 21:39:36 -0800]:
> ChangeSet 1.1938.445.11, 2004/12/21 11:09:49-08:00, [email protected]
>
> [PATCH] I2C: it87.c update
>
> - adds manual PWM
> - removes buggy "reset" module parameter
> - fixes some whitespaces
>
> Signed-off-by: Jonas Munsin <[email protected]>
> Signed-off-by: Greg Kroah-Hartman <[email protected]>
You might hold off on this one patch... see this:
http://marc.theaimsgroup.com/?l=linux-kernel&m=110514540928517&w=3
Regards,
--
Mark M. Hoffman
[email protected]
Hi Mark,
> * Greg KH <[email protected]> [2005-01-07 21:39:36 -0800]:
> > ChangeSet 1.1938.445.11, 2004/12/21 11:09:49-08:00, [email protected]
> >
> > [PATCH] I2C: it87.c update
> >
> > - adds manual PWM
> > - removes buggy "reset" module parameter
> > - fixes some whitespaces
> >
> > Signed-off-by: Jonas Munsin <[email protected]>
> > Signed-off-by: Greg Kroah-Hartman <[email protected]>
>
> You might hold off on this one patch... see this:
>
> http://marc.theaimsgroup.com/?l=linux-kernel&m=110514540928517&w=3
I second Mark on that. Please do not merge this one until Jonas and I
have analyzed the problem and found an acceptable solution. Stopping
fans on module load isn't exactly a good driver behavior :(
Thanks,
--
Jean Delvare
http://khali.linux-fr.org/
ChangeSet 1.1938.439.54, 2005/01/07 11:15:15-08:00, [email protected]
[PATCH] I2C: let I2C_ALGO_SGI depend on MIPS
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/algos/Kconfig | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
diff -Nru a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
--- a/drivers/i2c/algos/Kconfig 2005-01-07 14:53:33 -08:00
+++ b/drivers/i2c/algos/Kconfig 2005-01-07 14:53:33 -08:00
@@ -61,7 +61,7 @@
config I2C_ALGO_SGI
tristate "I2C SGI interfaces"
- depends on I2C
+ depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS)
help
Supports the SGI interfaces like the ones found on SGI Indy VINO
or SGI O2 MACE.
ChangeSet 1.1938.439.55, 2005/01/07 11:16:13-08:00, [email protected]
[PATCH] i2c-ali1563: fix init & exit section usage
Fix init & exit section usages, beginning with this diagnostic
from reference_discarded.pl (make buildcheck):
Error: ./drivers/i2c/busses/i2c-ali1563.o .data refers to 00000278 R_386_32 .exit.text
Signed-off-by: Randy Dunlap <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/busses/i2c-ali1563.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
--- a/drivers/i2c/busses/i2c-ali1563.c 2005-01-07 14:53:24 -08:00
+++ b/drivers/i2c/busses/i2c-ali1563.c 2005-01-07 14:53:24 -08:00
@@ -306,7 +306,7 @@
pci_write_config_word(dev,ALI1563_SMBBA,ctrl);
}
-static int __init ali1563_setup(struct pci_dev * dev)
+static int __devinit ali1563_setup(struct pci_dev * dev)
{
u16 ctrl;
@@ -362,7 +362,7 @@
.algo = &ali1563_algorithm,
};
-static int __init ali1563_probe(struct pci_dev * dev,
+static int __devinit ali1563_probe(struct pci_dev * dev,
const struct pci_device_id * id_table)
{
int error;
@@ -378,7 +378,7 @@
return error;
}
-static void __exit ali1563_remove(struct pci_dev * dev)
+static void __devexit ali1563_remove(struct pci_dev * dev)
{
i2c_del_adapter(&ali1563_adapter);
ali1563_shutdown(dev);
@@ -395,7 +395,7 @@
.name = "ali1563_i2c",
.id_table = ali1563_id_table,
.probe = ali1563_probe,
- .remove = ali1563_remove,
+ .remove = __devexit_p(ali1563_remove),
};
static int __init ali1563_init(void)
ChangeSet 1.1938.439.47, 2005/01/06 13:55:26-08:00, [email protected]
[PATCH] I2C: Fix MAX6657/8/9 detection in lm90
I received no additional feedback about my MAX6657/8/9 detection fix.
Since it was correct for the only chips I got a report for, I propose we
apply it. After all, maybe people don't know they have such a chip
because the detection was previously not correct.
The patch below is the one I sent to the LM Sensors and Linux Kernel
mailing-lists two weeks ago, unchanged. Thanks.
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
drivers/i2c/chips/lm90.c | 28 ++++++++++++++++++++--------
1 files changed, 20 insertions(+), 8 deletions(-)
diff -Nru a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
--- a/drivers/i2c/chips/lm90.c 2005-01-07 14:54:33 -08:00
+++ b/drivers/i2c/chips/lm90.c 2005-01-07 14:54:33 -08:00
@@ -35,12 +35,13 @@
* Among others, it has a higher accuracy than the LM90, much like the
* LM86 does.
*
- * This driver also supports the MAX6657 and MAX6658, sensor chips made
- * by Maxim. These chips are similar to the LM86. Complete datasheet
- * can be obtained at Maxim's website at:
+ * This driver also supports the MAX6657, MAX6658 and MAX6659 sensor
+ * chips made by Maxim. These chips are similar to the LM86. Complete
+ * datasheet can be obtained at Maxim's website at:
* http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
- * Note that there is no way to differenciate between both chips (but
- * no need either).
+ * Note that there is no easy way to differenciate between the three
+ * variants. The extra address and features of the MAX6659 are not
+ * supported by this driver.
*
* Since the LM90 was the first chipset supported by this driver, most
* comments will refer to this chipset, but are actually general and
@@ -70,9 +71,11 @@
/*
* Addresses to scan
- * Address is fully defined internally and cannot be changed.
+ * 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.
+ * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
*/
static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
@@ -386,8 +389,17 @@
}
} else
if (man_id == 0x4D) { /* Maxim */
- if (address == 0x4C
- && (reg_config1 & 0x1F) == 0
+ /*
+ * The Maxim variants do NOT have a chip_id register.
+ * Reading from that address will return the last read
+ * value, which in our case is those of the man_id
+ * register. Likewise, the config1 register seems to
+ * lack a low nibble, so the value will be those of the
+ * previous read, so in our case those of the man_id
+ * register.
+ */
+ if (chip_id == man_id
+ && (reg_config1 & 0x1F) == (man_id & 0x0F)
&& reg_convrate <= 0x09) {
kind = max6657;
}
On Sat, Jan 08, 2005 at 11:15:28AM +0100, Jean Delvare wrote:
> Hi Mark,
>
> > * Greg KH <[email protected]> [2005-01-07 21:39:36 -0800]:
> > > ChangeSet 1.1938.445.11, 2004/12/21 11:09:49-08:00, [email protected]
> > >
> > > [PATCH] I2C: it87.c update
> > >
> > > - adds manual PWM
> > > - removes buggy "reset" module parameter
> > > - fixes some whitespaces
> > >
> > > Signed-off-by: Jonas Munsin <[email protected]>
> > > Signed-off-by: Greg Kroah-Hartman <[email protected]>
> >
> > You might hold off on this one patch... see this:
> >
> > http://marc.theaimsgroup.com/?l=linux-kernel&m=110514540928517&w=3
>
> I second Mark on that. Please do not merge this one until Jonas and I
> have analyzed the problem and found an acceptable solution. Stopping
> fans on module load isn't exactly a good driver behavior :(
Ok, I've reverted this in the bk tree.
thanks,
greg k-h
On Fri, Jan 07, 2005 at 09:38:49PM -0800, Greg KH wrote:
> Hi,
>
> Here are some i2c driver fixes and updates for 2.6.10. There are a few
> new i2c drivers in here, and a number of bugfixes. Almost all of these
> patches have been in the past few -mm releases.
>
> Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.6
>
> Individual patches will follow, sent to the sensors and linux-kernel
> lists.
Could you please put a slightly more usefull subject line into your mails.
Three gazillion times the same subject absolutely does not help review.
On Sat, Jan 08, 2005 at 07:09:43PM +0000, Christoph Hellwig wrote:
> On Fri, Jan 07, 2005 at 09:38:49PM -0800, Greg KH wrote:
> > Hi,
> >
> > Here are some i2c driver fixes and updates for 2.6.10. There are a few
> > new i2c drivers in here, and a number of bugfixes. Almost all of these
> > patches have been in the past few -mm releases.
> >
> > Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.6
> >
> > Individual patches will follow, sent to the sensors and linux-kernel
> > lists.
>
> Could you please put a slightly more usefull subject line into your mails.
> Three gazillion times the same subject absolutely does not help review.
Hm, yeah, I'll work on my scripts to try to do this in the future. It
would be a good idea.
thanks,
greg k-h