108e7e278SJean Delvare /* 208e7e278SJean Delvare w83627ehf - Driver for the hardware monitoring functionality of 308e7e278SJean Delvare the Winbond W83627EHF Super-I/O chip 408e7e278SJean Delvare Copyright (C) 2005 Jean Delvare <khali@linux-fr.org> 508e7e278SJean Delvare 608e7e278SJean Delvare Shamelessly ripped from the w83627hf driver 708e7e278SJean Delvare Copyright (C) 2003 Mark Studebaker 808e7e278SJean Delvare 908e7e278SJean Delvare Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help 1008e7e278SJean Delvare in testing and debugging this driver. 1108e7e278SJean Delvare 128dd2d2caSJean Delvare This driver also supports the W83627EHG, which is the lead-free 138dd2d2caSJean Delvare version of the W83627EHF. 148dd2d2caSJean Delvare 1508e7e278SJean Delvare This program is free software; you can redistribute it and/or modify 1608e7e278SJean Delvare it under the terms of the GNU General Public License as published by 1708e7e278SJean Delvare the Free Software Foundation; either version 2 of the License, or 1808e7e278SJean Delvare (at your option) any later version. 1908e7e278SJean Delvare 2008e7e278SJean Delvare This program is distributed in the hope that it will be useful, 2108e7e278SJean Delvare but WITHOUT ANY WARRANTY; without even the implied warranty of 2208e7e278SJean Delvare MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2308e7e278SJean Delvare GNU General Public License for more details. 2408e7e278SJean Delvare 2508e7e278SJean Delvare You should have received a copy of the GNU General Public License 2608e7e278SJean Delvare along with this program; if not, write to the Free Software 2708e7e278SJean Delvare Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 2808e7e278SJean Delvare 2908e7e278SJean Delvare 3008e7e278SJean Delvare Supports the following chips: 3108e7e278SJean Delvare 3208e7e278SJean Delvare Chip #vin #fan #pwm #temp chip_id man_id 33cf0676feSRudolf Marek w83627ehf 10 5 - 3 0x88 0x5ca3 3408e7e278SJean Delvare */ 3508e7e278SJean Delvare 3608e7e278SJean Delvare #include <linux/module.h> 3708e7e278SJean Delvare #include <linux/init.h> 3808e7e278SJean Delvare #include <linux/slab.h> 3908e7e278SJean Delvare #include <linux/i2c.h> 40fde09509SJean Delvare #include <linux/i2c-isa.h> 41943b0830SMark M. Hoffman #include <linux/hwmon.h> 42412fec82SYuan Mu #include <linux/hwmon-sysfs.h> 43943b0830SMark M. Hoffman #include <linux/err.h> 449a61bf63SIngo Molnar #include <linux/mutex.h> 4508e7e278SJean Delvare #include <asm/io.h> 4608e7e278SJean Delvare #include "lm75.h" 4708e7e278SJean Delvare 482d8672c5SJean Delvare /* The actual ISA address is read from Super-I/O configuration space */ 492d8672c5SJean Delvare static unsigned short address; 5008e7e278SJean Delvare 5108e7e278SJean Delvare /* 5208e7e278SJean Delvare * Super-I/O constants and functions 5308e7e278SJean Delvare */ 5408e7e278SJean Delvare 5508e7e278SJean Delvare static int REG; /* The register to read/write */ 5608e7e278SJean Delvare static int VAL; /* The value to read/write */ 5708e7e278SJean Delvare 5808e7e278SJean Delvare #define W83627EHF_LD_HWM 0x0b 5908e7e278SJean Delvare 6008e7e278SJean Delvare #define SIO_REG_LDSEL 0x07 /* Logical device select */ 6108e7e278SJean Delvare #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ 6208e7e278SJean Delvare #define SIO_REG_ENABLE 0x30 /* Logical device enable */ 6308e7e278SJean Delvare #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ 6408e7e278SJean Delvare 6508e7e278SJean Delvare #define SIO_W83627EHF_ID 0x8840 6608e7e278SJean Delvare #define SIO_ID_MASK 0xFFC0 6708e7e278SJean Delvare 6808e7e278SJean Delvare static inline void 6908e7e278SJean Delvare superio_outb(int reg, int val) 7008e7e278SJean Delvare { 7108e7e278SJean Delvare outb(reg, REG); 7208e7e278SJean Delvare outb(val, VAL); 7308e7e278SJean Delvare } 7408e7e278SJean Delvare 7508e7e278SJean Delvare static inline int 7608e7e278SJean Delvare superio_inb(int reg) 7708e7e278SJean Delvare { 7808e7e278SJean Delvare outb(reg, REG); 7908e7e278SJean Delvare return inb(VAL); 8008e7e278SJean Delvare } 8108e7e278SJean Delvare 8208e7e278SJean Delvare static inline void 8308e7e278SJean Delvare superio_select(int ld) 8408e7e278SJean Delvare { 8508e7e278SJean Delvare outb(SIO_REG_LDSEL, REG); 8608e7e278SJean Delvare outb(ld, VAL); 8708e7e278SJean Delvare } 8808e7e278SJean Delvare 8908e7e278SJean Delvare static inline void 9008e7e278SJean Delvare superio_enter(void) 9108e7e278SJean Delvare { 9208e7e278SJean Delvare outb(0x87, REG); 9308e7e278SJean Delvare outb(0x87, REG); 9408e7e278SJean Delvare } 9508e7e278SJean Delvare 9608e7e278SJean Delvare static inline void 9708e7e278SJean Delvare superio_exit(void) 9808e7e278SJean Delvare { 9908e7e278SJean Delvare outb(0x02, REG); 10008e7e278SJean Delvare outb(0x02, VAL); 10108e7e278SJean Delvare } 10208e7e278SJean Delvare 10308e7e278SJean Delvare /* 10408e7e278SJean Delvare * ISA constants 10508e7e278SJean Delvare */ 10608e7e278SJean Delvare 107ada0c2f8SPetr Vandrovec #define REGION_ALIGNMENT ~7 108ada0c2f8SPetr Vandrovec #define REGION_OFFSET 5 109ada0c2f8SPetr Vandrovec #define REGION_LENGTH 2 11008e7e278SJean Delvare #define ADDR_REG_OFFSET 5 11108e7e278SJean Delvare #define DATA_REG_OFFSET 6 11208e7e278SJean Delvare 11308e7e278SJean Delvare #define W83627EHF_REG_BANK 0x4E 11408e7e278SJean Delvare #define W83627EHF_REG_CONFIG 0x40 11508e7e278SJean Delvare #define W83627EHF_REG_CHIP_ID 0x49 11608e7e278SJean Delvare #define W83627EHF_REG_MAN_ID 0x4F 11708e7e278SJean Delvare 11808e7e278SJean Delvare static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 }; 11908e7e278SJean Delvare static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c }; 12008e7e278SJean Delvare 121cf0676feSRudolf Marek /* The W83627EHF registers for nr=7,8,9 are in bank 5 */ 122cf0676feSRudolf Marek #define W83627EHF_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ 123cf0676feSRudolf Marek (0x554 + (((nr) - 7) * 2))) 124cf0676feSRudolf Marek #define W83627EHF_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ 125cf0676feSRudolf Marek (0x555 + (((nr) - 7) * 2))) 126cf0676feSRudolf Marek #define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ 127cf0676feSRudolf Marek (0x550 + (nr) - 7)) 128cf0676feSRudolf Marek 12908e7e278SJean Delvare #define W83627EHF_REG_TEMP1 0x27 13008e7e278SJean Delvare #define W83627EHF_REG_TEMP1_HYST 0x3a 13108e7e278SJean Delvare #define W83627EHF_REG_TEMP1_OVER 0x39 13208e7e278SJean Delvare static const u16 W83627EHF_REG_TEMP[] = { 0x150, 0x250 }; 13308e7e278SJean Delvare static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x153, 0x253 }; 13408e7e278SJean Delvare static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x155, 0x255 }; 13508e7e278SJean Delvare static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 }; 13608e7e278SJean Delvare 13708e7e278SJean Delvare /* Fan clock dividers are spread over the following five registers */ 13808e7e278SJean Delvare #define W83627EHF_REG_FANDIV1 0x47 13908e7e278SJean Delvare #define W83627EHF_REG_FANDIV2 0x4B 14008e7e278SJean Delvare #define W83627EHF_REG_VBAT 0x5D 14108e7e278SJean Delvare #define W83627EHF_REG_DIODE 0x59 14208e7e278SJean Delvare #define W83627EHF_REG_SMI_OVT 0x4C 14308e7e278SJean Delvare 144*a4589dbbSJean Delvare #define W83627EHF_REG_ALARM1 0x459 145*a4589dbbSJean Delvare #define W83627EHF_REG_ALARM2 0x45A 146*a4589dbbSJean Delvare #define W83627EHF_REG_ALARM3 0x45B 147*a4589dbbSJean Delvare 14808e7e278SJean Delvare /* 14908e7e278SJean Delvare * Conversions 15008e7e278SJean Delvare */ 15108e7e278SJean Delvare 15208e7e278SJean Delvare static inline unsigned int 15308e7e278SJean Delvare fan_from_reg(u8 reg, unsigned int div) 15408e7e278SJean Delvare { 15508e7e278SJean Delvare if (reg == 0 || reg == 255) 15608e7e278SJean Delvare return 0; 15708e7e278SJean Delvare return 1350000U / (reg * div); 15808e7e278SJean Delvare } 15908e7e278SJean Delvare 16008e7e278SJean Delvare static inline unsigned int 16108e7e278SJean Delvare div_from_reg(u8 reg) 16208e7e278SJean Delvare { 16308e7e278SJean Delvare return 1 << reg; 16408e7e278SJean Delvare } 16508e7e278SJean Delvare 16608e7e278SJean Delvare static inline int 16708e7e278SJean Delvare temp1_from_reg(s8 reg) 16808e7e278SJean Delvare { 16908e7e278SJean Delvare return reg * 1000; 17008e7e278SJean Delvare } 17108e7e278SJean Delvare 17208e7e278SJean Delvare static inline s8 17308e7e278SJean Delvare temp1_to_reg(int temp) 17408e7e278SJean Delvare { 17508e7e278SJean Delvare if (temp <= -128000) 17608e7e278SJean Delvare return -128; 17708e7e278SJean Delvare if (temp >= 127000) 17808e7e278SJean Delvare return 127; 17908e7e278SJean Delvare if (temp < 0) 18008e7e278SJean Delvare return (temp - 500) / 1000; 18108e7e278SJean Delvare return (temp + 500) / 1000; 18208e7e278SJean Delvare } 18308e7e278SJean Delvare 184cf0676feSRudolf Marek /* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */ 185cf0676feSRudolf Marek 186cf0676feSRudolf Marek static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 }; 187cf0676feSRudolf Marek 188cf0676feSRudolf Marek static inline long in_from_reg(u8 reg, u8 nr) 189cf0676feSRudolf Marek { 190cf0676feSRudolf Marek return reg * scale_in[nr]; 191cf0676feSRudolf Marek } 192cf0676feSRudolf Marek 193cf0676feSRudolf Marek static inline u8 in_to_reg(u32 val, u8 nr) 194cf0676feSRudolf Marek { 195cf0676feSRudolf Marek return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255); 196cf0676feSRudolf Marek } 197cf0676feSRudolf Marek 19808e7e278SJean Delvare /* 19908e7e278SJean Delvare * Data structures and manipulation thereof 20008e7e278SJean Delvare */ 20108e7e278SJean Delvare 20208e7e278SJean Delvare struct w83627ehf_data { 20308e7e278SJean Delvare struct i2c_client client; 204943b0830SMark M. Hoffman struct class_device *class_dev; 2059a61bf63SIngo Molnar struct mutex lock; 20608e7e278SJean Delvare 2079a61bf63SIngo Molnar struct mutex update_lock; 20808e7e278SJean Delvare char valid; /* !=0 if following fields are valid */ 20908e7e278SJean Delvare unsigned long last_updated; /* In jiffies */ 21008e7e278SJean Delvare 21108e7e278SJean Delvare /* Register values */ 212cf0676feSRudolf Marek u8 in[10]; /* Register value */ 213cf0676feSRudolf Marek u8 in_max[10]; /* Register value */ 214cf0676feSRudolf Marek u8 in_min[10]; /* Register value */ 21508e7e278SJean Delvare u8 fan[5]; 21608e7e278SJean Delvare u8 fan_min[5]; 21708e7e278SJean Delvare u8 fan_div[5]; 21808e7e278SJean Delvare u8 has_fan; /* some fan inputs can be disabled */ 21908e7e278SJean Delvare s8 temp1; 22008e7e278SJean Delvare s8 temp1_max; 22108e7e278SJean Delvare s8 temp1_max_hyst; 22208e7e278SJean Delvare s16 temp[2]; 22308e7e278SJean Delvare s16 temp_max[2]; 22408e7e278SJean Delvare s16 temp_max_hyst[2]; 225*a4589dbbSJean Delvare u32 alarms; 22608e7e278SJean Delvare }; 22708e7e278SJean Delvare 22808e7e278SJean Delvare static inline int is_word_sized(u16 reg) 22908e7e278SJean Delvare { 23008e7e278SJean Delvare return (((reg & 0xff00) == 0x100 23108e7e278SJean Delvare || (reg & 0xff00) == 0x200) 23208e7e278SJean Delvare && ((reg & 0x00ff) == 0x50 23308e7e278SJean Delvare || (reg & 0x00ff) == 0x53 23408e7e278SJean Delvare || (reg & 0x00ff) == 0x55)); 23508e7e278SJean Delvare } 23608e7e278SJean Delvare 23708e7e278SJean Delvare /* We assume that the default bank is 0, thus the following two functions do 23808e7e278SJean Delvare nothing for registers which live in bank 0. For others, they respectively 23908e7e278SJean Delvare set the bank register to the correct value (before the register is 24008e7e278SJean Delvare accessed), and back to 0 (afterwards). */ 24108e7e278SJean Delvare static inline void w83627ehf_set_bank(struct i2c_client *client, u16 reg) 24208e7e278SJean Delvare { 24308e7e278SJean Delvare if (reg & 0xff00) { 24408e7e278SJean Delvare outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET); 24508e7e278SJean Delvare outb_p(reg >> 8, client->addr + DATA_REG_OFFSET); 24608e7e278SJean Delvare } 24708e7e278SJean Delvare } 24808e7e278SJean Delvare 24908e7e278SJean Delvare static inline void w83627ehf_reset_bank(struct i2c_client *client, u16 reg) 25008e7e278SJean Delvare { 25108e7e278SJean Delvare if (reg & 0xff00) { 25208e7e278SJean Delvare outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET); 25308e7e278SJean Delvare outb_p(0, client->addr + DATA_REG_OFFSET); 25408e7e278SJean Delvare } 25508e7e278SJean Delvare } 25608e7e278SJean Delvare 25708e7e278SJean Delvare static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg) 25808e7e278SJean Delvare { 25908e7e278SJean Delvare struct w83627ehf_data *data = i2c_get_clientdata(client); 26008e7e278SJean Delvare int res, word_sized = is_word_sized(reg); 26108e7e278SJean Delvare 2629a61bf63SIngo Molnar mutex_lock(&data->lock); 26308e7e278SJean Delvare 26408e7e278SJean Delvare w83627ehf_set_bank(client, reg); 26508e7e278SJean Delvare outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); 26608e7e278SJean Delvare res = inb_p(client->addr + DATA_REG_OFFSET); 26708e7e278SJean Delvare if (word_sized) { 26808e7e278SJean Delvare outb_p((reg & 0xff) + 1, 26908e7e278SJean Delvare client->addr + ADDR_REG_OFFSET); 27008e7e278SJean Delvare res = (res << 8) + inb_p(client->addr + DATA_REG_OFFSET); 27108e7e278SJean Delvare } 27208e7e278SJean Delvare w83627ehf_reset_bank(client, reg); 27308e7e278SJean Delvare 2749a61bf63SIngo Molnar mutex_unlock(&data->lock); 27508e7e278SJean Delvare 27608e7e278SJean Delvare return res; 27708e7e278SJean Delvare } 27808e7e278SJean Delvare 27908e7e278SJean Delvare static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value) 28008e7e278SJean Delvare { 28108e7e278SJean Delvare struct w83627ehf_data *data = i2c_get_clientdata(client); 28208e7e278SJean Delvare int word_sized = is_word_sized(reg); 28308e7e278SJean Delvare 2849a61bf63SIngo Molnar mutex_lock(&data->lock); 28508e7e278SJean Delvare 28608e7e278SJean Delvare w83627ehf_set_bank(client, reg); 28708e7e278SJean Delvare outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); 28808e7e278SJean Delvare if (word_sized) { 28908e7e278SJean Delvare outb_p(value >> 8, client->addr + DATA_REG_OFFSET); 29008e7e278SJean Delvare outb_p((reg & 0xff) + 1, 29108e7e278SJean Delvare client->addr + ADDR_REG_OFFSET); 29208e7e278SJean Delvare } 29308e7e278SJean Delvare outb_p(value & 0xff, client->addr + DATA_REG_OFFSET); 29408e7e278SJean Delvare w83627ehf_reset_bank(client, reg); 29508e7e278SJean Delvare 2969a61bf63SIngo Molnar mutex_unlock(&data->lock); 29708e7e278SJean Delvare return 0; 29808e7e278SJean Delvare } 29908e7e278SJean Delvare 30008e7e278SJean Delvare /* This function assumes that the caller holds data->update_lock */ 30108e7e278SJean Delvare static void w83627ehf_write_fan_div(struct i2c_client *client, int nr) 30208e7e278SJean Delvare { 30308e7e278SJean Delvare struct w83627ehf_data *data = i2c_get_clientdata(client); 30408e7e278SJean Delvare u8 reg; 30508e7e278SJean Delvare 30608e7e278SJean Delvare switch (nr) { 30708e7e278SJean Delvare case 0: 30808e7e278SJean Delvare reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf) 30908e7e278SJean Delvare | ((data->fan_div[0] & 0x03) << 4); 31008e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg); 31108e7e278SJean Delvare reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf) 31208e7e278SJean Delvare | ((data->fan_div[0] & 0x04) << 3); 31308e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg); 31408e7e278SJean Delvare break; 31508e7e278SJean Delvare case 1: 31608e7e278SJean Delvare reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f) 31708e7e278SJean Delvare | ((data->fan_div[1] & 0x03) << 6); 31808e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg); 31908e7e278SJean Delvare reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf) 32008e7e278SJean Delvare | ((data->fan_div[1] & 0x04) << 4); 32108e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg); 32208e7e278SJean Delvare break; 32308e7e278SJean Delvare case 2: 32408e7e278SJean Delvare reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV2) & 0x3f) 32508e7e278SJean Delvare | ((data->fan_div[2] & 0x03) << 6); 32608e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_FANDIV2, reg); 32708e7e278SJean Delvare reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0x7f) 32808e7e278SJean Delvare | ((data->fan_div[2] & 0x04) << 5); 32908e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg); 33008e7e278SJean Delvare break; 33108e7e278SJean Delvare case 3: 33208e7e278SJean Delvare reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0xfc) 33308e7e278SJean Delvare | (data->fan_div[3] & 0x03); 33408e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg); 33508e7e278SJean Delvare reg = (w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT) & 0x7f) 33608e7e278SJean Delvare | ((data->fan_div[3] & 0x04) << 5); 33708e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_SMI_OVT, reg); 33808e7e278SJean Delvare break; 33908e7e278SJean Delvare case 4: 34008e7e278SJean Delvare reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73) 34108e7e278SJean Delvare | ((data->fan_div[4] & 0x03) << 3) 34208e7e278SJean Delvare | ((data->fan_div[4] & 0x04) << 5); 34308e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg); 34408e7e278SJean Delvare break; 34508e7e278SJean Delvare } 34608e7e278SJean Delvare } 34708e7e278SJean Delvare 34808e7e278SJean Delvare static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) 34908e7e278SJean Delvare { 35008e7e278SJean Delvare struct i2c_client *client = to_i2c_client(dev); 35108e7e278SJean Delvare struct w83627ehf_data *data = i2c_get_clientdata(client); 35208e7e278SJean Delvare int i; 35308e7e278SJean Delvare 3549a61bf63SIngo Molnar mutex_lock(&data->update_lock); 35508e7e278SJean Delvare 35608e7e278SJean Delvare if (time_after(jiffies, data->last_updated + HZ) 35708e7e278SJean Delvare || !data->valid) { 35808e7e278SJean Delvare /* Fan clock dividers */ 35908e7e278SJean Delvare i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1); 36008e7e278SJean Delvare data->fan_div[0] = (i >> 4) & 0x03; 36108e7e278SJean Delvare data->fan_div[1] = (i >> 6) & 0x03; 36208e7e278SJean Delvare i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV2); 36308e7e278SJean Delvare data->fan_div[2] = (i >> 6) & 0x03; 36408e7e278SJean Delvare i = w83627ehf_read_value(client, W83627EHF_REG_VBAT); 36508e7e278SJean Delvare data->fan_div[0] |= (i >> 3) & 0x04; 36608e7e278SJean Delvare data->fan_div[1] |= (i >> 4) & 0x04; 36708e7e278SJean Delvare data->fan_div[2] |= (i >> 5) & 0x04; 36808e7e278SJean Delvare if (data->has_fan & ((1 << 3) | (1 << 4))) { 36908e7e278SJean Delvare i = w83627ehf_read_value(client, W83627EHF_REG_DIODE); 37008e7e278SJean Delvare data->fan_div[3] = i & 0x03; 37108e7e278SJean Delvare data->fan_div[4] = ((i >> 2) & 0x03) 37208e7e278SJean Delvare | ((i >> 5) & 0x04); 37308e7e278SJean Delvare } 37408e7e278SJean Delvare if (data->has_fan & (1 << 3)) { 37508e7e278SJean Delvare i = w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT); 37608e7e278SJean Delvare data->fan_div[3] |= (i >> 5) & 0x04; 37708e7e278SJean Delvare } 37808e7e278SJean Delvare 379cf0676feSRudolf Marek /* Measured voltages and limits */ 380cf0676feSRudolf Marek for (i = 0; i < 10; i++) { 381cf0676feSRudolf Marek data->in[i] = w83627ehf_read_value(client, 382cf0676feSRudolf Marek W83627EHF_REG_IN(i)); 383cf0676feSRudolf Marek data->in_min[i] = w83627ehf_read_value(client, 384cf0676feSRudolf Marek W83627EHF_REG_IN_MIN(i)); 385cf0676feSRudolf Marek data->in_max[i] = w83627ehf_read_value(client, 386cf0676feSRudolf Marek W83627EHF_REG_IN_MAX(i)); 387cf0676feSRudolf Marek } 388cf0676feSRudolf Marek 38908e7e278SJean Delvare /* Measured fan speeds and limits */ 39008e7e278SJean Delvare for (i = 0; i < 5; i++) { 39108e7e278SJean Delvare if (!(data->has_fan & (1 << i))) 39208e7e278SJean Delvare continue; 39308e7e278SJean Delvare 39408e7e278SJean Delvare data->fan[i] = w83627ehf_read_value(client, 39508e7e278SJean Delvare W83627EHF_REG_FAN[i]); 39608e7e278SJean Delvare data->fan_min[i] = w83627ehf_read_value(client, 39708e7e278SJean Delvare W83627EHF_REG_FAN_MIN[i]); 39808e7e278SJean Delvare 39908e7e278SJean Delvare /* If we failed to measure the fan speed and clock 40008e7e278SJean Delvare divider can be increased, let's try that for next 40108e7e278SJean Delvare time */ 40208e7e278SJean Delvare if (data->fan[i] == 0xff 40308e7e278SJean Delvare && data->fan_div[i] < 0x07) { 40408e7e278SJean Delvare dev_dbg(&client->dev, "Increasing fan %d " 40508e7e278SJean Delvare "clock divider from %u to %u\n", 40608e7e278SJean Delvare i, div_from_reg(data->fan_div[i]), 40708e7e278SJean Delvare div_from_reg(data->fan_div[i] + 1)); 40808e7e278SJean Delvare data->fan_div[i]++; 40908e7e278SJean Delvare w83627ehf_write_fan_div(client, i); 41008e7e278SJean Delvare /* Preserve min limit if possible */ 41108e7e278SJean Delvare if (data->fan_min[i] >= 2 41208e7e278SJean Delvare && data->fan_min[i] != 255) 41308e7e278SJean Delvare w83627ehf_write_value(client, 41408e7e278SJean Delvare W83627EHF_REG_FAN_MIN[i], 41508e7e278SJean Delvare (data->fan_min[i] /= 2)); 41608e7e278SJean Delvare } 41708e7e278SJean Delvare } 41808e7e278SJean Delvare 41908e7e278SJean Delvare /* Measured temperatures and limits */ 42008e7e278SJean Delvare data->temp1 = w83627ehf_read_value(client, 42108e7e278SJean Delvare W83627EHF_REG_TEMP1); 42208e7e278SJean Delvare data->temp1_max = w83627ehf_read_value(client, 42308e7e278SJean Delvare W83627EHF_REG_TEMP1_OVER); 42408e7e278SJean Delvare data->temp1_max_hyst = w83627ehf_read_value(client, 42508e7e278SJean Delvare W83627EHF_REG_TEMP1_HYST); 42608e7e278SJean Delvare for (i = 0; i < 2; i++) { 42708e7e278SJean Delvare data->temp[i] = w83627ehf_read_value(client, 42808e7e278SJean Delvare W83627EHF_REG_TEMP[i]); 42908e7e278SJean Delvare data->temp_max[i] = w83627ehf_read_value(client, 43008e7e278SJean Delvare W83627EHF_REG_TEMP_OVER[i]); 43108e7e278SJean Delvare data->temp_max_hyst[i] = w83627ehf_read_value(client, 43208e7e278SJean Delvare W83627EHF_REG_TEMP_HYST[i]); 43308e7e278SJean Delvare } 43408e7e278SJean Delvare 435*a4589dbbSJean Delvare data->alarms = w83627ehf_read_value(client, 436*a4589dbbSJean Delvare W83627EHF_REG_ALARM1) | 437*a4589dbbSJean Delvare (w83627ehf_read_value(client, 438*a4589dbbSJean Delvare W83627EHF_REG_ALARM2) << 8) | 439*a4589dbbSJean Delvare (w83627ehf_read_value(client, 440*a4589dbbSJean Delvare W83627EHF_REG_ALARM3) << 16); 441*a4589dbbSJean Delvare 44208e7e278SJean Delvare data->last_updated = jiffies; 44308e7e278SJean Delvare data->valid = 1; 44408e7e278SJean Delvare } 44508e7e278SJean Delvare 4469a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 44708e7e278SJean Delvare return data; 44808e7e278SJean Delvare } 44908e7e278SJean Delvare 45008e7e278SJean Delvare /* 45108e7e278SJean Delvare * Sysfs callback functions 45208e7e278SJean Delvare */ 453cf0676feSRudolf Marek #define show_in_reg(reg) \ 454cf0676feSRudolf Marek static ssize_t \ 455cf0676feSRudolf Marek show_##reg(struct device *dev, struct device_attribute *attr, \ 456cf0676feSRudolf Marek char *buf) \ 457cf0676feSRudolf Marek { \ 458cf0676feSRudolf Marek struct w83627ehf_data *data = w83627ehf_update_device(dev); \ 459cf0676feSRudolf Marek struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ 460cf0676feSRudolf Marek int nr = sensor_attr->index; \ 461cf0676feSRudolf Marek return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \ 462cf0676feSRudolf Marek } 463cf0676feSRudolf Marek show_in_reg(in) 464cf0676feSRudolf Marek show_in_reg(in_min) 465cf0676feSRudolf Marek show_in_reg(in_max) 466cf0676feSRudolf Marek 467cf0676feSRudolf Marek #define store_in_reg(REG, reg) \ 468cf0676feSRudolf Marek static ssize_t \ 469cf0676feSRudolf Marek store_in_##reg (struct device *dev, struct device_attribute *attr, \ 470cf0676feSRudolf Marek const char *buf, size_t count) \ 471cf0676feSRudolf Marek { \ 472cf0676feSRudolf Marek struct i2c_client *client = to_i2c_client(dev); \ 473cf0676feSRudolf Marek struct w83627ehf_data *data = i2c_get_clientdata(client); \ 474cf0676feSRudolf Marek struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ 475cf0676feSRudolf Marek int nr = sensor_attr->index; \ 476cf0676feSRudolf Marek u32 val = simple_strtoul(buf, NULL, 10); \ 477cf0676feSRudolf Marek \ 478cf0676feSRudolf Marek mutex_lock(&data->update_lock); \ 479cf0676feSRudolf Marek data->in_##reg[nr] = in_to_reg(val, nr); \ 480cf0676feSRudolf Marek w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \ 481cf0676feSRudolf Marek data->in_##reg[nr]); \ 482cf0676feSRudolf Marek mutex_unlock(&data->update_lock); \ 483cf0676feSRudolf Marek return count; \ 484cf0676feSRudolf Marek } 485cf0676feSRudolf Marek 486cf0676feSRudolf Marek store_in_reg(MIN, min) 487cf0676feSRudolf Marek store_in_reg(MAX, max) 488cf0676feSRudolf Marek 489*a4589dbbSJean Delvare static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, char *buf) 490*a4589dbbSJean Delvare { 491*a4589dbbSJean Delvare struct w83627ehf_data *data = w83627ehf_update_device(dev); 492*a4589dbbSJean Delvare struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 493*a4589dbbSJean Delvare int nr = sensor_attr->index; 494*a4589dbbSJean Delvare return sprintf(buf, "%u\n", (data->alarms >> nr) & 0x01); 495*a4589dbbSJean Delvare } 496*a4589dbbSJean Delvare 497cf0676feSRudolf Marek static struct sensor_device_attribute sda_in_input[] = { 498cf0676feSRudolf Marek SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), 499cf0676feSRudolf Marek SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), 500cf0676feSRudolf Marek SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), 501cf0676feSRudolf Marek SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), 502cf0676feSRudolf Marek SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), 503cf0676feSRudolf Marek SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), 504cf0676feSRudolf Marek SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), 505cf0676feSRudolf Marek SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), 506cf0676feSRudolf Marek SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), 507cf0676feSRudolf Marek SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), 508cf0676feSRudolf Marek }; 509cf0676feSRudolf Marek 510*a4589dbbSJean Delvare static struct sensor_device_attribute sda_in_alarm[] = { 511*a4589dbbSJean Delvare SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), 512*a4589dbbSJean Delvare SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), 513*a4589dbbSJean Delvare SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), 514*a4589dbbSJean Delvare SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), 515*a4589dbbSJean Delvare SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8), 516*a4589dbbSJean Delvare SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21), 517*a4589dbbSJean Delvare SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20), 518*a4589dbbSJean Delvare SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16), 519*a4589dbbSJean Delvare SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17), 520*a4589dbbSJean Delvare SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19), 521*a4589dbbSJean Delvare }; 522*a4589dbbSJean Delvare 523cf0676feSRudolf Marek static struct sensor_device_attribute sda_in_min[] = { 524cf0676feSRudolf Marek SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), 525cf0676feSRudolf Marek SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), 526cf0676feSRudolf Marek SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), 527cf0676feSRudolf Marek SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), 528cf0676feSRudolf Marek SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), 529cf0676feSRudolf Marek SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), 530cf0676feSRudolf Marek SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), 531cf0676feSRudolf Marek SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), 532cf0676feSRudolf Marek SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), 533cf0676feSRudolf Marek SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9), 534cf0676feSRudolf Marek }; 535cf0676feSRudolf Marek 536cf0676feSRudolf Marek static struct sensor_device_attribute sda_in_max[] = { 537cf0676feSRudolf Marek SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), 538cf0676feSRudolf Marek SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), 539cf0676feSRudolf Marek SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), 540cf0676feSRudolf Marek SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), 541cf0676feSRudolf Marek SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), 542cf0676feSRudolf Marek SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), 543cf0676feSRudolf Marek SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), 544cf0676feSRudolf Marek SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), 545cf0676feSRudolf Marek SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), 546cf0676feSRudolf Marek SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), 547cf0676feSRudolf Marek }; 548cf0676feSRudolf Marek 549cf0676feSRudolf Marek static void device_create_file_in(struct device *dev, int i) 550cf0676feSRudolf Marek { 551cf0676feSRudolf Marek device_create_file(dev, &sda_in_input[i].dev_attr); 552*a4589dbbSJean Delvare device_create_file(dev, &sda_in_alarm[i].dev_attr); 553cf0676feSRudolf Marek device_create_file(dev, &sda_in_min[i].dev_attr); 554cf0676feSRudolf Marek device_create_file(dev, &sda_in_max[i].dev_attr); 555cf0676feSRudolf Marek } 55608e7e278SJean Delvare 55708e7e278SJean Delvare #define show_fan_reg(reg) \ 55808e7e278SJean Delvare static ssize_t \ 559412fec82SYuan Mu show_##reg(struct device *dev, struct device_attribute *attr, \ 560412fec82SYuan Mu char *buf) \ 56108e7e278SJean Delvare { \ 56208e7e278SJean Delvare struct w83627ehf_data *data = w83627ehf_update_device(dev); \ 563412fec82SYuan Mu struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ 564412fec82SYuan Mu int nr = sensor_attr->index; \ 56508e7e278SJean Delvare return sprintf(buf, "%d\n", \ 56608e7e278SJean Delvare fan_from_reg(data->reg[nr], \ 56708e7e278SJean Delvare div_from_reg(data->fan_div[nr]))); \ 56808e7e278SJean Delvare } 56908e7e278SJean Delvare show_fan_reg(fan); 57008e7e278SJean Delvare show_fan_reg(fan_min); 57108e7e278SJean Delvare 57208e7e278SJean Delvare static ssize_t 573412fec82SYuan Mu show_fan_div(struct device *dev, struct device_attribute *attr, 574412fec82SYuan Mu char *buf) 57508e7e278SJean Delvare { 57608e7e278SJean Delvare struct w83627ehf_data *data = w83627ehf_update_device(dev); 577412fec82SYuan Mu struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 578412fec82SYuan Mu int nr = sensor_attr->index; 579412fec82SYuan Mu return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr])); 58008e7e278SJean Delvare } 58108e7e278SJean Delvare 58208e7e278SJean Delvare static ssize_t 583412fec82SYuan Mu store_fan_min(struct device *dev, struct device_attribute *attr, 584412fec82SYuan Mu const char *buf, size_t count) 58508e7e278SJean Delvare { 58608e7e278SJean Delvare struct i2c_client *client = to_i2c_client(dev); 58708e7e278SJean Delvare struct w83627ehf_data *data = i2c_get_clientdata(client); 588412fec82SYuan Mu struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 589412fec82SYuan Mu int nr = sensor_attr->index; 59008e7e278SJean Delvare unsigned int val = simple_strtoul(buf, NULL, 10); 59108e7e278SJean Delvare unsigned int reg; 59208e7e278SJean Delvare u8 new_div; 59308e7e278SJean Delvare 5949a61bf63SIngo Molnar mutex_lock(&data->update_lock); 59508e7e278SJean Delvare if (!val) { 59608e7e278SJean Delvare /* No min limit, alarm disabled */ 59708e7e278SJean Delvare data->fan_min[nr] = 255; 59808e7e278SJean Delvare new_div = data->fan_div[nr]; /* No change */ 59908e7e278SJean Delvare dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1); 60008e7e278SJean Delvare } else if ((reg = 1350000U / val) >= 128 * 255) { 60108e7e278SJean Delvare /* Speed below this value cannot possibly be represented, 60208e7e278SJean Delvare even with the highest divider (128) */ 60308e7e278SJean Delvare data->fan_min[nr] = 254; 60408e7e278SJean Delvare new_div = 7; /* 128 == (1 << 7) */ 60508e7e278SJean Delvare dev_warn(dev, "fan%u low limit %u below minimum %u, set to " 60608e7e278SJean Delvare "minimum\n", nr + 1, val, fan_from_reg(254, 128)); 60708e7e278SJean Delvare } else if (!reg) { 60808e7e278SJean Delvare /* Speed above this value cannot possibly be represented, 60908e7e278SJean Delvare even with the lowest divider (1) */ 61008e7e278SJean Delvare data->fan_min[nr] = 1; 61108e7e278SJean Delvare new_div = 0; /* 1 == (1 << 0) */ 61208e7e278SJean Delvare dev_warn(dev, "fan%u low limit %u above maximum %u, set to " 613b9110b1cSJean Delvare "maximum\n", nr + 1, val, fan_from_reg(1, 1)); 61408e7e278SJean Delvare } else { 61508e7e278SJean Delvare /* Automatically pick the best divider, i.e. the one such 61608e7e278SJean Delvare that the min limit will correspond to a register value 61708e7e278SJean Delvare in the 96..192 range */ 61808e7e278SJean Delvare new_div = 0; 61908e7e278SJean Delvare while (reg > 192 && new_div < 7) { 62008e7e278SJean Delvare reg >>= 1; 62108e7e278SJean Delvare new_div++; 62208e7e278SJean Delvare } 62308e7e278SJean Delvare data->fan_min[nr] = reg; 62408e7e278SJean Delvare } 62508e7e278SJean Delvare 62608e7e278SJean Delvare /* Write both the fan clock divider (if it changed) and the new 62708e7e278SJean Delvare fan min (unconditionally) */ 62808e7e278SJean Delvare if (new_div != data->fan_div[nr]) { 62908e7e278SJean Delvare if (new_div > data->fan_div[nr]) 63008e7e278SJean Delvare data->fan[nr] >>= (data->fan_div[nr] - new_div); 63108e7e278SJean Delvare else 63208e7e278SJean Delvare data->fan[nr] <<= (new_div - data->fan_div[nr]); 63308e7e278SJean Delvare 63408e7e278SJean Delvare dev_dbg(dev, "fan%u clock divider changed from %u to %u\n", 63508e7e278SJean Delvare nr + 1, div_from_reg(data->fan_div[nr]), 63608e7e278SJean Delvare div_from_reg(new_div)); 63708e7e278SJean Delvare data->fan_div[nr] = new_div; 63808e7e278SJean Delvare w83627ehf_write_fan_div(client, nr); 63908e7e278SJean Delvare } 64008e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr], 64108e7e278SJean Delvare data->fan_min[nr]); 6429a61bf63SIngo Molnar mutex_unlock(&data->update_lock); 64308e7e278SJean Delvare 64408e7e278SJean Delvare return count; 64508e7e278SJean Delvare } 64608e7e278SJean Delvare 647412fec82SYuan Mu static struct sensor_device_attribute sda_fan_input[] = { 648412fec82SYuan Mu SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), 649412fec82SYuan Mu SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), 650412fec82SYuan Mu SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), 651412fec82SYuan Mu SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), 652412fec82SYuan Mu SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), 653412fec82SYuan Mu }; 65408e7e278SJean Delvare 655*a4589dbbSJean Delvare static struct sensor_device_attribute sda_fan_alarm[] = { 656*a4589dbbSJean Delvare SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6), 657*a4589dbbSJean Delvare SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7), 658*a4589dbbSJean Delvare SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11), 659*a4589dbbSJean Delvare SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 10), 660*a4589dbbSJean Delvare SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23), 661*a4589dbbSJean Delvare }; 662*a4589dbbSJean Delvare 663412fec82SYuan Mu static struct sensor_device_attribute sda_fan_min[] = { 664412fec82SYuan Mu SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, 665412fec82SYuan Mu store_fan_min, 0), 666412fec82SYuan Mu SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, 667412fec82SYuan Mu store_fan_min, 1), 668412fec82SYuan Mu SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, 669412fec82SYuan Mu store_fan_min, 2), 670412fec82SYuan Mu SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, 671412fec82SYuan Mu store_fan_min, 3), 672412fec82SYuan Mu SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, 673412fec82SYuan Mu store_fan_min, 4), 674412fec82SYuan Mu }; 67508e7e278SJean Delvare 676412fec82SYuan Mu static struct sensor_device_attribute sda_fan_div[] = { 677412fec82SYuan Mu SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), 678412fec82SYuan Mu SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), 679412fec82SYuan Mu SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), 680412fec82SYuan Mu SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3), 681412fec82SYuan Mu SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4), 682412fec82SYuan Mu }; 68308e7e278SJean Delvare 684412fec82SYuan Mu static void device_create_file_fan(struct device *dev, int i) 685412fec82SYuan Mu { 686412fec82SYuan Mu device_create_file(dev, &sda_fan_input[i].dev_attr); 687*a4589dbbSJean Delvare device_create_file(dev, &sda_fan_alarm[i].dev_attr); 688412fec82SYuan Mu device_create_file(dev, &sda_fan_div[i].dev_attr); 689412fec82SYuan Mu device_create_file(dev, &sda_fan_min[i].dev_attr); 690412fec82SYuan Mu } 69108e7e278SJean Delvare 69208e7e278SJean Delvare #define show_temp1_reg(reg) \ 69308e7e278SJean Delvare static ssize_t \ 6946f637a64SGreg Kroah-Hartman show_##reg(struct device *dev, struct device_attribute *attr, \ 6956f637a64SGreg Kroah-Hartman char *buf) \ 69608e7e278SJean Delvare { \ 69708e7e278SJean Delvare struct w83627ehf_data *data = w83627ehf_update_device(dev); \ 69808e7e278SJean Delvare return sprintf(buf, "%d\n", temp1_from_reg(data->reg)); \ 69908e7e278SJean Delvare } 70008e7e278SJean Delvare show_temp1_reg(temp1); 70108e7e278SJean Delvare show_temp1_reg(temp1_max); 70208e7e278SJean Delvare show_temp1_reg(temp1_max_hyst); 70308e7e278SJean Delvare 70408e7e278SJean Delvare #define store_temp1_reg(REG, reg) \ 70508e7e278SJean Delvare static ssize_t \ 7066f637a64SGreg Kroah-Hartman store_temp1_##reg(struct device *dev, struct device_attribute *attr, \ 7076f637a64SGreg Kroah-Hartman const char *buf, size_t count) \ 70808e7e278SJean Delvare { \ 70908e7e278SJean Delvare struct i2c_client *client = to_i2c_client(dev); \ 71008e7e278SJean Delvare struct w83627ehf_data *data = i2c_get_clientdata(client); \ 71108e7e278SJean Delvare u32 val = simple_strtoul(buf, NULL, 10); \ 71208e7e278SJean Delvare \ 7139a61bf63SIngo Molnar mutex_lock(&data->update_lock); \ 71408e7e278SJean Delvare data->temp1_##reg = temp1_to_reg(val); \ 71508e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \ 71608e7e278SJean Delvare data->temp1_##reg); \ 7179a61bf63SIngo Molnar mutex_unlock(&data->update_lock); \ 71808e7e278SJean Delvare return count; \ 71908e7e278SJean Delvare } 72008e7e278SJean Delvare store_temp1_reg(OVER, max); 72108e7e278SJean Delvare store_temp1_reg(HYST, max_hyst); 72208e7e278SJean Delvare 72308e7e278SJean Delvare #define show_temp_reg(reg) \ 72408e7e278SJean Delvare static ssize_t \ 725412fec82SYuan Mu show_##reg(struct device *dev, struct device_attribute *attr, \ 726412fec82SYuan Mu char *buf) \ 72708e7e278SJean Delvare { \ 72808e7e278SJean Delvare struct w83627ehf_data *data = w83627ehf_update_device(dev); \ 729412fec82SYuan Mu struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ 730412fec82SYuan Mu int nr = sensor_attr->index; \ 73108e7e278SJean Delvare return sprintf(buf, "%d\n", \ 73208e7e278SJean Delvare LM75_TEMP_FROM_REG(data->reg[nr])); \ 73308e7e278SJean Delvare } 73408e7e278SJean Delvare show_temp_reg(temp); 73508e7e278SJean Delvare show_temp_reg(temp_max); 73608e7e278SJean Delvare show_temp_reg(temp_max_hyst); 73708e7e278SJean Delvare 73808e7e278SJean Delvare #define store_temp_reg(REG, reg) \ 73908e7e278SJean Delvare static ssize_t \ 740412fec82SYuan Mu store_##reg(struct device *dev, struct device_attribute *attr, \ 741412fec82SYuan Mu const char *buf, size_t count) \ 74208e7e278SJean Delvare { \ 74308e7e278SJean Delvare struct i2c_client *client = to_i2c_client(dev); \ 74408e7e278SJean Delvare struct w83627ehf_data *data = i2c_get_clientdata(client); \ 745412fec82SYuan Mu struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ 746412fec82SYuan Mu int nr = sensor_attr->index; \ 74708e7e278SJean Delvare u32 val = simple_strtoul(buf, NULL, 10); \ 74808e7e278SJean Delvare \ 7499a61bf63SIngo Molnar mutex_lock(&data->update_lock); \ 75008e7e278SJean Delvare data->reg[nr] = LM75_TEMP_TO_REG(val); \ 75108e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \ 75208e7e278SJean Delvare data->reg[nr]); \ 7539a61bf63SIngo Molnar mutex_unlock(&data->update_lock); \ 75408e7e278SJean Delvare return count; \ 75508e7e278SJean Delvare } 75608e7e278SJean Delvare store_temp_reg(OVER, temp_max); 75708e7e278SJean Delvare store_temp_reg(HYST, temp_max_hyst); 75808e7e278SJean Delvare 759412fec82SYuan Mu static struct sensor_device_attribute sda_temp[] = { 760412fec82SYuan Mu SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0), 761412fec82SYuan Mu SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0), 762412fec82SYuan Mu SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1), 763412fec82SYuan Mu SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max, 764412fec82SYuan Mu store_temp1_max, 0), 765412fec82SYuan Mu SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, 766412fec82SYuan Mu store_temp_max, 0), 767412fec82SYuan Mu SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, 768412fec82SYuan Mu store_temp_max, 1), 769412fec82SYuan Mu SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst, 770412fec82SYuan Mu store_temp1_max_hyst, 0), 771412fec82SYuan Mu SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, 772412fec82SYuan Mu store_temp_max_hyst, 0), 773412fec82SYuan Mu SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, 774412fec82SYuan Mu store_temp_max_hyst, 1), 775*a4589dbbSJean Delvare SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), 776*a4589dbbSJean Delvare SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), 777*a4589dbbSJean Delvare SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), 778412fec82SYuan Mu }; 77908e7e278SJean Delvare 78008e7e278SJean Delvare /* 78108e7e278SJean Delvare * Driver and client management 78208e7e278SJean Delvare */ 78308e7e278SJean Delvare 78408e7e278SJean Delvare static struct i2c_driver w83627ehf_driver; 78508e7e278SJean Delvare 78608e7e278SJean Delvare static void w83627ehf_init_client(struct i2c_client *client) 78708e7e278SJean Delvare { 78808e7e278SJean Delvare int i; 78908e7e278SJean Delvare u8 tmp; 79008e7e278SJean Delvare 79108e7e278SJean Delvare /* Start monitoring is needed */ 79208e7e278SJean Delvare tmp = w83627ehf_read_value(client, W83627EHF_REG_CONFIG); 79308e7e278SJean Delvare if (!(tmp & 0x01)) 79408e7e278SJean Delvare w83627ehf_write_value(client, W83627EHF_REG_CONFIG, 79508e7e278SJean Delvare tmp | 0x01); 79608e7e278SJean Delvare 79708e7e278SJean Delvare /* Enable temp2 and temp3 if needed */ 79808e7e278SJean Delvare for (i = 0; i < 2; i++) { 79908e7e278SJean Delvare tmp = w83627ehf_read_value(client, 80008e7e278SJean Delvare W83627EHF_REG_TEMP_CONFIG[i]); 80108e7e278SJean Delvare if (tmp & 0x01) 80208e7e278SJean Delvare w83627ehf_write_value(client, 80308e7e278SJean Delvare W83627EHF_REG_TEMP_CONFIG[i], 80408e7e278SJean Delvare tmp & 0xfe); 80508e7e278SJean Delvare } 80608e7e278SJean Delvare } 80708e7e278SJean Delvare 8082d8672c5SJean Delvare static int w83627ehf_detect(struct i2c_adapter *adapter) 80908e7e278SJean Delvare { 81008e7e278SJean Delvare struct i2c_client *client; 81108e7e278SJean Delvare struct w83627ehf_data *data; 812412fec82SYuan Mu struct device *dev; 81308e7e278SJean Delvare int i, err = 0; 81408e7e278SJean Delvare 815ada0c2f8SPetr Vandrovec if (!request_region(address + REGION_OFFSET, REGION_LENGTH, 816cdaf7934SLaurent Riffard w83627ehf_driver.driver.name)) { 81708e7e278SJean Delvare err = -EBUSY; 81808e7e278SJean Delvare goto exit; 81908e7e278SJean Delvare } 82008e7e278SJean Delvare 821ba9c2e8dSDeepak Saxena if (!(data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) { 82208e7e278SJean Delvare err = -ENOMEM; 82308e7e278SJean Delvare goto exit_release; 82408e7e278SJean Delvare } 82508e7e278SJean Delvare 82608e7e278SJean Delvare client = &data->client; 82708e7e278SJean Delvare i2c_set_clientdata(client, data); 82808e7e278SJean Delvare client->addr = address; 8299a61bf63SIngo Molnar mutex_init(&data->lock); 83008e7e278SJean Delvare client->adapter = adapter; 83108e7e278SJean Delvare client->driver = &w83627ehf_driver; 83208e7e278SJean Delvare client->flags = 0; 833412fec82SYuan Mu dev = &client->dev; 83408e7e278SJean Delvare 83508e7e278SJean Delvare strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE); 83608e7e278SJean Delvare data->valid = 0; 8379a61bf63SIngo Molnar mutex_init(&data->update_lock); 83808e7e278SJean Delvare 83908e7e278SJean Delvare /* Tell the i2c layer a new client has arrived */ 84008e7e278SJean Delvare if ((err = i2c_attach_client(client))) 84108e7e278SJean Delvare goto exit_free; 84208e7e278SJean Delvare 84308e7e278SJean Delvare /* Initialize the chip */ 84408e7e278SJean Delvare w83627ehf_init_client(client); 84508e7e278SJean Delvare 84608e7e278SJean Delvare /* A few vars need to be filled upon startup */ 84708e7e278SJean Delvare for (i = 0; i < 5; i++) 84808e7e278SJean Delvare data->fan_min[i] = w83627ehf_read_value(client, 84908e7e278SJean Delvare W83627EHF_REG_FAN_MIN[i]); 85008e7e278SJean Delvare 85108e7e278SJean Delvare /* It looks like fan4 and fan5 pins can be alternatively used 85208e7e278SJean Delvare as fan on/off switches */ 85308e7e278SJean Delvare data->has_fan = 0x07; /* fan1, fan2 and fan3 */ 85408e7e278SJean Delvare i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1); 85508e7e278SJean Delvare if (i & (1 << 2)) 85608e7e278SJean Delvare data->has_fan |= (1 << 3); 85708e7e278SJean Delvare if (i & (1 << 0)) 85808e7e278SJean Delvare data->has_fan |= (1 << 4); 85908e7e278SJean Delvare 86008e7e278SJean Delvare /* Register sysfs hooks */ 861412fec82SYuan Mu data->class_dev = hwmon_device_register(dev); 862943b0830SMark M. Hoffman if (IS_ERR(data->class_dev)) { 863943b0830SMark M. Hoffman err = PTR_ERR(data->class_dev); 864943b0830SMark M. Hoffman goto exit_detach; 865943b0830SMark M. Hoffman } 866943b0830SMark M. Hoffman 867cf0676feSRudolf Marek for (i = 0; i < 10; i++) 868cf0676feSRudolf Marek device_create_file_in(dev, i); 869cf0676feSRudolf Marek 870412fec82SYuan Mu for (i = 0; i < 5; i++) { 871412fec82SYuan Mu if (data->has_fan & (1 << i)) 872412fec82SYuan Mu device_create_file_fan(dev, i); 87308e7e278SJean Delvare } 874412fec82SYuan Mu for (i = 0; i < ARRAY_SIZE(sda_temp); i++) 875412fec82SYuan Mu device_create_file(dev, &sda_temp[i].dev_attr); 87608e7e278SJean Delvare 87708e7e278SJean Delvare return 0; 87808e7e278SJean Delvare 879943b0830SMark M. Hoffman exit_detach: 880943b0830SMark M. Hoffman i2c_detach_client(client); 88108e7e278SJean Delvare exit_free: 88208e7e278SJean Delvare kfree(data); 88308e7e278SJean Delvare exit_release: 884ada0c2f8SPetr Vandrovec release_region(address + REGION_OFFSET, REGION_LENGTH); 88508e7e278SJean Delvare exit: 88608e7e278SJean Delvare return err; 88708e7e278SJean Delvare } 88808e7e278SJean Delvare 88908e7e278SJean Delvare static int w83627ehf_detach_client(struct i2c_client *client) 89008e7e278SJean Delvare { 891943b0830SMark M. Hoffman struct w83627ehf_data *data = i2c_get_clientdata(client); 89208e7e278SJean Delvare int err; 89308e7e278SJean Delvare 894943b0830SMark M. Hoffman hwmon_device_unregister(data->class_dev); 895943b0830SMark M. Hoffman 8967bef5594SJean Delvare if ((err = i2c_detach_client(client))) 89708e7e278SJean Delvare return err; 898ada0c2f8SPetr Vandrovec release_region(client->addr + REGION_OFFSET, REGION_LENGTH); 899943b0830SMark M. Hoffman kfree(data); 90008e7e278SJean Delvare 90108e7e278SJean Delvare return 0; 90208e7e278SJean Delvare } 90308e7e278SJean Delvare 90408e7e278SJean Delvare static struct i2c_driver w83627ehf_driver = { 905cdaf7934SLaurent Riffard .driver = { 90608e7e278SJean Delvare .name = "w83627ehf", 907cdaf7934SLaurent Riffard }, 9082d8672c5SJean Delvare .attach_adapter = w83627ehf_detect, 90908e7e278SJean Delvare .detach_client = w83627ehf_detach_client, 91008e7e278SJean Delvare }; 91108e7e278SJean Delvare 9122d8672c5SJean Delvare static int __init w83627ehf_find(int sioaddr, unsigned short *addr) 91308e7e278SJean Delvare { 91408e7e278SJean Delvare u16 val; 91508e7e278SJean Delvare 91608e7e278SJean Delvare REG = sioaddr; 91708e7e278SJean Delvare VAL = sioaddr + 1; 91808e7e278SJean Delvare superio_enter(); 91908e7e278SJean Delvare 92008e7e278SJean Delvare val = (superio_inb(SIO_REG_DEVID) << 8) 92108e7e278SJean Delvare | superio_inb(SIO_REG_DEVID + 1); 92208e7e278SJean Delvare if ((val & SIO_ID_MASK) != SIO_W83627EHF_ID) { 92308e7e278SJean Delvare superio_exit(); 92408e7e278SJean Delvare return -ENODEV; 92508e7e278SJean Delvare } 92608e7e278SJean Delvare 92708e7e278SJean Delvare superio_select(W83627EHF_LD_HWM); 92808e7e278SJean Delvare val = (superio_inb(SIO_REG_ADDR) << 8) 92908e7e278SJean Delvare | superio_inb(SIO_REG_ADDR + 1); 930ada0c2f8SPetr Vandrovec *addr = val & REGION_ALIGNMENT; 9312d8672c5SJean Delvare if (*addr == 0) { 93208e7e278SJean Delvare superio_exit(); 93308e7e278SJean Delvare return -ENODEV; 93408e7e278SJean Delvare } 93508e7e278SJean Delvare 93608e7e278SJean Delvare /* Activate logical device if needed */ 93708e7e278SJean Delvare val = superio_inb(SIO_REG_ENABLE); 93808e7e278SJean Delvare if (!(val & 0x01)) 93908e7e278SJean Delvare superio_outb(SIO_REG_ENABLE, val | 0x01); 94008e7e278SJean Delvare 94108e7e278SJean Delvare superio_exit(); 94208e7e278SJean Delvare return 0; 94308e7e278SJean Delvare } 94408e7e278SJean Delvare 94508e7e278SJean Delvare static int __init sensors_w83627ehf_init(void) 94608e7e278SJean Delvare { 9472d8672c5SJean Delvare if (w83627ehf_find(0x2e, &address) 9482d8672c5SJean Delvare && w83627ehf_find(0x4e, &address)) 94908e7e278SJean Delvare return -ENODEV; 95008e7e278SJean Delvare 951fde09509SJean Delvare return i2c_isa_add_driver(&w83627ehf_driver); 95208e7e278SJean Delvare } 95308e7e278SJean Delvare 95408e7e278SJean Delvare static void __exit sensors_w83627ehf_exit(void) 95508e7e278SJean Delvare { 956fde09509SJean Delvare i2c_isa_del_driver(&w83627ehf_driver); 95708e7e278SJean Delvare } 95808e7e278SJean Delvare 95908e7e278SJean Delvare MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); 96008e7e278SJean Delvare MODULE_DESCRIPTION("W83627EHF driver"); 96108e7e278SJean Delvare MODULE_LICENSE("GPL"); 96208e7e278SJean Delvare 96308e7e278SJean Delvare module_init(sensors_w83627ehf_init); 96408e7e278SJean Delvare module_exit(sensors_w83627ehf_exit); 965