#include <linux/ioport.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
#include <linux/hwmon.h>
#include <linux/err.h>
#include <linux/init.h>
+#include <linux/mutex.h>
#include <asm/io.h>
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Address is autodetected, there is no default value */
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{NULL}};
-
-enum chips { any_chip, smsc47b397 };
-static struct i2c_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .normal_isa = normal_isa,
- .probe = normal_i2c, /* cheat */
- .ignore = normal_i2c, /* cheat */
- .forces = forces,
-};
+static unsigned short address;
/* Super-I/0 registers and commands */
struct smsc47b397_data {
struct i2c_client client;
struct class_device *class_dev;
- struct semaphore lock;
+ struct mutex lock;
- struct semaphore update_lock;
+ struct mutex update_lock;
unsigned long last_updated; /* in jiffies */
int valid;
struct smsc47b397_data *data = i2c_get_clientdata(client);
int res;
- down(&data->lock);
+ mutex_lock(&data->lock);
outb(reg, client->addr);
res = inb_p(client->addr + 1);
- up(&data->lock);
+ mutex_unlock(&data->lock);
return res;
}
struct smsc47b397_data *data = i2c_get_clientdata(client);
int i;
- down(&data->update_lock);
+ mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
dev_dbg(&client->dev, "starting device update...\n");
dev_dbg(&client->dev, "... device update complete\n");
}
- up(&data->update_lock);
+ mutex_unlock(&data->update_lock);
return data;
}
#define device_create_file_fan(client, num) \
device_create_file(&client->dev, &dev_attr_fan##num##_input)
-static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind);
-
-static int smsc47b397_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_detect(adapter, &addr_data, smsc47b397_detect);
-}
-
static int smsc47b397_detach_client(struct i2c_client *client)
{
struct smsc47b397_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->class_dev);
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev, "Client deregistration failed, "
- "client not detached.\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
release_region(client->addr, SMSC_EXTENT);
kfree(data);
return 0;
}
+static int smsc47b397_detect(struct i2c_adapter *adapter);
+
static struct i2c_driver smsc47b397_driver = {
- .owner = THIS_MODULE,
- .name = "smsc47b397",
- .id = I2C_DRIVERID_SMSC47B397,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = smsc47b397_attach_adapter,
+ .driver = {
+ .name = "smsc47b397",
+ },
+ .attach_adapter = smsc47b397_detect,
.detach_client = smsc47b397_detach_client,
};
-static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int smsc47b397_detect(struct i2c_adapter *adapter)
{
struct i2c_client *new_client;
struct smsc47b397_data *data;
int err = 0;
- if (!i2c_is_isa_adapter(adapter)) {
- return 0;
- }
-
- if (!request_region(addr, SMSC_EXTENT, smsc47b397_driver.name)) {
- dev_err(&adapter->dev, "Region 0x%x already in use!\n", addr);
+ if (!request_region(address, SMSC_EXTENT,
+ smsc47b397_driver.driver.name)) {
+ dev_err(&adapter->dev, "Region 0x%x already in use!\n",
+ address);
return -EBUSY;
}
- if (!(data = kmalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
err = -ENOMEM;
goto error_release;
}
- memset(data, 0x00, sizeof(struct smsc47b397_data));
new_client = &data->client;
i2c_set_clientdata(new_client, data);
- new_client->addr = addr;
- init_MUTEX(&data->lock);
+ new_client->addr = address;
+ mutex_init(&data->lock);
new_client->adapter = adapter;
new_client->driver = &smsc47b397_driver;
new_client->flags = 0;
strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE);
- init_MUTEX(&data->update_lock);
+ mutex_init(&data->update_lock);
if ((err = i2c_attach_client(new_client)))
goto error_free;
error_free:
kfree(data);
error_release:
- release_region(addr, SMSC_EXTENT);
+ release_region(address, SMSC_EXTENT);
return err;
}
-static int __init smsc47b397_find(unsigned int *addr)
+static int __init smsc47b397_find(unsigned short *addr)
{
u8 id, rev;
superio_enter();
id = superio_inb(SUPERIO_REG_DEVID);
- if (id != 0x6f) {
+ if ((id != 0x6f) && (id != 0x81)) {
superio_exit();
return -ENODEV;
}
*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
| superio_inb(SUPERIO_REG_BASE_LSB);
- printk(KERN_INFO "smsc47b397: found SMSC LPC47B397-NC "
- "(base address 0x%04x, revision %u)\n", *addr, rev);
+ printk(KERN_INFO "smsc47b397: found SMSC %s "
+ "(base address 0x%04x, revision %u)\n",
+ id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev);
superio_exit();
return 0;
{
int ret;
- if ((ret = smsc47b397_find(normal_isa)))
+ if ((ret = smsc47b397_find(&address)))
return ret;
- return i2c_add_driver(&smsc47b397_driver);
+ return i2c_isa_add_driver(&smsc47b397_driver);
}
static void __exit smsc47b397_exit(void)
{
- i2c_del_driver(&smsc47b397_driver);
+ i2c_isa_del_driver(&smsc47b397_driver);
}
MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");