w83627hf.c revision 1c1381076f8c6cf0a2c9918194e3fa6369cdf06a
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>
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "lm75.h"
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic struct platform_device *pdev;
57d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
58d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare#define DRVNAME "w83627hf"
59d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvareenum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
60d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 force_addr;
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(force_addr, ushort, 0);
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(force_addr,
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 "Initialize the base address of the sensors");
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 force_i2c = 0x1f;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(force_i2c, byte, 0);
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(force_i2c,
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 "Initialize the i2c address of the sensors");
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
702251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvarestatic int reset;
712251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvaremodule_param(reset, bool, 0);
722251cf1a4b37bd483501614c2d78f5b8286f20d7Jean DelvareMODULE_PARM_DESC(reset, "Set to one to reset chip on load");
732251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int init = 1;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(init, bool, 0);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7867b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvarestatic unsigned short force_id;
7967b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvaremodule_param(force_id, ushort, 0);
8067b671bceb4a8340a30929e9642620d99ed5ad76Jean DelvareMODULE_PARM_DESC(force_id, "Override the detected device ID");
8167b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvare
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* modified from kernel/include/traps.c */
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int REG;		/* The register to read/write */
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	DEV	0x07	/* Register: Logical device select */
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int VAL;		/* The value to read/write */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* logical device numbers for superio_select (below) */
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_FDC		0x00
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_PRT		0x01
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_UART1	0x02
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_UART2	0x03
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_KBC		0x05
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_CIR		0x06 /* w83627hf only */
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GAME	0x07
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_MIDI	0x07
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO1	0x07
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO5	0x07 /* w83627thf only */
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO2	0x08
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO3	0x09
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO4	0x09 /* w83627thf only */
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_ACPI	0x0a
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_HWM		0x0b
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	DEVID	0x20	/* Register: Device ID */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_EN	0x30 /* w83627thf only */
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_IOSR	0xf3 /* w83627thf only */
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_DR	0xf4 /* w83627thf only */
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
110c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_EN	0x29 /* w83687thf only */
111c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_CFG	0xF0 /* w83687thf only */
112c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_DATA	0xF1 /* w83687thf only */
113c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_outb(int reg, int val)
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(reg, REG);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(val, VAL);
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_inb(int reg)
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(reg, REG);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return inb(VAL);
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_select(int ld)
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(DEV, REG);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(ld, VAL);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_enter(void)
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(0x87, REG);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(0x87, REG);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_exit(void)
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(0xAA, REG);
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W627_DEVID 0x52
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W627THF_DEVID 0x82
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W697_DEVID 0x60
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W637_DEVID 0x70
152c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W687THF_DEVID 0x85
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINB_ACT_REG 0x30
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINB_BASE_REG 0x60
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Constants specified below */
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
157ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec/* Alignment of the base address */
158ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_ALIGNMENT		~7
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
160ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec/* Offset & size of I/O region we are interested in */
161ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_REGION_OFFSET	5
162ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_REGION_SIZE	2
163ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec
164787c72b107888805981faf148c8fea96a752d22eJean Delvare/* Where are the sensors address/data registers relative to the region offset */
165787c72b107888805981faf148c8fea96a752d22eJean Delvare#define W83781D_ADDR_REG_OFFSET 0
166787c72b107888805981faf148c8fea96a752d22eJean Delvare#define W83781D_DATA_REG_OFFSET 1
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The W83781D registers */
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The W83782D registers for nr=7,8 are in bank 5 */
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x554 + (((nr) - 7) * 2)))
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x555 + (((nr) - 7) * 2)))
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN(nr)     ((nr < 7) ? (0x20 + (nr)) : \
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x550 + (nr) - 7))
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1772ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie/* nr:0-2 for fans:1-3 */
1782ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie#define W83627HF_REG_FAN_MIN(nr)	(0x3b + (nr))
1792ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie#define W83627HF_REG_FAN(nr)		(0x28 + (nr))
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie#define W83627HF_REG_TEMP2_CONFIG 0x152
182df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie#define W83627HF_REG_TEMP3_CONFIG 0x252
183df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie/* these are zero-based, unlike config constants above */
184df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp[]		= { 0x27, 0x150, 0x250 };
185df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp_hyst[]	= { 0x3A, 0x153, 0x253 };
186df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp_over[]	= { 0x39, 0x155, 0x255 };
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BANK 0x4E
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CONFIG 0x40
1914a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM1 0x459
1924a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM2 0x45A
1934a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM3 0x45B
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_CONFIG 0x4D
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS1 0x56
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS2 0x57
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS3 0x453
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_VID_FANDIV 0x47
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CHIPID 0x49
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_WCHIPID 0x58
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CHIPMAN 0x4F
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_PIN 0x4B
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_VBAT 0x5D
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_REG_PWM1 0x5A
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_REG_PWM2 0x5B
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
212c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM1		0x01	/* 697HF/637HF/687THF too */
213c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM2		0x03	/* 697HF/637HF/687THF too */
214c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM3		0x11	/* 637HF/687THF too */
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
216c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_VRM_OVT_CFG 	0x18	/* 637HF/687THF too */
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 };
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                             W83627THF_REG_PWM3 };
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \
22207584c762541672e35735b52af031183ca17a5a2Jim Cromie				    regpwm_627hf[nr] : regpwm[nr])
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2241550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83627HF_REG_PWM_FREQ		0x5C	/* Only for the 627HF */
2251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2261550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ1		0x00	/* 697HF/687THF too */
2271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ2		0x02	/* 697HF/687THF too */
2281550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ3		0x10	/* 687THF too */
2291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2301550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic const u8 W83637HF_REG_PWM_FREQ[] = { W83637HF_REG_PWM_FREQ1,
2311550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					W83637HF_REG_PWM_FREQ2,
2321550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					W83637HF_REG_PWM_FREQ3 };
2331550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2341550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83627HF_BASE_PWM_FREQ	46870
2351550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_I2C_ADDR 0x48
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_I2C_SUBADDR 0x4A
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Sensor selection */
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_SCFG1 0x5D
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_SCFG2 0x59
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_DEFAULT_BETA 3435
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Conversions. Limit checking is only done on the TO_REG
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   variants. Note that you should be a bit careful with which arguments
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   these macros are called: arguments may be evaluated more than once.
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   Fixing this is just not worth it. */
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) + 8)/16),0,255))
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IN_FROM_REG(val) ((val) * 16)
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 FAN_TO_REG(long rpm, int div)
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rpm == 0)
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 255;
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     254);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_MIN (-128000)
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_MAX ( 127000)
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TEMP: 0.001C/bit (-128C to +127C)
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   REG: 1C/bit, two's complement */
2675bfedac045082a97e20d47d876071279ef984d28Christian Hohnstaedtstatic u8 TEMP_TO_REG(long temp)
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ntemp += (ntemp<0 ? -500 : 500);
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return (u8)(ntemp / 1000);
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int TEMP_FROM_REG(u8 reg)
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return (s8)reg * 1000;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline unsigned long pwm_freq_from_reg_627hf(u8 reg)
2841550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
2851550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	unsigned long freq;
2861550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	freq = W83627HF_BASE_PWM_FREQ >> reg;
2871550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return freq;
2881550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
2891550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline u8 pwm_freq_to_reg_627hf(unsigned long val)
2901550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
2911550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u8 i;
2921550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Only 5 dividers (1 2 4 8 16)
2931550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	   Search for the nearest available frequency */
2941550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	for (i = 0; i < 4; i++) {
2951550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		if (val > (((W83627HF_BASE_PWM_FREQ >> i) +
2961550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			    (W83627HF_BASE_PWM_FREQ >> (i+1))) / 2))
2971550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			break;
2981550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	}
2991550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return i;
3001550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3011550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline unsigned long pwm_freq_from_reg(u8 reg)
3031550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
3041550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Clock bit 8 -> 180 kHz or 24 MHz */
3051550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	unsigned long clock = (reg & 0x80) ? 180000UL : 24000000UL;
3061550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3071550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	reg &= 0x7f;
3081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* This should not happen but anyway... */
3091550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (reg == 0)
3101550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		reg++;
3111550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return (clock / (reg << 8));
3121550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3131550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline u8 pwm_freq_to_reg(unsigned long val)
3141550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
3151550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Minimum divider value is 0x01 and maximum is 0x7F */
3161550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val >= 93750)	/* The highest we can do */
3171550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return 0x01;
3181550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val >= 720)	/* Use 24 MHz clock */
3191550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return (24000000UL / (val << 8));
3201550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val < 6)		/* The lowest we can do */
3211550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return 0xFF;
3221550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	else			/* Use 180 kHz clock */
3231550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return (0x80 | (180000UL / (val << 8)));
3241550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3261c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare#define BEEP_MASK_FROM_REG(val)		((val) & 0xff7fff)
3271c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare#define BEEP_MASK_TO_REG(val)		((val) & 0xff7fff)
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1 << (val))
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 DIV_TO_REG(long val)
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = SENSORS_LIMIT(val, 1, 128) >> 1;
335abc01922477104e8d72b494902aff37135c409e7Grant Coady	for (i = 0; i < 7; i++) {
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val == 0)
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val >>= 1;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((u8) i);
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
343ed6bafbf6017d6a007b39de6b65ad3b8ae4c8aeeJean Delvare/* For each registered chip, we need to keep some data in memory.
344ed6bafbf6017d6a007b39de6b65ad3b8ae4c8aeeJean Delvare   The structure is dynamically allocated. */
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct w83627hf_data {
346787c72b107888805981faf148c8fea96a752d22eJean Delvare	unsigned short addr;
347787c72b107888805981faf148c8fea96a752d22eJean Delvare	const char *name;
3481beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	struct device *hwmon_dev;
3499a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex lock;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enum chips type;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3529a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex update_lock;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char valid;		/* !=0 if following fields are valid */
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_updated;	/* In jiffies */
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in[9];		/* Register value */
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_max[9];		/* Register value */
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_min[9];		/* Register value */
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan[3];		/* Register value */
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_min[3];		/* Register value */
361df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp[3];		/* Register value */
362df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp_max[3];	/* Register value */
363df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp_max_hyst[3];	/* Register value */
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_div[3];		/* Register encoding, shifted right */
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vid;			/* Register encoding, combined */
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 alarms;		/* Register encoding, combined */
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 beep_mask;		/* Register encoding, combined */
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 pwm[3];		/* Register value */
3691550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u8 pwm_freq[3];		/* Register value */
370b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	u16 sens[3];		/* 1 = pentium diode; 2 = 3904 diode;
371b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare				   4 = thermistor */
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vrm;
373c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	u8 vrm_ovt;		/* Register value, 627THF/637HF/687THF only */
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
376787c72b107888805981faf148c8fea96a752d22eJean Delvarestruct w83627hf_sio_data {
377787c72b107888805981faf148c8fea96a752d22eJean Delvare	enum chips type;
378787c72b107888805981faf148c8fea96a752d22eJean Delvare};
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_probe(struct platform_device *pdev);
382d0546128980c18748010c758903b02909e634830Jean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev);
383787c72b107888805981faf148c8fea96a752d22eJean Delvare
384787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
385787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
386c09c5184a26158da32801e89d5849d774605f0ddJean Delvarestatic void w83627hf_update_fan_div(struct w83627hf_data *data);
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev);
388787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void w83627hf_init_device(struct platform_device *pdev);
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
390787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic struct platform_driver w83627hf_driver = {
391cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	.driver = {
392872188420997f7f7c1b968fd9bce6578e4c3d45fJean Delvare		.owner	= THIS_MODULE,
393d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		.name	= DRVNAME,
394cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	},
395787c72b107888805981faf148c8fea96a752d22eJean Delvare	.probe		= w83627hf_probe,
396787c72b107888805981faf148c8fea96a752d22eJean Delvare	.remove		= __devexit_p(w83627hf_remove),
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
40007584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
40107584c762541672e35735b52af031183ca17a5a2Jim Cromie{
40207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
40307584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
40407584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in[nr]));
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
40607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
40707584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_min(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_min[nr]));
41207584c762541672e35735b52af031183ca17a5a2Jim Cromie}
41307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
41407584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_max(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_max[nr]));
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
42007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
42107584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_min(struct device *dev, struct device_attribute *devattr,
42207584c762541672e35735b52af031183ca17a5a2Jim Cromie	     const char *buf, size_t count)
42307584c762541672e35735b52af031183ca17a5a2Jim Cromie{
42407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
42507584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
42607584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42807584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
42907584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->in_min[nr] = IN_TO_REG(val);
43007584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]);
43107584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
43207584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
43307584c762541672e35735b52af031183ca17a5a2Jim Cromie}
43407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
43507584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_max(struct device *dev, struct device_attribute *devattr,
43607584c762541672e35735b52af031183ca17a5a2Jim Cromie	     const char *buf, size_t count)
43707584c762541672e35735b52af031183ca17a5a2Jim Cromie{
43807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
43907584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
44007584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44207584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
44307584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->in_max[nr] = IN_TO_REG(val);
44407584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]);
44507584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
44607584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
44707584c762541672e35735b52af031183ca17a5a2Jim Cromie}
44807584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_vin_decl(offset) \
44907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
45007584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_input, NULL, offset);		\
45107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO|S_IWUSR,	\
45207584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_min, store_in_min, offset);	\
45307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO|S_IWUSR,	\
45407584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_max, store_in_max, offset);
45507584c762541672e35735b52af031183ca17a5a2Jim Cromie
45607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(1);
45707584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(2);
45807584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(3);
45907584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(4);
46007584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(5);
46107584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(6);
46207584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(7);
46307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(8);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* use a different set of functions for in0 */
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long in0;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
471c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
472c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in0 = (long)((reg * 488 + 70000 + 50) / 100);
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in0 = (long)IN_FROM_REG(reg);
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%ld\n", in0);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
483a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_0(struct device *dev, struct device_attribute *attr, char *buf)
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in[0]);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
489a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_min0(struct device *dev, struct device_attribute *attr, char *buf)
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in_min[0]);
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
495a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *attr, char *buf)
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in_max[0]);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr,
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *buf, size_t count)
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
504787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5099a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
512c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
513c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
5162723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu		data->in_min[0] =
5172723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
5182723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu					255);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_min[0] = IN_TO_REG(val);
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
523787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]);
5249a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
528a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr,
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *buf, size_t count)
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
531787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5369a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
539c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
540c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
5432723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu		data->in_max[0] =
5442723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
5452723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu					255);
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_max[0] = IN_TO_REG(val);
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
550787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]);
5519a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_input, S_IRUGO, show_regs_in_0, NULL);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs_in_min0, store_regs_in_min0);
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs_in_max0, store_regs_in_max0);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
56207584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
56307584c762541672e35735b52af031183ca17a5a2Jim Cromie{
56407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
56507584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
56607584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan[nr],
56707584c762541672e35735b52af031183ca17a5a2Jim Cromie				(long)DIV_FROM_REG(data->fan_div[nr])));
56807584c762541672e35735b52af031183ca17a5a2Jim Cromie}
56907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
57007584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
57107584c762541672e35735b52af031183ca17a5a2Jim Cromie{
57207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
57307584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
57407584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan_min[nr],
57507584c762541672e35735b52af031183ca17a5a2Jim Cromie				(long)DIV_FROM_REG(data->fan_div[nr])));
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
57807584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_min(struct device *dev, struct device_attribute *devattr,
57907584c762541672e35735b52af031183ca17a5a2Jim Cromie	      const char *buf, size_t count)
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
58107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
582787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
58307584c762541672e35735b52af031183ca17a5a2Jim Cromie	u32 val = simple_strtoul(buf, NULL, 10);
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5859a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
58607584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
5872ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
58807584c762541672e35735b52af031183ca17a5a2Jim Cromie			     data->fan_min[nr]);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5909a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
59307584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_fan_decl(offset)	\
59407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
59507584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_input, NULL, offset - 1);		\
59607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
59707584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_min, store_fan_min, offset - 1);
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59907584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(1);
60007584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(2);
60107584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(3);
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
60307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
60407584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp(struct device *dev, struct device_attribute *devattr, char *buf)
60507584c762541672e35735b52af031183ca17a5a2Jim Cromie{
60607584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
60707584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
608df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
609df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp[nr];
610df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
611df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
61407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
61507584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max(struct device *dev, struct device_attribute *devattr,
61607584c762541672e35735b52af031183ca17a5a2Jim Cromie	      char *buf)
61707584c762541672e35735b52af031183ca17a5a2Jim Cromie{
61807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
61907584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
620df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
621df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp_max[nr];
622df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
623df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
62607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
62707584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
62807584c762541672e35735b52af031183ca17a5a2Jim Cromie		   char *buf)
62907584c762541672e35735b52af031183ca17a5a2Jim Cromie{
63007584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
63107584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
632df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
633df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp_max_hyst[nr];
634df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
635df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
63607584c762541672e35735b52af031183ca17a5a2Jim Cromie}
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
63807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
63907584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max(struct device *dev, struct device_attribute *devattr,
64007584c762541672e35735b52af031183ca17a5a2Jim Cromie	       const char *buf, size_t count)
64107584c762541672e35735b52af031183ca17a5a2Jim Cromie{
64207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
64307584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
64407584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
645df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
64707584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
648df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	data->temp_max[nr] = tmp;
649df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
65007584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
65107584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
65207584c762541672e35735b52af031183ca17a5a2Jim Cromie}
65307584c762541672e35735b52af031183ca17a5a2Jim Cromie
65407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
65507584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
65607584c762541672e35735b52af031183ca17a5a2Jim Cromie		    const char *buf, size_t count)
65707584c762541672e35735b52af031183ca17a5a2Jim Cromie{
65807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
65907584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
66007584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
661df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
66207584c762541672e35735b52af031183ca17a5a2Jim Cromie
66307584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
664df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	data->temp_max_hyst[nr] = tmp;
665df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
66607584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
66707584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
66807584c762541672e35735b52af031183ca17a5a2Jim Cromie}
66907584c762541672e35735b52af031183ca17a5a2Jim Cromie
67007584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_decl(offset) \
67107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
672df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp, NULL, offset - 1);			\
67307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR,	 	\
674df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp_max, store_temp_max, offset - 1);	\
67507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR,	\
676df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp_max_hyst, store_temp_max_hyst, offset - 1);
67707584c762541672e35735b52af031183ca17a5a2Jim Cromie
67807584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(1);
67907584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(2);
68007584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(3);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
683a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
691a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
69390d6619a916062cb75a176aacb318d108758b4a5Jean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) data->vrm);
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
697a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustore_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
699787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->vrm = val;
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
710a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) data->alarms);
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
717e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
718e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvareshow_alarm(struct device *dev, struct device_attribute *attr, char *buf)
719e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
720e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
721e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
722e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
723e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
724e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
725e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
726e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
727e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
728e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
729e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
730e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10);
731e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16);
732e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17);
733e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
734e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
735e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
736e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
737e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
738e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
739e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
7401c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic ssize_t
7411c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvareshow_beep_mask(struct device *dev, struct device_attribute *attr, char *buf)
7421c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare{
7431c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
7441c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	return sprintf(buf, "%ld\n",
7451c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		      (long)BEEP_MASK_FROM_REG(data->beep_mask));
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
7491c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestore_beep_mask(struct device *dev, struct device_attribute *attr,
7501c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		const char *buf, size_t count)
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
752787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7531c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	unsigned long val;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7579a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7591c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	/* preserve beep enable */
7601c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	data->beep_mask = (data->beep_mask & 0x8000)
7611c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			| BEEP_MASK_TO_REG(val);
7621c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
7631c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    data->beep_mask & 0xff);
7641c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
7651c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    ((data->beep_mask) >> 16) & 0xff);
766787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
7671c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    (data->beep_mask >> 8) & 0xff);
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7699a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
7741c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		   show_beep_mask, store_beep_mask);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
777e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvareshow_beep(struct device *dev, struct device_attribute *attr, char *buf)
778e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
779e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
780e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
781e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
782e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
783e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
784e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
785e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestore_beep(struct device *dev, struct device_attribute *attr,
786e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		const char *buf, size_t count)
787e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
788e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
789e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
790e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	unsigned long bit;
791e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	u8 reg;
792e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
793e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	bit = simple_strtoul(buf, NULL, 10);
794e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bit & ~1)
795e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		return -EINVAL;
796e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
797e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	mutex_lock(&data->update_lock);
798e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bit)
799e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		data->beep_mask |= (1 << bitnr);
800e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	else
801e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		data->beep_mask &= ~(1 << bitnr);
802e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
803e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bitnr < 8) {
804e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS1);
805e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
806e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << bitnr);
807e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
808e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << bitnr);
809e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, reg);
810e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	} else if (bitnr < 16) {
811e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
812e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
813e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << (bitnr - 8));
814e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
815e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << (bitnr - 8));
816e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, reg);
817e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	} else {
818e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS3);
819e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
820e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << (bitnr - 16));
821e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
822e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << (bitnr - 16));
823e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, reg);
824e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	}
825e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	mutex_unlock(&data->update_lock);
826e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
827e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return count;
828e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
829e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
830e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
831e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 0);
832e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR,
833e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 1);
834e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR,
835e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 2);
836e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR,
837e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 3);
838e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR,
839e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 8);
840e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR,
841e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 9);
842e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR,
843e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 10);
844e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR,
845e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 16);
846e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR,
847e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 17);
848e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR,
849e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 6);
850e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR,
851e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 7);
852e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR,
853e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 11);
854e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
855e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 4);
856e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
857e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 5);
858e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR,
859e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 13);
8601c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
8611c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			show_beep, store_beep, 15);
862e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
863e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
86407584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
86607584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n",
86907584c762541672e35735b52af031183ca17a5a2Jim Cromie		       (long) DIV_FROM_REG(data->fan_div[nr]));
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Note: we save and restore the fan minimum here, because its value is
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   determined in part by the fan divisor.  This follows the principle of
873d6e05edc59ecd79e8badf440c0d295a979bdfa3eAndreas Mohr   least surprise; the user doesn't expect the fan minimum to change just
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   because the divisor changed. */
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
87607584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_div(struct device *dev, struct device_attribute *devattr,
87707584c762541672e35735b52af031183ca17a5a2Jim Cromie	      const char *buf, size_t count)
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
87907584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
880787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long min;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reg;
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long val = simple_strtoul(buf, NULL, 10);
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8859a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Save fan_min */
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	min = FAN_FROM_REG(data->fan_min[nr],
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   DIV_FROM_REG(data->fan_div[nr]));
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_div[nr] = DIV_TO_REG(val);
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
893787c72b107888805981faf148c8fea96a752d22eJean Delvare	reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       & (nr==0 ? 0xcf : 0x3f))
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
896787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
898787c72b107888805981faf148c8fea96a752d22eJean Delvare	reg = (w83627hf_read_value(data, W83781D_REG_VBAT)
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       & ~(1 << (5 + nr)))
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    | ((data->fan_div[nr] & 0x04) << (3 + nr));
901787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_VBAT, reg);
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore fan_min */
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
9052ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]);
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9079a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO|S_IWUSR,
91207584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 0);
91307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO|S_IWUSR,
91407584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 1);
91507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO|S_IWUSR,
91607584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 2);
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
91907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
92107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
92307584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long) data->pwm[nr]);
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
92707584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm(struct device *dev, struct device_attribute *devattr,
92807584c762541672e35735b52af031183ca17a5a2Jim Cromie	  const char *buf, size_t count)
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
93007584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
931787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
93207584c762541672e35735b52af031183ca17a5a2Jim Cromie	u32 val = simple_strtoul(buf, NULL, 10);
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9349a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->type == w83627thf) {
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* bits 0-3 are reserved  in 627THF */
93807584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm[nr] = PWM_TO_REG(val) & 0xf0;
939787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data,
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr),
94107584c762541672e35735b52af031183ca17a5a2Jim Cromie				     data->pwm[nr] |
942787c72b107888805981faf148c8fea96a752d22eJean Delvare				     (w83627hf_read_value(data,
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
94507584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm[nr] = PWM_TO_REG(val);
946787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data,
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr),
94807584c762541672e35735b52af031183ca17a5a2Jim Cromie				     data->pwm[nr]);
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9519a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
95507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0);
95607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1);
95707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
96007584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf)
9611550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
96207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
9631550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	struct w83627hf_data *data = w83627hf_update_device(dev);
9641550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83627hf)
9651550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return sprintf(buf, "%ld\n",
96607584c762541672e35735b52af031183ca17a5a2Jim Cromie			pwm_freq_from_reg_627hf(data->pwm_freq[nr]));
9671550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	else
9681550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return sprintf(buf, "%ld\n",
96907584c762541672e35735b52af031183ca17a5a2Jim Cromie			pwm_freq_from_reg(data->pwm_freq[nr]));
9701550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
9711550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9721550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t
97307584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm_freq(struct device *dev, struct device_attribute *devattr,
97407584c762541672e35735b52af031183ca17a5a2Jim Cromie	       const char *buf, size_t count)
9751550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
97607584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
9771550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	struct w83627hf_data *data = dev_get_drvdata(dev);
9781550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	static const u8 mask[]={0xF8, 0x8F};
9791550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u32 val;
9801550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9811550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	val = simple_strtoul(buf, NULL, 10);
9821550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9831550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	mutex_lock(&data->update_lock);
9841550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9851550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83627hf) {
98607584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val);
9871550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		w83627hf_write_value(data, W83627HF_REG_PWM_FREQ,
98807584c762541672e35735b52af031183ca17a5a2Jim Cromie				(data->pwm_freq[nr] << (nr*4)) |
9891550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				(w83627hf_read_value(data,
99007584c762541672e35735b52af031183ca17a5a2Jim Cromie				W83627HF_REG_PWM_FREQ) & mask[nr]));
9911550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	} else {
99207584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm_freq[nr] = pwm_freq_to_reg(val);
99307584c762541672e35735b52af031183ca17a5a2Jim Cromie		w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr],
99407584c762541672e35735b52af031183ca17a5a2Jim Cromie				data->pwm_freq[nr]);
9951550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	}
9961550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9971550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	mutex_unlock(&data->update_lock);
9981550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return count;
9991550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
10001550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
100107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO|S_IWUSR,
100207584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 0);
100307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO|S_IWUSR,
100407584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 1);
100507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO|S_IWUSR,
100607584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 2);
10071550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t
100907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_type(struct device *dev, struct device_attribute *devattr,
101007584c762541672e35735b52af031183ca17a5a2Jim Cromie	       char *buf)
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
101207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
101407584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long) data->sens[nr]);
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
101807584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_type(struct device *dev, struct device_attribute *devattr,
101907584c762541672e35735b52af031183ca17a5a2Jim Cromie		const char *buf, size_t count)
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
102107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
1022787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val, tmp;
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10279a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (val) {
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:		/* PII/Celeron diode */
1031787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1032787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
103307584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG1[nr]);
1034787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
1035787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG2,
103607584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG2[nr]);
103707584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:		/* 3904 */
1040787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1041787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
104207584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG1[nr]);
1043787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
1044787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG2,
104507584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp & ~BIT_SCFG2[nr]);
104607584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1048b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	case W83781D_DEFAULT_BETA:
1049b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
1050b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare			 "instead\n", W83781D_DEFAULT_BETA);
1051b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		/* fall through */
1052b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	case 4:		/* thermistor */
1053787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1054787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
105507584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp & ~BIT_SCFG1[nr]);
105607584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1059787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_err(dev,
1060b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		       "Invalid sensor type %ld; must be 1, 2, or 4\n",
1061b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		       (long) val);
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10659a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
106907584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_type(offset) \
107007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
107107584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_temp_type, store_temp_type, offset - 1);
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
107307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(1);
107407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(2);
107507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(3);
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
107707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
107807584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_name(struct device *dev, struct device_attribute *devattr, char *buf)
1079787c72b107888805981faf148c8fea96a752d22eJean Delvare{
1080787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
1081787c72b107888805981faf148c8fea96a752d22eJean Delvare
1082787c72b107888805981faf148c8fea96a752d22eJean Delvare	return sprintf(buf, "%s\n", data->name);
1083787c72b107888805981faf148c8fea96a752d22eJean Delvare}
1084787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
1085787c72b107888805981faf148c8fea96a752d22eJean Delvare
1086787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_find(int sioaddr, unsigned short *addr,
1087787c72b107888805981faf148c8fea96a752d22eJean Delvare				struct w83627hf_sio_data *sio_data)
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1089d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	int err = -ENODEV;
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 val;
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1092787c72b107888805981faf148c8fea96a752d22eJean Delvare	static const __initdata char *names[] = {
1093787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83627HF",
1094787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83627THF",
1095787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83697HF",
1096787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83637HF",
1097787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83687THF",
1098787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1099787c72b107888805981faf148c8fea96a752d22eJean Delvare
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG = sioaddr;
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	VAL = sioaddr + 1;
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_enter();
110467b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvare	val = force_id ? force_id : superio_inb(DEVID);
1105787c72b107888805981faf148c8fea96a752d22eJean Delvare	switch (val) {
1106787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W627_DEVID:
1107787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83627hf;
1108787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1109787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W627THF_DEVID:
1110787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83627thf;
1111787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1112787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W697_DEVID:
1113787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83697hf;
1114787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1115787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W637_DEVID:
1116787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83637hf;
1117787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1118787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W687THF_DEVID:
1119787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83687thf;
1120787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1121e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare	case 0xff:	/* No device at all */
1122e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare		goto exit;
1123787c72b107888805981faf148c8fea96a752d22eJean Delvare	default:
1124e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare		pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val);
1125d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		goto exit;
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_select(W83627HF_LD_HWM);
1129d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	force_addr &= WINB_ALIGNMENT;
1130d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (force_addr) {
1131d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Forcing address 0x%x\n",
1132d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		       force_addr);
1133d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		superio_outb(WINB_BASE_REG, force_addr >> 8);
1134d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		superio_outb(WINB_BASE_REG + 1, force_addr & 0xff);
1135d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	}
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = (superio_inb(WINB_BASE_REG) << 8) |
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       superio_inb(WINB_BASE_REG + 1);
1138ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec	*addr = val & WINB_ALIGNMENT;
1139d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (*addr == 0) {
1140d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Base address not set, "
1141d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		       "skipping\n");
1142d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		goto exit;
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1145d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	val = superio_inb(WINB_ACT_REG);
1146d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (!(val & 0x01)) {
1147d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n");
1148d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		superio_outb(WINB_ACT_REG, val | 0x01);
1149d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	}
1150d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
1151d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	err = 0;
1152787c72b107888805981faf148c8fea96a752d22eJean Delvare	pr_info(DRVNAME ": Found %s chip at %#x\n",
1153787c72b107888805981faf148c8fea96a752d22eJean Delvare		names[sio_data->type], *addr);
1154d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
1155d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare exit:
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_exit();
1157d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	return err;
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
116007584c762541672e35735b52af031183ca17a5a2Jim Cromie#define VIN_UNIT_ATTRS(_X_)	\
116107584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_input.dev_attr.attr,		\
116207584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_min.dev_attr.attr,		\
1163e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_max.dev_attr.attr,		\
1164e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_alarm.dev_attr.attr,		\
1165e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_beep.dev_attr.attr
116607584c762541672e35735b52af031183ca17a5a2Jim Cromie
116707584c762541672e35735b52af031183ca17a5a2Jim Cromie#define FAN_UNIT_ATTRS(_X_)	\
116807584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_input.dev_attr.attr,	\
116907584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_min.dev_attr.attr,		\
1170e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_div.dev_attr.attr,		\
1171e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_alarm.dev_attr.attr,	\
1172e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_beep.dev_attr.attr
117307584c762541672e35735b52af031183ca17a5a2Jim Cromie
117407584c762541672e35735b52af031183ca17a5a2Jim Cromie#define TEMP_UNIT_ATTRS(_X_)	\
117507584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_input.dev_attr.attr,	\
117607584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_max.dev_attr.attr,		\
117707584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr,	\
1178e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_type.dev_attr.attr,	\
1179e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr,	\
1180e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_beep.dev_attr.attr
118107584c762541672e35735b52af031183ca17a5a2Jim Cromie
1182c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes[] = {
1183c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_input.attr,
1184c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_min.attr,
1185c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_max.attr,
1186e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in0_alarm.dev_attr.attr,
1187e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in0_beep.dev_attr.attr,
118807584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(2),
118907584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(3),
119007584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(4),
119107584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(7),
119207584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(8),
119307584c762541672e35735b52af031183ca17a5a2Jim Cromie
119407584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(1),
119507584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(2),
119607584c762541672e35735b52af031183ca17a5a2Jim Cromie
119707584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(1),
119807584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(2),
1199c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1200c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_alarms.attr,
12011c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	&sensor_dev_attr_beep_enable.dev_attr.attr,
1202c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_beep_mask.attr,
1203c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
120407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm1.dev_attr.attr,
120507584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm2.dev_attr.attr,
1206787c72b107888805981faf148c8fea96a752d22eJean Delvare	&dev_attr_name.attr,
1207c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
1208c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1209c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1210c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group = {
1211c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = w83627hf_attributes,
1212c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1213c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1214c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes_opt[] = {
121507584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(1),
121607584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(5),
121707584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(6),
121807584c762541672e35735b52af031183ca17a5a2Jim Cromie
121907584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(3),
122007584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(3),
122107584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm3.dev_attr.attr,
122207584c762541672e35735b52af031183ca17a5a2Jim Cromie
122307584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
122407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
122507584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm3_freq.dev_attr.attr,
1226c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
1227c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1228c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1229c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group_opt = {
1230c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = w83627hf_attributes_opt,
1231c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1232c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1233787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627hf_probe(struct platform_device *pdev)
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1235787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct device *dev = &pdev->dev;
1236787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_sio_data *sio_data = dev->platform_data;
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data;
1238787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource *res;
12392ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	int err, i;
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1241787c72b107888805981faf148c8fea96a752d22eJean Delvare	static const char *names[] = {
1242787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83627hf",
1243787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83627thf",
1244787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83697hf",
1245787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83637hf",
1246787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83687thf",
1247787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1248787c72b107888805981faf148c8fea96a752d22eJean Delvare
1249787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1250787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) {
1251787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
1252787c72b107888805981faf148c8fea96a752d22eJean Delvare			(unsigned long)res->start,
1253787c72b107888805981faf148c8fea96a752d22eJean Delvare			(unsigned long)(res->start + WINB_REGION_SIZE - 1));
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EBUSY;
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR0;
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1258ba9c2e8d15da029ea3051c95e446b2d638ef02e2Deepak Saxena	if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR1;
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1262787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->addr = res->start;
1263787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->type = sio_data->type;
1264787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->name = names[sio_data->type];
12659a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->lock);
12669a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->update_lock);
1267787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_set_drvdata(pdev, data);
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the chip */
1270787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_init_device(pdev);
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* A few vars need to be filled upon startup */
12732ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	for (i = 0; i <= 2; i++)
12742ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie		data->fan_min[i] = w83627hf_read_value(
12752ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie					data, W83627HF_REG_FAN_MIN(i));
1276c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	w83627hf_update_fan_div(data);
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1278c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	/* Register common device attributes */
1279787c72b107888805981faf148c8fea96a752d22eJean Delvare	if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group)))
1280943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman		goto ERROR3;
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1282c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	/* Register chip-specific device attributes */
1283787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type == w83627hf || data->type == w83697hf)
128407584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
128507584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_input.dev_attr))
128607584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
128707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_min.dev_attr))
128807584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
128907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_max.dev_attr))
129007584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1291e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in5_alarm.dev_attr))
1292e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1293e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in5_beep.dev_attr))
1294e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
129507584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_input.dev_attr))
129607584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
129707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_min.dev_attr))
129807584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
129907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_max.dev_attr))
130007584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1301e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in6_alarm.dev_attr))
1302e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1303e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in6_beep.dev_attr))
1304e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
130507584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm1_freq.dev_attr))
130607584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
130707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm2_freq.dev_attr)))
1308c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1310787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type != w83697hf)
131107584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
131207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_input.dev_attr))
131307584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
131407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_min.dev_attr))
131507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
131607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_max.dev_attr))
131707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1318e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in1_alarm.dev_attr))
1319e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1320e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in1_beep.dev_attr))
1321e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
132207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_input.dev_attr))
132307584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
132407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_min.dev_attr))
132507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
132607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_div.dev_attr))
132707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1328e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_fan3_alarm.dev_attr))
1329e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1330e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_fan3_beep.dev_attr))
1331e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
133207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_input.dev_attr))
133307584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
133407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_max.dev_attr))
133507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
133607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_max_hyst.dev_attr))
133707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1338e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_temp3_alarm.dev_attr))
1339e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1340e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_temp3_beep.dev_attr))
1341e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
134207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_type.dev_attr)))
1343c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
1344c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1345787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type != w83697hf && data->vid != 0xff) {
13468a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare		/* Convert VID to voltage based on VRM */
13478a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare		data->vrm = vid_which_vrm();
13488a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare
1349787c72b107888805981faf148c8fea96a752d22eJean Delvare		if ((err = device_create_file(dev, &dev_attr_cpu0_vid))
1350787c72b107888805981faf148c8fea96a752d22eJean Delvare		 || (err = device_create_file(dev, &dev_attr_vrm)))
1351c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
13528a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare	}
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1354787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type == w83627thf || data->type == w83637hf
1355787c72b107888805981faf148c8fea96a752d22eJean Delvare	 || data->type == w83687thf)
135607584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
135707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm3.dev_attr)))
1358c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13601550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83637hf || data->type == w83687thf)
136107584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
136207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm1_freq.dev_attr))
136307584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
136407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm2_freq.dev_attr))
136507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
136607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm3_freq.dev_attr)))
13671550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			goto ERROR4;
13681550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
13691beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	data->hwmon_dev = hwmon_device_register(dev);
13701beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	if (IS_ERR(data->hwmon_dev)) {
13711beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones		err = PTR_ERR(data->hwmon_dev);
1372c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman		goto ERROR4;
1373c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	}
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1377c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman      ERROR4:
1378787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&dev->kobj, &w83627hf_group);
1379787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&dev->kobj, &w83627hf_group_opt);
1380943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman      ERROR3:
138104a6217df28e3004ba4e76eb0a356a30f72c564fJean Delvare	platform_set_drvdata(pdev, NULL);
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(data);
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ERROR1:
1384787c72b107888805981faf148c8fea96a752d22eJean Delvare	release_region(res->start, WINB_REGION_SIZE);
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ERROR0:
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1389787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev)
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1391787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = platform_get_drvdata(pdev);
1392787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource *res;
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13941beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	hwmon_device_unregister(data->hwmon_dev);
1395943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
1396787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group);
1397787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt);
139804a6217df28e3004ba4e76eb0a356a30f72c564fJean Delvare	platform_set_drvdata(pdev, NULL);
1399943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	kfree(data);
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1401787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1402787c72b107888805981faf148c8fea96a752d22eJean Delvare	release_region(res->start, WINB_REGION_SIZE);
1403787c72b107888805981faf148c8fea96a752d22eJean Delvare
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1408d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare/* Registers 0x50-0x5f are banked */
1409d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvarestatic inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg)
1410d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare{
1411d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	if ((reg & 0x00f0) == 0x50) {
1412d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
1413d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET);
1414d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	}
1415d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare}
1416d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare
1417d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare/* Not strictly necessary, but play it safe for now */
1418d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvarestatic inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg)
1419d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare{
1420d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	if (reg & 0xff00) {
1421d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
1422d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
1423d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	}
1424d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare}
1425d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare
1426787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res, word_sized;
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14309a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	word_sized = (((reg & 0xff00) == 0x100)
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0xff00) == 0x200))
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  && (((reg & 0x00ff) == 0x50)
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x53)
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x55));
1436d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_set_bank(data, reg);
1437787c72b107888805981faf148c8fea96a752d22eJean Delvare	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
1438787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (word_sized) {
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p((reg & 0xff) + 1,
1441787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res =
1443787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (res << 8) + inb_p(data->addr +
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       W83781D_DATA_REG_OFFSET);
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1446d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_reset_bank(data, reg);
14479a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res = 0xff, sel;
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_enter();
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_select(W83627HF_LD_GPIO5);
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure these GPIO pins are enabled */
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) {
1460787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n");
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure the pins are configured for input
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   There must be at least five (VRM 9), and possibly 6 (VRM 10) */
1466dd149c52223cfb05cdefb0755d3c2793e8d33edeYuan Mu	sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f;
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((sel & 0x1f) != 0x1f) {
1468787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"function\n");
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1473787c72b107888805981faf148c8fea96a752d22eJean Delvare	dev_info(&pdev->dev, "Reading VID from GPIO5\n");
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	res = superio_inb(W83627THF_GPIO5_DR) & sel;
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_exit();
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1481787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83687thf_read_vid(struct platform_device *pdev)
1482c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare{
1483c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	int res = 0xff;
1484c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1485c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	superio_enter();
1486c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	superio_select(W83627HF_LD_HWM);
1487c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1488c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	/* Make sure these GPIO pins are enabled */
1489c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) {
1490787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "VID disabled, no VID function\n");
1491c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		goto exit;
1492c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	}
1493c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1494c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	/* Make sure the pins are configured for input */
1495c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) {
1496787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "VID configured as output, "
1497c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare			"no VID function\n");
1498c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		goto exit;
1499c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	}
1500c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1501c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	res = superio_inb(W83687THF_VID_DATA) & 0x3f;
1502c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1503c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvareexit:
1504c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	superio_exit();
1505c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	return res;
1506c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare}
1507c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1508787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int word_sized;
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15129a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	word_sized = (((reg & 0xff00) == 0x100)
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0xff00) == 0x200))
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  && (((reg & 0x00ff) == 0x53)
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x55));
1517d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_set_bank(data, reg);
1518787c72b107888805981faf148c8fea96a752d22eJean Delvare	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (word_sized) {
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(value >> 8,
1521787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_DATA_REG_OFFSET);
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p((reg & 0xff) + 1,
1523787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb_p(value & 0xff,
1526787c72b107888805981faf148c8fea96a752d22eJean Delvare	       data->addr + W83781D_DATA_REG_OFFSET);
1527d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_reset_bank(data, reg);
15289a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1532787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void __devinit w83627hf_init_device(struct platform_device *pdev)
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1534787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = platform_get_drvdata(pdev);
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1536d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	enum chips type = data->type;
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 tmp;
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15392251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare	if (reset) {
15402251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare		/* Resetting the chip has been the default for a long time,
15412251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare		   but repeatedly caused problems (fans going to full
15422251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare		   speed...) so it is now optional. It might even go away if
15432251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare		   nobody reports it as being useful, as I see very little
15442251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare		   reason why this would be needed at all. */
1545787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_info(&pdev->dev, "If reset=1 solved a problem you were "
15462251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare			 "having, please report!\n");
15472251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* save this register */
1549787c72b107888805981faf148c8fea96a752d22eJean Delvare		i = w83627hf_read_value(data, W83781D_REG_BEEP_CONFIG);
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Reset all except Watchdog values and last conversion values
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   This sets fan-divs to 2, among others */
1552787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_CONFIG, 0x80);
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Restore the register and disable power-on abnormal beep.
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   This saves FAN 1/2/3 input/output values set by BIOS. */
1555787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Disable master beep-enable (reset turns it on).
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   Individual beeps should be reset to off but for some reason
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   disabling this bit helps some people not get beeped */
1559787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, 0);
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Minimize conflicts with other winbond i2c-only clients...  */
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* disable i2c subclients... how to disable main i2c client?? */
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* force i2c address to relatively uncommon address */
1565787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
1566787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read VID only once */
1569d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (type == w83627hf || type == w83637hf) {
1570787c72b107888805981faf148c8fea96a752d22eJean Delvare		int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
1571787c72b107888805981faf148c8fea96a752d22eJean Delvare		int hi = w83627hf_read_value(data, W83781D_REG_CHIPID);
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
1573d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	} else if (type == w83627thf) {
1574787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->vid = w83627thf_read_gpio5(pdev);
1575d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	} else if (type == w83687thf) {
1576787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->vid = w83687thf_read_vid(pdev);
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read VRM & OVT Config only once */
1580d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (type == w83627thf || type == w83637hf || type == w83687thf) {
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vrm_ovt =
1582787c72b107888805981faf148c8fea96a752d22eJean Delvare			w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG);
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1585787c72b107888805981faf148c8fea96a752d22eJean Delvare	tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 3; i++) {
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(tmp & BIT_SCFG1[i - 1])) {
1588b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare			data->sens[i - 1] = 4;
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (w83627hf_read_value
1591787c72b107888805981faf148c8fea96a752d22eJean Delvare			    (data,
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->sens[i - 1] = 1;
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->sens[i - 1] = 2;
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((type == w83697hf) && (i == 2))
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(init) {
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable temp2 */
1603df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie		tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tmp & 0x01) {
1605787c72b107888805981faf148c8fea96a752d22eJean Delvare			dev_warn(&pdev->dev, "Enabling temp2, readings "
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 "might not make sense\n");
1607df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp & 0xfe);
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable temp3 */
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (type != w83697hf) {
1613787c72b107888805981faf148c8fea96a752d22eJean Delvare			tmp = w83627hf_read_value(data,
1614df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie				W83627HF_REG_TEMP3_CONFIG);
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tmp & 0x01) {
1616787c72b107888805981faf148c8fea96a752d22eJean Delvare				dev_warn(&pdev->dev, "Enabling temp3, "
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 "readings might not make sense\n");
1618787c72b107888805981faf148c8fea96a752d22eJean Delvare				w83627hf_write_value(data,
1619df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start monitoring */
1625787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_CONFIG,
1626787c72b107888805981faf148c8fea96a752d22eJean Delvare			    (w83627hf_read_value(data,
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						W83781D_REG_CONFIG) & 0xf7)
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    | 0x01);
1629ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare
1630ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	/* Enable VBAT monitoring if needed */
1631ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	tmp = w83627hf_read_value(data, W83781D_REG_VBAT);
1632ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	if (!(tmp & 0x01))
1633ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare		w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01);
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1636c09c5184a26158da32801e89d5849d774605f0ddJean Delvarestatic void w83627hf_update_fan_div(struct w83627hf_data *data)
1637c09c5184a26158da32801e89d5849d774605f0ddJean Delvare{
1638c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	int reg;
1639c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
1640c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
1641c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[0] = (reg >> 4) & 0x03;
1642c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[1] = (reg >> 6) & 0x03;
1643c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	if (data->type != w83697hf) {
1644c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		data->fan_div[2] = (w83627hf_read_value(data,
1645c09c5184a26158da32801e89d5849d774605f0ddJean Delvare				       W83781D_REG_PIN) >> 6) & 0x03;
1646c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	}
1647c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	reg = w83627hf_read_value(data, W83781D_REG_VBAT);
1648c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[0] |= (reg >> 3) & 0x04;
1649c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[1] |= (reg >> 4) & 0x04;
1650c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	if (data->type != w83697hf)
1651c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		data->fan_div[2] |= (reg >> 5) & 0x04;
1652c09c5184a26158da32801e89d5849d774605f0ddJean Delvare}
1653c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev)
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1656787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
1657df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	int i, num_temps = (data->type == w83697hf) ? 2 : 3;
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16599a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    || !data->valid) {
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 8; i++) {
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* skip missing sensors */
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (((data->type == w83697hf) && (i == 1)) ||
1666c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare			    ((data->type != w83627hf && data->type != w83697hf)
16674a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu			    && (i == 5 || i == 6)))
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in[i] =
1670787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data, W83781D_REG_IN(i));
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_min[i] =
1672787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_IN_MIN(i));
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_max[i] =
1675787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_IN_MAX(i));
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16782ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie		for (i = 0; i <= 2; i++) {
16792ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			data->fan[i] =
16802ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			    w83627hf_read_value(data, W83627HF_REG_FAN(i));
16812ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			data->fan_min[i] =
1682787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
16832ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie					       W83627HF_REG_FAN_MIN(i));
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
168507584c762541672e35735b52af031183ca17a5a2Jim Cromie		for (i = 0; i <= 2; i++) {
1686787c72b107888805981faf148c8fea96a752d22eJean Delvare			u8 tmp = w83627hf_read_value(data,
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				W836X7HF_REG_PWM(data->type, i));
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			/* bits 0-3 are reserved  in 627THF */
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			if (data->type == w83627thf)
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp &= 0xf0;
169107584c762541672e35735b52af031183ca17a5a2Jim Cromie			data->pwm[i] = tmp;
169207584c762541672e35735b52af031183ca17a5a2Jim Cromie			if (i == 1 &&
169307584c762541672e35735b52af031183ca17a5a2Jim Cromie			    (data->type == w83627hf || data->type == w83697hf))
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16961550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		if (data->type == w83627hf) {
16971550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				u8 tmp = w83627hf_read_value(data,
16981550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez						W83627HF_REG_PWM_FREQ);
16991550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[0] = tmp & 0x07;
17001550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[1] = (tmp >> 4) & 0x07;
17011550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		} else if (data->type != w83627thf) {
17021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			for (i = 1; i <= 3; i++) {
17031550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[i - 1] =
17041550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					w83627hf_read_value(data,
17051550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez						W83637HF_REG_PWM_FREQ[i - 1]);
17061550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				if (i == 2 && (data->type == w83697hf))
17071550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					break;
17081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			}
17091550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		}
1710df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie		for (i = 0; i < num_temps; i++) {
1711df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp[i] = w83627hf_read_value(
1712df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp[i]);
1713df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp_max[i] = w83627hf_read_value(
1714df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp_over[i]);
1715df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp_max_hyst[i] = w83627hf_read_value(
1716df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp_hyst[i]);
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1719c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		w83627hf_update_fan_div(data);
1720c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarms =
1722787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_ALARM1) |
1723787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
1724787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
1725787c72b107888805981faf148c8fea96a752d22eJean Delvare		i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
17261c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		data->beep_mask = (i << 8) |
1727787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
1728787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_updated = jiffies;
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->valid = 1;
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17339a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return data;
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1738787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_device_add(unsigned short address,
1739787c72b107888805981faf148c8fea96a752d22eJean Delvare				      const struct w83627hf_sio_data *sio_data)
1740787c72b107888805981faf148c8fea96a752d22eJean Delvare{
1741787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource res = {
1742787c72b107888805981faf148c8fea96a752d22eJean Delvare		.start	= address + WINB_REGION_OFFSET,
1743787c72b107888805981faf148c8fea96a752d22eJean Delvare		.end	= address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1,
1744787c72b107888805981faf148c8fea96a752d22eJean Delvare		.name	= DRVNAME,
1745787c72b107888805981faf148c8fea96a752d22eJean Delvare		.flags	= IORESOURCE_IO,
1746787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1747787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
1748787c72b107888805981faf148c8fea96a752d22eJean Delvare
1749787c72b107888805981faf148c8fea96a752d22eJean Delvare	pdev = platform_device_alloc(DRVNAME, address);
1750787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (!pdev) {
1751787c72b107888805981faf148c8fea96a752d22eJean Delvare		err = -ENOMEM;
1752787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
1753787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit;
1754787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1755787c72b107888805981faf148c8fea96a752d22eJean Delvare
1756787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_device_add_resources(pdev, &res, 1);
1757787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err) {
1758787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device resource addition failed "
1759787c72b107888805981faf148c8fea96a752d22eJean Delvare		       "(%d)\n", err);
1760787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1761787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1762787c72b107888805981faf148c8fea96a752d22eJean Delvare
17632df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare	err = platform_device_add_data(pdev, sio_data,
17642df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare				       sizeof(struct w83627hf_sio_data));
17652df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare	if (err) {
1766787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
1767787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1768787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1769787c72b107888805981faf148c8fea96a752d22eJean Delvare
1770787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_device_add(pdev);
1771787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err) {
1772787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
1773787c72b107888805981faf148c8fea96a752d22eJean Delvare		       err);
1774787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1775787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1776787c72b107888805981faf148c8fea96a752d22eJean Delvare
1777787c72b107888805981faf148c8fea96a752d22eJean Delvare	return 0;
1778787c72b107888805981faf148c8fea96a752d22eJean Delvare
1779787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_device_put:
1780787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_device_put(pdev);
1781787c72b107888805981faf148c8fea96a752d22eJean Delvareexit:
1782787c72b107888805981faf148c8fea96a752d22eJean Delvare	return err;
1783787c72b107888805981faf148c8fea96a752d22eJean Delvare}
1784787c72b107888805981faf148c8fea96a752d22eJean Delvare
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sensors_w83627hf_init(void)
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1787787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
1788787c72b107888805981faf148c8fea96a752d22eJean Delvare	unsigned short address;
1789787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_sio_data sio_data;
1790787c72b107888805981faf148c8fea96a752d22eJean Delvare
1791787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (w83627hf_find(0x2e, &address, &sio_data)
1792787c72b107888805981faf148c8fea96a752d22eJean Delvare	 && w83627hf_find(0x4e, &address, &sio_data))
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1795787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_driver_register(&w83627hf_driver);
1796787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err)
1797787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit;
1798787c72b107888805981faf148c8fea96a752d22eJean Delvare
1799787c72b107888805981faf148c8fea96a752d22eJean Delvare	/* Sets global pdev as a side effect */
1800787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = w83627hf_device_add(address, &sio_data);
1801787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err)
1802787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_driver;
1803787c72b107888805981faf148c8fea96a752d22eJean Delvare
1804787c72b107888805981faf148c8fea96a752d22eJean Delvare	return 0;
1805787c72b107888805981faf148c8fea96a752d22eJean Delvare
1806787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_driver:
1807787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_driver_unregister(&w83627hf_driver);
1808787c72b107888805981faf148c8fea96a752d22eJean Delvareexit:
1809787c72b107888805981faf148c8fea96a752d22eJean Delvare	return err;
18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sensors_w83627hf_exit(void)
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1814787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_device_unregister(pdev);
1815787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_driver_unregister(&w83627hf_driver);
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      "Philip Edelbrock <phil@netroedge.com>, "
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      "and Mark Studebaker <mdsxyz123@yahoo.com>");
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("W83627HF driver");
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sensors_w83627hf_init);
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sensors_w83627hf_exit);
1826