* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-22 1:04 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1195, 2003/03/21 16:39:04-08:00, greg@kroah.com
[PATCH] i2c: fix up the chip driver names to play nice with sysfs
drivers/i2c/chips/adm1021.c | 2 +-
drivers/i2c/chips/lm75.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:40 2003
+++ b/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:40 2003
@@ -144,7 +144,7 @@
/* This is the driver that will be inserted */
static struct i2c_driver adm1021_driver = {
.owner = THIS_MODULE,
- .name = "ADM1021, MAX1617 sensor driver",
+ .name = "ADM1021-MAX1617",
.id = I2C_DRIVERID_ADM1021,
.flags = I2C_DF_NOTIFY,
.attach_adapter = adm1021_attach_adapter,
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:40 2003
+++ b/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:40 2003
@@ -82,7 +82,7 @@
/* This is the driver that will be inserted */
static struct i2c_driver lm75_driver = {
.owner = THIS_MODULE,
- .name = "LM75 sensor chip driver",
+ .name = "LM75 sensor",
.id = I2C_DRIVERID_LM75,
.flags = I2C_DF_NOTIFY,
.attach_adapter = lm75_attach_adapter,
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-22 1:04 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1192, 2003/03/21 16:07:30-08:00, greg@kroah.com
[PATCH] i2c: remove the data field from struct i2c_client
It's no longer needed, as the struct device should be used instead.
Created i2c_get_clientdata() and i2c_set_clientdata() to access the data.
drivers/i2c/chips/adm1021.c | 15 +++++++--------
drivers/i2c/chips/lm75.c | 8 ++++----
include/linux/i2c.h | 11 ++++++++++-
3 files changed, 21 insertions(+), 13 deletions(-)
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Fri Mar 21 16:53:07 2003
+++ b/drivers/i2c/chips/adm1021.c Fri Mar 21 16:53:07 2003
@@ -223,8 +223,8 @@
}
data = (struct adm1021_data *) (new_client + 1);
+ i2c_set_clientdata(new_client, data);
new_client->addr = address;
- new_client->data = data;
new_client->adapter = adapter;
new_client->driver = &adm1021_driver;
new_client->flags = 0;
@@ -354,8 +354,7 @@
int err;
- i2c_deregister_entry(((struct adm1021_data *) (client->data))->
- sysctl_id);
+ i2c_deregister_entry(((struct adm1021_data *) (i2c_get_clientdata(client)))->sysctl_id);
if ((err = i2c_detach_client(client))) {
printk
@@ -384,7 +383,7 @@
static void adm1021_update_client(struct i2c_client *client)
{
- struct adm1021_data *data = client->data;
+ struct adm1021_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
@@ -435,7 +434,7 @@
static void adm1021_temp(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
- struct adm1021_data *data = client->data;
+ struct adm1021_data *data = i2c_get_clientdata(client);
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
@@ -462,7 +461,7 @@
static void adm1021_remote_temp(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
- struct adm1021_data *data = client->data;
+ struct adm1021_data *data = i2c_get_clientdata(client);
int prec = 0;
if (operation == SENSORS_PROC_REAL_INFO)
@@ -535,7 +534,7 @@
static void adm1021_die_code(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
- struct adm1021_data *data = client->data;
+ struct adm1021_data *data = i2c_get_clientdata(client);
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
@@ -551,7 +550,7 @@
static void adm1021_alarms(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
- struct adm1021_data *data = client->data;
+ struct adm1021_data *data = i2c_get_clientdata(client);
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Fri Mar 21 16:53:07 2003
+++ b/drivers/i2c/chips/lm75.c Fri Mar 21 16:53:07 2003
@@ -142,8 +142,8 @@
}
data = (struct lm75_data *) (new_client + 1);
+ i2c_set_clientdata(new_client, data);
new_client->addr = address;
- new_client->data = data;
new_client->adapter = adapter;
new_client->driver = &lm75_driver;
new_client->flags = 0;
@@ -215,7 +215,7 @@
static int lm75_detach_client(struct i2c_client *client)
{
- struct lm75_data *data = client->data;
+ struct lm75_data *data = i2c_get_clientdata(client);
i2c_deregister_entry(data->sysctl_id);
i2c_detach_client(client);
@@ -263,7 +263,7 @@
static void lm75_update_client(struct i2c_client *client)
{
- struct lm75_data *data = client->data;
+ struct lm75_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
@@ -286,7 +286,7 @@
static void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
int *nrels_mag, long *results)
{
- struct lm75_data *data = client->data;
+ struct lm75_data *data = i2c_get_clientdata(client);
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 1;
else if (operation == SENSORS_PROC_REAL_READ) {
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri Mar 21 16:53:07 2003
+++ b/include/linux/i2c.h Fri Mar 21 16:53:07 2003
@@ -167,12 +167,21 @@
alignment considerations */
struct i2c_adapter *adapter; /* the adapter we sit on */
struct i2c_driver *driver; /* and our access routines */
- void *data; /* for the clients */
int usage_count; /* How many accesses currently */
/* to the client */
struct device dev; /* the device structure */
};
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
+
+static inline void *i2c_get_clientdata (struct i2c_client *dev)
+{
+ return dev_get_drvdata (&dev->dev);
+}
+
+static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
+{
+ return dev_set_drvdata (&dev->dev, data);
+}
/*
* The following structs are for those who like to implement new bus drivers:
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-22 1:04 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1196, 2003/03/21 16:45:59-08:00, greg@kroah.com
i2c: ugh, clean up lindent mess in i2c-proc.c::i2c_detect()
Yes, this function now goes beyond 80 columns, but it's almost
readable, while the previous version was not.
Also removed some #ifdefs
drivers/i2c/i2c-proc.c | 180 ++++++++++++-------------------------------------
1 files changed, 47 insertions(+), 133 deletions(-)
diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
--- a/drivers/i2c/i2c-proc.c Fri Mar 21 16:52:31 2003
+++ b/drivers/i2c/i2c-proc.c Fri Mar 21 16:52:31 2003
@@ -23,6 +23,8 @@
This driver puts entries in /proc/sys/dev/sensors for each I2C device
*/
+/* #define DEBUG 1 */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -581,9 +583,9 @@
is_isa ? SENSORS_ISA_BUS : i2c_adapter_id(adapter);
/* Forget it if we can't probe using SMBUS_QUICK */
- if ((!is_isa)
- && !i2c_check_functionality(adapter,
- I2C_FUNC_SMBUS_QUICK)) return -1;
+ if ((!is_isa) &&
+ !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
+ return -1;
for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
/* XXX: WTF is going on here??? */
@@ -594,31 +596,14 @@
/* If it is in one of the force entries, we don't do any
detection at all */
found = 0;
- for (i = 0;
- !found
- && (this_force =
- address_data->forces + i, this_force->force); i++) {
- for (j = 0;
- !found
- && (this_force->force[j] != SENSORS_I2C_END);
- j += 2) {
- if (
- ((adapter_id == this_force->force[j])
- ||
- ((this_force->
- force[j] == SENSORS_ANY_I2C_BUS)
- && !is_isa))
- && (addr == this_force->force[j + 1])) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found force parameter for adapter %d, addr %04x\n",
- adapter_id, addr);
-#endif
- if (
- (err =
- found_proc(adapter, addr, 0,
- this_force->
- kind))) return err;
+ for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
+ for (j = 0; !found && (this_force->force[j] != SENSORS_I2C_END); j += 2) {
+ if ( ((adapter_id == this_force->force[j]) ||
+ ((this_force->force[j] == SENSORS_ANY_I2C_BUS) && !is_isa)) &&
+ (addr == this_force->force[j + 1]) ) {
+ dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
+ if ((err = found_proc(adapter, addr, 0, this_force->kind)))
+ return err;
found = 1;
}
}
@@ -628,42 +613,22 @@
/* If this address is in one of the ignores, we can forget about it
right now */
- for (i = 0;
- !found
- && (address_data->ignore[i] != SENSORS_I2C_END);
- i += 2) {
- if (
- ((adapter_id == address_data->ignore[i])
- ||
- ((address_data->
- ignore[i] == SENSORS_ANY_I2C_BUS)
- && !is_isa))
- && (addr == address_data->ignore[i + 1])) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found ignore parameter for adapter %d, "
- "addr %04x\n", adapter_id, addr);
-#endif
+ for (i = 0; !found && (address_data->ignore[i] != SENSORS_I2C_END); i += 2) {
+ if ( ((adapter_id == address_data->ignore[i]) ||
+ ((address_data->ignore[i] == SENSORS_ANY_I2C_BUS) &&
+ !is_isa)) &&
+ (addr == address_data->ignore[i + 1])) {
+ dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
found = 1;
}
}
- for (i = 0;
- !found
- && (address_data->ignore_range[i] != SENSORS_I2C_END);
- i += 3) {
- if (
- ((adapter_id == address_data->ignore_range[i])
- ||
- ((address_data->
- ignore_range[i] ==
- SENSORS_ANY_I2C_BUS) & !is_isa))
- && (addr >= address_data->ignore_range[i + 1])
- && (addr <= address_data->ignore_range[i + 2])) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found ignore_range parameter for adapter %d, "
- "addr %04x\n", adapter_id, addr);
-#endif
+ for (i = 0; !found && (address_data->ignore_range[i] != SENSORS_I2C_END); i += 3) {
+ if ( ((adapter_id == address_data->ignore_range[i]) ||
+ ((address_data-> ignore_range[i] == SENSORS_ANY_I2C_BUS) &
+ !is_isa)) &&
+ (addr >= address_data->ignore_range[i + 1]) &&
+ (addr <= address_data->ignore_range[i + 2])) {
+ dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
found = 1;
}
}
@@ -673,68 +638,31 @@
/* Now, we will do a detection, but only if it is in the normal or
probe entries */
if (is_isa) {
- for (i = 0;
- !found
- && (address_data->normal_isa[i] !=
- SENSORS_ISA_END); i += 1) {
+ for (i = 0; !found && (address_data->normal_isa[i] != SENSORS_ISA_END); i += 1) {
if (addr == address_data->normal_isa[i]) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found normal isa entry for adapter %d, "
- "addr %04x\n", adapter_id,
- addr);
-#endif
+ dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
found = 1;
}
}
- for (i = 0;
- !found
- && (address_data->normal_isa_range[i] !=
- SENSORS_ISA_END); i += 3) {
- if ((addr >=
- address_data->normal_isa_range[i])
- && (addr <=
- address_data->normal_isa_range[i + 1])
- &&
- ((addr -
- address_data->normal_isa_range[i]) %
- address_data->normal_isa_range[i + 2] ==
- 0)) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found normal isa_range entry for adapter %d, "
- "addr %04x", adapter_id, addr);
-#endif
+ for (i = 0; !found && (address_data->normal_isa_range[i] != SENSORS_ISA_END); i += 3) {
+ if ((addr >= address_data->normal_isa_range[i]) &&
+ (addr <= address_data->normal_isa_range[i + 1]) &&
+ ((addr - address_data->normal_isa_range[i]) % address_data->normal_isa_range[i + 2] == 0)) {
+ dev_dbg(&adapter->dev, "found normal isa_range entry for adapter %d, addr %04x", adapter_id, addr);
found = 1;
}
}
} else {
- for (i = 0;
- !found && (address_data->normal_i2c[i] !=
- SENSORS_I2C_END); i += 1) {
+ for (i = 0; !found && (address_data->normal_i2c[i] != SENSORS_I2C_END); i += 1) {
if (addr == address_data->normal_i2c[i]) {
found = 1;
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found normal i2c entry for adapter %d, "
- "addr %02x", adapter_id, addr);
-#endif
+ dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x", adapter_id, addr);
}
}
- for (i = 0;
- !found
- && (address_data->normal_i2c_range[i] !=
- SENSORS_I2C_END); i += 2) {
- if ((addr >=
- address_data->normal_i2c_range[i])
- && (addr <=
- address_data->normal_i2c_range[i + 1]))
- {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found normal i2c_range entry for adapter %d, "
- "addr %04x\n", adapter_id, addr);
-#endif
+ for (i = 0; !found && (address_data->normal_i2c_range[i] != SENSORS_I2C_END); i += 2) {
+ if ((addr >= address_data->normal_i2c_range[i]) &&
+ (addr <= address_data->normal_i2c_range[i + 1])) {
+ dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, addr %04x\n", adapter_id, addr);
found = 1;
}
}
@@ -747,30 +675,17 @@
((address_data->
probe[i] == SENSORS_ANY_I2C_BUS) & !is_isa))
&& (addr == address_data->probe[i + 1])) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found probe parameter for adapter %d, "
- "addr %04x\n", adapter_id, addr);
-#endif
+ dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
found = 1;
}
}
- for (i = 0; !found &&
- (address_data->probe_range[i] != SENSORS_I2C_END);
- i += 3) {
- if (
- ((adapter_id == address_data->probe_range[i])
- ||
- ((address_data->probe_range[i] ==
- SENSORS_ANY_I2C_BUS) & !is_isa))
- && (addr >= address_data->probe_range[i + 1])
- && (addr <= address_data->probe_range[i + 2])) {
+ for (i = 0; !found && (address_data->probe_range[i] != SENSORS_I2C_END); i += 3) {
+ if ( ((adapter_id == address_data->probe_range[i]) ||
+ ((address_data->probe_range[i] == SENSORS_ANY_I2C_BUS) & !is_isa)) &&
+ (addr >= address_data->probe_range[i + 1]) &&
+ (addr <= address_data->probe_range[i + 2])) {
found = 1;
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found probe_range parameter for adapter %d, "
- "addr %04x\n", adapter_id, addr);
-#endif
+ dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
}
}
if (!found)
@@ -779,8 +694,7 @@
/* OK, so we really should examine this address. First check
whether there is some client here at all! */
if (is_isa ||
- (i2c_smbus_xfer
- (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
+ (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
if ((err = found_proc(adapter, addr, 0, -1)))
return err;
}
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-22 1:04 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1188, 2003/03/21 12:29:44-08:00, vandrove@vc.cvut.cz
[PATCH] Fix kobject_get oopses triggered by i2c in 2.5.65-bk
i2c initialization must not use module_init now, when it was converted
to the kobject interface. There are dozens of users which need it working
much sooner. i2c is subsystem after all, isn't it?
Fixes kernel oopses in kobject_get during system init which were happening
to me.
drivers/i2c/i2c-core.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri Mar 21 16:53:45 2003
+++ b/drivers/i2c/i2c-core.c Fri Mar 21 16:53:45 2003
@@ -675,7 +675,7 @@
bus_unregister(&i2c_bus_type);
}
-module_init(i2c_init);
+subsys_initcall(i2c_init);
module_exit(i2c_exit);
/* ----------------------------------------------------
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-22 1:04 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1190, 2003/03/21 14:38:21-08:00, greg@kroah.com
[PATCH] i2c: remove *data from i2c_adapter, as dev->data should be used instead.
drivers/i2c/i2c-elv.c | 2 +-
drivers/i2c/scx200_acb.c | 4 ++--
include/linux/i2c.h | 17 +++++++++++------
3 files changed, 14 insertions(+), 9 deletions(-)
diff -Nru a/drivers/i2c/i2c-elv.c b/drivers/i2c/i2c-elv.c
--- a/drivers/i2c/i2c-elv.c Fri Mar 21 16:53:26 2003
+++ b/drivers/i2c/i2c-elv.c Fri Mar 21 16:53:26 2003
@@ -150,7 +150,7 @@
return -ENODEV;
}
} else {
- bit_elv_ops.data=(void*)base;
+ i2c_set_adapdata(&bit_elv_ops, (void *)base);
if (bit_elv_init()==0) {
if(i2c_bit_add_bus(&bit_elv_ops) < 0)
return -ENODEV;
diff -Nru a/drivers/i2c/scx200_acb.c b/drivers/i2c/scx200_acb.c
--- a/drivers/i2c/scx200_acb.c Fri Mar 21 16:53:26 2003
+++ b/drivers/i2c/scx200_acb.c Fri Mar 21 16:53:26 2003
@@ -289,7 +289,7 @@
char rw, u8 command, int size,
union i2c_smbus_data *data)
{
- struct scx200_acb_iface *iface = adapter->data;
+ struct scx200_acb_iface *iface = i2c_get_adapdata(adapter);
int len;
u8 *buffer;
u16 cur_word;
@@ -455,7 +455,7 @@
memset(iface, 0, sizeof(*iface));
adapter = &iface->adapter;
- adapter->data = iface;
+ i2c_set_adapdata(adapter, iface);
snprintf(adapter->dev.name, DEVICE_NAME_SIZE, "SCx200 ACB%d", index);
adapter->owner = THIS_MODULE;
adapter->id = I2C_ALGO_SMBUS;
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri Mar 21 16:53:26 2003
+++ b/include/linux/i2c.h Fri Mar 21 16:53:26 2003
@@ -219,12 +219,7 @@
int (*client_register)(struct i2c_client *);
int (*client_unregister)(struct i2c_client *);
- void *data; /* private data for the adapter */
- /* some data fields that are used by all types */
- /* these data fields are readonly to the public */
- /* and can be set via the i2c_ioctl call */
-
- /* data fields that are valid for all devices */
+ /* data fields that are valid for all devices */
struct semaphore bus;
struct semaphore list;
unsigned int flags;/* flags specifying div. data */
@@ -241,6 +236,16 @@
#endif /* def CONFIG_PROC_FS */
};
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
+
+static inline void *i2c_get_adapdata (struct i2c_adapter *dev)
+{
+ return dev_get_drvdata (&dev->dev);
+}
+
+static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
+{
+ return dev_set_drvdata (&dev->dev, data);
+}
/*flags for the driver struct: */
#define I2C_DF_NOTIFY 0x01 /* notify on bus (de/a)ttaches */
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-22 1:04 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1189, 2003/03/21 12:45:28-08:00, greg@kroah.com
i2c: remove i2c_adapter->name and use dev->name instead.
drivers/i2c/busses/i2c-ali15x3.c | 8 ++--
drivers/i2c/busses/i2c-amd756.c | 6 ++-
drivers/i2c/busses/i2c-amd8111.c | 4 +-
drivers/i2c/busses/i2c-i801.c | 8 ++--
drivers/i2c/busses/i2c-isa.c | 4 +-
drivers/i2c/busses/i2c-piix4.c | 8 ++--
drivers/i2c/i2c-algo-bit.c | 13 +++---
drivers/i2c/i2c-algo-pcf.c | 19 ++++------
drivers/i2c/i2c-core.c | 73 ++++++++++++++++-----------------------
drivers/i2c/i2c-dev.c | 17 +++------
drivers/i2c/i2c-elektor.c | 10 +++--
drivers/i2c/i2c-elv.c | 4 +-
drivers/i2c/i2c-philips-par.c | 4 +-
drivers/i2c/i2c-velleman.c | 4 +-
drivers/i2c/scx200_acb.c | 28 ++++++--------
include/linux/i2c.h | 1
16 files changed, 105 insertions(+), 106 deletions(-)
diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- a/drivers/i2c/busses/i2c-ali15x3.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-ali15x3.c Fri Mar 21 16:53:36 2003
@@ -474,9 +474,11 @@
static struct i2c_adapter ali15x3_adapter = {
.owner = THIS_MODULE,
- .name = "unset",
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,
.algo = &smbus_algorithm,
+ .dev = {
+ .name = "unset",
+ },
};
static struct pci_device_id ali15x3_ids[] __devinitdata = {
@@ -500,8 +502,8 @@
/* set up the driverfs linkage to our parent device */
ali15x3_adapter.dev.parent = &dev->dev;
- sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x",
- ali15x3_smba);
+ snprintf(ali15x3_adapter.dev.name, DEVICE_NAME_SIZE,
+ "SMBus ALI15X3 adapter at %04x", ali15x3_smba);
return i2c_add_adapter(&ali15x3_adapter);
}
diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
--- a/drivers/i2c/busses/i2c-amd756.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-amd756.c Fri Mar 21 16:53:36 2003
@@ -312,9 +312,11 @@
static struct i2c_adapter amd756_adapter = {
.owner = THIS_MODULE,
- .name = "unset",
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756,
.algo = &smbus_algorithm,
+ .dev = {
+ .name = "unset",
+ },
};
enum chiptype { AMD756, AMD766, AMD768, NFORCE };
@@ -376,7 +378,7 @@
/* set up the driverfs linkage to our parent device */
amd756_adapter.dev.parent = &pdev->dev;
- sprintf(amd756_adapter.name,
+ snprintf(amd756_adapter.dev.name, DEVICE_NAME_SIZE,
"SMBus AMD75x adapter at %04x", amd756_ioport);
error = i2c_add_adapter(&amd756_adapter);
diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
--- a/drivers/i2c/busses/i2c-amd8111.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-amd8111.c Fri Mar 21 16:53:36 2003
@@ -357,8 +357,8 @@
goto out_kfree;
smbus->adapter.owner = THIS_MODULE;
- sprintf(smbus->adapter.name,
- "SMBus2 AMD8111 adapter at %04x", smbus->base);
+ snprintf(smbus->adapter.dev.name, DEVICE_NAME_SIZE,
+ "SMBus2 AMD8111 adapter at %04x", smbus->base);
smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- a/drivers/i2c/busses/i2c-i801.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-i801.c Fri Mar 21 16:53:36 2003
@@ -546,9 +546,11 @@
static struct i2c_adapter i801_adapter = {
.owner = THIS_MODULE,
- .name = "unset",
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
.algo = &smbus_algorithm,
+ .dev = {
+ .name = "unset",
+ },
};
static struct pci_device_id i801_ids[] __devinitdata = {
@@ -597,8 +599,8 @@
/* set up the driverfs linkage to our parent device */
i801_adapter.dev.parent = &dev->dev;
- sprintf(i801_adapter.name, "SMBus I801 adapter at %04x",
- i801_smba);
+ snprintf(i801_adapter.dev.name, DEVICE_NAME_SIZE,
+ "SMBus I801 adapter at %04x", i801_smba);
return i2c_add_adapter(&i801_adapter);
}
diff -Nru a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
--- a/drivers/i2c/busses/i2c-isa.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-isa.c Fri Mar 21 16:53:36 2003
@@ -39,9 +39,11 @@
/* There can only be one... */
static struct i2c_adapter isa_adapter = {
.owner = THIS_MODULE,
- .name = "ISA main adapter",
.id = I2C_ALGO_ISA | I2C_HW_ISA,
.algo = &isa_algorithm,
+ .dev = {
+ .name = "ISA main adapter",
+ },
};
static int __init i2c_isa_init(void)
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-piix4.c Fri Mar 21 16:53:36 2003
@@ -394,9 +394,11 @@
static struct i2c_adapter piix4_adapter = {
.owner = THIS_MODULE,
- .name = "unset",
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
.algo = &smbus_algorithm,
+ .dev = {
+ .name = "unset",
+ },
};
static struct pci_device_id piix4_ids[] __devinitdata = {
@@ -449,8 +451,8 @@
/* set up the driverfs linkage to our parent device */
piix4_adapter.dev.parent = &dev->dev;
- sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
- piix4_smba);
+ snprintf(piix4_adapter.dev.name, DEVICE_NAME_SIZE,
+ "SMBus PIIX4 adapter at %04x", piix4_smba);
retval = i2c_add_adapter(&piix4_adapter);
diff -Nru a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/i2c-algo-bit.c
--- a/drivers/i2c/i2c-algo-bit.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-algo-bit.c Fri Mar 21 16:53:36 2003
@@ -23,6 +23,8 @@
/* $Id: i2c-algo-bit.c,v 1.44 2003/01/21 08:08:16 kmalkki Exp $ */
+/* #define DEBUG 1 */
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -338,16 +340,14 @@
while (count > 0) {
c = *temp;
- DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: %s sendbytes: writing %2.2X\n",
- i2c_adap->name, c&0xff));
+ DEB2(dev_dbg(&i2c_adap->dev, "sendbytes: writing %2.2X\n", c&0xff));
retval = i2c_outb(i2c_adap,c);
if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */
count--;
temp++;
wrcount++;
} else { /* arbitration or no acknowledge */
- printk(KERN_ERR "i2c-algo-bit.o: %s sendbytes: error - bailout.\n",
- i2c_adap->name);
+ dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
i2c_stop(adap);
return (retval<0)? retval : -EFAULT;
/* got a better one ?? */
@@ -527,13 +527,12 @@
struct i2c_algo_bit_data *bit_adap = adap->algo_data;
if (bit_test) {
- int ret = test_bus(bit_adap, adap->name);
+ int ret = test_bus(bit_adap, adap->dev.name);
if (ret<0)
return -ENODEV;
}
- DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: hw routines for %s registered.\n",
- adap->name));
+ DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
/* register new adapter to i2c module... */
diff -Nru a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/i2c-algo-pcf.c
--- a/drivers/i2c/i2c-algo-pcf.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-algo-pcf.c Fri Mar 21 16:53:36 2003
@@ -27,6 +27,8 @@
messages, proper stop/repstart signaling during receive,
added detect code */
+/* #define DEBUG 1 */ /* to pick up dev_dbg calls */
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -222,21 +224,19 @@
int wrcount, status, timeout;
for (wrcount=0; wrcount<count; ++wrcount) {
- DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: %s i2c_write: writing %2.2X\n",
- i2c_adap->name, buf[wrcount]&0xff));
+ DEB2(dev_dbg(&i2c_adap->dev, "i2c_write: writing %2.2X\n",
+ buf[wrcount]&0xff));
i2c_outb(adap, buf[wrcount]);
timeout = wait_for_pin(adap, &status);
if (timeout) {
i2c_stop(adap);
- printk(KERN_ERR "i2c-algo-pcf.o: %s i2c_write: "
- "error - timeout.\n", i2c_adap->name);
+ dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n");
return -EREMOTEIO; /* got a better one ?? */
}
#ifndef STUB_I2C
if (status & I2C_PCF_LRB) {
i2c_stop(adap);
- printk(KERN_ERR "i2c-algo-pcf.o: %s i2c_write: "
- "error - no ack.\n", i2c_adap->name);
+ dev_err(&i2c_adap->dev, "i2c_write: error - no ack.\n");
return -EREMOTEIO; /* got a better one ?? */
}
#endif
@@ -263,14 +263,14 @@
if (wait_for_pin(adap, &status)) {
i2c_stop(adap);
- printk(KERN_ERR "i2c-algo-pcf.o: pcf_readbytes timed out.\n");
+ dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n");
return (-1);
}
#ifndef STUB_I2C
if ((status & I2C_PCF_LRB) && (i != count)) {
i2c_stop(adap);
- printk(KERN_ERR "i2c-algo-pcf.o: i2c_read: i2c_inb, No ack.\n");
+ dev_err(&i2c_adap->dev, "i2c_read: i2c_inb, No ack.\n");
return (-1);
}
#endif
@@ -445,8 +445,7 @@
struct i2c_algo_pcf_data *pcf_adap = adap->algo_data;
int rval;
- DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: hw routines for %s registered.\n",
- adap->name));
+ DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
/* register new adapter to i2c module... */
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-core.c Fri Mar 21 16:53:36 2003
@@ -23,6 +23,8 @@
/* $Id: i2c-core.c,v 1.95 2003/01/22 05:25:08 kmalkki Exp $ */
+/* #define DEBUG 1 */ /* needed to pick up the dev_dbg() calls */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -82,9 +84,8 @@
if (NULL == adapters[i])
break;
if (I2C_ADAP_MAX == i) {
- printk(KERN_WARNING
- " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n",
- adap->name);
+ dev_warn(&adap->dev,
+ "register_adapter - enlarge I2C_ADAP_MAX.\n");
res = -ENOMEM;
goto out_unlock;
}
@@ -105,7 +106,6 @@
if (adap->dev.parent == NULL)
adap->dev.parent = &legacy_bus;
sprintf(adap->dev.bus_id, "i2c-%d", i);
- strcpy(adap->dev.name, "i2c controller");
device_register(&adap->dev);
/* inform drivers of new adapters */
@@ -116,8 +116,7 @@
drivers[j]->attach_adapter(adap);
up(&core_lists);
- DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n",
- adap->name,i));
+ DEB(dev_dbg(&adap->dev, "registered as adapter %d.\n", i));
out_unlock:
up(&core_lists);
@@ -134,8 +133,7 @@
if (adap == adapters[i])
break;
if (I2C_ADAP_MAX == i) {
- printk( KERN_WARNING "i2c-core.o: unregister_adapter adap [%s] not found.\n",
- adap->name);
+ dev_warn(&adap->dev, "unregister_adapter adap not found.\n");
res = -ENODEV;
goto out_unlock;
}
@@ -148,9 +146,9 @@
for (j = 0; j < I2C_DRIVER_MAX; j++)
if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY))
if ((res = drivers[j]->attach_adapter(adap))) {
- printk(KERN_WARNING "i2c-core.o: can't detach adapter %s "
+ dev_warn(&adap->dev, "can't detach adapter"
"while detaching driver %s: driver not "
- "detached!",adap->name,drivers[j]->name);
+ "detached!", drivers[j]->name);
goto out_unlock;
}
@@ -164,10 +162,10 @@
* must be deleted, as this would cause invalid states.
*/
if ((res=client->driver->detach_client(client))) {
- printk(KERN_ERR "i2c-core.o: adapter %s not "
+ dev_err(&adap->dev, "adapter not "
"unregistered, because client at "
"address %02x can't be detached. ",
- adap->name, client->addr);
+ client->addr);
goto out_unlock;
}
}
@@ -180,7 +178,7 @@
adapters[i] = NULL;
- DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name));
+ DEB(dev_dbg(&adap->dev, "adapter unregistered\n"));
out_unlock:
up(&core_lists);
@@ -272,8 +270,7 @@
struct i2c_adapter *adap = adapters[k];
if (adap == NULL) /* skip empty entries. */
continue;
- DEB2(printk(KERN_DEBUG "i2c-core.o: examining adapter %s:\n",
- adap->name));
+ DEB2(dev_dbg(&adap->dev, "examining adapter\n"));
if (driver->flags & I2C_DF_DUMMY) {
/* DUMMY drivers do not register their clients, so we have to
* use a trick here: we call driver->attach_adapter to
@@ -281,11 +278,10 @@
* this or hell will break loose...
*/
if ((res = driver->attach_adapter(adap))) {
- printk(KERN_WARNING "i2c-core.o: while unregistering "
- "dummy driver %s, adapter %s could "
+ dev_warn(&adap->dev, "while unregistering "
+ "dummy driver %s, adapter could "
"not be detached properly; driver "
- "not unloaded!",driver->name,
- adap->name);
+ "not unloaded!",driver->name);
goto out_unlock;
}
} else {
@@ -296,19 +292,16 @@
DEB2(printk(KERN_DEBUG "i2c-core.o: "
"detaching client %s:\n",
client->name));
- if ((res = driver->
- detach_client(client)))
- {
- printk(KERN_ERR "i2c-core.o: while "
+ if ((res = driver->detach_client(client))) {
+ dev_err(&adap->dev, "while "
"unregistering driver "
"`%s', the client at "
"address %02x of "
- "adapter `%s' could not "
+ "adapter could not "
"be detached; driver "
"not unloaded!",
driver->name,
- client->addr,
- adap->name);
+ client->addr);
goto out_unlock;
}
}
@@ -374,16 +367,14 @@
if (adapter->client_register) {
if (adapter->client_register(client)) {
- printk(KERN_DEBUG
- "i2c-core.o: warning: client_register seems "
- "to have failed for client %02x at adapter %s\n",
- client->addr, adapter->name);
+ dev_warn(&adapter->dev, "warning: client_register "
+ "seems to have failed for client %02x\n",
+ client->addr);
}
}
- DEB(printk(KERN_DEBUG
- "i2c-core.o: client [%s] registered to adapter [%s] "
- "(pos. %d).\n", client->name, adapter->name, i));
+ DEB(dev_dbg(&adapter->dev, "client [%s] registered to adapter "
+ "(pos. %d).\n", client->name, i));
if (client->flags & I2C_CLIENT_ALLOW_USE)
client->usage_count = 0;
@@ -579,7 +570,7 @@
seq_printf(s, "dummy ");
seq_printf(s, "\t%-32s\t%-32s\n",
- adapter->name, adapter->algo->name);
+ adapter->dev.name, adapter->algo->name);
}
up(&core_lists);
@@ -688,8 +679,7 @@
int ret;
if (adap->algo->master_xfer) {
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_xfer: %s with %d msgs.\n",
- adap->name,num));
+ DEB2(dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num));
down(&adap->bus);
ret = adap->algo->master_xfer(adap,msgs,num);
@@ -697,8 +687,7 @@
return ret;
} else {
- printk(KERN_ERR "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
- adap->id);
+ dev_err(&adap->dev, "I2C level transfers not supported\n");
return -ENOSYS;
}
}
@@ -715,8 +704,8 @@
msg.len = count;
(const char *)msg.buf = buf;
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n",
- count,client->adapter->name));
+ DEB2(dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
+ count));
down(&adap->bus);
ret = adap->algo->master_xfer(adap,&msg,1);
@@ -745,8 +734,8 @@
msg.len = count;
msg.buf = buf;
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n",
- count,client->adapter->name));
+ DEB2(dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n",
+ count));
down(&adap->bus);
ret = adap->algo->master_xfer(adap,&msg,1);
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-dev.c Fri Mar 21 16:53:36 2003
@@ -30,6 +30,9 @@
/* $Id: i2c-dev.c,v 1.53 2003/01/21 08:08:16 kmalkki Exp $ */
+/* If you want debugging uncomment: */
+/* #define DEBUG 1 */
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
@@ -41,10 +44,6 @@
#include <linux/i2c-dev.h>
#include <asm/uaccess.h>
-/* If you want debugging uncomment: */
-/* #define DEBUG */
-
-
/* struct file_operations changed too often in the 2.1 series for nice code */
static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
@@ -386,11 +385,11 @@
char name[12];
if ((i = i2c_adapter_id(adap)) < 0) {
- printk(KERN_DEBUG "i2c-dev.o: Unknown adapter ?!?\n");
+ dev_dbg(&adap->dev, "Unknown adapter ?!?\n");
return -ENODEV;
}
if (i >= I2CDEV_ADAPS_MAX) {
- printk(KERN_DEBUG "i2c-dev.o: Adapter number too large?!? (%d)\n",i);
+ dev_dbg(&adap->dev, "Adapter number too large?!? (%d)\n",i);
return -ENODEV;
}
@@ -401,14 +400,12 @@
DEVFS_FL_DEFAULT, I2C_MAJOR, i,
S_IFCHR | S_IRUSR | S_IWUSR,
&i2cdev_fops, NULL);
- printk(KERN_DEBUG "i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i);
+ dev_dbg(&adap->dev, "Registered as minor %d\n", i);
} else {
/* This is actually a detach_adapter call! */
devfs_remove("i2c/%d", i);
i2cdev_adaps[i] = NULL;
-#ifdef DEBUG
- printk(KERN_DEBUG "i2c-dev.o: Adapter unregistered: %s\n",adap->name);
-#endif
+ dev_dbg(&adap->dev, "Adapter unregistered\n");
}
return 0;
diff -Nru a/drivers/i2c/i2c-elektor.c b/drivers/i2c/i2c-elektor.c
--- a/drivers/i2c/i2c-elektor.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-elektor.c Fri Mar 21 16:53:36 2003
@@ -174,10 +174,12 @@
};
static struct i2c_adapter pcf_isa_ops = {
- .owner = THIS_MODULE,
- .name = "PCF8584 ISA adapter",
- .id = I2C_HW_P_ELEK,
- .algo_data = &pcf_isa_data,
+ .owner = THIS_MODULE,
+ .id = I2C_HW_P_ELEK,
+ .algo_data = &pcf_isa_data,
+ .dev = {
+ .name = "PCF8584 ISA adapter",
+ },
};
static int __init i2c_pcfisa_init(void)
diff -Nru a/drivers/i2c/i2c-elv.c b/drivers/i2c/i2c-elv.c
--- a/drivers/i2c/i2c-elv.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-elv.c Fri Mar 21 16:53:36 2003
@@ -129,9 +129,11 @@
static struct i2c_adapter bit_elv_ops = {
.owner = THIS_MODULE,
- .name = "ELV Parallel port adaptor",
.id = I2C_HW_B_ELV,
.algo_data = &bit_elv_data,
+ .dev = {
+ .name = "ELV Parallel port adaptor",
+ },
};
static int __init i2c_bitelv_init(void)
diff -Nru a/drivers/i2c/i2c-philips-par.c b/drivers/i2c/i2c-philips-par.c
--- a/drivers/i2c/i2c-philips-par.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-philips-par.c Fri Mar 21 16:53:36 2003
@@ -151,8 +151,10 @@
static struct i2c_adapter bit_lp_ops = {
.owner = THIS_MODULE,
- .name = "Philips Parallel port adapter",
.id = I2C_HW_B_LP,
+ .dev = {
+ .name = "Philips Parallel port adapter",
+ },
};
static void i2c_parport_attach (struct parport *port)
diff -Nru a/drivers/i2c/i2c-velleman.c b/drivers/i2c/i2c-velleman.c
--- a/drivers/i2c/i2c-velleman.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-velleman.c Fri Mar 21 16:53:36 2003
@@ -114,9 +114,11 @@
static struct i2c_adapter bit_velle_ops = {
.owner = THIS_MODULE,
- .name = "Velleman K8000",
.id = I2C_HW_B_VELLE,
.algo_data = &bit_velle_data,
+ .dev = {
+ .name = "Velleman K8000",
+ },
};
static int __init i2c_bitvelle_init(void)
diff -Nru a/drivers/i2c/scx200_acb.c b/drivers/i2c/scx200_acb.c
--- a/drivers/i2c/scx200_acb.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/scx200_acb.c Fri Mar 21 16:53:36 2003
@@ -140,8 +140,7 @@
switch (iface->state) {
case state_idle:
- printk(KERN_WARNING NAME ": %s, interrupt in idle state\n",
- iface->adapter.name);
+ dev_warn(&iface->adapter.dev, "interrupt in idle state\n",);
break;
case state_address:
@@ -226,8 +225,8 @@
return;
error:
- printk(KERN_ERR NAME ": %s, %s in state %s\n", iface->adapter.name,
- errmsg, scx200_acb_state_name[iface->state]);
+ dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg,
+ scx200_acb_state_name[iface->state]);
iface->state = state_idle;
iface->result = -EIO;
@@ -236,8 +235,8 @@
static void scx200_acb_timeout(struct scx200_acb_iface *iface)
{
- printk(KERN_ERR NAME ": %s, timeout in state %s\n",
- iface->adapter.name, scx200_acb_state_name[iface->state]);
+ dev_err(&iface->adapter.dev, "timeout in state %s\n",
+ scx200_acb_state_name[iface->state]);
iface->state = state_idle;
iface->result = -EIO;
@@ -331,13 +330,12 @@
size, address, command, len, rw == I2C_SMBUS_READ);
if (!len && rw == I2C_SMBUS_READ) {
- printk(KERN_WARNING NAME ": %s, zero length read\n",
- adapter->name);
+ dev_warn(&adapter->dev, "zero length read\n");
return -EINVAL;
}
if (len && !buffer) {
- printk(KERN_WARNING NAME ": %s, nonzero length but no buffer\n", adapter->name);
+ dev_warn(&adapter->dev, "nonzero length but no buffer\n");
return -EFAULT;
}
@@ -458,17 +456,17 @@
memset(iface, 0, sizeof(*iface));
adapter = &iface->adapter;
adapter->data = iface;
- sprintf(adapter->name, "SCx200 ACB%d", index);
+ snprintf(adapter->dev.name, DEVICE_NAME_SIZE, "SCx200 ACB%d", index);
adapter->owner = THIS_MODULE;
adapter->id = I2C_ALGO_SMBUS;
adapter->algo = &scx200_acb_algorithm;
init_MUTEX(&iface->sem);
- sprintf(description, "NatSemi SCx200 ACCESS.bus [%s]", adapter->name);
+ snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->dev.name);
if (request_region(base, 8, description) == 0) {
- printk(KERN_ERR NAME ": %s, can't allocate io 0x%x-0x%x\n",
- adapter->name, base, base + 8-1);
+ dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n",
+ base, base + 8-1);
rc = -EBUSY;
goto errout;
}
@@ -476,14 +474,14 @@
rc = scx200_acb_probe(iface);
if (rc) {
- printk(KERN_WARNING NAME ": %s, probe failed\n", adapter->name);
+ dev_warn(&adapter->dev, "probe failed\n");
goto errout;
}
scx200_acb_reset(iface);
if (i2c_add_adapter(adapter) < 0) {
- printk(KERN_ERR NAME ": %s, failed to register\n", adapter->name);
+ dev_err(&adapter->dev, "failed to register\n");
rc = -ENODEV;
goto errout;
}
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri Mar 21 16:53:36 2003
+++ b/include/linux/i2c.h Fri Mar 21 16:53:36 2003
@@ -210,7 +210,6 @@
*/
struct i2c_adapter {
struct module *owner;
- char name[32]; /* some useful name to identify the adapter */
unsigned int id;/* == is algo->id | hwdep.struct->id, */
/* for registered values see below */
struct i2c_algorithm *algo;/* the algorithm to access the bus */
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-22 1:04 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1193, 2003/03/21 16:16:01-08:00, greg@kroah.com
i2c: Removed the name variable from i2c_client as the dev one should be used instead.
drivers/i2c/chips/adm1021.c | 2 +-
drivers/i2c/chips/lm75.c | 2 +-
drivers/i2c/i2c-core.c | 14 +++++++-------
drivers/i2c/i2c-dev.c | 4 +++-
include/linux/i2c.h | 1 -
5 files changed, 12 insertions(+), 11 deletions(-)
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:58 2003
+++ b/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:58 2003
@@ -299,7 +299,7 @@
}
/* Fill in the remaining client fields and put it into the global list */
- strcpy(new_client->name, client_name);
+ strncpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
data->type = kind;
new_client->id = adm1021_id++;
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:58 2003
+++ b/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:58 2003
@@ -180,7 +180,7 @@
}
/* Fill in the remaining client fields and put it into the global list */
- strcpy(new_client->name, client_name);
+ strncpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
new_client->id = lm75_id++;
data->valid = 0;
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri Mar 21 16:52:58 2003
+++ b/drivers/i2c/i2c-core.c Fri Mar 21 16:52:58 2003
@@ -291,9 +291,9 @@
client->driver == driver) {
DEB2(printk(KERN_DEBUG "i2c-core.o: "
"detaching client %s:\n",
- client->name));
+ client->dev.name));
if ((res = driver->detach_client(client))) {
- dev_err(&adap->dev, "while "
+ dev_err(&adap->dev, "while "
"unregistering driver "
"`%s', the client at "
"address %02x of "
@@ -355,7 +355,7 @@
printk(KERN_WARNING
" i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n",
- client->name);
+ client->dev.name);
out_unlock_list:
up(&adapter->list);
@@ -374,7 +374,7 @@
}
DEB(dev_dbg(&adapter->dev, "client [%s] registered to adapter "
- "(pos. %d).\n", client->name, i));
+ "(pos. %d).\n", client->dev.name, i));
if (client->flags & I2C_CLIENT_ALLOW_USE)
client->usage_count = 0;
@@ -395,7 +395,7 @@
if (res) {
printk(KERN_ERR
"i2c-core.o: client_unregister [%s] failed, "
- "client not detached", client->name);
+ "client not detached", client->dev.name);
goto out;
}
}
@@ -410,7 +410,7 @@
printk(KERN_WARNING
" i2c-core.o: unregister_client [%s] not found\n",
- client->name);
+ client->dev.name);
res = -ENODEV;
out_unlock:
@@ -522,7 +522,7 @@
client = adapters[i]->clients[order[j]];
len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n",
client->addr,
- client->name,
+ client->dev.name,
client->driver->name);
}
len = len - file->f_pos;
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c Fri Mar 21 16:52:58 2003
+++ b/drivers/i2c/i2c-dev.c Fri Mar 21 16:52:58 2003
@@ -86,7 +86,9 @@
};
static struct i2c_client i2cdev_client_template = {
- .name = "I2C /dev entry",
+ .dev = {
+ .name = "I2C /dev entry",
+ },
.id = 1,
.addr = -1,
.driver = &i2cdev_driver,
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri Mar 21 16:52:58 2003
+++ b/include/linux/i2c.h Fri Mar 21 16:52:58 2003
@@ -156,7 +156,6 @@
* function is mainly used for lookup & other admin. functions.
*/
struct i2c_client {
- char name[32];
int id;
unsigned int flags; /* div., see below */
unsigned int addr; /* chip address - NOTE: 7bit */
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-22 1:04 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1194, 2003/03/21 16:26:04-08:00, greg@kroah.com
i2c: actually register the i2c client device with the driver core.
We have to initialize the client structure with 0 to keep the
driver core from oopsing.
Now everything is hooked up enough to start removing the i2c sysctl
and proc crud.
drivers/i2c/chips/adm1021.c | 2 ++
drivers/i2c/chips/lm75.c | 2 ++
drivers/i2c/i2c-core.c | 10 ++++++++++
3 files changed, 14 insertions(+)
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:49 2003
+++ b/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:49 2003
@@ -221,6 +221,8 @@
err = -ENOMEM;
goto error0;
}
+ memset(new_client, 0x00, sizeof(struct i2c_client) +
+ sizeof(struct adm1021_data));
data = (struct adm1021_data *) (new_client + 1);
i2c_set_clientdata(new_client, data);
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:49 2003
+++ b/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:49 2003
@@ -140,6 +140,8 @@
err = -ENOMEM;
goto error0;
}
+ memset(new_client, 0x00, sizeof(struct i2c_client) +
+ sizeof(struct lm75_data));
data = (struct lm75_data *) (new_client + 1);
i2c_set_clientdata(new_client, data);
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri Mar 21 16:52:49 2003
+++ b/drivers/i2c/i2c-core.c Fri Mar 21 16:52:49 2003
@@ -378,6 +378,15 @@
if (client->flags & I2C_CLIENT_ALLOW_USE)
client->usage_count = 0;
+
+ client->dev.parent = &client->adapter->dev;
+ client->dev.driver = &client->driver->driver;
+ client->dev.bus = &i2c_bus_type;
+
+ snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), "i2c_dev_%d", i);
+ printk("registering %s\n", client->dev.bus_id);
+ device_register(&client->dev);
+
return 0;
}
@@ -414,6 +423,7 @@
res = -ENODEV;
out_unlock:
+ device_unregister(&client->dev);
up(&adapter->list);
out:
return res;
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-22 1:04 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1191, 2003/03/21 16:00:39-08:00, greg@kroah.com
i2c: add struct device to i2c_client structure
Not quite ready to hook it up to the driver core yet.
include/linux/i2c.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletion(-)
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri Mar 21 16:53:17 2003
+++ b/include/linux/i2c.h Fri Mar 21 16:53:17 2003
@@ -170,8 +170,9 @@
void *data; /* for the clients */
int usage_count; /* How many accesses currently */
/* to the client */
+ struct device dev; /* the device structure */
};
-
+#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
/*
* The following structs are for those who like to implement new bus drivers:
^ permalink raw reply [flat|nested] 98+ messages in thread
* [BK PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-22 1:04 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, sensors
Hi,
Here are some more i2c driver changes for 2.5.65. These include changes
that now hook up the i2c devices to the driver core. This results in a
sysfs tree that looks like the following on one of my boxes:
/sys/bus/i2c/
|-- devices
| `-- i2c_dev_0 -> ../../../devices/pci0/00:1f.3/i2c-0/i2c_dev_0
`-- drivers
`-- LM75 sensor
`-- i2c_dev_0 -> ../../../../devices/pci0/00:1f.3/i2c-0/i2c_dev_0
Now the fun work of starting to rip out the i2c sysctl and proc code can
begin :)
These changesets also include the patch from Petr Vandrovec that fixes
an oops on booting with i2c built into the kernel, and some more minor
cleanups to some of the i2c core code.
I'll try to post a document later this weekend on lkml and
kernel-janitors-discuss that explains how the i2c drivers will need to
be converted, and how people can help out now that the infrastructure is
finished.
Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.5
thanks,
greg k-h
drivers/i2c/busses/i2c-ali15x3.c | 8 +
drivers/i2c/busses/i2c-amd756.c | 6 -
drivers/i2c/busses/i2c-amd8111.c | 4
drivers/i2c/busses/i2c-i801.c | 8 +
drivers/i2c/busses/i2c-isa.c | 4
drivers/i2c/busses/i2c-piix4.c | 8 +
drivers/i2c/chips/adm1021.c | 21 ++--
drivers/i2c/chips/lm75.c | 14 +--
drivers/i2c/i2c-algo-bit.c | 13 +-
drivers/i2c/i2c-algo-pcf.c | 19 +---
drivers/i2c/i2c-core.c | 99 ++++++++++-----------
drivers/i2c/i2c-dev.c | 21 ++--
drivers/i2c/i2c-elektor.c | 10 +-
drivers/i2c/i2c-elv.c | 6 -
drivers/i2c/i2c-philips-par.c | 4
drivers/i2c/i2c-proc.c | 180 ++++++++++-----------------------------
drivers/i2c/i2c-velleman.c | 4
drivers/i2c/scx200_acb.c | 32 +++---
include/linux/i2c.h | 33 ++++---
19 files changed, 218 insertions(+), 276 deletions(-)
-----
Short log:
-----
Greg Kroah-Hartman <greg@kroah.com>:
o i2c: ugh, clean up lindent mess in i2c-proc.c::i2c_detect()
o i2c: fix up the chip driver names to play nice with sysfs
o i2c: actually register the i2c client device with the driver core
o i2c: Removed the name variable from i2c_client as the dev one should be used instead
o i2c: remove the data field from struct i2c_client
o i2c: add struct device to i2c_client structure
o i2c: remove *data from i2c_adapter, as dev->data should be used instead
o i2c: remove i2c_adapter->name and use dev->name instead
Petr Vandrovec <vandrove@vc.cvut.cz>:
o Fix kobject_get oopses triggered by i2c in 2.5.65-bk
-----
Long log:
-----
ChangeSet@1.1196, 2003-03-21 16:45:59-08:00, greg@kroah.com
i2c: ugh, clean up lindent mess in i2c-proc.c::i2c_detect()
Yes, this function now goes beyond 80 columns, but it's almost
readable, while the previous version was not.
Also removed some #ifdefs
drivers/i2c/i2c-proc.c | 180 ++++++++++++-------------------------------------
1 files changed, 47 insertions(+), 133 deletions(-)
------
ChangeSet@1.1195, 2003-03-21 16:39:04-08:00, greg@kroah.com
[PATCH] i2c: fix up the chip driver names to play nice with sysfs
drivers/i2c/chips/adm1021.c | 2 +-
drivers/i2c/chips/lm75.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
------
ChangeSet@1.1194, 2003-03-21 16:26:04-08:00, greg@kroah.com
i2c: actually register the i2c client device with the driver core.
We have to initialize the client structure with 0 to keep the
driver core from oopsing.
Now everything is hooked up enough to start removing the i2c sysctl
and proc crud.
drivers/i2c/chips/adm1021.c | 2 ++
drivers/i2c/chips/lm75.c | 2 ++
drivers/i2c/i2c-core.c | 10 ++++++++++
3 files changed, 14 insertions(+)
------
ChangeSet@1.1193, 2003-03-21 16:16:01-08:00, greg@kroah.com
i2c: Removed the name variable from i2c_client as the dev one should be used instead.
drivers/i2c/chips/adm1021.c | 2 +-
drivers/i2c/chips/lm75.c | 2 +-
drivers/i2c/i2c-core.c | 14 +++++++-------
drivers/i2c/i2c-dev.c | 4 +++-
include/linux/i2c.h | 1 -
5 files changed, 12 insertions(+), 11 deletions(-)
------
ChangeSet@1.1192, 2003-03-21 16:07:30-08:00, greg@kroah.com
[PATCH] i2c: remove the data field from struct i2c_client
It's no longer needed, as the struct device should be used instead.
Created i2c_get_clientdata() and i2c_set_clientdata() to access the data.
drivers/i2c/chips/adm1021.c | 15 +++++++--------
drivers/i2c/chips/lm75.c | 8 ++++----
include/linux/i2c.h | 11 ++++++++++-
3 files changed, 21 insertions(+), 13 deletions(-)
------
ChangeSet@1.1191, 2003-03-21 16:00:39-08:00, greg@kroah.com
i2c: add struct device to i2c_client structure
Not quite ready to hook it up to the driver core yet.
include/linux/i2c.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletion(-)
------
ChangeSet@1.1190, 2003-03-21 14:38:21-08:00, greg@kroah.com
[PATCH] i2c: remove *data from i2c_adapter, as dev->data should be used instead.
drivers/i2c/i2c-elv.c | 2 +-
drivers/i2c/scx200_acb.c | 4 ++--
include/linux/i2c.h | 17 +++++++++++------
3 files changed, 14 insertions(+), 9 deletions(-)
------
ChangeSet@1.1189, 2003-03-21 12:45:28-08:00, greg@kroah.com
i2c: remove i2c_adapter->name and use dev->name instead.
drivers/i2c/busses/i2c-ali15x3.c | 8 ++--
drivers/i2c/busses/i2c-amd756.c | 6 ++-
drivers/i2c/busses/i2c-amd8111.c | 4 +-
drivers/i2c/busses/i2c-i801.c | 8 ++--
drivers/i2c/busses/i2c-isa.c | 4 +-
drivers/i2c/busses/i2c-piix4.c | 8 ++--
drivers/i2c/i2c-algo-bit.c | 13 +++---
drivers/i2c/i2c-algo-pcf.c | 19 ++++------
drivers/i2c/i2c-core.c | 73 ++++++++++++++++-----------------------
drivers/i2c/i2c-dev.c | 17 +++------
drivers/i2c/i2c-elektor.c | 10 +++--
drivers/i2c/i2c-elv.c | 4 +-
drivers/i2c/i2c-philips-par.c | 4 +-
drivers/i2c/i2c-velleman.c | 4 +-
drivers/i2c/scx200_acb.c | 28 ++++++--------
include/linux/i2c.h | 1
16 files changed, 105 insertions(+), 106 deletions(-)
------
ChangeSet@1.1188, 2003-03-21 12:29:44-08:00, vandrove@vc.cvut.cz
[PATCH] Fix kobject_get oopses triggered by i2c in 2.5.65-bk
i2c initialization must not use module_init now, when it was converted
to the kobject interface. There are dozens of users which need it working
much sooner. i2c is subsystem after all, isn't it?
Fixes kernel oopses in kobject_get during system init which were happening
to me.
Push file://home/greg/linux/BK/i2c-2.5 -> file://home/greg/linux/BK/bleed-2.5
drivers/i2c/i2c-core.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
------
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Petr Vandrovec
-1 siblings, 0 replies; 98+ messages in thread
From: Petr Vandrovec @ 2003-03-22 2:33 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel, sensors
On Fri, Mar 21, 2003 at 05:04:00PM -0800, Greg KH wrote:
> ChangeSet 1.1189, 2003/03/21 12:45:28-08:00, greg@kroah.com
>
> i2c: remove i2c_adapter->name and use dev->name instead.
>
>
> drivers/i2c/busses/i2c-ali15x3.c | 8 ++--
> drivers/i2c/busses/i2c-amd756.c | 6 ++-
> drivers/i2c/busses/i2c-amd8111.c | 4 +-
> drivers/i2c/busses/i2c-i801.c | 8 ++--
> drivers/i2c/busses/i2c-isa.c | 4 +-
> drivers/i2c/busses/i2c-piix4.c | 8 ++--
> drivers/i2c/i2c-algo-bit.c | 13 +++---
> drivers/i2c/i2c-algo-pcf.c | 19 ++++------
> drivers/i2c/i2c-core.c | 73 ++++++++++++++++-----------------------
> drivers/i2c/i2c-dev.c | 17 +++------
> drivers/i2c/i2c-elektor.c | 10 +++--
> drivers/i2c/i2c-elv.c | 4 +-
> drivers/i2c/i2c-philips-par.c | 4 +-
> drivers/i2c/i2c-velleman.c | 4 +-
> drivers/i2c/scx200_acb.c | 28 ++++++--------
> include/linux/i2c.h | 1
> 16 files changed, 105 insertions(+), 106 deletions(-)
Although you'll not break matroxfb more than it is currently, can you
also update drivers/video/matrox/{i2c-matroxfb,matroxfb_maven}.* in
your updates? Or I'll send you patch after this change hits Linus kernel...
Only problem is that there are apps which search DDC channel by
looking for i2c bus named "DDC:fbX #Y on i2c-matroxfb", and this
looks too long for generic driver infrastructure. But "DDC:fbX #Y"
looks acceptable...
Thanks,
Petr Vandrovec
vandrove@vc.cvut.cz
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Petr Vandrovec
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-23 8:49 UTC (permalink / raw)
To: Petr Vandrovec; +Cc: linux-kernel, sensors
On Sat, Mar 22, 2003 at 03:33:51AM +0100, Petr Vandrovec wrote:
>
> Although you'll not break matroxfb more than it is currently, can you
> also update drivers/video/matrox/{i2c-matroxfb,matroxfb_maven}.* in
> your updates? Or I'll send you patch after this change hits Linus kernel...
Yeah, that stuff doesn't compile at all :)
I added a patch for the i2c related stuff to my tree that I just sent
out.
thanks for pointing it out.
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Pavel Machek
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-25 1:29 UTC (permalink / raw)
To: Pavel Machek; +Cc: linux-kernel, sensors
On Tue, Mar 25, 2003 at 10:35:50AM +0100, Pavel Machek wrote:
> Hi!
>
> > + .name = "ADM1021-MAX1617",
>
> Why dash here
>
> > + .name = "LM75 sensor",
>
> And space here? Also you should have
> either 2x "sensor" or none at all.
What do you mwan "2x"? I just shortened that name up to fit within the
16 characters that we are allowed for driver names. If you can come up
with some better ones, please let me know.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Dave Jones
-1 siblings, 0 replies; 98+ messages in thread
From: Dave Jones @ 2003-03-25 2:04 UTC (permalink / raw)
To: Greg KH; +Cc: Pavel Machek, linux-kernel, sensors
On Mon, Mar 24, 2003 at 05:29:23PM -0800, Greg KH wrote:
> > > + .name = "ADM1021-MAX1617",
> > Why dash here
> > > + .name = "LM75 sensor",
> > And space here? Also you should have
> > either 2x "sensor" or none at all.
> What do you mwan "2x"?
The way I parsed it, either have..
.name = "ADM1021-MAX1617 sensor",
.name = "LM75 sensor",
or
.name = "ADM1021-MAX1617",
.name = "LM75",
ie, both, or all. Personally the latter looks better to me.
Especially given the 16 char limit. Aren't these going to
be in a sysfs heirarchy where its obvious they are sensors
anyway ? like i2c/sensors/lm75 ?
Dave
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Dave Jones
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-03-25 3:34 UTC (permalink / raw)
To: Dave Jones, Pavel Machek, linux-kernel, sensors
On Tue, Mar 25, 2003 at 02:04:19AM +0000, Dave Jones wrote:
> On Mon, Mar 24, 2003 at 05:29:23PM -0800, Greg KH wrote:
>
> > > > + .name = "ADM1021-MAX1617",
> > > Why dash here
> > > > + .name = "LM75 sensor",
> > > And space here? Also you should have
> > > either 2x "sensor" or none at all.
> > What do you mwan "2x"?
>
> The way I parsed it, either have..
> .name = "ADM1021-MAX1617 sensor",
> .name = "LM75 sensor",
>
> or
>
> .name = "ADM1021-MAX1617",
> .name = "LM75",
>
> ie, both, or all. Personally the latter looks better to me.
Ah, yes, that makes more sense now.
Yes, we shouldn't have the "sensor" in the name.
> Especially given the 16 char limit. Aren't these going to
> be in a sysfs heirarchy where its obvious they are sensors
> anyway ? like i2c/sensors/lm75 ?
Yes, they show up as bus/i2c/drivers/
thanks,
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.65
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Pavel Machek
-1 siblings, 0 replies; 98+ messages in thread
From: Pavel Machek @ 2003-03-25 9:35 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel, sensors
Hi!
> + .name = "ADM1021-MAX1617",
Why dash here
> + .name = "LM75 sensor",
And space here? Also you should have
either 2x "sensor" or none at all.
--
Pavel
Written on sharp zaurus, because my Velo1 broke. If you have Velo you don't need...
^ permalink raw reply [flat|nested] 98+ messages in thread
* [BK PATCH] More i2c driver changes for 2.5.66
@ 2003-04-03 0:14 Greg KH
2003-04-03 0:15 ` [PATCH] " Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:14 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, sensors
Hi,
Here are some more i2c driver changes for 2.5.66. It adds two i2c chip
drivers, and converts all of them to the sysfs interface. In doing so,
I've ripped out all of the old /proc and sysctl mess. A number of small
bugfixes for some of the media i2c drivers are in here too.
I've also fixed up the bus_id of the i2c client devices, as the current
code can cause duplicate bus_ids which didn't play nice on some systems.
Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.5
thanks,
greg k-h
Documentation/i2c/proc-interface | 53 -
drivers/i2c/i2c-proc.c | 187 ---
include/linux/i2c-proc.h | 373 -------
Documentation/i2c/sysfs-interface | 177 +++
drivers/i2c/Kconfig | 11
drivers/i2c/Makefile | 2
drivers/i2c/busses/Kconfig | 13
drivers/i2c/chips/Kconfig | 70 +
drivers/i2c/chips/Makefile | 2
drivers/i2c/chips/adm1021.c | 360 +++----
drivers/i2c/chips/lm75.c | 187 +--
drivers/i2c/chips/via686a.c | 1010 +++++++++++++++++++-
drivers/i2c/chips/w83781d.c | 1892 +++++++++++++++++++++++++++++++++++++-
drivers/i2c/i2c-core.c | 190 ---
drivers/i2c/i2c-proc.c | 550 -----------
drivers/i2c/i2c-sensor.c | 182 +++
drivers/media/video/adv7175.c | 2
drivers/media/video/tvmixer.c | 20
include/linux/i2c-proc.h | 43
include/linux/i2c-sensor.h | 373 +++++++
include/linux/i2c-vid.h | 66 +
21 files changed, 3975 insertions(+), 1788 deletions(-)
-----
<azarah@gentoo.org>:
o i2c: w83781d i2c driver updated for 2.5.66-bk4 (with sysfs support, empty tree)
<j.dittmer@portrix.net>:
o i2c: add i2c-via686a driver
o i2c: fix compile bugs in tvmixer.c
Greg Kroah-Hartman <greg@kroah.com>:
o i2c: remove old proc documentation and add sysfs file documentation
o i2c: fix up broken drivers/i2c/busses build due to I2C_PROC now being gone
o i2c: clean up previous w83781d patch due to changes I made to i2c core and build
o i2c: remove all proc code from the i2c core, as it's no longer needed
o i2c: move i2c-proc to i2c-sensor and clean up all usages of it
o i2c: remove unused paramater in found_proc callback function
o i2c: remove proc and sysctl code from i2c-proc as it is no longer used
o i2c: remove sysctl and proc functions from via686a.c driver
o i2c: convert adm1021 chip driver to use sysfs files
o i2c: convert lm75 chip driver to use sysfs files
o i2c: change the way i2c creates the bus ids to actually be unique now
o i2c: fix memleak caused by my last patch fo the adv7175.c driver
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:15 ` Greg KH
@ 2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.3, 2003/03/31 15:25:48-08:00, greg@kroah.com
[PATCH] i2c: fix memleak caused by my last patch fo the adv7175.c driver
drivers/media/video/adv7175.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
diff -Nru a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
--- a/drivers/media/video/adv7175.c Wed Apr 2 16:01:53 2003
+++ b/drivers/media/video/adv7175.c Wed Apr 2 16:01:53 2003
@@ -231,7 +231,7 @@
static int adv717x_detach(struct i2c_client *client)
{
i2c_detach_client(client);
- i2c_get_clientdata(client);
+ kfree(i2c_get_clientdata(client));
kfree(client);
return 0;
}
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:15 ` [PATCH] " Greg KH
@ 2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.2, 2003/03/25 17:29:08-08:00, j.dittmer@portrix.net
[PATCH] i2c: add i2c-via686a driver
drivers/i2c/chips/Kconfig | 13
drivers/i2c/chips/Makefile | 1
drivers/i2c/chips/via686a.c | 952 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 966 insertions(+)
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig Wed Apr 2 16:02:02 2003
+++ b/drivers/i2c/chips/Kconfig Wed Apr 2 16:02:02 2003
@@ -37,4 +37,17 @@
in the lm_sensors package, which you can download at
http://www.lm-sensors.nu
+config SENSORS_VIA686A
+ tristate " VIA686A"
+ depends on I2C && I2C_PROC
+ help
+ support for via686a
+ If you say yes here you get support for the integrated sensors in
+ Via 686A/B South Bridges. This can also be built as a module
+ which can be inserted and removed while the kernel is running.
+
+ You will also need the latest user-space utilties: you can find them
+ in the lm_sensors package, which you can download at
+ http://www.lm-sensors.nu
+
endmenu
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile Wed Apr 2 16:02:02 2003
+++ b/drivers/i2c/chips/Makefile Wed Apr 2 16:02:02 2003
@@ -4,3 +4,4 @@
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
+obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/chips/via686a.c Wed Apr 2 16:02:02 2003
@@ -0,0 +1,952 @@
+/*
+ via686a.c - Part of lm_sensors, Linux kernel modules
+ for hardware monitoring
+
+ Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
+ Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ Mark Studebaker <mdsxyz123@yahoo.com>,
+ and Bob Dougherty <bobd@stanford.edu>
+ (Some conversion-factor data were contributed by Jonathan Teh Soon Yew
+ <j.teh@iname.com> and Alex van Kaam <darkside@chello.nl>.)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ Supports the Via VT82C686A, VT82C686B south bridges.
+ Reports all as a 686A.
+ See doc/chips/via686a for details.
+ Warning - only supports a single device.
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/i2c-proc.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+ the device at the given address. */
+static int force_addr = 0;
+MODULE_PARM(force_addr, "i");
+MODULE_PARM_DESC(force_addr,
+ "Initialize the base address of the sensors");
+
+/* Addresses to scan.
+ Note that we can't determine the ISA address until we have initialized
+ our module */
+static unsigned short normal_i2c[] = { SENSORS_I2C_END };
+static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
+static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
+static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(via686a);
+
+/*
+ The Via 686a southbridge has a LM78-like chip integrated on the same IC.
+ This driver is a customized copy of lm78.c
+*/
+
+/* Many VIA686A constants specified below */
+
+/* Length of ISA address segment */
+#define VIA686A_EXTENT 0x80
+#define VIA686A_BASE_REG 0x70
+#define VIA686A_ENABLE_REG 0x74
+
+/* The VIA686A registers */
+/* ins numbered 0-4 */
+#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
+#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
+#define VIA686A_REG_IN(nr) (0x22 + (nr))
+
+/* fans numbered 1-2 */
+#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
+#define VIA686A_REG_FAN(nr) (0x28 + (nr))
+
+/* the following values are as speced by VIA: */
+static const u8 regtemp[] = { 0x20, 0x21, 0x1f };
+static const u8 regover[] = { 0x39, 0x3d, 0x1d };
+static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e };
+
+/* temps numbered 1-3 */
+#define VIA686A_REG_TEMP(nr) (regtemp[(nr) - 1])
+#define VIA686A_REG_TEMP_OVER(nr) (regover[(nr) - 1])
+#define VIA686A_REG_TEMP_HYST(nr) (reghyst[(nr) - 1])
+#define VIA686A_REG_TEMP_LOW1 0x4b // bits 7-6
+#define VIA686A_REG_TEMP_LOW23 0x49 // 2 = bits 5-4, 3 = bits 7-6
+
+#define VIA686A_REG_ALARM1 0x41
+#define VIA686A_REG_ALARM2 0x42
+#define VIA686A_REG_FANDIV 0x47
+#define VIA686A_REG_CONFIG 0x40
+/* The following register sets temp interrupt mode (bits 1-0 for temp1,
+ 3-2 for temp2, 5-4 for temp3). Modes are:
+ 00 interrupt stays as long as value is out-of-range
+ 01 interrupt is cleared once register is read (default)
+ 10 comparator mode- like 00, but ignores hysteresis
+ 11 same as 00 */
+#define VIA686A_REG_TEMP_MODE 0x4b
+/* We'll just assume that you want to set all 3 simultaneously: */
+#define VIA686A_TEMP_MODE_MASK 0x3F
+#define VIA686A_TEMP_MODE_CONTINUOUS (0x00)
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+ variants.
+
+********* VOLTAGE CONVERSIONS (Bob Dougherty) ********
+ From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
+ voltagefactor[0]=1.25/2628; (2628/1.25=2102.4) // Vccp
+ voltagefactor[1]=1.25/2628; (2628/1.25=2102.4) // +2.5V
+ voltagefactor[2]=1.67/2628; (2628/1.67=1573.7) // +3.3V
+ voltagefactor[3]=2.6/2628; (2628/2.60=1010.8) // +5V
+ voltagefactor[4]=6.3/2628; (2628/6.30=417.14) // +12V
+ in[i]=(data[i+2]*25.0+133)*voltagefactor[i];
+ That is:
+ volts = (25*regVal+133)*factor
+ regVal = (volts/factor-133)/25
+ (These conversions were contributed by Jonathan Teh Soon Yew
+ <j.teh@iname.com>)
+
+ These get us close, but they don't completely agree with what my BIOS
+ says- they are all a bit low. But, it all we have to go on... */
+static inline u8 IN_TO_REG(long val, int inNum)
+{
+ /* to avoid floating point, we multiply everything by 100.
+ val is guaranteed to be positive, so we can achieve the effect of
+ rounding by (...*10+5)/10. Note that the *10 is hidden in the
+ /250 (which should really be /2500).
+ At the end, we need to /100 because we *100 everything and we need
+ to /10 because of the rounding thing, so we /1000. */
+ if (inNum <= 1)
+ return (u8)
+ SENSORS_LIMIT(((val * 210240 - 13300) / 250 + 5) / 1000,
+ 0, 255);
+ else if (inNum == 2)
+ return (u8)
+ SENSORS_LIMIT(((val * 157370 - 13300) / 250 + 5) / 1000,
+ 0, 255);
+ else if (inNum == 3)
+ return (u8)
+ SENSORS_LIMIT(((val * 101080 - 13300) / 250 + 5) / 1000,
+ 0, 255);
+ else
+ return (u8) SENSORS_LIMIT(((val * 41714 - 13300) / 250 + 5)
+ / 1000, 0, 255);
+}
+
+static inline long IN_FROM_REG(u8 val, int inNum)
+{
+ /* to avoid floating point, we multiply everything by 100.
+ val is guaranteed to be positive, so we can achieve the effect of
+ rounding by adding 0.5. Or, to avoid fp math, we do (...*10+5)/10.
+ We need to scale with *100 anyway, so no need to /100 at the end. */
+ if (inNum <= 1)
+ return (long) (((250000 * val + 13300) / 210240 * 10 + 5) /10);
+ else if (inNum == 2)
+ return (long) (((250000 * val + 13300) / 157370 * 10 + 5) /10);
+ else if (inNum == 3)
+ return (long) (((250000 * val + 13300) / 101080 * 10 + 5) /10);
+ else
+ return (long) (((250000 * val + 13300) / 41714 * 10 + 5) /10);
+}
+
+/********* FAN RPM CONVERSIONS ********/
+/* Higher register values = slower fans (the fan's strobe gates a counter).
+ But this chip saturates back at 0, not at 255 like all the other chips.
+ So, 0 means 0 RPM */
+static inline u8 FAN_TO_REG(long rpm, int div)
+{
+ if (rpm == 0)
+ return 0;
+ rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+ return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
+}
+
+#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1350000/((val)*(div)))
+
+/******** TEMP CONVERSIONS (Bob Dougherty) *********/
+/* linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
+ if(temp<169)
+ return double(temp)*0.427-32.08;
+ else if(temp>=169 && temp<=202)
+ return double(temp)*0.582-58.16;
+ else
+ return double(temp)*0.924-127.33;
+
+ A fifth-order polynomial fits the unofficial data (provided by Alex van
+ Kaam <darkside@chello.nl>) a bit better. It also give more reasonable
+ numbers on my machine (ie. they agree with what my BIOS tells me).
+ Here's the fifth-order fit to the 8-bit data:
+ temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
+ 2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
+
+ (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
+ finding my typos in this formula!)
+
+ Alas, none of the elegant function-fit solutions will work because we
+ aren't allowed to use floating point in the kernel and doing it with
+ integers doesn't rpovide enough precision. So we'll do boring old
+ look-up table stuff. The unofficial data (see below) have effectively
+ 7-bit resolution (they are rounded to the nearest degree). I'm assuming
+ that the transfer function of the device is monotonic and smooth, so a
+ smooth function fit to the data will allow us to get better precision.
+ I used the 5th-order poly fit described above and solved for
+ VIA register values 0-255. I *10 before rounding, so we get tenth-degree
+ precision. (I could have done all 1024 values for our 10-bit readings,
+ but the function is very linear in the useful range (0-80 deg C), so
+ we'll just use linear interpolation for 10-bit readings.) So, tempLUT
+ is the temp at via register values 0-255: */
+static const long tempLUT[] =
+ { -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
+ -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
+ -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
+ -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
+ -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
+ -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
+ -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
+ 20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
+ 88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
+ 142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
+ 193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
+ 245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
+ 299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
+ 353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
+ 409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
+ 469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
+ 538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
+ 621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
+ 728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
+ 870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
+ 1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
+ 1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
+};
+
+/* the original LUT values from Alex van Kaam <darkside@chello.nl>
+ (for via register values 12-240):
+{-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
+-30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
+-15,-14,-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,
+-3,-2,-2,-1,-1,0,0,1,1,1,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,9,10,10,11,11,12,
+12,12,13,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,21,21,21,22,22,
+22,23,23,24,24,25,25,26,26,26,27,27,27,28,28,29,29,30,30,30,31,31,32,32,33,
+33,34,34,35,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,
+45,46,46,47,48,48,49,49,50,51,51,52,52,53,53,54,55,55,56,57,57,58,59,59,60,
+61,62,62,63,64,65,66,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,83,84,
+85,86,88,89,91,92,94,96,97,99,101,103,105,107,109,110};
+
+
+ Here's the reverse LUT. I got it by doing a 6-th order poly fit (needed
+ an extra term for a good fit to these inverse data!) and then
+ solving for each temp value from -50 to 110 (the useable range for
+ this chip). Here's the fit:
+ viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
+ - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
+ Note that n=161: */
+static const u8 viaLUT[] =
+ { 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
+ 41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
+ 69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
+ 103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
+ 131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
+ 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
+ 182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
+ 200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
+ 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
+ 233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
+ 239, 240
+};
+
+/* Converting temps to (8-bit) hyst and over registers
+ No interpolation here. Just check the limits and go.
+ The +5 effectively rounds off properly and the +50 is because
+ the temps start at -50 */
+static inline u8 TEMP_TO_REG(long val)
+{
+ return (u8)
+ SENSORS_LIMIT(viaLUT[((val <= -500) ? 0 : (val >= 1100) ? 160 :
+ ((val + 5) / 10 + 50))], 0, 255);
+}
+
+/* for 8-bit temperature hyst and over registers
+ The temp values are already *10, so we don't need to do that.
+ But we _will_ round these off to the nearest degree with (...*10+5)/10 */
+#define TEMP_FROM_REG(val) ((tempLUT[(val)]*10+5)/10)
+
+/* for 10-bit temperature readings
+ You might _think_ this is too long to inline, but's it's really only
+ called once... */
+static inline long TEMP_FROM_REG10(u16 val)
+{
+ /* the temp values are already *10, so we don't need to do that. */
+ long temp;
+ u16 eightBits = val >> 2;
+ u16 twoBits = val & 3;
+
+ /* handle the extremes first (they won't interpolate well! ;-) */
+ if (val == 0)
+ return (long) tempLUT[0];
+ if (val == 1023)
+ return (long) tempLUT[255];
+
+ if (twoBits == 0)
+ return (long) tempLUT[eightBits];
+ else {
+ /* do some interpolation by multipying the lower and upper
+ bounds by 25, 50 or 75, then /100. */
+ temp = ((25 * (4 - twoBits)) * tempLUT[eightBits]
+ + (25 * twoBits) * tempLUT[eightBits + 1]);
+ /* increase the magnitude by 50 to achieve rounding. */
+ if (temp > 0)
+ temp += 50;
+ else
+ temp -= 50;
+ return (temp / 100);
+ }
+}
+
+#define ALARMS_FROM_REG(val) (val)
+
+#define DIV_FROM_REG(val) (1 << (val))
+#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
+
+/* Initial limits */
+#define VIA686A_INIT_IN_0 200
+#define VIA686A_INIT_IN_1 250
+#define VIA686A_INIT_IN_2 330
+#define VIA686A_INIT_IN_3 500
+#define VIA686A_INIT_IN_4 1200
+
+#define VIA686A_INIT_IN_PERCENTAGE 10
+
+#define VIA686A_INIT_IN_MIN_0 (VIA686A_INIT_IN_0 - VIA686A_INIT_IN_0 \
+ * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MAX_0 (VIA686A_INIT_IN_0 + VIA686A_INIT_IN_0 \
+ * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MIN_1 (VIA686A_INIT_IN_1 - VIA686A_INIT_IN_1 \
+ * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MAX_1 (VIA686A_INIT_IN_1 + VIA686A_INIT_IN_1 \
+ * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MIN_2 (VIA686A_INIT_IN_2 - VIA686A_INIT_IN_2 \
+ * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MAX_2 (VIA686A_INIT_IN_2 + VIA686A_INIT_IN_2 \
+ * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MIN_3 (VIA686A_INIT_IN_3 - VIA686A_INIT_IN_3 \
+ * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MAX_3 (VIA686A_INIT_IN_3 + VIA686A_INIT_IN_3 \
+ * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MIN_4 (VIA686A_INIT_IN_4 - VIA686A_INIT_IN_4 \
+ * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MAX_4 (VIA686A_INIT_IN_4 + VIA686A_INIT_IN_4 \
+ * VIA686A_INIT_IN_PERCENTAGE / 100)
+
+#define VIA686A_INIT_FAN_MIN 3000
+
+#define VIA686A_INIT_TEMP_OVER 600
+#define VIA686A_INIT_TEMP_HYST 500
+
+/* For the VIA686A, we need to keep some data in memory. That
+ data is pointed to by via686a_list[NR]->data. The structure itself is
+ dynamically allocated, at the same time when a new via686a client is
+ allocated. */
+struct via686a_data {
+ int sysctl_id;
+
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+
+ u8 in[5]; /* Register value */
+ u8 in_max[5]; /* Register value */
+ u8 in_min[5]; /* Register value */
+ u8 fan[2]; /* Register value */
+ u8 fan_min[2]; /* Register value */
+ u16 temp[3]; /* Register value 10 bit */
+ u8 temp_over[3]; /* Register value */
+ u8 temp_hyst[3]; /* Register value */
+ u8 fan_div[2]; /* Register encoding, shifted right */
+ u16 alarms; /* Register encoding, combined */
+};
+
+static struct pci_dev *s_bridge; /* pointer to the (only) via686a */
+
+static int via686a_attach_adapter(struct i2c_adapter *adapter);
+static int via686a_detect(struct i2c_adapter *adapter, int address,
+ unsigned short flags, int kind);
+static int via686a_detach_client(struct i2c_client *client);
+
+static int via686a_read_value(struct i2c_client *client, u8 register);
+static void via686a_write_value(struct i2c_client *client, u8 register,
+ u8 value);
+static void via686a_update_client(struct i2c_client *client);
+static void via686a_init_client(struct i2c_client *client);
+
+
+static void via686a_in(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results);
+static void via686a_fan(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results);
+static void via686a_temp(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results);
+static void via686a_alarms(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results);
+static void via686a_fan_div(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results);
+
+static int via686a_id = 0;
+
+/* The driver. I choose to use type i2c_driver, as at is identical to both
+ smbus_driver and isa_driver, and clients could be of either kind */
+static struct i2c_driver via686a_driver = {
+ .owner = THIS_MODULE,
+ .name = "VIA686A",
+ .id = I2C_DRIVERID_VIA686A,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = via686a_attach_adapter,
+ .detach_client = via686a_detach_client,
+};
+
+
+
+/* The /proc/sys entries */
+
+/* -- SENSORS SYSCTL START -- */
+#define VIA686A_SYSCTL_IN0 1000
+#define VIA686A_SYSCTL_IN1 1001
+#define VIA686A_SYSCTL_IN2 1002
+#define VIA686A_SYSCTL_IN3 1003
+#define VIA686A_SYSCTL_IN4 1004
+#define VIA686A_SYSCTL_FAN1 1101
+#define VIA686A_SYSCTL_FAN2 1102
+#define VIA686A_SYSCTL_TEMP 1200
+#define VIA686A_SYSCTL_TEMP2 1201
+#define VIA686A_SYSCTL_TEMP3 1202
+#define VIA686A_SYSCTL_FAN_DIV 2000
+#define VIA686A_SYSCTL_ALARMS 2001
+
+#define VIA686A_ALARM_IN0 0x01
+#define VIA686A_ALARM_IN1 0x02
+#define VIA686A_ALARM_IN2 0x04
+#define VIA686A_ALARM_IN3 0x08
+#define VIA686A_ALARM_TEMP 0x10
+#define VIA686A_ALARM_FAN1 0x40
+#define VIA686A_ALARM_FAN2 0x80
+#define VIA686A_ALARM_IN4 0x100
+#define VIA686A_ALARM_TEMP2 0x800
+#define VIA686A_ALARM_CHAS 0x1000
+#define VIA686A_ALARM_TEMP3 0x8000
+
+/* -- SENSORS SYSCTL END -- */
+
+/* These files are created for each detected VIA686A. This is just a template;
+ though at first sight, you might think we could use a statically
+ allocated list, we need some way to get back to the parent - which
+ is done through one of the 'extra' fields which are initialized
+ when a new copy is allocated. */
+static ctl_table via686a_dir_table_template[] = {
+ {VIA686A_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &via686a_in},
+ {VIA686A_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &via686a_in},
+ {VIA686A_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &via686a_in},
+ {VIA686A_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &via686a_in},
+ {VIA686A_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &via686a_in},
+ {VIA686A_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &via686a_fan},
+ {VIA686A_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &via686a_fan},
+ {VIA686A_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &via686a_temp},
+ {VIA686A_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
+ &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_temp},
+ {VIA686A_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
+ &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_temp},
+ {VIA686A_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
+ &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_fan_div},
+ {VIA686A_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
+ &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_alarms},
+ {0}
+};
+
+static inline int via686a_read_value(struct i2c_client *client, u8 reg)
+{
+ return (inb_p(client->addr + reg));
+}
+
+static inline void via686a_write_value(struct i2c_client *client, u8 reg,
+ u8 value)
+{
+ outb_p(value, client->addr + reg);
+}
+
+/* This is called when the module is loaded */
+static int via686a_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, via686a_detect);
+}
+
+int via686a_detect(struct i2c_adapter *adapter, int address,
+ unsigned short flags, int kind)
+{
+ int i;
+ struct i2c_client *new_client;
+ struct via686a_data *data;
+ int err = 0;
+ const char *type_name = "via686a";
+ const char client_name[] = "via686a chip";
+ u16 val;
+
+ /* Make sure we are probing the ISA bus!! */
+ if (!i2c_is_isa_adapter(adapter)) {
+ dev_err(&adapter->dev,
+ "via686a_detect called for an I2C bus adapter?!?\n");
+ return 0;
+ }
+
+ /* 8231 requires multiple of 256, we enforce that on 686 as well */
+ if(force_addr)
+ address = force_addr & 0xFF00;
+
+ if(force_addr) {
+ dev_warn(&adapter->dev,"forcing ISA address 0x%04X\n", address);
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))
+ return -ENODEV;
+ }
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
+ return -ENODEV;
+ if (!(val & 0x0001)) {
+ dev_warn(&adapter->dev,"enabling sensors\n");
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
+ val | 0x0001))
+ return -ENODEV;
+ }
+
+ /* Reserve the ISA region */
+ if (!request_region(address, VIA686A_EXTENT, "via686a-sensor")) {
+ dev_err(&adapter->dev,"region 0x%x already in use!\n",
+ address);
+ return -ENODEV;
+ }
+
+ if (!(new_client = kmalloc(sizeof(struct i2c_client) +
+ sizeof(struct via686a_data),
+ GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto ERROR0;
+ }
+
+ memset(new_client,0x00, sizeof(struct i2c_client) +
+ sizeof(struct via686a_data));
+ data = (struct via686a_data *) (new_client + 1);
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &via686a_driver;
+ new_client->flags = 0;
+
+ /* Fill in the remaining client fields and put into the global list */
+ snprintf(new_client->dev.name, DEVICE_NAME_SIZE, client_name);
+
+ new_client->id = via686a_id++;
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto ERROR3;
+
+ /* Register a new directory entry with module sensors */
+ if ((i = i2c_register_entry((struct i2c_client *) new_client,
+ type_name,
+ via686a_dir_table_template)) < 0) {
+ err = i;
+ goto ERROR4;
+ }
+ data->sysctl_id = i;
+
+ /* Initialize the VIA686A chip */
+ via686a_init_client(new_client);
+ return 0;
+
+ ERROR4:
+ i2c_detach_client(new_client);
+ ERROR3:
+ release_region(address, VIA686A_EXTENT);
+ kfree(new_client);
+ ERROR0:
+ return err;
+}
+
+static int via686a_detach_client(struct i2c_client *client)
+{
+ int err;
+ struct via686a_data *data = i2c_get_clientdata(client);
+ i2c_deregister_entry(data->sysctl_id);
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev,
+ "Client deregistration failed, client not detached.\n");
+ return err;
+ }
+
+ release_region(client->addr, VIA686A_EXTENT);
+ kfree(client);
+
+ return 0;
+}
+
+/* Called when we have found a new VIA686A. Set limits, etc. */
+static void via686a_init_client(struct i2c_client *client)
+{
+ int i;
+
+ /* Reset the device */
+ via686a_write_value(client, VIA686A_REG_CONFIG, 0x80);
+
+ /* Have to wait for reset to complete or else the following
+ initializations won't work reliably. The delay was arrived at
+ empirically, the datasheet doesn't tell you.
+ Waiting for the reset bit to clear doesn't work, it
+ clears in about 2-4 udelays and that isn't nearly enough. */
+ udelay(50);
+
+ via686a_write_value(client, VIA686A_REG_IN_MIN(0),
+ IN_TO_REG(VIA686A_INIT_IN_MIN_0, 0));
+ via686a_write_value(client, VIA686A_REG_IN_MAX(0),
+ IN_TO_REG(VIA686A_INIT_IN_MAX_0, 0));
+ via686a_write_value(client, VIA686A_REG_IN_MIN(1),
+ IN_TO_REG(VIA686A_INIT_IN_MIN_1, 1));
+ via686a_write_value(client, VIA686A_REG_IN_MAX(1),
+ IN_TO_REG(VIA686A_INIT_IN_MAX_1, 1));
+ via686a_write_value(client, VIA686A_REG_IN_MIN(2),
+ IN_TO_REG(VIA686A_INIT_IN_MIN_2, 2));
+ via686a_write_value(client, VIA686A_REG_IN_MAX(2),
+ IN_TO_REG(VIA686A_INIT_IN_MAX_2, 2));
+ via686a_write_value(client, VIA686A_REG_IN_MIN(3),
+ IN_TO_REG(VIA686A_INIT_IN_MIN_3, 3));
+ via686a_write_value(client, VIA686A_REG_IN_MAX(3),
+ IN_TO_REG(VIA686A_INIT_IN_MAX_3, 3));
+ via686a_write_value(client, VIA686A_REG_IN_MIN(4),
+ IN_TO_REG(VIA686A_INIT_IN_MIN_4, 4));
+ via686a_write_value(client, VIA686A_REG_IN_MAX(4),
+ IN_TO_REG(VIA686A_INIT_IN_MAX_4, 4));
+ via686a_write_value(client, VIA686A_REG_FAN_MIN(1),
+ FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2));
+ via686a_write_value(client, VIA686A_REG_FAN_MIN(2),
+ FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2));
+ for (i = 1; i <= 3; i++) {
+ via686a_write_value(client, VIA686A_REG_TEMP_OVER(i),
+ TEMP_TO_REG(VIA686A_INIT_TEMP_OVER));
+ via686a_write_value(client, VIA686A_REG_TEMP_HYST(i),
+ TEMP_TO_REG(VIA686A_INIT_TEMP_HYST));
+ }
+
+ /* Start monitoring */
+ via686a_write_value(client, VIA686A_REG_CONFIG, 0x01);
+
+ /* Cofigure temp interrupt mode for continuous-interrupt operation */
+ via686a_write_value(client, VIA686A_REG_TEMP_MODE,
+ via686a_read_value(client, VIA686A_REG_TEMP_MODE) &
+ !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
+}
+
+static void via686a_update_client(struct i2c_client *client)
+{
+ struct via686a_data *data = i2c_get_clientdata(client);
+ int i;
+
+ down(&data->update_lock);
+
+ if ((jiffies - data->last_updated > HZ + HZ / 2) ||
+ (jiffies < data->last_updated) || !data->valid) {
+
+ for (i = 0; i <= 4; i++) {
+ data->in[i] =
+ via686a_read_value(client, VIA686A_REG_IN(i));
+ data->in_min[i] = via686a_read_value(client,
+ VIA686A_REG_IN_MIN
+ (i));
+ data->in_max[i] =
+ via686a_read_value(client, VIA686A_REG_IN_MAX(i));
+ }
+ for (i = 1; i <= 2; i++) {
+ data->fan[i - 1] =
+ via686a_read_value(client, VIA686A_REG_FAN(i));
+ data->fan_min[i - 1] = via686a_read_value(client,
+ VIA686A_REG_FAN_MIN(i));
+ }
+ for (i = 1; i <= 3; i++) {
+ data->temp[i - 1] = via686a_read_value(client,
+ VIA686A_REG_TEMP(i)) << 2;
+ data->temp_over[i - 1] =
+ via686a_read_value(client,
+ VIA686A_REG_TEMP_OVER(i));
+ data->temp_hyst[i - 1] =
+ via686a_read_value(client,
+ VIA686A_REG_TEMP_HYST(i));
+ }
+ /* add in lower 2 bits
+ temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
+ temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
+ temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
+ */
+ data->temp[0] |= (via686a_read_value(client,
+ VIA686A_REG_TEMP_LOW1)
+ & 0xc0) >> 6;
+ data->temp[1] |=
+ (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
+ 0x30) >> 4;
+ data->temp[2] |=
+ (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
+ 0xc0) >> 6;
+
+ i = via686a_read_value(client, VIA686A_REG_FANDIV);
+ data->fan_div[0] = (i >> 4) & 0x03;
+ data->fan_div[1] = i >> 6;
+ data->alarms =
+ via686a_read_value(client,
+ VIA686A_REG_ALARM1) |
+ (via686a_read_value(client, VIA686A_REG_ALARM2) << 8);
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+}
+
+
+/* The next few functions are the call-back functions of the /proc/sys and
+ sysctl files. Which function is used is defined in the ctl_table in
+ the extra1 field.
+ Each function must return the magnitude (power of 10 to divide the date
+ with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
+ put a maximum of *nrels elements in results reflecting the data of this
+ file, and set *nrels to the number it actually put in it, if operation==
+ SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
+ results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
+ Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
+ large enough (by checking the incoming value of *nrels). This is not very
+ good practice, but as long as you put less than about 5 values in results,
+ you can assume it is large enough. */
+static void via686a_in(struct i2c_client *client, int operation, int ctl_name,
+ int *nrels_mag, long *results)
+{
+ struct via686a_data *data = i2c_get_clientdata(client);
+ int nr = ctl_name - VIA686A_SYSCTL_IN0;
+
+ if (operation == SENSORS_PROC_REAL_INFO)
+ *nrels_mag = 2;
+ else if (operation == SENSORS_PROC_REAL_READ) {
+ via686a_update_client(client);
+ results[0] = IN_FROM_REG(data->in_min[nr], nr);
+ results[1] = IN_FROM_REG(data->in_max[nr], nr);
+ results[2] = IN_FROM_REG(data->in[nr], nr);
+ *nrels_mag = 3;
+ } else if (operation == SENSORS_PROC_REAL_WRITE) {
+ if (*nrels_mag >= 1) {
+ data->in_min[nr] = IN_TO_REG(results[0], nr);
+ via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
+ data->in_min[nr]);
+ }
+ if (*nrels_mag >= 2) {
+ data->in_max[nr] = IN_TO_REG(results[1], nr);
+ via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
+ data->in_max[nr]);
+ }
+ }
+}
+
+void via686a_fan(struct i2c_client *client, int operation, int ctl_name,
+ int *nrels_mag, long *results)
+{
+ struct via686a_data *data = i2c_get_clientdata(client);
+ int nr = ctl_name - VIA686A_SYSCTL_FAN1 + 1;
+
+ if (operation == SENSORS_PROC_REAL_INFO)
+ *nrels_mag = 0;
+ else if (operation == SENSORS_PROC_REAL_READ) {
+ via686a_update_client(client);
+ results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
+ DIV_FROM_REG(data->fan_div
+ [nr - 1]));
+ results[1] = FAN_FROM_REG(data->fan[nr - 1],
+ DIV_FROM_REG(data->fan_div[nr - 1]));
+ *nrels_mag = 2;
+ } else if (operation == SENSORS_PROC_REAL_WRITE) {
+ if (*nrels_mag >= 1) {
+ data->fan_min[nr - 1] = FAN_TO_REG(results[0],
+ DIV_FROM_REG(data->
+ fan_div[nr -1]));
+ via686a_write_value(client,
+ VIA686A_REG_FAN_MIN(nr),
+ data->fan_min[nr - 1]);
+ }
+ }
+}
+
+void via686a_temp(struct i2c_client *client, int operation, int ctl_name,
+ int *nrels_mag, long *results)
+{
+ struct via686a_data *data = i2c_get_clientdata(client);
+ int nr = ctl_name - VIA686A_SYSCTL_TEMP;
+
+ if (operation == SENSORS_PROC_REAL_INFO)
+ *nrels_mag = 1;
+ else if (operation == SENSORS_PROC_REAL_READ) {
+ via686a_update_client(client);
+ results[0] = TEMP_FROM_REG(data->temp_over[nr]);
+ results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
+ results[2] = TEMP_FROM_REG10(data->temp[nr]);
+ *nrels_mag = 3;
+ } else if (operation == SENSORS_PROC_REAL_WRITE) {
+ if (*nrels_mag >= 1) {
+ data->temp_over[nr] = TEMP_TO_REG(results[0]);
+ via686a_write_value(client,
+ VIA686A_REG_TEMP_OVER(nr + 1),
+ data->temp_over[nr]);
+ }
+ if (*nrels_mag >= 2) {
+ data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
+ via686a_write_value(client,
+ VIA686A_REG_TEMP_HYST(nr + 1),
+ data->temp_hyst[nr]);
+ }
+ }
+}
+
+void via686a_alarms(struct i2c_client *client, int operation, int ctl_name,
+ int *nrels_mag, long *results)
+{
+ struct via686a_data *data = i2c_get_clientdata(client);
+ if (operation == SENSORS_PROC_REAL_INFO)
+ *nrels_mag = 0;
+ else if (operation == SENSORS_PROC_REAL_READ) {
+ via686a_update_client(client);
+ results[0] = ALARMS_FROM_REG(data->alarms);
+ *nrels_mag = 1;
+ }
+}
+
+void via686a_fan_div(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results)
+{
+ struct via686a_data *data = i2c_get_clientdata(client);
+ int old;
+
+ if (operation == SENSORS_PROC_REAL_INFO)
+ *nrels_mag = 0;
+ else if (operation == SENSORS_PROC_REAL_READ) {
+ via686a_update_client(client);
+ results[0] = DIV_FROM_REG(data->fan_div[0]);
+ results[1] = DIV_FROM_REG(data->fan_div[1]);
+ *nrels_mag = 2;
+ } else if (operation == SENSORS_PROC_REAL_WRITE) {
+ old = via686a_read_value(client, VIA686A_REG_FANDIV);
+ if (*nrels_mag >= 2) {
+ data->fan_div[1] = DIV_TO_REG(results[1]);
+ old = (old & 0x3f) | (data->fan_div[1] << 6);
+ }
+ if (*nrels_mag >= 1) {
+ data->fan_div[0] = DIV_TO_REG(results[0]);
+ old = (old & 0xcf) | (data->fan_div[0] << 4);
+ via686a_write_value(client, VIA686A_REG_FANDIV,
+ old);
+ }
+ }
+}
+
+
+static struct pci_device_id via686a_pci_ids[] __devinitdata = {
+ {
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = PCI_DEVICE_ID_VIA_82C686_4,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = 0,
+ .class_mask = 0,
+ .driver_data = 0,
+ },
+ { 0, }
+};
+
+static int __devinit via686a_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ u16 val;
+ int addr = 0;
+
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_read_config_word(dev, VIA686A_BASE_REG, &val))
+ return -ENODEV;
+
+ addr = val & ~(VIA686A_EXTENT - 1);
+ if (addr == 0 && force_addr == 0) {
+ dev_err(&dev->dev,"base address not set - upgrade BIOS or use force_addr=0xaddr\n");
+ return -ENODEV;
+ }
+ if (force_addr)
+ addr = force_addr; /* so detect will get called */
+
+ if (!addr) {
+ dev_err(&dev->dev,"No Via 686A sensors found.\n");
+ return -ENODEV;
+ }
+ normal_isa[0] = addr;
+ s_bridge = dev;
+ return i2c_add_driver(&via686a_driver);
+}
+
+static void __devexit via686a_pci_remove(struct pci_dev *dev)
+{
+ i2c_del_driver(&via686a_driver);
+}
+
+static struct pci_driver via686a_pci_driver = {
+ .name = "via686a",
+ .id_table = via686a_pci_ids,
+ .probe = via686a_pci_probe,
+ .remove = __devexit_p(via686a_pci_remove),
+};
+
+static int __init sm_via686a_init(void)
+{
+ return pci_module_init(&via686a_pci_driver);
+}
+
+static void __exit sm_via686a_exit(void)
+{
+ pci_unregister_driver(&via686a_pci_driver);
+}
+
+MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
+ "Mark Studebaker <mdsxyz123@yahoo.com> "
+ "and Bob Dougherty <bobd@stanford.edu>");
+MODULE_DESCRIPTION("VIA 686A Sensor device");
+MODULE_LICENSE("GPL");
+
+module_init(sm_via686a_init);
+module_exit(sm_via686a_exit);
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:14 [BK PATCH] More i2c driver changes for 2.5.66 Greg KH
@ 2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.1, 2003/03/25 17:22:33-08:00, j.dittmer@portrix.net
[PATCH] i2c: fix compile bugs in tvmixer.c
Additionally I need the following patch to tvmixer.c to compile properly
with CONFIG_SOUND_TVMIXER=m. Just a /client->name/client->dev.name/g.
drivers/media/video/tvmixer.c | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff -Nru a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
--- a/drivers/media/video/tvmixer.c Wed Apr 2 16:02:10 2003
+++ b/drivers/media/video/tvmixer.c Wed Apr 2 16:02:10 2003
@@ -87,7 +87,7 @@
if (cmd == SOUND_MIXER_INFO) {
mixer_info info;
strncpy(info.id, "tv card", sizeof(info.id));
- strncpy(info.name, client->name, sizeof(info.name));
+ strncpy(info.name, client->dev.name, sizeof(info.name));
info.modify_counter = 42 /* FIXME */;
if (copy_to_user((void *)arg, &info, sizeof(info)))
return -EFAULT;
@@ -96,7 +96,7 @@
if (cmd == SOUND_OLD_MIXER_INFO) {
_old_mixer_info info;
strncpy(info.id, "tv card", sizeof(info.id));
- strncpy(info.name, client->name, sizeof(info.name));
+ strncpy(info.name, client->dev.name, sizeof(info.name));
if (copy_to_user((void *)arg, &info, sizeof(info)))
return -EFAULT;
return 0;
@@ -237,7 +237,7 @@
int i;
if (debug)
- printk("tvmixer: adapter %s\n",adap->name);
+ printk("tvmixer: adapter %s\n",adap->dev.name);
for (i=0; i<I2C_CLIENT_MAX; i++) {
if (!adap->clients[i])
continue;
@@ -261,10 +261,10 @@
/* ignore that one */
if (debug)
printk("tvmixer: %s is not a tv card\n",
- client->adapter->name);
+ client->adapter->dev.name);
return -1;
}
- printk("tvmixer: debug: %s\n",client->name);
+ printk("tvmixer: debug: %s\n",client->dev.name);
/* unregister ?? */
for (i = 0; i < DEV_MAX; i++) {
@@ -273,7 +273,7 @@
unregister_sound_mixer(devices[i].minor);
devices[i].dev = NULL;
devices[i].minor = -1;
- printk("tvmixer: %s unregistered (#1)\n",client->name);
+ printk("tvmixer: %s unregistered (#1)\n",client->dev.name);
return 0;
}
}
@@ -298,13 +298,13 @@
if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) {
if (debug)
printk("tvmixer: %s: VIDIOCGAUDIO failed\n",
- client->name);
+ client->dev.name);
return -1;
}
if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) {
if (debug)
printk("tvmixer: %s: has no volume control\n",
- client->name);
+ client->dev.name);
return -1;
}
@@ -318,7 +318,7 @@
devices[i].count = 0;
devices[i].dev = client;
printk("tvmixer: %s (%s) registered with minor %d\n",
- client->name,client->adapter->name,minor);
+ client->dev.name,client->adapter->dev.name,minor);
return 0;
}
@@ -344,7 +344,7 @@
if (devices[i].minor != -1) {
unregister_sound_mixer(devices[i].minor);
printk("tvmixer: %s unregistered (#2)\n",
- devices[i].dev->name);
+ devices[i].dev->dev.name);
}
}
}
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:15 ` Greg KH
@ 2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.11, 2003/04/02 13:54:45-08:00, greg@kroah.com
i2c: remove all proc code from the i2c core, as it's no longer needed.
drivers/i2c/i2c-core.c | 187 -------------------------------------------------
1 files changed, 1 insertion(+), 186 deletions(-)
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Wed Apr 2 16:00:37 2003
+++ b/drivers/i2c/i2c-core.c Wed Apr 2 16:00:37 2003
@@ -29,7 +29,6 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
-#include <linux/proc_fs.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/seq_file.h>
@@ -46,15 +45,6 @@
/**** debug level */
static int i2c_debug;
-#ifdef CONFIG_PROC_FS
-static int i2cproc_register(struct i2c_adapter *adap, int bus);
-static void i2cproc_remove(int bus);
-#else
-# define i2cproc_register(adap, bus) 0
-# define i2cproc_remove(bus) do { } while (0)
-#endif /* CONFIG_PROC_FS */
-
-
int i2c_device_probe(struct device *dev)
{
return -ENODEV;
@@ -98,10 +88,6 @@
goto out_unlock;
}
- res = i2cproc_register(adap, i);
- if (res)
- goto out_unlock;
-
adapters[i] = adap;
init_MUTEX(&adap->bus);
@@ -180,8 +166,6 @@
}
}
- i2cproc_remove(i);
-
/* clean up the sysfs representation */
device_unregister(&adap->dev);
@@ -495,173 +479,6 @@
return 0;
}
-#ifdef CONFIG_PROC_FS
-/* This function generates the output for /proc/bus/i2c-? */
-static ssize_t i2cproc_bus_read(struct file *file, char *buf,
- size_t count, loff_t *ppos)
-{
- struct inode *inode = file->f_dentry->d_inode;
- char *kbuf;
- struct i2c_client *client;
- int i,j,k,order_nr,len=0;
- size_t len_total;
- int order[I2C_CLIENT_MAX];
-#define OUTPUT_LENGTH_PER_LINE 70
-
- len_total = file->f_pos + count;
- if (len_total > (I2C_CLIENT_MAX * OUTPUT_LENGTH_PER_LINE) )
- /* adjust to maximum file size */
- len_total = (I2C_CLIENT_MAX * OUTPUT_LENGTH_PER_LINE);
- for (i = 0; i < I2C_ADAP_MAX; i++)
- if (adapters[i]->inode == inode->i_ino) {
- /* We need a bit of slack in the kernel buffer; this makes the
- sprintf safe. */
- if (! (kbuf = kmalloc(len_total +
- OUTPUT_LENGTH_PER_LINE,
- GFP_KERNEL)))
- return -ENOMEM;
- /* Order will hold the indexes of the clients
- sorted by address */
- order_nr=0;
- for (j = 0; j < I2C_CLIENT_MAX; j++) {
- if ((client = adapters[i]->clients[j]) &&
- (client->driver->id != I2C_DRIVERID_I2CDEV)) {
- for(k = order_nr;
- (k > 0) &&
- adapters[i]->clients[order[k-1]]->
- addr > client->addr;
- k--)
- order[k] = order[k-1];
- order[k] = j;
- order_nr++;
- }
- }
-
-
- for (j = 0; (j < order_nr) && (len < len_total); j++) {
- client = adapters[i]->clients[order[j]];
- len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n",
- client->addr,
- client->dev.name,
- client->driver->name);
- }
- len = len - file->f_pos;
- if (len > count)
- len = count;
- if (len < 0)
- len = 0;
- if (copy_to_user (buf,kbuf+file->f_pos, len)) {
- kfree(kbuf);
- return -EFAULT;
- }
- file->f_pos += len;
- kfree(kbuf);
- return len;
- }
- return -ENOENT;
-}
-
-static struct file_operations i2cproc_operations = {
- .read = i2cproc_bus_read,
-};
-
-/* This function generates the output for /proc/bus/i2c */
-static int bus_i2c_show(struct seq_file *s, void *p)
-{
- int i;
-
- down(&core_lists);
- for (i = 0; i < I2C_ADAP_MAX; i++) {
- struct i2c_adapter *adapter = adapters[i];
-
- if (!adapter)
- continue;
-
- seq_printf(s, "i2c-%d\t", i);
-
- if (adapter->algo->smbus_xfer) {
- if (adapter->algo->master_xfer)
- seq_printf(s, "smbus/i2c");
- else
- seq_printf(s, "smbus ");
- } else if (adapter->algo->master_xfer)
- seq_printf(s ,"i2c ");
- else
- seq_printf(s, "dummy ");
-
- seq_printf(s, "\t%-32s\t%-32s\n",
- adapter->dev.name, adapter->algo->name);
- }
- up(&core_lists);
-
- return 0;
-}
-
-static int bus_i2c_open(struct inode *inode, struct file *file)
-{
- return single_open(file, bus_i2c_show, NULL);
-}
-
-static struct file_operations bus_i2c_fops = {
- .open = bus_i2c_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- };
-
-static int i2cproc_register(struct i2c_adapter *adap, int bus)
-{
- struct proc_dir_entry *proc_entry;
- char name[8];
-
- sprintf(name, "i2c-%d", bus);
-
- proc_entry = create_proc_entry(name, 0, proc_bus);
- if (!proc_entry)
- goto fail;
-
- proc_entry->proc_fops = &i2cproc_operations;
- proc_entry->owner = adap->owner;
- adap->inode = proc_entry->low_ino;
- return 0;
- fail:
- printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", name);
- return -ENOENT;
-}
-
-static void i2cproc_remove(int bus)
-{
- char name[8];
-
- sprintf(name,"i2c-%d", bus);
- remove_proc_entry(name, proc_bus);
-}
-
-static int __init i2cproc_init(void)
-{
- struct proc_dir_entry *proc_bus_i2c;
-
- proc_bus_i2c = create_proc_entry("i2c", 0, proc_bus);
- if (!proc_bus_i2c)
- goto fail;
- proc_bus_i2c->proc_fops = &bus_i2c_fops;
- proc_bus_i2c->owner = THIS_MODULE;
- return 0;
-
- fail:
- printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");
- return -ENOENT;
-}
-
-static void __exit i2cproc_cleanup(void)
-{
- remove_proc_entry("i2c",proc_bus);
-}
-#else
-static int __init i2cproc_init(void) { return 0; }
-static void __exit i2cproc_cleanup(void) { }
-#endif /* CONFIG_PROC_FS */
-
/* match always succeeds, as we want the probe() to tell if we really accept this match */
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
@@ -676,13 +493,11 @@
static int __init i2c_init(void)
{
- bus_register(&i2c_bus_type);
- return i2cproc_init();
+ return bus_register(&i2c_bus_type);
}
static void __exit i2c_exit(void)
{
- i2cproc_cleanup();
bus_unregister(&i2c_bus_type);
}
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Greg KH
(?)
@ 2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
-1 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.9, 2003/04/02 11:48:13-08:00, greg@kroah.com
i2c: remove unused paramater in found_proc callback function.
(the users of this function have already been changed in previous patches)
drivers/i2c/i2c-proc.c | 4 ++--
include/linux/i2c-proc.h | 3 +--
2 files changed, 3 insertions(+), 4 deletions(-)
diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
--- a/drivers/i2c/i2c-proc.c Wed Apr 2 16:00:55 2003
+++ b/drivers/i2c/i2c-proc.c Wed Apr 2 16:00:55 2003
@@ -69,7 +69,7 @@
((this_force->force[j] == SENSORS_ANY_I2C_BUS) && !is_isa)) &&
(addr == this_force->force[j + 1]) ) {
dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
- if ((err = found_proc(adapter, addr, 0, this_force->kind)))
+ if ((err = found_proc(adapter, addr, this_force->kind)))
return err;
found = 1;
}
@@ -162,7 +162,7 @@
whether there is some client here at all! */
if (is_isa ||
(i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
- if ((err = found_proc(adapter, addr, 0, -1)))
+ if ((err = found_proc(adapter, addr, -1)))
return err;
}
return 0;
diff -Nru a/include/linux/i2c-proc.h b/include/linux/i2c-proc.h
--- a/include/linux/i2c-proc.h Wed Apr 2 16:00:55 2003
+++ b/include/linux/i2c-proc.h Wed Apr 2 16:00:55 2003
@@ -328,8 +328,7 @@
SENSORS_INSMOD
typedef int i2c_found_addr_proc(struct i2c_adapter *adapter,
- int addr, unsigned short flags,
- int kind);
+ int addr, int kind);
/* Detect function. It iterates over all possible addresses itself. For
SMBus addresses, it will only call found_proc if some client is connected
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:15 ` Greg KH
@ 2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.4, 2003/04/01 11:48:21-08:00, greg@kroah.com
[PATCH] i2c: change the way i2c creates the bus ids to actually be unique now.
It also is much like the old naming scheme, to keep things consistent.
drivers/i2c/i2c-core.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletion(-)
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Wed Apr 2 16:01:44 2003
+++ b/drivers/i2c/i2c-core.c Wed Apr 2 16:01:44 2003
@@ -392,7 +392,8 @@
client->dev.driver = &client->driver->driver;
client->dev.bus = &i2c_bus_type;
- snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), "i2c_dev_%d", i);
+ snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
+ "%d-%04x", i2c_adapter_id(adapter), client->addr);
printk("registering %s\n", client->dev.bus_id);
device_register(&client->dev);
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.6, 2003/04/02 11:32:24-08:00, greg@kroah.com
i2c: convert adm1021 chip driver to use sysfs files.
Note, some data is not converted and will not be displayed.
Someone with this hardware is going to have to finish the rest of
this conversion.
drivers/i2c/chips/adm1021.c | 358 ++++++++++++++++++++------------------------
1 files changed, 166 insertions(+), 192 deletions(-)
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Wed Apr 2 16:01:25 2003
+++ b/drivers/i2c/chips/adm1021.c Wed Apr 2 16:01:25 2003
@@ -53,34 +53,34 @@
/* The adm1021 registers */
/* Read-only */
-#define ADM1021_REG_TEMP 0x00
-#define ADM1021_REG_REMOTE_TEMP 0x01
-#define ADM1021_REG_STATUS 0x02
-#define ADM1021_REG_MAN_ID 0x0FE /* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
-#define ADM1021_REG_DEV_ID 0x0FF /* ADM1021 = 0x0X, ADM1023 = 0x3X */
-#define ADM1021_REG_DIE_CODE 0x0FF /* MAX1617A */
+#define ADM1021_REG_TEMP 0x00
+#define ADM1021_REG_REMOTE_TEMP 0x01
+#define ADM1021_REG_STATUS 0x02
+#define ADM1021_REG_MAN_ID 0x0FE /* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
+#define ADM1021_REG_DEV_ID 0x0FF /* ADM1021 = 0x0X, ADM1023 = 0x3X */
+#define ADM1021_REG_DIE_CODE 0x0FF /* MAX1617A */
/* These use different addresses for reading/writing */
-#define ADM1021_REG_CONFIG_R 0x03
-#define ADM1021_REG_CONFIG_W 0x09
-#define ADM1021_REG_CONV_RATE_R 0x04
-#define ADM1021_REG_CONV_RATE_W 0x0A
+#define ADM1021_REG_CONFIG_R 0x03
+#define ADM1021_REG_CONFIG_W 0x09
+#define ADM1021_REG_CONV_RATE_R 0x04
+#define ADM1021_REG_CONV_RATE_W 0x0A
/* These are for the ADM1023's additional precision on the remote temp sensor */
-#define ADM1021_REG_REM_TEMP_PREC 0x010
-#define ADM1021_REG_REM_OFFSET 0x011
-#define ADM1021_REG_REM_OFFSET_PREC 0x012
-#define ADM1021_REG_REM_TOS_PREC 0x013
-#define ADM1021_REG_REM_THYST_PREC 0x014
+#define ADM1021_REG_REM_TEMP_PREC 0x010
+#define ADM1021_REG_REM_OFFSET 0x011
+#define ADM1021_REG_REM_OFFSET_PREC 0x012
+#define ADM1021_REG_REM_TOS_PREC 0x013
+#define ADM1021_REG_REM_THYST_PREC 0x014
/* limits */
-#define ADM1021_REG_TOS_R 0x05
-#define ADM1021_REG_TOS_W 0x0B
-#define ADM1021_REG_REMOTE_TOS_R 0x07
-#define ADM1021_REG_REMOTE_TOS_W 0x0D
-#define ADM1021_REG_THYST_R 0x06
-#define ADM1021_REG_THYST_W 0x0C
-#define ADM1021_REG_REMOTE_THYST_R 0x08
-#define ADM1021_REG_REMOTE_THYST_W 0x0E
+#define ADM1021_REG_TOS_R 0x05
+#define ADM1021_REG_TOS_W 0x0B
+#define ADM1021_REG_REMOTE_TOS_R 0x07
+#define ADM1021_REG_REMOTE_TOS_W 0x0D
+#define ADM1021_REG_THYST_R 0x06
+#define ADM1021_REG_THYST_W 0x0C
+#define ADM1021_REG_REMOTE_THYST_R 0x08
+#define ADM1021_REG_REMOTE_THYST_W 0x0E
/* write-only */
-#define ADM1021_REG_ONESHOT 0x0F
+#define ADM1021_REG_ONESHOT 0x0F
/* Conversions. Rounding and limit checking is only done on the TO_REG
@@ -88,8 +88,8 @@
these macros are called: arguments may be evaluated more than once.
Fixing this is just not worth it. */
/* Conversions note: 1021 uses normal integer signed-byte format*/
-#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
-#define TEMP_TO_REG(val) (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
+#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
+#define TEMP_TO_REG(val) (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
/* Initial values */
@@ -97,44 +97,43 @@
they don't quite work like a thermostat the way the LM75 does. I.e.,
a lower temp than THYST actually triggers an alarm instead of
clearing it. Weird, ey? --Phil */
-#define adm1021_INIT_TOS 60
-#define adm1021_INIT_THYST 20
-#define adm1021_INIT_REMOTE_TOS 60
-#define adm1021_INIT_REMOTE_THYST 20
+#define adm1021_INIT_TOS 60
+#define adm1021_INIT_THYST 20
+#define adm1021_INIT_REMOTE_TOS 60
+#define adm1021_INIT_REMOTE_THYST 20
/* Each client has this additional data */
struct adm1021_data {
- int sysctl_id;
enum chips type;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
- u8 temp, temp_os, temp_hyst; /* Register values */
- u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms, die_code;
+ u8 temp_max; /* Register values */
+ u8 temp_hyst;
+ u8 temp_input;
+ u8 remote_temp_max;
+ u8 remote_temp_hyst;
+ u8 remote_temp_input;
+ u8 alarms;
+ /* special values for ADM1021 only */
+ u8 die_code;
/* Special values for ADM1023 only */
- u8 remote_temp_prec, remote_temp_os_prec, remote_temp_hyst_prec,
- remote_temp_offset, remote_temp_offset_prec;
+ u8 remote_temp_prec;
+ u8 remote_temp_os_prec;
+ u8 remote_temp_hyst_prec;
+ u8 remote_temp_offset;
+ u8 remote_temp_offset_prec;
};
static int adm1021_attach_adapter(struct i2c_adapter *adapter);
-static int adm1021_detect(struct i2c_adapter *adapter, int address,
- unsigned short flags, int kind);
+static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind);
static void adm1021_init_client(struct i2c_client *client);
static int adm1021_detach_client(struct i2c_client *client);
static int adm1021_read_value(struct i2c_client *client, u8 reg);
static int adm1021_write_value(struct i2c_client *client, u8 reg,
u16 value);
-static void adm1021_temp(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
-static void adm1021_remote_temp(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag,
- long *results);
-static void adm1021_alarms(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
-static void adm1021_die_code(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
static void adm1021_update_client(struct i2c_client *client);
/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
@@ -151,45 +150,63 @@
.detach_client = adm1021_detach_client,
};
-/* These files are created for each detected adm1021. This is just a template;
- though at first sight, you might think we could use a statically
- allocated list, we need some way to get back to the parent - which
- is done through one of the 'extra' fields which are initialized
- when a new copy is allocated. */
-static ctl_table adm1021_dir_table_template[] = {
- {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_temp},
- {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_remote_temp},
- {ADM1021_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_die_code},
- {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_alarms},
- {0}
-};
-
-static ctl_table adm1021_max_dir_table_template[] = {
- {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_temp},
- {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_remote_temp},
- {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_alarms},
- {0}
-};
-
/* I choose here for semi-static allocation. Complete dynamic
allocation could also be used; the code needed for this would probably
take more memory than the datastructure takes now. */
static int adm1021_id = 0;
+#define show(value) \
+static ssize_t show_##value(struct device *dev, char *buf) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct adm1021_data *data = i2c_get_clientdata(client); \
+ int temp; \
+ \
+ adm1021_update_client(client); \
+ temp = TEMP_FROM_REG(data->value); \
+ return sprintf(buf, "%d\n", temp); \
+}
+show(temp_max);
+show(temp_hyst);
+show(temp_input);
+show(remote_temp_max);
+show(remote_temp_hyst);
+show(remote_temp_input);
+show(alarms);
+show(die_code);
+
+#define set(value, reg) \
+static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct adm1021_data *data = i2c_get_clientdata(client); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ \
+ data->value = TEMP_TO_REG(temp); \
+ adm1021_write_value(client, reg, data->value); \
+ return count; \
+}
+set(temp_max, ADM1021_REG_TOS_W);
+set(temp_hyst, ADM1021_REG_THYST_W);
+set(remote_temp_max, ADM1021_REG_REMOTE_TOS_W);
+set(remote_temp_hyst, ADM1021_REG_REMOTE_THYST_W);
+
+static DEVICE_ATTR(temp_max1, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
+static DEVICE_ATTR(temp_min1, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
+static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input, NULL);
+static DEVICE_ATTR(temp_max2, S_IWUSR | S_IRUGO, show_remote_temp_max, set_remote_temp_max);
+static DEVICE_ATTR(temp_min2, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst);
+static DEVICE_ATTR(temp_input2, S_IRUGO, show_remote_temp_input, NULL);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static DEVICE_ATTR(die_code, S_IRUGO, show_die_code, NULL);
+
+
static int adm1021_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_detect(adapter, &addr_data, adm1021_detect);
}
-static int adm1021_detect(struct i2c_adapter *adapter, int address,
- unsigned short flags, int kind)
+static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i;
struct i2c_client *new_client;
@@ -202,8 +219,7 @@
at this moment; i2c_detect really won't call us. */
#ifdef DEBUG
if (i2c_is_isa_adapter(adapter)) {
- printk
- ("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
+ dev_dbg(&adapter->dev, "adm1021_detect called for an ISA bus adapter?!?\n");
return 0;
}
#endif
@@ -232,35 +248,28 @@
new_client->flags = 0;
/* Now, we do the remaining detection. */
-
if (kind < 0) {
- if (
- (adm1021_read_value(new_client, ADM1021_REG_STATUS) &
- 0x03) != 0x00)
+ if ((adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0x03) != 0x00)
goto error1;
}
/* Determine the chip type. */
-
if (kind <= 0) {
i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID);
if (i == 0x41)
- if ((adm1021_read_value (new_client, ADM1021_REG_DEV_ID) & 0x0F0) == 0x030)
- kind = adm1023;
- else
- kind = adm1021;
+ if ((adm1021_read_value(new_client, ADM1021_REG_DEV_ID) & 0x0F0) == 0x030)
+ kind = adm1023;
+ else
+ kind = adm1021;
else if (i == 0x49)
kind = thmc10;
else if (i == 0x23)
kind = gl523sm;
else if ((i == 0x4d) &&
- (adm1021_read_value
- (new_client, ADM1021_REG_DEV_ID) == 0x01))
+ (adm1021_read_value(new_client, ADM1021_REG_DEV_ID) == 0x01))
kind = max1617a;
/* LM84 Mfr ID in a different place */
- else
- if (adm1021_read_value
- (new_client, ADM1021_REG_CONV_RATE_R) == 0x00)
+ else if (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) == 0x00)
kind = lm84;
else if (i == 0x54)
kind = mc1066;
@@ -293,10 +302,8 @@
type_name = "mc1066";
client_name = "MC1066 chip";
} else {
-#ifdef DEBUG
- printk("adm1021.o: Internal error: unknown kind (%d)?!?",
- kind);
-#endif
+ dev_err(&adapter->dev, "Internal error: unknown kind (%d)?!?",
+ kind);
goto error1;
}
@@ -312,25 +319,24 @@
if ((err = i2c_attach_client(new_client)))
goto error3;
- /* Register a new directory entry with module sensors */
- err = i2c_register_entry(new_client, type_name,
- (data->type == adm1021) ?
- adm1021_dir_table_template :
- adm1021_max_dir_table_template);
- if (err < 0)
- goto error4;
+ device_create_file(&new_client->dev, &dev_attr_temp_max1);
+ device_create_file(&new_client->dev, &dev_attr_temp_min1);
+ device_create_file(&new_client->dev, &dev_attr_temp_input1);
+ device_create_file(&new_client->dev, &dev_attr_temp_max2);
+ device_create_file(&new_client->dev, &dev_attr_temp_min2);
+ device_create_file(&new_client->dev, &dev_attr_temp_input2);
+ device_create_file(&new_client->dev, &dev_attr_alarms);
+ if (data->type == adm1021)
+ device_create_file(&new_client->dev, &dev_attr_die_code);
- data->sysctl_id = err;
/* Initialize the ADM1021 chip */
adm1021_init_client(new_client);
return 0;
- error4:
- i2c_detach_client(new_client);
- error3:
- error1:
+error3:
+error1:
kfree(new_client);
- error0:
+error0:
return err;
}
@@ -353,21 +359,15 @@
static int adm1021_detach_client(struct i2c_client *client)
{
-
int err;
- i2c_deregister_entry(((struct adm1021_data *) (i2c_get_clientdata(client)))->sysctl_id);
-
if ((err = i2c_detach_client(client))) {
- printk
- ("adm1021.o: Client deregistration failed, client not detached.\n");
+ dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
return err;
}
kfree(client);
-
return 0;
-
}
/* All registers are byte-sized */
@@ -391,39 +391,23 @@
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
(jiffies < data->last_updated) || !data->valid) {
+ dev_dbg(&client->dev, "Starting adm1021 update\n");
-#ifdef DEBUG
- printk("Starting adm1021 update\n");
-#endif
-
- data->temp = adm1021_read_value(client, ADM1021_REG_TEMP);
- data->temp_os =
- adm1021_read_value(client, ADM1021_REG_TOS_R);
- data->temp_hyst =
- adm1021_read_value(client, ADM1021_REG_THYST_R);
- data->remote_temp =
- adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
- data->remote_temp_os =
- adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
- data->remote_temp_hyst =
- adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
- data->alarms =
- adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec;
+ data->temp_input = adm1021_read_value(client, ADM1021_REG_TEMP);
+ data->temp_max = adm1021_read_value(client, ADM1021_REG_TOS_R);
+ data->temp_hyst = adm1021_read_value(client, ADM1021_REG_THYST_R);
+ data->remote_temp_input = adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
+ data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
+ data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
+ data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec;
if (data->type == adm1021)
- data->die_code =
- adm1021_read_value(client,
- ADM1021_REG_DIE_CODE);
+ data->die_code = adm1021_read_value(client, ADM1021_REG_DIE_CODE);
if (data->type == adm1023) {
- data->remote_temp_prec =
- adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
- data->remote_temp_os_prec =
- adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
- data->remote_temp_hyst_prec =
- adm1021_read_value(client, ADM1021_REG_REM_THYST_PREC);
- data->remote_temp_offset =
- adm1021_read_value(client, ADM1021_REG_REM_OFFSET);
- data->remote_temp_offset_prec =
- adm1021_read_value(client, ADM1021_REG_REM_OFFSET_PREC);
+ data->remote_temp_prec = adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
+ data->remote_temp_os_prec = adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
+ data->remote_temp_hyst_prec = adm1021_read_value(client, ADM1021_REG_REM_THYST_PREC);
+ data->remote_temp_offset = adm1021_read_value(client, ADM1021_REG_REM_OFFSET);
+ data->remote_temp_offset_prec = adm1021_read_value(client, ADM1021_REG_REM_OFFSET_PREC);
}
data->last_updated = jiffies;
data->valid = 1;
@@ -433,6 +417,9 @@
}
+/* FIXME, remove these four functions, they are here to verify the sysfs
+ * conversion is correct, or not */
+__attribute__((unused))
static void adm1021_temp(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
@@ -442,15 +429,15 @@
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
adm1021_update_client(client);
- results[0] = TEMP_FROM_REG(data->temp_os);
+ results[0] = TEMP_FROM_REG(data->temp_max);
results[1] = TEMP_FROM_REG(data->temp_hyst);
- results[2] = TEMP_FROM_REG(data->temp);
+ results[2] = TEMP_FROM_REG(data->temp_input);
*nrels_mag = 3;
} else if (operation == SENSORS_PROC_REAL_WRITE) {
if (*nrels_mag >= 1) {
- data->temp_os = TEMP_TO_REG(results[0]);
+ data->temp_max = TEMP_TO_REG(results[0]);
adm1021_write_value(client, ADM1021_REG_TOS_W,
- data->temp_os);
+ data->temp_max);
}
if (*nrels_mag >= 2) {
data->temp_hyst = TEMP_TO_REG(results[1]);
@@ -460,6 +447,7 @@
}
}
+__attribute__((unused))
static void adm1021_remote_temp(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
@@ -471,68 +459,53 @@
else { *nrels_mag = 0; }
else if (operation == SENSORS_PROC_REAL_READ) {
adm1021_update_client(client);
- results[0] = TEMP_FROM_REG(data->remote_temp_os);
+ results[0] = TEMP_FROM_REG(data->remote_temp_max);
results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
- results[2] = TEMP_FROM_REG(data->remote_temp);
+ results[2] = TEMP_FROM_REG(data->remote_temp_input);
if (data->type == adm1023) {
- results[0]=results[0]*1000 +
- ((data->remote_temp_os_prec >> 5) * 125);
- results[1]=results[1]*1000 +
- ((data->remote_temp_hyst_prec >> 5) * 125);
- results[2]=(TEMP_FROM_REG(data->remote_temp_offset)*1000) +
- ((data->remote_temp_offset_prec >> 5) * 125);
- results[3]=TEMP_FROM_REG(data->remote_temp)*1000 +
- ((data->remote_temp_prec >> 5) * 125);
- *nrels_mag = 4;
+ results[0] = results[0]*1000 + ((data->remote_temp_os_prec >> 5) * 125);
+ results[1] = results[1]*1000 + ((data->remote_temp_hyst_prec >> 5) * 125);
+ results[2] = (TEMP_FROM_REG(data->remote_temp_offset)*1000) + ((data->remote_temp_offset_prec >> 5) * 125);
+ results[3] = (TEMP_FROM_REG(data->remote_temp_input)*1000) + ((data->remote_temp_prec >> 5) * 125);
+ *nrels_mag = 4;
} else {
- *nrels_mag = 3;
+ *nrels_mag = 3;
}
} else if (operation == SENSORS_PROC_REAL_WRITE) {
if (*nrels_mag >= 1) {
if (data->type == adm1023) {
- prec=((results[0]-((results[0]/1000)*1000))/125)<<5;
- adm1021_write_value(client,
- ADM1021_REG_REM_TOS_PREC,
- prec);
- results[0]=results[0]/1000;
- data->remote_temp_os_prec=prec;
+ prec = ((results[0]-((results[0]/1000)*1000))/125)<<5;
+ adm1021_write_value(client, ADM1021_REG_REM_TOS_PREC, prec);
+ results[0] = results[0]/1000;
+ data->remote_temp_os_prec=prec;
}
- data->remote_temp_os = TEMP_TO_REG(results[0]);
- adm1021_write_value(client,
- ADM1021_REG_REMOTE_TOS_W,
- data->remote_temp_os);
+ data->remote_temp_max = TEMP_TO_REG(results[0]);
+ adm1021_write_value(client, ADM1021_REG_REMOTE_TOS_W, data->remote_temp_max);
}
if (*nrels_mag >= 2) {
if (data->type == adm1023) {
- prec=((results[1]-((results[1]/1000)*1000))/125)<<5;
- adm1021_write_value(client,
- ADM1021_REG_REM_THYST_PREC,
- prec);
- results[1]=results[1]/1000;
- data->remote_temp_hyst_prec=prec;
+ prec = ((results[1]-((results[1]/1000)*1000))/125)<<5;
+ adm1021_write_value(client, ADM1021_REG_REM_THYST_PREC, prec);
+ results[1] = results[1]/1000;
+ data->remote_temp_hyst_prec=prec;
}
data->remote_temp_hyst = TEMP_TO_REG(results[1]);
- adm1021_write_value(client,
- ADM1021_REG_REMOTE_THYST_W,
- data->remote_temp_hyst);
+ adm1021_write_value(client, ADM1021_REG_REMOTE_THYST_W, data->remote_temp_hyst);
}
if (*nrels_mag >= 3) {
if (data->type == adm1023) {
- prec=((results[2]-((results[2]/1000)*1000))/125)<<5;
- adm1021_write_value(client,
- ADM1021_REG_REM_OFFSET_PREC,
- prec);
- results[2]=results[2]/1000;
- data->remote_temp_offset_prec=prec;
- data->remote_temp_offset=results[2];
- adm1021_write_value(client,
- ADM1021_REG_REM_OFFSET,
- data->remote_temp_offset);
+ prec = ((results[2]-((results[2]/1000)*1000))/125)<<5;
+ adm1021_write_value(client, ADM1021_REG_REM_OFFSET_PREC, prec);
+ results[2]=results[2]/1000;
+ data->remote_temp_offset_prec=prec;
+ data->remote_temp_offset=results[2];
+ adm1021_write_value(client, ADM1021_REG_REM_OFFSET, data->remote_temp_offset);
}
}
}
}
+__attribute__((unused))
static void adm1021_die_code(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
@@ -549,6 +522,7 @@
}
}
+__attribute__((unused))
static void adm1021_alarms(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
@@ -574,8 +548,8 @@
i2c_del_driver(&adm1021_driver);
}
-MODULE_AUTHOR
- ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
+MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl> and "
+ "Philip Edelbrock <phil@netroedge.com>");
MODULE_DESCRIPTION("adm1021 driver");
MODULE_LICENSE("GPL");
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:15 ` Greg KH
@ 2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.10, 2003/04/02 12:01:21-08:00, greg@kroah.com
i2c: move i2c-proc to i2c-sensor and clean up all usages of it.
drivers/i2c/i2c-proc.c | 187 ----------------------
include/linux/i2c-proc.h | 373 --------------------------------------------
drivers/i2c/Kconfig | 11 -
drivers/i2c/Makefile | 2
drivers/i2c/chips/Kconfig | 13 +
drivers/i2c/chips/adm1021.c | 2
drivers/i2c/chips/lm75.c | 2
drivers/i2c/chips/via686a.c | 2
drivers/i2c/i2c-sensor.c | 182 +++++++++++++++++++++
include/linux/i2c-sensor.h | 373 ++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 568 insertions(+), 579 deletions(-)
diff -Nru a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
--- a/drivers/i2c/Kconfig Wed Apr 2 16:00:46 2003
+++ b/drivers/i2c/Kconfig Wed Apr 2 16:00:46 2003
@@ -196,17 +196,6 @@
<file:Documentation/modules.txt>.
The module will be called i2c-dev.
-config I2C_PROC
- tristate "I2C /proc interface (required for hardware sensors)"
- depends on I2C && SYSCTL
- help
- This provides support for i2c device entries in the /proc filesystem.
- The entries will be found in /proc/sys/dev/sensors.
-
- This code is also available as a module. If you want to compile
- it as a module, say M here and read <file:Documentation/modules.txt>.
- The module will be called i2c-proc.
-
source drivers/i2c/busses/Kconfig
source drivers/i2c/chips/Kconfig
diff -Nru a/drivers/i2c/Makefile b/drivers/i2c/Makefile
--- a/drivers/i2c/Makefile Wed Apr 2 16:00:46 2003
+++ b/drivers/i2c/Makefile Wed Apr 2 16:00:46 2003
@@ -14,5 +14,5 @@
obj-$(CONFIG_ITE_I2C_ADAP) += i2c-adap-ite.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
-obj-$(CONFIG_I2C_PROC) += i2c-proc.o
+obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o
obj-y += busses/ chips/
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig Wed Apr 2 16:00:46 2003
+++ b/drivers/i2c/chips/Kconfig Wed Apr 2 16:00:46 2003
@@ -1,13 +1,13 @@
#
# Sensor device configuration
-# All depend on EXPERIMENTAL, I2C and I2C_PROC.
+# All depend on EXPERIMENTAL and I2C
#
menu "I2C Hardware Sensors Chip support"
config SENSORS_ADM1021
tristate " Analog Devices ADM1021 and compatibles"
- depends on I2C && I2C_PROC
+ depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for Analog Devices ADM1021
and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
@@ -24,7 +24,7 @@
config SENSORS_LM75
tristate " National Semiconductors LM75 and compatibles"
- depends on I2C && I2C_PROC
+ depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for National Semiconductor LM75
sensor chips and clones: Dallas Semi DS75 and DS1775, TelCon
@@ -39,7 +39,7 @@
config SENSORS_VIA686A
tristate " VIA686A"
- depends on I2C && I2C_PROC
+ depends on I2C && EXPERIMENTAL
help
support for via686a
If you say yes here you get support for the integrated sensors in
@@ -49,5 +49,10 @@
You will also need the latest user-space utilties: you can find them
in the lm_sensors package, which you can download at
http://www.lm-sensors.nu
+
+config I2C_SENSOR
+ tristate
+ depends on SENSORS_ADM1021 || SENSORS_LM75 || SENSORS_VIA686A
+ default m
endmenu
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Wed Apr 2 16:00:46 2003
+++ b/drivers/i2c/chips/adm1021.c Wed Apr 2 16:00:46 2003
@@ -23,7 +23,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-proc.h>
+#include <linux/i2c-sensor.h>
/* Registers */
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Wed Apr 2 16:00:46 2003
+++ b/drivers/i2c/chips/lm75.c Wed Apr 2 16:00:46 2003
@@ -24,7 +24,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-proc.h>
+#include <linux/i2c-sensor.h>
/* Addresses to scan */
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c Wed Apr 2 16:00:46 2003
+++ b/drivers/i2c/chips/via686a.c Wed Apr 2 16:00:46 2003
@@ -36,7 +36,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/i2c-proc.h>
+#include <linux/i2c-sensor.h>
#include <linux/init.h>
#include <asm/io.h>
diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
--- a/drivers/i2c/i2c-proc.c Wed Apr 2 16:00:46 2003
+++ /dev/null Wed Dec 31 16:00:00 1969
@@ -1,187 +0,0 @@
-/*
- i2c-proc.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
- Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
- Mark D. Studebaker <mdsxyz123@yahoo.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/*
- This driver puts entries in /proc/sys/dev/sensors for each I2C device
-*/
-
-/* #define DEBUG 1 */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include <linux/sysctl.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/i2c.h>
-#include <linux/i2c-proc.h>
-#include <asm/uaccess.h>
-
-
-/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
-int i2c_detect(struct i2c_adapter *adapter,
- struct i2c_address_data *address_data,
- i2c_found_addr_proc * found_proc)
-{
- int addr, i, found, j, err;
- struct i2c_force_data *this_force;
- int is_isa = i2c_is_isa_adapter(adapter);
- int adapter_id =
- is_isa ? SENSORS_ISA_BUS : i2c_adapter_id(adapter);
-
- /* Forget it if we can't probe using SMBUS_QUICK */
- if ((!is_isa) &&
- !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
- return -1;
-
- for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
- /* XXX: WTF is going on here??? */
- if ((is_isa && check_region(addr, 1)) ||
- (!is_isa && i2c_check_addr(adapter, addr)))
- continue;
-
- /* If it is in one of the force entries, we don't do any
- detection at all */
- found = 0;
- for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
- for (j = 0; !found && (this_force->force[j] != SENSORS_I2C_END); j += 2) {
- if ( ((adapter_id == this_force->force[j]) ||
- ((this_force->force[j] == SENSORS_ANY_I2C_BUS) && !is_isa)) &&
- (addr == this_force->force[j + 1]) ) {
- dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
- if ((err = found_proc(adapter, addr, this_force->kind)))
- return err;
- found = 1;
- }
- }
- }
- if (found)
- continue;
-
- /* If this address is in one of the ignores, we can forget about it
- right now */
- for (i = 0; !found && (address_data->ignore[i] != SENSORS_I2C_END); i += 2) {
- if ( ((adapter_id == address_data->ignore[i]) ||
- ((address_data->ignore[i] == SENSORS_ANY_I2C_BUS) &&
- !is_isa)) &&
- (addr == address_data->ignore[i + 1])) {
- dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- for (i = 0; !found && (address_data->ignore_range[i] != SENSORS_I2C_END); i += 3) {
- if ( ((adapter_id == address_data->ignore_range[i]) ||
- ((address_data-> ignore_range[i] == SENSORS_ANY_I2C_BUS) &
- !is_isa)) &&
- (addr >= address_data->ignore_range[i + 1]) &&
- (addr <= address_data->ignore_range[i + 2])) {
- dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- if (found)
- continue;
-
- /* Now, we will do a detection, but only if it is in the normal or
- probe entries */
- if (is_isa) {
- for (i = 0; !found && (address_data->normal_isa[i] != SENSORS_ISA_END); i += 1) {
- if (addr == address_data->normal_isa[i]) {
- dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- for (i = 0; !found && (address_data->normal_isa_range[i] != SENSORS_ISA_END); i += 3) {
- if ((addr >= address_data->normal_isa_range[i]) &&
- (addr <= address_data->normal_isa_range[i + 1]) &&
- ((addr - address_data->normal_isa_range[i]) % address_data->normal_isa_range[i + 2] == 0)) {
- dev_dbg(&adapter->dev, "found normal isa_range entry for adapter %d, addr %04x", adapter_id, addr);
- found = 1;
- }
- }
- } else {
- for (i = 0; !found && (address_data->normal_i2c[i] != SENSORS_I2C_END); i += 1) {
- if (addr == address_data->normal_i2c[i]) {
- found = 1;
- dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x", adapter_id, addr);
- }
- }
- for (i = 0; !found && (address_data->normal_i2c_range[i] != SENSORS_I2C_END); i += 2) {
- if ((addr >= address_data->normal_i2c_range[i]) &&
- (addr <= address_data->normal_i2c_range[i + 1])) {
- dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- }
-
- for (i = 0;
- !found && (address_data->probe[i] != SENSORS_I2C_END);
- i += 2) {
- if (((adapter_id == address_data->probe[i]) ||
- ((address_data->
- probe[i] == SENSORS_ANY_I2C_BUS) & !is_isa))
- && (addr == address_data->probe[i + 1])) {
- dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
- found = 1;
- }
- }
- for (i = 0; !found && (address_data->probe_range[i] != SENSORS_I2C_END); i += 3) {
- if ( ((adapter_id == address_data->probe_range[i]) ||
- ((address_data->probe_range[i] == SENSORS_ANY_I2C_BUS) & !is_isa)) &&
- (addr >= address_data->probe_range[i + 1]) &&
- (addr <= address_data->probe_range[i + 2])) {
- found = 1;
- dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
- }
- }
- if (!found)
- continue;
-
- /* OK, so we really should examine this address. First check
- whether there is some client here at all! */
- if (is_isa ||
- (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
- if ((err = found_proc(adapter, addr, -1)))
- return err;
- }
- return 0;
-}
-
-static int __init i2c_proc_init(void)
-{
- return 0;
-}
-
-static void __exit i2c_proc_exit(void)
-{
-}
-
-EXPORT_SYMBOL(i2c_detect);
-
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
-MODULE_DESCRIPTION("i2c-proc driver");
-MODULE_LICENSE("GPL");
-
-module_init(i2c_proc_init);
-module_exit(i2c_proc_exit);
diff -Nru a/drivers/i2c/i2c-sensor.c b/drivers/i2c/i2c-sensor.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/i2c-sensor.c Wed Apr 2 16:00:46 2003
@@ -0,0 +1,182 @@
+/*
+ i2c-sensor.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* #define DEBUG 1 */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/sysctl.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <asm/uaccess.h>
+
+
+/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
+int i2c_detect(struct i2c_adapter *adapter,
+ struct i2c_address_data *address_data,
+ i2c_found_addr_proc * found_proc)
+{
+ int addr, i, found, j, err;
+ struct i2c_force_data *this_force;
+ int is_isa = i2c_is_isa_adapter(adapter);
+ int adapter_id =
+ is_isa ? SENSORS_ISA_BUS : i2c_adapter_id(adapter);
+
+ /* Forget it if we can't probe using SMBUS_QUICK */
+ if ((!is_isa) &&
+ !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
+ return -1;
+
+ for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
+ /* XXX: WTF is going on here??? */
+ if ((is_isa && check_region(addr, 1)) ||
+ (!is_isa && i2c_check_addr(adapter, addr)))
+ continue;
+
+ /* If it is in one of the force entries, we don't do any
+ detection at all */
+ found = 0;
+ for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
+ for (j = 0; !found && (this_force->force[j] != SENSORS_I2C_END); j += 2) {
+ if ( ((adapter_id == this_force->force[j]) ||
+ ((this_force->force[j] == SENSORS_ANY_I2C_BUS) && !is_isa)) &&
+ (addr == this_force->force[j + 1]) ) {
+ dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
+ if ((err = found_proc(adapter, addr, this_force->kind)))
+ return err;
+ found = 1;
+ }
+ }
+ }
+ if (found)
+ continue;
+
+ /* If this address is in one of the ignores, we can forget about it
+ right now */
+ for (i = 0; !found && (address_data->ignore[i] != SENSORS_I2C_END); i += 2) {
+ if ( ((adapter_id == address_data->ignore[i]) ||
+ ((address_data->ignore[i] == SENSORS_ANY_I2C_BUS) &&
+ !is_isa)) &&
+ (addr == address_data->ignore[i + 1])) {
+ dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
+ found = 1;
+ }
+ }
+ for (i = 0; !found && (address_data->ignore_range[i] != SENSORS_I2C_END); i += 3) {
+ if ( ((adapter_id == address_data->ignore_range[i]) ||
+ ((address_data-> ignore_range[i] == SENSORS_ANY_I2C_BUS) &
+ !is_isa)) &&
+ (addr >= address_data->ignore_range[i + 1]) &&
+ (addr <= address_data->ignore_range[i + 2])) {
+ dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
+ found = 1;
+ }
+ }
+ if (found)
+ continue;
+
+ /* Now, we will do a detection, but only if it is in the normal or
+ probe entries */
+ if (is_isa) {
+ for (i = 0; !found && (address_data->normal_isa[i] != SENSORS_ISA_END); i += 1) {
+ if (addr == address_data->normal_isa[i]) {
+ dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
+ found = 1;
+ }
+ }
+ for (i = 0; !found && (address_data->normal_isa_range[i] != SENSORS_ISA_END); i += 3) {
+ if ((addr >= address_data->normal_isa_range[i]) &&
+ (addr <= address_data->normal_isa_range[i + 1]) &&
+ ((addr - address_data->normal_isa_range[i]) % address_data->normal_isa_range[i + 2] == 0)) {
+ dev_dbg(&adapter->dev, "found normal isa_range entry for adapter %d, addr %04x", adapter_id, addr);
+ found = 1;
+ }
+ }
+ } else {
+ for (i = 0; !found && (address_data->normal_i2c[i] != SENSORS_I2C_END); i += 1) {
+ if (addr == address_data->normal_i2c[i]) {
+ found = 1;
+ dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x", adapter_id, addr);
+ }
+ }
+ for (i = 0; !found && (address_data->normal_i2c_range[i] != SENSORS_I2C_END); i += 2) {
+ if ((addr >= address_data->normal_i2c_range[i]) &&
+ (addr <= address_data->normal_i2c_range[i + 1])) {
+ dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, addr %04x\n", adapter_id, addr);
+ found = 1;
+ }
+ }
+ }
+
+ for (i = 0;
+ !found && (address_data->probe[i] != SENSORS_I2C_END);
+ i += 2) {
+ if (((adapter_id == address_data->probe[i]) ||
+ ((address_data->
+ probe[i] == SENSORS_ANY_I2C_BUS) & !is_isa))
+ && (addr == address_data->probe[i + 1])) {
+ dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
+ found = 1;
+ }
+ }
+ for (i = 0; !found && (address_data->probe_range[i] != SENSORS_I2C_END); i += 3) {
+ if ( ((adapter_id == address_data->probe_range[i]) ||
+ ((address_data->probe_range[i] == SENSORS_ANY_I2C_BUS) & !is_isa)) &&
+ (addr >= address_data->probe_range[i + 1]) &&
+ (addr <= address_data->probe_range[i + 2])) {
+ found = 1;
+ dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
+ }
+ }
+ if (!found)
+ continue;
+
+ /* OK, so we really should examine this address. First check
+ whether there is some client here at all! */
+ if (is_isa ||
+ (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
+ if ((err = found_proc(adapter, addr, -1)))
+ return err;
+ }
+ return 0;
+}
+
+static int __init i2c_sensor_init(void)
+{
+ return 0;
+}
+
+static void __exit i2c_sensor_exit(void)
+{
+}
+
+EXPORT_SYMBOL(i2c_detect);
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
+MODULE_DESCRIPTION("i2c-sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_sensor_init);
+module_exit(i2c_sensor_exit);
diff -Nru a/include/linux/i2c-proc.h b/include/linux/i2c-proc.h
--- a/include/linux/i2c-proc.h Wed Apr 2 16:00:46 2003
+++ /dev/null Wed Dec 31 16:00:00 1969
@@ -1,373 +0,0 @@
-/*
- i2c-proc.h - Part of the i2c package
- was originally sensors.h - Part of lm_sensors, Linux kernel modules
- for hardware monitoring
- Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
-
- 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.
-*/
-
-#ifndef _LINUX_I2C_PROC_H
-#define _LINUX_I2C_PROC_H
-
-#include <linux/sysctl.h>
-
-/* The type of callback functions used in sensors_{proc,sysctl}_real */
-typedef void (*i2c_real_callback) (struct i2c_client * client,
- int operation, int ctl_name,
- int *nrels_mag, long *results);
-
-/* Values for the operation field in the above function type */
-#define SENSORS_PROC_REAL_INFO 1
-#define SENSORS_PROC_REAL_READ 2
-#define SENSORS_PROC_REAL_WRITE 3
-
-/* A structure containing detect information.
- Force variables overrule all other variables; they force a detection on
- that place. If a specific chip is given, the module blindly assumes this
- chip type is present; if a general force (kind == 0) is given, the module
- will still try to figure out what type of chip is present. This is useful
- if for some reasons the detect for SMBus or ISA address space filled
- fails.
- probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
- A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second is the address.
- kind: The kind of chip. 0 equals any chip.
-*/
-struct i2c_force_data {
- unsigned short *force;
- unsigned short kind;
-};
-
-/* A structure containing the detect information.
- normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
- A list of I2C addresses which should normally be examined.
- normal_i2c_range: filled in by the module writer. Terminated by
- SENSORS_I2C_END
- A list of pairs of I2C addresses, each pair being an inclusive range of
- addresses which should normally be examined.
- normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
- A list of ISA addresses which should normally be examined.
- normal_isa_range: filled in by the module writer. Terminated by
- SENSORS_ISA_END
- A list of triples. The first two elements are ISA addresses, being an
- range of addresses which should normally be examined. The third is the
- modulo parameter: only addresses which are 0 module this value relative
- to the first address of the range are actually considered.
- probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
- A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second is the address. These
- addresses are also probed, as if they were in the 'normal' list.
- probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END
- values.
- A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second and third are addresses.
- These form an inclusive range of addresses that are also probed, as
- if they were in the 'normal' list.
- ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
- A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second is the I2C address. These
- addresses are never probed. This parameter overrules 'normal' and
- 'probe', but not the 'force' lists.
- ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END
- values.
- A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second and third are addresses.
- These form an inclusive range of I2C addresses that are never probed.
- This parameter overrules 'normal' and 'probe', but not the 'force' lists.
- force_data: insmod parameters. A list, ending with an element of which
- the force field is NULL.
-*/
-struct i2c_address_data {
- unsigned short *normal_i2c;
- unsigned short *normal_i2c_range;
- unsigned int *normal_isa;
- unsigned int *normal_isa_range;
- unsigned short *probe;
- unsigned short *probe_range;
- unsigned short *ignore;
- unsigned short *ignore_range;
- struct i2c_force_data *forces;
-};
-
-/* Internal numbers to terminate lists */
-#define SENSORS_I2C_END 0xfffe
-#define SENSORS_ISA_END 0xfffefffe
-
-/* The numbers to use to set an ISA or I2C bus address */
-#define SENSORS_ISA_BUS 9191
-#define SENSORS_ANY_I2C_BUS 0xffff
-
-/* The length of the option lists */
-#define SENSORS_MAX_OPTS 48
-
-/* Default fill of many variables */
-#define SENSORS_DEFAULTS {SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
- SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END}
-
-/* This is ugly. We need to evaluate SENSORS_MAX_OPTS before it is
- stringified */
-#define SENSORS_MODPARM_AUX1(x) "1-" #x "h"
-#define SENSORS_MODPARM_AUX(x) SENSORS_MODPARM_AUX1(x)
-#define SENSORS_MODPARM SENSORS_MODPARM_AUX(SENSORS_MAX_OPTS)
-
-/* SENSORS_MODULE_PARM creates a module parameter, and puts it in the
- module header */
-#define SENSORS_MODULE_PARM(var,desc) \
- static unsigned short var[SENSORS_MAX_OPTS] = SENSORS_DEFAULTS; \
- MODULE_PARM(var,SENSORS_MODPARM); \
- MODULE_PARM_DESC(var,desc)
-
-/* SENSORS_MODULE_PARM creates a 'force_*' module parameter, and puts it in
- the module header */
-#define SENSORS_MODULE_PARM_FORCE(name) \
- SENSORS_MODULE_PARM(force_ ## name, \
- "List of adapter,address pairs which are unquestionably" \
- " assumed to contain a `" # name "' chip")
-
-
-/* This defines several insmod variables, and the addr_data structure */
-#define SENSORS_INSMOD \
- SENSORS_MODULE_PARM(probe, \
- "List of adapter,address pairs to scan additionally"); \
- SENSORS_MODULE_PARM(probe_range, \
- "List of adapter,start-addr,end-addr triples to scan " \
- "additionally"); \
- SENSORS_MODULE_PARM(ignore, \
- "List of adapter,address pairs not to scan"); \
- SENSORS_MODULE_PARM(ignore_range, \
- "List of adapter,start-addr,end-addr triples not to " \
- "scan"); \
- static struct i2c_address_data addr_data = \
- {normal_i2c, normal_i2c_range, \
- normal_isa, normal_isa_range, \
- probe, probe_range, \
- ignore, ignore_range, \
- forces}
-
-/* The following functions create an enum with the chip names as elements.
- The first element of the enum is any_chip. These are the only macros
- a module will want to use. */
-
-#define SENSORS_INSMOD_0 \
- enum chips { any_chip }; \
- SENSORS_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- static struct i2c_force_data forces[] = {{force,any_chip},{NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_1(chip1) \
- enum chips { any_chip, chip1 }; \
- SENSORS_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- static struct i2c_force_data forces[] = {{force,any_chip},\
- {force_ ## chip1,chip1}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_2(chip1,chip2) \
- enum chips { any_chip, chip1, chip2 }; \
- SENSORS_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_3(chip1,chip2,chip3) \
- enum chips { any_chip, chip1, chip2, chip3 }; \
- SENSORS_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_4(chip1,chip2,chip3,chip4) \
- enum chips { any_chip, chip1, chip2, chip3, chip4 }; \
- SENSORS_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- SENSORS_MODULE_PARM_FORCE(chip4); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {force_ ## chip4,chip4}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_5(chip1,chip2,chip3,chip4,chip5) \
- enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \
- SENSORS_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- SENSORS_MODULE_PARM_FORCE(chip4); \
- SENSORS_MODULE_PARM_FORCE(chip5); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {force_ ## chip4,chip4}, \
- {force_ ## chip5,chip5}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_6(chip1,chip2,chip3,chip4,chip5,chip6) \
- enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \
- SENSORS_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- SENSORS_MODULE_PARM_FORCE(chip4); \
- SENSORS_MODULE_PARM_FORCE(chip5); \
- SENSORS_MODULE_PARM_FORCE(chip6); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {force_ ## chip4,chip4}, \
- {force_ ## chip5,chip5}, \
- {force_ ## chip6,chip6}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_7(chip1,chip2,chip3,chip4,chip5,chip6,chip7) \
- enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7 }; \
- SENSORS_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- SENSORS_MODULE_PARM_FORCE(chip4); \
- SENSORS_MODULE_PARM_FORCE(chip5); \
- SENSORS_MODULE_PARM_FORCE(chip6); \
- SENSORS_MODULE_PARM_FORCE(chip7); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {force_ ## chip4,chip4}, \
- {force_ ## chip5,chip5}, \
- {force_ ## chip6,chip6}, \
- {force_ ## chip7,chip7}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-#define SENSORS_INSMOD_8(chip1,chip2,chip3,chip4,chip5,chip6,chip7,chip8) \
- enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8 }; \
- SENSORS_MODULE_PARM(force, \
- "List of adapter,address pairs to boldly assume " \
- "to be present"); \
- SENSORS_MODULE_PARM_FORCE(chip1); \
- SENSORS_MODULE_PARM_FORCE(chip2); \
- SENSORS_MODULE_PARM_FORCE(chip3); \
- SENSORS_MODULE_PARM_FORCE(chip4); \
- SENSORS_MODULE_PARM_FORCE(chip5); \
- SENSORS_MODULE_PARM_FORCE(chip6); \
- SENSORS_MODULE_PARM_FORCE(chip7); \
- SENSORS_MODULE_PARM_FORCE(chip8); \
- static struct i2c_force_data forces[] = {{force,any_chip}, \
- {force_ ## chip1,chip1}, \
- {force_ ## chip2,chip2}, \
- {force_ ## chip3,chip3}, \
- {force_ ## chip4,chip4}, \
- {force_ ## chip5,chip5}, \
- {force_ ## chip6,chip6}, \
- {force_ ## chip7,chip7}, \
- {force_ ## chip8,chip8}, \
- {NULL}}; \
- SENSORS_INSMOD
-
-typedef int i2c_found_addr_proc(struct i2c_adapter *adapter,
- int addr, int kind);
-
-/* Detect function. It iterates over all possible addresses itself. For
- SMBus addresses, it will only call found_proc if some client is connected
- to the SMBus (unless a 'force' matched); for ISA detections, this is not
- done. */
-extern int i2c_detect(struct i2c_adapter *adapter,
- struct i2c_address_data *address_data,
- i2c_found_addr_proc * found_proc);
-
-
-/* This macro is used to scale user-input to sensible values in almost all
- chip drivers. */
-static inline int SENSORS_LIMIT(long value, long low, long high)
-{
- if (value < low)
- return low;
- else if (value > high)
- return high;
- else
- return value;
-}
-
-
-/* The maximum length of the prefix */
-#define SENSORS_PREFIX_MAX 20
-
-/* Sysctl IDs */
-#ifdef DEV_HWMON
-#define DEV_SENSORS DEV_HWMON
-#else /* ndef DEV_HWMOM */
-#define DEV_SENSORS 2 /* The id of the lm_sensors directory within the
- dev table */
-#endif /* def DEV_HWMON */
-
-#define SENSORS_CHIPS 1
-struct i2c_chips_data {
- int sysctl_id;
- char name[SENSORS_PREFIX_MAX + 13];
-};
-
-#endif /* def _LINUX_I2C_PROC_H */
-
diff -Nru a/include/linux/i2c-sensor.h b/include/linux/i2c-sensor.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/include/linux/i2c-sensor.h Wed Apr 2 16:00:46 2003
@@ -0,0 +1,373 @@
+/*
+ i2c-sensor.h - Part of the i2c package
+ was originally sensors.h - Part of lm_sensors, Linux kernel modules
+ for hardware monitoring
+ Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
+
+ 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.
+*/
+
+#ifndef _LINUX_I2C_SENSOR_H
+#define _LINUX_I2C_SENSOR_H
+
+#include <linux/sysctl.h>
+
+/* The type of callback functions used in sensors_{proc,sysctl}_real */
+typedef void (*i2c_real_callback) (struct i2c_client * client,
+ int operation, int ctl_name,
+ int *nrels_mag, long *results);
+
+/* Values for the operation field in the above function type */
+#define SENSORS_PROC_REAL_INFO 1
+#define SENSORS_PROC_REAL_READ 2
+#define SENSORS_PROC_REAL_WRITE 3
+
+/* A structure containing detect information.
+ Force variables overrule all other variables; they force a detection on
+ that place. If a specific chip is given, the module blindly assumes this
+ chip type is present; if a general force (kind == 0) is given, the module
+ will still try to figure out what type of chip is present. This is useful
+ if for some reasons the detect for SMBus or ISA address space filled
+ fails.
+ probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+ A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+ the ISA bus, -1 for any I2C bus), the second is the address.
+ kind: The kind of chip. 0 equals any chip.
+*/
+struct i2c_force_data {
+ unsigned short *force;
+ unsigned short kind;
+};
+
+/* A structure containing the detect information.
+ normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
+ A list of I2C addresses which should normally be examined.
+ normal_i2c_range: filled in by the module writer. Terminated by
+ SENSORS_I2C_END
+ A list of pairs of I2C addresses, each pair being an inclusive range of
+ addresses which should normally be examined.
+ normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
+ A list of ISA addresses which should normally be examined.
+ normal_isa_range: filled in by the module writer. Terminated by
+ SENSORS_ISA_END
+ A list of triples. The first two elements are ISA addresses, being an
+ range of addresses which should normally be examined. The third is the
+ modulo parameter: only addresses which are 0 module this value relative
+ to the first address of the range are actually considered.
+ probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+ A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+ the ISA bus, -1 for any I2C bus), the second is the address. These
+ addresses are also probed, as if they were in the 'normal' list.
+ probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END
+ values.
+ A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
+ the ISA bus, -1 for any I2C bus), the second and third are addresses.
+ These form an inclusive range of addresses that are also probed, as
+ if they were in the 'normal' list.
+ ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+ A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+ the ISA bus, -1 for any I2C bus), the second is the I2C address. These
+ addresses are never probed. This parameter overrules 'normal' and
+ 'probe', but not the 'force' lists.
+ ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END
+ values.
+ A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
+ the ISA bus, -1 for any I2C bus), the second and third are addresses.
+ These form an inclusive range of I2C addresses that are never probed.
+ This parameter overrules 'normal' and 'probe', but not the 'force' lists.
+ force_data: insmod parameters. A list, ending with an element of which
+ the force field is NULL.
+*/
+struct i2c_address_data {
+ unsigned short *normal_i2c;
+ unsigned short *normal_i2c_range;
+ unsigned int *normal_isa;
+ unsigned int *normal_isa_range;
+ unsigned short *probe;
+ unsigned short *probe_range;
+ unsigned short *ignore;
+ unsigned short *ignore_range;
+ struct i2c_force_data *forces;
+};
+
+/* Internal numbers to terminate lists */
+#define SENSORS_I2C_END 0xfffe
+#define SENSORS_ISA_END 0xfffefffe
+
+/* The numbers to use to set an ISA or I2C bus address */
+#define SENSORS_ISA_BUS 9191
+#define SENSORS_ANY_I2C_BUS 0xffff
+
+/* The length of the option lists */
+#define SENSORS_MAX_OPTS 48
+
+/* Default fill of many variables */
+#define SENSORS_DEFAULTS {SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+ SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END}
+
+/* This is ugly. We need to evaluate SENSORS_MAX_OPTS before it is
+ stringified */
+#define SENSORS_MODPARM_AUX1(x) "1-" #x "h"
+#define SENSORS_MODPARM_AUX(x) SENSORS_MODPARM_AUX1(x)
+#define SENSORS_MODPARM SENSORS_MODPARM_AUX(SENSORS_MAX_OPTS)
+
+/* SENSORS_MODULE_PARM creates a module parameter, and puts it in the
+ module header */
+#define SENSORS_MODULE_PARM(var,desc) \
+ static unsigned short var[SENSORS_MAX_OPTS] = SENSORS_DEFAULTS; \
+ MODULE_PARM(var,SENSORS_MODPARM); \
+ MODULE_PARM_DESC(var,desc)
+
+/* SENSORS_MODULE_PARM creates a 'force_*' module parameter, and puts it in
+ the module header */
+#define SENSORS_MODULE_PARM_FORCE(name) \
+ SENSORS_MODULE_PARM(force_ ## name, \
+ "List of adapter,address pairs which are unquestionably" \
+ " assumed to contain a `" # name "' chip")
+
+
+/* This defines several insmod variables, and the addr_data structure */
+#define SENSORS_INSMOD \
+ SENSORS_MODULE_PARM(probe, \
+ "List of adapter,address pairs to scan additionally"); \
+ SENSORS_MODULE_PARM(probe_range, \
+ "List of adapter,start-addr,end-addr triples to scan " \
+ "additionally"); \
+ SENSORS_MODULE_PARM(ignore, \
+ "List of adapter,address pairs not to scan"); \
+ SENSORS_MODULE_PARM(ignore_range, \
+ "List of adapter,start-addr,end-addr triples not to " \
+ "scan"); \
+ static struct i2c_address_data addr_data = \
+ {normal_i2c, normal_i2c_range, \
+ normal_isa, normal_isa_range, \
+ probe, probe_range, \
+ ignore, ignore_range, \
+ forces}
+
+/* The following functions create an enum with the chip names as elements.
+ The first element of the enum is any_chip. These are the only macros
+ a module will want to use. */
+
+#define SENSORS_INSMOD_0 \
+ enum chips { any_chip }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ static struct i2c_force_data forces[] = {{force,any_chip},{NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_1(chip1) \
+ enum chips { any_chip, chip1 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ static struct i2c_force_data forces[] = {{force,any_chip},\
+ {force_ ## chip1,chip1}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_2(chip1,chip2) \
+ enum chips { any_chip, chip1, chip2 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_3(chip1,chip2,chip3) \
+ enum chips { any_chip, chip1, chip2, chip3 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_4(chip1,chip2,chip3,chip4) \
+ enum chips { any_chip, chip1, chip2, chip3, chip4 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ SENSORS_MODULE_PARM_FORCE(chip4); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {force_ ## chip4,chip4}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_5(chip1,chip2,chip3,chip4,chip5) \
+ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ SENSORS_MODULE_PARM_FORCE(chip4); \
+ SENSORS_MODULE_PARM_FORCE(chip5); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {force_ ## chip4,chip4}, \
+ {force_ ## chip5,chip5}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_6(chip1,chip2,chip3,chip4,chip5,chip6) \
+ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ SENSORS_MODULE_PARM_FORCE(chip4); \
+ SENSORS_MODULE_PARM_FORCE(chip5); \
+ SENSORS_MODULE_PARM_FORCE(chip6); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {force_ ## chip4,chip4}, \
+ {force_ ## chip5,chip5}, \
+ {force_ ## chip6,chip6}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_7(chip1,chip2,chip3,chip4,chip5,chip6,chip7) \
+ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ SENSORS_MODULE_PARM_FORCE(chip4); \
+ SENSORS_MODULE_PARM_FORCE(chip5); \
+ SENSORS_MODULE_PARM_FORCE(chip6); \
+ SENSORS_MODULE_PARM_FORCE(chip7); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {force_ ## chip4,chip4}, \
+ {force_ ## chip5,chip5}, \
+ {force_ ## chip6,chip6}, \
+ {force_ ## chip7,chip7}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+#define SENSORS_INSMOD_8(chip1,chip2,chip3,chip4,chip5,chip6,chip7,chip8) \
+ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ SENSORS_MODULE_PARM_FORCE(chip4); \
+ SENSORS_MODULE_PARM_FORCE(chip5); \
+ SENSORS_MODULE_PARM_FORCE(chip6); \
+ SENSORS_MODULE_PARM_FORCE(chip7); \
+ SENSORS_MODULE_PARM_FORCE(chip8); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {force_ ## chip4,chip4}, \
+ {force_ ## chip5,chip5}, \
+ {force_ ## chip6,chip6}, \
+ {force_ ## chip7,chip7}, \
+ {force_ ## chip8,chip8}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
+typedef int i2c_found_addr_proc(struct i2c_adapter *adapter,
+ int addr, int kind);
+
+/* Detect function. It iterates over all possible addresses itself. For
+ SMBus addresses, it will only call found_proc if some client is connected
+ to the SMBus (unless a 'force' matched); for ISA detections, this is not
+ done. */
+extern int i2c_detect(struct i2c_adapter *adapter,
+ struct i2c_address_data *address_data,
+ i2c_found_addr_proc * found_proc);
+
+
+/* This macro is used to scale user-input to sensible values in almost all
+ chip drivers. */
+static inline int SENSORS_LIMIT(long value, long low, long high)
+{
+ if (value < low)
+ return low;
+ else if (value > high)
+ return high;
+ else
+ return value;
+}
+
+
+/* The maximum length of the prefix */
+#define SENSORS_PREFIX_MAX 20
+
+/* Sysctl IDs */
+#ifdef DEV_HWMON
+#define DEV_SENSORS DEV_HWMON
+#else /* ndef DEV_HWMOM */
+#define DEV_SENSORS 2 /* The id of the lm_sensors directory within the
+ dev table */
+#endif /* def DEV_HWMON */
+
+#define SENSORS_CHIPS 1
+struct i2c_chips_data {
+ int sysctl_id;
+ char name[SENSORS_PREFIX_MAX + 13];
+};
+
+#endif /* def _LINUX_I2C_SENSOR_H */
+
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Greg KH
(?)
@ 2003-04-03 0:15 ` Greg KH
2005-05-19 6:23 ` Greg KH
-1 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.7, 2003/04/02 11:34:13-08:00, greg@kroah.com
i2c: remove sysctl and proc functions from via686a.c driver
This still needs to be converted to use sysfs files, but due to
lack of hardware, I can not do this. This change is necessary as
the sysctl and proc interface is about to go away.
drivers/i2c/chips/via686a.c | 56 +++++++++++++-------------------------------
1 files changed, 17 insertions(+), 39 deletions(-)
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c Wed Apr 2 16:01:14 2003
+++ b/drivers/i2c/chips/via686a.c Wed Apr 2 16:01:14 2003
@@ -369,8 +369,6 @@
dynamically allocated, at the same time when a new via686a client is
allocated. */
struct via686a_data {
- int sysctl_id;
-
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -390,8 +388,7 @@
static struct pci_dev *s_bridge; /* pointer to the (only) via686a */
static int via686a_attach_adapter(struct i2c_adapter *adapter);
-static int via686a_detect(struct i2c_adapter *adapter, int address,
- unsigned short flags, int kind);
+static int via686a_detect(struct i2c_adapter *adapter, int address, int kind);
static int via686a_detach_client(struct i2c_client *client);
static int via686a_read_value(struct i2c_client *client, u8 register);
@@ -400,18 +397,6 @@
static void via686a_update_client(struct i2c_client *client);
static void via686a_init_client(struct i2c_client *client);
-
-static void via686a_in(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
-static void via686a_fan(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
-static void via686a_temp(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
-static void via686a_alarms(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
-static void via686a_fan_div(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
-
static int via686a_id = 0;
/* The driver. I choose to use type i2c_driver, as at is identical to both
@@ -457,6 +442,7 @@
/* -- SENSORS SYSCTL END -- */
+#if 0
/* These files are created for each detected VIA686A. This is just a template;
though at first sight, you might think we could use a statically
allocated list, we need some way to get back to the parent - which
@@ -489,6 +475,7 @@
&i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_alarms},
{0}
};
+#endif
static inline int via686a_read_value(struct i2c_client *client, u8 reg)
{
@@ -507,15 +494,12 @@
return i2c_detect(adapter, &addr_data, via686a_detect);
}
-int via686a_detect(struct i2c_adapter *adapter, int address,
- unsigned short flags, int kind)
+static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
{
- int i;
struct i2c_client *new_client;
struct via686a_data *data;
int err = 0;
- const char *type_name = "via686a";
- const char client_name[] = "via686a chip";
+ const char *name = "via686a";
u16 val;
/* Make sure we are probing the ISA bus!! */
@@ -570,7 +554,7 @@
new_client->flags = 0;
/* Fill in the remaining client fields and put into the global list */
- snprintf(new_client->dev.name, DEVICE_NAME_SIZE, client_name);
+ snprintf(new_client->dev.name, DEVICE_NAME_SIZE, name);
new_client->id = via686a_id++;
data->valid = 0;
@@ -579,21 +563,10 @@
if ((err = i2c_attach_client(new_client)))
goto ERROR3;
- /* Register a new directory entry with module sensors */
- if ((i = i2c_register_entry((struct i2c_client *) new_client,
- type_name,
- via686a_dir_table_template)) < 0) {
- err = i;
- goto ERROR4;
- }
- data->sysctl_id = i;
-
/* Initialize the VIA686A chip */
via686a_init_client(new_client);
return 0;
- ERROR4:
- i2c_detach_client(new_client);
ERROR3:
release_region(address, VIA686A_EXTENT);
kfree(new_client);
@@ -604,8 +577,6 @@
static int via686a_detach_client(struct i2c_client *client)
{
int err;
- struct via686a_data *data = i2c_get_clientdata(client);
- i2c_deregister_entry(data->sysctl_id);
if ((err = i2c_detach_client(client))) {
dev_err(&client->dev,
@@ -752,6 +723,9 @@
large enough (by checking the incoming value of *nrels). This is not very
good practice, but as long as you put less than about 5 values in results,
you can assume it is large enough. */
+/* FIXME, remove these functions, they are here to verify the sysfs conversion
+ * is correct, or not */
+__attribute__((unused))
static void via686a_in(struct i2c_client *client, int operation, int ctl_name,
int *nrels_mag, long *results)
{
@@ -780,7 +754,8 @@
}
}
-void via686a_fan(struct i2c_client *client, int operation, int ctl_name,
+__attribute__((unused))
+static void via686a_fan(struct i2c_client *client, int operation, int ctl_name,
int *nrels_mag, long *results)
{
struct via686a_data *data = i2c_get_clientdata(client);
@@ -808,7 +783,8 @@
}
}
-void via686a_temp(struct i2c_client *client, int operation, int ctl_name,
+__attribute__((unused))
+static void via686a_temp(struct i2c_client *client, int operation, int ctl_name,
int *nrels_mag, long *results)
{
struct via686a_data *data = i2c_get_clientdata(client);
@@ -838,7 +814,8 @@
}
}
-void via686a_alarms(struct i2c_client *client, int operation, int ctl_name,
+__attribute__((unused))
+static void via686a_alarms(struct i2c_client *client, int operation, int ctl_name,
int *nrels_mag, long *results)
{
struct via686a_data *data = i2c_get_clientdata(client);
@@ -851,7 +828,8 @@
}
}
-void via686a_fan_div(struct i2c_client *client, int operation,
+__attribute__((unused))
+static void via686a_fan_div(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
struct via686a_data *data = i2c_get_clientdata(client);
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:15 ` Greg KH
@ 2003-04-03 0:15 ` Greg KH
2005-05-19 6:23 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.5, 2003/04/02 11:29:55-08:00, greg@kroah.com
i2c: convert lm75 chip driver to use sysfs files.
drivers/i2c/chips/lm75.c | 185 +++++++++++++++++++----------------------------
1 files changed, 77 insertions(+), 108 deletions(-)
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Wed Apr 2 16:01:36 2003
+++ b/drivers/i2c/chips/lm75.c Wed Apr 2 16:01:36 2003
@@ -18,6 +18,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/* #define DEBUG 1 */
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -25,8 +27,6 @@
#include <linux/i2c-proc.h>
-#define LM75_SYSCTL_TEMP 1200 /* Degrees Celsius * 10 */
-
/* Addresses to scan */
static unsigned short normal_i2c[] = { SENSORS_I2C_END };
static unsigned short normal_i2c_range[] = { 0x48, 0x4f, SENSORS_I2C_END };
@@ -39,97 +39,113 @@
/* Many LM75 constants specified below */
/* The LM75 registers */
-#define LM75_REG_TEMP 0x00
-#define LM75_REG_CONF 0x01
-#define LM75_REG_TEMP_HYST 0x02
-#define LM75_REG_TEMP_OS 0x03
+#define LM75_REG_TEMP 0x00
+#define LM75_REG_CONF 0x01
+#define LM75_REG_TEMP_HYST 0x02
+#define LM75_REG_TEMP_OS 0x03
/* Conversions. Rounding and limit checking is only done on the TO_REG
variants. Note that you should be a bit careful with which arguments
these macros are called: arguments may be evaluated more than once.
Fixing this is just not worth it. */
-#define TEMP_FROM_REG(val) ((((val & 0x7fff) >> 7) * 5) | ((val & 0x8000)?-256:0))
-#define TEMP_TO_REG(val) (SENSORS_LIMIT((val<0?(0x200+((val)/5))<<7:(((val) + 2) / 5) << 7),0,0xffff))
+#define TEMP_FROM_REG(val) ((((val & 0x7fff) >> 7) * 5) | ((val & 0x8000)?-256:0))
+#define TEMP_TO_REG(val) (SENSORS_LIMIT((val<0?(0x200+((val)/5))<<7:(((val) + 2) / 5) << 7),0,0xffff))
/* Initial values */
-#define LM75_INIT_TEMP_OS 600
-#define LM75_INIT_TEMP_HYST 500
+#define LM75_INIT_TEMP_OS 600
+#define LM75_INIT_TEMP_HYST 500
/* Each client has this additional data */
struct lm75_data {
- int sysctl_id;
-
- struct semaphore update_lock;
- char valid; /* !=0 if following fields are valid */
- unsigned long last_updated; /* In jiffies */
-
- u16 temp, temp_os, temp_hyst; /* Register values */
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+ u16 temp_input; /* Register values */
+ u16 temp_max;
+ u16 temp_hyst;
};
static int lm75_attach_adapter(struct i2c_adapter *adapter);
-static int lm75_detect(struct i2c_adapter *adapter, int address,
- unsigned short flags, int kind);
+static int lm75_detect(struct i2c_adapter *adapter, int address, int kind);
static void lm75_init_client(struct i2c_client *client);
static int lm75_detach_client(struct i2c_client *client);
-static u16 swap_bytes(u16 val);
static int lm75_read_value(struct i2c_client *client, u8 reg);
static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value);
-static void lm75_temp(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
static void lm75_update_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver lm75_driver = {
.owner = THIS_MODULE,
- .name = "LM75 sensor",
+ .name = "lm75",
.id = I2C_DRIVERID_LM75,
.flags = I2C_DF_NOTIFY,
.attach_adapter = lm75_attach_adapter,
.detach_client = lm75_detach_client,
};
-/* These files are created for each detected LM75. This is just a template;
- though at first sight, you might think we could use a statically
- allocated list, we need some way to get back to the parent - which
- is done through one of the 'extra' fields which are initialized
- when a new copy is allocated. */
-static ctl_table lm75_dir_table_template[] = {
- {LM75_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &lm75_temp},
- {0}
-};
-
static int lm75_id = 0;
+#define show(value) \
+static ssize_t show_##value(struct device *dev, char *buf) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct lm75_data *data = i2c_get_clientdata(client); \
+ int temp; \
+ \
+ lm75_update_client(client); \
+ temp = TEMP_FROM_REG(data->value); \
+ return sprintf(buf, "%d\n", temp * 100); \
+}
+show(temp_max);
+show(temp_hyst);
+show(temp_input);
+
+#define set(value, reg) \
+static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct lm75_data *data = i2c_get_clientdata(client); \
+ int temp = simple_strtoul(buf, NULL, 10) / 100; \
+ \
+ data->value = TEMP_TO_REG(temp); \
+ lm75_write_value(client, reg, data->value); \
+ return count; \
+}
+set(temp_max, LM75_REG_TEMP_OS);
+set(temp_hyst, LM75_REG_TEMP_HYST);
+
+static DEVICE_ATTR(temp_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
+static DEVICE_ATTR(temp_min, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
+static DEVICE_ATTR(temp_input, S_IRUGO, show_temp_input, NULL);
+
static int lm75_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_detect(adapter, &addr_data, lm75_detect);
}
/* This function is called by i2c_detect */
-static int lm75_detect(struct i2c_adapter *adapter, int address,
- unsigned short flags, int kind)
+static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i, cur, conf, hyst, os;
struct i2c_client *new_client;
struct lm75_data *data;
int err = 0;
- const char *type_name, *client_name;
+ const char *name;
/* Make sure we aren't probing the ISA bus!! This is just a safety check
at this moment; i2c_detect really won't call us. */
#ifdef DEBUG
if (i2c_is_isa_adapter(adapter)) {
- printk
- ("lm75.o: lm75_detect called for an ISA bus adapter?!?\n");
- return 0;
+ dev_dbg(&adapter->dev,
+ "lm75_detect called for an ISA bus adapter?!?\n");
+ goto exit;
}
#endif
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
- goto error0;
+ goto exit;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
@@ -138,7 +154,7 @@
sizeof(struct lm75_data),
GFP_KERNEL))) {
err = -ENOMEM;
- goto error0;
+ goto exit;
}
memset(new_client, 0x00, sizeof(struct i2c_client) +
sizeof(struct lm75_data));
@@ -157,16 +173,10 @@
hyst = i2c_smbus_read_word_data(new_client, 2);
os = i2c_smbus_read_word_data(new_client, 3);
for (i = 0; i <= 0x1f; i++)
- if (
- (i2c_smbus_read_byte_data
- (new_client, i * 8 + 1) != conf)
- ||
- (i2c_smbus_read_word_data
- (new_client, i * 8 + 2) != hyst)
- ||
- (i2c_smbus_read_word_data
- (new_client, i * 8 + 3) != os))
- goto error1;
+ if ((i2c_smbus_read_byte_data(new_client, i * 8 + 1) != conf) ||
+ (i2c_smbus_read_word_data(new_client, i * 8 + 2) != hyst) ||
+ (i2c_smbus_read_word_data(new_client, i * 8 + 3) != os))
+ goto exit_free;
}
/* Determine the chip type - only one kind supported! */
@@ -174,15 +184,15 @@
kind = lm75;
if (kind == lm75) {
- type_name = "lm75";
- client_name = "LM75 chip";
+ name = "lm75";
} else {
- pr_debug("lm75.o: Internal error: unknown kind (%d)?!?", kind);
- goto error1;
+ dev_dbg(&adapter->dev, "Internal error: unknown kind (%d)?!?",
+ kind);
+ goto exit_free;
}
/* Fill in the remaining client fields and put it into the global list */
- strncpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
+ strncpy(new_client->dev.name, name, DEVICE_NAME_SIZE);
new_client->id = lm75_id++;
data->valid = 0;
@@ -190,36 +200,23 @@
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
- goto error3;
+ goto exit_free;
- /* Register a new directory entry with module sensors */
- i = i2c_register_entry(new_client, type_name, lm75_dir_table_template);
- if (i < 0) {
- err = i;
- goto error4;
- }
- data->sysctl_id = i;
+ device_create_file(&new_client->dev, &dev_attr_temp_max);
+ device_create_file(&new_client->dev, &dev_attr_temp_min);
+ device_create_file(&new_client->dev, &dev_attr_temp_input);
lm75_init_client(new_client);
return 0;
-/* OK, this is not exactly good programming practice, usually. But it is
- very code-efficient in this case. */
-
- error4:
- i2c_detach_client(new_client);
- error3:
- error1:
+exit_free:
kfree(new_client);
- error0:
+exit:
return err;
}
static int lm75_detach_client(struct i2c_client *client)
{
- struct lm75_data *data = i2c_get_clientdata(client);
-
- i2c_deregister_entry(data->sysctl_id);
i2c_detach_client(client);
kfree(client);
return 0;
@@ -271,44 +268,16 @@
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
(jiffies < data->last_updated) || !data->valid) {
- pr_debug("Starting lm75 update\n");
+ dev_dbg(&client->dev, "Starting lm75 update\n");
- data->temp = lm75_read_value(client, LM75_REG_TEMP);
- data->temp_os = lm75_read_value(client, LM75_REG_TEMP_OS);
- data->temp_hyst =
- lm75_read_value(client, LM75_REG_TEMP_HYST);
+ data->temp_input = lm75_read_value(client, LM75_REG_TEMP);
+ data->temp_max = lm75_read_value(client, LM75_REG_TEMP_OS);
+ data->temp_hyst = lm75_read_value(client, LM75_REG_TEMP_HYST);
data->last_updated = jiffies;
data->valid = 1;
}
up(&data->update_lock);
-}
-
-
-static void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
- int *nrels_mag, long *results)
-{
- struct lm75_data *data = i2c_get_clientdata(client);
- if (operation == SENSORS_PROC_REAL_INFO)
- *nrels_mag = 1;
- else if (operation == SENSORS_PROC_REAL_READ) {
- lm75_update_client(client);
- results[0] = TEMP_FROM_REG(data->temp_os);
- results[1] = TEMP_FROM_REG(data->temp_hyst);
- results[2] = TEMP_FROM_REG(data->temp);
- *nrels_mag = 3;
- } else if (operation == SENSORS_PROC_REAL_WRITE) {
- if (*nrels_mag >= 1) {
- data->temp_os = TEMP_TO_REG(results[0]);
- lm75_write_value(client, LM75_REG_TEMP_OS,
- data->temp_os);
- }
- if (*nrels_mag >= 2) {
- data->temp_hyst = TEMP_TO_REG(results[1]);
- lm75_write_value(client, LM75_REG_TEMP_HYST,
- data->temp_hyst);
- }
- }
}
static int __init sensors_lm75_init(void)
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.8, 2003/04/02 11:45:21-08:00, greg@kroah.com
i2c: remove proc and sysctl code from i2c-proc as it is no longer used.
drivers/i2c/i2c-proc.c | 546 -----------------------------------------------
include/linux/i2c-proc.h | 40 ---
2 files changed, 586 deletions(-)
diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
--- a/drivers/i2c/i2c-proc.c Wed Apr 2 16:01:04 2003
+++ b/drivers/i2c/i2c-proc.c Wed Apr 2 16:01:04 2003
@@ -37,539 +37,6 @@
#include <linux/i2c-proc.h>
#include <asm/uaccess.h>
-static int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
- long *results, int magnitude);
-static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize,
- long *results, int magnitude);
-static int i2c_proc_chips(ctl_table * ctl, int write,
- struct file *filp, void *buffer,
- size_t * lenp);
-static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
- void *oldval, size_t * oldlenp,
- void *newval, size_t newlen,
- void **context);
-
-#define SENSORS_ENTRY_MAX 20
-static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX];
-
-static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX];
-
-static ctl_table i2c_proc_dev_sensors[] = {
- {SENSORS_CHIPS, "chips", NULL, 0, 0644, NULL, &i2c_proc_chips,
- &i2c_sysctl_chips},
- {0}
-};
-
-static ctl_table i2c_proc_dev[] = {
- {DEV_SENSORS, "sensors", NULL, 0, 0555, i2c_proc_dev_sensors},
- {0},
-};
-
-
-static ctl_table i2c_proc[] = {
- {CTL_DEV, "dev", NULL, 0, 0555, i2c_proc_dev},
- {0}
-};
-
-
-static struct ctl_table_header *i2c_proc_header;
-
-/* This returns a nice name for a new directory; for example lm78-isa-0310
- (for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for
- a LM75 chip on the third i2c bus at address 0x4e).
- name is allocated first. */
-static char *generate_name(struct i2c_client *client, const char *prefix)
-{
- struct i2c_adapter *adapter = client->adapter;
- int addr = client->addr;
- char name_buffer[50], *name;
-
- if (i2c_is_isa_adapter(adapter)) {
- sprintf(name_buffer, "%s-isa-%04x", prefix, addr);
- } else if (adapter->algo->smbus_xfer || adapter->algo->master_xfer) {
- int id = i2c_adapter_id(adapter);
- if (id < 0)
- return ERR_PTR(-ENOENT);
- sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr);
- } else { /* dummy adapter, generate prefix */
- int end, i;
-
- sprintf(name_buffer, "%s-", prefix);
- end = strlen(name_buffer);
-
- for (i = 0; i < 32; i++) {
- if (adapter->algo->name[i] == ' ')
- break;
- name_buffer[end++] = tolower(adapter->algo->name[i]);
- }
-
- name_buffer[end] = 0;
- sprintf(name_buffer + end, "-%04x", addr);
- }
-
- name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL);
- if (unlikely(!name))
- return ERR_PTR(-ENOMEM);
- strcpy(name, name_buffer);
- return name;
-}
-
-/* This rather complex function must be called when you want to add an entry
- to /proc/sys/dev/sensors/chips. It also creates a new directory within
- /proc/sys/dev/sensors/.
- ctl_template should be a template of the newly created directory. It is
- copied in memory. The extra2 field of each file is set to point to client.
- If any driver wants subdirectories within the newly created directory,
- this function must be updated! */
-int i2c_register_entry(struct i2c_client *client, const char *prefix,
- struct ctl_table *leaf)
-{
- struct { struct ctl_table root[2], dev[2], sensors[2]; } *tbl;
- struct ctl_table_header *hdr;
- struct ctl_table *tmp;
- const char *name;
- int id;
-
- name = generate_name(client, prefix);
- if (IS_ERR(name))
- return PTR_ERR(name);
-
- for (id = 0; id < SENSORS_ENTRY_MAX; id++) {
- if (!i2c_entries[id])
- goto free_slot;
- }
-
- goto out_free_name;
-
- free_slot:
- tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
- if (unlikely(!tbl))
- goto out_free_name;
- memset(tbl, 0, sizeof(*tbl));
-
- for (tmp = leaf; tmp->ctl_name; tmp++)
- tmp->extra2 = client;
-
- tbl->sensors->ctl_name = id+256;
- tbl->sensors->procname = name;
- tbl->sensors->mode = 0555;
- tbl->sensors->child = leaf;
-
- tbl->dev->ctl_name = DEV_SENSORS;
- tbl->dev->procname = "sensors";
- tbl->dev->mode = 0555;
- tbl->dev->child = tbl->sensors;
-
- tbl->root->ctl_name = CTL_DEV;
- tbl->root->procname = "dev";
- tbl->root->mode = 0555;
- tbl->root->child = tbl->dev;
-
- hdr = register_sysctl_table(tbl->root, 0);
- if (unlikely(!hdr))
- goto out_free_tbl;
-
- i2c_entries[id] = hdr;
- i2c_clients[id] = client;
-
- return (id + 256); /* XXX(hch) why?? */
-
- out_free_tbl:
- kfree(tbl);
- out_free_name:
- kfree(name);
- return -ENOMEM;
-}
-
-void i2c_deregister_entry(int id)
-{
- id -= 256;
-
- if (i2c_entries[id]) {
- struct ctl_table_header *hdr = i2c_entries[id];
- struct ctl_table *tbl = hdr->ctl_table;
-
- unregister_sysctl_table(hdr);
- kfree(tbl->child->child->procname);
- kfree(tbl); /* actually the whole anonymous struct */
- }
-
- i2c_entries[id] = NULL;
- i2c_clients[id] = NULL;
-}
-
-static int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp,
- void *buffer, size_t * lenp)
-{
- char BUF[SENSORS_PREFIX_MAX + 30];
- int buflen, curbufsize, i;
- struct ctl_table *client_tbl;
-
- if (write)
- return 0;
-
- /* If buffer is size 0, or we try to read when not at the start, we
- return nothing. Note that I think writing when not at the start
- does not work either, but anyway, this is straight from the kernel
- sources. */
- if (!*lenp || (filp->f_pos && !write)) {
- *lenp = 0;
- return 0;
- }
- curbufsize = 0;
- for (i = 0; i < SENSORS_ENTRY_MAX; i++)
- if (i2c_entries[i]) {
- client_tbl =
- i2c_entries[i]->ctl_table->child->child;
- buflen =
- sprintf(BUF, "%d\t%s\n", client_tbl->ctl_name,
- client_tbl->procname);
- if (buflen + curbufsize > *lenp)
- buflen = *lenp - curbufsize;
- if(copy_to_user(buffer, BUF, buflen))
- return -EFAULT;
- curbufsize += buflen;
- (char *) buffer += buflen;
- }
- *lenp = curbufsize;
- filp->f_pos += curbufsize;
- return 0;
-}
-
-static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
- void *oldval, size_t * oldlenp, void *newval,
- size_t newlen, void **context)
-{
- struct i2c_chips_data data;
- int i, oldlen, nrels, maxels,ret=0;
- struct ctl_table *client_tbl;
-
- if (oldval && oldlenp && !((ret = get_user(oldlen, oldlenp))) &&
- oldlen) {
- maxels = oldlen / sizeof(struct i2c_chips_data);
- nrels = 0;
- for (i = 0; (i < SENSORS_ENTRY_MAX) && (nrels < maxels);
- i++)
- if (i2c_entries[i]) {
- client_tbl =
- i2c_entries[i]->ctl_table->child->
- child;
- data.sysctl_id = client_tbl->ctl_name;
- strcpy(data.name, client_tbl->procname);
- if(copy_to_user(oldval, &data,
- sizeof(struct
- i2c_chips_data)))
- return -EFAULT;
- (char *) oldval +=
- sizeof(struct i2c_chips_data);
- nrels++;
- }
- oldlen = nrels * sizeof(struct i2c_chips_data);
- if(put_user(oldlen, oldlenp))
- return -EFAULT;
- }
- return ret;
-}
-
-
-/* This function reads or writes a 'real' value (encoded by the combination
- of an integer and a magnitude, the last is the power of ten the value
- should be divided with) to a /proc/sys directory. To use this function,
- you must (before registering the ctl_table) set the extra2 field to the
- client, and the extra1 field to a function of the form:
- void func(struct i2c_client *client, int operation, int ctl_name,
- int *nrels_mag, long *results)
- This function can be called for three values of operation. If operation
- equals SENSORS_PROC_REAL_INFO, the magnitude should be returned in
- nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should
- be read into results. nrels_mag should return the number of elements
- read; the maximum number is put in it on entry. Finally, if operation
- equals SENSORS_PROC_REAL_WRITE, the values in results should be
- written to the chip. nrels_mag contains on entry the number of elements
- found.
- In all cases, client points to the client we wish to interact with,
- and ctl_name is the SYSCTL id of the file we are accessing. */
-int i2c_proc_real(ctl_table * ctl, int write, struct file *filp,
- void *buffer, size_t * lenp)
-{
-#define MAX_RESULTS 32
- int mag, nrels = MAX_RESULTS;
- long results[MAX_RESULTS];
- i2c_real_callback callback = ctl->extra1;
- struct i2c_client *client = ctl->extra2;
- int res;
-
- /* If buffer is size 0, or we try to read when not at the start, we
- return nothing. Note that I think writing when not at the start
- does not work either, but anyway, this is straight from the kernel
- sources. */
- if (!*lenp || (filp->f_pos && !write)) {
- *lenp = 0;
- return 0;
- }
-
- /* Get the magnitude */
- callback(client, SENSORS_PROC_REAL_INFO, ctl->ctl_name, &mag,
- NULL);
-
- if (write) {
- /* Read the complete input into results, converting to longs */
- res = i2c_parse_reals(&nrels, buffer, *lenp, results, mag);
- if (res)
- return res;
-
- if (!nrels)
- return 0;
-
- /* Now feed this information back to the client */
- callback(client, SENSORS_PROC_REAL_WRITE, ctl->ctl_name,
- &nrels, results);
-
- filp->f_pos += *lenp;
- return 0;
- } else { /* read */
- /* Get the information from the client into results */
- callback(client, SENSORS_PROC_REAL_READ, ctl->ctl_name,
- &nrels, results);
-
- /* And write them to buffer, converting to reals */
- res = i2c_write_reals(nrels, buffer, lenp, results, mag);
- if (res)
- return res;
- filp->f_pos += *lenp;
- return 0;
- }
-}
-
-/* This function is equivalent to i2c_proc_real, only it interacts with
- the sysctl(2) syscall, and returns no reals, but integers */
-int i2c_sysctl_real(ctl_table * table, int *name, int nlen,
- void *oldval, size_t * oldlenp, void *newval,
- size_t newlen, void **context)
-{
- long results[MAX_RESULTS];
- int oldlen, nrels = MAX_RESULTS,ret=0;
- i2c_real_callback callback = table->extra1;
- struct i2c_client *client = table->extra2;
-
- /* Check if we need to output the old values */
- if (oldval && oldlenp && !((ret=get_user(oldlen, oldlenp))) && oldlen) {
- callback(client, SENSORS_PROC_REAL_READ, table->ctl_name,
- &nrels, results);
-
- /* Note the rounding factor! */
- if (nrels * sizeof(long) < oldlen)
- oldlen = nrels * sizeof(long);
- oldlen = (oldlen / sizeof(long)) * sizeof(long);
- if(copy_to_user(oldval, results, oldlen))
- return -EFAULT;
- if(put_user(oldlen, oldlenp))
- return -EFAULT;
- }
-
- if (newval && newlen) {
- /* Note the rounding factor! */
- newlen -= newlen % sizeof(long);
- nrels = newlen / sizeof(long);
- if(copy_from_user(results, newval, newlen))
- return -EFAULT;
-
- /* Get the new values back to the client */
- callback(client, SENSORS_PROC_REAL_WRITE, table->ctl_name,
- &nrels, results);
- }
- return ret;
-}
-
-
-/* nrels contains initially the maximum number of elements which can be
- put in results, and finally the number of elements actually put there.
- A magnitude of 1 will multiply everything with 10; etc.
- buffer, bufsize is the character buffer we read from and its length.
- results will finally contain the parsed integers.
-
- Buffer should contain several reals, separated by whitespace. A real
- has the following syntax:
- [ Minus ] Digit* [ Dot Digit* ]
- (everything between [] is optional; * means zero or more).
- When the next character is unparsable, everything is skipped until the
- next whitespace.
-
- WARNING! This is tricky code. I have tested it, but there may still be
- hidden bugs in it, even leading to crashes and things!
-*/
-static int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
- long *results, int magnitude)
-{
- int maxels, min, mag;
- long res,ret=0;
- char nextchar = 0;
-
- maxels = *nrels;
- *nrels = 0;
-
- while (bufsize && (*nrels < maxels)) {
-
- /* Skip spaces at the start */
- while (bufsize &&
- !((ret=get_user(nextchar, (char *) buffer))) &&
- isspace((int) nextchar)) {
- bufsize--;
- ((char *) buffer)++;
- }
-
- if (ret)
- return -EFAULT;
- /* Well, we may be done now */
- if (!bufsize)
- return 0;
-
- /* New defaults for our result */
- min = 0;
- res = 0;
- mag = magnitude;
-
- /* Check for a minus */
- if (!((ret=get_user(nextchar, (char *) buffer)))
- && (nextchar == '-')) {
- min = 1;
- bufsize--;
- ((char *) buffer)++;
- }
- if (ret)
- return -EFAULT;
-
- /* Digits before a decimal dot */
- while (bufsize &&
- !((ret=get_user(nextchar, (char *) buffer))) &&
- isdigit((int) nextchar)) {
- res = res * 10 + nextchar - '0';
- bufsize--;
- ((char *) buffer)++;
- }
- if (ret)
- return -EFAULT;
-
- /* If mag < 0, we must actually divide here! */
- while (mag < 0) {
- res = res / 10;
- mag++;
- }
-
- if (bufsize && (nextchar == '.')) {
- /* Skip the dot */
- bufsize--;
- ((char *) buffer)++;
-
- /* Read digits while they are significant */
- while (bufsize && (mag > 0) &&
- !((ret=get_user(nextchar, (char *) buffer))) &&
- isdigit((int) nextchar)) {
- res = res * 10 + nextchar - '0';
- mag--;
- bufsize--;
- ((char *) buffer)++;
- }
- if (ret)
- return -EFAULT;
- }
- /* If we are out of data, but mag > 0, we need to scale here */
- while (mag > 0) {
- res = res * 10;
- mag--;
- }
-
- /* Skip everything until we hit whitespace */
- while (bufsize &&
- !((ret=get_user(nextchar, (char *) buffer))) &&
- isspace((int) nextchar)) {
- bufsize--;
- ((char *) buffer)++;
- }
- if (ret)
- return -EFAULT;
-
- /* Put res in results */
- results[*nrels] = (min ? -1 : 1) * res;
- (*nrels)++;
- }
-
- /* Well, there may be more in the buffer, but we need no more data.
- Ignore anything that is left. */
- return 0;
-}
-
-static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize,
- long *results, int magnitude)
-{
-#define BUFLEN 20
- char BUF[BUFLEN + 1]; /* An individual representation should fit! */
- char printfstr[10];
- int nr = 0;
- int buflen, mag, times;
- int curbufsize = 0;
-
- while ((nr < nrels) && (curbufsize < *bufsize)) {
- mag = magnitude;
-
- if (nr != 0) {
- if(put_user(' ', (char *) buffer))
- return -EFAULT;
- curbufsize++;
- ((char *) buffer)++;
- }
-
- /* Fill BUF with the representation of the next string */
- if (mag <= 0) {
- buflen = sprintf(BUF, "%ld", results[nr]);
- if (buflen < 0) { /* Oops, a sprintf error! */
- *bufsize = 0;
- return -EINVAL;
- }
- while ((mag < 0) && (buflen < BUFLEN)) {
- BUF[buflen++] = '0';
- mag++;
- }
- BUF[buflen] = 0;
- } else {
- times = 1;
- for (times = 1; mag-- > 0; times *= 10);
- if (results[nr] < 0) {
- BUF[0] = '-';
- buflen = 1;
- } else
- buflen = 0;
- strcpy(printfstr, "%ld.%0Xld");
- printfstr[6] = magnitude + '0';
- buflen +=
- sprintf(BUF + buflen, printfstr,
- abs(results[nr]) / times,
- abs(results[nr]) % times);
- if (buflen < 0) { /* Oops, a sprintf error! */
- *bufsize = 0;
- return -EINVAL;
- }
- }
-
- /* Now copy it to the user-space buffer */
- if (buflen + curbufsize > *bufsize)
- buflen = *bufsize - curbufsize;
- if(copy_to_user(buffer, BUF, buflen))
- return -EFAULT;
- curbufsize += buflen;
- (char *) buffer += buflen;
-
- nr++;
- }
- if (curbufsize < *bufsize) {
- if(put_user('\n', (char *) buffer))
- return -EFAULT;
- curbufsize++;
- }
- *bufsize = curbufsize;
- return 0;
-}
-
/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
int i2c_detect(struct i2c_adapter *adapter,
@@ -703,26 +170,13 @@
static int __init i2c_proc_init(void)
{
- printk(KERN_INFO "i2c-proc.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
- if (!
- (i2c_proc_header =
- register_sysctl_table(i2c_proc, 0))) {
- printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n");
- return -EPERM;
- }
- i2c_proc_header->ctl_table->child->de->owner = THIS_MODULE;
return 0;
}
static void __exit i2c_proc_exit(void)
{
- unregister_sysctl_table(i2c_proc_header);
}
-EXPORT_SYMBOL(i2c_register_entry);
-EXPORT_SYMBOL(i2c_deregister_entry);
-EXPORT_SYMBOL(i2c_proc_real);
-EXPORT_SYMBOL(i2c_sysctl_real);
EXPORT_SYMBOL(i2c_detect);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
diff -Nru a/include/linux/i2c-proc.h b/include/linux/i2c-proc.h
--- a/include/linux/i2c-proc.h Wed Apr 2 16:01:04 2003
+++ b/include/linux/i2c-proc.h Wed Apr 2 16:01:04 2003
@@ -34,46 +34,6 @@
#define SENSORS_PROC_REAL_READ 2
#define SENSORS_PROC_REAL_WRITE 3
-/* These funcion reads or writes a 'real' value (encoded by the combination
- of an integer and a magnitude, the last is the power of ten the value
- should be divided with) to a /proc/sys directory. To use these functions,
- you must (before registering the ctl_table) set the extra2 field to the
- client, and the extra1 field to a function of the form:
- void func(struct i2c_client *client, int operation, int ctl_name,
- int *nrels_mag, long *results)
- This last function can be called for three values of operation. If
- operation equals SENSORS_PROC_REAL_INFO, the magnitude should be returned
- in nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should
- be read into results. nrels_mag should return the number of elements
- read; the maximum number is put in it on entry. Finally, if operation
- equals SENSORS_PROC_REAL_WRITE, the values in results should be
- written to the chip. nrels_mag contains on entry the number of elements
- found.
- In all cases, client points to the client we wish to interact with,
- and ctl_name is the SYSCTL id of the file we are accessing. */
-extern int i2c_sysctl_real(ctl_table * table, int *name, int nlen,
- void *oldval, size_t * oldlenp,
- void *newval, size_t newlen,
- void **context);
-extern int i2c_proc_real(ctl_table * ctl, int write, struct file *filp,
- void *buffer, size_t * lenp);
-
-
-
-/* These rather complex functions must be called when you want to add or
- delete an entry in /proc/sys/dev/sensors/chips (not yet implemented). It
- also creates a new directory within /proc/sys/dev/sensors/.
- ctl_template should be a template of the newly created directory. It is
- copied in memory. The extra2 field of each file is set to point to client.
- If any driver wants subdirectories within the newly created directory,
- these functions must be updated! */
-extern int i2c_register_entry(struct i2c_client *client,
- const char *prefix,
- ctl_table * ctl_template);
-
-extern void i2c_deregister_entry(int id);
-
-
/* A structure containing detect information.
Force variables overrule all other variables; they force a detection on
that place. If a specific chip is given, the module blindly assumes this
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:15 ` Greg KH
@ 2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1009, 2003/04/02 15:36:11-08:00, greg@kroah.com
i2c: fix up broken drivers/i2c/busses build due to I2C_PROC now being gone.
drivers/i2c/busses/Kconfig | 13 ++++++-------
1 files changed, 6 insertions(+), 7 deletions(-)
diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig Wed Apr 2 16:00:11 2003
+++ b/drivers/i2c/busses/Kconfig Wed Apr 2 16:00:11 2003
@@ -1,13 +1,12 @@
#
# Sensor device configuration
-# All depend on EXPERIMENTAL, I2C and I2C_PROC.
#
menu "I2C Hardware Sensors Mainboard support"
config I2C_ALI15X3
tristate " ALI 15x3"
- depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+ depends on I2C && PCI && EXPERIMENTAL
help
If you say yes to this option, support will be included for the
Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
@@ -21,7 +20,7 @@
config I2C_AMD756
tristate " AMD 756/766"
- depends on I2C && I2C_PROC
+ depends on I2C && EXPERIMENTAL
help
If you say yes to this option, support will be included for the AMD
756/766/768 mainboard I2C interfaces.
@@ -38,7 +37,7 @@
config I2C_AMD8111
tristate " AMD 8111"
- depends on I2C && I2C_PROC
+ depends on I2C && EXPERIMENTAL
help
If you say yes to this option, support will be included for the AMD
8111 mainboard I2C interfaces.
@@ -55,7 +54,7 @@
config I2C_I801
tristate " Intel 801"
- depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+ depends on I2C && PCI && EXPERIMENTAL
help
If you say yes to this option, support will be included for the Intel
801 family of mainboard I2C interfaces. Specifically, the following
@@ -78,7 +77,7 @@
config I2C_ISA
tristate " ISA Bus support"
- depends on I2C && I2C_PROC && ISA && EXPERIMENTAL
+ depends on I2C && ISA && EXPERIMENTAL
help
If you say yes to this option, support will be included for i2c
interfaces that are on the ISA bus.
@@ -96,7 +95,7 @@
config I2C_PIIX4
tristate " Intel PIIX4"
- depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+ depends on I2C && PCI && EXPERIMENTAL
help
If you say yes to this option, support will be included for the Intel
PIIX4 family of mainboard I2C interfaces. Specifically, the following
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:15 ` Greg KH
@ 2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.13, 2003/04/02 14:18:09-08:00, greg@kroah.com
i2c: clean up previous w83781d patch due to changes I made to i2c core and build.
drivers/i2c/chips/Kconfig | 30 +++++++++++++++---------------
drivers/i2c/chips/Makefile | 1 +
drivers/i2c/chips/w83781d.c | 8 +++-----
include/linux/i2c-vid.h | 4 ++--
4 files changed, 21 insertions(+), 22 deletions(-)
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig Wed Apr 2 16:00:19 2003
+++ b/drivers/i2c/chips/Kconfig Wed Apr 2 16:00:19 2003
@@ -37,20 +37,6 @@
in the lm_sensors package, which you can download at
http://www.lm-sensors.nu
-config SENSORS_W83781D
- tristate " Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
- depends on I2C && I2C_PROC
- help
- If you say yes here you get support for the Winbond W8378x series
- of sensor chips: the W83781D, W83782D, W83783S and W83682HF,
- and the similar Asus AS99127F. This
- can also be built as a module which can be inserted and removed
- while the kernel is running.
-
- You will also need the latest user-space utilties: you can find them
- in the lm_sensors package, which you can download at
- http://www.lm-sensors.nu
-
config SENSORS_VIA686A
tristate " VIA686A"
depends on I2C && EXPERIMENTAL
@@ -64,9 +50,23 @@
in the lm_sensors package, which you can download at
http://www.lm-sensors.nu
+config SENSORS_W83781D
+ tristate " Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Winbond W8378x series
+ of sensor chips: the W83781D, W83782D, W83783S and W83682HF,
+ and the similar Asus AS99127F. This
+ can also be built as a module which can be inserted and removed
+ while the kernel is running.
+
+ You will also need the latest user-space utilties: you can find them
+ in the lm_sensors package, which you can download at
+ http://www.lm-sensors.nu
+
config I2C_SENSOR
tristate
- depends on SENSORS_ADM1021 || SENSORS_LM75 || SENSORS_VIA686A
+ depends on SENSORS_ADM1021 || SENSORS_LM75 || SENSORS_VIA686A || SENSORS_W83781D
default m
endmenu
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile Wed Apr 2 16:00:19 2003
+++ b/drivers/i2c/chips/Makefile Wed Apr 2 16:00:19 2003
@@ -5,3 +5,4 @@
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
+obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c Wed Apr 2 16:00:19 2003
+++ b/drivers/i2c/chips/w83781d.c Wed Apr 2 16:00:19 2003
@@ -38,7 +38,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/i2c-proc.h>
+#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
#include <asm/io.h>
@@ -332,8 +332,7 @@
};
static int w83781d_attach_adapter(struct i2c_adapter *adapter);
-static int w83781d_detect(struct i2c_adapter *adapter, int address,
- unsigned short flags, int kind);
+static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
static int w83781d_detach_client(struct i2c_client *client);
static int w83781d_read_value(struct i2c_client *client, u16 register);
@@ -1031,8 +1030,7 @@
}
static int
-w83781d_detect(struct i2c_adapter *adapter, int address,
- unsigned short flags, int kind)
+w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i = 0, val1 = 0, val2, id;
struct i2c_client *new_client;
diff -Nru a/include/linux/i2c-vid.h b/include/linux/i2c-vid.h
--- a/include/linux/i2c-vid.h Wed Apr 2 16:00:19 2003
+++ b/include/linux/i2c-vid.h Wed Apr 2 16:00:19 2003
@@ -1,6 +1,6 @@
/*
- vrm.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
+ i2c-vid.h - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
With assistance from Trent Piepho <xyzzy@speakeasy.org>
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:15 ` Greg KH
@ 2003-04-03 0:15 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1010, 2003/04/02 15:39:28-08:00, greg@kroah.com
i2c: remove old proc documentation and add sysfs file documentation
Documentation/i2c/proc-interface | 53 -----------
Documentation/i2c/sysfs-interface | 177 ++++++++++++++++++++++++++++++++++++++
2 files changed, 177 insertions(+), 53 deletions(-)
diff -Nru a/Documentation/i2c/proc-interface b/Documentation/i2c/proc-interface
--- a/Documentation/i2c/proc-interface Wed Apr 2 16:00:02 2003
+++ /dev/null Wed Dec 31 16:00:00 1969
@@ -1,53 +0,0 @@
-i2c-core is the core i2c module (surprise!) which offers general routines on
-which other modules build. You will find that all i2c-related modules depend
-on this module, so it will (need to) be loaded whenever another i2c-related
-module is loaded. Seen from the outside, the most interesting is the /proc
-interface. Note that there is no corresponding sysctl interface!
-
-/proc/bus/i2c
-=============
-
-Whenever i2c-core is loaded, you will find a file /proc/bus/i2c, which lists
-all currently registered I2C adapters. Each line contains exactly one
-I2C adapter. Each line has the following format: "i2c-%d\t%9s\t%-32s't%-32s\n",
-which works out to four columns separated by tabs. Note that the file
-will be empty, if no adapters are registered at all.
-
-Adapters are numbered from 0 upwards. The first column contains the number
-of the adapter, for example "i2c-4" for adapter 4. The name listed is also
-the name of the /proc file which lists all devices attached to it, and
-of the /dev file which corresponds to this adapter.
-
-The second column documents what kind of adapter this is. Some adapters
-understand the full I2C protocol, others only a subset called SMBus,
-and yet others are some kind of pseudo-adapters that do not understand
-i2c at all. Possible values in here are "i2c", "smbus", "i2c/smbus"
-and "dummy". Because the SMBus protocol can be fully emulated by i2c
-adapters, if you see "i2c" here, SMBus is supported too. There may
-be some future adapters which support both specific SMBus commands and
-general I2C, and they will display "i2c/smbus".
-
-The third and fourth column are respectively the algorithm and adapter
-name of this adapter. Each adapter is associated with an algorithm,
-and several adapters can share the same algorithm. The combination of
-algorithm name and adapter name should be unique for an adapter, but
-you can't really count on that yet.
-
-
-/proc/bus/i2c-*
-===============
-
-Each registered adapter gets its own file in /proc/bus/, which lists
-the devices registered to the adapter. Each line in such a file contains
-one registered device. Each line has the following format:
-"%02x\t%-32s\t%-32s\n", which works out to three columns separated by
-tabs. Note that this file can be empty, if no devices are found on
-the adapter.
-
-The first column contains the (hexadecimal) address of the client. As
-only 7-bit addresses are supported at this moment, two digits are
-enough.
-
-The second and third column are respectively the client name and the
-driver name of this client. Each client is associated with a driver,
-and several clients can share the same driver.
diff -Nru a/Documentation/i2c/sysfs-interface b/Documentation/i2c/sysfs-interface
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/Documentation/i2c/sysfs-interface Wed Apr 2 16:00:02 2003
@@ -0,0 +1,177 @@
+Naming and data format standards for sysfs files
+------------------------------------------------
+
+The libsensors library offers an interface to the raw sensors data
+through the sysfs interface. See libsensors documentation and source for
+more further information.
+
+An alternative method that some programs use is to access the sysfs
+files directly. This document briefly describes the standards that the
+drivers follow, so that an application program can scan for entries and
+access this data in a simple and consistent way.
+
+If you are developing a userspace application please send us feedback on
+this standard.
+
+Note that motherboards vary widely in the connections to sensor chips.
+There is no standard that ensures, for example, that the second
+temperature sensor is connected to the CPU, or that the second fan is on
+the CPU. Therefore, programs must provide a facility for the user to
+label or bind /proc entries for display. Sensor chips often have unused
+inputs that should be ignored by user programs.
+
+Each chip gets its own directory in the sysfs /sys/devices tree. To
+find all sensor chips, it is easier to follow the symlinks from
+/sys/i2c/devices/
+
+All sysfs values are fixed point numbers. To get the true value of some
+of the values, you should divide by the specified value.
+
+There is only one value per file, unlike the older /proc specification.
+
+Alarms are direct indications read from the chips. The drivers do NOT
+make comparisons of readings to thresholds. This allows violations
+between readings to be caught and alarmed. The exact definition of an
+alarm (for example, whether a threshold must be met or must be exceeded
+to cause an alarm) is chip-dependent.
+
+
+-------------------------------------------------------------------------
+
+sysfs entries are as follows:
+
+
+Entry Function
+----- --------
+alarms Alarm bitmask.
+ Read only.
+ Integer representation of one to four bytes.
+ A '1' bit means an alarm.
+ Chips should be programmed for 'comparator' mode so that
+ the alarm will 'come back' after you read the register
+ if it is still valid.
+ Generally a direct representation of a chip's internal
+ alarm registers; there is no standard for the position
+ of individual bits.
+ Bits are defined in kernel/include/sensors.h.
+
+beep_enable Beep/interrupt enable
+ 0 to disable.
+ 1 to enable.
+ Read/Write
+
+beep_mask Bitmask for beep.
+ Same format as 'alarms' with the same bit locations.
+ Read only.
+
+curr_max[1-n] Current max value
+ Fixed point XXXXX, divide by 1000 to get Amps.
+ Read/Write.
+
+curr_min[1-n] Current min or hysteresis value.
+ Preferably a hysteresis value, reported as a absolute
+ current, NOT a delta from the max value.
+ Fixed point XXXXX, divide by 1000 to get Amps.
+ Read/Write.
+
+curr_input[1-n] Current input value
+ Fixed point XXXXX, divide by 1000 to get Amps.
+ Read only.
+
+fan_min[1-3] Fan minimum value
+ Integer value indicating RPM
+ Read/Write.
+
+fan_input[1-3] Fan input value.
+ Integer value indicating RPM
+ Read only.
+
+fan_div[1-3] Fan divisor.
+ Integers in powers of two (1,2,4,8,16,32,64,128).
+ Some chips only support values 1,2,4,8.
+ See doc/fan-divisors for details.
+
+in_min[0-8] Voltage min value.
+ Fixed point value in form XXXX. Divide by 1000 to get
+ Volts.
+ Read/Write
+
+in_max[0-8] Voltage max value.
+ Fixed point value in form XXXX. Divide by 1000 to get
+ Volts.
+ Read/Write
+
+in_input[0-8] Voltage input value.
+ Fixed point value in form XXXX. Divide by 1000 to get
+ Volts.
+ Read only
+ Actual voltage depends on the scaling resistors on the
+ motherboard, as recommended in the chip datasheet.
+ This varies by chip and by motherboard.
+ Because of this variation, values are generally NOT scaled
+ by the chip driver, and must be done by the application.
+ However, some drivers (notably lm87 and via686a)
+ do scale, with various degrees of success.
+ These drivers will output the actual voltage.
+ First two values are read/write and third is read only.
+ Typical usage:
+ in_*0 CPU #1 voltage (not scaled)
+ in_*1 CPU #1 voltage (not scaled)
+ in_*2 3.3V nominal (not scaled)
+ in_*3 5.0V nominal (scaled)
+ in_*4 12.0V nominal (scaled)
+ in_*5 -12.0V nominal (scaled)
+ in_*6 -5.0V nominal (scaled)
+ in_*7 varies
+ in_*8 varies
+
+pwm[1-3] Pulse width modulation fan control.
+ Integer 0 - 255
+ Read/Write
+ 255 is max or 100%.
+ Corresponds to the fans 1-3.
+
+pwm_enable[1-3] pwm enable
+ not always present even if pwm* is.
+ 0 to turn off
+ 1 to turn on
+ Read/Write
+
+sensor[1-3] Sensor type selection.
+ Integers 1,2,3, or thermistor Beta value (3435)
+ Read/Write.
+
+temp_max[1-3] Temperature max value.
+ Fixed point value in form XXXXX and should be divided by
+ 1000 to get degrees Celsius.
+ Read/Write value.
+
+temp_min[1-3] Temperature min or hysteresis value.
+ Fixed point value in form XXXXX and should be divided by
+ 1000 to get degrees Celsius. This is preferably a
+ hysteresis value, reported as a absolute temperature,
+ NOT a delta from the max value.
+ Read/Write value.
+
+temp_input[1-3] Temperature input value.
+ Read only value.
+
+ If there are multiple temperature sensors, temp_*1 is
+ generally the sensor inside the chip itself, generally
+ reported as "motherboard temperature". temp_*2 and
+ temp_*3 are generally sensors external to the chip
+ itself, for example the thermal diode inside the CPU or
+ a thermistor nearby.
+
+vid CPU core voltage.
+ Read only.
+ Fixed point value in form XXXX corresponding to CPU core
+ voltage as told to the sensor chip. Divide by 1000 to
+ get Volts. Not always correct.
+
+vrm Voltage Regulator Module version number.
+ Read only.
+ Two digit number (XX), first is major version, second is
+ minor version.
+ Affects the way the driver calculates the core voltage from
+ the vid pins. See doc/vid for details.
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2003-04-03 0:15 ` Greg KH
@ 2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-04-03 0:15 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.12, 2003/04/02 14:07:40-08:00, azarah@gentoo.org
[PATCH] i2c: w83781d i2c driver updated for 2.5.66-bk4 (with sysfs support, empty tree)
This should have a working w83781d driver updated for 2.5.66-bk4.
Currently sysfs support is working, and are according to the spec
(sensors-sysfs) in the 'lm sensors sysfs file structure' thread.
Thus I used 'temp_input[1-3]', as there was not final decision
on having them temp_input[0-2] as well, for example.
drivers/i2c/chips/Kconfig | 14
drivers/i2c/chips/w83781d.c | 1884 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/i2c-vid.h | 62 +
3 files changed, 1960 insertions(+)
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig Wed Apr 2 16:00:28 2003
+++ b/drivers/i2c/chips/Kconfig Wed Apr 2 16:00:28 2003
@@ -36,6 +36,20 @@
You will also need the latest user-space utilties: you can find them
in the lm_sensors package, which you can download at
http://www.lm-sensors.nu
+
+config SENSORS_W83781D
+ tristate " Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
+ depends on I2C && I2C_PROC
+ help
+ If you say yes here you get support for the Winbond W8378x series
+ of sensor chips: the W83781D, W83782D, W83783S and W83682HF,
+ and the similar Asus AS99127F. This
+ can also be built as a module which can be inserted and removed
+ while the kernel is running.
+
+ You will also need the latest user-space utilties: you can find them
+ in the lm_sensors package, which you can download at
+ http://www.lm-sensors.nu
config SENSORS_VIA686A
tristate " VIA686A"
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/chips/w83781d.c Wed Apr 2 16:00:28 2003
@@ -0,0 +1,1884 @@
+/*
+ w83781d.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ and Mark Studebaker <mdsxyz123@yahoo.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ Supports following chips:
+
+ Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ as99127f 7 3 1? 3 0x30 0x12c3 yes no
+ asb100 "bach" (type_name = as99127f) 0x30 0x0694 yes no
+ w83781d 7 3 0 3 0x10 0x5ca3 yes yes
+ w83627hf 9 3 2 3 0x20 0x5ca3 yes yes(LPC)
+ w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes
+ w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no
+ w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC)
+
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-proc.h>
+#include <linux/i2c-vid.h>
+#include <asm/io.h>
+
+/* RT Table support #defined so we can take it out if it gets bothersome */
+#define W83781D_RT 1
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { SENSORS_I2C_END };
+static unsigned short normal_i2c_range[] = { 0x20, 0x2f, SENSORS_I2C_END };
+static unsigned int normal_isa[] = { 0x0290, SENSORS_ISA_END };
+static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_6(w83781d, w83782d, w83783s, w83627hf, as99127f, w83697hf);
+SENSORS_MODULE_PARM(force_subclients, "List of subclient addresses: "
+ "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int init = 1;
+MODULE_PARM(init, "i");
+MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
+
+/* Constants specified below */
+
+/* Length of ISA address segment */
+#define W83781D_EXTENT 8
+
+/* Where are the ISA address/data registers relative to the base address */
+#define W83781D_ADDR_REG_OFFSET 5
+#define W83781D_DATA_REG_OFFSET 6
+
+/* The W83781D registers */
+/* The W83782D registers for nr=7,8 are in bank 5 */
+#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
+ (0x554 + (((nr) - 7) * 2)))
+#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
+ (0x555 + (((nr) - 7) * 2)))
+#define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
+ (0x550 + (nr) - 7))
+
+#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
+#define W83781D_REG_FAN(nr) (0x27 + (nr))
+
+#define W83781D_REG_BANK 0x4E
+#define W83781D_REG_TEMP2_CONFIG 0x152
+#define W83781D_REG_TEMP3_CONFIG 0x252
+#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \
+ ((nr == 2) ? (0x0150) : \
+ (0x27)))
+#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \
+ ((nr == 2) ? (0x153) : \
+ (0x3A)))
+#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \
+ ((nr == 2) ? (0x155) : \
+ (0x39)))
+
+#define W83781D_REG_CONFIG 0x40
+#define W83781D_REG_ALARM1 0x41
+#define W83781D_REG_ALARM2 0x42
+#define W83781D_REG_ALARM3 0x450 /* not on W83781D */
+
+#define W83781D_REG_IRQ 0x4C
+#define W83781D_REG_BEEP_CONFIG 0x4D
+#define W83781D_REG_BEEP_INTS1 0x56
+#define W83781D_REG_BEEP_INTS2 0x57
+#define W83781D_REG_BEEP_INTS3 0x453 /* not on W83781D */
+
+#define W83781D_REG_VID_FANDIV 0x47
+
+#define W83781D_REG_CHIPID 0x49
+#define W83781D_REG_WCHIPID 0x58
+#define W83781D_REG_CHIPMAN 0x4F
+#define W83781D_REG_PIN 0x4B
+
+/* 782D/783S only */
+#define W83781D_REG_VBAT 0x5D
+
+/* PWM 782D (1-4) and 783S (1-2) only */
+#define W83781D_REG_PWM1 0x5B /* 782d and 783s/627hf datasheets disagree */
+ /* on which is which; */
+#define W83781D_REG_PWM2 0x5A /* We follow the 782d convention here, */
+ /* However 782d is probably wrong. */
+#define W83781D_REG_PWM3 0x5E
+#define W83781D_REG_PWM4 0x5F
+#define W83781D_REG_PWMCLK12 0x5C
+#define W83781D_REG_PWMCLK34 0x45C
+static const u8 regpwm[] = { W83781D_REG_PWM1, W83781D_REG_PWM2,
+ W83781D_REG_PWM3, W83781D_REG_PWM4
+};
+
+#define W83781D_REG_PWM(nr) (regpwm[(nr) - 1])
+
+#define W83781D_REG_I2C_ADDR 0x48
+#define W83781D_REG_I2C_SUBADDR 0x4A
+
+/* The following are undocumented in the data sheets however we
+ received the information in an email from Winbond tech support */
+/* Sensor selection - not on 781d */
+#define W83781D_REG_SCFG1 0x5D
+static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
+
+#define W83781D_REG_SCFG2 0x59
+static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
+
+#define W83781D_DEFAULT_BETA 3435
+
+/* RT Table registers */
+#define W83781D_REG_RT_IDX 0x50
+#define W83781D_REG_RT_VAL 0x51
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+ variants. Note that you should be a bit careful with which arguments
+ these macros are called: arguments may be evaluated more than once.
+ Fixing this is just not worth it. */
+#define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
+#define IN_FROM_REG(val) (((val) * 16) / 10)
+
+static inline u8
+FAN_TO_REG(long rpm, int div)
+{
+ if (rpm == 0)
+ return 255;
+ rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+ return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+#define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \
+ ((val) == 255 ? 0 : \
+ 1350000 / ((val) * (div))))
+
+#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val / 10) < 0 ? (((val / 10) - 5) / 10) : \
+ ((val / 10) + 5) / 10), 0, 255))
+#define TEMP_FROM_REG(val) ((((val ) > 0x80 ? (val) - 0x100 : (val)) * 10) * 10)
+
+#define TEMP_ADD_TO_REG(val) (SENSORS_LIMIT(((((val / 10) + 2) / 5) << 7),\
+ 0, 0xffff))
+#define TEMP_ADD_FROM_REG(val) ((((val) >> 7) * 5) * 10)
+
+#define AS99127_TEMP_ADD_TO_REG(val) (SENSORS_LIMIT((((((val / 10) + 2)*4)/10) \
+ << 7), 0, 0xffff))
+#define AS99127_TEMP_ADD_FROM_REG(val) (((((val) >> 7) * 10) / 4) * 10)
+
+#define ALARMS_FROM_REG(val) (val)
+#define PWM_FROM_REG(val) (val)
+#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
+#define BEEP_MASK_FROM_REG(val) (val)
+#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff)
+
+#define BEEP_ENABLE_TO_REG(val) ((val) ? 1 : 0)
+#define BEEP_ENABLE_FROM_REG(val) ((val) ? 1 : 0)
+
+#define DIV_FROM_REG(val) (1 << (val))
+
+static inline u8
+DIV_TO_REG(long val, enum chips type)
+{
+ int i;
+ val = SENSORS_LIMIT(val, 1,
+ ((type == w83781d
+ || type == as99127f) ? 8 : 128)) >> 1;
+ for (i = 0; i < 6; i++) {
+ if (val == 0)
+ break;
+ val >>= 1;
+ }
+ return ((u8) i);
+}
+
+/* Initial limits */
+#define W83781D_INIT_IN_0 (vid == 3500 ? 280 : vid / 10)
+#define W83781D_INIT_IN_1 (vid == 3500 ? 280 : vid / 10)
+#define W83781D_INIT_IN_2 330
+#define W83781D_INIT_IN_3 (((500) * 100) / 168)
+#define W83781D_INIT_IN_4 (((1200) * 10) / 38)
+#define W83781D_INIT_IN_5 (((-1200) * -604) / 2100)
+#define W83781D_INIT_IN_6 (((-500) * -604) / 909)
+#define W83781D_INIT_IN_7 (((500) * 100) / 168)
+#define W83781D_INIT_IN_8 300
+/* Initial limits for 782d/783s negative voltages */
+/* Note level shift. Change min/max below if you change these. */
+#define W83782D_INIT_IN_5 ((((-1200) + 1491) * 100)/514)
+#define W83782D_INIT_IN_6 ((( (-500) + 771) * 100)/314)
+
+#define W83781D_INIT_IN_PERCENTAGE 10
+#define W83781D_INIT_IN_MIN(val) (val - val * W83781D_INIT_IN_PERCENTAGE / 100)
+#define W83781D_INIT_IN_MAX(val) (val + val * W83781D_INIT_IN_PERCENTAGE / 100)
+
+#define W83781D_INIT_IN_MIN_0 W83781D_INIT_IN_MIN(W83781D_INIT_IN_0)
+#define W83781D_INIT_IN_MAX_0 W83781D_INIT_IN_MAX(W83781D_INIT_IN_0)
+#define W83781D_INIT_IN_MIN_1 W83781D_INIT_IN_MIN(W83781D_INIT_IN_1)
+#define W83781D_INIT_IN_MAX_1 W83781D_INIT_IN_MAX(W83781D_INIT_IN_1)
+#define W83781D_INIT_IN_MIN_2 W83781D_INIT_IN_MIN(W83781D_INIT_IN_2)
+#define W83781D_INIT_IN_MAX_2 W83781D_INIT_IN_MAX(W83781D_INIT_IN_2)
+#define W83781D_INIT_IN_MIN_3 W83781D_INIT_IN_MIN(W83781D_INIT_IN_3)
+#define W83781D_INIT_IN_MAX_3 W83781D_INIT_IN_MAX(W83781D_INIT_IN_3)
+#define W83781D_INIT_IN_MIN_4 W83781D_INIT_IN_MIN(W83781D_INIT_IN_4)
+#define W83781D_INIT_IN_MAX_4 W83781D_INIT_IN_MAX(W83781D_INIT_IN_4)
+#define W83781D_INIT_IN_MIN_5 W83781D_INIT_IN_MIN(W83781D_INIT_IN_5)
+#define W83781D_INIT_IN_MAX_5 W83781D_INIT_IN_MAX(W83781D_INIT_IN_5)
+#define W83781D_INIT_IN_MIN_6 W83781D_INIT_IN_MIN(W83781D_INIT_IN_6)
+#define W83781D_INIT_IN_MAX_6 W83781D_INIT_IN_MAX(W83781D_INIT_IN_6)
+#define W83781D_INIT_IN_MIN_7 W83781D_INIT_IN_MIN(W83781D_INIT_IN_7)
+#define W83781D_INIT_IN_MAX_7 W83781D_INIT_IN_MAX(W83781D_INIT_IN_7)
+#define W83781D_INIT_IN_MIN_8 W83781D_INIT_IN_MIN(W83781D_INIT_IN_8)
+#define W83781D_INIT_IN_MAX_8 W83781D_INIT_IN_MAX(W83781D_INIT_IN_8)
+
+/* Initial limits for 782d/783s negative voltages */
+/* These aren't direct multiples because of level shift */
+/* Beware going negative - check */
+#define W83782D_INIT_IN_MIN_5_TMP \
+ (((-1200 * (100 + W83781D_INIT_IN_PERCENTAGE)) + (1491 * 100))/514)
+#define W83782D_INIT_IN_MIN_5 \
+ ((W83782D_INIT_IN_MIN_5_TMP > 0) ? W83782D_INIT_IN_MIN_5_TMP : 0)
+#define W83782D_INIT_IN_MAX_5 \
+ (((-1200 * (100 - W83781D_INIT_IN_PERCENTAGE)) + (1491 * 100))/514)
+#define W83782D_INIT_IN_MIN_6_TMP \
+ ((( -500 * (100 + W83781D_INIT_IN_PERCENTAGE)) + (771 * 100))/314)
+#define W83782D_INIT_IN_MIN_6 \
+ ((W83782D_INIT_IN_MIN_6_TMP > 0) ? W83782D_INIT_IN_MIN_6_TMP : 0)
+#define W83782D_INIT_IN_MAX_6 \
+ ((( -500 * (100 - W83781D_INIT_IN_PERCENTAGE)) + (771 * 100))/314)
+
+#define W83781D_INIT_FAN_MIN_1 3000
+#define W83781D_INIT_FAN_MIN_2 3000
+#define W83781D_INIT_FAN_MIN_3 3000
+
+/* temp = value / 100 */
+#define W83781D_INIT_TEMP_OVER 6000
+#define W83781D_INIT_TEMP_HYST 12700 /* must be 127 for ALARM to work */
+#define W83781D_INIT_TEMP2_OVER 6000
+#define W83781D_INIT_TEMP2_HYST 5000
+#define W83781D_INIT_TEMP3_OVER 6000
+#define W83781D_INIT_TEMP3_HYST 5000
+
+/* There are some complications in a module like this. First off, W83781D chips
+ may be both present on the SMBus and the ISA bus, and we have to handle
+ those cases separately at some places. Second, there might be several
+ W83781D chips available (well, actually, that is probably never done; but
+ it is a clean illustration of how to handle a case like that). Finally,
+ a specific chip may be attached to *both* ISA and SMBus, and we would
+ not like to detect it double. Fortunately, in the case of the W83781D at
+ least, a register tells us what SMBus address we are on, so that helps
+ a bit - except if there could be more than one SMBus. Groan. No solution
+ for this yet. */
+
+/* This module may seem overly long and complicated. In fact, it is not so
+ bad. Quite a lot of bookkeeping is done. A real driver can often cut
+ some corners. */
+
+/* For each registered W83781D, we need to keep some data in memory. That
+ data is pointed to by w83781d_list[NR]->data. The structure itself is
+ dynamically allocated, at the same time when a new w83781d client is
+ allocated. */
+struct w83781d_data {
+ struct semaphore lock;
+ enum chips type;
+
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+
+ struct i2c_client *lm75; /* for secondary I2C addresses */
+ /* pointer to array of 2 subclients */
+
+ u8 in[9]; /* Register value - 8 & 9 for 782D only */
+ u8 in_max[9]; /* Register value - 8 & 9 for 782D only */
+ u8 in_min[9]; /* Register value - 8 & 9 for 782D only */
+ u8 fan[3]; /* Register value */
+ u8 fan_min[3]; /* Register value */
+ u8 temp;
+ u8 temp_min; /* Register value */
+ u8 temp_max; /* Register value */
+ u16 temp_add[2]; /* Register value */
+ u16 temp_max_add[2]; /* Register value */
+ u16 temp_min_add[2]; /* Register value */
+ u8 fan_div[3]; /* Register encoding, shifted right */
+ u8 vid; /* Register encoding, combined */
+ u32 alarms; /* Register encoding, combined */
+ u32 beep_mask; /* Register encoding, combined */
+ u8 beep_enable; /* Boolean */
+ u8 pwm[4]; /* Register value */
+ u8 pwmenable[4]; /* Boolean */
+ u16 sens[3]; /* 782D/783S only.
+ 1 = pentium diode; 2 = 3904 diode;
+ 3000-5000 = thermistor beta.
+ Default = 3435.
+ Other Betas unimplemented */
+#ifdef W83781D_RT
+ u8 rt[3][32]; /* Register value */
+#endif
+ u8 vrm;
+};
+
+static int w83781d_attach_adapter(struct i2c_adapter *adapter);
+static int w83781d_detect(struct i2c_adapter *adapter, int address,
+ unsigned short flags, int kind);
+static int w83781d_detach_client(struct i2c_client *client);
+
+static int w83781d_read_value(struct i2c_client *client, u16 register);
+static int w83781d_write_value(struct i2c_client *client, u16 register,
+ u16 value);
+static void w83781d_update_client(struct i2c_client *client);
+static void w83781d_init_client(struct i2c_client *client);
+
+static inline u16 swap_bytes(u16 val)
+{
+ return (val >> 8) | (val << 8);
+}
+
+static struct i2c_driver w83781d_driver = {
+ .owner = THIS_MODULE,
+ .name = "w83781d",
+ .id = I2C_DRIVERID_W83781D,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = w83781d_attach_adapter,
+ .detach_client = w83781d_detach_client,
+};
+
+/* following are the sysfs callback functions */
+#define show_in_reg(reg) \
+static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83781d_data *data = i2c_get_clientdata(client); \
+ \
+ w83781d_update_client(client); \
+ \
+ return sprintf(buf,"%ld\n", (long)IN_FROM_REG(data->reg[nr])); \
+}
+show_in_reg(in);
+show_in_reg(in_min);
+show_in_reg(in_max);
+
+#define store_in_reg(REG, reg) \
+static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83781d_data *data = i2c_get_clientdata(client); \
+ u32 val; \
+ \
+ val = simple_strtoul(buf, NULL, 10); \
+ data->in_##reg[nr] = IN_TO_REG(val); \
+ w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
+ \
+ return count; \
+}
+store_in_reg(MIN, min);
+store_in_reg(MAX, max);
+
+#define sysfs_in_offset(offset) \
+static ssize_t \
+show_regs_in_##offset (struct device *dev, char *buf) \
+{ \
+ return show_in(dev, buf, 0x##offset); \
+} \
+static DEVICE_ATTR(in_input##offset, S_IRUGO, show_regs_in_##offset, NULL)
+
+#define sysfs_in_reg_offset(reg, offset) \
+static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \
+{ \
+ return show_in_##reg (dev, buf, 0x##offset); \
+} \
+static ssize_t store_regs_in_##reg##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+ return store_in_##reg (dev, buf, count, 0x##offset); \
+} \
+static DEVICE_ATTR(in_##reg##offset, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset)
+
+#define sysfs_in_offsets(offset) \
+sysfs_in_offset(offset); \
+sysfs_in_reg_offset(min, offset); \
+sysfs_in_reg_offset(max, offset);
+
+sysfs_in_offsets(0);
+sysfs_in_offsets(1);
+sysfs_in_offsets(2);
+sysfs_in_offsets(3);
+sysfs_in_offsets(4);
+sysfs_in_offsets(5);
+sysfs_in_offsets(6);
+sysfs_in_offsets(7);
+sysfs_in_offsets(8);
+
+#define device_create_file_in(client, offset) \
+device_create_file(&client->dev, &dev_attr_in_input##offset); \
+device_create_file(&client->dev, &dev_attr_in_min##offset); \
+device_create_file(&client->dev, &dev_attr_in_max##offset);
+
+#define show_fan_reg(reg) \
+static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83781d_data *data = i2c_get_clientdata(client); \
+ \
+ w83781d_update_client(client); \
+ \
+ return sprintf(buf,"%ld\n", \
+ FAN_FROM_REG(data->reg[nr-1], (long)DIV_FROM_REG(data->fan_div[nr-1]))); \
+}
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t
+store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->fan_min[nr - 1] =
+ FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1]));
+ w83781d_write_value(client, W83781D_REG_FAN_MIN(nr),
+ data->fan_min[nr - 1]);
+
+ return count;
+}
+
+#define sysfs_fan_offset(offset) \
+static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \
+{ \
+ return show_fan(dev, buf, 0x##offset); \
+} \
+static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_regs_fan_##offset, NULL)
+
+#define sysfs_fan_min_offset(offset) \
+static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \
+{ \
+ return show_fan_min(dev, buf, 0x##offset); \
+} \
+static ssize_t store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+ return store_fan_min(dev, buf, count, 0x##offset); \
+} \
+static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset)
+
+sysfs_fan_offset(1);
+sysfs_fan_min_offset(1);
+sysfs_fan_offset(2);
+sysfs_fan_min_offset(2);
+sysfs_fan_offset(3);
+sysfs_fan_min_offset(3);
+
+#define device_create_file_fan(client, offset) \
+device_create_file(&client->dev, &dev_attr_fan_input##offset); \
+device_create_file(&client->dev, &dev_attr_fan_min##offset); \
+
+#define show_temp_reg(reg) \
+static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83781d_data *data = i2c_get_clientdata(client); \
+ \
+ w83781d_update_client(client); \
+ \
+ if (nr >= 2) { /* TEMP2 and TEMP3 */ \
+ if (data->type == as99127f) { \
+ return sprintf(buf,"%ld\n", \
+ (long)AS99127_TEMP_ADD_FROM_REG(data->reg##_add[nr-2])); \
+ } else { \
+ return sprintf(buf,"%ld\n", \
+ (long)TEMP_ADD_FROM_REG(data->reg##_add[nr-2])); \
+ } \
+ } else { /* TEMP1 */ \
+ return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \
+ } \
+}
+show_temp_reg(temp);
+show_temp_reg(temp_min);
+show_temp_reg(temp_max);
+
+#define store_temp_reg(REG, reg) \
+static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83781d_data *data = i2c_get_clientdata(client); \
+ u32 val; \
+ \
+ val = simple_strtoul(buf, NULL, 10); \
+ \
+ if (nr >= 2) { /* TEMP2 and TEMP3 */ \
+ if (data->type == as99127f) \
+ data->temp_##reg##_add[nr-2] = AS99127_TEMP_ADD_TO_REG(val); \
+ else \
+ data->temp_##reg##_add[nr-2] = TEMP_ADD_TO_REG(val); \
+ \
+ w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \
+ data->temp_##reg##_add[nr-2]); \
+ } else { /* TEMP1 */ \
+ data->temp_##reg = TEMP_TO_REG(val); \
+ w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \
+ data->temp_##reg); \
+ } \
+ \
+ return count; \
+}
+store_temp_reg(OVER, min);
+store_temp_reg(HYST, max);
+
+#define sysfs_temp_offset(offset) \
+static ssize_t \
+show_regs_temp_##offset (struct device *dev, char *buf) \
+{ \
+ return show_temp(dev, buf, 0x##offset); \
+} \
+static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_regs_temp_##offset, NULL)
+
+#define sysfs_temp_reg_offset(reg, offset) \
+static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \
+{ \
+ return show_temp_##reg (dev, buf, 0x##offset); \
+} \
+static ssize_t store_regs_temp_##reg##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+ return store_temp_##reg (dev, buf, count, 0x##offset); \
+} \
+static DEVICE_ATTR(temp_##reg##offset, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset)
+
+#define sysfs_temp_offsets(offset) \
+sysfs_temp_offset(offset); \
+sysfs_temp_reg_offset(min, offset); \
+sysfs_temp_reg_offset(max, offset);
+
+sysfs_temp_offsets(1);
+sysfs_temp_offsets(2);
+sysfs_temp_offsets(3);
+
+#define device_create_file_temp(client, offset) \
+device_create_file(&client->dev, &dev_attr_temp_input##offset); \
+device_create_file(&client->dev, &dev_attr_temp_max##offset); \
+device_create_file(&client->dev, &dev_attr_temp_min##offset);
+
+static ssize_t
+show_vid_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+
+ w83781d_update_client(client);
+
+ return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+}
+
+static
+DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL)
+#define device_create_file_vid(client) \
+device_create_file(&client->dev, &dev_attr_vid);
+static ssize_t
+show_vrm_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+
+ w83781d_update_client(client);
+
+ return sprintf(buf, "%ld\n", (long) data->vrm);
+}
+
+static ssize_t
+store_vrm_reg(struct device *dev, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->vrm = val;
+
+ return count;
+}
+
+static
+DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg)
+#define device_create_file_vrm(client) \
+device_create_file(&client->dev, &dev_attr_vrm);
+static ssize_t
+show_alarms_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+
+ w83781d_update_client(client);
+
+ return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+}
+
+static
+DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
+#define device_create_file_alarms(client) \
+device_create_file(&client->dev, &dev_attr_alarms);
+#define show_beep_reg(REG, reg) \
+static ssize_t show_beep_##reg (struct device *dev, char *buf) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83781d_data *data = i2c_get_clientdata(client); \
+ \
+ w83781d_update_client(client); \
+ \
+ return sprintf(buf,"%ld\n", (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \
+}
+show_beep_reg(ENABLE, enable);
+show_beep_reg(MASK, mask);
+
+#define BEEP_ENABLE 0 /* Store beep_enable */
+#define BEEP_MASK 1 /* Store beep_mask */
+
+static ssize_t
+store_beep_reg(struct device *dev, const char *buf, size_t count,
+ int update_mask)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ u32 val, val2;
+
+ val = simple_strtoul(buf, NULL, 10);
+
+ if (update_mask == BEEP_MASK) { /* We are storing beep_mask */
+ data->beep_mask = BEEP_MASK_TO_REG(val);
+ w83781d_write_value(client, W83781D_REG_BEEP_INTS1,
+ data->beep_mask & 0xff);
+
+ if ((data->type != w83781d) && (data->type != as99127f)) {
+ w83781d_write_value(client, W83781D_REG_BEEP_INTS3,
+ ((data->beep_mask) >> 16) & 0xff);
+ }
+
+ val2 = (data->beep_mask >> 8) & 0x7f;
+ } else { /* We are storing beep_enable */
+ val2 = w83781d_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f;
+ data->beep_enable = BEEP_ENABLE_TO_REG(val);
+ }
+
+ w83781d_write_value(client, W83781D_REG_BEEP_INTS2,
+ val2 | data->beep_enable << 7);
+
+ return count;
+}
+
+#define sysfs_beep(REG, reg) \
+static ssize_t show_regs_beep_##reg (struct device *dev, char *buf) \
+{ \
+ return show_beep_##reg(dev, buf); \
+} \
+static ssize_t store_regs_beep_##reg (struct device *dev, const char *buf, size_t count) \
+{ \
+ return store_beep_reg(dev, buf, count, BEEP_##REG); \
+} \
+static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg)
+
+sysfs_beep(ENABLE, enable);
+sysfs_beep(MASK, mask);
+
+#define device_create_file_beep(client) \
+device_create_file(&client->dev, &dev_attr_beep_enable); \
+device_create_file(&client->dev, &dev_attr_beep_mask);
+
+/* w83697hf only has two fans */
+static ssize_t
+show_fan_div_reg(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+
+ w83781d_update_client(client);
+
+ return sprintf(buf, "%ld\n",
+ (long) DIV_FROM_REG(data->fan_div[nr - 1]));
+}
+
+/* w83697hf only has two fans */
+static ssize_t
+store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ u32 val, old, old2, old3;
+
+ val = simple_strtoul(buf, NULL, 10);
+ old = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
+
+ data->fan_div[nr - 1] = DIV_TO_REG(val, data->type);
+
+ /* w83781d and as99127f don't have extended divisor bits */
+ if ((data->type != w83781d) && data->type != as99127f) {
+ old3 = w83781d_read_value(client, W83781D_REG_VBAT);
+ }
+ if (nr >= 3 && data->type != w83697hf) {
+ old2 = w83781d_read_value(client, W83781D_REG_PIN);
+ old2 = (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6);
+ w83781d_write_value(client, W83781D_REG_PIN, old2);
+
+ if ((data->type != w83781d) && (data->type != as99127f)) {
+ old3 = (old3 & 0x7f) | ((data->fan_div[2] & 0x04) << 5);
+ }
+ }
+ if (nr >= 2) {
+ old = (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
+
+ if ((data->type != w83781d) && (data->type != as99127f)) {
+ old3 = (old3 & 0xbf) | ((data->fan_div[1] & 0x04) << 4);
+ }
+ }
+ if (nr >= 1) {
+ old = (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
+ w83781d_write_value(client, W83781D_REG_VID_FANDIV, old);
+
+ if ((data->type != w83781d) && (data->type != as99127f)) {
+ old3 = (old3 & 0xdf) | ((data->fan_div[0] & 0x04) << 3);
+ w83781d_write_value(client, W83781D_REG_VBAT, old3);
+ }
+ }
+
+ return count;
+}
+
+#define sysfs_fan_div(offset) \
+static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \
+{ \
+ return show_fan_div_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_fan_div_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+ return store_fan_div_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(fan_div##offset, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset)
+
+sysfs_fan_div(1);
+sysfs_fan_div(2);
+sysfs_fan_div(3);
+
+#define device_create_file_fan_div(client, offset) \
+device_create_file(&client->dev, &dev_attr_fan_div##offset); \
+
+/* w83697hf only has two fans */
+static ssize_t
+show_pwm_reg(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+
+ w83781d_update_client(client);
+
+ return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr - 1]));
+}
+
+/* w83697hf only has two fans */
+static ssize_t
+show_pwmenable_reg(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+
+ w83781d_update_client(client);
+
+ return sprintf(buf, "%ld\n", (long) data->pwmenable[nr - 1]);
+}
+
+static ssize_t
+store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+
+ data->pwm[nr - 1] = PWM_TO_REG(val);
+ w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]);
+
+ return count;
+}
+
+static ssize_t
+store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ u32 val, j, k;
+
+ val = simple_strtoul(buf, NULL, 10);
+
+ /* only PWM2 can be enabled/disabled */
+ if (nr == 2) {
+ j = w83781d_read_value(client, W83781D_REG_PWMCLK12);
+ k = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
+
+ if (val > 0) {
+ if (!(j & 0x08))
+ w83781d_write_value(client,
+ W83781D_REG_PWMCLK12,
+ j | 0x08);
+ if (k & 0x10)
+ w83781d_write_value(client,
+ W83781D_REG_BEEP_CONFIG,
+ k & 0xef);
+
+ data->pwmenable[1] = 1;
+ } else {
+ if (j & 0x08)
+ w83781d_write_value(client,
+ W83781D_REG_PWMCLK12,
+ j & 0xf7);
+ if (!(k & 0x10))
+ w83781d_write_value(client,
+ W83781D_REG_BEEP_CONFIG,
+ j | 0x10);
+
+ data->pwmenable[1] = 0;
+ }
+ }
+
+ return count;
+}
+
+#define sysfs_pwm(offset) \
+static ssize_t show_regs_pwm_##offset (struct device *dev, char *buf) \
+{ \
+ return show_pwm_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_pwm_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+ return store_pwm_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, show_regs_pwm_##offset, store_regs_pwm_##offset)
+
+#define sysfs_pwmenable(offset) \
+static ssize_t show_regs_pwmenable_##offset (struct device *dev, char *buf) \
+{ \
+ return show_pwmenable_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_pwmenable_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+ return store_pwmenable_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(pwm_enable##offset, S_IRUGO | S_IWUSR, show_regs_pwmenable_##offset, store_regs_pwmenable_##offset)
+
+sysfs_pwm(1);
+sysfs_pwm(2);
+sysfs_pwmenable(2); /* only PWM2 can be enabled/disabled */
+sysfs_pwm(3);
+sysfs_pwm(4);
+
+#define device_create_file_pwm(client, offset) \
+device_create_file(&client->dev, &dev_attr_pwm##offset); \
+
+#define device_create_file_pwmenable(client, offset) \
+device_create_file(&client->dev, &dev_attr_pwm_enable##offset); \
+
+static ssize_t
+show_sensor_reg(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+
+ w83781d_update_client(client);
+
+ return sprintf(buf, "%ld\n", (long) data->sens[nr - 1]);
+}
+
+static ssize_t
+store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ u32 val, tmp;
+
+ val = simple_strtoul(buf, NULL, 10);
+
+ switch (val) {
+ case 1: /* PII/Celeron diode */
+ tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
+ w83781d_write_value(client, W83781D_REG_SCFG1,
+ tmp | BIT_SCFG1[nr - 1]);
+ tmp = w83781d_read_value(client, W83781D_REG_SCFG2);
+ w83781d_write_value(client, W83781D_REG_SCFG2,
+ tmp | BIT_SCFG2[nr - 1]);
+ data->sens[nr - 1] = val;
+ break;
+ case 2: /* 3904 */
+ tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
+ w83781d_write_value(client, W83781D_REG_SCFG1,
+ tmp | BIT_SCFG1[nr - 1]);
+ tmp = w83781d_read_value(client, W83781D_REG_SCFG2);
+ w83781d_write_value(client, W83781D_REG_SCFG2,
+ tmp & ~BIT_SCFG2[nr - 1]);
+ data->sens[nr - 1] = val;
+ break;
+ case W83781D_DEFAULT_BETA: /* thermistor */
+ tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
+ w83781d_write_value(client, W83781D_REG_SCFG1,
+ tmp & ~BIT_SCFG1[nr - 1]);
+ data->sens[nr - 1] = val;
+ break;
+ default:
+ dev_err(&client->dev,
+ "Invalid sensor type %ld; must be 1, 2, or %d\n",
+ (long) val, W83781D_DEFAULT_BETA);
+ break;
+ }
+
+ return count;
+}
+
+#define sysfs_sensor(offset) \
+static ssize_t show_regs_sensor_##offset (struct device *dev, char *buf) \
+{ \
+ return show_sensor_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_sensor_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+ return store_sensor_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(sensor##offset, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset)
+
+sysfs_sensor(1);
+sysfs_sensor(2);
+sysfs_sensor(3);
+
+#define device_create_file_sensor(client, offset) \
+device_create_file(&client->dev, &dev_attr_sensor##offset); \
+
+#ifdef W83781D_RT
+static ssize_t
+show_rt_reg(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ int i, j = 0;
+
+ w83781d_update_client(client);
+
+ for (i = 0; i < 32; i++) {
+ if (i > 0)
+ j += sprintf(buf, " %ld", (long) data->rt[nr - 1][i]);
+ else
+ j += sprintf(buf, "%ld", (long) data->rt[nr - 1][i]);
+ }
+ j += sprintf(buf, "\n");
+
+ return j;
+}
+
+static ssize_t
+store_rt_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ u32 val, i;
+
+ for (i = 0; i < count; i++) {
+ val = simple_strtoul(buf + count, NULL, 10);
+
+ /* fixme: no bounds checking 0-255 */
+ data->rt[nr - 1][i] = val & 0xff;
+ w83781d_write_value(client, W83781D_REG_RT_IDX, i);
+ w83781d_write_value(client, W83781D_REG_RT_VAL,
+ data->rt[nr - 1][i]);
+ }
+
+ return count;
+}
+
+#define sysfs_rt(offset) \
+static ssize_t show_regs_rt_##offset (struct device *dev, char *buf) \
+{ \
+ return show_rt_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_rt_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+ return store_rt_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset)
+
+sysfs_rt(1);
+sysfs_rt(2);
+sysfs_rt(3);
+
+#define device_create_file_rt(client, offset) \
+device_create_file(&client->dev, &dev_attr_rt##offset); \
+
+#endif /* ifdef W83781D_RT */
+
+/* This function is called when:
+ * w83781d_driver is inserted (when this module is loaded), for each
+ available adapter
+ * when a new adapter is inserted (and w83781d_driver is still present) */
+static int
+w83781d_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, w83781d_detect);
+}
+
+static int
+w83781d_detect(struct i2c_adapter *adapter, int address,
+ unsigned short flags, int kind)
+{
+ int i = 0, val1 = 0, val2, id;
+ struct i2c_client *new_client;
+ struct w83781d_data *data;
+ int err = 0;
+ const char *type_name = "";
+ const char *client_name = "";
+ int is_isa = i2c_is_isa_adapter(adapter);
+ enum vendor { winbond, asus } vendid;
+
+ if (!is_isa
+ && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ goto ERROR0;
+
+ if (is_isa) {
+ if (!request_region(address, W83781D_EXTENT, "w83781d"))
+ goto ERROR0;
+ release_region(address, W83781D_EXTENT);
+ }
+
+ /* Probe whether there is anything available on this address. Already
+ done for SMBus clients */
+ if (kind < 0) {
+ if (is_isa) {
+
+#define REALLY_SLOW_IO
+ /* We need the timeouts for at least some LM78-like chips. But only
+ if we read 'undefined' registers. */
+ i = inb_p(address + 1);
+ if (inb_p(address + 2) != i)
+ goto ERROR0;
+ if (inb_p(address + 3) != i)
+ goto ERROR0;
+ if (inb_p(address + 7) != i)
+ goto ERROR0;
+#undef REALLY_SLOW_IO
+
+ /* Let's just hope nothing breaks here */
+ i = inb_p(address + 5) & 0x7f;
+ outb_p(~i & 0x7f, address + 5);
+ if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
+ outb_p(i, address + 5);
+ return 0;
+ }
+ }
+ }
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access w83781d_{read,write}_value. */
+
+ if (!(new_client = kmalloc(sizeof (struct i2c_client) +
+ sizeof (struct w83781d_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto ERROR0;
+ }
+
+ memset(new_client, 0x00, sizeof (struct i2c_client) +
+ sizeof (struct w83781d_data));
+
+ data = (struct w83781d_data *) (new_client + 1);
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ init_MUTEX(&data->lock);
+ new_client->adapter = adapter;
+ new_client->driver = &w83781d_driver;
+ new_client->flags = 0;
+
+ /* Now, we do the remaining detection. */
+
+ /* The w8378?d may be stuck in some other bank than bank 0. This may
+ make reading other information impossible. Specify a force=... or
+ force_*=... parameter, and the Winbond will be reset to the right
+ bank. */
+ if (kind < 0) {
+ if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80)
+ goto ERROR1;
+ val1 = w83781d_read_value(new_client, W83781D_REG_BANK);
+ val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
+ /* Check for Winbond or Asus ID if in bank 0 */
+ if ((!(val1 & 0x07)) &&
+ (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)
+ && (val2 != 0x94))
+ || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)
+ && (val2 != 0x06))))
+ goto ERROR1;
+ /* If Winbond SMBus, check address at 0x48. Asus doesn't support */
+ if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
+ ((val1 & 0x80) && (val2 == 0x5c)))) {
+ if (w83781d_read_value
+ (new_client, W83781D_REG_I2C_ADDR) != address)
+ goto ERROR1;
+ }
+ }
+
+ /* We have either had a force parameter, or we have already detected the
+ Winbond. Put it now into bank 0 and Vendor ID High Byte */
+ w83781d_write_value(new_client, W83781D_REG_BANK,
+ (w83781d_read_value(new_client,
+ W83781D_REG_BANK) & 0x78) |
+ 0x80);
+
+ /* Determine the chip type. */
+ if (kind <= 0) {
+ /* get vendor ID */
+ val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
+ if (val2 == 0x5c)
+ vendid = winbond;
+ else if ((val2 == 0x12) || (val2 == 0x06))
+ vendid = asus;
+ else
+ goto ERROR1;
+ /* mask off lower bit, not reliable */
+ val1 =
+ w83781d_read_value(new_client, W83781D_REG_WCHIPID) & 0xfe;
+ if (val1 == 0x10 && vendid == winbond)
+ kind = w83781d;
+ else if (val1 == 0x30 && vendid == winbond)
+ kind = w83782d;
+ else if (val1 == 0x40 && vendid == winbond && !is_isa)
+ kind = w83783s;
+ else if (val1 == 0x20 && vendid == winbond)
+ kind = w83627hf;
+ else if (val1 == 0x30 && vendid == asus && !is_isa)
+ kind = as99127f;
+ else if (val1 == 0x60 && vendid == winbond && is_isa)
+ kind = w83697hf;
+ else {
+ if (kind == 0)
+ dev_warn(&new_client->dev,
+ "Ignoring 'force' parameter for unknown chip at"
+ "adapter %d, address 0x%02x\n",
+ i2c_adapter_id(adapter), address);
+ goto ERROR1;
+ }
+ }
+
+ if (kind == w83781d) {
+ type_name = "w83781d";
+ client_name = "W83781D chip";
+ } else if (kind == w83782d) {
+ type_name = "w83782d";
+ client_name = "W83782D chip";
+ } else if (kind == w83783s) {
+ type_name = "w83783s";
+ client_name = "W83783S chip";
+ } else if (kind == w83627hf) {
+ type_name = "w83627hf";
+ client_name = "W83627HF chip";
+ } else if (kind == as99127f) {
+ type_name = "as99127f";
+ client_name = "AS99127F chip";
+ } else if (kind == w83697hf) {
+ type_name = "w83697hf";
+ client_name = "W83697HF chip";
+ } else {
+ dev_err(&new_client->dev, "Internal error: unknown kind (%d)?!?", kind);
+ goto ERROR1;
+ }
+
+ /* Reserve the ISA region */
+ if (is_isa)
+ request_region(address, W83781D_EXTENT, type_name);
+
+ /* Fill in the remaining client fields and put it into the global list */
+ strncpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
+ data->type = kind;
+
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto ERROR3;
+
+ /* attach secondary i2c lm75-like clients */
+ if (!is_isa) {
+ if (!(data->lm75 = kmalloc(2 * sizeof (struct i2c_client),
+ GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto ERROR4;
+ }
+
+ memset(data->lm75, 0x00, 2 * sizeof (struct i2c_client));
+
+ id = i2c_adapter_id(adapter);
+ if (force_subclients[0] == id && force_subclients[1] == address) {
+ for (i = 2; i <= 3; i++) {
+ if (force_subclients[i] < 0x48 ||
+ force_subclients[i] > 0x4f) {
+ dev_err(&new_client->dev,
+ "Invalid subclient address %d; must be 0x48-0x4f\n",
+ force_subclients[i]);
+ goto ERROR5;
+ }
+ }
+ w83781d_write_value(new_client,
+ W83781D_REG_I2C_SUBADDR,
+ (force_subclients[2] & 0x07) |
+ ((force_subclients[3] & 0x07) <<
+ 4));
+ data->lm75[0].addr = force_subclients[2];
+ } else {
+ val1 = w83781d_read_value(new_client,
+ W83781D_REG_I2C_SUBADDR);
+ data->lm75[0].addr = 0x48 + (val1 & 0x07);
+ }
+ if (kind != w83783s) {
+ if (force_subclients[0] == id &&
+ force_subclients[1] == address) {
+ data->lm75[1].addr = force_subclients[3];
+ } else {
+ data->lm75[1].addr =
+ 0x48 + ((val1 >> 4) & 0x07);
+ }
+ if (data->lm75[0].addr == data->lm75[1].addr) {
+ dev_err(&new_client->dev,
+ "Duplicate addresses 0x%x for subclients.\n",
+ data->lm75[0].addr);
+ goto ERROR5;
+ }
+ }
+ if (kind == w83781d)
+ client_name = "W83781D subclient";
+ else if (kind == w83782d)
+ client_name = "W83782D subclient";
+ else if (kind == w83783s)
+ client_name = "W83783S subclient";
+ else if (kind == w83627hf)
+ client_name = "W83627HF subclient";
+ else if (kind == as99127f)
+ client_name = "AS99127F subclient";
+
+ for (i = 0; i <= 1; i++) {
+ i2c_set_clientdata(&data->lm75[i], NULL); /* store all data in w83781d */
+ data->lm75[i].adapter = adapter;
+ data->lm75[i].driver = &w83781d_driver;
+ data->lm75[i].flags = 0;
+ strncpy(data->lm75[i].dev.name, client_name,
+ DEVICE_NAME_SIZE);
+ if (kind == w83783s)
+ break;
+ }
+ } else {
+ data->lm75 = NULL;
+ }
+
+ device_create_file_in(new_client, 0);
+ if (kind != w83783s && kind != w83697hf)
+ device_create_file_in(new_client, 1);
+ device_create_file_in(new_client, 2);
+ device_create_file_in(new_client, 3);
+ device_create_file_in(new_client, 4);
+ device_create_file_in(new_client, 5);
+ device_create_file_in(new_client, 6);
+ if (kind != as99127f && kind != w83781d && kind != w83783s) {
+ device_create_file_in(new_client, 7);
+ device_create_file_in(new_client, 8);
+ }
+
+ device_create_file_fan(new_client, 1);
+ device_create_file_fan(new_client, 2);
+ if (kind != w83697hf)
+ device_create_file_fan(new_client, 3);
+
+ device_create_file_temp(new_client, 1);
+ device_create_file_temp(new_client, 2);
+ if (kind != w83783s && kind != w83697hf)
+ device_create_file_temp(new_client, 3);
+
+ if (kind != w83697hf)
+ device_create_file_vid(new_client);
+
+ if (kind != w83697hf)
+ device_create_file_vrm(new_client);
+
+ device_create_file_fan_div(new_client, 1);
+ device_create_file_fan_div(new_client, 2);
+ if (kind != w83697hf)
+ device_create_file_fan_div(new_client, 3);
+
+ device_create_file_alarms(new_client);
+
+ device_create_file_beep(new_client);
+
+ if (kind != w83781d) {
+ device_create_file_pwm(new_client, 1);
+ device_create_file_pwm(new_client, 2);
+ device_create_file_pwmenable(new_client, 2);
+ }
+ if (kind == w83782d && !is_isa) {
+ device_create_file_pwm(new_client, 3);
+ device_create_file_pwm(new_client, 4);
+ }
+
+ if (kind != as99127f && kind != w83781d) {
+ device_create_file_sensor(new_client, 1);
+ device_create_file_sensor(new_client, 2);
+ if (kind != w83783s && kind != w83697hf)
+ device_create_file_sensor(new_client, 3);
+ }
+#ifdef W83781D_RT
+ if (kind == w83781d) {
+ device_create_file_rt(new_client, 1);
+ device_create_file_rt(new_client, 2);
+ device_create_file_rt(new_client, 3);
+ }
+#endif
+
+ /* Initialize the chip */
+ w83781d_init_client(new_client);
+ return 0;
+
+/* OK, this is not exactly good programming practice, usually. But it is
+ very code-efficient in this case. */
+
+ ERROR5:
+ if (!is_isa) {
+ i2c_detach_client(&data->lm75[0]);
+ if (data->type != w83783s)
+ i2c_detach_client(&data->lm75[1]);
+ kfree(data->lm75);
+ }
+ ERROR4:
+ i2c_detach_client(new_client);
+ ERROR3:
+ if (is_isa)
+ release_region(address, W83781D_EXTENT);
+ ERROR1:
+ kfree(new_client);
+ ERROR0:
+ return err;
+}
+
+static int
+w83781d_detach_client(struct i2c_client *client)
+{
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev,
+ "Client deregistration failed, client not detached.\n");
+ return err;
+ }
+
+ if (i2c_is_isa_client(client)) {
+ release_region(client->addr, W83781D_EXTENT);
+ } else {
+ i2c_detach_client(&data->lm75[0]);
+ if (data->type != w83783s)
+ i2c_detach_client(&data->lm75[1]);
+ kfree(data->lm75);
+ }
+ kfree(client);
+
+ return 0;
+}
+
+/* The SMBus locks itself, usually, but nothing may access the Winbond between
+ bank switches. ISA access must always be locked explicitly!
+ We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
+ would slow down the W83781D access and should not be necessary.
+ There are some ugly typecasts here, but the good news is - they should
+ nowhere else be necessary! */
+static int
+w83781d_read_value(struct i2c_client *client, u16 reg)
+{
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ int res, word_sized, bank;
+ struct i2c_client *cl;
+
+ down(&data->lock);
+ if (i2c_is_isa_client(client)) {
+ word_sized = (((reg & 0xff00) == 0x100)
+ || ((reg & 0xff00) == 0x200))
+ && (((reg & 0x00ff) == 0x50)
+ || ((reg & 0x00ff) == 0x53)
+ || ((reg & 0x00ff) == 0x55));
+ if (reg & 0xff00) {
+ outb_p(W83781D_REG_BANK,
+ client->addr + W83781D_ADDR_REG_OFFSET);
+ outb_p(reg >> 8,
+ client->addr + W83781D_DATA_REG_OFFSET);
+ }
+ outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
+ res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
+ if (word_sized) {
+ outb_p((reg & 0xff) + 1,
+ client->addr + W83781D_ADDR_REG_OFFSET);
+ res =
+ (res << 8) + inb_p(client->addr +
+ W83781D_DATA_REG_OFFSET);
+ }
+ if (reg & 0xff00) {
+ outb_p(W83781D_REG_BANK,
+ client->addr + W83781D_ADDR_REG_OFFSET);
+ outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
+ }
+ } else {
+ bank = (reg >> 8) & 0x0f;
+ if (bank > 2)
+ /* switch banks */
+ i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
+ bank);
+ if (bank == 0 || bank > 2) {
+ res = i2c_smbus_read_byte_data(client, reg & 0xff);
+ } else {
+ /* switch to subclient */
+ cl = &data->lm75[bank - 1];
+ /* convert from ISA to LM75 I2C addresses */
+ switch (reg & 0xff) {
+ case 0x50: /* TEMP */
+ res =
+ swap_bytes(i2c_smbus_read_word_data(cl, 0));
+ break;
+ case 0x52: /* CONFIG */
+ res = i2c_smbus_read_byte_data(cl, 1);
+ break;
+ case 0x53: /* HYST */
+ res =
+ swap_bytes(i2c_smbus_read_word_data(cl, 2));
+ break;
+ case 0x55: /* OVER */
+ default:
+ res =
+ swap_bytes(i2c_smbus_read_word_data(cl, 3));
+ break;
+ }
+ }
+ if (bank > 2)
+ i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
+ }
+ up(&data->lock);
+ return res;
+}
+
+static int
+w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
+{
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ int word_sized, bank;
+ struct i2c_client *cl;
+
+ down(&data->lock);
+ if (i2c_is_isa_client(client)) {
+ word_sized = (((reg & 0xff00) == 0x100)
+ || ((reg & 0xff00) == 0x200))
+ && (((reg & 0x00ff) == 0x53)
+ || ((reg & 0x00ff) == 0x55));
+ if (reg & 0xff00) {
+ outb_p(W83781D_REG_BANK,
+ client->addr + W83781D_ADDR_REG_OFFSET);
+ outb_p(reg >> 8,
+ client->addr + W83781D_DATA_REG_OFFSET);
+ }
+ outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
+ if (word_sized) {
+ outb_p(value >> 8,
+ client->addr + W83781D_DATA_REG_OFFSET);
+ outb_p((reg & 0xff) + 1,
+ client->addr + W83781D_ADDR_REG_OFFSET);
+ }
+ outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET);
+ if (reg & 0xff00) {
+ outb_p(W83781D_REG_BANK,
+ client->addr + W83781D_ADDR_REG_OFFSET);
+ outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
+ }
+ } else {
+ bank = (reg >> 8) & 0x0f;
+ if (bank > 2)
+ /* switch banks */
+ i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
+ bank);
+ if (bank == 0 || bank > 2) {
+ i2c_smbus_write_byte_data(client, reg & 0xff,
+ value & 0xff);
+ } else {
+ /* switch to subclient */
+ cl = &data->lm75[bank - 1];
+ /* convert from ISA to LM75 I2C addresses */
+ switch (reg & 0xff) {
+ case 0x52: /* CONFIG */
+ i2c_smbus_write_byte_data(cl, 1, value & 0xff);
+ break;
+ case 0x53: /* HYST */
+ i2c_smbus_write_word_data(cl, 2,
+ swap_bytes(value));
+ break;
+ case 0x55: /* OVER */
+ i2c_smbus_write_word_data(cl, 3,
+ swap_bytes(value));
+ break;
+ }
+ }
+ if (bank > 2)
+ i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
+ }
+ up(&data->lock);
+ return 0;
+}
+
+/* Called when we have found a new W83781D. It should set limits, etc. */
+static void
+w83781d_init_client(struct i2c_client *client)
+{
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ int vid = 0, i, p;
+ int type = data->type;
+ u8 tmp;
+
+ if (init && type != as99127f) { /* this resets registers we don't have
+ documentation for on the as99127f */
+ /* save these registers */
+ i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
+ p = w83781d_read_value(client, W83781D_REG_PWMCLK12);
+ /* Reset all except Watchdog values and last conversion values
+ This sets fan-divs to 2, among others */
+ w83781d_write_value(client, W83781D_REG_CONFIG, 0x80);
+ /* Restore the registers and disable power-on abnormal beep.
+ This saves FAN 1/2/3 input/output values set by BIOS. */
+ w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80);
+ w83781d_write_value(client, W83781D_REG_PWMCLK12, p);
+ /* Disable master beep-enable (reset turns it on).
+ Individual beep_mask should be reset to off but for some reason
+ disabling this bit helps some people not get beeped */
+ w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
+ }
+
+ if (type != w83697hf) {
+ vid = w83781d_read_value(client, W83781D_REG_VID_FANDIV) & 0x0f;
+ vid |=
+ (w83781d_read_value(client, W83781D_REG_CHIPID) & 0x01) <<
+ 4;
+ data->vrm = DEFAULT_VRM;
+ vid = vid_from_reg(vid, data->vrm);
+ }
+
+ if ((type != w83781d) && (type != as99127f)) {
+ tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
+ for (i = 1; i <= 3; i++) {
+ if (!(tmp & BIT_SCFG1[i - 1])) {
+ data->sens[i - 1] = W83781D_DEFAULT_BETA;
+ } else {
+ if (w83781d_read_value
+ (client,
+ W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
+ data->sens[i - 1] = 1;
+ else
+ data->sens[i - 1] = 2;
+ }
+ if ((type == w83783s || type == w83697hf) && (i == 2))
+ break;
+ }
+ }
+#ifdef W83781D_RT
+/*
+ Fill up the RT Tables.
+ We assume that they are 32 bytes long, in order for temp 1-3.
+ Data sheet documentation is sparse.
+ We also assume that it is only for the 781D although I suspect
+ that the others support it as well....
+*/
+
+ if (init && type == w83781d) {
+ u16 k = 0;
+/*
+ Auto-indexing doesn't seem to work...
+ w83781d_write_value(client,W83781D_REG_RT_IDX,0);
+*/
+ for (i = 0; i < 3; i++) {
+ int j;
+ for (j = 0; j < 32; j++) {
+ w83781d_write_value(client,
+ W83781D_REG_RT_IDX, k++);
+ data->rt[i][j] =
+ w83781d_read_value(client,
+ W83781D_REG_RT_VAL);
+ }
+ }
+ }
+#endif /* W83781D_RT */
+
+ if (init) {
+ w83781d_write_value(client, W83781D_REG_IN_MIN(0),
+ IN_TO_REG(W83781D_INIT_IN_MIN_0));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(0),
+ IN_TO_REG(W83781D_INIT_IN_MAX_0));
+ if (type != w83783s && type != w83697hf) {
+ w83781d_write_value(client, W83781D_REG_IN_MIN(1),
+ IN_TO_REG(W83781D_INIT_IN_MIN_1));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(1),
+ IN_TO_REG(W83781D_INIT_IN_MAX_1));
+ }
+
+ w83781d_write_value(client, W83781D_REG_IN_MIN(2),
+ IN_TO_REG(W83781D_INIT_IN_MIN_2));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(2),
+ IN_TO_REG(W83781D_INIT_IN_MAX_2));
+ w83781d_write_value(client, W83781D_REG_IN_MIN(3),
+ IN_TO_REG(W83781D_INIT_IN_MIN_3));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(3),
+ IN_TO_REG(W83781D_INIT_IN_MAX_3));
+ w83781d_write_value(client, W83781D_REG_IN_MIN(4),
+ IN_TO_REG(W83781D_INIT_IN_MIN_4));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(4),
+ IN_TO_REG(W83781D_INIT_IN_MAX_4));
+ if (type == w83781d || type == as99127f) {
+ w83781d_write_value(client, W83781D_REG_IN_MIN(5),
+ IN_TO_REG(W83781D_INIT_IN_MIN_5));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(5),
+ IN_TO_REG(W83781D_INIT_IN_MAX_5));
+ } else {
+ w83781d_write_value(client, W83781D_REG_IN_MIN(5),
+ IN_TO_REG(W83782D_INIT_IN_MIN_5));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(5),
+ IN_TO_REG(W83782D_INIT_IN_MAX_5));
+ }
+ if (type == w83781d || type == as99127f) {
+ w83781d_write_value(client, W83781D_REG_IN_MIN(6),
+ IN_TO_REG(W83781D_INIT_IN_MIN_6));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(6),
+ IN_TO_REG(W83781D_INIT_IN_MAX_6));
+ } else {
+ w83781d_write_value(client, W83781D_REG_IN_MIN(6),
+ IN_TO_REG(W83782D_INIT_IN_MIN_6));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(6),
+ IN_TO_REG(W83782D_INIT_IN_MAX_6));
+ }
+ if ((type == w83782d) || (type == w83627hf) ||
+ (type == w83697hf)) {
+ w83781d_write_value(client, W83781D_REG_IN_MIN(7),
+ IN_TO_REG(W83781D_INIT_IN_MIN_7));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(7),
+ IN_TO_REG(W83781D_INIT_IN_MAX_7));
+ w83781d_write_value(client, W83781D_REG_IN_MIN(8),
+ IN_TO_REG(W83781D_INIT_IN_MIN_8));
+ w83781d_write_value(client, W83781D_REG_IN_MAX(8),
+ IN_TO_REG(W83781D_INIT_IN_MAX_8));
+ w83781d_write_value(client, W83781D_REG_VBAT,
+ (w83781d_read_value
+ (client,
+ W83781D_REG_VBAT) | 0x01));
+ }
+ w83781d_write_value(client, W83781D_REG_FAN_MIN(1),
+ FAN_TO_REG(W83781D_INIT_FAN_MIN_1, 2));
+ w83781d_write_value(client, W83781D_REG_FAN_MIN(2),
+ FAN_TO_REG(W83781D_INIT_FAN_MIN_2, 2));
+ if (type != w83697hf) {
+ w83781d_write_value(client, W83781D_REG_FAN_MIN(3),
+ FAN_TO_REG(W83781D_INIT_FAN_MIN_3,
+ 2));
+ }
+
+ w83781d_write_value(client, W83781D_REG_TEMP_OVER(1),
+ TEMP_TO_REG(W83781D_INIT_TEMP_OVER));
+ w83781d_write_value(client, W83781D_REG_TEMP_HYST(1),
+ TEMP_TO_REG(W83781D_INIT_TEMP_HYST));
+
+ if (type == as99127f) {
+ w83781d_write_value(client, W83781D_REG_TEMP_OVER(2),
+ AS99127_TEMP_ADD_TO_REG
+ (W83781D_INIT_TEMP2_OVER));
+ w83781d_write_value(client, W83781D_REG_TEMP_HYST(2),
+ AS99127_TEMP_ADD_TO_REG
+ (W83781D_INIT_TEMP2_HYST));
+ } else {
+ w83781d_write_value(client, W83781D_REG_TEMP_OVER(2),
+ TEMP_ADD_TO_REG
+ (W83781D_INIT_TEMP2_OVER));
+ w83781d_write_value(client, W83781D_REG_TEMP_HYST(2),
+ TEMP_ADD_TO_REG
+ (W83781D_INIT_TEMP2_HYST));
+ }
+ w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG, 0x00);
+
+ if (type == as99127f) {
+ w83781d_write_value(client, W83781D_REG_TEMP_OVER(3),
+ AS99127_TEMP_ADD_TO_REG
+ (W83781D_INIT_TEMP3_OVER));
+ w83781d_write_value(client, W83781D_REG_TEMP_HYST(3),
+ AS99127_TEMP_ADD_TO_REG
+ (W83781D_INIT_TEMP3_HYST));
+ } else if (type != w83783s && type != w83697hf) {
+ w83781d_write_value(client, W83781D_REG_TEMP_OVER(3),
+ TEMP_ADD_TO_REG
+ (W83781D_INIT_TEMP3_OVER));
+ w83781d_write_value(client, W83781D_REG_TEMP_HYST(3),
+ TEMP_ADD_TO_REG
+ (W83781D_INIT_TEMP3_HYST));
+ }
+ if (type != w83783s && type != w83697hf) {
+ w83781d_write_value(client, W83781D_REG_TEMP3_CONFIG,
+ 0x00);
+ }
+ if (type != w83781d) {
+ /* enable comparator mode for temp2 and temp3 so
+ alarm indication will work correctly */
+ w83781d_write_value(client, W83781D_REG_IRQ, 0x41);
+ for (i = 0; i < 3; i++)
+ data->pwmenable[i] = 1;
+ }
+ }
+
+ /* Start monitoring */
+ w83781d_write_value(client, W83781D_REG_CONFIG,
+ (w83781d_read_value(client,
+ W83781D_REG_CONFIG) & 0xf7)
+ | 0x01);
+}
+
+static void
+w83781d_update_client(struct i2c_client *client)
+{
+ struct w83781d_data *data = i2c_get_clientdata(client);
+ int i;
+
+ down(&data->update_lock);
+
+ if (time_after
+ (jiffies - data->last_updated, (unsigned long) (HZ + HZ / 2))
+ || time_before(jiffies, data->last_updated) || !data->valid) {
+ pr_debug(KERN_DEBUG "Starting device update\n");
+
+ for (i = 0; i <= 8; i++) {
+ if ((data->type == w83783s || data->type == w83697hf)
+ && (i == 1))
+ continue; /* 783S has no in1 */
+ data->in[i] =
+ w83781d_read_value(client, W83781D_REG_IN(i));
+ data->in_min[i] =
+ w83781d_read_value(client, W83781D_REG_IN_MIN(i));
+ data->in_max[i] =
+ w83781d_read_value(client, W83781D_REG_IN_MAX(i));
+ if ((data->type != w83782d) && (data->type != w83697hf)
+ && (data->type != w83627hf) && (i == 6))
+ break;
+ }
+ for (i = 1; i <= 3; i++) {
+ data->fan[i - 1] =
+ w83781d_read_value(client, W83781D_REG_FAN(i));
+ data->fan_min[i - 1] =
+ w83781d_read_value(client, W83781D_REG_FAN_MIN(i));
+ }
+ if (data->type != w83781d) {
+ for (i = 1; i <= 4; i++) {
+ data->pwm[i - 1] =
+ w83781d_read_value(client,
+ W83781D_REG_PWM(i));
+ if (((data->type == w83783s)
+ || (data->type == w83627hf)
+ || (data->type == as99127f)
+ || (data->type == w83697hf)
+ || ((data->type == w83782d)
+ && i2c_is_isa_client(client)))
+ && i == 2)
+ break;
+ }
+ }
+
+ data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1));
+ data->temp_min =
+ w83781d_read_value(client, W83781D_REG_TEMP_OVER(1));
+ data->temp_max =
+ w83781d_read_value(client, W83781D_REG_TEMP_HYST(1));
+ data->temp_add[0] =
+ w83781d_read_value(client, W83781D_REG_TEMP(2));
+ data->temp_max_add[0] =
+ w83781d_read_value(client, W83781D_REG_TEMP_OVER(2));
+ data->temp_min_add[0] =
+ w83781d_read_value(client, W83781D_REG_TEMP_HYST(2));
+ if (data->type != w83783s && data->type != w83697hf) {
+ data->temp_add[1] =
+ w83781d_read_value(client, W83781D_REG_TEMP(3));
+ data->temp_max_add[1] =
+ w83781d_read_value(client,
+ W83781D_REG_TEMP_OVER(3));
+ data->temp_min_add[1] =
+ w83781d_read_value(client,
+ W83781D_REG_TEMP_HYST(3));
+ }
+ i = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
+ if (data->type != w83697hf) {
+ data->vid = i & 0x0f;
+ data->vid |=
+ (w83781d_read_value(client, W83781D_REG_CHIPID) &
+ 0x01)
+ << 4;
+ }
+ data->fan_div[0] = (i >> 4) & 0x03;
+ data->fan_div[1] = (i >> 6) & 0x03;
+ if (data->type != w83697hf) {
+ data->fan_div[2] = (w83781d_read_value(client,
+ W83781D_REG_PIN)
+ >> 6) & 0x03;
+ }
+ if ((data->type != w83781d) && (data->type != as99127f)) {
+ i = w83781d_read_value(client, W83781D_REG_VBAT);
+ data->fan_div[0] |= (i >> 3) & 0x04;
+ data->fan_div[1] |= (i >> 4) & 0x04;
+ if (data->type != w83697hf)
+ data->fan_div[2] |= (i >> 5) & 0x04;
+ }
+ data->alarms =
+ w83781d_read_value(client,
+ W83781D_REG_ALARM1) +
+ (w83781d_read_value(client, W83781D_REG_ALARM2) << 8);
+ if ((data->type == w83782d) || (data->type == w83627hf)) {
+ data->alarms |=
+ w83781d_read_value(client,
+ W83781D_REG_ALARM3) << 16;
+ }
+ i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2);
+ data->beep_enable = i >> 7;
+ data->beep_mask = ((i & 0x7f) << 8) +
+ w83781d_read_value(client, W83781D_REG_BEEP_INTS1);
+ if ((data->type != w83781d) && (data->type != as99127f)) {
+ data->beep_mask |=
+ w83781d_read_value(client,
+ W83781D_REG_BEEP_INTS3) << 16;
+ }
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+}
+
+static int __init
+sensors_w83781d_init(void)
+{
+ return i2c_add_driver(&w83781d_driver);
+}
+
+static void __exit
+sensors_w83781d_exit(void)
+{
+ i2c_del_driver(&w83781d_driver);
+}
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
+ "Philip Edelbrock <phil@netroedge.com>, "
+ "and Mark Studebaker <mdsxyz123@yahoo.com>");
+MODULE_DESCRIPTION("W83781D driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83781d_init);
+module_exit(sensors_w83781d_exit);
diff -Nru a/include/linux/i2c-vid.h b/include/linux/i2c-vid.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/include/linux/i2c-vid.h Wed Apr 2 16:00:28 2003
@@ -0,0 +1,62 @@
+/*
+ vrm.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+ With assistance from Trent Piepho <xyzzy@speakeasy.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ This file contains common code for decoding VID pins.
+ This file is #included in various chip drivers in this directory.
+ As the user is unlikely to load more than one driver which
+ includes this code we don't worry about the wasted space.
+ Reference: VRM x.y DC-DC Converter Design Guidelines,
+ available at http://developer.intel.com
+*/
+
+/*
+ Legal val values 00 - 1F.
+ vrm is the Intel VRM document version.
+ Note: vrm version is scaled by 10 and the return value is scaled by 1000
+ to avoid floating point in the kernel.
+*/
+
+#define DEFAULT_VRM 82
+
+static inline int vid_from_reg(int val, int vrm)
+{
+ switch(vrm) {
+
+ case 91: /* VRM 9.1 */
+ case 90: /* VRM 9.0 */
+ return(val == 0x1f ? 0 :
+ 1850 - val * 25);
+
+ case 85: /* VRM 8.5 */
+ return((val & 0x10 ? 25 : 0) +
+ ((val & 0x0f) > 0x04 ? 2050 : 1250) -
+ ((val & 0x0f) * 50));
+
+ case 84: /* VRM 8.4 */
+ val &= 0x0f;
+ /* fall through */
+ default: /* VRM 8.2 */
+ return(val == 0x1f ? 0 :
+ val & 0x10 ? 5100 - (val) * 100 :
+ 2050 - (val) * 50);
+ }
+}
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Albert Cranford
-1 siblings, 0 replies; 98+ messages in thread
From: Albert Cranford @ 2003-04-03 6:21 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel, sensors
I read the thread concerning the removal of proc.c & proc.h
but hope that this does not go to Linus until the interface
between i2c & sensors to application is somewhat defined.
At the moment we have a sysctl API used by sensors, video and
other i2c kernel applications that is working.
Our desire to switch the sensors to sysfs interface should not
break other applications. At least until we have a model/api
to propose to these other drivers.
In my personal home systems I use it87 driver and have been
somewhat successful in switching to sysfs. A big blocking
point is there is no application to read/set/monitor the
driver, so it is basically unverified. I would hate to
put other i2c applications in the same boat.
Your thoughts?
Albert
Greg KH wrote:
> ChangeSet 1.977.29.8, 2003/04/02 11:45:21-08:00, greg@kroah.com
>
> i2c: remove proc and sysctl code from i2c-proc as it is no longer used.
>
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Albert Cranford
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-04-03 6:33 UTC (permalink / raw)
To: Albert Cranford; +Cc: linux-kernel, sensors
On Thu, Apr 03, 2003 at 01:21:13AM -0500, Albert Cranford wrote:
> I read the thread concerning the removal of proc.c & proc.h
> but hope that this does not go to Linus until the interface
> between i2c & sensors to application is somewhat defined.
>
> At the moment we have a sysctl API used by sensors, video and
> other i2c kernel applications that is working.
The only in-kernel drivers that were using the sysctl/proc interface was
the lm75 and adm1021 drivers. The video and other i2c kernel drivers do
not use this interface at all.
Those two drivers, and the two other chip drivers that I added to the
kernel in this set of patches were converted over to the sysfs interface
(well one of the new ones were, the other one will build and run, but
doesn't export any sysfs files yet, that will change soon.)
> Our desire to switch the sensors to sysfs interface should not
> break other applications. At least until we have a model/api
> to propose to these other drivers.
Yes, any applications that used the sysctl interface to get data from
those two driver will break. However we have to switch at some point in
time, and the userspace library can't be worked on very well if the
kernel can't support it yet :)
So I'm choosing to update the kernel first, and will be working on the
library in the coming weeks. As there is no real sensors support
besides those two drivers in the main kernel, I didn't break much :)
> In my personal home systems I use it87 driver and have been
> somewhat successful in switching to sysfs. A big blocking
> point is there is no application to read/set/monitor the
> driver, so it is basically unverified.
I tested the changes I did by using echo and cat, no library or other
applications are needed just yet.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Albert Cranford
-1 siblings, 0 replies; 98+ messages in thread
From: Albert Cranford @ 2003-04-03 13:06 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel, sensors
Your right, nobody outside of sensors uses i2c-proc, but
why not create a new i2c-sysfs.h in drivers/i2c locally
and and adjust the couple of existing drivers.
We all know the application library is not going to have
access to include/linux/include/i2c-xxxx.h anyhow.
Later we can completely remove linux/include/linux/i2c-proc.h
which the existing application library relies upon.
ALbert
Greg KH wrote:
> On Thu, Apr 03, 2003 at 01:21:13AM -0500, Albert Cranford wrote:
>
>>I read the thread concerning the removal of proc.c & proc.h
>>but hope that this does not go to Linus until the interface
>>between i2c & sensors to application is somewhat defined.
>>
>>At the moment we have a sysctl API used by sensors, video and
>>other i2c kernel applications that is working.
>
>
> The only in-kernel drivers that were using the sysctl/proc interface was
> the lm75 and adm1021 drivers. The video and other i2c kernel drivers do
> not use this interface at all.
>
> Those two drivers, and the two other chip drivers that I added to the
> kernel in this set of patches were converted over to the sysfs interface
> (well one of the new ones were, the other one will build and run, but
> doesn't export any sysfs files yet, that will change soon.)
>
>
>>Our desire to switch the sensors to sysfs interface should not
>>break other applications. At least until we have a model/api
>>to propose to these other drivers.
>
>
> Yes, any applications that used the sysctl interface to get data from
> those two driver will break. However we have to switch at some point in
> time, and the userspace library can't be worked on very well if the
> kernel can't support it yet :)
>
> So I'm choosing to update the kernel first, and will be working on the
> library in the coming weeks. As there is no real sensors support
> besides those two drivers in the main kernel, I didn't break much :)
>
>
>>In my personal home systems I use it87 driver and have been
>>somewhat successful in switching to sysfs. A big blocking
>>point is there is no application to read/set/monitor the
>>driver, so it is basically unverified.
>
>
> I tested the changes I did by using echo and cat, no library or other
> applications are needed just yet.
>
> thanks,
>
> greg k-h
>
>
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Albert Cranford
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-04-03 16:37 UTC (permalink / raw)
To: Albert Cranford; +Cc: linux-kernel, sensors
On Thu, Apr 03, 2003 at 08:06:06AM -0500, Albert Cranford wrote:
> Your right, nobody outside of sensors uses i2c-proc, but
> why not create a new i2c-sysfs.h in drivers/i2c locally
> and and adjust the couple of existing drivers.
What would i2c-sysfs.h be needed for? All of the needed sysfs prototype
functions are already in device.h.
> We all know the application library is not going to have
> access to include/linux/include/i2c-xxxx.h anyhow.
It never did :)
> Later we can completely remove linux/include/linux/i2c-proc.h
> which the existing application library relies upon.
No userspace program should rely on kernel header files.
And I didn't take away the functionality that i2c-proc.h provided with
the list of devices supported and such. Just the unused function
prototypes that dealt with the proc and sysctl interface.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* [BK PATCH] More i2c driver changes for 2.5.69
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-05-09 23:55 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, sensors
Hi,
Here are some more minor i2c fixups for 2.5.69. They are basically a
bunch of fixes for the it87 driver, and a few other minor changes.
Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.5
thanks,
greg k-h
drivers/i2c/chips/it87.c | 195 +++++++++++++++++++++++------------------------
drivers/i2c/i2c-core.c | 33 ++++++-
include/linux/i2c.h | 13 +--
3 files changed, 133 insertions(+), 108 deletions(-)
-----
<warp:mercury.d2dc.net>:
o I2C: And another it87 patch
o I2C: Yet another it87 patch
o I2C: Another it87 patch
Greg Kroah-Hartman:
o i2c: register the i2c_adapter_driver so things link up properly in sysfs
o i2c: add i2c_adapter class support
Mark W. McClelland:
o I2C: add more classes
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.69
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-05-09 23:56 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.1, 2003/05/09 13:53:57-07:00, greg@kroah.com
[PATCH] i2c: add i2c_adapter class support
drivers/i2c/i2c-core.c | 23 ++++++++++++++++++++---
include/linux/i2c.h | 3 ++-
2 files changed, 22 insertions(+), 4 deletions(-)
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri May 9 16:48:30 2003
+++ b/drivers/i2c/i2c-core.c Fri May 9 16:48:30 2003
@@ -62,6 +62,10 @@
.remove = i2c_device_remove,
};
+static struct class i2c_adapter_class = {
+ .name = "i2c-adapter"
+};
+
/* ---------------------------------------------------
* registering functions
@@ -97,6 +101,13 @@
adap->dev.driver = &i2c_generic_driver;
device_register(&adap->dev);
+ /* Add this adapter to the i2c_adapter class */
+ memset(&adap->class_dev, 0x00, sizeof(struct class_device));
+ adap->class_dev.dev = &adap->dev;
+ adap->class_dev.class = &i2c_adapter_class;
+ strncpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
+ class_device_register(&adap->class_dev);
+
/* inform drivers of new adapters */
list_for_each(item,&drivers) {
driver = list_entry(item, struct i2c_driver, list);
@@ -150,6 +161,7 @@
}
/* clean up the sysfs representation */
+ class_device_unregister(&adap->class_dev);
device_unregister(&adap->dev);
list_del(&adap->list);
@@ -443,14 +455,19 @@
.match = i2c_device_match,
};
-
static int __init i2c_init(void)
{
- return bus_register(&i2c_bus_type);
+ int retval;
+
+ retval = bus_register(&i2c_bus_type);
+ if (retval)
+ return retval;
+ return class_register(&i2c_adapter_class);
}
static void __exit i2c_exit(void)
{
+ class_unregister(&i2c_adapter_class);
bus_unregister(&i2c_bus_type);
}
@@ -475,7 +492,7 @@
return ret;
} else {
- dev_err(&adap->dev, "I2C level transfers not supported\n");
+ DEB2(dev_dbg(&adap->dev, "I2C level transfers not supported\n"));
return -ENOSYS;
}
}
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri May 9 16:48:30 2003
+++ b/include/linux/i2c.h Fri May 9 16:48:30 2003
@@ -240,7 +240,8 @@
int timeout;
int retries;
- struct device dev; /* the adapter device */
+ struct device dev; /* the adapter device */
+ struct class_device class_dev; /* the class device */
#ifdef CONFIG_PROC_FS
/* No need to set this when you initialize the adapter */
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.69
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-05-09 23:56 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.3, 2003/05/09 14:54:04-07:00, warp@mercury.d2dc.net
[PATCH] I2C: Another it87 patch.
This is against my last.
While the old code most definitely did /something/ to the register for
setting the fan div, the 'what' is a more interesting question.
To be honest I could not figure out what it was trying to do, because
the way it was inserting values disagreed with not only the data sheet,
but how it parsed the very same register.
This corrects the issue, and allows one to properly control the divisor
on all 3 fans, including the (much more limited) 3rd fan.
drivers/i2c/chips/it87.c | 34 ++++++++++++++++++++++++++++------
1 files changed, 28 insertions(+), 6 deletions(-)
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c Fri May 9 16:48:09 2003
+++ b/drivers/i2c/chips/it87.c Fri May 9 16:48:09 2003
@@ -159,7 +159,14 @@
205-(val)*5)
#define ALARMS_FROM_REG(val) (val)
-#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
+static int log2(int val)
+{
+ int answer = 0;
+ while ((val >>= 1))
+ answer++;
+ return answer;
+}
+#define DIV_TO_REG(val) log2(val)
#define DIV_FROM_REG(val) (1 << (val))
/* Initial limits. Use the config file to set better limits. */
@@ -520,10 +527,25 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
- int old = it87_read_value(client, IT87_REG_FAN_DIV);
- data->fan_div[nr] = DIV_TO_REG(val);
- old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
- it87_write_value(client, IT87_REG_FAN_DIV, old);
+ u8 old = it87_read_value(client, IT87_REG_FAN_DIV);
+
+ switch (nr) {
+ case 0:
+ case 1:
+ data->fan_div[nr] = DIV_TO_REG(val);
+ break;
+ case 2:
+ if (val < 8)
+ data->fan_div[nr] = 1;
+ else
+ data->fan_div[nr] = 3;
+ }
+ val = old & 0x100;
+ val |= (data->fan_div[0] & 0x07);
+ val |= (data->fan_div[1] & 0x07) << 3;
+ if (data->fan_div[2] == 3)
+ val |= 0x1 << 6;
+ it87_write_value(client, IT87_REG_FAN_DIV, val);
return count;
}
@@ -961,7 +983,7 @@
i = it87_read_value(client, IT87_REG_FAN_DIV);
data->fan_div[0] = i & 0x07;
data->fan_div[1] = (i >> 3) & 0x07;
- data->fan_div[2] = 1;
+ data->fan_div[2] = (i & 0x40) ? 3 : 1;
data->alarms =
it87_read_value(client, IT87_REG_ALARM1) |
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.69
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-05-09 23:56 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.5, 2003/05/09 14:54:25-07:00, warp@mercury.d2dc.net
[PATCH] I2C: And another it87 patch.
Don't provide min/max for in8, which allowed one to scribble on
registers one should not be messing with. (My fault, oops.)
The setting of the temp high/low registers was off by one, not mine this
time. While I was at it, I reordered a few other register accesses to
be base 0 instead of base 1.
The temp interface was slightly incorrect, degrees * 100 instead of
degrees * 1000, also fixed.
And lastly, when changing the fan count divisor, fix up the min setting
to still be roughly the same. (Previously the meaning of the value in
the register changed, but not the value itself, resulting in, undesired
surprises.)
drivers/i2c/chips/it87.c | 77 ++++++++++++++++++++++++++++-------------------
1 files changed, 47 insertions(+), 30 deletions(-)
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c Fri May 9 16:47:47 2003
+++ b/drivers/i2c/chips/it87.c Fri May 9 16:47:47 2003
@@ -80,17 +80,17 @@
/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
-#define IT87_REG_FAN(nr) (0x0c + (nr))
-#define IT87_REG_FAN_MIN(nr) (0x0f + (nr))
+#define IT87_REG_FAN(nr) (0x0d + (nr))
+#define IT87_REG_FAN_MIN(nr) (0x10 + (nr))
#define IT87_REG_FAN_CTRL 0x13
#define IT87_REG_VIN(nr) (0x20 + (nr))
-#define IT87_REG_TEMP(nr) (0x28 + (nr))
+#define IT87_REG_TEMP(nr) (0x29 + (nr))
#define IT87_REG_VIN_MAX(nr) (0x30 + (nr) * 2)
#define IT87_REG_VIN_MIN(nr) (0x31 + (nr) * 2)
-#define IT87_REG_TEMP_HIGH(nr) (0x3e + (nr) * 2)
-#define IT87_REG_TEMP_LOW(nr) (0x3f + (nr) * 2)
+#define IT87_REG_TEMP_HIGH(nr) (0x40 + ((nr) * 2))
+#define IT87_REG_TEMP_LOW(nr) (0x41 + ((nr) * 2))
#define IT87_REG_I2C_ADDR 0x48
@@ -289,6 +289,9 @@
{ \
return show_in(dev, buf, 0x##offset); \
} \
+static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in##offset, NULL)
+
+#define limit_in_offset(offset) \
static ssize_t \
show_in##offset##_min (struct device *dev, char *buf) \
{ \
@@ -309,20 +312,27 @@
{ \
return set_in_max(dev, buf, count, 0x##offset); \
} \
-static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in##offset, NULL) \
static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \
show_in##offset##_min, set_in##offset##_min) \
static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \
show_in##offset##_max, set_in##offset##_max)
show_in_offset(0);
+limit_in_offset(0);
show_in_offset(1);
+limit_in_offset(1);
show_in_offset(2);
+limit_in_offset(2);
show_in_offset(3);
+limit_in_offset(3);
show_in_offset(4);
+limit_in_offset(4);
show_in_offset(5);
+limit_in_offset(5);
show_in_offset(6);
+limit_in_offset(6);
show_in_offset(7);
+limit_in_offset(7);
show_in_offset(8);
/* 3 temperatures */
@@ -331,7 +341,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*10 );
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*100 );
}
/* more like overshoot temperature */
static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
@@ -339,7 +349,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*10);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*100);
}
/* more like hysteresis temperature */
static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
@@ -347,14 +357,14 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])*10);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])*100);
}
static ssize_t set_temp_max(struct device *dev, const char *buf,
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)/10;
+ int val = simple_strtol(buf, NULL, 10)/100;
data->temp_high[nr] = TEMP_TO_REG(val);
it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]);
return count;
@@ -364,7 +374,7 @@
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
- int val = simple_strtol(buf, NULL, 10)/10;
+ int val = simple_strtol(buf, NULL, 10)/100;
data->temp_low[nr] = TEMP_TO_REG(val);
it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]);
return count;
@@ -480,7 +490,7 @@
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
- it87_write_value(client, IT87_REG_FAN_MIN(nr+1), data->fan_min[nr]);
+ it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
return count;
}
static ssize_t set_fan_div(struct device *dev, const char *buf,
@@ -489,8 +499,12 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
+ int i, min[3];
u8 old = it87_read_value(client, IT87_REG_FAN_DIV);
+ for (i = 0; i < 3; i++)
+ min[i] = FAN_FROM_REG(data->fan_min[i], DIV_FROM_REG(data->fan_div[i]));
+
switch (nr) {
case 0:
case 1:
@@ -508,6 +522,11 @@
if (data->fan_div[2] == 3)
val |= 0x1 << 6;
it87_write_value(client, IT87_REG_FAN_DIV, val);
+
+ for (i = 0; i < 3; i++) {
+ data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i]));
+ it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]);
+ }
return count;
}
@@ -704,7 +723,6 @@
device_create_file(&new_client->dev, &dev_attr_in_min5);
device_create_file(&new_client->dev, &dev_attr_in_min6);
device_create_file(&new_client->dev, &dev_attr_in_min7);
- device_create_file(&new_client->dev, &dev_attr_in_min8);
device_create_file(&new_client->dev, &dev_attr_in_max0);
device_create_file(&new_client->dev, &dev_attr_in_max1);
device_create_file(&new_client->dev, &dev_attr_in_max2);
@@ -713,7 +731,6 @@
device_create_file(&new_client->dev, &dev_attr_in_max5);
device_create_file(&new_client->dev, &dev_attr_in_max6);
device_create_file(&new_client->dev, &dev_attr_in_max7);
- device_create_file(&new_client->dev, &dev_attr_in_max8);
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_input2);
device_create_file(&new_client->dev, &dev_attr_temp_input3);
@@ -849,23 +866,23 @@
it87_write_value(client, IT87_REG_VIN_MAX(7),
IN_TO_REG(IT87_INIT_IN_MAX_7));
/* Note: Battery voltage does not have limit registers */
- it87_write_value(client, IT87_REG_FAN_MIN(1),
+ it87_write_value(client, IT87_REG_FAN_MIN(0),
FAN_TO_REG(IT87_INIT_FAN_MIN_1, 2));
- it87_write_value(client, IT87_REG_FAN_MIN(2),
+ it87_write_value(client, IT87_REG_FAN_MIN(1),
FAN_TO_REG(IT87_INIT_FAN_MIN_2, 2));
- it87_write_value(client, IT87_REG_FAN_MIN(3),
+ it87_write_value(client, IT87_REG_FAN_MIN(2),
FAN_TO_REG(IT87_INIT_FAN_MIN_3, 2));
- it87_write_value(client, IT87_REG_TEMP_HIGH(1),
+ it87_write_value(client, IT87_REG_TEMP_HIGH(0),
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_1));
- it87_write_value(client, IT87_REG_TEMP_LOW(1),
+ it87_write_value(client, IT87_REG_TEMP_LOW(0),
TEMP_TO_REG(IT87_INIT_TEMP_LOW_1));
- it87_write_value(client, IT87_REG_TEMP_HIGH(2),
+ it87_write_value(client, IT87_REG_TEMP_HIGH(1),
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_2));
- it87_write_value(client, IT87_REG_TEMP_LOW(2),
+ it87_write_value(client, IT87_REG_TEMP_LOW(1),
TEMP_TO_REG(IT87_INIT_TEMP_LOW_2));
- it87_write_value(client, IT87_REG_TEMP_HIGH(3),
+ it87_write_value(client, IT87_REG_TEMP_HIGH(2),
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_3));
- it87_write_value(client, IT87_REG_TEMP_LOW(3),
+ it87_write_value(client, IT87_REG_TEMP_LOW(2),
TEMP_TO_REG(IT87_INIT_TEMP_LOW_3));
/* Enable voltage monitors */
@@ -918,18 +935,18 @@
data->in_min[8] = 0;
data->in_max[8] = 255;
- for (i = 1; i <= 3; i++) {
- data->fan[i - 1] =
+ for (i = 0; i < 3; i++) {
+ data->fan[i] =
it87_read_value(client, IT87_REG_FAN(i));
- data->fan_min[i - 1] =
+ data->fan_min[i] =
it87_read_value(client, IT87_REG_FAN_MIN(i));
}
- for (i = 1; i <= 3; i++) {
- data->temp[i - 1] =
+ for (i = 0; i < 3; i++) {
+ data->temp[i] =
it87_read_value(client, IT87_REG_TEMP(i));
- data->temp_high[i - 1] =
+ data->temp_high[i] =
it87_read_value(client, IT87_REG_TEMP_HIGH(i));
- data->temp_low[i - 1] =
+ data->temp_low[i] =
it87_read_value(client, IT87_REG_TEMP_LOW(i));
}
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.69
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-05-09 23:56 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.4, 2003/05/09 14:54:15-07:00, warp@mercury.d2dc.net
[PATCH] I2C: Yet another it87 patch.
Ok, after writing up something in the way of a perl script to make some
sense of the data for voltages, and finding that there is no sense to
make, I took a longer look at things.
The it87 driver in 2.5.x is doing some, down right /odd/ math on the
numbers for the in_input* readings, and the 2.4.x driver is doing
something quite different.
And while it might be possible to get sane numbers out of the 2.5.x
driver, people /expect/ to get the numbers that they were getting from
2.4.x.
So this patch puts things back to the simpler calculations done by the
2.4.x lm-sensors drivers, and my script confirms that the numbers come
out right.
drivers/i2c/chips/it87.c | 84 ++++++++++++-----------------------------------
1 files changed, 23 insertions(+), 61 deletions(-)
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c Fri May 9 16:47:59 2003
+++ b/drivers/i2c/chips/it87.c Fri May 9 16:47:59 2003
@@ -99,46 +99,8 @@
#define IT87_REG_CHIPID 0x58
-static inline u8 IN_TO_REG(long val, int inNum)
-{
- /* to avoid floating point, we multiply everything by 100.
- val is guaranteed to be positive, so we can achieve the effect of
- rounding by (...*10+5)/10. Note that the *10 is hidden in the
- /250 (which should really be /2500).
- At the end, we need to /100 because we *100 everything and we need
- to /10 because of the rounding thing, so we /1000. */
- if (inNum <= 1)
- return (u8)
- SENSORS_LIMIT(((val * 210240 - 13300) / 250 + 5) / 1000,
- 0, 255);
- else if (inNum == 2)
- return (u8)
- SENSORS_LIMIT(((val * 157370 - 13300) / 250 + 5) / 1000,
- 0, 255);
- else if (inNum == 3)
- return (u8)
- SENSORS_LIMIT(((val * 101080 - 13300) / 250 + 5) / 1000,
- 0, 255);
- else
- return (u8) SENSORS_LIMIT(((val * 41714 - 13300) / 250 + 5)
- / 1000, 0, 255);
-}
-
-static inline long IN_FROM_REG(u8 val, int inNum)
-{
- /* to avoid floating point, we multiply everything by 100.
- val is guaranteed to be positive, so we can achieve the effect of
- rounding by adding 0.5. Or, to avoid fp math, we do (...*10+5)/10.
- We need to scale with *100 anyway, so no need to /100 at the end. */
- if (inNum <= 1)
- return (long) (((250000 * val + 13300) / 210240 * 10 + 5) /10);
- else if (inNum == 2)
- return (long) (((250000 * val + 13300) / 157370 * 10 + 5) /10);
- else if (inNum == 3)
- return (long) (((250000 * val + 13300) / 101080 * 10 + 5) /10);
- else
- return (long) (((250000 * val + 13300) / 41714 * 10 + 5) /10);
-}
+#define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
+#define IN_FROM_REG(val) (((val) * 16) / 10)
static inline u8 FAN_TO_REG(long rpm, int div)
{
@@ -279,7 +241,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)*10 );
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])*10 );
}
static ssize_t show_in_min(struct device *dev, char *buf, int nr)
@@ -287,7 +249,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)*10 );
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])*10 );
}
static ssize_t show_in_max(struct device *dev, char *buf, int nr)
@@ -295,7 +257,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)*10 );
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])*10 );
}
static ssize_t set_in_min(struct device *dev, const char *buf,
@@ -304,7 +266,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10)/10;
- data->in_min[nr] = IN_TO_REG(val,nr);
+ data->in_min[nr] = IN_TO_REG(val);
it87_write_value(client, IT87_REG_VIN_MIN(nr),
data->in_min[nr]);
return count;
@@ -315,7 +277,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10)/10;
- data->in_max[nr] = IN_TO_REG(val,nr);
+ data->in_max[nr] = IN_TO_REG(val);
it87_write_value(client, IT87_REG_VIN_MAX(nr),
data->in_max[nr]);
return count;
@@ -855,37 +817,37 @@
This sets fan-divs to 2, among others */
it87_write_value(client, IT87_REG_CONFIG, 0x80);
it87_write_value(client, IT87_REG_VIN_MIN(0),
- IN_TO_REG(IT87_INIT_IN_MIN_0, 0));
+ IN_TO_REG(IT87_INIT_IN_MIN_0));
it87_write_value(client, IT87_REG_VIN_MAX(0),
- IN_TO_REG(IT87_INIT_IN_MAX_0, 0));
+ IN_TO_REG(IT87_INIT_IN_MAX_0));
it87_write_value(client, IT87_REG_VIN_MIN(1),
- IN_TO_REG(IT87_INIT_IN_MIN_1, 1));
+ IN_TO_REG(IT87_INIT_IN_MIN_1));
it87_write_value(client, IT87_REG_VIN_MAX(1),
- IN_TO_REG(IT87_INIT_IN_MAX_1, 1));
+ IN_TO_REG(IT87_INIT_IN_MAX_1));
it87_write_value(client, IT87_REG_VIN_MIN(2),
- IN_TO_REG(IT87_INIT_IN_MIN_2, 2));
+ IN_TO_REG(IT87_INIT_IN_MIN_2));
it87_write_value(client, IT87_REG_VIN_MAX(2),
- IN_TO_REG(IT87_INIT_IN_MAX_2, 2));
+ IN_TO_REG(IT87_INIT_IN_MAX_2));
it87_write_value(client, IT87_REG_VIN_MIN(3),
- IN_TO_REG(IT87_INIT_IN_MIN_3, 3));
+ IN_TO_REG(IT87_INIT_IN_MIN_3));
it87_write_value(client, IT87_REG_VIN_MAX(3),
- IN_TO_REG(IT87_INIT_IN_MAX_3, 3));
+ IN_TO_REG(IT87_INIT_IN_MAX_3));
it87_write_value(client, IT87_REG_VIN_MIN(4),
- IN_TO_REG(IT87_INIT_IN_MIN_4, 4));
+ IN_TO_REG(IT87_INIT_IN_MIN_4));
it87_write_value(client, IT87_REG_VIN_MAX(4),
- IN_TO_REG(IT87_INIT_IN_MAX_4, 4));
+ IN_TO_REG(IT87_INIT_IN_MAX_4));
it87_write_value(client, IT87_REG_VIN_MIN(5),
- IN_TO_REG(IT87_INIT_IN_MIN_5, 5));
+ IN_TO_REG(IT87_INIT_IN_MIN_5));
it87_write_value(client, IT87_REG_VIN_MAX(5),
- IN_TO_REG(IT87_INIT_IN_MAX_5, 5));
+ IN_TO_REG(IT87_INIT_IN_MAX_5));
it87_write_value(client, IT87_REG_VIN_MIN(6),
- IN_TO_REG(IT87_INIT_IN_MIN_6, 6));
+ IN_TO_REG(IT87_INIT_IN_MIN_6));
it87_write_value(client, IT87_REG_VIN_MAX(6),
- IN_TO_REG(IT87_INIT_IN_MAX_6, 6));
+ IN_TO_REG(IT87_INIT_IN_MAX_6));
it87_write_value(client, IT87_REG_VIN_MIN(7),
- IN_TO_REG(IT87_INIT_IN_MIN_7, 7));
+ IN_TO_REG(IT87_INIT_IN_MIN_7));
it87_write_value(client, IT87_REG_VIN_MAX(7),
- IN_TO_REG(IT87_INIT_IN_MAX_7, 7));
+ IN_TO_REG(IT87_INIT_IN_MAX_7));
/* Note: Battery voltage does not have limit registers */
it87_write_value(client, IT87_REG_FAN_MIN(1),
FAN_TO_REG(IT87_INIT_FAN_MIN_1, 2));
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.69
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-05-09 23:56 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.6, 2003/05/09 16:12:53-07:00, greg@kroah.com
[PATCH] i2c: register the i2c_adapter_driver so things link up properly in sysfs
drivers/i2c/i2c-core.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri May 9 16:47:36 2003
+++ b/drivers/i2c/i2c-core.c Fri May 9 16:47:36 2003
@@ -55,8 +55,8 @@
return 0;
}
-static struct device_driver i2c_generic_driver = {
- .name = "i2c",
+static struct device_driver i2c_adapter_driver = {
+ .name = "i2c_adapter",
.bus = &i2c_bus_type,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
@@ -98,7 +98,7 @@
if (adap->dev.parent == NULL)
adap->dev.parent = &legacy_bus;
sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
- adap->dev.driver = &i2c_generic_driver;
+ adap->dev.driver = &i2c_adapter_driver;
device_register(&adap->dev);
/* Add this adapter to the i2c_adapter class */
@@ -462,12 +462,16 @@
retval = bus_register(&i2c_bus_type);
if (retval)
return retval;
+ retval = driver_register(&i2c_adapter_driver);
+ if (retval)
+ return retval;
return class_register(&i2c_adapter_class);
}
static void __exit i2c_exit(void)
{
class_unregister(&i2c_adapter_class);
+ driver_unregister(&i2c_adapter_driver);
bus_unregister(&i2c_bus_type);
}
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.69
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-05-09 23:56 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.2, 2003/05/09 13:58:10-07:00, mark@alpha.dyndns.org
[PATCH] I2C: add more classes
Add I2C classes for analog and digital cameras, and fix a typo.
include/linux/i2c.h | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri May 9 16:48:20 2003
+++ b/include/linux/i2c.h Fri May 9 16:48:20 2003
@@ -281,10 +281,12 @@
/* Must equal I2C_M_TEN below */
/* i2c adapter classes (bitmask) */
-#define I2C_ADAP_CLASS_SMBUS (1<<0) /* lm_sensors, ... */
-#define I2C_ADAP_CLASS_TV_ANALOG (1<<1) /* bttv + friends */
-#define I2C_ADAP_CLASS_TV_DIGINAL (1<<2) /* dbv cards */
-#define I2C_ADAP_CLASS_DDC (1<<3) /* i2c-matroxfb ? */
+#define I2C_ADAP_CLASS_SMBUS (1<<0) /* lm_sensors, ... */
+#define I2C_ADAP_CLASS_TV_ANALOG (1<<1) /* bttv + friends */
+#define I2C_ADAP_CLASS_TV_DIGITAL (1<<2) /* dbv cards */
+#define I2C_ADAP_CLASS_DDC (1<<3) /* i2c-matroxfb ? */
+#define I2C_ADAP_CLASS_CAM_ANALOG (1<<4) /* camera with analog CCD */
+#define I2C_ADAP_CLASS_CAM_DIGITAL (1<<5) /* most webcams */
/* i2c_client_address_data is the struct for holding default client
* addresses for a driver and for the parameters supplied on the
^ permalink raw reply [flat|nested] 98+ messages in thread
* [BK PATCH] More i2c driver changes for 2.5.70
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-06-11 20:35 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, sensors
Hi,
Here are some more i2c driver changes for 2.5.70. These consist of a new i2c
client driver, a new i2c bus driver, some coding style fixes for the new bus
driver, and a bunch of sparse warning removels.
Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.5
thanks,
greg k-h
-----
drivers/i2c/Kconfig | 4
drivers/i2c/Makefile | 1
drivers/i2c/chips/Kconfig | 19
drivers/i2c/chips/Makefile | 1
drivers/i2c/chips/lm85.c | 1223 +++++++++++++++++++++++++++++++++++++++++++++
drivers/i2c/i2c-core.c | 36 -
drivers/i2c/i2c-dev.c | 10
drivers/i2c/i2c-iop3xx.c | 868 +++++++++++++++++++++++++------
drivers/i2c/i2c-iop3xx.h | 238 ++++++--
include/linux/i2c-dev.h | 6
include/linux/i2c.h | 4
11 files changed, 2150 insertions(+), 260 deletions(-)
-----
<margitsw:t-online.de>:
o I2C: add LM85 driver
<peterm:remware.demon.co.uk>:
o I2C: add New bus driver: XSCALE iop3xx
Greg Kroah-Hartman:
o I2C: fix up sparse warnings in the i2c-dev driver
o I2C: fix up sparse warnings in drivers/i2c/i2c-core.c
o I2C: fix some errors found by sparse in include/linux/i2c.h
o I2C: coding style updates for i2c-iop3xx driver
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-06-11 20:36 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.6, 2003/06/11 12:29:21-07:00, greg@kroah.com
[PATCH] I2C: fix some errors found by sparse in include/linux/i2c.h
include/linux/i2c.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Wed Jun 11 13:25:03 2003
+++ b/include/linux/i2c.h Wed Jun 11 13:25:03 2003
@@ -176,7 +176,7 @@
static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
{
- return dev_set_drvdata (&dev->dev, data);
+ dev_set_drvdata (&dev->dev, data);
}
#define I2C_DEVNAME(str) .dev = { .name = str }
@@ -261,7 +261,7 @@
static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
{
- return dev_set_drvdata (&dev->dev, data);
+ dev_set_drvdata (&dev->dev, data);
}
/*flags for the driver struct: */
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-06-11 20:36 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.4, 2003/06/11 11:43:02-07:00, peterm@remware.demon.co.uk
[PATCH] I2C: add New bus driver: XSCALE iop3xx
drivers/i2c/Kconfig | 4
drivers/i2c/Makefile | 1
drivers/i2c/i2c-iop3xx.c | 565 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/i2c/i2c-iop3xx.h | 120 +++++++++
4 files changed, 690 insertions(+)
diff -Nru a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
--- a/drivers/i2c/Kconfig Wed Jun 11 13:25:23 2003
+++ b/drivers/i2c/Kconfig Wed Jun 11 13:25:23 2003
@@ -193,6 +193,10 @@
tristate "IBM on-chip I2C Adapter"
depends on I2C_IBM_OCP_ALGO
+config I2C_IOP3XX
+ tristate "Intel XScale IOP3xx on-chip I2C interface"
+ depends on ARCH_IOP3XX && I2C
+
config I2C_CHARDEV
tristate "I2C device interface"
depends on I2C
diff -Nru a/drivers/i2c/Makefile b/drivers/i2c/Makefile
--- a/drivers/i2c/Makefile Wed Jun 11 13:25:23 2003
+++ b/drivers/i2c/Makefile Wed Jun 11 13:25:23 2003
@@ -16,4 +16,5 @@
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o
+obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-y += busses/ chips/
diff -Nru a/drivers/i2c/i2c-iop3xx.c b/drivers/i2c/i2c-iop3xx.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/i2c-iop3xx.c Wed Jun 11 13:25:23 2003
@@ -0,0 +1,565 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx */
+/* ------------------------------------------------------------------------- */
+/* 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. idasilva@mvista.com
+
+ 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 <kmalkki@cc.hut.fi>,
+ Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
+
+ ---------------------------------------------------------------------------*/
+
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+
+
+#include <asm/arch-iop3xx/iop321.h>
+#include <asm/arch-iop3xx/iop321-irqs.h>
+#include "i2c-iop3xx.h"
+
+
+/* ----- 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)
+{
+ unsigned char addr;
+
+ addr = ( msg->addr << 1 );
+
+ if (msg->flags & I2C_M_RD )
+ addr |= 1;
+
+/* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
+ 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)
+{
+ // Follows devman 9.3
+ *iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET;
+ *iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS;
+ *iop3xx_adap->biu->CR = 0;
+}
+
+static inline void iop3xx_adap_set_slave_addr(
+ struct i2c_algo_iop3xx_data *iop3xx_adap )
+{
+ *iop3xx_adap->biu->SAR = MYSAR;
+}
+
+static inline void iop3xx_adap_enable(
+ struct i2c_algo_iop3xx_data *iop3xx_adap )
+{
+ u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE;
+
+/* 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;
+
+ cr |= IOP321_ICR_ALDIE|IOP321_ICR_BERRIE|
+ IOP321_ICR_RXFULLIE|IOP321_ICR_TXEMPTYIE;
+
+ *iop3xx_adap->biu->CR = cr;
+}
+
+static void iop3xx_adap_transaction_cleanup(
+ struct i2c_algo_iop3xx_data *iop3xx_adap )
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+
+ cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE |
+ IOP321_ICR_MSTOP | IOP321_ICR_SCLEN );
+ *iop3xx_adap->biu->CR = cr;
+}
+
+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;
+}
+
+
+
+static void iop3xx_i2c_handler( int this_irq,
+ void *dev_id,
+ struct pt_regs *regs)
+/*
+ * NB: the handler has to clear the source of the interrupt!
+ * Then it passes the SR flags of interest to BH via adap data
+ */
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
+
+ u32 sr = *iop3xx_adap->biu->SR;
+
+ if ( (sr &= iop3xx_adap->biu->SR_enabled) ){
+ *iop3xx_adap->biu->SR = sr;
+ iop3xx_adap->biu->SR_received |= sr;
+ wake_up_interruptible(&iop3xx_adap->waitq);
+ }
+}
+
+
+static int iop3xx_adap_error( u32 sr )
+// check all error conditions, clear them , report most important
+{
+ int rc = 0;
+
+ if ( (sr&IOP321_ISR_BERRD) ) {
+ if ( !rc ) rc = -I2C_ERR_BERR;
+ }
+ if ( (sr&IOP321_ISR_ALD) ){
+ if ( !rc ) rc = -I2C_ERR_ALD;
+ }
+ return rc;
+}
+
+static inline u32 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;
+ spin_unlock_irqrestore( &iop3xx_adap->lock, flags );
+
+ return sr;
+}
+
+/*
+ * sleep until interrupted, then recover and analyse the SR
+ * saved by handler
+ */
+typedef int (* CompareFunc)( 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,
+ CompareFunc compare )
+{
+ unsigned sr = 0;
+ int interrupted;
+ int done;
+ int rc;
+
+ do {
+ interrupted = wait_event_interruptible_timeout (
+ iop3xx_adap->waitq,
+ (done = compare( sr = get_srstat(iop3xx_adap),flags )),
+ iop3xx_adap->timeout
+ );
+ if ( (rc = iop3xx_adap_error( sr )) < 0 ){
+ *status = sr;
+ return rc;
+ }else if ( !interrupted ){
+ *status = sr;
+ return rc = -ETIMEDOUT;
+ }
+ } while( !done );
+
+ *status = sr;
+
+ return rc = 0;
+}
+
+
+
+
+/*
+ * Concrete CompareFuncs
+ */
+static int all_bits_clear( unsigned test, unsigned mask ) {
+ return (test&mask) == 0;
+}
+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)
+{
+ return iop3xx_adap_wait_event(
+ iop3xx_adap,
+ IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD,
+ status, any_bits_set );
+}
+
+static int iop3xx_adap_wait_rx_done(
+ struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+{
+ return iop3xx_adap_wait_event(
+ iop3xx_adap,
+ IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_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)
+{
+ *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;
+}
+
+static int iop3xx_adap_send_target_slave_addr(
+ struct i2c_algo_iop3xx_data *iop3xx_adap, struct i2c_msg* msg )
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+ int status;
+ int rc;
+
+ *iop3xx_adap->biu->DBR = iic_cook_addr( msg );
+
+ cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
+ cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE;
+
+ *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 )
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+ int status;
+ int rc;
+
+ *iop3xx_adap->biu->DBR = byte;
+ cr &= ~IOP321_ICR_MSTART;
+ if ( stop ){
+ cr |= IOP321_ICR_MSTOP;
+ }else{
+ cr &= ~IOP321_ICR_MSTOP;
+ }
+ *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
+ rc = iop3xx_adap_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 )
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+ int status;
+ int rc;
+
+ cr &= ~IOP321_ICR_MSTART;
+
+ if ( stop ){
+ cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;
+ }else{
+ cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
+ }
+ *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
+
+ rc = iop3xx_adap_wait_rx_done( iop3xx_adap, &status );
+
+ *byte = *iop3xx_adap->biu->DBR;
+
+ return rc;
+}
+
+
+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);
+ }
+ return rc;
+}
+
+
+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);
+ }
+ return rc;
+}
+
+
+/*
+ * Description: This function implements combined transactions. Combined
+ * transactions consist of combinations of reading and writing blocks of data.
+ * FROM THE SAME ADDRESS
+ * 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 )
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
+ int rc;
+
+ rc = iop3xx_adap_send_target_slave_addr( iop3xx_adap, pmsg );
+ if ( rc < 0 ){
+ return rc;
+ }
+
+ if ( (pmsg->flags&I2C_M_RD) ){
+ return iop3xx_i2c_readbytes( i2c_adap, pmsg->buf, pmsg->len );
+ }else{
+ return iop3xx_i2c_writebytes( i2c_adap, pmsg->buf, pmsg->len );
+ }
+}
+
+
+
+/*
+ * master_xfer() - main read/write entry
+ */
+static int iop3xx_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 );
+
+ for ( im = 0; ret == 0 && im != num; ++im ){
+ ret = iop3xx_handle_msg( i2c_adap, &msgs[im] );
+ }
+
+ iop3xx_adap_transaction_cleanup( iop3xx_adap );
+
+ return ret;
+}
+
+
+
+static int algo_control(struct i2c_adapter *adapter,
+ unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+
+static u32 iic_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C|I2C_FUNC_SMBUS_EMUL;
+}
+
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static struct i2c_algorithm iic_algo = {
+ .name = "IOP3xx I2C algorithm",
+ .id = I2C_ALGO_OCP_IOP3XX,
+ .master_xfer = iop3xx_master_xfer,
+ .algo_control = algo_control,
+ .functionality = iic_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+
+
+static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+
+ if ( !request_region( REGION_START(iop3xx_adap),
+ REGION_LENGTH(iop3xx_adap),
+ iic_adap->name ) ){
+ return -ENODEV;
+ }
+
+ init_waitqueue_head( &iop3xx_adap->waitq );
+ spin_lock_init( &iop3xx_adap->lock );
+
+ if ( request_irq(
+ iop3xx_adap->biu->irq,
+ iop3xx_i2c_handler,
+ /* SA_SAMPLE_RANDOM */ 0,
+ iic_adap->name,
+ iop3xx_adap ) ){
+ return -ENODEV;
+ }
+
+/* register new iic_adapter to i2c module... */
+
+ iic_adap->id |= iic_algo.id;
+ iic_adap->algo = &iic_algo;
+
+ iic_adap->timeout = 100; /* default values, should */
+ iic_adap->retries = 3; /* be replaced by defines */
+
+ iop3xx_adap_init( iic_adap->algo_data );
+ i2c_add_adapter(iic_adap);
+ return 0;
+}
+
+
+static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+
+ iop3xx_adap_final_cleanup( iop3xx_adap );
+ free_irq( iop3xx_adap->biu->irq, iop3xx_adap );
+
+ release_region( REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
+
+ return i2c_del_adapter( iic_adap );
+}
+
+#ifdef CONFIG_ARCH_IOP321
+
+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
+};
+
+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
+};
+
+#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "
+#else
+#error Please define the BIU struct iop3xx_biu for your processor arch
+#endif
+
+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
+};
+
+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
+};
+
+static int __init i2c_iop3xx_init (void)
+{
+ return i2c_iop3xx_add_bus(&iop3xx_ops0) ||
+ i2c_iop3xx_add_bus(&iop3xx_ops1);
+}
+
+static void __exit i2c_iop3xx_exit (void)
+{
+ i2c_iop3xx_del_bus(&iop3xx_ops0);
+ i2c_iop3xx_del_bus(&iop3xx_ops1);
+}
+
+module_init (i2c_iop3xx_init);
+module_exit (i2c_iop3xx_exit);
+
+MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
+MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(i2c_debug,"i");
+
+MODULE_PARM_DESC(i2c_debug,
+ "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
+
diff -Nru a/drivers/i2c/i2c-iop3xx.h b/drivers/i2c/i2c-iop3xx.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/i2c-iop3xx.h Wed Jun 11 13:25:23 2003
@@ -0,0 +1,120 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-iop3xx.h algorithm driver definitions private to i2c-iop3xx.c */
+/* ------------------------------------------------------------------------- */
+/* 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. */
+/* ------------------------------------------------------------------------- */
+
+
+#ifndef I2C_IOP3XX_H
+#define I2C_IOP3XX_H 1
+
+/*
+ * 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 */
+/*
+ * IOP321_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 */
+/*
+ * "NOTE: To avoid I2C bus integrity problems,
+ * the user needs to ensure that the GPIO Output Data Register -
+ * GPOD bits associated with an I2C port are cleared prior to setting
+ * the enable bit for that I2C serial port.
+ * 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
+ * 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 IOP321_IDBR_MASK 0x00ff
+
+#define IOP321_IBMR_SCL 0x0002
+#define IOP321_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 MYSAR 0x02 /* SWAG a suitable slave address */
+
+#define I2C_ERR 321
+#define I2C_ERR_BERR (I2C_ERR+0)
+#define I2C_ERR_ALD (I2C_ERR+1)
+
+
+typedef volatile u32* r32;
+
+struct iop3xx_biu { /* Bus Interface Unit - the hardware */
+/* physical hardware defs - regs*/
+ r32 CR;
+ r32 SR;
+ r32 SAR;
+ r32 DBR;
+ r32 BMR;
+/* irq bit vector */
+ u32 irq;
+/* stored flags */
+ u32 SR_enabled, SR_received;
+};
+
+struct i2c_algo_iop3xx_data {
+ int channel;
+
+ wait_queue_head_t waitq;
+ spinlock_t lock;
+ int timeout;
+ struct iop3xx_biu* biu;
+};
+
+#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 */
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-06-11 20:36 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.7, 2003/06/11 12:29:31-07:00, greg@kroah.com
[PATCH] I2C: fix up sparse warnings in drivers/i2c/i2c-core.c
drivers/i2c/i2c-core.c | 36 ++++++++++++++----------------------
1 files changed, 14 insertions(+), 22 deletions(-)
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Wed Jun 11 13:24:53 2003
+++ b/drivers/i2c/i2c-core.c Wed Jun 11 13:24:53 2003
@@ -510,7 +510,7 @@
msg.addr = client->addr;
msg.flags = client->flags & I2C_M_TEN;
msg.len = count;
- (const char *)msg.buf = buf;
+ msg.buf = (char *)buf;
DEB2(dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
count));
@@ -861,13 +861,13 @@
return 0;
}
-extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value)
+s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value)
{
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
value,0,I2C_SMBUS_QUICK,NULL);
}
-extern s32 i2c_smbus_read_byte(struct i2c_client * client)
+s32 i2c_smbus_read_byte(struct i2c_client *client)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -877,14 +877,14 @@
return 0x0FF & data.byte;
}
-extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value)
+s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
{
union i2c_smbus_data data; /* only for PEC */
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
}
-extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
+s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -894,8 +894,7 @@
return 0x0FF & data.byte;
}
-extern s32 i2c_smbus_write_byte_data(struct i2c_client * client, u8 command,
- u8 value)
+s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
{
union i2c_smbus_data data;
data.byte = value;
@@ -904,7 +903,7 @@
I2C_SMBUS_BYTE_DATA,&data);
}
-extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command)
+s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -914,8 +913,7 @@
return 0x0FFFF & data.word;
}
-extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
- u8 command, u16 value)
+s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
{
union i2c_smbus_data data;
data.word = value;
@@ -924,8 +922,7 @@
I2C_SMBUS_WORD_DATA,&data);
}
-extern s32 i2c_smbus_process_call(struct i2c_client * client,
- u8 command, u16 value)
+s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value)
{
union i2c_smbus_data data;
data.word = value;
@@ -938,8 +935,7 @@
}
/* Returns the number of read bytes */
-extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
- u8 command, u8 *values)
+s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -954,8 +950,7 @@
}
}
-extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
- u8 command, u8 length, u8 *values)
+s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -970,8 +965,7 @@
}
/* Returns the number of read bytes */
-extern s32 i2c_smbus_block_process_call(struct i2c_client * client,
- u8 command, u8 length, u8 *values)
+s32 i2c_smbus_block_process_call(struct i2c_client *client, u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -990,8 +984,7 @@
}
/* Returns the number of read bytes */
-extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
- u8 command, u8 *values)
+s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -1006,8 +999,7 @@
}
}
-extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
- u8 command, u8 length, u8 *values)
+s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-06-11 20:36 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.8, 2003/06/11 12:29:42-07:00, greg@kroah.com
[PATCH] I2C: fix up sparse warnings in the i2c-dev driver
drivers/i2c/i2c-dev.c | 10 +++++-----
include/linux/i2c-dev.h | 6 +++---
2 files changed, 8 insertions(+), 8 deletions(-)
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c Wed Jun 11 13:24:43 2003
+++ b/drivers/i2c/i2c-dev.c Wed Jun 11 13:24:43 2003
@@ -122,7 +122,7 @@
}
static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
+static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
loff_t *offset)
{
char *tmp;
@@ -147,7 +147,7 @@
return ret;
}
-static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
+static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t count,
loff_t *offset)
{
int ret;
@@ -211,12 +211,12 @@
return 0;
case I2C_FUNCS:
funcs = i2c_get_functionality(client->adapter);
- return (copy_to_user((unsigned long *)arg,&funcs,
+ return (copy_to_user((unsigned long __user *)arg, &funcs,
sizeof(unsigned long)))?-EFAULT:0;
case I2C_RDWR:
if (copy_from_user(&rdwr_arg,
- (struct i2c_rdwr_ioctl_data *)arg,
+ (struct i2c_rdwr_ioctl_data __user *)arg,
sizeof(rdwr_arg)))
return -EFAULT;
@@ -284,7 +284,7 @@
case I2C_SMBUS:
if (copy_from_user(&data_arg,
- (struct i2c_smbus_ioctl_data *) arg,
+ (struct i2c_smbus_ioctl_data __user *) arg,
sizeof(struct i2c_smbus_ioctl_data)))
return -EFAULT;
if ((data_arg.size != I2C_SMBUS_BYTE) &&
diff -Nru a/include/linux/i2c-dev.h b/include/linux/i2c-dev.h
--- a/include/linux/i2c-dev.h Wed Jun 11 13:24:43 2003
+++ b/include/linux/i2c-dev.h Wed Jun 11 13:24:43 2003
@@ -34,13 +34,13 @@
__u8 read_write;
__u8 command;
__u32 size;
- union i2c_smbus_data *data;
+ union i2c_smbus_data __user *data;
};
/* This is the structure as used in the I2C_RDWR ioctl call */
struct i2c_rdwr_ioctl_data {
- struct i2c_msg *msgs; /* pointers to i2c_msgs */
- __u32 nmsgs; /* number of i2c_msgs */
+ struct i2c_msg __user *msgs; /* pointers to i2c_msgs */
+ __u32 nmsgs; /* number of i2c_msgs */
};
#endif /* _LINUX_I2C_DEV_H */
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.70
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-06-11 20:36 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.3, 2003/06/11 11:42:47-07:00, margitsw@t-online.de
[PATCH] I2C: add LM85 driver
Nothing extra in sysfs (yet) but I have left the way open in the driver
to do this.
Provides vid, vrm, fan_input(1-4), fan_min(1-4), pwm(1-3),
pwm_enable(1-3), in_input(0-4), in_min(0-4), in_max(0-4),
temp_input(1-3), temp_min(1-3), temp_max(1-3), alarms.
drivers/i2c/chips/Kconfig | 19
drivers/i2c/chips/Makefile | 1
drivers/i2c/chips/lm85.c | 1223 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1241 insertions(+), 2 deletions(-)
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig Wed Jun 11 13:25:33 2003
+++ b/drivers/i2c/chips/Kconfig Wed Jun 11 13:25:33 2003
@@ -47,6 +47,21 @@
in the lm_sensors package, which you can download at
http://www.lm-sensors.nu
+config SENSORS_LM85
+ tristate " National Semiconductors LM85 and compatibles"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for National Semiconductor LM85
+ sensor chips and clones: ADT7463 and ADM1027.
+ This can also be built as a module which can be inserted and
+ removed while the kernel is running.
+
+ The module will be called lm85.
+
+ You will also need the latest user-space utilties: you can find them
+ in the lm_sensors package, which you can download at
+ http://www.lm-sensors.nu
+
config SENSORS_VIA686A
tristate " VIA686A"
depends on I2C && EXPERIMENTAL
@@ -76,8 +91,8 @@
config I2C_SENSOR
tristate
- default y if SENSORS_ADM1021=y || SENSORS_IT87=y || SENSORS_LM75=y || SENSORS_VIA686A=y || SENSORS_W83781D=y
- default m if SENSORS_ADM1021=m || SENSORS_IT87=m || SENSORS_LM75=m || SENSORS_VIA686A=m || SENSORS_W83781D=m
+ default y if SENSORS_ADM1021=y || SENSORS_IT87=y || SENSORS_LM75=y || SENSORS_VIA686A=y || SENSORS_W83781D=y || SENSORS_LM85=y
+ default m if SENSORS_ADM1021=m || SENSORS_IT87=m || SENSORS_LM75=m || SENSORS_VIA686A=m || SENSORS_W83781D=m || SENSORS_LM85=m
default n
endmenu
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile Wed Jun 11 13:25:33 2003
+++ b/drivers/i2c/chips/Makefile Wed Jun 11 13:25:33 2003
@@ -5,5 +5,6 @@
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
+obj-$(CONFIG_SENSORS_LM85) += lm85.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/chips/lm85.c Wed Jun 11 13:25:33 2003
@@ -0,0 +1,1223 @@
+/*
+ lm85.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
+ Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
+ Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de>
+
+ Chip details at <http://www.national.com/ds/LM/LM85.pdf>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+/*
+#include <asm/io.h>
+*/
+
+#undef LM85EXTENDEDFUNC /* Extended functionality */
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_4(lm85b, lm85c, adm1027, adt7463);
+
+/* Enable debug if true */
+static int lm85debug = 0;
+
+/* The LM85 registers */
+
+#define LM85_REG_IN(nr) (0x20 + (nr))
+#define LM85_REG_IN_MIN(nr) (0x44 + (nr) * 2)
+#define LM85_REG_IN_MAX(nr) (0x45 + (nr) * 2)
+
+#define LM85_REG_TEMP(nr) (0x25 + (nr))
+#define LM85_REG_TEMP_MIN(nr) (0x4e + (nr) * 2)
+#define LM85_REG_TEMP_MAX(nr) (0x4f + (nr) * 2)
+
+/* Fan speeds are LSB, MSB (2 bytes) */
+#define LM85_REG_FAN(nr) (0x28 + (nr) *2)
+#define LM85_REG_FAN_MIN(nr) (0x54 + (nr) *2)
+
+#define LM85_REG_PWM(nr) (0x30 + (nr))
+
+#define ADT7463_REG_OPPOINT(nr) (0x33 + (nr))
+
+#define ADT7463_REG_TMIN_CTL1 0x36
+#define ADT7463_REG_TMIN_CTL2 0x37
+
+#define LM85_REG_DEVICE 0x3d
+#define LM85_REG_COMPANY 0x3e
+#define LM85_REG_VERSTEP 0x3f
+/* These are the recognized values for the above regs */
+#define LM85_DEVICE_ADX 0x27
+#define LM85_COMPANY_NATIONAL 0x01
+#define LM85_COMPANY_ANALOG_DEV 0x41
+#define LM85_VERSTEP_GENERIC 0x60
+#define LM85_VERSTEP_LM85C 0x60
+#define LM85_VERSTEP_LM85B 0x62
+#define LM85_VERSTEP_ADM1027 0x60
+#define LM85_VERSTEP_ADT7463 0x62
+
+#define LM85_REG_CONFIG 0x40
+
+#define LM85_REG_ALARM1 0x41
+#define LM85_REG_ALARM2 0x42
+
+#define LM85_REG_VID 0x43
+
+/* Automated FAN control */
+#define LM85_REG_AFAN_CONFIG(nr) (0x5c + (nr))
+#define LM85_REG_AFAN_RANGE(nr) (0x5f + (nr))
+#define LM85_REG_AFAN_SPIKE1 0x62
+#define LM85_REG_AFAN_SPIKE2 0x63
+#define LM85_REG_AFAN_MINPWM(nr) (0x64 + (nr))
+#define LM85_REG_AFAN_LIMIT(nr) (0x67 + (nr))
+#define LM85_REG_AFAN_CRITICAL(nr) (0x6a + (nr))
+#define LM85_REG_AFAN_HYST1 0x6d
+#define LM85_REG_AFAN_HYST2 0x6e
+
+#define LM85_REG_TACH_MODE 0x74
+#define LM85_REG_SPINUP_CTL 0x75
+
+#define ADM1027_REG_TEMP_OFFSET(nr) (0x70 + (nr))
+#define ADM1027_REG_CONFIG2 0x73
+#define ADM1027_REG_INTMASK1 0x74
+#define ADM1027_REG_INTMASK2 0x75
+#define ADM1027_REG_EXTEND_ADC1 0x76
+#define ADM1027_REG_EXTEND_ADC2 0x77
+#define ADM1027_REG_CONFIG3 0x78
+#define ADM1027_REG_FAN_PPR 0x7b
+
+#define ADT7463_REG_THERM 0x79
+#define ADT7463_REG_THERM_LIMIT 0x7A
+
+#define LM85_ALARM_IN0 0x0001
+#define LM85_ALARM_IN1 0x0002
+#define LM85_ALARM_IN2 0x0004
+#define LM85_ALARM_IN3 0x0008
+#define LM85_ALARM_TEMP1 0x0010
+#define LM85_ALARM_TEMP2 0x0020
+#define LM85_ALARM_TEMP3 0x0040
+#define LM85_ALARM_ALARM2 0x0080
+#define LM85_ALARM_IN4 0x0100
+#define LM85_ALARM_RESERVED 0x0200
+#define LM85_ALARM_FAN1 0x0400
+#define LM85_ALARM_FAN2 0x0800
+#define LM85_ALARM_FAN3 0x1000
+#define LM85_ALARM_FAN4 0x2000
+#define LM85_ALARM_TEMP1_FAULT 0x4000
+#define LM85_ALARM_TEMP3_FAULT 0x8000
+
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+ variants. Note that you should be a bit careful with which arguments
+ these macros are called: arguments may be evaluated more than once.
+ */
+
+/* IN are scaled 1.000 == 0xc0, mag = 3 */
+#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*0xc0+500)/1000),0,255))
+#define INEXT_FROM_REG(val,ext) (((val)*1000 + (ext)*250 + 96)/0xc0)
+#define IN_FROM_REG(val) (INEXT_FROM_REG(val,0))
+
+/* IN are scaled acording to built-in resistors */
+static int lm85_scaling[] = { /* .001 Volts */
+ 2500, 2250, 3300, 5000, 12000
+ };
+#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from))
+#define INS_TO_REG(n,val) (SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255))
+#define INSEXT_FROM_REG(n,val,ext) (SCALE((val)*4 + (ext),192*4,lm85_scaling[n]))
+/*
+#define INS_FROM_REG(n,val) (INSEXT_FROM_REG(n,val,0))
+*/
+#define INS_FROM_REG(n,val) ( ( (val*4*lm85_scaling[n]) + (192*4/2) ) / (192*4) )
+
+/* FAN speed is measured using 90kHz clock */
+#define FAN_TO_REG(val) (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534))
+#define FAN_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:5400000/(val))
+
+/* Temperature is reported in .01 degC increments */
+#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+50)/100,-127,127))
+#define TEMPEXT_FROM_REG(val,ext) ((val)*100 + (ext)*25)
+#define TEMP_FROM_REG(val) (TEMPEXT_FROM_REG(val,0))
+#define EXTTEMP_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
+
+#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
+#define PWM_FROM_REG(val) (val)
+
+#define EXT_FROM_REG(val,sensor) (((val)>>(sensor * 2))&0x03)
+
+#ifdef LM85EXTENDEDFUNC /* Extended functionality */
+
+/* ZONEs have the following parameters:
+ * Limit (low) temp, 1. degC
+ * Hysteresis (below limit), 1. degC (0-15)
+ * Range of speed control, .1 degC (2-80)
+ * Critical (high) temp, 1. degC
+ *
+ * FAN PWMs have the following parameters:
+ * Reference Zone, 1, 2, 3, etc.
+ * Spinup time, .05 sec
+ * PWM value at limit/low temp, 1 count
+ * PWM Frequency, 1. Hz
+ * PWM is Min or OFF below limit, flag
+ * Invert PWM output, flag
+ *
+ * Some chips filter the temp, others the fan.
+ * Filter constant (or disabled) .1 seconds
+ */
+
+/* These are the zone temperature range encodings */
+static int lm85_range_map[] = { /* .1 degC */
+ 20, 25, 33, 40, 50, 66,
+ 80, 100, 133, 160, 200, 266,
+ 320, 400, 533, 800
+ };
+static int RANGE_TO_REG( int range )
+{
+ int i;
+
+ if( range >= lm85_range_map[15] ) { return 15 ; }
+ for( i = 0 ; i < 15 ; ++i )
+ if( range <= lm85_range_map[i] )
+ break ;
+ return( i & 0x0f );
+}
+#define RANGE_FROM_REG(val) (lm85_range_map[(val)&0x0f])
+
+/* These are the Acoustic Enhancement, or Temperature smoothing encodings
+ * NOTE: The enable/disable bit is INCLUDED in these encodings as the
+ * MSB (bit 3, value 8). If the enable bit is 0, the encoded value
+ * is ignored, or set to 0.
+ */
+static int lm85_smooth_map[] = { /* .1 sec */
+ 350, 176, 118, 70, 44, 30, 16, 8
+/* 35.4 * 1/1, 1/2, 1/3, 1/5, 1/8, 1/12, 1/24, 1/48 */
+ };
+static int SMOOTH_TO_REG( int smooth )
+{
+ int i;
+
+ if( smooth <= 0 ) { return 0 ; } /* Disabled */
+ for( i = 0 ; i < 7 ; ++i )
+ if( smooth >= lm85_smooth_map[i] )
+ break ;
+ return( (i & 0x07) | 0x08 );
+}
+#define SMOOTH_FROM_REG(val) ((val)&0x08?lm85_smooth_map[(val)&0x07]:0)
+
+/* These are the fan spinup delay time encodings */
+static int lm85_spinup_map[] = { /* .1 sec */
+ 0, 1, 2, 4, 7, 10, 20, 40
+ };
+static int SPINUP_TO_REG( int spinup )
+{
+ int i;
+
+ if( spinup >= lm85_spinup_map[7] ) { return 7 ; }
+ for( i = 0 ; i < 7 ; ++i )
+ if( spinup <= lm85_spinup_map[i] )
+ break ;
+ return( i & 0x07 );
+}
+#define SPINUP_FROM_REG(val) (lm85_spinup_map[(val)&0x07])
+
+/* These are the PWM frequency encodings */
+static int lm85_freq_map[] = { /* .1 Hz */
+ 100, 150, 230, 300, 380, 470, 620, 980
+ };
+static int FREQ_TO_REG( int freq )
+{
+ int i;
+
+ if( freq >= lm85_freq_map[7] ) { return 7 ; }
+ for( i = 0 ; i < 7 ; ++i )
+ if( freq <= lm85_freq_map[i] )
+ break ;
+ return( i & 0x07 );
+}
+#define FREQ_FROM_REG(val) (lm85_freq_map[(val)&0x07])
+
+/* Since we can't use strings, I'm abusing these numbers
+ * to stand in for the following meanings:
+ * 1 -- PWM responds to Zone 1
+ * 2 -- PWM responds to Zone 2
+ * 3 -- PWM responds to Zone 3
+ * 23 -- PWM responds to the higher temp of Zone 2 or 3
+ * 123 -- PWM responds to highest of Zone 1, 2, or 3
+ * 0 -- PWM is always at 0% (ie, off)
+ * -1 -- PWM is always at 100%
+ * -2 -- PWM responds to manual control
+ */
+
+#endif /* Extended functionality */
+
+static int lm85_zone_map[] = { 1, 2, 3, -1, 0, 23, 123, -2 };
+#define ZONE_FROM_REG(val) (lm85_zone_map[((val)>>5)&0x07])
+
+#ifdef LM85EXTENDEDFUNC /* Extended functionality */
+
+static int ZONE_TO_REG( int zone )
+{
+ int i;
+
+ for( i = 0 ; i <= 7 ; ++i )
+ if( zone == lm85_zone_map[i] )
+ break ;
+ if( i > 7 ) /* Not found. */
+ i = 3; /* Always 100% */
+ return( (i & 0x07)<<5 );
+}
+
+#endif /* Extended functionality */
+
+#define HYST_TO_REG(val) (SENSORS_LIMIT((-(val)+5)/10,0,15))
+#define HYST_FROM_REG(val) (-(val)*10)
+
+#define OFFSET_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
+#define OFFSET_FROM_REG(val) ((val)*25)
+
+#define PPR_MASK(fan) (0x03<<(fan *2))
+#define PPR_TO_REG(val,fan) (SENSORS_LIMIT((val)-1,0,3)<<(fan *2))
+#define PPR_FROM_REG(val,fan) ((((val)>>(fan * 2))&0x03)+1)
+
+/* i2c-vid.h defines vid_from_reg() */
+#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
+
+#define ALARMS_FROM_REG(val) (val)
+
+/* Unlike some other drivers we DO NOT set initial limits. Use
+ * the config file to set limits. Some users have reported
+ * motherboards shutting down when we set limits in a previous
+ * version of the driver.
+ */
+
+/* Typically used with Pentium 4 systems v9.1 VRM spec */
+#define LM85_INIT_VRM 91
+
+/* Chip sampling rates
+ *
+ * Some sensors are not updated more frequently than once per second
+ * so it doesn't make sense to read them more often than that.
+ * We cache the results and return the saved data if the driver
+ * is called again before a second has elapsed.
+ *
+ * Also, there is significant configuration data for this chip
+ * given the automatic PWM fan control that is possible. There
+ * are about 47 bytes of config data to only 22 bytes of actual
+ * readings. So, we keep the config data up to date in the cache
+ * when it is written and only sample it once every 1 *minute*
+ */
+#define LM85_DATA_INTERVAL (HZ + HZ / 2)
+#define LM85_CONFIG_INTERVAL (1 * 60 * HZ)
+
+/* For each registered LM85, we need to keep some data in memory. That
+ data is pointed to by lm85_list[NR]->data. The structure itself is
+ dynamically allocated, at the same time when a new lm85 client is
+ allocated. */
+
+/* LM85 can automatically adjust fan speeds based on temperature
+ * This structure encapsulates an entire Zone config. There are
+ * three zones (one for each temperature input) on the lm85
+ */
+struct lm85_zone {
+ s8 limit; /* Low temp limit */
+ u8 hyst; /* Low limit hysteresis. (0-15) */
+ u8 range; /* Temp range, encoded */
+ s8 critical; /* "All fans ON" temp limit */
+};
+
+struct lm85_autofan {
+ u8 config; /* Register value */
+ u8 freq; /* PWM frequency, encoded */
+ u8 min_pwm; /* Minimum PWM value, encoded */
+ u8 min_off; /* Min PWM or OFF below "limit", flag */
+};
+
+struct lm85_data {
+ struct semaphore lock;
+ enum chips type;
+
+ struct semaphore update_lock;
+ int valid; /* !=0 if following fields are valid */
+ unsigned long last_reading; /* In jiffies */
+ unsigned long last_config; /* In jiffies */
+
+ u8 in[5]; /* Register value */
+ u8 in_max[5]; /* Register value */
+ u8 in_min[5]; /* Register value */
+ s8 temp[3]; /* Register value */
+ s8 temp_min[3]; /* Register value */
+ s8 temp_max[3]; /* Register value */
+ s8 temp_offset[3]; /* Register value */
+ u16 fan[4]; /* Register value */
+ u16 fan_min[4]; /* Register value */
+ u8 pwm[3]; /* Register value */
+ u8 spinup_ctl; /* Register encoding, combined */
+ u8 tach_mode; /* Register encoding, combined */
+ u16 extend_adc; /* Register value */
+ u8 fan_ppr; /* Register value */
+ u8 smooth[3]; /* Register encoding */
+ u8 vid; /* Register value */
+ u8 vrm; /* VRM version */
+ u8 syncpwm3; /* Saved PWM3 for TACH 2,3,4 config */
+ u8 oppoint[3]; /* Register value */
+ u16 tmin_ctl; /* Register value */
+ u32 therm_total; /* Cummulative therm count */
+ u8 therm_limit; /* Register value */
+ u16 alarms; /* Register encoding, combined */
+ struct lm85_autofan autofan[3];
+ struct lm85_zone zone[3];
+};
+
+static int lm85_attach_adapter(struct i2c_adapter *adapter);
+static int lm85_detect(struct i2c_adapter *adapter, int address,
+ int kind);
+static int lm85_detach_client(struct i2c_client *client);
+
+static int lm85_read_value(struct i2c_client *client, u8 register);
+static int lm85_write_value(struct i2c_client *client, u8 register, int value);
+static void lm85_update_client(struct i2c_client *client);
+static void lm85_init_client(struct i2c_client *client);
+
+
+static struct i2c_driver lm85_driver = {
+ .owner = THIS_MODULE,
+ .name = "lm85",
+ .id = I2C_DRIVERID_LM85,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = lm85_attach_adapter,
+ .detach_client = lm85_detach_client,
+};
+
+/* Unique ID assigned to each LM85 detected */
+static int lm85_id = 0;
+
+
+/* 4 Fans */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr]) );
+}
+static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr]) );
+}
+static ssize_t set_fan_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->fan_min[nr] = FAN_TO_REG(val);
+ lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]);
+ return count;
+}
+
+#define show_fan_offset(offset) \
+static ssize_t show_fan_##offset (struct device *dev, char *buf) \
+{ \
+ return show_fan(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_fan_min(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t set_fan_##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_fan_min(dev, buf, count, 0x##offset - 1); \
+} \
+static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_fan_##offset, NULL) \
+static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, \
+ show_fan_##offset##_min, set_fan_##offset##_min)
+
+show_fan_offset(1);
+show_fan_offset(2);
+show_fan_offset(3);
+show_fan_offset(4);
+
+/* vid, vrm, alarms */
+
+static ssize_t show_vid_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+}
+
+static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL)
+
+static ssize_t show_vrm_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf, "%ld\n", (long) data->vrm);
+}
+
+static ssize_t store_vrm_reg(struct device *dev, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->vrm = val;
+ return count;
+}
+
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg)
+
+static ssize_t show_alarms_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
+
+/* pwm */
+
+static ssize_t show_pwm(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm[nr]) );
+}
+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 lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->pwm[nr] = PWM_TO_REG(val);
+ lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]);
+ return count;
+}
+static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+ int pwm_zone;
+
+ lm85_update_client(client);
+ pwm_zone = ZONE_FROM_REG(data->autofan[nr].config);
+ return sprintf(buf,"%d\n", (pwm_zone != 0 && pwm_zone != -1) );
+}
+
+#define show_pwm_reg(offset) \
+static ssize_t show_pwm_##offset (struct device *dev, char *buf) \
+{ \
+ return show_pwm(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t set_pwm_##offset (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_pwm(dev, buf, count, 0x##offset - 1); \
+} \
+static ssize_t show_pwm_enable##offset (struct device *dev, char *buf) \
+{ \
+ return show_pwm_enable(dev, buf, 0x##offset - 1); \
+} \
+static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
+ show_pwm_##offset, set_pwm_##offset) \
+static DEVICE_ATTR(pwm_enable##offset, S_IRUGO, show_pwm_enable##offset, NULL)
+
+show_pwm_reg(1);
+show_pwm_reg(2);
+show_pwm_reg(3);
+
+/* Voltages */
+
+static ssize_t show_in(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]) );
+}
+static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]) );
+}
+static ssize_t set_in_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->in_min[nr] = INS_TO_REG(nr, val);
+ lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]);
+ return count;
+}
+static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]) );
+}
+static ssize_t set_in_max(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->in_max[nr] = INS_TO_REG(nr, val);
+ lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]);
+ return count;
+}
+#define show_in_reg(offset) \
+static ssize_t show_in_##offset (struct device *dev, char *buf) \
+{ \
+ return show_in(dev, buf, 0x##offset); \
+} \
+static ssize_t show_in_##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_in_min(dev, buf, 0x##offset); \
+} \
+static ssize_t show_in_##offset##_max (struct device *dev, char *buf) \
+{ \
+ return show_in_max(dev, buf, 0x##offset); \
+} \
+static ssize_t set_in_##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_in_min(dev, buf, count, 0x##offset); \
+} \
+static ssize_t set_in_##offset##_max (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_in_max(dev, buf, count, 0x##offset); \
+} \
+static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in_##offset, NULL) \
+static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \
+ show_in_##offset##_min, set_in_##offset##_min) \
+static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \
+ show_in_##offset##_max, set_in_##offset##_max)
+
+show_in_reg(0);
+show_in_reg(1);
+show_in_reg(2);
+show_in_reg(3);
+show_in_reg(4);
+
+/* Temps */
+
+static ssize_t show_temp(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]) );
+}
+static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]) );
+}
+static ssize_t set_temp_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->temp_min[nr] = TEMP_TO_REG(val);
+ lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]);
+ return count;
+}
+static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]) );
+}
+static ssize_t set_temp_max(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->temp_max[nr] = TEMP_TO_REG(val);
+ lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]);
+ return count;
+}
+#define show_temp_reg(offset) \
+static ssize_t show_temp_##offset (struct device *dev, char *buf) \
+{ \
+ return show_temp(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t show_temp_##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_temp_min(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t show_temp_##offset##_max (struct device *dev, char *buf) \
+{ \
+ return show_temp_max(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t set_temp_##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_temp_min(dev, buf, count, 0x##offset - 1); \
+} \
+static ssize_t set_temp_##offset##_max (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_temp_max(dev, buf, count, 0x##offset - 1); \
+} \
+static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_temp_##offset, NULL) \
+static DEVICE_ATTR(temp_min##offset, S_IRUGO | S_IWUSR, \
+ show_temp_##offset##_min, set_temp_##offset##_min) \
+static DEVICE_ATTR(temp_max##offset, S_IRUGO | S_IWUSR, \
+ show_temp_##offset##_max, set_temp_##offset##_max)
+
+show_temp_reg(1);
+show_temp_reg(2);
+show_temp_reg(3);
+
+
+int lm85_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, lm85_detect);
+}
+
+int lm85_detect(struct i2c_adapter *adapter, int address,
+ int kind)
+{
+ int company, verstep ;
+ struct i2c_client *new_client = NULL;
+ struct lm85_data *data;
+ int err = 0;
+ const char *type_name = "";
+
+ if (i2c_is_isa_adapter(adapter)) {
+ /* This chip has no ISA interface */
+ goto ERROR0 ;
+ };
+
+ if (!i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA)) {
+ /* We need to be able to do byte I/O */
+ goto ERROR0 ;
+ };
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access lm85_{read,write}_value. */
+
+ if (!(new_client = kmalloc((sizeof(struct i2c_client)) +
+ sizeof(struct lm85_data),
+ GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto ERROR0;
+ }
+
+ memset(new_client, 0, sizeof(struct i2c_client) +
+ sizeof(struct lm85_data));
+ data = (struct lm85_data *) (new_client + 1);
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &lm85_driver;
+ new_client->flags = 0;
+
+ /* Now, we do the remaining detection. */
+
+ company = lm85_read_value(new_client, LM85_REG_COMPANY);
+ verstep = lm85_read_value(new_client, LM85_REG_VERSTEP);
+
+ if (lm85debug) {
+ printk("lm85: Detecting device at %d,0x%02x with"
+ " COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
+ i2c_adapter_id(new_client->adapter), new_client->addr,
+ company, verstep);
+ }
+
+ /* If auto-detecting, Determine the chip type. */
+ if (kind <= 0) {
+ if (lm85debug) {
+ printk("lm85: Autodetecting device at %d,0x%02x ...\n",
+ i2c_adapter_id(adapter), address );
+ }
+ if( company == LM85_COMPANY_NATIONAL
+ && verstep == LM85_VERSTEP_LM85C ) {
+ kind = lm85c ;
+ } else if( company == LM85_COMPANY_NATIONAL
+ && verstep == LM85_VERSTEP_LM85B ) {
+ kind = lm85b ;
+ } else if( company == LM85_COMPANY_NATIONAL
+ && (verstep & 0xf0) == LM85_VERSTEP_GENERIC ) {
+ printk("lm85: Unrecgonized version/stepping 0x%02x"
+ " Defaulting to LM85.\n", verstep );
+ kind = any_chip ;
+ } else if( company == LM85_COMPANY_ANALOG_DEV
+ && verstep == LM85_VERSTEP_ADM1027 ) {
+ kind = adm1027 ;
+ } else if( company == LM85_COMPANY_ANALOG_DEV
+ && verstep == LM85_VERSTEP_ADT7463 ) {
+ kind = adt7463 ;
+ } else if( company == LM85_COMPANY_ANALOG_DEV
+ && (verstep & 0xf0) == LM85_VERSTEP_GENERIC ) {
+ printk("lm85: Unrecgonized version/stepping 0x%02x"
+ " Defaulting to ADM1027.\n", verstep );
+ kind = adm1027 ;
+ } else if( kind == 0 && (verstep & 0xf0) == 0x60) {
+ printk("lm85: Generic LM85 Version 6 detected\n");
+ /* Leave kind as "any_chip" */
+ } else {
+ if (lm85debug) {
+ printk("lm85: Autodetection failed\n");
+ }
+ /* Not an LM85 ... */
+ if( kind == 0 ) { /* User used force=x,y */
+ printk("lm85: Generic LM85 Version 6 not"
+ " found at %d,0x%02x. Try force_lm85c.\n",
+ i2c_adapter_id(adapter), address );
+ }
+ err = 0 ;
+ goto ERROR1;
+ }
+ }
+
+ /* Fill in the chip specific driver values */
+ if ( kind == any_chip ) {
+ type_name = "lm85";
+ strlcpy(new_client->dev.name, "Generic LM85", DEVICE_NAME_SIZE);
+ } else if ( kind == lm85b ) {
+ type_name = "lm85b";
+ strlcpy(new_client->dev.name, "National LM85-B", DEVICE_NAME_SIZE);
+ } else if ( kind == lm85c ) {
+ type_name = "lm85c";
+ strlcpy(new_client->dev.name, "National LM85-C", DEVICE_NAME_SIZE);
+ } else if ( kind == adm1027 ) {
+ type_name = "adm1027";
+ strlcpy(new_client->dev.name, "Analog Devices ADM1027", DEVICE_NAME_SIZE);
+ } else if ( kind == adt7463 ) {
+ type_name = "adt7463";
+ strlcpy(new_client->dev.name, "Analog Devices ADT7463", DEVICE_NAME_SIZE);
+ } else {
+ dev_dbg(&adapter->dev, "Internal error, invalid kind (%d)!", kind);
+ err = -EFAULT ;
+ goto ERROR1;
+ }
+
+ /* Fill in the remaining client fields */
+ new_client->id = lm85_id++;
+ data->type = kind;
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ if (lm85debug) {
+ printk("lm85: Assigning ID %d to %s at %d,0x%02x\n",
+ new_client->id, new_client->dev.name,
+ i2c_adapter_id(new_client->adapter),
+ new_client->addr);
+ }
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto ERROR1;
+
+ /* Set the VRM version */
+ data->vrm = LM85_INIT_VRM ;
+
+ device_create_file(&new_client->dev, &dev_attr_fan_input1);
+ device_create_file(&new_client->dev, &dev_attr_fan_input2);
+ device_create_file(&new_client->dev, &dev_attr_fan_input3);
+ device_create_file(&new_client->dev, &dev_attr_fan_input4);
+ device_create_file(&new_client->dev, &dev_attr_fan_min1);
+ device_create_file(&new_client->dev, &dev_attr_fan_min2);
+ device_create_file(&new_client->dev, &dev_attr_fan_min3);
+ device_create_file(&new_client->dev, &dev_attr_fan_min4);
+ device_create_file(&new_client->dev, &dev_attr_pwm1);
+ device_create_file(&new_client->dev, &dev_attr_pwm2);
+ device_create_file(&new_client->dev, &dev_attr_pwm3);
+ device_create_file(&new_client->dev, &dev_attr_pwm_enable1);
+ device_create_file(&new_client->dev, &dev_attr_pwm_enable2);
+ device_create_file(&new_client->dev, &dev_attr_pwm_enable3);
+ device_create_file(&new_client->dev, &dev_attr_in_input0);
+ device_create_file(&new_client->dev, &dev_attr_in_input1);
+ device_create_file(&new_client->dev, &dev_attr_in_input2);
+ device_create_file(&new_client->dev, &dev_attr_in_input3);
+ device_create_file(&new_client->dev, &dev_attr_in_input4);
+ device_create_file(&new_client->dev, &dev_attr_in_min0);
+ device_create_file(&new_client->dev, &dev_attr_in_min1);
+ device_create_file(&new_client->dev, &dev_attr_in_min2);
+ device_create_file(&new_client->dev, &dev_attr_in_min3);
+ device_create_file(&new_client->dev, &dev_attr_in_min4);
+ device_create_file(&new_client->dev, &dev_attr_in_max0);
+ device_create_file(&new_client->dev, &dev_attr_in_max1);
+ device_create_file(&new_client->dev, &dev_attr_in_max2);
+ device_create_file(&new_client->dev, &dev_attr_in_max3);
+ device_create_file(&new_client->dev, &dev_attr_in_max4);
+ device_create_file(&new_client->dev, &dev_attr_temp_input1);
+ device_create_file(&new_client->dev, &dev_attr_temp_input2);
+ device_create_file(&new_client->dev, &dev_attr_temp_input3);
+ device_create_file(&new_client->dev, &dev_attr_temp_min1);
+ device_create_file(&new_client->dev, &dev_attr_temp_min2);
+ device_create_file(&new_client->dev, &dev_attr_temp_min3);
+ device_create_file(&new_client->dev, &dev_attr_temp_max1);
+ device_create_file(&new_client->dev, &dev_attr_temp_max2);
+ device_create_file(&new_client->dev, &dev_attr_temp_max3);
+ device_create_file(&new_client->dev, &dev_attr_vrm);
+ device_create_file(&new_client->dev, &dev_attr_vid);
+ device_create_file(&new_client->dev, &dev_attr_alarms);
+
+ /* Initialize the LM85 chip */
+ lm85_init_client(new_client);
+ return 0;
+
+ /* Error out and cleanup code */
+ ERROR1:
+ kfree(new_client);
+ ERROR0:
+ return err;
+}
+
+int lm85_detach_client(struct i2c_client *client)
+{
+ i2c_detach_client(client);
+ kfree(client);
+ return 0;
+}
+
+
+int lm85_read_value(struct i2c_client *client, u8 reg)
+{
+ int res;
+
+ /* What size location is it? */
+ switch( reg ) {
+ case LM85_REG_FAN(0) : /* Read WORD data */
+ case LM85_REG_FAN(1) :
+ case LM85_REG_FAN(2) :
+ case LM85_REG_FAN(3) :
+ case LM85_REG_FAN_MIN(0) :
+ case LM85_REG_FAN_MIN(1) :
+ case LM85_REG_FAN_MIN(2) :
+ case LM85_REG_FAN_MIN(3) :
+ case LM85_REG_ALARM1 : /* Read both bytes at once */
+ case ADM1027_REG_EXTEND_ADC1 : /* Read two bytes at once */
+ res = i2c_smbus_read_byte_data(client, reg) & 0xff ;
+ res |= i2c_smbus_read_byte_data(client, reg+1) << 8 ;
+ break ;
+ case ADT7463_REG_TMIN_CTL1 : /* Read WORD MSB, LSB */
+ res = i2c_smbus_read_byte_data(client, reg) << 8 ;
+ res |= i2c_smbus_read_byte_data(client, reg+1) & 0xff ;
+ break ;
+ default: /* Read BYTE data */
+ res = i2c_smbus_read_byte_data(client, reg);
+ break ;
+ }
+
+ return res ;
+}
+
+int lm85_write_value(struct i2c_client *client, u8 reg, int value)
+{
+ int res ;
+
+ switch( reg ) {
+ case LM85_REG_FAN(0) : /* Write WORD data */
+ case LM85_REG_FAN(1) :
+ case LM85_REG_FAN(2) :
+ case LM85_REG_FAN(3) :
+ case LM85_REG_FAN_MIN(0) :
+ case LM85_REG_FAN_MIN(1) :
+ case LM85_REG_FAN_MIN(2) :
+ case LM85_REG_FAN_MIN(3) :
+ /* NOTE: ALARM is read only, so not included here */
+ res = i2c_smbus_write_byte_data(client, reg, value & 0xff) ;
+ res |= i2c_smbus_write_byte_data(client, reg+1, (value>>8) & 0xff) ;
+ break ;
+ case ADT7463_REG_TMIN_CTL1 : /* Write WORD MSB, LSB */
+ res = i2c_smbus_write_byte_data(client, reg, (value>>8) & 0xff);
+ res |= i2c_smbus_write_byte_data(client, reg+1, value & 0xff) ;
+ break ;
+ default: /* Write BYTE data */
+ res = i2c_smbus_write_byte_data(client, reg, value);
+ break ;
+ }
+
+ return res ;
+}
+
+void lm85_init_client(struct i2c_client *client)
+{
+ int value;
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ if (lm85debug) {
+ printk("lm85(%d): Initializing device\n", client->id);
+ }
+
+ /* Warn if part was not "READY" */
+ value = lm85_read_value(client, LM85_REG_CONFIG);
+ if (lm85debug) {
+ printk("lm85(%d): LM85_REG_CONFIG is: 0x%02x\n", client->id, value );
+ }
+ if( value & 0x02 ) {
+ printk("lm85(%d): Client (%d,0x%02x) config is locked.\n",
+ client->id,
+ i2c_adapter_id(client->adapter), client->addr );
+ };
+ if( ! (value & 0x04) ) {
+ printk("lm85(%d): Client (%d,0x%02x) is not ready.\n",
+ client->id,
+ i2c_adapter_id(client->adapter), client->addr );
+ };
+ if( value & 0x10
+ && ( data->type == adm1027
+ || data->type == adt7463 ) ) {
+ printk("lm85(%d): Client (%d,0x%02x) VxI mode is set. "
+ "Please report this to the lm85 maintainer.\n",
+ client->id,
+ i2c_adapter_id(client->adapter), client->addr );
+ };
+
+ /* WE INTENTIONALLY make no changes to the limits,
+ * offsets, pwms, fans and zones. If they were
+ * configured, we don't want to mess with them.
+ * If they weren't, the default is 100% PWM, no
+ * control and will suffice until 'sensors -s'
+ * can be run by the user.
+ */
+
+ /* Start monitoring */
+ value = lm85_read_value(client, LM85_REG_CONFIG);
+ /* Try to clear LOCK, Set START, save everything else */
+ value = (value & ~ 0x02) | 0x01 ;
+ if (lm85debug) {
+ printk("lm85(%d): Setting CONFIG to: 0x%02x\n", client->id, value );
+ }
+ lm85_write_value(client, LM85_REG_CONFIG, value);
+
+}
+
+void lm85_update_client(struct i2c_client *client)
+{
+ struct lm85_data *data = i2c_get_clientdata(client);
+ int i;
+
+ down(&data->update_lock);
+
+ if ( !data->valid ||
+ (jiffies - data->last_reading > LM85_DATA_INTERVAL ) ) {
+ /* Things that change quickly */
+
+ if (lm85debug) {
+ printk("lm85(%d): Reading sensor values\n", client->id);
+ }
+ /* Have to read extended bits first to "freeze" the
+ * more significant bits that are read later.
+ */
+ if ( (data->type == adm1027) || (data->type == adt7463) ) {
+ data->extend_adc =
+ lm85_read_value(client, ADM1027_REG_EXTEND_ADC1);
+ }
+
+ for (i = 0; i <= 4; ++i) {
+ data->in[i] =
+ lm85_read_value(client, LM85_REG_IN(i));
+ }
+
+ for (i = 0; i <= 3; ++i) {
+ data->fan[i] =
+ lm85_read_value(client, LM85_REG_FAN(i));
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ data->temp[i] =
+ lm85_read_value(client, LM85_REG_TEMP(i));
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ data->pwm[i] =
+ lm85_read_value(client, LM85_REG_PWM(i));
+ }
+
+ if ( data->type == adt7463 ) {
+ if( data->therm_total < ULONG_MAX - 256 ) {
+ data->therm_total +=
+ lm85_read_value(client, ADT7463_REG_THERM );
+ }
+ }
+
+ data->alarms = lm85_read_value(client, LM85_REG_ALARM1);
+
+ data->last_reading = jiffies ;
+ }; /* last_reading */
+
+ if ( !data->valid ||
+ (jiffies - data->last_config > LM85_CONFIG_INTERVAL) ) {
+ /* Things that don't change often */
+
+ if (lm85debug) {
+ printk("lm85(%d): Reading config values\n", client->id);
+ }
+ for (i = 0; i <= 4; ++i) {
+ data->in_min[i] =
+ lm85_read_value(client, LM85_REG_IN_MIN(i));
+ data->in_max[i] =
+ lm85_read_value(client, LM85_REG_IN_MAX(i));
+ }
+
+ for (i = 0; i <= 3; ++i) {
+ data->fan_min[i] =
+ lm85_read_value(client, LM85_REG_FAN_MIN(i));
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ data->temp_min[i] =
+ lm85_read_value(client, LM85_REG_TEMP_MIN(i));
+ data->temp_max[i] =
+ lm85_read_value(client, LM85_REG_TEMP_MAX(i));
+ }
+
+ data->vid = lm85_read_value(client, LM85_REG_VID);
+
+ for (i = 0; i <= 2; ++i) {
+ int val ;
+ data->autofan[i].config =
+ lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
+ val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
+ data->autofan[i].freq = val & 0x07 ;
+ data->zone[i].range = (val >> 4) & 0x0f ;
+ data->autofan[i].min_pwm =
+ lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
+ data->zone[i].limit =
+ lm85_read_value(client, LM85_REG_AFAN_LIMIT(i));
+ data->zone[i].critical =
+ lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i));
+ }
+
+ i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
+ data->smooth[0] = i & 0x0f ;
+ data->syncpwm3 = i & 0x10 ; /* Save PWM3 config */
+ data->autofan[0].min_off = (i & 0x20) != 0 ;
+ data->autofan[1].min_off = (i & 0x40) != 0 ;
+ data->autofan[2].min_off = (i & 0x80) != 0 ;
+ i = lm85_read_value(client, LM85_REG_AFAN_SPIKE2);
+ data->smooth[1] = (i>>4) & 0x0f ;
+ data->smooth[2] = i & 0x0f ;
+
+ i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
+ data->zone[0].hyst = (i>>4) & 0x0f ;
+ data->zone[1].hyst = i & 0x0f ;
+
+ i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
+ data->zone[2].hyst = (i>>4) & 0x0f ;
+
+ if ( (data->type == lm85b) || (data->type == lm85c) ) {
+ data->tach_mode = lm85_read_value(client,
+ LM85_REG_TACH_MODE );
+ data->spinup_ctl = lm85_read_value(client,
+ LM85_REG_SPINUP_CTL );
+ } else if ( (data->type == adt7463) || (data->type == adm1027) ) {
+ if ( data->type == adt7463 ) {
+ for (i = 0; i <= 2; ++i) {
+ data->oppoint[i] = lm85_read_value(client,
+ ADT7463_REG_OPPOINT(i) );
+ }
+ data->tmin_ctl = lm85_read_value(client,
+ ADT7463_REG_TMIN_CTL1 );
+ data->therm_limit = lm85_read_value(client,
+ ADT7463_REG_THERM_LIMIT );
+ }
+ for (i = 0; i <= 2; ++i) {
+ data->temp_offset[i] = lm85_read_value(client,
+ ADM1027_REG_TEMP_OFFSET(i) );
+ }
+ data->tach_mode = lm85_read_value(client,
+ ADM1027_REG_CONFIG3 );
+ data->fan_ppr = lm85_read_value(client,
+ ADM1027_REG_FAN_PPR );
+ }
+
+ data->last_config = jiffies;
+ }; /* last_config */
+
+ data->valid = 1;
+
+ up(&data->update_lock);
+}
+
+
+static int __init sm_lm85_init(void)
+{
+ return i2c_add_driver(&lm85_driver);
+}
+
+static void __exit sm_lm85_exit(void)
+{
+ i2c_del_driver(&lm85_driver);
+}
+
+/* Thanks to Richard Barrington for adding the LM85 to sensors-detect.
+ * Thanks to Margit Schubert-While <margitsw@t-online.de> for help with
+ * post 2.7.0 CVS changes
+ */
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, Margit Schubert-While <margitsw@t-online.de>");
+MODULE_DESCRIPTION("LM85-B, LM85-C driver");
+MODULE_PARM(lm85debug, "i");
+MODULE_PARM_DESC(lm85debug, "Enable debugging statements");
+
+module_init(sm_lm85_init);
+module_exit(sm_lm85_exit);
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2003-06-11 20:36 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.5, 2003/06/11 12:07:27-07:00, greg@kroah.com
[PATCH] I2C: coding style updates for i2c-iop3xx driver
drivers/i2c/i2c-iop3xx.c | 303 +++++++++++++++++++++--------------------------
drivers/i2c/i2c-iop3xx.h | 118 ++++++++----------
2 files changed, 195 insertions(+), 226 deletions(-)
diff -Nru a/drivers/i2c/i2c-iop3xx.c b/drivers/i2c/i2c-iop3xx.c
--- a/drivers/i2c/i2c-iop3xx.c Wed Jun 11 13:25:13 2003
+++ b/drivers/i2c/i2c-iop3xx.c Wed Jun 11 13:25:13 2003
@@ -50,8 +50,8 @@
/* ----- global defines ----------------------------------------------- */
#define PASSERT(x) do { if (!(x) ) \
- printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\
- } while (0)
+ printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\
+ } while (0)
/* ----- global variables --------------------------------------------- */
@@ -61,13 +61,13 @@
{
unsigned char addr;
- addr = ( msg->addr << 1 );
+ addr = (msg->addr << 1);
- if (msg->flags & I2C_M_RD )
+ if (msg->flags & I2C_M_RD)
addr |= 1;
-/* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
- if (msg->flags & I2C_M_REV_DIR_ADDR )
+ /* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
+ if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
return addr;
@@ -76,100 +76,93 @@
static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
- // Follows devman 9.3
+ /* Follows devman 9.3 */
*iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET;
*iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS;
*iop3xx_adap->biu->CR = 0;
}
-static inline void iop3xx_adap_set_slave_addr(
- struct i2c_algo_iop3xx_data *iop3xx_adap )
+static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
*iop3xx_adap->biu->SAR = MYSAR;
}
-static inline void iop3xx_adap_enable(
- struct i2c_algo_iop3xx_data *iop3xx_adap )
+static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE;
-/* NB SR bits not same position as CR IE bits :-( */
+ /* 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;
+ IOP321_ISR_ALD | IOP321_ISR_BERRD |
+ IOP321_ISR_RXFULL | IOP321_ISR_TXEMPTY;
- cr |= IOP321_ICR_ALDIE|IOP321_ICR_BERRIE|
- IOP321_ICR_RXFULLIE|IOP321_ICR_TXEMPTYIE;
+ cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
+ IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE;
*iop3xx_adap->biu->CR = cr;
}
-static void iop3xx_adap_transaction_cleanup(
- struct i2c_algo_iop3xx_data *iop3xx_adap )
+static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
unsigned cr = *iop3xx_adap->biu->CR;
cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE |
- IOP321_ICR_MSTOP | IOP321_ICR_SCLEN );
+ IOP321_ICR_MSTOP | IOP321_ICR_SCLEN);
*iop3xx_adap->biu->CR = cr;
}
-static void iop3xx_adap_final_cleanup(
- struct i2c_algo_iop3xx_data *iop3xx_adap )
+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);
+ cr &= ~(IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
+ IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE);
iop3xx_adap->biu->SR_enabled = 0;
*iop3xx_adap->biu->CR = cr;
}
-
-
-static void iop3xx_i2c_handler( int this_irq,
- void *dev_id,
- struct pt_regs *regs)
/*
* NB: the handler has to clear the source of the interrupt!
* Then it passes the SR flags of interest to BH via adap data
*/
+static void iop3xx_i2c_handler(int this_irq,
+ void *dev_id,
+ struct pt_regs *regs)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
u32 sr = *iop3xx_adap->biu->SR;
- if ( (sr &= iop3xx_adap->biu->SR_enabled) ){
+ if ((sr &= iop3xx_adap->biu->SR_enabled)) {
*iop3xx_adap->biu->SR = sr;
iop3xx_adap->biu->SR_received |= sr;
wake_up_interruptible(&iop3xx_adap->waitq);
}
}
-
-static int iop3xx_adap_error( u32 sr )
-// check all error conditions, clear them , report most important
+/* check all error conditions, clear them , report most important */
+static int iop3xx_adap_error(u32 sr)
{
int rc = 0;
- if ( (sr&IOP321_ISR_BERRD) ) {
+ if ((sr&IOP321_ISR_BERRD)) {
if ( !rc ) rc = -I2C_ERR_BERR;
}
- if ( (sr&IOP321_ISR_ALD) ){
+ if ((sr&IOP321_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 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
unsigned long flags;
u32 sr;
- spin_lock_irqsave( &iop3xx_adap->lock, flags );
+ spin_lock_irqsave(&iop3xx_adap->lock, flags);
sr = iop3xx_adap->biu->SR_received;
iop3xx_adap->biu->SR_received = 0;
- spin_unlock_irqrestore( &iop3xx_adap->lock, flags );
+ spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
return sr;
}
@@ -178,12 +171,12 @@
* sleep until interrupted, then recover and analyse the SR
* saved by handler
*/
-typedef int (* CompareFunc)( unsigned test, unsigned mask );
+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,
- CompareFunc compare )
+static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ unsigned flags, unsigned* status,
+ compare_func compare)
{
unsigned sr = 0;
int interrupted;
@@ -196,100 +189,94 @@
(done = compare( sr = get_srstat(iop3xx_adap),flags )),
iop3xx_adap->timeout
);
- if ( (rc = iop3xx_adap_error( sr )) < 0 ){
+ if ((rc = iop3xx_adap_error(sr)) < 0) {
*status = sr;
return rc;
- }else if ( !interrupted ){
+ }else if (!interrupted) {
*status = sr;
return rc = -ETIMEDOUT;
}
- } while( !done );
+ } while(!done);
*status = sr;
return rc = 0;
}
-
-
-
/*
- * Concrete CompareFuncs
+ * Concrete compare_funcs
*/
-static int all_bits_clear( unsigned test, unsigned mask ) {
- return (test&mask) == 0;
+static int all_bits_clear(unsigned test, unsigned mask)
+{
+ return (test & mask) == 0;
}
-static int any_bits_set( unsigned test, unsigned mask ) {
- return (test&mask) != 0;
+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_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
return iop3xx_adap_wait_event(
iop3xx_adap,
IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD,
- status, any_bits_set );
+ status, any_bits_set);
}
-static int iop3xx_adap_wait_rx_done(
- struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
return iop3xx_adap_wait_event(
iop3xx_adap,
IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD,
- status, any_bits_set );
+ status, any_bits_set);
}
-static int iop3xx_adap_wait_idle(
- struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+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 );
+ iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear);
}
-//
-// Description: This performs the IOP3xx initialization sequence
-// Valid for IOP321. Maybe valid for IOP310?.
-//
+/*
+ * 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)
{
- *IOP321_GPOD &= ~(iop3xx_adap->channel==0?
+ *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 );
+ iop3xx_adap_reset(iop3xx_adap);
+ iop3xx_adap_set_slave_addr(iop3xx_adap);
+ iop3xx_adap_enable(iop3xx_adap);
return 0;
}
-static int iop3xx_adap_send_target_slave_addr(
- struct i2c_algo_iop3xx_data *iop3xx_adap, struct i2c_msg* msg )
+static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ struct i2c_msg* msg)
{
unsigned cr = *iop3xx_adap->biu->CR;
int status;
int rc;
- *iop3xx_adap->biu->DBR = iic_cook_addr( msg );
+ *iop3xx_adap->biu->DBR = iic_cook_addr(msg);
- cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
+ cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK);
cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE;
*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 );
+ 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_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop)
{
unsigned cr = *iop3xx_adap->biu->CR;
int status;
@@ -297,19 +284,19 @@
*iop3xx_adap->biu->DBR = byte;
cr &= ~IOP321_ICR_MSTART;
- if ( stop ){
+ if (stop) {
cr |= IOP321_ICR_MSTOP;
- }else{
+ } else {
cr &= ~IOP321_ICR_MSTOP;
}
*iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
- rc = iop3xx_adap_wait_tx_done( iop3xx_adap, &status );
+ rc = iop3xx_adap_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_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ char* byte, int stop)
{
unsigned cr = *iop3xx_adap->biu->CR;
int status;
@@ -317,49 +304,46 @@
cr &= ~IOP321_ICR_MSTART;
- if ( stop ){
+ if (stop) {
cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;
- }else{
+ } else {
cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
}
*iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
- rc = iop3xx_adap_wait_rx_done( iop3xx_adap, &status );
+ rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status);
*byte = *iop3xx_adap->biu->DBR;
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 ){
+ for (ii = 0; rc == 0 && ii != count; ++ii) {
rc = iop3xx_adap_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 ){
+ for (ii = 0; rc == 0 && ii != count; ++ii) {
rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
}
return rc;
}
-
/*
* Description: This function implements combined transactions. Combined
* transactions consist of combinations of reading and writing blocks of data.
@@ -367,63 +351,55 @@
* 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_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 );
- if ( rc < 0 ){
+ rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg);
+ if (rc < 0) {
return rc;
}
- if ( (pmsg->flags&I2C_M_RD) ){
- return iop3xx_i2c_readbytes( i2c_adap, pmsg->buf, pmsg->len );
- }else{
- return iop3xx_i2c_writebytes( i2c_adap, pmsg->buf, pmsg->len );
+ if ((pmsg->flags&I2C_M_RD)) {
+ return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len);
+ } else {
+ return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len);
}
}
-
-
/*
* 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_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_adap_wait_idle(iop3xx_adap, &status);
+ iop3xx_adap_reset(iop3xx_adap);
+ iop3xx_adap_enable(iop3xx_adap);
- for ( im = 0; ret == 0 && im != num; ++im ){
- ret = iop3xx_handle_msg( i2c_adap, &msgs[im] );
+ for (im = 0; ret == 0 && im != num; ++im) {
+ ret = iop3xx_handle_msg(i2c_adap, &msgs[im]);
}
- iop3xx_adap_transaction_cleanup( iop3xx_adap );
+ iop3xx_adap_transaction_cleanup(iop3xx_adap);
return ret;
}
-
-
-static int algo_control(struct i2c_adapter *adapter,
- unsigned int cmd, unsigned long arg)
+static int algo_control(struct i2c_adapter *adapter, unsigned int cmd,
+ unsigned long arg)
{
return 0;
}
-
static u32 iic_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C|I2C_FUNC_SMBUS_EMUL;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
@@ -440,74 +416,70 @@
/*
* registering functions to load algorithms at runtime
*/
-
-
static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
- if ( !request_region( REGION_START(iop3xx_adap),
+ if (!request_region( REGION_START(iop3xx_adap),
REGION_LENGTH(iop3xx_adap),
- iic_adap->name ) ){
+ iic_adap->name)) {
return -ENODEV;
}
-
- init_waitqueue_head( &iop3xx_adap->waitq );
- spin_lock_init( &iop3xx_adap->lock );
- if ( request_irq(
+ init_waitqueue_head(&iop3xx_adap->waitq);
+ spin_lock_init(&iop3xx_adap->lock);
+
+ if (request_irq(
iop3xx_adap->biu->irq,
iop3xx_i2c_handler,
/* SA_SAMPLE_RANDOM */ 0,
iic_adap->name,
- iop3xx_adap ) ){
+ iop3xx_adap)) {
return -ENODEV;
}
-/* register new iic_adapter to i2c module... */
-
+ /* register new iic_adapter to i2c module... */
iic_adap->id |= iic_algo.id;
iic_adap->algo = &iic_algo;
- iic_adap->timeout = 100; /* default values, should */
- iic_adap->retries = 3; /* be replaced by defines */
+ iic_adap->timeout = 100; /* default values, should */
+ iic_adap->retries = 3; /* be replaced by defines */
- iop3xx_adap_init( iic_adap->algo_data );
+ iop3xx_adap_init(iic_adap->algo_data);
i2c_add_adapter(iic_adap);
return 0;
}
-
static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
- iop3xx_adap_final_cleanup( iop3xx_adap );
- free_irq( iop3xx_adap->biu->irq, iop3xx_adap );
+ iop3xx_adap_final_cleanup(iop3xx_adap);
+ free_irq(iop3xx_adap->biu->irq, iop3xx_adap);
- release_region( REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
+ release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
- return i2c_del_adapter( iic_adap );
+ return i2c_del_adapter(iic_adap);
}
#ifdef CONFIG_ARCH_IOP321
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
+ .CR = IOP321_ICR0,
+ .SR = IOP321_ISR0,
+ .SAR = IOP321_ISAR0,
+ .DBR = IOP321_IDBR0,
+ .BMR = IOP321_IBMR0,
+ .irq = IRQ_IOP321_I2C_0,
};
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
+ .CR = IOP321_ICR1,
+ .SR = IOP321_ISR1,
+ .SAR = IOP321_ISAR1,
+ .DBR = IOP321_IDBR1,
+ .BMR = IOP321_IBMR1,
+ .irq = IRQ_IOP321_I2C_1,
};
#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "
@@ -515,28 +487,28 @@
#error Please define the BIU struct iop3xx_biu for your processor arch
#endif
-static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = {
- .channel = 0,
- .biu = &biu0,
- .timeout = 1*HZ
+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
+static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = {
+ .channel = 1,
+ .biu = &biu1,
+ .timeout = 1*HZ,
};
static struct i2c_adapter iop3xx_ops0 = {
.owner = THIS_MODULE,
.name = ADAPTER_NAME_ROOT "0",
.id = I2C_HW_IOP321,
- .algo_data = &algo_iop3xx_data0
+ .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
+ .algo_data = &algo_iop3xx_data1,
};
static int __init i2c_iop3xx_init (void)
@@ -560,6 +532,5 @@
MODULE_PARM(i2c_debug,"i");
-MODULE_PARM_DESC(i2c_debug,
- "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
+MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
diff -Nru a/drivers/i2c/i2c-iop3xx.h b/drivers/i2c/i2c-iop3xx.h
--- a/drivers/i2c/i2c-iop3xx.h Wed Jun 11 13:25:13 2003
+++ b/drivers/i2c/i2c-iop3xx.h Wed Jun 11 13:25:13 2003
@@ -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 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 */
/*
* IOP321_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 IOP321_ICR_UE 0x0040 /* 1=Unit Enable */
/*
* "NOTE: To avoid I2C bus integrity problems,
* the user needs to ensure that the GPIO Output Data Register -
@@ -46,56 +46,54 @@
* the enable bit for that I2C serial port.
* 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
- * 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 IOP321_IDBR_MASK 0x00ff
-
-#define IOP321_IBMR_SCL 0x0002
-#define IOP321_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 MYSAR 0x02 /* SWAG a suitable slave address */
-
-#define I2C_ERR 321
-#define I2C_ERR_BERR (I2C_ERR+0)
-#define I2C_ERR_ALD (I2C_ERR+1)
-
+ */
+#define IOP321_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */
+#define IOP321_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 IOP321_IDBR_MASK 0x00ff
+
+#define IOP321_IBMR_SCL 0x0002
+#define IOP321_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 MYSAR 0x02 /* SWAG a suitable slave address */
+
+#define I2C_ERR 321
+#define I2C_ERR_BERR (I2C_ERR+0)
+#define I2C_ERR_ALD (I2C_ERR+1)
-typedef volatile u32* r32;
struct iop3xx_biu { /* Bus Interface Unit - the hardware */
/* physical hardware defs - regs*/
- r32 CR;
- r32 SR;
- r32 SAR;
- r32 DBR;
- r32 BMR;
+ u32 *CR;
+ u32 *SR;
+ u32 *SAR;
+ u32 *DBR;
+ u32 *BMR;
/* irq bit vector */
u32 irq;
/* stored flags */
@@ -111,10 +109,10 @@
struct iop3xx_biu* biu;
};
-#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 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)
+#define IRQ_STATUS_MASK(adap) (1<<adap->biu->irq)
#endif /* I2C_IOP3XX_H */
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
2005-05-19 6:23 ` Greg KH
@ 2005-05-19 6:23 ` Philip Pokorny
-1 siblings, 0 replies; 98+ messages in thread
From: Philip Pokorny @ 2003-06-12 2:40 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel, sensors
I think there is a race condition here in the "set" functions.
I had added a down()/up() semaphore pair to the write clauses of the
functions in the pre-sysfs driver to prevent the xx_update_client() call
from modifying the cached values at the same time that the set_xxx()
function was trying to change them.
So for example:
> static ssize_t set_temp_max(struct device *dev, const char *buf,
> size_t count, int nr)
> {
> struct i2c_client *client = to_i2c_client(dev);
> struct lm85_data *data = i2c_get_clientdata(client);
>
> int val = simple_strtol(buf, NULL, 10);
> + down(&data->update_lock);
> data->temp_max[nr] = TEMP_TO_REG(val);
> lm85_write_value(client, LM85_REG_TEMP_MAX(nr),
> data->temp_max[nr]);
> + up(&data->update_lock);
> return count;
> }
Isn't that still needed?
:v)
Greg KH wrote:
> ChangeSet 1.1419.1.3, 2003/06/11 11:42:47-07:00, margitsw@t-online.de
>
> [PATCH] I2C: add LM85 driver
>
> Nothing extra in sysfs (yet) but I have left the way open in the driver
> to do this.
> Provides vid, vrm, fan_input(1-4), fan_min(1-4), pwm(1-3),
> pwm_enable(1-3), in_input(0-4), in_min(0-4), in_max(0-4),
> temp_input(1-3), temp_min(1-3), temp_max(1-3), alarms.
>
>
> drivers/i2c/chips/Kconfig | 19
> drivers/i2c/chips/Makefile | 1
> drivers/i2c/chips/lm85.c | 1223 +++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 1241 insertions(+), 2 deletions(-)
>
> +static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct lm85_data *data = i2c_get_clientdata(client);
> +
> + lm85_update_client(client);
> + return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]) );
> +}
> +static ssize_t set_temp_max(struct device *dev, const char *buf,
> + size_t count, int nr)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct lm85_data *data = i2c_get_clientdata(client);
> +
> + int val = simple_strtol(buf, NULL, 10);
> + data->temp_max[nr] = TEMP_TO_REG(val);
> + lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]);
> + return count;
> +}
--
Philip Pokorny, Director of Engineering
Tel: 415-358-2635 Fax: 415-358-2646 Toll Free: 888-PENGUIN
PENGUIN COMPUTING, INC.
www.penguincomputing.com
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
@ 2003-06-12 9:16 Margit Schubert-While
0 siblings, 0 replies; 98+ messages in thread
From: Margit Schubert-While @ 2003-06-12 9:16 UTC (permalink / raw)
To: linux-kernel
> I think there is a race condition here in the "set" functions.
Hi Philip, long time no see :-)
Yes, you are right.
Will be sending a patch to Greg shortly.
Couple of other things have to be fixed as well.
Just realized that temp scaling is wrong.
Should be scaling by 1000 not 100.
(Gee, and that after I had mailed Greg that a couple of other sensors
get it wrong)
Margit
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
@ 2003-06-12 10:22 Margit Schubert-While
2003-06-16 18:42 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Margit Schubert-While @ 2003-06-12 10:22 UTC (permalink / raw)
To: linux-kernel; +Cc: Greg KH
[-- Attachment #1: Type: text/plain, Size: 154 bytes --]
OK Here's the patch which :
1) Fixes the race conditions
2) Correctly reports the temps :-)
3) Removes a bit of gunk in the defines which I forgot
Margit
[-- Attachment #2: lm85patch --]
[-- Type: application/octet-stream, Size: 4193 bytes --]
diff -Naur linux-2.5.70/drivers/i2c/chips/lm85.c linux-2.5.70mw/drivers/i2c/chips/lm85.c
--- linux-2.5.70/drivers/i2c/chips/lm85.c 2003-06-12 10:37:45.000000000 +0200
+++ linux-2.5.70mw/drivers/i2c/chips/lm85.c 2003-06-12 11:38:16.000000000 +0200
@@ -148,20 +148,17 @@
#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from))
#define INS_TO_REG(n,val) (SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255))
#define INSEXT_FROM_REG(n,val,ext) (SCALE((val)*4 + (ext),192*4,lm85_scaling[n]))
-/*
#define INS_FROM_REG(n,val) (INSEXT_FROM_REG(n,val,0))
-*/
-#define INS_FROM_REG(n,val) ( ( (val*4*lm85_scaling[n]) + (192*4/2) ) / (192*4) )
/* FAN speed is measured using 90kHz clock */
#define FAN_TO_REG(val) (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534))
#define FAN_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:5400000/(val))
-/* Temperature is reported in .01 degC increments */
-#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+50)/100,-127,127))
-#define TEMPEXT_FROM_REG(val,ext) ((val)*100 + (ext)*25)
+/* Temperature is reported in .001 degC increments */
+#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+500)/1000,-127,127))
+#define TEMPEXT_FROM_REG(val,ext) ((val)*1000 + (ext)*250)
#define TEMP_FROM_REG(val) (TEMPEXT_FROM_REG(val,0))
-#define EXTTEMP_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
+#define EXTTEMP_TO_REG(val) (SENSORS_LIMIT((val)/250,-127,127))
#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
#define PWM_FROM_REG(val) (val)
@@ -437,10 +434,13 @@
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
+ int val;
- int val = simple_strtol(buf, NULL, 10);
+ down(&data->update_lock);
+ val = simple_strtol(buf, NULL, 10);
data->fan_min[nr] = FAN_TO_REG(val);
lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]);
+ up(&data->update_lock);
return count;
}
@@ -528,10 +528,13 @@
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
+ int val;
- int val = simple_strtol(buf, NULL, 10);
+ down(&data->update_lock);
+ val = simple_strtol(buf, NULL, 10);
data->pwm[nr] = PWM_TO_REG(val);
lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]);
+ up(&data->update_lock);
return count;
}
static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
@@ -590,10 +593,13 @@
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
+ int val;
- int val = simple_strtol(buf, NULL, 10);
+ down(&data->update_lock);
+ val = simple_strtol(buf, NULL, 10);
data->in_min[nr] = INS_TO_REG(nr, val);
lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]);
+ up(&data->update_lock);
return count;
}
static ssize_t show_in_max(struct device *dev, char *buf, int nr)
@@ -609,10 +615,13 @@
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
+ int val;
- int val = simple_strtol(buf, NULL, 10);
+ down(&data->update_lock);
+ val = simple_strtol(buf, NULL, 10);
data->in_max[nr] = INS_TO_REG(nr, val);
lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]);
+ up(&data->update_lock);
return count;
}
#define show_in_reg(offset) \
@@ -673,10 +682,13 @@
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
+ int val;
- int val = simple_strtol(buf, NULL, 10);
+ down(&data->update_lock);
+ val = simple_strtol(buf, NULL, 10);
data->temp_min[nr] = TEMP_TO_REG(val);
lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]);
+ up(&data->update_lock);
return count;
}
static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
@@ -692,10 +704,13 @@
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
+ int val;
- int val = simple_strtol(buf, NULL, 10);
+ down(&data->update_lock);
+ val = simple_strtol(buf, NULL, 10);
data->temp_max[nr] = TEMP_TO_REG(val);
lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]);
+ up(&data->update_lock);
return count;
}
#define show_temp_reg(offset) \
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
2003-06-12 10:22 Margit Schubert-While
@ 2003-06-16 18:42 ` Greg KH
2003-06-18 12:18 ` Margit Schubert-While
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-06-16 18:42 UTC (permalink / raw)
To: Margit Schubert-While; +Cc: linux-kernel
On Thu, Jun 12, 2003 at 12:22:33PM +0200, Margit Schubert-While wrote:
> OK Here's the patch which :
> 1) Fixes the race conditions
> 2) Correctly reports the temps :-)
> 3) Removes a bit of gunk in the defines which I forgot
Applied, thanks.
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
2003-06-16 18:42 ` Greg KH
@ 2003-06-18 12:18 ` Margit Schubert-While
2003-06-18 14:22 ` Greg KH
0 siblings, 1 reply; 98+ messages in thread
From: Margit Schubert-While @ 2003-06-18 12:18 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel
The lm85, adm1021 patches also apply cleanly to 2.5.72 :-)
Question to Greg, Philip :
Is there really a race conditon with the update function ?
If so, all sensors are incorrect (also in CVS lmsensors).
Comments ?
Is any thought being given to merging ACPI and sensors ?
Margit
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
2003-06-18 12:18 ` Margit Schubert-While
@ 2003-06-18 14:22 ` Greg KH
2003-06-18 15:53 ` Margit Schubert-While
0 siblings, 1 reply; 98+ messages in thread
From: Greg KH @ 2003-06-18 14:22 UTC (permalink / raw)
To: Margit Schubert-While; +Cc: linux-kernel
On Wed, Jun 18, 2003 at 02:18:51PM +0200, Margit Schubert-While wrote:
> The lm85, adm1021 patches also apply cleanly to 2.5.72 :-)
Yes, I have them in a bk tree and will be sending them to Linus later
today :)
> Question to Greg, Philip :
> Is there really a race conditon with the update function ?
Where do you think the race is?
> If so, all sensors are incorrect (also in CVS lmsensors).
> Comments ?
>
> Is any thought being given to merging ACPI and sensors ?
The way we report the sensor values to userspace, yes, I have talked
with the acpi people about this in the past. But it looks like a 2.7
thing at the earliest.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* Re: [PATCH] More i2c driver changes for 2.5.70
2003-06-18 14:22 ` Greg KH
@ 2003-06-18 15:53 ` Margit Schubert-While
0 siblings, 0 replies; 98+ messages in thread
From: Margit Schubert-While @ 2003-06-18 15:53 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel
>
>Yes, I have them in a bk tree and will be sending them to Linus later
Super, then I can take the heat from Philip from not including his
latest patches.
>Where do o you think the race is?
I have no idea.. Ask Philip, Either we have a problem or not.
I am just trying to conform.
> > If so, all sensors are incorrect (also in CVS lmsensors).
> > Comments ?
Nothing here ?
> >
> > Is any thought being given to merging ACPI and sensors ?
>
>The way we report the sensor values to userspace, yes, I have talked
>with the acpi people about this in the past. But it looks like a 2.7
>thing at the earliest.
Super, at least something.
>thanks,
>
>greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* [BK PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, sensors
Hi,
Here are some more i2c driver changes for 2.5.65. These include changes
that now hook up the i2c devices to the driver core. This results in a
sysfs tree that looks like the following on one of my boxes:
/sys/bus/i2c/
|-- devices
| `-- i2c_dev_0 -> ../../../devices/pci0/00:1f.3/i2c-0/i2c_dev_0
`-- drivers
`-- LM75 sensor
`-- i2c_dev_0 -> ../../../../devices/pci0/00:1f.3/i2c-0/i2c_dev_0
Now the fun work of starting to rip out the i2c sysctl and proc code can
begin :)
These changesets also include the patch from Petr Vandrovec that fixes
an oops on booting with i2c built into the kernel, and some more minor
cleanups to some of the i2c core code.
I'll try to post a document later this weekend on lkml and
kernel-janitors-discuss that explains how the i2c drivers will need to
be converted, and how people can help out now that the infrastructure is
finished.
Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.5
thanks,
greg k-h
drivers/i2c/busses/i2c-ali15x3.c | 8 +
drivers/i2c/busses/i2c-amd756.c | 6 -
drivers/i2c/busses/i2c-amd8111.c | 4
drivers/i2c/busses/i2c-i801.c | 8 +
drivers/i2c/busses/i2c-isa.c | 4
drivers/i2c/busses/i2c-piix4.c | 8 +
drivers/i2c/chips/adm1021.c | 21 ++--
drivers/i2c/chips/lm75.c | 14 +--
drivers/i2c/i2c-algo-bit.c | 13 +-
drivers/i2c/i2c-algo-pcf.c | 19 +---
drivers/i2c/i2c-core.c | 99 ++++++++++-----------
drivers/i2c/i2c-dev.c | 21 ++--
drivers/i2c/i2c-elektor.c | 10 +-
drivers/i2c/i2c-elv.c | 6 -
drivers/i2c/i2c-philips-par.c | 4
drivers/i2c/i2c-proc.c | 180 ++++++++++-----------------------------
drivers/i2c/i2c-velleman.c | 4
drivers/i2c/scx200_acb.c | 32 +++---
include/linux/i2c.h | 33 ++++---
19 files changed, 218 insertions(+), 276 deletions(-)
-----
Short log:
-----
Greg Kroah-Hartman <greg@kroah.com>:
o i2c: ugh, clean up lindent mess in i2c-proc.c::i2c_detect()
o i2c: fix up the chip driver names to play nice with sysfs
o i2c: actually register the i2c client device with the driver core
o i2c: Removed the name variable from i2c_client as the dev one should be used instead
o i2c: remove the data field from struct i2c_client
o i2c: add struct device to i2c_client structure
o i2c: remove *data from i2c_adapter, as dev->data should be used instead
o i2c: remove i2c_adapter->name and use dev->name instead
Petr Vandrovec <vandrove@vc.cvut.cz>:
o Fix kobject_get oopses triggered by i2c in 2.5.65-bk
-----
Long log:
-----
ChangeSet@1.1196, 2003-03-21 16:45:59-08:00, greg@kroah.com
i2c: ugh, clean up lindent mess in i2c-proc.c::i2c_detect()
Yes, this function now goes beyond 80 columns, but it's almost
readable, while the previous version was not.
Also removed some #ifdefs
drivers/i2c/i2c-proc.c | 180 ++++++++++++-------------------------------------
1 files changed, 47 insertions(+), 133 deletions(-)
------
ChangeSet@1.1195, 2003-03-21 16:39:04-08:00, greg@kroah.com
[PATCH] i2c: fix up the chip driver names to play nice with sysfs
drivers/i2c/chips/adm1021.c | 2 +-
drivers/i2c/chips/lm75.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
------
ChangeSet@1.1194, 2003-03-21 16:26:04-08:00, greg@kroah.com
i2c: actually register the i2c client device with the driver core.
We have to initialize the client structure with 0 to keep the
driver core from oopsing.
Now everything is hooked up enough to start removing the i2c sysctl
and proc crud.
drivers/i2c/chips/adm1021.c | 2 ++
drivers/i2c/chips/lm75.c | 2 ++
drivers/i2c/i2c-core.c | 10 ++++++++++
3 files changed, 14 insertions(+)
------
ChangeSet@1.1193, 2003-03-21 16:16:01-08:00, greg@kroah.com
i2c: Removed the name variable from i2c_client as the dev one should be used instead.
drivers/i2c/chips/adm1021.c | 2 +-
drivers/i2c/chips/lm75.c | 2 +-
drivers/i2c/i2c-core.c | 14 +++++++-------
drivers/i2c/i2c-dev.c | 4 +++-
include/linux/i2c.h | 1 -
5 files changed, 12 insertions(+), 11 deletions(-)
------
ChangeSet@1.1192, 2003-03-21 16:07:30-08:00, greg@kroah.com
[PATCH] i2c: remove the data field from struct i2c_client
It's no longer needed, as the struct device should be used instead.
Created i2c_get_clientdata() and i2c_set_clientdata() to access the data.
drivers/i2c/chips/adm1021.c | 15 +++++++--------
drivers/i2c/chips/lm75.c | 8 ++++----
include/linux/i2c.h | 11 ++++++++++-
3 files changed, 21 insertions(+), 13 deletions(-)
------
ChangeSet@1.1191, 2003-03-21 16:00:39-08:00, greg@kroah.com
i2c: add struct device to i2c_client structure
Not quite ready to hook it up to the driver core yet.
include/linux/i2c.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletion(-)
------
ChangeSet@1.1190, 2003-03-21 14:38:21-08:00, greg@kroah.com
[PATCH] i2c: remove *data from i2c_adapter, as dev->data should be used instead.
drivers/i2c/i2c-elv.c | 2 +-
drivers/i2c/scx200_acb.c | 4 ++--
include/linux/i2c.h | 17 +++++++++++------
3 files changed, 14 insertions(+), 9 deletions(-)
------
ChangeSet@1.1189, 2003-03-21 12:45:28-08:00, greg@kroah.com
i2c: remove i2c_adapter->name and use dev->name instead.
drivers/i2c/busses/i2c-ali15x3.c | 8 ++--
drivers/i2c/busses/i2c-amd756.c | 6 ++-
drivers/i2c/busses/i2c-amd8111.c | 4 +-
drivers/i2c/busses/i2c-i801.c | 8 ++--
drivers/i2c/busses/i2c-isa.c | 4 +-
drivers/i2c/busses/i2c-piix4.c | 8 ++--
drivers/i2c/i2c-algo-bit.c | 13 +++---
drivers/i2c/i2c-algo-pcf.c | 19 ++++------
drivers/i2c/i2c-core.c | 73 ++++++++++++++++-----------------------
drivers/i2c/i2c-dev.c | 17 +++------
drivers/i2c/i2c-elektor.c | 10 +++--
drivers/i2c/i2c-elv.c | 4 +-
drivers/i2c/i2c-philips-par.c | 4 +-
drivers/i2c/i2c-velleman.c | 4 +-
drivers/i2c/scx200_acb.c | 28 ++++++--------
include/linux/i2c.h | 1
16 files changed, 105 insertions(+), 106 deletions(-)
------
ChangeSet@1.1188, 2003-03-21 12:29:44-08:00, vandrove@vc.cvut.cz
[PATCH] Fix kobject_get oopses triggered by i2c in 2.5.65-bk
i2c initialization must not use module_init now, when it was converted
to the kobject interface. There are dozens of users which need it working
much sooner. i2c is subsystem after all, isn't it?
Fixes kernel oopses in kobject_get during system init which were happening
to me.
Push file://home/greg/linux/BK/i2c-2.5 -> file://home/greg/linux/BK/bleed-2.5
drivers/i2c/i2c-core.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
------
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1191, 2003/03/21 16:00:39-08:00, greg@kroah.com
i2c: add struct device to i2c_client structure
Not quite ready to hook it up to the driver core yet.
include/linux/i2c.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletion(-)
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri Mar 21 16:53:17 2003
+++ b/include/linux/i2c.h Fri Mar 21 16:53:17 2003
@@ -170,8 +170,9 @@
void *data; /* for the clients */
int usage_count; /* How many accesses currently */
/* to the client */
+ struct device dev; /* the device structure */
};
-
+#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
/*
* The following structs are for those who like to implement new bus drivers:
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1188, 2003/03/21 12:29:44-08:00, vandrove@vc.cvut.cz
[PATCH] Fix kobject_get oopses triggered by i2c in 2.5.65-bk
i2c initialization must not use module_init now, when it was converted
to the kobject interface. There are dozens of users which need it working
much sooner. i2c is subsystem after all, isn't it?
Fixes kernel oopses in kobject_get during system init which were happening
to me.
drivers/i2c/i2c-core.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri Mar 21 16:53:45 2003
+++ b/drivers/i2c/i2c-core.c Fri Mar 21 16:53:45 2003
@@ -675,7 +675,7 @@
bus_unregister(&i2c_bus_type);
}
-module_init(i2c_init);
+subsys_initcall(i2c_init);
module_exit(i2c_exit);
/* ----------------------------------------------------
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1192, 2003/03/21 16:07:30-08:00, greg@kroah.com
[PATCH] i2c: remove the data field from struct i2c_client
It's no longer needed, as the struct device should be used instead.
Created i2c_get_clientdata() and i2c_set_clientdata() to access the data.
drivers/i2c/chips/adm1021.c | 15 +++++++--------
drivers/i2c/chips/lm75.c | 8 ++++----
include/linux/i2c.h | 11 ++++++++++-
3 files changed, 21 insertions(+), 13 deletions(-)
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Fri Mar 21 16:53:07 2003
+++ b/drivers/i2c/chips/adm1021.c Fri Mar 21 16:53:07 2003
@@ -223,8 +223,8 @@
}
data = (struct adm1021_data *) (new_client + 1);
+ i2c_set_clientdata(new_client, data);
new_client->addr = address;
- new_client->data = data;
new_client->adapter = adapter;
new_client->driver = &adm1021_driver;
new_client->flags = 0;
@@ -354,8 +354,7 @@
int err;
- i2c_deregister_entry(((struct adm1021_data *) (client->data))->
- sysctl_id);
+ i2c_deregister_entry(((struct adm1021_data *) (i2c_get_clientdata(client)))->sysctl_id);
if ((err = i2c_detach_client(client))) {
printk
@@ -384,7 +383,7 @@
static void adm1021_update_client(struct i2c_client *client)
{
- struct adm1021_data *data = client->data;
+ struct adm1021_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
@@ -435,7 +434,7 @@
static void adm1021_temp(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
- struct adm1021_data *data = client->data;
+ struct adm1021_data *data = i2c_get_clientdata(client);
if (operation = SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
@@ -462,7 +461,7 @@
static void adm1021_remote_temp(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
- struct adm1021_data *data = client->data;
+ struct adm1021_data *data = i2c_get_clientdata(client);
int prec = 0;
if (operation = SENSORS_PROC_REAL_INFO)
@@ -535,7 +534,7 @@
static void adm1021_die_code(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
- struct adm1021_data *data = client->data;
+ struct adm1021_data *data = i2c_get_clientdata(client);
if (operation = SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
@@ -551,7 +550,7 @@
static void adm1021_alarms(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
- struct adm1021_data *data = client->data;
+ struct adm1021_data *data = i2c_get_clientdata(client);
if (operation = SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
else if (operation = SENSORS_PROC_REAL_READ) {
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Fri Mar 21 16:53:07 2003
+++ b/drivers/i2c/chips/lm75.c Fri Mar 21 16:53:07 2003
@@ -142,8 +142,8 @@
}
data = (struct lm75_data *) (new_client + 1);
+ i2c_set_clientdata(new_client, data);
new_client->addr = address;
- new_client->data = data;
new_client->adapter = adapter;
new_client->driver = &lm75_driver;
new_client->flags = 0;
@@ -215,7 +215,7 @@
static int lm75_detach_client(struct i2c_client *client)
{
- struct lm75_data *data = client->data;
+ struct lm75_data *data = i2c_get_clientdata(client);
i2c_deregister_entry(data->sysctl_id);
i2c_detach_client(client);
@@ -263,7 +263,7 @@
static void lm75_update_client(struct i2c_client *client)
{
- struct lm75_data *data = client->data;
+ struct lm75_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
@@ -286,7 +286,7 @@
static void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
int *nrels_mag, long *results)
{
- struct lm75_data *data = client->data;
+ struct lm75_data *data = i2c_get_clientdata(client);
if (operation = SENSORS_PROC_REAL_INFO)
*nrels_mag = 1;
else if (operation = SENSORS_PROC_REAL_READ) {
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri Mar 21 16:53:07 2003
+++ b/include/linux/i2c.h Fri Mar 21 16:53:07 2003
@@ -167,12 +167,21 @@
alignment considerations */
struct i2c_adapter *adapter; /* the adapter we sit on */
struct i2c_driver *driver; /* and our access routines */
- void *data; /* for the clients */
int usage_count; /* How many accesses currently */
/* to the client */
struct device dev; /* the device structure */
};
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
+
+static inline void *i2c_get_clientdata (struct i2c_client *dev)
+{
+ return dev_get_drvdata (&dev->dev);
+}
+
+static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
+{
+ return dev_set_drvdata (&dev->dev, data);
+}
/*
* The following structs are for those who like to implement new bus drivers:
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1189, 2003/03/21 12:45:28-08:00, greg@kroah.com
i2c: remove i2c_adapter->name and use dev->name instead.
drivers/i2c/busses/i2c-ali15x3.c | 8 ++--
drivers/i2c/busses/i2c-amd756.c | 6 ++-
drivers/i2c/busses/i2c-amd8111.c | 4 +-
drivers/i2c/busses/i2c-i801.c | 8 ++--
drivers/i2c/busses/i2c-isa.c | 4 +-
drivers/i2c/busses/i2c-piix4.c | 8 ++--
drivers/i2c/i2c-algo-bit.c | 13 +++---
drivers/i2c/i2c-algo-pcf.c | 19 ++++------
drivers/i2c/i2c-core.c | 73 ++++++++++++++++-----------------------
drivers/i2c/i2c-dev.c | 17 +++------
drivers/i2c/i2c-elektor.c | 10 +++--
drivers/i2c/i2c-elv.c | 4 +-
drivers/i2c/i2c-philips-par.c | 4 +-
drivers/i2c/i2c-velleman.c | 4 +-
drivers/i2c/scx200_acb.c | 28 ++++++--------
include/linux/i2c.h | 1
16 files changed, 105 insertions(+), 106 deletions(-)
diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- a/drivers/i2c/busses/i2c-ali15x3.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-ali15x3.c Fri Mar 21 16:53:36 2003
@@ -474,9 +474,11 @@
static struct i2c_adapter ali15x3_adapter = {
.owner = THIS_MODULE,
- .name = "unset",
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,
.algo = &smbus_algorithm,
+ .dev = {
+ .name = "unset",
+ },
};
static struct pci_device_id ali15x3_ids[] __devinitdata = {
@@ -500,8 +502,8 @@
/* set up the driverfs linkage to our parent device */
ali15x3_adapter.dev.parent = &dev->dev;
- sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x",
- ali15x3_smba);
+ snprintf(ali15x3_adapter.dev.name, DEVICE_NAME_SIZE,
+ "SMBus ALI15X3 adapter at %04x", ali15x3_smba);
return i2c_add_adapter(&ali15x3_adapter);
}
diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
--- a/drivers/i2c/busses/i2c-amd756.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-amd756.c Fri Mar 21 16:53:36 2003
@@ -312,9 +312,11 @@
static struct i2c_adapter amd756_adapter = {
.owner = THIS_MODULE,
- .name = "unset",
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756,
.algo = &smbus_algorithm,
+ .dev = {
+ .name = "unset",
+ },
};
enum chiptype { AMD756, AMD766, AMD768, NFORCE };
@@ -376,7 +378,7 @@
/* set up the driverfs linkage to our parent device */
amd756_adapter.dev.parent = &pdev->dev;
- sprintf(amd756_adapter.name,
+ snprintf(amd756_adapter.dev.name, DEVICE_NAME_SIZE,
"SMBus AMD75x adapter at %04x", amd756_ioport);
error = i2c_add_adapter(&amd756_adapter);
diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
--- a/drivers/i2c/busses/i2c-amd8111.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-amd8111.c Fri Mar 21 16:53:36 2003
@@ -357,8 +357,8 @@
goto out_kfree;
smbus->adapter.owner = THIS_MODULE;
- sprintf(smbus->adapter.name,
- "SMBus2 AMD8111 adapter at %04x", smbus->base);
+ snprintf(smbus->adapter.dev.name, DEVICE_NAME_SIZE,
+ "SMBus2 AMD8111 adapter at %04x", smbus->base);
smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- a/drivers/i2c/busses/i2c-i801.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-i801.c Fri Mar 21 16:53:36 2003
@@ -546,9 +546,11 @@
static struct i2c_adapter i801_adapter = {
.owner = THIS_MODULE,
- .name = "unset",
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
.algo = &smbus_algorithm,
+ .dev = {
+ .name = "unset",
+ },
};
static struct pci_device_id i801_ids[] __devinitdata = {
@@ -597,8 +599,8 @@
/* set up the driverfs linkage to our parent device */
i801_adapter.dev.parent = &dev->dev;
- sprintf(i801_adapter.name, "SMBus I801 adapter at %04x",
- i801_smba);
+ snprintf(i801_adapter.dev.name, DEVICE_NAME_SIZE,
+ "SMBus I801 adapter at %04x", i801_smba);
return i2c_add_adapter(&i801_adapter);
}
diff -Nru a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
--- a/drivers/i2c/busses/i2c-isa.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-isa.c Fri Mar 21 16:53:36 2003
@@ -39,9 +39,11 @@
/* There can only be one... */
static struct i2c_adapter isa_adapter = {
.owner = THIS_MODULE,
- .name = "ISA main adapter",
.id = I2C_ALGO_ISA | I2C_HW_ISA,
.algo = &isa_algorithm,
+ .dev = {
+ .name = "ISA main adapter",
+ },
};
static int __init i2c_isa_init(void)
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/busses/i2c-piix4.c Fri Mar 21 16:53:36 2003
@@ -394,9 +394,11 @@
static struct i2c_adapter piix4_adapter = {
.owner = THIS_MODULE,
- .name = "unset",
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
.algo = &smbus_algorithm,
+ .dev = {
+ .name = "unset",
+ },
};
static struct pci_device_id piix4_ids[] __devinitdata = {
@@ -449,8 +451,8 @@
/* set up the driverfs linkage to our parent device */
piix4_adapter.dev.parent = &dev->dev;
- sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
- piix4_smba);
+ snprintf(piix4_adapter.dev.name, DEVICE_NAME_SIZE,
+ "SMBus PIIX4 adapter at %04x", piix4_smba);
retval = i2c_add_adapter(&piix4_adapter);
diff -Nru a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/i2c-algo-bit.c
--- a/drivers/i2c/i2c-algo-bit.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-algo-bit.c Fri Mar 21 16:53:36 2003
@@ -23,6 +23,8 @@
/* $Id: i2c-algo-bit.c,v 1.44 2003/01/21 08:08:16 kmalkki Exp $ */
+/* #define DEBUG 1 */
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -338,16 +340,14 @@
while (count > 0) {
c = *temp;
- DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: %s sendbytes: writing %2.2X\n",
- i2c_adap->name, c&0xff));
+ DEB2(dev_dbg(&i2c_adap->dev, "sendbytes: writing %2.2X\n", c&0xff));
retval = i2c_outb(i2c_adap,c);
if ((retval>0) || (nak_ok && (retval=0))) { /* ok or ignored NAK */
count--;
temp++;
wrcount++;
} else { /* arbitration or no acknowledge */
- printk(KERN_ERR "i2c-algo-bit.o: %s sendbytes: error - bailout.\n",
- i2c_adap->name);
+ dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
i2c_stop(adap);
return (retval<0)? retval : -EFAULT;
/* got a better one ?? */
@@ -527,13 +527,12 @@
struct i2c_algo_bit_data *bit_adap = adap->algo_data;
if (bit_test) {
- int ret = test_bus(bit_adap, adap->name);
+ int ret = test_bus(bit_adap, adap->dev.name);
if (ret<0)
return -ENODEV;
}
- DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: hw routines for %s registered.\n",
- adap->name));
+ DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
/* register new adapter to i2c module... */
diff -Nru a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/i2c-algo-pcf.c
--- a/drivers/i2c/i2c-algo-pcf.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-algo-pcf.c Fri Mar 21 16:53:36 2003
@@ -27,6 +27,8 @@
messages, proper stop/repstart signaling during receive,
added detect code */
+/* #define DEBUG 1 */ /* to pick up dev_dbg calls */
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -222,21 +224,19 @@
int wrcount, status, timeout;
for (wrcount=0; wrcount<count; ++wrcount) {
- DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: %s i2c_write: writing %2.2X\n",
- i2c_adap->name, buf[wrcount]&0xff));
+ DEB2(dev_dbg(&i2c_adap->dev, "i2c_write: writing %2.2X\n",
+ buf[wrcount]&0xff));
i2c_outb(adap, buf[wrcount]);
timeout = wait_for_pin(adap, &status);
if (timeout) {
i2c_stop(adap);
- printk(KERN_ERR "i2c-algo-pcf.o: %s i2c_write: "
- "error - timeout.\n", i2c_adap->name);
+ dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n");
return -EREMOTEIO; /* got a better one ?? */
}
#ifndef STUB_I2C
if (status & I2C_PCF_LRB) {
i2c_stop(adap);
- printk(KERN_ERR "i2c-algo-pcf.o: %s i2c_write: "
- "error - no ack.\n", i2c_adap->name);
+ dev_err(&i2c_adap->dev, "i2c_write: error - no ack.\n");
return -EREMOTEIO; /* got a better one ?? */
}
#endif
@@ -263,14 +263,14 @@
if (wait_for_pin(adap, &status)) {
i2c_stop(adap);
- printk(KERN_ERR "i2c-algo-pcf.o: pcf_readbytes timed out.\n");
+ dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n");
return (-1);
}
#ifndef STUB_I2C
if ((status & I2C_PCF_LRB) && (i != count)) {
i2c_stop(adap);
- printk(KERN_ERR "i2c-algo-pcf.o: i2c_read: i2c_inb, No ack.\n");
+ dev_err(&i2c_adap->dev, "i2c_read: i2c_inb, No ack.\n");
return (-1);
}
#endif
@@ -445,8 +445,7 @@
struct i2c_algo_pcf_data *pcf_adap = adap->algo_data;
int rval;
- DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: hw routines for %s registered.\n",
- adap->name));
+ DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
/* register new adapter to i2c module... */
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-core.c Fri Mar 21 16:53:36 2003
@@ -23,6 +23,8 @@
/* $Id: i2c-core.c,v 1.95 2003/01/22 05:25:08 kmalkki Exp $ */
+/* #define DEBUG 1 */ /* needed to pick up the dev_dbg() calls */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -82,9 +84,8 @@
if (NULL = adapters[i])
break;
if (I2C_ADAP_MAX = i) {
- printk(KERN_WARNING
- " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n",
- adap->name);
+ dev_warn(&adap->dev,
+ "register_adapter - enlarge I2C_ADAP_MAX.\n");
res = -ENOMEM;
goto out_unlock;
}
@@ -105,7 +106,6 @@
if (adap->dev.parent = NULL)
adap->dev.parent = &legacy_bus;
sprintf(adap->dev.bus_id, "i2c-%d", i);
- strcpy(adap->dev.name, "i2c controller");
device_register(&adap->dev);
/* inform drivers of new adapters */
@@ -116,8 +116,7 @@
drivers[j]->attach_adapter(adap);
up(&core_lists);
- DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n",
- adap->name,i));
+ DEB(dev_dbg(&adap->dev, "registered as adapter %d.\n", i));
out_unlock:
up(&core_lists);
@@ -134,8 +133,7 @@
if (adap = adapters[i])
break;
if (I2C_ADAP_MAX = i) {
- printk( KERN_WARNING "i2c-core.o: unregister_adapter adap [%s] not found.\n",
- adap->name);
+ dev_warn(&adap->dev, "unregister_adapter adap not found.\n");
res = -ENODEV;
goto out_unlock;
}
@@ -148,9 +146,9 @@
for (j = 0; j < I2C_DRIVER_MAX; j++)
if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY))
if ((res = drivers[j]->attach_adapter(adap))) {
- printk(KERN_WARNING "i2c-core.o: can't detach adapter %s "
+ dev_warn(&adap->dev, "can't detach adapter"
"while detaching driver %s: driver not "
- "detached!",adap->name,drivers[j]->name);
+ "detached!", drivers[j]->name);
goto out_unlock;
}
@@ -164,10 +162,10 @@
* must be deleted, as this would cause invalid states.
*/
if ((res=client->driver->detach_client(client))) {
- printk(KERN_ERR "i2c-core.o: adapter %s not "
+ dev_err(&adap->dev, "adapter not "
"unregistered, because client at "
"address %02x can't be detached. ",
- adap->name, client->addr);
+ client->addr);
goto out_unlock;
}
}
@@ -180,7 +178,7 @@
adapters[i] = NULL;
- DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name));
+ DEB(dev_dbg(&adap->dev, "adapter unregistered\n"));
out_unlock:
up(&core_lists);
@@ -272,8 +270,7 @@
struct i2c_adapter *adap = adapters[k];
if (adap = NULL) /* skip empty entries. */
continue;
- DEB2(printk(KERN_DEBUG "i2c-core.o: examining adapter %s:\n",
- adap->name));
+ DEB2(dev_dbg(&adap->dev, "examining adapter\n"));
if (driver->flags & I2C_DF_DUMMY) {
/* DUMMY drivers do not register their clients, so we have to
* use a trick here: we call driver->attach_adapter to
@@ -281,11 +278,10 @@
* this or hell will break loose...
*/
if ((res = driver->attach_adapter(adap))) {
- printk(KERN_WARNING "i2c-core.o: while unregistering "
- "dummy driver %s, adapter %s could "
+ dev_warn(&adap->dev, "while unregistering "
+ "dummy driver %s, adapter could "
"not be detached properly; driver "
- "not unloaded!",driver->name,
- adap->name);
+ "not unloaded!",driver->name);
goto out_unlock;
}
} else {
@@ -296,19 +292,16 @@
DEB2(printk(KERN_DEBUG "i2c-core.o: "
"detaching client %s:\n",
client->name));
- if ((res = driver->
- detach_client(client)))
- {
- printk(KERN_ERR "i2c-core.o: while "
+ if ((res = driver->detach_client(client))) {
+ dev_err(&adap->dev, "while "
"unregistering driver "
"`%s', the client at "
"address %02x of "
- "adapter `%s' could not "
+ "adapter could not "
"be detached; driver "
"not unloaded!",
driver->name,
- client->addr,
- adap->name);
+ client->addr);
goto out_unlock;
}
}
@@ -374,16 +367,14 @@
if (adapter->client_register) {
if (adapter->client_register(client)) {
- printk(KERN_DEBUG
- "i2c-core.o: warning: client_register seems "
- "to have failed for client %02x at adapter %s\n",
- client->addr, adapter->name);
+ dev_warn(&adapter->dev, "warning: client_register "
+ "seems to have failed for client %02x\n",
+ client->addr);
}
}
- DEB(printk(KERN_DEBUG
- "i2c-core.o: client [%s] registered to adapter [%s] "
- "(pos. %d).\n", client->name, adapter->name, i));
+ DEB(dev_dbg(&adapter->dev, "client [%s] registered to adapter "
+ "(pos. %d).\n", client->name, i));
if (client->flags & I2C_CLIENT_ALLOW_USE)
client->usage_count = 0;
@@ -579,7 +570,7 @@
seq_printf(s, "dummy ");
seq_printf(s, "\t%-32s\t%-32s\n",
- adapter->name, adapter->algo->name);
+ adapter->dev.name, adapter->algo->name);
}
up(&core_lists);
@@ -688,8 +679,7 @@
int ret;
if (adap->algo->master_xfer) {
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_xfer: %s with %d msgs.\n",
- adap->name,num));
+ DEB2(dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num));
down(&adap->bus);
ret = adap->algo->master_xfer(adap,msgs,num);
@@ -697,8 +687,7 @@
return ret;
} else {
- printk(KERN_ERR "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
- adap->id);
+ dev_err(&adap->dev, "I2C level transfers not supported\n");
return -ENOSYS;
}
}
@@ -715,8 +704,8 @@
msg.len = count;
(const char *)msg.buf = buf;
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n",
- count,client->adapter->name));
+ DEB2(dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
+ count));
down(&adap->bus);
ret = adap->algo->master_xfer(adap,&msg,1);
@@ -745,8 +734,8 @@
msg.len = count;
msg.buf = buf;
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n",
- count,client->adapter->name));
+ DEB2(dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n",
+ count));
down(&adap->bus);
ret = adap->algo->master_xfer(adap,&msg,1);
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-dev.c Fri Mar 21 16:53:36 2003
@@ -30,6 +30,9 @@
/* $Id: i2c-dev.c,v 1.53 2003/01/21 08:08:16 kmalkki Exp $ */
+/* If you want debugging uncomment: */
+/* #define DEBUG 1 */
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
@@ -41,10 +44,6 @@
#include <linux/i2c-dev.h>
#include <asm/uaccess.h>
-/* If you want debugging uncomment: */
-/* #define DEBUG */
-
-
/* struct file_operations changed too often in the 2.1 series for nice code */
static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
@@ -386,11 +385,11 @@
char name[12];
if ((i = i2c_adapter_id(adap)) < 0) {
- printk(KERN_DEBUG "i2c-dev.o: Unknown adapter ?!?\n");
+ dev_dbg(&adap->dev, "Unknown adapter ?!?\n");
return -ENODEV;
}
if (i >= I2CDEV_ADAPS_MAX) {
- printk(KERN_DEBUG "i2c-dev.o: Adapter number too large?!? (%d)\n",i);
+ dev_dbg(&adap->dev, "Adapter number too large?!? (%d)\n",i);
return -ENODEV;
}
@@ -401,14 +400,12 @@
DEVFS_FL_DEFAULT, I2C_MAJOR, i,
S_IFCHR | S_IRUSR | S_IWUSR,
&i2cdev_fops, NULL);
- printk(KERN_DEBUG "i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i);
+ dev_dbg(&adap->dev, "Registered as minor %d\n", i);
} else {
/* This is actually a detach_adapter call! */
devfs_remove("i2c/%d", i);
i2cdev_adaps[i] = NULL;
-#ifdef DEBUG
- printk(KERN_DEBUG "i2c-dev.o: Adapter unregistered: %s\n",adap->name);
-#endif
+ dev_dbg(&adap->dev, "Adapter unregistered\n");
}
return 0;
diff -Nru a/drivers/i2c/i2c-elektor.c b/drivers/i2c/i2c-elektor.c
--- a/drivers/i2c/i2c-elektor.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-elektor.c Fri Mar 21 16:53:36 2003
@@ -174,10 +174,12 @@
};
static struct i2c_adapter pcf_isa_ops = {
- .owner = THIS_MODULE,
- .name = "PCF8584 ISA adapter",
- .id = I2C_HW_P_ELEK,
- .algo_data = &pcf_isa_data,
+ .owner = THIS_MODULE,
+ .id = I2C_HW_P_ELEK,
+ .algo_data = &pcf_isa_data,
+ .dev = {
+ .name = "PCF8584 ISA adapter",
+ },
};
static int __init i2c_pcfisa_init(void)
diff -Nru a/drivers/i2c/i2c-elv.c b/drivers/i2c/i2c-elv.c
--- a/drivers/i2c/i2c-elv.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-elv.c Fri Mar 21 16:53:36 2003
@@ -129,9 +129,11 @@
static struct i2c_adapter bit_elv_ops = {
.owner = THIS_MODULE,
- .name = "ELV Parallel port adaptor",
.id = I2C_HW_B_ELV,
.algo_data = &bit_elv_data,
+ .dev = {
+ .name = "ELV Parallel port adaptor",
+ },
};
static int __init i2c_bitelv_init(void)
diff -Nru a/drivers/i2c/i2c-philips-par.c b/drivers/i2c/i2c-philips-par.c
--- a/drivers/i2c/i2c-philips-par.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-philips-par.c Fri Mar 21 16:53:36 2003
@@ -151,8 +151,10 @@
static struct i2c_adapter bit_lp_ops = {
.owner = THIS_MODULE,
- .name = "Philips Parallel port adapter",
.id = I2C_HW_B_LP,
+ .dev = {
+ .name = "Philips Parallel port adapter",
+ },
};
static void i2c_parport_attach (struct parport *port)
diff -Nru a/drivers/i2c/i2c-velleman.c b/drivers/i2c/i2c-velleman.c
--- a/drivers/i2c/i2c-velleman.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/i2c-velleman.c Fri Mar 21 16:53:36 2003
@@ -114,9 +114,11 @@
static struct i2c_adapter bit_velle_ops = {
.owner = THIS_MODULE,
- .name = "Velleman K8000",
.id = I2C_HW_B_VELLE,
.algo_data = &bit_velle_data,
+ .dev = {
+ .name = "Velleman K8000",
+ },
};
static int __init i2c_bitvelle_init(void)
diff -Nru a/drivers/i2c/scx200_acb.c b/drivers/i2c/scx200_acb.c
--- a/drivers/i2c/scx200_acb.c Fri Mar 21 16:53:36 2003
+++ b/drivers/i2c/scx200_acb.c Fri Mar 21 16:53:36 2003
@@ -140,8 +140,7 @@
switch (iface->state) {
case state_idle:
- printk(KERN_WARNING NAME ": %s, interrupt in idle state\n",
- iface->adapter.name);
+ dev_warn(&iface->adapter.dev, "interrupt in idle state\n",);
break;
case state_address:
@@ -226,8 +225,8 @@
return;
error:
- printk(KERN_ERR NAME ": %s, %s in state %s\n", iface->adapter.name,
- errmsg, scx200_acb_state_name[iface->state]);
+ dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg,
+ scx200_acb_state_name[iface->state]);
iface->state = state_idle;
iface->result = -EIO;
@@ -236,8 +235,8 @@
static void scx200_acb_timeout(struct scx200_acb_iface *iface)
{
- printk(KERN_ERR NAME ": %s, timeout in state %s\n",
- iface->adapter.name, scx200_acb_state_name[iface->state]);
+ dev_err(&iface->adapter.dev, "timeout in state %s\n",
+ scx200_acb_state_name[iface->state]);
iface->state = state_idle;
iface->result = -EIO;
@@ -331,13 +330,12 @@
size, address, command, len, rw = I2C_SMBUS_READ);
if (!len && rw = I2C_SMBUS_READ) {
- printk(KERN_WARNING NAME ": %s, zero length read\n",
- adapter->name);
+ dev_warn(&adapter->dev, "zero length read\n");
return -EINVAL;
}
if (len && !buffer) {
- printk(KERN_WARNING NAME ": %s, nonzero length but no buffer\n", adapter->name);
+ dev_warn(&adapter->dev, "nonzero length but no buffer\n");
return -EFAULT;
}
@@ -458,17 +456,17 @@
memset(iface, 0, sizeof(*iface));
adapter = &iface->adapter;
adapter->data = iface;
- sprintf(adapter->name, "SCx200 ACB%d", index);
+ snprintf(adapter->dev.name, DEVICE_NAME_SIZE, "SCx200 ACB%d", index);
adapter->owner = THIS_MODULE;
adapter->id = I2C_ALGO_SMBUS;
adapter->algo = &scx200_acb_algorithm;
init_MUTEX(&iface->sem);
- sprintf(description, "NatSemi SCx200 ACCESS.bus [%s]", adapter->name);
+ snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->dev.name);
if (request_region(base, 8, description) = 0) {
- printk(KERN_ERR NAME ": %s, can't allocate io 0x%x-0x%x\n",
- adapter->name, base, base + 8-1);
+ dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n",
+ base, base + 8-1);
rc = -EBUSY;
goto errout;
}
@@ -476,14 +474,14 @@
rc = scx200_acb_probe(iface);
if (rc) {
- printk(KERN_WARNING NAME ": %s, probe failed\n", adapter->name);
+ dev_warn(&adapter->dev, "probe failed\n");
goto errout;
}
scx200_acb_reset(iface);
if (i2c_add_adapter(adapter) < 0) {
- printk(KERN_ERR NAME ": %s, failed to register\n", adapter->name);
+ dev_err(&adapter->dev, "failed to register\n");
rc = -ENODEV;
goto errout;
}
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri Mar 21 16:53:36 2003
+++ b/include/linux/i2c.h Fri Mar 21 16:53:36 2003
@@ -210,7 +210,6 @@
*/
struct i2c_adapter {
struct module *owner;
- char name[32]; /* some useful name to identify the adapter */
unsigned int id;/* = is algo->id | hwdep.struct->id, */
/* for registered values see below */
struct i2c_algorithm *algo;/* the algorithm to access the bus */
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1196, 2003/03/21 16:45:59-08:00, greg@kroah.com
i2c: ugh, clean up lindent mess in i2c-proc.c::i2c_detect()
Yes, this function now goes beyond 80 columns, but it's almost
readable, while the previous version was not.
Also removed some #ifdefs
drivers/i2c/i2c-proc.c | 180 ++++++++++++-------------------------------------
1 files changed, 47 insertions(+), 133 deletions(-)
diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
--- a/drivers/i2c/i2c-proc.c Fri Mar 21 16:52:31 2003
+++ b/drivers/i2c/i2c-proc.c Fri Mar 21 16:52:31 2003
@@ -23,6 +23,8 @@
This driver puts entries in /proc/sys/dev/sensors for each I2C device
*/
+/* #define DEBUG 1 */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -581,9 +583,9 @@
is_isa ? SENSORS_ISA_BUS : i2c_adapter_id(adapter);
/* Forget it if we can't probe using SMBUS_QUICK */
- if ((!is_isa)
- && !i2c_check_functionality(adapter,
- I2C_FUNC_SMBUS_QUICK)) return -1;
+ if ((!is_isa) &&
+ !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
+ return -1;
for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
/* XXX: WTF is going on here??? */
@@ -594,31 +596,14 @@
/* If it is in one of the force entries, we don't do any
detection at all */
found = 0;
- for (i = 0;
- !found
- && (this_force - address_data->forces + i, this_force->force); i++) {
- for (j = 0;
- !found
- && (this_force->force[j] != SENSORS_I2C_END);
- j += 2) {
- if (
- ((adapter_id = this_force->force[j])
- ||
- ((this_force->
- force[j] = SENSORS_ANY_I2C_BUS)
- && !is_isa))
- && (addr = this_force->force[j + 1])) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found force parameter for adapter %d, addr %04x\n",
- adapter_id, addr);
-#endif
- if (
- (err - found_proc(adapter, addr, 0,
- this_force->
- kind))) return err;
+ for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
+ for (j = 0; !found && (this_force->force[j] != SENSORS_I2C_END); j += 2) {
+ if ( ((adapter_id = this_force->force[j]) ||
+ ((this_force->force[j] = SENSORS_ANY_I2C_BUS) && !is_isa)) &&
+ (addr = this_force->force[j + 1]) ) {
+ dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
+ if ((err = found_proc(adapter, addr, 0, this_force->kind)))
+ return err;
found = 1;
}
}
@@ -628,42 +613,22 @@
/* If this address is in one of the ignores, we can forget about it
right now */
- for (i = 0;
- !found
- && (address_data->ignore[i] != SENSORS_I2C_END);
- i += 2) {
- if (
- ((adapter_id = address_data->ignore[i])
- ||
- ((address_data->
- ignore[i] = SENSORS_ANY_I2C_BUS)
- && !is_isa))
- && (addr = address_data->ignore[i + 1])) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found ignore parameter for adapter %d, "
- "addr %04x\n", adapter_id, addr);
-#endif
+ for (i = 0; !found && (address_data->ignore[i] != SENSORS_I2C_END); i += 2) {
+ if ( ((adapter_id = address_data->ignore[i]) ||
+ ((address_data->ignore[i] = SENSORS_ANY_I2C_BUS) &&
+ !is_isa)) &&
+ (addr = address_data->ignore[i + 1])) {
+ dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
found = 1;
}
}
- for (i = 0;
- !found
- && (address_data->ignore_range[i] != SENSORS_I2C_END);
- i += 3) {
- if (
- ((adapter_id = address_data->ignore_range[i])
- ||
- ((address_data->
- ignore_range[i] =
- SENSORS_ANY_I2C_BUS) & !is_isa))
- && (addr >= address_data->ignore_range[i + 1])
- && (addr <= address_data->ignore_range[i + 2])) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found ignore_range parameter for adapter %d, "
- "addr %04x\n", adapter_id, addr);
-#endif
+ for (i = 0; !found && (address_data->ignore_range[i] != SENSORS_I2C_END); i += 3) {
+ if ( ((adapter_id = address_data->ignore_range[i]) ||
+ ((address_data-> ignore_range[i] = SENSORS_ANY_I2C_BUS) &
+ !is_isa)) &&
+ (addr >= address_data->ignore_range[i + 1]) &&
+ (addr <= address_data->ignore_range[i + 2])) {
+ dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
found = 1;
}
}
@@ -673,68 +638,31 @@
/* Now, we will do a detection, but only if it is in the normal or
probe entries */
if (is_isa) {
- for (i = 0;
- !found
- && (address_data->normal_isa[i] !- SENSORS_ISA_END); i += 1) {
+ for (i = 0; !found && (address_data->normal_isa[i] != SENSORS_ISA_END); i += 1) {
if (addr = address_data->normal_isa[i]) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found normal isa entry for adapter %d, "
- "addr %04x\n", adapter_id,
- addr);
-#endif
+ dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
found = 1;
}
}
- for (i = 0;
- !found
- && (address_data->normal_isa_range[i] !- SENSORS_ISA_END); i += 3) {
- if ((addr >- address_data->normal_isa_range[i])
- && (addr <- address_data->normal_isa_range[i + 1])
- &&
- ((addr -
- address_data->normal_isa_range[i]) %
- address_data->normal_isa_range[i + 2] =
- 0)) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found normal isa_range entry for adapter %d, "
- "addr %04x", adapter_id, addr);
-#endif
+ for (i = 0; !found && (address_data->normal_isa_range[i] != SENSORS_ISA_END); i += 3) {
+ if ((addr >= address_data->normal_isa_range[i]) &&
+ (addr <= address_data->normal_isa_range[i + 1]) &&
+ ((addr - address_data->normal_isa_range[i]) % address_data->normal_isa_range[i + 2] = 0)) {
+ dev_dbg(&adapter->dev, "found normal isa_range entry for adapter %d, addr %04x", adapter_id, addr);
found = 1;
}
}
} else {
- for (i = 0;
- !found && (address_data->normal_i2c[i] !- SENSORS_I2C_END); i += 1) {
+ for (i = 0; !found && (address_data->normal_i2c[i] != SENSORS_I2C_END); i += 1) {
if (addr = address_data->normal_i2c[i]) {
found = 1;
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found normal i2c entry for adapter %d, "
- "addr %02x", adapter_id, addr);
-#endif
+ dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x", adapter_id, addr);
}
}
- for (i = 0;
- !found
- && (address_data->normal_i2c_range[i] !- SENSORS_I2C_END); i += 2) {
- if ((addr >- address_data->normal_i2c_range[i])
- && (addr <- address_data->normal_i2c_range[i + 1]))
- {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found normal i2c_range entry for adapter %d, "
- "addr %04x\n", adapter_id, addr);
-#endif
+ for (i = 0; !found && (address_data->normal_i2c_range[i] != SENSORS_I2C_END); i += 2) {
+ if ((addr >= address_data->normal_i2c_range[i]) &&
+ (addr <= address_data->normal_i2c_range[i + 1])) {
+ dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, addr %04x\n", adapter_id, addr);
found = 1;
}
}
@@ -747,30 +675,17 @@
((address_data->
probe[i] = SENSORS_ANY_I2C_BUS) & !is_isa))
&& (addr = address_data->probe[i + 1])) {
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found probe parameter for adapter %d, "
- "addr %04x\n", adapter_id, addr);
-#endif
+ dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
found = 1;
}
}
- for (i = 0; !found &&
- (address_data->probe_range[i] != SENSORS_I2C_END);
- i += 3) {
- if (
- ((adapter_id = address_data->probe_range[i])
- ||
- ((address_data->probe_range[i] =
- SENSORS_ANY_I2C_BUS) & !is_isa))
- && (addr >= address_data->probe_range[i + 1])
- && (addr <= address_data->probe_range[i + 2])) {
+ for (i = 0; !found && (address_data->probe_range[i] != SENSORS_I2C_END); i += 3) {
+ if ( ((adapter_id = address_data->probe_range[i]) ||
+ ((address_data->probe_range[i] = SENSORS_ANY_I2C_BUS) & !is_isa)) &&
+ (addr >= address_data->probe_range[i + 1]) &&
+ (addr <= address_data->probe_range[i + 2])) {
found = 1;
-#ifdef DEBUG
- printk
- (KERN_DEBUG "i2c-proc.o: found probe_range parameter for adapter %d, "
- "addr %04x\n", adapter_id, addr);
-#endif
+ dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
}
}
if (!found)
@@ -779,8 +694,7 @@
/* OK, so we really should examine this address. First check
whether there is some client here at all! */
if (is_isa ||
- (i2c_smbus_xfer
- (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
+ (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
if ((err = found_proc(adapter, addr, 0, -1)))
return err;
}
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1193, 2003/03/21 16:16:01-08:00, greg@kroah.com
i2c: Removed the name variable from i2c_client as the dev one should be used instead.
drivers/i2c/chips/adm1021.c | 2 +-
drivers/i2c/chips/lm75.c | 2 +-
drivers/i2c/i2c-core.c | 14 +++++++-------
drivers/i2c/i2c-dev.c | 4 +++-
include/linux/i2c.h | 1 -
5 files changed, 12 insertions(+), 11 deletions(-)
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:58 2003
+++ b/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:58 2003
@@ -299,7 +299,7 @@
}
/* Fill in the remaining client fields and put it into the global list */
- strcpy(new_client->name, client_name);
+ strncpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
data->type = kind;
new_client->id = adm1021_id++;
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:58 2003
+++ b/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:58 2003
@@ -180,7 +180,7 @@
}
/* Fill in the remaining client fields and put it into the global list */
- strcpy(new_client->name, client_name);
+ strncpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
new_client->id = lm75_id++;
data->valid = 0;
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri Mar 21 16:52:58 2003
+++ b/drivers/i2c/i2c-core.c Fri Mar 21 16:52:58 2003
@@ -291,9 +291,9 @@
client->driver = driver) {
DEB2(printk(KERN_DEBUG "i2c-core.o: "
"detaching client %s:\n",
- client->name));
+ client->dev.name));
if ((res = driver->detach_client(client))) {
- dev_err(&adap->dev, "while "
+ dev_err(&adap->dev, "while "
"unregistering driver "
"`%s', the client at "
"address %02x of "
@@ -355,7 +355,7 @@
printk(KERN_WARNING
" i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n",
- client->name);
+ client->dev.name);
out_unlock_list:
up(&adapter->list);
@@ -374,7 +374,7 @@
}
DEB(dev_dbg(&adapter->dev, "client [%s] registered to adapter "
- "(pos. %d).\n", client->name, i));
+ "(pos. %d).\n", client->dev.name, i));
if (client->flags & I2C_CLIENT_ALLOW_USE)
client->usage_count = 0;
@@ -395,7 +395,7 @@
if (res) {
printk(KERN_ERR
"i2c-core.o: client_unregister [%s] failed, "
- "client not detached", client->name);
+ "client not detached", client->dev.name);
goto out;
}
}
@@ -410,7 +410,7 @@
printk(KERN_WARNING
" i2c-core.o: unregister_client [%s] not found\n",
- client->name);
+ client->dev.name);
res = -ENODEV;
out_unlock:
@@ -522,7 +522,7 @@
client = adapters[i]->clients[order[j]];
len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n",
client->addr,
- client->name,
+ client->dev.name,
client->driver->name);
}
len = len - file->f_pos;
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c Fri Mar 21 16:52:58 2003
+++ b/drivers/i2c/i2c-dev.c Fri Mar 21 16:52:58 2003
@@ -86,7 +86,9 @@
};
static struct i2c_client i2cdev_client_template = {
- .name = "I2C /dev entry",
+ .dev = {
+ .name = "I2C /dev entry",
+ },
.id = 1,
.addr = -1,
.driver = &i2cdev_driver,
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri Mar 21 16:52:58 2003
+++ b/include/linux/i2c.h Fri Mar 21 16:52:58 2003
@@ -156,7 +156,6 @@
* function is mainly used for lookup & other admin. functions.
*/
struct i2c_client {
- char name[32];
int id;
unsigned int flags; /* div., see below */
unsigned int addr; /* chip address - NOTE: 7bit */
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1190, 2003/03/21 14:38:21-08:00, greg@kroah.com
[PATCH] i2c: remove *data from i2c_adapter, as dev->data should be used instead.
drivers/i2c/i2c-elv.c | 2 +-
drivers/i2c/scx200_acb.c | 4 ++--
include/linux/i2c.h | 17 +++++++++++------
3 files changed, 14 insertions(+), 9 deletions(-)
diff -Nru a/drivers/i2c/i2c-elv.c b/drivers/i2c/i2c-elv.c
--- a/drivers/i2c/i2c-elv.c Fri Mar 21 16:53:26 2003
+++ b/drivers/i2c/i2c-elv.c Fri Mar 21 16:53:26 2003
@@ -150,7 +150,7 @@
return -ENODEV;
}
} else {
- bit_elv_ops.data=(void*)base;
+ i2c_set_adapdata(&bit_elv_ops, (void *)base);
if (bit_elv_init()=0) {
if(i2c_bit_add_bus(&bit_elv_ops) < 0)
return -ENODEV;
diff -Nru a/drivers/i2c/scx200_acb.c b/drivers/i2c/scx200_acb.c
--- a/drivers/i2c/scx200_acb.c Fri Mar 21 16:53:26 2003
+++ b/drivers/i2c/scx200_acb.c Fri Mar 21 16:53:26 2003
@@ -289,7 +289,7 @@
char rw, u8 command, int size,
union i2c_smbus_data *data)
{
- struct scx200_acb_iface *iface = adapter->data;
+ struct scx200_acb_iface *iface = i2c_get_adapdata(adapter);
int len;
u8 *buffer;
u16 cur_word;
@@ -455,7 +455,7 @@
memset(iface, 0, sizeof(*iface));
adapter = &iface->adapter;
- adapter->data = iface;
+ i2c_set_adapdata(adapter, iface);
snprintf(adapter->dev.name, DEVICE_NAME_SIZE, "SCx200 ACB%d", index);
adapter->owner = THIS_MODULE;
adapter->id = I2C_ALGO_SMBUS;
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri Mar 21 16:53:26 2003
+++ b/include/linux/i2c.h Fri Mar 21 16:53:26 2003
@@ -219,12 +219,7 @@
int (*client_register)(struct i2c_client *);
int (*client_unregister)(struct i2c_client *);
- void *data; /* private data for the adapter */
- /* some data fields that are used by all types */
- /* these data fields are readonly to the public */
- /* and can be set via the i2c_ioctl call */
-
- /* data fields that are valid for all devices */
+ /* data fields that are valid for all devices */
struct semaphore bus;
struct semaphore list;
unsigned int flags;/* flags specifying div. data */
@@ -241,6 +236,16 @@
#endif /* def CONFIG_PROC_FS */
};
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
+
+static inline void *i2c_get_adapdata (struct i2c_adapter *dev)
+{
+ return dev_get_drvdata (&dev->dev);
+}
+
+static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
+{
+ return dev_set_drvdata (&dev->dev, data);
+}
/*flags for the driver struct: */
#define I2C_DF_NOTIFY 0x01 /* notify on bus (de/a)ttaches */
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1194, 2003/03/21 16:26:04-08:00, greg@kroah.com
i2c: actually register the i2c client device with the driver core.
We have to initialize the client structure with 0 to keep the
driver core from oopsing.
Now everything is hooked up enough to start removing the i2c sysctl
and proc crud.
drivers/i2c/chips/adm1021.c | 2 ++
drivers/i2c/chips/lm75.c | 2 ++
drivers/i2c/i2c-core.c | 10 ++++++++++
3 files changed, 14 insertions(+)
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:49 2003
+++ b/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:49 2003
@@ -221,6 +221,8 @@
err = -ENOMEM;
goto error0;
}
+ memset(new_client, 0x00, sizeof(struct i2c_client) +
+ sizeof(struct adm1021_data));
data = (struct adm1021_data *) (new_client + 1);
i2c_set_clientdata(new_client, data);
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:49 2003
+++ b/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:49 2003
@@ -140,6 +140,8 @@
err = -ENOMEM;
goto error0;
}
+ memset(new_client, 0x00, sizeof(struct i2c_client) +
+ sizeof(struct lm75_data));
data = (struct lm75_data *) (new_client + 1);
i2c_set_clientdata(new_client, data);
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri Mar 21 16:52:49 2003
+++ b/drivers/i2c/i2c-core.c Fri Mar 21 16:52:49 2003
@@ -378,6 +378,15 @@
if (client->flags & I2C_CLIENT_ALLOW_USE)
client->usage_count = 0;
+
+ client->dev.parent = &client->adapter->dev;
+ client->dev.driver = &client->driver->driver;
+ client->dev.bus = &i2c_bus_type;
+
+ snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), "i2c_dev_%d", i);
+ printk("registering %s\n", client->dev.bus_id);
+ device_register(&client->dev);
+
return 0;
}
@@ -414,6 +423,7 @@
res = -ENODEV;
out_unlock:
+ device_unregister(&client->dev);
up(&adapter->list);
out:
return res;
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1195, 2003/03/21 16:39:04-08:00, greg@kroah.com
[PATCH] i2c: fix up the chip driver names to play nice with sysfs
drivers/i2c/chips/adm1021.c | 2 +-
drivers/i2c/chips/lm75.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:40 2003
+++ b/drivers/i2c/chips/adm1021.c Fri Mar 21 16:52:40 2003
@@ -144,7 +144,7 @@
/* This is the driver that will be inserted */
static struct i2c_driver adm1021_driver = {
.owner = THIS_MODULE,
- .name = "ADM1021, MAX1617 sensor driver",
+ .name = "ADM1021-MAX1617",
.id = I2C_DRIVERID_ADM1021,
.flags = I2C_DF_NOTIFY,
.attach_adapter = adm1021_attach_adapter,
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:40 2003
+++ b/drivers/i2c/chips/lm75.c Fri Mar 21 16:52:40 2003
@@ -82,7 +82,7 @@
/* This is the driver that will be inserted */
static struct i2c_driver lm75_driver = {
.owner = THIS_MODULE,
- .name = "LM75 sensor chip driver",
+ .name = "LM75 sensor",
.id = I2C_DRIVERID_LM75,
.flags = I2C_DF_NOTIFY,
.attach_adapter = lm75_attach_adapter,
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Petr Vandrovec
0 siblings, 0 replies; 98+ messages in thread
From: Petr Vandrovec @ 2005-05-19 6:23 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel, sensors
On Fri, Mar 21, 2003 at 05:04:00PM -0800, Greg KH wrote:
> ChangeSet 1.1189, 2003/03/21 12:45:28-08:00, greg@kroah.com
>
> i2c: remove i2c_adapter->name and use dev->name instead.
>
>
> drivers/i2c/busses/i2c-ali15x3.c | 8 ++--
> drivers/i2c/busses/i2c-amd756.c | 6 ++-
> drivers/i2c/busses/i2c-amd8111.c | 4 +-
> drivers/i2c/busses/i2c-i801.c | 8 ++--
> drivers/i2c/busses/i2c-isa.c | 4 +-
> drivers/i2c/busses/i2c-piix4.c | 8 ++--
> drivers/i2c/i2c-algo-bit.c | 13 +++---
> drivers/i2c/i2c-algo-pcf.c | 19 ++++------
> drivers/i2c/i2c-core.c | 73 ++++++++++++++++-----------------------
> drivers/i2c/i2c-dev.c | 17 +++------
> drivers/i2c/i2c-elektor.c | 10 +++--
> drivers/i2c/i2c-elv.c | 4 +-
> drivers/i2c/i2c-philips-par.c | 4 +-
> drivers/i2c/i2c-velleman.c | 4 +-
> drivers/i2c/scx200_acb.c | 28 ++++++--------
> include/linux/i2c.h | 1
> 16 files changed, 105 insertions(+), 106 deletions(-)
Although you'll not break matroxfb more than it is currently, can you
also update drivers/video/matrox/{i2c-matroxfb,matroxfb_maven}.* in
your updates? Or I'll send you patch after this change hits Linus kernel...
Only problem is that there are apps which search DDC channel by
looking for i2c bus named "DDC:fbX #Y on i2c-matroxfb", and this
looks too long for generic driver infrastructure. But "DDC:fbX #Y"
looks acceptable...
Thanks,
Petr Vandrovec
vandrove@vc.cvut.cz
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: Petr Vandrovec; +Cc: linux-kernel, sensors
On Sat, Mar 22, 2003 at 03:33:51AM +0100, Petr Vandrovec wrote:
>
> Although you'll not break matroxfb more than it is currently, can you
> also update drivers/video/matrox/{i2c-matroxfb,matroxfb_maven}.* in
> your updates? Or I'll send you patch after this change hits Linus kernel...
Yeah, that stuff doesn't compile at all :)
I added a patch for the i2c related stuff to my tree that I just sent
out.
thanks for pointing it out.
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: Pavel Machek; +Cc: linux-kernel, sensors
On Tue, Mar 25, 2003 at 10:35:50AM +0100, Pavel Machek wrote:
> Hi!
>
> > + .name = "ADM1021-MAX1617",
>
> Why dash here
>
> > + .name = "LM75 sensor",
>
> And space here? Also you should have
> either 2x "sensor" or none at all.
What do you mwan "2x"? I just shortened that name up to fit within the
16 characters that we are allowed for driver names. If you can come up
with some better ones, please let me know.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Dave Jones
0 siblings, 0 replies; 98+ messages in thread
From: Dave Jones @ 2005-05-19 6:23 UTC (permalink / raw)
To: Greg KH; +Cc: Pavel Machek, linux-kernel, sensors
On Mon, Mar 24, 2003 at 05:29:23PM -0800, Greg KH wrote:
> > > + .name = "ADM1021-MAX1617",
> > Why dash here
> > > + .name = "LM75 sensor",
> > And space here? Also you should have
> > either 2x "sensor" or none at all.
> What do you mwan "2x"?
The way I parsed it, either have..
.name = "ADM1021-MAX1617 sensor",
.name = "LM75 sensor",
or
.name = "ADM1021-MAX1617",
.name = "LM75",
ie, both, or all. Personally the latter looks better to me.
Especially given the 16 char limit. Aren't these going to
be in a sysfs heirarchy where its obvious they are sensors
anyway ? like i2c/sensors/lm75 ?
Dave
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: Dave Jones, Pavel Machek, linux-kernel, sensors
On Tue, Mar 25, 2003 at 02:04:19AM +0000, Dave Jones wrote:
> On Mon, Mar 24, 2003 at 05:29:23PM -0800, Greg KH wrote:
>
> > > > + .name = "ADM1021-MAX1617",
> > > Why dash here
> > > > + .name = "LM75 sensor",
> > > And space here? Also you should have
> > > either 2x "sensor" or none at all.
> > What do you mwan "2x"?
>
> The way I parsed it, either have..
> .name = "ADM1021-MAX1617 sensor",
> .name = "LM75 sensor",
>
> or
>
> .name = "ADM1021-MAX1617",
> .name = "LM75",
>
> ie, both, or all. Personally the latter looks better to me.
Ah, yes, that makes more sense now.
Yes, we shouldn't have the "sensor" in the name.
> Especially given the 16 char limit. Aren't these going to
> be in a sysfs heirarchy where its obvious they are sensors
> anyway ? like i2c/sensors/lm75 ?
Yes, they show up as bus/i2c/drivers/
thanks,
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.65
@ 2005-05-19 6:23 ` Pavel Machek
0 siblings, 0 replies; 98+ messages in thread
From: Pavel Machek @ 2005-05-19 6:23 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel, sensors
Hi!
> + .name = "ADM1021-MAX1617",
Why dash here
> + .name = "LM75 sensor",
And space here? Also you should have
either 2x "sensor" or none at all.
--
Pavel
Written on sharp zaurus, because my Velo1 broke. If you have Velo you don't need...
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.66
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.6, 2003/04/02 11:32:24-08:00, greg@kroah.com
i2c: convert adm1021 chip driver to use sysfs files.
Note, some data is not converted and will not be displayed.
Someone with this hardware is going to have to finish the rest of
this conversion.
drivers/i2c/chips/adm1021.c | 358 ++++++++++++++++++++------------------------
1 files changed, 166 insertions(+), 192 deletions(-)
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c Wed Apr 2 16:01:25 2003
+++ b/drivers/i2c/chips/adm1021.c Wed Apr 2 16:01:25 2003
@@ -53,34 +53,34 @@
/* The adm1021 registers */
/* Read-only */
-#define ADM1021_REG_TEMP 0x00
-#define ADM1021_REG_REMOTE_TEMP 0x01
-#define ADM1021_REG_STATUS 0x02
-#define ADM1021_REG_MAN_ID 0x0FE /* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
-#define ADM1021_REG_DEV_ID 0x0FF /* ADM1021 = 0x0X, ADM1023 = 0x3X */
-#define ADM1021_REG_DIE_CODE 0x0FF /* MAX1617A */
+#define ADM1021_REG_TEMP 0x00
+#define ADM1021_REG_REMOTE_TEMP 0x01
+#define ADM1021_REG_STATUS 0x02
+#define ADM1021_REG_MAN_ID 0x0FE /* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
+#define ADM1021_REG_DEV_ID 0x0FF /* ADM1021 = 0x0X, ADM1023 = 0x3X */
+#define ADM1021_REG_DIE_CODE 0x0FF /* MAX1617A */
/* These use different addresses for reading/writing */
-#define ADM1021_REG_CONFIG_R 0x03
-#define ADM1021_REG_CONFIG_W 0x09
-#define ADM1021_REG_CONV_RATE_R 0x04
-#define ADM1021_REG_CONV_RATE_W 0x0A
+#define ADM1021_REG_CONFIG_R 0x03
+#define ADM1021_REG_CONFIG_W 0x09
+#define ADM1021_REG_CONV_RATE_R 0x04
+#define ADM1021_REG_CONV_RATE_W 0x0A
/* These are for the ADM1023's additional precision on the remote temp sensor */
-#define ADM1021_REG_REM_TEMP_PREC 0x010
-#define ADM1021_REG_REM_OFFSET 0x011
-#define ADM1021_REG_REM_OFFSET_PREC 0x012
-#define ADM1021_REG_REM_TOS_PREC 0x013
-#define ADM1021_REG_REM_THYST_PREC 0x014
+#define ADM1021_REG_REM_TEMP_PREC 0x010
+#define ADM1021_REG_REM_OFFSET 0x011
+#define ADM1021_REG_REM_OFFSET_PREC 0x012
+#define ADM1021_REG_REM_TOS_PREC 0x013
+#define ADM1021_REG_REM_THYST_PREC 0x014
/* limits */
-#define ADM1021_REG_TOS_R 0x05
-#define ADM1021_REG_TOS_W 0x0B
-#define ADM1021_REG_REMOTE_TOS_R 0x07
-#define ADM1021_REG_REMOTE_TOS_W 0x0D
-#define ADM1021_REG_THYST_R 0x06
-#define ADM1021_REG_THYST_W 0x0C
-#define ADM1021_REG_REMOTE_THYST_R 0x08
-#define ADM1021_REG_REMOTE_THYST_W 0x0E
+#define ADM1021_REG_TOS_R 0x05
+#define ADM1021_REG_TOS_W 0x0B
+#define ADM1021_REG_REMOTE_TOS_R 0x07
+#define ADM1021_REG_REMOTE_TOS_W 0x0D
+#define ADM1021_REG_THYST_R 0x06
+#define ADM1021_REG_THYST_W 0x0C
+#define ADM1021_REG_REMOTE_THYST_R 0x08
+#define ADM1021_REG_REMOTE_THYST_W 0x0E
/* write-only */
-#define ADM1021_REG_ONESHOT 0x0F
+#define ADM1021_REG_ONESHOT 0x0F
/* Conversions. Rounding and limit checking is only done on the TO_REG
@@ -88,8 +88,8 @@
these macros are called: arguments may be evaluated more than once.
Fixing this is just not worth it. */
/* Conversions note: 1021 uses normal integer signed-byte format*/
-#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
-#define TEMP_TO_REG(val) (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
+#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
+#define TEMP_TO_REG(val) (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
/* Initial values */
@@ -97,44 +97,43 @@
they don't quite work like a thermostat the way the LM75 does. I.e.,
a lower temp than THYST actually triggers an alarm instead of
clearing it. Weird, ey? --Phil */
-#define adm1021_INIT_TOS 60
-#define adm1021_INIT_THYST 20
-#define adm1021_INIT_REMOTE_TOS 60
-#define adm1021_INIT_REMOTE_THYST 20
+#define adm1021_INIT_TOS 60
+#define adm1021_INIT_THYST 20
+#define adm1021_INIT_REMOTE_TOS 60
+#define adm1021_INIT_REMOTE_THYST 20
/* Each client has this additional data */
struct adm1021_data {
- int sysctl_id;
enum chips type;
struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
- u8 temp, temp_os, temp_hyst; /* Register values */
- u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms, die_code;
+ u8 temp_max; /* Register values */
+ u8 temp_hyst;
+ u8 temp_input;
+ u8 remote_temp_max;
+ u8 remote_temp_hyst;
+ u8 remote_temp_input;
+ u8 alarms;
+ /* special values for ADM1021 only */
+ u8 die_code;
/* Special values for ADM1023 only */
- u8 remote_temp_prec, remote_temp_os_prec, remote_temp_hyst_prec,
- remote_temp_offset, remote_temp_offset_prec;
+ u8 remote_temp_prec;
+ u8 remote_temp_os_prec;
+ u8 remote_temp_hyst_prec;
+ u8 remote_temp_offset;
+ u8 remote_temp_offset_prec;
};
static int adm1021_attach_adapter(struct i2c_adapter *adapter);
-static int adm1021_detect(struct i2c_adapter *adapter, int address,
- unsigned short flags, int kind);
+static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind);
static void adm1021_init_client(struct i2c_client *client);
static int adm1021_detach_client(struct i2c_client *client);
static int adm1021_read_value(struct i2c_client *client, u8 reg);
static int adm1021_write_value(struct i2c_client *client, u8 reg,
u16 value);
-static void adm1021_temp(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
-static void adm1021_remote_temp(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag,
- long *results);
-static void adm1021_alarms(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
-static void adm1021_die_code(struct i2c_client *client, int operation,
- int ctl_name, int *nrels_mag, long *results);
static void adm1021_update_client(struct i2c_client *client);
/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
@@ -151,45 +150,63 @@
.detach_client = adm1021_detach_client,
};
-/* These files are created for each detected adm1021. This is just a template;
- though at first sight, you might think we could use a statically
- allocated list, we need some way to get back to the parent - which
- is done through one of the 'extra' fields which are initialized
- when a new copy is allocated. */
-static ctl_table adm1021_dir_table_template[] = {
- {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_temp},
- {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_remote_temp},
- {ADM1021_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_die_code},
- {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_alarms},
- {0}
-};
-
-static ctl_table adm1021_max_dir_table_template[] = {
- {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_temp},
- {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_remote_temp},
- {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
- &i2c_sysctl_real, NULL, &adm1021_alarms},
- {0}
-};
-
/* I choose here for semi-static allocation. Complete dynamic
allocation could also be used; the code needed for this would probably
take more memory than the datastructure takes now. */
static int adm1021_id = 0;
+#define show(value) \
+static ssize_t show_##value(struct device *dev, char *buf) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct adm1021_data *data = i2c_get_clientdata(client); \
+ int temp; \
+ \
+ adm1021_update_client(client); \
+ temp = TEMP_FROM_REG(data->value); \
+ return sprintf(buf, "%d\n", temp); \
+}
+show(temp_max);
+show(temp_hyst);
+show(temp_input);
+show(remote_temp_max);
+show(remote_temp_hyst);
+show(remote_temp_input);
+show(alarms);
+show(die_code);
+
+#define set(value, reg) \
+static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct adm1021_data *data = i2c_get_clientdata(client); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ \
+ data->value = TEMP_TO_REG(temp); \
+ adm1021_write_value(client, reg, data->value); \
+ return count; \
+}
+set(temp_max, ADM1021_REG_TOS_W);
+set(temp_hyst, ADM1021_REG_THYST_W);
+set(remote_temp_max, ADM1021_REG_REMOTE_TOS_W);
+set(remote_temp_hyst, ADM1021_REG_REMOTE_THYST_W);
+
+static DEVICE_ATTR(temp_max1, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
+static DEVICE_ATTR(temp_min1, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
+static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input, NULL);
+static DEVICE_ATTR(temp_max2, S_IWUSR | S_IRUGO, show_remote_temp_max, set_remote_temp_max);
+static DEVICE_ATTR(temp_min2, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst);
+static DEVICE_ATTR(temp_input2, S_IRUGO, show_remote_temp_input, NULL);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static DEVICE_ATTR(die_code, S_IRUGO, show_die_code, NULL);
+
+
static int adm1021_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_detect(adapter, &addr_data, adm1021_detect);
}
-static int adm1021_detect(struct i2c_adapter *adapter, int address,
- unsigned short flags, int kind)
+static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i;
struct i2c_client *new_client;
@@ -202,8 +219,7 @@
at this moment; i2c_detect really won't call us. */
#ifdef DEBUG
if (i2c_is_isa_adapter(adapter)) {
- printk
- ("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
+ dev_dbg(&adapter->dev, "adm1021_detect called for an ISA bus adapter?!?\n");
return 0;
}
#endif
@@ -232,35 +248,28 @@
new_client->flags = 0;
/* Now, we do the remaining detection. */
-
if (kind < 0) {
- if (
- (adm1021_read_value(new_client, ADM1021_REG_STATUS) &
- 0x03) != 0x00)
+ if ((adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0x03) != 0x00)
goto error1;
}
/* Determine the chip type. */
-
if (kind <= 0) {
i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID);
if (i = 0x41)
- if ((adm1021_read_value (new_client, ADM1021_REG_DEV_ID) & 0x0F0) = 0x030)
- kind = adm1023;
- else
- kind = adm1021;
+ if ((adm1021_read_value(new_client, ADM1021_REG_DEV_ID) & 0x0F0) = 0x030)
+ kind = adm1023;
+ else
+ kind = adm1021;
else if (i = 0x49)
kind = thmc10;
else if (i = 0x23)
kind = gl523sm;
else if ((i = 0x4d) &&
- (adm1021_read_value
- (new_client, ADM1021_REG_DEV_ID) = 0x01))
+ (adm1021_read_value(new_client, ADM1021_REG_DEV_ID) = 0x01))
kind = max1617a;
/* LM84 Mfr ID in a different place */
- else
- if (adm1021_read_value
- (new_client, ADM1021_REG_CONV_RATE_R) = 0x00)
+ else if (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) = 0x00)
kind = lm84;
else if (i = 0x54)
kind = mc1066;
@@ -293,10 +302,8 @@
type_name = "mc1066";
client_name = "MC1066 chip";
} else {
-#ifdef DEBUG
- printk("adm1021.o: Internal error: unknown kind (%d)?!?",
- kind);
-#endif
+ dev_err(&adapter->dev, "Internal error: unknown kind (%d)?!?",
+ kind);
goto error1;
}
@@ -312,25 +319,24 @@
if ((err = i2c_attach_client(new_client)))
goto error3;
- /* Register a new directory entry with module sensors */
- err = i2c_register_entry(new_client, type_name,
- (data->type = adm1021) ?
- adm1021_dir_table_template :
- adm1021_max_dir_table_template);
- if (err < 0)
- goto error4;
+ device_create_file(&new_client->dev, &dev_attr_temp_max1);
+ device_create_file(&new_client->dev, &dev_attr_temp_min1);
+ device_create_file(&new_client->dev, &dev_attr_temp_input1);
+ device_create_file(&new_client->dev, &dev_attr_temp_max2);
+ device_create_file(&new_client->dev, &dev_attr_temp_min2);
+ device_create_file(&new_client->dev, &dev_attr_temp_input2);
+ device_create_file(&new_client->dev, &dev_attr_alarms);
+ if (data->type = adm1021)
+ device_create_file(&new_client->dev, &dev_attr_die_code);
- data->sysctl_id = err;
/* Initialize the ADM1021 chip */
adm1021_init_client(new_client);
return 0;
- error4:
- i2c_detach_client(new_client);
- error3:
- error1:
+error3:
+error1:
kfree(new_client);
- error0:
+error0:
return err;
}
@@ -353,21 +359,15 @@
static int adm1021_detach_client(struct i2c_client *client)
{
-
int err;
- i2c_deregister_entry(((struct adm1021_data *) (i2c_get_clientdata(client)))->sysctl_id);
-
if ((err = i2c_detach_client(client))) {
- printk
- ("adm1021.o: Client deregistration failed, client not detached.\n");
+ dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
return err;
}
kfree(client);
-
return 0;
-
}
/* All registers are byte-sized */
@@ -391,39 +391,23 @@
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
(jiffies < data->last_updated) || !data->valid) {
+ dev_dbg(&client->dev, "Starting adm1021 update\n");
-#ifdef DEBUG
- printk("Starting adm1021 update\n");
-#endif
-
- data->temp = adm1021_read_value(client, ADM1021_REG_TEMP);
- data->temp_os - adm1021_read_value(client, ADM1021_REG_TOS_R);
- data->temp_hyst - adm1021_read_value(client, ADM1021_REG_THYST_R);
- data->remote_temp - adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
- data->remote_temp_os - adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
- data->remote_temp_hyst - adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
- data->alarms - adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec;
+ data->temp_input = adm1021_read_value(client, ADM1021_REG_TEMP);
+ data->temp_max = adm1021_read_value(client, ADM1021_REG_TOS_R);
+ data->temp_hyst = adm1021_read_value(client, ADM1021_REG_THYST_R);
+ data->remote_temp_input = adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
+ data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
+ data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
+ data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec;
if (data->type = adm1021)
- data->die_code - adm1021_read_value(client,
- ADM1021_REG_DIE_CODE);
+ data->die_code = adm1021_read_value(client, ADM1021_REG_DIE_CODE);
if (data->type = adm1023) {
- data->remote_temp_prec - adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
- data->remote_temp_os_prec - adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
- data->remote_temp_hyst_prec - adm1021_read_value(client, ADM1021_REG_REM_THYST_PREC);
- data->remote_temp_offset - adm1021_read_value(client, ADM1021_REG_REM_OFFSET);
- data->remote_temp_offset_prec - adm1021_read_value(client, ADM1021_REG_REM_OFFSET_PREC);
+ data->remote_temp_prec = adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
+ data->remote_temp_os_prec = adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
+ data->remote_temp_hyst_prec = adm1021_read_value(client, ADM1021_REG_REM_THYST_PREC);
+ data->remote_temp_offset = adm1021_read_value(client, ADM1021_REG_REM_OFFSET);
+ data->remote_temp_offset_prec = adm1021_read_value(client, ADM1021_REG_REM_OFFSET_PREC);
}
data->last_updated = jiffies;
data->valid = 1;
@@ -433,6 +417,9 @@
}
+/* FIXME, remove these four functions, they are here to verify the sysfs
+ * conversion is correct, or not */
+__attribute__((unused))
static void adm1021_temp(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
@@ -442,15 +429,15 @@
*nrels_mag = 0;
else if (operation = SENSORS_PROC_REAL_READ) {
adm1021_update_client(client);
- results[0] = TEMP_FROM_REG(data->temp_os);
+ results[0] = TEMP_FROM_REG(data->temp_max);
results[1] = TEMP_FROM_REG(data->temp_hyst);
- results[2] = TEMP_FROM_REG(data->temp);
+ results[2] = TEMP_FROM_REG(data->temp_input);
*nrels_mag = 3;
} else if (operation = SENSORS_PROC_REAL_WRITE) {
if (*nrels_mag >= 1) {
- data->temp_os = TEMP_TO_REG(results[0]);
+ data->temp_max = TEMP_TO_REG(results[0]);
adm1021_write_value(client, ADM1021_REG_TOS_W,
- data->temp_os);
+ data->temp_max);
}
if (*nrels_mag >= 2) {
data->temp_hyst = TEMP_TO_REG(results[1]);
@@ -460,6 +447,7 @@
}
}
+__attribute__((unused))
static void adm1021_remote_temp(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
@@ -471,68 +459,53 @@
else { *nrels_mag = 0; }
else if (operation = SENSORS_PROC_REAL_READ) {
adm1021_update_client(client);
- results[0] = TEMP_FROM_REG(data->remote_temp_os);
+ results[0] = TEMP_FROM_REG(data->remote_temp_max);
results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
- results[2] = TEMP_FROM_REG(data->remote_temp);
+ results[2] = TEMP_FROM_REG(data->remote_temp_input);
if (data->type = adm1023) {
- results[0]=results[0]*1000 +
- ((data->remote_temp_os_prec >> 5) * 125);
- results[1]=results[1]*1000 +
- ((data->remote_temp_hyst_prec >> 5) * 125);
- results[2]=(TEMP_FROM_REG(data->remote_temp_offset)*1000) +
- ((data->remote_temp_offset_prec >> 5) * 125);
- results[3]=TEMP_FROM_REG(data->remote_temp)*1000 +
- ((data->remote_temp_prec >> 5) * 125);
- *nrels_mag = 4;
+ results[0] = results[0]*1000 + ((data->remote_temp_os_prec >> 5) * 125);
+ results[1] = results[1]*1000 + ((data->remote_temp_hyst_prec >> 5) * 125);
+ results[2] = (TEMP_FROM_REG(data->remote_temp_offset)*1000) + ((data->remote_temp_offset_prec >> 5) * 125);
+ results[3] = (TEMP_FROM_REG(data->remote_temp_input)*1000) + ((data->remote_temp_prec >> 5) * 125);
+ *nrels_mag = 4;
} else {
- *nrels_mag = 3;
+ *nrels_mag = 3;
}
} else if (operation = SENSORS_PROC_REAL_WRITE) {
if (*nrels_mag >= 1) {
if (data->type = adm1023) {
- prec=((results[0]-((results[0]/1000)*1000))/125)<<5;
- adm1021_write_value(client,
- ADM1021_REG_REM_TOS_PREC,
- prec);
- results[0]=results[0]/1000;
- data->remote_temp_os_prec=prec;
+ prec = ((results[0]-((results[0]/1000)*1000))/125)<<5;
+ adm1021_write_value(client, ADM1021_REG_REM_TOS_PREC, prec);
+ results[0] = results[0]/1000;
+ data->remote_temp_os_prec=prec;
}
- data->remote_temp_os = TEMP_TO_REG(results[0]);
- adm1021_write_value(client,
- ADM1021_REG_REMOTE_TOS_W,
- data->remote_temp_os);
+ data->remote_temp_max = TEMP_TO_REG(results[0]);
+ adm1021_write_value(client, ADM1021_REG_REMOTE_TOS_W, data->remote_temp_max);
}
if (*nrels_mag >= 2) {
if (data->type = adm1023) {
- prec=((results[1]-((results[1]/1000)*1000))/125)<<5;
- adm1021_write_value(client,
- ADM1021_REG_REM_THYST_PREC,
- prec);
- results[1]=results[1]/1000;
- data->remote_temp_hyst_prec=prec;
+ prec = ((results[1]-((results[1]/1000)*1000))/125)<<5;
+ adm1021_write_value(client, ADM1021_REG_REM_THYST_PREC, prec);
+ results[1] = results[1]/1000;
+ data->remote_temp_hyst_prec=prec;
}
data->remote_temp_hyst = TEMP_TO_REG(results[1]);
- adm1021_write_value(client,
- ADM1021_REG_REMOTE_THYST_W,
- data->remote_temp_hyst);
+ adm1021_write_value(client, ADM1021_REG_REMOTE_THYST_W, data->remote_temp_hyst);
}
if (*nrels_mag >= 3) {
if (data->type = adm1023) {
- prec=((results[2]-((results[2]/1000)*1000))/125)<<5;
- adm1021_write_value(client,
- ADM1021_REG_REM_OFFSET_PREC,
- prec);
- results[2]=results[2]/1000;
- data->remote_temp_offset_prec=prec;
- data->remote_temp_offset=results[2];
- adm1021_write_value(client,
- ADM1021_REG_REM_OFFSET,
- data->remote_temp_offset);
+ prec = ((results[2]-((results[2]/1000)*1000))/125)<<5;
+ adm1021_write_value(client, ADM1021_REG_REM_OFFSET_PREC, prec);
+ results[2]=results[2]/1000;
+ data->remote_temp_offset_prec=prec;
+ data->remote_temp_offset=results[2];
+ adm1021_write_value(client, ADM1021_REG_REM_OFFSET, data->remote_temp_offset);
}
}
}
}
+__attribute__((unused))
static void adm1021_die_code(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
@@ -549,6 +522,7 @@
}
}
+__attribute__((unused))
static void adm1021_alarms(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
@@ -574,8 +548,8 @@
i2c_del_driver(&adm1021_driver);
}
-MODULE_AUTHOR
- ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
+MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl> and "
+ "Philip Edelbrock <phil@netroedge.com>");
MODULE_DESCRIPTION("adm1021 driver");
MODULE_LICENSE("GPL");
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.66
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.977.29.8, 2003/04/02 11:45:21-08:00, greg@kroah.com
i2c: remove proc and sysctl code from i2c-proc as it is no longer used.
drivers/i2c/i2c-proc.c | 546 -----------------------------------------------
include/linux/i2c-proc.h | 40 ---
2 files changed, 586 deletions(-)
diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
--- a/drivers/i2c/i2c-proc.c Wed Apr 2 16:01:04 2003
+++ b/drivers/i2c/i2c-proc.c Wed Apr 2 16:01:04 2003
@@ -37,539 +37,6 @@
#include <linux/i2c-proc.h>
#include <asm/uaccess.h>
-static int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
- long *results, int magnitude);
-static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize,
- long *results, int magnitude);
-static int i2c_proc_chips(ctl_table * ctl, int write,
- struct file *filp, void *buffer,
- size_t * lenp);
-static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
- void *oldval, size_t * oldlenp,
- void *newval, size_t newlen,
- void **context);
-
-#define SENSORS_ENTRY_MAX 20
-static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX];
-
-static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX];
-
-static ctl_table i2c_proc_dev_sensors[] = {
- {SENSORS_CHIPS, "chips", NULL, 0, 0644, NULL, &i2c_proc_chips,
- &i2c_sysctl_chips},
- {0}
-};
-
-static ctl_table i2c_proc_dev[] = {
- {DEV_SENSORS, "sensors", NULL, 0, 0555, i2c_proc_dev_sensors},
- {0},
-};
-
-
-static ctl_table i2c_proc[] = {
- {CTL_DEV, "dev", NULL, 0, 0555, i2c_proc_dev},
- {0}
-};
-
-
-static struct ctl_table_header *i2c_proc_header;
-
-/* This returns a nice name for a new directory; for example lm78-isa-0310
- (for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for
- a LM75 chip on the third i2c bus at address 0x4e).
- name is allocated first. */
-static char *generate_name(struct i2c_client *client, const char *prefix)
-{
- struct i2c_adapter *adapter = client->adapter;
- int addr = client->addr;
- char name_buffer[50], *name;
-
- if (i2c_is_isa_adapter(adapter)) {
- sprintf(name_buffer, "%s-isa-%04x", prefix, addr);
- } else if (adapter->algo->smbus_xfer || adapter->algo->master_xfer) {
- int id = i2c_adapter_id(adapter);
- if (id < 0)
- return ERR_PTR(-ENOENT);
- sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr);
- } else { /* dummy adapter, generate prefix */
- int end, i;
-
- sprintf(name_buffer, "%s-", prefix);
- end = strlen(name_buffer);
-
- for (i = 0; i < 32; i++) {
- if (adapter->algo->name[i] = ' ')
- break;
- name_buffer[end++] = tolower(adapter->algo->name[i]);
- }
-
- name_buffer[end] = 0;
- sprintf(name_buffer + end, "-%04x", addr);
- }
-
- name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL);
- if (unlikely(!name))
- return ERR_PTR(-ENOMEM);
- strcpy(name, name_buffer);
- return name;
-}
-
-/* This rather complex function must be called when you want to add an entry
- to /proc/sys/dev/sensors/chips. It also creates a new directory within
- /proc/sys/dev/sensors/.
- ctl_template should be a template of the newly created directory. It is
- copied in memory. The extra2 field of each file is set to point to client.
- If any driver wants subdirectories within the newly created directory,
- this function must be updated! */
-int i2c_register_entry(struct i2c_client *client, const char *prefix,
- struct ctl_table *leaf)
-{
- struct { struct ctl_table root[2], dev[2], sensors[2]; } *tbl;
- struct ctl_table_header *hdr;
- struct ctl_table *tmp;
- const char *name;
- int id;
-
- name = generate_name(client, prefix);
- if (IS_ERR(name))
- return PTR_ERR(name);
-
- for (id = 0; id < SENSORS_ENTRY_MAX; id++) {
- if (!i2c_entries[id])
- goto free_slot;
- }
-
- goto out_free_name;
-
- free_slot:
- tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
- if (unlikely(!tbl))
- goto out_free_name;
- memset(tbl, 0, sizeof(*tbl));
-
- for (tmp = leaf; tmp->ctl_name; tmp++)
- tmp->extra2 = client;
-
- tbl->sensors->ctl_name = id+256;
- tbl->sensors->procname = name;
- tbl->sensors->mode = 0555;
- tbl->sensors->child = leaf;
-
- tbl->dev->ctl_name = DEV_SENSORS;
- tbl->dev->procname = "sensors";
- tbl->dev->mode = 0555;
- tbl->dev->child = tbl->sensors;
-
- tbl->root->ctl_name = CTL_DEV;
- tbl->root->procname = "dev";
- tbl->root->mode = 0555;
- tbl->root->child = tbl->dev;
-
- hdr = register_sysctl_table(tbl->root, 0);
- if (unlikely(!hdr))
- goto out_free_tbl;
-
- i2c_entries[id] = hdr;
- i2c_clients[id] = client;
-
- return (id + 256); /* XXX(hch) why?? */
-
- out_free_tbl:
- kfree(tbl);
- out_free_name:
- kfree(name);
- return -ENOMEM;
-}
-
-void i2c_deregister_entry(int id)
-{
- id -= 256;
-
- if (i2c_entries[id]) {
- struct ctl_table_header *hdr = i2c_entries[id];
- struct ctl_table *tbl = hdr->ctl_table;
-
- unregister_sysctl_table(hdr);
- kfree(tbl->child->child->procname);
- kfree(tbl); /* actually the whole anonymous struct */
- }
-
- i2c_entries[id] = NULL;
- i2c_clients[id] = NULL;
-}
-
-static int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp,
- void *buffer, size_t * lenp)
-{
- char BUF[SENSORS_PREFIX_MAX + 30];
- int buflen, curbufsize, i;
- struct ctl_table *client_tbl;
-
- if (write)
- return 0;
-
- /* If buffer is size 0, or we try to read when not at the start, we
- return nothing. Note that I think writing when not at the start
- does not work either, but anyway, this is straight from the kernel
- sources. */
- if (!*lenp || (filp->f_pos && !write)) {
- *lenp = 0;
- return 0;
- }
- curbufsize = 0;
- for (i = 0; i < SENSORS_ENTRY_MAX; i++)
- if (i2c_entries[i]) {
- client_tbl - i2c_entries[i]->ctl_table->child->child;
- buflen - sprintf(BUF, "%d\t%s\n", client_tbl->ctl_name,
- client_tbl->procname);
- if (buflen + curbufsize > *lenp)
- buflen = *lenp - curbufsize;
- if(copy_to_user(buffer, BUF, buflen))
- return -EFAULT;
- curbufsize += buflen;
- (char *) buffer += buflen;
- }
- *lenp = curbufsize;
- filp->f_pos += curbufsize;
- return 0;
-}
-
-static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
- void *oldval, size_t * oldlenp, void *newval,
- size_t newlen, void **context)
-{
- struct i2c_chips_data data;
- int i, oldlen, nrels, maxels,ret=0;
- struct ctl_table *client_tbl;
-
- if (oldval && oldlenp && !((ret = get_user(oldlen, oldlenp))) &&
- oldlen) {
- maxels = oldlen / sizeof(struct i2c_chips_data);
- nrels = 0;
- for (i = 0; (i < SENSORS_ENTRY_MAX) && (nrels < maxels);
- i++)
- if (i2c_entries[i]) {
- client_tbl - i2c_entries[i]->ctl_table->child->
- child;
- data.sysctl_id = client_tbl->ctl_name;
- strcpy(data.name, client_tbl->procname);
- if(copy_to_user(oldval, &data,
- sizeof(struct
- i2c_chips_data)))
- return -EFAULT;
- (char *) oldval +- sizeof(struct i2c_chips_data);
- nrels++;
- }
- oldlen = nrels * sizeof(struct i2c_chips_data);
- if(put_user(oldlen, oldlenp))
- return -EFAULT;
- }
- return ret;
-}
-
-
-/* This function reads or writes a 'real' value (encoded by the combination
- of an integer and a magnitude, the last is the power of ten the value
- should be divided with) to a /proc/sys directory. To use this function,
- you must (before registering the ctl_table) set the extra2 field to the
- client, and the extra1 field to a function of the form:
- void func(struct i2c_client *client, int operation, int ctl_name,
- int *nrels_mag, long *results)
- This function can be called for three values of operation. If operation
- equals SENSORS_PROC_REAL_INFO, the magnitude should be returned in
- nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should
- be read into results. nrels_mag should return the number of elements
- read; the maximum number is put in it on entry. Finally, if operation
- equals SENSORS_PROC_REAL_WRITE, the values in results should be
- written to the chip. nrels_mag contains on entry the number of elements
- found.
- In all cases, client points to the client we wish to interact with,
- and ctl_name is the SYSCTL id of the file we are accessing. */
-int i2c_proc_real(ctl_table * ctl, int write, struct file *filp,
- void *buffer, size_t * lenp)
-{
-#define MAX_RESULTS 32
- int mag, nrels = MAX_RESULTS;
- long results[MAX_RESULTS];
- i2c_real_callback callback = ctl->extra1;
- struct i2c_client *client = ctl->extra2;
- int res;
-
- /* If buffer is size 0, or we try to read when not at the start, we
- return nothing. Note that I think writing when not at the start
- does not work either, but anyway, this is straight from the kernel
- sources. */
- if (!*lenp || (filp->f_pos && !write)) {
- *lenp = 0;
- return 0;
- }
-
- /* Get the magnitude */
- callback(client, SENSORS_PROC_REAL_INFO, ctl->ctl_name, &mag,
- NULL);
-
- if (write) {
- /* Read the complete input into results, converting to longs */
- res = i2c_parse_reals(&nrels, buffer, *lenp, results, mag);
- if (res)
- return res;
-
- if (!nrels)
- return 0;
-
- /* Now feed this information back to the client */
- callback(client, SENSORS_PROC_REAL_WRITE, ctl->ctl_name,
- &nrels, results);
-
- filp->f_pos += *lenp;
- return 0;
- } else { /* read */
- /* Get the information from the client into results */
- callback(client, SENSORS_PROC_REAL_READ, ctl->ctl_name,
- &nrels, results);
-
- /* And write them to buffer, converting to reals */
- res = i2c_write_reals(nrels, buffer, lenp, results, mag);
- if (res)
- return res;
- filp->f_pos += *lenp;
- return 0;
- }
-}
-
-/* This function is equivalent to i2c_proc_real, only it interacts with
- the sysctl(2) syscall, and returns no reals, but integers */
-int i2c_sysctl_real(ctl_table * table, int *name, int nlen,
- void *oldval, size_t * oldlenp, void *newval,
- size_t newlen, void **context)
-{
- long results[MAX_RESULTS];
- int oldlen, nrels = MAX_RESULTS,ret=0;
- i2c_real_callback callback = table->extra1;
- struct i2c_client *client = table->extra2;
-
- /* Check if we need to output the old values */
- if (oldval && oldlenp && !((ret=get_user(oldlen, oldlenp))) && oldlen) {
- callback(client, SENSORS_PROC_REAL_READ, table->ctl_name,
- &nrels, results);
-
- /* Note the rounding factor! */
- if (nrels * sizeof(long) < oldlen)
- oldlen = nrels * sizeof(long);
- oldlen = (oldlen / sizeof(long)) * sizeof(long);
- if(copy_to_user(oldval, results, oldlen))
- return -EFAULT;
- if(put_user(oldlen, oldlenp))
- return -EFAULT;
- }
-
- if (newval && newlen) {
- /* Note the rounding factor! */
- newlen -= newlen % sizeof(long);
- nrels = newlen / sizeof(long);
- if(copy_from_user(results, newval, newlen))
- return -EFAULT;
-
- /* Get the new values back to the client */
- callback(client, SENSORS_PROC_REAL_WRITE, table->ctl_name,
- &nrels, results);
- }
- return ret;
-}
-
-
-/* nrels contains initially the maximum number of elements which can be
- put in results, and finally the number of elements actually put there.
- A magnitude of 1 will multiply everything with 10; etc.
- buffer, bufsize is the character buffer we read from and its length.
- results will finally contain the parsed integers.
-
- Buffer should contain several reals, separated by whitespace. A real
- has the following syntax:
- [ Minus ] Digit* [ Dot Digit* ]
- (everything between [] is optional; * means zero or more).
- When the next character is unparsable, everything is skipped until the
- next whitespace.
-
- WARNING! This is tricky code. I have tested it, but there may still be
- hidden bugs in it, even leading to crashes and things!
-*/
-static int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
- long *results, int magnitude)
-{
- int maxels, min, mag;
- long res,ret=0;
- char nextchar = 0;
-
- maxels = *nrels;
- *nrels = 0;
-
- while (bufsize && (*nrels < maxels)) {
-
- /* Skip spaces at the start */
- while (bufsize &&
- !((ret=get_user(nextchar, (char *) buffer))) &&
- isspace((int) nextchar)) {
- bufsize--;
- ((char *) buffer)++;
- }
-
- if (ret)
- return -EFAULT;
- /* Well, we may be done now */
- if (!bufsize)
- return 0;
-
- /* New defaults for our result */
- min = 0;
- res = 0;
- mag = magnitude;
-
- /* Check for a minus */
- if (!((ret=get_user(nextchar, (char *) buffer)))
- && (nextchar = '-')) {
- min = 1;
- bufsize--;
- ((char *) buffer)++;
- }
- if (ret)
- return -EFAULT;
-
- /* Digits before a decimal dot */
- while (bufsize &&
- !((ret=get_user(nextchar, (char *) buffer))) &&
- isdigit((int) nextchar)) {
- res = res * 10 + nextchar - '0';
- bufsize--;
- ((char *) buffer)++;
- }
- if (ret)
- return -EFAULT;
-
- /* If mag < 0, we must actually divide here! */
- while (mag < 0) {
- res = res / 10;
- mag++;
- }
-
- if (bufsize && (nextchar = '.')) {
- /* Skip the dot */
- bufsize--;
- ((char *) buffer)++;
-
- /* Read digits while they are significant */
- while (bufsize && (mag > 0) &&
- !((ret=get_user(nextchar, (char *) buffer))) &&
- isdigit((int) nextchar)) {
- res = res * 10 + nextchar - '0';
- mag--;
- bufsize--;
- ((char *) buffer)++;
- }
- if (ret)
- return -EFAULT;
- }
- /* If we are out of data, but mag > 0, we need to scale here */
- while (mag > 0) {
- res = res * 10;
- mag--;
- }
-
- /* Skip everything until we hit whitespace */
- while (bufsize &&
- !((ret=get_user(nextchar, (char *) buffer))) &&
- isspace((int) nextchar)) {
- bufsize--;
- ((char *) buffer)++;
- }
- if (ret)
- return -EFAULT;
-
- /* Put res in results */
- results[*nrels] = (min ? -1 : 1) * res;
- (*nrels)++;
- }
-
- /* Well, there may be more in the buffer, but we need no more data.
- Ignore anything that is left. */
- return 0;
-}
-
-static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize,
- long *results, int magnitude)
-{
-#define BUFLEN 20
- char BUF[BUFLEN + 1]; /* An individual representation should fit! */
- char printfstr[10];
- int nr = 0;
- int buflen, mag, times;
- int curbufsize = 0;
-
- while ((nr < nrels) && (curbufsize < *bufsize)) {
- mag = magnitude;
-
- if (nr != 0) {
- if(put_user(' ', (char *) buffer))
- return -EFAULT;
- curbufsize++;
- ((char *) buffer)++;
- }
-
- /* Fill BUF with the representation of the next string */
- if (mag <= 0) {
- buflen = sprintf(BUF, "%ld", results[nr]);
- if (buflen < 0) { /* Oops, a sprintf error! */
- *bufsize = 0;
- return -EINVAL;
- }
- while ((mag < 0) && (buflen < BUFLEN)) {
- BUF[buflen++] = '0';
- mag++;
- }
- BUF[buflen] = 0;
- } else {
- times = 1;
- for (times = 1; mag-- > 0; times *= 10);
- if (results[nr] < 0) {
- BUF[0] = '-';
- buflen = 1;
- } else
- buflen = 0;
- strcpy(printfstr, "%ld.%0Xld");
- printfstr[6] = magnitude + '0';
- buflen +- sprintf(BUF + buflen, printfstr,
- abs(results[nr]) / times,
- abs(results[nr]) % times);
- if (buflen < 0) { /* Oops, a sprintf error! */
- *bufsize = 0;
- return -EINVAL;
- }
- }
-
- /* Now copy it to the user-space buffer */
- if (buflen + curbufsize > *bufsize)
- buflen = *bufsize - curbufsize;
- if(copy_to_user(buffer, BUF, buflen))
- return -EFAULT;
- curbufsize += buflen;
- (char *) buffer += buflen;
-
- nr++;
- }
- if (curbufsize < *bufsize) {
- if(put_user('\n', (char *) buffer))
- return -EFAULT;
- curbufsize++;
- }
- *bufsize = curbufsize;
- return 0;
-}
-
/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
int i2c_detect(struct i2c_adapter *adapter,
@@ -703,26 +170,13 @@
static int __init i2c_proc_init(void)
{
- printk(KERN_INFO "i2c-proc.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
- if (!
- (i2c_proc_header - register_sysctl_table(i2c_proc, 0))) {
- printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n");
- return -EPERM;
- }
- i2c_proc_header->ctl_table->child->de->owner = THIS_MODULE;
return 0;
}
static void __exit i2c_proc_exit(void)
{
- unregister_sysctl_table(i2c_proc_header);
}
-EXPORT_SYMBOL(i2c_register_entry);
-EXPORT_SYMBOL(i2c_deregister_entry);
-EXPORT_SYMBOL(i2c_proc_real);
-EXPORT_SYMBOL(i2c_sysctl_real);
EXPORT_SYMBOL(i2c_detect);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
diff -Nru a/include/linux/i2c-proc.h b/include/linux/i2c-proc.h
--- a/include/linux/i2c-proc.h Wed Apr 2 16:01:04 2003
+++ b/include/linux/i2c-proc.h Wed Apr 2 16:01:04 2003
@@ -34,46 +34,6 @@
#define SENSORS_PROC_REAL_READ 2
#define SENSORS_PROC_REAL_WRITE 3
-/* These funcion reads or writes a 'real' value (encoded by the combination
- of an integer and a magnitude, the last is the power of ten the value
- should be divided with) to a /proc/sys directory. To use these functions,
- you must (before registering the ctl_table) set the extra2 field to the
- client, and the extra1 field to a function of the form:
- void func(struct i2c_client *client, int operation, int ctl_name,
- int *nrels_mag, long *results)
- This last function can be called for three values of operation. If
- operation equals SENSORS_PROC_REAL_INFO, the magnitude should be returned
- in nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should
- be read into results. nrels_mag should return the number of elements
- read; the maximum number is put in it on entry. Finally, if operation
- equals SENSORS_PROC_REAL_WRITE, the values in results should be
- written to the chip. nrels_mag contains on entry the number of elements
- found.
- In all cases, client points to the client we wish to interact with,
- and ctl_name is the SYSCTL id of the file we are accessing. */
-extern int i2c_sysctl_real(ctl_table * table, int *name, int nlen,
- void *oldval, size_t * oldlenp,
- void *newval, size_t newlen,
- void **context);
-extern int i2c_proc_real(ctl_table * ctl, int write, struct file *filp,
- void *buffer, size_t * lenp);
-
-
-
-/* These rather complex functions must be called when you want to add or
- delete an entry in /proc/sys/dev/sensors/chips (not yet implemented). It
- also creates a new directory within /proc/sys/dev/sensors/.
- ctl_template should be a template of the newly created directory. It is
- copied in memory. The extra2 field of each file is set to point to client.
- If any driver wants subdirectories within the newly created directory,
- these functions must be updated! */
-extern int i2c_register_entry(struct i2c_client *client,
- const char *prefix,
- ctl_table * ctl_template);
-
-extern void i2c_deregister_entry(int id);
-
-
/* A structure containing detect information.
Force variables overrule all other variables; they force a detection on
that place. If a specific chip is given, the module blindly assumes this
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.66
@ 2005-05-19 6:23 ` Albert Cranford
0 siblings, 0 replies; 98+ messages in thread
From: Albert Cranford @ 2005-05-19 6:23 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel, sensors
I read the thread concerning the removal of proc.c & proc.h
but hope that this does not go to Linus until the interface
between i2c & sensors to application is somewhat defined.
At the moment we have a sysctl API used by sensors, video and
other i2c kernel applications that is working.
Our desire to switch the sensors to sysfs interface should not
break other applications. At least until we have a model/api
to propose to these other drivers.
In my personal home systems I use it87 driver and have been
somewhat successful in switching to sysfs. A big blocking
point is there is no application to read/set/monitor the
driver, so it is basically unverified. I would hate to
put other i2c applications in the same boat.
Your thoughts?
Albert
Greg KH wrote:
> ChangeSet 1.977.29.8, 2003/04/02 11:45:21-08:00, greg@kroah.com
>
> i2c: remove proc and sysctl code from i2c-proc as it is no longer used.
>
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.66
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: Albert Cranford; +Cc: linux-kernel, sensors
On Thu, Apr 03, 2003 at 01:21:13AM -0500, Albert Cranford wrote:
> I read the thread concerning the removal of proc.c & proc.h
> but hope that this does not go to Linus until the interface
> between i2c & sensors to application is somewhat defined.
>
> At the moment we have a sysctl API used by sensors, video and
> other i2c kernel applications that is working.
The only in-kernel drivers that were using the sysctl/proc interface was
the lm75 and adm1021 drivers. The video and other i2c kernel drivers do
not use this interface at all.
Those two drivers, and the two other chip drivers that I added to the
kernel in this set of patches were converted over to the sysfs interface
(well one of the new ones were, the other one will build and run, but
doesn't export any sysfs files yet, that will change soon.)
> Our desire to switch the sensors to sysfs interface should not
> break other applications. At least until we have a model/api
> to propose to these other drivers.
Yes, any applications that used the sysctl interface to get data from
those two driver will break. However we have to switch at some point in
time, and the userspace library can't be worked on very well if the
kernel can't support it yet :)
So I'm choosing to update the kernel first, and will be working on the
library in the coming weeks. As there is no real sensors support
besides those two drivers in the main kernel, I didn't break much :)
> In my personal home systems I use it87 driver and have been
> somewhat successful in switching to sysfs. A big blocking
> point is there is no application to read/set/monitor the
> driver, so it is basically unverified.
I tested the changes I did by using echo and cat, no library or other
applications are needed just yet.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.66
@ 2005-05-19 6:23 ` Albert Cranford
0 siblings, 0 replies; 98+ messages in thread
From: Albert Cranford @ 2005-05-19 6:23 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel, sensors
Your right, nobody outside of sensors uses i2c-proc, but
why not create a new i2c-sysfs.h in drivers/i2c locally
and and adjust the couple of existing drivers.
We all know the application library is not going to have
access to include/linux/include/i2c-xxxx.h anyhow.
Later we can completely remove linux/include/linux/i2c-proc.h
which the existing application library relies upon.
ALbert
Greg KH wrote:
> On Thu, Apr 03, 2003 at 01:21:13AM -0500, Albert Cranford wrote:
>
>>I read the thread concerning the removal of proc.c & proc.h
>>but hope that this does not go to Linus until the interface
>>between i2c & sensors to application is somewhat defined.
>>
>>At the moment we have a sysctl API used by sensors, video and
>>other i2c kernel applications that is working.
>
>
> The only in-kernel drivers that were using the sysctl/proc interface was
> the lm75 and adm1021 drivers. The video and other i2c kernel drivers do
> not use this interface at all.
>
> Those two drivers, and the two other chip drivers that I added to the
> kernel in this set of patches were converted over to the sysfs interface
> (well one of the new ones were, the other one will build and run, but
> doesn't export any sysfs files yet, that will change soon.)
>
>
>>Our desire to switch the sensors to sysfs interface should not
>>break other applications. At least until we have a model/api
>>to propose to these other drivers.
>
>
> Yes, any applications that used the sysctl interface to get data from
> those two driver will break. However we have to switch at some point in
> time, and the userspace library can't be worked on very well if the
> kernel can't support it yet :)
>
> So I'm choosing to update the kernel first, and will be working on the
> library in the coming weeks. As there is no real sensors support
> besides those two drivers in the main kernel, I didn't break much :)
>
>
>>In my personal home systems I use it87 driver and have been
>>somewhat successful in switching to sysfs. A big blocking
>>point is there is no application to read/set/monitor the
>>driver, so it is basically unverified.
>
>
> I tested the changes I did by using echo and cat, no library or other
> applications are needed just yet.
>
> thanks,
>
> greg k-h
>
>
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Greg KH
(?)
(?)
@ 2005-05-19 6:23 ` Albert Cranford
-1 siblings, 0 replies; 98+ messages in thread
From: Albert Cranford @ 2005-05-19 6:23 UTC (permalink / raw)
To: lm-sensors
Linux kenel mail list removed on purpose.
Whoa! I just saw the patches submitted to linux kernel
and not to sensors list. Come on Greg this is not proper.
Whats this config item CONFIG_SENSOR ?
This is the wrong way to register sensors to sysfs.
New sensors can never be tested before included in the kernel
with this philosophy.
Whats wrong with the opposite philosophy of creating
a sysfs interface and in the sensor driver just make
the sysfs call?
Albert
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.66
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: Albert Cranford; +Cc: linux-kernel, sensors
On Thu, Apr 03, 2003 at 08:06:06AM -0500, Albert Cranford wrote:
> Your right, nobody outside of sensors uses i2c-proc, but
> why not create a new i2c-sysfs.h in drivers/i2c locally
> and and adjust the couple of existing drivers.
What would i2c-sysfs.h be needed for? All of the needed sysfs prototype
functions are already in device.h.
> We all know the application library is not going to have
> access to include/linux/include/i2c-xxxx.h anyhow.
It never did :)
> Later we can completely remove linux/include/linux/i2c-proc.h
> which the existing application library relies upon.
No userspace program should rely on kernel header files.
And I didn't take away the functionality that i2c-proc.h provided with
the list of devices supported and such. Just the unused function
prototypes that dealt with the proc and sysctl interface.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Greg KH
` (3 preceding siblings ...)
(?)
@ 2005-05-19 6:23 ` Greg KH
-1 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: lm-sensors
On Thu, Apr 03, 2003 at 08:42:50AM -0500, Albert Cranford wrote:
> Linux kenel mail list removed on purpose.
Why?
> Whoa! I just saw the patches submitted to linux kernel
> and not to sensors list. Come on Greg this is not proper.
All of these patches, with the lone exception of the renaming i2c-proc.c
to i2c-sensor.c and the removal of the unused proc functions were posted
to both the sensors and linux kernel mailing lists in the past. I and
others said that it would be good to rename the file, as it doesn't make
any sense anymore.
And I just posted a question asking if that lone function that is now in
i2c-sensors.c is even needed anymore.
Or do you mean that this series of patches specifically were not sent to
the sensors list? They were, it looks like the sensors list dropped
them for somereason. Look at the email header of the messages on lkml
for proof of that.
> Whats this config item CONFIG_SENSOR ?
It's CONFIG_I2C_SENSOR which replaces I2C_PROC. It's used to determine
if we need to build i2c-sensor.o or not.
> This is the wrong way to register sensors to sysfs.
Why? What did I do different that was wrong, or not previously posted
to this list?
> New sensors can never be tested before included in the kernel
> with this philosophy.
Yes they can, just like I tested, and others are currently testing. I
am getting patches for this conversion :)
> Whats wrong with the opposite philosophy of creating
> a sysfs interface and in the sensor driver just make
> the sysfs call?
The callbacks do not match up at all from the "old" proc file interface
with the sysfs interface. And we moved to one value per file. Both of
those changes would have been very cludgy to fit into the current api,
so they were changed. This was shown in the many patches on this list
before I sent my changes off to Linus.
I don't want to be seen as breaking things without a good reason. These
are good changes. They reduced the amount of kernel code, and have
moved the i2c chips into the sysfs heirachy, which will allow them to be
seen by userspace tools that get entire system information (people are
currently working on libsysfs to make userspace interaction with the
sysfs tree simpler, although find and cat and echo work good for me :)
thanks,
greg k-h
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.66
2005-05-19 6:23 ` Greg KH
` (2 preceding siblings ...)
(?)
@ 2005-05-19 6:23 ` Mark M. Hoffman
-1 siblings, 0 replies; 98+ messages in thread
From: Mark M. Hoffman @ 2005-05-19 6:23 UTC (permalink / raw)
To: lm-sensors
* Greg KH <greg@kroah.com> [2003-04-03 08:45:56 -0800]:
> Or do you mean that this series of patches specifically were not sent to
> the sensors list? They were, it looks like the sensors list dropped
> them for somereason. Look at the email header of the messages on lkml
> for proof of that.
I noticed that the sensors list spam marker tagged a bunch
of your (Greg's) messages... IIRC something about "numerically
obscured URL" (likely referring to the BK URLs). I don't
know what to suggest except... subscribers can't rely on that
tag alone.
Regards,
--
Mark M. Hoffman
mhoffman@lightlink.com
^ permalink raw reply [flat|nested] 98+ messages in thread
* [BK PATCH] More i2c driver changes for 2.5.69
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, sensors
Hi,
Here are some more minor i2c fixups for 2.5.69. They are basically a
bunch of fixes for the it87 driver, and a few other minor changes.
Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.5
thanks,
greg k-h
drivers/i2c/chips/it87.c | 195 +++++++++++++++++++++++------------------------
drivers/i2c/i2c-core.c | 33 ++++++-
include/linux/i2c.h | 13 +--
3 files changed, 133 insertions(+), 108 deletions(-)
-----
<warp:mercury.d2dc.net>:
o I2C: And another it87 patch
o I2C: Yet another it87 patch
o I2C: Another it87 patch
Greg Kroah-Hartman:
o i2c: register the i2c_adapter_driver so things link up properly in sysfs
o i2c: add i2c_adapter class support
Mark W. McClelland:
o I2C: add more classes
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.69
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.1, 2003/05/09 13:53:57-07:00, greg@kroah.com
[PATCH] i2c: add i2c_adapter class support
drivers/i2c/i2c-core.c | 23 ++++++++++++++++++++---
include/linux/i2c.h | 3 ++-
2 files changed, 22 insertions(+), 4 deletions(-)
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri May 9 16:48:30 2003
+++ b/drivers/i2c/i2c-core.c Fri May 9 16:48:30 2003
@@ -62,6 +62,10 @@
.remove = i2c_device_remove,
};
+static struct class i2c_adapter_class = {
+ .name = "i2c-adapter"
+};
+
/* ---------------------------------------------------
* registering functions
@@ -97,6 +101,13 @@
adap->dev.driver = &i2c_generic_driver;
device_register(&adap->dev);
+ /* Add this adapter to the i2c_adapter class */
+ memset(&adap->class_dev, 0x00, sizeof(struct class_device));
+ adap->class_dev.dev = &adap->dev;
+ adap->class_dev.class = &i2c_adapter_class;
+ strncpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
+ class_device_register(&adap->class_dev);
+
/* inform drivers of new adapters */
list_for_each(item,&drivers) {
driver = list_entry(item, struct i2c_driver, list);
@@ -150,6 +161,7 @@
}
/* clean up the sysfs representation */
+ class_device_unregister(&adap->class_dev);
device_unregister(&adap->dev);
list_del(&adap->list);
@@ -443,14 +455,19 @@
.match = i2c_device_match,
};
-
static int __init i2c_init(void)
{
- return bus_register(&i2c_bus_type);
+ int retval;
+
+ retval = bus_register(&i2c_bus_type);
+ if (retval)
+ return retval;
+ return class_register(&i2c_adapter_class);
}
static void __exit i2c_exit(void)
{
+ class_unregister(&i2c_adapter_class);
bus_unregister(&i2c_bus_type);
}
@@ -475,7 +492,7 @@
return ret;
} else {
- dev_err(&adap->dev, "I2C level transfers not supported\n");
+ DEB2(dev_dbg(&adap->dev, "I2C level transfers not supported\n"));
return -ENOSYS;
}
}
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri May 9 16:48:30 2003
+++ b/include/linux/i2c.h Fri May 9 16:48:30 2003
@@ -240,7 +240,8 @@
int timeout;
int retries;
- struct device dev; /* the adapter device */
+ struct device dev; /* the adapter device */
+ struct class_device class_dev; /* the class device */
#ifdef CONFIG_PROC_FS
/* No need to set this when you initialize the adapter */
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.69
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.6, 2003/05/09 16:12:53-07:00, greg@kroah.com
[PATCH] i2c: register the i2c_adapter_driver so things link up properly in sysfs
drivers/i2c/i2c-core.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Fri May 9 16:47:36 2003
+++ b/drivers/i2c/i2c-core.c Fri May 9 16:47:36 2003
@@ -55,8 +55,8 @@
return 0;
}
-static struct device_driver i2c_generic_driver = {
- .name = "i2c",
+static struct device_driver i2c_adapter_driver = {
+ .name = "i2c_adapter",
.bus = &i2c_bus_type,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
@@ -98,7 +98,7 @@
if (adap->dev.parent = NULL)
adap->dev.parent = &legacy_bus;
sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
- adap->dev.driver = &i2c_generic_driver;
+ adap->dev.driver = &i2c_adapter_driver;
device_register(&adap->dev);
/* Add this adapter to the i2c_adapter class */
@@ -462,12 +462,16 @@
retval = bus_register(&i2c_bus_type);
if (retval)
return retval;
+ retval = driver_register(&i2c_adapter_driver);
+ if (retval)
+ return retval;
return class_register(&i2c_adapter_class);
}
static void __exit i2c_exit(void)
{
class_unregister(&i2c_adapter_class);
+ driver_unregister(&i2c_adapter_driver);
bus_unregister(&i2c_bus_type);
}
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.69
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.4, 2003/05/09 14:54:15-07:00, warp@mercury.d2dc.net
[PATCH] I2C: Yet another it87 patch.
Ok, after writing up something in the way of a perl script to make some
sense of the data for voltages, and finding that there is no sense to
make, I took a longer look at things.
The it87 driver in 2.5.x is doing some, down right /odd/ math on the
numbers for the in_input* readings, and the 2.4.x driver is doing
something quite different.
And while it might be possible to get sane numbers out of the 2.5.x
driver, people /expect/ to get the numbers that they were getting from
2.4.x.
So this patch puts things back to the simpler calculations done by the
2.4.x lm-sensors drivers, and my script confirms that the numbers come
out right.
drivers/i2c/chips/it87.c | 84 ++++++++++++-----------------------------------
1 files changed, 23 insertions(+), 61 deletions(-)
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c Fri May 9 16:47:59 2003
+++ b/drivers/i2c/chips/it87.c Fri May 9 16:47:59 2003
@@ -99,46 +99,8 @@
#define IT87_REG_CHIPID 0x58
-static inline u8 IN_TO_REG(long val, int inNum)
-{
- /* to avoid floating point, we multiply everything by 100.
- val is guaranteed to be positive, so we can achieve the effect of
- rounding by (...*10+5)/10. Note that the *10 is hidden in the
- /250 (which should really be /2500).
- At the end, we need to /100 because we *100 everything and we need
- to /10 because of the rounding thing, so we /1000. */
- if (inNum <= 1)
- return (u8)
- SENSORS_LIMIT(((val * 210240 - 13300) / 250 + 5) / 1000,
- 0, 255);
- else if (inNum = 2)
- return (u8)
- SENSORS_LIMIT(((val * 157370 - 13300) / 250 + 5) / 1000,
- 0, 255);
- else if (inNum = 3)
- return (u8)
- SENSORS_LIMIT(((val * 101080 - 13300) / 250 + 5) / 1000,
- 0, 255);
- else
- return (u8) SENSORS_LIMIT(((val * 41714 - 13300) / 250 + 5)
- / 1000, 0, 255);
-}
-
-static inline long IN_FROM_REG(u8 val, int inNum)
-{
- /* to avoid floating point, we multiply everything by 100.
- val is guaranteed to be positive, so we can achieve the effect of
- rounding by adding 0.5. Or, to avoid fp math, we do (...*10+5)/10.
- We need to scale with *100 anyway, so no need to /100 at the end. */
- if (inNum <= 1)
- return (long) (((250000 * val + 13300) / 210240 * 10 + 5) /10);
- else if (inNum = 2)
- return (long) (((250000 * val + 13300) / 157370 * 10 + 5) /10);
- else if (inNum = 3)
- return (long) (((250000 * val + 13300) / 101080 * 10 + 5) /10);
- else
- return (long) (((250000 * val + 13300) / 41714 * 10 + 5) /10);
-}
+#define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
+#define IN_FROM_REG(val) (((val) * 16) / 10)
static inline u8 FAN_TO_REG(long rpm, int div)
{
@@ -279,7 +241,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)*10 );
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])*10 );
}
static ssize_t show_in_min(struct device *dev, char *buf, int nr)
@@ -287,7 +249,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)*10 );
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])*10 );
}
static ssize_t show_in_max(struct device *dev, char *buf, int nr)
@@ -295,7 +257,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)*10 );
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])*10 );
}
static ssize_t set_in_min(struct device *dev, const char *buf,
@@ -304,7 +266,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10)/10;
- data->in_min[nr] = IN_TO_REG(val,nr);
+ data->in_min[nr] = IN_TO_REG(val);
it87_write_value(client, IT87_REG_VIN_MIN(nr),
data->in_min[nr]);
return count;
@@ -315,7 +277,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10)/10;
- data->in_max[nr] = IN_TO_REG(val,nr);
+ data->in_max[nr] = IN_TO_REG(val);
it87_write_value(client, IT87_REG_VIN_MAX(nr),
data->in_max[nr]);
return count;
@@ -855,37 +817,37 @@
This sets fan-divs to 2, among others */
it87_write_value(client, IT87_REG_CONFIG, 0x80);
it87_write_value(client, IT87_REG_VIN_MIN(0),
- IN_TO_REG(IT87_INIT_IN_MIN_0, 0));
+ IN_TO_REG(IT87_INIT_IN_MIN_0));
it87_write_value(client, IT87_REG_VIN_MAX(0),
- IN_TO_REG(IT87_INIT_IN_MAX_0, 0));
+ IN_TO_REG(IT87_INIT_IN_MAX_0));
it87_write_value(client, IT87_REG_VIN_MIN(1),
- IN_TO_REG(IT87_INIT_IN_MIN_1, 1));
+ IN_TO_REG(IT87_INIT_IN_MIN_1));
it87_write_value(client, IT87_REG_VIN_MAX(1),
- IN_TO_REG(IT87_INIT_IN_MAX_1, 1));
+ IN_TO_REG(IT87_INIT_IN_MAX_1));
it87_write_value(client, IT87_REG_VIN_MIN(2),
- IN_TO_REG(IT87_INIT_IN_MIN_2, 2));
+ IN_TO_REG(IT87_INIT_IN_MIN_2));
it87_write_value(client, IT87_REG_VIN_MAX(2),
- IN_TO_REG(IT87_INIT_IN_MAX_2, 2));
+ IN_TO_REG(IT87_INIT_IN_MAX_2));
it87_write_value(client, IT87_REG_VIN_MIN(3),
- IN_TO_REG(IT87_INIT_IN_MIN_3, 3));
+ IN_TO_REG(IT87_INIT_IN_MIN_3));
it87_write_value(client, IT87_REG_VIN_MAX(3),
- IN_TO_REG(IT87_INIT_IN_MAX_3, 3));
+ IN_TO_REG(IT87_INIT_IN_MAX_3));
it87_write_value(client, IT87_REG_VIN_MIN(4),
- IN_TO_REG(IT87_INIT_IN_MIN_4, 4));
+ IN_TO_REG(IT87_INIT_IN_MIN_4));
it87_write_value(client, IT87_REG_VIN_MAX(4),
- IN_TO_REG(IT87_INIT_IN_MAX_4, 4));
+ IN_TO_REG(IT87_INIT_IN_MAX_4));
it87_write_value(client, IT87_REG_VIN_MIN(5),
- IN_TO_REG(IT87_INIT_IN_MIN_5, 5));
+ IN_TO_REG(IT87_INIT_IN_MIN_5));
it87_write_value(client, IT87_REG_VIN_MAX(5),
- IN_TO_REG(IT87_INIT_IN_MAX_5, 5));
+ IN_TO_REG(IT87_INIT_IN_MAX_5));
it87_write_value(client, IT87_REG_VIN_MIN(6),
- IN_TO_REG(IT87_INIT_IN_MIN_6, 6));
+ IN_TO_REG(IT87_INIT_IN_MIN_6));
it87_write_value(client, IT87_REG_VIN_MAX(6),
- IN_TO_REG(IT87_INIT_IN_MAX_6, 6));
+ IN_TO_REG(IT87_INIT_IN_MAX_6));
it87_write_value(client, IT87_REG_VIN_MIN(7),
- IN_TO_REG(IT87_INIT_IN_MIN_7, 7));
+ IN_TO_REG(IT87_INIT_IN_MIN_7));
it87_write_value(client, IT87_REG_VIN_MAX(7),
- IN_TO_REG(IT87_INIT_IN_MAX_7, 7));
+ IN_TO_REG(IT87_INIT_IN_MAX_7));
/* Note: Battery voltage does not have limit registers */
it87_write_value(client, IT87_REG_FAN_MIN(1),
FAN_TO_REG(IT87_INIT_FAN_MIN_1, 2));
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.69
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.3, 2003/05/09 14:54:04-07:00, warp@mercury.d2dc.net
[PATCH] I2C: Another it87 patch.
This is against my last.
While the old code most definitely did /something/ to the register for
setting the fan div, the 'what' is a more interesting question.
To be honest I could not figure out what it was trying to do, because
the way it was inserting values disagreed with not only the data sheet,
but how it parsed the very same register.
This corrects the issue, and allows one to properly control the divisor
on all 3 fans, including the (much more limited) 3rd fan.
drivers/i2c/chips/it87.c | 34 ++++++++++++++++++++++++++++------
1 files changed, 28 insertions(+), 6 deletions(-)
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c Fri May 9 16:48:09 2003
+++ b/drivers/i2c/chips/it87.c Fri May 9 16:48:09 2003
@@ -159,7 +159,14 @@
205-(val)*5)
#define ALARMS_FROM_REG(val) (val)
-#define DIV_TO_REG(val) ((val)=8?3:(val)=4?2:(val)=1?0:1)
+static int log2(int val)
+{
+ int answer = 0;
+ while ((val >>= 1))
+ answer++;
+ return answer;
+}
+#define DIV_TO_REG(val) log2(val)
#define DIV_FROM_REG(val) (1 << (val))
/* Initial limits. Use the config file to set better limits. */
@@ -520,10 +527,25 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
- int old = it87_read_value(client, IT87_REG_FAN_DIV);
- data->fan_div[nr] = DIV_TO_REG(val);
- old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
- it87_write_value(client, IT87_REG_FAN_DIV, old);
+ u8 old = it87_read_value(client, IT87_REG_FAN_DIV);
+
+ switch (nr) {
+ case 0:
+ case 1:
+ data->fan_div[nr] = DIV_TO_REG(val);
+ break;
+ case 2:
+ if (val < 8)
+ data->fan_div[nr] = 1;
+ else
+ data->fan_div[nr] = 3;
+ }
+ val = old & 0x100;
+ val |= (data->fan_div[0] & 0x07);
+ val |= (data->fan_div[1] & 0x07) << 3;
+ if (data->fan_div[2] = 3)
+ val |= 0x1 << 6;
+ it87_write_value(client, IT87_REG_FAN_DIV, val);
return count;
}
@@ -961,7 +983,7 @@
i = it87_read_value(client, IT87_REG_FAN_DIV);
data->fan_div[0] = i & 0x07;
data->fan_div[1] = (i >> 3) & 0x07;
- data->fan_div[2] = 1;
+ data->fan_div[2] = (i & 0x40) ? 3 : 1;
data->alarms it87_read_value(client, IT87_REG_ALARM1) |
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.69
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.2, 2003/05/09 13:58:10-07:00, mark@alpha.dyndns.org
[PATCH] I2C: add more classes
Add I2C classes for analog and digital cameras, and fix a typo.
include/linux/i2c.h | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Fri May 9 16:48:20 2003
+++ b/include/linux/i2c.h Fri May 9 16:48:20 2003
@@ -281,10 +281,12 @@
/* Must equal I2C_M_TEN below */
/* i2c adapter classes (bitmask) */
-#define I2C_ADAP_CLASS_SMBUS (1<<0) /* lm_sensors, ... */
-#define I2C_ADAP_CLASS_TV_ANALOG (1<<1) /* bttv + friends */
-#define I2C_ADAP_CLASS_TV_DIGINAL (1<<2) /* dbv cards */
-#define I2C_ADAP_CLASS_DDC (1<<3) /* i2c-matroxfb ? */
+#define I2C_ADAP_CLASS_SMBUS (1<<0) /* lm_sensors, ... */
+#define I2C_ADAP_CLASS_TV_ANALOG (1<<1) /* bttv + friends */
+#define I2C_ADAP_CLASS_TV_DIGITAL (1<<2) /* dbv cards */
+#define I2C_ADAP_CLASS_DDC (1<<3) /* i2c-matroxfb ? */
+#define I2C_ADAP_CLASS_CAM_ANALOG (1<<4) /* camera with analog CCD */
+#define I2C_ADAP_CLASS_CAM_DIGITAL (1<<5) /* most webcams */
/* i2c_client_address_data is the struct for holding default client
* addresses for a driver and for the parameters supplied on the
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.69
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1083.2.5, 2003/05/09 14:54:25-07:00, warp@mercury.d2dc.net
[PATCH] I2C: And another it87 patch.
Don't provide min/max for in8, which allowed one to scribble on
registers one should not be messing with. (My fault, oops.)
The setting of the temp high/low registers was off by one, not mine this
time. While I was at it, I reordered a few other register accesses to
be base 0 instead of base 1.
The temp interface was slightly incorrect, degrees * 100 instead of
degrees * 1000, also fixed.
And lastly, when changing the fan count divisor, fix up the min setting
to still be roughly the same. (Previously the meaning of the value in
the register changed, but not the value itself, resulting in, undesired
surprises.)
drivers/i2c/chips/it87.c | 77 ++++++++++++++++++++++++++++-------------------
1 files changed, 47 insertions(+), 30 deletions(-)
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c Fri May 9 16:47:47 2003
+++ b/drivers/i2c/chips/it87.c Fri May 9 16:47:47 2003
@@ -80,17 +80,17 @@
/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
-#define IT87_REG_FAN(nr) (0x0c + (nr))
-#define IT87_REG_FAN_MIN(nr) (0x0f + (nr))
+#define IT87_REG_FAN(nr) (0x0d + (nr))
+#define IT87_REG_FAN_MIN(nr) (0x10 + (nr))
#define IT87_REG_FAN_CTRL 0x13
#define IT87_REG_VIN(nr) (0x20 + (nr))
-#define IT87_REG_TEMP(nr) (0x28 + (nr))
+#define IT87_REG_TEMP(nr) (0x29 + (nr))
#define IT87_REG_VIN_MAX(nr) (0x30 + (nr) * 2)
#define IT87_REG_VIN_MIN(nr) (0x31 + (nr) * 2)
-#define IT87_REG_TEMP_HIGH(nr) (0x3e + (nr) * 2)
-#define IT87_REG_TEMP_LOW(nr) (0x3f + (nr) * 2)
+#define IT87_REG_TEMP_HIGH(nr) (0x40 + ((nr) * 2))
+#define IT87_REG_TEMP_LOW(nr) (0x41 + ((nr) * 2))
#define IT87_REG_I2C_ADDR 0x48
@@ -289,6 +289,9 @@
{ \
return show_in(dev, buf, 0x##offset); \
} \
+static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in##offset, NULL)
+
+#define limit_in_offset(offset) \
static ssize_t \
show_in##offset##_min (struct device *dev, char *buf) \
{ \
@@ -309,20 +312,27 @@
{ \
return set_in_max(dev, buf, count, 0x##offset); \
} \
-static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in##offset, NULL) \
static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \
show_in##offset##_min, set_in##offset##_min) \
static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \
show_in##offset##_max, set_in##offset##_max)
show_in_offset(0);
+limit_in_offset(0);
show_in_offset(1);
+limit_in_offset(1);
show_in_offset(2);
+limit_in_offset(2);
show_in_offset(3);
+limit_in_offset(3);
show_in_offset(4);
+limit_in_offset(4);
show_in_offset(5);
+limit_in_offset(5);
show_in_offset(6);
+limit_in_offset(6);
show_in_offset(7);
+limit_in_offset(7);
show_in_offset(8);
/* 3 temperatures */
@@ -331,7 +341,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*10 );
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*100 );
}
/* more like overshoot temperature */
static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
@@ -339,7 +349,7 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*10);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*100);
}
/* more like hysteresis temperature */
static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
@@ -347,14 +357,14 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])*10);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])*100);
}
static ssize_t set_temp_max(struct device *dev, const char *buf,
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)/10;
+ int val = simple_strtol(buf, NULL, 10)/100;
data->temp_high[nr] = TEMP_TO_REG(val);
it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]);
return count;
@@ -364,7 +374,7 @@
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
- int val = simple_strtol(buf, NULL, 10)/10;
+ int val = simple_strtol(buf, NULL, 10)/100;
data->temp_low[nr] = TEMP_TO_REG(val);
it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]);
return count;
@@ -480,7 +490,7 @@
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
- it87_write_value(client, IT87_REG_FAN_MIN(nr+1), data->fan_min[nr]);
+ it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
return count;
}
static ssize_t set_fan_div(struct device *dev, const char *buf,
@@ -489,8 +499,12 @@
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
+ int i, min[3];
u8 old = it87_read_value(client, IT87_REG_FAN_DIV);
+ for (i = 0; i < 3; i++)
+ min[i] = FAN_FROM_REG(data->fan_min[i], DIV_FROM_REG(data->fan_div[i]));
+
switch (nr) {
case 0:
case 1:
@@ -508,6 +522,11 @@
if (data->fan_div[2] = 3)
val |= 0x1 << 6;
it87_write_value(client, IT87_REG_FAN_DIV, val);
+
+ for (i = 0; i < 3; i++) {
+ data->fan_min[i]úN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i]));
+ it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]);
+ }
return count;
}
@@ -704,7 +723,6 @@
device_create_file(&new_client->dev, &dev_attr_in_min5);
device_create_file(&new_client->dev, &dev_attr_in_min6);
device_create_file(&new_client->dev, &dev_attr_in_min7);
- device_create_file(&new_client->dev, &dev_attr_in_min8);
device_create_file(&new_client->dev, &dev_attr_in_max0);
device_create_file(&new_client->dev, &dev_attr_in_max1);
device_create_file(&new_client->dev, &dev_attr_in_max2);
@@ -713,7 +731,6 @@
device_create_file(&new_client->dev, &dev_attr_in_max5);
device_create_file(&new_client->dev, &dev_attr_in_max6);
device_create_file(&new_client->dev, &dev_attr_in_max7);
- device_create_file(&new_client->dev, &dev_attr_in_max8);
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_input2);
device_create_file(&new_client->dev, &dev_attr_temp_input3);
@@ -849,23 +866,23 @@
it87_write_value(client, IT87_REG_VIN_MAX(7),
IN_TO_REG(IT87_INIT_IN_MAX_7));
/* Note: Battery voltage does not have limit registers */
- it87_write_value(client, IT87_REG_FAN_MIN(1),
+ it87_write_value(client, IT87_REG_FAN_MIN(0),
FAN_TO_REG(IT87_INIT_FAN_MIN_1, 2));
- it87_write_value(client, IT87_REG_FAN_MIN(2),
+ it87_write_value(client, IT87_REG_FAN_MIN(1),
FAN_TO_REG(IT87_INIT_FAN_MIN_2, 2));
- it87_write_value(client, IT87_REG_FAN_MIN(3),
+ it87_write_value(client, IT87_REG_FAN_MIN(2),
FAN_TO_REG(IT87_INIT_FAN_MIN_3, 2));
- it87_write_value(client, IT87_REG_TEMP_HIGH(1),
+ it87_write_value(client, IT87_REG_TEMP_HIGH(0),
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_1));
- it87_write_value(client, IT87_REG_TEMP_LOW(1),
+ it87_write_value(client, IT87_REG_TEMP_LOW(0),
TEMP_TO_REG(IT87_INIT_TEMP_LOW_1));
- it87_write_value(client, IT87_REG_TEMP_HIGH(2),
+ it87_write_value(client, IT87_REG_TEMP_HIGH(1),
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_2));
- it87_write_value(client, IT87_REG_TEMP_LOW(2),
+ it87_write_value(client, IT87_REG_TEMP_LOW(1),
TEMP_TO_REG(IT87_INIT_TEMP_LOW_2));
- it87_write_value(client, IT87_REG_TEMP_HIGH(3),
+ it87_write_value(client, IT87_REG_TEMP_HIGH(2),
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_3));
- it87_write_value(client, IT87_REG_TEMP_LOW(3),
+ it87_write_value(client, IT87_REG_TEMP_LOW(2),
TEMP_TO_REG(IT87_INIT_TEMP_LOW_3));
/* Enable voltage monitors */
@@ -918,18 +935,18 @@
data->in_min[8] = 0;
data->in_max[8] = 255;
- for (i = 1; i <= 3; i++) {
- data->fan[i - 1] + for (i = 0; i < 3; i++) {
+ data->fan[i] it87_read_value(client, IT87_REG_FAN(i));
- data->fan_min[i - 1] + data->fan_min[i] it87_read_value(client, IT87_REG_FAN_MIN(i));
}
- for (i = 1; i <= 3; i++) {
- data->temp[i - 1] + for (i = 0; i < 3; i++) {
+ data->temp[i] it87_read_value(client, IT87_REG_TEMP(i));
- data->temp_high[i - 1] + data->temp_high[i] it87_read_value(client, IT87_REG_TEMP_HIGH(i));
- data->temp_low[i - 1] + data->temp_low[i] it87_read_value(client, IT87_REG_TEMP_LOW(i));
}
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.69
2005-05-19 6:23 ` Greg KH
` (4 preceding siblings ...)
(?)
@ 2005-05-19 6:23 ` Philip Pokorny
-1 siblings, 0 replies; 98+ messages in thread
From: Philip Pokorny @ 2005-05-19 6:23 UTC (permalink / raw)
To: lm-sensors
Greg KH wrote:
> ChangeSet 1.1083.2.5, 2003/05/09 14:54:25-07:00, warp@mercury.d2dc.net
>
> [PATCH] I2C: And another it87 patch.
> And lastly, when changing the fan count divisor, fix up the min setting
> to still be roughly the same. (Previously the meaning of the value in
> the register changed, but not the value itself, resulting in, undesired
> surprises.)
Hmmm... I don't think any of the other drives make this adjustment.
I think the expectation would be that fan divisors and minimums would be set
using 'sensors -s' but I could see that this could create an order dependancy.
If the minmum was set before the divisor, and the divisor was changing, then
you'd get the wrong result.
So this is probably a good idea, but we'll need to watch for this in the other
drivers either for 2.7.1 or as they are converted to the new CVS...
:v)
^ permalink raw reply [flat|nested] 98+ messages in thread
* [BK PATCH] More i2c driver changes for 2.5.70
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: torvalds; +Cc: linux-kernel, sensors
Hi,
Here are some more i2c driver changes for 2.5.70. These consist of a new i2c
client driver, a new i2c bus driver, some coding style fixes for the new bus
driver, and a bunch of sparse warning removels.
Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.5
thanks,
greg k-h
-----
drivers/i2c/Kconfig | 4
drivers/i2c/Makefile | 1
drivers/i2c/chips/Kconfig | 19
drivers/i2c/chips/Makefile | 1
drivers/i2c/chips/lm85.c | 1223 +++++++++++++++++++++++++++++++++++++++++++++
drivers/i2c/i2c-core.c | 36 -
drivers/i2c/i2c-dev.c | 10
drivers/i2c/i2c-iop3xx.c | 868 +++++++++++++++++++++++++------
drivers/i2c/i2c-iop3xx.h | 238 ++++++--
include/linux/i2c-dev.h | 6
include/linux/i2c.h | 4
11 files changed, 2150 insertions(+), 260 deletions(-)
-----
<margitsw:t-online.de>:
o I2C: add LM85 driver
<peterm:remware.demon.co.uk>:
o I2C: add New bus driver: XSCALE iop3xx
Greg Kroah-Hartman:
o I2C: fix up sparse warnings in the i2c-dev driver
o I2C: fix up sparse warnings in drivers/i2c/i2c-core.c
o I2C: fix some errors found by sparse in include/linux/i2c.h
o I2C: coding style updates for i2c-iop3xx driver
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.70
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.5, 2003/06/11 12:07:27-07:00, greg@kroah.com
[PATCH] I2C: coding style updates for i2c-iop3xx driver
drivers/i2c/i2c-iop3xx.c | 303 +++++++++++++++++++++--------------------------
drivers/i2c/i2c-iop3xx.h | 118 ++++++++----------
2 files changed, 195 insertions(+), 226 deletions(-)
diff -Nru a/drivers/i2c/i2c-iop3xx.c b/drivers/i2c/i2c-iop3xx.c
--- a/drivers/i2c/i2c-iop3xx.c Wed Jun 11 13:25:13 2003
+++ b/drivers/i2c/i2c-iop3xx.c Wed Jun 11 13:25:13 2003
@@ -50,8 +50,8 @@
/* ----- global defines ----------------------------------------------- */
#define PASSERT(x) do { if (!(x) ) \
- printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\
- } while (0)
+ printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\
+ } while (0)
/* ----- global variables --------------------------------------------- */
@@ -61,13 +61,13 @@
{
unsigned char addr;
- addr = ( msg->addr << 1 );
+ addr = (msg->addr << 1);
- if (msg->flags & I2C_M_RD )
+ if (msg->flags & I2C_M_RD)
addr |= 1;
-/* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
- if (msg->flags & I2C_M_REV_DIR_ADDR )
+ /* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
+ if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
return addr;
@@ -76,100 +76,93 @@
static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
- // Follows devman 9.3
+ /* Follows devman 9.3 */
*iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET;
*iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS;
*iop3xx_adap->biu->CR = 0;
}
-static inline void iop3xx_adap_set_slave_addr(
- struct i2c_algo_iop3xx_data *iop3xx_adap )
+static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
*iop3xx_adap->biu->SAR = MYSAR;
}
-static inline void iop3xx_adap_enable(
- struct i2c_algo_iop3xx_data *iop3xx_adap )
+static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE;
-/* NB SR bits not same position as CR IE bits :-( */
+ /* 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;
+ IOP321_ISR_ALD | IOP321_ISR_BERRD |
+ IOP321_ISR_RXFULL | IOP321_ISR_TXEMPTY;
- cr |= IOP321_ICR_ALDIE|IOP321_ICR_BERRIE|
- IOP321_ICR_RXFULLIE|IOP321_ICR_TXEMPTYIE;
+ cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
+ IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE;
*iop3xx_adap->biu->CR = cr;
}
-static void iop3xx_adap_transaction_cleanup(
- struct i2c_algo_iop3xx_data *iop3xx_adap )
+static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
unsigned cr = *iop3xx_adap->biu->CR;
cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE |
- IOP321_ICR_MSTOP | IOP321_ICR_SCLEN );
+ IOP321_ICR_MSTOP | IOP321_ICR_SCLEN);
*iop3xx_adap->biu->CR = cr;
}
-static void iop3xx_adap_final_cleanup(
- struct i2c_algo_iop3xx_data *iop3xx_adap )
+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);
+ cr &= ~(IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
+ IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE);
iop3xx_adap->biu->SR_enabled = 0;
*iop3xx_adap->biu->CR = cr;
}
-
-
-static void iop3xx_i2c_handler( int this_irq,
- void *dev_id,
- struct pt_regs *regs)
/*
* NB: the handler has to clear the source of the interrupt!
* Then it passes the SR flags of interest to BH via adap data
*/
+static void iop3xx_i2c_handler(int this_irq,
+ void *dev_id,
+ struct pt_regs *regs)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
u32 sr = *iop3xx_adap->biu->SR;
- if ( (sr &= iop3xx_adap->biu->SR_enabled) ){
+ if ((sr &= iop3xx_adap->biu->SR_enabled)) {
*iop3xx_adap->biu->SR = sr;
iop3xx_adap->biu->SR_received |= sr;
wake_up_interruptible(&iop3xx_adap->waitq);
}
}
-
-static int iop3xx_adap_error( u32 sr )
-// check all error conditions, clear them , report most important
+/* check all error conditions, clear them , report most important */
+static int iop3xx_adap_error(u32 sr)
{
int rc = 0;
- if ( (sr&IOP321_ISR_BERRD) ) {
+ if ((sr&IOP321_ISR_BERRD)) {
if ( !rc ) rc = -I2C_ERR_BERR;
}
- if ( (sr&IOP321_ISR_ALD) ){
+ if ((sr&IOP321_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 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
unsigned long flags;
u32 sr;
- spin_lock_irqsave( &iop3xx_adap->lock, flags );
+ spin_lock_irqsave(&iop3xx_adap->lock, flags);
sr = iop3xx_adap->biu->SR_received;
iop3xx_adap->biu->SR_received = 0;
- spin_unlock_irqrestore( &iop3xx_adap->lock, flags );
+ spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
return sr;
}
@@ -178,12 +171,12 @@
* sleep until interrupted, then recover and analyse the SR
* saved by handler
*/
-typedef int (* CompareFunc)( unsigned test, unsigned mask );
+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,
- CompareFunc compare )
+static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ unsigned flags, unsigned* status,
+ compare_func compare)
{
unsigned sr = 0;
int interrupted;
@@ -196,100 +189,94 @@
(done = compare( sr = get_srstat(iop3xx_adap),flags )),
iop3xx_adap->timeout
);
- if ( (rc = iop3xx_adap_error( sr )) < 0 ){
+ if ((rc = iop3xx_adap_error(sr)) < 0) {
*status = sr;
return rc;
- }else if ( !interrupted ){
+ }else if (!interrupted) {
*status = sr;
return rc = -ETIMEDOUT;
}
- } while( !done );
+ } while(!done);
*status = sr;
return rc = 0;
}
-
-
-
/*
- * Concrete CompareFuncs
+ * Concrete compare_funcs
*/
-static int all_bits_clear( unsigned test, unsigned mask ) {
- return (test&mask) = 0;
+static int all_bits_clear(unsigned test, unsigned mask)
+{
+ return (test & mask) = 0;
}
-static int any_bits_set( unsigned test, unsigned mask ) {
- return (test&mask) != 0;
+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_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
return iop3xx_adap_wait_event(
iop3xx_adap,
IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD,
- status, any_bits_set );
+ status, any_bits_set);
}
-static int iop3xx_adap_wait_rx_done(
- struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
return iop3xx_adap_wait_event(
iop3xx_adap,
IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD,
- status, any_bits_set );
+ status, any_bits_set);
}
-static int iop3xx_adap_wait_idle(
- struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+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 );
+ iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear);
}
-//
-// Description: This performs the IOP3xx initialization sequence
-// Valid for IOP321. Maybe valid for IOP310?.
-//
+/*
+ * 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)
{
- *IOP321_GPOD &= ~(iop3xx_adap->channel=0?
+ *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 );
+ iop3xx_adap_reset(iop3xx_adap);
+ iop3xx_adap_set_slave_addr(iop3xx_adap);
+ iop3xx_adap_enable(iop3xx_adap);
return 0;
}
-static int iop3xx_adap_send_target_slave_addr(
- struct i2c_algo_iop3xx_data *iop3xx_adap, struct i2c_msg* msg )
+static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ struct i2c_msg* msg)
{
unsigned cr = *iop3xx_adap->biu->CR;
int status;
int rc;
- *iop3xx_adap->biu->DBR = iic_cook_addr( msg );
+ *iop3xx_adap->biu->DBR = iic_cook_addr(msg);
- cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
+ cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK);
cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE;
*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 );
+ 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_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop)
{
unsigned cr = *iop3xx_adap->biu->CR;
int status;
@@ -297,19 +284,19 @@
*iop3xx_adap->biu->DBR = byte;
cr &= ~IOP321_ICR_MSTART;
- if ( stop ){
+ if (stop) {
cr |= IOP321_ICR_MSTOP;
- }else{
+ } else {
cr &= ~IOP321_ICR_MSTOP;
}
*iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
- rc = iop3xx_adap_wait_tx_done( iop3xx_adap, &status );
+ rc = iop3xx_adap_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_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ char* byte, int stop)
{
unsigned cr = *iop3xx_adap->biu->CR;
int status;
@@ -317,49 +304,46 @@
cr &= ~IOP321_ICR_MSTART;
- if ( stop ){
+ if (stop) {
cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;
- }else{
+ } else {
cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
}
*iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
- rc = iop3xx_adap_wait_rx_done( iop3xx_adap, &status );
+ rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status);
*byte = *iop3xx_adap->biu->DBR;
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 ){
+ for (ii = 0; rc = 0 && ii != count; ++ii) {
rc = iop3xx_adap_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 ){
+ for (ii = 0; rc = 0 && ii != count; ++ii) {
rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii=count-1);
}
return rc;
}
-
/*
* Description: This function implements combined transactions. Combined
* transactions consist of combinations of reading and writing blocks of data.
@@ -367,63 +351,55 @@
* 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_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 );
- if ( rc < 0 ){
+ rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg);
+ if (rc < 0) {
return rc;
}
- if ( (pmsg->flags&I2C_M_RD) ){
- return iop3xx_i2c_readbytes( i2c_adap, pmsg->buf, pmsg->len );
- }else{
- return iop3xx_i2c_writebytes( i2c_adap, pmsg->buf, pmsg->len );
+ if ((pmsg->flags&I2C_M_RD)) {
+ return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len);
+ } else {
+ return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len);
}
}
-
-
/*
* 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_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_adap_wait_idle(iop3xx_adap, &status);
+ iop3xx_adap_reset(iop3xx_adap);
+ iop3xx_adap_enable(iop3xx_adap);
- for ( im = 0; ret = 0 && im != num; ++im ){
- ret = iop3xx_handle_msg( i2c_adap, &msgs[im] );
+ for (im = 0; ret = 0 && im != num; ++im) {
+ ret = iop3xx_handle_msg(i2c_adap, &msgs[im]);
}
- iop3xx_adap_transaction_cleanup( iop3xx_adap );
+ iop3xx_adap_transaction_cleanup(iop3xx_adap);
return ret;
}
-
-
-static int algo_control(struct i2c_adapter *adapter,
- unsigned int cmd, unsigned long arg)
+static int algo_control(struct i2c_adapter *adapter, unsigned int cmd,
+ unsigned long arg)
{
return 0;
}
-
static u32 iic_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C|I2C_FUNC_SMBUS_EMUL;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
@@ -440,74 +416,70 @@
/*
* registering functions to load algorithms at runtime
*/
-
-
static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
- if ( !request_region( REGION_START(iop3xx_adap),
+ if (!request_region( REGION_START(iop3xx_adap),
REGION_LENGTH(iop3xx_adap),
- iic_adap->name ) ){
+ iic_adap->name)) {
return -ENODEV;
}
-
- init_waitqueue_head( &iop3xx_adap->waitq );
- spin_lock_init( &iop3xx_adap->lock );
- if ( request_irq(
+ init_waitqueue_head(&iop3xx_adap->waitq);
+ spin_lock_init(&iop3xx_adap->lock);
+
+ if (request_irq(
iop3xx_adap->biu->irq,
iop3xx_i2c_handler,
/* SA_SAMPLE_RANDOM */ 0,
iic_adap->name,
- iop3xx_adap ) ){
+ iop3xx_adap)) {
return -ENODEV;
}
-/* register new iic_adapter to i2c module... */
-
+ /* register new iic_adapter to i2c module... */
iic_adap->id |= iic_algo.id;
iic_adap->algo = &iic_algo;
- iic_adap->timeout = 100; /* default values, should */
- iic_adap->retries = 3; /* be replaced by defines */
+ iic_adap->timeout = 100; /* default values, should */
+ iic_adap->retries = 3; /* be replaced by defines */
- iop3xx_adap_init( iic_adap->algo_data );
+ iop3xx_adap_init(iic_adap->algo_data);
i2c_add_adapter(iic_adap);
return 0;
}
-
static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
- iop3xx_adap_final_cleanup( iop3xx_adap );
- free_irq( iop3xx_adap->biu->irq, iop3xx_adap );
+ iop3xx_adap_final_cleanup(iop3xx_adap);
+ free_irq(iop3xx_adap->biu->irq, iop3xx_adap);
- release_region( REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
+ release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
- return i2c_del_adapter( iic_adap );
+ return i2c_del_adapter(iic_adap);
}
#ifdef CONFIG_ARCH_IOP321
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
+ .CR = IOP321_ICR0,
+ .SR = IOP321_ISR0,
+ .SAR = IOP321_ISAR0,
+ .DBR = IOP321_IDBR0,
+ .BMR = IOP321_IBMR0,
+ .irq = IRQ_IOP321_I2C_0,
};
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
+ .CR = IOP321_ICR1,
+ .SR = IOP321_ISR1,
+ .SAR = IOP321_ISAR1,
+ .DBR = IOP321_IDBR1,
+ .BMR = IOP321_IBMR1,
+ .irq = IRQ_IOP321_I2C_1,
};
#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "
@@ -515,28 +487,28 @@
#error Please define the BIU struct iop3xx_biu for your processor arch
#endif
-static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = {
- .channel = 0,
- .biu = &biu0,
- .timeout = 1*HZ
+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
+static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = {
+ .channel = 1,
+ .biu = &biu1,
+ .timeout = 1*HZ,
};
static struct i2c_adapter iop3xx_ops0 = {
.owner = THIS_MODULE,
.name = ADAPTER_NAME_ROOT "0",
.id = I2C_HW_IOP321,
- .algo_data = &algo_iop3xx_data0
+ .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
+ .algo_data = &algo_iop3xx_data1,
};
static int __init i2c_iop3xx_init (void)
@@ -560,6 +532,5 @@
MODULE_PARM(i2c_debug,"i");
-MODULE_PARM_DESC(i2c_debug,
- "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
+MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
diff -Nru a/drivers/i2c/i2c-iop3xx.h b/drivers/i2c/i2c-iop3xx.h
--- a/drivers/i2c/i2c-iop3xx.h Wed Jun 11 13:25:13 2003
+++ b/drivers/i2c/i2c-iop3xx.h Wed Jun 11 13:25:13 2003
@@ -25,20 +25,20 @@
/*
* iop321 hardware bit definitions
*/
-#define IOP321_ICR_FAST_MODE 0x8000 /* 1@0kBps, 0\x100kBps */
-#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 IOP321_ICR_FAST_MODE 0x8000 /* 1@0kBps, 0\x100kBps */
+#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 */
/*
* IOP321_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 IOP321_ICR_UE 0x0040 /* 1=Unit Enable */
/*
* "NOTE: To avoid I2C bus integrity problems,
* the user needs to ensure that the GPIO Output Data Register -
@@ -46,56 +46,54 @@
* the enable bit for that I2C serial port.
* 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
- * 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 IOP321_IDBR_MASK 0x00ff
-
-#define IOP321_IBMR_SCL 0x0002
-#define IOP321_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 MYSAR 0x02 /* SWAG a suitable slave address */
-
-#define I2C_ERR 321
-#define I2C_ERR_BERR (I2C_ERR+0)
-#define I2C_ERR_ALD (I2C_ERR+1)
-
+ */
+#define IOP321_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */
+#define IOP321_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 IOP321_IDBR_MASK 0x00ff
+
+#define IOP321_IBMR_SCL 0x0002
+#define IOP321_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 MYSAR 0x02 /* SWAG a suitable slave address */
+
+#define I2C_ERR 321
+#define I2C_ERR_BERR (I2C_ERR+0)
+#define I2C_ERR_ALD (I2C_ERR+1)
-typedef volatile u32* r32;
struct iop3xx_biu { /* Bus Interface Unit - the hardware */
/* physical hardware defs - regs*/
- r32 CR;
- r32 SR;
- r32 SAR;
- r32 DBR;
- r32 BMR;
+ u32 *CR;
+ u32 *SR;
+ u32 *SAR;
+ u32 *DBR;
+ u32 *BMR;
/* irq bit vector */
u32 irq;
/* stored flags */
@@ -111,10 +109,10 @@
struct iop3xx_biu* biu;
};
-#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 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)
+#define IRQ_STATUS_MASK(adap) (1<<adap->biu->irq)
#endif /* I2C_IOP3XX_H */
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.70
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.4, 2003/06/11 11:43:02-07:00, peterm@remware.demon.co.uk
[PATCH] I2C: add New bus driver: XSCALE iop3xx
drivers/i2c/Kconfig | 4
drivers/i2c/Makefile | 1
drivers/i2c/i2c-iop3xx.c | 565 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/i2c/i2c-iop3xx.h | 120 +++++++++
4 files changed, 690 insertions(+)
diff -Nru a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
--- a/drivers/i2c/Kconfig Wed Jun 11 13:25:23 2003
+++ b/drivers/i2c/Kconfig Wed Jun 11 13:25:23 2003
@@ -193,6 +193,10 @@
tristate "IBM on-chip I2C Adapter"
depends on I2C_IBM_OCP_ALGO
+config I2C_IOP3XX
+ tristate "Intel XScale IOP3xx on-chip I2C interface"
+ depends on ARCH_IOP3XX && I2C
+
config I2C_CHARDEV
tristate "I2C device interface"
depends on I2C
diff -Nru a/drivers/i2c/Makefile b/drivers/i2c/Makefile
--- a/drivers/i2c/Makefile Wed Jun 11 13:25:23 2003
+++ b/drivers/i2c/Makefile Wed Jun 11 13:25:23 2003
@@ -16,4 +16,5 @@
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o
+obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-y += busses/ chips/
diff -Nru a/drivers/i2c/i2c-iop3xx.c b/drivers/i2c/i2c-iop3xx.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/i2c-iop3xx.c Wed Jun 11 13:25:23 2003
@@ -0,0 +1,565 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx */
+/* ------------------------------------------------------------------------- */
+/* 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. idasilva@mvista.com
+
+ 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 <kmalkki@cc.hut.fi>,
+ Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
+
+ ---------------------------------------------------------------------------*/
+
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+
+
+#include <asm/arch-iop3xx/iop321.h>
+#include <asm/arch-iop3xx/iop321-irqs.h>
+#include "i2c-iop3xx.h"
+
+
+/* ----- 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)
+{
+ unsigned char addr;
+
+ addr = ( msg->addr << 1 );
+
+ if (msg->flags & I2C_M_RD )
+ addr |= 1;
+
+/* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
+ 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)
+{
+ // Follows devman 9.3
+ *iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET;
+ *iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS;
+ *iop3xx_adap->biu->CR = 0;
+}
+
+static inline void iop3xx_adap_set_slave_addr(
+ struct i2c_algo_iop3xx_data *iop3xx_adap )
+{
+ *iop3xx_adap->biu->SAR = MYSAR;
+}
+
+static inline void iop3xx_adap_enable(
+ struct i2c_algo_iop3xx_data *iop3xx_adap )
+{
+ u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE;
+
+/* 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;
+
+ cr |= IOP321_ICR_ALDIE|IOP321_ICR_BERRIE|
+ IOP321_ICR_RXFULLIE|IOP321_ICR_TXEMPTYIE;
+
+ *iop3xx_adap->biu->CR = cr;
+}
+
+static void iop3xx_adap_transaction_cleanup(
+ struct i2c_algo_iop3xx_data *iop3xx_adap )
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+
+ cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE |
+ IOP321_ICR_MSTOP | IOP321_ICR_SCLEN );
+ *iop3xx_adap->biu->CR = cr;
+}
+
+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;
+}
+
+
+
+static void iop3xx_i2c_handler( int this_irq,
+ void *dev_id,
+ struct pt_regs *regs)
+/*
+ * NB: the handler has to clear the source of the interrupt!
+ * Then it passes the SR flags of interest to BH via adap data
+ */
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
+
+ u32 sr = *iop3xx_adap->biu->SR;
+
+ if ( (sr &= iop3xx_adap->biu->SR_enabled) ){
+ *iop3xx_adap->biu->SR = sr;
+ iop3xx_adap->biu->SR_received |= sr;
+ wake_up_interruptible(&iop3xx_adap->waitq);
+ }
+}
+
+
+static int iop3xx_adap_error( u32 sr )
+// check all error conditions, clear them , report most important
+{
+ int rc = 0;
+
+ if ( (sr&IOP321_ISR_BERRD) ) {
+ if ( !rc ) rc = -I2C_ERR_BERR;
+ }
+ if ( (sr&IOP321_ISR_ALD) ){
+ if ( !rc ) rc = -I2C_ERR_ALD;
+ }
+ return rc;
+}
+
+static inline u32 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;
+ spin_unlock_irqrestore( &iop3xx_adap->lock, flags );
+
+ return sr;
+}
+
+/*
+ * sleep until interrupted, then recover and analyse the SR
+ * saved by handler
+ */
+typedef int (* CompareFunc)( 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,
+ CompareFunc compare )
+{
+ unsigned sr = 0;
+ int interrupted;
+ int done;
+ int rc;
+
+ do {
+ interrupted = wait_event_interruptible_timeout (
+ iop3xx_adap->waitq,
+ (done = compare( sr = get_srstat(iop3xx_adap),flags )),
+ iop3xx_adap->timeout
+ );
+ if ( (rc = iop3xx_adap_error( sr )) < 0 ){
+ *status = sr;
+ return rc;
+ }else if ( !interrupted ){
+ *status = sr;
+ return rc = -ETIMEDOUT;
+ }
+ } while( !done );
+
+ *status = sr;
+
+ return rc = 0;
+}
+
+
+
+
+/*
+ * Concrete CompareFuncs
+ */
+static int all_bits_clear( unsigned test, unsigned mask ) {
+ return (test&mask) = 0;
+}
+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)
+{
+ return iop3xx_adap_wait_event(
+ iop3xx_adap,
+ IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD,
+ status, any_bits_set );
+}
+
+static int iop3xx_adap_wait_rx_done(
+ struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+{
+ return iop3xx_adap_wait_event(
+ iop3xx_adap,
+ IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_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)
+{
+ *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;
+}
+
+static int iop3xx_adap_send_target_slave_addr(
+ struct i2c_algo_iop3xx_data *iop3xx_adap, struct i2c_msg* msg )
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+ int status;
+ int rc;
+
+ *iop3xx_adap->biu->DBR = iic_cook_addr( msg );
+
+ cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
+ cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE;
+
+ *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 )
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+ int status;
+ int rc;
+
+ *iop3xx_adap->biu->DBR = byte;
+ cr &= ~IOP321_ICR_MSTART;
+ if ( stop ){
+ cr |= IOP321_ICR_MSTOP;
+ }else{
+ cr &= ~IOP321_ICR_MSTOP;
+ }
+ *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
+ rc = iop3xx_adap_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 )
+{
+ unsigned cr = *iop3xx_adap->biu->CR;
+ int status;
+ int rc;
+
+ cr &= ~IOP321_ICR_MSTART;
+
+ if ( stop ){
+ cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;
+ }else{
+ cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
+ }
+ *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
+
+ rc = iop3xx_adap_wait_rx_done( iop3xx_adap, &status );
+
+ *byte = *iop3xx_adap->biu->DBR;
+
+ return rc;
+}
+
+
+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);
+ }
+ return rc;
+}
+
+
+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);
+ }
+ return rc;
+}
+
+
+/*
+ * Description: This function implements combined transactions. Combined
+ * transactions consist of combinations of reading and writing blocks of data.
+ * FROM THE SAME ADDRESS
+ * 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 )
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
+ int rc;
+
+ rc = iop3xx_adap_send_target_slave_addr( iop3xx_adap, pmsg );
+ if ( rc < 0 ){
+ return rc;
+ }
+
+ if ( (pmsg->flags&I2C_M_RD) ){
+ return iop3xx_i2c_readbytes( i2c_adap, pmsg->buf, pmsg->len );
+ }else{
+ return iop3xx_i2c_writebytes( i2c_adap, pmsg->buf, pmsg->len );
+ }
+}
+
+
+
+/*
+ * master_xfer() - main read/write entry
+ */
+static int iop3xx_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 );
+
+ for ( im = 0; ret = 0 && im != num; ++im ){
+ ret = iop3xx_handle_msg( i2c_adap, &msgs[im] );
+ }
+
+ iop3xx_adap_transaction_cleanup( iop3xx_adap );
+
+ return ret;
+}
+
+
+
+static int algo_control(struct i2c_adapter *adapter,
+ unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+
+static u32 iic_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C|I2C_FUNC_SMBUS_EMUL;
+}
+
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static struct i2c_algorithm iic_algo = {
+ .name = "IOP3xx I2C algorithm",
+ .id = I2C_ALGO_OCP_IOP3XX,
+ .master_xfer = iop3xx_master_xfer,
+ .algo_control = algo_control,
+ .functionality = iic_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+
+
+static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+
+ if ( !request_region( REGION_START(iop3xx_adap),
+ REGION_LENGTH(iop3xx_adap),
+ iic_adap->name ) ){
+ return -ENODEV;
+ }
+
+ init_waitqueue_head( &iop3xx_adap->waitq );
+ spin_lock_init( &iop3xx_adap->lock );
+
+ if ( request_irq(
+ iop3xx_adap->biu->irq,
+ iop3xx_i2c_handler,
+ /* SA_SAMPLE_RANDOM */ 0,
+ iic_adap->name,
+ iop3xx_adap ) ){
+ return -ENODEV;
+ }
+
+/* register new iic_adapter to i2c module... */
+
+ iic_adap->id |= iic_algo.id;
+ iic_adap->algo = &iic_algo;
+
+ iic_adap->timeout = 100; /* default values, should */
+ iic_adap->retries = 3; /* be replaced by defines */
+
+ iop3xx_adap_init( iic_adap->algo_data );
+ i2c_add_adapter(iic_adap);
+ return 0;
+}
+
+
+static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap)
+{
+ struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+
+ iop3xx_adap_final_cleanup( iop3xx_adap );
+ free_irq( iop3xx_adap->biu->irq, iop3xx_adap );
+
+ release_region( REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
+
+ return i2c_del_adapter( iic_adap );
+}
+
+#ifdef CONFIG_ARCH_IOP321
+
+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
+};
+
+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
+};
+
+#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "
+#else
+#error Please define the BIU struct iop3xx_biu for your processor arch
+#endif
+
+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
+};
+
+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
+};
+
+static int __init i2c_iop3xx_init (void)
+{
+ return i2c_iop3xx_add_bus(&iop3xx_ops0) ||
+ i2c_iop3xx_add_bus(&iop3xx_ops1);
+}
+
+static void __exit i2c_iop3xx_exit (void)
+{
+ i2c_iop3xx_del_bus(&iop3xx_ops0);
+ i2c_iop3xx_del_bus(&iop3xx_ops1);
+}
+
+module_init (i2c_iop3xx_init);
+module_exit (i2c_iop3xx_exit);
+
+MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
+MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(i2c_debug,"i");
+
+MODULE_PARM_DESC(i2c_debug,
+ "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
+
diff -Nru a/drivers/i2c/i2c-iop3xx.h b/drivers/i2c/i2c-iop3xx.h
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/i2c-iop3xx.h Wed Jun 11 13:25:23 2003
@@ -0,0 +1,120 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-iop3xx.h algorithm driver definitions private to i2c-iop3xx.c */
+/* ------------------------------------------------------------------------- */
+/* 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. */
+/* ------------------------------------------------------------------------- */
+
+
+#ifndef I2C_IOP3XX_H
+#define I2C_IOP3XX_H 1
+
+/*
+ * iop321 hardware bit definitions
+ */
+#define IOP321_ICR_FAST_MODE 0x8000 /* 1@0kBps, 0\x100kBps */
+#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 */
+/*
+ * IOP321_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 */
+/*
+ * "NOTE: To avoid I2C bus integrity problems,
+ * the user needs to ensure that the GPIO Output Data Register -
+ * GPOD bits associated with an I2C port are cleared prior to setting
+ * the enable bit for that I2C serial port.
+ * 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
+ * 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 IOP321_IDBR_MASK 0x00ff
+
+#define IOP321_IBMR_SCL 0x0002
+#define IOP321_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 MYSAR 0x02 /* SWAG a suitable slave address */
+
+#define I2C_ERR 321
+#define I2C_ERR_BERR (I2C_ERR+0)
+#define I2C_ERR_ALD (I2C_ERR+1)
+
+
+typedef volatile u32* r32;
+
+struct iop3xx_biu { /* Bus Interface Unit - the hardware */
+/* physical hardware defs - regs*/
+ r32 CR;
+ r32 SR;
+ r32 SAR;
+ r32 DBR;
+ r32 BMR;
+/* irq bit vector */
+ u32 irq;
+/* stored flags */
+ u32 SR_enabled, SR_received;
+};
+
+struct i2c_algo_iop3xx_data {
+ int channel;
+
+ wait_queue_head_t waitq;
+ spinlock_t lock;
+ int timeout;
+ struct iop3xx_biu* biu;
+};
+
+#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 */
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.70
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.6, 2003/06/11 12:29:21-07:00, greg@kroah.com
[PATCH] I2C: fix some errors found by sparse in include/linux/i2c.h
include/linux/i2c.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Wed Jun 11 13:25:03 2003
+++ b/include/linux/i2c.h Wed Jun 11 13:25:03 2003
@@ -176,7 +176,7 @@
static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
{
- return dev_set_drvdata (&dev->dev, data);
+ dev_set_drvdata (&dev->dev, data);
}
#define I2C_DEVNAME(str) .dev = { .name = str }
@@ -261,7 +261,7 @@
static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
{
- return dev_set_drvdata (&dev->dev, data);
+ dev_set_drvdata (&dev->dev, data);
}
/*flags for the driver struct: */
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.70
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.7, 2003/06/11 12:29:31-07:00, greg@kroah.com
[PATCH] I2C: fix up sparse warnings in drivers/i2c/i2c-core.c
drivers/i2c/i2c-core.c | 36 ++++++++++++++----------------------
1 files changed, 14 insertions(+), 22 deletions(-)
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c Wed Jun 11 13:24:53 2003
+++ b/drivers/i2c/i2c-core.c Wed Jun 11 13:24:53 2003
@@ -510,7 +510,7 @@
msg.addr = client->addr;
msg.flags = client->flags & I2C_M_TEN;
msg.len = count;
- (const char *)msg.buf = buf;
+ msg.buf = (char *)buf;
DEB2(dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
count));
@@ -861,13 +861,13 @@
return 0;
}
-extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value)
+s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value)
{
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
value,0,I2C_SMBUS_QUICK,NULL);
}
-extern s32 i2c_smbus_read_byte(struct i2c_client * client)
+s32 i2c_smbus_read_byte(struct i2c_client *client)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -877,14 +877,14 @@
return 0x0FF & data.byte;
}
-extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value)
+s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
{
union i2c_smbus_data data; /* only for PEC */
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
}
-extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
+s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -894,8 +894,7 @@
return 0x0FF & data.byte;
}
-extern s32 i2c_smbus_write_byte_data(struct i2c_client * client, u8 command,
- u8 value)
+s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
{
union i2c_smbus_data data;
data.byte = value;
@@ -904,7 +903,7 @@
I2C_SMBUS_BYTE_DATA,&data);
}
-extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command)
+s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -914,8 +913,7 @@
return 0x0FFFF & data.word;
}
-extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
- u8 command, u16 value)
+s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
{
union i2c_smbus_data data;
data.word = value;
@@ -924,8 +922,7 @@
I2C_SMBUS_WORD_DATA,&data);
}
-extern s32 i2c_smbus_process_call(struct i2c_client * client,
- u8 command, u16 value)
+s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value)
{
union i2c_smbus_data data;
data.word = value;
@@ -938,8 +935,7 @@
}
/* Returns the number of read bytes */
-extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
- u8 command, u8 *values)
+s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -954,8 +950,7 @@
}
}
-extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
- u8 command, u8 length, u8 *values)
+s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -970,8 +965,7 @@
}
/* Returns the number of read bytes */
-extern s32 i2c_smbus_block_process_call(struct i2c_client * client,
- u8 command, u8 length, u8 *values)
+s32 i2c_smbus_block_process_call(struct i2c_client *client, u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -990,8 +984,7 @@
}
/* Returns the number of read bytes */
-extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
- u8 command, u8 *values)
+s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
{
union i2c_smbus_data data;
int i;
@@ -1006,8 +999,7 @@
}
}
-extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
- u8 command, u8 length, u8 *values)
+s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.70
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.8, 2003/06/11 12:29:42-07:00, greg@kroah.com
[PATCH] I2C: fix up sparse warnings in the i2c-dev driver
drivers/i2c/i2c-dev.c | 10 +++++-----
include/linux/i2c-dev.h | 6 +++---
2 files changed, 8 insertions(+), 8 deletions(-)
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c Wed Jun 11 13:24:43 2003
+++ b/drivers/i2c/i2c-dev.c Wed Jun 11 13:24:43 2003
@@ -122,7 +122,7 @@
}
static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
+static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
loff_t *offset)
{
char *tmp;
@@ -147,7 +147,7 @@
return ret;
}
-static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
+static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t count,
loff_t *offset)
{
int ret;
@@ -211,12 +211,12 @@
return 0;
case I2C_FUNCS:
funcs = i2c_get_functionality(client->adapter);
- return (copy_to_user((unsigned long *)arg,&funcs,
+ return (copy_to_user((unsigned long __user *)arg, &funcs,
sizeof(unsigned long)))?-EFAULT:0;
case I2C_RDWR:
if (copy_from_user(&rdwr_arg,
- (struct i2c_rdwr_ioctl_data *)arg,
+ (struct i2c_rdwr_ioctl_data __user *)arg,
sizeof(rdwr_arg)))
return -EFAULT;
@@ -284,7 +284,7 @@
case I2C_SMBUS:
if (copy_from_user(&data_arg,
- (struct i2c_smbus_ioctl_data *) arg,
+ (struct i2c_smbus_ioctl_data __user *) arg,
sizeof(struct i2c_smbus_ioctl_data)))
return -EFAULT;
if ((data_arg.size != I2C_SMBUS_BYTE) &&
diff -Nru a/include/linux/i2c-dev.h b/include/linux/i2c-dev.h
--- a/include/linux/i2c-dev.h Wed Jun 11 13:24:43 2003
+++ b/include/linux/i2c-dev.h Wed Jun 11 13:24:43 2003
@@ -34,13 +34,13 @@
__u8 read_write;
__u8 command;
__u32 size;
- union i2c_smbus_data *data;
+ union i2c_smbus_data __user *data;
};
/* This is the structure as used in the I2C_RDWR ioctl call */
struct i2c_rdwr_ioctl_data {
- struct i2c_msg *msgs; /* pointers to i2c_msgs */
- __u32 nmsgs; /* number of i2c_msgs */
+ struct i2c_msg __user *msgs; /* pointers to i2c_msgs */
+ __u32 nmsgs; /* number of i2c_msgs */
};
#endif /* _LINUX_I2C_DEV_H */
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.70
@ 2005-05-19 6:23 ` Greg KH
0 siblings, 0 replies; 98+ messages in thread
From: Greg KH @ 2005-05-19 6:23 UTC (permalink / raw)
To: linux-kernel, sensors
ChangeSet 1.1419.1.3, 2003/06/11 11:42:47-07:00, margitsw@t-online.de
[PATCH] I2C: add LM85 driver
Nothing extra in sysfs (yet) but I have left the way open in the driver
to do this.
Provides vid, vrm, fan_input(1-4), fan_min(1-4), pwm(1-3),
pwm_enable(1-3), in_input(0-4), in_min(0-4), in_max(0-4),
temp_input(1-3), temp_min(1-3), temp_max(1-3), alarms.
drivers/i2c/chips/Kconfig | 19
drivers/i2c/chips/Makefile | 1
drivers/i2c/chips/lm85.c | 1223 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1241 insertions(+), 2 deletions(-)
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig Wed Jun 11 13:25:33 2003
+++ b/drivers/i2c/chips/Kconfig Wed Jun 11 13:25:33 2003
@@ -47,6 +47,21 @@
in the lm_sensors package, which you can download at
http://www.lm-sensors.nu
+config SENSORS_LM85
+ tristate " National Semiconductors LM85 and compatibles"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for National Semiconductor LM85
+ sensor chips and clones: ADT7463 and ADM1027.
+ This can also be built as a module which can be inserted and
+ removed while the kernel is running.
+
+ The module will be called lm85.
+
+ You will also need the latest user-space utilties: you can find them
+ in the lm_sensors package, which you can download at
+ http://www.lm-sensors.nu
+
config SENSORS_VIA686A
tristate " VIA686A"
depends on I2C && EXPERIMENTAL
@@ -76,8 +91,8 @@
config I2C_SENSOR
tristate
- default y if SENSORS_ADM1021=y || SENSORS_IT87=y || SENSORS_LM75=y || SENSORS_VIA686A=y || SENSORS_W83781D=y
- default m if SENSORS_ADM1021=m || SENSORS_IT87=m || SENSORS_LM75=m || SENSORS_VIA686A=m || SENSORS_W83781D=m
+ default y if SENSORS_ADM1021=y || SENSORS_IT87=y || SENSORS_LM75=y || SENSORS_VIA686A=y || SENSORS_W83781D=y || SENSORS_LM85=y
+ default m if SENSORS_ADM1021=m || SENSORS_IT87=m || SENSORS_LM75=m || SENSORS_VIA686A=m || SENSORS_W83781D=m || SENSORS_LM85=m
default n
endmenu
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile Wed Jun 11 13:25:33 2003
+++ b/drivers/i2c/chips/Makefile Wed Jun 11 13:25:33 2003
@@ -5,5 +5,6 @@
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
+obj-$(CONFIG_SENSORS_LM85) += lm85.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/chips/lm85.c Wed Jun 11 13:25:33 2003
@@ -0,0 +1,1223 @@
+/*
+ lm85.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
+ Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
+ Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de>
+
+ Chip details at <http://www.national.com/ds/LM/LM85.pdf>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+/*
+#include <asm/io.h>
+*/
+
+#undef LM85EXTENDEDFUNC /* Extended functionality */
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_4(lm85b, lm85c, adm1027, adt7463);
+
+/* Enable debug if true */
+static int lm85debug = 0;
+
+/* The LM85 registers */
+
+#define LM85_REG_IN(nr) (0x20 + (nr))
+#define LM85_REG_IN_MIN(nr) (0x44 + (nr) * 2)
+#define LM85_REG_IN_MAX(nr) (0x45 + (nr) * 2)
+
+#define LM85_REG_TEMP(nr) (0x25 + (nr))
+#define LM85_REG_TEMP_MIN(nr) (0x4e + (nr) * 2)
+#define LM85_REG_TEMP_MAX(nr) (0x4f + (nr) * 2)
+
+/* Fan speeds are LSB, MSB (2 bytes) */
+#define LM85_REG_FAN(nr) (0x28 + (nr) *2)
+#define LM85_REG_FAN_MIN(nr) (0x54 + (nr) *2)
+
+#define LM85_REG_PWM(nr) (0x30 + (nr))
+
+#define ADT7463_REG_OPPOINT(nr) (0x33 + (nr))
+
+#define ADT7463_REG_TMIN_CTL1 0x36
+#define ADT7463_REG_TMIN_CTL2 0x37
+
+#define LM85_REG_DEVICE 0x3d
+#define LM85_REG_COMPANY 0x3e
+#define LM85_REG_VERSTEP 0x3f
+/* These are the recognized values for the above regs */
+#define LM85_DEVICE_ADX 0x27
+#define LM85_COMPANY_NATIONAL 0x01
+#define LM85_COMPANY_ANALOG_DEV 0x41
+#define LM85_VERSTEP_GENERIC 0x60
+#define LM85_VERSTEP_LM85C 0x60
+#define LM85_VERSTEP_LM85B 0x62
+#define LM85_VERSTEP_ADM1027 0x60
+#define LM85_VERSTEP_ADT7463 0x62
+
+#define LM85_REG_CONFIG 0x40
+
+#define LM85_REG_ALARM1 0x41
+#define LM85_REG_ALARM2 0x42
+
+#define LM85_REG_VID 0x43
+
+/* Automated FAN control */
+#define LM85_REG_AFAN_CONFIG(nr) (0x5c + (nr))
+#define LM85_REG_AFAN_RANGE(nr) (0x5f + (nr))
+#define LM85_REG_AFAN_SPIKE1 0x62
+#define LM85_REG_AFAN_SPIKE2 0x63
+#define LM85_REG_AFAN_MINPWM(nr) (0x64 + (nr))
+#define LM85_REG_AFAN_LIMIT(nr) (0x67 + (nr))
+#define LM85_REG_AFAN_CRITICAL(nr) (0x6a + (nr))
+#define LM85_REG_AFAN_HYST1 0x6d
+#define LM85_REG_AFAN_HYST2 0x6e
+
+#define LM85_REG_TACH_MODE 0x74
+#define LM85_REG_SPINUP_CTL 0x75
+
+#define ADM1027_REG_TEMP_OFFSET(nr) (0x70 + (nr))
+#define ADM1027_REG_CONFIG2 0x73
+#define ADM1027_REG_INTMASK1 0x74
+#define ADM1027_REG_INTMASK2 0x75
+#define ADM1027_REG_EXTEND_ADC1 0x76
+#define ADM1027_REG_EXTEND_ADC2 0x77
+#define ADM1027_REG_CONFIG3 0x78
+#define ADM1027_REG_FAN_PPR 0x7b
+
+#define ADT7463_REG_THERM 0x79
+#define ADT7463_REG_THERM_LIMIT 0x7A
+
+#define LM85_ALARM_IN0 0x0001
+#define LM85_ALARM_IN1 0x0002
+#define LM85_ALARM_IN2 0x0004
+#define LM85_ALARM_IN3 0x0008
+#define LM85_ALARM_TEMP1 0x0010
+#define LM85_ALARM_TEMP2 0x0020
+#define LM85_ALARM_TEMP3 0x0040
+#define LM85_ALARM_ALARM2 0x0080
+#define LM85_ALARM_IN4 0x0100
+#define LM85_ALARM_RESERVED 0x0200
+#define LM85_ALARM_FAN1 0x0400
+#define LM85_ALARM_FAN2 0x0800
+#define LM85_ALARM_FAN3 0x1000
+#define LM85_ALARM_FAN4 0x2000
+#define LM85_ALARM_TEMP1_FAULT 0x4000
+#define LM85_ALARM_TEMP3_FAULT 0x8000
+
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+ variants. Note that you should be a bit careful with which arguments
+ these macros are called: arguments may be evaluated more than once.
+ */
+
+/* IN are scaled 1.000 = 0xc0, mag = 3 */
+#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*0xc0+500)/1000),0,255))
+#define INEXT_FROM_REG(val,ext) (((val)*1000 + (ext)*250 + 96)/0xc0)
+#define IN_FROM_REG(val) (INEXT_FROM_REG(val,0))
+
+/* IN are scaled acording to built-in resistors */
+static int lm85_scaling[] = { /* .001 Volts */
+ 2500, 2250, 3300, 5000, 12000
+ };
+#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from))
+#define INS_TO_REG(n,val) (SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255))
+#define INSEXT_FROM_REG(n,val,ext) (SCALE((val)*4 + (ext),192*4,lm85_scaling[n]))
+/*
+#define INS_FROM_REG(n,val) (INSEXT_FROM_REG(n,val,0))
+*/
+#define INS_FROM_REG(n,val) ( ( (val*4*lm85_scaling[n]) + (192*4/2) ) / (192*4) )
+
+/* FAN speed is measured using 90kHz clock */
+#define FAN_TO_REG(val) (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534))
+#define FAN_FROM_REG(val) ((val)=0?-1:(val)=0xffff?0:5400000/(val))
+
+/* Temperature is reported in .01 degC increments */
+#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+50)/100,-127,127))
+#define TEMPEXT_FROM_REG(val,ext) ((val)*100 + (ext)*25)
+#define TEMP_FROM_REG(val) (TEMPEXT_FROM_REG(val,0))
+#define EXTTEMP_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
+
+#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
+#define PWM_FROM_REG(val) (val)
+
+#define EXT_FROM_REG(val,sensor) (((val)>>(sensor * 2))&0x03)
+
+#ifdef LM85EXTENDEDFUNC /* Extended functionality */
+
+/* ZONEs have the following parameters:
+ * Limit (low) temp, 1. degC
+ * Hysteresis (below limit), 1. degC (0-15)
+ * Range of speed control, .1 degC (2-80)
+ * Critical (high) temp, 1. degC
+ *
+ * FAN PWMs have the following parameters:
+ * Reference Zone, 1, 2, 3, etc.
+ * Spinup time, .05 sec
+ * PWM value at limit/low temp, 1 count
+ * PWM Frequency, 1. Hz
+ * PWM is Min or OFF below limit, flag
+ * Invert PWM output, flag
+ *
+ * Some chips filter the temp, others the fan.
+ * Filter constant (or disabled) .1 seconds
+ */
+
+/* These are the zone temperature range encodings */
+static int lm85_range_map[] = { /* .1 degC */
+ 20, 25, 33, 40, 50, 66,
+ 80, 100, 133, 160, 200, 266,
+ 320, 400, 533, 800
+ };
+static int RANGE_TO_REG( int range )
+{
+ int i;
+
+ if( range >= lm85_range_map[15] ) { return 15 ; }
+ for( i = 0 ; i < 15 ; ++i )
+ if( range <= lm85_range_map[i] )
+ break ;
+ return( i & 0x0f );
+}
+#define RANGE_FROM_REG(val) (lm85_range_map[(val)&0x0f])
+
+/* These are the Acoustic Enhancement, or Temperature smoothing encodings
+ * NOTE: The enable/disable bit is INCLUDED in these encodings as the
+ * MSB (bit 3, value 8). If the enable bit is 0, the encoded value
+ * is ignored, or set to 0.
+ */
+static int lm85_smooth_map[] = { /* .1 sec */
+ 350, 176, 118, 70, 44, 30, 16, 8
+/* 35.4 * 1/1, 1/2, 1/3, 1/5, 1/8, 1/12, 1/24, 1/48 */
+ };
+static int SMOOTH_TO_REG( int smooth )
+{
+ int i;
+
+ if( smooth <= 0 ) { return 0 ; } /* Disabled */
+ for( i = 0 ; i < 7 ; ++i )
+ if( smooth >= lm85_smooth_map[i] )
+ break ;
+ return( (i & 0x07) | 0x08 );
+}
+#define SMOOTH_FROM_REG(val) ((val)&0x08?lm85_smooth_map[(val)&0x07]:0)
+
+/* These are the fan spinup delay time encodings */
+static int lm85_spinup_map[] = { /* .1 sec */
+ 0, 1, 2, 4, 7, 10, 20, 40
+ };
+static int SPINUP_TO_REG( int spinup )
+{
+ int i;
+
+ if( spinup >= lm85_spinup_map[7] ) { return 7 ; }
+ for( i = 0 ; i < 7 ; ++i )
+ if( spinup <= lm85_spinup_map[i] )
+ break ;
+ return( i & 0x07 );
+}
+#define SPINUP_FROM_REG(val) (lm85_spinup_map[(val)&0x07])
+
+/* These are the PWM frequency encodings */
+static int lm85_freq_map[] = { /* .1 Hz */
+ 100, 150, 230, 300, 380, 470, 620, 980
+ };
+static int FREQ_TO_REG( int freq )
+{
+ int i;
+
+ if( freq >= lm85_freq_map[7] ) { return 7 ; }
+ for( i = 0 ; i < 7 ; ++i )
+ if( freq <= lm85_freq_map[i] )
+ break ;
+ return( i & 0x07 );
+}
+#define FREQ_FROM_REG(val) (lm85_freq_map[(val)&0x07])
+
+/* Since we can't use strings, I'm abusing these numbers
+ * to stand in for the following meanings:
+ * 1 -- PWM responds to Zone 1
+ * 2 -- PWM responds to Zone 2
+ * 3 -- PWM responds to Zone 3
+ * 23 -- PWM responds to the higher temp of Zone 2 or 3
+ * 123 -- PWM responds to highest of Zone 1, 2, or 3
+ * 0 -- PWM is always at 0% (ie, off)
+ * -1 -- PWM is always at 100%
+ * -2 -- PWM responds to manual control
+ */
+
+#endif /* Extended functionality */
+
+static int lm85_zone_map[] = { 1, 2, 3, -1, 0, 23, 123, -2 };
+#define ZONE_FROM_REG(val) (lm85_zone_map[((val)>>5)&0x07])
+
+#ifdef LM85EXTENDEDFUNC /* Extended functionality */
+
+static int ZONE_TO_REG( int zone )
+{
+ int i;
+
+ for( i = 0 ; i <= 7 ; ++i )
+ if( zone = lm85_zone_map[i] )
+ break ;
+ if( i > 7 ) /* Not found. */
+ i = 3; /* Always 100% */
+ return( (i & 0x07)<<5 );
+}
+
+#endif /* Extended functionality */
+
+#define HYST_TO_REG(val) (SENSORS_LIMIT((-(val)+5)/10,0,15))
+#define HYST_FROM_REG(val) (-(val)*10)
+
+#define OFFSET_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
+#define OFFSET_FROM_REG(val) ((val)*25)
+
+#define PPR_MASK(fan) (0x03<<(fan *2))
+#define PPR_TO_REG(val,fan) (SENSORS_LIMIT((val)-1,0,3)<<(fan *2))
+#define PPR_FROM_REG(val,fan) ((((val)>>(fan * 2))&0x03)+1)
+
+/* i2c-vid.h defines vid_from_reg() */
+#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
+
+#define ALARMS_FROM_REG(val) (val)
+
+/* Unlike some other drivers we DO NOT set initial limits. Use
+ * the config file to set limits. Some users have reported
+ * motherboards shutting down when we set limits in a previous
+ * version of the driver.
+ */
+
+/* Typically used with Pentium 4 systems v9.1 VRM spec */
+#define LM85_INIT_VRM 91
+
+/* Chip sampling rates
+ *
+ * Some sensors are not updated more frequently than once per second
+ * so it doesn't make sense to read them more often than that.
+ * We cache the results and return the saved data if the driver
+ * is called again before a second has elapsed.
+ *
+ * Also, there is significant configuration data for this chip
+ * given the automatic PWM fan control that is possible. There
+ * are about 47 bytes of config data to only 22 bytes of actual
+ * readings. So, we keep the config data up to date in the cache
+ * when it is written and only sample it once every 1 *minute*
+ */
+#define LM85_DATA_INTERVAL (HZ + HZ / 2)
+#define LM85_CONFIG_INTERVAL (1 * 60 * HZ)
+
+/* For each registered LM85, we need to keep some data in memory. That
+ data is pointed to by lm85_list[NR]->data. The structure itself is
+ dynamically allocated, at the same time when a new lm85 client is
+ allocated. */
+
+/* LM85 can automatically adjust fan speeds based on temperature
+ * This structure encapsulates an entire Zone config. There are
+ * three zones (one for each temperature input) on the lm85
+ */
+struct lm85_zone {
+ s8 limit; /* Low temp limit */
+ u8 hyst; /* Low limit hysteresis. (0-15) */
+ u8 range; /* Temp range, encoded */
+ s8 critical; /* "All fans ON" temp limit */
+};
+
+struct lm85_autofan {
+ u8 config; /* Register value */
+ u8 freq; /* PWM frequency, encoded */
+ u8 min_pwm; /* Minimum PWM value, encoded */
+ u8 min_off; /* Min PWM or OFF below "limit", flag */
+};
+
+struct lm85_data {
+ struct semaphore lock;
+ enum chips type;
+
+ struct semaphore update_lock;
+ int valid; /* !=0 if following fields are valid */
+ unsigned long last_reading; /* In jiffies */
+ unsigned long last_config; /* In jiffies */
+
+ u8 in[5]; /* Register value */
+ u8 in_max[5]; /* Register value */
+ u8 in_min[5]; /* Register value */
+ s8 temp[3]; /* Register value */
+ s8 temp_min[3]; /* Register value */
+ s8 temp_max[3]; /* Register value */
+ s8 temp_offset[3]; /* Register value */
+ u16 fan[4]; /* Register value */
+ u16 fan_min[4]; /* Register value */
+ u8 pwm[3]; /* Register value */
+ u8 spinup_ctl; /* Register encoding, combined */
+ u8 tach_mode; /* Register encoding, combined */
+ u16 extend_adc; /* Register value */
+ u8 fan_ppr; /* Register value */
+ u8 smooth[3]; /* Register encoding */
+ u8 vid; /* Register value */
+ u8 vrm; /* VRM version */
+ u8 syncpwm3; /* Saved PWM3 for TACH 2,3,4 config */
+ u8 oppoint[3]; /* Register value */
+ u16 tmin_ctl; /* Register value */
+ u32 therm_total; /* Cummulative therm count */
+ u8 therm_limit; /* Register value */
+ u16 alarms; /* Register encoding, combined */
+ struct lm85_autofan autofan[3];
+ struct lm85_zone zone[3];
+};
+
+static int lm85_attach_adapter(struct i2c_adapter *adapter);
+static int lm85_detect(struct i2c_adapter *adapter, int address,
+ int kind);
+static int lm85_detach_client(struct i2c_client *client);
+
+static int lm85_read_value(struct i2c_client *client, u8 register);
+static int lm85_write_value(struct i2c_client *client, u8 register, int value);
+static void lm85_update_client(struct i2c_client *client);
+static void lm85_init_client(struct i2c_client *client);
+
+
+static struct i2c_driver lm85_driver = {
+ .owner = THIS_MODULE,
+ .name = "lm85",
+ .id = I2C_DRIVERID_LM85,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = lm85_attach_adapter,
+ .detach_client = lm85_detach_client,
+};
+
+/* Unique ID assigned to each LM85 detected */
+static int lm85_id = 0;
+
+
+/* 4 Fans */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr]) );
+}
+static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr]) );
+}
+static ssize_t set_fan_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->fan_min[nr] = FAN_TO_REG(val);
+ lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]);
+ return count;
+}
+
+#define show_fan_offset(offset) \
+static ssize_t show_fan_##offset (struct device *dev, char *buf) \
+{ \
+ return show_fan(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_fan_min(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t set_fan_##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_fan_min(dev, buf, count, 0x##offset - 1); \
+} \
+static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_fan_##offset, NULL) \
+static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, \
+ show_fan_##offset##_min, set_fan_##offset##_min)
+
+show_fan_offset(1);
+show_fan_offset(2);
+show_fan_offset(3);
+show_fan_offset(4);
+
+/* vid, vrm, alarms */
+
+static ssize_t show_vid_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+}
+
+static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL)
+
+static ssize_t show_vrm_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf, "%ld\n", (long) data->vrm);
+}
+
+static ssize_t store_vrm_reg(struct device *dev, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ data->vrm = val;
+ return count;
+}
+
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg)
+
+static ssize_t show_alarms_reg(struct device *dev, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
+
+/* pwm */
+
+static ssize_t show_pwm(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm[nr]) );
+}
+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 lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->pwm[nr] = PWM_TO_REG(val);
+ lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]);
+ return count;
+}
+static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+ int pwm_zone;
+
+ lm85_update_client(client);
+ pwm_zone = ZONE_FROM_REG(data->autofan[nr].config);
+ return sprintf(buf,"%d\n", (pwm_zone != 0 && pwm_zone != -1) );
+}
+
+#define show_pwm_reg(offset) \
+static ssize_t show_pwm_##offset (struct device *dev, char *buf) \
+{ \
+ return show_pwm(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t set_pwm_##offset (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_pwm(dev, buf, count, 0x##offset - 1); \
+} \
+static ssize_t show_pwm_enable##offset (struct device *dev, char *buf) \
+{ \
+ return show_pwm_enable(dev, buf, 0x##offset - 1); \
+} \
+static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
+ show_pwm_##offset, set_pwm_##offset) \
+static DEVICE_ATTR(pwm_enable##offset, S_IRUGO, show_pwm_enable##offset, NULL)
+
+show_pwm_reg(1);
+show_pwm_reg(2);
+show_pwm_reg(3);
+
+/* Voltages */
+
+static ssize_t show_in(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]) );
+}
+static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]) );
+}
+static ssize_t set_in_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->in_min[nr] = INS_TO_REG(nr, val);
+ lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]);
+ return count;
+}
+static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]) );
+}
+static ssize_t set_in_max(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->in_max[nr] = INS_TO_REG(nr, val);
+ lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]);
+ return count;
+}
+#define show_in_reg(offset) \
+static ssize_t show_in_##offset (struct device *dev, char *buf) \
+{ \
+ return show_in(dev, buf, 0x##offset); \
+} \
+static ssize_t show_in_##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_in_min(dev, buf, 0x##offset); \
+} \
+static ssize_t show_in_##offset##_max (struct device *dev, char *buf) \
+{ \
+ return show_in_max(dev, buf, 0x##offset); \
+} \
+static ssize_t set_in_##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_in_min(dev, buf, count, 0x##offset); \
+} \
+static ssize_t set_in_##offset##_max (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_in_max(dev, buf, count, 0x##offset); \
+} \
+static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in_##offset, NULL) \
+static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \
+ show_in_##offset##_min, set_in_##offset##_min) \
+static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \
+ show_in_##offset##_max, set_in_##offset##_max)
+
+show_in_reg(0);
+show_in_reg(1);
+show_in_reg(2);
+show_in_reg(3);
+show_in_reg(4);
+
+/* Temps */
+
+static ssize_t show_temp(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]) );
+}
+static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]) );
+}
+static ssize_t set_temp_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->temp_min[nr] = TEMP_TO_REG(val);
+ lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]);
+ return count;
+}
+static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ lm85_update_client(client);
+ return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]) );
+}
+static ssize_t set_temp_max(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ int val = simple_strtol(buf, NULL, 10);
+ data->temp_max[nr] = TEMP_TO_REG(val);
+ lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]);
+ return count;
+}
+#define show_temp_reg(offset) \
+static ssize_t show_temp_##offset (struct device *dev, char *buf) \
+{ \
+ return show_temp(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t show_temp_##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_temp_min(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t show_temp_##offset##_max (struct device *dev, char *buf) \
+{ \
+ return show_temp_max(dev, buf, 0x##offset - 1); \
+} \
+static ssize_t set_temp_##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_temp_min(dev, buf, count, 0x##offset - 1); \
+} \
+static ssize_t set_temp_##offset##_max (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_temp_max(dev, buf, count, 0x##offset - 1); \
+} \
+static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_temp_##offset, NULL) \
+static DEVICE_ATTR(temp_min##offset, S_IRUGO | S_IWUSR, \
+ show_temp_##offset##_min, set_temp_##offset##_min) \
+static DEVICE_ATTR(temp_max##offset, S_IRUGO | S_IWUSR, \
+ show_temp_##offset##_max, set_temp_##offset##_max)
+
+show_temp_reg(1);
+show_temp_reg(2);
+show_temp_reg(3);
+
+
+int lm85_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, lm85_detect);
+}
+
+int lm85_detect(struct i2c_adapter *adapter, int address,
+ int kind)
+{
+ int company, verstep ;
+ struct i2c_client *new_client = NULL;
+ struct lm85_data *data;
+ int err = 0;
+ const char *type_name = "";
+
+ if (i2c_is_isa_adapter(adapter)) {
+ /* This chip has no ISA interface */
+ goto ERROR0 ;
+ };
+
+ if (!i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA)) {
+ /* We need to be able to do byte I/O */
+ goto ERROR0 ;
+ };
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access lm85_{read,write}_value. */
+
+ if (!(new_client = kmalloc((sizeof(struct i2c_client)) +
+ sizeof(struct lm85_data),
+ GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto ERROR0;
+ }
+
+ memset(new_client, 0, sizeof(struct i2c_client) +
+ sizeof(struct lm85_data));
+ data = (struct lm85_data *) (new_client + 1);
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &lm85_driver;
+ new_client->flags = 0;
+
+ /* Now, we do the remaining detection. */
+
+ company = lm85_read_value(new_client, LM85_REG_COMPANY);
+ verstep = lm85_read_value(new_client, LM85_REG_VERSTEP);
+
+ if (lm85debug) {
+ printk("lm85: Detecting device at %d,0x%02x with"
+ " COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
+ i2c_adapter_id(new_client->adapter), new_client->addr,
+ company, verstep);
+ }
+
+ /* If auto-detecting, Determine the chip type. */
+ if (kind <= 0) {
+ if (lm85debug) {
+ printk("lm85: Autodetecting device at %d,0x%02x ...\n",
+ i2c_adapter_id(adapter), address );
+ }
+ if( company = LM85_COMPANY_NATIONAL
+ && verstep = LM85_VERSTEP_LM85C ) {
+ kind = lm85c ;
+ } else if( company = LM85_COMPANY_NATIONAL
+ && verstep = LM85_VERSTEP_LM85B ) {
+ kind = lm85b ;
+ } else if( company = LM85_COMPANY_NATIONAL
+ && (verstep & 0xf0) = LM85_VERSTEP_GENERIC ) {
+ printk("lm85: Unrecgonized version/stepping 0x%02x"
+ " Defaulting to LM85.\n", verstep );
+ kind = any_chip ;
+ } else if( company = LM85_COMPANY_ANALOG_DEV
+ && verstep = LM85_VERSTEP_ADM1027 ) {
+ kind = adm1027 ;
+ } else if( company = LM85_COMPANY_ANALOG_DEV
+ && verstep = LM85_VERSTEP_ADT7463 ) {
+ kind = adt7463 ;
+ } else if( company = LM85_COMPANY_ANALOG_DEV
+ && (verstep & 0xf0) = LM85_VERSTEP_GENERIC ) {
+ printk("lm85: Unrecgonized version/stepping 0x%02x"
+ " Defaulting to ADM1027.\n", verstep );
+ kind = adm1027 ;
+ } else if( kind = 0 && (verstep & 0xf0) = 0x60) {
+ printk("lm85: Generic LM85 Version 6 detected\n");
+ /* Leave kind as "any_chip" */
+ } else {
+ if (lm85debug) {
+ printk("lm85: Autodetection failed\n");
+ }
+ /* Not an LM85 ... */
+ if( kind = 0 ) { /* User used force=x,y */
+ printk("lm85: Generic LM85 Version 6 not"
+ " found at %d,0x%02x. Try force_lm85c.\n",
+ i2c_adapter_id(adapter), address );
+ }
+ err = 0 ;
+ goto ERROR1;
+ }
+ }
+
+ /* Fill in the chip specific driver values */
+ if ( kind = any_chip ) {
+ type_name = "lm85";
+ strlcpy(new_client->dev.name, "Generic LM85", DEVICE_NAME_SIZE);
+ } else if ( kind = lm85b ) {
+ type_name = "lm85b";
+ strlcpy(new_client->dev.name, "National LM85-B", DEVICE_NAME_SIZE);
+ } else if ( kind = lm85c ) {
+ type_name = "lm85c";
+ strlcpy(new_client->dev.name, "National LM85-C", DEVICE_NAME_SIZE);
+ } else if ( kind = adm1027 ) {
+ type_name = "adm1027";
+ strlcpy(new_client->dev.name, "Analog Devices ADM1027", DEVICE_NAME_SIZE);
+ } else if ( kind = adt7463 ) {
+ type_name = "adt7463";
+ strlcpy(new_client->dev.name, "Analog Devices ADT7463", DEVICE_NAME_SIZE);
+ } else {
+ dev_dbg(&adapter->dev, "Internal error, invalid kind (%d)!", kind);
+ err = -EFAULT ;
+ goto ERROR1;
+ }
+
+ /* Fill in the remaining client fields */
+ new_client->id = lm85_id++;
+ data->type = kind;
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ if (lm85debug) {
+ printk("lm85: Assigning ID %d to %s at %d,0x%02x\n",
+ new_client->id, new_client->dev.name,
+ i2c_adapter_id(new_client->adapter),
+ new_client->addr);
+ }
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto ERROR1;
+
+ /* Set the VRM version */
+ data->vrm = LM85_INIT_VRM ;
+
+ device_create_file(&new_client->dev, &dev_attr_fan_input1);
+ device_create_file(&new_client->dev, &dev_attr_fan_input2);
+ device_create_file(&new_client->dev, &dev_attr_fan_input3);
+ device_create_file(&new_client->dev, &dev_attr_fan_input4);
+ device_create_file(&new_client->dev, &dev_attr_fan_min1);
+ device_create_file(&new_client->dev, &dev_attr_fan_min2);
+ device_create_file(&new_client->dev, &dev_attr_fan_min3);
+ device_create_file(&new_client->dev, &dev_attr_fan_min4);
+ device_create_file(&new_client->dev, &dev_attr_pwm1);
+ device_create_file(&new_client->dev, &dev_attr_pwm2);
+ device_create_file(&new_client->dev, &dev_attr_pwm3);
+ device_create_file(&new_client->dev, &dev_attr_pwm_enable1);
+ device_create_file(&new_client->dev, &dev_attr_pwm_enable2);
+ device_create_file(&new_client->dev, &dev_attr_pwm_enable3);
+ device_create_file(&new_client->dev, &dev_attr_in_input0);
+ device_create_file(&new_client->dev, &dev_attr_in_input1);
+ device_create_file(&new_client->dev, &dev_attr_in_input2);
+ device_create_file(&new_client->dev, &dev_attr_in_input3);
+ device_create_file(&new_client->dev, &dev_attr_in_input4);
+ device_create_file(&new_client->dev, &dev_attr_in_min0);
+ device_create_file(&new_client->dev, &dev_attr_in_min1);
+ device_create_file(&new_client->dev, &dev_attr_in_min2);
+ device_create_file(&new_client->dev, &dev_attr_in_min3);
+ device_create_file(&new_client->dev, &dev_attr_in_min4);
+ device_create_file(&new_client->dev, &dev_attr_in_max0);
+ device_create_file(&new_client->dev, &dev_attr_in_max1);
+ device_create_file(&new_client->dev, &dev_attr_in_max2);
+ device_create_file(&new_client->dev, &dev_attr_in_max3);
+ device_create_file(&new_client->dev, &dev_attr_in_max4);
+ device_create_file(&new_client->dev, &dev_attr_temp_input1);
+ device_create_file(&new_client->dev, &dev_attr_temp_input2);
+ device_create_file(&new_client->dev, &dev_attr_temp_input3);
+ device_create_file(&new_client->dev, &dev_attr_temp_min1);
+ device_create_file(&new_client->dev, &dev_attr_temp_min2);
+ device_create_file(&new_client->dev, &dev_attr_temp_min3);
+ device_create_file(&new_client->dev, &dev_attr_temp_max1);
+ device_create_file(&new_client->dev, &dev_attr_temp_max2);
+ device_create_file(&new_client->dev, &dev_attr_temp_max3);
+ device_create_file(&new_client->dev, &dev_attr_vrm);
+ device_create_file(&new_client->dev, &dev_attr_vid);
+ device_create_file(&new_client->dev, &dev_attr_alarms);
+
+ /* Initialize the LM85 chip */
+ lm85_init_client(new_client);
+ return 0;
+
+ /* Error out and cleanup code */
+ ERROR1:
+ kfree(new_client);
+ ERROR0:
+ return err;
+}
+
+int lm85_detach_client(struct i2c_client *client)
+{
+ i2c_detach_client(client);
+ kfree(client);
+ return 0;
+}
+
+
+int lm85_read_value(struct i2c_client *client, u8 reg)
+{
+ int res;
+
+ /* What size location is it? */
+ switch( reg ) {
+ case LM85_REG_FAN(0) : /* Read WORD data */
+ case LM85_REG_FAN(1) :
+ case LM85_REG_FAN(2) :
+ case LM85_REG_FAN(3) :
+ case LM85_REG_FAN_MIN(0) :
+ case LM85_REG_FAN_MIN(1) :
+ case LM85_REG_FAN_MIN(2) :
+ case LM85_REG_FAN_MIN(3) :
+ case LM85_REG_ALARM1 : /* Read both bytes at once */
+ case ADM1027_REG_EXTEND_ADC1 : /* Read two bytes at once */
+ res = i2c_smbus_read_byte_data(client, reg) & 0xff ;
+ res |= i2c_smbus_read_byte_data(client, reg+1) << 8 ;
+ break ;
+ case ADT7463_REG_TMIN_CTL1 : /* Read WORD MSB, LSB */
+ res = i2c_smbus_read_byte_data(client, reg) << 8 ;
+ res |= i2c_smbus_read_byte_data(client, reg+1) & 0xff ;
+ break ;
+ default: /* Read BYTE data */
+ res = i2c_smbus_read_byte_data(client, reg);
+ break ;
+ }
+
+ return res ;
+}
+
+int lm85_write_value(struct i2c_client *client, u8 reg, int value)
+{
+ int res ;
+
+ switch( reg ) {
+ case LM85_REG_FAN(0) : /* Write WORD data */
+ case LM85_REG_FAN(1) :
+ case LM85_REG_FAN(2) :
+ case LM85_REG_FAN(3) :
+ case LM85_REG_FAN_MIN(0) :
+ case LM85_REG_FAN_MIN(1) :
+ case LM85_REG_FAN_MIN(2) :
+ case LM85_REG_FAN_MIN(3) :
+ /* NOTE: ALARM is read only, so not included here */
+ res = i2c_smbus_write_byte_data(client, reg, value & 0xff) ;
+ res |= i2c_smbus_write_byte_data(client, reg+1, (value>>8) & 0xff) ;
+ break ;
+ case ADT7463_REG_TMIN_CTL1 : /* Write WORD MSB, LSB */
+ res = i2c_smbus_write_byte_data(client, reg, (value>>8) & 0xff);
+ res |= i2c_smbus_write_byte_data(client, reg+1, value & 0xff) ;
+ break ;
+ default: /* Write BYTE data */
+ res = i2c_smbus_write_byte_data(client, reg, value);
+ break ;
+ }
+
+ return res ;
+}
+
+void lm85_init_client(struct i2c_client *client)
+{
+ int value;
+ struct lm85_data *data = i2c_get_clientdata(client);
+
+ if (lm85debug) {
+ printk("lm85(%d): Initializing device\n", client->id);
+ }
+
+ /* Warn if part was not "READY" */
+ value = lm85_read_value(client, LM85_REG_CONFIG);
+ if (lm85debug) {
+ printk("lm85(%d): LM85_REG_CONFIG is: 0x%02x\n", client->id, value );
+ }
+ if( value & 0x02 ) {
+ printk("lm85(%d): Client (%d,0x%02x) config is locked.\n",
+ client->id,
+ i2c_adapter_id(client->adapter), client->addr );
+ };
+ if( ! (value & 0x04) ) {
+ printk("lm85(%d): Client (%d,0x%02x) is not ready.\n",
+ client->id,
+ i2c_adapter_id(client->adapter), client->addr );
+ };
+ if( value & 0x10
+ && ( data->type = adm1027
+ || data->type = adt7463 ) ) {
+ printk("lm85(%d): Client (%d,0x%02x) VxI mode is set. "
+ "Please report this to the lm85 maintainer.\n",
+ client->id,
+ i2c_adapter_id(client->adapter), client->addr );
+ };
+
+ /* WE INTENTIONALLY make no changes to the limits,
+ * offsets, pwms, fans and zones. If they were
+ * configured, we don't want to mess with them.
+ * If they weren't, the default is 100% PWM, no
+ * control and will suffice until 'sensors -s'
+ * can be run by the user.
+ */
+
+ /* Start monitoring */
+ value = lm85_read_value(client, LM85_REG_CONFIG);
+ /* Try to clear LOCK, Set START, save everything else */
+ value = (value & ~ 0x02) | 0x01 ;
+ if (lm85debug) {
+ printk("lm85(%d): Setting CONFIG to: 0x%02x\n", client->id, value );
+ }
+ lm85_write_value(client, LM85_REG_CONFIG, value);
+
+}
+
+void lm85_update_client(struct i2c_client *client)
+{
+ struct lm85_data *data = i2c_get_clientdata(client);
+ int i;
+
+ down(&data->update_lock);
+
+ if ( !data->valid ||
+ (jiffies - data->last_reading > LM85_DATA_INTERVAL ) ) {
+ /* Things that change quickly */
+
+ if (lm85debug) {
+ printk("lm85(%d): Reading sensor values\n", client->id);
+ }
+ /* Have to read extended bits first to "freeze" the
+ * more significant bits that are read later.
+ */
+ if ( (data->type = adm1027) || (data->type = adt7463) ) {
+ data->extend_adc + lm85_read_value(client, ADM1027_REG_EXTEND_ADC1);
+ }
+
+ for (i = 0; i <= 4; ++i) {
+ data->in[i] + lm85_read_value(client, LM85_REG_IN(i));
+ }
+
+ for (i = 0; i <= 3; ++i) {
+ data->fan[i] + lm85_read_value(client, LM85_REG_FAN(i));
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ data->temp[i] + lm85_read_value(client, LM85_REG_TEMP(i));
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ data->pwm[i] + lm85_read_value(client, LM85_REG_PWM(i));
+ }
+
+ if ( data->type = adt7463 ) {
+ if( data->therm_total < ULONG_MAX - 256 ) {
+ data->therm_total ++ lm85_read_value(client, ADT7463_REG_THERM );
+ }
+ }
+
+ data->alarms = lm85_read_value(client, LM85_REG_ALARM1);
+
+ data->last_reading = jiffies ;
+ }; /* last_reading */
+
+ if ( !data->valid ||
+ (jiffies - data->last_config > LM85_CONFIG_INTERVAL) ) {
+ /* Things that don't change often */
+
+ if (lm85debug) {
+ printk("lm85(%d): Reading config values\n", client->id);
+ }
+ for (i = 0; i <= 4; ++i) {
+ data->in_min[i] + lm85_read_value(client, LM85_REG_IN_MIN(i));
+ data->in_max[i] + lm85_read_value(client, LM85_REG_IN_MAX(i));
+ }
+
+ for (i = 0; i <= 3; ++i) {
+ data->fan_min[i] + lm85_read_value(client, LM85_REG_FAN_MIN(i));
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ data->temp_min[i] + lm85_read_value(client, LM85_REG_TEMP_MIN(i));
+ data->temp_max[i] + lm85_read_value(client, LM85_REG_TEMP_MAX(i));
+ }
+
+ data->vid = lm85_read_value(client, LM85_REG_VID);
+
+ for (i = 0; i <= 2; ++i) {
+ int val ;
+ data->autofan[i].config + lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
+ val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
+ data->autofan[i].freq = val & 0x07 ;
+ data->zone[i].range = (val >> 4) & 0x0f ;
+ data->autofan[i].min_pwm + lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
+ data->zone[i].limit + lm85_read_value(client, LM85_REG_AFAN_LIMIT(i));
+ data->zone[i].critical + lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i));
+ }
+
+ i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
+ data->smooth[0] = i & 0x0f ;
+ data->syncpwm3 = i & 0x10 ; /* Save PWM3 config */
+ data->autofan[0].min_off = (i & 0x20) != 0 ;
+ data->autofan[1].min_off = (i & 0x40) != 0 ;
+ data->autofan[2].min_off = (i & 0x80) != 0 ;
+ i = lm85_read_value(client, LM85_REG_AFAN_SPIKE2);
+ data->smooth[1] = (i>>4) & 0x0f ;
+ data->smooth[2] = i & 0x0f ;
+
+ i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
+ data->zone[0].hyst = (i>>4) & 0x0f ;
+ data->zone[1].hyst = i & 0x0f ;
+
+ i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
+ data->zone[2].hyst = (i>>4) & 0x0f ;
+
+ if ( (data->type = lm85b) || (data->type = lm85c) ) {
+ data->tach_mode = lm85_read_value(client,
+ LM85_REG_TACH_MODE );
+ data->spinup_ctl = lm85_read_value(client,
+ LM85_REG_SPINUP_CTL );
+ } else if ( (data->type = adt7463) || (data->type = adm1027) ) {
+ if ( data->type = adt7463 ) {
+ for (i = 0; i <= 2; ++i) {
+ data->oppoint[i] = lm85_read_value(client,
+ ADT7463_REG_OPPOINT(i) );
+ }
+ data->tmin_ctl = lm85_read_value(client,
+ ADT7463_REG_TMIN_CTL1 );
+ data->therm_limit = lm85_read_value(client,
+ ADT7463_REG_THERM_LIMIT );
+ }
+ for (i = 0; i <= 2; ++i) {
+ data->temp_offset[i] = lm85_read_value(client,
+ ADM1027_REG_TEMP_OFFSET(i) );
+ }
+ data->tach_mode = lm85_read_value(client,
+ ADM1027_REG_CONFIG3 );
+ data->fan_ppr = lm85_read_value(client,
+ ADM1027_REG_FAN_PPR );
+ }
+
+ data->last_config = jiffies;
+ }; /* last_config */
+
+ data->valid = 1;
+
+ up(&data->update_lock);
+}
+
+
+static int __init sm_lm85_init(void)
+{
+ return i2c_add_driver(&lm85_driver);
+}
+
+static void __exit sm_lm85_exit(void)
+{
+ i2c_del_driver(&lm85_driver);
+}
+
+/* Thanks to Richard Barrington for adding the LM85 to sensors-detect.
+ * Thanks to Margit Schubert-While <margitsw@t-online.de> for help with
+ * post 2.7.0 CVS changes
+ */
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, Margit Schubert-While <margitsw@t-online.de>");
+MODULE_DESCRIPTION("LM85-B, LM85-C driver");
+MODULE_PARM(lm85debug, "i");
+MODULE_PARM_DESC(lm85debug, "Enable debugging statements");
+
+module_init(sm_lm85_init);
+module_exit(sm_lm85_exit);
^ permalink raw reply [flat|nested] 98+ messages in thread
* [PATCH] More i2c driver changes for 2.5.70
@ 2005-05-19 6:23 ` Philip Pokorny
0 siblings, 0 replies; 98+ messages in thread
From: Philip Pokorny @ 2005-05-19 6:23 UTC (permalink / raw)
To: Greg KH; +Cc: linux-kernel, sensors
I think there is a race condition here in the "set" functions.
I had added a down()/up() semaphore pair to the write clauses of the
functions in the pre-sysfs driver to prevent the xx_update_client() call
from modifying the cached values at the same time that the set_xxx()
function was trying to change them.
So for example:
> static ssize_t set_temp_max(struct device *dev, const char *buf,
> size_t count, int nr)
> {
> struct i2c_client *client = to_i2c_client(dev);
> struct lm85_data *data = i2c_get_clientdata(client);
>
> int val = simple_strtol(buf, NULL, 10);
> + down(&data->update_lock);
> data->temp_max[nr] = TEMP_TO_REG(val);
> lm85_write_value(client, LM85_REG_TEMP_MAX(nr),
> data->temp_max[nr]);
> + up(&data->update_lock);
> return count;
> }
Isn't that still needed?
:v)
Greg KH wrote:
> ChangeSet 1.1419.1.3, 2003/06/11 11:42:47-07:00, margitsw@t-online.de
>
> [PATCH] I2C: add LM85 driver
>
> Nothing extra in sysfs (yet) but I have left the way open in the driver
> to do this.
> Provides vid, vrm, fan_input(1-4), fan_min(1-4), pwm(1-3),
> pwm_enable(1-3), in_input(0-4), in_min(0-4), in_max(0-4),
> temp_input(1-3), temp_min(1-3), temp_max(1-3), alarms.
>
>
> drivers/i2c/chips/Kconfig | 19
> drivers/i2c/chips/Makefile | 1
> drivers/i2c/chips/lm85.c | 1223 +++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 1241 insertions(+), 2 deletions(-)
>
> +static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct lm85_data *data = i2c_get_clientdata(client);
> +
> + lm85_update_client(client);
> + return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]) );
> +}
> +static ssize_t set_temp_max(struct device *dev, const char *buf,
> + size_t count, int nr)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct lm85_data *data = i2c_get_clientdata(client);
> +
> + int val = simple_strtol(buf, NULL, 10);
> + data->temp_max[nr] = TEMP_TO_REG(val);
> + lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]);
> + return count;
> +}
--
Philip Pokorny, Director of Engineering
Tel: 415-358-2635 Fax: 415-358-2646 Toll Free: 888-PENGUIN
PENGUIN COMPUTING, INC.
www.penguincomputing.com
^ permalink raw reply [flat|nested] 98+ messages in thread
end of thread, other threads:[~2005-05-19 6:23 UTC | newest]
Thread overview: 98+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-06-11 20:35 [BK PATCH] More i2c driver changes for 2.5.70 Greg KH
2005-05-19 6:23 ` Greg KH
2003-06-11 20:36 ` [PATCH] " Greg KH
2005-05-19 6:23 ` Greg KH
2003-06-11 20:36 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-06-11 20:36 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-06-11 20:36 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-06-11 20:36 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-06-11 20:36 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-06-12 2:40 ` Philip Pokorny
2005-05-19 6:23 ` Philip Pokorny
-- strict thread matches above, loose matches on Subject: below --
2003-06-12 10:22 Margit Schubert-While
2003-06-16 18:42 ` Greg KH
2003-06-18 12:18 ` Margit Schubert-While
2003-06-18 14:22 ` Greg KH
2003-06-18 15:53 ` Margit Schubert-While
2003-06-12 9:16 Margit Schubert-While
2003-05-09 23:55 [BK PATCH] More i2c driver changes for 2.5.69 Greg KH
2005-05-19 6:23 ` Greg KH
2003-05-09 23:56 ` [PATCH] " Greg KH
2005-05-19 6:23 ` Greg KH
2003-05-09 23:56 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-05-09 23:56 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-05-09 23:56 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-05-09 23:56 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-05-09 23:56 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-04-03 0:14 [BK PATCH] More i2c driver changes for 2.5.66 Greg KH
2003-04-03 0:15 ` [PATCH] " Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 0:15 ` Greg KH
2003-04-03 6:21 ` Albert Cranford
2005-05-19 6:23 ` Albert Cranford
2003-04-03 6:33 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-04-03 13:06 ` Albert Cranford
2005-05-19 6:23 ` Albert Cranford
2003-04-03 16:37 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-22 1:04 [BK PATCH] More i2c driver changes for 2.5.65 Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-22 1:04 ` [PATCH] " Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-22 1:04 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-22 1:04 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-22 1:04 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-22 1:04 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-22 1:04 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-22 1:04 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-22 1:04 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-22 1:04 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-25 9:35 ` Pavel Machek
2005-05-19 6:23 ` Pavel Machek
2003-03-25 1:29 ` Greg KH
2005-05-19 6:23 ` Greg KH
2003-03-25 2:04 ` Dave Jones
2005-05-19 6:23 ` Dave Jones
2003-03-25 3:34 ` Greg KH
2005-05-19 6:23 ` Greg KH
2005-05-19 6:23 ` [PATCH] More i2c driver changes for 2.5.66 Albert Cranford
2005-05-19 6:23 ` Mark M. Hoffman
2005-05-19 6:23 ` Greg KH
2005-05-19 6:23 ` [PATCH] More i2c driver changes for 2.5.69 Philip Pokorny
2003-03-22 2:33 ` [PATCH] More i2c driver changes for 2.5.65 Petr Vandrovec
2005-05-19 6:23 ` Petr Vandrovec
2003-03-23 8:49 ` Greg KH
2005-05-19 6:23 ` Greg KH
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.