X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fhwmon%2Fgl520sm.c;h=dee93ec87d02a2c3c2f343ed6e2caeb0f7b35384;hb=fb7b26e47ef932a21f0cac4cf04e8f51105d77d7;hp=ed56e09c3dd7147b4f209fb0a79244300692c341;hpb=8cab24f0b1daf23ba042464f0d4a4e51695bed74;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index ed56e09c3dd7..dee93ec87d02 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -73,41 +73,10 @@ static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 }; #define GL520_REG_BEEP_MASK 0x10 #define GL520_REG_BEEP_ENABLE GL520_REG_CONF -/* - * Function declarations - */ - -static int gl520_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info); -static void gl520_init_client(struct i2c_client *client); -static int gl520_remove(struct i2c_client *client); -static int gl520_read_value(struct i2c_client *client, u8 reg); -static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value); -static struct gl520_data *gl520_update_device(struct device *dev); - -/* Driver data */ -static const struct i2c_device_id gl520_id[] = { - { "gl520sm", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, gl520_id); - -static struct i2c_driver gl520_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "gl520sm", - }, - .probe = gl520_probe, - .remove = gl520_remove, - .id_table = gl520_id, - .detect = gl520_detect, - .address_list = normal_i2c, -}; - /* Client data */ struct gl520_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[3]; struct mutex update_lock; char valid; /* zero until the following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -131,6 +100,102 @@ struct gl520_data { u8 two_temps; }; +/* + * Registers 0x07 to 0x0c are word-sized, others are byte-sized + * GL520 uses a high-byte first convention + */ +static int gl520_read_value(struct i2c_client *client, u8 reg) +{ + if ((reg >= 0x07) && (reg <= 0x0c)) + return i2c_smbus_read_word_swapped(client, reg); + else + return i2c_smbus_read_byte_data(client, reg); +} + +static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value) +{ + if ((reg >= 0x07) && (reg <= 0x0c)) + return i2c_smbus_write_word_swapped(client, reg, value); + else + return i2c_smbus_write_byte_data(client, reg, value); +} + +static struct gl520_data *gl520_update_device(struct device *dev) +{ + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int val, i; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { + + dev_dbg(&client->dev, "Starting gl520sm update\n"); + + data->alarms = gl520_read_value(client, GL520_REG_ALARMS); + data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); + data->vid = gl520_read_value(client, + GL520_REG_VID_INPUT) & 0x1f; + + for (i = 0; i < 4; i++) { + data->in_input[i] = gl520_read_value(client, + GL520_REG_IN_INPUT[i]); + val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]); + data->in_min[i] = val & 0xff; + data->in_max[i] = (val >> 8) & 0xff; + } + + val = gl520_read_value(client, GL520_REG_FAN_INPUT); + data->fan_input[0] = (val >> 8) & 0xff; + data->fan_input[1] = val & 0xff; + + val = gl520_read_value(client, GL520_REG_FAN_MIN); + data->fan_min[0] = (val >> 8) & 0xff; + data->fan_min[1] = val & 0xff; + + data->temp_input[0] = gl520_read_value(client, + GL520_REG_TEMP_INPUT[0]); + data->temp_max[0] = gl520_read_value(client, + GL520_REG_TEMP_MAX[0]); + data->temp_max_hyst[0] = gl520_read_value(client, + GL520_REG_TEMP_MAX_HYST[0]); + + val = gl520_read_value(client, GL520_REG_FAN_DIV); + data->fan_div[0] = (val >> 6) & 0x03; + data->fan_div[1] = (val >> 4) & 0x03; + data->fan_off = (val >> 2) & 0x01; + + data->alarms &= data->alarm_mask; + + val = gl520_read_value(client, GL520_REG_CONF); + data->beep_enable = !((val >> 2) & 1); + + /* Temp1 and Vin4 are the same input */ + if (data->two_temps) { + data->temp_input[1] = gl520_read_value(client, + GL520_REG_TEMP_INPUT[1]); + data->temp_max[1] = gl520_read_value(client, + GL520_REG_TEMP_MAX[1]); + data->temp_max_hyst[1] = gl520_read_value(client, + GL520_REG_TEMP_MAX_HYST[1]); + } else { + data->in_input[4] = gl520_read_value(client, + GL520_REG_IN_INPUT[4]); + data->in_min[4] = gl520_read_value(client, + GL520_REG_IN_MIN[4]); + data->in_max[4] = gl520_read_value(client, + GL520_REG_IN_MAX[4]); + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + /* * Sysfs stuff */ @@ -191,8 +256,8 @@ static ssize_t get_in_max(struct device *dev, struct device_attribute *attr, static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; u8 r; long v; @@ -225,8 +290,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; u8 r; long v; @@ -326,8 +391,8 @@ static ssize_t get_fan_off(struct device *dev, struct device_attribute *attr, static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; u8 r; unsigned long v; @@ -365,8 +430,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; u8 r; unsigned long v; @@ -414,8 +479,8 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, static ssize_t set_fan_off(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 r; unsigned long v; int err; @@ -482,8 +547,8 @@ static ssize_t get_temp_max_hyst(struct device *dev, static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; long v; int err; @@ -502,8 +567,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; long v; int err; @@ -555,8 +620,8 @@ static ssize_t get_beep_mask(struct device *dev, struct device_attribute *attr, static ssize_t set_beep_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 r; unsigned long v; int err; @@ -579,8 +644,8 @@ static ssize_t set_beep_enable(struct device *dev, struct device_attribute static ssize_t set_beep_mask(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long r; int err; @@ -633,8 +698,8 @@ static ssize_t get_beep(struct device *dev, struct device_attribute *attr, static ssize_t set_beep(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int bitnr = to_sensor_dev_attr(attr)->index; unsigned long bit; @@ -772,52 +837,6 @@ static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info) return 0; } -static int gl520_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct gl520_data *data; - int err; - - data = devm_kzalloc(&client->dev, sizeof(struct gl520_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the GL520SM chip */ - gl520_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &gl520_group); - if (err) - return err; - - if (data->two_temps) - err = sysfs_create_group(&client->dev.kobj, &gl520_group_temp2); - else - err = sysfs_create_group(&client->dev.kobj, &gl520_group_in4); - - if (err) - goto exit_remove_files; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &gl520_group); - sysfs_remove_group(&client->dev.kobj, &gl520_group_in4); - sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2); - return err; -} - - /* Called when we have found a new GL520SM. */ static void gl520_init_client(struct i2c_client *client) { @@ -856,115 +875,53 @@ static void gl520_init_client(struct i2c_client *client) gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); } -static int gl520_remove(struct i2c_client *client) +static int gl520_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct gl520_data *data = i2c_get_clientdata(client); + struct device *dev = &client->dev; + struct device *hwmon_dev; + struct gl520_data *data; - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &gl520_group); - sysfs_remove_group(&client->dev.kobj, &gl520_group_in4); - sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2); + data = devm_kzalloc(dev, sizeof(struct gl520_data), GFP_KERNEL); + if (!data) + return -ENOMEM; - return 0; -} + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->client = client; + /* Initialize the GL520SM chip */ + gl520_init_client(client); -/* - * Registers 0x07 to 0x0c are word-sized, others are byte-sized - * GL520 uses a high-byte first convention - */ -static int gl520_read_value(struct i2c_client *client, u8 reg) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return i2c_smbus_read_word_swapped(client, reg); - else - return i2c_smbus_read_byte_data(client, reg); -} + /* sysfs hooks */ + data->groups[0] = &gl520_group; -static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return i2c_smbus_write_word_swapped(client, reg, value); + if (data->two_temps) + data->groups[1] = &gl520_group_temp2; else - return i2c_smbus_write_byte_data(client, reg, value); -} - - -static struct gl520_data *gl520_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - int val, i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - - dev_dbg(&client->dev, "Starting gl520sm update\n"); - - data->alarms = gl520_read_value(client, GL520_REG_ALARMS); - data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); - data->vid = gl520_read_value(client, - GL520_REG_VID_INPUT) & 0x1f; - - for (i = 0; i < 4; i++) { - data->in_input[i] = gl520_read_value(client, - GL520_REG_IN_INPUT[i]); - val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]); - data->in_min[i] = val & 0xff; - data->in_max[i] = (val >> 8) & 0xff; - } - - val = gl520_read_value(client, GL520_REG_FAN_INPUT); - data->fan_input[0] = (val >> 8) & 0xff; - data->fan_input[1] = val & 0xff; + data->groups[1] = &gl520_group_in4; - val = gl520_read_value(client, GL520_REG_FAN_MIN); - data->fan_min[0] = (val >> 8) & 0xff; - data->fan_min[1] = val & 0xff; - - data->temp_input[0] = gl520_read_value(client, - GL520_REG_TEMP_INPUT[0]); - data->temp_max[0] = gl520_read_value(client, - GL520_REG_TEMP_MAX[0]); - data->temp_max_hyst[0] = gl520_read_value(client, - GL520_REG_TEMP_MAX_HYST[0]); - - val = gl520_read_value(client, GL520_REG_FAN_DIV); - data->fan_div[0] = (val >> 6) & 0x03; - data->fan_div[1] = (val >> 4) & 0x03; - data->fan_off = (val >> 2) & 0x01; - - data->alarms &= data->alarm_mask; - - val = gl520_read_value(client, GL520_REG_CONF); - data->beep_enable = !((val >> 2) & 1); - - /* Temp1 and Vin4 are the same input */ - if (data->two_temps) { - data->temp_input[1] = gl520_read_value(client, - GL520_REG_TEMP_INPUT[1]); - data->temp_max[1] = gl520_read_value(client, - GL520_REG_TEMP_MAX[1]); - data->temp_max_hyst[1] = gl520_read_value(client, - GL520_REG_TEMP_MAX_HYST[1]); - } else { - data->in_input[4] = gl520_read_value(client, - GL520_REG_IN_INPUT[4]); - data->in_min[4] = gl520_read_value(client, - GL520_REG_IN_MIN[4]); - data->in_max[4] = gl520_read_value(client, - GL520_REG_IN_MAX[4]); - } - - data->last_updated = jiffies; - data->valid = 1; - } + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} - mutex_unlock(&data->update_lock); +static const struct i2c_device_id gl520_id[] = { + { "gl520sm", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, gl520_id); - return data; -} +static struct i2c_driver gl520_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "gl520sm", + }, + .probe = gl520_probe, + .id_table = gl520_id, + .detect = gl520_detect, + .address_list = normal_i2c, +}; module_i2c_driver(gl520_driver);