w83627hf.c revision 64f503076f9921fc714a2c79fb0fa520869d2c08
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * w83627hf.c - Part of lm_sensors, Linux kernel modules for hardware
327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck *		monitoring
427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * Copyright (c) 1998 - 2003  Frodo Looijaard <frodol@dds.nl>,
527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck *			      Philip Edelbrock <phil@netroedge.com>,
627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck *			      and Mark Studebaker <mdsxyz123@yahoo.com>
727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org>
827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * Copyright (c) 2007  Jean Delvare <khali@linux-fr.org>
927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck *
1027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * This program is free software; you can redistribute it and/or modify
1127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * it under the terms of the GNU General Public License as published by
1227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * the Free Software Foundation; either version 2 of the License, or
1327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * (at your option) any later version.
1427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck *
1527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * This program is distributed in the hope that it will be useful,
1627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of
1727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * GNU General Public License for more details.
1927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck *
2027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * You should have received a copy of the GNU General Public License
2127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * along with this program; if not, write to the Free Software
2227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck */
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * Supports following chips:
2727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck *
2827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
2927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * w83627hf	9	3	2	3	0x20	0x5ca3	no	yes(LPC)
3027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * w83627thf	7	3	3	3	0x90	0x5ca3	no	yes(LPC)
3127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * w83637hf	7	3	3	3	0x80	0x5ca3	no	yes(LPC)
3227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * w83687thf	7	3	3	3	0x90	0x5ca3	no	yes(LPC)
3327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * w83697hf	8	2	2	2	0x60	0x5ca3	no	yes(LPC)
3427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck *
3527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * For other winbond chips, and for i2c support in the above chips,
3627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * use w83781d.c.
3727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck *
3827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * Note: automatic ("cruise") fan control for 697, 637 & 627thf not
3927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * supported yet.
4027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck */
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4218de030f1dbaef0c13cf393899a298d978aa200fJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
4318de030f1dbaef0c13cf393899a298d978aa200fJoe Perches
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/jiffies.h>
48787c72b107888805981faf148c8fea96a752d22eJean Delvare#include <linux/platform_device.h>
49943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/hwmon.h>
5007584c762541672e35735b52af031183ca17a5a2Jim Cromie#include <linux/hwmon-sysfs.h>
51303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare#include <linux/hwmon-vid.h>
52943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/err.h>
539a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar#include <linux/mutex.h>
54d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare#include <linux/ioport.h>
55b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare#include <linux/acpi.h>
566055fae8aceee41471edfd1876e5617d16e028feH Hartley Sweeten#include <linux/io.h>
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "lm75.h"
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic struct platform_device *pdev;
60d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
61d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare#define DRVNAME "w83627hf"
62d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvareenum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
63d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
64b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvarestruct w83627hf_sio_data {
65b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	enum chips type;
66b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	int sioaddr;
67b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare};
68b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 force_i2c = 0x1f;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(force_i2c, byte, 0);
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(force_i2c,
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 "Initialize the i2c address of the sensors");
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7490ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool init = 1;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(init, bool, 0);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7867b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvarestatic unsigned short force_id;
7967b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvaremodule_param(force_id, ushort, 0);
8067b671bceb4a8340a30929e9642620d99ed5ad76Jean DelvareMODULE_PARM_DESC(force_id, "Override the detected device ID");
8167b671bceb4a8340a30929e9642620d99ed5ad76Jean Delvare
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* modified from kernel/include/traps.c */
8327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck#define DEV			0x07 /* Register: Logical device select */
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* logical device numbers for superio_select (below) */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_FDC		0x00
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_PRT		0x01
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_UART1	0x02
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_UART2	0x03
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_KBC		0x05
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_CIR		0x06 /* w83627hf only */
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GAME	0x07
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_MIDI	0x07
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO1	0x07
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO5	0x07 /* w83627thf only */
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO2	0x08
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO3	0x09
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_GPIO4	0x09 /* w83627thf only */
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_ACPI	0x0a
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_LD_HWM		0x0b
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck#define DEVID			0x20 /* Register: Device ID */
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_EN	0x30 /* w83627thf only */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_IOSR	0xf3 /* w83627thf only */
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627THF_GPIO5_DR	0xf4 /* w83627thf only */
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
108c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_EN	0x29 /* w83687thf only */
109c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_CFG	0xF0 /* w83687thf only */
110c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83687THF_VID_DATA	0xF1 /* w83687thf only */
111c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
113b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvaresuperio_outb(struct w83627hf_sio_data *sio, int reg, int val)
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
115b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(reg, sio->sioaddr);
116b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(val, sio->sioaddr + 1);
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
120b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvaresuperio_inb(struct w83627hf_sio_data *sio, int reg)
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
122b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(reg, sio->sioaddr);
123b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	return inb(sio->sioaddr + 1);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
127b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvaresuperio_select(struct w83627hf_sio_data *sio, int ld)
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
129b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(DEV, sio->sioaddr);
130b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(ld,  sio->sioaddr + 1);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
134b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvaresuperio_enter(struct w83627hf_sio_data *sio)
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
136b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(0x87, sio->sioaddr);
137b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(0x87, sio->sioaddr);
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
141b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvaresuperio_exit(struct w83627hf_sio_data *sio)
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
143b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	outb(0xAA, sio->sioaddr);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W627_DEVID 0x52
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W627THF_DEVID 0x82
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W697_DEVID 0x60
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W637_DEVID 0x70
150c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W687THF_DEVID 0x85
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINB_ACT_REG 0x30
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WINB_BASE_REG 0x60
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Constants specified below */
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
155ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec/* Alignment of the base address */
156ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_ALIGNMENT		~7
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
158ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec/* Offset & size of I/O region we are interested in */
159ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_REGION_OFFSET	5
160ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec#define WINB_REGION_SIZE	2
161ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec
162787c72b107888805981faf148c8fea96a752d22eJean Delvare/* Where are the sensors address/data registers relative to the region offset */
163787c72b107888805981faf148c8fea96a752d22eJean Delvare#define W83781D_ADDR_REG_OFFSET 0
164787c72b107888805981faf148c8fea96a752d22eJean Delvare#define W83781D_DATA_REG_OFFSET 1
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The W83781D registers */
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The W83782D registers for nr=7,8 are in bank 5 */
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x554 + (((nr) - 7) * 2)))
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x555 + (((nr) - 7) * 2)))
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_IN(nr)     ((nr < 7) ? (0x20 + (nr)) : \
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   (0x550 + (nr) - 7))
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1752ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie/* nr:0-2 for fans:1-3 */
1762ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie#define W83627HF_REG_FAN_MIN(nr)	(0x3b + (nr))
1772ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie#define W83627HF_REG_FAN(nr)		(0x28 + (nr))
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
179df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie#define W83627HF_REG_TEMP2_CONFIG 0x152
180df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie#define W83627HF_REG_TEMP3_CONFIG 0x252
181df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie/* these are zero-based, unlike config constants above */
182df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp[]		= { 0x27, 0x150, 0x250 };
183df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp_hyst[]	= { 0x3A, 0x153, 0x253 };
184df48ed804f44a040e990976b537efc1e133c74d8Jim Cromiestatic const u16 w83627hf_reg_temp_over[]	= { 0x39, 0x155, 0x255 };
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BANK 0x4E
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CONFIG 0x40
1894a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM1 0x459
1904a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM2 0x45A
1914a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu#define W83781D_REG_ALARM3 0x45B
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_CONFIG 0x4D
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS1 0x56
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS2 0x57
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_BEEP_INTS3 0x453
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_VID_FANDIV 0x47
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CHIPID 0x49
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_WCHIPID 0x58
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_CHIPMAN 0x4F
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_PIN 0x4B
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_VBAT 0x5D
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_REG_PWM1 0x5A
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83627HF_REG_PWM2 0x5B
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
210a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic const u8 W83627THF_REG_PWM_ENABLE[] = {
211a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	0x04,		/* FAN 1 mode */
212a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	0x04,		/* FAN 2 mode */
213a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	0x12,		/* FAN AUX mode */
214a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer};
215a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic const u8 W83627THF_PWM_ENABLE_SHIFT[] = { 2, 4, 1 };
216a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
217c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM1		0x01	/* 697HF/637HF/687THF too */
218c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM2		0x03	/* 697HF/637HF/687THF too */
219c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_PWM3		0x11	/* 637HF/687THF too */
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare#define W83627THF_REG_VRM_OVT_CFG 	0x18	/* 637HF/687THF too */
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 };
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                             W83627THF_REG_PWM3 };
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \
22707584c762541672e35735b52af031183ca17a5a2Jim Cromie				    regpwm_627hf[nr] : regpwm[nr])
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83627HF_REG_PWM_FREQ		0x5C	/* Only for the 627HF */
2301550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2311550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ1		0x00	/* 697HF/687THF too */
2321550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ2		0x02	/* 697HF/687THF too */
2331550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83637HF_REG_PWM_FREQ3		0x10	/* 687THF too */
2341550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2351550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic const u8 W83637HF_REG_PWM_FREQ[] = { W83637HF_REG_PWM_FREQ1,
2361550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					W83637HF_REG_PWM_FREQ2,
2371550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					W83637HF_REG_PWM_FREQ3 };
2381550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2391550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez#define W83627HF_BASE_PWM_FREQ	46870
2401550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_I2C_ADDR 0x48
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_I2C_SUBADDR 0x4A
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Sensor selection */
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_SCFG1 0x5D
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_REG_SCFG2 0x59
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W83781D_DEFAULT_BETA 3435
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck/*
25227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * Conversions. Limit checking is only done on the TO_REG
25327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * variants. Note that you should be a bit careful with which arguments
25427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * these macros are called: arguments may be evaluated more than once.
25527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * Fixing this is just not worth it.
25627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck */
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) + 8)/16),0,255))
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IN_FROM_REG(val) ((val) * 16)
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 FAN_TO_REG(long rpm, int div)
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rpm == 0)
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 255;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     254);
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_MIN (-128000)
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_MAX ( 127000)
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck/*
27327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * TEMP: 0.001C/bit (-128C to +127C)
27427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * REG: 1C/bit, two's complement
27527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck */
2765bfedac045082a97e20d47d876071279ef984d28Christian Hohnstaedtstatic u8 TEMP_TO_REG(long temp)
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ntemp += (ntemp<0 ? -500 : 500);
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return (u8)(ntemp / 1000);
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int TEMP_FROM_REG(u8 reg)
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return (s8)reg * 1000;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2921550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline unsigned long pwm_freq_from_reg_627hf(u8 reg)
2931550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
2941550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	unsigned long freq;
2951550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	freq = W83627HF_BASE_PWM_FREQ >> reg;
2961550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return freq;
2971550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
2981550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline u8 pwm_freq_to_reg_627hf(unsigned long val)
2991550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
3001550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u8 i;
30127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	/*
30227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	 * Only 5 dividers (1 2 4 8 16)
30327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	 * Search for the nearest available frequency
30427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	 */
3051550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	for (i = 0; i < 4; i++) {
3061550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		if (val > (((W83627HF_BASE_PWM_FREQ >> i) +
3071550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			    (W83627HF_BASE_PWM_FREQ >> (i+1))) / 2))
3081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			break;
3091550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	}
3101550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return i;
3111550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3121550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3131550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline unsigned long pwm_freq_from_reg(u8 reg)
3141550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
3151550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Clock bit 8 -> 180 kHz or 24 MHz */
3161550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	unsigned long clock = (reg & 0x80) ? 180000UL : 24000000UL;
3171550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3181550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	reg &= 0x7f;
3191550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* This should not happen but anyway... */
3201550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (reg == 0)
3211550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		reg++;
3227fe83ad877321f44c8141b8334bd2f6614deb739Frans Meulenbroeks	return clock / (reg << 8);
3231550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3241550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline u8 pwm_freq_to_reg(unsigned long val)
3251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
3261550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	/* Minimum divider value is 0x01 and maximum is 0x7F */
3271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val >= 93750)	/* The highest we can do */
3281550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return 0x01;
3291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val >= 720)	/* Use 24 MHz clock */
3307fe83ad877321f44c8141b8334bd2f6614deb739Frans Meulenbroeks		return 24000000UL / (val << 8);
3311550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (val < 6)		/* The lowest we can do */
3321550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return 0xFF;
3331550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	else			/* Use 180 kHz clock */
3347fe83ad877321f44c8141b8334bd2f6614deb739Frans Meulenbroeks		return 0x80 | (180000UL / (val << 8));
3351550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
3361550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
3371c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare#define BEEP_MASK_FROM_REG(val)		((val) & 0xff7fff)
3381c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare#define BEEP_MASK_TO_REG(val)		((val) & 0xff7fff)
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1 << (val))
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 DIV_TO_REG(long val)
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = SENSORS_LIMIT(val, 1, 128) >> 1;
346abc01922477104e8d72b494902aff37135c409e7Grant Coady	for (i = 0; i < 7; i++) {
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val == 0)
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val >>= 1;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3517fe83ad877321f44c8141b8334bd2f6614deb739Frans Meulenbroeks	return (u8)i;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck/*
35527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * For each registered chip, we need to keep some data in memory.
35627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * The structure is dynamically allocated.
35727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck */
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct w83627hf_data {
359787c72b107888805981faf148c8fea96a752d22eJean Delvare	unsigned short addr;
360787c72b107888805981faf148c8fea96a752d22eJean Delvare	const char *name;
3611beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	struct device *hwmon_dev;
3629a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex lock;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enum chips type;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3659a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex update_lock;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char valid;		/* !=0 if following fields are valid */
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_updated;	/* In jiffies */
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in[9];		/* Register value */
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_max[9];		/* Register value */
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_min[9];		/* Register value */
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan[3];		/* Register value */
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_min[3];		/* Register value */
374df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp[3];		/* Register value */
375df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp_max[3];	/* Register value */
376df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 temp_max_hyst[3];	/* Register value */
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_div[3];		/* Register encoding, shifted right */
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vid;			/* Register encoding, combined */
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 alarms;		/* Register encoding, combined */
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 beep_mask;		/* Register encoding, combined */
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 pwm[3];		/* Register value */
382a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	u8 pwm_enable[3];	/* 1 = manual
38327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck				 * 2 = thermal cruise (also called SmartFan I)
38427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck				 * 3 = fan speed cruise
38527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck				 */
3861550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	u8 pwm_freq[3];		/* Register value */
387b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	u16 sens[3];		/* 1 = pentium diode; 2 = 3904 diode;
38827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck				 * 4 = thermistor
38927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck				 */
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vrm;
391c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	u8 vrm_ovt;		/* Register value, 627THF/637HF/687THF only */
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
395787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_probe(struct platform_device *pdev);
396d0546128980c18748010c758903b02909e634830Jean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev);
397787c72b107888805981faf148c8fea96a752d22eJean Delvare
398787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
399787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
400c09c5184a26158da32801e89d5849d774605f0ddJean Delvarestatic void w83627hf_update_fan_div(struct w83627hf_data *data);
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev);
402787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void w83627hf_init_device(struct platform_device *pdev);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
404787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic struct platform_driver w83627hf_driver = {
405cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	.driver = {
406872188420997f7f7c1b968fd9bce6578e4c3d45fJean Delvare		.owner	= THIS_MODULE,
407d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		.name	= DRVNAME,
408cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	},
409787c72b107888805981faf148c8fea96a752d22eJean Delvare	.probe		= w83627hf_probe,
410787c72b107888805981faf148c8fea96a752d22eJean Delvare	.remove		= __devexit_p(w83627hf_remove),
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
41407584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
41507584c762541672e35735b52af031183ca17a5a2Jim Cromie{
41607584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
41707584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
41807584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in[nr]));
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
42007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
42107584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_min(struct device *dev, struct device_attribute *devattr, char *buf)
42207584c762541672e35735b52af031183ca17a5a2Jim Cromie{
42307584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
42407584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
42507584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_min[nr]));
42607584c762541672e35735b52af031183ca17a5a2Jim Cromie}
42707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
42807584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_max(struct device *dev, struct device_attribute *devattr, char *buf)
42907584c762541672e35735b52af031183ca17a5a2Jim Cromie{
43007584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
43107584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
43207584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_max[nr]));
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
43407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
43507584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_min(struct device *dev, struct device_attribute *devattr,
43607584c762541672e35735b52af031183ca17a5a2Jim Cromie	     const char *buf, size_t count)
43707584c762541672e35735b52af031183ca17a5a2Jim Cromie{
43807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
43907584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
44027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	long val;
44127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
44227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck
44327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtol(buf, 10, &val);
44427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
44527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44707584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
44807584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->in_min[nr] = IN_TO_REG(val);
44907584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]);
45007584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
45107584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
45207584c762541672e35735b52af031183ca17a5a2Jim Cromie}
45307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
45407584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_max(struct device *dev, struct device_attribute *devattr,
45507584c762541672e35735b52af031183ca17a5a2Jim Cromie	     const char *buf, size_t count)
45607584c762541672e35735b52af031183ca17a5a2Jim Cromie{
45707584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
45807584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
45927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	long val;
46027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
46127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck
46227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtol(buf, 10, &val);
46327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
46427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46607584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
46707584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->in_max[nr] = IN_TO_REG(val);
46807584c762541672e35735b52af031183ca17a5a2Jim Cromie	w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]);
46907584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
47007584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
47107584c762541672e35735b52af031183ca17a5a2Jim Cromie}
47207584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_vin_decl(offset) \
47307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
47407584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_input, NULL, offset);		\
47507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO|S_IWUSR,	\
47607584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_min, store_in_min, offset);	\
47707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO|S_IWUSR,	\
47807584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_in_max, store_in_max, offset);
47907584c762541672e35735b52af031183ca17a5a2Jim Cromie
48007584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(1);
48107584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(2);
48207584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(3);
48307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(4);
48407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(5);
48507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(6);
48607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(7);
48707584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(8);
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* use a different set of functions for in0 */
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long in0;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
495c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
496c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in0 = (long)((reg * 488 + 70000 + 50) / 100);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		in0 = (long)IN_FROM_REG(reg);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%ld\n", in0);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
507a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_0(struct device *dev, struct device_attribute *attr, char *buf)
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in[0]);
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
513a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_min0(struct device *dev, struct device_attribute *attr, char *buf)
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in_min[0]);
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
519a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *attr, char *buf)
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return show_in_0(data, buf, data->in_max[0]);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
525a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr,
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *buf, size_t count)
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
528787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
52927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	unsigned long val;
53027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &val);
53327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
53427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5369a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
539c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
540c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
5432723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu		data->in_min[0] =
5442723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
5452723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu					255);
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_min[0] = IN_TO_REG(val);
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
550787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]);
5519a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
555a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr,
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *buf, size_t count)
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
558787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
55927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	unsigned long val;
56027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &val);
56327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
56427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5669a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->vrm_ovt & 0x01) &&
569c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		(w83627thf == data->type || w83637hf == data->type
570c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		 || w83687thf == data->type))
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM9 calculation */
5732723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu		data->in_max[0] =
5742723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu			SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
5752723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu					255);
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* use VRM8 (standard) calculation */
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_max[0] = IN_TO_REG(val);
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
580787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]);
5819a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_input, S_IRUGO, show_regs_in_0, NULL);
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs_in_min0, store_regs_in_min0);
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs_in_max0, store_regs_in_max0);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
59207584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
59307584c762541672e35735b52af031183ca17a5a2Jim Cromie{
59407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
59507584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
59607584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan[nr],
59707584c762541672e35735b52af031183ca17a5a2Jim Cromie				(long)DIV_FROM_REG(data->fan_div[nr])));
59807584c762541672e35735b52af031183ca17a5a2Jim Cromie}
59907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
60007584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
60107584c762541672e35735b52af031183ca17a5a2Jim Cromie{
60207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
60307584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
60407584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan_min[nr],
60507584c762541672e35735b52af031183ca17a5a2Jim Cromie				(long)DIV_FROM_REG(data->fan_div[nr])));
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
60807584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_min(struct device *dev, struct device_attribute *devattr,
60907584c762541672e35735b52af031183ca17a5a2Jim Cromie	      const char *buf, size_t count)
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
61107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
612787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
61327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	unsigned long val;
61427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
61527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck
61627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &val);
61727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
61827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6209a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
62107584c762541672e35735b52af031183ca17a5a2Jim Cromie	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
6222ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
62307584c762541672e35735b52af031183ca17a5a2Jim Cromie			     data->fan_min[nr]);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6259a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
62807584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_fan_decl(offset)	\
62907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
63007584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_input, NULL, offset - 1);		\
63107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
63207584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_min, store_fan_min, offset - 1);
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
63407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(1);
63507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(2);
63607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(3);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
63807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
63907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp(struct device *dev, struct device_attribute *devattr, char *buf)
64007584c762541672e35735b52af031183ca17a5a2Jim Cromie{
64107584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
64207584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
643df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
644df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp[nr];
645df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
646df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
64907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
65007584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max(struct device *dev, struct device_attribute *devattr,
65107584c762541672e35735b52af031183ca17a5a2Jim Cromie	      char *buf)
65207584c762541672e35735b52af031183ca17a5a2Jim Cromie{
65307584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
65407584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
655df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
656df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp_max[nr];
657df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
658df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
66107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
66207584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
66307584c762541672e35735b52af031183ca17a5a2Jim Cromie		   char *buf)
66407584c762541672e35735b52af031183ca17a5a2Jim Cromie{
66507584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
66607584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = w83627hf_update_device(dev);
667df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie
668df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	u16 tmp = data->temp_max_hyst[nr];
669df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
670df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					  : (long) TEMP_FROM_REG(tmp));
67107584c762541672e35735b52af031183ca17a5a2Jim Cromie}
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
67307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
67407584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max(struct device *dev, struct device_attribute *devattr,
67507584c762541672e35735b52af031183ca17a5a2Jim Cromie	       const char *buf, size_t count)
67607584c762541672e35735b52af031183ca17a5a2Jim Cromie{
67707584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
67807584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
67927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	u16 tmp;
68027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	long val;
68127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
68327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtol(buf, 10, &val);
68427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
68527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
68627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck
68727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
68807584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
689df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	data->temp_max[nr] = tmp;
690df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
69107584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
69207584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
69307584c762541672e35735b52af031183ca17a5a2Jim Cromie}
69407584c762541672e35735b52af031183ca17a5a2Jim Cromie
69507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
69607584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
69707584c762541672e35735b52af031183ca17a5a2Jim Cromie		    const char *buf, size_t count)
69807584c762541672e35735b52af031183ca17a5a2Jim Cromie{
69907584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
70007584c762541672e35735b52af031183ca17a5a2Jim Cromie	struct w83627hf_data *data = dev_get_drvdata(dev);
70127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	u16 tmp;
70227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	long val;
70327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
70427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck
70527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtol(buf, 10, &val);
70627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
70727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
70807584c762541672e35735b52af031183ca17a5a2Jim Cromie
70927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
71007584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_lock(&data->update_lock);
711df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	data->temp_max_hyst[nr] = tmp;
712df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
71307584c762541672e35735b52af031183ca17a5a2Jim Cromie	mutex_unlock(&data->update_lock);
71407584c762541672e35735b52af031183ca17a5a2Jim Cromie	return count;
71507584c762541672e35735b52af031183ca17a5a2Jim Cromie}
71607584c762541672e35735b52af031183ca17a5a2Jim Cromie
71707584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_decl(offset) \
71807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
719df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp, NULL, offset - 1);			\
72007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR,	 	\
721df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp_max, store_temp_max, offset - 1);	\
72207584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR,	\
723df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			  show_temp_max_hyst, store_temp_max_hyst, offset - 1);
72407584c762541672e35735b52af031183ca17a5a2Jim Cromie
72507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(1);
72607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(2);
72707584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(3);
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
730a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
738a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
74090d6619a916062cb75a176aacb318d108758b4a5Jean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) data->vrm);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
744a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustore_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
746787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
74727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	unsigned long val;
74827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
75027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &val);
75127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
75227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->vrm = val;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
760a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) data->alarms);
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
767e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
768e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvareshow_alarm(struct device *dev, struct device_attribute *attr, char *buf)
769e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
770e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
771e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
772e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
773e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
774e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
775e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
776e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
777e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
778e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
779e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
780e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10);
781e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16);
782e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17);
783e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
784e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
785e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
786e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
787e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
788e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
789e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
7901c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic ssize_t
7911c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvareshow_beep_mask(struct device *dev, struct device_attribute *attr, char *buf)
7921c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare{
7931c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
7941c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	return sprintf(buf, "%ld\n",
7951c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		      (long)BEEP_MASK_FROM_REG(data->beep_mask));
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
7991c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestore_beep_mask(struct device *dev, struct device_attribute *attr,
8001c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		const char *buf, size_t count)
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
802787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
8031c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	unsigned long val;
80427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &val);
80727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
80827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8109a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8121c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	/* preserve beep enable */
8131c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	data->beep_mask = (data->beep_mask & 0x8000)
8141c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			| BEEP_MASK_TO_REG(val);
8151c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
8161c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    data->beep_mask & 0xff);
8171c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
8181c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    ((data->beep_mask) >> 16) & 0xff);
819787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
8201c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			    (data->beep_mask >> 8) & 0xff);
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8229a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8261c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
8271c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		   show_beep_mask, store_beep_mask);
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
830e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvareshow_beep(struct device *dev, struct device_attribute *attr, char *buf)
831e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
832e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = w83627hf_update_device(dev);
833e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
834e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
835e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
836e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
837e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
838e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestore_beep(struct device *dev, struct device_attribute *attr,
839e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		const char *buf, size_t count)
840e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{
841e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
842e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
843e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	u8 reg;
84427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	unsigned long bit;
84527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
84627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck
84727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &bit);
84827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
84927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
850e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
851e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bit & ~1)
852e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		return -EINVAL;
853e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
854e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	mutex_lock(&data->update_lock);
855e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bit)
856e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		data->beep_mask |= (1 << bitnr);
857e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	else
858e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		data->beep_mask &= ~(1 << bitnr);
859e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
860e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	if (bitnr < 8) {
861e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS1);
862e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
863e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << bitnr);
864e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
865e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << bitnr);
866e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, reg);
867e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	} else if (bitnr < 16) {
868e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
869e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
870e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << (bitnr - 8));
871e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
872e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << (bitnr - 8));
873e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, reg);
874e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	} else {
875e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS3);
876e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		if (bit)
877e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg |= (1 << (bitnr - 16));
878e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		else
879e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			reg &= ~(1 << (bitnr - 16));
880e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, reg);
881e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	}
882e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	mutex_unlock(&data->update_lock);
883e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
884e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	return count;
885e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare}
886e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
887e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
888e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 0);
889e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR,
890e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 1);
891e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR,
892e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 2);
893e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR,
894e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 3);
895e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR,
896e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 8);
897e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR,
898e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 9);
899e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR,
900e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 10);
901e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR,
902e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 16);
903e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR,
904e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 17);
905e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR,
906e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 6);
907e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR,
908e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 7);
909e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR,
910e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 11);
911e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
912e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 4);
913e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
914e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 5);
915e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR,
916e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare			show_beep, store_beep, 13);
9171c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
9181c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare			show_beep, store_beep, 15);
919e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare
920e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t
92107584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_div(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);
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n",
92607584c762541672e35735b52af031183ca17a5a2Jim Cromie		       (long) DIV_FROM_REG(data->fan_div[nr]));
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
92827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck/*
92927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * Note: we save and restore the fan minimum here, because its value is
93027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * determined in part by the fan divisor.  This follows the principle of
93127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * least surprise; the user doesn't expect the fan minimum to change just
93227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck * because the divisor changed.
93327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck */
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
93507584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_div(struct device *dev, struct device_attribute *devattr,
93607584c762541672e35735b52af031183ca17a5a2Jim Cromie	      const char *buf, size_t count)
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
93807584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
939787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long min;
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reg;
94227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	unsigned long val;
94327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
94427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck
94527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &val);
94627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
94727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9499a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Save fan_min */
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	min = FAN_FROM_REG(data->fan_min[nr],
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   DIV_FROM_REG(data->fan_div[nr]));
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_div[nr] = DIV_TO_REG(val);
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
957787c72b107888805981faf148c8fea96a752d22eJean Delvare	reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       & (nr==0 ? 0xcf : 0x3f))
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
960787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
962787c72b107888805981faf148c8fea96a752d22eJean Delvare	reg = (w83627hf_read_value(data, W83781D_REG_VBAT)
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       & ~(1 << (5 + nr)))
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    | ((data->fan_div[nr] & 0x04) << (3 + nr));
965787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_VBAT, reg);
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore fan_min */
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
9692ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]);
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9719a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
97507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO|S_IWUSR,
97607584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 0);
97707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO|S_IWUSR,
97807584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 1);
97907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO|S_IWUSR,
98007584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_fan_div, store_fan_div, 2);
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
98307584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
98507584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
98707584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long) data->pwm[nr]);
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
99107584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm(struct device *dev, struct device_attribute *devattr,
99207584c762541672e35735b52af031183ca17a5a2Jim Cromie	  const char *buf, size_t count)
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
99407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
995787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
99627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	unsigned long val;
99727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
99827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck
99927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &val);
100027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
100127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10039a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->type == w83627thf) {
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* bits 0-3 are reserved  in 627THF */
100707584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm[nr] = PWM_TO_REG(val) & 0xf0;
1008787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data,
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr),
101007584c762541672e35735b52af031183ca17a5a2Jim Cromie				     data->pwm[nr] |
1011787c72b107888805981faf148c8fea96a752d22eJean Delvare				     (w83627hf_read_value(data,
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
101407584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm[nr] = PWM_TO_REG(val);
1015787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data,
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     W836X7HF_REG_PWM(data->type, nr),
101707584c762541672e35735b52af031183ca17a5a2Jim Cromie				     data->pwm[nr]);
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10209a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
102407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0);
102507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1);
102607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2);
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
1029a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyershow_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf)
1030a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer{
1031a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	int nr = to_sensor_dev_attr(devattr)->index;
1032a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	struct w83627hf_data *data = w83627hf_update_device(dev);
1033a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	return sprintf(buf, "%d\n", data->pwm_enable[nr]);
1034a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer}
1035a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1036a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic ssize_t
1037a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstore_pwm_enable(struct device *dev, struct device_attribute *devattr,
1038a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	  const char *buf, size_t count)
1039a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer{
1040a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	int nr = to_sensor_dev_attr(devattr)->index;
1041a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	struct w83627hf_data *data = dev_get_drvdata(dev);
1042a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	u8 reg;
104327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	unsigned long val;
104427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
1045a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
104627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &val);
104727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
104827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
104927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck
105027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (!val || val > 3)	/* modes 1, 2 and 3 are supported */
1051a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		return -EINVAL;
1052a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	mutex_lock(&data->update_lock);
1053a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	data->pwm_enable[nr] = val;
1054a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]);
1055a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]);
1056a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr];
1057a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg);
1058a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	mutex_unlock(&data->update_lock);
1059a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	return count;
1060a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer}
1061a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1062a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
1063a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer						  store_pwm_enable, 0);
1064a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
1065a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer						  store_pwm_enable, 1);
1066a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
1067a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer						  store_pwm_enable, 2);
1068a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1069a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic ssize_t
107007584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf)
10711550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
107207584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
10731550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	struct w83627hf_data *data = w83627hf_update_device(dev);
10741550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83627hf)
10751550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return sprintf(buf, "%ld\n",
107607584c762541672e35735b52af031183ca17a5a2Jim Cromie			pwm_freq_from_reg_627hf(data->pwm_freq[nr]));
10771550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	else
10781550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		return sprintf(buf, "%ld\n",
107907584c762541672e35735b52af031183ca17a5a2Jim Cromie			pwm_freq_from_reg(data->pwm_freq[nr]));
10801550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
10811550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10821550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t
108307584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm_freq(struct device *dev, struct device_attribute *devattr,
108407584c762541672e35735b52af031183ca17a5a2Jim Cromie	       const char *buf, size_t count)
10851550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{
108607584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
10871550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	struct w83627hf_data *data = dev_get_drvdata(dev);
10881550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	static const u8 mask[]={0xF8, 0x8F};
108927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	unsigned long val;
109027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
10911550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
109227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &val);
109327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
109427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
10951550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10961550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	mutex_lock(&data->update_lock);
10971550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
10981550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83627hf) {
109907584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val);
11001550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		w83627hf_write_value(data, W83627HF_REG_PWM_FREQ,
110107584c762541672e35735b52af031183ca17a5a2Jim Cromie				(data->pwm_freq[nr] << (nr*4)) |
11021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				(w83627hf_read_value(data,
110307584c762541672e35735b52af031183ca17a5a2Jim Cromie				W83627HF_REG_PWM_FREQ) & mask[nr]));
11041550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	} else {
110507584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->pwm_freq[nr] = pwm_freq_to_reg(val);
110607584c762541672e35735b52af031183ca17a5a2Jim Cromie		w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr],
110707584c762541672e35735b52af031183ca17a5a2Jim Cromie				data->pwm_freq[nr]);
11081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	}
11091550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
11101550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	mutex_unlock(&data->update_lock);
11111550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	return count;
11121550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez}
11131550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
111407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO|S_IWUSR,
111507584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 0);
111607584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO|S_IWUSR,
111707584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 1);
111807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO|S_IWUSR,
111907584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_pwm_freq, store_pwm_freq, 2);
11201550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
11211550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t
112207584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_type(struct device *dev, struct device_attribute *devattr,
112307584c762541672e35735b52af031183ca17a5a2Jim Cromie	       char *buf)
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
112507584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data = w83627hf_update_device(dev);
112707584c762541672e35735b52af031183ca17a5a2Jim Cromie	return sprintf(buf, "%ld\n", (long) data->sens[nr]);
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
113107584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_type(struct device *dev, struct device_attribute *devattr,
113207584c762541672e35735b52af031183ca17a5a2Jim Cromie		const char *buf, size_t count)
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
113407584c762541672e35735b52af031183ca17a5a2Jim Cromie	int nr = to_sensor_dev_attr(devattr)->index;
1135787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
113627b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	unsigned long val;
113727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	u32 tmp;
113827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	int err;
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
114027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = kstrtoul(buf, 10, &val);
114127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
114227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		return err;
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11449a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (val) {
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:		/* PII/Celeron diode */
1148787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1149787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
115007584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG1[nr]);
1151787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
1152787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG2,
115307584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG2[nr]);
115407584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:		/* 3904 */
1157787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1158787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
115907584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp | BIT_SCFG1[nr]);
1160787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG2);
1161787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG2,
116207584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp & ~BIT_SCFG2[nr]);
116307584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1165b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	case W83781D_DEFAULT_BETA:
1166b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
1167b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare			 "instead\n", W83781D_DEFAULT_BETA);
1168b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		/* fall through */
1169b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare	case 4:		/* thermistor */
1170787c72b107888805981faf148c8fea96a752d22eJean Delvare		tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
1171787c72b107888805981faf148c8fea96a752d22eJean Delvare		w83627hf_write_value(data, W83781D_REG_SCFG1,
117207584c762541672e35735b52af031183ca17a5a2Jim Cromie				    tmp & ~BIT_SCFG1[nr]);
117307584c762541672e35735b52af031183ca17a5a2Jim Cromie		data->sens[nr] = val;
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1176787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_err(dev,
1177b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		       "Invalid sensor type %ld; must be 1, 2, or 4\n",
1178b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare		       (long) val);
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11829a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
118607584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_type(offset) \
118707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
118807584c762541672e35735b52af031183ca17a5a2Jim Cromie			  show_temp_type, store_temp_type, offset - 1);
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
119007584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(1);
119107584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(2);
119207584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(3);
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
119407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t
119507584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_name(struct device *dev, struct device_attribute *devattr, char *buf)
1196787c72b107888805981faf148c8fea96a752d22eJean Delvare{
1197787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
1198787c72b107888805981faf148c8fea96a752d22eJean Delvare
1199787c72b107888805981faf148c8fea96a752d22eJean Delvare	return sprintf(buf, "%s\n", data->name);
1200787c72b107888805981faf148c8fea96a752d22eJean Delvare}
1201787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
1202787c72b107888805981faf148c8fea96a752d22eJean Delvare
1203787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_find(int sioaddr, unsigned short *addr,
1204787c72b107888805981faf148c8fea96a752d22eJean Delvare				struct w83627hf_sio_data *sio_data)
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1206d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	int err = -ENODEV;
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 val;
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
120964f503076f9921fc714a2c79fb0fa520869d2c08Andi Kleen	static __initconst char *const names[] = {
1210787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83627HF",
1211787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83627THF",
1212787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83697HF",
1213787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83637HF",
1214787c72b107888805981faf148c8fea96a752d22eJean Delvare		"W83687THF",
1215787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1216787c72b107888805981faf148c8fea96a752d22eJean Delvare
1217c46c0e9188685c0276b4c0adf9fb7e903937e35bChristian Schulte	sio_data->sioaddr = sioaddr;
1218b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_enter(sio_data);
1219b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	val = force_id ? force_id : superio_inb(sio_data, DEVID);
1220787c72b107888805981faf148c8fea96a752d22eJean Delvare	switch (val) {
1221787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W627_DEVID:
1222787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83627hf;
1223787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1224787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W627THF_DEVID:
1225787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83627thf;
1226787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1227787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W697_DEVID:
1228787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83697hf;
1229787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1230787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W637_DEVID:
1231787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83637hf;
1232787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1233787c72b107888805981faf148c8fea96a752d22eJean Delvare	case W687THF_DEVID:
1234787c72b107888805981faf148c8fea96a752d22eJean Delvare		sio_data->type = w83687thf;
1235787c72b107888805981faf148c8fea96a752d22eJean Delvare		break;
1236e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare	case 0xff:	/* No device at all */
1237e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare		goto exit;
1238787c72b107888805981faf148c8fea96a752d22eJean Delvare	default:
1239e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare		pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val);
1240d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		goto exit;
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1243b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_select(sio_data, W83627HF_LD_HWM);
1244b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	val = (superio_inb(sio_data, WINB_BASE_REG) << 8) |
1245b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	       superio_inb(sio_data, WINB_BASE_REG + 1);
1246ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec	*addr = val & WINB_ALIGNMENT;
1247d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (*addr == 0) {
124818de030f1dbaef0c13cf393899a298d978aa200fJoe Perches		pr_warn("Base address not set, skipping\n");
1249d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare		goto exit;
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1252b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	val = superio_inb(sio_data, WINB_ACT_REG);
1253d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (!(val & 0x01)) {
125418de030f1dbaef0c13cf393899a298d978aa200fJoe Perches		pr_warn("Enabling HWM logical device\n");
1255b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare		superio_outb(sio_data, WINB_ACT_REG, val | 0x01);
1256d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	}
1257d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
1258d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	err = 0;
1259787c72b107888805981faf148c8fea96a752d22eJean Delvare	pr_info(DRVNAME ": Found %s chip at %#x\n",
1260787c72b107888805981faf148c8fea96a752d22eJean Delvare		names[sio_data->type], *addr);
1261d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare
1262d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare exit:
1263b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_exit(sio_data);
1264d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	return err;
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
126707584c762541672e35735b52af031183ca17a5a2Jim Cromie#define VIN_UNIT_ATTRS(_X_)	\
126807584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_input.dev_attr.attr,		\
126907584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_in##_X_##_min.dev_attr.attr,		\
1270e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_max.dev_attr.attr,		\
1271e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_alarm.dev_attr.attr,		\
1272e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in##_X_##_beep.dev_attr.attr
127307584c762541672e35735b52af031183ca17a5a2Jim Cromie
127407584c762541672e35735b52af031183ca17a5a2Jim Cromie#define FAN_UNIT_ATTRS(_X_)	\
127507584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_input.dev_attr.attr,	\
127607584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_fan##_X_##_min.dev_attr.attr,		\
1277e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_div.dev_attr.attr,		\
1278e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_alarm.dev_attr.attr,	\
1279e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_fan##_X_##_beep.dev_attr.attr
128007584c762541672e35735b52af031183ca17a5a2Jim Cromie
128107584c762541672e35735b52af031183ca17a5a2Jim Cromie#define TEMP_UNIT_ATTRS(_X_)	\
128207584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_input.dev_attr.attr,	\
128307584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_max.dev_attr.attr,		\
128407584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr,	\
1285e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_type.dev_attr.attr,	\
1286e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr,	\
1287e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_temp##_X_##_beep.dev_attr.attr
128807584c762541672e35735b52af031183ca17a5a2Jim Cromie
1289c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes[] = {
1290c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_input.attr,
1291c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_min.attr,
1292c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_in0_max.attr,
1293e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in0_alarm.dev_attr.attr,
1294e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare	&sensor_dev_attr_in0_beep.dev_attr.attr,
129507584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(2),
129607584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(3),
129707584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(4),
129807584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(7),
129907584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(8),
130007584c762541672e35735b52af031183ca17a5a2Jim Cromie
130107584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(1),
130207584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(2),
130307584c762541672e35735b52af031183ca17a5a2Jim Cromie
130407584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(1),
130507584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(2),
1306c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1307c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_alarms.attr,
13081c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare	&sensor_dev_attr_beep_enable.dev_attr.attr,
1309c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_beep_mask.attr,
1310c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
131107584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm1.dev_attr.attr,
131207584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm2.dev_attr.attr,
1313787c72b107888805981faf148c8fea96a752d22eJean Delvare	&dev_attr_name.attr,
1314c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
1315c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1316c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1317c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group = {
1318c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = w83627hf_attributes,
1319c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1320c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1321c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes_opt[] = {
132207584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(1),
132307584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(5),
132407584c762541672e35735b52af031183ca17a5a2Jim Cromie	VIN_UNIT_ATTRS(6),
132507584c762541672e35735b52af031183ca17a5a2Jim Cromie
132607584c762541672e35735b52af031183ca17a5a2Jim Cromie	FAN_UNIT_ATTRS(3),
132707584c762541672e35735b52af031183ca17a5a2Jim Cromie	TEMP_UNIT_ATTRS(3),
132807584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm3.dev_attr.attr,
132907584c762541672e35735b52af031183ca17a5a2Jim Cromie
133007584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
133107584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
133207584c762541672e35735b52af031183ca17a5a2Jim Cromie	&sensor_dev_attr_pwm3_freq.dev_attr.attr,
1333a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1334a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
1335a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
1336a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
1337a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1338c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
1339c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1340c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1341c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group_opt = {
1342c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = w83627hf_attributes_opt,
1343c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
1344c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1345787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627hf_probe(struct platform_device *pdev)
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1347787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct device *dev = &pdev->dev;
1348787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_sio_data *sio_data = dev->platform_data;
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct w83627hf_data *data;
1350787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource *res;
13512ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	int err, i;
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1353787c72b107888805981faf148c8fea96a752d22eJean Delvare	static const char *names[] = {
1354787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83627hf",
1355787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83627thf",
1356787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83697hf",
1357787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83637hf",
1358787c72b107888805981faf148c8fea96a752d22eJean Delvare		"w83687thf",
1359787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1360787c72b107888805981faf148c8fea96a752d22eJean Delvare
1361787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
13620cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck	if (!devm_request_region(dev, res->start, WINB_REGION_SIZE, DRVNAME)) {
1363787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
1364787c72b107888805981faf148c8fea96a752d22eJean Delvare			(unsigned long)res->start,
1365787c72b107888805981faf148c8fea96a752d22eJean Delvare			(unsigned long)(res->start + WINB_REGION_SIZE - 1));
13660cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck		return -EBUSY;
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13690cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck	data = devm_kzalloc(dev, sizeof(struct w83627hf_data), GFP_KERNEL);
13700cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck	if (!data)
13710cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck		return -ENOMEM;
13720cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck
1373787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->addr = res->start;
1374787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->type = sio_data->type;
1375787c72b107888805981faf148c8fea96a752d22eJean Delvare	data->name = names[sio_data->type];
13769a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->lock);
13779a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->update_lock);
1378787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_set_drvdata(pdev, data);
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the chip */
1381787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_init_device(pdev);
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* A few vars need to be filled upon startup */
13842ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie	for (i = 0; i <= 2; i++)
13852ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie		data->fan_min[i] = w83627hf_read_value(
13862ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie					data, W83627HF_REG_FAN_MIN(i));
1387c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	w83627hf_update_fan_div(data);
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1389c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	/* Register common device attributes */
139027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	err = sysfs_create_group(&dev->kobj, &w83627hf_group);
139127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	if (err)
13920cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck		return err;
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1394c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	/* Register chip-specific device attributes */
1395787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type == w83627hf || data->type == w83697hf)
139607584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
139707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_input.dev_attr))
139807584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
139907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_min.dev_attr))
140007584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
140107584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in5_max.dev_attr))
140207584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1403e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in5_alarm.dev_attr))
1404e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1405e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in5_beep.dev_attr))
1406e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
140707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_input.dev_attr))
140807584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
140907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_min.dev_attr))
141007584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
141107584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in6_max.dev_attr))
141207584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1413e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in6_alarm.dev_attr))
1414e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1415e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in6_beep.dev_attr))
1416e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
141707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm1_freq.dev_attr))
141807584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
141907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm2_freq.dev_attr)))
14200cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck			goto error;
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1422787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type != w83697hf)
142307584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
142407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_input.dev_attr))
142507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
142607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_min.dev_attr))
142707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
142807584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_in1_max.dev_attr))
142907584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1430e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in1_alarm.dev_attr))
1431e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1432e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_in1_beep.dev_attr))
1433e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
143407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_input.dev_attr))
143507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
143607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_min.dev_attr))
143707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
143807584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_fan3_div.dev_attr))
143907584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1440e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_fan3_alarm.dev_attr))
1441e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1442e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_fan3_beep.dev_attr))
1443e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
144407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_input.dev_attr))
144507584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
144607584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_max.dev_attr))
144707584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
144807584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_max_hyst.dev_attr))
144907584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
1450e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_temp3_alarm.dev_attr))
1451e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
1452e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare				&sensor_dev_attr_temp3_beep.dev_attr))
1453e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare		 || (err = device_create_file(dev,
145407584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_temp3_type.dev_attr)))
14550cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck			goto error;
1456c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
1457787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type != w83697hf && data->vid != 0xff) {
14588a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare		/* Convert VID to voltage based on VRM */
14598a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare		data->vrm = vid_which_vrm();
14608a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare
1461787c72b107888805981faf148c8fea96a752d22eJean Delvare		if ((err = device_create_file(dev, &dev_attr_cpu0_vid))
1462787c72b107888805981faf148c8fea96a752d22eJean Delvare		 || (err = device_create_file(dev, &dev_attr_vrm)))
14630cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck			goto error;
14648a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare	}
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1466787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (data->type == w83627thf || data->type == w83637hf
146727b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	    || data->type == w83687thf) {
146827b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		err = device_create_file(dev, &sensor_dev_attr_pwm3.dev_attr);
146927b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		if (err)
14700cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck			goto error;
147127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	}
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14731550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez	if (data->type == w83637hf || data->type == w83687thf)
147407584c762541672e35735b52af031183ca17a5a2Jim Cromie		if ((err = device_create_file(dev,
147507584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm1_freq.dev_attr))
147607584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
147707584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm2_freq.dev_attr))
147807584c762541672e35735b52af031183ca17a5a2Jim Cromie		 || (err = device_create_file(dev,
147907584c762541672e35735b52af031183ca17a5a2Jim Cromie				&sensor_dev_attr_pwm3_freq.dev_attr)))
14800cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck			goto error;
14811550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez
1482a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	if (data->type != w83627hf)
1483a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		if ((err = device_create_file(dev,
1484a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				&sensor_dev_attr_pwm1_enable.dev_attr))
1485a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		 || (err = device_create_file(dev,
1486a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				&sensor_dev_attr_pwm2_enable.dev_attr)))
14870cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck			goto error;
1488a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
1489a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	if (data->type == w83627thf || data->type == w83637hf
149027b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	    || data->type == w83687thf) {
149127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		err = device_create_file(dev,
149227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck					 &sensor_dev_attr_pwm3_enable.dev_attr);
149327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck		if (err)
14940cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck			goto error;
149527b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	}
1496a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer
14971beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	data->hwmon_dev = hwmon_device_register(dev);
14981beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	if (IS_ERR(data->hwmon_dev)) {
14991beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones		err = PTR_ERR(data->hwmon_dev);
15000cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck		goto error;
1501c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	}
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15050cf46997218344e6223a7874ff9433b09c12dd60Guenter Roeck error:
1506787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&dev->kobj, &w83627hf_group);
1507787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&dev->kobj, &w83627hf_group_opt);
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev)
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1513787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = platform_get_drvdata(pdev);
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15151beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	hwmon_device_unregister(data->hwmon_dev);
1516943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
1517787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group);
1518787c72b107888805981faf148c8fea96a752d22eJean Delvare	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt);
1519787c72b107888805981faf148c8fea96a752d22eJean Delvare
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1524d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare/* Registers 0x50-0x5f are banked */
1525d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvarestatic inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg)
1526d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare{
1527d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	if ((reg & 0x00f0) == 0x50) {
1528d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
1529d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET);
1530d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	}
1531d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare}
1532d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare
1533d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare/* Not strictly necessary, but play it safe for now */
1534d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvarestatic inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg)
1535d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare{
1536d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	if (reg & 0xff00) {
1537d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
1538d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare		outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
1539d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	}
1540d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare}
1541d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare
1542787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res, word_sized;
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15469a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	word_sized = (((reg & 0xff00) == 0x100)
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0xff00) == 0x200))
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  && (((reg & 0x00ff) == 0x50)
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x53)
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x55));
1552d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_set_bank(data, reg);
1553787c72b107888805981faf148c8fea96a752d22eJean Delvare	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
1554787c72b107888805981faf148c8fea96a752d22eJean Delvare	res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (word_sized) {
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p((reg & 0xff) + 1,
1557787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res =
1559787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (res << 8) + inb_p(data->addr +
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       W83781D_DATA_REG_OFFSET);
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1562d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_reset_bank(data, reg);
15639a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1567787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1569b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res = 0xff, sel;
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1572b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_enter(sio_data);
1573b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_select(sio_data, W83627HF_LD_GPIO5);
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure these GPIO pins are enabled */
1576b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	if (!(superio_inb(sio_data, W83627THF_GPIO5_EN) & (1<<3))) {
1577787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n");
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
158127b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	/*
158227b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	 * Make sure the pins are configured for input
158327b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	 * There must be at least five (VRM 9), and possibly 6 (VRM 10)
158427b9de3c4ae302c51d99187047e6ebebb21fd29bGuenter Roeck	 */
1585b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	sel = superio_inb(sio_data, W83627THF_GPIO5_IOSR) & 0x3f;
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((sel & 0x1f) != 0x1f) {
1587787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"function\n");
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1592787c72b107888805981faf148c8fea96a752d22eJean Delvare	dev_info(&pdev->dev, "Reading VID from GPIO5\n");
1593b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	res = superio_inb(sio_data, W83627THF_GPIO5_DR) & sel;
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
1596b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_exit(sio_data);
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1600787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83687thf_read_vid(struct platform_device *pdev)
1601c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare{
1602b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
1603c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	int res = 0xff;
1604c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1605b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_enter(sio_data);
1606b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_select(sio_data, W83627HF_LD_HWM);
1607c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1608c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	/* Make sure these GPIO pins are enabled */
1609b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	if (!(superio_inb(sio_data, W83687THF_VID_EN) & (1 << 2))) {
1610787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "VID disabled, no VID function\n");
1611c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		goto exit;
1612c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	}
1613c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1614c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	/* Make sure the pins are configured for input */
1615b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	if (!(superio_inb(sio_data, W83687THF_VID_CFG) & (1 << 4))) {
1616787c72b107888805981faf148c8fea96a752d22eJean Delvare		dev_dbg(&pdev->dev, "VID configured as output, "
1617c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare			"no VID function\n");
1618c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare		goto exit;
1619c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	}
1620c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1621b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	res = superio_inb(sio_data, W83687THF_VID_DATA) & 0x3f;
1622c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1623c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvareexit:
1624b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare	superio_exit(sio_data);
1625c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare	return res;
1626c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare}
1627c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare
1628787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int word_sized;
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16329a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	word_sized = (((reg & 0xff00) == 0x100)
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0xff00) == 0x200))
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  && (((reg & 0x00ff) == 0x53)
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   || ((reg & 0x00ff) == 0x55));
1637d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_set_bank(data, reg);
1638787c72b107888805981faf148c8fea96a752d22eJean Delvare	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (word_sized) {
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(value >> 8,
1641787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_DATA_REG_OFFSET);
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p((reg & 0xff) + 1,
1643787c72b107888805981faf148c8fea96a752d22eJean Delvare		       data->addr + W83781D_ADDR_REG_OFFSET);
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb_p(value & 0xff,
1646787c72b107888805981faf148c8fea96a752d22eJean Delvare	       data->addr + W83781D_DATA_REG_OFFSET);
1647d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare	w83627hf_reset_bank(data, reg);
16489a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1652787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void __devinit w83627hf_init_device(struct platform_device *pdev)
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1654787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = platform_get_drvdata(pdev);
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1656d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	enum chips type = data->type;
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 tmp;
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Minimize conflicts with other winbond i2c-only clients...  */
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* disable i2c subclients... how to disable main i2c client?? */
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* force i2c address to relatively uncommon address */
1662787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
1663787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read VID only once */
1666d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (type == w83627hf || type == w83637hf) {
1667787c72b107888805981faf148c8fea96a752d22eJean Delvare		int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
1668787c72b107888805981faf148c8fea96a752d22eJean Delvare		int hi = w83627hf_read_value(data, W83781D_REG_CHIPID);
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
1670d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	} else if (type == w83627thf) {
1671787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->vid = w83627thf_read_gpio5(pdev);
1672d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	} else if (type == w83687thf) {
1673787c72b107888805981faf148c8fea96a752d22eJean Delvare		data->vid = w83687thf_read_vid(pdev);
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read VRM & OVT Config only once */
1677d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare	if (type == w83627thf || type == w83637hf || type == w83687thf) {
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vrm_ovt =
1679787c72b107888805981faf148c8fea96a752d22eJean Delvare			w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG);
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1682787c72b107888805981faf148c8fea96a752d22eJean Delvare	tmp = w83627hf_read_value(data, W83781D_REG_SCFG1);
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i <= 3; i++) {
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(tmp & BIT_SCFG1[i - 1])) {
1685b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare			data->sens[i - 1] = 4;
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (w83627hf_read_value
1688787c72b107888805981faf148c8fea96a752d22eJean Delvare			    (data,
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->sens[i - 1] = 1;
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->sens[i - 1] = 2;
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((type == w83697hf) && (i == 2))
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(init) {
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable temp2 */
1700df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie		tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tmp & 0x01) {
1702787c72b107888805981faf148c8fea96a752d22eJean Delvare			dev_warn(&pdev->dev, "Enabling temp2, readings "
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 "might not make sense\n");
1704df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp & 0xfe);
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable temp3 */
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (type != w83697hf) {
1710787c72b107888805981faf148c8fea96a752d22eJean Delvare			tmp = w83627hf_read_value(data,
1711df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie				W83627HF_REG_TEMP3_CONFIG);
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tmp & 0x01) {
1713787c72b107888805981faf148c8fea96a752d22eJean Delvare				dev_warn(&pdev->dev, "Enabling temp3, "
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 "readings might not make sense\n");
1715787c72b107888805981faf148c8fea96a752d22eJean Delvare				w83627hf_write_value(data,
1716df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie					W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start monitoring */
1722787c72b107888805981faf148c8fea96a752d22eJean Delvare	w83627hf_write_value(data, W83781D_REG_CONFIG,
1723787c72b107888805981faf148c8fea96a752d22eJean Delvare			    (w83627hf_read_value(data,
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						W83781D_REG_CONFIG) & 0xf7)
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    | 0x01);
1726ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare
1727ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	/* Enable VBAT monitoring if needed */
1728ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	tmp = w83627hf_read_value(data, W83781D_REG_VBAT);
1729ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare	if (!(tmp & 0x01))
1730ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare		w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01);
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1733c09c5184a26158da32801e89d5849d774605f0ddJean Delvarestatic void w83627hf_update_fan_div(struct w83627hf_data *data)
1734c09c5184a26158da32801e89d5849d774605f0ddJean Delvare{
1735c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	int reg;
1736c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
1737c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
1738c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[0] = (reg >> 4) & 0x03;
1739c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[1] = (reg >> 6) & 0x03;
1740c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	if (data->type != w83697hf) {
1741c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		data->fan_div[2] = (w83627hf_read_value(data,
1742c09c5184a26158da32801e89d5849d774605f0ddJean Delvare				       W83781D_REG_PIN) >> 6) & 0x03;
1743c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	}
1744c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	reg = w83627hf_read_value(data, W83781D_REG_VBAT);
1745c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[0] |= (reg >> 3) & 0x04;
1746c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	data->fan_div[1] |= (reg >> 4) & 0x04;
1747c09c5184a26158da32801e89d5849d774605f0ddJean Delvare	if (data->type != w83697hf)
1748c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		data->fan_div[2] |= (reg >> 5) & 0x04;
1749c09c5184a26158da32801e89d5849d774605f0ddJean Delvare}
1750c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev)
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1753787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_data *data = dev_get_drvdata(dev);
1754df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie	int i, num_temps = (data->type == w83697hf) ? 2 : 3;
1755a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer	int num_pwms = (data->type == w83697hf) ? 2 : 3;
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17579a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    || !data->valid) {
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 8; i++) {
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* skip missing sensors */
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (((data->type == w83697hf) && (i == 1)) ||
1764c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare			    ((data->type != w83627hf && data->type != w83697hf)
17654a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu			    && (i == 5 || i == 6)))
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in[i] =
1768787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data, W83781D_REG_IN(i));
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_min[i] =
1770787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_IN_MIN(i));
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_max[i] =
1773787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       W83781D_REG_IN_MAX(i));
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17762ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie		for (i = 0; i <= 2; i++) {
17772ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			data->fan[i] =
17782ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			    w83627hf_read_value(data, W83627HF_REG_FAN(i));
17792ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie			data->fan_min[i] =
1780787c72b107888805981faf148c8fea96a752d22eJean Delvare			    w83627hf_read_value(data,
17812ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie					       W83627HF_REG_FAN_MIN(i));
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
178307584c762541672e35735b52af031183ca17a5a2Jim Cromie		for (i = 0; i <= 2; i++) {
1784787c72b107888805981faf148c8fea96a752d22eJean Delvare			u8 tmp = w83627hf_read_value(data,
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				W836X7HF_REG_PWM(data->type, i));
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			/* bits 0-3 are reserved  in 627THF */
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			if (data->type == w83627thf)
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp &= 0xf0;
178907584c762541672e35735b52af031183ca17a5a2Jim Cromie			data->pwm[i] = tmp;
179007584c762541672e35735b52af031183ca17a5a2Jim Cromie			if (i == 1 &&
179107584c762541672e35735b52af031183ca17a5a2Jim Cromie			    (data->type == w83627hf || data->type == w83697hf))
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17941550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		if (data->type == w83627hf) {
17951550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				u8 tmp = w83627hf_read_value(data,
17961550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez						W83627HF_REG_PWM_FREQ);
17971550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[0] = tmp & 0x07;
17981550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[1] = (tmp >> 4) & 0x07;
17991550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		} else if (data->type != w83627thf) {
18001550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			for (i = 1; i <= 3; i++) {
18011550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				data->pwm_freq[i - 1] =
18021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					w83627hf_read_value(data,
18031550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez						W83637HF_REG_PWM_FREQ[i - 1]);
18041550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez				if (i == 2 && (data->type == w83697hf))
18051550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez					break;
18061550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez			}
18071550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez		}
1808a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		if (data->type != w83627hf) {
1809a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer			for (i = 0; i < num_pwms; i++) {
1810a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				u8 tmp = w83627hf_read_value(data,
1811a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer					W83627THF_REG_PWM_ENABLE[i]);
1812a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer				data->pwm_enable[i] =
1813a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer					((tmp >> W83627THF_PWM_ENABLE_SHIFT[i])
1814a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer					& 0x03) + 1;
1815a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer			}
1816a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer		}
1817df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie		for (i = 0; i < num_temps; i++) {
1818df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp[i] = w83627hf_read_value(
1819df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp[i]);
1820df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp_max[i] = w83627hf_read_value(
1821df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp_over[i]);
1822df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie			data->temp_max_hyst[i] = w83627hf_read_value(
1823df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie						data, w83627hf_reg_temp_hyst[i]);
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1826c09c5184a26158da32801e89d5849d774605f0ddJean Delvare		w83627hf_update_fan_div(data);
1827c09c5184a26158da32801e89d5849d774605f0ddJean Delvare
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarms =
1829787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_ALARM1) |
1830787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
1831787c72b107888805981faf148c8fea96a752d22eJean Delvare		    (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
1832787c72b107888805981faf148c8fea96a752d22eJean Delvare		i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
18331c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare		data->beep_mask = (i << 8) |
1834787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
1835787c72b107888805981faf148c8fea96a752d22eJean Delvare		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_updated = jiffies;
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->valid = 1;
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18409a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return data;
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1845787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_device_add(unsigned short address,
1846787c72b107888805981faf148c8fea96a752d22eJean Delvare				      const struct w83627hf_sio_data *sio_data)
1847787c72b107888805981faf148c8fea96a752d22eJean Delvare{
1848787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct resource res = {
1849787c72b107888805981faf148c8fea96a752d22eJean Delvare		.start	= address + WINB_REGION_OFFSET,
1850787c72b107888805981faf148c8fea96a752d22eJean Delvare		.end	= address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1,
1851787c72b107888805981faf148c8fea96a752d22eJean Delvare		.name	= DRVNAME,
1852787c72b107888805981faf148c8fea96a752d22eJean Delvare		.flags	= IORESOURCE_IO,
1853787c72b107888805981faf148c8fea96a752d22eJean Delvare	};
1854787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
1855787c72b107888805981faf148c8fea96a752d22eJean Delvare
1856b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare	err = acpi_check_resource_conflict(&res);
1857b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare	if (err)
1858b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare		goto exit;
1859b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare
1860787c72b107888805981faf148c8fea96a752d22eJean Delvare	pdev = platform_device_alloc(DRVNAME, address);
1861787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (!pdev) {
1862787c72b107888805981faf148c8fea96a752d22eJean Delvare		err = -ENOMEM;
186318de030f1dbaef0c13cf393899a298d978aa200fJoe Perches		pr_err("Device allocation failed\n");
1864787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit;
1865787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1866787c72b107888805981faf148c8fea96a752d22eJean Delvare
1867787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_device_add_resources(pdev, &res, 1);
1868787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err) {
186918de030f1dbaef0c13cf393899a298d978aa200fJoe Perches		pr_err("Device resource addition failed (%d)\n", err);
1870787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1871787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1872787c72b107888805981faf148c8fea96a752d22eJean Delvare
18732df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare	err = platform_device_add_data(pdev, sio_data,
18742df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare				       sizeof(struct w83627hf_sio_data));
18752df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare	if (err) {
187618de030f1dbaef0c13cf393899a298d978aa200fJoe Perches		pr_err("Platform data allocation failed\n");
1877787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1878787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1879787c72b107888805981faf148c8fea96a752d22eJean Delvare
1880787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_device_add(pdev);
1881787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err) {
188218de030f1dbaef0c13cf393899a298d978aa200fJoe Perches		pr_err("Device addition failed (%d)\n", err);
1883787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_device_put;
1884787c72b107888805981faf148c8fea96a752d22eJean Delvare	}
1885787c72b107888805981faf148c8fea96a752d22eJean Delvare
1886787c72b107888805981faf148c8fea96a752d22eJean Delvare	return 0;
1887787c72b107888805981faf148c8fea96a752d22eJean Delvare
1888787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_device_put:
1889787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_device_put(pdev);
1890787c72b107888805981faf148c8fea96a752d22eJean Delvareexit:
1891787c72b107888805981faf148c8fea96a752d22eJean Delvare	return err;
1892787c72b107888805981faf148c8fea96a752d22eJean Delvare}
1893787c72b107888805981faf148c8fea96a752d22eJean Delvare
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sensors_w83627hf_init(void)
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1896787c72b107888805981faf148c8fea96a752d22eJean Delvare	int err;
1897787c72b107888805981faf148c8fea96a752d22eJean Delvare	unsigned short address;
1898787c72b107888805981faf148c8fea96a752d22eJean Delvare	struct w83627hf_sio_data sio_data;
1899787c72b107888805981faf148c8fea96a752d22eJean Delvare
1900787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (w83627hf_find(0x2e, &address, &sio_data)
1901787c72b107888805981faf148c8fea96a752d22eJean Delvare	 && w83627hf_find(0x4e, &address, &sio_data))
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1904787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = platform_driver_register(&w83627hf_driver);
1905787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err)
1906787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit;
1907787c72b107888805981faf148c8fea96a752d22eJean Delvare
1908787c72b107888805981faf148c8fea96a752d22eJean Delvare	/* Sets global pdev as a side effect */
1909787c72b107888805981faf148c8fea96a752d22eJean Delvare	err = w83627hf_device_add(address, &sio_data);
1910787c72b107888805981faf148c8fea96a752d22eJean Delvare	if (err)
1911787c72b107888805981faf148c8fea96a752d22eJean Delvare		goto exit_driver;
1912787c72b107888805981faf148c8fea96a752d22eJean Delvare
1913787c72b107888805981faf148c8fea96a752d22eJean Delvare	return 0;
1914787c72b107888805981faf148c8fea96a752d22eJean Delvare
1915787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_driver:
1916787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_driver_unregister(&w83627hf_driver);
1917787c72b107888805981faf148c8fea96a752d22eJean Delvareexit:
1918787c72b107888805981faf148c8fea96a752d22eJean Delvare	return err;
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sensors_w83627hf_exit(void)
19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1923787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_device_unregister(pdev);
1924787c72b107888805981faf148c8fea96a752d22eJean Delvare	platform_driver_unregister(&w83627hf_driver);
19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      "Philip Edelbrock <phil@netroedge.com>, "
19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      "and Mark Studebaker <mdsxyz123@yahoo.com>");
19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("W83627HF driver");
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sensors_w83627hf_init);
19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sensors_w83627hf_exit);
1935