w83627hf.c revision c46c0e9188685c0276b4c0adf9fb7e903937e35b
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    w83627hf.c - Part of lm_sensors, Linux kernel modules for hardware
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                monitoring
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Copyright (c) 1998 - 2003  Frodo Looijaard <frodol@dds.nl>,
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Philip Edelbrock <phil@netroedge.com>,
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    and Mark Studebaker <mdsxyz123@yahoo.com>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org>
8787c72b107888805981faf148c8fea96a752d22eJean Delvare    Copyright (c) 2007  Jean Delvare <khali@linux-fr.org>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This program is free software; you can redistribute it and/or modify
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    it under the terms of the GNU General Public License as published by
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    the Free Software Foundation; either version 2 of the License, or
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    (at your option) any later version.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This program is distributed in the hope that it will be useful,
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    but WITHOUT ANY WARRANTY; without even the implied warranty of
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    GNU General Public License for more details.
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    You should have received a copy of the GNU General Public License
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    along with this program; if not, write to the Free Software
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Supports following chips:
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    w83627hf	9	3	2	3	0x20	0x5ca3	no	yes(LPC)
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    w83627thf	7	3	3	3	0x90	0x5ca3	no	yes(LPC)
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    w83637hf	7	3	3	3	0x80	0x5ca3	no	yes(LPC)
32c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare    w83687thf	7	3	3	3	0x90	0x5ca3	no	yes(LPC)
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    w83697hf	8	2	2	2	0x60	0x5ca3	no	yes(LPC)
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    For other winbond chips, and for i2c support in the above chips,
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    use w83781d.c.
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Note: automatic ("cruise") fan control for 697, 637 & 627thf not
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    supported yet.
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/jiffies.h>
46787c72b107888805981faf148c8fea96a752d22eJean Delvare#include <linux/platform_device.h>
47943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/hwmon.h>
4807584c762541672e35735b52af031183ca17a5a2Jim Cromie#include <linux/hwmon-sysfs.h>
49303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare#include <linux/hwmon-vid.h>
50943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/err.h>
519a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar#include <linux/mutex.h>
52d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare#include <linux/ioport.h>
53b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare#include <linux/acpi.h>
546055fae8aceee41471edfd1876e5617d16e028feH Hartley Sweeten#include <linux/io.h>
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "lm75.h"
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic struct platform_device *pdev;
58d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
59d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare#define DRVNAME "w83627hf"
60d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvareenum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
61d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
62b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvarestruct w83627hf_sio_data {
63b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	enum chips type;
64b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	int sioaddr;
65b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare};
66b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 force_i2c = 0x1f;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(force_i2c, byte, 0);
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(force_i2c,
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 "Initialize the i2c address of the sensors");
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int init = 1;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(init, bool, 0);
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7667b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvarestatic unsigned short force_id;
7767b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvaremodule_param(force_id, ushort, 0);
7867b671bceb4a8340a30929e9642620d99ed5ad76Jean DelvareMODULE_PARM_DESC(force_id, "Override the detected device ID");
7967b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvare
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* modified from kernel/include/traps.c */
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	DEV	0x07	/* Register: Logical device select */
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
111b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvaresuperio_outb(struct w83627hf_sio_data *sio, int reg, int val)
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
113b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(reg, sio->sioaddr);
114b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(val, sio->sioaddr + 1);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
118b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvaresuperio_inb(struct w83627hf_sio_data *sio, int reg)
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
120b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(reg, sio->sioaddr);
121b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	return inb(sio->sioaddr + 1);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
125b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvaresuperio_select(struct w83627hf_sio_data *sio, int ld)
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
127b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(DEV, sio->sioaddr);
128b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(ld,  sio->sioaddr + 1);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
132b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvaresuperio_enter(struct w83627hf_sio_data *sio)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
134b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(0x87, sio->sioaddr);
135b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(0x87, sio->sioaddr);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
139b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvaresuperio_exit(struct w83627hf_sio_data *sio)
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
141b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(0xAA, sio->sioaddr);
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
1732ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie/* nr:0-2 for fans:1-3 */
1742ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie#define W83627HF_REG_FAN_MIN(nr)	(0x3b + (nr))
1752ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie#define W83627HF_REG_FAN(nr)		(0x28 + (nr))
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
177df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie#define W83627HF_REG_TEMP2_CONFIG 0x152
178df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie#define W83627HF_REG_TEMP3_CONFIG 0x252
179df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie/* these are zero-based, unlike config constants above */
180df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp[]		= { 0x27, 0x150, 0x250 };
181df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp_hyst[]	= { 0x3A, 0x153, 0x253 };
182df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp_over[]	= { 0x39, 0x155, 0x255 };
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BANK 0x4E
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CONFIG 0x40
1874a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM1 0x459
1884a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM2 0x45A
1894a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM3 0x45B
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_CONFIG 0x4D
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS1 0x56
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS2 0x57
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS3 0x453
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_VID_FANDIV 0x47
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CHIPID 0x49
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_WCHIPID 0x58
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CHIPMAN 0x4F
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_PIN 0x4B
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_VBAT 0x5D
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_REG_PWM1 0x5A
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_REG_PWM2 0x5B
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
208a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic const u8 W83627THF_REG_PWM_ENABLE[] = {
209a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	0x04,		/* FAN 1 mode */
210a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	0x04,		/* FAN 2 mode */
211a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	0x12,		/* FAN AUX mode */
212a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer};
213a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic const u8 W83627THF_PWM_ENABLE_SHIFT[] = { 2, 4, 1 };
214a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
215c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM1		0x01	/* 697HF/637HF/687THF too */
216c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM2		0x03	/* 697HF/637HF/687THF too */
217c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM3		0x11	/* 637HF/687THF too */
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
219c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_VRM_OVT_CFG 	0x18	/* 637HF/687THF too */
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 };
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                             W83627THF_REG_PWM3 };
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \
22507584c762541672e35735b52af031183ca17a5a2Jim Cromie				    regpwm_627hf[nr] : regpwm[nr])
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83627HF_REG_PWM_FREQ		0x5C	/* Only for the 627HF */
2281550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ1		0x00	/* 697HF/687THF too */
2301550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ2		0x02	/* 697HF/687THF too */
2311550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ3		0x10	/* 687THF too */
2321550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2331550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic const u8 W83637HF_REG_PWM_FREQ[] = { W83637HF_REG_PWM_FREQ1,
2341550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					W83637HF_REG_PWM_FREQ2,
2351550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					W83637HF_REG_PWM_FREQ3 };
2361550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2371550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83627HF_BASE_PWM_FREQ	46870
2381550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_I2C_ADDR 0x48
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_I2C_SUBADDR 0x4A
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Sensor selection */
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_SCFG1 0x5D
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_SCFG2 0x59
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_DEFAULT_BETA 3435
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Conversions. Limit checking is only done on the TO_REG
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   variants. Note that you should be a bit careful with which arguments
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   these macros are called: arguments may be evaluated more than once.
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   Fixing this is just not worth it. */
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) + 8)/16),0,255))
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IN_FROM_REG(val) ((val) * 16)
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 FAN_TO_REG(long rpm, int div)
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rpm == 0)
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 255;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     254);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_MIN (-128000)
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_MAX ( 127000)
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TEMP: 0.001C/bit (-128C to +127C)
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   REG: 1C/bit, two's complement */
2705bfedac045082a97e20d47d876071279ef984d28Christian Hohnstaedtstatic u8 TEMP_TO_REG(long temp)
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ntemp += (ntemp<0 ? -500 : 500);
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return (u8)(ntemp / 1000);
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int TEMP_FROM_REG(u8 reg)
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return (s8)reg * 1000;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2861550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline unsigned long pwm_freq_from_reg_627hf(u8 reg)
2871550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
2881550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	unsigned long freq;
2891550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	freq = W83627HF_BASE_PWM_FREQ >> reg;
2901550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return freq;
2911550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
2921550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline u8 pwm_freq_to_reg_627hf(unsigned long val)
2931550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
2941550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u8 i;
2951550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Only 5 dividers (1 2 4 8 16)
2961550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	   Search for the nearest available frequency */
2971550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	for (i = 0; i < 4; i++) {
2981550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		if (val > (((W83627HF_BASE_PWM_FREQ >> i) +
2991550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			    (W83627HF_BASE_PWM_FREQ >> (i+1))) / 2))
3001550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			break;
3011550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	}
3021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return i;
3031550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3041550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3051550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline unsigned long pwm_freq_from_reg(u8 reg)
3061550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
3071550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Clock bit 8 -> 180 kHz or 24 MHz */
3081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	unsigned long clock = (reg & 0x80) ? 180000UL : 24000000UL;
3091550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3101550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	reg &= 0x7f;
3111550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* This should not happen but anyway... */
3121550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (reg == 0)
3131550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		reg++;
3141550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return (clock / (reg << 8));
3151550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3161550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline u8 pwm_freq_to_reg(unsigned long val)
3171550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
3181550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Minimum divider value is 0x01 and maximum is 0x7F */
3191550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val >= 93750)	/* The highest we can do */
3201550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return 0x01;
3211550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val >= 720)	/* Use 24 MHz clock */
3221550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return (24000000UL / (val << 8));
3231550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val < 6)		/* The lowest we can do */
3241550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return 0xFF;
3251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	else			/* Use 180 kHz clock */
3261550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return (0x80 | (180000UL / (val << 8)));
3271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3281550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3291c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare#define BEEP_MASK_FROM_REG(val)		((val) & 0xff7fff)
3301c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare#define BEEP_MASK_TO_REG(val)		((val) & 0xff7fff)
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1 << (val))
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 DIV_TO_REG(long val)
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = SENSORS_LIMIT(val, 1, 128) >> 1;
338abc01922477104e8d72b494902aff37135c409e7Grant Coady	for (i = 0; i < 7; i++) {
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val == 0)
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val >>= 1;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((u8) i);
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
346ed6bafbf6017d6a007b39de6b65ad3b8ae4c8aeeJean Delvare/* For each registered chip, we need to keep some data in memory.
347ed6bafbf6017d6a007b39de6b65ad3b8ae4c8aeeJean Delvare   The structure is dynamically allocated. */
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct w83627hf_data {
349787c72b107888805981faf148c8fea96a752d22eJean Delvare	unsigned short addr;
350787c72b107888805981faf148c8fea96a752d22eJean Delvare	const char *name;
3511beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	struct device *hwmon_dev;
3529a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex lock;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enum chips type;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3559a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex update_lock;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char valid;		/* !=0 if following fields are valid */
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_updated;	/* In jiffies */
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in[9];		/* Register value */
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_max[9];		/* Register value */
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_min[9];		/* Register value */
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan[3];		/* Register value */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_min[3];		/* Register value */
364df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp[3];		/* Register value */
365df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp_max[3];	/* Register value */
366df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp_max_hyst[3];	/* Register value */
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_div[3];		/* Register encoding, shifted right */
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vid;			/* Register encoding, combined */
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 alarms;		/* Register encoding, combined */
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 beep_mask;		/* Register encoding, combined */
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 pwm[3];		/* Register value */
372a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	u8 pwm_enable[3];	/* 1 = manual
373a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				   2 = thermal cruise (also called SmartFan I)
374a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				   3 = fan speed cruise */
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
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
383787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_probe(struct platform_device *pdev);
384d0546128980c18748010c758903b02909e634830Jean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev);
385787c72b107888805981faf148c8fea96a752d22eJean Delvare
386787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
387787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
388c09c5184a26158da32801e89d5849d774605f0ddJean Delvarestatic void w83627hf_update_fan_div(struct w83627hf_data *data);
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev);
390787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void w83627hf_init_device(struct platform_device *pdev);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
392787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic struct platform_driver w83627hf_driver = {
393cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	.driver = {
394872188420997f7f7c1b968fd9bce6578e4c3d45fJean Delvare		.owner	= THIS_MODULE,
395d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		.name	= DRVNAME,
396cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	},
397787c72b107888805981faf148c8fea96a752d22eJean Delvare	.probe		= w83627hf_probe,
398787c72b107888805981faf148c8fea96a752d22eJean Delvare	.remove		= __devexit_p(w83627hf_remove),
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
40207584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
40307584c762541672e35735b52af031183ca17a5a2Jim Cromie{
40407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
40507584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
40607584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in[nr]));
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
40807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
40907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_min(struct device *dev, struct device_attribute *devattr, char *buf)
41007584c762541672e35735b52af031183ca17a5a2Jim Cromie{
41107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
41207584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
41307584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_min[nr]));
41407584c762541672e35735b52af031183ca17a5a2Jim Cromie}
41507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
41607584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_max(struct device *dev, struct device_attribute *devattr, char *buf)
41707584c762541672e35735b52af031183ca17a5a2Jim Cromie{
41807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
41907584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
42007584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_max[nr]));
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
42207584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
42307584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_min(struct device *dev, struct device_attribute *devattr,
42407584c762541672e35735b52af031183ca17a5a2Jim Cromie	     const char *buf, size_t count)
42507584c762541672e35735b52af031183ca17a5a2Jim Cromie{
42607584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
42707584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
42807584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43007584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
43107584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->in_min[nr] = IN_TO_REG(val);
43207584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]);
43307584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
43407584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
43507584c762541672e35735b52af031183ca17a5a2Jim Cromie}
43607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
43707584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_max(struct device *dev, struct device_attribute *devattr,
43807584c762541672e35735b52af031183ca17a5a2Jim Cromie	     const char *buf, size_t count)
43907584c762541672e35735b52af031183ca17a5a2Jim Cromie{
44007584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
44107584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
44207584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44407584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
44507584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->in_max[nr] = IN_TO_REG(val);
44607584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]);
44707584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
44807584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
44907584c762541672e35735b52af031183ca17a5a2Jim Cromie}
45007584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_vin_decl(offset) \
45107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
45207584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_input, NULL, offset);		\
45307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO|S_IWUSR,	\
45407584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_min, store_in_min, offset);	\
45507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO|S_IWUSR,	\
45607584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_max, store_in_max, offset);
45707584c762541672e35735b52af031183ca17a5a2Jim Cromie
45807584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(1);
45907584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(2);
46007584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(3);
46107584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(4);
46207584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(5);
46307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(6);
46407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(7);
46507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(8);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* use a different set of functions for in0 */
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long in0;
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
473c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
474c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in0 = (long)((reg * 488 + 70000 + 50) / 100);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in0 = (long)IN_FROM_REG(reg);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%ld\n", in0);
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
485a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_0(struct device *dev, struct device_attribute *attr, char *buf)
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in[0]);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_min0(struct device *dev, struct device_attribute *attr, char *buf)
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in_min[0]);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
497a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *attr, char *buf)
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in_max[0]);
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
503a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr,
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *buf, size_t count)
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
506787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5119a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
514c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
515c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
5182723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu		data->in_min[0] =
5192723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
5202723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu					255);
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_min[0] = IN_TO_REG(val);
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
525787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]);
5269a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
530a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr,
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *buf, size_t count)
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
533787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5389a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
541c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
542c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
5452723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu		data->in_max[0] =
5462723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
5472723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu					255);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_max[0] = IN_TO_REG(val);
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
552787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]);
5539a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_input, S_IRUGO, show_regs_in_0, NULL);
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs_in_min0, store_regs_in_min0);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs_in_max0, store_regs_in_max0);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
56407584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
56507584c762541672e35735b52af031183ca17a5a2Jim Cromie{
56607584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
56707584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
56807584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan[nr],
56907584c762541672e35735b52af031183ca17a5a2Jim Cromie				(long)DIV_FROM_REG(data->fan_div[nr])));
57007584c762541672e35735b52af031183ca17a5a2Jim Cromie}
57107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
57207584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
57307584c762541672e35735b52af031183ca17a5a2Jim Cromie{
57407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
57507584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
57607584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan_min[nr],
57707584c762541672e35735b52af031183ca17a5a2Jim Cromie				(long)DIV_FROM_REG(data->fan_div[nr])));
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
58007584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_min(struct device *dev, struct device_attribute *devattr,
58107584c762541672e35735b52af031183ca17a5a2Jim Cromie	      const char *buf, size_t count)
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
58307584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
584787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
58507584c762541672e35735b52af031183ca17a5a2Jim Cromie	u32 val = simple_strtoul(buf, NULL, 10);
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5879a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
58807584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
5892ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
59007584c762541672e35735b52af031183ca17a5a2Jim Cromie			     data->fan_min[nr]);
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5929a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
59507584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_fan_decl(offset)	\
59607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
59707584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_input, NULL, offset - 1);		\
59807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
59907584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_min, store_fan_min, offset - 1);
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
60107584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(1);
60207584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(2);
60307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(3);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
60507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
60607584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp(struct device *dev, struct device_attribute *devattr, char *buf)
60707584c762541672e35735b52af031183ca17a5a2Jim Cromie{
60807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
60907584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
610df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
611df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp[nr];
612df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
613df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
61607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
61707584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max(struct device *dev, struct device_attribute *devattr,
61807584c762541672e35735b52af031183ca17a5a2Jim Cromie	      char *buf)
61907584c762541672e35735b52af031183ca17a5a2Jim Cromie{
62007584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
62107584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
622df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
623df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp_max[nr];
624df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
625df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
62807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
62907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
63007584c762541672e35735b52af031183ca17a5a2Jim Cromie		   char *buf)
63107584c762541672e35735b52af031183ca17a5a2Jim Cromie{
63207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
63307584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
634df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
635df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp_max_hyst[nr];
636df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
637df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
63807584c762541672e35735b52af031183ca17a5a2Jim Cromie}
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
64007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
64107584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max(struct device *dev, struct device_attribute *devattr,
64207584c762541672e35735b52af031183ca17a5a2Jim Cromie	       const char *buf, size_t count)
64307584c762541672e35735b52af031183ca17a5a2Jim Cromie{
64407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
64507584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
64607584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
647df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
64907584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
650df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	data->temp_max[nr] = tmp;
651df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
65207584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
65307584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
65407584c762541672e35735b52af031183ca17a5a2Jim Cromie}
65507584c762541672e35735b52af031183ca17a5a2Jim Cromie
65607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
65707584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
65807584c762541672e35735b52af031183ca17a5a2Jim Cromie		    const char *buf, size_t count)
65907584c762541672e35735b52af031183ca17a5a2Jim Cromie{
66007584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
66107584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
66207584c762541672e35735b52af031183ca17a5a2Jim Cromie	long val = simple_strtol(buf, NULL, 10);
663df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
66407584c762541672e35735b52af031183ca17a5a2Jim Cromie
66507584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
666df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	data->temp_max_hyst[nr] = tmp;
667df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
66807584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
66907584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
67007584c762541672e35735b52af031183ca17a5a2Jim Cromie}
67107584c762541672e35735b52af031183ca17a5a2Jim Cromie
67207584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_decl(offset) \
67307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
674df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp, NULL, offset - 1);			\
67507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR,	 	\
676df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp_max, store_temp_max, offset - 1);	\
67707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR,	\
678df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp_max_hyst, store_temp_max_hyst, offset - 1);
67907584c762541672e35735b52af031183ca17a5a2Jim Cromie
68007584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(1);
68107584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(2);
68207584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(3);
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
685a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
693a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
69590d6619a916062cb75a176aacb318d108758b4a5Jean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) data->vrm);
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
699a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustore_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
701787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->vrm = val;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
712a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) data->alarms);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
719e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
720e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvareshow_alarm(struct device *dev, struct device_attribute *attr, char *buf)
721e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
722e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
723e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
724e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
725e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
726e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
727e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
728e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
729e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
730e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
731e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
732e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10);
733e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16);
734e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17);
735e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
736e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
737e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
738e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
739e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
740e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
741e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
7421c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic ssize_t
7431c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvareshow_beep_mask(struct device *dev, struct device_attribute *attr, char *buf)
7441c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare{
7451c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
7461c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	return sprintf(buf, "%ld\n",
7471c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		      (long)BEEP_MASK_FROM_REG(data->beep_mask));
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
7511c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestore_beep_mask(struct device *dev, struct device_attribute *attr,
7521c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		const char *buf, size_t count)
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
754787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7551c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	unsigned long val;
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7599a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7611c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	/* preserve beep enable */
7621c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	data->beep_mask = (data->beep_mask & 0x8000)
7631c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			| BEEP_MASK_TO_REG(val);
7641c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
7651c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    data->beep_mask & 0xff);
7661c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
7671c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    ((data->beep_mask) >> 16) & 0xff);
768787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
7691c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    (data->beep_mask >> 8) & 0xff);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7719a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7751c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
7761c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		   show_beep_mask, store_beep_mask);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
779e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvareshow_beep(struct device *dev, struct device_attribute *attr, char *buf)
780e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
781e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
782e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
783e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
784e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
785e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
786e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
787e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestore_beep(struct device *dev, struct device_attribute *attr,
788e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		const char *buf, size_t count)
789e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
790e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
791e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
792e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	unsigned long bit;
793e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	u8 reg;
794e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
795e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	bit = simple_strtoul(buf, NULL, 10);
796e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bit & ~1)
797e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		return -EINVAL;
798e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
799e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	mutex_lock(&data->update_lock);
800e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bit)
801e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		data->beep_mask |= (1 << bitnr);
802e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	else
803e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		data->beep_mask &= ~(1 << bitnr);
804e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
805e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bitnr < 8) {
806e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS1);
807e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
808e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << bitnr);
809e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
810e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << bitnr);
811e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, reg);
812e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	} else if (bitnr < 16) {
813e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
814e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
815e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << (bitnr - 8));
816e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
817e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << (bitnr - 8));
818e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, reg);
819e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	} else {
820e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS3);
821e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
822e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << (bitnr - 16));
823e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
824e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << (bitnr - 16));
825e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, reg);
826e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	}
827e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	mutex_unlock(&data->update_lock);
828e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
829e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return count;
830e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
831e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
832e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
833e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 0);
834e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR,
835e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 1);
836e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR,
837e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 2);
838e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR,
839e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 3);
840e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR,
841e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 8);
842e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR,
843e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 9);
844e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR,
845e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 10);
846e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR,
847e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 16);
848e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR,
849e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 17);
850e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR,
851e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 6);
852e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR,
853e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 7);
854e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR,
855e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 11);
856e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
857e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 4);
858e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
859e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 5);
860e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR,
861e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 13);
8621c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
8631c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			show_beep, store_beep, 15);
864e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
865e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
86607584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
86807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n",
87107584c762541672e35735b52af031183ca17a5a2Jim Cromie		       (long) DIV_FROM_REG(data->fan_div[nr]));
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Note: we save and restore the fan minimum here, because its value is
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   determined in part by the fan divisor.  This follows the principle of
875d6e05edc59ecd79e8badf440c0d295a979bdfa3eAndreas Mohr   least surprise; the user doesn't expect the fan minimum to change just
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   because the divisor changed. */
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
87807584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_div(struct device *dev, struct device_attribute *devattr,
87907584c762541672e35735b52af031183ca17a5a2Jim Cromie	      const char *buf, size_t count)
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
88107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
882787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long min;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reg;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long val = simple_strtoul(buf, NULL, 10);
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8879a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Save fan_min */
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	min = FAN_FROM_REG(data->fan_min[nr],
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   DIV_FROM_REG(data->fan_div[nr]));
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_div[nr] = DIV_TO_REG(val);
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
895787c72b107888805981faf148c8fea96a752d22eJean Delvare	reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       & (nr==0 ? 0xcf : 0x3f))
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
898787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
900787c72b107888805981faf148c8fea96a752d22eJean Delvare	reg = (w83627hf_read_value(data, W83781D_REG_VBAT)
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       & ~(1 << (5 + nr)))
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    | ((data->fan_div[nr] & 0x04) << (3 + nr));
903787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_VBAT, reg);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore fan_min */
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
9072ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9099a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO|S_IWUSR,
91407584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 0);
91507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO|S_IWUSR,
91607584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 1);
91707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO|S_IWUSR,
91807584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 2);
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
92107584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
92307584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
92507584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long) data->pwm[nr]);
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
92907584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm(struct device *dev, struct device_attribute *devattr,
93007584c762541672e35735b52af031183ca17a5a2Jim Cromie	  const char *buf, size_t count)
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
93207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
933787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
93407584c762541672e35735b52af031183ca17a5a2Jim Cromie	u32 val = simple_strtoul(buf, NULL, 10);
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9369a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->type == w83627thf) {
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* bits 0-3 are reserved  in 627THF */
94007584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm[nr] = PWM_TO_REG(val) & 0xf0;
941787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data,
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr),
94307584c762541672e35735b52af031183ca17a5a2Jim Cromie				     data->pwm[nr] |
944787c72b107888805981faf148c8fea96a752d22eJean Delvare				     (w83627hf_read_value(data,
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
94707584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm[nr] = PWM_TO_REG(val);
948787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data,
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr),
95007584c762541672e35735b52af031183ca17a5a2Jim Cromie				     data->pwm[nr]);
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9539a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
95707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0);
95807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1);
95907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2);
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
962a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyershow_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf)
963a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer{
964a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	int nr = to_sensor_dev_attr(devattr)->index;
965a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	struct w83627hf_data *data = w83627hf_update_device(dev);
966a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	return sprintf(buf, "%d\n", data->pwm_enable[nr]);
967a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer}
968a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
969a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic ssize_t
970a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstore_pwm_enable(struct device *dev, struct device_attribute *devattr,
971a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	  const char *buf, size_t count)
972a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer{
973a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	int nr = to_sensor_dev_attr(devattr)->index;
974a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	struct w83627hf_data *data = dev_get_drvdata(dev);
975a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	unsigned long val = simple_strtoul(buf, NULL, 10);
976a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	u8 reg;
977a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
978a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	if (!val || (val > 3))	/* modes 1, 2 and 3 are supported */
979a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		return -EINVAL;
980a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	mutex_lock(&data->update_lock);
981a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	data->pwm_enable[nr] = val;
982a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]);
983a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]);
984a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr];
985a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg);
986a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	mutex_unlock(&data->update_lock);
987a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	return count;
988a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer}
989a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
990a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
991a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer						  store_pwm_enable, 0);
992a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
993a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer						  store_pwm_enable, 1);
994a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
995a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer						  store_pwm_enable, 2);
996a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
997a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic ssize_t
99807584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf)
9991550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
100007584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
10011550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	struct w83627hf_data *data = w83627hf_update_device(dev);
10021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83627hf)
10031550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return sprintf(buf, "%ld\n",
100407584c762541672e35735b52af031183ca17a5a2Jim Cromie			pwm_freq_from_reg_627hf(data->pwm_freq[nr]));
10051550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	else
10061550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return sprintf(buf, "%ld\n",
100707584c762541672e35735b52af031183ca17a5a2Jim Cromie			pwm_freq_from_reg(data->pwm_freq[nr]));
10081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
10091550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10101550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t
101107584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm_freq(struct device *dev, struct device_attribute *devattr,
101207584c762541672e35735b52af031183ca17a5a2Jim Cromie	       const char *buf, size_t count)
10131550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
101407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
10151550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	struct w83627hf_data *data = dev_get_drvdata(dev);
10161550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	static const u8 mask[]={0xF8, 0x8F};
10171550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u32 val;
10181550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10191550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	val = simple_strtoul(buf, NULL, 10);
10201550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10211550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	mutex_lock(&data->update_lock);
10221550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10231550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83627hf) {
102407584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val);
10251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		w83627hf_write_value(data, W83627HF_REG_PWM_FREQ,
102607584c762541672e35735b52af031183ca17a5a2Jim Cromie				(data->pwm_freq[nr] << (nr*4)) |
10271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				(w83627hf_read_value(data,
102807584c762541672e35735b52af031183ca17a5a2Jim Cromie				W83627HF_REG_PWM_FREQ) & mask[nr]));
10291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	} else {
103007584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm_freq[nr] = pwm_freq_to_reg(val);
103107584c762541672e35735b52af031183ca17a5a2Jim Cromie		w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr],
103207584c762541672e35735b52af031183ca17a5a2Jim Cromie				data->pwm_freq[nr]);
10331550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	}
10341550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10351550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	mutex_unlock(&data->update_lock);
10361550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return count;
10371550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
10381550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
103907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO|S_IWUSR,
104007584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 0);
104107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO|S_IWUSR,
104207584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 1);
104307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO|S_IWUSR,
104407584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 2);
10451550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10461550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t
104707584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_type(struct device *dev, struct device_attribute *devattr,
104807584c762541672e35735b52af031183ca17a5a2Jim Cromie	       char *buf)
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
105007584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
105207584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long) data->sens[nr]);
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
105607584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_type(struct device *dev, struct device_attribute *devattr,
105707584c762541672e35735b52af031183ca17a5a2Jim Cromie		const char *buf, size_t count)
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
105907584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
1060787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val, tmp;
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtoul(buf, NULL, 10);
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10659a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (val) {
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:		/* PII/Celeron diode */
1069787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1070787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
107107584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG1[nr]);
1072787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
1073787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG2,
107407584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG2[nr]);
107507584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:		/* 3904 */
1078787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1079787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
108007584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG1[nr]);
1081787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
1082787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG2,
108307584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp & ~BIT_SCFG2[nr]);
108407584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1086b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	case W83781D_DEFAULT_BETA:
1087b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
1088b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare			 "instead\n", W83781D_DEFAULT_BETA);
1089b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		/* fall through */
1090b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	case 4:		/* thermistor */
1091787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1092787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
109307584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp & ~BIT_SCFG1[nr]);
109407584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1097787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_err(dev,
1098b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		       "Invalid sensor type %ld; must be 1, 2, or 4\n",
1099b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		       (long) val);
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11039a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
110707584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_type(offset) \
110807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
110907584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_temp_type, store_temp_type, offset - 1);
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111107584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(1);
111207584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(2);
111307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(3);
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
111607584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_name(struct device *dev, struct device_attribute *devattr, char *buf)
1117787c72b107888805981faf148c8fea96a752d22eJean Delvare{
1118787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
1119787c72b107888805981faf148c8fea96a752d22eJean Delvare
1120787c72b107888805981faf148c8fea96a752d22eJean Delvare	return sprintf(buf, "%s\n", data->name);
1121787c72b107888805981faf148c8fea96a752d22eJean Delvare}
1122787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
1123787c72b107888805981faf148c8fea96a752d22eJean Delvare
1124787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_find(int sioaddr, unsigned short *addr,
1125787c72b107888805981faf148c8fea96a752d22eJean Delvare				struct w83627hf_sio_data *sio_data)
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1127d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	int err = -ENODEV;
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 val;
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1130787c72b107888805981faf148c8fea96a752d22eJean Delvare	static const __initdata char *names[] = {
1131787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83627HF",
1132787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83627THF",
1133787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83697HF",
1134787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83637HF",
1135787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83687THF",
1136787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1137787c72b107888805981faf148c8fea96a752d22eJean Delvare
1138c46c0e9188685c0276b4c0adf9fb7e903937e35bChristian Schulte	sio_data->sioaddr = sioaddr;
1139b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_enter(sio_data);
1140b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	val = force_id ? force_id : superio_inb(sio_data, DEVID);
1141787c72b107888805981faf148c8fea96a752d22eJean Delvare	switch (val) {
1142787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W627_DEVID:
1143787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83627hf;
1144787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1145787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W627THF_DEVID:
1146787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83627thf;
1147787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1148787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W697_DEVID:
1149787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83697hf;
1150787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1151787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W637_DEVID:
1152787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83637hf;
1153787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1154787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W687THF_DEVID:
1155787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83687thf;
1156787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1157e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare	case 0xff:	/* No device at all */
1158e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare		goto exit;
1159787c72b107888805981faf148c8fea96a752d22eJean Delvare	default:
1160e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare		pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val);
1161d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		goto exit;
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1164b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_select(sio_data, W83627HF_LD_HWM);
1165b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	val = (superio_inb(sio_data, WINB_BASE_REG) << 8) |
1166b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	       superio_inb(sio_data, WINB_BASE_REG + 1);
1167ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec	*addr = val & WINB_ALIGNMENT;
1168d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (*addr == 0) {
1169d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Base address not set, "
1170d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		       "skipping\n");
1171d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		goto exit;
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1174b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	val = superio_inb(sio_data, WINB_ACT_REG);
1175d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (!(val & 0x01)) {
1176d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n");
1177b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare		superio_outb(sio_data, WINB_ACT_REG, val | 0x01);
1178d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	}
1179d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
1180d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	err = 0;
1181787c72b107888805981faf148c8fea96a752d22eJean Delvare	pr_info(DRVNAME ": Found %s chip at %#x\n",
1182787c72b107888805981faf148c8fea96a752d22eJean Delvare		names[sio_data->type], *addr);
1183d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
1184d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare exit:
1185b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_exit(sio_data);
1186d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	return err;
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
118907584c762541672e35735b52af031183ca17a5a2Jim Cromie#define VIN_UNIT_ATTRS(_X_)	\
119007584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_input.dev_attr.attr,		\
119107584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_min.dev_attr.attr,		\
1192e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_max.dev_attr.attr,		\
1193e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_alarm.dev_attr.attr,		\
1194e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_beep.dev_attr.attr
119507584c762541672e35735b52af031183ca17a5a2Jim Cromie
119607584c762541672e35735b52af031183ca17a5a2Jim Cromie#define FAN_UNIT_ATTRS(_X_)	\
119707584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_input.dev_attr.attr,	\
119807584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_min.dev_attr.attr,		\
1199e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_div.dev_attr.attr,		\
1200e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_alarm.dev_attr.attr,	\
1201e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_beep.dev_attr.attr
120207584c762541672e35735b52af031183ca17a5a2Jim Cromie
120307584c762541672e35735b52af031183ca17a5a2Jim Cromie#define TEMP_UNIT_ATTRS(_X_)	\
120407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_input.dev_attr.attr,	\
120507584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_max.dev_attr.attr,		\
120607584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr,	\
1207e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_type.dev_attr.attr,	\
1208e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr,	\
1209e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_beep.dev_attr.attr
121007584c762541672e35735b52af031183ca17a5a2Jim Cromie
1211c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes[] = {
1212c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_input.attr,
1213c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_min.attr,
1214c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_max.attr,
1215e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in0_alarm.dev_attr.attr,
1216e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in0_beep.dev_attr.attr,
121707584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(2),
121807584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(3),
121907584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(4),
122007584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(7),
122107584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(8),
122207584c762541672e35735b52af031183ca17a5a2Jim Cromie
122307584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(1),
122407584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(2),
122507584c762541672e35735b52af031183ca17a5a2Jim Cromie
122607584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(1),
122707584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(2),
1228c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1229c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_alarms.attr,
12301c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	&sensor_dev_attr_beep_enable.dev_attr.attr,
1231c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_beep_mask.attr,
1232c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
123307584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm1.dev_attr.attr,
123407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm2.dev_attr.attr,
1235787c72b107888805981faf148c8fea96a752d22eJean Delvare	&dev_attr_name.attr,
1236c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
1237c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1238c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1239c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group = {
1240c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = w83627hf_attributes,
1241c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1242c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1243c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes_opt[] = {
124407584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(1),
124507584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(5),
124607584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(6),
124707584c762541672e35735b52af031183ca17a5a2Jim Cromie
124807584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(3),
124907584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(3),
125007584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm3.dev_attr.attr,
125107584c762541672e35735b52af031183ca17a5a2Jim Cromie
125207584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
125307584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
125407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm3_freq.dev_attr.attr,
1255a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1256a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
1257a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
1258a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
1259a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1260c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
1261c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1262c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1263c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group_opt = {
1264c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = w83627hf_attributes_opt,
1265c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1266c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1267787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627hf_probe(struct platform_device *pdev)
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1269787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct device *dev = &pdev->dev;
1270787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_sio_data *sio_data = dev->platform_data;
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data;
1272787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource *res;
12732ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	int err, i;
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1275787c72b107888805981faf148c8fea96a752d22eJean Delvare	static const char *names[] = {
1276787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83627hf",
1277787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83627thf",
1278787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83697hf",
1279787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83637hf",
1280787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83687thf",
1281787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1282787c72b107888805981faf148c8fea96a752d22eJean Delvare
1283787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1284787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) {
1285787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
1286787c72b107888805981faf148c8fea96a752d22eJean Delvare			(unsigned long)res->start,
1287787c72b107888805981faf148c8fea96a752d22eJean Delvare			(unsigned long)(res->start + WINB_REGION_SIZE - 1));
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EBUSY;
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR0;
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1292ba9c2e8d15da029ea3051c95e446b2d638ef02e2Deepak Saxena	if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR1;
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1296787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->addr = res->start;
1297787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->type = sio_data->type;
1298787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->name = names[sio_data->type];
12999a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->lock);
13009a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->update_lock);
1301787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_set_drvdata(pdev, data);
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the chip */
1304787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_init_device(pdev);
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* A few vars need to be filled upon startup */
13072ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	for (i = 0; i <= 2; i++)
13082ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie		data->fan_min[i] = w83627hf_read_value(
13092ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie					data, W83627HF_REG_FAN_MIN(i));
1310c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	w83627hf_update_fan_div(data);
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1312c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	/* Register common device attributes */
1313787c72b107888805981faf148c8fea96a752d22eJean Delvare	if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group)))
1314943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman		goto ERROR3;
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1316c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	/* Register chip-specific device attributes */
1317787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type == w83627hf || data->type == w83697hf)
131807584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
131907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_input.dev_attr))
132007584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
132107584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_min.dev_attr))
132207584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
132307584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_max.dev_attr))
132407584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1325e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in5_alarm.dev_attr))
1326e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1327e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in5_beep.dev_attr))
1328e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
132907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_input.dev_attr))
133007584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
133107584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_min.dev_attr))
133207584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
133307584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_max.dev_attr))
133407584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1335e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in6_alarm.dev_attr))
1336e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1337e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in6_beep.dev_attr))
1338e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
133907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm1_freq.dev_attr))
134007584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
134107584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm2_freq.dev_attr)))
1342c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1344787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type != w83697hf)
134507584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
134607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_input.dev_attr))
134707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
134807584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_min.dev_attr))
134907584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
135007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_max.dev_attr))
135107584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1352e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in1_alarm.dev_attr))
1353e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1354e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in1_beep.dev_attr))
1355e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
135607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_input.dev_attr))
135707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
135807584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_min.dev_attr))
135907584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
136007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_div.dev_attr))
136107584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1362e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_fan3_alarm.dev_attr))
1363e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1364e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_fan3_beep.dev_attr))
1365e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
136607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_input.dev_attr))
136707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
136807584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_max.dev_attr))
136907584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
137007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_max_hyst.dev_attr))
137107584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1372e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_temp3_alarm.dev_attr))
1373e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1374e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_temp3_beep.dev_attr))
1375e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
137607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_type.dev_attr)))
1377c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
1378c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1379787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type != w83697hf && data->vid != 0xff) {
13808a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare		/* Convert VID to voltage based on VRM */
13818a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare		data->vrm = vid_which_vrm();
13828a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare
1383787c72b107888805981faf148c8fea96a752d22eJean Delvare		if ((err = device_create_file(dev, &dev_attr_cpu0_vid))
1384787c72b107888805981faf148c8fea96a752d22eJean Delvare		 || (err = device_create_file(dev, &dev_attr_vrm)))
1385c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
13868a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare	}
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1388787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type == w83627thf || data->type == w83637hf
1389787c72b107888805981faf148c8fea96a752d22eJean Delvare	 || data->type == w83687thf)
139007584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
139107584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm3.dev_attr)))
1392c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman			goto ERROR4;
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13941550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83637hf || data->type == w83687thf)
139507584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
139607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm1_freq.dev_attr))
139707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
139807584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm2_freq.dev_attr))
139907584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
140007584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm3_freq.dev_attr)))
14011550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			goto ERROR4;
14021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
1403a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	if (data->type != w83627hf)
1404a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		if ((err = device_create_file(dev,
1405a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				&sensor_dev_attr_pwm1_enable.dev_attr))
1406a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		 || (err = device_create_file(dev,
1407a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				&sensor_dev_attr_pwm2_enable.dev_attr)))
1408a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer			goto ERROR4;
1409a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1410a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	if (data->type == w83627thf || data->type == w83637hf
1411a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	 || data->type == w83687thf)
1412a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		if ((err = device_create_file(dev,
1413a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				&sensor_dev_attr_pwm3_enable.dev_attr)))
1414a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer			goto ERROR4;
1415a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
14161beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	data->hwmon_dev = hwmon_device_register(dev);
14171beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	if (IS_ERR(data->hwmon_dev)) {
14181beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones		err = PTR_ERR(data->hwmon_dev);
1419c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman		goto ERROR4;
1420c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	}
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1424c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman      ERROR4:
1425787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&dev->kobj, &w83627hf_group);
1426787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&dev->kobj, &w83627hf_group_opt);
1427943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman      ERROR3:
142804a6217df28e3004ba4e76eb0a356a30f72c564fJean Delvare	platform_set_drvdata(pdev, NULL);
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(data);
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ERROR1:
1431787c72b107888805981faf148c8fea96a752d22eJean Delvare	release_region(res->start, WINB_REGION_SIZE);
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ERROR0:
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1436787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev)
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1438787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = platform_get_drvdata(pdev);
1439787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource *res;
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14411beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	hwmon_device_unregister(data->hwmon_dev);
1442943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
1443787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group);
1444787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt);
144504a6217df28e3004ba4e76eb0a356a30f72c564fJean Delvare	platform_set_drvdata(pdev, NULL);
1446943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	kfree(data);
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1448787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1449787c72b107888805981faf148c8fea96a752d22eJean Delvare	release_region(res->start, WINB_REGION_SIZE);
1450787c72b107888805981faf148c8fea96a752d22eJean Delvare
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1455d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare/* Registers 0x50-0x5f are banked */
1456d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvarestatic inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg)
1457d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare{
1458d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	if ((reg & 0x00f0) == 0x50) {
1459d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
1460d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET);
1461d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	}
1462d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare}
1463d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare
1464d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare/* Not strictly necessary, but play it safe for now */
1465d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvarestatic inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg)
1466d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare{
1467d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	if (reg & 0xff00) {
1468d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
1469d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
1470d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	}
1471d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare}
1472d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare
1473787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res, word_sized;
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14779a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	word_sized = (((reg & 0xff00) == 0x100)
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0xff00) == 0x200))
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  && (((reg & 0x00ff) == 0x50)
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x53)
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x55));
1483d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_set_bank(data, reg);
1484787c72b107888805981faf148c8fea96a752d22eJean Delvare	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
1485787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (word_sized) {
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p((reg & 0xff) + 1,
1488787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res =
1490787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (res << 8) + inb_p(data->addr +
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       W83781D_DATA_REG_OFFSET);
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1493d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_reset_bank(data, reg);
14949a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1498787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1500b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res = 0xff, sel;
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1503b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_enter(sio_data);
1504b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_select(sio_data, W83627HF_LD_GPIO5);
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure these GPIO pins are enabled */
1507b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	if (!(superio_inb(sio_data, W83627THF_GPIO5_EN) & (1<<3))) {
1508787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n");
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure the pins are configured for input
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   There must be at least five (VRM 9), and possibly 6 (VRM 10) */
1514b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	sel = superio_inb(sio_data, W83627THF_GPIO5_IOSR) & 0x3f;
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((sel & 0x1f) != 0x1f) {
1516787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"function\n");
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521787c72b107888805981faf148c8fea96a752d22eJean Delvare	dev_info(&pdev->dev, "Reading VID from GPIO5\n");
1522b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	res = superio_inb(sio_data, W83627THF_GPIO5_DR) & sel;
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
1525b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_exit(sio_data);
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1529787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83687thf_read_vid(struct platform_device *pdev)
1530c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare{
1531b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
1532c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	int res = 0xff;
1533c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1534b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_enter(sio_data);
1535b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_select(sio_data, W83627HF_LD_HWM);
1536c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1537c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	/* Make sure these GPIO pins are enabled */
1538b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	if (!(superio_inb(sio_data, W83687THF_VID_EN) & (1 << 2))) {
1539787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "VID disabled, no VID function\n");
1540c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		goto exit;
1541c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	}
1542c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1543c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	/* Make sure the pins are configured for input */
1544b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	if (!(superio_inb(sio_data, W83687THF_VID_CFG) & (1 << 4))) {
1545787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "VID configured as output, "
1546c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare			"no VID function\n");
1547c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		goto exit;
1548c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	}
1549c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1550b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	res = superio_inb(sio_data, W83687THF_VID_DATA) & 0x3f;
1551c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1552c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvareexit:
1553b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_exit(sio_data);
1554c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	return res;
1555c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare}
1556c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1557787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int word_sized;
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15619a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	word_sized = (((reg & 0xff00) == 0x100)
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0xff00) == 0x200))
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  && (((reg & 0x00ff) == 0x53)
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x55));
1566d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_set_bank(data, reg);
1567787c72b107888805981faf148c8fea96a752d22eJean Delvare	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (word_sized) {
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(value >> 8,
1570787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_DATA_REG_OFFSET);
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p((reg & 0xff) + 1,
1572787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb_p(value & 0xff,
1575787c72b107888805981faf148c8fea96a752d22eJean Delvare	       data->addr + W83781D_DATA_REG_OFFSET);
1576d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_reset_bank(data, reg);
15779a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void __devinit w83627hf_init_device(struct platform_device *pdev)
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1583787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = platform_get_drvdata(pdev);
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1585d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	enum chips type = data->type;
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 tmp;
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Minimize conflicts with other winbond i2c-only clients...  */
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* disable i2c subclients... how to disable main i2c client?? */
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* force i2c address to relatively uncommon address */
1591787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
1592787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read VID only once */
1595d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (type == w83627hf || type == w83637hf) {
1596787c72b107888805981faf148c8fea96a752d22eJean Delvare		int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
1597787c72b107888805981faf148c8fea96a752d22eJean Delvare		int hi = w83627hf_read_value(data, W83781D_REG_CHIPID);
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
1599d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	} else if (type == w83627thf) {
1600787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->vid = w83627thf_read_gpio5(pdev);
1601d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	} else if (type == w83687thf) {
1602787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->vid = w83687thf_read_vid(pdev);
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read VRM & OVT Config only once */
1606d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (type == w83627thf || type == w83637hf || type == w83687thf) {
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vrm_ovt =
1608787c72b107888805981faf148c8fea96a752d22eJean Delvare			w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG);
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1611787c72b107888805981faf148c8fea96a752d22eJean Delvare	tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 3; i++) {
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(tmp & BIT_SCFG1[i - 1])) {
1614b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare			data->sens[i - 1] = 4;
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (w83627hf_read_value
1617787c72b107888805981faf148c8fea96a752d22eJean Delvare			    (data,
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->sens[i - 1] = 1;
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->sens[i - 1] = 2;
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((type == w83697hf) && (i == 2))
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(init) {
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable temp2 */
1629df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie		tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tmp & 0x01) {
1631787c72b107888805981faf148c8fea96a752d22eJean Delvare			dev_warn(&pdev->dev, "Enabling temp2, readings "
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 "might not make sense\n");
1633df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp & 0xfe);
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable temp3 */
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (type != w83697hf) {
1639787c72b107888805981faf148c8fea96a752d22eJean Delvare			tmp = w83627hf_read_value(data,
1640df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie				W83627HF_REG_TEMP3_CONFIG);
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tmp & 0x01) {
1642787c72b107888805981faf148c8fea96a752d22eJean Delvare				dev_warn(&pdev->dev, "Enabling temp3, "
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 "readings might not make sense\n");
1644787c72b107888805981faf148c8fea96a752d22eJean Delvare				w83627hf_write_value(data,
1645df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start monitoring */
1651787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_CONFIG,
1652787c72b107888805981faf148c8fea96a752d22eJean Delvare			    (w83627hf_read_value(data,
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						W83781D_REG_CONFIG) & 0xf7)
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    | 0x01);
1655ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare
1656ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	/* Enable VBAT monitoring if needed */
1657ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	tmp = w83627hf_read_value(data, W83781D_REG_VBAT);
1658ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	if (!(tmp & 0x01))
1659ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare		w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01);
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1662c09c5184a26158da32801e89d5849d774605f0ddJean Delvarestatic void w83627hf_update_fan_div(struct w83627hf_data *data)
1663c09c5184a26158da32801e89d5849d774605f0ddJean Delvare{
1664c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	int reg;
1665c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
1666c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
1667c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[0] = (reg >> 4) & 0x03;
1668c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[1] = (reg >> 6) & 0x03;
1669c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	if (data->type != w83697hf) {
1670c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		data->fan_div[2] = (w83627hf_read_value(data,
1671c09c5184a26158da32801e89d5849d774605f0ddJean Delvare				       W83781D_REG_PIN) >> 6) & 0x03;
1672c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	}
1673c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	reg = w83627hf_read_value(data, W83781D_REG_VBAT);
1674c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[0] |= (reg >> 3) & 0x04;
1675c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[1] |= (reg >> 4) & 0x04;
1676c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	if (data->type != w83697hf)
1677c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		data->fan_div[2] |= (reg >> 5) & 0x04;
1678c09c5184a26158da32801e89d5849d774605f0ddJean Delvare}
1679c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev)
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1682787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
1683df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	int i, num_temps = (data->type == w83697hf) ? 2 : 3;
1684a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	int num_pwms = (data->type == w83697hf) ? 2 : 3;
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16869a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    || !data->valid) {
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 8; i++) {
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* skip missing sensors */
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (((data->type == w83697hf) && (i == 1)) ||
1693c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare			    ((data->type != w83627hf && data->type != w83697hf)
16944a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu			    && (i == 5 || i == 6)))
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in[i] =
1697787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data, W83781D_REG_IN(i));
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_min[i] =
1699787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_IN_MIN(i));
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_max[i] =
1702787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_IN_MAX(i));
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17052ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie		for (i = 0; i <= 2; i++) {
17062ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			data->fan[i] =
17072ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			    w83627hf_read_value(data, W83627HF_REG_FAN(i));
17082ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			data->fan_min[i] =
1709787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
17102ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie					       W83627HF_REG_FAN_MIN(i));
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
171207584c762541672e35735b52af031183ca17a5a2Jim Cromie		for (i = 0; i <= 2; i++) {
1713787c72b107888805981faf148c8fea96a752d22eJean Delvare			u8 tmp = w83627hf_read_value(data,
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				W836X7HF_REG_PWM(data->type, i));
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			/* bits 0-3 are reserved  in 627THF */
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			if (data->type == w83627thf)
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp &= 0xf0;
171807584c762541672e35735b52af031183ca17a5a2Jim Cromie			data->pwm[i] = tmp;
171907584c762541672e35735b52af031183ca17a5a2Jim Cromie			if (i == 1 &&
172007584c762541672e35735b52af031183ca17a5a2Jim Cromie			    (data->type == w83627hf || data->type == w83697hf))
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17231550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		if (data->type == w83627hf) {
17241550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				u8 tmp = w83627hf_read_value(data,
17251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez						W83627HF_REG_PWM_FREQ);
17261550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[0] = tmp & 0x07;
17271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[1] = (tmp >> 4) & 0x07;
17281550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		} else if (data->type != w83627thf) {
17291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			for (i = 1; i <= 3; i++) {
17301550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[i - 1] =
17311550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					w83627hf_read_value(data,
17321550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez						W83637HF_REG_PWM_FREQ[i - 1]);
17331550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				if (i == 2 && (data->type == w83697hf))
17341550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					break;
17351550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			}
17361550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		}
1737a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		if (data->type != w83627hf) {
1738a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer			for (i = 0; i < num_pwms; i++) {
1739a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				u8 tmp = w83627hf_read_value(data,
1740a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer					W83627THF_REG_PWM_ENABLE[i]);
1741a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				data->pwm_enable[i] =
1742a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer					((tmp >> W83627THF_PWM_ENABLE_SHIFT[i])
1743a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer					& 0x03) + 1;
1744a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer			}
1745a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		}
1746df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie		for (i = 0; i < num_temps; i++) {
1747df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp[i] = w83627hf_read_value(
1748df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp[i]);
1749df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp_max[i] = w83627hf_read_value(
1750df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp_over[i]);
1751df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp_max_hyst[i] = w83627hf_read_value(
1752df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp_hyst[i]);
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1755c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		w83627hf_update_fan_div(data);
1756c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarms =
1758787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_ALARM1) |
1759787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
1760787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
1761787c72b107888805981faf148c8fea96a752d22eJean Delvare		i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
17621c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		data->beep_mask = (i << 8) |
1763787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
1764787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_updated = jiffies;
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->valid = 1;
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17699a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return data;
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1774787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_device_add(unsigned short address,
1775787c72b107888805981faf148c8fea96a752d22eJean Delvare				      const struct w83627hf_sio_data *sio_data)
1776787c72b107888805981faf148c8fea96a752d22eJean Delvare{
1777787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource res = {
1778787c72b107888805981faf148c8fea96a752d22eJean Delvare		.start	= address + WINB_REGION_OFFSET,
1779787c72b107888805981faf148c8fea96a752d22eJean Delvare		.end	= address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1,
1780787c72b107888805981faf148c8fea96a752d22eJean Delvare		.name	= DRVNAME,
1781787c72b107888805981faf148c8fea96a752d22eJean Delvare		.flags	= IORESOURCE_IO,
1782787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1783787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
1784787c72b107888805981faf148c8fea96a752d22eJean Delvare
1785b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare	err = acpi_check_resource_conflict(&res);
1786b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare	if (err)
1787b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare		goto exit;
1788b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare
1789787c72b107888805981faf148c8fea96a752d22eJean Delvare	pdev = platform_device_alloc(DRVNAME, address);
1790787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (!pdev) {
1791787c72b107888805981faf148c8fea96a752d22eJean Delvare		err = -ENOMEM;
1792787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
1793787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit;
1794787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1795787c72b107888805981faf148c8fea96a752d22eJean Delvare
1796787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_device_add_resources(pdev, &res, 1);
1797787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err) {
1798787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device resource addition failed "
1799787c72b107888805981faf148c8fea96a752d22eJean Delvare		       "(%d)\n", err);
1800787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1801787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1802787c72b107888805981faf148c8fea96a752d22eJean Delvare
18032df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare	err = platform_device_add_data(pdev, sio_data,
18042df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare				       sizeof(struct w83627hf_sio_data));
18052df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare	if (err) {
1806787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
1807787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1808787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1809787c72b107888805981faf148c8fea96a752d22eJean Delvare
1810787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_device_add(pdev);
1811787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err) {
1812787c72b107888805981faf148c8fea96a752d22eJean Delvare		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
1813787c72b107888805981faf148c8fea96a752d22eJean Delvare		       err);
1814787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1815787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1816787c72b107888805981faf148c8fea96a752d22eJean Delvare
1817787c72b107888805981faf148c8fea96a752d22eJean Delvare	return 0;
1818787c72b107888805981faf148c8fea96a752d22eJean Delvare
1819787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_device_put:
1820787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_device_put(pdev);
1821787c72b107888805981faf148c8fea96a752d22eJean Delvareexit:
1822787c72b107888805981faf148c8fea96a752d22eJean Delvare	return err;
1823787c72b107888805981faf148c8fea96a752d22eJean Delvare}
1824787c72b107888805981faf148c8fea96a752d22eJean Delvare
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sensors_w83627hf_init(void)
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1827787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
1828787c72b107888805981faf148c8fea96a752d22eJean Delvare	unsigned short address;
1829787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_sio_data sio_data;
1830787c72b107888805981faf148c8fea96a752d22eJean Delvare
1831787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (w83627hf_find(0x2e, &address, &sio_data)
1832787c72b107888805981faf148c8fea96a752d22eJean Delvare	 && w83627hf_find(0x4e, &address, &sio_data))
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1835787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_driver_register(&w83627hf_driver);
1836787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err)
1837787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit;
1838787c72b107888805981faf148c8fea96a752d22eJean Delvare
1839787c72b107888805981faf148c8fea96a752d22eJean Delvare	/* Sets global pdev as a side effect */
1840787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = w83627hf_device_add(address, &sio_data);
1841787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err)
1842787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_driver;
1843787c72b107888805981faf148c8fea96a752d22eJean Delvare
1844787c72b107888805981faf148c8fea96a752d22eJean Delvare	return 0;
1845787c72b107888805981faf148c8fea96a752d22eJean Delvare
1846787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_driver:
1847787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_driver_unregister(&w83627hf_driver);
1848787c72b107888805981faf148c8fea96a752d22eJean Delvareexit:
1849787c72b107888805981faf148c8fea96a752d22eJean Delvare	return err;
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sensors_w83627hf_exit(void)
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1854787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_device_unregister(pdev);
1855787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_driver_unregister(&w83627hf_driver);
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      "Philip Edelbrock <phil@netroedge.com>, "
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      "and Mark Studebaker <mdsxyz123@yahoo.com>");
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("W83627HF driver");
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sensors_w83627hf_init);
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sensors_w83627hf_exit);
1866