18d5d45fbSJean Delvare /* 28d5d45fbSJean Delvare w83781d.c - Part of lm_sensors, Linux kernel modules for hardware 38d5d45fbSJean Delvare monitoring 48d5d45fbSJean Delvare Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>, 58d5d45fbSJean Delvare Philip Edelbrock <phil@netroedge.com>, 68d5d45fbSJean Delvare and Mark Studebaker <mdsxyz123@yahoo.com> 7360782ddSJean Delvare Copyright (c) 2007 - 2008 Jean Delvare <khali@linux-fr.org> 88d5d45fbSJean Delvare 98d5d45fbSJean Delvare This program is free software; you can redistribute it and/or modify 108d5d45fbSJean Delvare it under the terms of the GNU General Public License as published by 118d5d45fbSJean Delvare the Free Software Foundation; either version 2 of the License, or 128d5d45fbSJean Delvare (at your option) any later version. 138d5d45fbSJean Delvare 148d5d45fbSJean Delvare This program is distributed in the hope that it will be useful, 158d5d45fbSJean Delvare but WITHOUT ANY WARRANTY; without even the implied warranty of 168d5d45fbSJean Delvare MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 178d5d45fbSJean Delvare GNU General Public License for more details. 188d5d45fbSJean Delvare 198d5d45fbSJean Delvare You should have received a copy of the GNU General Public License 208d5d45fbSJean Delvare along with this program; if not, write to the Free Software 218d5d45fbSJean Delvare Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 228d5d45fbSJean Delvare */ 238d5d45fbSJean Delvare 248d5d45fbSJean Delvare /* 258d5d45fbSJean Delvare Supports following chips: 268d5d45fbSJean Delvare 278d5d45fbSJean Delvare Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA 288d5d45fbSJean Delvare as99127f 7 3 0 3 0x31 0x12c3 yes no 298d5d45fbSJean Delvare as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no 308d5d45fbSJean Delvare w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes 318d5d45fbSJean Delvare w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes 328d5d45fbSJean Delvare w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no 338d5d45fbSJean Delvare 348d5d45fbSJean Delvare */ 358d5d45fbSJean Delvare 361ca28218SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 371ca28218SJoe Perches 388d5d45fbSJean Delvare #include <linux/module.h> 398d5d45fbSJean Delvare #include <linux/init.h> 408d5d45fbSJean Delvare #include <linux/slab.h> 418d5d45fbSJean Delvare #include <linux/jiffies.h> 428d5d45fbSJean Delvare #include <linux/i2c.h> 43943b0830SMark M. Hoffman #include <linux/hwmon.h> 44303760b4SJean Delvare #include <linux/hwmon-vid.h> 4534875337SJean Delvare #include <linux/hwmon-sysfs.h> 46311ce2efSJim Cromie #include <linux/sysfs.h> 47943b0830SMark M. Hoffman #include <linux/err.h> 489a61bf63SIngo Molnar #include <linux/mutex.h> 498d5d45fbSJean Delvare 50443850ceSWolfgang Grandegger #ifdef CONFIG_ISA 51443850ceSWolfgang Grandegger #include <linux/platform_device.h> 52443850ceSWolfgang Grandegger #include <linux/ioport.h> 536055fae8SH Hartley Sweeten #include <linux/io.h> 54443850ceSWolfgang Grandegger #endif 55443850ceSWolfgang Grandegger 56443850ceSWolfgang Grandegger #include "lm75.h" 577666c13cSJean Delvare 588d5d45fbSJean Delvare /* Addresses to scan */ 5925e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 606722feadSJean Delvare 0x2e, 0x2f, I2C_CLIENT_END }; 613aed198cSJean Delvare 62e5e9f44cSJean Delvare enum chips { w83781d, w83782d, w83783s, as99127f }; 63e5e9f44cSJean Delvare 64e5e9f44cSJean Delvare /* Insmod parameters */ 653aed198cSJean Delvare static unsigned short force_subclients[4]; 663aed198cSJean Delvare module_param_array(force_subclients, short, NULL, 0); 673aed198cSJean Delvare MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " 688d5d45fbSJean Delvare "{bus, clientaddr, subclientaddr1, subclientaddr2}"); 698d5d45fbSJean Delvare 7090ab5ee9SRusty Russell static bool reset; 71fabddcd4SJean Delvare module_param(reset, bool, 0); 72fabddcd4SJean Delvare MODULE_PARM_DESC(reset, "Set to one to reset chip on load"); 73fabddcd4SJean Delvare 7490ab5ee9SRusty Russell static bool init = 1; 758d5d45fbSJean Delvare module_param(init, bool, 0); 768d5d45fbSJean Delvare MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); 778d5d45fbSJean Delvare 788d5d45fbSJean Delvare /* Constants specified below */ 798d5d45fbSJean Delvare 808d5d45fbSJean Delvare /* Length of ISA address segment */ 818d5d45fbSJean Delvare #define W83781D_EXTENT 8 828d5d45fbSJean Delvare 838d5d45fbSJean Delvare /* Where are the ISA address/data registers relative to the base address */ 848d5d45fbSJean Delvare #define W83781D_ADDR_REG_OFFSET 5 858d5d45fbSJean Delvare #define W83781D_DATA_REG_OFFSET 6 868d5d45fbSJean Delvare 8734875337SJean Delvare /* The device registers */ 8834875337SJean Delvare /* in nr from 0 to 8 */ 898d5d45fbSJean Delvare #define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ 908d5d45fbSJean Delvare (0x554 + (((nr) - 7) * 2))) 918d5d45fbSJean Delvare #define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ 928d5d45fbSJean Delvare (0x555 + (((nr) - 7) * 2))) 938d5d45fbSJean Delvare #define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ 948d5d45fbSJean Delvare (0x550 + (nr) - 7)) 958d5d45fbSJean Delvare 9634875337SJean Delvare /* fan nr from 0 to 2 */ 9734875337SJean Delvare #define W83781D_REG_FAN_MIN(nr) (0x3b + (nr)) 9834875337SJean Delvare #define W83781D_REG_FAN(nr) (0x28 + (nr)) 998d5d45fbSJean Delvare 1008d5d45fbSJean Delvare #define W83781D_REG_BANK 0x4E 1018d5d45fbSJean Delvare #define W83781D_REG_TEMP2_CONFIG 0x152 1028d5d45fbSJean Delvare #define W83781D_REG_TEMP3_CONFIG 0x252 10334875337SJean Delvare /* temp nr from 1 to 3 */ 1048d5d45fbSJean Delvare #define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \ 1058d5d45fbSJean Delvare ((nr == 2) ? (0x0150) : \ 1068d5d45fbSJean Delvare (0x27))) 1078d5d45fbSJean Delvare #define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \ 1088d5d45fbSJean Delvare ((nr == 2) ? (0x153) : \ 1098d5d45fbSJean Delvare (0x3A))) 1108d5d45fbSJean Delvare #define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \ 1118d5d45fbSJean Delvare ((nr == 2) ? (0x155) : \ 1128d5d45fbSJean Delvare (0x39))) 1138d5d45fbSJean Delvare 1148d5d45fbSJean Delvare #define W83781D_REG_CONFIG 0x40 115c7f5d7edSJean Delvare 116c7f5d7edSJean Delvare /* Interrupt status (W83781D, AS99127F) */ 1178d5d45fbSJean Delvare #define W83781D_REG_ALARM1 0x41 1188d5d45fbSJean Delvare #define W83781D_REG_ALARM2 0x42 1198d5d45fbSJean Delvare 12005663368SJean Delvare /* Real-time status (W83782D, W83783S) */ 121c7f5d7edSJean Delvare #define W83782D_REG_ALARM1 0x459 122c7f5d7edSJean Delvare #define W83782D_REG_ALARM2 0x45A 123c7f5d7edSJean Delvare #define W83782D_REG_ALARM3 0x45B 124c7f5d7edSJean Delvare 1258d5d45fbSJean Delvare #define W83781D_REG_BEEP_CONFIG 0x4D 1268d5d45fbSJean Delvare #define W83781D_REG_BEEP_INTS1 0x56 1278d5d45fbSJean Delvare #define W83781D_REG_BEEP_INTS2 0x57 1288d5d45fbSJean Delvare #define W83781D_REG_BEEP_INTS3 0x453 /* not on W83781D */ 1298d5d45fbSJean Delvare 1308d5d45fbSJean Delvare #define W83781D_REG_VID_FANDIV 0x47 1318d5d45fbSJean Delvare 1328d5d45fbSJean Delvare #define W83781D_REG_CHIPID 0x49 1338d5d45fbSJean Delvare #define W83781D_REG_WCHIPID 0x58 1348d5d45fbSJean Delvare #define W83781D_REG_CHIPMAN 0x4F 1358d5d45fbSJean Delvare #define W83781D_REG_PIN 0x4B 1368d5d45fbSJean Delvare 1378d5d45fbSJean Delvare /* 782D/783S only */ 1388d5d45fbSJean Delvare #define W83781D_REG_VBAT 0x5D 1398d5d45fbSJean Delvare 1408d5d45fbSJean Delvare /* PWM 782D (1-4) and 783S (1-2) only */ 14134875337SJean Delvare static const u8 W83781D_REG_PWM[] = { 0x5B, 0x5A, 0x5E, 0x5F }; 1428d5d45fbSJean Delvare #define W83781D_REG_PWMCLK12 0x5C 1438d5d45fbSJean Delvare #define W83781D_REG_PWMCLK34 0x45C 1448d5d45fbSJean Delvare 1458d5d45fbSJean Delvare #define W83781D_REG_I2C_ADDR 0x48 1468d5d45fbSJean Delvare #define W83781D_REG_I2C_SUBADDR 0x4A 1478d5d45fbSJean Delvare 1488d5d45fbSJean Delvare /* The following are undocumented in the data sheets however we 1498d5d45fbSJean Delvare received the information in an email from Winbond tech support */ 1508d5d45fbSJean Delvare /* Sensor selection - not on 781d */ 1518d5d45fbSJean Delvare #define W83781D_REG_SCFG1 0x5D 1528d5d45fbSJean Delvare static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 }; 1538d5d45fbSJean Delvare 1548d5d45fbSJean Delvare #define W83781D_REG_SCFG2 0x59 1558d5d45fbSJean Delvare static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 }; 1568d5d45fbSJean Delvare 1578d5d45fbSJean Delvare #define W83781D_DEFAULT_BETA 3435 1588d5d45fbSJean Delvare 159474d00a8SJean Delvare /* Conversions */ 160474d00a8SJean Delvare #define IN_TO_REG(val) SENSORS_LIMIT(((val) + 8) / 16, 0, 255) 161474d00a8SJean Delvare #define IN_FROM_REG(val) ((val) * 16) 1628d5d45fbSJean Delvare 1638d5d45fbSJean Delvare static inline u8 1648d5d45fbSJean Delvare FAN_TO_REG(long rpm, int div) 1658d5d45fbSJean Delvare { 1668d5d45fbSJean Delvare if (rpm == 0) 1678d5d45fbSJean Delvare return 255; 1688d5d45fbSJean Delvare rpm = SENSORS_LIMIT(rpm, 1, 1000000); 1698d5d45fbSJean Delvare return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); 1708d5d45fbSJean Delvare } 1718d5d45fbSJean Delvare 172474d00a8SJean Delvare static inline long 173474d00a8SJean Delvare FAN_FROM_REG(u8 val, int div) 174474d00a8SJean Delvare { 175474d00a8SJean Delvare if (val == 0) 176474d00a8SJean Delvare return -1; 177474d00a8SJean Delvare if (val == 255) 178474d00a8SJean Delvare return 0; 179474d00a8SJean Delvare return 1350000 / (val * div); 180474d00a8SJean Delvare } 1818d5d45fbSJean Delvare 182474d00a8SJean Delvare #define TEMP_TO_REG(val) SENSORS_LIMIT((val) / 1000, -127, 128) 183474d00a8SJean Delvare #define TEMP_FROM_REG(val) ((val) * 1000) 1848d5d45fbSJean Delvare 1858d5d45fbSJean Delvare #define BEEP_MASK_FROM_REG(val, type) ((type) == as99127f ? \ 1862fbbbf14SJean Delvare (~(val)) & 0x7fff : (val) & 0xff7fff) 1878d5d45fbSJean Delvare #define BEEP_MASK_TO_REG(val, type) ((type) == as99127f ? \ 1882fbbbf14SJean Delvare (~(val)) & 0x7fff : (val) & 0xff7fff) 1898d5d45fbSJean Delvare 1908d5d45fbSJean Delvare #define DIV_FROM_REG(val) (1 << (val)) 1918d5d45fbSJean Delvare 1928d5d45fbSJean Delvare static inline u8 1938d5d45fbSJean Delvare DIV_TO_REG(long val, enum chips type) 1948d5d45fbSJean Delvare { 1958d5d45fbSJean Delvare int i; 1968d5d45fbSJean Delvare val = SENSORS_LIMIT(val, 1, 1978d5d45fbSJean Delvare ((type == w83781d 1988d5d45fbSJean Delvare || type == as99127f) ? 8 : 128)) >> 1; 1998d5d45fbSJean Delvare for (i = 0; i < 7; i++) { 2008d5d45fbSJean Delvare if (val == 0) 2018d5d45fbSJean Delvare break; 2028d5d45fbSJean Delvare val >>= 1; 2038d5d45fbSJean Delvare } 204474d00a8SJean Delvare return i; 2058d5d45fbSJean Delvare } 2068d5d45fbSJean Delvare 2078d5d45fbSJean Delvare struct w83781d_data { 2080217eae3SWolfgang Grandegger struct i2c_client *client; 2091beeffe4STony Jones struct device *hwmon_dev; 2109a61bf63SIngo Molnar struct mutex lock; 2118d5d45fbSJean Delvare enum chips type; 2128d5d45fbSJean Delvare 213360782ddSJean Delvare /* For ISA device only */ 214360782ddSJean Delvare const char *name; 215360782ddSJean Delvare int isa_addr; 216360782ddSJean Delvare 2179a61bf63SIngo Molnar struct mutex update_lock; 2188d5d45fbSJean Delvare char valid; /* !=0 if following fields are valid */ 2198d5d45fbSJean Delvare unsigned long last_updated; /* In jiffies */ 2208d5d45fbSJean Delvare 2218d5d45fbSJean Delvare struct i2c_client *lm75[2]; /* for secondary I2C addresses */ 2228d5d45fbSJean Delvare /* array of 2 pointers to subclients */ 2238d5d45fbSJean Delvare 2248d5d45fbSJean Delvare u8 in[9]; /* Register value - 8 & 9 for 782D only */ 2258d5d45fbSJean Delvare u8 in_max[9]; /* Register value - 8 & 9 for 782D only */ 2268d5d45fbSJean Delvare u8 in_min[9]; /* Register value - 8 & 9 for 782D only */ 2278d5d45fbSJean Delvare u8 fan[3]; /* Register value */ 2288d5d45fbSJean Delvare u8 fan_min[3]; /* Register value */ 229474d00a8SJean Delvare s8 temp; /* Register value */ 230474d00a8SJean Delvare s8 temp_max; /* Register value */ 231474d00a8SJean Delvare s8 temp_max_hyst; /* Register value */ 2328d5d45fbSJean Delvare u16 temp_add[2]; /* Register value */ 2338d5d45fbSJean Delvare u16 temp_max_add[2]; /* Register value */ 2348d5d45fbSJean Delvare u16 temp_max_hyst_add[2]; /* Register value */ 2358d5d45fbSJean Delvare u8 fan_div[3]; /* Register encoding, shifted right */ 2368d5d45fbSJean Delvare u8 vid; /* Register encoding, combined */ 2378d5d45fbSJean Delvare u32 alarms; /* Register encoding, combined */ 2388d5d45fbSJean Delvare u32 beep_mask; /* Register encoding, combined */ 2398d5d45fbSJean Delvare u8 pwm[4]; /* Register value */ 24034875337SJean Delvare u8 pwm2_enable; /* Boolean */ 2418d5d45fbSJean Delvare u16 sens[3]; /* 782D/783S only. 2428d5d45fbSJean Delvare 1 = pentium diode; 2 = 3904 diode; 243b26f9330SJean Delvare 4 = thermistor */ 2448d5d45fbSJean Delvare u8 vrm; 2458d5d45fbSJean Delvare }; 2468d5d45fbSJean Delvare 247443850ceSWolfgang Grandegger static struct w83781d_data *w83781d_data_if_isa(void); 248443850ceSWolfgang Grandegger static int w83781d_alias_detect(struct i2c_client *client, u8 chipid); 249443850ceSWolfgang Grandegger 25031b8dc4dSJean Delvare static int w83781d_read_value(struct w83781d_data *data, u16 reg); 25131b8dc4dSJean Delvare static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value); 2528d5d45fbSJean Delvare static struct w83781d_data *w83781d_update_device(struct device *dev); 2537666c13cSJean Delvare static void w83781d_init_device(struct device *dev); 2548d5d45fbSJean Delvare 2558d5d45fbSJean Delvare /* following are the sysfs callback functions */ 2568d5d45fbSJean Delvare #define show_in_reg(reg) \ 25734875337SJean Delvare static ssize_t show_##reg(struct device *dev, struct device_attribute *da, \ 25834875337SJean Delvare char *buf) \ 2598d5d45fbSJean Delvare { \ 26034875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ 2618d5d45fbSJean Delvare struct w83781d_data *data = w83781d_update_device(dev); \ 26234875337SJean Delvare return sprintf(buf, "%ld\n", \ 26334875337SJean Delvare (long)IN_FROM_REG(data->reg[attr->index])); \ 2648d5d45fbSJean Delvare } 2658d5d45fbSJean Delvare show_in_reg(in); 2668d5d45fbSJean Delvare show_in_reg(in_min); 2678d5d45fbSJean Delvare show_in_reg(in_max); 2688d5d45fbSJean Delvare 2698d5d45fbSJean Delvare #define store_in_reg(REG, reg) \ 27034875337SJean Delvare static ssize_t store_in_##reg(struct device *dev, struct device_attribute \ 27134875337SJean Delvare *da, const char *buf, size_t count) \ 2728d5d45fbSJean Delvare { \ 27334875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ 2747666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); \ 27534875337SJean Delvare int nr = attr->index; \ 276*c531eb3fSGuenter Roeck unsigned long val; \ 277*c531eb3fSGuenter Roeck int err = kstrtoul(buf, 10, &val); \ 278*c531eb3fSGuenter Roeck if (err) \ 279*c531eb3fSGuenter Roeck return err; \ 2809a61bf63SIngo Molnar mutex_lock(&data->update_lock); \ 2818d5d45fbSJean Delvare data->in_##reg[nr] = IN_TO_REG(val); \ 282*c531eb3fSGuenter Roeck w83781d_write_value(data, W83781D_REG_IN_##REG(nr), \ 283*c531eb3fSGuenter Roeck data->in_##reg[nr]); \ 2848d5d45fbSJean Delvare \ 2859a61bf63SIngo Molnar mutex_unlock(&data->update_lock); \ 2868d5d45fbSJean Delvare return count; \ 2878d5d45fbSJean Delvare } 2888d5d45fbSJean Delvare store_in_reg(MIN, min); 2898d5d45fbSJean Delvare store_in_reg(MAX, max); 2908d5d45fbSJean Delvare 2918d5d45fbSJean Delvare #define sysfs_in_offsets(offset) \ 29234875337SJean Delvare static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ 29334875337SJean Delvare show_in, NULL, offset); \ 29434875337SJean Delvare static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ 29534875337SJean Delvare show_in_min, store_in_min, offset); \ 29634875337SJean Delvare static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ 29734875337SJean Delvare show_in_max, store_in_max, offset) 2988d5d45fbSJean Delvare 2998d5d45fbSJean Delvare sysfs_in_offsets(0); 3008d5d45fbSJean Delvare sysfs_in_offsets(1); 3018d5d45fbSJean Delvare sysfs_in_offsets(2); 3028d5d45fbSJean Delvare sysfs_in_offsets(3); 3038d5d45fbSJean Delvare sysfs_in_offsets(4); 3048d5d45fbSJean Delvare sysfs_in_offsets(5); 3058d5d45fbSJean Delvare sysfs_in_offsets(6); 3068d5d45fbSJean Delvare sysfs_in_offsets(7); 3078d5d45fbSJean Delvare sysfs_in_offsets(8); 3088d5d45fbSJean Delvare 3098d5d45fbSJean Delvare #define show_fan_reg(reg) \ 31034875337SJean Delvare static ssize_t show_##reg(struct device *dev, struct device_attribute *da, \ 31134875337SJean Delvare char *buf) \ 3128d5d45fbSJean Delvare { \ 31334875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ 3148d5d45fbSJean Delvare struct w83781d_data *data = w83781d_update_device(dev); \ 3158d5d45fbSJean Delvare return sprintf(buf, "%ld\n", \ 31634875337SJean Delvare FAN_FROM_REG(data->reg[attr->index], \ 31734875337SJean Delvare DIV_FROM_REG(data->fan_div[attr->index]))); \ 3188d5d45fbSJean Delvare } 3198d5d45fbSJean Delvare show_fan_reg(fan); 3208d5d45fbSJean Delvare show_fan_reg(fan_min); 3218d5d45fbSJean Delvare 3228d5d45fbSJean Delvare static ssize_t 32334875337SJean Delvare store_fan_min(struct device *dev, struct device_attribute *da, 32434875337SJean Delvare const char *buf, size_t count) 3258d5d45fbSJean Delvare { 32634875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 3277666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 32834875337SJean Delvare int nr = attr->index; 329*c531eb3fSGuenter Roeck unsigned long val; 330*c531eb3fSGuenter Roeck int err; 3318d5d45fbSJean Delvare 332*c531eb3fSGuenter Roeck err = kstrtoul(buf, 10, &val); 333*c531eb3fSGuenter Roeck if (err) 334*c531eb3fSGuenter Roeck return err; 3358d5d45fbSJean Delvare 3369a61bf63SIngo Molnar mutex_lock(&data->update_lock); 33734875337SJean Delvare data->fan_min[nr] = 33834875337SJean Delvare FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); 33931b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), 34034875337SJean Delvare data->fan_min[nr]); 3418d5d45fbSJean Delvare 3429a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 3438d5d45fbSJean Delvare return count; 3448d5d45fbSJean Delvare } 3458d5d45fbSJean Delvare 34634875337SJean Delvare static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); 34734875337SJean Delvare static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, 34834875337SJean Delvare show_fan_min, store_fan_min, 0); 34934875337SJean Delvare static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); 35034875337SJean Delvare static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, 35134875337SJean Delvare show_fan_min, store_fan_min, 1); 35234875337SJean Delvare static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); 35334875337SJean Delvare static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR, 35434875337SJean Delvare show_fan_min, store_fan_min, 2); 3558d5d45fbSJean Delvare 3568d5d45fbSJean Delvare #define show_temp_reg(reg) \ 35734875337SJean Delvare static ssize_t show_##reg(struct device *dev, struct device_attribute *da, \ 35834875337SJean Delvare char *buf) \ 3598d5d45fbSJean Delvare { \ 36034875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ 3618d5d45fbSJean Delvare struct w83781d_data *data = w83781d_update_device(dev); \ 36234875337SJean Delvare int nr = attr->index; \ 3638d5d45fbSJean Delvare if (nr >= 2) { /* TEMP2 and TEMP3 */ \ 3648d5d45fbSJean Delvare return sprintf(buf, "%d\n", \ 3658d5d45fbSJean Delvare LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \ 3668d5d45fbSJean Delvare } else { /* TEMP1 */ \ 3678d5d45fbSJean Delvare return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->reg)); \ 3688d5d45fbSJean Delvare } \ 3698d5d45fbSJean Delvare } 3708d5d45fbSJean Delvare show_temp_reg(temp); 3718d5d45fbSJean Delvare show_temp_reg(temp_max); 3728d5d45fbSJean Delvare show_temp_reg(temp_max_hyst); 3738d5d45fbSJean Delvare 3748d5d45fbSJean Delvare #define store_temp_reg(REG, reg) \ 37534875337SJean Delvare static ssize_t store_temp_##reg(struct device *dev, \ 37634875337SJean Delvare struct device_attribute *da, const char *buf, size_t count) \ 3778d5d45fbSJean Delvare { \ 37834875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ 3797666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); \ 38034875337SJean Delvare int nr = attr->index; \ 3815bfedac0SChristian Hohnstaedt long val; \ 382*c531eb3fSGuenter Roeck int err = kstrtol(buf, 10, &val); \ 383*c531eb3fSGuenter Roeck if (err) \ 384*c531eb3fSGuenter Roeck return err; \ 3859a61bf63SIngo Molnar mutex_lock(&data->update_lock); \ 3868d5d45fbSJean Delvare \ 3878d5d45fbSJean Delvare if (nr >= 2) { /* TEMP2 and TEMP3 */ \ 3888d5d45fbSJean Delvare data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ 38931b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \ 3908d5d45fbSJean Delvare data->temp_##reg##_add[nr-2]); \ 3918d5d45fbSJean Delvare } else { /* TEMP1 */ \ 3928d5d45fbSJean Delvare data->temp_##reg = TEMP_TO_REG(val); \ 39331b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \ 3948d5d45fbSJean Delvare data->temp_##reg); \ 3958d5d45fbSJean Delvare } \ 3968d5d45fbSJean Delvare \ 3979a61bf63SIngo Molnar mutex_unlock(&data->update_lock); \ 3988d5d45fbSJean Delvare return count; \ 3998d5d45fbSJean Delvare } 4008d5d45fbSJean Delvare store_temp_reg(OVER, max); 4018d5d45fbSJean Delvare store_temp_reg(HYST, max_hyst); 4028d5d45fbSJean Delvare 4038d5d45fbSJean Delvare #define sysfs_temp_offsets(offset) \ 40434875337SJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ 40534875337SJean Delvare show_temp, NULL, offset); \ 40634875337SJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ 40734875337SJean Delvare show_temp_max, store_temp_max, offset); \ 40834875337SJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ 40934875337SJean Delvare show_temp_max_hyst, store_temp_max_hyst, offset); 4108d5d45fbSJean Delvare 4118d5d45fbSJean Delvare sysfs_temp_offsets(1); 4128d5d45fbSJean Delvare sysfs_temp_offsets(2); 4138d5d45fbSJean Delvare sysfs_temp_offsets(3); 4148d5d45fbSJean Delvare 4158d5d45fbSJean Delvare static ssize_t 4168d5d45fbSJean Delvare show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) 4178d5d45fbSJean Delvare { 4188d5d45fbSJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 4198d5d45fbSJean Delvare return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); 4208d5d45fbSJean Delvare } 4218d5d45fbSJean Delvare 422311ce2efSJim Cromie static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); 423311ce2efSJim Cromie 4248d5d45fbSJean Delvare static ssize_t 4258d5d45fbSJean Delvare show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) 4268d5d45fbSJean Delvare { 42790d6619aSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 4288d5d45fbSJean Delvare return sprintf(buf, "%ld\n", (long) data->vrm); 4298d5d45fbSJean Delvare } 4308d5d45fbSJean Delvare 4318d5d45fbSJean Delvare static ssize_t 432*c531eb3fSGuenter Roeck store_vrm_reg(struct device *dev, struct device_attribute *attr, 433*c531eb3fSGuenter Roeck const char *buf, size_t count) 4348d5d45fbSJean Delvare { 4357666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 436*c531eb3fSGuenter Roeck unsigned long val; 437*c531eb3fSGuenter Roeck int err; 4388d5d45fbSJean Delvare 439*c531eb3fSGuenter Roeck err = kstrtoul(buf, 10, &val); 440*c531eb3fSGuenter Roeck if (err) 441*c531eb3fSGuenter Roeck return err; 442*c531eb3fSGuenter Roeck data->vrm = SENSORS_LIMIT(val, 0, 255); 4438d5d45fbSJean Delvare 4448d5d45fbSJean Delvare return count; 4458d5d45fbSJean Delvare } 4468d5d45fbSJean Delvare 447311ce2efSJim Cromie static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); 448311ce2efSJim Cromie 4498d5d45fbSJean Delvare static ssize_t 4508d5d45fbSJean Delvare show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) 4518d5d45fbSJean Delvare { 4528d5d45fbSJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 4538d5d45fbSJean Delvare return sprintf(buf, "%u\n", data->alarms); 4548d5d45fbSJean Delvare } 4558d5d45fbSJean Delvare 456311ce2efSJim Cromie static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); 457311ce2efSJim Cromie 4587d4a1374SJean Delvare static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, 4597d4a1374SJean Delvare char *buf) 4607d4a1374SJean Delvare { 4617d4a1374SJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 4627d4a1374SJean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 4637d4a1374SJean Delvare return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); 4647d4a1374SJean Delvare } 4657d4a1374SJean Delvare 4667d4a1374SJean Delvare /* The W83781D has a single alarm bit for temp2 and temp3 */ 4677d4a1374SJean Delvare static ssize_t show_temp3_alarm(struct device *dev, 4687d4a1374SJean Delvare struct device_attribute *attr, char *buf) 4697d4a1374SJean Delvare { 4707d4a1374SJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 4717d4a1374SJean Delvare int bitnr = (data->type == w83781d) ? 5 : 13; 4727d4a1374SJean Delvare return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); 4737d4a1374SJean Delvare } 4747d4a1374SJean Delvare 4757d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); 4767d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); 4777d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); 4787d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); 4797d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); 4807d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); 4817d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10); 4827d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16); 4837d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17); 4847d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); 4857d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); 4867d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); 4877d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); 4887d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); 4897d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp3_alarm, NULL, 0); 4907d4a1374SJean Delvare 491*c531eb3fSGuenter Roeck static ssize_t show_beep_mask(struct device *dev, 492*c531eb3fSGuenter Roeck struct device_attribute *attr, char *buf) 4938d5d45fbSJean Delvare { 4948d5d45fbSJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 4958d5d45fbSJean Delvare return sprintf(buf, "%ld\n", 4968d5d45fbSJean Delvare (long)BEEP_MASK_FROM_REG(data->beep_mask, data->type)); 4978d5d45fbSJean Delvare } 4988d5d45fbSJean Delvare 4998d5d45fbSJean Delvare static ssize_t 50034875337SJean Delvare store_beep_mask(struct device *dev, struct device_attribute *attr, 50134875337SJean Delvare const char *buf, size_t count) 5028d5d45fbSJean Delvare { 5037666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 504*c531eb3fSGuenter Roeck unsigned long val; 505*c531eb3fSGuenter Roeck int err; 5068d5d45fbSJean Delvare 507*c531eb3fSGuenter Roeck err = kstrtoul(buf, 10, &val); 508*c531eb3fSGuenter Roeck if (err) 509*c531eb3fSGuenter Roeck return err; 5108d5d45fbSJean Delvare 5119a61bf63SIngo Molnar mutex_lock(&data->update_lock); 5122fbbbf14SJean Delvare data->beep_mask &= 0x8000; /* preserve beep enable */ 5132fbbbf14SJean Delvare data->beep_mask |= BEEP_MASK_TO_REG(val, data->type); 51431b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_BEEP_INTS1, 5158d5d45fbSJean Delvare data->beep_mask & 0xff); 51634875337SJean Delvare w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 5172fbbbf14SJean Delvare (data->beep_mask >> 8) & 0xff); 51834875337SJean Delvare if (data->type != w83781d && data->type != as99127f) { 51931b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_BEEP_INTS3, 5208d5d45fbSJean Delvare ((data->beep_mask) >> 16) & 0xff); 5218d5d45fbSJean Delvare } 5229a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 52334875337SJean Delvare 5248d5d45fbSJean Delvare return count; 5258d5d45fbSJean Delvare } 5268d5d45fbSJean Delvare 52734875337SJean Delvare static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, 52834875337SJean Delvare show_beep_mask, store_beep_mask); 5298d5d45fbSJean Delvare 5307d4a1374SJean Delvare static ssize_t show_beep(struct device *dev, struct device_attribute *attr, 5317d4a1374SJean Delvare char *buf) 5327d4a1374SJean Delvare { 5337d4a1374SJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 5347d4a1374SJean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 5357d4a1374SJean Delvare return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); 5367d4a1374SJean Delvare } 5377d4a1374SJean Delvare 5387d4a1374SJean Delvare static ssize_t 5397d4a1374SJean Delvare store_beep(struct device *dev, struct device_attribute *attr, 5407d4a1374SJean Delvare const char *buf, size_t count) 5417d4a1374SJean Delvare { 5427d4a1374SJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 5437d4a1374SJean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 5447d4a1374SJean Delvare u8 reg; 545*c531eb3fSGuenter Roeck unsigned long bit; 546*c531eb3fSGuenter Roeck int err; 5477d4a1374SJean Delvare 548*c531eb3fSGuenter Roeck err = kstrtoul(buf, 10, &bit); 549*c531eb3fSGuenter Roeck if (err) 550*c531eb3fSGuenter Roeck return err; 551*c531eb3fSGuenter Roeck 5527d4a1374SJean Delvare if (bit & ~1) 5537d4a1374SJean Delvare return -EINVAL; 5547d4a1374SJean Delvare 5557d4a1374SJean Delvare mutex_lock(&data->update_lock); 5567d4a1374SJean Delvare if (bit) 5577d4a1374SJean Delvare data->beep_mask |= (1 << bitnr); 5587d4a1374SJean Delvare else 5597d4a1374SJean Delvare data->beep_mask &= ~(1 << bitnr); 5607d4a1374SJean Delvare 5617d4a1374SJean Delvare if (bitnr < 8) { 5627d4a1374SJean Delvare reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS1); 5637d4a1374SJean Delvare if (bit) 5647d4a1374SJean Delvare reg |= (1 << bitnr); 5657d4a1374SJean Delvare else 5667d4a1374SJean Delvare reg &= ~(1 << bitnr); 5677d4a1374SJean Delvare w83781d_write_value(data, W83781D_REG_BEEP_INTS1, reg); 5687d4a1374SJean Delvare } else if (bitnr < 16) { 5697d4a1374SJean Delvare reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS2); 5707d4a1374SJean Delvare if (bit) 5717d4a1374SJean Delvare reg |= (1 << (bitnr - 8)); 5727d4a1374SJean Delvare else 5737d4a1374SJean Delvare reg &= ~(1 << (bitnr - 8)); 5747d4a1374SJean Delvare w83781d_write_value(data, W83781D_REG_BEEP_INTS2, reg); 5757d4a1374SJean Delvare } else { 5767d4a1374SJean Delvare reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS3); 5777d4a1374SJean Delvare if (bit) 5787d4a1374SJean Delvare reg |= (1 << (bitnr - 16)); 5797d4a1374SJean Delvare else 5807d4a1374SJean Delvare reg &= ~(1 << (bitnr - 16)); 5817d4a1374SJean Delvare w83781d_write_value(data, W83781D_REG_BEEP_INTS3, reg); 5827d4a1374SJean Delvare } 5837d4a1374SJean Delvare mutex_unlock(&data->update_lock); 5847d4a1374SJean Delvare 5857d4a1374SJean Delvare return count; 5867d4a1374SJean Delvare } 5877d4a1374SJean Delvare 5887d4a1374SJean Delvare /* The W83781D has a single beep bit for temp2 and temp3 */ 5897d4a1374SJean Delvare static ssize_t show_temp3_beep(struct device *dev, 5907d4a1374SJean Delvare struct device_attribute *attr, char *buf) 5917d4a1374SJean Delvare { 5927d4a1374SJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 5937d4a1374SJean Delvare int bitnr = (data->type == w83781d) ? 5 : 13; 5947d4a1374SJean Delvare return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); 5957d4a1374SJean Delvare } 5967d4a1374SJean Delvare 5977d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, 5987d4a1374SJean Delvare show_beep, store_beep, 0); 5997d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, 6007d4a1374SJean Delvare show_beep, store_beep, 1); 6017d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, 6027d4a1374SJean Delvare show_beep, store_beep, 2); 6037d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, 6047d4a1374SJean Delvare show_beep, store_beep, 3); 6057d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, 6067d4a1374SJean Delvare show_beep, store_beep, 8); 6077d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR, 6087d4a1374SJean Delvare show_beep, store_beep, 9); 6097d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR, 6107d4a1374SJean Delvare show_beep, store_beep, 10); 6117d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR, 6127d4a1374SJean Delvare show_beep, store_beep, 16); 6137d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR, 6147d4a1374SJean Delvare show_beep, store_beep, 17); 6157d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, 6167d4a1374SJean Delvare show_beep, store_beep, 6); 6177d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, 6187d4a1374SJean Delvare show_beep, store_beep, 7); 6197d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR, 6207d4a1374SJean Delvare show_beep, store_beep, 11); 6217d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, 6227d4a1374SJean Delvare show_beep, store_beep, 4); 6237d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, 6247d4a1374SJean Delvare show_beep, store_beep, 5); 6257d4a1374SJean Delvare static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, 6267d4a1374SJean Delvare show_temp3_beep, store_beep, 13); 6272fbbbf14SJean Delvare static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, 6282fbbbf14SJean Delvare show_beep, store_beep, 15); 6297d4a1374SJean Delvare 6308d5d45fbSJean Delvare static ssize_t 63134875337SJean Delvare show_fan_div(struct device *dev, struct device_attribute *da, char *buf) 6328d5d45fbSJean Delvare { 63334875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 6348d5d45fbSJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 6358d5d45fbSJean Delvare return sprintf(buf, "%ld\n", 63634875337SJean Delvare (long) DIV_FROM_REG(data->fan_div[attr->index])); 6378d5d45fbSJean Delvare } 6388d5d45fbSJean Delvare 6398d5d45fbSJean Delvare /* Note: we save and restore the fan minimum here, because its value is 6408d5d45fbSJean Delvare determined in part by the fan divisor. This follows the principle of 641d6e05edcSAndreas Mohr least surprise; the user doesn't expect the fan minimum to change just 6428d5d45fbSJean Delvare because the divisor changed. */ 6438d5d45fbSJean Delvare static ssize_t 64434875337SJean Delvare store_fan_div(struct device *dev, struct device_attribute *da, 64534875337SJean Delvare const char *buf, size_t count) 6468d5d45fbSJean Delvare { 64734875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 6487666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 6498d5d45fbSJean Delvare unsigned long min; 65034875337SJean Delvare int nr = attr->index; 6518d5d45fbSJean Delvare u8 reg; 652*c531eb3fSGuenter Roeck unsigned long val; 653*c531eb3fSGuenter Roeck int err; 654*c531eb3fSGuenter Roeck 655*c531eb3fSGuenter Roeck err = kstrtoul(buf, 10, &val); 656*c531eb3fSGuenter Roeck if (err) 657*c531eb3fSGuenter Roeck return err; 6588d5d45fbSJean Delvare 6599a61bf63SIngo Molnar mutex_lock(&data->update_lock); 6608d5d45fbSJean Delvare 6618d5d45fbSJean Delvare /* Save fan_min */ 6628d5d45fbSJean Delvare min = FAN_FROM_REG(data->fan_min[nr], 6638d5d45fbSJean Delvare DIV_FROM_REG(data->fan_div[nr])); 6648d5d45fbSJean Delvare 6658d5d45fbSJean Delvare data->fan_div[nr] = DIV_TO_REG(val, data->type); 6668d5d45fbSJean Delvare 667*c531eb3fSGuenter Roeck reg = (w83781d_read_value(data, nr == 2 ? 668*c531eb3fSGuenter Roeck W83781D_REG_PIN : W83781D_REG_VID_FANDIV) 6698d5d45fbSJean Delvare & (nr == 0 ? 0xcf : 0x3f)) 6708d5d45fbSJean Delvare | ((data->fan_div[nr] & 0x03) << (nr == 0 ? 4 : 6)); 671*c531eb3fSGuenter Roeck w83781d_write_value(data, nr == 2 ? 672*c531eb3fSGuenter Roeck W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); 6738d5d45fbSJean Delvare 6748d5d45fbSJean Delvare /* w83781d and as99127f don't have extended divisor bits */ 6758d5d45fbSJean Delvare if (data->type != w83781d && data->type != as99127f) { 67631b8dc4dSJean Delvare reg = (w83781d_read_value(data, W83781D_REG_VBAT) 6778d5d45fbSJean Delvare & ~(1 << (5 + nr))) 6788d5d45fbSJean Delvare | ((data->fan_div[nr] & 0x04) << (3 + nr)); 67931b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_VBAT, reg); 6808d5d45fbSJean Delvare } 6818d5d45fbSJean Delvare 6828d5d45fbSJean Delvare /* Restore fan_min */ 6838d5d45fbSJean Delvare data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); 68434875337SJean Delvare w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), data->fan_min[nr]); 6858d5d45fbSJean Delvare 6869a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 6878d5d45fbSJean Delvare return count; 6888d5d45fbSJean Delvare } 6898d5d45fbSJean Delvare 69034875337SJean Delvare static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, 69134875337SJean Delvare show_fan_div, store_fan_div, 0); 69234875337SJean Delvare static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, 69334875337SJean Delvare show_fan_div, store_fan_div, 1); 69434875337SJean Delvare static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR, 69534875337SJean Delvare show_fan_div, store_fan_div, 2); 6968d5d45fbSJean Delvare 6978d5d45fbSJean Delvare static ssize_t 69834875337SJean Delvare show_pwm(struct device *dev, struct device_attribute *da, char *buf) 6998d5d45fbSJean Delvare { 70034875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 7018d5d45fbSJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 70234875337SJean Delvare return sprintf(buf, "%d\n", (int)data->pwm[attr->index]); 7038d5d45fbSJean Delvare } 7048d5d45fbSJean Delvare 7058d5d45fbSJean Delvare static ssize_t 70634875337SJean Delvare show_pwm2_enable(struct device *dev, struct device_attribute *da, char *buf) 7078d5d45fbSJean Delvare { 7088d5d45fbSJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 70934875337SJean Delvare return sprintf(buf, "%d\n", (int)data->pwm2_enable); 7108d5d45fbSJean Delvare } 7118d5d45fbSJean Delvare 7128d5d45fbSJean Delvare static ssize_t 71334875337SJean Delvare store_pwm(struct device *dev, struct device_attribute *da, const char *buf, 71434875337SJean Delvare size_t count) 7158d5d45fbSJean Delvare { 71634875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 7177666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 71834875337SJean Delvare int nr = attr->index; 719*c531eb3fSGuenter Roeck unsigned long val; 720*c531eb3fSGuenter Roeck int err; 7218d5d45fbSJean Delvare 722*c531eb3fSGuenter Roeck err = kstrtoul(buf, 10, &val); 723*c531eb3fSGuenter Roeck if (err) 724*c531eb3fSGuenter Roeck return err; 7258d5d45fbSJean Delvare 7269a61bf63SIngo Molnar mutex_lock(&data->update_lock); 72734875337SJean Delvare data->pwm[nr] = SENSORS_LIMIT(val, 0, 255); 72834875337SJean Delvare w83781d_write_value(data, W83781D_REG_PWM[nr], data->pwm[nr]); 7299a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7308d5d45fbSJean Delvare return count; 7318d5d45fbSJean Delvare } 7328d5d45fbSJean Delvare 7338d5d45fbSJean Delvare static ssize_t 73434875337SJean Delvare store_pwm2_enable(struct device *dev, struct device_attribute *da, 73534875337SJean Delvare const char *buf, size_t count) 7368d5d45fbSJean Delvare { 7377666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 738*c531eb3fSGuenter Roeck unsigned long val; 739*c531eb3fSGuenter Roeck u32 reg; 740*c531eb3fSGuenter Roeck int err; 7418d5d45fbSJean Delvare 742*c531eb3fSGuenter Roeck err = kstrtoul(buf, 10, &val); 743*c531eb3fSGuenter Roeck if (err) 744*c531eb3fSGuenter Roeck return err; 7458d5d45fbSJean Delvare 7469a61bf63SIngo Molnar mutex_lock(&data->update_lock); 7478d5d45fbSJean Delvare 7488d5d45fbSJean Delvare switch (val) { 7498d5d45fbSJean Delvare case 0: 7508d5d45fbSJean Delvare case 1: 75131b8dc4dSJean Delvare reg = w83781d_read_value(data, W83781D_REG_PWMCLK12); 75231b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_PWMCLK12, 7538d5d45fbSJean Delvare (reg & 0xf7) | (val << 3)); 7548d5d45fbSJean Delvare 75531b8dc4dSJean Delvare reg = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); 75631b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, 7578d5d45fbSJean Delvare (reg & 0xef) | (!val << 4)); 7588d5d45fbSJean Delvare 75934875337SJean Delvare data->pwm2_enable = val; 7608d5d45fbSJean Delvare break; 7618d5d45fbSJean Delvare 7628d5d45fbSJean Delvare default: 7639a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7648d5d45fbSJean Delvare return -EINVAL; 7658d5d45fbSJean Delvare } 7668d5d45fbSJean Delvare 7679a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 7688d5d45fbSJean Delvare return count; 7698d5d45fbSJean Delvare } 7708d5d45fbSJean Delvare 77134875337SJean Delvare static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 0); 77234875337SJean Delvare static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 1); 77334875337SJean Delvare static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 2); 77434875337SJean Delvare static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 3); 77534875337SJean Delvare /* only PWM2 can be enabled/disabled */ 77634875337SJean Delvare static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, 77734875337SJean Delvare show_pwm2_enable, store_pwm2_enable); 7788d5d45fbSJean Delvare 7798d5d45fbSJean Delvare static ssize_t 78034875337SJean Delvare show_sensor(struct device *dev, struct device_attribute *da, char *buf) 7818d5d45fbSJean Delvare { 78234875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 7838d5d45fbSJean Delvare struct w83781d_data *data = w83781d_update_device(dev); 78434875337SJean Delvare return sprintf(buf, "%d\n", (int)data->sens[attr->index]); 7858d5d45fbSJean Delvare } 7868d5d45fbSJean Delvare 7878d5d45fbSJean Delvare static ssize_t 78834875337SJean Delvare store_sensor(struct device *dev, struct device_attribute *da, 78934875337SJean Delvare const char *buf, size_t count) 7908d5d45fbSJean Delvare { 79134875337SJean Delvare struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 7927666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 79334875337SJean Delvare int nr = attr->index; 794*c531eb3fSGuenter Roeck unsigned long val; 795*c531eb3fSGuenter Roeck u32 tmp; 796*c531eb3fSGuenter Roeck int err; 7978d5d45fbSJean Delvare 798*c531eb3fSGuenter Roeck err = kstrtoul(buf, 10, &val); 799*c531eb3fSGuenter Roeck if (err) 800*c531eb3fSGuenter Roeck return err; 8018d5d45fbSJean Delvare 8029a61bf63SIngo Molnar mutex_lock(&data->update_lock); 8038d5d45fbSJean Delvare 8048d5d45fbSJean Delvare switch (val) { 8058d5d45fbSJean Delvare case 1: /* PII/Celeron diode */ 80631b8dc4dSJean Delvare tmp = w83781d_read_value(data, W83781D_REG_SCFG1); 80731b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_SCFG1, 80834875337SJean Delvare tmp | BIT_SCFG1[nr]); 80931b8dc4dSJean Delvare tmp = w83781d_read_value(data, W83781D_REG_SCFG2); 81031b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_SCFG2, 81134875337SJean Delvare tmp | BIT_SCFG2[nr]); 81234875337SJean Delvare data->sens[nr] = val; 8138d5d45fbSJean Delvare break; 8148d5d45fbSJean Delvare case 2: /* 3904 */ 81531b8dc4dSJean Delvare tmp = w83781d_read_value(data, W83781D_REG_SCFG1); 81631b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_SCFG1, 81734875337SJean Delvare tmp | BIT_SCFG1[nr]); 81831b8dc4dSJean Delvare tmp = w83781d_read_value(data, W83781D_REG_SCFG2); 81931b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_SCFG2, 82034875337SJean Delvare tmp & ~BIT_SCFG2[nr]); 82134875337SJean Delvare data->sens[nr] = val; 8228d5d45fbSJean Delvare break; 823b26f9330SJean Delvare case W83781D_DEFAULT_BETA: 824b26f9330SJean Delvare dev_warn(dev, "Sensor type %d is deprecated, please use 4 " 825b26f9330SJean Delvare "instead\n", W83781D_DEFAULT_BETA); 826b26f9330SJean Delvare /* fall through */ 827b26f9330SJean Delvare case 4: /* thermistor */ 82831b8dc4dSJean Delvare tmp = w83781d_read_value(data, W83781D_REG_SCFG1); 82931b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_SCFG1, 83034875337SJean Delvare tmp & ~BIT_SCFG1[nr]); 83134875337SJean Delvare data->sens[nr] = val; 8328d5d45fbSJean Delvare break; 8338d5d45fbSJean Delvare default: 834b26f9330SJean Delvare dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or 4\n", 835b26f9330SJean Delvare (long) val); 8368d5d45fbSJean Delvare break; 8378d5d45fbSJean Delvare } 8388d5d45fbSJean Delvare 8399a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 8408d5d45fbSJean Delvare return count; 8418d5d45fbSJean Delvare } 8428d5d45fbSJean Delvare 84334875337SJean Delvare static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR, 84434875337SJean Delvare show_sensor, store_sensor, 0); 84534875337SJean Delvare static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, 846393cdad6SMark M. Hoffman show_sensor, store_sensor, 1); 84734875337SJean Delvare static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, 848393cdad6SMark M. Hoffman show_sensor, store_sensor, 2); 8498d5d45fbSJean Delvare 8508d5d45fbSJean Delvare /* Assumes that adapter is of I2C, not ISA variety. 8518d5d45fbSJean Delvare * OTHERWISE DON'T CALL THIS 8528d5d45fbSJean Delvare */ 8538d5d45fbSJean Delvare static int 8540217eae3SWolfgang Grandegger w83781d_detect_subclients(struct i2c_client *new_client) 8558d5d45fbSJean Delvare { 8568d5d45fbSJean Delvare int i, val1 = 0, id; 8578d5d45fbSJean Delvare int err; 8580217eae3SWolfgang Grandegger int address = new_client->addr; 8590217eae3SWolfgang Grandegger unsigned short sc_addr[2]; 8600217eae3SWolfgang Grandegger struct i2c_adapter *adapter = new_client->adapter; 8618d5d45fbSJean Delvare struct w83781d_data *data = i2c_get_clientdata(new_client); 8620217eae3SWolfgang Grandegger enum chips kind = data->type; 8638d5d45fbSJean Delvare 8648d5d45fbSJean Delvare id = i2c_adapter_id(adapter); 8658d5d45fbSJean Delvare 8668d5d45fbSJean Delvare if (force_subclients[0] == id && force_subclients[1] == address) { 8678d5d45fbSJean Delvare for (i = 2; i <= 3; i++) { 8688d5d45fbSJean Delvare if (force_subclients[i] < 0x48 || 8698d5d45fbSJean Delvare force_subclients[i] > 0x4f) { 8708d5d45fbSJean Delvare dev_err(&new_client->dev, "Invalid subclient " 8718d5d45fbSJean Delvare "address %d; must be 0x48-0x4f\n", 8728d5d45fbSJean Delvare force_subclients[i]); 8738d5d45fbSJean Delvare err = -EINVAL; 8748d5d45fbSJean Delvare goto ERROR_SC_1; 8758d5d45fbSJean Delvare } 8768d5d45fbSJean Delvare } 87731b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_I2C_SUBADDR, 8788d5d45fbSJean Delvare (force_subclients[2] & 0x07) | 8798d5d45fbSJean Delvare ((force_subclients[3] & 0x07) << 4)); 8800217eae3SWolfgang Grandegger sc_addr[0] = force_subclients[2]; 8818d5d45fbSJean Delvare } else { 88231b8dc4dSJean Delvare val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR); 8830217eae3SWolfgang Grandegger sc_addr[0] = 0x48 + (val1 & 0x07); 8848d5d45fbSJean Delvare } 8858d5d45fbSJean Delvare 8868d5d45fbSJean Delvare if (kind != w83783s) { 8878d5d45fbSJean Delvare if (force_subclients[0] == id && 8888d5d45fbSJean Delvare force_subclients[1] == address) { 8890217eae3SWolfgang Grandegger sc_addr[1] = force_subclients[3]; 8908d5d45fbSJean Delvare } else { 8910217eae3SWolfgang Grandegger sc_addr[1] = 0x48 + ((val1 >> 4) & 0x07); 8928d5d45fbSJean Delvare } 8930217eae3SWolfgang Grandegger if (sc_addr[0] == sc_addr[1]) { 8948d5d45fbSJean Delvare dev_err(&new_client->dev, 8958d5d45fbSJean Delvare "Duplicate addresses 0x%x for subclients.\n", 8960217eae3SWolfgang Grandegger sc_addr[0]); 8978d5d45fbSJean Delvare err = -EBUSY; 8988d5d45fbSJean Delvare goto ERROR_SC_2; 8998d5d45fbSJean Delvare } 9008d5d45fbSJean Delvare } 9018d5d45fbSJean Delvare 9028d5d45fbSJean Delvare for (i = 0; i <= 1; i++) { 9030217eae3SWolfgang Grandegger data->lm75[i] = i2c_new_dummy(adapter, sc_addr[i]); 9040217eae3SWolfgang Grandegger if (!data->lm75[i]) { 9058d5d45fbSJean Delvare dev_err(&new_client->dev, "Subclient %d " 9068d5d45fbSJean Delvare "registration at address 0x%x " 9070217eae3SWolfgang Grandegger "failed.\n", i, sc_addr[i]); 9080217eae3SWolfgang Grandegger err = -ENOMEM; 9098d5d45fbSJean Delvare if (i == 1) 9108d5d45fbSJean Delvare goto ERROR_SC_3; 9118d5d45fbSJean Delvare goto ERROR_SC_2; 9128d5d45fbSJean Delvare } 9138d5d45fbSJean Delvare if (kind == w83783s) 9148d5d45fbSJean Delvare break; 9158d5d45fbSJean Delvare } 9168d5d45fbSJean Delvare 9178d5d45fbSJean Delvare return 0; 9188d5d45fbSJean Delvare 9198d5d45fbSJean Delvare /* Undo inits in case of errors */ 9208d5d45fbSJean Delvare ERROR_SC_3: 9210217eae3SWolfgang Grandegger i2c_unregister_device(data->lm75[0]); 9228d5d45fbSJean Delvare ERROR_SC_2: 9238d5d45fbSJean Delvare ERROR_SC_1: 9248d5d45fbSJean Delvare return err; 9258d5d45fbSJean Delvare } 9268d5d45fbSJean Delvare 927311ce2efSJim Cromie #define IN_UNIT_ATTRS(X) \ 92834875337SJean Delvare &sensor_dev_attr_in##X##_input.dev_attr.attr, \ 92934875337SJean Delvare &sensor_dev_attr_in##X##_min.dev_attr.attr, \ 9307d4a1374SJean Delvare &sensor_dev_attr_in##X##_max.dev_attr.attr, \ 9317d4a1374SJean Delvare &sensor_dev_attr_in##X##_alarm.dev_attr.attr, \ 9327d4a1374SJean Delvare &sensor_dev_attr_in##X##_beep.dev_attr.attr 933311ce2efSJim Cromie 934311ce2efSJim Cromie #define FAN_UNIT_ATTRS(X) \ 93534875337SJean Delvare &sensor_dev_attr_fan##X##_input.dev_attr.attr, \ 93634875337SJean Delvare &sensor_dev_attr_fan##X##_min.dev_attr.attr, \ 9377d4a1374SJean Delvare &sensor_dev_attr_fan##X##_div.dev_attr.attr, \ 9387d4a1374SJean Delvare &sensor_dev_attr_fan##X##_alarm.dev_attr.attr, \ 9397d4a1374SJean Delvare &sensor_dev_attr_fan##X##_beep.dev_attr.attr 940311ce2efSJim Cromie 941311ce2efSJim Cromie #define TEMP_UNIT_ATTRS(X) \ 94234875337SJean Delvare &sensor_dev_attr_temp##X##_input.dev_attr.attr, \ 94334875337SJean Delvare &sensor_dev_attr_temp##X##_max.dev_attr.attr, \ 9447d4a1374SJean Delvare &sensor_dev_attr_temp##X##_max_hyst.dev_attr.attr, \ 9457d4a1374SJean Delvare &sensor_dev_attr_temp##X##_alarm.dev_attr.attr, \ 9467d4a1374SJean Delvare &sensor_dev_attr_temp##X##_beep.dev_attr.attr 947311ce2efSJim Cromie 948311ce2efSJim Cromie static struct attribute *w83781d_attributes[] = { 949311ce2efSJim Cromie IN_UNIT_ATTRS(0), 950311ce2efSJim Cromie IN_UNIT_ATTRS(2), 951311ce2efSJim Cromie IN_UNIT_ATTRS(3), 952311ce2efSJim Cromie IN_UNIT_ATTRS(4), 953311ce2efSJim Cromie IN_UNIT_ATTRS(5), 954311ce2efSJim Cromie IN_UNIT_ATTRS(6), 955311ce2efSJim Cromie FAN_UNIT_ATTRS(1), 956311ce2efSJim Cromie FAN_UNIT_ATTRS(2), 957311ce2efSJim Cromie FAN_UNIT_ATTRS(3), 958311ce2efSJim Cromie TEMP_UNIT_ATTRS(1), 959311ce2efSJim Cromie TEMP_UNIT_ATTRS(2), 960311ce2efSJim Cromie &dev_attr_cpu0_vid.attr, 961311ce2efSJim Cromie &dev_attr_vrm.attr, 962311ce2efSJim Cromie &dev_attr_alarms.attr, 963311ce2efSJim Cromie &dev_attr_beep_mask.attr, 9642fbbbf14SJean Delvare &sensor_dev_attr_beep_enable.dev_attr.attr, 965311ce2efSJim Cromie NULL 966311ce2efSJim Cromie }; 967311ce2efSJim Cromie static const struct attribute_group w83781d_group = { 968311ce2efSJim Cromie .attrs = w83781d_attributes, 969311ce2efSJim Cromie }; 970311ce2efSJim Cromie 971311ce2efSJim Cromie static struct attribute *w83781d_attributes_opt[] = { 972311ce2efSJim Cromie IN_UNIT_ATTRS(1), 973311ce2efSJim Cromie IN_UNIT_ATTRS(7), 974311ce2efSJim Cromie IN_UNIT_ATTRS(8), 975311ce2efSJim Cromie TEMP_UNIT_ATTRS(3), 97634875337SJean Delvare &sensor_dev_attr_pwm1.dev_attr.attr, 97734875337SJean Delvare &sensor_dev_attr_pwm2.dev_attr.attr, 97834875337SJean Delvare &sensor_dev_attr_pwm3.dev_attr.attr, 97934875337SJean Delvare &sensor_dev_attr_pwm4.dev_attr.attr, 980311ce2efSJim Cromie &dev_attr_pwm2_enable.attr, 98134875337SJean Delvare &sensor_dev_attr_temp1_type.dev_attr.attr, 98234875337SJean Delvare &sensor_dev_attr_temp2_type.dev_attr.attr, 98334875337SJean Delvare &sensor_dev_attr_temp3_type.dev_attr.attr, 984311ce2efSJim Cromie NULL 985311ce2efSJim Cromie }; 986311ce2efSJim Cromie static const struct attribute_group w83781d_group_opt = { 987311ce2efSJim Cromie .attrs = w83781d_attributes_opt, 988311ce2efSJim Cromie }; 989311ce2efSJim Cromie 9907666c13cSJean Delvare /* No clean up is done on error, it's up to the caller */ 9917666c13cSJean Delvare static int 9927666c13cSJean Delvare w83781d_create_files(struct device *dev, int kind, int is_isa) 9937666c13cSJean Delvare { 9947666c13cSJean Delvare int err; 9957666c13cSJean Delvare 996*c531eb3fSGuenter Roeck err = sysfs_create_group(&dev->kobj, &w83781d_group); 997*c531eb3fSGuenter Roeck if (err) 9987666c13cSJean Delvare return err; 9997666c13cSJean Delvare 10007666c13cSJean Delvare if (kind != w83783s) { 100134875337SJean Delvare if ((err = device_create_file(dev, 100234875337SJean Delvare &sensor_dev_attr_in1_input.dev_attr)) 100334875337SJean Delvare || (err = device_create_file(dev, 100434875337SJean Delvare &sensor_dev_attr_in1_min.dev_attr)) 100534875337SJean Delvare || (err = device_create_file(dev, 10067d4a1374SJean Delvare &sensor_dev_attr_in1_max.dev_attr)) 10077d4a1374SJean Delvare || (err = device_create_file(dev, 10087d4a1374SJean Delvare &sensor_dev_attr_in1_alarm.dev_attr)) 10097d4a1374SJean Delvare || (err = device_create_file(dev, 10107d4a1374SJean Delvare &sensor_dev_attr_in1_beep.dev_attr))) 10117666c13cSJean Delvare return err; 10127666c13cSJean Delvare } 10137666c13cSJean Delvare if (kind != as99127f && kind != w83781d && kind != w83783s) { 101434875337SJean Delvare if ((err = device_create_file(dev, 101534875337SJean Delvare &sensor_dev_attr_in7_input.dev_attr)) 101634875337SJean Delvare || (err = device_create_file(dev, 101734875337SJean Delvare &sensor_dev_attr_in7_min.dev_attr)) 101834875337SJean Delvare || (err = device_create_file(dev, 101934875337SJean Delvare &sensor_dev_attr_in7_max.dev_attr)) 102034875337SJean Delvare || (err = device_create_file(dev, 10217d4a1374SJean Delvare &sensor_dev_attr_in7_alarm.dev_attr)) 10227d4a1374SJean Delvare || (err = device_create_file(dev, 10237d4a1374SJean Delvare &sensor_dev_attr_in7_beep.dev_attr)) 10247d4a1374SJean Delvare || (err = device_create_file(dev, 102534875337SJean Delvare &sensor_dev_attr_in8_input.dev_attr)) 102634875337SJean Delvare || (err = device_create_file(dev, 102734875337SJean Delvare &sensor_dev_attr_in8_min.dev_attr)) 102834875337SJean Delvare || (err = device_create_file(dev, 10297d4a1374SJean Delvare &sensor_dev_attr_in8_max.dev_attr)) 10307d4a1374SJean Delvare || (err = device_create_file(dev, 10317d4a1374SJean Delvare &sensor_dev_attr_in8_alarm.dev_attr)) 10327d4a1374SJean Delvare || (err = device_create_file(dev, 10337d4a1374SJean Delvare &sensor_dev_attr_in8_beep.dev_attr))) 10347666c13cSJean Delvare return err; 10357666c13cSJean Delvare } 10367666c13cSJean Delvare if (kind != w83783s) { 103734875337SJean Delvare if ((err = device_create_file(dev, 103834875337SJean Delvare &sensor_dev_attr_temp3_input.dev_attr)) 10397666c13cSJean Delvare || (err = device_create_file(dev, 104034875337SJean Delvare &sensor_dev_attr_temp3_max.dev_attr)) 104134875337SJean Delvare || (err = device_create_file(dev, 10427d4a1374SJean Delvare &sensor_dev_attr_temp3_max_hyst.dev_attr)) 10437d4a1374SJean Delvare || (err = device_create_file(dev, 10447d4a1374SJean Delvare &sensor_dev_attr_temp3_alarm.dev_attr)) 10457d4a1374SJean Delvare || (err = device_create_file(dev, 10467d4a1374SJean Delvare &sensor_dev_attr_temp3_beep.dev_attr))) 10477d4a1374SJean Delvare return err; 10487d4a1374SJean Delvare 10497768aa76SJean Delvare if (kind != w83781d) { 10507d4a1374SJean Delvare err = sysfs_chmod_file(&dev->kobj, 10517d4a1374SJean Delvare &sensor_dev_attr_temp3_alarm.dev_attr.attr, 10527d4a1374SJean Delvare S_IRUGO | S_IWUSR); 10537d4a1374SJean Delvare if (err) 10547666c13cSJean Delvare return err; 10557666c13cSJean Delvare } 10567768aa76SJean Delvare } 10577666c13cSJean Delvare 10587666c13cSJean Delvare if (kind != w83781d && kind != as99127f) { 105934875337SJean Delvare if ((err = device_create_file(dev, 106034875337SJean Delvare &sensor_dev_attr_pwm1.dev_attr)) 106134875337SJean Delvare || (err = device_create_file(dev, 106234875337SJean Delvare &sensor_dev_attr_pwm2.dev_attr)) 10637666c13cSJean Delvare || (err = device_create_file(dev, &dev_attr_pwm2_enable))) 10647666c13cSJean Delvare return err; 10657666c13cSJean Delvare } 10667666c13cSJean Delvare if (kind == w83782d && !is_isa) { 106734875337SJean Delvare if ((err = device_create_file(dev, 106834875337SJean Delvare &sensor_dev_attr_pwm3.dev_attr)) 106934875337SJean Delvare || (err = device_create_file(dev, 107034875337SJean Delvare &sensor_dev_attr_pwm4.dev_attr))) 10717666c13cSJean Delvare return err; 10727666c13cSJean Delvare } 10737666c13cSJean Delvare 10747666c13cSJean Delvare if (kind != as99127f && kind != w83781d) { 107534875337SJean Delvare if ((err = device_create_file(dev, 107634875337SJean Delvare &sensor_dev_attr_temp1_type.dev_attr)) 10777666c13cSJean Delvare || (err = device_create_file(dev, 107834875337SJean Delvare &sensor_dev_attr_temp2_type.dev_attr))) 10797666c13cSJean Delvare return err; 10807666c13cSJean Delvare if (kind != w83783s) { 1081*c531eb3fSGuenter Roeck err = device_create_file(dev, 1082*c531eb3fSGuenter Roeck &sensor_dev_attr_temp3_type.dev_attr); 1083*c531eb3fSGuenter Roeck if (err) 10847666c13cSJean Delvare return err; 10857666c13cSJean Delvare } 10867666c13cSJean Delvare } 10877666c13cSJean Delvare 10887666c13cSJean Delvare return 0; 10897666c13cSJean Delvare } 10907666c13cSJean Delvare 10910217eae3SWolfgang Grandegger /* Return 0 if detection is successful, -ENODEV otherwise */ 10928d5d45fbSJean Delvare static int 1093310ec792SJean Delvare w83781d_detect(struct i2c_client *client, struct i2c_board_info *info) 10948d5d45fbSJean Delvare { 1095bab2bf44SJean Delvare int val1, val2; 10960217eae3SWolfgang Grandegger struct w83781d_data *isa = w83781d_data_if_isa(); 10970217eae3SWolfgang Grandegger struct i2c_adapter *adapter = client->adapter; 10980217eae3SWolfgang Grandegger int address = client->addr; 1099bab2bf44SJean Delvare const char *client_name; 11008d5d45fbSJean Delvare enum vendor { winbond, asus } vendid; 11018d5d45fbSJean Delvare 11020217eae3SWolfgang Grandegger if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 11030217eae3SWolfgang Grandegger return -ENODEV; 11048d5d45fbSJean Delvare 11050217eae3SWolfgang Grandegger /* We block updates of the ISA device to minimize the risk of 11060217eae3SWolfgang Grandegger concurrent access to the same W83781D chip through different 11070217eae3SWolfgang Grandegger interfaces. */ 11080217eae3SWolfgang Grandegger if (isa) 11090217eae3SWolfgang Grandegger mutex_lock(&isa->update_lock); 11108d5d45fbSJean Delvare 1111bab2bf44SJean Delvare if (i2c_smbus_read_byte_data(client, W83781D_REG_CONFIG) & 0x80) { 1112bab2bf44SJean Delvare dev_dbg(&adapter->dev, 1113bab2bf44SJean Delvare "Detection of w83781d chip failed at step 3\n"); 11140217eae3SWolfgang Grandegger goto err_nodev; 11158d5d45fbSJean Delvare } 1116bab2bf44SJean Delvare 11170217eae3SWolfgang Grandegger val1 = i2c_smbus_read_byte_data(client, W83781D_REG_BANK); 11180217eae3SWolfgang Grandegger val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN); 11198d5d45fbSJean Delvare /* Check for Winbond or Asus ID if in bank 0 */ 1120bab2bf44SJean Delvare if (!(val1 & 0x07) && 1121bab2bf44SJean Delvare ((!(val1 & 0x80) && val2 != 0xa3 && val2 != 0xc3) || 1122bab2bf44SJean Delvare ((val1 & 0x80) && val2 != 0x5c && val2 != 0x12))) { 1123bab2bf44SJean Delvare dev_dbg(&adapter->dev, 1124bab2bf44SJean Delvare "Detection of w83781d chip failed at step 4\n"); 11250217eae3SWolfgang Grandegger goto err_nodev; 11268d5d45fbSJean Delvare } 11278d5d45fbSJean Delvare /* If Winbond SMBus, check address at 0x48. 11288d5d45fbSJean Delvare Asus doesn't support, except for as99127f rev.2 */ 1129bab2bf44SJean Delvare if ((!(val1 & 0x80) && val2 == 0xa3) || 1130bab2bf44SJean Delvare ((val1 & 0x80) && val2 == 0x5c)) { 1131bab2bf44SJean Delvare if (i2c_smbus_read_byte_data(client, W83781D_REG_I2C_ADDR) 1132bab2bf44SJean Delvare != address) { 1133bab2bf44SJean Delvare dev_dbg(&adapter->dev, 1134bab2bf44SJean Delvare "Detection of w83781d chip failed at step 5\n"); 11350217eae3SWolfgang Grandegger goto err_nodev; 11368d5d45fbSJean Delvare } 11378d5d45fbSJean Delvare } 11388d5d45fbSJean Delvare 1139bab2bf44SJean Delvare /* Put it now into bank 0 and Vendor ID High Byte */ 11400217eae3SWolfgang Grandegger i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 11410217eae3SWolfgang Grandegger (i2c_smbus_read_byte_data(client, W83781D_REG_BANK) 1142311ce2efSJim Cromie & 0x78) | 0x80); 11438d5d45fbSJean Delvare 1144bab2bf44SJean Delvare /* Get the vendor ID */ 11450217eae3SWolfgang Grandegger val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN); 11468d5d45fbSJean Delvare if (val2 == 0x5c) 11478d5d45fbSJean Delvare vendid = winbond; 11488d5d45fbSJean Delvare else if (val2 == 0x12) 11498d5d45fbSJean Delvare vendid = asus; 11508d5d45fbSJean Delvare else { 1151bab2bf44SJean Delvare dev_dbg(&adapter->dev, 1152bab2bf44SJean Delvare "w83781d chip vendor is neither Winbond nor Asus\n"); 11530217eae3SWolfgang Grandegger goto err_nodev; 11548d5d45fbSJean Delvare } 11558d5d45fbSJean Delvare 1156bab2bf44SJean Delvare /* Determine the chip type. */ 11570217eae3SWolfgang Grandegger val1 = i2c_smbus_read_byte_data(client, W83781D_REG_WCHIPID); 11588d5d45fbSJean Delvare if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond) 1159bab2bf44SJean Delvare client_name = "w83781d"; 11608d5d45fbSJean Delvare else if (val1 == 0x30 && vendid == winbond) 1161bab2bf44SJean Delvare client_name = "w83782d"; 11627666c13cSJean Delvare else if (val1 == 0x40 && vendid == winbond && address == 0x2d) 1163bab2bf44SJean Delvare client_name = "w83783s"; 11646722feadSJean Delvare else if (val1 == 0x31) 1165bab2bf44SJean Delvare client_name = "as99127f"; 1166bab2bf44SJean Delvare else 11670217eae3SWolfgang Grandegger goto err_nodev; 1168c6566206SJean Delvare 1169bab2bf44SJean Delvare if (val1 <= 0x30 && w83781d_alias_detect(client, val1)) { 1170c6566206SJean Delvare dev_dbg(&adapter->dev, "Device at 0x%02x appears to " 1171c6566206SJean Delvare "be the same as ISA device\n", address); 11720217eae3SWolfgang Grandegger goto err_nodev; 1173c6566206SJean Delvare } 11748d5d45fbSJean Delvare 11750217eae3SWolfgang Grandegger if (isa) 11760217eae3SWolfgang Grandegger mutex_unlock(&isa->update_lock); 11770217eae3SWolfgang Grandegger 11780217eae3SWolfgang Grandegger strlcpy(info->type, client_name, I2C_NAME_SIZE); 11798d5d45fbSJean Delvare 11800217eae3SWolfgang Grandegger return 0; 11810217eae3SWolfgang Grandegger 11820217eae3SWolfgang Grandegger err_nodev: 11830217eae3SWolfgang Grandegger if (isa) 11840217eae3SWolfgang Grandegger mutex_unlock(&isa->update_lock); 11850217eae3SWolfgang Grandegger return -ENODEV; 11860217eae3SWolfgang Grandegger } 11870217eae3SWolfgang Grandegger 11880217eae3SWolfgang Grandegger static int 11890217eae3SWolfgang Grandegger w83781d_probe(struct i2c_client *client, const struct i2c_device_id *id) 11900217eae3SWolfgang Grandegger { 11910217eae3SWolfgang Grandegger struct device *dev = &client->dev; 11920217eae3SWolfgang Grandegger struct w83781d_data *data; 11930217eae3SWolfgang Grandegger int err; 11940217eae3SWolfgang Grandegger 11950217eae3SWolfgang Grandegger data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL); 11960217eae3SWolfgang Grandegger if (!data) { 11970217eae3SWolfgang Grandegger err = -ENOMEM; 11980217eae3SWolfgang Grandegger goto ERROR1; 11990217eae3SWolfgang Grandegger } 12000217eae3SWolfgang Grandegger 12010217eae3SWolfgang Grandegger i2c_set_clientdata(client, data); 12020217eae3SWolfgang Grandegger mutex_init(&data->lock); 12030217eae3SWolfgang Grandegger mutex_init(&data->update_lock); 12040217eae3SWolfgang Grandegger 12050217eae3SWolfgang Grandegger data->type = id->driver_data; 12060217eae3SWolfgang Grandegger data->client = client; 12078d5d45fbSJean Delvare 12088d5d45fbSJean Delvare /* attach secondary i2c lm75-like clients */ 12090217eae3SWolfgang Grandegger err = w83781d_detect_subclients(client); 12100217eae3SWolfgang Grandegger if (err) 12118d5d45fbSJean Delvare goto ERROR3; 12128d5d45fbSJean Delvare 12138d5d45fbSJean Delvare /* Initialize the chip */ 12147666c13cSJean Delvare w83781d_init_device(dev); 12158d5d45fbSJean Delvare 12168d5d45fbSJean Delvare /* Register sysfs hooks */ 12170217eae3SWolfgang Grandegger err = w83781d_create_files(dev, data->type, 0); 12187666c13cSJean Delvare if (err) 1219311ce2efSJim Cromie goto ERROR4; 1220311ce2efSJim Cromie 12211beeffe4STony Jones data->hwmon_dev = hwmon_device_register(dev); 12221beeffe4STony Jones if (IS_ERR(data->hwmon_dev)) { 12231beeffe4STony Jones err = PTR_ERR(data->hwmon_dev); 1224943b0830SMark M. Hoffman goto ERROR4; 1225943b0830SMark M. Hoffman } 1226943b0830SMark M. Hoffman 12278d5d45fbSJean Delvare return 0; 12288d5d45fbSJean Delvare 1229943b0830SMark M. Hoffman ERROR4: 1230311ce2efSJim Cromie sysfs_remove_group(&dev->kobj, &w83781d_group); 1231311ce2efSJim Cromie sysfs_remove_group(&dev->kobj, &w83781d_group_opt); 1232311ce2efSJim Cromie 12330217eae3SWolfgang Grandegger if (data->lm75[0]) 12340217eae3SWolfgang Grandegger i2c_unregister_device(data->lm75[0]); 12350217eae3SWolfgang Grandegger if (data->lm75[1]) 12360217eae3SWolfgang Grandegger i2c_unregister_device(data->lm75[1]); 12378d5d45fbSJean Delvare ERROR3: 12388d5d45fbSJean Delvare kfree(data); 12398d5d45fbSJean Delvare ERROR1: 12408d5d45fbSJean Delvare return err; 12418d5d45fbSJean Delvare } 12428d5d45fbSJean Delvare 12438d5d45fbSJean Delvare static int 12440217eae3SWolfgang Grandegger w83781d_remove(struct i2c_client *client) 12458d5d45fbSJean Delvare { 1246943b0830SMark M. Hoffman struct w83781d_data *data = i2c_get_clientdata(client); 12470217eae3SWolfgang Grandegger struct device *dev = &client->dev; 12488d5d45fbSJean Delvare 12491beeffe4STony Jones hwmon_device_unregister(data->hwmon_dev); 12508d5d45fbSJean Delvare 12510217eae3SWolfgang Grandegger sysfs_remove_group(&dev->kobj, &w83781d_group); 12520217eae3SWolfgang Grandegger sysfs_remove_group(&dev->kobj, &w83781d_group_opt); 12538d5d45fbSJean Delvare 12540217eae3SWolfgang Grandegger if (data->lm75[0]) 12550217eae3SWolfgang Grandegger i2c_unregister_device(data->lm75[0]); 12560217eae3SWolfgang Grandegger if (data->lm75[1]) 12570217eae3SWolfgang Grandegger i2c_unregister_device(data->lm75[1]); 12580217eae3SWolfgang Grandegger 1259943b0830SMark M. Hoffman kfree(data); 1260943b0830SMark M. Hoffman 12618d5d45fbSJean Delvare return 0; 12628d5d45fbSJean Delvare } 12638d5d45fbSJean Delvare 12648d5d45fbSJean Delvare static int 1265443850ceSWolfgang Grandegger w83781d_read_value_i2c(struct w83781d_data *data, u16 reg) 12668d5d45fbSJean Delvare { 12670217eae3SWolfgang Grandegger struct i2c_client *client = data->client; 1268443850ceSWolfgang Grandegger int res, bank; 12698d5d45fbSJean Delvare struct i2c_client *cl; 12708d5d45fbSJean Delvare 12718d5d45fbSJean Delvare bank = (reg >> 8) & 0x0f; 12728d5d45fbSJean Delvare if (bank > 2) 12738d5d45fbSJean Delvare /* switch banks */ 12748d5d45fbSJean Delvare i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 12758d5d45fbSJean Delvare bank); 12768d5d45fbSJean Delvare if (bank == 0 || bank > 2) { 12778d5d45fbSJean Delvare res = i2c_smbus_read_byte_data(client, reg & 0xff); 12788d5d45fbSJean Delvare } else { 12798d5d45fbSJean Delvare /* switch to subclient */ 12808d5d45fbSJean Delvare cl = data->lm75[bank - 1]; 12818d5d45fbSJean Delvare /* convert from ISA to LM75 I2C addresses */ 12828d5d45fbSJean Delvare switch (reg & 0xff) { 12838d5d45fbSJean Delvare case 0x50: /* TEMP */ 128490f4102cSJean Delvare res = i2c_smbus_read_word_swapped(cl, 0); 12858d5d45fbSJean Delvare break; 12868d5d45fbSJean Delvare case 0x52: /* CONFIG */ 12878d5d45fbSJean Delvare res = i2c_smbus_read_byte_data(cl, 1); 12888d5d45fbSJean Delvare break; 12898d5d45fbSJean Delvare case 0x53: /* HYST */ 129090f4102cSJean Delvare res = i2c_smbus_read_word_swapped(cl, 2); 12918d5d45fbSJean Delvare break; 12928d5d45fbSJean Delvare case 0x55: /* OVER */ 12938d5d45fbSJean Delvare default: 129490f4102cSJean Delvare res = i2c_smbus_read_word_swapped(cl, 3); 12958d5d45fbSJean Delvare break; 12968d5d45fbSJean Delvare } 12978d5d45fbSJean Delvare } 12988d5d45fbSJean Delvare if (bank > 2) 12998d5d45fbSJean Delvare i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); 1300443850ceSWolfgang Grandegger 13018d5d45fbSJean Delvare return res; 13028d5d45fbSJean Delvare } 13038d5d45fbSJean Delvare 13048d5d45fbSJean Delvare static int 1305443850ceSWolfgang Grandegger w83781d_write_value_i2c(struct w83781d_data *data, u16 reg, u16 value) 13068d5d45fbSJean Delvare { 13070217eae3SWolfgang Grandegger struct i2c_client *client = data->client; 1308443850ceSWolfgang Grandegger int bank; 13098d5d45fbSJean Delvare struct i2c_client *cl; 13108d5d45fbSJean Delvare 13118d5d45fbSJean Delvare bank = (reg >> 8) & 0x0f; 13128d5d45fbSJean Delvare if (bank > 2) 13138d5d45fbSJean Delvare /* switch banks */ 13148d5d45fbSJean Delvare i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 13158d5d45fbSJean Delvare bank); 13168d5d45fbSJean Delvare if (bank == 0 || bank > 2) { 13178d5d45fbSJean Delvare i2c_smbus_write_byte_data(client, reg & 0xff, 13188d5d45fbSJean Delvare value & 0xff); 13198d5d45fbSJean Delvare } else { 13208d5d45fbSJean Delvare /* switch to subclient */ 13218d5d45fbSJean Delvare cl = data->lm75[bank - 1]; 13228d5d45fbSJean Delvare /* convert from ISA to LM75 I2C addresses */ 13238d5d45fbSJean Delvare switch (reg & 0xff) { 13248d5d45fbSJean Delvare case 0x52: /* CONFIG */ 13258d5d45fbSJean Delvare i2c_smbus_write_byte_data(cl, 1, value & 0xff); 13268d5d45fbSJean Delvare break; 13278d5d45fbSJean Delvare case 0x53: /* HYST */ 132890f4102cSJean Delvare i2c_smbus_write_word_swapped(cl, 2, value); 13298d5d45fbSJean Delvare break; 13308d5d45fbSJean Delvare case 0x55: /* OVER */ 133190f4102cSJean Delvare i2c_smbus_write_word_swapped(cl, 3, value); 13328d5d45fbSJean Delvare break; 13338d5d45fbSJean Delvare } 13348d5d45fbSJean Delvare } 13358d5d45fbSJean Delvare if (bank > 2) 13368d5d45fbSJean Delvare i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); 1337443850ceSWolfgang Grandegger 13388d5d45fbSJean Delvare return 0; 13398d5d45fbSJean Delvare } 13408d5d45fbSJean Delvare 13418d5d45fbSJean Delvare static void 13427666c13cSJean Delvare w83781d_init_device(struct device *dev) 13438d5d45fbSJean Delvare { 13447666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 13458d5d45fbSJean Delvare int i, p; 13468d5d45fbSJean Delvare int type = data->type; 13478d5d45fbSJean Delvare u8 tmp; 13488d5d45fbSJean Delvare 1349fabddcd4SJean Delvare if (reset && type != as99127f) { /* this resets registers we don't have 13508d5d45fbSJean Delvare documentation for on the as99127f */ 1351fabddcd4SJean Delvare /* Resetting the chip has been the default for a long time, 1352fabddcd4SJean Delvare but it causes the BIOS initializations (fan clock dividers, 1353fabddcd4SJean Delvare thermal sensor types...) to be lost, so it is now optional. 1354fabddcd4SJean Delvare It might even go away if nobody reports it as being useful, 1355fabddcd4SJean Delvare as I see very little reason why this would be needed at 1356fabddcd4SJean Delvare all. */ 13577666c13cSJean Delvare dev_info(dev, "If reset=1 solved a problem you were " 1358fabddcd4SJean Delvare "having, please report!\n"); 1359fabddcd4SJean Delvare 13608d5d45fbSJean Delvare /* save these registers */ 136131b8dc4dSJean Delvare i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); 136231b8dc4dSJean Delvare p = w83781d_read_value(data, W83781D_REG_PWMCLK12); 13638d5d45fbSJean Delvare /* Reset all except Watchdog values and last conversion values 13648d5d45fbSJean Delvare This sets fan-divs to 2, among others */ 136531b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_CONFIG, 0x80); 13668d5d45fbSJean Delvare /* Restore the registers and disable power-on abnormal beep. 13678d5d45fbSJean Delvare This saves FAN 1/2/3 input/output values set by BIOS. */ 136831b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80); 136931b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_PWMCLK12, p); 1370*c531eb3fSGuenter Roeck /* 1371*c531eb3fSGuenter Roeck * Disable master beep-enable (reset turns it on). 1372*c531eb3fSGuenter Roeck * Individual beep_mask should be reset to off but for some 1373*c531eb3fSGuenter Roeck * reason disabling this bit helps some people not get beeped 1374*c531eb3fSGuenter Roeck */ 137531b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 0); 13768d5d45fbSJean Delvare } 13778d5d45fbSJean Delvare 1378fabddcd4SJean Delvare /* Disable power-on abnormal beep, as advised by the datasheet. 1379fabddcd4SJean Delvare Already done if reset=1. */ 1380fabddcd4SJean Delvare if (init && !reset && type != as99127f) { 138131b8dc4dSJean Delvare i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); 138231b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80); 1383fabddcd4SJean Delvare } 1384fabddcd4SJean Delvare 1385303760b4SJean Delvare data->vrm = vid_which_vrm(); 13868d5d45fbSJean Delvare 13878d5d45fbSJean Delvare if ((type != w83781d) && (type != as99127f)) { 138831b8dc4dSJean Delvare tmp = w83781d_read_value(data, W83781D_REG_SCFG1); 13898d5d45fbSJean Delvare for (i = 1; i <= 3; i++) { 13908d5d45fbSJean Delvare if (!(tmp & BIT_SCFG1[i - 1])) { 1391b26f9330SJean Delvare data->sens[i - 1] = 4; 13928d5d45fbSJean Delvare } else { 13938d5d45fbSJean Delvare if (w83781d_read_value 139431b8dc4dSJean Delvare (data, 13958d5d45fbSJean Delvare W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) 13968d5d45fbSJean Delvare data->sens[i - 1] = 1; 13978d5d45fbSJean Delvare else 13988d5d45fbSJean Delvare data->sens[i - 1] = 2; 13998d5d45fbSJean Delvare } 14008d5d45fbSJean Delvare if (type == w83783s && i == 2) 14018d5d45fbSJean Delvare break; 14028d5d45fbSJean Delvare } 14038d5d45fbSJean Delvare } 14048d5d45fbSJean Delvare 14058d5d45fbSJean Delvare if (init && type != as99127f) { 14068d5d45fbSJean Delvare /* Enable temp2 */ 140731b8dc4dSJean Delvare tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG); 14088d5d45fbSJean Delvare if (tmp & 0x01) { 14097666c13cSJean Delvare dev_warn(dev, "Enabling temp2, readings " 14108d5d45fbSJean Delvare "might not make sense\n"); 141131b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG, 14128d5d45fbSJean Delvare tmp & 0xfe); 14138d5d45fbSJean Delvare } 14148d5d45fbSJean Delvare 14158d5d45fbSJean Delvare /* Enable temp3 */ 14168d5d45fbSJean Delvare if (type != w83783s) { 141731b8dc4dSJean Delvare tmp = w83781d_read_value(data, 14188d5d45fbSJean Delvare W83781D_REG_TEMP3_CONFIG); 14198d5d45fbSJean Delvare if (tmp & 0x01) { 14207666c13cSJean Delvare dev_warn(dev, "Enabling temp3, " 14218d5d45fbSJean Delvare "readings might not make sense\n"); 142231b8dc4dSJean Delvare w83781d_write_value(data, 14238d5d45fbSJean Delvare W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); 14248d5d45fbSJean Delvare } 14258d5d45fbSJean Delvare } 14268d5d45fbSJean Delvare } 14278d5d45fbSJean Delvare 14288d5d45fbSJean Delvare /* Start monitoring */ 142931b8dc4dSJean Delvare w83781d_write_value(data, W83781D_REG_CONFIG, 143031b8dc4dSJean Delvare (w83781d_read_value(data, 14318d5d45fbSJean Delvare W83781D_REG_CONFIG) & 0xf7) 14328d5d45fbSJean Delvare | 0x01); 14337666c13cSJean Delvare 14347666c13cSJean Delvare /* A few vars need to be filled upon startup */ 143534875337SJean Delvare for (i = 0; i < 3; i++) { 143634875337SJean Delvare data->fan_min[i] = w83781d_read_value(data, 14377666c13cSJean Delvare W83781D_REG_FAN_MIN(i)); 14387666c13cSJean Delvare } 14397666c13cSJean Delvare 14407666c13cSJean Delvare mutex_init(&data->update_lock); 14418d5d45fbSJean Delvare } 14428d5d45fbSJean Delvare 14438d5d45fbSJean Delvare static struct w83781d_data *w83781d_update_device(struct device *dev) 14448d5d45fbSJean Delvare { 14457666c13cSJean Delvare struct w83781d_data *data = dev_get_drvdata(dev); 14460217eae3SWolfgang Grandegger struct i2c_client *client = data->client; 14478d5d45fbSJean Delvare int i; 14488d5d45fbSJean Delvare 14499a61bf63SIngo Molnar mutex_lock(&data->update_lock); 14508d5d45fbSJean Delvare 14518d5d45fbSJean Delvare if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 14528d5d45fbSJean Delvare || !data->valid) { 14538d5d45fbSJean Delvare dev_dbg(dev, "Starting device update\n"); 14548d5d45fbSJean Delvare 14558d5d45fbSJean Delvare for (i = 0; i <= 8; i++) { 14568d5d45fbSJean Delvare if (data->type == w83783s && i == 1) 14578d5d45fbSJean Delvare continue; /* 783S has no in1 */ 14588d5d45fbSJean Delvare data->in[i] = 145931b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_IN(i)); 14608d5d45fbSJean Delvare data->in_min[i] = 146131b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_IN_MIN(i)); 14628d5d45fbSJean Delvare data->in_max[i] = 146331b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_IN_MAX(i)); 146405663368SJean Delvare if ((data->type != w83782d) && (i == 6)) 14658d5d45fbSJean Delvare break; 14668d5d45fbSJean Delvare } 146734875337SJean Delvare for (i = 0; i < 3; i++) { 146834875337SJean Delvare data->fan[i] = 146931b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_FAN(i)); 147034875337SJean Delvare data->fan_min[i] = 147131b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_FAN_MIN(i)); 14728d5d45fbSJean Delvare } 14738d5d45fbSJean Delvare if (data->type != w83781d && data->type != as99127f) { 147434875337SJean Delvare for (i = 0; i < 4; i++) { 147534875337SJean Delvare data->pwm[i] = 147631b8dc4dSJean Delvare w83781d_read_value(data, 147734875337SJean Delvare W83781D_REG_PWM[i]); 1478848ddf11SJean Delvare /* Only W83782D on SMBus has PWM3 and PWM4 */ 1479848ddf11SJean Delvare if ((data->type != w83782d || !client) 148034875337SJean Delvare && i == 1) 14818d5d45fbSJean Delvare break; 14828d5d45fbSJean Delvare } 14838d5d45fbSJean Delvare /* Only PWM2 can be disabled */ 148434875337SJean Delvare data->pwm2_enable = (w83781d_read_value(data, 14858d5d45fbSJean Delvare W83781D_REG_PWMCLK12) & 0x08) >> 3; 14868d5d45fbSJean Delvare } 14878d5d45fbSJean Delvare 148831b8dc4dSJean Delvare data->temp = w83781d_read_value(data, W83781D_REG_TEMP(1)); 14898d5d45fbSJean Delvare data->temp_max = 149031b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_TEMP_OVER(1)); 14918d5d45fbSJean Delvare data->temp_max_hyst = 149231b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_TEMP_HYST(1)); 14938d5d45fbSJean Delvare data->temp_add[0] = 149431b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_TEMP(2)); 14958d5d45fbSJean Delvare data->temp_max_add[0] = 149631b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_TEMP_OVER(2)); 14978d5d45fbSJean Delvare data->temp_max_hyst_add[0] = 149831b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_TEMP_HYST(2)); 14998d5d45fbSJean Delvare if (data->type != w83783s) { 15008d5d45fbSJean Delvare data->temp_add[1] = 150131b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_TEMP(3)); 15028d5d45fbSJean Delvare data->temp_max_add[1] = 150331b8dc4dSJean Delvare w83781d_read_value(data, 15048d5d45fbSJean Delvare W83781D_REG_TEMP_OVER(3)); 15058d5d45fbSJean Delvare data->temp_max_hyst_add[1] = 150631b8dc4dSJean Delvare w83781d_read_value(data, 15078d5d45fbSJean Delvare W83781D_REG_TEMP_HYST(3)); 15088d5d45fbSJean Delvare } 150931b8dc4dSJean Delvare i = w83781d_read_value(data, W83781D_REG_VID_FANDIV); 15108d5d45fbSJean Delvare data->vid = i & 0x0f; 151131b8dc4dSJean Delvare data->vid |= (w83781d_read_value(data, 15128d5d45fbSJean Delvare W83781D_REG_CHIPID) & 0x01) << 4; 15138d5d45fbSJean Delvare data->fan_div[0] = (i >> 4) & 0x03; 15148d5d45fbSJean Delvare data->fan_div[1] = (i >> 6) & 0x03; 151531b8dc4dSJean Delvare data->fan_div[2] = (w83781d_read_value(data, 15168d5d45fbSJean Delvare W83781D_REG_PIN) >> 6) & 0x03; 15178d5d45fbSJean Delvare if ((data->type != w83781d) && (data->type != as99127f)) { 151831b8dc4dSJean Delvare i = w83781d_read_value(data, W83781D_REG_VBAT); 15198d5d45fbSJean Delvare data->fan_div[0] |= (i >> 3) & 0x04; 15208d5d45fbSJean Delvare data->fan_div[1] |= (i >> 4) & 0x04; 15218d5d45fbSJean Delvare data->fan_div[2] |= (i >> 5) & 0x04; 15228d5d45fbSJean Delvare } 152305663368SJean Delvare if (data->type == w83782d) { 152431b8dc4dSJean Delvare data->alarms = w83781d_read_value(data, 1525c7f5d7edSJean Delvare W83782D_REG_ALARM1) 152631b8dc4dSJean Delvare | (w83781d_read_value(data, 1527c7f5d7edSJean Delvare W83782D_REG_ALARM2) << 8) 152831b8dc4dSJean Delvare | (w83781d_read_value(data, 1529c7f5d7edSJean Delvare W83782D_REG_ALARM3) << 16); 1530c7f5d7edSJean Delvare } else if (data->type == w83783s) { 153131b8dc4dSJean Delvare data->alarms = w83781d_read_value(data, 1532c7f5d7edSJean Delvare W83782D_REG_ALARM1) 153331b8dc4dSJean Delvare | (w83781d_read_value(data, 1534c7f5d7edSJean Delvare W83782D_REG_ALARM2) << 8); 1535c7f5d7edSJean Delvare } else { 1536c7f5d7edSJean Delvare /* No real-time status registers, fall back to 1537c7f5d7edSJean Delvare interrupt status registers */ 153831b8dc4dSJean Delvare data->alarms = w83781d_read_value(data, 1539c7f5d7edSJean Delvare W83781D_REG_ALARM1) 154031b8dc4dSJean Delvare | (w83781d_read_value(data, 1541c7f5d7edSJean Delvare W83781D_REG_ALARM2) << 8); 15428d5d45fbSJean Delvare } 154331b8dc4dSJean Delvare i = w83781d_read_value(data, W83781D_REG_BEEP_INTS2); 15442fbbbf14SJean Delvare data->beep_mask = (i << 8) + 154531b8dc4dSJean Delvare w83781d_read_value(data, W83781D_REG_BEEP_INTS1); 15468d5d45fbSJean Delvare if ((data->type != w83781d) && (data->type != as99127f)) { 15478d5d45fbSJean Delvare data->beep_mask |= 154831b8dc4dSJean Delvare w83781d_read_value(data, 15498d5d45fbSJean Delvare W83781D_REG_BEEP_INTS3) << 16; 15508d5d45fbSJean Delvare } 15518d5d45fbSJean Delvare data->last_updated = jiffies; 15528d5d45fbSJean Delvare data->valid = 1; 15538d5d45fbSJean Delvare } 15548d5d45fbSJean Delvare 15559a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 15568d5d45fbSJean Delvare 15578d5d45fbSJean Delvare return data; 15588d5d45fbSJean Delvare } 15598d5d45fbSJean Delvare 15600217eae3SWolfgang Grandegger static const struct i2c_device_id w83781d_ids[] = { 15610217eae3SWolfgang Grandegger { "w83781d", w83781d, }, 15620217eae3SWolfgang Grandegger { "w83782d", w83782d, }, 15630217eae3SWolfgang Grandegger { "w83783s", w83783s, }, 15640217eae3SWolfgang Grandegger { "as99127f", as99127f }, 15650217eae3SWolfgang Grandegger { /* LIST END */ } 15660217eae3SWolfgang Grandegger }; 15670217eae3SWolfgang Grandegger MODULE_DEVICE_TABLE(i2c, w83781d_ids); 15680217eae3SWolfgang Grandegger 15690217eae3SWolfgang Grandegger static struct i2c_driver w83781d_driver = { 15700217eae3SWolfgang Grandegger .class = I2C_CLASS_HWMON, 15710217eae3SWolfgang Grandegger .driver = { 15720217eae3SWolfgang Grandegger .name = "w83781d", 15730217eae3SWolfgang Grandegger }, 15740217eae3SWolfgang Grandegger .probe = w83781d_probe, 15750217eae3SWolfgang Grandegger .remove = w83781d_remove, 15760217eae3SWolfgang Grandegger .id_table = w83781d_ids, 15770217eae3SWolfgang Grandegger .detect = w83781d_detect, 1578c3813d6aSJean Delvare .address_list = normal_i2c, 15790217eae3SWolfgang Grandegger }; 15800217eae3SWolfgang Grandegger 15810217eae3SWolfgang Grandegger /* 15820217eae3SWolfgang Grandegger * ISA related code 15830217eae3SWolfgang Grandegger */ 1584443850ceSWolfgang Grandegger #ifdef CONFIG_ISA 1585443850ceSWolfgang Grandegger 1586443850ceSWolfgang Grandegger /* ISA device, if found */ 1587443850ceSWolfgang Grandegger static struct platform_device *pdev; 1588443850ceSWolfgang Grandegger 1589443850ceSWolfgang Grandegger static unsigned short isa_address = 0x290; 1590443850ceSWolfgang Grandegger 1591443850ceSWolfgang Grandegger /* I2C devices get this name attribute automatically, but for ISA devices 1592443850ceSWolfgang Grandegger we must create it by ourselves. */ 1593443850ceSWolfgang Grandegger static ssize_t 1594443850ceSWolfgang Grandegger show_name(struct device *dev, struct device_attribute *devattr, char *buf) 1595443850ceSWolfgang Grandegger { 1596443850ceSWolfgang Grandegger struct w83781d_data *data = dev_get_drvdata(dev); 1597360782ddSJean Delvare return sprintf(buf, "%s\n", data->name); 1598443850ceSWolfgang Grandegger } 1599443850ceSWolfgang Grandegger static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 1600443850ceSWolfgang Grandegger 1601443850ceSWolfgang Grandegger static struct w83781d_data *w83781d_data_if_isa(void) 1602443850ceSWolfgang Grandegger { 1603443850ceSWolfgang Grandegger return pdev ? platform_get_drvdata(pdev) : NULL; 1604443850ceSWolfgang Grandegger } 1605443850ceSWolfgang Grandegger 1606443850ceSWolfgang Grandegger /* Returns 1 if the I2C chip appears to be an alias of the ISA chip */ 1607443850ceSWolfgang Grandegger static int w83781d_alias_detect(struct i2c_client *client, u8 chipid) 1608443850ceSWolfgang Grandegger { 16090217eae3SWolfgang Grandegger struct w83781d_data *isa; 1610443850ceSWolfgang Grandegger int i; 1611443850ceSWolfgang Grandegger 1612443850ceSWolfgang Grandegger if (!pdev) /* No ISA chip */ 1613443850ceSWolfgang Grandegger return 0; 1614443850ceSWolfgang Grandegger 1615443850ceSWolfgang Grandegger isa = platform_get_drvdata(pdev); 1616443850ceSWolfgang Grandegger 1617443850ceSWolfgang Grandegger if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr) 1618443850ceSWolfgang Grandegger return 0; /* Address doesn't match */ 1619443850ceSWolfgang Grandegger if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid) 1620443850ceSWolfgang Grandegger return 0; /* Chip type doesn't match */ 1621443850ceSWolfgang Grandegger 1622443850ceSWolfgang Grandegger /* We compare all the limit registers, the config register and the 1623443850ceSWolfgang Grandegger * interrupt mask registers */ 1624443850ceSWolfgang Grandegger for (i = 0x2b; i <= 0x3d; i++) { 16250217eae3SWolfgang Grandegger if (w83781d_read_value(isa, i) != 16260217eae3SWolfgang Grandegger i2c_smbus_read_byte_data(client, i)) 1627443850ceSWolfgang Grandegger return 0; 1628443850ceSWolfgang Grandegger } 1629443850ceSWolfgang Grandegger if (w83781d_read_value(isa, W83781D_REG_CONFIG) != 16300217eae3SWolfgang Grandegger i2c_smbus_read_byte_data(client, W83781D_REG_CONFIG)) 1631443850ceSWolfgang Grandegger return 0; 1632443850ceSWolfgang Grandegger for (i = 0x43; i <= 0x46; i++) { 16330217eae3SWolfgang Grandegger if (w83781d_read_value(isa, i) != 16340217eae3SWolfgang Grandegger i2c_smbus_read_byte_data(client, i)) 1635443850ceSWolfgang Grandegger return 0; 1636443850ceSWolfgang Grandegger } 1637443850ceSWolfgang Grandegger 1638443850ceSWolfgang Grandegger return 1; 1639443850ceSWolfgang Grandegger } 1640443850ceSWolfgang Grandegger 1641443850ceSWolfgang Grandegger static int 1642443850ceSWolfgang Grandegger w83781d_read_value_isa(struct w83781d_data *data, u16 reg) 1643443850ceSWolfgang Grandegger { 1644443850ceSWolfgang Grandegger int word_sized, res; 1645443850ceSWolfgang Grandegger 1646443850ceSWolfgang Grandegger word_sized = (((reg & 0xff00) == 0x100) 1647443850ceSWolfgang Grandegger || ((reg & 0xff00) == 0x200)) 1648443850ceSWolfgang Grandegger && (((reg & 0x00ff) == 0x50) 1649443850ceSWolfgang Grandegger || ((reg & 0x00ff) == 0x53) 1650443850ceSWolfgang Grandegger || ((reg & 0x00ff) == 0x55)); 1651443850ceSWolfgang Grandegger if (reg & 0xff00) { 1652443850ceSWolfgang Grandegger outb_p(W83781D_REG_BANK, 1653360782ddSJean Delvare data->isa_addr + W83781D_ADDR_REG_OFFSET); 1654443850ceSWolfgang Grandegger outb_p(reg >> 8, 1655360782ddSJean Delvare data->isa_addr + W83781D_DATA_REG_OFFSET); 1656443850ceSWolfgang Grandegger } 1657360782ddSJean Delvare outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET); 1658360782ddSJean Delvare res = inb_p(data->isa_addr + W83781D_DATA_REG_OFFSET); 1659443850ceSWolfgang Grandegger if (word_sized) { 1660443850ceSWolfgang Grandegger outb_p((reg & 0xff) + 1, 1661360782ddSJean Delvare data->isa_addr + W83781D_ADDR_REG_OFFSET); 1662443850ceSWolfgang Grandegger res = 1663360782ddSJean Delvare (res << 8) + inb_p(data->isa_addr + 1664443850ceSWolfgang Grandegger W83781D_DATA_REG_OFFSET); 1665443850ceSWolfgang Grandegger } 1666443850ceSWolfgang Grandegger if (reg & 0xff00) { 1667443850ceSWolfgang Grandegger outb_p(W83781D_REG_BANK, 1668360782ddSJean Delvare data->isa_addr + W83781D_ADDR_REG_OFFSET); 1669360782ddSJean Delvare outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET); 1670443850ceSWolfgang Grandegger } 1671443850ceSWolfgang Grandegger return res; 1672443850ceSWolfgang Grandegger } 1673443850ceSWolfgang Grandegger 1674443850ceSWolfgang Grandegger static void 1675443850ceSWolfgang Grandegger w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value) 1676443850ceSWolfgang Grandegger { 1677443850ceSWolfgang Grandegger int word_sized; 1678443850ceSWolfgang Grandegger 1679443850ceSWolfgang Grandegger word_sized = (((reg & 0xff00) == 0x100) 1680443850ceSWolfgang Grandegger || ((reg & 0xff00) == 0x200)) 1681443850ceSWolfgang Grandegger && (((reg & 0x00ff) == 0x53) 1682443850ceSWolfgang Grandegger || ((reg & 0x00ff) == 0x55)); 1683443850ceSWolfgang Grandegger if (reg & 0xff00) { 1684443850ceSWolfgang Grandegger outb_p(W83781D_REG_BANK, 1685360782ddSJean Delvare data->isa_addr + W83781D_ADDR_REG_OFFSET); 1686443850ceSWolfgang Grandegger outb_p(reg >> 8, 1687360782ddSJean Delvare data->isa_addr + W83781D_DATA_REG_OFFSET); 1688443850ceSWolfgang Grandegger } 1689360782ddSJean Delvare outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET); 1690443850ceSWolfgang Grandegger if (word_sized) { 1691443850ceSWolfgang Grandegger outb_p(value >> 8, 1692360782ddSJean Delvare data->isa_addr + W83781D_DATA_REG_OFFSET); 1693443850ceSWolfgang Grandegger outb_p((reg & 0xff) + 1, 1694360782ddSJean Delvare data->isa_addr + W83781D_ADDR_REG_OFFSET); 1695443850ceSWolfgang Grandegger } 1696360782ddSJean Delvare outb_p(value & 0xff, data->isa_addr + W83781D_DATA_REG_OFFSET); 1697443850ceSWolfgang Grandegger if (reg & 0xff00) { 1698443850ceSWolfgang Grandegger outb_p(W83781D_REG_BANK, 1699360782ddSJean Delvare data->isa_addr + W83781D_ADDR_REG_OFFSET); 1700360782ddSJean Delvare outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET); 1701443850ceSWolfgang Grandegger } 1702443850ceSWolfgang Grandegger } 1703443850ceSWolfgang Grandegger 1704443850ceSWolfgang Grandegger /* The SMBus locks itself, usually, but nothing may access the Winbond between 1705443850ceSWolfgang Grandegger bank switches. ISA access must always be locked explicitly! 1706443850ceSWolfgang Grandegger We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, 1707443850ceSWolfgang Grandegger would slow down the W83781D access and should not be necessary. 1708443850ceSWolfgang Grandegger There are some ugly typecasts here, but the good news is - they should 1709443850ceSWolfgang Grandegger nowhere else be necessary! */ 1710443850ceSWolfgang Grandegger static int 1711443850ceSWolfgang Grandegger w83781d_read_value(struct w83781d_data *data, u16 reg) 1712443850ceSWolfgang Grandegger { 17130217eae3SWolfgang Grandegger struct i2c_client *client = data->client; 1714443850ceSWolfgang Grandegger int res; 1715443850ceSWolfgang Grandegger 1716443850ceSWolfgang Grandegger mutex_lock(&data->lock); 17170217eae3SWolfgang Grandegger if (client) 1718443850ceSWolfgang Grandegger res = w83781d_read_value_i2c(data, reg); 1719443850ceSWolfgang Grandegger else 1720443850ceSWolfgang Grandegger res = w83781d_read_value_isa(data, reg); 1721443850ceSWolfgang Grandegger mutex_unlock(&data->lock); 1722443850ceSWolfgang Grandegger return res; 1723443850ceSWolfgang Grandegger } 1724443850ceSWolfgang Grandegger 1725443850ceSWolfgang Grandegger static int 1726443850ceSWolfgang Grandegger w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value) 1727443850ceSWolfgang Grandegger { 17280217eae3SWolfgang Grandegger struct i2c_client *client = data->client; 1729443850ceSWolfgang Grandegger 1730443850ceSWolfgang Grandegger mutex_lock(&data->lock); 17310217eae3SWolfgang Grandegger if (client) 1732443850ceSWolfgang Grandegger w83781d_write_value_i2c(data, reg, value); 1733443850ceSWolfgang Grandegger else 1734443850ceSWolfgang Grandegger w83781d_write_value_isa(data, reg, value); 1735443850ceSWolfgang Grandegger mutex_unlock(&data->lock); 1736443850ceSWolfgang Grandegger return 0; 1737443850ceSWolfgang Grandegger } 1738443850ceSWolfgang Grandegger 1739443850ceSWolfgang Grandegger static int __devinit 1740443850ceSWolfgang Grandegger w83781d_isa_probe(struct platform_device *pdev) 1741443850ceSWolfgang Grandegger { 1742443850ceSWolfgang Grandegger int err, reg; 1743443850ceSWolfgang Grandegger struct w83781d_data *data; 1744443850ceSWolfgang Grandegger struct resource *res; 1745443850ceSWolfgang Grandegger 1746443850ceSWolfgang Grandegger /* Reserve the ISA region */ 1747443850ceSWolfgang Grandegger res = platform_get_resource(pdev, IORESOURCE_IO, 0); 1748443850ceSWolfgang Grandegger if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2, 1749443850ceSWolfgang Grandegger "w83781d")) { 1750443850ceSWolfgang Grandegger err = -EBUSY; 1751443850ceSWolfgang Grandegger goto exit; 1752443850ceSWolfgang Grandegger } 1753443850ceSWolfgang Grandegger 1754443850ceSWolfgang Grandegger data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL); 1755443850ceSWolfgang Grandegger if (!data) { 1756443850ceSWolfgang Grandegger err = -ENOMEM; 1757443850ceSWolfgang Grandegger goto exit_release_region; 1758443850ceSWolfgang Grandegger } 1759443850ceSWolfgang Grandegger mutex_init(&data->lock); 1760360782ddSJean Delvare data->isa_addr = res->start; 1761443850ceSWolfgang Grandegger platform_set_drvdata(pdev, data); 1762443850ceSWolfgang Grandegger 1763443850ceSWolfgang Grandegger reg = w83781d_read_value(data, W83781D_REG_WCHIPID); 1764443850ceSWolfgang Grandegger switch (reg) { 1765443850ceSWolfgang Grandegger case 0x30: 1766443850ceSWolfgang Grandegger data->type = w83782d; 1767360782ddSJean Delvare data->name = "w83782d"; 1768443850ceSWolfgang Grandegger break; 1769443850ceSWolfgang Grandegger default: 1770443850ceSWolfgang Grandegger data->type = w83781d; 1771360782ddSJean Delvare data->name = "w83781d"; 1772443850ceSWolfgang Grandegger } 1773443850ceSWolfgang Grandegger 1774443850ceSWolfgang Grandegger /* Initialize the W83781D chip */ 1775443850ceSWolfgang Grandegger w83781d_init_device(&pdev->dev); 1776443850ceSWolfgang Grandegger 1777443850ceSWolfgang Grandegger /* Register sysfs hooks */ 1778443850ceSWolfgang Grandegger err = w83781d_create_files(&pdev->dev, data->type, 1); 1779443850ceSWolfgang Grandegger if (err) 1780443850ceSWolfgang Grandegger goto exit_remove_files; 1781443850ceSWolfgang Grandegger 1782443850ceSWolfgang Grandegger err = device_create_file(&pdev->dev, &dev_attr_name); 1783443850ceSWolfgang Grandegger if (err) 1784443850ceSWolfgang Grandegger goto exit_remove_files; 1785443850ceSWolfgang Grandegger 1786443850ceSWolfgang Grandegger data->hwmon_dev = hwmon_device_register(&pdev->dev); 1787443850ceSWolfgang Grandegger if (IS_ERR(data->hwmon_dev)) { 1788443850ceSWolfgang Grandegger err = PTR_ERR(data->hwmon_dev); 1789443850ceSWolfgang Grandegger goto exit_remove_files; 1790443850ceSWolfgang Grandegger } 1791443850ceSWolfgang Grandegger 1792443850ceSWolfgang Grandegger return 0; 1793443850ceSWolfgang Grandegger 1794443850ceSWolfgang Grandegger exit_remove_files: 1795443850ceSWolfgang Grandegger sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); 1796443850ceSWolfgang Grandegger sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); 1797443850ceSWolfgang Grandegger device_remove_file(&pdev->dev, &dev_attr_name); 1798443850ceSWolfgang Grandegger kfree(data); 1799443850ceSWolfgang Grandegger exit_release_region: 1800443850ceSWolfgang Grandegger release_region(res->start + W83781D_ADDR_REG_OFFSET, 2); 1801443850ceSWolfgang Grandegger exit: 1802443850ceSWolfgang Grandegger return err; 1803443850ceSWolfgang Grandegger } 1804443850ceSWolfgang Grandegger 1805443850ceSWolfgang Grandegger static int __devexit 1806443850ceSWolfgang Grandegger w83781d_isa_remove(struct platform_device *pdev) 1807443850ceSWolfgang Grandegger { 1808443850ceSWolfgang Grandegger struct w83781d_data *data = platform_get_drvdata(pdev); 1809443850ceSWolfgang Grandegger 1810443850ceSWolfgang Grandegger hwmon_device_unregister(data->hwmon_dev); 1811443850ceSWolfgang Grandegger sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); 1812443850ceSWolfgang Grandegger sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); 1813443850ceSWolfgang Grandegger device_remove_file(&pdev->dev, &dev_attr_name); 1814360782ddSJean Delvare release_region(data->isa_addr + W83781D_ADDR_REG_OFFSET, 2); 1815443850ceSWolfgang Grandegger kfree(data); 1816443850ceSWolfgang Grandegger 1817443850ceSWolfgang Grandegger return 0; 1818443850ceSWolfgang Grandegger } 1819443850ceSWolfgang Grandegger 1820443850ceSWolfgang Grandegger static struct platform_driver w83781d_isa_driver = { 1821443850ceSWolfgang Grandegger .driver = { 1822443850ceSWolfgang Grandegger .owner = THIS_MODULE, 1823443850ceSWolfgang Grandegger .name = "w83781d", 1824443850ceSWolfgang Grandegger }, 1825443850ceSWolfgang Grandegger .probe = w83781d_isa_probe, 1826443850ceSWolfgang Grandegger .remove = __devexit_p(w83781d_isa_remove), 1827443850ceSWolfgang Grandegger }; 1828443850ceSWolfgang Grandegger 18297666c13cSJean Delvare /* return 1 if a supported chip is found, 0 otherwise */ 18307666c13cSJean Delvare static int __init 18317666c13cSJean Delvare w83781d_isa_found(unsigned short address) 18327666c13cSJean Delvare { 18337666c13cSJean Delvare int val, save, found = 0; 1834b0bcdd3cSJean Delvare int port; 18357666c13cSJean Delvare 1836b0bcdd3cSJean Delvare /* Some boards declare base+0 to base+7 as a PNP device, some base+4 1837b0bcdd3cSJean Delvare * to base+7 and some base+5 to base+6. So we better request each port 1838b0bcdd3cSJean Delvare * individually for the probing phase. */ 1839b0bcdd3cSJean Delvare for (port = address; port < address + W83781D_EXTENT; port++) { 1840b0bcdd3cSJean Delvare if (!request_region(port, 1, "w83781d")) { 18411ca28218SJoe Perches pr_debug("Failed to request port 0x%x\n", port); 1842b0bcdd3cSJean Delvare goto release; 18432961cb22SJean Delvare } 18442961cb22SJean Delvare } 18457666c13cSJean Delvare 18467666c13cSJean Delvare #define REALLY_SLOW_IO 18477666c13cSJean Delvare /* We need the timeouts for at least some W83781D-like 18487666c13cSJean Delvare chips. But only if we read 'undefined' registers. */ 18497666c13cSJean Delvare val = inb_p(address + 1); 18507666c13cSJean Delvare if (inb_p(address + 2) != val 18517666c13cSJean Delvare || inb_p(address + 3) != val 18527666c13cSJean Delvare || inb_p(address + 7) != val) { 18531ca28218SJoe Perches pr_debug("Detection failed at step %d\n", 1); 18547666c13cSJean Delvare goto release; 18557666c13cSJean Delvare } 18567666c13cSJean Delvare #undef REALLY_SLOW_IO 18577666c13cSJean Delvare 18587666c13cSJean Delvare /* We should be able to change the 7 LSB of the address port. The 18597666c13cSJean Delvare MSB (busy flag) should be clear initially, set after the write. */ 18607666c13cSJean Delvare save = inb_p(address + W83781D_ADDR_REG_OFFSET); 18617666c13cSJean Delvare if (save & 0x80) { 18621ca28218SJoe Perches pr_debug("Detection failed at step %d\n", 2); 18637666c13cSJean Delvare goto release; 18647666c13cSJean Delvare } 18657666c13cSJean Delvare val = ~save & 0x7f; 18667666c13cSJean Delvare outb_p(val, address + W83781D_ADDR_REG_OFFSET); 18677666c13cSJean Delvare if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) { 18687666c13cSJean Delvare outb_p(save, address + W83781D_ADDR_REG_OFFSET); 18691ca28218SJoe Perches pr_debug("Detection failed at step %d\n", 3); 18707666c13cSJean Delvare goto release; 18717666c13cSJean Delvare } 18727666c13cSJean Delvare 18737666c13cSJean Delvare /* We found a device, now see if it could be a W83781D */ 18747666c13cSJean Delvare outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET); 18757666c13cSJean Delvare val = inb_p(address + W83781D_DATA_REG_OFFSET); 18767666c13cSJean Delvare if (val & 0x80) { 18771ca28218SJoe Perches pr_debug("Detection failed at step %d\n", 4); 18787666c13cSJean Delvare goto release; 18797666c13cSJean Delvare } 18807666c13cSJean Delvare outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); 18817666c13cSJean Delvare save = inb_p(address + W83781D_DATA_REG_OFFSET); 18827666c13cSJean Delvare outb_p(W83781D_REG_CHIPMAN, address + W83781D_ADDR_REG_OFFSET); 18837666c13cSJean Delvare val = inb_p(address + W83781D_DATA_REG_OFFSET); 18847666c13cSJean Delvare if ((!(save & 0x80) && (val != 0xa3)) 18857666c13cSJean Delvare || ((save & 0x80) && (val != 0x5c))) { 18861ca28218SJoe Perches pr_debug("Detection failed at step %d\n", 5); 18877666c13cSJean Delvare goto release; 18887666c13cSJean Delvare } 18897666c13cSJean Delvare outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET); 18907666c13cSJean Delvare val = inb_p(address + W83781D_DATA_REG_OFFSET); 18917666c13cSJean Delvare if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */ 18921ca28218SJoe Perches pr_debug("Detection failed at step %d\n", 6); 18937666c13cSJean Delvare goto release; 18947666c13cSJean Delvare } 18957666c13cSJean Delvare 18967666c13cSJean Delvare /* The busy flag should be clear again */ 18977666c13cSJean Delvare if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) { 18981ca28218SJoe Perches pr_debug("Detection failed at step %d\n", 7); 18997666c13cSJean Delvare goto release; 19007666c13cSJean Delvare } 19017666c13cSJean Delvare 19027666c13cSJean Delvare /* Determine the chip type */ 19037666c13cSJean Delvare outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); 19047666c13cSJean Delvare save = inb_p(address + W83781D_DATA_REG_OFFSET); 19057666c13cSJean Delvare outb_p(save & 0xf8, address + W83781D_DATA_REG_OFFSET); 19067666c13cSJean Delvare outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET); 19077666c13cSJean Delvare val = inb_p(address + W83781D_DATA_REG_OFFSET); 19087666c13cSJean Delvare if ((val & 0xfe) == 0x10 /* W83781D */ 190905663368SJean Delvare || val == 0x30) /* W83782D */ 19107666c13cSJean Delvare found = 1; 19117666c13cSJean Delvare 19127666c13cSJean Delvare if (found) 19131ca28218SJoe Perches pr_info("Found a %s chip at %#x\n", 19147666c13cSJean Delvare val == 0x30 ? "W83782D" : "W83781D", (int)address); 19157666c13cSJean Delvare 19167666c13cSJean Delvare release: 1917b0bcdd3cSJean Delvare for (port--; port >= address; port--) 1918b0bcdd3cSJean Delvare release_region(port, 1); 19197666c13cSJean Delvare return found; 19207666c13cSJean Delvare } 19217666c13cSJean Delvare 19227666c13cSJean Delvare static int __init 19237666c13cSJean Delvare w83781d_isa_device_add(unsigned short address) 19247666c13cSJean Delvare { 19257666c13cSJean Delvare struct resource res = { 19267666c13cSJean Delvare .start = address, 192715bde2f1SJean Delvare .end = address + W83781D_EXTENT - 1, 19287666c13cSJean Delvare .name = "w83781d", 19297666c13cSJean Delvare .flags = IORESOURCE_IO, 19307666c13cSJean Delvare }; 19317666c13cSJean Delvare int err; 19327666c13cSJean Delvare 19337666c13cSJean Delvare pdev = platform_device_alloc("w83781d", address); 19347666c13cSJean Delvare if (!pdev) { 19357666c13cSJean Delvare err = -ENOMEM; 19361ca28218SJoe Perches pr_err("Device allocation failed\n"); 19377666c13cSJean Delvare goto exit; 19387666c13cSJean Delvare } 19397666c13cSJean Delvare 19407666c13cSJean Delvare err = platform_device_add_resources(pdev, &res, 1); 19417666c13cSJean Delvare if (err) { 19421ca28218SJoe Perches pr_err("Device resource addition failed (%d)\n", err); 19437666c13cSJean Delvare goto exit_device_put; 19447666c13cSJean Delvare } 19457666c13cSJean Delvare 19467666c13cSJean Delvare err = platform_device_add(pdev); 19477666c13cSJean Delvare if (err) { 19481ca28218SJoe Perches pr_err("Device addition failed (%d)\n", err); 19497666c13cSJean Delvare goto exit_device_put; 19507666c13cSJean Delvare } 19517666c13cSJean Delvare 19527666c13cSJean Delvare return 0; 19537666c13cSJean Delvare 19547666c13cSJean Delvare exit_device_put: 19557666c13cSJean Delvare platform_device_put(pdev); 19567666c13cSJean Delvare exit: 19577666c13cSJean Delvare pdev = NULL; 19587666c13cSJean Delvare return err; 19597666c13cSJean Delvare } 19607666c13cSJean Delvare 19618d5d45fbSJean Delvare static int __init 1962443850ceSWolfgang Grandegger w83781d_isa_register(void) 19638d5d45fbSJean Delvare { 1964fde09509SJean Delvare int res; 1965fde09509SJean Delvare 19667666c13cSJean Delvare if (w83781d_isa_found(isa_address)) { 19677666c13cSJean Delvare res = platform_driver_register(&w83781d_isa_driver); 19687666c13cSJean Delvare if (res) 1969c6566206SJean Delvare goto exit; 19707666c13cSJean Delvare 19717666c13cSJean Delvare /* Sets global pdev as a side effect */ 19727666c13cSJean Delvare res = w83781d_isa_device_add(isa_address); 19737666c13cSJean Delvare if (res) 19747666c13cSJean Delvare goto exit_unreg_isa_driver; 19757666c13cSJean Delvare } 1976fde09509SJean Delvare 1977fde09509SJean Delvare return 0; 19787666c13cSJean Delvare 19797666c13cSJean Delvare exit_unreg_isa_driver: 19807666c13cSJean Delvare platform_driver_unregister(&w83781d_isa_driver); 19817666c13cSJean Delvare exit: 19827666c13cSJean Delvare return res; 19838d5d45fbSJean Delvare } 19848d5d45fbSJean Delvare 1985dd56b638SGeert Uytterhoeven static void 1986443850ceSWolfgang Grandegger w83781d_isa_unregister(void) 19878d5d45fbSJean Delvare { 19887666c13cSJean Delvare if (pdev) { 19897666c13cSJean Delvare platform_device_unregister(pdev); 19907666c13cSJean Delvare platform_driver_unregister(&w83781d_isa_driver); 19917666c13cSJean Delvare } 1992443850ceSWolfgang Grandegger } 1993443850ceSWolfgang Grandegger #else /* !CONFIG_ISA */ 1994443850ceSWolfgang Grandegger 1995443850ceSWolfgang Grandegger static struct w83781d_data *w83781d_data_if_isa(void) 1996443850ceSWolfgang Grandegger { 1997443850ceSWolfgang Grandegger return NULL; 1998443850ceSWolfgang Grandegger } 1999443850ceSWolfgang Grandegger 2000443850ceSWolfgang Grandegger static int 2001443850ceSWolfgang Grandegger w83781d_alias_detect(struct i2c_client *client, u8 chipid) 2002443850ceSWolfgang Grandegger { 2003443850ceSWolfgang Grandegger return 0; 2004443850ceSWolfgang Grandegger } 2005443850ceSWolfgang Grandegger 2006443850ceSWolfgang Grandegger static int 2007443850ceSWolfgang Grandegger w83781d_read_value(struct w83781d_data *data, u16 reg) 2008443850ceSWolfgang Grandegger { 2009443850ceSWolfgang Grandegger int res; 2010443850ceSWolfgang Grandegger 2011443850ceSWolfgang Grandegger mutex_lock(&data->lock); 2012443850ceSWolfgang Grandegger res = w83781d_read_value_i2c(data, reg); 2013443850ceSWolfgang Grandegger mutex_unlock(&data->lock); 2014443850ceSWolfgang Grandegger 2015443850ceSWolfgang Grandegger return res; 2016443850ceSWolfgang Grandegger } 2017443850ceSWolfgang Grandegger 2018443850ceSWolfgang Grandegger static int 2019443850ceSWolfgang Grandegger w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value) 2020443850ceSWolfgang Grandegger { 2021443850ceSWolfgang Grandegger mutex_lock(&data->lock); 2022443850ceSWolfgang Grandegger w83781d_write_value_i2c(data, reg, value); 2023443850ceSWolfgang Grandegger mutex_unlock(&data->lock); 2024443850ceSWolfgang Grandegger 2025443850ceSWolfgang Grandegger return 0; 2026443850ceSWolfgang Grandegger } 2027443850ceSWolfgang Grandegger 2028443850ceSWolfgang Grandegger static int __init 2029443850ceSWolfgang Grandegger w83781d_isa_register(void) 2030443850ceSWolfgang Grandegger { 2031443850ceSWolfgang Grandegger return 0; 2032443850ceSWolfgang Grandegger } 2033443850ceSWolfgang Grandegger 2034dd56b638SGeert Uytterhoeven static void 2035443850ceSWolfgang Grandegger w83781d_isa_unregister(void) 2036443850ceSWolfgang Grandegger { 2037443850ceSWolfgang Grandegger } 2038443850ceSWolfgang Grandegger #endif /* CONFIG_ISA */ 2039443850ceSWolfgang Grandegger 2040443850ceSWolfgang Grandegger static int __init 2041443850ceSWolfgang Grandegger sensors_w83781d_init(void) 2042443850ceSWolfgang Grandegger { 2043443850ceSWolfgang Grandegger int res; 2044443850ceSWolfgang Grandegger 2045443850ceSWolfgang Grandegger /* We register the ISA device first, so that we can skip the 2046443850ceSWolfgang Grandegger * registration of an I2C interface to the same device. */ 2047443850ceSWolfgang Grandegger res = w83781d_isa_register(); 2048443850ceSWolfgang Grandegger if (res) 2049443850ceSWolfgang Grandegger goto exit; 2050443850ceSWolfgang Grandegger 2051443850ceSWolfgang Grandegger res = i2c_add_driver(&w83781d_driver); 2052443850ceSWolfgang Grandegger if (res) 2053443850ceSWolfgang Grandegger goto exit_unreg_isa; 2054443850ceSWolfgang Grandegger 2055443850ceSWolfgang Grandegger return 0; 2056443850ceSWolfgang Grandegger 2057443850ceSWolfgang Grandegger exit_unreg_isa: 2058443850ceSWolfgang Grandegger w83781d_isa_unregister(); 2059443850ceSWolfgang Grandegger exit: 2060443850ceSWolfgang Grandegger return res; 2061443850ceSWolfgang Grandegger } 2062443850ceSWolfgang Grandegger 2063443850ceSWolfgang Grandegger static void __exit 2064443850ceSWolfgang Grandegger sensors_w83781d_exit(void) 2065443850ceSWolfgang Grandegger { 2066443850ceSWolfgang Grandegger w83781d_isa_unregister(); 20678d5d45fbSJean Delvare i2c_del_driver(&w83781d_driver); 20688d5d45fbSJean Delvare } 20698d5d45fbSJean Delvare 20708d5d45fbSJean Delvare MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " 20718d5d45fbSJean Delvare "Philip Edelbrock <phil@netroedge.com>, " 20728d5d45fbSJean Delvare "and Mark Studebaker <mdsxyz123@yahoo.com>"); 20738d5d45fbSJean Delvare MODULE_DESCRIPTION("W83781D driver"); 20748d5d45fbSJean Delvare MODULE_LICENSE("GPL"); 20758d5d45fbSJean Delvare 20768d5d45fbSJean Delvare module_init(sensors_w83781d_init); 20778d5d45fbSJean Delvare module_exit(sensors_w83781d_exit); 2078