w83627hf.c revision 07584c762541672e35735b52af031183ca17a5a2
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
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* modified from kernel/include/traps.c */
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int REG;		/* The register to read/write */
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	DEV	0x07	/* Register: Logical device select */
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int VAL;		/* The value to read/write */
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* logical device numbers for superio_select (below) */
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_FDC		0x00
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_PRT		0x01
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_UART1	0x02
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_UART2	0x03
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_KBC		0x05
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_CIR		0x06 /* w83627hf only */
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GAME	0x07
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_MIDI	0x07
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO1	0x07
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO5	0x07 /* w83627thf only */
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO2	0x08
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO3	0x09
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO4	0x09 /* w83627thf only */
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_ACPI	0x0a
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_HWM		0x0b
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	DEVID	0x20	/* Register: Device ID */
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_EN	0x30 /* w83627thf only */
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_IOSR	0xf3 /* w83627thf only */
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_DR	0xf4 /* w83627thf only */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
106c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_EN	0x29 /* w83687thf only */
107c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_CFG	0xF0 /* w83687thf only */
108c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_DATA	0xF1 /* w83687thf only */
109c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_outb(int reg, int val)
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(reg, REG);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(val, VAL);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_inb(int reg)
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(reg, REG);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return inb(VAL);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_select(int ld)
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(DEV, REG);
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(ld, VAL);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_enter(void)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(0x87, REG);
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(0x87, REG);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuperio_exit(void)
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(0xAA, REG);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W627_DEVID 0x52
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W627THF_DEVID 0x82
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W697_DEVID 0x60
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W637_DEVID 0x70
148c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W687THF_DEVID 0x85
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINB_ACT_REG 0x30
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINB_BASE_REG 0x60
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Constants specified below */
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
153ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec/* Alignment of the base address */
154ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_ALIGNMENT		~7
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
156ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec/* Offset & size of I/O region we are interested in */
157ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_REGION_OFFSET	5
158ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_REGION_SIZE	2
159ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec
160787c72b107888805981faf148c8fea96a752d22eJean Delvare/* Where are the sensors address/data registers relative to the region offset */
161787c72b107888805981faf148c8fea96a752d22eJean Delvare#define W83781D_ADDR_REG_OFFSET 0
162787c72b107888805981faf148c8fea96a752d22eJean Delvare#define W83781D_DATA_REG_OFFSET 1
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The W83781D registers */
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The W83782D registers for nr=7,8 are in bank 5 */
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x554 + (((nr) - 7) * 2)))
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x555 + (((nr) - 7) * 2)))
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN(nr)     ((nr < 7) ? (0x20 + (nr)) : \
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x550 + (nr) - 7))
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_FAN(nr) (0x27 + (nr))
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_TEMP2_CONFIG 0x152
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_TEMP3_CONFIG 0x252
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_TEMP(nr)		((nr == 3) ? (0x0250) : \
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((nr == 2) ? (0x0150) : \
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					             (0x27)))
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_TEMP_HYST(nr)	((nr == 3) ? (0x253) : \
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((nr == 2) ? (0x153) : \
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					             (0x3A)))
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_TEMP_OVER(nr)	((nr == 3) ? (0x255) : \
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					((nr == 2) ? (0x155) : \
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					             (0x39)))
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
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BEEP_MASK_FROM_REG(val)		 (val)
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BEEP_MASK_TO_REG(val)		((val) & 0xffffff)
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BEEP_ENABLE_TO_REG(val)		((val)?1:0)
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BEEP_ENABLE_FROM_REG(val)	((val)?1:0)
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1 << (val))
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 DIV_TO_REG(long val)
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = SENSORS_LIMIT(val, 1, 128) >> 1;
337abc01922477104e8d72b494902aff37135c409e7Grant Coady	for (i = 0; i < 7; i++) {
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val == 0)
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val >>= 1;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((u8) i);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
345ed6bafbf6017d6a007b39de6b65ad3b8ae4c8aeeJean Delvare/* For each registered chip, we need to keep some data in memory.
346ed6bafbf6017d6a007b39de6b65ad3b8ae4c8aeeJean Delvare   The structure is dynamically allocated. */
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct w83627hf_data {
348787c72b107888805981faf148c8fea96a752d22eJean Delvare	unsigned short addr;
349787c72b107888805981faf148c8fea96a752d22eJean Delvare	const char *name;
3501beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	struct device *hwmon_dev;
3519a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex lock;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enum chips type;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3549a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex update_lock;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char valid;		/* !=0 if following fields are valid */
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_updated;	/* In jiffies */
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in[9];		/* Register value */
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_max[9];		/* Register value */
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_min[9];		/* Register value */
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan[3];		/* Register value */
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_min[3];		/* Register value */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 temp;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 temp_max;		/* Register value */
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 temp_max_hyst;	/* Register value */
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 temp_add[2];	/* Register value */
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 temp_max_add[2];	/* Register value */
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 temp_max_hyst_add[2]; /* Register value */
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_div[3];		/* Register encoding, shifted right */
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vid;			/* Register encoding, combined */
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 alarms;		/* Register encoding, combined */
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 beep_mask;		/* Register encoding, combined */
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 beep_enable;		/* Boolean */
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 pwm[3];		/* Register value */
3751550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u8 pwm_freq[3];		/* Register value */
376b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	u16 sens[3];		/* 1 = pentium diode; 2 = 3904 diode;
377b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare				   4 = thermistor */
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vrm;
379c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	u8 vrm_ovt;		/* Register value, 627THF/637HF/687THF only */
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
382787c72b107888805981faf148c8fea96a752d22eJean Delvarestruct w83627hf_sio_data {
383787c72b107888805981faf148c8fea96a752d22eJean Delvare	enum chips type;
384787c72b107888805981faf148c8fea96a752d22eJean Delvare};
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
387787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_probe(struct platform_device *pdev);
388d0546128980c18748010c758903b02909e634830Jean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev);
389787c72b107888805981faf148c8fea96a752d22eJean Delvare
390787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
391787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev);
393787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void w83627hf_init_device(struct platform_device *pdev);
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
395787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic struct platform_driver w83627hf_driver = {
396cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	.driver = {
397872188420997f7f7c1b968fd9bce6578e4c3d45fJean Delvare		.owner	= THIS_MODULE,
398d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		.name	= DRVNAME,
399cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	},
400787c72b107888805981faf148c8fea96a752d22eJean Delvare	.probe		= w83627hf_probe,
401787c72b107888805981faf148c8fea96a752d22eJean Delvare	.remove		= __devexit_p(w83627hf_remove),
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
40507584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
40607584c762541672e35735b52af031183ca17a5a2Jim Cromie{
40707584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
40807584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
40907584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in[nr]));
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
41107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
41207584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_min(struct device *dev, struct device_attribute *devattr, char *buf)
41307584c762541672e35735b52af031183ca17a5a2Jim Cromie{
41407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
41507584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
41607584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_min[nr]));
41707584c762541672e35735b52af031183ca17a5a2Jim Cromie}
41807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
41907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_max(struct device *dev, struct device_attribute *devattr, char *buf)
42007584c762541672e35735b52af031183ca17a5a2Jim Cromie{
42107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
42207584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
42307584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_max[nr]));
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
42507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
42607584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_min(struct device *dev, struct device_attribute *devattr,
42707584c762541672e35735b52af031183ca17a5a2Jim Cromie	     const char *buf, size_t count)
42807584c762541672e35735b52af031183ca17a5a2Jim Cromie{
42907584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
43007584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
43107584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43307584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
43407584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->in_min[nr] = IN_TO_REG(val);
43507584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]);
43607584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
43707584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
43807584c762541672e35735b52af031183ca17a5a2Jim Cromie}
43907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
44007584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_max(struct device *dev, struct device_attribute *devattr,
44107584c762541672e35735b52af031183ca17a5a2Jim Cromie	     const char *buf, size_t count)
44207584c762541672e35735b52af031183ca17a5a2Jim Cromie{
44307584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
44407584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
44507584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44707584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
44807584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->in_max[nr] = IN_TO_REG(val);
44907584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]);
45007584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
45107584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
45207584c762541672e35735b52af031183ca17a5a2Jim Cromie}
45307584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_vin_decl(offset) \
45407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
45507584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_input, NULL, offset);		\
45607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO|S_IWUSR,	\
45707584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_min, store_in_min, offset);	\
45807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO|S_IWUSR,	\
45907584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_max, store_in_max, offset);
46007584c762541672e35735b52af031183ca17a5a2Jim Cromie
46107584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(1);
46207584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(2);
46307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(3);
46407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(4);
46507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(5);
46607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(6);
46707584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(7);
46807584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(8);
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* use a different set of functions for in0 */
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long in0;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
476c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
477c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in0 = (long)((reg * 488 + 70000 + 50) / 100);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in0 = (long)IN_FROM_REG(reg);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%ld\n", in0);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
488a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_0(struct device *dev, struct device_attribute *attr, char *buf)
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in[0]);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
494a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_min0(struct device *dev, struct device_attribute *attr, char *buf)
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in_min[0]);
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
500a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *attr, char *buf)
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in_max[0]);
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
506a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr,
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *buf, size_t count)
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
509787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5149a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
517c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
518c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
5212723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu		data->in_min[0] =
5222723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
5232723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu					255);
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_min[0] = IN_TO_REG(val);
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
528787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]);
5299a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
533a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr,
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *buf, size_t count)
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
536787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5419a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
544c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
545c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
5482723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu		data->in_max[0] =
5492723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
5502723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu					255);
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_max[0] = IN_TO_REG(val);
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
555787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]);
5569a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_input, S_IRUGO, show_regs_in_0, NULL);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs_in_min0, store_regs_in_min0);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs_in_max0, store_regs_in_max0);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
56707584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
56807584c762541672e35735b52af031183ca17a5a2Jim Cromie{
56907584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
57007584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
57107584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan[nr],
57207584c762541672e35735b52af031183ca17a5a2Jim Cromie				(long)DIV_FROM_REG(data->fan_div[nr])));
57307584c762541672e35735b52af031183ca17a5a2Jim Cromie}
57407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
57507584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
57607584c762541672e35735b52af031183ca17a5a2Jim Cromie{
57707584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
57807584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
57907584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan_min[nr],
58007584c762541672e35735b52af031183ca17a5a2Jim Cromie				(long)DIV_FROM_REG(data->fan_div[nr])));
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
58307584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_min(struct device *dev, struct device_attribute *devattr,
58407584c762541672e35735b52af031183ca17a5a2Jim Cromie	      const char *buf, size_t count)
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
58607584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
587787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
58807584c762541672e35735b52af031183ca17a5a2Jim Cromie	u32 val = simple_strtoul(buf, NULL, 10);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5909a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
59107584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
59207584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1),
59307584c762541672e35735b52af031183ca17a5a2Jim Cromie			     data->fan_min[nr]);
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5959a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
59807584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_fan_decl(offset)	\
59907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
60007584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_input, NULL, offset - 1);		\
60107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
60207584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_min, store_fan_min, offset - 1);
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
60407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(1);
60507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(2);
60607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(3);
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
60807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
60907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp(struct device *dev, struct device_attribute *devattr, char *buf)
61007584c762541672e35735b52af031183ca17a5a2Jim Cromie{
61107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
61207584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
61307584c762541672e35735b52af031183ca17a5a2Jim Cromie	if (nr >= 2) {	/* TEMP2 and TEMP3 */
61407584c762541672e35735b52af031183ca17a5a2Jim Cromie		return sprintf(buf, "%ld\n",
61507584c762541672e35735b52af031183ca17a5a2Jim Cromie			(long)LM75_TEMP_FROM_REG(data->temp_add[nr-2]));
61607584c762541672e35735b52af031183ca17a5a2Jim Cromie	} else {	/* TEMP1 */
61707584c762541672e35735b52af031183ca17a5a2Jim Cromie		return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->temp));
61807584c762541672e35735b52af031183ca17a5a2Jim Cromie	}
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
62107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
62207584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max(struct device *dev, struct device_attribute *devattr,
62307584c762541672e35735b52af031183ca17a5a2Jim Cromie	      char *buf)
62407584c762541672e35735b52af031183ca17a5a2Jim Cromie{
62507584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
62607584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
62707584c762541672e35735b52af031183ca17a5a2Jim Cromie	if (nr >= 2) {	/* TEMP2 and TEMP3 */
62807584c762541672e35735b52af031183ca17a5a2Jim Cromie		return sprintf(buf, "%ld\n",
62907584c762541672e35735b52af031183ca17a5a2Jim Cromie			(long)LM75_TEMP_FROM_REG(data->temp_max_add[nr-2]));
63007584c762541672e35735b52af031183ca17a5a2Jim Cromie	} else {	/* TEMP1 */
63107584c762541672e35735b52af031183ca17a5a2Jim Cromie		return sprintf(buf, "%ld\n",
63207584c762541672e35735b52af031183ca17a5a2Jim Cromie			(long)TEMP_FROM_REG(data->temp_max));
63307584c762541672e35735b52af031183ca17a5a2Jim Cromie	}
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
63607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
63707584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
63807584c762541672e35735b52af031183ca17a5a2Jim Cromie		   char *buf)
63907584c762541672e35735b52af031183ca17a5a2Jim Cromie{
64007584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
64107584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
64207584c762541672e35735b52af031183ca17a5a2Jim Cromie	if (nr >= 2) {	/* TEMP2 and TEMP3 */
64307584c762541672e35735b52af031183ca17a5a2Jim Cromie		return sprintf(buf, "%ld\n",
64407584c762541672e35735b52af031183ca17a5a2Jim Cromie			(long)LM75_TEMP_FROM_REG(data->temp_max_hyst_add[nr-2]));
64507584c762541672e35735b52af031183ca17a5a2Jim Cromie	} else {	/* TEMP1 */
64607584c762541672e35735b52af031183ca17a5a2Jim Cromie		return sprintf(buf, "%ld\n",
64707584c762541672e35735b52af031183ca17a5a2Jim Cromie			(long)TEMP_FROM_REG(data->temp_max_hyst));
64807584c762541672e35735b52af031183ca17a5a2Jim Cromie	}
64907584c762541672e35735b52af031183ca17a5a2Jim Cromie}
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
65107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
65207584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max(struct device *dev, struct device_attribute *devattr,
65307584c762541672e35735b52af031183ca17a5a2Jim Cromie	       const char *buf, size_t count)
65407584c762541672e35735b52af031183ca17a5a2Jim Cromie{
65507584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
65607584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
65707584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
65907584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
66107584c762541672e35735b52af031183ca17a5a2Jim Cromie	if (nr >= 2) {	/* TEMP2 and TEMP3 */
66207584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->temp_max_add[nr-2] = LM75_TEMP_TO_REG(val);
66307584c762541672e35735b52af031183ca17a5a2Jim Cromie		w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr),
66407584c762541672e35735b52af031183ca17a5a2Jim Cromie				data->temp_max_add[nr-2]);
66507584c762541672e35735b52af031183ca17a5a2Jim Cromie	} else {	/* TEMP1 */
66607584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->temp_max = TEMP_TO_REG(val);
66707584c762541672e35735b52af031183ca17a5a2Jim Cromie		w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr),
66807584c762541672e35735b52af031183ca17a5a2Jim Cromie			data->temp_max);
66907584c762541672e35735b52af031183ca17a5a2Jim Cromie	}
67007584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
67107584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
67207584c762541672e35735b52af031183ca17a5a2Jim Cromie}
67307584c762541672e35735b52af031183ca17a5a2Jim Cromie
67407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
67507584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
67607584c762541672e35735b52af031183ca17a5a2Jim Cromie		    const char *buf, size_t count)
67707584c762541672e35735b52af031183ca17a5a2Jim Cromie{
67807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
67907584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
68007584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
68107584c762541672e35735b52af031183ca17a5a2Jim Cromie
68207584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
68307584c762541672e35735b52af031183ca17a5a2Jim Cromie
68407584c762541672e35735b52af031183ca17a5a2Jim Cromie	if (nr >= 2) {	/* TEMP2 and TEMP3 */
68507584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->temp_max_hyst_add[nr-2] = LM75_TEMP_TO_REG(val);
68607584c762541672e35735b52af031183ca17a5a2Jim Cromie		w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr),
68707584c762541672e35735b52af031183ca17a5a2Jim Cromie				data->temp_max_hyst_add[nr-2]);
68807584c762541672e35735b52af031183ca17a5a2Jim Cromie	} else {	/* TEMP1 */
68907584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->temp_max_hyst = TEMP_TO_REG(val);
69007584c762541672e35735b52af031183ca17a5a2Jim Cromie		w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr),
69107584c762541672e35735b52af031183ca17a5a2Jim Cromie			data->temp_max_hyst);
69207584c762541672e35735b52af031183ca17a5a2Jim Cromie	}
69307584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
69407584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
69507584c762541672e35735b52af031183ca17a5a2Jim Cromie}
69607584c762541672e35735b52af031183ca17a5a2Jim Cromie
69707584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_decl(offset) \
69807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
69907584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_temp, NULL, offset);			\
70007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR,	 	\
70107584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_temp_max, store_temp_max, offset);	\
70207584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR,	\
70307584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_temp_max_hyst, store_temp_max_hyst, offset);
70407584c762541672e35735b52af031183ca17a5a2Jim Cromie
70507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(1);
70607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(2);
70707584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(3);
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
710a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vid_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) vid_from_reg(data->vid, data->vrm));
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
718a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
72090d6619a916062cb75a176aacb318d108758b4a5Jean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) data->vrm);
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
724a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustore_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
726787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->vrm = val;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
737a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) data->alarms);
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define show_beep_reg(REG, reg) \
745a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev); \
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%ld\n", \
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_beep_reg(ENABLE, enable)
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_beep_reg(MASK, mask)
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BEEP_ENABLE			0	/* Store beep_enable */
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BEEP_MASK			1	/* Store beep_mask */
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstore_beep_reg(struct device *dev, const char *buf, size_t count,
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       int update_mask)
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
761787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val, val2;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7669a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (update_mask == BEEP_MASK) {	/* We are storing beep_mask */
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->beep_mask = BEEP_MASK_TO_REG(val);
770787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    data->beep_mask & 0xff);
772787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    ((data->beep_mask) >> 16) & 0xff);
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val2 = (data->beep_mask >> 8) & 0x7f;
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {		/* We are storing beep_enable */
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val2 =
777787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f;
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->beep_enable = BEEP_ENABLE_TO_REG(val);
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    val2 | data->beep_enable << 7);
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7849a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sysfs_beep(REG, reg) \
789a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
791a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannou	return show_beep_##reg(dev, attr, buf); \
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} \
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t \
794a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustore_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return store_beep_reg(dev, buf, count, BEEP_##REG); \
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} \
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  show_regs_beep_##reg, store_regs_beep_##reg);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_beep(ENABLE, enable);
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_beep(MASK, mask);
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
80507584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
80707584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n",
81007584c762541672e35735b52af031183ca17a5a2Jim Cromie		       (long) DIV_FROM_REG(data->fan_div[nr]));
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Note: we save and restore the fan minimum here, because its value is
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   determined in part by the fan divisor.  This follows the principle of
814d6e05edc59ecd79e8badf440c0d295a979bdfa3eAndreas Mohr   least surprise; the user doesn't expect the fan minimum to change just
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   because the divisor changed. */
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
81707584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_div(struct device *dev, struct device_attribute *devattr,
81807584c762541672e35735b52af031183ca17a5a2Jim Cromie	      const char *buf, size_t count)
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
82007584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
821787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long min;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reg;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long val = simple_strtoul(buf, NULL, 10);
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8269a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Save fan_min */
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	min = FAN_FROM_REG(data->fan_min[nr],
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   DIV_FROM_REG(data->fan_div[nr]));
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_div[nr] = DIV_TO_REG(val);
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
834787c72b107888805981faf148c8fea96a752d22eJean Delvare	reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       & (nr==0 ? 0xcf : 0x3f))
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
837787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
839787c72b107888805981faf148c8fea96a752d22eJean Delvare	reg = (w83627hf_read_value(data, W83781D_REG_VBAT)
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       & ~(1 << (5 + nr)))
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    | ((data->fan_div[nr] & 0x04) << (3 + nr));
842787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_VBAT, reg);
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore fan_min */
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
846787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8489a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
85207584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO|S_IWUSR,
85307584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 0);
85407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO|S_IWUSR,
85507584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 1);
85607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO|S_IWUSR,
85707584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 2);
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
86007584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
86207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
86407584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long) data->pwm[nr]);
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
86807584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm(struct device *dev, struct device_attribute *devattr,
86907584c762541672e35735b52af031183ca17a5a2Jim Cromie	  const char *buf, size_t count)
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
87107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
872787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
87307584c762541672e35735b52af031183ca17a5a2Jim Cromie	u32 val = simple_strtoul(buf, NULL, 10);
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8759a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->type == w83627thf) {
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* bits 0-3 are reserved  in 627THF */
87907584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm[nr] = PWM_TO_REG(val) & 0xf0;
880787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data,
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr),
88207584c762541672e35735b52af031183ca17a5a2Jim Cromie				     data->pwm[nr] |
883787c72b107888805981faf148c8fea96a752d22eJean Delvare				     (w83627hf_read_value(data,
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
88607584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm[nr] = PWM_TO_REG(val);
887787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data,
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr),
88907584c762541672e35735b52af031183ca17a5a2Jim Cromie				     data->pwm[nr]);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8929a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
89607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0);
89707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1);
89807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
90107584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf)
9021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
90307584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
9041550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	struct w83627hf_data *data = w83627hf_update_device(dev);
9051550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83627hf)
9061550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return sprintf(buf, "%ld\n",
90707584c762541672e35735b52af031183ca17a5a2Jim Cromie			pwm_freq_from_reg_627hf(data->pwm_freq[nr]));
9081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	else
9091550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return sprintf(buf, "%ld\n",
91007584c762541672e35735b52af031183ca17a5a2Jim Cromie			pwm_freq_from_reg(data->pwm_freq[nr]));
9111550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
9121550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9131550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t
91407584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm_freq(struct device *dev, struct device_attribute *devattr,
91507584c762541672e35735b52af031183ca17a5a2Jim Cromie	       const char *buf, size_t count)
9161550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
91707584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
9181550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	struct w83627hf_data *data = dev_get_drvdata(dev);
9191550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	static const u8 mask[]={0xF8, 0x8F};
9201550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u32 val;
9211550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9221550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	val = simple_strtoul(buf, NULL, 10);
9231550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9241550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	mutex_lock(&data->update_lock);
9251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9261550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83627hf) {
92707584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val);
9281550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		w83627hf_write_value(data, W83627HF_REG_PWM_FREQ,
92907584c762541672e35735b52af031183ca17a5a2Jim Cromie				(data->pwm_freq[nr] << (nr*4)) |
9301550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				(w83627hf_read_value(data,
93107584c762541672e35735b52af031183ca17a5a2Jim Cromie				W83627HF_REG_PWM_FREQ) & mask[nr]));
9321550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	} else {
93307584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm_freq[nr] = pwm_freq_to_reg(val);
93407584c762541672e35735b52af031183ca17a5a2Jim Cromie		w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr],
93507584c762541672e35735b52af031183ca17a5a2Jim Cromie				data->pwm_freq[nr]);
9361550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	}
9371550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9381550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	mutex_unlock(&data->update_lock);
9391550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return count;
9401550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
9411550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
94207584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO|S_IWUSR,
94307584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 0);
94407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO|S_IWUSR,
94507584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 1);
94607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO|S_IWUSR,
94707584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 2);
9481550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
9491550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t
95007584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_type(struct device *dev, struct device_attribute *devattr,
95107584c762541672e35735b52af031183ca17a5a2Jim Cromie	       char *buf)
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
95307584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
95507584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long) data->sens[nr]);
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
95907584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_type(struct device *dev, struct device_attribute *devattr,
96007584c762541672e35735b52af031183ca17a5a2Jim Cromie		const char *buf, size_t count)
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
96207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
963787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val, tmp;
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9689a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (val) {
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:		/* PII/Celeron diode */
972787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
973787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
97407584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG1[nr]);
975787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
976787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG2,
97707584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG2[nr]);
97807584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:		/* 3904 */
981787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
982787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
98307584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG1[nr]);
984787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
985787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG2,
98607584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp & ~BIT_SCFG2[nr]);
98707584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
989b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	case W83781D_DEFAULT_BETA:
990b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
991b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare			 "instead\n", W83781D_DEFAULT_BETA);
992b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		/* fall through */
993b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	case 4:		/* thermistor */
994787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
995787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
99607584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp & ~BIT_SCFG1[nr]);
99707584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1000787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_err(dev,
1001b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		       "Invalid sensor type %ld; must be 1, 2, or 4\n",
1002b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		       (long) val);
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10069a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101007584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_type(offset) \
101107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
101207584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_temp_type, store_temp_type, offset - 1);
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(1);
101507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(2);
101607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(3);
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
101907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_name(struct device *dev, struct device_attribute *devattr, char *buf)
1020787c72b107888805981faf148c8fea96a752d22eJean Delvare{
1021787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
1022787c72b107888805981faf148c8fea96a752d22eJean Delvare
1023787c72b107888805981faf148c8fea96a752d22eJean Delvare	return sprintf(buf, "%s\n", data->name);
1024787c72b107888805981faf148c8fea96a752d22eJean Delvare}
1025787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
1026787c72b107888805981faf148c8fea96a752d22eJean Delvare
1027787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_find(int sioaddr, unsigned short *addr,
1028787c72b107888805981faf148c8fea96a752d22eJean Delvare				struct w83627hf_sio_data *sio_data)
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1030d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	int err = -ENODEV;
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 val;
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1033787c72b107888805981faf148c8fea96a752d22eJean Delvare	static const __initdata char *names[] = {
1034787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83627HF",
1035787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83627THF",
1036787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83697HF",
1037787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83637HF",
1038787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83687THF",
1039787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1040787c72b107888805981faf148c8fea96a752d22eJean Delvare
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG = sioaddr;
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	VAL = sioaddr + 1;
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_enter();
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val= superio_inb(DEVID);
1046787c72b107888805981faf148c8fea96a752d22eJean Delvare	switch (val) {
1047787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W627_DEVID:
1048787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83627hf;
1049787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1050787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W627THF_DEVID:
1051787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83627thf;
1052787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1053787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W697_DEVID:
1054787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83697hf;
1055787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1056787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W637_DEVID:
1057787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83637hf;
1058787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1059787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W687THF_DEVID:
1060787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83687thf;
1061787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1062e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare	case 0xff:	/* No device at all */
1063e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare		goto exit;
1064787c72b107888805981faf148c8fea96a752d22eJean Delvare	default:
1065e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare		pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val);
1066d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		goto exit;
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_select(W83627HF_LD_HWM);
1070d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	force_addr &= WINB_ALIGNMENT;
1071d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (force_addr) {
1072d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Forcing address 0x%x\n",
1073d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		       force_addr);
1074d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		superio_outb(WINB_BASE_REG, force_addr >> 8);
1075d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		superio_outb(WINB_BASE_REG + 1, force_addr & 0xff);
1076d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	}
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = (superio_inb(WINB_BASE_REG) << 8) |
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       superio_inb(WINB_BASE_REG + 1);
1079ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec	*addr = val & WINB_ALIGNMENT;
1080d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (*addr == 0) {
1081d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Base address not set, "
1082d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		       "skipping\n");
1083d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		goto exit;
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1086d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	val = superio_inb(WINB_ACT_REG);
1087d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (!(val & 0x01)) {
1088d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n");
1089d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		superio_outb(WINB_ACT_REG, val | 0x01);
1090d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	}
1091d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
1092d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	err = 0;
1093787c72b107888805981faf148c8fea96a752d22eJean Delvare	pr_info(DRVNAME ": Found %s chip at %#x\n",
1094787c72b107888805981faf148c8fea96a752d22eJean Delvare		names[sio_data->type], *addr);
1095d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
1096d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare exit:
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_exit();
1098d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	return err;
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
110107584c762541672e35735b52af031183ca17a5a2Jim Cromie#define VIN_UNIT_ATTRS(_X_)	\
110207584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_input.dev_attr.attr,		\
110307584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_min.dev_attr.attr,		\
110407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_max.dev_attr.attr
110507584c762541672e35735b52af031183ca17a5a2Jim Cromie
110607584c762541672e35735b52af031183ca17a5a2Jim Cromie#define FAN_UNIT_ATTRS(_X_)	\
110707584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_input.dev_attr.attr,	\
110807584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_min.dev_attr.attr,		\
110907584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_div.dev_attr.attr
111007584c762541672e35735b52af031183ca17a5a2Jim Cromie
111107584c762541672e35735b52af031183ca17a5a2Jim Cromie#define TEMP_UNIT_ATTRS(_X_)	\
111207584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_input.dev_attr.attr,	\
111307584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_max.dev_attr.attr,		\
111407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr,	\
111507584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_type.dev_attr.attr
111607584c762541672e35735b52af031183ca17a5a2Jim Cromie
1117c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes[] = {
1118c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_input.attr,
1119c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_min.attr,
1120c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_max.attr,
112107584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(2),
112207584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(3),
112307584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(4),
112407584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(7),
112507584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(8),
112607584c762541672e35735b52af031183ca17a5a2Jim Cromie
112707584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(1),
112807584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(2),
112907584c762541672e35735b52af031183ca17a5a2Jim Cromie
113007584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(1),
113107584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(2),
1132c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1133c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_alarms.attr,
1134c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_beep_enable.attr,
1135c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_beep_mask.attr,
1136c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
113707584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm1.dev_attr.attr,
113807584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm2.dev_attr.attr,
1139787c72b107888805981faf148c8fea96a752d22eJean Delvare	&dev_attr_name.attr,
1140c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
1141c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1142c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1143c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group = {
1144c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = w83627hf_attributes,
1145c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1146c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1147c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes_opt[] = {
114807584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(1),
114907584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(5),
115007584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(6),
115107584c762541672e35735b52af031183ca17a5a2Jim Cromie
115207584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(3),
115307584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(3),
115407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm3.dev_attr.attr,
115507584c762541672e35735b52af031183ca17a5a2Jim Cromie
115607584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
115707584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
115807584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm3_freq.dev_attr.attr,
1159c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
1160c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1161c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1162c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group_opt = {
1163c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = w83627hf_attributes_opt,
1164c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1165c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1166787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627hf_probe(struct platform_device *pdev)
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1168787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct device *dev = &pdev->dev;
1169787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_sio_data *sio_data = dev->platform_data;
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data;
1171787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource *res;
1172787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1174787c72b107888805981faf148c8fea96a752d22eJean Delvare	static const char *names[] = {
1175787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83627hf",
1176787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83627thf",
1177787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83697hf",
1178787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83637hf",
1179787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83687thf",
1180787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1181787c72b107888805981faf148c8fea96a752d22eJean Delvare
1182787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1183787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) {
1184787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
1185787c72b107888805981faf148c8fea96a752d22eJean Delvare			(unsigned long)res->start,
1186787c72b107888805981faf148c8fea96a752d22eJean Delvare			(unsigned long)(res->start + WINB_REGION_SIZE - 1));
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EBUSY;
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR0;
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191ba9c2e8d15da029ea3051c95e446b2d638ef02e2Deepak Saxena	if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR1;
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1195787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->addr = res->start;
1196787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->type = sio_data->type;
1197787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->name = names[sio_data->type];
11989a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->lock);
11999a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->update_lock);
1200787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_set_drvdata(pdev, data);
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the chip */
1203787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_init_device(pdev);
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* A few vars need to be filled upon startup */
1206787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1));
1207787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2));
1208787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3));
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1210c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	/* Register common device attributes */
1211787c72b107888805981faf148c8fea96a752d22eJean Delvare	if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group)))
1212943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman		goto ERROR3;
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1214c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	/* Register chip-specific device attributes */
1215787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type == w83627hf || data->type == w83697hf)
121607584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
121707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_input.dev_attr))
121807584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
121907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_min.dev_attr))
122007584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
122107584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_max.dev_attr))
122207584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
122307584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_input.dev_attr))
122407584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
122507584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_min.dev_attr))
122607584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
122707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_max.dev_attr))
122807584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
122907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm1_freq.dev_attr))
123007584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
123107584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm2_freq.dev_attr)))
1232c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1234787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type != w83697hf)
123507584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
123607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_input.dev_attr))
123707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
123807584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_min.dev_attr))
123907584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
124007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_max.dev_attr))
124107584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
124207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_input.dev_attr))
124307584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
124407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_min.dev_attr))
124507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
124607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_div.dev_attr))
124707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
124807584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_input.dev_attr))
124907584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
125007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_max.dev_attr))
125107584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
125207584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_max_hyst.dev_attr))
125307584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
125407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_type.dev_attr)))
1255c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
1256c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1257787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type != w83697hf && data->vid != 0xff) {
12588a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare		/* Convert VID to voltage based on VRM */
12598a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare		data->vrm = vid_which_vrm();
12608a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare
1261787c72b107888805981faf148c8fea96a752d22eJean Delvare		if ((err = device_create_file(dev, &dev_attr_cpu0_vid))
1262787c72b107888805981faf148c8fea96a752d22eJean Delvare		 || (err = device_create_file(dev, &dev_attr_vrm)))
1263c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
12648a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare	}
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1266787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type == w83627thf || data->type == w83637hf
1267787c72b107888805981faf148c8fea96a752d22eJean Delvare	 || data->type == w83687thf)
126807584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
126907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm3.dev_attr)))
1270c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12721550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83637hf || data->type == w83687thf)
127307584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
127407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm1_freq.dev_attr))
127507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
127607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm2_freq.dev_attr))
127707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
127807584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm3_freq.dev_attr)))
12791550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			goto ERROR4;
12801550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
12811beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	data->hwmon_dev = hwmon_device_register(dev);
12821beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	if (IS_ERR(data->hwmon_dev)) {
12831beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones		err = PTR_ERR(data->hwmon_dev);
1284c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman		goto ERROR4;
1285c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	}
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1289c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman      ERROR4:
1290787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&dev->kobj, &w83627hf_group);
1291787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&dev->kobj, &w83627hf_group_opt);
1292943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman      ERROR3:
129304a6217df28e3004ba4e76eb0a356a30f72c564fJean Delvare	platform_set_drvdata(pdev, NULL);
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(data);
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ERROR1:
1296787c72b107888805981faf148c8fea96a752d22eJean Delvare	release_region(res->start, WINB_REGION_SIZE);
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ERROR0:
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1301787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev)
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1303787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = platform_get_drvdata(pdev);
1304787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource *res;
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13061beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	hwmon_device_unregister(data->hwmon_dev);
1307943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
1308787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group);
1309787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt);
131004a6217df28e3004ba4e76eb0a356a30f72c564fJean Delvare	platform_set_drvdata(pdev, NULL);
1311943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	kfree(data);
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1313787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1314787c72b107888805981faf148c8fea96a752d22eJean Delvare	release_region(res->start, WINB_REGION_SIZE);
1315787c72b107888805981faf148c8fea96a752d22eJean Delvare
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1320787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res, word_sized;
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13249a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	word_sized = (((reg & 0xff00) == 0x100)
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0xff00) == 0x200))
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  && (((reg & 0x00ff) == 0x50)
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x53)
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x55));
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg & 0xff00) {
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(W83781D_REG_BANK,
1332787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(reg >> 8,
1334787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_DATA_REG_OFFSET);
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1336787c72b107888805981faf148c8fea96a752d22eJean Delvare	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
1337787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (word_sized) {
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p((reg & 0xff) + 1,
1340787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res =
1342787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (res << 8) + inb_p(data->addr +
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       W83781D_DATA_REG_OFFSET);
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg & 0xff00) {
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(W83781D_REG_BANK,
1347787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
1348787c72b107888805981faf148c8fea96a752d22eJean Delvare		outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13509a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1354787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res = 0xff, sel;
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_enter();
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_select(W83627HF_LD_GPIO5);
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure these GPIO pins are enabled */
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) {
1363787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n");
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure the pins are configured for input
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   There must be at least five (VRM 9), and possibly 6 (VRM 10) */
1369dd149c52223cfb05cdefb0755d3c2793e8d33edeYuan Mu	sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f;
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((sel & 0x1f) != 0x1f) {
1371787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"function\n");
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1376787c72b107888805981faf148c8fea96a752d22eJean Delvare	dev_info(&pdev->dev, "Reading VID from GPIO5\n");
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	res = superio_inb(W83627THF_GPIO5_DR) & sel;
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	superio_exit();
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1384787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83687thf_read_vid(struct platform_device *pdev)
1385c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare{
1386c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	int res = 0xff;
1387c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1388c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	superio_enter();
1389c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	superio_select(W83627HF_LD_HWM);
1390c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1391c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	/* Make sure these GPIO pins are enabled */
1392c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) {
1393787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "VID disabled, no VID function\n");
1394c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		goto exit;
1395c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	}
1396c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1397c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	/* Make sure the pins are configured for input */
1398c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) {
1399787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "VID configured as output, "
1400c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare			"no VID function\n");
1401c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		goto exit;
1402c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	}
1403c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1404c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	res = superio_inb(W83687THF_VID_DATA) & 0x3f;
1405c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1406c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvareexit:
1407c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	superio_exit();
1408c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	return res;
1409c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare}
1410c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1411787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int word_sized;
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14159a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	word_sized = (((reg & 0xff00) == 0x100)
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0xff00) == 0x200))
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  && (((reg & 0x00ff) == 0x53)
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x55));
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg & 0xff00) {
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(W83781D_REG_BANK,
1422787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(reg >> 8,
1424787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_DATA_REG_OFFSET);
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1426787c72b107888805981faf148c8fea96a752d22eJean Delvare	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (word_sized) {
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(value >> 8,
1429787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_DATA_REG_OFFSET);
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p((reg & 0xff) + 1,
1431787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb_p(value & 0xff,
1434787c72b107888805981faf148c8fea96a752d22eJean Delvare	       data->addr + W83781D_DATA_REG_OFFSET);
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg & 0xff00) {
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(W83781D_REG_BANK,
1437787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
1438787c72b107888805981faf148c8fea96a752d22eJean Delvare		outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14409a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1444787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void __devinit w83627hf_init_device(struct platform_device *pdev)
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1446787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = platform_get_drvdata(pdev);
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1448d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	enum chips type = data->type;
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 tmp;
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14512251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare	if (reset) {
14522251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare		/* Resetting the chip has been the default for a long time,
14532251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare		   but repeatedly caused problems (fans going to full
14542251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare		   speed...) so it is now optional. It might even go away if
14552251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare		   nobody reports it as being useful, as I see very little
14562251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare		   reason why this would be needed at all. */
1457787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_info(&pdev->dev, "If reset=1 solved a problem you were "
14582251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare			 "having, please report!\n");
14592251cf1a4b37bd483501614c2d78f5b8286f20d7Jean Delvare
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* save this register */
1461787c72b107888805981faf148c8fea96a752d22eJean Delvare		i = w83627hf_read_value(data, W83781D_REG_BEEP_CONFIG);
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Reset all except Watchdog values and last conversion values
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   This sets fan-divs to 2, among others */
1464787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_CONFIG, 0x80);
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Restore the register and disable power-on abnormal beep.
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   This saves FAN 1/2/3 input/output values set by BIOS. */
1467787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Disable master beep-enable (reset turns it on).
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   Individual beeps should be reset to off but for some reason
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   disabling this bit helps some people not get beeped */
1471787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, 0);
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Minimize conflicts with other winbond i2c-only clients...  */
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* disable i2c subclients... how to disable main i2c client?? */
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* force i2c address to relatively uncommon address */
1477787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
1478787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read VID only once */
1481d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (type == w83627hf || type == w83637hf) {
1482787c72b107888805981faf148c8fea96a752d22eJean Delvare		int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
1483787c72b107888805981faf148c8fea96a752d22eJean Delvare		int hi = w83627hf_read_value(data, W83781D_REG_CHIPID);
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
1485d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	} else if (type == w83627thf) {
1486787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->vid = w83627thf_read_gpio5(pdev);
1487d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	} else if (type == w83687thf) {
1488787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->vid = w83687thf_read_vid(pdev);
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read VRM & OVT Config only once */
1492d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (type == w83627thf || type == w83637hf || type == w83687thf) {
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vrm_ovt =
1494787c72b107888805981faf148c8fea96a752d22eJean Delvare			w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG);
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1497787c72b107888805981faf148c8fea96a752d22eJean Delvare	tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 3; i++) {
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(tmp & BIT_SCFG1[i - 1])) {
1500b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare			data->sens[i - 1] = 4;
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (w83627hf_read_value
1503787c72b107888805981faf148c8fea96a752d22eJean Delvare			    (data,
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->sens[i - 1] = 1;
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->sens[i - 1] = 2;
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((type == w83697hf) && (i == 2))
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(init) {
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable temp2 */
1515787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_TEMP2_CONFIG);
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tmp & 0x01) {
1517787c72b107888805981faf148c8fea96a752d22eJean Delvare			dev_warn(&pdev->dev, "Enabling temp2, readings "
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 "might not make sense\n");
1519787c72b107888805981faf148c8fea96a752d22eJean Delvare			w83627hf_write_value(data, W83781D_REG_TEMP2_CONFIG,
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp & 0xfe);
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable temp3 */
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (type != w83697hf) {
1525787c72b107888805981faf148c8fea96a752d22eJean Delvare			tmp = w83627hf_read_value(data,
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				W83781D_REG_TEMP3_CONFIG);
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tmp & 0x01) {
1528787c72b107888805981faf148c8fea96a752d22eJean Delvare				dev_warn(&pdev->dev, "Enabling temp3, "
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 "readings might not make sense\n");
1530787c72b107888805981faf148c8fea96a752d22eJean Delvare				w83627hf_write_value(data,
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start monitoring */
1537787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_CONFIG,
1538787c72b107888805981faf148c8fea96a752d22eJean Delvare			    (w83627hf_read_value(data,
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						W83781D_REG_CONFIG) & 0xf7)
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    | 0x01);
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev)
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1545787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15489a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    || !data->valid) {
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 8; i++) {
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* skip missing sensors */
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (((data->type == w83697hf) && (i == 1)) ||
1555c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare			    ((data->type != w83627hf && data->type != w83697hf)
15564a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu			    && (i == 5 || i == 6)))
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in[i] =
1559787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data, W83781D_REG_IN(i));
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_min[i] =
1561787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_IN_MIN(i));
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_max[i] =
1564787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_IN_MAX(i));
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 1; i <= 3; i++) {
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan[i - 1] =
1569787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data, W83781D_REG_FAN(i));
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan_min[i - 1] =
1571787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_FAN_MIN(i));
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
157407584c762541672e35735b52af031183ca17a5a2Jim Cromie		for (i = 0; i <= 2; i++) {
1575787c72b107888805981faf148c8fea96a752d22eJean Delvare			u8 tmp = w83627hf_read_value(data,
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				W836X7HF_REG_PWM(data->type, i));
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			/* bits 0-3 are reserved  in 627THF */
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			if (data->type == w83627thf)
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp &= 0xf0;
158007584c762541672e35735b52af031183ca17a5a2Jim Cromie			data->pwm[i] = tmp;
158107584c762541672e35735b52af031183ca17a5a2Jim Cromie			if (i == 1 &&
158207584c762541672e35735b52af031183ca17a5a2Jim Cromie			    (data->type == w83627hf || data->type == w83697hf))
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15851550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		if (data->type == w83627hf) {
15861550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				u8 tmp = w83627hf_read_value(data,
15871550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez						W83627HF_REG_PWM_FREQ);
15881550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[0] = tmp & 0x07;
15891550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[1] = (tmp >> 4) & 0x07;
15901550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		} else if (data->type != w83627thf) {
15911550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			for (i = 1; i <= 3; i++) {
15921550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[i - 1] =
15931550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					w83627hf_read_value(data,
15941550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez						W83637HF_REG_PWM_FREQ[i - 1]);
15951550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				if (i == 2 && (data->type == w83697hf))
15961550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					break;
15971550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			}
15981550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		}
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1600787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1));
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_max =
1602787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_TEMP_OVER(1));
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_max_hyst =
1604787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_TEMP_HYST(1));
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_add[0] =
1606787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_TEMP(2));
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_max_add[0] =
1608787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_TEMP_OVER(2));
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_max_hyst_add[0] =
1610787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_TEMP_HYST(2));
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data->type != w83697hf) {
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp_add[1] =
1613787c72b107888805981faf148c8fea96a752d22eJean Delvare			  w83627hf_read_value(data, W83781D_REG_TEMP(3));
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp_max_add[1] =
1615787c72b107888805981faf148c8fea96a752d22eJean Delvare			  w83627hf_read_value(data, W83781D_REG_TEMP_OVER(3));
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp_max_hyst_add[1] =
1617787c72b107888805981faf148c8fea96a752d22eJean Delvare			  w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3));
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1620787c72b107888805981faf148c8fea96a752d22eJean Delvare		i = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[0] = (i >> 4) & 0x03;
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[1] = (i >> 6) & 0x03;
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data->type != w83697hf) {
1624787c72b107888805981faf148c8fea96a752d22eJean Delvare			data->fan_div[2] = (w83627hf_read_value(data,
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_PIN) >> 6) & 0x03;
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1627787c72b107888805981faf148c8fea96a752d22eJean Delvare		i = w83627hf_read_value(data, W83781D_REG_VBAT);
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[0] |= (i >> 3) & 0x04;
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[1] |= (i >> 4) & 0x04;
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data->type != w83697hf)
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan_div[2] |= (i >> 5) & 0x04;
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarms =
1633787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_ALARM1) |
1634787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
1635787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
1636787c72b107888805981faf148c8fea96a752d22eJean Delvare		i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->beep_enable = i >> 7;
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->beep_mask = ((i & 0x7f) << 8) |
1639787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
1640787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_updated = jiffies;
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->valid = 1;
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16459a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return data;
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1650787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_device_add(unsigned short address,
1651787c72b107888805981faf148c8fea96a752d22eJean Delvare				      const struct w83627hf_sio_data *sio_data)
1652787c72b107888805981faf148c8fea96a752d22eJean Delvare{
1653787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource res = {
1654787c72b107888805981faf148c8fea96a752d22eJean Delvare		.start	= address + WINB_REGION_OFFSET,
1655787c72b107888805981faf148c8fea96a752d22eJean Delvare		.end	= address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1,
1656787c72b107888805981faf148c8fea96a752d22eJean Delvare		.name	= DRVNAME,
1657787c72b107888805981faf148c8fea96a752d22eJean Delvare		.flags	= IORESOURCE_IO,
1658787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1659787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
1660787c72b107888805981faf148c8fea96a752d22eJean Delvare
1661787c72b107888805981faf148c8fea96a752d22eJean Delvare	pdev = platform_device_alloc(DRVNAME, address);
1662787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (!pdev) {
1663787c72b107888805981faf148c8fea96a752d22eJean Delvare		err = -ENOMEM;
1664787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
1665787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit;
1666787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1667787c72b107888805981faf148c8fea96a752d22eJean Delvare
1668787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_device_add_resources(pdev, &res, 1);
1669787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err) {
1670787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device resource addition failed "
1671787c72b107888805981faf148c8fea96a752d22eJean Delvare		       "(%d)\n", err);
1672787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1673787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1674787c72b107888805981faf148c8fea96a752d22eJean Delvare
16752df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare	err = platform_device_add_data(pdev, sio_data,
16762df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare				       sizeof(struct w83627hf_sio_data));
16772df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare	if (err) {
1678787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
1679787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1680787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1681787c72b107888805981faf148c8fea96a752d22eJean Delvare
1682787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_device_add(pdev);
1683787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err) {
1684787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
1685787c72b107888805981faf148c8fea96a752d22eJean Delvare		       err);
1686787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1687787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1688787c72b107888805981faf148c8fea96a752d22eJean Delvare
1689787c72b107888805981faf148c8fea96a752d22eJean Delvare	return 0;
1690787c72b107888805981faf148c8fea96a752d22eJean Delvare
1691787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_device_put:
1692787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_device_put(pdev);
1693787c72b107888805981faf148c8fea96a752d22eJean Delvareexit:
1694787c72b107888805981faf148c8fea96a752d22eJean Delvare	return err;
1695787c72b107888805981faf148c8fea96a752d22eJean Delvare}
1696787c72b107888805981faf148c8fea96a752d22eJean Delvare
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sensors_w83627hf_init(void)
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1699787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
1700787c72b107888805981faf148c8fea96a752d22eJean Delvare	unsigned short address;
1701787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_sio_data sio_data;
1702787c72b107888805981faf148c8fea96a752d22eJean Delvare
1703787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (w83627hf_find(0x2e, &address, &sio_data)
1704787c72b107888805981faf148c8fea96a752d22eJean Delvare	 && w83627hf_find(0x4e, &address, &sio_data))
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1707787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_driver_register(&w83627hf_driver);
1708787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err)
1709787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit;
1710787c72b107888805981faf148c8fea96a752d22eJean Delvare
1711787c72b107888805981faf148c8fea96a752d22eJean Delvare	/* Sets global pdev as a side effect */
1712787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = w83627hf_device_add(address, &sio_data);
1713787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err)
1714787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_driver;
1715787c72b107888805981faf148c8fea96a752d22eJean Delvare
1716787c72b107888805981faf148c8fea96a752d22eJean Delvare	return 0;
1717787c72b107888805981faf148c8fea96a752d22eJean Delvare
1718787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_driver:
1719787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_driver_unregister(&w83627hf_driver);
1720787c72b107888805981faf148c8fea96a752d22eJean Delvareexit:
1721787c72b107888805981faf148c8fea96a752d22eJean Delvare	return err;
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sensors_w83627hf_exit(void)
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1726787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_device_unregister(pdev);
1727787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_driver_unregister(&w83627hf_driver);
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      "Philip Edelbrock <phil@netroedge.com>, "
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      "and Mark Studebaker <mdsxyz123@yahoo.com>");
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("W83627HF driver");
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sensors_w83627hf_init);
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sensors_w83627hf_exit);
1738