159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick/* 27cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * smsc47m192.c - Support for hardware monitoring block of 37cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * SMSC LPC47M192 and compatible Super I/O chips 47cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * 57cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * Copyright (C) 2006 Hartmut Rick <linux@rick.claranet.de> 67cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * 77cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * Derived from lm78.c and other chip drivers. 87cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * 97cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * This program is free software; you can redistribute it and/or modify 107cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * it under the terms of the GNU General Public License as published by 117cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * the Free Software Foundation; either version 2 of the License, or 127cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * (at your option) any later version. 137cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * 147cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * This program is distributed in the hope that it will be useful, 157cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 167cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 177cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * GNU General Public License for more details. 187cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * 197cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * You should have received a copy of the GNU General Public License 207cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * along with this program; if not, write to the Free Software 217cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 227cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck */ 2359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 2459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#include <linux/module.h> 2559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#include <linux/init.h> 2659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#include <linux/slab.h> 2759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#include <linux/jiffies.h> 2859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#include <linux/i2c.h> 2959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#include <linux/hwmon.h> 3059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#include <linux/hwmon-sysfs.h> 3159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#include <linux/hwmon-vid.h> 3259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#include <linux/err.h> 33ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare#include <linux/sysfs.h> 34e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare#include <linux/mutex.h> 3559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 3659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick/* Addresses to scan */ 3725e9c86d5a6d82ea45eb680fc66bf73ac5e50dffMark M. Hoffmanstatic const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; 3859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 3959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick/* SMSC47M192 registers */ 407cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck#define SMSC47M192_REG_IN(nr) ((nr) < 6 ? (0x20 + (nr)) : \ 4159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick (0x50 + (nr) - 6)) 427cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck#define SMSC47M192_REG_IN_MAX(nr) ((nr) < 6 ? (0x2b + (nr) * 2) : \ 4359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick (0x54 + (((nr) - 6) * 2))) 447cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck#define SMSC47M192_REG_IN_MIN(nr) ((nr) < 6 ? (0x2c + (nr) * 2) : \ 4559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick (0x55 + (((nr) - 6) * 2))) 4659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic u8 SMSC47M192_REG_TEMP[3] = { 0x27, 0x26, 0x52 }; 4759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic u8 SMSC47M192_REG_TEMP_MAX[3] = { 0x39, 0x37, 0x58 }; 4859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic u8 SMSC47M192_REG_TEMP_MIN[3] = { 0x3A, 0x38, 0x59 }; 497cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck#define SMSC47M192_REG_TEMP_OFFSET(nr) ((nr) == 2 ? 0x1e : 0x1f) 5059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#define SMSC47M192_REG_ALARM1 0x41 5159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#define SMSC47M192_REG_ALARM2 0x42 5259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#define SMSC47M192_REG_VID 0x47 5359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#define SMSC47M192_REG_VID4 0x49 5459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#define SMSC47M192_REG_CONFIG 0x40 5559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#define SMSC47M192_REG_SFR 0x4f 5659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#define SMSC47M192_REG_COMPANY_ID 0x3e 5759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#define SMSC47M192_REG_VERSION 0x3f 5859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 5959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick/* generalised scaling with integer rounding */ 6059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic inline int SCALE(long val, int mul, int div) 6159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 6259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick if (val < 0) 6359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return (val * mul - div / 2) / div; 6459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick else 6559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return (val * mul + div / 2) / div; 6659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 6759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 6859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick/* Conversions */ 6959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 7059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick/* smsc47m192 internally scales voltage measurements */ 7159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 }; 7259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 7359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic inline unsigned int IN_FROM_REG(u8 reg, int n) 7459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 7559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return SCALE(reg, nom_mv[n], 192); 7659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 7759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 7859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic inline u8 IN_TO_REG(unsigned long val, int n) 7959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 8059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255); 8159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 8259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 837cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck/* 847cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * TEMP: 0.001 degC units (-128C to +127C) 857cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * REG: 1C/bit, two's complement 867cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck */ 8759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic inline s8 TEMP_TO_REG(int val) 8859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 8959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000); 9059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 9159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 9259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic inline int TEMP_FROM_REG(s8 val) 9359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 9459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return val * 1000; 9559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 9659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 9759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstruct smsc47m192_data { 981beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones struct device *hwmon_dev; 99e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare struct mutex update_lock; 10059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick char valid; /* !=0 if following fields are valid */ 10159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick unsigned long last_updated; /* In jiffies */ 10259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 10359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick u8 in[8]; /* Register value */ 10459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick u8 in_max[8]; /* Register value */ 10559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick u8 in_min[8]; /* Register value */ 10659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick s8 temp[3]; /* Register value */ 10759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick s8 temp_max[3]; /* Register value */ 10859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick s8 temp_min[3]; /* Register value */ 10959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick s8 temp_offset[3]; /* Register value */ 11059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick u16 alarms; /* Register encoding, combined */ 11159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick u8 vid; /* Register encoding, combined */ 11259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick u8 vrm; 11359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick}; 11459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 1158fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvarestatic int smsc47m192_probe(struct i2c_client *client, 1168fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare const struct i2c_device_id *id); 117310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int smsc47m192_detect(struct i2c_client *client, 1188fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare struct i2c_board_info *info); 1198fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvarestatic int smsc47m192_remove(struct i2c_client *client); 12059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic struct smsc47m192_data *smsc47m192_update_device(struct device *dev); 12159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 1228fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvarestatic const struct i2c_device_id smsc47m192_id[] = { 1231f86df49ddfd0067cce941187d57b2fd2f749a9eJean Delvare { "smsc47m192", 0 }, 1248fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare { } 1258fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare}; 1268fb597bb6ec80d53836229bf3576c7b848b909e3Jean DelvareMODULE_DEVICE_TABLE(i2c, smsc47m192_id); 1278fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare 12859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic struct i2c_driver smsc47m192_driver = { 1298fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare .class = I2C_CLASS_HWMON, 13059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick .driver = { 13159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick .name = "smsc47m192", 13259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick }, 1338fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare .probe = smsc47m192_probe, 1348fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare .remove = smsc47m192_remove, 1358fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare .id_table = smsc47m192_id, 1368fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare .detect = smsc47m192_detect, 137c3813d6af177fab19e322f3114b1f64fbcf08d71Jean Delvare .address_list = normal_i2c, 13859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick}; 13959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 14059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick/* Voltages */ 14159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t show_in(struct device *dev, struct device_attribute *attr, 14259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick char *buf) 14359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 14459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 14559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 14659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = smsc47m192_update_device(dev); 14759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr)); 14859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 14959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 15059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t show_in_min(struct device *dev, struct device_attribute *attr, 15159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick char *buf) 15259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 15359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 15459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 15559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = smsc47m192_update_device(dev); 15659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr)); 15759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 15859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 15959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t show_in_max(struct device *dev, struct device_attribute *attr, 16059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick char *buf) 16159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 16259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 16359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 16459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = smsc47m192_update_device(dev); 16559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr)); 16659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 16759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 16859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t set_in_min(struct device *dev, struct device_attribute *attr, 16959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick const char *buf, size_t count) 17059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 17159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 17259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 17359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct i2c_client *client = to_i2c_client(dev); 17459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = i2c_get_clientdata(client); 1757cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck unsigned long val; 1767cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck int err; 1777cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck 1787cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck err = kstrtoul(buf, 10, &val); 1797cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck if (err) 1807cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck return err; 18159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 182e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_lock(&data->update_lock); 18359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->in_min[nr] = IN_TO_REG(val, nr); 18459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr), 18559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->in_min[nr]); 186e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_unlock(&data->update_lock); 18759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return count; 18859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 18959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 19059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t set_in_max(struct device *dev, struct device_attribute *attr, 19159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick const char *buf, size_t count) 19259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 19359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 19459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 19559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct i2c_client *client = to_i2c_client(dev); 19659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = i2c_get_clientdata(client); 1977cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck unsigned long val; 1987cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck int err; 1997cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck 2007cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck err = kstrtoul(buf, 10, &val); 2017cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck if (err) 2027cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck return err; 20359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 204e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_lock(&data->update_lock); 20559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->in_max[nr] = IN_TO_REG(val, nr); 20659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr), 20759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->in_max[nr]); 208e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_unlock(&data->update_lock); 20959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return count; 21059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 21159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 21259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#define show_in_offset(offset) \ 21359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ 21459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick show_in, NULL, offset); \ 21559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ 21659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick show_in_min, set_in_min, offset); \ 21759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ 21859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick show_in_max, set_in_max, offset); 21959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 22059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_in_offset(0) 22159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_in_offset(1) 22259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_in_offset(2) 22359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_in_offset(3) 22459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_in_offset(4) 22559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_in_offset(5) 22659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_in_offset(6) 22759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_in_offset(7) 22859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 22959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick/* Temperatures */ 23059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t show_temp(struct device *dev, struct device_attribute *attr, 23159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick char *buf) 23259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 23359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 23459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 23559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = smsc47m192_update_device(dev); 23659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); 23759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 23859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 23959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, 24059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick char *buf) 24159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 24259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 24359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 24459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = smsc47m192_update_device(dev); 24559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); 24659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 24759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 24859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, 24959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick char *buf) 25059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 25159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 25259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 25359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = smsc47m192_update_device(dev); 25459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); 25559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 25659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 25759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, 25859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick const char *buf, size_t count) 25959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 26059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 26159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 26259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct i2c_client *client = to_i2c_client(dev); 26359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = i2c_get_clientdata(client); 2647cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck long val; 2657cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck int err; 2667cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck 2677cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck err = kstrtol(buf, 10, &val); 2687cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck if (err) 2697cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck return err; 27059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 271e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_lock(&data->update_lock); 27259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_min[nr] = TEMP_TO_REG(val); 27359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr], 27459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_min[nr]); 275e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_unlock(&data->update_lock); 27659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return count; 27759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 27859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 27959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, 28059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick const char *buf, size_t count) 28159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 28259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 28359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 28459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct i2c_client *client = to_i2c_client(dev); 28559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = i2c_get_clientdata(client); 2867cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck long val; 2877cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck int err; 2887cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck 2897cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck err = kstrtol(buf, 10, &val); 2907cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck if (err) 2917cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck return err; 29259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 293e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_lock(&data->update_lock); 29459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_max[nr] = TEMP_TO_REG(val); 29559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr], 29659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_max[nr]); 297e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_unlock(&data->update_lock); 29859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return count; 29959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 30059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 30159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t show_temp_offset(struct device *dev, struct device_attribute 30259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick *attr, char *buf) 30359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 30459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 30559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 30659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = smsc47m192_update_device(dev); 30759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr])); 30859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 30959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 31059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t set_temp_offset(struct device *dev, struct device_attribute 31159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick *attr, const char *buf, size_t count) 31259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 31359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 31459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 31559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct i2c_client *client = to_i2c_client(dev); 31659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = i2c_get_clientdata(client); 31759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); 3187cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck long val; 3197cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck int err; 3207cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck 3217cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck err = kstrtol(buf, 10, &val); 3227cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck if (err) 3237cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck return err; 32459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 325e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_lock(&data->update_lock); 32659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_offset[nr] = TEMP_TO_REG(val); 3277cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck if (nr > 1) 32859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, 32959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); 33059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick else if (data->temp_offset[nr] != 0) { 3317cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck /* 3327cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * offset[0] and offset[1] share the same register, 3337cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * SFR bit 4 activates offset[0] 3347cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck */ 33559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, 3367cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck (sfr & 0xef) | (nr == 0 ? 0x10 : 0)); 33759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_offset[1-nr] = 0; 33859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, 33959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); 3407cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck } else if ((sfr & 0x10) == (nr == 0 ? 0x10 : 0)) 34159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, 34259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_TEMP_OFFSET(nr), 0); 343e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_unlock(&data->update_lock); 34459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return count; 34559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 34659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 34759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick#define show_temp_index(index) \ 34859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, \ 34959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick show_temp, NULL, index-1); \ 35059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR, \ 35159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick show_temp_min, set_temp_min, index-1); \ 35259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR, \ 35359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick show_temp_max, set_temp_max, index-1); \ 35459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR, \ 35559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick show_temp_offset, set_temp_offset, index-1); 35659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 35759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_temp_index(1) 35859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_temp_index(2) 35959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickshow_temp_index(3) 36059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 36159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick/* VID */ 36259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t show_vid(struct device *dev, struct device_attribute *attr, 36359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick char *buf) 36459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 36559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = smsc47m192_update_device(dev); 36659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); 36759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 36859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); 36959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 37059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t show_vrm(struct device *dev, struct device_attribute *attr, 37159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick char *buf) 37259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 37390d6619a916062cb75a176aacb318d108758b4a5Jean Delvare struct smsc47m192_data *data = dev_get_drvdata(dev); 37459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return sprintf(buf, "%d\n", data->vrm); 37559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 37659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 37759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t set_vrm(struct device *dev, struct device_attribute *attr, 37859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick const char *buf, size_t count) 37959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 3808f74efe81d122c071410fd74f42879ef81439fa4Jean Delvare struct smsc47m192_data *data = dev_get_drvdata(dev); 3817cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck unsigned long val; 3827cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck int err; 3837cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck 3847cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck err = kstrtoul(buf, 10, &val); 3857cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck if (err) 3867cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck return err; 3877cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck 3887cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck data->vrm = val; 38959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return count; 39059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 39159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); 39259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 39359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick/* Alarms */ 39459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic ssize_t show_alarm(struct device *dev, struct device_attribute *attr, 39559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick char *buf) 39659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 39759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 39859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int nr = sensor_attr->index; 39959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = smsc47m192_update_device(dev); 40059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0); 40159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 40259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 40359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010); 40459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020); 40559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040); 4067817a39e65f04abe136d94a65fa26b7fe3334a1fJean Delvarestatic SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 0x4000); 4077817a39e65f04abe136d94a65fa26b7fe3334a1fJean Delvarestatic SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 0x8000); 40859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001); 40959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002); 41059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004); 41159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008); 41259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100); 41359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200); 41459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400); 41559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800); 41659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 417ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvarestatic struct attribute *smsc47m192_attributes[] = { 418ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in0_input.dev_attr.attr, 419ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in0_min.dev_attr.attr, 420ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in0_max.dev_attr.attr, 421ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in0_alarm.dev_attr.attr, 422ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in1_input.dev_attr.attr, 423ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in1_min.dev_attr.attr, 424ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in1_max.dev_attr.attr, 425ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in1_alarm.dev_attr.attr, 426ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in2_input.dev_attr.attr, 427ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in2_min.dev_attr.attr, 428ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in2_max.dev_attr.attr, 429ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in2_alarm.dev_attr.attr, 430ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in3_input.dev_attr.attr, 431ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in3_min.dev_attr.attr, 432ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in3_max.dev_attr.attr, 433ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in3_alarm.dev_attr.attr, 434ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in5_input.dev_attr.attr, 435ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in5_min.dev_attr.attr, 436ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in5_max.dev_attr.attr, 437ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in5_alarm.dev_attr.attr, 438ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in6_input.dev_attr.attr, 439ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in6_min.dev_attr.attr, 440ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in6_max.dev_attr.attr, 441ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in6_alarm.dev_attr.attr, 442ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in7_input.dev_attr.attr, 443ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in7_min.dev_attr.attr, 444ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in7_max.dev_attr.attr, 445ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in7_alarm.dev_attr.attr, 446ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare 447ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp1_input.dev_attr.attr, 448ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp1_max.dev_attr.attr, 449ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp1_min.dev_attr.attr, 450ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp1_offset.dev_attr.attr, 451ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp1_alarm.dev_attr.attr, 452ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp2_input.dev_attr.attr, 453ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp2_max.dev_attr.attr, 454ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp2_min.dev_attr.attr, 455ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp2_offset.dev_attr.attr, 456ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp2_alarm.dev_attr.attr, 4577817a39e65f04abe136d94a65fa26b7fe3334a1fJean Delvare &sensor_dev_attr_temp2_fault.dev_attr.attr, 458ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp3_input.dev_attr.attr, 459ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp3_max.dev_attr.attr, 460ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp3_min.dev_attr.attr, 461ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp3_offset.dev_attr.attr, 462ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_temp3_alarm.dev_attr.attr, 4637817a39e65f04abe136d94a65fa26b7fe3334a1fJean Delvare &sensor_dev_attr_temp3_fault.dev_attr.attr, 464ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare 465ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &dev_attr_cpu0_vid.attr, 466ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &dev_attr_vrm.attr, 467ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare NULL 468ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare}; 469ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare 470ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvarestatic const struct attribute_group smsc47m192_group = { 471ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare .attrs = smsc47m192_attributes, 472ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare}; 473ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare 474ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvarestatic struct attribute *smsc47m192_attributes_in4[] = { 475ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in4_input.dev_attr.attr, 476ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in4_min.dev_attr.attr, 477ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in4_max.dev_attr.attr, 478ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare &sensor_dev_attr_in4_alarm.dev_attr.attr, 479ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare NULL 480ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare}; 481ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare 482ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvarestatic const struct attribute_group smsc47m192_group_in4 = { 483ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare .attrs = smsc47m192_attributes_in4, 484ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare}; 485ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare 48659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic void smsc47m192_init_client(struct i2c_client *client) 48759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 48859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int i; 48959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); 49059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); 49159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 49259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick /* select cycle mode (pause 1 sec between updates) */ 49359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, 49459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick (sfr & 0xfd) | 0x02); 49559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick if (!(config & 0x01)) { 49659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick /* initialize alarm limits */ 4977cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck for (i = 0; i < 8; i++) { 49859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, 49959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_IN_MIN(i), 0); 50059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, 50159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_IN_MAX(i), 0xff); 50259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick } 5037cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck for (i = 0; i < 3; i++) { 50459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, 50559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_TEMP_MIN[i], 0x80); 50659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, 50759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_TEMP_MAX[i], 0x7f); 50859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick } 50959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 51059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick /* start monitoring */ 51159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG, 51259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick (config & 0xf7) | 0x01); 51359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick } 51459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 51559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 5168fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare/* Return 0 if detection is successful, -ENODEV otherwise */ 517310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int smsc47m192_detect(struct i2c_client *client, 5188fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare struct i2c_board_info *info) 51959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 5208fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare struct i2c_adapter *adapter = client->adapter; 5218fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare int version; 52259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 52359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 5248fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare return -ENODEV; 52559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 52659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick /* Detection criteria from sensors_detect script */ 52752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare version = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VERSION); 52852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare if (i2c_smbus_read_byte_data(client, 52959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_COMPANY_ID) == 0x55 53052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare && (version & 0xf0) == 0x20 53152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare && (i2c_smbus_read_byte_data(client, 53259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_VID) & 0x70) == 0x00 53352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare && (i2c_smbus_read_byte_data(client, 53459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_VID4) & 0xfe) == 0x80) { 53552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare dev_info(&adapter->dev, 53652df6440a29123eed912183fe785bbe174ef14b9Jean Delvare "found SMSC47M192 or compatible, " 53752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare "version 2, stepping A%d\n", version & 0x0f); 53852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare } else { 53952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare dev_dbg(&adapter->dev, 54052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare "SMSC47M192 detection failed at 0x%02x\n", 54152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare client->addr); 54252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare return -ENODEV; 54359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick } 54459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 5458fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE); 5468fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare 5478fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare return 0; 5488fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare} 5498fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare 5508fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvarestatic int smsc47m192_probe(struct i2c_client *client, 5518fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare const struct i2c_device_id *id) 5528fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare{ 5538fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare struct smsc47m192_data *data; 5548fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare int config; 5558fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare int err; 5568fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare 5578fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL); 5588fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare if (!data) { 5598fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare err = -ENOMEM; 5608fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare goto exit; 5618fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare } 5628fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare 5638fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare i2c_set_clientdata(client, data); 56459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->vrm = vid_which_vrm(); 565e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_init(&data->update_lock); 56659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 56759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick /* Initialize the SMSC47M192 chip */ 56859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick smsc47m192_init_client(client); 56959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 57059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick /* Register sysfs hooks */ 5717cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group); 5727cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck if (err) 5738fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvare goto exit_free; 57459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 57559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick /* Pin 110 is either in4 (+12V) or VID4 */ 57659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); 57759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick if (!(config & 0x20)) { 5787cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck err = sysfs_create_group(&client->dev.kobj, 5797cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck &smsc47m192_group_in4); 5807cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck if (err) 581ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare goto exit_remove_files; 582ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare } 583ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare 5841beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones data->hwmon_dev = hwmon_device_register(&client->dev); 5851beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones if (IS_ERR(data->hwmon_dev)) { 5861beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones err = PTR_ERR(data->hwmon_dev); 587ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare goto exit_remove_files; 58859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick } 58959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 59059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return 0; 59159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 592ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvareexit_remove_files: 593ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); 594ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); 59559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickexit_free: 59659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick kfree(data); 59759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickexit: 59859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return err; 59959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 60059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 6018fb597bb6ec80d53836229bf3576c7b848b909e3Jean Delvarestatic int smsc47m192_remove(struct i2c_client *client) 60259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 60359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = i2c_get_clientdata(client); 60459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 6051beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones hwmon_device_unregister(data->hwmon_dev); 606ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); 607ce8c6ce1eceecfe090f6c1aa4108087b2051497bJean Delvare sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); 60859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 60959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick kfree(data); 61059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 61159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return 0; 61259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 61359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 61459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rickstatic struct smsc47m192_data *smsc47m192_update_device(struct device *dev) 61559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick{ 61659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct i2c_client *client = to_i2c_client(dev); 61759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick struct smsc47m192_data *data = i2c_get_clientdata(client); 61859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick int i, config; 61959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 620e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_lock(&data->update_lock); 62159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 62259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 62359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick || !data->valid) { 62459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); 62559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 62659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick dev_dbg(&client->dev, "Starting smsc47m192 update\n"); 62759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 62859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick for (i = 0; i <= 7; i++) { 62959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->in[i] = i2c_smbus_read_byte_data(client, 63059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_IN(i)); 63159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->in_min[i] = i2c_smbus_read_byte_data(client, 63259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_IN_MIN(i)); 63359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->in_max[i] = i2c_smbus_read_byte_data(client, 63459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_IN_MAX(i)); 63559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick } 63659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick for (i = 0; i < 3; i++) { 63759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp[i] = i2c_smbus_read_byte_data(client, 63859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_TEMP[i]); 63959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_max[i] = i2c_smbus_read_byte_data(client, 64059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_TEMP_MAX[i]); 64159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_min[i] = i2c_smbus_read_byte_data(client, 64259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_TEMP_MIN[i]); 64359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick } 64459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick for (i = 1; i < 3; i++) 64559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_offset[i] = i2c_smbus_read_byte_data(client, 64659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_TEMP_OFFSET(i)); 6477cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck /* 6487cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * first offset is temp_offset[0] if SFR bit 4 is set, 6497cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck * temp_offset[1] otherwise 6507cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck */ 65159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick if (sfr & 0x10) { 65259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_offset[0] = data->temp_offset[1]; 65359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_offset[1] = 0; 65459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick } else 65559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->temp_offset[0] = 0; 65659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 65759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID) 65859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick & 0x0f; 65959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick config = i2c_smbus_read_byte_data(client, 66059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_CONFIG); 66159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick if (config & 0x20) 66259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->vid |= (i2c_smbus_read_byte_data(client, 66359ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_VID4) & 0x01) << 4; 66459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->alarms = i2c_smbus_read_byte_data(client, 66559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick SMSC47M192_REG_ALARM1) | 66659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick (i2c_smbus_read_byte_data(client, 6677cc3cb6662a21a59a2e0e752a8ebd95137c71d3aGuenter Roeck SMSC47M192_REG_ALARM2) << 8); 66859ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 66959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->last_updated = jiffies; 67059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick data->valid = 1; 67159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick } 67259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 673e4a7167f82130fa95005097797bb1ec9c76201fdJean Delvare mutex_unlock(&data->update_lock); 67459ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 67559ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick return data; 67659ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick} 67759ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 678f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(smsc47m192_driver); 67959ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut Rick 68059ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut RickMODULE_AUTHOR("Hartmut Rick <linux@rick.claranet.de>"); 68159ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut RickMODULE_DESCRIPTION("SMSC47M192 driver"); 68259ac83677f72ea2cc25b5426e7df9589aa7a5384Hartmut RickMODULE_LICENSE("GPL"); 683