asb100.c revision 310ec79210d754afe51e2e4a983e846b60179abd
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100.c - Part of lm_sensors, Linux kernel modules for hardware 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monitoring 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 2004 Mark M. Hoffman <mhoffman@lightlink.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (derived from w83781d.c) 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 1998 - 2003 Frodo Looijaard <frodol@dds.nl>, 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Philip Edelbrock <phil@netroedge.com>, and 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Mark Studebaker <mdsxyz123@yahoo.com> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This driver supports the hardware sensor chips: Asus ASB100 and 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100-A "BACH". 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100-A supports pwm1, while plain ASB100 does not. There is no known 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds way for the driver to tell which one is there. 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100 7 3 1 4 0x31 0x0694 yes no 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h> 42943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/hwmon.h> 43fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare#include <linux/hwmon-sysfs.h> 44303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare#include <linux/hwmon-vid.h> 45943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/err.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 47ff3240946d6a3d9f2ecf273f7330e09eec5484ebDominik Hackl#include <linux/jiffies.h> 489a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar#include <linux/mutex.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "lm75.h" 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* I2C addresses to scan */ 5225e9c86d5a6d82ea45eb680fc66bf73ac5e50dffMark M. Hoffmanstatic const unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Insmod parameters */ 55f4b50261207c987913f076d867c2e154d71fd012Jean DelvareI2C_CLIENT_INSMOD_1(asb100); 563aed198c35567e5a721f52c0bde23167867e6af6Jean Delvare 573aed198c35567e5a721f52c0bde23167867e6af6Jean Delvarestatic unsigned short force_subclients[4]; 583aed198c35567e5a721f52c0bde23167867e6af6Jean Delvaremodule_param_array(force_subclients, short, NULL, 0); 593aed198c35567e5a721f52c0bde23167867e6af6Jean DelvareMODULE_PARM_DESC(force_subclients, "List of subclient addresses: " 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "{bus, clientaddr, subclientaddr1, subclientaddr2}"); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Voltage IN registers 0-6 */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_IN(nr) (0x20 + (nr)) 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_IN_MAX(nr) (0x2b + (nr * 2)) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_IN_MIN(nr) (0x2c + (nr * 2)) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FAN IN registers 1-3 */ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_FAN(nr) (0x28 + (nr)) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_FAN_MIN(nr) (0x3b + (nr)) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TEMPERATURE registers 1-4 */ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u16 asb100_reg_temp[] = {0, 0x27, 0x150, 0x250, 0x17}; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u16 asb100_reg_temp_max[] = {0, 0x39, 0x155, 0x255, 0x18}; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u16 asb100_reg_temp_hyst[] = {0, 0x3a, 0x153, 0x253, 0x19}; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_TEMP(nr) (asb100_reg_temp[nr]) 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_TEMP_MAX(nr) (asb100_reg_temp_max[nr]) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_TEMP_HYST(nr) (asb100_reg_temp_hyst[nr]) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_TEMP2_CONFIG 0x0152 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_TEMP3_CONFIG 0x0252 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_CONFIG 0x40 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_ALARM1 0x41 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_ALARM2 0x42 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_SMIM1 0x43 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_SMIM2 0x44 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_VID_FANDIV 0x47 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_I2C_ADDR 0x48 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_CHIPID 0x49 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_I2C_SUBADDR 0x4a 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_PIN 0x4b 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_IRQ 0x4c 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_BANK 0x4e 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_CHIPMAN 0x4f 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_WCHIPID 0x58 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* bit 7 -> enable, bits 0-3 -> duty cycle */ 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_REG_PWM1 0x59 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CONVERSIONS 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Rounding and limit checking is only done on the TO_REG variants. */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These constants are a guess, consistent w/ w83781d */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_IN_MIN ( 0) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_IN_MAX (4080) 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* IN: 1/1000 V (0V to 4.08V) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REG: 16mV/bit */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 IN_TO_REG(unsigned val) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned nval = SENSORS_LIMIT(val, ASB100_IN_MIN, ASB100_IN_MAX); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (nval + 8) / 16; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned IN_FROM_REG(u8 reg) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return reg * 16; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 FAN_TO_REG(long rpm, int div) 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rpm == -1) 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rpm == 0) 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 255; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpm = SENSORS_LIMIT(rpm, 1, 1000000); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int FAN_FROM_REG(u8 val, int div) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These constants are a guess, consistent w/ w83781d */ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_TEMP_MIN (-128000) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ASB100_TEMP_MAX ( 127000) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TEMP: 0.001C/bit (-128C to +127C) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REG: 1C/bit, two's complement */ 1445bfedac045082a97e20d47d876071279ef984d28Christian Hohnstaedtstatic u8 TEMP_TO_REG(long temp) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ntemp = SENSORS_LIMIT(temp, ASB100_TEMP_MIN, ASB100_TEMP_MAX); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ntemp += (ntemp<0 ? -500 : 500); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (u8)(ntemp / 1000); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int TEMP_FROM_REG(u8 reg) 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (s8)reg * 1000; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* PWM: 0 - 255 per sensors documentation 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REG: (6.25% duty cycle per bit) */ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 ASB100_PWM_TO_REG(int pwm) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pwm = SENSORS_LIMIT(pwm, 0, 255); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (u8)(pwm / 16); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ASB100_PWM_FROM_REG(u8 reg) 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return reg * 16; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1 << (val)) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FAN DIV: 1, 2, 4, or 8 (defaults to 2) 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REG: 0, 1, 2, or 3 (respectively) (defaults to 1) */ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 DIV_TO_REG(long val) 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* For each registered client, we need to keep some data in memory. That 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data is pointed to by client->data. The structure itself is 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dynamically allocated, at the same time the client itself is allocated. */ 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct asb100_data { 1821beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones struct device *hwmon_dev; 1839a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar struct mutex lock; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1859a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar struct mutex update_lock; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long last_updated; /* In jiffies */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* array of 2 pointers to subclients */ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *lm75[2]; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char valid; /* !=0 if following fields are valid */ 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 in[7]; /* Register value */ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 in_max[7]; /* Register value */ 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 in_min[7]; /* Register value */ 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 fan[3]; /* Register value */ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 fan_min[3]; /* Register value */ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 temp[4]; /* Register value (0 and 3 are u8 only) */ 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 temp_max[4]; /* Register value (0 and 3 are u8 only) */ 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 temp_hyst[4]; /* Register value (0 and 3 are u8 only) */ 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 fan_div[3]; /* Register encoding, right justified */ 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 pwm; /* Register encoding */ 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 vid; /* Register encoding, combined */ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 alarms; /* Register encoding, combined */ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 vrm; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int asb100_read_value(struct i2c_client *client, u16 reg); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void asb100_write_value(struct i2c_client *client, u16 reg, u16 val); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 210063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic int asb100_probe(struct i2c_client *client, 211063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare const struct i2c_device_id *id); 212310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int asb100_detect(struct i2c_client *client, 213063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare struct i2c_board_info *info); 214063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic int asb100_remove(struct i2c_client *client); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct asb100_data *asb100_update_device(struct device *dev); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void asb100_init_client(struct i2c_client *client); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 218063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic const struct i2c_device_id asb100_id[] = { 219063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare { "asb100", asb100 }, 220063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare { } 221063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare}; 222063675b15608dfbb8404b3a19546d579bd039d02Jean DelvareMODULE_DEVICE_TABLE(i2c, asb100_id); 223063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_driver asb100_driver = { 225063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare .class = I2C_CLASS_HWMON, 226cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard .driver = { 227cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard .name = "asb100", 228cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard }, 229063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare .probe = asb100_probe, 230063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare .remove = asb100_remove, 231063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare .id_table = asb100_id, 232063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare .detect = asb100_detect, 233063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare .address_data = &addr_data, 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7 Voltages */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define show_in_reg(reg) \ 238fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ 239fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare char *buf) \ 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \ 241fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare int nr = to_sensor_dev_attr(attr)->index; \ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = asb100_update_device(dev); \ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_in_reg(in) 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_in_reg(in_min) 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_in_reg(in_max) 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define set_in_reg(REG, reg) \ 251fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t set_in_##reg(struct device *dev, struct device_attribute *attr, \ 252fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare const char *buf, size_t count) \ 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \ 254fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare int nr = to_sensor_dev_attr(attr)->index; \ 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); \ 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = i2c_get_clientdata(client); \ 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val = simple_strtoul(buf, NULL, 10); \ 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds \ 2599a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); \ 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_##reg[nr] = IN_TO_REG(val); \ 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100_write_value(client, ASB100_REG_IN_##REG(nr), \ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_##reg[nr]); \ 2639a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); \ 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; \ 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_in_reg(MIN, min) 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_in_reg(MAX, max) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sysfs_in(offset) \ 271fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ 272fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare show_in, NULL, offset); \ 273fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ 274fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare show_in_min, set_in_min, offset); \ 275fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ 276fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare show_in_max, set_in_max, offset) 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(0); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(1); 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(2); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(3); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(4); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(5); 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_in(6); 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3 Fans */ 287fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t show_fan(struct device *dev, struct device_attribute *attr, 288fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare char *buf) 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 290fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare int nr = to_sensor_dev_attr(attr)->index; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = asb100_update_device(dev); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DIV_FROM_REG(data->fan_div[nr]))); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 296fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, 297fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare char *buf) 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 299fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = asb100_update_device(dev); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DIV_FROM_REG(data->fan_div[nr]))); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 305fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, 306fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare char *buf) 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 308fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = asb100_update_device(dev); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 313fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, 314fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare const char *buf, size_t count) 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 316fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = i2c_get_clientdata(client); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 val = simple_strtoul(buf, NULL, 10); 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3219a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); 3249a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Note: we save and restore the fan minimum here, because its value is 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds determined in part by the fan divisor. This follows the principle of 330d6e05edc59ecd79e8badf440c0d295a979bdfa3eAndreas Mohr least surprise; the user doesn't expect the fan minimum to change just 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds because the divisor changed. */ 332fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, 333fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare const char *buf, size_t count) 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 335fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare int nr = to_sensor_dev_attr(attr)->index; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = i2c_get_clientdata(client); 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long min; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val = simple_strtoul(buf, NULL, 10); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int reg; 341af221931519571028c98cf7c7030dd973a524011Jean Delvare 3429a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds min = FAN_FROM_REG(data->fan_min[nr], 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DIV_FROM_REG(data->fan_div[nr])); 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[nr] = DIV_TO_REG(val); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 348af221931519571028c98cf7c7030dd973a524011Jean Delvare switch (nr) { 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: /* fan 1 */ 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = asb100_read_value(client, ASB100_REG_VID_FANDIV); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = (reg & 0xcf) | (data->fan_div[0] << 4); 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100_write_value(client, ASB100_REG_VID_FANDIV, reg); 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: /* fan 2 */ 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = asb100_read_value(client, ASB100_REG_VID_FANDIV); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = (reg & 0x3f) | (data->fan_div[1] << 6); 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100_write_value(client, ASB100_REG_VID_FANDIV, reg); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: /* fan 3 */ 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = asb100_read_value(client, ASB100_REG_PIN); 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = (reg & 0x3f) | (data->fan_div[2] << 6); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100_write_value(client, ASB100_REG_PIN, reg); 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[nr] = 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3729a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sysfs_fan(offset) \ 378fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ 379fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare show_fan, NULL, offset - 1); \ 380fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ 381fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare show_fan_min, set_fan_min, offset - 1); \ 382fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ 383fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare show_fan_div, set_fan_div, offset - 1) 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_fan(1); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_fan(2); 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_fan(3); 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4 Temp. Sensors */ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sprintf_temp_from_reg(u16 reg, char *buf, int nr) 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (nr) { 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: case 2: 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(reg)); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: case 3: default: 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = sprintf(buf, "%d\n", TEMP_FROM_REG(reg)); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 404af221931519571028c98cf7c7030dd973a524011Jean Delvare 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define show_temp_reg(reg) \ 406fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ 407fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare char *buf) \ 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \ 409fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare int nr = to_sensor_dev_attr(attr)->index; \ 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = asb100_update_device(dev); \ 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf_temp_from_reg(data->reg[nr], buf, nr); \ 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_temp_reg(temp); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_temp_reg(temp_max); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsshow_temp_reg(temp_hyst); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define set_temp_reg(REG, reg) \ 419fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic ssize_t set_##reg(struct device *dev, struct device_attribute *attr, \ 420fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare const char *buf, size_t count) \ 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \ 422fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare int nr = to_sensor_dev_attr(attr)->index; \ 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); \ 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = i2c_get_clientdata(client); \ 4255bfedac045082a97e20d47d876071279ef984d28Christian Hohnstaedt long val = simple_strtol(buf, NULL, 10); \ 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds \ 4279a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); \ 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (nr) { \ 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: case 2: \ 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->reg[nr] = LM75_TEMP_TO_REG(val); \ 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; \ 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: case 3: default: \ 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->reg[nr] = TEMP_TO_REG(val); \ 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; \ 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } \ 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100_write_value(client, ASB100_REG_TEMP_##REG(nr+1), \ 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->reg[nr]); \ 4389a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); \ 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; \ 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_temp_reg(MAX, temp_max); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_temp_reg(HYST, temp_hyst); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sysfs_temp(num) \ 446fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(temp##num##_input, S_IRUGO, \ 447fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare show_temp, NULL, num - 1); \ 448fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \ 449fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare show_temp_max, set_temp_max, num - 1); \ 450fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvarestatic SENSOR_DEVICE_ATTR(temp##num##_max_hyst, S_IRUGO | S_IWUSR, \ 451fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare show_temp_hyst, set_temp_hyst, num - 1) 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_temp(1); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_temp(2); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_temp(3); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssysfs_temp(4); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* VID */ 459af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t show_vid(struct device *dev, struct device_attribute *attr, 460af221931519571028c98cf7c7030dd973a524011Jean Delvare char *buf) 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = asb100_update_device(dev); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* VRM */ 469af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t show_vrm(struct device *dev, struct device_attribute *attr, 470af221931519571028c98cf7c7030dd973a524011Jean Delvare char *buf) 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 47290d6619a916062cb75a176aacb318d108758b4a5Jean Delvare struct asb100_data *data = dev_get_drvdata(dev); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%d\n", data->vrm); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 476af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t set_vrm(struct device *dev, struct device_attribute *attr, 477af221931519571028c98cf7c7030dd973a524011Jean Delvare const char *buf, size_t count) 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4798f74efe81d122c071410fd74f42879ef81439fa4Jean Delvare struct asb100_data *data = dev_get_drvdata(dev); 4808f74efe81d122c071410fd74f42879ef81439fa4Jean Delvare data->vrm = simple_strtoul(buf, NULL, 10); 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Alarms */ 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 487af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t show_alarms(struct device *dev, struct device_attribute *attr, 488af221931519571028c98cf7c7030dd973a524011Jean Delvare char *buf) 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = asb100_update_device(dev); 49168188ba7de2db9999ff08a4544a78b2f10eb08bdJean Delvare return sprintf(buf, "%u\n", data->alarms); 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 496636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic ssize_t show_alarm(struct device *dev, struct device_attribute *attr, 497636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare char *buf) 498636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare{ 499636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 500636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare struct asb100_data *data = asb100_update_device(dev); 501636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); 502636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare} 503636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); 504636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); 505636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); 506636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); 507636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); 508636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); 509636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); 510636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); 511636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); 512636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); 513636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13); 514636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1 PWM */ 516af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, 517af221931519571028c98cf7c7030dd973a524011Jean Delvare char *buf) 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = asb100_update_device(dev); 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%d\n", ASB100_PWM_FROM_REG(data->pwm & 0x0f)); 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 523af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, 524af221931519571028c98cf7c7030dd973a524011Jean Delvare const char *buf, size_t count) 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = i2c_get_clientdata(client); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val = simple_strtoul(buf, NULL, 10); 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5309a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm &= 0x80; /* keep the enable bit */ 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm |= (0x0f & ASB100_PWM_TO_REG(val)); 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100_write_value(client, ASB100_REG_PWM1, data->pwm); 5349a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 538af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t show_pwm_enable1(struct device *dev, 539af221931519571028c98cf7c7030dd973a524011Jean Delvare struct device_attribute *attr, char *buf) 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = asb100_update_device(dev); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%d\n", (data->pwm & 0x80) ? 1 : 0); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 545af221931519571028c98cf7c7030dd973a524011Jean Delvarestatic ssize_t set_pwm_enable1(struct device *dev, 546af221931519571028c98cf7c7030dd973a524011Jean Delvare struct device_attribute *attr, const char *buf, size_t count) 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = i2c_get_clientdata(client); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val = simple_strtoul(buf, NULL, 10); 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5529a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm &= 0x0f; /* keep the duty cycle bits */ 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm |= (val ? 0x80 : 0x00); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds asb100_write_value(client, ASB100_REG_PWM1, data->pwm); 5569a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1); 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_pwm_enable1, set_pwm_enable1); 563c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 564c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic struct attribute *asb100_attributes[] = { 565fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in0_input.dev_attr.attr, 566fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in0_min.dev_attr.attr, 567fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in0_max.dev_attr.attr, 568fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in1_input.dev_attr.attr, 569fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in1_min.dev_attr.attr, 570fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in1_max.dev_attr.attr, 571fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in2_input.dev_attr.attr, 572fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in2_min.dev_attr.attr, 573fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in2_max.dev_attr.attr, 574fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in3_input.dev_attr.attr, 575fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in3_min.dev_attr.attr, 576fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in3_max.dev_attr.attr, 577fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in4_input.dev_attr.attr, 578fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in4_min.dev_attr.attr, 579fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in4_max.dev_attr.attr, 580fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in5_input.dev_attr.attr, 581fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in5_min.dev_attr.attr, 582fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in5_max.dev_attr.attr, 583fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in6_input.dev_attr.attr, 584fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in6_min.dev_attr.attr, 585fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_in6_max.dev_attr.attr, 586fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare 587fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_fan1_input.dev_attr.attr, 588fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_fan1_min.dev_attr.attr, 589fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_fan1_div.dev_attr.attr, 590fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_fan2_input.dev_attr.attr, 591fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_fan2_min.dev_attr.attr, 592fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_fan2_div.dev_attr.attr, 593fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_fan3_input.dev_attr.attr, 594fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_fan3_min.dev_attr.attr, 595fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_fan3_div.dev_attr.attr, 596fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare 597fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp1_input.dev_attr.attr, 598fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp1_max.dev_attr.attr, 599fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 600fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp2_input.dev_attr.attr, 601fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp2_max.dev_attr.attr, 602fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, 603fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp3_input.dev_attr.attr, 604fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp3_max.dev_attr.attr, 605fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, 606fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp4_input.dev_attr.attr, 607fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp4_max.dev_attr.attr, 608fad33c5fdae73a75af2f8ecf69147011bd57e28cJean Delvare &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, 609c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 610636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_in0_alarm.dev_attr.attr, 611636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_in1_alarm.dev_attr.attr, 612636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_in2_alarm.dev_attr.attr, 613636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_in3_alarm.dev_attr.attr, 614636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_in4_alarm.dev_attr.attr, 615636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_fan1_alarm.dev_attr.attr, 616636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_fan2_alarm.dev_attr.attr, 617636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_fan3_alarm.dev_attr.attr, 618636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_temp1_alarm.dev_attr.attr, 619636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_temp2_alarm.dev_attr.attr, 620636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare &sensor_dev_attr_temp3_alarm.dev_attr.attr, 621636866b9f0a72583d2361a897668eb19ff37ded6Jean Delvare 622c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman &dev_attr_cpu0_vid.attr, 623c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman &dev_attr_vrm.attr, 624c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman &dev_attr_alarms.attr, 625c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman &dev_attr_pwm1.attr, 626c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman &dev_attr_pwm1_enable.attr, 627c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 628c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman NULL 629c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman}; 630c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 631c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffmanstatic const struct attribute_group asb100_group = { 632c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman .attrs = asb100_attributes, 633c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman}; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 635063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic int asb100_detect_subclients(struct i2c_client *client) 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, id, err; 638063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare int address = client->addr; 639063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare unsigned short sc_addr[2]; 640af221931519571028c98cf7c7030dd973a524011Jean Delvare struct asb100_data *data = i2c_get_clientdata(client); 641063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare struct i2c_adapter *adapter = client->adapter; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id = i2c_adapter_id(adapter); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (force_subclients[0] == id && force_subclients[1] == address) { 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 2; i <= 3; i++) { 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (force_subclients[i] < 0x48 || 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_subclients[i] > 0x4f) { 649af221931519571028c98cf7c7030dd973a524011Jean Delvare dev_err(&client->dev, "invalid subclient " 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "address %d; must be 0x48-0x4f\n", 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_subclients[i]); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENODEV; 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto ERROR_SC_2; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 656af221931519571028c98cf7c7030dd973a524011Jean Delvare asb100_write_value(client, ASB100_REG_I2C_SUBADDR, 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (force_subclients[2] & 0x07) | 658af221931519571028c98cf7c7030dd973a524011Jean Delvare ((force_subclients[3] & 0x07) << 4)); 659063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare sc_addr[0] = force_subclients[2]; 660063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare sc_addr[1] = force_subclients[3]; 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 662af221931519571028c98cf7c7030dd973a524011Jean Delvare int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR); 663063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare sc_addr[0] = 0x48 + (val & 0x07); 664063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare sc_addr[1] = 0x48 + ((val >> 4) & 0x07); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 667063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare if (sc_addr[0] == sc_addr[1]) { 668af221931519571028c98cf7c7030dd973a524011Jean Delvare dev_err(&client->dev, "duplicate addresses 0x%x " 669063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare "for subclients\n", sc_addr[0]); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENODEV; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto ERROR_SC_2; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 674063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]); 675063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare if (!data->lm75[0]) { 676af221931519571028c98cf7c7030dd973a524011Jean Delvare dev_err(&client->dev, "subclient %d registration " 677063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare "at address 0x%x failed.\n", 1, sc_addr[0]); 678063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare err = -ENOMEM; 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto ERROR_SC_2; 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 682063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]); 683063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare if (!data->lm75[1]) { 684af221931519571028c98cf7c7030dd973a524011Jean Delvare dev_err(&client->dev, "subclient %d registration " 685063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare "at address 0x%x failed.\n", 2, sc_addr[1]); 686063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare err = -ENOMEM; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto ERROR_SC_3; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Undo inits in case of errors */ 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsERROR_SC_3: 694063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare i2c_unregister_device(data->lm75[0]); 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsERROR_SC_2: 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 699063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare/* Return 0 if detection is successful, -ENODEV otherwise */ 700310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int asb100_detect(struct i2c_client *client, 701063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare struct i2c_board_info *info) 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 703063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare struct i2c_adapter *adapter = client->adapter; 70452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare int val1, val2; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pr_debug("asb100.o: detect failed, " 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "smbus byte data not supported!\n"); 709063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare return -ENODEV; 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK); 71352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN); 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare /* If we're in bank 0 */ 71652df6440a29123eed912183fe785bbe174ef14b9Jean Delvare if ((!(val1 & 0x07)) && 71752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare /* Check for ASB100 ID (low byte) */ 71852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare (((!(val1 & 0x80)) && (val2 != 0x94)) || 71952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare /* Check for ASB100 ID (high byte ) */ 72052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare ((val1 & 0x80) && (val2 != 0x06)))) { 72152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare pr_debug("asb100: detect failed, bad chip id 0x%02x!\n", val2); 72252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare return -ENODEV; 72352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare } 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 72552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare /* Put it now into bank 0 and Vendor ID High Byte */ 726063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 727063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare (i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78) 728063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare | 0x80); 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Determine the chip type. */ 73152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID); 73252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN); 73352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare 73452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare if (val1 != 0x31 || val2 != 0x06) 73552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare return -ENODEV; 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 737063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare strlcpy(info->type, "asb100", I2C_NAME_SIZE); 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 739063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare return 0; 740063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare} 741063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare 742063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic int asb100_probe(struct i2c_client *client, 743063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare const struct i2c_device_id *id) 744063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare{ 745063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare int err; 746063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare struct asb100_data *data; 747063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare 748063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL); 749063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare if (!data) { 750063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare pr_debug("asb100.o: probe failed, kzalloc failed!\n"); 751063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare err = -ENOMEM; 752063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare goto ERROR0; 753063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare } 754063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare 755063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare i2c_set_clientdata(client, data); 756063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare mutex_init(&data->lock); 757063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare mutex_init(&data->update_lock); 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Attach secondary lm75 clients */ 760063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare err = asb100_detect_subclients(client); 761063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare if (err) 762063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare goto ERROR1; 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the chip */ 765af221931519571028c98cf7c7030dd973a524011Jean Delvare asb100_init_client(client); 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* A few vars need to be filled upon startup */ 768af221931519571028c98cf7c7030dd973a524011Jean Delvare data->fan_min[0] = asb100_read_value(client, ASB100_REG_FAN_MIN(0)); 769af221931519571028c98cf7c7030dd973a524011Jean Delvare data->fan_min[1] = asb100_read_value(client, ASB100_REG_FAN_MIN(1)); 770af221931519571028c98cf7c7030dd973a524011Jean Delvare data->fan_min[2] = asb100_read_value(client, ASB100_REG_FAN_MIN(2)); 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Register sysfs hooks */ 773af221931519571028c98cf7c7030dd973a524011Jean Delvare if ((err = sysfs_create_group(&client->dev.kobj, &asb100_group))) 774c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman goto ERROR3; 775c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman 776af221931519571028c98cf7c7030dd973a524011Jean Delvare data->hwmon_dev = hwmon_device_register(&client->dev); 7771beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones if (IS_ERR(data->hwmon_dev)) { 7781beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones err = PTR_ERR(data->hwmon_dev); 779c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. Hoffman goto ERROR4; 780943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman } 781943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 784c1685f61b0a3110b701d09b84a9f9a3d4e9ef2e2Mark M. HoffmanERROR4: 785af221931519571028c98cf7c7030dd973a524011Jean Delvare sysfs_remove_group(&client->dev.kobj, &asb100_group); 786943b0830cebe4711354945ed3cb44e84152aaca0Mark M. HoffmanERROR3: 787063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare i2c_unregister_device(data->lm75[1]); 788063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare i2c_unregister_device(data->lm75[0]); 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsERROR1: 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(data); 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsERROR0: 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 795063675b15608dfbb8404b3a19546d579bd039d02Jean Delvarestatic int asb100_remove(struct i2c_client *client) 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 797943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman struct asb100_data *data = i2c_get_clientdata(client); 798943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman 799063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare hwmon_device_unregister(data->hwmon_dev); 800063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare sysfs_remove_group(&client->dev.kobj, &asb100_group); 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 802063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare i2c_unregister_device(data->lm75[1]); 803063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare i2c_unregister_device(data->lm75[0]); 804943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman 805063675b15608dfbb8404b3a19546d579bd039d02Jean Delvare kfree(data); 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The SMBus locks itself, usually, but nothing may access the chip between 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bank switches. */ 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int asb100_read_value(struct i2c_client *client, u16 reg) 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = i2c_get_clientdata(client); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *cl; 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res, bank; 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8189a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->lock); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bank = (reg >> 8) & 0x0f; 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bank > 2) 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* switch banks */ 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_smbus_write_byte_data(client, ASB100_REG_BANK, bank); 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bank == 0 || bank > 2) { 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = i2c_smbus_read_byte_data(client, reg & 0xff); 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* switch to subclient */ 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cl = data->lm75[bank - 1]; 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* convert from ISA to LM75 I2C addresses */ 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (reg & 0xff) { 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x50: /* TEMP */ 834af221931519571028c98cf7c7030dd973a524011Jean Delvare res = swab16(i2c_smbus_read_word_data(cl, 0)); 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x52: /* CONFIG */ 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = i2c_smbus_read_byte_data(cl, 1); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x53: /* HYST */ 840af221931519571028c98cf7c7030dd973a524011Jean Delvare res = swab16(i2c_smbus_read_word_data(cl, 2)); 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x55: /* MAX */ 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 844af221931519571028c98cf7c7030dd973a524011Jean Delvare res = swab16(i2c_smbus_read_word_data(cl, 3)); 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bank > 2) 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8529a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->lock); 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void asb100_write_value(struct i2c_client *client, u16 reg, u16 value) 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = i2c_get_clientdata(client); 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *cl; 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int 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 i2c_smbus_write_byte_data(client, reg & 0xff, value & 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 0x52: /* CONFIG */ 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_smbus_write_byte_data(cl, 1, value & 0xff); 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x53: /* HYST */ 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_smbus_write_word_data(cl, 2, swab16(value)); 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x55: /* MAX */ 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_smbus_write_word_data(cl, 3, swab16(value)); 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bank > 2) 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8939a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->lock); 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void asb100_init_client(struct i2c_client *client) 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = i2c_get_clientdata(client); 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 900303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare data->vrm = vid_which_vrm(); 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start monitoring */ 903af221931519571028c98cf7c7030dd973a524011Jean Delvare asb100_write_value(client, ASB100_REG_CONFIG, 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (asb100_read_value(client, ASB100_REG_CONFIG) & 0xf7) | 0x01); 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct asb100_data *asb100_update_device(struct device *dev) 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct asb100_data *data = i2c_get_clientdata(client); 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9139a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || !data->valid) { 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "starting device update...\n"); 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7 voltage inputs */ 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 7; i++) { 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in[i] = asb100_read_value(client, 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100_REG_IN(i)); 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_min[i] = asb100_read_value(client, 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100_REG_IN_MIN(i)); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_max[i] = asb100_read_value(client, 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100_REG_IN_MAX(i)); 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3 fan inputs */ 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 3; i++) { 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan[i] = asb100_read_value(client, 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100_REG_FAN(i)); 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[i] = asb100_read_value(client, 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100_REG_FAN_MIN(i)); 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4 temperature inputs */ 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= 4; i++) { 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp[i-1] = asb100_read_value(client, 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100_REG_TEMP(i)); 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_max[i-1] = asb100_read_value(client, 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100_REG_TEMP_MAX(i)); 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_hyst[i-1] = asb100_read_value(client, 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100_REG_TEMP_HYST(i)); 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* VID and fan divisors */ 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = asb100_read_value(client, ASB100_REG_VID_FANDIV); 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->vid = i & 0x0f; 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->vid |= (asb100_read_value(client, 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100_REG_CHIPID) & 0x01) << 4; 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[0] = (i >> 4) & 0x03; 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[1] = (i >> 6) & 0x03; 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[2] = (asb100_read_value(client, 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASB100_REG_PIN) >> 6) & 0x03; 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PWM */ 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm = asb100_read_value(client, ASB100_REG_PWM1); 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* alarms */ 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->alarms = asb100_read_value(client, ASB100_REG_ALARM1) + 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (asb100_read_value(client, ASB100_REG_ALARM2) << 8); 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->last_updated = jiffies; 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->valid = 1; 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "... device update complete\n"); 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9719a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return data; 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init asb100_init(void) 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i2c_add_driver(&asb100_driver); 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit asb100_exit(void) 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_del_driver(&asb100_driver); 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ASB100 Bach driver"); 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(asb100_init); 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(asb100_exit); 992