Commit 17e7dc43 authored by Jean Delvare's avatar Jean Delvare Committed by Mark M. Hoffman

hwmon/sis5595: Convert to a platform driver

Convert the sis5595 driver from the nonsensical i2c-isa hack to a
regular platform driver.
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 1e71a5a2
...@@ -431,8 +431,7 @@ config SENSORS_PC87427 ...@@ -431,8 +431,7 @@ config SENSORS_PC87427
config SENSORS_SIS5595 config SENSORS_SIS5595
tristate "Silicon Integrated Systems Corp. SiS5595" tristate "Silicon Integrated Systems Corp. SiS5595"
depends on I2C && PCI && EXPERIMENTAL depends on PCI
select I2C_ISA
help help
If you say yes here you get support for the integrated sensors in If you say yes here you get support for the integrated sensors in
SiS5595 South Bridges. SiS5595 South Bridges.
......
...@@ -54,8 +54,7 @@ ...@@ -54,8 +54,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/i2c.h> #include <linux/platform_device.h>
#include <linux/i2c-isa.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -72,10 +71,7 @@ module_param(force_addr, ushort, 0); ...@@ -72,10 +71,7 @@ module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr, MODULE_PARM_DESC(force_addr,
"Initialize the base address of the sensors"); "Initialize the base address of the sensors");
/* Device address static struct platform_device *pdev;
Note that we can't determine the ISA address until we have initialized
our module */
static unsigned short address;
/* Many SIS5595 constants specified below */ /* Many SIS5595 constants specified below */
...@@ -165,7 +161,8 @@ static inline u8 DIV_TO_REG(int val) ...@@ -165,7 +161,8 @@ static inline u8 DIV_TO_REG(int val)
/* For each registered chip, we need to keep some data in memory. /* For each registered chip, we need to keep some data in memory.
The structure is dynamically allocated. */ The structure is dynamically allocated. */
struct sis5595_data { struct sis5595_data {
struct i2c_client client; unsigned short addr;
const char *name;
struct class_device *class_dev; struct class_device *class_dev;
struct mutex lock; struct mutex lock;
...@@ -189,21 +186,21 @@ struct sis5595_data { ...@@ -189,21 +186,21 @@ struct sis5595_data {
static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */ static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */
static int sis5595_detect(struct i2c_adapter *adapter); static int sis5595_probe(struct platform_device *pdev);
static int sis5595_detach_client(struct i2c_client *client); static int sis5595_remove(struct platform_device *pdev);
static int sis5595_read_value(struct i2c_client *client, u8 reg); static int sis5595_read_value(struct sis5595_data *data, u8 reg);
static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value); static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value);
static struct sis5595_data *sis5595_update_device(struct device *dev); static struct sis5595_data *sis5595_update_device(struct device *dev);
static void sis5595_init_client(struct i2c_client *client); static void sis5595_init_device(struct sis5595_data *data);
static struct i2c_driver sis5595_driver = { static struct platform_driver sis5595_driver = {
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "sis5595", .name = "sis5595",
}, },
.attach_adapter = sis5595_detect, .probe = sis5595_probe,
.detach_client = sis5595_detach_client, .remove = __devexit_p(sis5595_remove),
}; };
/* 4 Voltages */ /* 4 Voltages */
...@@ -228,13 +225,12 @@ static ssize_t show_in_max(struct device *dev, char *buf, int nr) ...@@ -228,13 +225,12 @@ static ssize_t show_in_max(struct device *dev, char *buf, int nr)
static ssize_t set_in_min(struct device *dev, const char *buf, static ssize_t set_in_min(struct device *dev, const char *buf,
size_t count, int nr) size_t count, int nr)
{ {
struct i2c_client *client = to_i2c_client(dev); struct sis5595_data *data = dev_get_drvdata(dev);
struct sis5595_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
data->in_min[nr] = IN_TO_REG(val); data->in_min[nr] = IN_TO_REG(val);
sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]); sis5595_write_value(data, SIS5595_REG_IN_MIN(nr), data->in_min[nr]);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
...@@ -242,13 +238,12 @@ static ssize_t set_in_min(struct device *dev, const char *buf, ...@@ -242,13 +238,12 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
static ssize_t set_in_max(struct device *dev, const char *buf, static ssize_t set_in_max(struct device *dev, const char *buf,
size_t count, int nr) size_t count, int nr)
{ {
struct i2c_client *client = to_i2c_client(dev); struct sis5595_data *data = dev_get_drvdata(dev);
struct sis5595_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
data->in_max[nr] = IN_TO_REG(val); data->in_max[nr] = IN_TO_REG(val);
sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]); sis5595_write_value(data, SIS5595_REG_IN_MAX(nr), data->in_max[nr]);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
...@@ -307,13 +302,12 @@ static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, ...@@ -307,13 +302,12 @@ static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr,
static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{ {
struct i2c_client *client = to_i2c_client(dev); struct sis5595_data *data = dev_get_drvdata(dev);
struct sis5595_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_over = TEMP_TO_REG(val); data->temp_over = TEMP_TO_REG(val);
sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over); sis5595_write_value(data, SIS5595_REG_TEMP_OVER, data->temp_over);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
...@@ -326,13 +320,12 @@ static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, ...@@ -326,13 +320,12 @@ static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr,
static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{ {
struct i2c_client *client = to_i2c_client(dev); struct sis5595_data *data = dev_get_drvdata(dev);
struct sis5595_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10); long val = simple_strtol(buf, NULL, 10);
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
data->temp_hyst = TEMP_TO_REG(val); data->temp_hyst = TEMP_TO_REG(val);
sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst); sis5595_write_value(data, SIS5595_REG_TEMP_HYST, data->temp_hyst);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
...@@ -361,13 +354,12 @@ static ssize_t show_fan_min(struct device *dev, char *buf, int nr) ...@@ -361,13 +354,12 @@ static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
static ssize_t set_fan_min(struct device *dev, const char *buf, static ssize_t set_fan_min(struct device *dev, const char *buf,
size_t count, int nr) size_t count, int nr)
{ {
struct i2c_client *client = to_i2c_client(dev); struct sis5595_data *data = dev_get_drvdata(dev);
struct sis5595_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); sis5595_write_value(data, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
...@@ -385,8 +377,7 @@ static ssize_t show_fan_div(struct device *dev, char *buf, int nr) ...@@ -385,8 +377,7 @@ static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
static ssize_t set_fan_div(struct device *dev, const char *buf, static ssize_t set_fan_div(struct device *dev, const char *buf,
size_t count, int nr) size_t count, int nr)
{ {
struct i2c_client *client = to_i2c_client(dev); struct sis5595_data *data = dev_get_drvdata(dev);
struct sis5595_data *data = i2c_get_clientdata(client);
unsigned long min; unsigned long min;
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
int reg; int reg;
...@@ -394,7 +385,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, ...@@ -394,7 +385,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
min = FAN_FROM_REG(data->fan_min[nr], min = FAN_FROM_REG(data->fan_min[nr],
DIV_FROM_REG(data->fan_div[nr])); DIV_FROM_REG(data->fan_div[nr]));
reg = sis5595_read_value(client, SIS5595_REG_FANDIV); reg = sis5595_read_value(data, SIS5595_REG_FANDIV);
switch (val) { switch (val) {
case 1: data->fan_div[nr] = 0; break; case 1: data->fan_div[nr] = 0; break;
...@@ -402,7 +393,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, ...@@ -402,7 +393,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
case 4: data->fan_div[nr] = 2; break; case 4: data->fan_div[nr] = 2; break;
case 8: data->fan_div[nr] = 3; break; case 8: data->fan_div[nr] = 3; break;
default: default:
dev_err(&client->dev, "fan_div value %ld not " dev_err(dev, "fan_div value %ld not "
"supported. Choose one of 1, 2, 4 or 8!\n", val); "supported. Choose one of 1, 2, 4 or 8!\n", val);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
return -EINVAL; return -EINVAL;
...@@ -416,10 +407,10 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, ...@@ -416,10 +407,10 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
reg = (reg & 0x3f) | (data->fan_div[nr] << 6); reg = (reg & 0x3f) | (data->fan_div[nr] << 6);
break; break;
} }
sis5595_write_value(client, SIS5595_REG_FANDIV, reg); sis5595_write_value(data, SIS5595_REG_FANDIV, reg);
data->fan_min[nr] = data->fan_min[nr] =
FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); sis5595_write_value(data, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
...@@ -473,6 +464,14 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch ...@@ -473,6 +464,14 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
} }
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
static ssize_t show_name(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct sis5595_data *data = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", data->name);
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static struct attribute *sis5595_attributes[] = { static struct attribute *sis5595_attributes[] = {
&dev_attr_in0_input.attr, &dev_attr_in0_input.attr,
&dev_attr_in0_min.attr, &dev_attr_in0_min.attr,
...@@ -495,6 +494,7 @@ static struct attribute *sis5595_attributes[] = { ...@@ -495,6 +494,7 @@ static struct attribute *sis5595_attributes[] = {
&dev_attr_fan2_div.attr, &dev_attr_fan2_div.attr,
&dev_attr_alarms.attr, &dev_attr_alarms.attr,
&dev_attr_name.attr,
NULL NULL
}; };
...@@ -518,65 +518,32 @@ static const struct attribute_group sis5595_group_opt = { ...@@ -518,65 +518,32 @@ static const struct attribute_group sis5595_group_opt = {
}; };
/* This is called when the module is loaded */ /* This is called when the module is loaded */
static int sis5595_detect(struct i2c_adapter *adapter) static int __devinit sis5595_probe(struct platform_device *pdev)
{ {
int err = 0; int err = 0;
int i; int i;
struct i2c_client *new_client;
struct sis5595_data *data; struct sis5595_data *data;
struct resource *res;
char val; char val;
u16 a;
if (force_addr)
address = force_addr & ~(SIS5595_EXTENT - 1);
/* Reserve the ISA region */ /* Reserve the ISA region */
if (!request_region(address, SIS5595_EXTENT, res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!request_region(res->start, SIS5595_EXTENT,
sis5595_driver.driver.name)) { sis5595_driver.driver.name)) {
err = -EBUSY; err = -EBUSY;
goto exit; goto exit;
} }
if (force_addr) {
dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n", address);
if (PCIBIOS_SUCCESSFUL !=
pci_write_config_word(s_bridge, SIS5595_BASE_REG, address))
goto exit_release;
if (PCIBIOS_SUCCESSFUL !=
pci_read_config_word(s_bridge, SIS5595_BASE_REG, &a))
goto exit_release;
if ((a & ~(SIS5595_EXTENT - 1)) != address)
/* doesn't work for some chips? */
goto exit_release;
}
if (PCIBIOS_SUCCESSFUL !=
pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val)) {
goto exit_release;
}
if ((val & 0x80) == 0) {
if (PCIBIOS_SUCCESSFUL !=
pci_write_config_byte(s_bridge, SIS5595_ENABLE_REG,
val | 0x80))
goto exit_release;
if (PCIBIOS_SUCCESSFUL !=
pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val))
goto exit_release;
if ((val & 0x80) == 0)
/* doesn't work for some chips! */
goto exit_release;
}
if (!(data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL))) { if (!(data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
err = -ENOMEM; err = -ENOMEM;
goto exit_release; goto exit_release;
} }
new_client = &data->client;
new_client->addr = address;
mutex_init(&data->lock); mutex_init(&data->lock);
i2c_set_clientdata(new_client, data); mutex_init(&data->update_lock);
new_client->adapter = adapter; data->addr = res->start;
new_client->driver = &sis5595_driver; data->name = "sis5595";
new_client->flags = 0; platform_set_drvdata(pdev, data);
/* Check revision and pin registers to determine whether 4 or 5 voltages */ /* Check revision and pin registers to determine whether 4 or 5 voltages */
pci_read_config_byte(s_bridge, SIS5595_REVISION_REG, &(data->revision)); pci_read_config_byte(s_bridge, SIS5595_REVISION_REG, &(data->revision));
...@@ -589,47 +556,37 @@ static int sis5595_detect(struct i2c_adapter *adapter) ...@@ -589,47 +556,37 @@ static int sis5595_detect(struct i2c_adapter *adapter)
data->maxins = 4; data->maxins = 4;
} }
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE);
data->valid = 0;
mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/* Initialize the SIS5595 chip */ /* Initialize the SIS5595 chip */
sis5595_init_client(new_client); sis5595_init_device(data);
/* A few vars need to be filled upon startup */ /* A few vars need to be filled upon startup */
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
data->fan_min[i] = sis5595_read_value(new_client, data->fan_min[i] = sis5595_read_value(data,
SIS5595_REG_FAN_MIN(i)); SIS5595_REG_FAN_MIN(i));
} }
/* Register sysfs hooks */ /* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &sis5595_group))) if ((err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group)))
goto exit_detach; goto exit_free;
if (data->maxins == 4) { if (data->maxins == 4) {
if ((err = device_create_file(&new_client->dev, if ((err = device_create_file(&pdev->dev,
&dev_attr_in4_input)) &dev_attr_in4_input))
|| (err = device_create_file(&new_client->dev, || (err = device_create_file(&pdev->dev,
&dev_attr_in4_min)) &dev_attr_in4_min))
|| (err = device_create_file(&new_client->dev, || (err = device_create_file(&pdev->dev,
&dev_attr_in4_max))) &dev_attr_in4_max)))
goto exit_remove_files; goto exit_remove_files;
} else { } else {
if ((err = device_create_file(&new_client->dev, if ((err = device_create_file(&pdev->dev,
&dev_attr_temp1_input)) &dev_attr_temp1_input))
|| (err = device_create_file(&new_client->dev, || (err = device_create_file(&pdev->dev,
&dev_attr_temp1_max)) &dev_attr_temp1_max))
|| (err = device_create_file(&new_client->dev, || (err = device_create_file(&pdev->dev,
&dev_attr_temp1_max_hyst))) &dev_attr_temp1_max_hyst)))
goto exit_remove_files; goto exit_remove_files;
} }
data->class_dev = hwmon_device_register(&new_client->dev); data->class_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->class_dev)) { if (IS_ERR(data->class_dev)) {
err = PTR_ERR(data->class_dev); err = PTR_ERR(data->class_dev);
goto exit_remove_files; goto exit_remove_files;
...@@ -638,32 +595,26 @@ static int sis5595_detect(struct i2c_adapter *adapter) ...@@ -638,32 +595,26 @@ static int sis5595_detect(struct i2c_adapter *adapter)
return 0; return 0;
exit_remove_files: exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &sis5595_group); sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
sysfs_remove_group(&new_client->dev.kobj, &sis5595_group_opt); sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
exit_detach:
i2c_detach_client(new_client);
exit_free: exit_free:
kfree(data); kfree(data);
exit_release: exit_release:
release_region(address, SIS5595_EXTENT); release_region(res->start, SIS5595_EXTENT);
exit: exit:
return err; return err;
} }
static int sis5595_detach_client(struct i2c_client *client) static int __devexit sis5595_remove(struct platform_device *pdev)
{ {
struct sis5595_data *data = i2c_get_clientdata(client); struct sis5595_data *data = platform_get_drvdata(pdev);
int err;
hwmon_device_unregister(data->class_dev); hwmon_device_unregister(data->class_dev);
sysfs_remove_group(&client->dev.kobj, &sis5595_group); sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
sysfs_remove_group(&client->dev.kobj, &sis5595_group_opt); sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
if ((err = i2c_detach_client(client)))
return err;
release_region(client->addr, SIS5595_EXTENT);
release_region(data->addr, SIS5595_EXTENT);
platform_set_drvdata(pdev, NULL);
kfree(data); kfree(data);
return 0; return 0;
...@@ -671,41 +622,37 @@ static int sis5595_detach_client(struct i2c_client *client) ...@@ -671,41 +622,37 @@ static int sis5595_detach_client(struct i2c_client *client)
/* ISA access must be locked explicitly. */ /* ISA access must be locked explicitly. */
static int sis5595_read_value(struct i2c_client *client, u8 reg) static int sis5595_read_value(struct sis5595_data *data, u8 reg)
{ {
int res; int res;
struct sis5595_data *data = i2c_get_clientdata(client);
mutex_lock(&data->lock); mutex_lock(&data->lock);
outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); outb_p(reg, data->addr + SIS5595_ADDR_REG_OFFSET);
res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET); res = inb_p(data->addr + SIS5595_DATA_REG_OFFSET);
mutex_unlock(&data->lock); mutex_unlock(&data->lock);
return res; return res;
} }
static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value) static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value)
{ {
struct sis5595_data *data = i2c_get_clientdata(client);
mutex_lock(&data->lock); mutex_lock(&data->lock);
outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); outb_p(reg, data->addr + SIS5595_ADDR_REG_OFFSET);
outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET); outb_p(value, data->addr + SIS5595_DATA_REG_OFFSET);
mutex_unlock(&data->lock); mutex_unlock(&data->lock);
return 0;
} }
/* Called when we have found a new SIS5595. */ /* Called when we have found a new SIS5595. */
static void sis5595_init_client(struct i2c_client *client) static void __devinit sis5595_init_device(struct sis5595_data *data)
{ {
u8 config = sis5595_read_value(client, SIS5595_REG_CONFIG); u8 config = sis5595_read_value(data, SIS5595_REG_CONFIG);
if (!(config & 0x01)) if (!(config & 0x01))
sis5595_write_value(client, SIS5595_REG_CONFIG, sis5595_write_value(data, SIS5595_REG_CONFIG,
(config & 0xf7) | 0x01); (config & 0xf7) | 0x01);
} }
static struct sis5595_data *sis5595_update_device(struct device *dev) static struct sis5595_data *sis5595_update_device(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct sis5595_data *data = dev_get_drvdata(dev);
struct sis5595_data *data = i2c_get_clientdata(client);
int i; int i;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
...@@ -715,35 +662,35 @@ static struct sis5595_data *sis5595_update_device(struct device *dev) ...@@ -715,35 +662,35 @@ static struct sis5595_data *sis5595_update_device(struct device *dev)
for (i = 0; i <= data->maxins; i++) { for (i = 0; i <= data->maxins; i++) {
data->in[i] = data->in[i] =
sis5595_read_value(client, SIS5595_REG_IN(i)); sis5595_read_value(data, SIS5595_REG_IN(i));
data->in_min[i] = data->in_min[i] =
sis5595_read_value(client, sis5595_read_value(data,
SIS5595_REG_IN_MIN(i)); SIS5595_REG_IN_MIN(i));
data->in_max[i] = data->in_max[i] =
sis5595_read_value(client, sis5595_read_value(data,
SIS5595_REG_IN_MAX(i)); SIS5595_REG_IN_MAX(i));
} }
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
data->fan[i] = data->fan[i] =
sis5595_read_value(client, SIS5595_REG_FAN(i)); sis5595_read_value(data, SIS5595_REG_FAN(i));
data->fan_min[i] = data->fan_min[i] =
sis5595_read_value(client, sis5595_read_value(data,
SIS5595_REG_FAN_MIN(i)); SIS5595_REG_FAN_MIN(i));
} }
if (data->maxins == 3) { if (data->maxins == 3) {
data->temp = data->temp =
sis5595_read_value(client, SIS5595_REG_TEMP); sis5595_read_value(data, SIS5595_REG_TEMP);
data->temp_over = data->temp_over =
sis5595_read_value(client, SIS5595_REG_TEMP_OVER); sis5595_read_value(data, SIS5595_REG_TEMP_OVER);
data->temp_hyst = data->temp_hyst =
sis5595_read_value(client, SIS5595_REG_TEMP_HYST); sis5595_read_value(data, SIS5595_REG_TEMP_HYST);
} }
i = sis5595_read_value(client, SIS5595_REG_FANDIV); i = sis5595_read_value(data, SIS5595_REG_FANDIV);
data->fan_div[0] = (i >> 4) & 0x03; data->fan_div[0] = (i >> 4) & 0x03;
data->fan_div[1] = i >> 6; data->fan_div[1] = i >> 6;
data->alarms = data->alarms =
sis5595_read_value(client, SIS5595_REG_ALARM1) | sis5595_read_value(data, SIS5595_REG_ALARM1) |
(sis5595_read_value(client, SIS5595_REG_ALARM2) << 8); (sis5595_read_value(data, SIS5595_REG_ALARM2) << 8);
data->last_updated = jiffies; data->last_updated = jiffies;
data->valid = 1; data->valid = 1;
} }
...@@ -774,10 +721,50 @@ static int blacklist[] __devinitdata = { ...@@ -774,10 +721,50 @@ static int blacklist[] __devinitdata = {
PCI_DEVICE_ID_SI_5598, PCI_DEVICE_ID_SI_5598,
0 }; 0 };
static int __devinit sis5595_device_add(unsigned short address)
{
struct resource res = {
.start = address,
.end = address + SIS5595_EXTENT - 1,
.name = "sis5595",
.flags = IORESOURCE_IO,
};
int err;
pdev = platform_device_alloc("sis5595", address);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR "sis5595: Device allocation failed\n");
goto exit;
}
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR "sis5595: Device resource addition failed "
"(%d)\n", err);
goto exit_device_put;
}
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR "sis5595: Device addition failed (%d)\n",
err);
goto exit_device_put;
}
return 0;
exit_device_put:
platform_device_put(pdev);
exit:
return err;
}
static int __devinit sis5595_pci_probe(struct pci_dev *dev, static int __devinit sis5595_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
u16 val; u16 address;
u8 enable;
int *i; int *i;
for (i = blacklist; *i != 0; i++) { for (i = blacklist; *i != 0; i++) {
...@@ -790,27 +777,68 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev, ...@@ -790,27 +777,68 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
} }
} }
force_addr &= ~(SIS5595_EXTENT - 1);
if (force_addr) {
dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", force_addr);
pci_write_config_word(dev, SIS5595_BASE_REG, force_addr);
}
if (PCIBIOS_SUCCESSFUL != if (PCIBIOS_SUCCESSFUL !=
pci_read_config_word(dev, SIS5595_BASE_REG, &val)) pci_read_config_word(dev, SIS5595_BASE_REG, &address)) {
dev_err(&dev->dev, "Failed to read ISA address\n");
return -ENODEV; return -ENODEV;
}
address = val & ~(SIS5595_EXTENT - 1); address &= ~(SIS5595_EXTENT - 1);
if (address == 0 && force_addr == 0) { if (!address) {
dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n"); dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
return -ENODEV; return -ENODEV;
} }
if (force_addr && address != force_addr) {
/* doesn't work for some chips? */
dev_err(&dev->dev, "Failed to force ISA address\n");
return -ENODEV;
}
s_bridge = pci_dev_get(dev); if (PCIBIOS_SUCCESSFUL !=
if (i2c_isa_add_driver(&sis5595_driver)) { pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) {
pci_dev_put(s_bridge); dev_err(&dev->dev, "Failed to read enable register\n");
s_bridge = NULL; return -ENODEV;
}
if (!(enable & 0x80)) {
if ((PCIBIOS_SUCCESSFUL !=
pci_write_config_byte(dev, SIS5595_ENABLE_REG,
enable | 0x80))
|| (PCIBIOS_SUCCESSFUL !=
pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable))
|| (!(enable & 0x80))) {
/* doesn't work for some chips! */
dev_err(&dev->dev, "Failed to enable HWM device\n");
return -ENODEV;
}
} }
if (platform_driver_register(&sis5595_driver)) {
dev_dbg(&dev->dev, "Failed to register sis5595 driver\n");
goto exit;
}
s_bridge = pci_dev_get(dev);
/* Sets global pdev as a side effect */
if (sis5595_device_add(address))
goto exit_unregister;
/* Always return failure here. This is to allow other drivers to bind /* Always return failure here. This is to allow other drivers to bind
* to this pci device. We don't really want to have control over the * to this pci device. We don't really want to have control over the
* pci device, we only wanted to read as few register values from it. * pci device, we only wanted to read as few register values from it.
*/ */
return -ENODEV; return -ENODEV;
exit_unregister:
pci_dev_put(dev);
platform_driver_unregister(&sis5595_driver);
exit:
return -ENODEV;
} }
static struct pci_driver sis5595_pci_driver = { static struct pci_driver sis5595_pci_driver = {
...@@ -828,7 +856,8 @@ static void __exit sm_sis5595_exit(void) ...@@ -828,7 +856,8 @@ static void __exit sm_sis5595_exit(void)
{ {
pci_unregister_driver(&sis5595_pci_driver); pci_unregister_driver(&sis5595_pci_driver);
if (s_bridge != NULL) { if (s_bridge != NULL) {
i2c_isa_del_driver(&sis5595_driver); platform_device_unregister(pdev);
platform_driver_unregister(&sis5595_driver);
pci_dev_put(s_bridge); pci_dev_put(s_bridge);
s_bridge = NULL; s_bridge = NULL;
} }
......
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