xref: /linux/drivers/hwmon/w83627ehf.c (revision a4589dbb4e2dc758d1aadb8b5d7e5a598ccb0341)
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