w83627hf.c revision b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    w83627hf.c - Part of lm_sensors, Linux kernel modules for hardware
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                monitoring
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Copyright (c) 1998 - 2003  Frodo Looijaard <frodol@dds.nl>,
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Philip Edelbrock <phil@netroedge.com>,
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    and Mark Studebaker <mdsxyz123@yahoo.com>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org>
8787c72b107888805981faf148c8fea96a752d22eJean Delvare    Copyright (c) 2007  Jean Delvare <khali@linux-fr.org>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This program is free software; you can redistribute it and/or modify
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    it under the terms of the GNU General Public License as published by
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    the Free Software Foundation; either version 2 of the License, or
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    (at your option) any later version.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This program is distributed in the hope that it will be useful,
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    but WITHOUT ANY WARRANTY; without even the implied warranty of
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    GNU General Public License for more details.
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    You should have received a copy of the GNU General Public License
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    along with this program; if not, write to the Free Software
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Supports following chips:
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    w83627hf	9	3	2	3	0x20	0x5ca3	no	yes(LPC)
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    w83627thf	7	3	3	3	0x90	0x5ca3	no	yes(LPC)
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    w83637hf	7	3	3	3	0x80	0x5ca3	no	yes(LPC)
32c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare    w83687thf	7	3	3	3	0x90	0x5ca3	no	yes(LPC)
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    w83697hf	8	2	2	2	0x60	0x5ca3	no	yes(LPC)
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    For other winbond chips, and for i2c support in the above chips,
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    use w83781d.c.
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Note: automatic ("cruise") fan control for 697, 637 & 627thf not
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    supported yet.
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/jiffies.h>
46787c72b107888805981faf148c8fea96a752d22eJean Delvare#include <linux/platform_device.h>
47943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/hwmon.h>
4807584c762541672e35735b52af031183ca17a5a2Jim Cromie#include <linux/hwmon-sysfs.h>
49303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare#include <linux/hwmon-vid.h>
50943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/err.h>
519a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar#include <linux/mutex.h>
52d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare#include <linux/ioport.h>
53b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare#include <linux/acpi.h>
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "lm75.h"
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic struct platform_device *pdev;
58d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
59d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare#define DRVNAME "w83627hf"
60d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvareenum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
61d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 force_addr;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(force_addr, ushort, 0);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(force_addr,
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 "Initialize the base address of the sensors");
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 force_i2c = 0x1f;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(force_i2c, byte, 0);
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(force_i2c,
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 "Initialize the i2c address of the sensors");
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int init = 1;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(init, bool, 0);
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7567b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvarestatic unsigned short force_id;
7667b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvaremodule_param(force_id, ushort, 0);
7767b671bceb4a8340a30929e9642620d99ed5ad76Jean DelvareMODULE_PARM_DESC(force_id, "Override the detected device ID");
7867b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvare
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* modified from kernel/include/traps.c */
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int REG;		/* The register to read/write */
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	DEV	0x07	/* Register: Logical device select */
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int VAL;		/* The value to read/write */
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* logical device numbers for superio_select (below) */
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_FDC		0x00
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_PRT		0x01
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_UART1	0x02
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_UART2	0x03
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_KBC		0x05
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_CIR		0x06 /* w83627hf only */
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GAME	0x07
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_MIDI	0x07
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO1	0x07
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO5	0x07 /* w83627thf only */
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO2	0x08
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO3	0x09
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO4	0x09 /* w83627thf only */
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_ACPI	0x0a
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_HWM		0x0b
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	DEVID	0x20	/* Register: Device ID */
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_EN	0x30 /* w83627thf only */
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_IOSR	0xf3 /* w83627thf only */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_DR	0xf4 /* w83627thf only */
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
107c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_EN	0x29 /* w83687thf only */
108c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_CFG	0xF0 /* w83687thf only */
109c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_DATA	0xF1 /* w83687thf only */
110c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_outb(int reg, int val)
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(reg, REG);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(val, VAL);
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_inb(int reg)
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(reg, REG);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return inb(VAL);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_select(int ld)
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(DEV, REG);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(ld, VAL);
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_enter(void)
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(0x87, REG);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(0x87, REG);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_exit(void)
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(0xAA, REG);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W627_DEVID 0x52
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W627THF_DEVID 0x82
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W697_DEVID 0x60
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W637_DEVID 0x70
149c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W687THF_DEVID 0x85
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINB_ACT_REG 0x30
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINB_BASE_REG 0x60
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Constants specified below */
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
154ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec/* Alignment of the base address */
155ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_ALIGNMENT		~7
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
157ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec/* Offset & size of I/O region we are interested in */
158ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_REGION_OFFSET	5
159ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_REGION_SIZE	2
160ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec
161787c72b107888805981faf148c8fea96a752d22eJean Delvare/* Where are the sensors address/data registers relative to the region offset */
162787c72b107888805981faf148c8fea96a752d22eJean Delvare#define W83781D_ADDR_REG_OFFSET 0
163787c72b107888805981faf148c8fea96a752d22eJean Delvare#define W83781D_DATA_REG_OFFSET 1
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The W83781D registers */
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The W83782D registers for nr=7,8 are in bank 5 */
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x554 + (((nr) - 7) * 2)))
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x555 + (((nr) - 7) * 2)))
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN(nr)     ((nr < 7) ? (0x20 + (nr)) : \
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x550 + (nr) - 7))
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1742ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie/* nr:0-2 for fans:1-3 */
1752ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie#define W83627HF_REG_FAN_MIN(nr)	(0x3b + (nr))
1762ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie#define W83627HF_REG_FAN(nr)		(0x28 + (nr))
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
178df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie#define W83627HF_REG_TEMP2_CONFIG 0x152
179df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie#define W83627HF_REG_TEMP3_CONFIG 0x252
180df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie/* these are zero-based, unlike config constants above */
181df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp[]		= { 0x27, 0x150, 0x250 };
182df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp_hyst[]	= { 0x3A, 0x153, 0x253 };
183df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp_over[]	= { 0x39, 0x155, 0x255 };
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BANK 0x4E
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CONFIG 0x40
1884a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM1 0x459
1894a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM2 0x45A
1904a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM3 0x45B
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_CONFIG 0x4D
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS1 0x56
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS2 0x57
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS3 0x453
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_VID_FANDIV 0x47
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CHIPID 0x49
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_WCHIPID 0x58
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CHIPMAN 0x4F
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_PIN 0x4B
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_VBAT 0x5D
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_REG_PWM1 0x5A
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_REG_PWM2 0x5B
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
209a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic const u8 W83627THF_REG_PWM_ENABLE[] = {
210a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	0x04,		/* FAN 1 mode */
211a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	0x04,		/* FAN 2 mode */
212a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	0x12,		/* FAN AUX mode */
213a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer};
214a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic const u8 W83627THF_PWM_ENABLE_SHIFT[] = { 2, 4, 1 };
215a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
216c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM1		0x01	/* 697HF/637HF/687THF too */
217c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM2		0x03	/* 697HF/637HF/687THF too */
218c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM3		0x11	/* 637HF/687THF too */
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
220c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_VRM_OVT_CFG 	0x18	/* 637HF/687THF too */
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 };
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                             W83627THF_REG_PWM3 };
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \
22607584c762541672e35735b52af031183ca17a5a2Jim Cromie				    regpwm_627hf[nr] : regpwm[nr])
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2281550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83627HF_REG_PWM_FREQ		0x5C	/* Only for the 627HF */
2291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2301550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ1		0x00	/* 697HF/687THF too */
2311550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ2		0x02	/* 697HF/687THF too */
2321550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ3		0x10	/* 687THF too */
2331550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2341550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic const u8 W83637HF_REG_PWM_FREQ[] = { W83637HF_REG_PWM_FREQ1,
2351550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					W83637HF_REG_PWM_FREQ2,
2361550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					W83637HF_REG_PWM_FREQ3 };
2371550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2381550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83627HF_BASE_PWM_FREQ	46870
2391550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_I2C_ADDR 0x48
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_I2C_SUBADDR 0x4A
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Sensor selection */
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_SCFG1 0x5D
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_SCFG2 0x59
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_DEFAULT_BETA 3435
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Conversions. Limit checking is only done on the TO_REG
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   variants. Note that you should be a bit careful with which arguments
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   these macros are called: arguments may be evaluated more than once.
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   Fixing this is just not worth it. */
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) + 8)/16),0,255))
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IN_FROM_REG(val) ((val) * 16)
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 FAN_TO_REG(long rpm, int div)
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rpm == 0)
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 255;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     254);
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_MIN (-128000)
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_MAX ( 127000)
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TEMP: 0.001C/bit (-128C to +127C)
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   REG: 1C/bit, two's complement */
2715bfedac045082a97e20d47d876071279ef984d28Christian Hohnstaedtstatic u8 TEMP_TO_REG(long temp)
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX);
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ntemp += (ntemp<0 ? -500 : 500);
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return (u8)(ntemp / 1000);
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int TEMP_FROM_REG(u8 reg)
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return (s8)reg * 1000;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2871550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline unsigned long pwm_freq_from_reg_627hf(u8 reg)
2881550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
2891550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	unsigned long freq;
2901550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	freq = W83627HF_BASE_PWM_FREQ >> reg;
2911550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return freq;
2921550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
2931550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline u8 pwm_freq_to_reg_627hf(unsigned long val)
2941550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
2951550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u8 i;
2961550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Only 5 dividers (1 2 4 8 16)
2971550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	   Search for the nearest available frequency */
2981550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	for (i = 0; i < 4; i++) {
2991550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		if (val > (((W83627HF_BASE_PWM_FREQ >> i) +
3001550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			    (W83627HF_BASE_PWM_FREQ >> (i+1))) / 2))
3011550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			break;
3021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	}
3031550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return i;
3041550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3051550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3061550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline unsigned long pwm_freq_from_reg(u8 reg)
3071550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
3081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Clock bit 8 -> 180 kHz or 24 MHz */
3091550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	unsigned long clock = (reg & 0x80) ? 180000UL : 24000000UL;
3101550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3111550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	reg &= 0x7f;
3121550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* This should not happen but anyway... */
3131550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (reg == 0)
3141550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		reg++;
3151550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return (clock / (reg << 8));
3161550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3171550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline u8 pwm_freq_to_reg(unsigned long val)
3181550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
3191550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Minimum divider value is 0x01 and maximum is 0x7F */
3201550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val >= 93750)	/* The highest we can do */
3211550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return 0x01;
3221550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val >= 720)	/* Use 24 MHz clock */
3231550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return (24000000UL / (val << 8));
3241550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val < 6)		/* The lowest we can do */
3251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return 0xFF;
3261550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	else			/* Use 180 kHz clock */
3271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return (0x80 | (180000UL / (val << 8)));
3281550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3301c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare#define BEEP_MASK_FROM_REG(val)		((val) & 0xff7fff)
3311c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare#define BEEP_MASK_TO_REG(val)		((val) & 0xff7fff)
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1 << (val))
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 DIV_TO_REG(long val)
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = SENSORS_LIMIT(val, 1, 128) >> 1;
339abc01922477104e8d72b494902aff37135c409e7Grant Coady	for (i = 0; i < 7; i++) {
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val == 0)
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val >>= 1;
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((u8) i);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
347ed6bafbf6017d6a007b39de6b65ad3b8ae4c8aeeJean Delvare/* For each registered chip, we need to keep some data in memory.
348ed6bafbf6017d6a007b39de6b65ad3b8ae4c8aeeJean Delvare   The structure is dynamically allocated. */
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct w83627hf_data {
350787c72b107888805981faf148c8fea96a752d22eJean Delvare	unsigned short addr;
351787c72b107888805981faf148c8fea96a752d22eJean Delvare	const char *name;
3521beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	struct device *hwmon_dev;
3539a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex lock;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enum chips type;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3569a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex update_lock;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char valid;		/* !=0 if following fields are valid */
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_updated;	/* In jiffies */
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in[9];		/* Register value */
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_max[9];		/* Register value */
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_min[9];		/* Register value */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan[3];		/* Register value */
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_min[3];		/* Register value */
365df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp[3];		/* Register value */
366df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp_max[3];	/* Register value */
367df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp_max_hyst[3];	/* Register value */
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_div[3];		/* Register encoding, shifted right */
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vid;			/* Register encoding, combined */
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 alarms;		/* Register encoding, combined */
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 beep_mask;		/* Register encoding, combined */
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 pwm[3];		/* Register value */
373a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	u8 pwm_enable[3];	/* 1 = manual
374a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				   2 = thermal cruise (also called SmartFan I)
375a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				   3 = fan speed cruise */
3761550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u8 pwm_freq[3];		/* Register value */
377b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	u16 sens[3];		/* 1 = pentium diode; 2 = 3904 diode;
378b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare				   4 = thermistor */
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vrm;
380c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	u8 vrm_ovt;		/* Register value, 627THF/637HF/687THF only */
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
383787c72b107888805981faf148c8fea96a752d22eJean Delvarestruct w83627hf_sio_data {
384787c72b107888805981faf148c8fea96a752d22eJean Delvare	enum chips type;
385787c72b107888805981faf148c8fea96a752d22eJean Delvare};
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
388787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_probe(struct platform_device *pdev);
389d0546128980c18748010c758903b02909e634830Jean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev);
390787c72b107888805981faf148c8fea96a752d22eJean Delvare
391787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
392787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
393c09c5184a26158da32801e89d5849d774605f0ddJean Delvarestatic void w83627hf_update_fan_div(struct w83627hf_data *data);
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev);
395787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void w83627hf_init_device(struct platform_device *pdev);
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
397787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic struct platform_driver w83627hf_driver = {
398cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	.driver = {
399872188420997f7f7c1b968fd9bce6578e4c3d45fJean Delvare		.owner	= THIS_MODULE,
400d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		.name	= DRVNAME,
401cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	},
402787c72b107888805981faf148c8fea96a752d22eJean Delvare	.probe		= w83627hf_probe,
403787c72b107888805981faf148c8fea96a752d22eJean Delvare	.remove		= __devexit_p(w83627hf_remove),
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
40707584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
40807584c762541672e35735b52af031183ca17a5a2Jim Cromie{
40907584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
41007584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
41107584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in[nr]));
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
41307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
41407584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_min(struct device *dev, struct device_attribute *devattr, char *buf)
41507584c762541672e35735b52af031183ca17a5a2Jim Cromie{
41607584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
41707584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
41807584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_min[nr]));
41907584c762541672e35735b52af031183ca17a5a2Jim Cromie}
42007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
42107584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_max(struct device *dev, struct device_attribute *devattr, char *buf)
42207584c762541672e35735b52af031183ca17a5a2Jim Cromie{
42307584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
42407584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
42507584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_max[nr]));
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
42707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
42807584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_min(struct device *dev, struct device_attribute *devattr,
42907584c762541672e35735b52af031183ca17a5a2Jim Cromie	     const char *buf, size_t count)
43007584c762541672e35735b52af031183ca17a5a2Jim Cromie{
43107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
43207584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
43307584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43507584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
43607584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->in_min[nr] = IN_TO_REG(val);
43707584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]);
43807584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
43907584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
44007584c762541672e35735b52af031183ca17a5a2Jim Cromie}
44107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
44207584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_max(struct device *dev, struct device_attribute *devattr,
44307584c762541672e35735b52af031183ca17a5a2Jim Cromie	     const char *buf, size_t count)
44407584c762541672e35735b52af031183ca17a5a2Jim Cromie{
44507584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
44607584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
44707584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44907584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
45007584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->in_max[nr] = IN_TO_REG(val);
45107584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]);
45207584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
45307584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
45407584c762541672e35735b52af031183ca17a5a2Jim Cromie}
45507584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_vin_decl(offset) \
45607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
45707584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_input, NULL, offset);		\
45807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO|S_IWUSR,	\
45907584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_min, store_in_min, offset);	\
46007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO|S_IWUSR,	\
46107584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_max, store_in_max, offset);
46207584c762541672e35735b52af031183ca17a5a2Jim Cromie
46307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(1);
46407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(2);
46507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(3);
46607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(4);
46707584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(5);
46807584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(6);
46907584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(7);
47007584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(8);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* use a different set of functions for in0 */
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long in0;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
478c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
479c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in0 = (long)((reg * 488 + 70000 + 50) / 100);
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in0 = (long)IN_FROM_REG(reg);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%ld\n", in0);
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
490a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_0(struct device *dev, struct device_attribute *attr, char *buf)
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in[0]);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
496a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_min0(struct device *dev, struct device_attribute *attr, char *buf)
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in_min[0]);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
502a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *attr, char *buf)
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in_max[0]);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
508a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr,
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *buf, size_t count)
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
511787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5169a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
519c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
520c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
5232723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu		data->in_min[0] =
5242723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
5252723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu					255);
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_min[0] = IN_TO_REG(val);
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
530787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]);
5319a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
535a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr,
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *buf, size_t count)
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
538787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5439a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
546c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
547c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
5502723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu		data->in_max[0] =
5512723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
5522723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu					255);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_max[0] = IN_TO_REG(val);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
557787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]);
5589a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_input, S_IRUGO, show_regs_in_0, NULL);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs_in_min0, store_regs_in_min0);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs_in_max0, store_regs_in_max0);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
56907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
57007584c762541672e35735b52af031183ca17a5a2Jim Cromie{
57107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
57207584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
57307584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan[nr],
57407584c762541672e35735b52af031183ca17a5a2Jim Cromie				(long)DIV_FROM_REG(data->fan_div[nr])));
57507584c762541672e35735b52af031183ca17a5a2Jim Cromie}
57607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
57707584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
57807584c762541672e35735b52af031183ca17a5a2Jim Cromie{
57907584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
58007584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
58107584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan_min[nr],
58207584c762541672e35735b52af031183ca17a5a2Jim Cromie				(long)DIV_FROM_REG(data->fan_div[nr])));
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
58507584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_min(struct device *dev, struct device_attribute *devattr,
58607584c762541672e35735b52af031183ca17a5a2Jim Cromie	      const char *buf, size_t count)
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
58807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
589787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
59007584c762541672e35735b52af031183ca17a5a2Jim Cromie	u32 val = simple_strtoul(buf, NULL, 10);
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5929a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
59307584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
5942ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
59507584c762541672e35735b52af031183ca17a5a2Jim Cromie			     data->fan_min[nr]);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5979a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
60007584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_fan_decl(offset)	\
60107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
60207584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_input, NULL, offset - 1);		\
60307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
60407584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_min, store_fan_min, offset - 1);
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
60607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(1);
60707584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(2);
60807584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(3);
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
61007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
61107584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp(struct device *dev, struct device_attribute *devattr, char *buf)
61207584c762541672e35735b52af031183ca17a5a2Jim Cromie{
61307584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
61407584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
615df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
616df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp[nr];
617df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
618df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
62107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
62207584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max(struct device *dev, struct device_attribute *devattr,
62307584c762541672e35735b52af031183ca17a5a2Jim Cromie	      char *buf)
62407584c762541672e35735b52af031183ca17a5a2Jim Cromie{
62507584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
62607584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
627df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
628df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp_max[nr];
629df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
630df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
63307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
63407584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
63507584c762541672e35735b52af031183ca17a5a2Jim Cromie		   char *buf)
63607584c762541672e35735b52af031183ca17a5a2Jim Cromie{
63707584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
63807584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
639df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
640df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp_max_hyst[nr];
641df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
642df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
64307584c762541672e35735b52af031183ca17a5a2Jim Cromie}
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
64507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
64607584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max(struct device *dev, struct device_attribute *devattr,
64707584c762541672e35735b52af031183ca17a5a2Jim Cromie	       const char *buf, size_t count)
64807584c762541672e35735b52af031183ca17a5a2Jim Cromie{
64907584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
65007584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
65107584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
652df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
65407584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
655df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	data->temp_max[nr] = tmp;
656df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
65707584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
65807584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
65907584c762541672e35735b52af031183ca17a5a2Jim Cromie}
66007584c762541672e35735b52af031183ca17a5a2Jim Cromie
66107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
66207584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
66307584c762541672e35735b52af031183ca17a5a2Jim Cromie		    const char *buf, size_t count)
66407584c762541672e35735b52af031183ca17a5a2Jim Cromie{
66507584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
66607584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
66707584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
668df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
66907584c762541672e35735b52af031183ca17a5a2Jim Cromie
67007584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
671df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	data->temp_max_hyst[nr] = tmp;
672df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
67307584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
67407584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
67507584c762541672e35735b52af031183ca17a5a2Jim Cromie}
67607584c762541672e35735b52af031183ca17a5a2Jim Cromie
67707584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_decl(offset) \
67807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
679df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp, NULL, offset - 1);			\
68007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR,	 	\
681df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp_max, store_temp_max, offset - 1);	\
68207584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR,	\
683df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp_max_hyst, store_temp_max_hyst, offset - 1);
68407584c762541672e35735b52af031183ca17a5a2Jim Cromie
68507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(1);
68607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(2);
68707584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(3);
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
690a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
698a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
70090d6619a916062cb75a176aacb318d108758b4a5Jean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) data->vrm);
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
704a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustore_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
706787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->vrm = val;
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
717a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) data->alarms);
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
724e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
725e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvareshow_alarm(struct device *dev, struct device_attribute *attr, char *buf)
726e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
727e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
728e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
729e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
730e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
731e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
732e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
733e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
734e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
735e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
736e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
737e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10);
738e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16);
739e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17);
740e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
741e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
742e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
743e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
744e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
745e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
746e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
7471c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic ssize_t
7481c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvareshow_beep_mask(struct device *dev, struct device_attribute *attr, char *buf)
7491c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare{
7501c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
7511c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	return sprintf(buf, "%ld\n",
7521c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		      (long)BEEP_MASK_FROM_REG(data->beep_mask));
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
7561c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestore_beep_mask(struct device *dev, struct device_attribute *attr,
7571c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		const char *buf, size_t count)
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
759787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7601c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	unsigned long val;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7649a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7661c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	/* preserve beep enable */
7671c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	data->beep_mask = (data->beep_mask & 0x8000)
7681c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			| BEEP_MASK_TO_REG(val);
7691c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
7701c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    data->beep_mask & 0xff);
7711c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
7721c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    ((data->beep_mask) >> 16) & 0xff);
773787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
7741c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    (data->beep_mask >> 8) & 0xff);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7769a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7801c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
7811c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		   show_beep_mask, store_beep_mask);
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
784e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvareshow_beep(struct device *dev, struct device_attribute *attr, char *buf)
785e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
786e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
787e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
788e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
789e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
790e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
791e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
792e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestore_beep(struct device *dev, struct device_attribute *attr,
793e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		const char *buf, size_t count)
794e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
795e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
796e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
797e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	unsigned long bit;
798e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	u8 reg;
799e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
800e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	bit = simple_strtoul(buf, NULL, 10);
801e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bit & ~1)
802e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		return -EINVAL;
803e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
804e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	mutex_lock(&data->update_lock);
805e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bit)
806e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		data->beep_mask |= (1 << bitnr);
807e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	else
808e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		data->beep_mask &= ~(1 << bitnr);
809e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
810e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bitnr < 8) {
811e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS1);
812e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
813e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << bitnr);
814e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
815e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << bitnr);
816e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, reg);
817e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	} else if (bitnr < 16) {
818e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
819e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
820e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << (bitnr - 8));
821e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
822e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << (bitnr - 8));
823e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, reg);
824e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	} else {
825e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS3);
826e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
827e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << (bitnr - 16));
828e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
829e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << (bitnr - 16));
830e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, reg);
831e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	}
832e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	mutex_unlock(&data->update_lock);
833e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
834e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return count;
835e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
836e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
837e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
838e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 0);
839e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR,
840e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 1);
841e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR,
842e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 2);
843e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR,
844e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 3);
845e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR,
846e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 8);
847e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR,
848e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 9);
849e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR,
850e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 10);
851e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR,
852e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 16);
853e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR,
854e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 17);
855e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR,
856e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 6);
857e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR,
858e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 7);
859e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR,
860e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 11);
861e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
862e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 4);
863e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
864e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 5);
865e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR,
866e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 13);
8671c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
8681c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			show_beep, store_beep, 15);
869e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
870e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
87107584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
87307584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n",
87607584c762541672e35735b52af031183ca17a5a2Jim Cromie		       (long) DIV_FROM_REG(data->fan_div[nr]));
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Note: we save and restore the fan minimum here, because its value is
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   determined in part by the fan divisor.  This follows the principle of
880d6e05edc59ecd79e8badf440c0d295a979bdfa3eAndreas Mohr   least surprise; the user doesn't expect the fan minimum to change just
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   because the divisor changed. */
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
88307584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_div(struct device *dev, struct device_attribute *devattr,
88407584c762541672e35735b52af031183ca17a5a2Jim Cromie	      const char *buf, size_t count)
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
88607584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
887787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long min;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reg;
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long val = simple_strtoul(buf, NULL, 10);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8929a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Save fan_min */
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	min = FAN_FROM_REG(data->fan_min[nr],
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   DIV_FROM_REG(data->fan_div[nr]));
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_div[nr] = DIV_TO_REG(val);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
900787c72b107888805981faf148c8fea96a752d22eJean Delvare	reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       & (nr==0 ? 0xcf : 0x3f))
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
903787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
905787c72b107888805981faf148c8fea96a752d22eJean Delvare	reg = (w83627hf_read_value(data, W83781D_REG_VBAT)
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       & ~(1 << (5 + nr)))
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    | ((data->fan_div[nr] & 0x04) << (3 + nr));
908787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_VBAT, reg);
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore fan_min */
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
9122ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]);
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9149a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO|S_IWUSR,
91907584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 0);
92007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO|S_IWUSR,
92107584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 1);
92207584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO|S_IWUSR,
92307584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 2);
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
92607584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
92807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
93007584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long) data->pwm[nr]);
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
93407584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm(struct device *dev, struct device_attribute *devattr,
93507584c762541672e35735b52af031183ca17a5a2Jim Cromie	  const char *buf, size_t count)
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
93707584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
938787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
93907584c762541672e35735b52af031183ca17a5a2Jim Cromie	u32 val = simple_strtoul(buf, NULL, 10);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9419a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->type == w83627thf) {
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* bits 0-3 are reserved  in 627THF */
94507584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm[nr] = PWM_TO_REG(val) & 0xf0;
946787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data,
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr),
94807584c762541672e35735b52af031183ca17a5a2Jim Cromie				     data->pwm[nr] |
949787c72b107888805981faf148c8fea96a752d22eJean Delvare				     (w83627hf_read_value(data,
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
95207584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm[nr] = PWM_TO_REG(val);
953787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data,
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr),
95507584c762541672e35735b52af031183ca17a5a2Jim Cromie				     data->pwm[nr]);
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9589a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
96207584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0);
96307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1);
96407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2);
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
967a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyershow_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf)
968a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer{
969a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	int nr = to_sensor_dev_attr(devattr)->index;
970a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	struct w83627hf_data *data = w83627hf_update_device(dev);
971a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	return sprintf(buf, "%d\n", data->pwm_enable[nr]);
972a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer}
973a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
974a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic ssize_t
975a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstore_pwm_enable(struct device *dev, struct device_attribute *devattr,
976a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	  const char *buf, size_t count)
977a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer{
978a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	int nr = to_sensor_dev_attr(devattr)->index;
979a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	struct w83627hf_data *data = dev_get_drvdata(dev);
980a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	unsigned long val = simple_strtoul(buf, NULL, 10);
981a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	u8 reg;
982a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
983a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	if (!val || (val > 3))	/* modes 1, 2 and 3 are supported */
984a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		return -EINVAL;
985a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	mutex_lock(&data->update_lock);
986a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	data->pwm_enable[nr] = val;
987a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]);
988a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]);
989a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr];
990a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg);
991a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	mutex_unlock(&data->update_lock);
992a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	return count;
993a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer}
994a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
995a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
996a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer						  store_pwm_enable, 0);
997a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
998a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer						  store_pwm_enable, 1);
999a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
1000a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer						  store_pwm_enable, 2);
1001a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1002a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic ssize_t
100307584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf)
10041550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
100507584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
10061550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	struct w83627hf_data *data = w83627hf_update_device(dev);
10071550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83627hf)
10081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return sprintf(buf, "%ld\n",
100907584c762541672e35735b52af031183ca17a5a2Jim Cromie			pwm_freq_from_reg_627hf(data->pwm_freq[nr]));
10101550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	else
10111550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return sprintf(buf, "%ld\n",
101207584c762541672e35735b52af031183ca17a5a2Jim Cromie			pwm_freq_from_reg(data->pwm_freq[nr]));
10131550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
10141550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10151550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t
101607584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm_freq(struct device *dev, struct device_attribute *devattr,
101707584c762541672e35735b52af031183ca17a5a2Jim Cromie	       const char *buf, size_t count)
10181550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
101907584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
10201550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	struct w83627hf_data *data = dev_get_drvdata(dev);
10211550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	static const u8 mask[]={0xF8, 0x8F};
10221550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u32 val;
10231550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10241550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	val = simple_strtoul(buf, NULL, 10);
10251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10261550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	mutex_lock(&data->update_lock);
10271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10281550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83627hf) {
102907584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val);
10301550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		w83627hf_write_value(data, W83627HF_REG_PWM_FREQ,
103107584c762541672e35735b52af031183ca17a5a2Jim Cromie				(data->pwm_freq[nr] << (nr*4)) |
10321550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				(w83627hf_read_value(data,
103307584c762541672e35735b52af031183ca17a5a2Jim Cromie				W83627HF_REG_PWM_FREQ) & mask[nr]));
10341550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	} else {
103507584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm_freq[nr] = pwm_freq_to_reg(val);
103607584c762541672e35735b52af031183ca17a5a2Jim Cromie		w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr],
103707584c762541672e35735b52af031183ca17a5a2Jim Cromie				data->pwm_freq[nr]);
10381550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	}
10391550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10401550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	mutex_unlock(&data->update_lock);
10411550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return count;
10421550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
10431550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
104407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO|S_IWUSR,
104507584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 0);
104607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO|S_IWUSR,
104707584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 1);
104807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO|S_IWUSR,
104907584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 2);
10501550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10511550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t
105207584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_type(struct device *dev, struct device_attribute *devattr,
105307584c762541672e35735b52af031183ca17a5a2Jim Cromie	       char *buf)
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
105507584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
105707584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long) data->sens[nr]);
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
106107584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_type(struct device *dev, struct device_attribute *devattr,
106207584c762541672e35735b52af031183ca17a5a2Jim Cromie		const char *buf, size_t count)
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
106407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
1065787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val, tmp;
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10709a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (val) {
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:		/* PII/Celeron diode */
1074787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1075787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
107607584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG1[nr]);
1077787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
1078787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG2,
107907584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG2[nr]);
108007584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:		/* 3904 */
1083787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1084787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
108507584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG1[nr]);
1086787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
1087787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG2,
108807584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp & ~BIT_SCFG2[nr]);
108907584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1091b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	case W83781D_DEFAULT_BETA:
1092b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
1093b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare			 "instead\n", W83781D_DEFAULT_BETA);
1094b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		/* fall through */
1095b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	case 4:		/* thermistor */
1096787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1097787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
109807584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp & ~BIT_SCFG1[nr]);
109907584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1102787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_err(dev,
1103b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		       "Invalid sensor type %ld; must be 1, 2, or 4\n",
1104b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		       (long) val);
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11089a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111207584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_type(offset) \
111307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
111407584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_temp_type, store_temp_type, offset - 1);
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(1);
111707584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(2);
111807584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(3);
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
112007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
112107584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_name(struct device *dev, struct device_attribute *devattr, char *buf)
1122787c72b107888805981faf148c8fea96a752d22eJean Delvare{
1123787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
1124787c72b107888805981faf148c8fea96a752d22eJean Delvare
1125787c72b107888805981faf148c8fea96a752d22eJean Delvare	return sprintf(buf, "%s\n", data->name);
1126787c72b107888805981faf148c8fea96a752d22eJean Delvare}
1127787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
1128787c72b107888805981faf148c8fea96a752d22eJean Delvare
1129787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_find(int sioaddr, unsigned short *addr,
1130787c72b107888805981faf148c8fea96a752d22eJean Delvare				struct w83627hf_sio_data *sio_data)
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1132d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	int err = -ENODEV;
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 val;
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1135787c72b107888805981faf148c8fea96a752d22eJean Delvare	static const __initdata char *names[] = {
1136787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83627HF",
1137787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83627THF",
1138787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83697HF",
1139787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83637HF",
1140787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83687THF",
1141787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1142787c72b107888805981faf148c8fea96a752d22eJean Delvare
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG = sioaddr;
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	VAL = sioaddr + 1;
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_enter();
114767b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvare	val = force_id ? force_id : superio_inb(DEVID);
1148787c72b107888805981faf148c8fea96a752d22eJean Delvare	switch (val) {
1149787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W627_DEVID:
1150787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83627hf;
1151787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1152787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W627THF_DEVID:
1153787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83627thf;
1154787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1155787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W697_DEVID:
1156787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83697hf;
1157787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1158787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W637_DEVID:
1159787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83637hf;
1160787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1161787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W687THF_DEVID:
1162787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83687thf;
1163787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1164e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare	case 0xff:	/* No device at all */
1165e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare		goto exit;
1166787c72b107888805981faf148c8fea96a752d22eJean Delvare	default:
1167e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare		pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val);
1168d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		goto exit;
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_select(W83627HF_LD_HWM);
1172d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	force_addr &= WINB_ALIGNMENT;
1173d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (force_addr) {
1174d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Forcing address 0x%x\n",
1175d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		       force_addr);
1176d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		superio_outb(WINB_BASE_REG, force_addr >> 8);
1177d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		superio_outb(WINB_BASE_REG + 1, force_addr & 0xff);
1178d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	}
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = (superio_inb(WINB_BASE_REG) << 8) |
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       superio_inb(WINB_BASE_REG + 1);
1181ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec	*addr = val & WINB_ALIGNMENT;
1182d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (*addr == 0) {
1183d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Base address not set, "
1184d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		       "skipping\n");
1185d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		goto exit;
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1188d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	val = superio_inb(WINB_ACT_REG);
1189d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (!(val & 0x01)) {
1190d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n");
1191d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		superio_outb(WINB_ACT_REG, val | 0x01);
1192d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	}
1193d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
1194d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	err = 0;
1195787c72b107888805981faf148c8fea96a752d22eJean Delvare	pr_info(DRVNAME ": Found %s chip at %#x\n",
1196787c72b107888805981faf148c8fea96a752d22eJean Delvare		names[sio_data->type], *addr);
1197d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
1198d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare exit:
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_exit();
1200d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	return err;
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
120307584c762541672e35735b52af031183ca17a5a2Jim Cromie#define VIN_UNIT_ATTRS(_X_)	\
120407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_input.dev_attr.attr,		\
120507584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_min.dev_attr.attr,		\
1206e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_max.dev_attr.attr,		\
1207e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_alarm.dev_attr.attr,		\
1208e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_beep.dev_attr.attr
120907584c762541672e35735b52af031183ca17a5a2Jim Cromie
121007584c762541672e35735b52af031183ca17a5a2Jim Cromie#define FAN_UNIT_ATTRS(_X_)	\
121107584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_input.dev_attr.attr,	\
121207584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_min.dev_attr.attr,		\
1213e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_div.dev_attr.attr,		\
1214e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_alarm.dev_attr.attr,	\
1215e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_beep.dev_attr.attr
121607584c762541672e35735b52af031183ca17a5a2Jim Cromie
121707584c762541672e35735b52af031183ca17a5a2Jim Cromie#define TEMP_UNIT_ATTRS(_X_)	\
121807584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_input.dev_attr.attr,	\
121907584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_max.dev_attr.attr,		\
122007584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr,	\
1221e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_type.dev_attr.attr,	\
1222e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr,	\
1223e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_beep.dev_attr.attr
122407584c762541672e35735b52af031183ca17a5a2Jim Cromie
1225c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes[] = {
1226c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_input.attr,
1227c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_min.attr,
1228c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_max.attr,
1229e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in0_alarm.dev_attr.attr,
1230e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in0_beep.dev_attr.attr,
123107584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(2),
123207584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(3),
123307584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(4),
123407584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(7),
123507584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(8),
123607584c762541672e35735b52af031183ca17a5a2Jim Cromie
123707584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(1),
123807584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(2),
123907584c762541672e35735b52af031183ca17a5a2Jim Cromie
124007584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(1),
124107584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(2),
1242c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1243c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_alarms.attr,
12441c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	&sensor_dev_attr_beep_enable.dev_attr.attr,
1245c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_beep_mask.attr,
1246c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
124707584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm1.dev_attr.attr,
124807584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm2.dev_attr.attr,
1249787c72b107888805981faf148c8fea96a752d22eJean Delvare	&dev_attr_name.attr,
1250c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
1251c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1252c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1253c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group = {
1254c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = w83627hf_attributes,
1255c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1256c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1257c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes_opt[] = {
125807584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(1),
125907584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(5),
126007584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(6),
126107584c762541672e35735b52af031183ca17a5a2Jim Cromie
126207584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(3),
126307584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(3),
126407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm3.dev_attr.attr,
126507584c762541672e35735b52af031183ca17a5a2Jim Cromie
126607584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
126707584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
126807584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm3_freq.dev_attr.attr,
1269a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1270a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
1271a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
1272a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
1273a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1274c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
1275c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1276c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1277c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group_opt = {
1278c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = w83627hf_attributes_opt,
1279c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1280c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1281787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627hf_probe(struct platform_device *pdev)
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1283787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct device *dev = &pdev->dev;
1284787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_sio_data *sio_data = dev->platform_data;
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data;
1286787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource *res;
12872ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	int err, i;
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1289787c72b107888805981faf148c8fea96a752d22eJean Delvare	static const char *names[] = {
1290787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83627hf",
1291787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83627thf",
1292787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83697hf",
1293787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83637hf",
1294787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83687thf",
1295787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1296787c72b107888805981faf148c8fea96a752d22eJean Delvare
1297787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1298787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) {
1299787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
1300787c72b107888805981faf148c8fea96a752d22eJean Delvare			(unsigned long)res->start,
1301787c72b107888805981faf148c8fea96a752d22eJean Delvare			(unsigned long)(res->start + WINB_REGION_SIZE - 1));
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EBUSY;
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR0;
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1306ba9c2e8d15da029ea3051c95e446b2d638ef02e2Deepak Saxena	if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR1;
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1310787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->addr = res->start;
1311787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->type = sio_data->type;
1312787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->name = names[sio_data->type];
13139a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->lock);
13149a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->update_lock);
1315787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_set_drvdata(pdev, data);
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the chip */
1318787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_init_device(pdev);
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* A few vars need to be filled upon startup */
13212ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	for (i = 0; i <= 2; i++)
13222ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie		data->fan_min[i] = w83627hf_read_value(
13232ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie					data, W83627HF_REG_FAN_MIN(i));
1324c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	w83627hf_update_fan_div(data);
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1326c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	/* Register common device attributes */
1327787c72b107888805981faf148c8fea96a752d22eJean Delvare	if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group)))
1328943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman		goto ERROR3;
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1330c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	/* Register chip-specific device attributes */
1331787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type == w83627hf || data->type == w83697hf)
133207584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
133307584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_input.dev_attr))
133407584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
133507584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_min.dev_attr))
133607584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
133707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_max.dev_attr))
133807584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1339e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in5_alarm.dev_attr))
1340e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1341e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in5_beep.dev_attr))
1342e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
134307584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_input.dev_attr))
134407584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
134507584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_min.dev_attr))
134607584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
134707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_max.dev_attr))
134807584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1349e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in6_alarm.dev_attr))
1350e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1351e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in6_beep.dev_attr))
1352e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
135307584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm1_freq.dev_attr))
135407584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
135507584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm2_freq.dev_attr)))
1356c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1358787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type != w83697hf)
135907584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
136007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_input.dev_attr))
136107584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
136207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_min.dev_attr))
136307584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
136407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_max.dev_attr))
136507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1366e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in1_alarm.dev_attr))
1367e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1368e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in1_beep.dev_attr))
1369e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
137007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_input.dev_attr))
137107584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
137207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_min.dev_attr))
137307584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
137407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_div.dev_attr))
137507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1376e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_fan3_alarm.dev_attr))
1377e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1378e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_fan3_beep.dev_attr))
1379e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
138007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_input.dev_attr))
138107584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
138207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_max.dev_attr))
138307584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
138407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_max_hyst.dev_attr))
138507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1386e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_temp3_alarm.dev_attr))
1387e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1388e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_temp3_beep.dev_attr))
1389e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
139007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_type.dev_attr)))
1391c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
1392c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1393787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type != w83697hf && data->vid != 0xff) {
13948a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare		/* Convert VID to voltage based on VRM */
13958a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare		data->vrm = vid_which_vrm();
13968a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare
1397787c72b107888805981faf148c8fea96a752d22eJean Delvare		if ((err = device_create_file(dev, &dev_attr_cpu0_vid))
1398787c72b107888805981faf148c8fea96a752d22eJean Delvare		 || (err = device_create_file(dev, &dev_attr_vrm)))
1399c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
14008a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare	}
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1402787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type == w83627thf || data->type == w83637hf
1403787c72b107888805981faf148c8fea96a752d22eJean Delvare	 || data->type == w83687thf)
140407584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
140507584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm3.dev_attr)))
1406c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83637hf || data->type == w83687thf)
140907584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
141007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm1_freq.dev_attr))
141107584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
141207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm2_freq.dev_attr))
141307584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
141407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm3_freq.dev_attr)))
14151550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			goto ERROR4;
14161550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
1417a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	if (data->type != w83627hf)
1418a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		if ((err = device_create_file(dev,
1419a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				&sensor_dev_attr_pwm1_enable.dev_attr))
1420a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		 || (err = device_create_file(dev,
1421a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				&sensor_dev_attr_pwm2_enable.dev_attr)))
1422a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer			goto ERROR4;
1423a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1424a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	if (data->type == w83627thf || data->type == w83637hf
1425a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	 || data->type == w83687thf)
1426a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		if ((err = device_create_file(dev,
1427a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				&sensor_dev_attr_pwm3_enable.dev_attr)))
1428a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer			goto ERROR4;
1429a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
14301beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	data->hwmon_dev = hwmon_device_register(dev);
14311beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	if (IS_ERR(data->hwmon_dev)) {
14321beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones		err = PTR_ERR(data->hwmon_dev);
1433c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman		goto ERROR4;
1434c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	}
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1438c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman      ERROR4:
1439787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&dev->kobj, &w83627hf_group);
1440787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&dev->kobj, &w83627hf_group_opt);
1441943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman      ERROR3:
144204a6217df28e3004ba4e76eb0a356a30f72c564fJean Delvare	platform_set_drvdata(pdev, NULL);
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(data);
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ERROR1:
1445787c72b107888805981faf148c8fea96a752d22eJean Delvare	release_region(res->start, WINB_REGION_SIZE);
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ERROR0:
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1450787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev)
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1452787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = platform_get_drvdata(pdev);
1453787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource *res;
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14551beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	hwmon_device_unregister(data->hwmon_dev);
1456943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
1457787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group);
1458787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt);
145904a6217df28e3004ba4e76eb0a356a30f72c564fJean Delvare	platform_set_drvdata(pdev, NULL);
1460943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	kfree(data);
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1462787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1463787c72b107888805981faf148c8fea96a752d22eJean Delvare	release_region(res->start, WINB_REGION_SIZE);
1464787c72b107888805981faf148c8fea96a752d22eJean Delvare
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1469d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare/* Registers 0x50-0x5f are banked */
1470d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvarestatic inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg)
1471d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare{
1472d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	if ((reg & 0x00f0) == 0x50) {
1473d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
1474d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET);
1475d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	}
1476d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare}
1477d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare
1478d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare/* Not strictly necessary, but play it safe for now */
1479d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvarestatic inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg)
1480d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare{
1481d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	if (reg & 0xff00) {
1482d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
1483d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
1484d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	}
1485d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare}
1486d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare
1487787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res, word_sized;
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14919a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	word_sized = (((reg & 0xff00) == 0x100)
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0xff00) == 0x200))
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  && (((reg & 0x00ff) == 0x50)
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x53)
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x55));
1497d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_set_bank(data, reg);
1498787c72b107888805981faf148c8fea96a752d22eJean Delvare	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
1499787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (word_sized) {
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p((reg & 0xff) + 1,
1502787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res =
1504787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (res << 8) + inb_p(data->addr +
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       W83781D_DATA_REG_OFFSET);
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1507d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_reset_bank(data, reg);
15089a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1512787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res = 0xff, sel;
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_enter();
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_select(W83627HF_LD_GPIO5);
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure these GPIO pins are enabled */
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) {
1521787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n");
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure the pins are configured for input
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   There must be at least five (VRM 9), and possibly 6 (VRM 10) */
1527dd149c52223cfb05cdefb0755d3c2793e8d33edeYuan Mu	sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f;
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((sel & 0x1f) != 0x1f) {
1529787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"function\n");
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1534787c72b107888805981faf148c8fea96a752d22eJean Delvare	dev_info(&pdev->dev, "Reading VID from GPIO5\n");
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	res = superio_inb(W83627THF_GPIO5_DR) & sel;
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_exit();
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1542787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83687thf_read_vid(struct platform_device *pdev)
1543c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare{
1544c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	int res = 0xff;
1545c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1546c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	superio_enter();
1547c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	superio_select(W83627HF_LD_HWM);
1548c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1549c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	/* Make sure these GPIO pins are enabled */
1550c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) {
1551787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "VID disabled, no VID function\n");
1552c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		goto exit;
1553c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	}
1554c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1555c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	/* Make sure the pins are configured for input */
1556c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) {
1557787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "VID configured as output, "
1558c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare			"no VID function\n");
1559c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		goto exit;
1560c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	}
1561c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1562c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	res = superio_inb(W83687THF_VID_DATA) & 0x3f;
1563c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1564c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvareexit:
1565c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	superio_exit();
1566c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	return res;
1567c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare}
1568c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1569787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int word_sized;
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15739a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	word_sized = (((reg & 0xff00) == 0x100)
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0xff00) == 0x200))
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  && (((reg & 0x00ff) == 0x53)
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x55));
1578d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_set_bank(data, reg);
1579787c72b107888805981faf148c8fea96a752d22eJean Delvare	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (word_sized) {
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(value >> 8,
1582787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_DATA_REG_OFFSET);
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p((reg & 0xff) + 1,
1584787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb_p(value & 0xff,
1587787c72b107888805981faf148c8fea96a752d22eJean Delvare	       data->addr + W83781D_DATA_REG_OFFSET);
1588d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_reset_bank(data, reg);
15899a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1593787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void __devinit w83627hf_init_device(struct platform_device *pdev)
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1595787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = platform_get_drvdata(pdev);
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1597d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	enum chips type = data->type;
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 tmp;
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Minimize conflicts with other winbond i2c-only clients...  */
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* disable i2c subclients... how to disable main i2c client?? */
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* force i2c address to relatively uncommon address */
1603787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
1604787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read VID only once */
1607d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (type == w83627hf || type == w83637hf) {
1608787c72b107888805981faf148c8fea96a752d22eJean Delvare		int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
1609787c72b107888805981faf148c8fea96a752d22eJean Delvare		int hi = w83627hf_read_value(data, W83781D_REG_CHIPID);
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
1611d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	} else if (type == w83627thf) {
1612787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->vid = w83627thf_read_gpio5(pdev);
1613d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	} else if (type == w83687thf) {
1614787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->vid = w83687thf_read_vid(pdev);
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read VRM & OVT Config only once */
1618d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (type == w83627thf || type == w83637hf || type == w83687thf) {
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vrm_ovt =
1620787c72b107888805981faf148c8fea96a752d22eJean Delvare			w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG);
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1623787c72b107888805981faf148c8fea96a752d22eJean Delvare	tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 3; i++) {
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(tmp & BIT_SCFG1[i - 1])) {
1626b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare			data->sens[i - 1] = 4;
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (w83627hf_read_value
1629787c72b107888805981faf148c8fea96a752d22eJean Delvare			    (data,
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->sens[i - 1] = 1;
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->sens[i - 1] = 2;
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((type == w83697hf) && (i == 2))
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(init) {
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable temp2 */
1641df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie		tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tmp & 0x01) {
1643787c72b107888805981faf148c8fea96a752d22eJean Delvare			dev_warn(&pdev->dev, "Enabling temp2, readings "
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 "might not make sense\n");
1645df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp & 0xfe);
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable temp3 */
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (type != w83697hf) {
1651787c72b107888805981faf148c8fea96a752d22eJean Delvare			tmp = w83627hf_read_value(data,
1652df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie				W83627HF_REG_TEMP3_CONFIG);
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tmp & 0x01) {
1654787c72b107888805981faf148c8fea96a752d22eJean Delvare				dev_warn(&pdev->dev, "Enabling temp3, "
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 "readings might not make sense\n");
1656787c72b107888805981faf148c8fea96a752d22eJean Delvare				w83627hf_write_value(data,
1657df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start monitoring */
1663787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_CONFIG,
1664787c72b107888805981faf148c8fea96a752d22eJean Delvare			    (w83627hf_read_value(data,
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						W83781D_REG_CONFIG) & 0xf7)
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    | 0x01);
1667ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare
1668ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	/* Enable VBAT monitoring if needed */
1669ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	tmp = w83627hf_read_value(data, W83781D_REG_VBAT);
1670ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	if (!(tmp & 0x01))
1671ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare		w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01);
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1674c09c5184a26158da32801e89d5849d774605f0ddJean Delvarestatic void w83627hf_update_fan_div(struct w83627hf_data *data)
1675c09c5184a26158da32801e89d5849d774605f0ddJean Delvare{
1676c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	int reg;
1677c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
1678c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
1679c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[0] = (reg >> 4) & 0x03;
1680c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[1] = (reg >> 6) & 0x03;
1681c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	if (data->type != w83697hf) {
1682c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		data->fan_div[2] = (w83627hf_read_value(data,
1683c09c5184a26158da32801e89d5849d774605f0ddJean Delvare				       W83781D_REG_PIN) >> 6) & 0x03;
1684c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	}
1685c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	reg = w83627hf_read_value(data, W83781D_REG_VBAT);
1686c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[0] |= (reg >> 3) & 0x04;
1687c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[1] |= (reg >> 4) & 0x04;
1688c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	if (data->type != w83697hf)
1689c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		data->fan_div[2] |= (reg >> 5) & 0x04;
1690c09c5184a26158da32801e89d5849d774605f0ddJean Delvare}
1691c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev)
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1694787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
1695df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	int i, num_temps = (data->type == w83697hf) ? 2 : 3;
1696a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	int num_pwms = (data->type == w83697hf) ? 2 : 3;
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16989a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    || !data->valid) {
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 8; i++) {
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* skip missing sensors */
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (((data->type == w83697hf) && (i == 1)) ||
1705c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare			    ((data->type != w83627hf && data->type != w83697hf)
17064a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu			    && (i == 5 || i == 6)))
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in[i] =
1709787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data, W83781D_REG_IN(i));
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_min[i] =
1711787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_IN_MIN(i));
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_max[i] =
1714787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_IN_MAX(i));
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17172ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie		for (i = 0; i <= 2; i++) {
17182ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			data->fan[i] =
17192ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			    w83627hf_read_value(data, W83627HF_REG_FAN(i));
17202ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			data->fan_min[i] =
1721787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
17222ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie					       W83627HF_REG_FAN_MIN(i));
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
172407584c762541672e35735b52af031183ca17a5a2Jim Cromie		for (i = 0; i <= 2; i++) {
1725787c72b107888805981faf148c8fea96a752d22eJean Delvare			u8 tmp = w83627hf_read_value(data,
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				W836X7HF_REG_PWM(data->type, i));
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			/* bits 0-3 are reserved  in 627THF */
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			if (data->type == w83627thf)
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp &= 0xf0;
173007584c762541672e35735b52af031183ca17a5a2Jim Cromie			data->pwm[i] = tmp;
173107584c762541672e35735b52af031183ca17a5a2Jim Cromie			if (i == 1 &&
173207584c762541672e35735b52af031183ca17a5a2Jim Cromie			    (data->type == w83627hf || data->type == w83697hf))
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17351550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		if (data->type == w83627hf) {
17361550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				u8 tmp = w83627hf_read_value(data,
17371550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez						W83627HF_REG_PWM_FREQ);
17381550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[0] = tmp & 0x07;
17391550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[1] = (tmp >> 4) & 0x07;
17401550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		} else if (data->type != w83627thf) {
17411550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			for (i = 1; i <= 3; i++) {
17421550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[i - 1] =
17431550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					w83627hf_read_value(data,
17441550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez						W83637HF_REG_PWM_FREQ[i - 1]);
17451550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				if (i == 2 && (data->type == w83697hf))
17461550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					break;
17471550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			}
17481550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		}
1749a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		if (data->type != w83627hf) {
1750a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer			for (i = 0; i < num_pwms; i++) {
1751a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				u8 tmp = w83627hf_read_value(data,
1752a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer					W83627THF_REG_PWM_ENABLE[i]);
1753a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				data->pwm_enable[i] =
1754a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer					((tmp >> W83627THF_PWM_ENABLE_SHIFT[i])
1755a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer					& 0x03) + 1;
1756a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer			}
1757a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		}
1758df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie		for (i = 0; i < num_temps; i++) {
1759df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp[i] = w83627hf_read_value(
1760df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp[i]);
1761df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp_max[i] = w83627hf_read_value(
1762df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp_over[i]);
1763df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp_max_hyst[i] = w83627hf_read_value(
1764df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp_hyst[i]);
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1767c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		w83627hf_update_fan_div(data);
1768c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarms =
1770787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_ALARM1) |
1771787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
1772787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
1773787c72b107888805981faf148c8fea96a752d22eJean Delvare		i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
17741c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		data->beep_mask = (i << 8) |
1775787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
1776787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_updated = jiffies;
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->valid = 1;
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17819a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return data;
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1786787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_device_add(unsigned short address,
1787787c72b107888805981faf148c8fea96a752d22eJean Delvare				      const struct w83627hf_sio_data *sio_data)
1788787c72b107888805981faf148c8fea96a752d22eJean Delvare{
1789787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource res = {
1790787c72b107888805981faf148c8fea96a752d22eJean Delvare		.start	= address + WINB_REGION_OFFSET,
1791787c72b107888805981faf148c8fea96a752d22eJean Delvare		.end	= address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1,
1792787c72b107888805981faf148c8fea96a752d22eJean Delvare		.name	= DRVNAME,
1793787c72b107888805981faf148c8fea96a752d22eJean Delvare		.flags	= IORESOURCE_IO,
1794787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1795787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
1796787c72b107888805981faf148c8fea96a752d22eJean Delvare
1797b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare	err = acpi_check_resource_conflict(&res);
1798b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare	if (err)
1799b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare		goto exit;
1800b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare
1801787c72b107888805981faf148c8fea96a752d22eJean Delvare	pdev = platform_device_alloc(DRVNAME, address);
1802787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (!pdev) {
1803787c72b107888805981faf148c8fea96a752d22eJean Delvare		err = -ENOMEM;
1804787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
1805787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit;
1806787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1807787c72b107888805981faf148c8fea96a752d22eJean Delvare
1808787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_device_add_resources(pdev, &res, 1);
1809787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err) {
1810787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device resource addition failed "
1811787c72b107888805981faf148c8fea96a752d22eJean Delvare		       "(%d)\n", err);
1812787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1813787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1814787c72b107888805981faf148c8fea96a752d22eJean Delvare
18152df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare	err = platform_device_add_data(pdev, sio_data,
18162df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare				       sizeof(struct w83627hf_sio_data));
18172df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare	if (err) {
1818787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
1819787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1820787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1821787c72b107888805981faf148c8fea96a752d22eJean Delvare
1822787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_device_add(pdev);
1823787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err) {
1824787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
1825787c72b107888805981faf148c8fea96a752d22eJean Delvare		       err);
1826787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1827787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1828787c72b107888805981faf148c8fea96a752d22eJean Delvare
1829787c72b107888805981faf148c8fea96a752d22eJean Delvare	return 0;
1830787c72b107888805981faf148c8fea96a752d22eJean Delvare
1831787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_device_put:
1832787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_device_put(pdev);
1833787c72b107888805981faf148c8fea96a752d22eJean Delvareexit:
1834787c72b107888805981faf148c8fea96a752d22eJean Delvare	return err;
1835787c72b107888805981faf148c8fea96a752d22eJean Delvare}
1836787c72b107888805981faf148c8fea96a752d22eJean Delvare
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sensors_w83627hf_init(void)
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1839787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
1840787c72b107888805981faf148c8fea96a752d22eJean Delvare	unsigned short address;
1841787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_sio_data sio_data;
1842787c72b107888805981faf148c8fea96a752d22eJean Delvare
1843787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (w83627hf_find(0x2e, &address, &sio_data)
1844787c72b107888805981faf148c8fea96a752d22eJean Delvare	 && w83627hf_find(0x4e, &address, &sio_data))
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1847787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_driver_register(&w83627hf_driver);
1848787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err)
1849787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit;
1850787c72b107888805981faf148c8fea96a752d22eJean Delvare
1851787c72b107888805981faf148c8fea96a752d22eJean Delvare	/* Sets global pdev as a side effect */
1852787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = w83627hf_device_add(address, &sio_data);
1853787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err)
1854787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_driver;
1855787c72b107888805981faf148c8fea96a752d22eJean Delvare
1856787c72b107888805981faf148c8fea96a752d22eJean Delvare	return 0;
1857787c72b107888805981faf148c8fea96a752d22eJean Delvare
1858787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_driver:
1859787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_driver_unregister(&w83627hf_driver);
1860787c72b107888805981faf148c8fea96a752d22eJean Delvareexit:
1861787c72b107888805981faf148c8fea96a752d22eJean Delvare	return err;
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sensors_w83627hf_exit(void)
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1866787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_device_unregister(pdev);
1867787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_driver_unregister(&w83627hf_driver);
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      "Philip Edelbrock <phil@netroedge.com>, "
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      "and Mark Studebaker <mdsxyz123@yahoo.com>");
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("W83627HF driver");
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sensors_w83627hf_init);
18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sensors_w83627hf_exit);
1878