18d5d45fbSJean Delvare /* 2*fbb6670dSGuenter Roeck * adm1031.c - Part of lm_sensors, Linux kernel modules for hardware 3*fbb6670dSGuenter Roeck * monitoring 4*fbb6670dSGuenter Roeck * Based on lm75.c and lm85.c 5*fbb6670dSGuenter Roeck * Supports adm1030 / adm1031 6*fbb6670dSGuenter Roeck * Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org> 7*fbb6670dSGuenter Roeck * Reworked by Jean Delvare <khali@linux-fr.org> 8*fbb6670dSGuenter Roeck * 9*fbb6670dSGuenter Roeck * This program is free software; you can redistribute it and/or modify 10*fbb6670dSGuenter Roeck * it under the terms of the GNU General Public License as published by 11*fbb6670dSGuenter Roeck * the Free Software Foundation; either version 2 of the License, or 12*fbb6670dSGuenter Roeck * (at your option) any later version. 13*fbb6670dSGuenter Roeck * 14*fbb6670dSGuenter Roeck * This program is distributed in the hope that it will be useful, 15*fbb6670dSGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 16*fbb6670dSGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*fbb6670dSGuenter Roeck * GNU General Public License for more details. 18*fbb6670dSGuenter Roeck * 19*fbb6670dSGuenter Roeck * You should have received a copy of the GNU General Public License 20*fbb6670dSGuenter Roeck * along with this program; if not, write to the Free Software 21*fbb6670dSGuenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 228d5d45fbSJean Delvare */ 238d5d45fbSJean Delvare 248d5d45fbSJean Delvare #include <linux/module.h> 258d5d45fbSJean Delvare #include <linux/init.h> 268d5d45fbSJean Delvare #include <linux/slab.h> 278d5d45fbSJean Delvare #include <linux/jiffies.h> 288d5d45fbSJean Delvare #include <linux/i2c.h> 29943b0830SMark M. Hoffman #include <linux/hwmon.h> 30c801082dSJean Delvare #include <linux/hwmon-sysfs.h> 31943b0830SMark M. Hoffman #include <linux/err.h> 329a61bf63SIngo Molnar #include <linux/mutex.h> 338d5d45fbSJean Delvare 348d5d45fbSJean Delvare /* Following macros takes channel parameter starting from 0 to 2 */ 358d5d45fbSJean Delvare #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) 368d5d45fbSJean Delvare #define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) 378d5d45fbSJean Delvare #define ADM1031_REG_PWM (0x22) 388d5d45fbSJean Delvare #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) 3987c33daaSJean Delvare #define ADM1031_REG_FAN_FILTER (0x23) 408d5d45fbSJean Delvare 4149dc9efeSIra Snyder #define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) 428d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) 438d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) 448d5d45fbSJean Delvare #define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) 458d5d45fbSJean Delvare 466d6006b8SJean Delvare #define ADM1031_REG_TEMP(nr) (0x0a + (nr)) 478d5d45fbSJean Delvare #define ADM1031_REG_AUTO_TEMP(nr) (0x24 + (nr)) 488d5d45fbSJean Delvare 498d5d45fbSJean Delvare #define ADM1031_REG_STATUS(nr) (0x2 + (nr)) 508d5d45fbSJean Delvare 516d6006b8SJean Delvare #define ADM1031_REG_CONF1 0x00 526d6006b8SJean Delvare #define ADM1031_REG_CONF2 0x01 536d6006b8SJean Delvare #define ADM1031_REG_EXT_TEMP 0x06 548d5d45fbSJean Delvare 558d5d45fbSJean Delvare #define ADM1031_CONF1_MONITOR_ENABLE 0x01 /* Monitoring enable */ 568d5d45fbSJean Delvare #define ADM1031_CONF1_PWM_INVERT 0x08 /* PWM Invert */ 578d5d45fbSJean Delvare #define ADM1031_CONF1_AUTO_MODE 0x80 /* Auto FAN */ 588d5d45fbSJean Delvare 598d5d45fbSJean Delvare #define ADM1031_CONF2_PWM1_ENABLE 0x01 608d5d45fbSJean Delvare #define ADM1031_CONF2_PWM2_ENABLE 0x02 618d5d45fbSJean Delvare #define ADM1031_CONF2_TACH1_ENABLE 0x04 628d5d45fbSJean Delvare #define ADM1031_CONF2_TACH2_ENABLE 0x08 638d5d45fbSJean Delvare #define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan)) 648d5d45fbSJean Delvare 6587c33daaSJean Delvare #define ADM1031_UPDATE_RATE_MASK 0x1c 6687c33daaSJean Delvare #define ADM1031_UPDATE_RATE_SHIFT 2 6787c33daaSJean Delvare 688d5d45fbSJean Delvare /* Addresses to scan */ 6925e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; 708d5d45fbSJean Delvare 71e5e9f44cSJean Delvare enum chips { adm1030, adm1031 }; 728d5d45fbSJean Delvare 738d5d45fbSJean Delvare typedef u8 auto_chan_table_t[8][2]; 748d5d45fbSJean Delvare 758d5d45fbSJean Delvare /* Each client has this additional data */ 768d5d45fbSJean Delvare struct adm1031_data { 771beeffe4STony Jones struct device *hwmon_dev; 789a61bf63SIngo Molnar struct mutex update_lock; 798d5d45fbSJean Delvare int chip_type; 808d5d45fbSJean Delvare char valid; /* !=0 if following fields are valid */ 818d5d45fbSJean Delvare unsigned long last_updated; /* In jiffies */ 82a51b9944SGuenter Roeck unsigned int update_interval; /* In milliseconds */ 83*fbb6670dSGuenter Roeck /* 84*fbb6670dSGuenter Roeck * The chan_select_table contains the possible configurations for 858d5d45fbSJean Delvare * auto fan control. 868d5d45fbSJean Delvare */ 876d6006b8SJean Delvare const auto_chan_table_t *chan_select_table; 888d5d45fbSJean Delvare u16 alarm; 898d5d45fbSJean Delvare u8 conf1; 908d5d45fbSJean Delvare u8 conf2; 918d5d45fbSJean Delvare u8 fan[2]; 928d5d45fbSJean Delvare u8 fan_div[2]; 938d5d45fbSJean Delvare u8 fan_min[2]; 948d5d45fbSJean Delvare u8 pwm[2]; 958d5d45fbSJean Delvare u8 old_pwm[2]; 968d5d45fbSJean Delvare s8 temp[3]; 978d5d45fbSJean Delvare u8 ext_temp[3]; 988d5d45fbSJean Delvare u8 auto_temp[3]; 998d5d45fbSJean Delvare u8 auto_temp_min[3]; 1008d5d45fbSJean Delvare u8 auto_temp_off[3]; 1018d5d45fbSJean Delvare u8 auto_temp_max[3]; 10249dc9efeSIra Snyder s8 temp_offset[3]; 1038d5d45fbSJean Delvare s8 temp_min[3]; 1048d5d45fbSJean Delvare s8 temp_max[3]; 1058d5d45fbSJean Delvare s8 temp_crit[3]; 1068d5d45fbSJean Delvare }; 1078d5d45fbSJean Delvare 108af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client, 109af200f88SJean Delvare const struct i2c_device_id *id); 110310ec792SJean Delvare static int adm1031_detect(struct i2c_client *client, 111af200f88SJean Delvare struct i2c_board_info *info); 1128d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client); 113af200f88SJean Delvare static int adm1031_remove(struct i2c_client *client); 1148d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev); 1158d5d45fbSJean Delvare 116af200f88SJean Delvare static const struct i2c_device_id adm1031_id[] = { 117af200f88SJean Delvare { "adm1030", adm1030 }, 118af200f88SJean Delvare { "adm1031", adm1031 }, 119af200f88SJean Delvare { } 120af200f88SJean Delvare }; 121af200f88SJean Delvare MODULE_DEVICE_TABLE(i2c, adm1031_id); 122af200f88SJean Delvare 1238d5d45fbSJean Delvare /* This is the driver that will be inserted */ 1248d5d45fbSJean Delvare static struct i2c_driver adm1031_driver = { 125af200f88SJean Delvare .class = I2C_CLASS_HWMON, 126cdaf7934SLaurent Riffard .driver = { 1278d5d45fbSJean Delvare .name = "adm1031", 128cdaf7934SLaurent Riffard }, 129af200f88SJean Delvare .probe = adm1031_probe, 130af200f88SJean Delvare .remove = adm1031_remove, 131af200f88SJean Delvare .id_table = adm1031_id, 132af200f88SJean Delvare .detect = adm1031_detect, 133c3813d6aSJean Delvare .address_list = normal_i2c, 1348d5d45fbSJean Delvare }; 1358d5d45fbSJean Delvare 1368d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) 1378d5d45fbSJean Delvare { 1388d5d45fbSJean Delvare return i2c_smbus_read_byte_data(client, reg); 1398d5d45fbSJean Delvare } 1408d5d45fbSJean Delvare 1418d5d45fbSJean Delvare static inline int 1428d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value) 1438d5d45fbSJean Delvare { 1448d5d45fbSJean Delvare return i2c_smbus_write_byte_data(client, reg, value); 1458d5d45fbSJean Delvare } 1468d5d45fbSJean Delvare 1478d5d45fbSJean Delvare 1488d5d45fbSJean Delvare #define TEMP_TO_REG(val) (((val) < 0 ? ((val - 500) / 1000) : \ 1498d5d45fbSJean Delvare ((val + 500) / 1000))) 1508d5d45fbSJean Delvare 1518d5d45fbSJean Delvare #define TEMP_FROM_REG(val) ((val) * 1000) 1528d5d45fbSJean Delvare 1538d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) 1548d5d45fbSJean Delvare 15549dc9efeSIra Snyder #define TEMP_OFFSET_TO_REG(val) (TEMP_TO_REG(val) & 0x8f) 15649dc9efeSIra Snyder #define TEMP_OFFSET_FROM_REG(val) TEMP_FROM_REG((val) < 0 ? \ 15749dc9efeSIra Snyder (val) | 0x70 : (val)) 15849dc9efeSIra Snyder 1591c720093SGuenter Roeck #define FAN_FROM_REG(reg, div) ((reg) ? \ 1601c720093SGuenter Roeck (11250 * 60) / ((reg) * (div)) : 0) 1618d5d45fbSJean Delvare 1628d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div) 1638d5d45fbSJean Delvare { 1648d5d45fbSJean Delvare int tmp; 1658d5d45fbSJean Delvare tmp = FAN_FROM_REG(SENSORS_LIMIT(reg, 0, 65535), div); 1668d5d45fbSJean Delvare return tmp > 255 ? 255 : tmp; 1678d5d45fbSJean Delvare } 1688d5d45fbSJean Delvare 1698d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg) (1<<(((reg)&0xc0)>>6)) 1708d5d45fbSJean Delvare 1718d5d45fbSJean Delvare #define PWM_TO_REG(val) (SENSORS_LIMIT((val), 0, 255) >> 4) 1728d5d45fbSJean Delvare #define PWM_FROM_REG(val) ((val) << 4) 1738d5d45fbSJean Delvare 1748d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg) (((reg) >> 5) & 7) 1758d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg) \ 1768d5d45fbSJean Delvare (((reg) & 0x1F) | (((val) << 5) & 0xe0)) 1778d5d45fbSJean Delvare 1788d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg) \ 1798d5d45fbSJean Delvare ((((val) / 500) & 0xf8) | ((reg) & 0x7)) 1808d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg) (5000 * (1 << ((reg) & 0x7))) 1818d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg) (1000 * ((((reg) >> 3) & 0x1f) << 2)) 1828d5d45fbSJean Delvare 1838d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg) ((((reg) >> 3) & 0x1f) << 2) 1848d5d45fbSJean Delvare 1858d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg) \ 1868d5d45fbSJean Delvare (AUTO_TEMP_MIN_FROM_REG(reg) - 5000) 1878d5d45fbSJean Delvare 1888d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg) \ 1898d5d45fbSJean Delvare (AUTO_TEMP_RANGE_FROM_REG(reg) + \ 1908d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG(reg)) 1918d5d45fbSJean Delvare 1928d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm) 1938d5d45fbSJean Delvare { 1948d5d45fbSJean Delvare int ret; 1958d5d45fbSJean Delvare int range = val - AUTO_TEMP_MIN_FROM_REG(reg); 1968d5d45fbSJean Delvare 1978d5d45fbSJean Delvare range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm); 1988d5d45fbSJean Delvare ret = ((reg & 0xf8) | 1998d5d45fbSJean Delvare (range < 10000 ? 0 : 2008d5d45fbSJean Delvare range < 20000 ? 1 : 2018d5d45fbSJean Delvare range < 40000 ? 2 : range < 80000 ? 3 : 4)); 2028d5d45fbSJean Delvare return ret; 2038d5d45fbSJean Delvare } 2048d5d45fbSJean Delvare 2058d5d45fbSJean Delvare /* FAN auto control */ 2068d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx) \ 2078d5d45fbSJean Delvare (*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2] 2088d5d45fbSJean Delvare 209*fbb6670dSGuenter Roeck /* 210*fbb6670dSGuenter Roeck * The tables below contains the possible values for the auto fan 2118d5d45fbSJean Delvare * control bitfields. the index in the table is the register value. 2128d5d45fbSJean Delvare * MSb is the auto fan control enable bit, so the four first entries 2138d5d45fbSJean Delvare * in the table disables auto fan control when both bitfields are zero. 2148d5d45fbSJean Delvare */ 2156d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = { 2168d5d45fbSJean Delvare { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2178d5d45fbSJean Delvare { 2 /* 0b010 */ , 4 /* 0b100 */ }, 2188d5d45fbSJean Delvare { 2 /* 0b010 */ , 2 /* 0b010 */ }, 2198d5d45fbSJean Delvare { 4 /* 0b100 */ , 4 /* 0b100 */ }, 2208d5d45fbSJean Delvare { 7 /* 0b111 */ , 7 /* 0b111 */ }, 2218d5d45fbSJean Delvare }; 2228d5d45fbSJean Delvare 2236d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = { 2248d5d45fbSJean Delvare { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2258d5d45fbSJean Delvare { 2 /* 0b10 */ , 0 }, 2268d5d45fbSJean Delvare { 0xff /* invalid */ , 0 }, 2278d5d45fbSJean Delvare { 0xff /* invalid */ , 0 }, 2288d5d45fbSJean Delvare { 3 /* 0b11 */ , 0 }, 2298d5d45fbSJean Delvare }; 2308d5d45fbSJean Delvare 231*fbb6670dSGuenter Roeck /* 232*fbb6670dSGuenter Roeck * That function checks if a bitfield is valid and returns the other bitfield 2338d5d45fbSJean Delvare * nearest match if no exact match where found. 2348d5d45fbSJean Delvare */ 2358d5d45fbSJean Delvare static int 2368d5d45fbSJean Delvare get_fan_auto_nearest(struct adm1031_data *data, 2378d5d45fbSJean Delvare int chan, u8 val, u8 reg, u8 *new_reg) 2388d5d45fbSJean Delvare { 2398d5d45fbSJean Delvare int i; 2408d5d45fbSJean Delvare int first_match = -1, exact_match = -1; 2418d5d45fbSJean Delvare u8 other_reg_val = 2428d5d45fbSJean Delvare (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1]; 2438d5d45fbSJean Delvare 2448d5d45fbSJean Delvare if (val == 0) { 2458d5d45fbSJean Delvare *new_reg = 0; 2468d5d45fbSJean Delvare return 0; 2478d5d45fbSJean Delvare } 2488d5d45fbSJean Delvare 2498d5d45fbSJean Delvare for (i = 0; i < 8; i++) { 2508d5d45fbSJean Delvare if ((val == (*data->chan_select_table)[i][chan]) && 2518d5d45fbSJean Delvare ((*data->chan_select_table)[i][chan ? 0 : 1] == 2528d5d45fbSJean Delvare other_reg_val)) { 2538d5d45fbSJean Delvare /* We found an exact match */ 2548d5d45fbSJean Delvare exact_match = i; 2558d5d45fbSJean Delvare break; 2568d5d45fbSJean Delvare } else if (val == (*data->chan_select_table)[i][chan] && 2578d5d45fbSJean Delvare first_match == -1) { 258*fbb6670dSGuenter Roeck /* 259*fbb6670dSGuenter Roeck * Save the first match in case of an exact match has 2606d6006b8SJean Delvare * not been found 2618d5d45fbSJean Delvare */ 2628d5d45fbSJean Delvare first_match = i; 2638d5d45fbSJean Delvare } 2648d5d45fbSJean Delvare } 2658d5d45fbSJean Delvare 2661c720093SGuenter Roeck if (exact_match >= 0) 2678d5d45fbSJean Delvare *new_reg = exact_match; 2681c720093SGuenter Roeck else if (first_match >= 0) 2698d5d45fbSJean Delvare *new_reg = first_match; 2701c720093SGuenter Roeck else 2718d5d45fbSJean Delvare return -EINVAL; 2721c720093SGuenter Roeck 2738d5d45fbSJean Delvare return 0; 2748d5d45fbSJean Delvare } 2758d5d45fbSJean Delvare 276c801082dSJean Delvare static ssize_t show_fan_auto_channel(struct device *dev, 277c801082dSJean Delvare struct device_attribute *attr, char *buf) 2788d5d45fbSJean Delvare { 279c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 2808d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 2818d5d45fbSJean Delvare return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr)); 2828d5d45fbSJean Delvare } 2838d5d45fbSJean Delvare 2848d5d45fbSJean Delvare static ssize_t 285c801082dSJean Delvare set_fan_auto_channel(struct device *dev, struct device_attribute *attr, 286c801082dSJean Delvare const char *buf, size_t count) 2878d5d45fbSJean Delvare { 2888d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 2898d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 290c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 2911c720093SGuenter Roeck long val; 2928d5d45fbSJean Delvare u8 reg; 2938d5d45fbSJean Delvare int ret; 2948d5d45fbSJean Delvare u8 old_fan_mode; 2958d5d45fbSJean Delvare 2961c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 2971c720093SGuenter Roeck if (ret) 2981c720093SGuenter Roeck return ret; 2991c720093SGuenter Roeck 3008d5d45fbSJean Delvare old_fan_mode = data->conf1; 3018d5d45fbSJean Delvare 3029a61bf63SIngo Molnar mutex_lock(&data->update_lock); 3038d5d45fbSJean Delvare 3041c720093SGuenter Roeck ret = get_fan_auto_nearest(data, nr, val, data->conf1, ®); 3051c720093SGuenter Roeck if (ret) { 3069a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 3078d5d45fbSJean Delvare return ret; 3088d5d45fbSJean Delvare } 3096d6006b8SJean Delvare data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); 3106d6006b8SJean Delvare if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^ 3118d5d45fbSJean Delvare (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) { 3128d5d45fbSJean Delvare if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { 313*fbb6670dSGuenter Roeck /* 314*fbb6670dSGuenter Roeck * Switch to Auto Fan Mode 3158d5d45fbSJean Delvare * Save PWM registers 316*fbb6670dSGuenter Roeck * Set PWM registers to 33% Both 317*fbb6670dSGuenter Roeck */ 3188d5d45fbSJean Delvare data->old_pwm[0] = data->pwm[0]; 3198d5d45fbSJean Delvare data->old_pwm[1] = data->pwm[1]; 3208d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_PWM, 0x55); 3218d5d45fbSJean Delvare } else { 3228d5d45fbSJean Delvare /* Switch to Manual Mode */ 3238d5d45fbSJean Delvare data->pwm[0] = data->old_pwm[0]; 3248d5d45fbSJean Delvare data->pwm[1] = data->old_pwm[1]; 3258d5d45fbSJean Delvare /* Restore PWM registers */ 3268d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_PWM, 3278d5d45fbSJean Delvare data->pwm[0] | (data->pwm[1] << 4)); 3288d5d45fbSJean Delvare } 3298d5d45fbSJean Delvare } 3308d5d45fbSJean Delvare data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); 3318d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); 3329a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 3338d5d45fbSJean Delvare return count; 3348d5d45fbSJean Delvare } 3358d5d45fbSJean Delvare 336c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_channel, S_IRUGO | S_IWUSR, 337c801082dSJean Delvare show_fan_auto_channel, set_fan_auto_channel, 0); 338c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_channel, S_IRUGO | S_IWUSR, 339c801082dSJean Delvare show_fan_auto_channel, set_fan_auto_channel, 1); 3408d5d45fbSJean Delvare 3418d5d45fbSJean Delvare /* Auto Temps */ 342c801082dSJean Delvare static ssize_t show_auto_temp_off(struct device *dev, 343c801082dSJean Delvare struct device_attribute *attr, char *buf) 3448d5d45fbSJean Delvare { 345c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3468d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 3478d5d45fbSJean Delvare return sprintf(buf, "%d\n", 3488d5d45fbSJean Delvare AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr])); 3498d5d45fbSJean Delvare } 350c801082dSJean Delvare static ssize_t show_auto_temp_min(struct device *dev, 351c801082dSJean Delvare struct device_attribute *attr, char *buf) 3528d5d45fbSJean Delvare { 353c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3548d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 3558d5d45fbSJean Delvare return sprintf(buf, "%d\n", 3568d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr])); 3578d5d45fbSJean Delvare } 3588d5d45fbSJean Delvare static ssize_t 359c801082dSJean Delvare set_auto_temp_min(struct device *dev, struct device_attribute *attr, 360c801082dSJean Delvare const char *buf, size_t count) 3618d5d45fbSJean Delvare { 3628d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 3638d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 364c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3651c720093SGuenter Roeck long val; 3661c720093SGuenter Roeck int ret; 3671c720093SGuenter Roeck 3681c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 3691c720093SGuenter Roeck if (ret) 3701c720093SGuenter Roeck return ret; 3718d5d45fbSJean Delvare 3729a61bf63SIngo Molnar mutex_lock(&data->update_lock); 3738d5d45fbSJean Delvare data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); 3748d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), 3758d5d45fbSJean Delvare data->auto_temp[nr]); 3769a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 3778d5d45fbSJean Delvare return count; 3788d5d45fbSJean Delvare } 379c801082dSJean Delvare static ssize_t show_auto_temp_max(struct device *dev, 380c801082dSJean Delvare struct device_attribute *attr, char *buf) 3818d5d45fbSJean Delvare { 382c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3838d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 3848d5d45fbSJean Delvare return sprintf(buf, "%d\n", 3858d5d45fbSJean Delvare AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr])); 3868d5d45fbSJean Delvare } 3878d5d45fbSJean Delvare static ssize_t 388c801082dSJean Delvare set_auto_temp_max(struct device *dev, struct device_attribute *attr, 389c801082dSJean Delvare const char *buf, size_t count) 3908d5d45fbSJean Delvare { 3918d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 3928d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 393c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3941c720093SGuenter Roeck long val; 3951c720093SGuenter Roeck int ret; 3961c720093SGuenter Roeck 3971c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 3981c720093SGuenter Roeck if (ret) 3991c720093SGuenter Roeck return ret; 4008d5d45fbSJean Delvare 4019a61bf63SIngo Molnar mutex_lock(&data->update_lock); 4021c720093SGuenter Roeck data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], 4031c720093SGuenter Roeck data->pwm[nr]); 4048d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), 4058d5d45fbSJean Delvare data->temp_max[nr]); 4069a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 4078d5d45fbSJean Delvare return count; 4088d5d45fbSJean Delvare } 4098d5d45fbSJean Delvare 4108d5d45fbSJean Delvare #define auto_temp_reg(offset) \ 411c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO, \ 412c801082dSJean Delvare show_auto_temp_off, NULL, offset - 1); \ 413c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR, \ 414c801082dSJean Delvare show_auto_temp_min, set_auto_temp_min, offset - 1); \ 415c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR, \ 416c801082dSJean Delvare show_auto_temp_max, set_auto_temp_max, offset - 1) 4178d5d45fbSJean Delvare 4188d5d45fbSJean Delvare auto_temp_reg(1); 4198d5d45fbSJean Delvare auto_temp_reg(2); 4208d5d45fbSJean Delvare auto_temp_reg(3); 4218d5d45fbSJean Delvare 4228d5d45fbSJean Delvare /* pwm */ 423c801082dSJean Delvare static ssize_t show_pwm(struct device *dev, 424c801082dSJean Delvare struct device_attribute *attr, char *buf) 4258d5d45fbSJean Delvare { 426c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4278d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 4288d5d45fbSJean Delvare return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); 4298d5d45fbSJean Delvare } 430c801082dSJean Delvare static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, 431c801082dSJean Delvare const char *buf, size_t count) 4328d5d45fbSJean Delvare { 4338d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 4348d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 435c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 4361c720093SGuenter Roeck long val; 4371c720093SGuenter Roeck int ret, reg; 4381c720093SGuenter Roeck 4391c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 4401c720093SGuenter Roeck if (ret) 4411c720093SGuenter Roeck return ret; 4428d5d45fbSJean Delvare 4439a61bf63SIngo Molnar mutex_lock(&data->update_lock); 4448d5d45fbSJean Delvare if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && 4458d5d45fbSJean Delvare (((val>>4) & 0xf) != 5)) { 4468d5d45fbSJean Delvare /* In automatic mode, the only PWM accepted is 33% */ 4479a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 4488d5d45fbSJean Delvare return -EINVAL; 4498d5d45fbSJean Delvare } 4508d5d45fbSJean Delvare data->pwm[nr] = PWM_TO_REG(val); 4518d5d45fbSJean Delvare reg = adm1031_read_value(client, ADM1031_REG_PWM); 4528d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_PWM, 4538d5d45fbSJean Delvare nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) 4548d5d45fbSJean Delvare : (data->pwm[nr] & 0xf) | (reg & 0xf0)); 4559a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 4568d5d45fbSJean Delvare return count; 4578d5d45fbSJean Delvare } 4588d5d45fbSJean Delvare 459c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0); 460c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1); 461c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_min_pwm, S_IRUGO | S_IWUSR, 462c801082dSJean Delvare show_pwm, set_pwm, 0); 463c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_min_pwm, S_IRUGO | S_IWUSR, 464c801082dSJean Delvare show_pwm, set_pwm, 1); 4658d5d45fbSJean Delvare 4668d5d45fbSJean Delvare /* Fans */ 4678d5d45fbSJean Delvare 4688d5d45fbSJean Delvare /* 4698d5d45fbSJean Delvare * That function checks the cases where the fan reading is not 4708d5d45fbSJean Delvare * relevant. It is used to provide 0 as fan reading when the fan is 4718d5d45fbSJean Delvare * not supposed to run 4728d5d45fbSJean Delvare */ 4738d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan) 4748d5d45fbSJean Delvare { 4758d5d45fbSJean Delvare int res = 0; 4768d5d45fbSJean Delvare 4778d5d45fbSJean Delvare if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { 4788d5d45fbSJean Delvare switch (data->conf1 & 0x60) { 4791c720093SGuenter Roeck case 0x00: 4801c720093SGuenter Roeck /* 4811c720093SGuenter Roeck * remote temp1 controls fan1, 4821c720093SGuenter Roeck * remote temp2 controls fan2 4831c720093SGuenter Roeck */ 4848d5d45fbSJean Delvare res = data->temp[chan+1] >= 4858d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]); 4868d5d45fbSJean Delvare break; 4878d5d45fbSJean Delvare case 0x20: /* remote temp1 controls both fans */ 4888d5d45fbSJean Delvare res = 4898d5d45fbSJean Delvare data->temp[1] >= 4908d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]); 4918d5d45fbSJean Delvare break; 4928d5d45fbSJean Delvare case 0x40: /* remote temp2 controls both fans */ 4938d5d45fbSJean Delvare res = 4948d5d45fbSJean Delvare data->temp[2] >= 4958d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]); 4968d5d45fbSJean Delvare break; 4978d5d45fbSJean Delvare case 0x60: /* max controls both fans */ 4988d5d45fbSJean Delvare res = 4998d5d45fbSJean Delvare data->temp[0] >= 5008d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0]) 5018d5d45fbSJean Delvare || data->temp[1] >= 5028d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]) 5038d5d45fbSJean Delvare || (data->chip_type == adm1031 5048d5d45fbSJean Delvare && data->temp[2] >= 5058d5d45fbSJean Delvare AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2])); 5068d5d45fbSJean Delvare break; 5078d5d45fbSJean Delvare } 5088d5d45fbSJean Delvare } else { 5098d5d45fbSJean Delvare res = data->pwm[chan] > 0; 5108d5d45fbSJean Delvare } 5118d5d45fbSJean Delvare return res; 5128d5d45fbSJean Delvare } 5138d5d45fbSJean Delvare 5148d5d45fbSJean Delvare 515c801082dSJean Delvare static ssize_t show_fan(struct device *dev, 516c801082dSJean Delvare struct device_attribute *attr, char *buf) 5178d5d45fbSJean Delvare { 518c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5198d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 5208d5d45fbSJean Delvare int value; 5218d5d45fbSJean Delvare 5228d5d45fbSJean Delvare value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr], 5238d5d45fbSJean Delvare FAN_DIV_FROM_REG(data->fan_div[nr])) : 0; 5248d5d45fbSJean Delvare return sprintf(buf, "%d\n", value); 5258d5d45fbSJean Delvare } 5268d5d45fbSJean Delvare 527c801082dSJean Delvare static ssize_t show_fan_div(struct device *dev, 528c801082dSJean Delvare struct device_attribute *attr, char *buf) 5298d5d45fbSJean Delvare { 530c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5318d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 5328d5d45fbSJean Delvare return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr])); 5338d5d45fbSJean Delvare } 534c801082dSJean Delvare static ssize_t show_fan_min(struct device *dev, 535c801082dSJean Delvare struct device_attribute *attr, char *buf) 5368d5d45fbSJean Delvare { 537c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5388d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 5398d5d45fbSJean Delvare return sprintf(buf, "%d\n", 5408d5d45fbSJean Delvare FAN_FROM_REG(data->fan_min[nr], 5418d5d45fbSJean Delvare FAN_DIV_FROM_REG(data->fan_div[nr]))); 5428d5d45fbSJean Delvare } 543c801082dSJean Delvare static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, 544c801082dSJean Delvare const char *buf, size_t count) 5458d5d45fbSJean Delvare { 5468d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 5478d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 548c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5491c720093SGuenter Roeck long val; 5501c720093SGuenter Roeck int ret; 5511c720093SGuenter Roeck 5521c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 5531c720093SGuenter Roeck if (ret) 5541c720093SGuenter Roeck return ret; 5558d5d45fbSJean Delvare 5569a61bf63SIngo Molnar mutex_lock(&data->update_lock); 5578d5d45fbSJean Delvare if (val) { 5588d5d45fbSJean Delvare data->fan_min[nr] = 5598d5d45fbSJean Delvare FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); 5608d5d45fbSJean Delvare } else { 5618d5d45fbSJean Delvare data->fan_min[nr] = 0xff; 5628d5d45fbSJean Delvare } 5638d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); 5649a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 5658d5d45fbSJean Delvare return count; 5668d5d45fbSJean Delvare } 567c801082dSJean Delvare static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, 568c801082dSJean Delvare const char *buf, size_t count) 5698d5d45fbSJean Delvare { 5708d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 5718d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 572c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 5731c720093SGuenter Roeck long val; 5748d5d45fbSJean Delvare u8 tmp; 5758d5d45fbSJean Delvare int old_div; 5768d5d45fbSJean Delvare int new_min; 5771c720093SGuenter Roeck int ret; 5781c720093SGuenter Roeck 5791c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 5801c720093SGuenter Roeck if (ret) 5811c720093SGuenter Roeck return ret; 5828d5d45fbSJean Delvare 5838d5d45fbSJean Delvare tmp = val == 8 ? 0xc0 : 5848d5d45fbSJean Delvare val == 4 ? 0x80 : 5858d5d45fbSJean Delvare val == 2 ? 0x40 : 5868d5d45fbSJean Delvare val == 1 ? 0x00 : 5878d5d45fbSJean Delvare 0xff; 5888d5d45fbSJean Delvare if (tmp == 0xff) 5898d5d45fbSJean Delvare return -EINVAL; 5908d5d45fbSJean Delvare 5919a61bf63SIngo Molnar mutex_lock(&data->update_lock); 59238a1f0e9SJean Delvare /* Get fresh readings */ 59338a1f0e9SJean Delvare data->fan_div[nr] = adm1031_read_value(client, 59438a1f0e9SJean Delvare ADM1031_REG_FAN_DIV(nr)); 59538a1f0e9SJean Delvare data->fan_min[nr] = adm1031_read_value(client, 59638a1f0e9SJean Delvare ADM1031_REG_FAN_MIN(nr)); 59738a1f0e9SJean Delvare 59838a1f0e9SJean Delvare /* Write the new clock divider and fan min */ 5998d5d45fbSJean Delvare old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); 6006d6006b8SJean Delvare data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]); 6016d6006b8SJean Delvare new_min = data->fan_min[nr] * old_div / val; 6028d5d45fbSJean Delvare data->fan_min[nr] = new_min > 0xff ? 0xff : new_min; 6038d5d45fbSJean Delvare 6048d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr), 6058d5d45fbSJean Delvare data->fan_div[nr]); 6068d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), 6078d5d45fbSJean Delvare data->fan_min[nr]); 60838a1f0e9SJean Delvare 60938a1f0e9SJean Delvare /* Invalidate the cache: fan speed is no longer valid */ 61038a1f0e9SJean Delvare data->valid = 0; 6119a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 6128d5d45fbSJean Delvare return count; 6138d5d45fbSJean Delvare } 6148d5d45fbSJean Delvare 6158d5d45fbSJean Delvare #define fan_offset(offset) \ 616c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ 617c801082dSJean Delvare show_fan, NULL, offset - 1); \ 618c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ 619c801082dSJean Delvare show_fan_min, set_fan_min, offset - 1); \ 620c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ 621c801082dSJean Delvare show_fan_div, set_fan_div, offset - 1) 6228d5d45fbSJean Delvare 6238d5d45fbSJean Delvare fan_offset(1); 6248d5d45fbSJean Delvare fan_offset(2); 6258d5d45fbSJean Delvare 6268d5d45fbSJean Delvare 6278d5d45fbSJean Delvare /* Temps */ 628c801082dSJean Delvare static ssize_t show_temp(struct device *dev, 629c801082dSJean Delvare struct device_attribute *attr, char *buf) 6308d5d45fbSJean Delvare { 631c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6328d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 6338d5d45fbSJean Delvare int ext; 6348d5d45fbSJean Delvare ext = nr == 0 ? 6358d5d45fbSJean Delvare ((data->ext_temp[nr] >> 6) & 0x3) * 2 : 6368d5d45fbSJean Delvare (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); 6378d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); 6388d5d45fbSJean Delvare } 63949dc9efeSIra Snyder static ssize_t show_temp_offset(struct device *dev, 64049dc9efeSIra Snyder struct device_attribute *attr, char *buf) 64149dc9efeSIra Snyder { 64249dc9efeSIra Snyder int nr = to_sensor_dev_attr(attr)->index; 64349dc9efeSIra Snyder struct adm1031_data *data = adm1031_update_device(dev); 64449dc9efeSIra Snyder return sprintf(buf, "%d\n", 64549dc9efeSIra Snyder TEMP_OFFSET_FROM_REG(data->temp_offset[nr])); 64649dc9efeSIra Snyder } 647c801082dSJean Delvare static ssize_t show_temp_min(struct device *dev, 648c801082dSJean Delvare struct device_attribute *attr, char *buf) 6498d5d45fbSJean Delvare { 650c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6518d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 6528d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); 6538d5d45fbSJean Delvare } 654c801082dSJean Delvare static ssize_t show_temp_max(struct device *dev, 655c801082dSJean Delvare struct device_attribute *attr, char *buf) 6568d5d45fbSJean Delvare { 657c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6588d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 6598d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); 6608d5d45fbSJean Delvare } 661c801082dSJean Delvare static ssize_t show_temp_crit(struct device *dev, 662c801082dSJean Delvare struct device_attribute *attr, char *buf) 6638d5d45fbSJean Delvare { 664c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6658d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 6668d5d45fbSJean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); 6678d5d45fbSJean Delvare } 66849dc9efeSIra Snyder static ssize_t set_temp_offset(struct device *dev, 66949dc9efeSIra Snyder struct device_attribute *attr, const char *buf, 67049dc9efeSIra Snyder size_t count) 67149dc9efeSIra Snyder { 67249dc9efeSIra Snyder struct i2c_client *client = to_i2c_client(dev); 67349dc9efeSIra Snyder struct adm1031_data *data = i2c_get_clientdata(client); 67449dc9efeSIra Snyder int nr = to_sensor_dev_attr(attr)->index; 6751c720093SGuenter Roeck long val; 6761c720093SGuenter Roeck int ret; 67749dc9efeSIra Snyder 6781c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 6791c720093SGuenter Roeck if (ret) 6801c720093SGuenter Roeck return ret; 6811c720093SGuenter Roeck 68249dc9efeSIra Snyder val = SENSORS_LIMIT(val, -15000, 15000); 68349dc9efeSIra Snyder mutex_lock(&data->update_lock); 68449dc9efeSIra Snyder data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val); 68549dc9efeSIra Snyder adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr), 68649dc9efeSIra Snyder data->temp_offset[nr]); 68749dc9efeSIra Snyder mutex_unlock(&data->update_lock); 68849dc9efeSIra Snyder return count; 68949dc9efeSIra Snyder } 690c801082dSJean Delvare static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, 691c801082dSJean Delvare const char *buf, size_t count) 6928d5d45fbSJean Delvare { 6938d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 6948d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 695c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 6961c720093SGuenter Roeck long val; 6971c720093SGuenter Roeck int ret; 6988d5d45fbSJean Delvare 6991c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 7001c720093SGuenter Roeck if (ret) 7011c720093SGuenter Roeck return ret; 7021c720093SGuenter Roeck 7038d5d45fbSJean Delvare val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); 7049a61bf63SIngo Molnar mutex_lock(&data->update_lock); 7058d5d45fbSJean Delvare data->temp_min[nr] = TEMP_TO_REG(val); 7068d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), 7078d5d45fbSJean Delvare data->temp_min[nr]); 7089a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7098d5d45fbSJean Delvare return count; 7108d5d45fbSJean Delvare } 711c801082dSJean Delvare static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, 712c801082dSJean Delvare const char *buf, size_t count) 7138d5d45fbSJean Delvare { 7148d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 7158d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 716c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7171c720093SGuenter Roeck long val; 7181c720093SGuenter Roeck int ret; 7198d5d45fbSJean Delvare 7201c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 7211c720093SGuenter Roeck if (ret) 7221c720093SGuenter Roeck return ret; 7231c720093SGuenter Roeck 7248d5d45fbSJean Delvare val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); 7259a61bf63SIngo Molnar mutex_lock(&data->update_lock); 7268d5d45fbSJean Delvare data->temp_max[nr] = TEMP_TO_REG(val); 7278d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), 7288d5d45fbSJean Delvare data->temp_max[nr]); 7299a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7308d5d45fbSJean Delvare return count; 7318d5d45fbSJean Delvare } 732c801082dSJean Delvare static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, 733c801082dSJean Delvare const char *buf, size_t count) 7348d5d45fbSJean Delvare { 7358d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 7368d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 737c801082dSJean Delvare int nr = to_sensor_dev_attr(attr)->index; 7381c720093SGuenter Roeck long val; 7391c720093SGuenter Roeck int ret; 7408d5d45fbSJean Delvare 7411c720093SGuenter Roeck ret = kstrtol(buf, 10, &val); 7421c720093SGuenter Roeck if (ret) 7431c720093SGuenter Roeck return ret; 7441c720093SGuenter Roeck 7458d5d45fbSJean Delvare val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); 7469a61bf63SIngo Molnar mutex_lock(&data->update_lock); 7478d5d45fbSJean Delvare data->temp_crit[nr] = TEMP_TO_REG(val); 7488d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), 7498d5d45fbSJean Delvare data->temp_crit[nr]); 7509a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7518d5d45fbSJean Delvare return count; 7528d5d45fbSJean Delvare } 7538d5d45fbSJean Delvare 7548d5d45fbSJean Delvare #define temp_reg(offset) \ 755c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ 756c801082dSJean Delvare show_temp, NULL, offset - 1); \ 75749dc9efeSIra Snyder static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \ 75849dc9efeSIra Snyder show_temp_offset, set_temp_offset, offset - 1); \ 759c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ 760c801082dSJean Delvare show_temp_min, set_temp_min, offset - 1); \ 761c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ 762c801082dSJean Delvare show_temp_max, set_temp_max, offset - 1); \ 763c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \ 764c801082dSJean Delvare show_temp_crit, set_temp_crit, offset - 1) 7658d5d45fbSJean Delvare 7668d5d45fbSJean Delvare temp_reg(1); 7678d5d45fbSJean Delvare temp_reg(2); 7688d5d45fbSJean Delvare temp_reg(3); 7698d5d45fbSJean Delvare 7708d5d45fbSJean Delvare /* Alarms */ 7711c720093SGuenter Roeck static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, 7721c720093SGuenter Roeck char *buf) 7738d5d45fbSJean Delvare { 7748d5d45fbSJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 7758d5d45fbSJean Delvare return sprintf(buf, "%d\n", data->alarm); 7768d5d45fbSJean Delvare } 7778d5d45fbSJean Delvare 7788d5d45fbSJean Delvare static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 7798d5d45fbSJean Delvare 780050ab878SJean Delvare static ssize_t show_alarm(struct device *dev, 781050ab878SJean Delvare struct device_attribute *attr, char *buf) 782050ab878SJean Delvare { 783050ab878SJean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 784050ab878SJean Delvare struct adm1031_data *data = adm1031_update_device(dev); 785050ab878SJean Delvare return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1); 786050ab878SJean Delvare } 787050ab878SJean Delvare 788050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0); 789050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1); 790050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2); 791050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); 792050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 4); 793050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 5); 794050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); 795050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 7); 796050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 8); 797050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 9); 798050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 10); 799050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11); 800050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12); 801050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); 802050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); 8038d5d45fbSJean Delvare 804a51b9944SGuenter Roeck /* Update Interval */ 805a51b9944SGuenter Roeck static const unsigned int update_intervals[] = { 80687c33daaSJean Delvare 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 80787c33daaSJean Delvare }; 80887c33daaSJean Delvare 809a51b9944SGuenter Roeck static ssize_t show_update_interval(struct device *dev, 81087c33daaSJean Delvare struct device_attribute *attr, char *buf) 81187c33daaSJean Delvare { 81287c33daaSJean Delvare struct i2c_client *client = to_i2c_client(dev); 81387c33daaSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 81487c33daaSJean Delvare 815a51b9944SGuenter Roeck return sprintf(buf, "%u\n", data->update_interval); 81687c33daaSJean Delvare } 81787c33daaSJean Delvare 818a51b9944SGuenter Roeck static ssize_t set_update_interval(struct device *dev, 81987c33daaSJean Delvare struct device_attribute *attr, 82087c33daaSJean Delvare const char *buf, size_t count) 82187c33daaSJean Delvare { 82287c33daaSJean Delvare struct i2c_client *client = to_i2c_client(dev); 82387c33daaSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 82487c33daaSJean Delvare unsigned long val; 82587c33daaSJean Delvare int i, err; 82687c33daaSJean Delvare u8 reg; 82787c33daaSJean Delvare 828179c4fdbSFrans Meulenbroeks err = kstrtoul(buf, 10, &val); 82987c33daaSJean Delvare if (err) 83087c33daaSJean Delvare return err; 83187c33daaSJean Delvare 832a51b9944SGuenter Roeck /* 833a51b9944SGuenter Roeck * Find the nearest update interval from the table. 834a51b9944SGuenter Roeck * Use it to determine the matching update rate. 835a51b9944SGuenter Roeck */ 836a51b9944SGuenter Roeck for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) { 837a51b9944SGuenter Roeck if (val >= update_intervals[i]) 83887c33daaSJean Delvare break; 83987c33daaSJean Delvare } 840a51b9944SGuenter Roeck /* if not found, we point to the last entry (lowest update interval) */ 84187c33daaSJean Delvare 84287c33daaSJean Delvare /* set the new update rate while preserving other settings */ 84387c33daaSJean Delvare reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); 84487c33daaSJean Delvare reg &= ~ADM1031_UPDATE_RATE_MASK; 84587c33daaSJean Delvare reg |= i << ADM1031_UPDATE_RATE_SHIFT; 84687c33daaSJean Delvare adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg); 84787c33daaSJean Delvare 84887c33daaSJean Delvare mutex_lock(&data->update_lock); 849a51b9944SGuenter Roeck data->update_interval = update_intervals[i]; 85087c33daaSJean Delvare mutex_unlock(&data->update_lock); 85187c33daaSJean Delvare 85287c33daaSJean Delvare return count; 85387c33daaSJean Delvare } 85487c33daaSJean Delvare 855a51b9944SGuenter Roeck static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval, 856a51b9944SGuenter Roeck set_update_interval); 85787c33daaSJean Delvare 858681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = { 859c801082dSJean Delvare &sensor_dev_attr_fan1_input.dev_attr.attr, 860c801082dSJean Delvare &sensor_dev_attr_fan1_div.dev_attr.attr, 861c801082dSJean Delvare &sensor_dev_attr_fan1_min.dev_attr.attr, 862050ab878SJean Delvare &sensor_dev_attr_fan1_alarm.dev_attr.attr, 863050ab878SJean Delvare &sensor_dev_attr_fan1_fault.dev_attr.attr, 864c801082dSJean Delvare &sensor_dev_attr_pwm1.dev_attr.attr, 865c801082dSJean Delvare &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, 866c801082dSJean Delvare &sensor_dev_attr_temp1_input.dev_attr.attr, 86749dc9efeSIra Snyder &sensor_dev_attr_temp1_offset.dev_attr.attr, 868c801082dSJean Delvare &sensor_dev_attr_temp1_min.dev_attr.attr, 869050ab878SJean Delvare &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 870c801082dSJean Delvare &sensor_dev_attr_temp1_max.dev_attr.attr, 871050ab878SJean Delvare &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 872c801082dSJean Delvare &sensor_dev_attr_temp1_crit.dev_attr.attr, 873050ab878SJean Delvare &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 874c801082dSJean Delvare &sensor_dev_attr_temp2_input.dev_attr.attr, 87549dc9efeSIra Snyder &sensor_dev_attr_temp2_offset.dev_attr.attr, 876c801082dSJean Delvare &sensor_dev_attr_temp2_min.dev_attr.attr, 877050ab878SJean Delvare &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, 878c801082dSJean Delvare &sensor_dev_attr_temp2_max.dev_attr.attr, 879050ab878SJean Delvare &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, 880c801082dSJean Delvare &sensor_dev_attr_temp2_crit.dev_attr.attr, 881050ab878SJean Delvare &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, 882050ab878SJean Delvare &sensor_dev_attr_temp2_fault.dev_attr.attr, 883681c6f7aSMark M. Hoffman 884c801082dSJean Delvare &sensor_dev_attr_auto_temp1_off.dev_attr.attr, 885c801082dSJean Delvare &sensor_dev_attr_auto_temp1_min.dev_attr.attr, 886c801082dSJean Delvare &sensor_dev_attr_auto_temp1_max.dev_attr.attr, 887681c6f7aSMark M. Hoffman 888c801082dSJean Delvare &sensor_dev_attr_auto_temp2_off.dev_attr.attr, 889c801082dSJean Delvare &sensor_dev_attr_auto_temp2_min.dev_attr.attr, 890c801082dSJean Delvare &sensor_dev_attr_auto_temp2_max.dev_attr.attr, 891681c6f7aSMark M. Hoffman 892c801082dSJean Delvare &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, 893681c6f7aSMark M. Hoffman 894a51b9944SGuenter Roeck &dev_attr_update_interval.attr, 895681c6f7aSMark M. Hoffman &dev_attr_alarms.attr, 896681c6f7aSMark M. Hoffman 897681c6f7aSMark M. Hoffman NULL 898681c6f7aSMark M. Hoffman }; 899681c6f7aSMark M. Hoffman 900681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = { 901681c6f7aSMark M. Hoffman .attrs = adm1031_attributes, 902681c6f7aSMark M. Hoffman }; 903681c6f7aSMark M. Hoffman 904681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = { 905c801082dSJean Delvare &sensor_dev_attr_fan2_input.dev_attr.attr, 906c801082dSJean Delvare &sensor_dev_attr_fan2_div.dev_attr.attr, 907c801082dSJean Delvare &sensor_dev_attr_fan2_min.dev_attr.attr, 908050ab878SJean Delvare &sensor_dev_attr_fan2_alarm.dev_attr.attr, 909050ab878SJean Delvare &sensor_dev_attr_fan2_fault.dev_attr.attr, 910c801082dSJean Delvare &sensor_dev_attr_pwm2.dev_attr.attr, 911c801082dSJean Delvare &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, 912c801082dSJean Delvare &sensor_dev_attr_temp3_input.dev_attr.attr, 91349dc9efeSIra Snyder &sensor_dev_attr_temp3_offset.dev_attr.attr, 914c801082dSJean Delvare &sensor_dev_attr_temp3_min.dev_attr.attr, 915050ab878SJean Delvare &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, 916c801082dSJean Delvare &sensor_dev_attr_temp3_max.dev_attr.attr, 917050ab878SJean Delvare &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, 918c801082dSJean Delvare &sensor_dev_attr_temp3_crit.dev_attr.attr, 919050ab878SJean Delvare &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, 920050ab878SJean Delvare &sensor_dev_attr_temp3_fault.dev_attr.attr, 921c801082dSJean Delvare &sensor_dev_attr_auto_temp3_off.dev_attr.attr, 922c801082dSJean Delvare &sensor_dev_attr_auto_temp3_min.dev_attr.attr, 923c801082dSJean Delvare &sensor_dev_attr_auto_temp3_max.dev_attr.attr, 924c801082dSJean Delvare &sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr, 925681c6f7aSMark M. Hoffman NULL 926681c6f7aSMark M. Hoffman }; 927681c6f7aSMark M. Hoffman 928681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = { 929681c6f7aSMark M. Hoffman .attrs = adm1031_attributes_opt, 930681c6f7aSMark M. Hoffman }; 931681c6f7aSMark M. Hoffman 932af200f88SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */ 933310ec792SJean Delvare static int adm1031_detect(struct i2c_client *client, 934af200f88SJean Delvare struct i2c_board_info *info) 9358d5d45fbSJean Delvare { 936af200f88SJean Delvare struct i2c_adapter *adapter = client->adapter; 93752df6440SJean Delvare const char *name; 93852df6440SJean Delvare int id, co; 9398d5d45fbSJean Delvare 9408d5d45fbSJean Delvare if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 941af200f88SJean Delvare return -ENODEV; 9428d5d45fbSJean Delvare 9436d6006b8SJean Delvare id = i2c_smbus_read_byte_data(client, 0x3d); 9446d6006b8SJean Delvare co = i2c_smbus_read_byte_data(client, 0x3e); 9458d5d45fbSJean Delvare 9468d5d45fbSJean Delvare if (!((id == 0x31 || id == 0x30) && co == 0x41)) 947af200f88SJean Delvare return -ENODEV; 94852df6440SJean Delvare name = (id == 0x30) ? "adm1030" : "adm1031"; 9498d5d45fbSJean Delvare 950af200f88SJean Delvare strlcpy(info->type, name, I2C_NAME_SIZE); 9518d5d45fbSJean Delvare 952af200f88SJean Delvare return 0; 953af200f88SJean Delvare } 954af200f88SJean Delvare 955af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client, 956af200f88SJean Delvare const struct i2c_device_id *id) 957af200f88SJean Delvare { 958af200f88SJean Delvare struct adm1031_data *data; 959af200f88SJean Delvare int err; 960af200f88SJean Delvare 961af200f88SJean Delvare data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL); 962af200f88SJean Delvare if (!data) { 963af200f88SJean Delvare err = -ENOMEM; 964af200f88SJean Delvare goto exit; 965af200f88SJean Delvare } 966af200f88SJean Delvare 967af200f88SJean Delvare i2c_set_clientdata(client, data); 968af200f88SJean Delvare data->chip_type = id->driver_data; 9699a61bf63SIngo Molnar mutex_init(&data->update_lock); 9708d5d45fbSJean Delvare 971af200f88SJean Delvare if (data->chip_type == adm1030) 972af200f88SJean Delvare data->chan_select_table = &auto_channel_select_table_adm1030; 973af200f88SJean Delvare else 974af200f88SJean Delvare data->chan_select_table = &auto_channel_select_table_adm1031; 9758d5d45fbSJean Delvare 9768d5d45fbSJean Delvare /* Initialize the ADM1031 chip */ 9776d6006b8SJean Delvare adm1031_init_client(client); 9788d5d45fbSJean Delvare 9798d5d45fbSJean Delvare /* Register sysfs hooks */ 9801c720093SGuenter Roeck err = sysfs_create_group(&client->dev.kobj, &adm1031_group); 9811c720093SGuenter Roeck if (err) 982af200f88SJean Delvare goto exit_free; 983681c6f7aSMark M. Hoffman 984af200f88SJean Delvare if (data->chip_type == adm1031) { 9851c720093SGuenter Roeck err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt); 9861c720093SGuenter Roeck if (err) 987681c6f7aSMark M. Hoffman goto exit_remove; 988681c6f7aSMark M. Hoffman } 989681c6f7aSMark M. Hoffman 9906d6006b8SJean Delvare data->hwmon_dev = hwmon_device_register(&client->dev); 9911beeffe4STony Jones if (IS_ERR(data->hwmon_dev)) { 9921beeffe4STony Jones err = PTR_ERR(data->hwmon_dev); 993681c6f7aSMark M. Hoffman goto exit_remove; 9948d5d45fbSJean Delvare } 9958d5d45fbSJean Delvare 9968d5d45fbSJean Delvare return 0; 9978d5d45fbSJean Delvare 998681c6f7aSMark M. Hoffman exit_remove: 9996d6006b8SJean Delvare sysfs_remove_group(&client->dev.kobj, &adm1031_group); 10006d6006b8SJean Delvare sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); 10018d5d45fbSJean Delvare exit_free: 10021f57ff89SAlexey Dobriyan kfree(data); 10038d5d45fbSJean Delvare exit: 10048d5d45fbSJean Delvare return err; 10058d5d45fbSJean Delvare } 10068d5d45fbSJean Delvare 1007af200f88SJean Delvare static int adm1031_remove(struct i2c_client *client) 10088d5d45fbSJean Delvare { 1009943b0830SMark M. Hoffman struct adm1031_data *data = i2c_get_clientdata(client); 1010943b0830SMark M. Hoffman 10111beeffe4STony Jones hwmon_device_unregister(data->hwmon_dev); 1012681c6f7aSMark M. Hoffman sysfs_remove_group(&client->dev.kobj, &adm1031_group); 1013681c6f7aSMark M. Hoffman sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); 1014943b0830SMark M. Hoffman kfree(data); 10158d5d45fbSJean Delvare return 0; 10168d5d45fbSJean Delvare } 10178d5d45fbSJean Delvare 10188d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client) 10198d5d45fbSJean Delvare { 10208d5d45fbSJean Delvare unsigned int read_val; 10218d5d45fbSJean Delvare unsigned int mask; 102287c33daaSJean Delvare int i; 10238d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 10248d5d45fbSJean Delvare 10258d5d45fbSJean Delvare mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE); 10268d5d45fbSJean Delvare if (data->chip_type == adm1031) { 10278d5d45fbSJean Delvare mask |= (ADM1031_CONF2_PWM2_ENABLE | 10288d5d45fbSJean Delvare ADM1031_CONF2_TACH2_ENABLE); 10298d5d45fbSJean Delvare } 10308d5d45fbSJean Delvare /* Initialize the ADM1031 chip (enables fan speed reading ) */ 10318d5d45fbSJean Delvare read_val = adm1031_read_value(client, ADM1031_REG_CONF2); 10321c720093SGuenter Roeck if ((read_val | mask) != read_val) 10338d5d45fbSJean Delvare adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask); 10348d5d45fbSJean Delvare 10358d5d45fbSJean Delvare read_val = adm1031_read_value(client, ADM1031_REG_CONF1); 10368d5d45fbSJean Delvare if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) { 10371c720093SGuenter Roeck adm1031_write_value(client, ADM1031_REG_CONF1, 10381c720093SGuenter Roeck read_val | ADM1031_CONF1_MONITOR_ENABLE); 10398d5d45fbSJean Delvare } 10408d5d45fbSJean Delvare 104187c33daaSJean Delvare /* Read the chip's update rate */ 104287c33daaSJean Delvare mask = ADM1031_UPDATE_RATE_MASK; 104387c33daaSJean Delvare read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); 104487c33daaSJean Delvare i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT; 1045a51b9944SGuenter Roeck /* Save it as update interval */ 1046a51b9944SGuenter Roeck data->update_interval = update_intervals[i]; 10478d5d45fbSJean Delvare } 10488d5d45fbSJean Delvare 10498d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev) 10508d5d45fbSJean Delvare { 10518d5d45fbSJean Delvare struct i2c_client *client = to_i2c_client(dev); 10528d5d45fbSJean Delvare struct adm1031_data *data = i2c_get_clientdata(client); 105387c33daaSJean Delvare unsigned long next_update; 10548d5d45fbSJean Delvare int chan; 10558d5d45fbSJean Delvare 10569a61bf63SIngo Molnar mutex_lock(&data->update_lock); 10578d5d45fbSJean Delvare 1058a51b9944SGuenter Roeck next_update = data->last_updated 1059a51b9944SGuenter Roeck + msecs_to_jiffies(data->update_interval); 106087c33daaSJean Delvare if (time_after(jiffies, next_update) || !data->valid) { 10618d5d45fbSJean Delvare 10628d5d45fbSJean Delvare dev_dbg(&client->dev, "Starting adm1031 update\n"); 10638d5d45fbSJean Delvare for (chan = 0; 10648d5d45fbSJean Delvare chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) { 10658d5d45fbSJean Delvare u8 oldh, newh; 10668d5d45fbSJean Delvare 10678d5d45fbSJean Delvare oldh = 10688d5d45fbSJean Delvare adm1031_read_value(client, ADM1031_REG_TEMP(chan)); 10698d5d45fbSJean Delvare data->ext_temp[chan] = 10708d5d45fbSJean Delvare adm1031_read_value(client, ADM1031_REG_EXT_TEMP); 10718d5d45fbSJean Delvare newh = 10728d5d45fbSJean Delvare adm1031_read_value(client, ADM1031_REG_TEMP(chan)); 10738d5d45fbSJean Delvare if (newh != oldh) { 10748d5d45fbSJean Delvare data->ext_temp[chan] = 10758d5d45fbSJean Delvare adm1031_read_value(client, 10768d5d45fbSJean Delvare ADM1031_REG_EXT_TEMP); 10778d5d45fbSJean Delvare #ifdef DEBUG 10788d5d45fbSJean Delvare oldh = 10798d5d45fbSJean Delvare adm1031_read_value(client, 10808d5d45fbSJean Delvare ADM1031_REG_TEMP(chan)); 10818d5d45fbSJean Delvare 10828d5d45fbSJean Delvare /* oldh is actually newer */ 10838d5d45fbSJean Delvare if (newh != oldh) 10848d5d45fbSJean Delvare dev_warn(&client->dev, 10851c720093SGuenter Roeck "Remote temperature may be wrong.\n"); 10868d5d45fbSJean Delvare #endif 10878d5d45fbSJean Delvare } 10888d5d45fbSJean Delvare data->temp[chan] = newh; 10898d5d45fbSJean Delvare 109049dc9efeSIra Snyder data->temp_offset[chan] = 109149dc9efeSIra Snyder adm1031_read_value(client, 109249dc9efeSIra Snyder ADM1031_REG_TEMP_OFFSET(chan)); 10938d5d45fbSJean Delvare data->temp_min[chan] = 10948d5d45fbSJean Delvare adm1031_read_value(client, 10958d5d45fbSJean Delvare ADM1031_REG_TEMP_MIN(chan)); 10968d5d45fbSJean Delvare data->temp_max[chan] = 10978d5d45fbSJean Delvare adm1031_read_value(client, 10988d5d45fbSJean Delvare ADM1031_REG_TEMP_MAX(chan)); 10998d5d45fbSJean Delvare data->temp_crit[chan] = 11008d5d45fbSJean Delvare adm1031_read_value(client, 11018d5d45fbSJean Delvare ADM1031_REG_TEMP_CRIT(chan)); 11028d5d45fbSJean Delvare data->auto_temp[chan] = 11038d5d45fbSJean Delvare adm1031_read_value(client, 11048d5d45fbSJean Delvare ADM1031_REG_AUTO_TEMP(chan)); 11058d5d45fbSJean Delvare 11068d5d45fbSJean Delvare } 11078d5d45fbSJean Delvare 11088d5d45fbSJean Delvare data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1); 11098d5d45fbSJean Delvare data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2); 11108d5d45fbSJean Delvare 11118d5d45fbSJean Delvare data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0)) 11121c720093SGuenter Roeck | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8); 11131c720093SGuenter Roeck if (data->chip_type == adm1030) 11148d5d45fbSJean Delvare data->alarm &= 0xc0ff; 11158d5d45fbSJean Delvare 11161c720093SGuenter Roeck for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2); 11171c720093SGuenter Roeck chan++) { 11188d5d45fbSJean Delvare data->fan_div[chan] = 11191c720093SGuenter Roeck adm1031_read_value(client, 11201c720093SGuenter Roeck ADM1031_REG_FAN_DIV(chan)); 11218d5d45fbSJean Delvare data->fan_min[chan] = 11221c720093SGuenter Roeck adm1031_read_value(client, 11231c720093SGuenter Roeck ADM1031_REG_FAN_MIN(chan)); 11248d5d45fbSJean Delvare data->fan[chan] = 11251c720093SGuenter Roeck adm1031_read_value(client, 11261c720093SGuenter Roeck ADM1031_REG_FAN_SPEED(chan)); 11278d5d45fbSJean Delvare data->pwm[chan] = 11281c720093SGuenter Roeck (adm1031_read_value(client, 11291c720093SGuenter Roeck ADM1031_REG_PWM) >> (4 * chan)) & 0x0f; 11308d5d45fbSJean Delvare } 11318d5d45fbSJean Delvare data->last_updated = jiffies; 11328d5d45fbSJean Delvare data->valid = 1; 11338d5d45fbSJean Delvare } 11348d5d45fbSJean Delvare 11359a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 11368d5d45fbSJean Delvare 11378d5d45fbSJean Delvare return data; 11388d5d45fbSJean Delvare } 11398d5d45fbSJean Delvare 1140f0967eeaSAxel Lin module_i2c_driver(adm1031_driver); 11418d5d45fbSJean Delvare 11428d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>"); 11438d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver"); 11448d5d45fbSJean Delvare MODULE_LICENSE("GPL"); 1145