w83627hf.c revision 7fe83ad877321f44c8141b8334bd2f6614deb739
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds w83627hf.c - Part of lm_sensors, Linux kernel modules for hardware 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monitoring 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (c) 1998 - 2003 Frodo Looijaard <frodol@dds.nl>, 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Philip Edelbrock <phil@netroedge.com>, 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds and Mark Studebaker <mdsxyz123@yahoo.com> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org> 8787c72b107888805981faf148c8fea96a752d22eJean Delvare Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Supports following chips: 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) 32c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare w83687thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC) 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds For other winbond chips, and for i2c support in the above chips, 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds use w83781d.c. 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Note: automatic ("cruise") fan control for 697, 637 & 627thf not 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds supported yet. 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 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 */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#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 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#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 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Conversions. Limit checking is only done on the TO_REG 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds variants. Note that you should be a bit careful with which arguments 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds these macros are called: arguments may be evaluated more than once. 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Fixing this is just not worth it. */ 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255)) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IN_FROM_REG(val) ((val) * 16) 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 FAN_TO_REG(long rpm, int div) 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rpm == 0) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 255; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpm = SENSORS_LIMIT(rpm, 1, 1000000); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 254); 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_MIN (-128000) 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_MAX ( 127000) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TEMP: 0.001C/bit (-128C to +127C) 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REG: 1C/bit, two's complement */ 2725bfedac045082a97e20d47d876071279ef984d28Christian Hohnstaedtstatic u8 TEMP_TO_REG(long temp) 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ntemp += (ntemp<0 ? -500 : 500); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (u8)(ntemp / 1000); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int TEMP_FROM_REG(u8 reg) 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (s8)reg * 1000; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2881550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline unsigned long pwm_freq_from_reg_627hf(u8 reg) 2891550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{ 2901550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez unsigned long freq; 2911550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez freq = W83627HF_BASE_PWM_FREQ >> reg; 2921550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez return freq; 2931550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez} 2941550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline u8 pwm_freq_to_reg_627hf(unsigned long val) 2951550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{ 2961550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez u8 i; 2971550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez /* Only 5 dividers (1 2 4 8 16) 2981550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez Search for the nearest available frequency */ 2991550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez for (i = 0; i < 4; i++) { 3001550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez if (val > (((W83627HF_BASE_PWM_FREQ >> i) + 3011550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez (W83627HF_BASE_PWM_FREQ >> (i+1))) / 2)) 3021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez break; 3031550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez } 3041550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez return i; 3051550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez} 3061550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 3071550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline unsigned long pwm_freq_from_reg(u8 reg) 3081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{ 3091550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez /* Clock bit 8 -> 180 kHz or 24 MHz */ 3101550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez unsigned long clock = (reg & 0x80) ? 180000UL : 24000000UL; 3111550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 3121550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez reg &= 0x7f; 3131550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez /* This should not happen but anyway... */ 3141550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez if (reg == 0) 3151550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez reg++; 3167fe83ad877321f44c8141b8334bd2f6614deb739Frans Meulenbroeks return clock / (reg << 8); 3171550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez} 3181550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic inline u8 pwm_freq_to_reg(unsigned long val) 3191550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{ 3201550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez /* Minimum divider value is 0x01 and maximum is 0x7F */ 3211550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez if (val >= 93750) /* The highest we can do */ 3221550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez return 0x01; 3231550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez if (val >= 720) /* Use 24 MHz clock */ 3247fe83ad877321f44c8141b8334bd2f6614deb739Frans Meulenbroeks return 24000000UL / (val << 8); 3251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez if (val < 6) /* The lowest we can do */ 3261550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez return 0xFF; 3271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez else /* Use 180 kHz clock */ 3287fe83ad877321f44c8141b8334bd2f6614deb739Frans Meulenbroeks return 0x80 | (180000UL / (val << 8)); 3291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez} 3301550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 3311c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare#define BEEP_MASK_FROM_REG(val) ((val) & 0xff7fff) 3321c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare#define BEEP_MASK_TO_REG(val) ((val) & 0xff7fff) 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1 << (val)) 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 DIV_TO_REG(long val) 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = SENSORS_LIMIT(val, 1, 128) >> 1; 340abc01922477104e8d72b494902aff37135c409e7Grant Coady for (i = 0; i < 7; i++) { 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val == 0) 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val >>= 1; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3457fe83ad877321f44c8141b8334bd2f6614deb739Frans Meulenbroeks return (u8)i; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 348ed6bafbf6017d6a007b39de6b65ad3b8ae4c8aeeJean Delvare/* For each registered chip, we need to keep some data in memory. 349ed6bafbf6017d6a007b39de6b65ad3b8ae4c8aeeJean Delvare The structure is dynamically allocated. */ 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct w83627hf_data { 351787c72b107888805981faf148c8fea96a752d22eJean Delvare unsigned short addr; 352787c72b107888805981faf148c8fea96a752d22eJean Delvare const char *name; 3531beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones struct device *hwmon_dev; 3549a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar struct mutex lock; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum chips type; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3579a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar struct mutex update_lock; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char valid; /* !=0 if following fields are valid */ 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long last_updated; /* In jiffies */ 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 in[9]; /* Register value */ 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 in_max[9]; /* Register value */ 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 in_min[9]; /* Register value */ 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 fan[3]; /* Register value */ 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 fan_min[3]; /* Register value */ 366df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie u16 temp[3]; /* Register value */ 367df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie u16 temp_max[3]; /* Register value */ 368df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie u16 temp_max_hyst[3]; /* Register value */ 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 fan_div[3]; /* Register encoding, shifted right */ 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 vid; /* Register encoding, combined */ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 alarms; /* Register encoding, combined */ 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 beep_mask; /* Register encoding, combined */ 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 pwm[3]; /* Register value */ 374a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer u8 pwm_enable[3]; /* 1 = manual 375a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer 2 = thermal cruise (also called SmartFan I) 376a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer 3 = fan speed cruise */ 3771550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez u8 pwm_freq[3]; /* Register value */ 378b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare u16 sens[3]; /* 1 = pentium diode; 2 = 3904 diode; 379b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare 4 = thermistor */ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 vrm; 381c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 385787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_probe(struct platform_device *pdev); 386d0546128980c18748010c758903b02909e634830Jean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev); 387787c72b107888805981faf148c8fea96a752d22eJean Delvare 388787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg); 389787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value); 390c09c5184a26158da32801e89d5849d774605f0ddJean Delvarestatic void w83627hf_update_fan_div(struct w83627hf_data *data); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev); 392787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void w83627hf_init_device(struct platform_device *pdev); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 394787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic struct platform_driver w83627hf_driver = { 395cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard .driver = { 396872188420997f7f7c1b968fd9bce6578e4c3d45fJean Delvare .owner = THIS_MODULE, 397d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare .name = DRVNAME, 398cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard }, 399787c72b107888805981faf148c8fea96a752d22eJean Delvare .probe = w83627hf_probe, 400787c72b107888805981faf148c8fea96a752d22eJean Delvare .remove = __devexit_p(w83627hf_remove), 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 40407584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_input(struct device *dev, struct device_attribute *devattr, char *buf) 40507584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 40607584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 40707584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = w83627hf_update_device(dev); 40807584c762541672e35735b52af031183ca17a5a2Jim Cromie return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in[nr])); 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 41007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 41107584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_min(struct device *dev, struct device_attribute *devattr, char *buf) 41207584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 41307584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 41407584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = w83627hf_update_device(dev); 41507584c762541672e35735b52af031183ca17a5a2Jim Cromie return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_min[nr])); 41607584c762541672e35735b52af031183ca17a5a2Jim Cromie} 41707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 41807584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_in_max(struct device *dev, struct device_attribute *devattr, char *buf) 41907584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 42007584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 42107584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = w83627hf_update_device(dev); 42207584c762541672e35735b52af031183ca17a5a2Jim Cromie return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_max[nr])); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 42407584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 42507584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_min(struct device *dev, struct device_attribute *devattr, 42607584c762541672e35735b52af031183ca17a5a2Jim Cromie const char *buf, size_t count) 42707584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 42807584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 42907584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = dev_get_drvdata(dev); 43007584c762541672e35735b52af031183ca17a5a2Jim Cromie long val = simple_strtol(buf, NULL, 10); 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43207584c762541672e35735b52af031183ca17a5a2Jim Cromie mutex_lock(&data->update_lock); 43307584c762541672e35735b52af031183ca17a5a2Jim Cromie data->in_min[nr] = IN_TO_REG(val); 43407584c762541672e35735b52af031183ca17a5a2Jim Cromie w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]); 43507584c762541672e35735b52af031183ca17a5a2Jim Cromie mutex_unlock(&data->update_lock); 43607584c762541672e35735b52af031183ca17a5a2Jim Cromie return count; 43707584c762541672e35735b52af031183ca17a5a2Jim Cromie} 43807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 43907584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_in_max(struct device *dev, struct device_attribute *devattr, 44007584c762541672e35735b52af031183ca17a5a2Jim Cromie const char *buf, size_t count) 44107584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 44207584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 44307584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = dev_get_drvdata(dev); 44407584c762541672e35735b52af031183ca17a5a2Jim Cromie long val = simple_strtol(buf, NULL, 10); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44607584c762541672e35735b52af031183ca17a5a2Jim Cromie mutex_lock(&data->update_lock); 44707584c762541672e35735b52af031183ca17a5a2Jim Cromie data->in_max[nr] = IN_TO_REG(val); 44807584c762541672e35735b52af031183ca17a5a2Jim Cromie w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]); 44907584c762541672e35735b52af031183ca17a5a2Jim Cromie mutex_unlock(&data->update_lock); 45007584c762541672e35735b52af031183ca17a5a2Jim Cromie return count; 45107584c762541672e35735b52af031183ca17a5a2Jim Cromie} 45207584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_vin_decl(offset) \ 45307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ 45407584c762541672e35735b52af031183ca17a5a2Jim Cromie show_in_input, NULL, offset); \ 45507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO|S_IWUSR, \ 45607584c762541672e35735b52af031183ca17a5a2Jim Cromie show_in_min, store_in_min, offset); \ 45707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO|S_IWUSR, \ 45807584c762541672e35735b52af031183ca17a5a2Jim Cromie show_in_max, store_in_max, offset); 45907584c762541672e35735b52af031183ca17a5a2Jim Cromie 46007584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(1); 46107584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(2); 46207584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(3); 46307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(4); 46407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(5); 46507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(6); 46607584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(7); 46707584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_vin_decl(8); 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* use a different set of functions for in0 */ 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg) 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long in0; 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((data->vrm_ovt & 0x01) && 475c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare (w83627thf == data->type || w83637hf == data->type 476c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare || w83687thf == data->type)) 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* use VRM9 calculation */ 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in0 = (long)((reg * 488 + 70000 + 50) / 100); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* use VRM8 (standard) calculation */ 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in0 = (long)IN_FROM_REG(reg); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%ld\n", in0); 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 487a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_0(struct device *dev, struct device_attribute *attr, char *buf) 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct w83627hf_data *data = w83627hf_update_device(dev); 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return show_in_0(data, buf, data->in[0]); 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 493a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_min0(struct device *dev, struct device_attribute *attr, char *buf) 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct w83627hf_data *data = w83627hf_update_device(dev); 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return show_in_0(data, buf, data->in_min[0]); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 499a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *attr, char *buf) 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct w83627hf_data *data = w83627hf_update_device(dev); 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return show_in_0(data, buf, data->in_max[0]); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 505a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr, 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *buf, size_t count) 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 508787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 val; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = simple_strtoul(buf, NULL, 10); 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5139a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((data->vrm_ovt & 0x01) && 516c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare (w83627thf == data->type || w83637hf == data->type 517c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare || w83687thf == data->type)) 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* use VRM9 calculation */ 5202723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu data->in_min[0] = 5212723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0, 5222723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu 255); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* use VRM8 (standard) calculation */ 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_min[0] = IN_TO_REG(val); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 527787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]); 5289a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 532a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustatic ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr, 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *buf, size_t count) 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 535787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 val; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = simple_strtoul(buf, NULL, 10); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5409a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((data->vrm_ovt & 0x01) && 543c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare (w83627thf == data->type || w83637hf == data->type 544c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare || w83687thf == data->type)) 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* use VRM9 calculation */ 5472723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu data->in_max[0] = 5482723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0, 5492723ab91cb4019def10bdb01b0fecb85e6ac7884Yuan Mu 255); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* use VRM8 (standard) calculation */ 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_max[0] = IN_TO_REG(val); 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 554787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]); 5559a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_input, S_IRUGO, show_regs_in_0, NULL); 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_regs_in_min0, store_regs_in_min0); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_regs_in_max0, store_regs_in_max0); 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 56607584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_input(struct device *dev, struct device_attribute *devattr, char *buf) 56707584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 56807584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 56907584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = w83627hf_update_device(dev); 57007584c762541672e35735b52af031183ca17a5a2Jim Cromie return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan[nr], 57107584c762541672e35735b52af031183ca17a5a2Jim Cromie (long)DIV_FROM_REG(data->fan_div[nr]))); 57207584c762541672e35735b52af031183ca17a5a2Jim Cromie} 57307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 57407584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_min(struct device *dev, struct device_attribute *devattr, char *buf) 57507584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 57607584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 57707584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = w83627hf_update_device(dev); 57807584c762541672e35735b52af031183ca17a5a2Jim Cromie return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan_min[nr], 57907584c762541672e35735b52af031183ca17a5a2Jim Cromie (long)DIV_FROM_REG(data->fan_div[nr]))); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 58207584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_min(struct device *dev, struct device_attribute *devattr, 58307584c762541672e35735b52af031183ca17a5a2Jim Cromie const char *buf, size_t count) 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 58507584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 586787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 58707584c762541672e35735b52af031183ca17a5a2Jim Cromie u32 val = simple_strtoul(buf, NULL, 10); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5899a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 59007584c762541672e35735b52af031183ca17a5a2Jim Cromie data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); 5912ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), 59207584c762541672e35735b52af031183ca17a5a2Jim Cromie data->fan_min[nr]); 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5949a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 59707584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_fan_decl(offset) \ 59807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ 59907584c762541672e35735b52af031183ca17a5a2Jim Cromie show_fan_input, NULL, offset - 1); \ 60007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ 60107584c762541672e35735b52af031183ca17a5a2Jim Cromie show_fan_min, store_fan_min, offset - 1); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 60307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(1); 60407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(2); 60507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_fan_decl(3); 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 60707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 60807584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp(struct device *dev, struct device_attribute *devattr, char *buf) 60907584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 61007584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 61107584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = w83627hf_update_device(dev); 612df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie 613df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie u16 tmp = data->temp[nr]; 614df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) 615df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie : (long) TEMP_FROM_REG(tmp)); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 61907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max(struct device *dev, struct device_attribute *devattr, 62007584c762541672e35735b52af031183ca17a5a2Jim Cromie char *buf) 62107584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 62207584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 62307584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = w83627hf_update_device(dev); 624df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie 625df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie u16 tmp = data->temp_max[nr]; 626df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) 627df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie : (long) TEMP_FROM_REG(tmp)); 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 63007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 63107584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_max_hyst(struct device *dev, struct device_attribute *devattr, 63207584c762541672e35735b52af031183ca17a5a2Jim Cromie char *buf) 63307584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 63407584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 63507584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = w83627hf_update_device(dev); 636df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie 637df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie u16 tmp = data->temp_max_hyst[nr]; 638df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) 639df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie : (long) TEMP_FROM_REG(tmp)); 64007584c762541672e35735b52af031183ca17a5a2Jim Cromie} 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 64207584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 64307584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max(struct device *dev, struct device_attribute *devattr, 64407584c762541672e35735b52af031183ca17a5a2Jim Cromie const char *buf, size_t count) 64507584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 64607584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 64707584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = dev_get_drvdata(dev); 64807584c762541672e35735b52af031183ca17a5a2Jim Cromie long val = simple_strtol(buf, NULL, 10); 649df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val); 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 65107584c762541672e35735b52af031183ca17a5a2Jim Cromie mutex_lock(&data->update_lock); 652df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie data->temp_max[nr] = tmp; 653df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp); 65407584c762541672e35735b52af031183ca17a5a2Jim Cromie mutex_unlock(&data->update_lock); 65507584c762541672e35735b52af031183ca17a5a2Jim Cromie return count; 65607584c762541672e35735b52af031183ca17a5a2Jim Cromie} 65707584c762541672e35735b52af031183ca17a5a2Jim Cromie 65807584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 65907584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_max_hyst(struct device *dev, struct device_attribute *devattr, 66007584c762541672e35735b52af031183ca17a5a2Jim Cromie const char *buf, size_t count) 66107584c762541672e35735b52af031183ca17a5a2Jim Cromie{ 66207584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 66307584c762541672e35735b52af031183ca17a5a2Jim Cromie struct w83627hf_data *data = dev_get_drvdata(dev); 66407584c762541672e35735b52af031183ca17a5a2Jim Cromie long val = simple_strtol(buf, NULL, 10); 665df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val); 66607584c762541672e35735b52af031183ca17a5a2Jim Cromie 66707584c762541672e35735b52af031183ca17a5a2Jim Cromie mutex_lock(&data->update_lock); 668df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie data->temp_max_hyst[nr] = tmp; 669df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp); 67007584c762541672e35735b52af031183ca17a5a2Jim Cromie mutex_unlock(&data->update_lock); 67107584c762541672e35735b52af031183ca17a5a2Jim Cromie return count; 67207584c762541672e35735b52af031183ca17a5a2Jim Cromie} 67307584c762541672e35735b52af031183ca17a5a2Jim Cromie 67407584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_decl(offset) \ 67507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ 676df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie show_temp, NULL, offset - 1); \ 67707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR, \ 678df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie show_temp_max, store_temp_max, offset - 1); \ 67907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR, \ 680df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie show_temp_max_hyst, store_temp_max_hyst, offset - 1); 68107584c762541672e35735b52af031183ca17a5a2Jim Cromie 68207584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(1); 68307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(2); 68407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_decl(3); 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 687a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct w83627hf_data *data = w83627hf_update_device(dev); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 695a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 69790d6619a916062cb75a176aacb318d108758b4a5Jean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%ld\n", (long) data->vrm); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 701a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoustore_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 703787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 val; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = simple_strtoul(buf, NULL, 10); 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->vrm = val; 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 714a5099cfc2e82240b0a3e72ad79a5969d5af1a7dcYani Ioannoushow_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct w83627hf_data *data = w83627hf_update_device(dev); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%ld\n", (long) data->alarms); 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t 722e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvareshow_alarm(struct device *dev, struct device_attribute *attr, char *buf) 723e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{ 724e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare struct w83627hf_data *data = w83627hf_update_device(dev); 725e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 726e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); 727e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare} 728e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); 729e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); 730e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); 731e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); 732e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); 733e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); 734e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10); 735e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16); 736e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17); 737e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); 738e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); 739e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); 740e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); 741e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); 742e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13); 743e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare 7441c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic ssize_t 7451c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvareshow_beep_mask(struct device *dev, struct device_attribute *attr, char *buf) 7461c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare{ 7471c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare struct w83627hf_data *data = w83627hf_update_device(dev); 7481c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare return sprintf(buf, "%ld\n", 7491c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare (long)BEEP_MASK_FROM_REG(data->beep_mask)); 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 7531c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestore_beep_mask(struct device *dev, struct device_attribute *attr, 7541c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare const char *buf, size_t count) 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 756787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 7571c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare unsigned long val; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = simple_strtoul(buf, NULL, 10); 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7619a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7631c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare /* preserve beep enable */ 7641c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare data->beep_mask = (data->beep_mask & 0x8000) 7651c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare | BEEP_MASK_TO_REG(val); 7661c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, 7671c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare data->beep_mask & 0xff); 7681c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, 7691c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare ((data->beep_mask) >> 16) & 0xff); 770787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, 7711c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare (data->beep_mask >> 8) & 0xff); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7739a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7771c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, 7781c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare show_beep_mask, store_beep_mask); 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 781e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvareshow_beep(struct device *dev, struct device_attribute *attr, char *buf) 782e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{ 783e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare struct w83627hf_data *data = w83627hf_update_device(dev); 784e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 785e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); 786e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare} 787e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare 788e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t 789e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestore_beep(struct device *dev, struct device_attribute *attr, 790e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare const char *buf, size_t count) 791e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare{ 792e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 793e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 794e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare unsigned long bit; 795e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare u8 reg; 796e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare 797e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare bit = simple_strtoul(buf, NULL, 10); 798e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare if (bit & ~1) 799e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare return -EINVAL; 800e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare 801e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare mutex_lock(&data->update_lock); 802e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare if (bit) 803e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare data->beep_mask |= (1 << bitnr); 804e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare else 805e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare data->beep_mask &= ~(1 << bitnr); 806e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare 807e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare if (bitnr < 8) { 808e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS1); 809e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare if (bit) 810e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare reg |= (1 << bitnr); 811e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare else 812e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare reg &= ~(1 << bitnr); 813e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, reg); 814e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare } else if (bitnr < 16) { 815e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2); 816e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare if (bit) 817e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare reg |= (1 << (bitnr - 8)); 818e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare else 819e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare reg &= ~(1 << (bitnr - 8)); 820e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, reg); 821e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare } else { 822e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS3); 823e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare if (bit) 824e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare reg |= (1 << (bitnr - 16)); 825e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare else 826e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare reg &= ~(1 << (bitnr - 16)); 827e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, reg); 828e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare } 829e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare mutex_unlock(&data->update_lock); 830e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare 831e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare return count; 832e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare} 833e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare 834e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, 835e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 0); 836e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, 837e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 1); 838e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, 839e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 2); 840e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, 841e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 3); 842e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, 843e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 8); 844e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR, 845e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 9); 846e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR, 847e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 10); 848e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR, 849e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 16); 850e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR, 851e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 17); 852e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, 853e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 6); 854e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, 855e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 7); 856e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR, 857e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 11); 858e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, 859e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 4); 860e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, 861e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 5); 862e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR, 863e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare show_beep, store_beep, 13); 8641c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvarestatic SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, 8651c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare show_beep, store_beep, 15); 866e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare 867e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvarestatic ssize_t 86807584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 87007584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct w83627hf_data *data = w83627hf_update_device(dev); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%ld\n", 87307584c762541672e35735b52af031183ca17a5a2Jim Cromie (long) DIV_FROM_REG(data->fan_div[nr])); 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Note: we save and restore the fan minimum here, because its value is 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds determined in part by the fan divisor. This follows the principle of 877d6e05edc59ecd79e8badf440c0d295a979bdfa3eAndreas Mohr least surprise; the user doesn't expect the fan minimum to change just 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds because the divisor changed. */ 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 88007584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_fan_div(struct device *dev, struct device_attribute *devattr, 88107584c762541672e35735b52af031183ca17a5a2Jim Cromie const char *buf, size_t count) 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 88307584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 884787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long min; 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 reg; 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val = simple_strtoul(buf, NULL, 10); 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8899a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Save fan_min */ 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds min = FAN_FROM_REG(data->fan_min[nr], 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DIV_FROM_REG(data->fan_div[nr])); 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[nr] = DIV_TO_REG(val); 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 897787c72b107888805981faf148c8fea96a752d22eJean Delvare reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds & (nr==0 ? 0xcf : 0x3f)) 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); 900787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 902787c72b107888805981faf148c8fea96a752d22eJean Delvare reg = (w83627hf_read_value(data, W83781D_REG_VBAT) 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds & ~(1 << (5 + nr))) 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((data->fan_div[nr] & 0x04) << (3 + nr)); 905787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_VBAT, reg); 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Restore fan_min */ 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); 9092ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]); 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9119a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO|S_IWUSR, 91607584c762541672e35735b52af031183ca17a5a2Jim Cromie show_fan_div, store_fan_div, 0); 91707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO|S_IWUSR, 91807584c762541672e35735b52af031183ca17a5a2Jim Cromie show_fan_div, store_fan_div, 1); 91907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO|S_IWUSR, 92007584c762541672e35735b52af031183ca17a5a2Jim Cromie show_fan_div, store_fan_div, 2); 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 92307584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm(struct device *dev, struct device_attribute *devattr, char *buf) 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 92507584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct w83627hf_data *data = w83627hf_update_device(dev); 92707584c762541672e35735b52af031183ca17a5a2Jim Cromie return sprintf(buf, "%ld\n", (long) data->pwm[nr]); 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 93107584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm(struct device *dev, struct device_attribute *devattr, 93207584c762541672e35735b52af031183ca17a5a2Jim Cromie const char *buf, size_t count) 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 93407584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 935787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 93607584c762541672e35735b52af031183ca17a5a2Jim Cromie u32 val = simple_strtoul(buf, NULL, 10); 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9389a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->type == w83627thf) { 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* bits 0-3 are reserved in 627THF */ 94207584c762541672e35735b52af031183ca17a5a2Jim Cromie data->pwm[nr] = PWM_TO_REG(val) & 0xf0; 943787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W836X7HF_REG_PWM(data->type, nr), 94507584c762541672e35735b52af031183ca17a5a2Jim Cromie data->pwm[nr] | 946787c72b107888805981faf148c8fea96a752d22eJean Delvare (w83627hf_read_value(data, 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W836X7HF_REG_PWM(data->type, nr)) & 0x0f)); 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 94907584c762541672e35735b52af031183ca17a5a2Jim Cromie data->pwm[nr] = PWM_TO_REG(val); 950787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W836X7HF_REG_PWM(data->type, nr), 95207584c762541672e35735b52af031183ca17a5a2Jim Cromie data->pwm[nr]); 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9559a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 95907584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0); 96007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1); 96107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2); 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 964a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyershow_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf) 965a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer{ 966a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer int nr = to_sensor_dev_attr(devattr)->index; 967a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer struct w83627hf_data *data = w83627hf_update_device(dev); 968a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer return sprintf(buf, "%d\n", data->pwm_enable[nr]); 969a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer} 970a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer 971a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic ssize_t 972a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstore_pwm_enable(struct device *dev, struct device_attribute *devattr, 973a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer const char *buf, size_t count) 974a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer{ 975a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer int nr = to_sensor_dev_attr(devattr)->index; 976a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer struct w83627hf_data *data = dev_get_drvdata(dev); 977a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer unsigned long val = simple_strtoul(buf, NULL, 10); 978a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer u8 reg; 979a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer 980a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer if (!val || (val > 3)) /* modes 1, 2 and 3 are supported */ 981a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer return -EINVAL; 982a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer mutex_lock(&data->update_lock); 983a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer data->pwm_enable[nr] = val; 984a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]); 985a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]); 986a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr]; 987a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg); 988a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer mutex_unlock(&data->update_lock); 989a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer return count; 990a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer} 991a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer 992a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, 993a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer store_pwm_enable, 0); 994a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, 995a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer store_pwm_enable, 1); 996a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, 997a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer store_pwm_enable, 2); 998a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer 999a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyerstatic ssize_t 100007584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf) 10011550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{ 100207584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 10031550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez struct w83627hf_data *data = w83627hf_update_device(dev); 10041550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez if (data->type == w83627hf) 10051550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez return sprintf(buf, "%ld\n", 100607584c762541672e35735b52af031183ca17a5a2Jim Cromie pwm_freq_from_reg_627hf(data->pwm_freq[nr])); 10071550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez else 10081550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez return sprintf(buf, "%ld\n", 100907584c762541672e35735b52af031183ca17a5a2Jim Cromie pwm_freq_from_reg(data->pwm_freq[nr])); 10101550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez} 10111550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 10121550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t 101307584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_pwm_freq(struct device *dev, struct device_attribute *devattr, 101407584c762541672e35735b52af031183ca17a5a2Jim Cromie const char *buf, size_t count) 10151550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez{ 101607584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 10171550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez struct w83627hf_data *data = dev_get_drvdata(dev); 10181550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez static const u8 mask[]={0xF8, 0x8F}; 10191550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez u32 val; 10201550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 10211550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez val = simple_strtoul(buf, NULL, 10); 10221550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 10231550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez mutex_lock(&data->update_lock); 10241550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 10251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez if (data->type == w83627hf) { 102607584c762541672e35735b52af031183ca17a5a2Jim Cromie data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val); 10271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez w83627hf_write_value(data, W83627HF_REG_PWM_FREQ, 102807584c762541672e35735b52af031183ca17a5a2Jim Cromie (data->pwm_freq[nr] << (nr*4)) | 10291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez (w83627hf_read_value(data, 103007584c762541672e35735b52af031183ca17a5a2Jim Cromie W83627HF_REG_PWM_FREQ) & mask[nr])); 10311550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez } else { 103207584c762541672e35735b52af031183ca17a5a2Jim Cromie data->pwm_freq[nr] = pwm_freq_to_reg(val); 103307584c762541672e35735b52af031183ca17a5a2Jim Cromie w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr], 103407584c762541672e35735b52af031183ca17a5a2Jim Cromie data->pwm_freq[nr]); 10351550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez } 10361550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 10371550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez mutex_unlock(&data->update_lock); 10381550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez return count; 10391550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez} 10401550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 104107584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO|S_IWUSR, 104207584c762541672e35735b52af031183ca17a5a2Jim Cromie show_pwm_freq, store_pwm_freq, 0); 104307584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO|S_IWUSR, 104407584c762541672e35735b52af031183ca17a5a2Jim Cromie show_pwm_freq, store_pwm_freq, 1); 104507584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO|S_IWUSR, 104607584c762541672e35735b52af031183ca17a5a2Jim Cromie show_pwm_freq, store_pwm_freq, 2); 10471550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 10481550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinezstatic ssize_t 104907584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_temp_type(struct device *dev, struct device_attribute *devattr, 105007584c762541672e35735b52af031183ca17a5a2Jim Cromie char *buf) 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 105207584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct w83627hf_data *data = w83627hf_update_device(dev); 105407584c762541672e35735b52af031183ca17a5a2Jim Cromie return sprintf(buf, "%ld\n", (long) data->sens[nr]); 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 105807584c762541672e35735b52af031183ca17a5a2Jim Cromiestore_temp_type(struct device *dev, struct device_attribute *devattr, 105907584c762541672e35735b52af031183ca17a5a2Jim Cromie const char *buf, size_t count) 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 106107584c762541672e35735b52af031183ca17a5a2Jim Cromie int nr = to_sensor_dev_attr(devattr)->index; 1062787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 val, tmp; 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = simple_strtoul(buf, NULL, 10); 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10679a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (val) { 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: /* PII/Celeron diode */ 1071787c72b107888805981faf148c8fea96a752d22eJean Delvare tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); 1072787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_SCFG1, 107307584c762541672e35735b52af031183ca17a5a2Jim Cromie tmp | BIT_SCFG1[nr]); 1074787c72b107888805981faf148c8fea96a752d22eJean Delvare tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); 1075787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_SCFG2, 107607584c762541672e35735b52af031183ca17a5a2Jim Cromie tmp | BIT_SCFG2[nr]); 107707584c762541672e35735b52af031183ca17a5a2Jim Cromie data->sens[nr] = val; 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: /* 3904 */ 1080787c72b107888805981faf148c8fea96a752d22eJean Delvare tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); 1081787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_SCFG1, 108207584c762541672e35735b52af031183ca17a5a2Jim Cromie tmp | BIT_SCFG1[nr]); 1083787c72b107888805981faf148c8fea96a752d22eJean Delvare tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); 1084787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_SCFG2, 108507584c762541672e35735b52af031183ca17a5a2Jim Cromie tmp & ~BIT_SCFG2[nr]); 108607584c762541672e35735b52af031183ca17a5a2Jim Cromie data->sens[nr] = val; 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1088b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare case W83781D_DEFAULT_BETA: 1089b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare dev_warn(dev, "Sensor type %d is deprecated, please use 4 " 1090b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare "instead\n", W83781D_DEFAULT_BETA); 1091b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare /* fall through */ 1092b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare case 4: /* thermistor */ 1093787c72b107888805981faf148c8fea96a752d22eJean Delvare tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); 1094787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_SCFG1, 109507584c762541672e35735b52af031183ca17a5a2Jim Cromie tmp & ~BIT_SCFG1[nr]); 109607584c762541672e35735b52af031183ca17a5a2Jim Cromie data->sens[nr] = val; 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1099787c72b107888805981faf148c8fea96a752d22eJean Delvare dev_err(dev, 1100b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare "Invalid sensor type %ld; must be 1, 2, or 4\n", 1101b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare (long) val); 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11059a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 110907584c762541672e35735b52af031183ca17a5a2Jim Cromie#define sysfs_temp_type(offset) \ 111007584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ 111107584c762541672e35735b52af031183ca17a5a2Jim Cromie show_temp_type, store_temp_type, offset - 1); 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111307584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(1); 111407584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(2); 111507584c762541672e35735b52af031183ca17a5a2Jim Cromiesysfs_temp_type(3); 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111707584c762541672e35735b52af031183ca17a5a2Jim Cromiestatic ssize_t 111807584c762541672e35735b52af031183ca17a5a2Jim Cromieshow_name(struct device *dev, struct device_attribute *devattr, char *buf) 1119787c72b107888805981faf148c8fea96a752d22eJean Delvare{ 1120787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 1121787c72b107888805981faf148c8fea96a752d22eJean Delvare 1122787c72b107888805981faf148c8fea96a752d22eJean Delvare return sprintf(buf, "%s\n", data->name); 1123787c72b107888805981faf148c8fea96a752d22eJean Delvare} 1124787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 1125787c72b107888805981faf148c8fea96a752d22eJean Delvare 1126787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_find(int sioaddr, unsigned short *addr, 1127787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_sio_data *sio_data) 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1129d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare int err = -ENODEV; 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 val; 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1132787c72b107888805981faf148c8fea96a752d22eJean Delvare static const __initdata char *names[] = { 1133787c72b107888805981faf148c8fea96a752d22eJean Delvare "W83627HF", 1134787c72b107888805981faf148c8fea96a752d22eJean Delvare "W83627THF", 1135787c72b107888805981faf148c8fea96a752d22eJean Delvare "W83697HF", 1136787c72b107888805981faf148c8fea96a752d22eJean Delvare "W83637HF", 1137787c72b107888805981faf148c8fea96a752d22eJean Delvare "W83687THF", 1138787c72b107888805981faf148c8fea96a752d22eJean Delvare }; 1139787c72b107888805981faf148c8fea96a752d22eJean Delvare 1140c46c0e9188685c0276b4c0adf9fb7e903937e35bChristian Schulte sio_data->sioaddr = sioaddr; 1141b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_enter(sio_data); 1142b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare val = force_id ? force_id : superio_inb(sio_data, DEVID); 1143787c72b107888805981faf148c8fea96a752d22eJean Delvare switch (val) { 1144787c72b107888805981faf148c8fea96a752d22eJean Delvare case W627_DEVID: 1145787c72b107888805981faf148c8fea96a752d22eJean Delvare sio_data->type = w83627hf; 1146787c72b107888805981faf148c8fea96a752d22eJean Delvare break; 1147787c72b107888805981faf148c8fea96a752d22eJean Delvare case W627THF_DEVID: 1148787c72b107888805981faf148c8fea96a752d22eJean Delvare sio_data->type = w83627thf; 1149787c72b107888805981faf148c8fea96a752d22eJean Delvare break; 1150787c72b107888805981faf148c8fea96a752d22eJean Delvare case W697_DEVID: 1151787c72b107888805981faf148c8fea96a752d22eJean Delvare sio_data->type = w83697hf; 1152787c72b107888805981faf148c8fea96a752d22eJean Delvare break; 1153787c72b107888805981faf148c8fea96a752d22eJean Delvare case W637_DEVID: 1154787c72b107888805981faf148c8fea96a752d22eJean Delvare sio_data->type = w83637hf; 1155787c72b107888805981faf148c8fea96a752d22eJean Delvare break; 1156787c72b107888805981faf148c8fea96a752d22eJean Delvare case W687THF_DEVID: 1157787c72b107888805981faf148c8fea96a752d22eJean Delvare sio_data->type = w83687thf; 1158787c72b107888805981faf148c8fea96a752d22eJean Delvare break; 1159e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare case 0xff: /* No device at all */ 1160e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare goto exit; 1161787c72b107888805981faf148c8fea96a752d22eJean Delvare default: 1162e142e2a30787e9fa1bf0f66aa1d01727ce718cc7Jean Delvare pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val); 1163d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare goto exit; 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1166b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_select(sio_data, W83627HF_LD_HWM); 1167b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare val = (superio_inb(sio_data, WINB_BASE_REG) << 8) | 1168b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_inb(sio_data, WINB_BASE_REG + 1); 1169ada0c2f8fa087dc1dbc34e096c318739b1d6381aPetr Vandrovec *addr = val & WINB_ALIGNMENT; 1170d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare if (*addr == 0) { 117118de030f1dbaef0c13cf393899a298d978aa200fJoe Perches pr_warn("Base address not set, skipping\n"); 1172d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare goto exit; 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1175b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare val = superio_inb(sio_data, WINB_ACT_REG); 1176d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare if (!(val & 0x01)) { 117718de030f1dbaef0c13cf393899a298d978aa200fJoe Perches pr_warn("Enabling HWM logical device\n"); 1178b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_outb(sio_data, WINB_ACT_REG, val | 0x01); 1179d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare } 1180d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare 1181d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare err = 0; 1182787c72b107888805981faf148c8fea96a752d22eJean Delvare pr_info(DRVNAME ": Found %s chip at %#x\n", 1183787c72b107888805981faf148c8fea96a752d22eJean Delvare names[sio_data->type], *addr); 1184d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare 1185d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare exit: 1186b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_exit(sio_data); 1187d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare return err; 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 119007584c762541672e35735b52af031183ca17a5a2Jim Cromie#define VIN_UNIT_ATTRS(_X_) \ 119107584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in##_X_##_input.dev_attr.attr, \ 119207584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in##_X_##_min.dev_attr.attr, \ 1193e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in##_X_##_max.dev_attr.attr, \ 1194e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in##_X_##_alarm.dev_attr.attr, \ 1195e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in##_X_##_beep.dev_attr.attr 119607584c762541672e35735b52af031183ca17a5a2Jim Cromie 119707584c762541672e35735b52af031183ca17a5a2Jim Cromie#define FAN_UNIT_ATTRS(_X_) \ 119807584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_fan##_X_##_input.dev_attr.attr, \ 119907584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_fan##_X_##_min.dev_attr.attr, \ 1200e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_fan##_X_##_div.dev_attr.attr, \ 1201e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_fan##_X_##_alarm.dev_attr.attr, \ 1202e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_fan##_X_##_beep.dev_attr.attr 120307584c762541672e35735b52af031183ca17a5a2Jim Cromie 120407584c762541672e35735b52af031183ca17a5a2Jim Cromie#define TEMP_UNIT_ATTRS(_X_) \ 120507584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_temp##_X_##_input.dev_attr.attr, \ 120607584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_temp##_X_##_max.dev_attr.attr, \ 120707584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr, \ 1208e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_temp##_X_##_type.dev_attr.attr, \ 1209e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr, \ 1210e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_temp##_X_##_beep.dev_attr.attr 121107584c762541672e35735b52af031183ca17a5a2Jim Cromie 1212c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes[] = { 1213c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman &dev_attr_in0_input.attr, 1214c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman &dev_attr_in0_min.attr, 1215c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman &dev_attr_in0_max.attr, 1216e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in0_alarm.dev_attr.attr, 1217e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in0_beep.dev_attr.attr, 121807584c762541672e35735b52af031183ca17a5a2Jim Cromie VIN_UNIT_ATTRS(2), 121907584c762541672e35735b52af031183ca17a5a2Jim Cromie VIN_UNIT_ATTRS(3), 122007584c762541672e35735b52af031183ca17a5a2Jim Cromie VIN_UNIT_ATTRS(4), 122107584c762541672e35735b52af031183ca17a5a2Jim Cromie VIN_UNIT_ATTRS(7), 122207584c762541672e35735b52af031183ca17a5a2Jim Cromie VIN_UNIT_ATTRS(8), 122307584c762541672e35735b52af031183ca17a5a2Jim Cromie 122407584c762541672e35735b52af031183ca17a5a2Jim Cromie FAN_UNIT_ATTRS(1), 122507584c762541672e35735b52af031183ca17a5a2Jim Cromie FAN_UNIT_ATTRS(2), 122607584c762541672e35735b52af031183ca17a5a2Jim Cromie 122707584c762541672e35735b52af031183ca17a5a2Jim Cromie TEMP_UNIT_ATTRS(1), 122807584c762541672e35735b52af031183ca17a5a2Jim Cromie TEMP_UNIT_ATTRS(2), 1229c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 1230c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman &dev_attr_alarms.attr, 12311c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare &sensor_dev_attr_beep_enable.dev_attr.attr, 1232c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman &dev_attr_beep_mask.attr, 1233c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 123407584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm1.dev_attr.attr, 123507584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm2.dev_attr.attr, 1236787c72b107888805981faf148c8fea96a752d22eJean Delvare &dev_attr_name.attr, 1237c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman NULL 1238c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman}; 1239c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 1240c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group = { 1241c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman .attrs = w83627hf_attributes, 1242c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman}; 1243c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 1244c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *w83627hf_attributes_opt[] = { 124507584c762541672e35735b52af031183ca17a5a2Jim Cromie VIN_UNIT_ATTRS(1), 124607584c762541672e35735b52af031183ca17a5a2Jim Cromie VIN_UNIT_ATTRS(5), 124707584c762541672e35735b52af031183ca17a5a2Jim Cromie VIN_UNIT_ATTRS(6), 124807584c762541672e35735b52af031183ca17a5a2Jim Cromie 124907584c762541672e35735b52af031183ca17a5a2Jim Cromie FAN_UNIT_ATTRS(3), 125007584c762541672e35735b52af031183ca17a5a2Jim Cromie TEMP_UNIT_ATTRS(3), 125107584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm3.dev_attr.attr, 125207584c762541672e35735b52af031183ca17a5a2Jim Cromie 125307584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm1_freq.dev_attr.attr, 125407584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm2_freq.dev_attr.attr, 125507584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm3_freq.dev_attr.attr, 1256a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer 1257a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer &sensor_dev_attr_pwm1_enable.dev_attr.attr, 1258a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer &sensor_dev_attr_pwm2_enable.dev_attr.attr, 1259a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer &sensor_dev_attr_pwm3_enable.dev_attr.attr, 1260a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer 1261c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman NULL 1262c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman}; 1263c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 1264c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group w83627hf_group_opt = { 1265c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman .attrs = w83627hf_attributes_opt, 1266c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman}; 1267c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 1268787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627hf_probe(struct platform_device *pdev) 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1270787c72b107888805981faf148c8fea96a752d22eJean Delvare struct device *dev = &pdev->dev; 1271787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_sio_data *sio_data = dev->platform_data; 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct w83627hf_data *data; 1273787c72b107888805981faf148c8fea96a752d22eJean Delvare struct resource *res; 12742ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie int err, i; 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1276787c72b107888805981faf148c8fea96a752d22eJean Delvare static const char *names[] = { 1277787c72b107888805981faf148c8fea96a752d22eJean Delvare "w83627hf", 1278787c72b107888805981faf148c8fea96a752d22eJean Delvare "w83627thf", 1279787c72b107888805981faf148c8fea96a752d22eJean Delvare "w83697hf", 1280787c72b107888805981faf148c8fea96a752d22eJean Delvare "w83637hf", 1281787c72b107888805981faf148c8fea96a752d22eJean Delvare "w83687thf", 1282787c72b107888805981faf148c8fea96a752d22eJean Delvare }; 1283787c72b107888805981faf148c8fea96a752d22eJean Delvare 1284787c72b107888805981faf148c8fea96a752d22eJean Delvare res = platform_get_resource(pdev, IORESOURCE_IO, 0); 1285787c72b107888805981faf148c8fea96a752d22eJean Delvare if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) { 1286787c72b107888805981faf148c8fea96a752d22eJean Delvare dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", 1287787c72b107888805981faf148c8fea96a752d22eJean Delvare (unsigned long)res->start, 1288787c72b107888805981faf148c8fea96a752d22eJean Delvare (unsigned long)(res->start + WINB_REGION_SIZE - 1)); 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EBUSY; 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto ERROR0; 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1293ba9c2e8d15da029ea3051c95e446b2d638ef02e2Deepak Saxena if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) { 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOMEM; 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto ERROR1; 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1297787c72b107888805981faf148c8fea96a752d22eJean Delvare data->addr = res->start; 1298787c72b107888805981faf148c8fea96a752d22eJean Delvare data->type = sio_data->type; 1299787c72b107888805981faf148c8fea96a752d22eJean Delvare data->name = names[sio_data->type]; 13009a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_init(&data->lock); 13019a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_init(&data->update_lock); 1302787c72b107888805981faf148c8fea96a752d22eJean Delvare platform_set_drvdata(pdev, data); 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the chip */ 1305787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_init_device(pdev); 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* A few vars need to be filled upon startup */ 13082ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie for (i = 0; i <= 2; i++) 13092ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie data->fan_min[i] = w83627hf_read_value( 13102ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie data, W83627HF_REG_FAN_MIN(i)); 1311c09c5184a26158da32801e89d5849d774605f0ddJean Delvare w83627hf_update_fan_div(data); 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1313c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman /* Register common device attributes */ 1314787c72b107888805981faf148c8fea96a752d22eJean Delvare if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group))) 1315943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman goto ERROR3; 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1317c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman /* Register chip-specific device attributes */ 1318787c72b107888805981faf148c8fea96a752d22eJean Delvare if (data->type == w83627hf || data->type == w83697hf) 131907584c762541672e35735b52af031183ca17a5a2Jim Cromie if ((err = device_create_file(dev, 132007584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in5_input.dev_attr)) 132107584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 132207584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in5_min.dev_attr)) 132307584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 132407584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in5_max.dev_attr)) 132507584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 1326e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in5_alarm.dev_attr)) 1327e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare || (err = device_create_file(dev, 1328e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in5_beep.dev_attr)) 1329e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare || (err = device_create_file(dev, 133007584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in6_input.dev_attr)) 133107584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 133207584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in6_min.dev_attr)) 133307584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 133407584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in6_max.dev_attr)) 133507584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 1336e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in6_alarm.dev_attr)) 1337e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare || (err = device_create_file(dev, 1338e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in6_beep.dev_attr)) 1339e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare || (err = device_create_file(dev, 134007584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm1_freq.dev_attr)) 134107584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 134207584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm2_freq.dev_attr))) 1343c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman goto ERROR4; 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1345787c72b107888805981faf148c8fea96a752d22eJean Delvare if (data->type != w83697hf) 134607584c762541672e35735b52af031183ca17a5a2Jim Cromie if ((err = device_create_file(dev, 134707584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in1_input.dev_attr)) 134807584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 134907584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in1_min.dev_attr)) 135007584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 135107584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_in1_max.dev_attr)) 135207584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 1353e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in1_alarm.dev_attr)) 1354e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare || (err = device_create_file(dev, 1355e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_in1_beep.dev_attr)) 1356e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare || (err = device_create_file(dev, 135707584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_fan3_input.dev_attr)) 135807584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 135907584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_fan3_min.dev_attr)) 136007584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 136107584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_fan3_div.dev_attr)) 136207584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 1363e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_fan3_alarm.dev_attr)) 1364e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare || (err = device_create_file(dev, 1365e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_fan3_beep.dev_attr)) 1366e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare || (err = device_create_file(dev, 136707584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_temp3_input.dev_attr)) 136807584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 136907584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_temp3_max.dev_attr)) 137007584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 137107584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_temp3_max_hyst.dev_attr)) 137207584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 1373e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_temp3_alarm.dev_attr)) 1374e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare || (err = device_create_file(dev, 1375e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare &sensor_dev_attr_temp3_beep.dev_attr)) 1376e3604c626cdcddf37bf5c9663ae75b79dad40000Jean Delvare || (err = device_create_file(dev, 137707584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_temp3_type.dev_attr))) 1378c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman goto ERROR4; 1379c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 1380787c72b107888805981faf148c8fea96a752d22eJean Delvare if (data->type != w83697hf && data->vid != 0xff) { 13818a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare /* Convert VID to voltage based on VRM */ 13828a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare data->vrm = vid_which_vrm(); 13838a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare 1384787c72b107888805981faf148c8fea96a752d22eJean Delvare if ((err = device_create_file(dev, &dev_attr_cpu0_vid)) 1385787c72b107888805981faf148c8fea96a752d22eJean Delvare || (err = device_create_file(dev, &dev_attr_vrm))) 1386c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman goto ERROR4; 13878a665a0552c414af88788cc0e2cf0e4626182c20Jean Delvare } 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1389787c72b107888805981faf148c8fea96a752d22eJean Delvare if (data->type == w83627thf || data->type == w83637hf 1390787c72b107888805981faf148c8fea96a752d22eJean Delvare || data->type == w83687thf) 139107584c762541672e35735b52af031183ca17a5a2Jim Cromie if ((err = device_create_file(dev, 139207584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm3.dev_attr))) 1393c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman goto ERROR4; 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13951550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez if (data->type == w83637hf || data->type == w83687thf) 139607584c762541672e35735b52af031183ca17a5a2Jim Cromie if ((err = device_create_file(dev, 139707584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm1_freq.dev_attr)) 139807584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 139907584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm2_freq.dev_attr)) 140007584c762541672e35735b52af031183ca17a5a2Jim Cromie || (err = device_create_file(dev, 140107584c762541672e35735b52af031183ca17a5a2Jim Cromie &sensor_dev_attr_pwm3_freq.dev_attr))) 14021550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez goto ERROR4; 14031550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez 1404a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer if (data->type != w83627hf) 1405a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer if ((err = device_create_file(dev, 1406a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer &sensor_dev_attr_pwm1_enable.dev_attr)) 1407a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer || (err = device_create_file(dev, 1408a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer &sensor_dev_attr_pwm2_enable.dev_attr))) 1409a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer goto ERROR4; 1410a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer 1411a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer if (data->type == w83627thf || data->type == w83637hf 1412a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer || data->type == w83687thf) 1413a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer if ((err = device_create_file(dev, 1414a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer &sensor_dev_attr_pwm3_enable.dev_attr))) 1415a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer goto ERROR4; 1416a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer 14171beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones data->hwmon_dev = hwmon_device_register(dev); 14181beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones if (IS_ERR(data->hwmon_dev)) { 14191beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones err = PTR_ERR(data->hwmon_dev); 1420c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman goto ERROR4; 1421c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman } 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1425c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman ERROR4: 1426787c72b107888805981faf148c8fea96a752d22eJean Delvare sysfs_remove_group(&dev->kobj, &w83627hf_group); 1427787c72b107888805981faf148c8fea96a752d22eJean Delvare sysfs_remove_group(&dev->kobj, &w83627hf_group_opt); 1428943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman ERROR3: 142904a6217df28e3004ba4e76eb0a356a30f72c564fJean Delvare platform_set_drvdata(pdev, NULL); 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(data); 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ERROR1: 1432787c72b107888805981faf148c8fea96a752d22eJean Delvare release_region(res->start, WINB_REGION_SIZE); 14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ERROR0: 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1437787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devexit w83627hf_remove(struct platform_device *pdev) 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1439787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = platform_get_drvdata(pdev); 1440787c72b107888805981faf148c8fea96a752d22eJean Delvare struct resource *res; 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14421beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones hwmon_device_unregister(data->hwmon_dev); 1443943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman 1444787c72b107888805981faf148c8fea96a752d22eJean Delvare sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group); 1445787c72b107888805981faf148c8fea96a752d22eJean Delvare sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt); 144604a6217df28e3004ba4e76eb0a356a30f72c564fJean Delvare platform_set_drvdata(pdev, NULL); 1447943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman kfree(data); 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1449787c72b107888805981faf148c8fea96a752d22eJean Delvare res = platform_get_resource(pdev, IORESOURCE_IO, 0); 1450787c72b107888805981faf148c8fea96a752d22eJean Delvare release_region(res->start, WINB_REGION_SIZE); 1451787c72b107888805981faf148c8fea96a752d22eJean Delvare 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1456d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare/* Registers 0x50-0x5f are banked */ 1457d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvarestatic inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg) 1458d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare{ 1459d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare if ((reg & 0x00f0) == 0x50) { 1460d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET); 1461d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET); 1462d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare } 1463d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare} 1464d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare 1465d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare/* Not strictly necessary, but play it safe for now */ 1466d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvarestatic inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg) 1467d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare{ 1468d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare if (reg & 0xff00) { 1469d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET); 1470d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare outb_p(0, data->addr + W83781D_DATA_REG_OFFSET); 1471d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare } 1472d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare} 1473d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare 1474787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_read_value(struct w83627hf_data *data, u16 reg) 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res, word_sized; 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14789a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->lock); 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds word_sized = (((reg & 0xff00) == 0x100) 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || ((reg & 0xff00) == 0x200)) 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && (((reg & 0x00ff) == 0x50) 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || ((reg & 0x00ff) == 0x53) 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || ((reg & 0x00ff) == 0x55)); 1484d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare w83627hf_set_bank(data, reg); 1485787c72b107888805981faf148c8fea96a752d22eJean Delvare outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); 1486787c72b107888805981faf148c8fea96a752d22eJean Delvare res = inb_p(data->addr + W83781D_DATA_REG_OFFSET); 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (word_sized) { 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p((reg & 0xff) + 1, 1489787c72b107888805981faf148c8fea96a752d22eJean Delvare data->addr + W83781D_ADDR_REG_OFFSET); 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = 1491787c72b107888805981faf148c8fea96a752d22eJean Delvare (res << 8) + inb_p(data->addr + 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W83781D_DATA_REG_OFFSET); 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1494d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare w83627hf_reset_bank(data, reg); 14959a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->lock); 14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1499787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83627thf_read_gpio5(struct platform_device *pdev) 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1501b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare struct w83627hf_sio_data *sio_data = pdev->dev.platform_data; 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res = 0xff, sel; 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1504b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_enter(sio_data); 1505b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_select(sio_data, W83627HF_LD_GPIO5); 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make sure these GPIO pins are enabled */ 1508b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare if (!(superio_inb(sio_data, W83627THF_GPIO5_EN) & (1<<3))) { 1509787c72b107888805981faf148c8fea96a752d22eJean Delvare dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n"); 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make sure the pins are configured for input 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds There must be at least five (VRM 9), and possibly 6 (VRM 10) */ 1515b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare sel = superio_inb(sio_data, W83627THF_GPIO5_IOSR) & 0x3f; 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((sel & 0x1f) != 0x1f) { 1517787c72b107888805981faf148c8fea96a752d22eJean Delvare dev_dbg(&pdev->dev, "GPIO5 not configured for VID " 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "function\n"); 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1522787c72b107888805981faf148c8fea96a752d22eJean Delvare dev_info(&pdev->dev, "Reading VID from GPIO5\n"); 1523b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare res = superio_inb(sio_data, W83627THF_GPIO5_DR) & sel; 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 1526b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_exit(sio_data); 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1530787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __devinit w83687thf_read_vid(struct platform_device *pdev) 1531c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare{ 1532b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare struct w83627hf_sio_data *sio_data = pdev->dev.platform_data; 1533c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare int res = 0xff; 1534c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare 1535b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_enter(sio_data); 1536b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_select(sio_data, W83627HF_LD_HWM); 1537c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare 1538c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare /* Make sure these GPIO pins are enabled */ 1539b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare if (!(superio_inb(sio_data, W83687THF_VID_EN) & (1 << 2))) { 1540787c72b107888805981faf148c8fea96a752d22eJean Delvare dev_dbg(&pdev->dev, "VID disabled, no VID function\n"); 1541c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare goto exit; 1542c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare } 1543c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare 1544c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare /* Make sure the pins are configured for input */ 1545b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare if (!(superio_inb(sio_data, W83687THF_VID_CFG) & (1 << 4))) { 1546787c72b107888805981faf148c8fea96a752d22eJean Delvare dev_dbg(&pdev->dev, "VID configured as output, " 1547c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare "no VID function\n"); 1548c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare goto exit; 1549c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare } 1550c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare 1551b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare res = superio_inb(sio_data, W83687THF_VID_DATA) & 0x3f; 1552c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare 1553c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvareexit: 1554b72656dbc491484765776a16eeb55ef2e90efea6Jean Delvare superio_exit(sio_data); 1555c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare return res; 1556c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare} 1557c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare 1558787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value) 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int word_sized; 15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15629a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->lock); 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds word_sized = (((reg & 0xff00) == 0x100) 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || ((reg & 0xff00) == 0x200)) 15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && (((reg & 0x00ff) == 0x53) 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || ((reg & 0x00ff) == 0x55)); 1567d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare w83627hf_set_bank(data, reg); 1568787c72b107888805981faf148c8fea96a752d22eJean Delvare outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (word_sized) { 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(value >> 8, 1571787c72b107888805981faf148c8fea96a752d22eJean Delvare data->addr + W83781D_DATA_REG_OFFSET); 15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p((reg & 0xff) + 1, 1573787c72b107888805981faf148c8fea96a752d22eJean Delvare data->addr + W83781D_ADDR_REG_OFFSET); 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(value & 0xff, 1576787c72b107888805981faf148c8fea96a752d22eJean Delvare data->addr + W83781D_DATA_REG_OFFSET); 1577d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44Jean Delvare w83627hf_reset_bank(data, reg); 15789a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->lock); 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1582787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic void __devinit w83627hf_init_device(struct platform_device *pdev) 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1584787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = platform_get_drvdata(pdev); 15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1586d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare enum chips type = data->type; 15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 tmp; 15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Minimize conflicts with other winbond i2c-only clients... */ 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* disable i2c subclients... how to disable main i2c client?? */ 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* force i2c address to relatively uncommon address */ 1592787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89); 1593787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c); 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read VID only once */ 1596d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare if (type == w83627hf || type == w83637hf) { 1597787c72b107888805981faf148c8fea96a752d22eJean Delvare int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV); 1598787c72b107888805981faf148c8fea96a752d22eJean Delvare int hi = w83627hf_read_value(data, W83781D_REG_CHIPID); 15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); 1600d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare } else if (type == w83627thf) { 1601787c72b107888805981faf148c8fea96a752d22eJean Delvare data->vid = w83627thf_read_gpio5(pdev); 1602d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare } else if (type == w83687thf) { 1603787c72b107888805981faf148c8fea96a752d22eJean Delvare data->vid = w83687thf_read_vid(pdev); 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read VRM & OVT Config only once */ 1607d27c37c0be3fd97a696dafb28507277d49875dcbJean Delvare if (type == w83627thf || type == w83637hf || type == w83687thf) { 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->vrm_ovt = 1609787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG); 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1612787c72b107888805981faf148c8fea96a752d22eJean Delvare tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 3; i++) { 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(tmp & BIT_SCFG1[i - 1])) { 1615b26f93309282bdfebb3edb8939e022a4bbe56dfeJean Delvare data->sens[i - 1] = 4; 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (w83627hf_read_value 1618787c72b107888805981faf148c8fea96a752d22eJean Delvare (data, 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->sens[i - 1] = 1; 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->sens[i - 1] = 2; 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((type == w83697hf) && (i == 2)) 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(init) { 16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Enable temp2 */ 1630df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG); 16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp & 0x01) { 1632787c72b107888805981faf148c8fea96a752d22eJean Delvare dev_warn(&pdev->dev, "Enabling temp2, readings " 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "might not make sense\n"); 1634df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG, 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp & 0xfe); 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Enable temp3 */ 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (type != w83697hf) { 1640787c72b107888805981faf148c8fea96a752d22eJean Delvare tmp = w83627hf_read_value(data, 1641df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie W83627HF_REG_TEMP3_CONFIG); 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp & 0x01) { 1643787c72b107888805981faf148c8fea96a752d22eJean Delvare dev_warn(&pdev->dev, "Enabling temp3, " 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "readings might not make sense\n"); 1645787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, 1646df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe); 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start monitoring */ 1652787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_write_value(data, W83781D_REG_CONFIG, 1653787c72b107888805981faf148c8fea96a752d22eJean Delvare (w83627hf_read_value(data, 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W83781D_REG_CONFIG) & 0xf7) 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | 0x01); 1656ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare 1657ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare /* Enable VBAT monitoring if needed */ 1658ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare tmp = w83627hf_read_value(data, W83781D_REG_VBAT); 1659ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare if (!(tmp & 0x01)) 1660ef878b11ba245d14b7db7816217a825d6a894182Jean Delvare w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01); 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1663c09c5184a26158da32801e89d5849d774605f0ddJean Delvarestatic void w83627hf_update_fan_div(struct w83627hf_data *data) 1664c09c5184a26158da32801e89d5849d774605f0ddJean Delvare{ 1665c09c5184a26158da32801e89d5849d774605f0ddJean Delvare int reg; 1666c09c5184a26158da32801e89d5849d774605f0ddJean Delvare 1667c09c5184a26158da32801e89d5849d774605f0ddJean Delvare reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV); 1668c09c5184a26158da32801e89d5849d774605f0ddJean Delvare data->fan_div[0] = (reg >> 4) & 0x03; 1669c09c5184a26158da32801e89d5849d774605f0ddJean Delvare data->fan_div[1] = (reg >> 6) & 0x03; 1670c09c5184a26158da32801e89d5849d774605f0ddJean Delvare if (data->type != w83697hf) { 1671c09c5184a26158da32801e89d5849d774605f0ddJean Delvare data->fan_div[2] = (w83627hf_read_value(data, 1672c09c5184a26158da32801e89d5849d774605f0ddJean Delvare W83781D_REG_PIN) >> 6) & 0x03; 1673c09c5184a26158da32801e89d5849d774605f0ddJean Delvare } 1674c09c5184a26158da32801e89d5849d774605f0ddJean Delvare reg = w83627hf_read_value(data, W83781D_REG_VBAT); 1675c09c5184a26158da32801e89d5849d774605f0ddJean Delvare data->fan_div[0] |= (reg >> 3) & 0x04; 1676c09c5184a26158da32801e89d5849d774605f0ddJean Delvare data->fan_div[1] |= (reg >> 4) & 0x04; 1677c09c5184a26158da32801e89d5849d774605f0ddJean Delvare if (data->type != w83697hf) 1678c09c5184a26158da32801e89d5849d774605f0ddJean Delvare data->fan_div[2] |= (reg >> 5) & 0x04; 1679c09c5184a26158da32801e89d5849d774605f0ddJean Delvare} 1680c09c5184a26158da32801e89d5849d774605f0ddJean Delvare 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct w83627hf_data *w83627hf_update_device(struct device *dev) 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1683787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_data *data = dev_get_drvdata(dev); 1684df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie int i, num_temps = (data->type == w83697hf) ? 2 : 3; 1685a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer int num_pwms = (data->type == w83697hf) ? 2 : 3; 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16879a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || !data->valid) { 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i <= 8; i++) { 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* skip missing sensors */ 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((data->type == w83697hf) && (i == 1)) || 1694c2db6ce14a743ac5f8973124272cf425c4f86b90Jean Delvare ((data->type != w83627hf && data->type != w83697hf) 16954a1c4447e523003019a2bf9b972ed6fe411e84d2Yuan Mu && (i == 5 || i == 6))) 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in[i] = 1698787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_read_value(data, W83781D_REG_IN(i)); 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_min[i] = 1700787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_read_value(data, 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W83781D_REG_IN_MIN(i)); 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_max[i] = 1703787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_read_value(data, 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W83781D_REG_IN_MAX(i)); 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17062ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie for (i = 0; i <= 2; i++) { 17072ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie data->fan[i] = 17082ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie w83627hf_read_value(data, W83627HF_REG_FAN(i)); 17092ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie data->fan_min[i] = 1710787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_read_value(data, 17112ca2fcd124c00a5e733fb0206ef106fade9a76a4Jim Cromie W83627HF_REG_FAN_MIN(i)); 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 171307584c762541672e35735b52af031183ca17a5a2Jim Cromie for (i = 0; i <= 2; i++) { 1714787c72b107888805981faf148c8fea96a752d22eJean Delvare u8 tmp = w83627hf_read_value(data, 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W836X7HF_REG_PWM(data->type, i)); 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* bits 0-3 are reserved in 627THF */ 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->type == w83627thf) 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp &= 0xf0; 171907584c762541672e35735b52af031183ca17a5a2Jim Cromie data->pwm[i] = tmp; 172007584c762541672e35735b52af031183ca17a5a2Jim Cromie if (i == 1 && 172107584c762541672e35735b52af031183ca17a5a2Jim Cromie (data->type == w83627hf || data->type == w83697hf)) 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17241550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez if (data->type == w83627hf) { 17251550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez u8 tmp = w83627hf_read_value(data, 17261550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez W83627HF_REG_PWM_FREQ); 17271550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez data->pwm_freq[0] = tmp & 0x07; 17281550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez data->pwm_freq[1] = (tmp >> 4) & 0x07; 17291550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez } else if (data->type != w83627thf) { 17301550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez for (i = 1; i <= 3; i++) { 17311550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez data->pwm_freq[i - 1] = 17321550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez w83627hf_read_value(data, 17331550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez W83637HF_REG_PWM_FREQ[i - 1]); 17341550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez if (i == 2 && (data->type == w83697hf)) 17351550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez break; 17361550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez } 17371550cb6d7e78c7cfdd7b48bee6809795d43d6a33Carlos Olalla Martinez } 1738a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer if (data->type != w83627hf) { 1739a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer for (i = 0; i < num_pwms; i++) { 1740a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer u8 tmp = w83627hf_read_value(data, 1741a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer W83627THF_REG_PWM_ENABLE[i]); 1742a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer data->pwm_enable[i] = 1743a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer ((tmp >> W83627THF_PWM_ENABLE_SHIFT[i]) 1744a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer & 0x03) + 1; 1745a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer } 1746a95a5ed856e902e513119d4cc5b745faa202f761Dominik Geyer } 1747df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie for (i = 0; i < num_temps; i++) { 1748df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie data->temp[i] = w83627hf_read_value( 1749df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie data, w83627hf_reg_temp[i]); 1750df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie data->temp_max[i] = w83627hf_read_value( 1751df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie data, w83627hf_reg_temp_over[i]); 1752df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie data->temp_max_hyst[i] = w83627hf_read_value( 1753df48ed804f44a040e990976b537efc1e133c74d8Jim Cromie data, w83627hf_reg_temp_hyst[i]); 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1756c09c5184a26158da32801e89d5849d774605f0ddJean Delvare w83627hf_update_fan_div(data); 1757c09c5184a26158da32801e89d5849d774605f0ddJean Delvare 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->alarms = 1759787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_read_value(data, W83781D_REG_ALARM1) | 1760787c72b107888805981faf148c8fea96a752d22eJean Delvare (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) | 1761787c72b107888805981faf148c8fea96a752d22eJean Delvare (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16); 1762787c72b107888805981faf148c8fea96a752d22eJean Delvare i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2); 17631c1381076f8c6cf0a2c9918194e3fa6369cdf06aJean Delvare data->beep_mask = (i << 8) | 1764787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) | 1765787c72b107888805981faf148c8fea96a752d22eJean Delvare w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16; 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->last_updated = jiffies; 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->valid = 1; 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17709a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return data; 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1775787c72b107888805981faf148c8fea96a752d22eJean Delvarestatic int __init w83627hf_device_add(unsigned short address, 1776787c72b107888805981faf148c8fea96a752d22eJean Delvare const struct w83627hf_sio_data *sio_data) 1777787c72b107888805981faf148c8fea96a752d22eJean Delvare{ 1778787c72b107888805981faf148c8fea96a752d22eJean Delvare struct resource res = { 1779787c72b107888805981faf148c8fea96a752d22eJean Delvare .start = address + WINB_REGION_OFFSET, 1780787c72b107888805981faf148c8fea96a752d22eJean Delvare .end = address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1, 1781787c72b107888805981faf148c8fea96a752d22eJean Delvare .name = DRVNAME, 1782787c72b107888805981faf148c8fea96a752d22eJean Delvare .flags = IORESOURCE_IO, 1783787c72b107888805981faf148c8fea96a752d22eJean Delvare }; 1784787c72b107888805981faf148c8fea96a752d22eJean Delvare int err; 1785787c72b107888805981faf148c8fea96a752d22eJean Delvare 1786b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare err = acpi_check_resource_conflict(&res); 1787b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare if (err) 1788b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare goto exit; 1789b9acb64a385c5b26fc392e0d58ac7b8e0a2cd812Jean Delvare 1790787c72b107888805981faf148c8fea96a752d22eJean Delvare pdev = platform_device_alloc(DRVNAME, address); 1791787c72b107888805981faf148c8fea96a752d22eJean Delvare if (!pdev) { 1792787c72b107888805981faf148c8fea96a752d22eJean Delvare err = -ENOMEM; 179318de030f1dbaef0c13cf393899a298d978aa200fJoe Perches pr_err("Device allocation failed\n"); 1794787c72b107888805981faf148c8fea96a752d22eJean Delvare goto exit; 1795787c72b107888805981faf148c8fea96a752d22eJean Delvare } 1796787c72b107888805981faf148c8fea96a752d22eJean Delvare 1797787c72b107888805981faf148c8fea96a752d22eJean Delvare err = platform_device_add_resources(pdev, &res, 1); 1798787c72b107888805981faf148c8fea96a752d22eJean Delvare if (err) { 179918de030f1dbaef0c13cf393899a298d978aa200fJoe Perches pr_err("Device resource addition failed (%d)\n", err); 1800787c72b107888805981faf148c8fea96a752d22eJean Delvare goto exit_device_put; 1801787c72b107888805981faf148c8fea96a752d22eJean Delvare } 1802787c72b107888805981faf148c8fea96a752d22eJean Delvare 18032df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare err = platform_device_add_data(pdev, sio_data, 18042df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare sizeof(struct w83627hf_sio_data)); 18052df6d811574f46bea0d38bf91aa54df4c05488cdJean Delvare if (err) { 180618de030f1dbaef0c13cf393899a298d978aa200fJoe Perches pr_err("Platform data allocation failed\n"); 1807787c72b107888805981faf148c8fea96a752d22eJean Delvare goto exit_device_put; 1808787c72b107888805981faf148c8fea96a752d22eJean Delvare } 1809787c72b107888805981faf148c8fea96a752d22eJean Delvare 1810787c72b107888805981faf148c8fea96a752d22eJean Delvare err = platform_device_add(pdev); 1811787c72b107888805981faf148c8fea96a752d22eJean Delvare if (err) { 181218de030f1dbaef0c13cf393899a298d978aa200fJoe Perches pr_err("Device addition failed (%d)\n", err); 1813787c72b107888805981faf148c8fea96a752d22eJean Delvare goto exit_device_put; 1814787c72b107888805981faf148c8fea96a752d22eJean Delvare } 1815787c72b107888805981faf148c8fea96a752d22eJean Delvare 1816787c72b107888805981faf148c8fea96a752d22eJean Delvare return 0; 1817787c72b107888805981faf148c8fea96a752d22eJean Delvare 1818787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_device_put: 1819787c72b107888805981faf148c8fea96a752d22eJean Delvare platform_device_put(pdev); 1820787c72b107888805981faf148c8fea96a752d22eJean Delvareexit: 1821787c72b107888805981faf148c8fea96a752d22eJean Delvare return err; 1822787c72b107888805981faf148c8fea96a752d22eJean Delvare} 1823787c72b107888805981faf148c8fea96a752d22eJean Delvare 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sensors_w83627hf_init(void) 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1826787c72b107888805981faf148c8fea96a752d22eJean Delvare int err; 1827787c72b107888805981faf148c8fea96a752d22eJean Delvare unsigned short address; 1828787c72b107888805981faf148c8fea96a752d22eJean Delvare struct w83627hf_sio_data sio_data; 1829787c72b107888805981faf148c8fea96a752d22eJean Delvare 1830787c72b107888805981faf148c8fea96a752d22eJean Delvare if (w83627hf_find(0x2e, &address, &sio_data) 1831787c72b107888805981faf148c8fea96a752d22eJean Delvare && w83627hf_find(0x4e, &address, &sio_data)) 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1834787c72b107888805981faf148c8fea96a752d22eJean Delvare err = platform_driver_register(&w83627hf_driver); 1835787c72b107888805981faf148c8fea96a752d22eJean Delvare if (err) 1836787c72b107888805981faf148c8fea96a752d22eJean Delvare goto exit; 1837787c72b107888805981faf148c8fea96a752d22eJean Delvare 1838787c72b107888805981faf148c8fea96a752d22eJean Delvare /* Sets global pdev as a side effect */ 1839787c72b107888805981faf148c8fea96a752d22eJean Delvare err = w83627hf_device_add(address, &sio_data); 1840787c72b107888805981faf148c8fea96a752d22eJean Delvare if (err) 1841787c72b107888805981faf148c8fea96a752d22eJean Delvare goto exit_driver; 1842787c72b107888805981faf148c8fea96a752d22eJean Delvare 1843787c72b107888805981faf148c8fea96a752d22eJean Delvare return 0; 1844787c72b107888805981faf148c8fea96a752d22eJean Delvare 1845787c72b107888805981faf148c8fea96a752d22eJean Delvareexit_driver: 1846787c72b107888805981faf148c8fea96a752d22eJean Delvare platform_driver_unregister(&w83627hf_driver); 1847787c72b107888805981faf148c8fea96a752d22eJean Delvareexit: 1848787c72b107888805981faf148c8fea96a752d22eJean Delvare return err; 18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sensors_w83627hf_exit(void) 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1853787c72b107888805981faf148c8fea96a752d22eJean Delvare platform_device_unregister(pdev); 1854787c72b107888805981faf148c8fea96a752d22eJean Delvare platform_driver_unregister(&w83627hf_driver); 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Philip Edelbrock <phil@netroedge.com>, " 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "and Mark Studebaker <mdsxyz123@yahoo.com>"); 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("W83627HF driver"); 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sensors_w83627hf_init); 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sensors_w83627hf_exit); 1865