diff options
Diffstat (limited to 'drivers/hwmon/max6650.c')
| -rw-r--r-- | drivers/hwmon/max6650.c | 563 |
1 files changed, 286 insertions, 277 deletions
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index 52d528b76cc..162a520f4bd 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c @@ -2,7 +2,7 @@ * max6650.c - Part of lm_sensors, Linux kernel modules for hardware * monitoring. * - * (C) 2007 by Hans J. Koch <hjk@linutronix.de> + * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de> * * based on code written by John Morris <john.morris@spirentcom.com> * Copyright (c) 2003 Spirent Communications @@ -12,7 +12,7 @@ * also work with the MAX6651. It does not distinguish max6650 and max6651 * chips. * - * Tha datasheet was last seen at: + * The datasheet was last seen at: * * http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf * @@ -41,13 +41,6 @@ #include <linux/err.h> /* - * Addresses to scan. There are four disjoint possibilities, by pin config. - */ - -static const unsigned short normal_i2c[] = {0x1b, 0x1f, 0x48, 0x4b, - I2C_CLIENT_END}; - -/* * Insmod parameters */ @@ -62,8 +55,6 @@ module_param(fan_voltage, int, S_IRUGO); module_param(prescaler, int, S_IRUGO); module_param(clock, int, S_IRUGO); -I2C_CLIENT_INSMOD_1(max6650); - /* * MAX 6650/6651 registers */ @@ -98,39 +89,31 @@ I2C_CLIENT_INSMOD_1(max6650); #define MAX6650_CFG_MODE_OPEN_LOOP 0x30 #define MAX6650_COUNT_MASK 0x03 +/* + * Alarm status register bits + */ + +#define MAX6650_ALRM_MAX 0x01 +#define MAX6650_ALRM_MIN 0x02 +#define MAX6650_ALRM_TACH 0x04 +#define MAX6650_ALRM_GPIO1 0x08 +#define MAX6650_ALRM_GPIO2 0x10 + /* Minimum and maximum values of the FAN-RPM */ #define FAN_RPM_MIN 240 #define FAN_RPM_MAX 30000 #define DIV_FROM_REG(reg) (1 << (reg & 7)) -static int max6650_attach_adapter(struct i2c_adapter *adapter); -static int max6650_detect(struct i2c_adapter *adapter, int address, int kind); -static int max6650_init_client(struct i2c_client *client); -static int max6650_detach_client(struct i2c_client *client); -static struct max6650_data *max6650_update_device(struct device *dev); - -/* - * Driver data (common to all clients) - */ - -static struct i2c_driver max6650_driver = { - .driver = { - .name = "max6650", - }, - .attach_adapter = max6650_attach_adapter, - .detach_client = max6650_detach_client, -}; - /* * Client data (each client gets its own) */ -struct max6650_data -{ - struct i2c_client client; - struct device *hwmon_dev; +struct max6650_data { + struct i2c_client *client; + const struct attribute_group *groups[3]; struct mutex update_lock; + int nr_fans; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -140,8 +123,54 @@ struct max6650_data u8 tach[4]; u8 count; u8 dac; + u8 alarm; +}; + +static const u8 tach_reg[] = { + MAX6650_REG_TACH0, + MAX6650_REG_TACH1, + MAX6650_REG_TACH2, + MAX6650_REG_TACH3, }; +static struct max6650_data *max6650_update_device(struct device *dev) +{ + struct max6650_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + data->speed = i2c_smbus_read_byte_data(client, + MAX6650_REG_SPEED); + data->config = i2c_smbus_read_byte_data(client, + MAX6650_REG_CONFIG); + for (i = 0; i < data->nr_fans; i++) { + data->tach[i] = i2c_smbus_read_byte_data(client, + tach_reg[i]); + } + data->count = i2c_smbus_read_byte_data(client, + MAX6650_REG_COUNT); + data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC); + + /* + * Alarms are cleared on read in case the condition that + * caused the alarm is removed. Keep the value latched here + * for providing the register through different alarm files. + */ + data->alarm |= i2c_smbus_read_byte_data(client, + MAX6650_REG_ALARM); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + static ssize_t get_fan(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -150,13 +179,13 @@ static ssize_t get_fan(struct device *dev, struct device_attribute *devattr, int rpm; /* - * Calculation details: - * - * Each tachometer counts over an interval given by the "count" - * register (0.25, 0.5, 1 or 2 seconds). This module assumes - * that the fans produce two pulses per revolution (this seems - * to be the most common). - */ + * Calculation details: + * + * Each tachometer counts over an interval given by the "count" + * register (0.25, 0.5, 1 or 2 seconds). This module assumes + * that the fans produce two pulses per revolution (this seems + * to be the most common). + */ rpm = ((data->tach[attr->index] * 120) / DIV_FROM_REG(data->count)); return sprintf(buf, "%d\n", rpm); @@ -210,12 +239,12 @@ static ssize_t get_target(struct device *dev, struct device_attribute *devattr, int kscale, ktach, rpm; /* - * Use the datasheet equation: - * - * FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)] - * - * then multiply by 60 to give rpm. - */ + * Use the datasheet equation: + * + * FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)] + * + * then multiply by 60 to give rpm. + */ kscale = DIV_FROM_REG(data->config); ktach = data->speed; @@ -226,19 +255,24 @@ static ssize_t get_target(struct device *dev, struct device_attribute *devattr, static ssize_t set_target(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct max6650_data *data = i2c_get_clientdata(client); - int rpm = simple_strtoul(buf, NULL, 10); + struct max6650_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int kscale, ktach; + unsigned long rpm; + int err; - rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX); + err = kstrtoul(buf, 10, &rpm); + if (err) + return err; + + rpm = clamp_val(rpm, FAN_RPM_MIN, FAN_RPM_MAX); /* - * Divide the required speed by 60 to get from rpm to rps, then - * use the datasheet equation: - * - * KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1 - */ + * Divide the required speed by 60 to get from rpm to rps, then + * use the datasheet equation: + * + * KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1 + */ mutex_lock(&data->update_lock); @@ -272,8 +306,10 @@ static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr, int pwm; struct max6650_data *data = max6650_update_device(dev); - /* Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans. - Lower DAC values mean higher speeds. */ + /* + * Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans. + * Lower DAC values mean higher speeds. + */ if (data->config & MAX6650_CFG_V12) pwm = 255 - (255 * (int)data->dac)/180; else @@ -288,11 +324,16 @@ static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr, static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct max6650_data *data = i2c_get_clientdata(client); - int pwm = simple_strtoul(buf, NULL, 10); + struct max6650_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + unsigned long pwm; + int err; - pwm = SENSORS_LIMIT(pwm, 0, 255); + err = kstrtoul(buf, 10, &pwm); + if (err) + return err; + + pwm = clamp_val(pwm, 0, 255); mutex_lock(&data->update_lock); @@ -329,16 +370,18 @@ static ssize_t get_enable(struct device *dev, struct device_attribute *devattr, static ssize_t set_enable(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct max6650_data *data = i2c_get_clientdata(client); - int mode = simple_strtoul(buf, NULL, 10); + struct max6650_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int max6650_modes[3] = {0, 3, 2}; + unsigned long mode; + int err; - if ((mode < 0)||(mode > 2)) { - dev_err(&client->dev, - "illegal value for pwm1_enable (%d)\n", mode); + err = kstrtoul(buf, 10, &mode); + if (err) + return err; + + if (mode > 2) return -EINVAL; - } mutex_lock(&data->update_lock); @@ -377,9 +420,14 @@ static ssize_t get_div(struct device *dev, struct device_attribute *devattr, static ssize_t set_div(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct max6650_data *data = i2c_get_clientdata(client); - int div = simple_strtoul(buf, NULL, 10); + struct max6650_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + unsigned long div; + int err; + + err = kstrtoul(buf, 10, &div); + if (err) + return err; mutex_lock(&data->update_lock); switch (div) { @@ -396,8 +444,7 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr, data->count = 3; break; default: - dev_err(&client->dev, - "illegal value for fan divider (%d)\n", div); + mutex_unlock(&data->update_lock); return -EINVAL; } @@ -407,6 +454,33 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr, return count; } +/* + * Get alarm stati: + * Possible values: + * 0 = no alarm + * 1 = alarm + */ + +static ssize_t get_alarm(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct max6650_data *data = max6650_update_device(dev); + struct i2c_client *client = data->client; + int alarm = 0; + + if (data->alarm & attr->index) { + mutex_lock(&data->update_lock); + alarm = 1; + data->alarm &= ~attr->index; + data->alarm |= i2c_smbus_read_byte_data(client, + MAX6650_REG_ALARM); + mutex_unlock(&data->update_lock); + } + + return sprintf(buf, "%d\n", alarm); +} + static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0); static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1); static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2); @@ -415,221 +489,155 @@ static DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, get_target, set_target); static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, get_div, set_div); static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, get_enable, set_enable); static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm); +static SENSOR_DEVICE_ATTR(fan1_max_alarm, S_IRUGO, get_alarm, NULL, + MAX6650_ALRM_MAX); +static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, get_alarm, NULL, + MAX6650_ALRM_MIN); +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_alarm, NULL, + MAX6650_ALRM_TACH); +static SENSOR_DEVICE_ATTR(gpio1_alarm, S_IRUGO, get_alarm, NULL, + MAX6650_ALRM_GPIO1); +static SENSOR_DEVICE_ATTR(gpio2_alarm, S_IRUGO, get_alarm, NULL, + MAX6650_ALRM_GPIO2); + +static umode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a, + int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct max6650_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + u8 alarm_en = i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN); + struct device_attribute *devattr; + + /* + * Hide the alarms that have not been enabled by the firmware + */ + devattr = container_of(a, struct device_attribute, attr); + if (devattr == &sensor_dev_attr_fan1_max_alarm.dev_attr + || devattr == &sensor_dev_attr_fan1_min_alarm.dev_attr + || devattr == &sensor_dev_attr_fan1_fault.dev_attr + || devattr == &sensor_dev_attr_gpio1_alarm.dev_attr + || devattr == &sensor_dev_attr_gpio2_alarm.dev_attr) { + if (!(alarm_en & to_sensor_dev_attr(devattr)->index)) + return 0; + } + + return a->mode; +} static struct attribute *max6650_attrs[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, &dev_attr_fan1_target.attr, &dev_attr_fan1_div.attr, &dev_attr_pwm1_enable.attr, &dev_attr_pwm1.attr, + &sensor_dev_attr_fan1_max_alarm.dev_attr.attr, + &sensor_dev_attr_fan1_min_alarm.dev_attr.attr, + &sensor_dev_attr_fan1_fault.dev_attr.attr, + &sensor_dev_attr_gpio1_alarm.dev_attr.attr, + &sensor_dev_attr_gpio2_alarm.dev_attr.attr, NULL }; -static struct attribute_group max6650_attr_grp = { +static const struct attribute_group max6650_group = { .attrs = max6650_attrs, + .is_visible = max6650_attrs_visible, }; -/* - * Real code - */ - -static int max6650_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) { - dev_dbg(&adapter->dev, - "FATAL: max6650_attach_adapter class HWMON not set\n"); - return 0; - } +static struct attribute *max6651_attrs[] = { + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + NULL +}; - return i2c_probe(adapter, &addr_data, max6650_detect); -} +static const struct attribute_group max6651_group = { + .attrs = max6651_attrs, +}; /* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. + * Real code */ -static int max6650_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *client; - struct max6650_data *data; - int err = -ENODEV; - - dev_dbg(&adapter->dev, "max6650_detect called, kind = %d\n", kind); - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support " - "byte read mode, skipping.\n"); - return 0; - } - - if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) { - dev_err(&adapter->dev, "max6650: out of memory.\n"); - return -ENOMEM; - } - - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &max6650_driver; - - /* - * Now we do the remaining detection. A negative kind means that - * the driver was loaded with no force parameter (default), so we - * must both detect and identify the chip (actually there is only - * one possible kind of chip for now, max6650). A zero kind means that - * the driver was loaded with the force parameter, the detection - * step shall be skipped. A positive kind means that the driver - * was loaded with the force parameter and a given kind of chip is - * requested, so both the detection and the identification steps - * are skipped. - * - * Currently I can find no way to distinguish between a MAX6650 and - * a MAX6651. This driver has only been tried on the former. - */ - - if ((kind < 0) && - ( (i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG) & 0xC0) - ||(i2c_smbus_read_byte_data(client, MAX6650_REG_GPIO_STAT) & 0xE0) - ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN) & 0xE0) - ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM) & 0xE0) - ||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) { - dev_dbg(&adapter->dev, - "max6650: detection failed at 0x%02x.\n", address); - goto err_free; - } - - dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address); - - strlcpy(client->name, "max6650", I2C_NAME_SIZE); - mutex_init(&data->update_lock); - - if ((err = i2c_attach_client(client))) { - dev_err(&adapter->dev, "max6650: failed to attach client.\n"); - goto err_free; - } - - /* - * Initialize the max6650 chip - */ - if (max6650_init_client(client)) - goto err_detach; - - err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp); - if (err) - goto err_detach; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (!IS_ERR(data->hwmon_dev)) - return 0; - - err = PTR_ERR(data->hwmon_dev); - dev_err(&client->dev, "error registering hwmon device.\n"); - sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); -err_detach: - i2c_detach_client(client); -err_free: - kfree(data); - return err; -} - -static int max6650_detach_client(struct i2c_client *client) +static int max6650_init_client(struct max6650_data *data, + struct i2c_client *client) { - struct max6650_data *data = i2c_get_clientdata(client); - int err; - - sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); - hwmon_device_unregister(data->hwmon_dev); - err = i2c_detach_client(client); - if (!err) - kfree(data); - return err; -} - -static int max6650_init_client(struct i2c_client *client) -{ - struct max6650_data *data = i2c_get_clientdata(client); + struct device *dev = &client->dev; int config; int err = -EIO; config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG); if (config < 0) { - dev_err(&client->dev, "Error reading config, aborting.\n"); + dev_err(dev, "Error reading config, aborting.\n"); return err; } switch (fan_voltage) { - case 0: - break; - case 5: - config &= ~MAX6650_CFG_V12; - break; - case 12: - config |= MAX6650_CFG_V12; - break; - default: - dev_err(&client->dev, - "illegal value for fan_voltage (%d)\n", - fan_voltage); + case 0: + break; + case 5: + config &= ~MAX6650_CFG_V12; + break; + case 12: + config |= MAX6650_CFG_V12; + break; + default: + dev_err(dev, "illegal value for fan_voltage (%d)\n", + fan_voltage); } - dev_info(&client->dev, "Fan voltage is set to %dV.\n", + dev_info(dev, "Fan voltage is set to %dV.\n", (config & MAX6650_CFG_V12) ? 12 : 5); switch (prescaler) { - case 0: - break; - case 1: - config &= ~MAX6650_CFG_PRESCALER_MASK; - break; - case 2: - config = (config & ~MAX6650_CFG_PRESCALER_MASK) - | MAX6650_CFG_PRESCALER_2; - break; - case 4: - config = (config & ~MAX6650_CFG_PRESCALER_MASK) - | MAX6650_CFG_PRESCALER_4; - break; - case 8: - config = (config & ~MAX6650_CFG_PRESCALER_MASK) - | MAX6650_CFG_PRESCALER_8; - break; - case 16: - config = (config & ~MAX6650_CFG_PRESCALER_MASK) - | MAX6650_CFG_PRESCALER_16; - break; - default: - dev_err(&client->dev, - "illegal value for prescaler (%d)\n", - prescaler); + case 0: + break; + case 1: + config &= ~MAX6650_CFG_PRESCALER_MASK; + break; + case 2: + config = (config & ~MAX6650_CFG_PRESCALER_MASK) + | MAX6650_CFG_PRESCALER_2; + break; + case 4: + config = (config & ~MAX6650_CFG_PRESCALER_MASK) + | MAX6650_CFG_PRESCALER_4; + break; + case 8: + config = (config & ~MAX6650_CFG_PRESCALER_MASK) + | MAX6650_CFG_PRESCALER_8; + break; + case 16: + config = (config & ~MAX6650_CFG_PRESCALER_MASK) + | MAX6650_CFG_PRESCALER_16; + break; + default: + dev_err(dev, "illegal value for prescaler (%d)\n", prescaler); } - dev_info(&client->dev, "Prescaler is set to %d.\n", + dev_info(dev, "Prescaler is set to %d.\n", 1 << (config & MAX6650_CFG_PRESCALER_MASK)); - /* If mode is set to "full off", we change it to "open loop" and + /* + * If mode is set to "full off", we change it to "open loop" and * set DAC to 255, which has the same effect. We do this because - * there's no "full off" mode defined in hwmon specifcations. + * there's no "full off" mode defined in hwmon specifications. */ if ((config & MAX6650_CFG_MODE_MASK) == MAX6650_CFG_MODE_OFF) { - dev_dbg(&client->dev, "Change mode to open loop, full off.\n"); + dev_dbg(dev, "Change mode to open loop, full off.\n"); config = (config & ~MAX6650_CFG_MODE_MASK) | MAX6650_CFG_MODE_OPEN_LOOP; if (i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, 255)) { - dev_err(&client->dev, "DAC write error, aborting.\n"); + dev_err(dev, "DAC write error, aborting.\n"); return err; } } if (i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, config)) { - dev_err(&client->dev, "Config write error, aborting.\n"); + dev_err(dev, "Config write error, aborting.\n"); return err; } @@ -639,56 +647,57 @@ static int max6650_init_client(struct i2c_client *client) return 0; } -static const u8 tach_reg[] = { - MAX6650_REG_TACH0, - MAX6650_REG_TACH1, - MAX6650_REG_TACH2, - MAX6650_REG_TACH3, -}; - -static struct max6650_data *max6650_update_device(struct device *dev) +static int max6650_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - int i; - struct i2c_client *client = to_i2c_client(dev); - struct max6650_data *data = i2c_get_clientdata(client); + struct device *dev = &client->dev; + struct max6650_data *data; + struct device *hwmon_dev; + int err; - mutex_lock(&data->update_lock); + data = devm_kzalloc(dev, sizeof(struct max6650_data), GFP_KERNEL); + if (!data) + return -ENOMEM; - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - data->speed = i2c_smbus_read_byte_data(client, - MAX6650_REG_SPEED); - data->config = i2c_smbus_read_byte_data(client, - MAX6650_REG_CONFIG); - for (i = 0; i < 4; i++) { - data->tach[i] = i2c_smbus_read_byte_data(client, - tach_reg[i]); - } - data->count = i2c_smbus_read_byte_data(client, - MAX6650_REG_COUNT); - data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC); + data->client = client; + mutex_init(&data->update_lock); + data->nr_fans = id->driver_data; - data->last_updated = jiffies; - data->valid = 1; - } + /* + * Initialize the max6650 chip + */ + err = max6650_init_client(data, client); + if (err) + return err; - mutex_unlock(&data->update_lock); + data->groups[0] = &max6650_group; + /* 3 additional fan inputs for the MAX6651 */ + if (data->nr_fans == 4) + data->groups[1] = &max6651_group; - return data; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, + client->name, data, + data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } -static int __init sensors_max6650_init(void) -{ - return i2c_add_driver(&max6650_driver); -} +static const struct i2c_device_id max6650_id[] = { + { "max6650", 1 }, + { "max6651", 4 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max6650_id); -static void __exit sensors_max6650_exit(void) -{ - i2c_del_driver(&max6650_driver); -} +static struct i2c_driver max6650_driver = { + .driver = { + .name = "max6650", + }, + .probe = max6650_probe, + .id_table = max6650_id, +}; + +module_i2c_driver(max6650_driver); MODULE_AUTHOR("Hans J. Koch"); MODULE_DESCRIPTION("MAX6650 sensor driver"); MODULE_LICENSE("GPL"); - -module_init(sensors_max6650_init); -module_exit(sensors_max6650_exit); |
