Commit 37581a1c authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.5

into kroah.com:/home/greg/linux/BK/i2c-2.5
parents 797886bf 7eaa539b
...@@ -196,17 +196,6 @@ config I2C_CHARDEV ...@@ -196,17 +196,6 @@ config I2C_CHARDEV
<file:Documentation/modules.txt>. <file:Documentation/modules.txt>.
The module will be called i2c-dev. 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/busses/Kconfig
source drivers/i2c/chips/Kconfig source drivers/i2c/chips/Kconfig
......
...@@ -14,5 +14,5 @@ obj-$(CONFIG_ITE_I2C_ALGO) += i2c-algo-ite.o ...@@ -14,5 +14,5 @@ obj-$(CONFIG_ITE_I2C_ALGO) += i2c-algo-ite.o
obj-$(CONFIG_ITE_I2C_ADAP) += i2c-adap-ite.o obj-$(CONFIG_ITE_I2C_ADAP) += i2c-adap-ite.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.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/ obj-y += busses/ chips/
# #
# Sensor device configuration # Sensor device configuration
# All depend on EXPERIMENTAL, I2C and I2C_PROC. # All depend on EXPERIMENTAL and I2C
# #
menu "I2C Hardware Sensors Chip support" menu "I2C Hardware Sensors Chip support"
config SENSORS_ADM1021 config SENSORS_ADM1021
tristate " Analog Devices ADM1021 and compatibles" tristate " Analog Devices ADM1021 and compatibles"
depends on I2C && I2C_PROC depends on I2C && EXPERIMENTAL
help help
If you say yes here you get support for Analog Devices ADM1021 If you say yes here you get support for Analog Devices ADM1021
and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A, and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
...@@ -24,7 +24,7 @@ config SENSORS_ADM1021 ...@@ -24,7 +24,7 @@ config SENSORS_ADM1021
config SENSORS_LM75 config SENSORS_LM75
tristate " National Semiconductors LM75 and compatibles" tristate " National Semiconductors LM75 and compatibles"
depends on I2C && I2C_PROC depends on I2C && EXPERIMENTAL
help help
If you say yes here you get support for National Semiconductor LM75 If you say yes here you get support for National Semiconductor LM75
sensor chips and clones: Dallas Semi DS75 and DS1775, TelCon sensor chips and clones: Dallas Semi DS75 and DS1775, TelCon
...@@ -37,4 +37,36 @@ config SENSORS_LM75 ...@@ -37,4 +37,36 @@ config SENSORS_LM75
in the lm_sensors package, which you can download at in the lm_sensors package, which you can download at
http://www.lm-sensors.nu http://www.lm-sensors.nu
config SENSORS_VIA686A
tristate " VIA686A"
depends on I2C && EXPERIMENTAL
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
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 || SENSORS_W83781D
default m
endmenu endmenu
...@@ -4,3 +4,5 @@ ...@@ -4,3 +4,5 @@
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o obj-$(CONFIG_SENSORS_LM75) += lm75.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
This diff is collapsed.
...@@ -18,14 +18,14 @@ ...@@ -18,14 +18,14 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* #define DEBUG 1 */
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-proc.h> #include <linux/i2c-sensor.h>
#define LM75_SYSCTL_TEMP 1200 /* Degrees Celsius * 10 */
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { SENSORS_I2C_END }; static unsigned short normal_i2c[] = { SENSORS_I2C_END };
...@@ -57,79 +57,95 @@ SENSORS_INSMOD_1(lm75); ...@@ -57,79 +57,95 @@ SENSORS_INSMOD_1(lm75);
/* Each client has this additional data */ /* Each client has this additional data */
struct lm75_data { struct lm75_data {
int sysctl_id;
struct semaphore update_lock; struct semaphore update_lock;
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
u16 temp_input; /* Register values */
u16 temp, temp_os, temp_hyst; /* Register values */ u16 temp_max;
u16 temp_hyst;
}; };
static int lm75_attach_adapter(struct i2c_adapter *adapter); static int lm75_attach_adapter(struct i2c_adapter *adapter);
static int lm75_detect(struct i2c_adapter *adapter, int address, static int lm75_detect(struct i2c_adapter *adapter, int address, int kind);
unsigned short flags, int kind);
static void lm75_init_client(struct i2c_client *client); static void lm75_init_client(struct i2c_client *client);
static int lm75_detach_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_read_value(struct i2c_client *client, u8 reg);
static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value); 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); static void lm75_update_client(struct i2c_client *client);
/* This is the driver that will be inserted */ /* This is the driver that will be inserted */
static struct i2c_driver lm75_driver = { static struct i2c_driver lm75_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "LM75 sensor", .name = "lm75",
.id = I2C_DRIVERID_LM75, .id = I2C_DRIVERID_LM75,
.flags = I2C_DF_NOTIFY, .flags = I2C_DF_NOTIFY,
.attach_adapter = lm75_attach_adapter, .attach_adapter = lm75_attach_adapter,
.detach_client = lm75_detach_client, .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; 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) static int lm75_attach_adapter(struct i2c_adapter *adapter)
{ {
return i2c_detect(adapter, &addr_data, lm75_detect); return i2c_detect(adapter, &addr_data, lm75_detect);
} }
/* This function is called by i2c_detect */ /* This function is called by i2c_detect */
static int lm75_detect(struct i2c_adapter *adapter, int address, static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
unsigned short flags, int kind)
{ {
int i, cur, conf, hyst, os; int i, cur, conf, hyst, os;
struct i2c_client *new_client; struct i2c_client *new_client;
struct lm75_data *data; struct lm75_data *data;
int err = 0; 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 /* 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. */ at this moment; i2c_detect really won't call us. */
#ifdef DEBUG #ifdef DEBUG
if (i2c_is_isa_adapter(adapter)) { if (i2c_is_isa_adapter(adapter)) {
printk dev_dbg(&adapter->dev,
("lm75.o: lm75_detect called for an ISA bus adapter?!?\n"); "lm75_detect called for an ISA bus adapter?!?\n");
return 0; goto exit;
} }
#endif #endif
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA))
goto error0; goto exit;
/* OK. For now, we presume we have a valid client. We now create the /* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. client structure, even though we cannot fill it completely yet.
...@@ -138,7 +154,7 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, ...@@ -138,7 +154,7 @@ static int lm75_detect(struct i2c_adapter *adapter, int address,
sizeof(struct lm75_data), sizeof(struct lm75_data),
GFP_KERNEL))) { GFP_KERNEL))) {
err = -ENOMEM; err = -ENOMEM;
goto error0; goto exit;
} }
memset(new_client, 0x00, sizeof(struct i2c_client) + memset(new_client, 0x00, sizeof(struct i2c_client) +
sizeof(struct lm75_data)); sizeof(struct lm75_data));
...@@ -157,16 +173,10 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, ...@@ -157,16 +173,10 @@ static int lm75_detect(struct i2c_adapter *adapter, int address,
hyst = i2c_smbus_read_word_data(new_client, 2); hyst = i2c_smbus_read_word_data(new_client, 2);
os = i2c_smbus_read_word_data(new_client, 3); os = i2c_smbus_read_word_data(new_client, 3);
for (i = 0; i <= 0x1f; i++) for (i = 0; i <= 0x1f; i++)
if ( if ((i2c_smbus_read_byte_data(new_client, i * 8 + 1) != conf) ||
(i2c_smbus_read_byte_data (i2c_smbus_read_word_data(new_client, i * 8 + 2) != hyst) ||
(new_client, i * 8 + 1) != conf) (i2c_smbus_read_word_data(new_client, i * 8 + 3) != os))
|| goto exit_free;
(i2c_smbus_read_word_data
(new_client, i * 8 + 2) != hyst)
||
(i2c_smbus_read_word_data
(new_client, i * 8 + 3) != os))
goto error1;
} }
/* Determine the chip type - only one kind supported! */ /* Determine the chip type - only one kind supported! */
...@@ -174,15 +184,15 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, ...@@ -174,15 +184,15 @@ static int lm75_detect(struct i2c_adapter *adapter, int address,
kind = lm75; kind = lm75;
if (kind == lm75) { if (kind == lm75) {
type_name = "lm75"; name = "lm75";
client_name = "LM75 chip";
} else { } else {
pr_debug("lm75.o: Internal error: unknown kind (%d)?!?", kind); dev_dbg(&adapter->dev, "Internal error: unknown kind (%d)?!?",
goto error1; kind);
goto exit_free;
} }
/* Fill in the remaining client fields and put it into the global list */ /* 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++; new_client->id = lm75_id++;
data->valid = 0; data->valid = 0;
...@@ -190,36 +200,23 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, ...@@ -190,36 +200,23 @@ static int lm75_detect(struct i2c_adapter *adapter, int address,
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
goto error3; goto exit_free;
/* Register a new directory entry with module sensors */ device_create_file(&new_client->dev, &dev_attr_temp_max);
i = i2c_register_entry(new_client, type_name, lm75_dir_table_template); device_create_file(&new_client->dev, &dev_attr_temp_min);
if (i < 0) { device_create_file(&new_client->dev, &dev_attr_temp_input);
err = i;
goto error4;
}
data->sysctl_id = i;
lm75_init_client(new_client); lm75_init_client(new_client);
return 0; return 0;
/* OK, this is not exactly good programming practice, usually. But it is exit_free:
very code-efficient in this case. */
error4:
i2c_detach_client(new_client);
error3:
error1:
kfree(new_client); kfree(new_client);
error0: exit:
return err; return err;
} }
static int lm75_detach_client(struct i2c_client *client) 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); i2c_detach_client(client);
kfree(client); kfree(client);
return 0; return 0;
...@@ -271,12 +268,11 @@ static void lm75_update_client(struct i2c_client *client) ...@@ -271,12 +268,11 @@ static void lm75_update_client(struct i2c_client *client)
if ((jiffies - data->last_updated > HZ + HZ / 2) || if ((jiffies - data->last_updated > HZ + HZ / 2) ||
(jiffies < data->last_updated) || !data->valid) { (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_input = lm75_read_value(client, LM75_REG_TEMP);
data->temp_os = lm75_read_value(client, LM75_REG_TEMP_OS); data->temp_max = lm75_read_value(client, LM75_REG_TEMP_OS);
data->temp_hyst = data->temp_hyst = lm75_read_value(client, LM75_REG_TEMP_HYST);
lm75_read_value(client, LM75_REG_TEMP_HYST);
data->last_updated = jiffies; data->last_updated = jiffies;
data->valid = 1; data->valid = 1;
} }
...@@ -284,33 +280,6 @@ static void lm75_update_client(struct i2c_client *client) ...@@ -284,33 +280,6 @@ static void lm75_update_client(struct i2c_client *client)
up(&data->update_lock); 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) static int __init sensors_lm75_init(void)
{ {
return i2c_add_driver(&lm75_driver); return i2c_add_driver(&lm75_driver);
......
This diff is collapsed.
This diff is collapsed.
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
...@@ -46,15 +45,6 @@ static DECLARE_MUTEX(core_lists); ...@@ -46,15 +45,6 @@ static DECLARE_MUTEX(core_lists);
/**** debug level */ /**** debug level */
static int i2c_debug; 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) int i2c_device_probe(struct device *dev)
{ {
return -ENODEV; return -ENODEV;
...@@ -98,10 +88,6 @@ int i2c_add_adapter(struct i2c_adapter *adap) ...@@ -98,10 +88,6 @@ int i2c_add_adapter(struct i2c_adapter *adap)
goto out_unlock; goto out_unlock;
} }
res = i2cproc_register(adap, i);
if (res)
goto out_unlock;
adapters[i] = adap; adapters[i] = adap;
init_MUTEX(&adap->bus); init_MUTEX(&adap->bus);
...@@ -180,8 +166,6 @@ int i2c_del_adapter(struct i2c_adapter *adap) ...@@ -180,8 +166,6 @@ int i2c_del_adapter(struct i2c_adapter *adap)
} }
} }
i2cproc_remove(i);
/* clean up the sysfs representation */ /* clean up the sysfs representation */
device_unregister(&adap->dev); device_unregister(&adap->dev);
...@@ -392,7 +376,8 @@ int i2c_attach_client(struct i2c_client *client) ...@@ -392,7 +376,8 @@ int i2c_attach_client(struct i2c_client *client)
client->dev.driver = &client->driver->driver; client->dev.driver = &client->driver->driver;
client->dev.bus = &i2c_bus_type; 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); printk("registering %s\n", client->dev.bus_id);
device_register(&client->dev); device_register(&client->dev);
...@@ -494,173 +479,6 @@ int i2c_release_client(struct i2c_client *client) ...@@ -494,173 +479,6 @@ int i2c_release_client(struct i2c_client *client)
return 0; 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 */ /* 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) static int i2c_device_match(struct device *dev, struct device_driver *drv)
{ {
...@@ -675,13 +493,11 @@ struct bus_type i2c_bus_type = { ...@@ -675,13 +493,11 @@ struct bus_type i2c_bus_type = {
static int __init i2c_init(void) static int __init i2c_init(void)
{ {
bus_register(&i2c_bus_type); return bus_register(&i2c_bus_type);
return i2cproc_init();
} }
static void __exit i2c_exit(void) static void __exit i2c_exit(void)
{ {
i2cproc_cleanup();
bus_unregister(&i2c_bus_type); bus_unregister(&i2c_bus_type);
} }
......
This diff is collapsed.
/*
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);
...@@ -231,7 +231,7 @@ int adv717x_probe(struct i2c_adapter *adap) ...@@ -231,7 +231,7 @@ int adv717x_probe(struct i2c_adapter *adap)
static int adv717x_detach(struct i2c_client *client) static int adv717x_detach(struct i2c_client *client)
{ {
i2c_detach_client(client); i2c_detach_client(client);
i2c_get_clientdata(client); kfree(i2c_get_clientdata(client));
kfree(client); kfree(client);
return 0; return 0;
} }
......
...@@ -87,7 +87,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm ...@@ -87,7 +87,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm
if (cmd == SOUND_MIXER_INFO) { if (cmd == SOUND_MIXER_INFO) {
mixer_info info; mixer_info info;
strncpy(info.id, "tv card", sizeof(info.id)); 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 */; info.modify_counter = 42 /* FIXME */;
if (copy_to_user((void *)arg, &info, sizeof(info))) if (copy_to_user((void *)arg, &info, sizeof(info)))
return -EFAULT; return -EFAULT;
...@@ -96,7 +96,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm ...@@ -96,7 +96,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm
if (cmd == SOUND_OLD_MIXER_INFO) { if (cmd == SOUND_OLD_MIXER_INFO) {
_old_mixer_info info; _old_mixer_info info;
strncpy(info.id, "tv card", sizeof(info.id)); 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))) if (copy_to_user((void *)arg, &info, sizeof(info)))
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -237,7 +237,7 @@ static int tvmixer_adapters(struct i2c_adapter *adap) ...@@ -237,7 +237,7 @@ static int tvmixer_adapters(struct i2c_adapter *adap)
int i; int i;
if (debug) 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++) { for (i=0; i<I2C_CLIENT_MAX; i++) {
if (!adap->clients[i]) if (!adap->clients[i])
continue; continue;
...@@ -261,10 +261,10 @@ static int tvmixer_clients(struct i2c_client *client) ...@@ -261,10 +261,10 @@ static int tvmixer_clients(struct i2c_client *client)
/* ignore that one */ /* ignore that one */
if (debug) if (debug)
printk("tvmixer: %s is not a tv card\n", printk("tvmixer: %s is not a tv card\n",
client->adapter->name); client->adapter->dev.name);
return -1; return -1;
} }
printk("tvmixer: debug: %s\n",client->name); printk("tvmixer: debug: %s\n",client->dev.name);
/* unregister ?? */ /* unregister ?? */
for (i = 0; i < DEV_MAX; i++) { for (i = 0; i < DEV_MAX; i++) {
...@@ -273,7 +273,7 @@ static int tvmixer_clients(struct i2c_client *client) ...@@ -273,7 +273,7 @@ static int tvmixer_clients(struct i2c_client *client)
unregister_sound_mixer(devices[i].minor); unregister_sound_mixer(devices[i].minor);
devices[i].dev = NULL; devices[i].dev = NULL;
devices[i].minor = -1; devices[i].minor = -1;
printk("tvmixer: %s unregistered (#1)\n",client->name); printk("tvmixer: %s unregistered (#1)\n",client->dev.name);
return 0; return 0;
} }
} }
...@@ -298,13 +298,13 @@ static int tvmixer_clients(struct i2c_client *client) ...@@ -298,13 +298,13 @@ static int tvmixer_clients(struct i2c_client *client)
if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) { if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) {
if (debug) if (debug)
printk("tvmixer: %s: VIDIOCGAUDIO failed\n", printk("tvmixer: %s: VIDIOCGAUDIO failed\n",
client->name); client->dev.name);
return -1; return -1;
} }
if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) { if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) {
if (debug) if (debug)
printk("tvmixer: %s: has no volume control\n", printk("tvmixer: %s: has no volume control\n",
client->name); client->dev.name);
return -1; return -1;
} }
...@@ -318,7 +318,7 @@ static int tvmixer_clients(struct i2c_client *client) ...@@ -318,7 +318,7 @@ static int tvmixer_clients(struct i2c_client *client)
devices[i].count = 0; devices[i].count = 0;
devices[i].dev = client; devices[i].dev = client;
printk("tvmixer: %s (%s) registered with minor %d\n", 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; return 0;
} }
...@@ -344,7 +344,7 @@ static void tvmixer_cleanup_module(void) ...@@ -344,7 +344,7 @@ static void tvmixer_cleanup_module(void)
if (devices[i].minor != -1) { if (devices[i].minor != -1) {
unregister_sound_mixer(devices[i].minor); unregister_sound_mixer(devices[i].minor);
printk("tvmixer: %s unregistered (#2)\n", printk("tvmixer: %s unregistered (#2)\n",
devices[i].dev->name); devices[i].dev->dev.name);
} }
} }
} }
......
/* /*
i2c-proc.h - Part of the i2c package i2c-sensor.h - Part of the i2c package
was originally sensors.h - Part of lm_sensors, Linux kernel modules was originally sensors.h - Part of lm_sensors, Linux kernel modules
for hardware monitoring for hardware monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#ifndef _LINUX_I2C_PROC_H #ifndef _LINUX_I2C_SENSOR_H
#define _LINUX_I2C_PROC_H #define _LINUX_I2C_SENSOR_H
#include <linux/sysctl.h> #include <linux/sysctl.h>
...@@ -34,46 +34,6 @@ typedef void (*i2c_real_callback) (struct i2c_client * client, ...@@ -34,46 +34,6 @@ typedef void (*i2c_real_callback) (struct i2c_client * client,
#define SENSORS_PROC_REAL_READ 2 #define SENSORS_PROC_REAL_READ 2
#define SENSORS_PROC_REAL_WRITE 3 #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. /* A structure containing detect information.
Force variables overrule all other variables; they force a detection on Force variables overrule all other variables; they force a detection on
that place. If a specific chip is given, the module blindly assumes this that place. If a specific chip is given, the module blindly assumes this
...@@ -368,8 +328,7 @@ struct i2c_address_data { ...@@ -368,8 +328,7 @@ struct i2c_address_data {
SENSORS_INSMOD SENSORS_INSMOD
typedef int i2c_found_addr_proc(struct i2c_adapter *adapter, typedef int i2c_found_addr_proc(struct i2c_adapter *adapter,
int addr, unsigned short flags, int addr, int kind);
int kind);
/* Detect function. It iterates over all possible addresses itself. For /* Detect function. It iterates over all possible addresses itself. For
SMBus addresses, it will only call found_proc if some client is connected SMBus addresses, it will only call found_proc if some client is connected
...@@ -410,5 +369,5 @@ struct i2c_chips_data { ...@@ -410,5 +369,5 @@ struct i2c_chips_data {
char name[SENSORS_PREFIX_MAX + 13]; char name[SENSORS_PREFIX_MAX + 13];
}; };
#endif /* def _LINUX_I2C_PROC_H */ #endif /* def _LINUX_I2C_SENSOR_H */
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment