11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
28c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * asb100.c - Part of lm_sensors, Linux kernel modules for hardware
38c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *	      monitoring
48c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *
58c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * Copyright (C) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
68c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *
78c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * (derived from w83781d.c)
88c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *
98c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * Copyright (C) 1998 - 2003  Frodo Looijaard <frodol@dds.nl>,
108c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *			      Philip Edelbrock <phil@netroedge.com>, and
118c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *			      Mark Studebaker <mdsxyz123@yahoo.com>
128c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *
138c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * This program is free software; you can redistribute it and/or modify
148c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * it under the terms of the GNU General Public License as published by
158c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * the Free Software Foundation; either version 2 of the License, or
168c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * (at your option) any later version.
178c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *
188c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * This program is distributed in the hope that it will be useful,
198c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of
208c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
218c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * GNU General Public License for more details.
228c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *
238c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * You should have received a copy of the GNU General Public License
248c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * along with this program; if not, write to the Free Software
258c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
268c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck */
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
298c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * This driver supports the hardware sensor chips: Asus ASB100 and
308c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * ASB100-A "BACH".
318c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *
328c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * ASB100-A supports pwm1, while plain ASB100 does not.  There is no known
338c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * way for the driver to tell which one is there.
348c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck *
354101ece3a226e68a5335dd8a15c7ab8663972b81Jean Delvare * Chip		#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
368c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * asb100	7	3	1	4	0x31	0x0694	yes	no
378c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck */
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
394d630e2ba59a231c8e5031cc55e16737aa59af97Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
404d630e2ba59a231c8e5031cc55e16737aa59af97Joe Perches
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h>
44943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/hwmon.h>
45fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare#include <linux/hwmon-sysfs.h>
46303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare#include <linux/hwmon-vid.h>
47943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/err.h>
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
49ff3240946d6a3d9f2ecf273f7330e09eec5484ebDominik Hackl#include <linux/jiffies.h>
509a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar#include <linux/mutex.h>
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "lm75.h"
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* I2C addresses to scan */
5425e9c86d5a6d82ea45eb680fc66bf73ac5e50dffMark M. Hoffmanstatic const unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
563aed198c35567e5a721f52c0bde23167867e6af6Jean Delvarestatic unsigned short force_subclients[4];
573aed198c35567e5a721f52c0bde23167867e6af6Jean Delvaremodule_param_array(force_subclients, short, NULL, 0);
58b55f375725ff85aada394da488802b0a3cc99e88Guenter RoeckMODULE_PARM_DESC(force_subclients,
59b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck	"List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Voltage IN registers 0-6 */
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_IN(nr)	(0x20 + (nr))
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_IN_MAX(nr)	(0x2b + (nr * 2))
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_IN_MIN(nr)	(0x2c + (nr * 2))
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FAN IN registers 1-3 */
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_FAN(nr)	(0x28 + (nr))
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_FAN_MIN(nr)	(0x3b + (nr))
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TEMPERATURE registers 1-4 */
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u16 asb100_reg_temp[]	= {0, 0x27, 0x150, 0x250, 0x17};
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u16 asb100_reg_temp_max[]	= {0, 0x39, 0x155, 0x255, 0x18};
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u16 asb100_reg_temp_hyst[]	= {0, 0x3a, 0x153, 0x253, 0x19};
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_TEMP(nr) (asb100_reg_temp[nr])
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_TEMP_MAX(nr) (asb100_reg_temp_max[nr])
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_TEMP_HYST(nr) (asb100_reg_temp_hyst[nr])
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_TEMP2_CONFIG	0x0152
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_TEMP3_CONFIG	0x0252
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_CONFIG	0x40
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_ALARM1	0x41
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_ALARM2	0x42
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_SMIM1	0x43
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_SMIM2	0x44
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_VID_FANDIV	0x47
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_I2C_ADDR	0x48
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_CHIPID	0x49
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_I2C_SUBADDR	0x4a
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_PIN		0x4b
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_IRQ		0x4c
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_BANK		0x4e
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_CHIPMAN	0x4f
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_WCHIPID	0x58
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* bit 7 -> enable, bits 0-3 -> duty cycle */
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_PWM1		0x59
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1028c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck/*
1038c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * CONVERSIONS
1048c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * Rounding and limit checking is only done on the TO_REG variants.
1058c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck */
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These constants are a guess, consistent w/ w83781d */
1088c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck#define ASB100_IN_MIN		0
1098c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck#define ASB100_IN_MAX		4080
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1118c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck/*
1128c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * IN: 1/1000 V (0V to 4.08V)
1138c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * REG: 16mV/bit
1148c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck */
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 IN_TO_REG(unsigned val)
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1172a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	unsigned nval = clamp_val(val, ASB100_IN_MIN, ASB100_IN_MAX);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (nval + 8) / 16;
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned IN_FROM_REG(u8 reg)
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return reg * 16;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 FAN_TO_REG(long rpm, int div)
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rpm == -1)
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rpm == 0)
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 255;
1322a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	rpm = clamp_val(rpm, 1, 1000000);
1332a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int FAN_FROM_REG(u8 val, int div)
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1388c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	return val == 0 ? -1 : val == 255 ? 0 : 1350000 / (val * div);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These constants are a guess, consistent w/ w83781d */
1428c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck#define ASB100_TEMP_MIN		-128000
1438c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck#define ASB100_TEMP_MAX		127000
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1458c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck/*
1468c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * TEMP: 0.001C/bit (-128C to +127C)
1478c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * REG: 1C/bit, two's complement
1488c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck */
1495bfedac045082a97e20d47d876071279ef984d28Christian Hohnstaedtstatic u8 TEMP_TO_REG(long temp)
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1512a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	int ntemp = clamp_val(temp, ASB100_TEMP_MIN, ASB100_TEMP_MAX);
1528c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	ntemp += (ntemp < 0 ? -500 : 500);
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (u8)(ntemp / 1000);
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int TEMP_FROM_REG(u8 reg)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (s8)reg * 1000;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1618c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck/*
1628c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * PWM: 0 - 255 per sensors documentation
1638c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * REG: (6.25% duty cycle per bit)
1648c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck */
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 ASB100_PWM_TO_REG(int pwm)
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1672a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	pwm = clamp_val(pwm, 0, 255);
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (u8)(pwm / 16);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ASB100_PWM_FROM_REG(u8 reg)
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return reg * 16;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1 << (val))
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1788c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck/*
1798c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * FAN DIV: 1, 2, 4, or 8 (defaults to 2)
1808c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * REG: 0, 1, 2, or 3 (respectively) (defaults to 1)
1818c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck */
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 DIV_TO_REG(long val)
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1848c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	return val == 8 ? 3 : val == 4 ? 2 : val == 1 ? 0 : 1;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1878c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck/*
1888c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * For each registered client, we need to keep some data in memory. That
1898c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * data is pointed to by client->data. The structure itself is
1908c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * dynamically allocated, at the same time the client itself is allocated.
1918c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck */
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct asb100_data {
1931beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	struct device *hwmon_dev;
1949a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex lock;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1969a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex update_lock;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_updated;	/* In jiffies */
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* array of 2 pointers to subclients */
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *lm75[2];
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char valid;		/* !=0 if following fields are valid */
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in[7];		/* Register value */
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_max[7];		/* Register value */
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_min[7];		/* Register value */
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan[3];		/* Register value */
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_min[3];		/* Register value */
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 temp[4];		/* Register value (0 and 3 are u8 only) */
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 temp_max[4];	/* Register value (0 and 3 are u8 only) */
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 temp_hyst[4];	/* Register value (0 and 3 are u8 only) */
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_div[3];		/* Register encoding, right justified */
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 pwm;			/* Register encoding */
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vid;			/* Register encoding, combined */
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 alarms;		/* Register encoding, combined */
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vrm;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int asb100_read_value(struct i2c_client *client, u16 reg);
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void asb100_write_value(struct i2c_client *client, u16 reg, u16 val);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic int asb100_probe(struct i2c_client *client,
222063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare			const struct i2c_device_id *id);
223310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int asb100_detect(struct i2c_client *client,
224063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare			 struct i2c_board_info *info);
225063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic int asb100_remove(struct i2c_client *client);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct asb100_data *asb100_update_device(struct device *dev);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void asb100_init_client(struct i2c_client *client);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
229063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic const struct i2c_device_id asb100_id[] = {
2301f86df49ddfd0067cce941187d57b2fd2f749a9eJean Delvare	{ "asb100", 0 },
231063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	{ }
232063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare};
233063675b15608dfbb8404b3a19546d579bd039d02Jean DelvareMODULE_DEVICE_TABLE(i2c, asb100_id);
234063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_driver asb100_driver = {
236063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	.class		= I2C_CLASS_HWMON,
237cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	.driver = {
238cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard		.name	= "asb100",
239cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	},
240063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	.probe		= asb100_probe,
241063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	.remove		= asb100_remove,
242063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	.id_table	= asb100_id,
243063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	.detect		= asb100_detect,
244c3813d6af177fab19e322f3114b1f64fbcf08d71Jean Delvare	.address_list	= normal_i2c,
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7 Voltages */
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define show_in_reg(reg) \
249fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
250fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		char *buf) \
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
252fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	int nr = to_sensor_dev_attr(attr)->index; \
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = asb100_update_device(dev); \
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_in_reg(in)
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_in_reg(in_min)
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_in_reg(in_max)
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define set_in_reg(REG, reg) \
262fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t set_in_##reg(struct device *dev, struct device_attribute *attr, \
263fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		const char *buf, size_t count) \
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
265fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	int nr = to_sensor_dev_attr(attr)->index; \
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev); \
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = i2c_get_clientdata(client); \
2688c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	unsigned long val; \
2698c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	int err = kstrtoul(buf, 10, &val); \
2708c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	if (err) \
2718c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck		return err; \
2729a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock); \
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_##reg[nr] = IN_TO_REG(val); \
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	asb100_write_value(client, ASB100_REG_IN_##REG(nr), \
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->in_##reg[nr]); \
2769a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock); \
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count; \
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_in_reg(MIN, min)
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_in_reg(MAX, max)
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sysfs_in(offset) \
284fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
285fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		show_in, NULL, offset); \
286fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
287fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		show_in_min, set_in_min, offset); \
288fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
289fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		show_in_max, set_in_max, offset)
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(0);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(1);
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(2);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(3);
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(4);
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(5);
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(6);
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3 Fans */
300fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t show_fan(struct device *dev, struct device_attribute *attr,
301fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		char *buf)
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
303fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	int nr = to_sensor_dev_attr(attr)->index;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = asb100_update_device(dev);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DIV_FROM_REG(data->fan_div[nr])));
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
309fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
310fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		char *buf)
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
312fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	int nr = to_sensor_dev_attr(attr)->index;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = asb100_update_device(dev);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DIV_FROM_REG(data->fan_div[nr])));
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
318fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
319fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		char *buf)
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
321fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	int nr = to_sensor_dev_attr(attr)->index;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = asb100_update_device(dev);
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
326fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
327fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		const char *buf, size_t count)
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
329fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	int nr = to_sensor_dev_attr(attr)->index;
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = i2c_get_clientdata(client);
3328c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	unsigned long val;
3338c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	int err;
3348c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck
3358c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	err = kstrtoul(buf, 10, &val);
3368c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	if (err)
3378c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck		return err;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3399a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]);
3429a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3468c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck/*
3478c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * Note: we save and restore the fan minimum here, because its value is
3488c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * determined in part by the fan divisor.  This follows the principle of
3498c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * least surprise; the user doesn't expect the fan minimum to change just
3508c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * because the divisor changed.
3518c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck */
352fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
353fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		const char *buf, size_t count)
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
355fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	int nr = to_sensor_dev_attr(attr)->index;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = i2c_get_clientdata(client);
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long min;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int reg;
3608c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	unsigned long val;
3618c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	int err;
3628c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck
3638c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	err = kstrtoul(buf, 10, &val);
3648c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	if (err)
3658c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck		return err;
366af221931519571028c98cf7c7030dd973a524011Jean Delvare
3679a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	min = FAN_FROM_REG(data->fan_min[nr],
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DIV_FROM_REG(data->fan_div[nr]));
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_div[nr] = DIV_TO_REG(val);
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
373af221931519571028c98cf7c7030dd973a524011Jean Delvare	switch (nr) {
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0:	/* fan 1 */
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reg = asb100_read_value(client, ASB100_REG_VID_FANDIV);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reg = (reg & 0xcf) | (data->fan_div[0] << 4);
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		asb100_write_value(client, ASB100_REG_VID_FANDIV, reg);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:	/* fan 2 */
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reg = asb100_read_value(client, ASB100_REG_VID_FANDIV);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reg = (reg & 0x3f) | (data->fan_div[1] << 6);
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		asb100_write_value(client, ASB100_REG_VID_FANDIV, reg);
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:	/* fan 3 */
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reg = asb100_read_value(client, ASB100_REG_PIN);
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reg = (reg & 0x3f) | (data->fan_div[2] << 6);
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		asb100_write_value(client, ASB100_REG_PIN, reg);
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] =
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]);
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3979a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sysfs_fan(offset) \
403fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
404fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		show_fan, NULL, offset - 1); \
405fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
406fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		show_fan_min, set_fan_min, offset - 1); \
407fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
408fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		show_fan_div, set_fan_div, offset - 1)
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_fan(1);
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_fan(2);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_fan(3);
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4 Temp. Sensors */
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sprintf_temp_from_reg(u16 reg, char *buf, int nr)
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (nr) {
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1: case 2:
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(reg));
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0: case 3: default:
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = sprintf(buf, "%d\n", TEMP_FROM_REG(reg));
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
429af221931519571028c98cf7c7030dd973a524011Jean Delvare
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define show_temp_reg(reg) \
431fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
432fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		char *buf) \
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
434fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	int nr = to_sensor_dev_attr(attr)->index; \
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = asb100_update_device(dev); \
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf_temp_from_reg(data->reg[nr], buf, nr); \
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_temp_reg(temp);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_temp_reg(temp_max);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_temp_reg(temp_hyst);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define set_temp_reg(REG, reg) \
444fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t set_##reg(struct device *dev, struct device_attribute *attr, \
445fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		const char *buf, size_t count) \
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
447fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	int nr = to_sensor_dev_attr(attr)->index; \
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev); \
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = i2c_get_clientdata(client); \
4508c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	long val; \
4518c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	int err = kstrtol(buf, 10, &val); \
4528c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	if (err) \
4538c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck		return err; \
4549a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock); \
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (nr) { \
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1: case 2: \
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->reg[nr] = LM75_TEMP_TO_REG(val); \
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break; \
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0: case 3: default: \
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->reg[nr] = TEMP_TO_REG(val); \
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break; \
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} \
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	asb100_write_value(client, ASB100_REG_TEMP_##REG(nr+1), \
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->reg[nr]); \
4659a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock); \
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count; \
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_temp_reg(MAX, temp_max);
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_temp_reg(HYST, temp_hyst);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sysfs_temp(num) \
473fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(temp##num##_input, S_IRUGO, \
474fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		show_temp, NULL, num - 1); \
475fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \
476fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		show_temp_max, set_temp_max, num - 1); \
477fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(temp##num##_max_hyst, S_IRUGO | S_IWUSR, \
478fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare		show_temp_hyst, set_temp_hyst, num - 1)
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_temp(1);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_temp(2);
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_temp(3);
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_temp(4);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* VID */
486af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t show_vid(struct device *dev, struct device_attribute *attr,
487af221931519571028c98cf7c7030dd973a524011Jean Delvare		char *buf)
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = asb100_update_device(dev);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* VRM */
496af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
497af221931519571028c98cf7c7030dd973a524011Jean Delvare		char *buf)
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
49990d6619a916062cb75a176aacb318d108758b4a5Jean Delvare	struct asb100_data *data = dev_get_drvdata(dev);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%d\n", data->vrm);
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
503af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
504af221931519571028c98cf7c7030dd973a524011Jean Delvare		const char *buf, size_t count)
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5068f74efe81d122c071410fd74f42879ef81439fa4Jean Delvare	struct asb100_data *data = dev_get_drvdata(dev);
5078c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	unsigned long val;
5088c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	int err;
5098c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck
5108c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	err = kstrtoul(buf, 10, &val);
5118c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	if (err)
5128c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck		return err;
513db59ac434230c2d6c051bb314f320ad977e6841dAxel Lin
514db59ac434230c2d6c051bb314f320ad977e6841dAxel Lin	if (val > 255)
515db59ac434230c2d6c051bb314f320ad977e6841dAxel Lin		return -EINVAL;
516db59ac434230c2d6c051bb314f320ad977e6841dAxel Lin
5178c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	data->vrm = val;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Alarms */
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
524af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
525af221931519571028c98cf7c7030dd973a524011Jean Delvare		char *buf)
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = asb100_update_device(dev);
52868188ba7de2db9999ff08a4544a78b2f10eb08bdJean Delvare	return sprintf(buf, "%u\n", data->alarms);
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
533636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
534636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare		char *buf)
535636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare{
536636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
537636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	struct asb100_data *data = asb100_update_device(dev);
538636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
539636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare}
540636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
541636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
542636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
543636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
544636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
545636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
546636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
547636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
548636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
549636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
550636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
551636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1 PWM */
553af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t show_pwm1(struct device *dev, struct device_attribute *attr,
554af221931519571028c98cf7c7030dd973a524011Jean Delvare		char *buf)
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = asb100_update_device(dev);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%d\n", ASB100_PWM_FROM_REG(data->pwm & 0x0f));
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
560af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t set_pwm1(struct device *dev, struct device_attribute *attr,
561af221931519571028c98cf7c7030dd973a524011Jean Delvare		const char *buf, size_t count)
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = i2c_get_clientdata(client);
5658c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	unsigned long val;
5668c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	int err;
5678c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck
5688c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	err = kstrtoul(buf, 10, &val);
5698c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	if (err)
5708c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck		return err;
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5729a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->pwm &= 0x80; /* keep the enable bit */
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->pwm |= (0x0f & ASB100_PWM_TO_REG(val));
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	asb100_write_value(client, ASB100_REG_PWM1, data->pwm);
5769a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
580af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t show_pwm_enable1(struct device *dev,
581af221931519571028c98cf7c7030dd973a524011Jean Delvare		struct device_attribute *attr, char *buf)
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = asb100_update_device(dev);
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%d\n", (data->pwm & 0x80) ? 1 : 0);
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
587af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t set_pwm_enable1(struct device *dev,
588af221931519571028c98cf7c7030dd973a524011Jean Delvare		struct device_attribute *attr, const char *buf, size_t count)
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = i2c_get_clientdata(client);
5928c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	unsigned long val;
5938c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	int err;
5948c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck
5958c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	err = kstrtoul(buf, 10, &val);
5968c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	if (err)
5978c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck		return err;
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5999a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->pwm &= 0x0f; /* keep the duty cycle bits */
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->pwm |= (val ? 0x80 : 0x00);
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	asb100_write_value(client, ASB100_REG_PWM1, data->pwm);
6039a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		show_pwm_enable1, set_pwm_enable1);
610c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
611c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *asb100_attributes[] = {
612fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in0_input.dev_attr.attr,
613fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in0_min.dev_attr.attr,
614fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in0_max.dev_attr.attr,
615fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in1_input.dev_attr.attr,
616fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in1_min.dev_attr.attr,
617fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in1_max.dev_attr.attr,
618fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in2_input.dev_attr.attr,
619fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in2_min.dev_attr.attr,
620fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in2_max.dev_attr.attr,
621fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in3_input.dev_attr.attr,
622fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in3_min.dev_attr.attr,
623fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in3_max.dev_attr.attr,
624fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in4_input.dev_attr.attr,
625fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in4_min.dev_attr.attr,
626fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in4_max.dev_attr.attr,
627fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in5_input.dev_attr.attr,
628fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in5_min.dev_attr.attr,
629fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in5_max.dev_attr.attr,
630fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in6_input.dev_attr.attr,
631fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in6_min.dev_attr.attr,
632fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_in6_max.dev_attr.attr,
633fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare
634fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_fan1_input.dev_attr.attr,
635fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_fan1_min.dev_attr.attr,
636fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_fan1_div.dev_attr.attr,
637fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_fan2_input.dev_attr.attr,
638fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_fan2_min.dev_attr.attr,
639fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_fan2_div.dev_attr.attr,
640fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_fan3_input.dev_attr.attr,
641fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_fan3_min.dev_attr.attr,
642fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_fan3_div.dev_attr.attr,
643fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare
644fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp1_input.dev_attr.attr,
645fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp1_max.dev_attr.attr,
646fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
647fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp2_input.dev_attr.attr,
648fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp2_max.dev_attr.attr,
649fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
650fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp3_input.dev_attr.attr,
651fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp3_max.dev_attr.attr,
652fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
653fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp4_input.dev_attr.attr,
654fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp4_max.dev_attr.attr,
655fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare	&sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
656c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
657636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_in0_alarm.dev_attr.attr,
658636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_in1_alarm.dev_attr.attr,
659636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_in2_alarm.dev_attr.attr,
660636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_in3_alarm.dev_attr.attr,
661636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_in4_alarm.dev_attr.attr,
662636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
663636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
664636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
665636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
666636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
667636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
668636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare
669c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_cpu0_vid.attr,
670c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_vrm.attr,
671c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_alarms.attr,
672c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_pwm1.attr,
673c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	&dev_attr_pwm1_enable.attr,
674c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
675c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	NULL
676c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
677c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
678c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group asb100_group = {
679c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman	.attrs = asb100_attributes,
680c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman};
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
682063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic int asb100_detect_subclients(struct i2c_client *client)
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, id, err;
685063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	int address = client->addr;
686063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	unsigned short sc_addr[2];
687af221931519571028c98cf7c7030dd973a524011Jean Delvare	struct asb100_data *data = i2c_get_clientdata(client);
688063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	struct i2c_adapter *adapter = client->adapter;
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	id = i2c_adapter_id(adapter);
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (force_subclients[0] == id && force_subclients[1] == address) {
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 2; i <= 3; i++) {
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (force_subclients[i] < 0x48 ||
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    force_subclients[i] > 0x4f) {
696b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck				dev_err(&client->dev,
697b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck					"invalid subclient address %d; must be 0x48-0x4f\n",
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					force_subclients[i]);
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err = -ENODEV;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto ERROR_SC_2;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
703af221931519571028c98cf7c7030dd973a524011Jean Delvare		asb100_write_value(client, ASB100_REG_I2C_SUBADDR,
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(force_subclients[2] & 0x07) |
705af221931519571028c98cf7c7030dd973a524011Jean Delvare					((force_subclients[3] & 0x07) << 4));
706063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare		sc_addr[0] = force_subclients[2];
707063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare		sc_addr[1] = force_subclients[3];
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
709af221931519571028c98cf7c7030dd973a524011Jean Delvare		int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR);
710063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare		sc_addr[0] = 0x48 + (val & 0x07);
711063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare		sc_addr[1] = 0x48 + ((val >> 4) & 0x07);
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
714063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	if (sc_addr[0] == sc_addr[1]) {
715b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck		dev_err(&client->dev,
716b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck			"duplicate addresses 0x%x for subclients\n",
717b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck			sc_addr[0]);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENODEV;
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR_SC_2;
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
722063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]);
723063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	if (!data->lm75[0]) {
724b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck		dev_err(&client->dev,
725b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck			"subclient %d registration at address 0x%x failed.\n",
726b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck			1, sc_addr[0]);
727063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare		err = -ENOMEM;
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR_SC_2;
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]);
732063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	if (!data->lm75[1]) {
733b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck		dev_err(&client->dev,
734b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck			"subclient %d registration at address 0x%x failed.\n",
735b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck			2, sc_addr[1]);
736063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare		err = -ENOMEM;
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto ERROR_SC_3;
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Undo inits in case of errors */
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsERROR_SC_3:
744063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	i2c_unregister_device(data->lm75[0]);
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsERROR_SC_2:
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
749063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare/* Return 0 if detection is successful, -ENODEV otherwise */
750310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int asb100_detect(struct i2c_client *client,
751063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare			 struct i2c_board_info *info)
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
753063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	struct i2c_adapter *adapter = client->adapter;
75452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	int val1, val2;
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
7574d630e2ba59a231c8e5031cc55e16737aa59af97Joe Perches		pr_debug("detect failed, smbus byte data not supported!\n");
758063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare		return -ENODEV;
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
76152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK);
76252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
76452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	/* If we're in bank 0 */
76552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	if ((!(val1 & 0x07)) &&
76652df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			/* Check for ASB100 ID (low byte) */
76752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			(((!(val1 & 0x80)) && (val2 != 0x94)) ||
76852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			/* Check for ASB100 ID (high byte ) */
76952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			((val1 & 0x80) && (val2 != 0x06)))) {
7704d630e2ba59a231c8e5031cc55e16737aa59af97Joe Perches		pr_debug("detect failed, bad chip id 0x%02x!\n", val2);
77152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		return -ENODEV;
77252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	}
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
77452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	/* Put it now into bank 0 and Vendor ID High Byte */
775063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	i2c_smbus_write_byte_data(client, ASB100_REG_BANK,
776063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare		(i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78)
777063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare		| 0x80);
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Determine the chip type. */
78052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID);
78152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
78252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare
78352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	if (val1 != 0x31 || val2 != 0x06)
78452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		return -ENODEV;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
786063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	strlcpy(info->type, "asb100", I2C_NAME_SIZE);
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
788063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	return 0;
789063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare}
790063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare
791063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic int asb100_probe(struct i2c_client *client,
792063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare			const struct i2c_device_id *id)
793063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare{
794063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	int err;
795063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	struct asb100_data *data;
796063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare
79764adf39837c7cf744161b18598577cbe2467a01dGuenter Roeck	data = devm_kzalloc(&client->dev, sizeof(struct asb100_data),
79864adf39837c7cf744161b18598577cbe2467a01dGuenter Roeck			    GFP_KERNEL);
79964adf39837c7cf744161b18598577cbe2467a01dGuenter Roeck	if (!data)
80064adf39837c7cf744161b18598577cbe2467a01dGuenter Roeck		return -ENOMEM;
801063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare
802063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	i2c_set_clientdata(client, data);
803063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	mutex_init(&data->lock);
804063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	mutex_init(&data->update_lock);
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Attach secondary lm75 clients */
807063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	err = asb100_detect_subclients(client);
808063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	if (err)
80964adf39837c7cf744161b18598577cbe2467a01dGuenter Roeck		return err;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the chip */
812af221931519571028c98cf7c7030dd973a524011Jean Delvare	asb100_init_client(client);
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* A few vars need to be filled upon startup */
815af221931519571028c98cf7c7030dd973a524011Jean Delvare	data->fan_min[0] = asb100_read_value(client, ASB100_REG_FAN_MIN(0));
816af221931519571028c98cf7c7030dd973a524011Jean Delvare	data->fan_min[1] = asb100_read_value(client, ASB100_REG_FAN_MIN(1));
817af221931519571028c98cf7c7030dd973a524011Jean Delvare	data->fan_min[2] = asb100_read_value(client, ASB100_REG_FAN_MIN(2));
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Register sysfs hooks */
8208c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	err = sysfs_create_group(&client->dev.kobj, &asb100_group);
8218c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck	if (err)
822c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman		goto ERROR3;
823c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman
824af221931519571028c98cf7c7030dd973a524011Jean Delvare	data->hwmon_dev = hwmon_device_register(&client->dev);
8251beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	if (IS_ERR(data->hwmon_dev)) {
8261beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones		err = PTR_ERR(data->hwmon_dev);
827c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman		goto ERROR4;
828943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	}
829943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
832c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. HoffmanERROR4:
833af221931519571028c98cf7c7030dd973a524011Jean Delvare	sysfs_remove_group(&client->dev.kobj, &asb100_group);
834943b0830cebe4711354945ed3cb44e84152aaca0Mark M. HoffmanERROR3:
835063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	i2c_unregister_device(data->lm75[1]);
836063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	i2c_unregister_device(data->lm75[0]);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
840063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic int asb100_remove(struct i2c_client *client)
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
842943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	struct asb100_data *data = i2c_get_clientdata(client);
843943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
844063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	hwmon_device_unregister(data->hwmon_dev);
845063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	sysfs_remove_group(&client->dev.kobj, &asb100_group);
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
847063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	i2c_unregister_device(data->lm75[1]);
848063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare	i2c_unregister_device(data->lm75[0]);
849943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8538c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck/*
8548c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * The SMBus locks itself, usually, but nothing may access the chip between
8558c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck * bank switches.
8568c103696fa59e1b810bf24a63304acd5ab585c12Guenter Roeck */
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int asb100_read_value(struct i2c_client *client, u16 reg)
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = i2c_get_clientdata(client);
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *cl;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res, bank;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8639a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bank = (reg >> 8) & 0x0f;
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bank > 2)
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* switch banks */
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_smbus_write_byte_data(client, ASB100_REG_BANK, bank);
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bank == 0 || bank > 2) {
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = i2c_smbus_read_byte_data(client, reg & 0xff);
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* switch to subclient */
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cl = data->lm75[bank - 1];
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* convert from ISA to LM75 I2C addresses */
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (reg & 0xff) {
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x50: /* TEMP */
87990f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare			res = i2c_smbus_read_word_swapped(cl, 0);
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x52: /* CONFIG */
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			res = i2c_smbus_read_byte_data(cl, 1);
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x53: /* HYST */
88590f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare			res = i2c_smbus_read_word_swapped(cl, 2);
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x55: /* MAX */
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
88990f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare			res = i2c_smbus_read_word_swapped(cl, 3);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bank > 2)
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0);
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8979a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void asb100_write_value(struct i2c_client *client, u16 reg, u16 value)
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = i2c_get_clientdata(client);
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *cl;
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int bank;
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9089a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->lock);
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bank = (reg >> 8) & 0x0f;
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bank > 2)
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* switch banks */
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_smbus_write_byte_data(client, ASB100_REG_BANK, bank);
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bank == 0 || bank > 2) {
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_smbus_write_byte_data(client, reg & 0xff, value & 0xff);
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* switch to subclient */
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cl = data->lm75[bank - 1];
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* convert from ISA to LM75 I2C addresses */
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (reg & 0xff) {
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x52: /* CONFIG */
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i2c_smbus_write_byte_data(cl, 1, value & 0xff);
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x53: /* HYST */
92790f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare			i2c_smbus_write_word_swapped(cl, 2, value);
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x55: /* MAX */
93090f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare			i2c_smbus_write_word_swapped(cl, 3, value);
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bank > 2)
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0);
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9389a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->lock);
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void asb100_init_client(struct i2c_client *client)
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = i2c_get_clientdata(client);
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
945303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare	data->vrm = vid_which_vrm();
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start monitoring */
948af221931519571028c98cf7c7030dd973a524011Jean Delvare	asb100_write_value(client, ASB100_REG_CONFIG,
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(asb100_read_value(client, ASB100_REG_CONFIG) & 0xf7) | 0x01);
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct asb100_data *asb100_update_device(struct device *dev)
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct asb100_data *data = i2c_get_clientdata(client);
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9589a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| !data->valid) {
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "starting device update...\n");
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* 7 voltage inputs */
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < 7; i++) {
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in[i] = asb100_read_value(client,
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ASB100_REG_IN(i));
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_min[i] = asb100_read_value(client,
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ASB100_REG_IN_MIN(i));
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_max[i] = asb100_read_value(client,
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ASB100_REG_IN_MAX(i));
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* 3 fan inputs */
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < 3; i++) {
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan[i] = asb100_read_value(client,
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ASB100_REG_FAN(i));
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan_min[i] = asb100_read_value(client,
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ASB100_REG_FAN_MIN(i));
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* 4 temperature inputs */
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 1; i <= 4; i++) {
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp[i-1] = asb100_read_value(client,
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ASB100_REG_TEMP(i));
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp_max[i-1] = asb100_read_value(client,
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ASB100_REG_TEMP_MAX(i));
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp_hyst[i-1] = asb100_read_value(client,
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ASB100_REG_TEMP_HYST(i));
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* VID and fan divisors */
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = asb100_read_value(client, ASB100_REG_VID_FANDIV);
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vid = i & 0x0f;
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->vid |= (asb100_read_value(client,
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ASB100_REG_CHIPID) & 0x01) << 4;
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[0] = (i >> 4) & 0x03;
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[1] = (i >> 6) & 0x03;
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[2] = (asb100_read_value(client,
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ASB100_REG_PIN) >> 6) & 0x03;
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* PWM */
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm = asb100_read_value(client, ASB100_REG_PWM1);
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* alarms */
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarms = asb100_read_value(client, ASB100_REG_ALARM1) +
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(asb100_read_value(client, ASB100_REG_ALARM2) << 8);
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_updated = jiffies;
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->valid = 1;
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "... device update complete\n");
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10169a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return data;
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(asb100_driver);
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ASB100 Bach driver");
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1026