adm1026.c revision 1f57ff89fee47a317e9e8ca63bf0f139802cc116
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026.c - Part of lm_sensors, Linux kernel modules for hardware 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monitoring 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 2004 Justin Thiessen <jthiessen@penguincomputing.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Chip details at: 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds <http://www.analog.com/UploadedFiles/Data_Sheets/779263102ADM1026_a.pdf> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/jiffies.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c-sensor.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c-vid.h> 3310c08f8100ee2c4d27b862635574cdf4ef439e67Jean Delvare#include <linux/hwmon-sysfs.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Addresses to scan */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Insmod parameters */ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsSENSORS_INSMOD_1(adm1026); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1 }; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1 }; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1 }; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1 }; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(gpio_input,int,NULL,0); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gpio_input,"List of GPIO pins (0-16) to program as inputs"); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(gpio_output,int,NULL,0); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gpio_output,"List of GPIO pins (0-16) to program as " 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "outputs"); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(gpio_inverted,int,NULL,0); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gpio_inverted,"List of GPIO pins (0-16) to program as " 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "inverted"); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(gpio_normal,int,NULL,0); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gpio_normal,"List of GPIO pins (0-16) to program as " 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "normal/non-inverted"); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(gpio_fan,int,NULL,0); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gpio_fan,"List of GPIO pins (0-7) to program as fan tachs"); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Many ADM1026 constants specified below */ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The ADM1026 registers */ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_CONFIG1 0x00 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_MONITOR 0x01 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_INT_ENABLE 0x02 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_INT_CLEAR 0x04 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_AIN8_9 0x08 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_THERM_HOT 0x10 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_DAC_AFC 0x20 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_PWM_AFC 0x40 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_RESET 0x80 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_CONFIG2 0x01 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_CONFIG3 0x07 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG3_GPIO16_ENABLE 0x01 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG3_CI_CLEAR 0x02 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG3_VREF_250 0x04 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG3_GPIO16_DIR 0x40 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG3_GPIO16_POL 0x80 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_E2CONFIG 0x13 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E2CFG_READ 0x01 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E2CFG_WRITE 0x02 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E2CFG_ERASE 0x04 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E2CFG_ROM 0x08 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E2CFG_CLK_EXT 0x80 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* There are 10 general analog inputs and 7 dedicated inputs 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * They are: 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 - 9 = AIN0 - AIN9 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10 = Vbat 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11 = 3.3V Standby 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12 = 3.3V Main 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 13 = +5V 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 14 = Vccp (CPU core voltage) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15 = +12V 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16 = -12V 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN[] = { 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x36, 0x37, 0x27, 0x29, 0x26, 0x2a, 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x2b, 0x2c, 0x2d, 0x2e, 0x2f 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN_MIN[] = { 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a, 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x4b, 0x4c, 0x4d, 0x4e, 0x4f 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN_MAX[] = { 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x43, 0x44, 0x45, 0x46, 0x47 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temperatures are: 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 - Internal 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 - External 1 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 - External 2 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP[] = { 0x1f, 0x28, 0x29 }; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 }; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 }; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 }; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f }; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f }; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_FAN(nr) (0x38 + (nr)) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_FAN_MIN(nr) (0x60 + (nr)) 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_FAN_DIV_0_3 0x02 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_FAN_DIV_4_7 0x03 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_DAC 0x04 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_PWM 0x05 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_CFG_0_3 0x08 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_CFG_4_7 0x09 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_CFG_8_11 0x0a 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_CFG_12_15 0x0b 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CFG_16 in REG_CFG3 */ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_STATUS_0_7 0x24 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_STATUS_8_15 0x25 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* STATUS_16 in REG_STATUS4 */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_MASK_0_7 0x1c 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_MASK_8_15 0x1d 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* MASK_16 in REG_MASK4 */ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_COMPANY 0x16 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_VERSTEP 0x17 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These are the recognized values for the above regs */ 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_COMPANY_ANALOG_DEV 0x41 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_VERSTEP_GENERIC 0x40 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_VERSTEP_ADM1026 0x44 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_MASK1 0x18 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_MASK2 0x19 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_MASK3 0x1a 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_MASK4 0x1b 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_STATUS1 0x20 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_STATUS2 0x21 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_STATUS3 0x22 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_STATUS4 0x23 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_FAN_ACTIVATION_TEMP_HYST -6 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_FAN_CONTROL_TEMP_RANGE 20 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_PWM_MAX 255 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Conversions. Rounding and limit checking is only done on the TO_REG 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * variants. Note that you should be a bit careful with which arguments 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these macros are called: arguments may be evaluated more than once. 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* IN are scaled acording to built-in resistors. These are the 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * voltages corresponding to 3/4 of full scale (192 or 0xc0) 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: The -12V input needs an additional factor to account 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for the Vref pullup resistor. 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NEG12_OFFSET = SCALE * Vref / V-192 - Vref 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = 13875 * 2.50 / 1.875 - 2500 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = 16000 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The values in this table are based on Table II, page 15 of the 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * datasheet. 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_scaling[] = { /* .001 Volts */ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2250, 2250, 2250, 2250, 2250, 2250, 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1875, 1875, 1875, 1875, 3000, 3330, 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3330, 4995, 2250, 12000, 13875 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NEG12_OFFSET 16000 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from)) 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INS_TO_REG(n,val) (SENSORS_LIMIT(SCALE(val,adm1026_scaling[n],192),\ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0,255)) 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INS_FROM_REG(n,val) (SCALE(val,192,adm1026_scaling[n])) 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FAN speed is measured using 22.5kHz clock and counts for 2 pulses 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and we assume a 2 pulse-per-rev fan tach signal 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FAN_TO_REG(val,div) ((val)<=0 ? 0xff : SENSORS_LIMIT(1350000/((val)*\ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (div)),1,254)) 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==0xff ? 0 : 1350000/((val)*\ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (div))) 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1<<(val)) 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_TO_REG(val) ((val)>=8 ? 3 : (val)>=4 ? 2 : (val)>=2 ? 1 : 0) 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temperature is reported in 1 degC increments */ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\ 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -127,127)) 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_FROM_REG(val) ((val) * 1000) 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -127,127)) 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OFFSET_FROM_REG(val) ((val) * 1000) 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255)) 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_FROM_REG(val) (val) 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_MIN_TO_REG(val) ((val) & 0xf0) 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4)) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Analog output is a voltage, and scaled to millivolts. The datasheet 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * indicates that the DAC could be used to drive the fans, but in our 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * example board (Arima HDAMA) it isn't connected to the fans at all. 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500),0,255)) 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_FROM_REG(val) (((val)*2500)/255) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Typically used with systems using a v9.1 VRM spec ? */ 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_INIT_VRM 91 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Chip sampling rates 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some sensors are not updated more frequently than once per second 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * so it doesn't make sense to read them more often than that. 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We cache the results and return the saved data if the driver 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is called again before a second has elapsed. 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Also, there is significant configuration data for this chip 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * So, we keep the config data up to date in the cache 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when it is written and only sample it once every 5 *minutes* 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_DATA_INTERVAL (1 * HZ) 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_CONFIG_INTERVAL (5 * 60 * HZ) 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* We allow for multiple chips in a single system. 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For each registered ADM1026, we need to keep state information 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * at client->data. The adm1026_data structure is dynamically 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocated, when a new client structure is allocated. */ 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pwm_data { 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 pwm; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 enable; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 auto_pwm_min; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct adm1026_data { 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client client; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct semaphore lock; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum chips type; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct semaphore update_lock; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int valid; /* !=0 if following fields are valid */ 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long last_reading; /* In jiffies */ 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long last_config; /* In jiffies */ 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 in[17]; /* Register value */ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 in_max[17]; /* Register value */ 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 in_min[17]; /* Register value */ 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s8 temp[3]; /* Register value */ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s8 temp_min[3]; /* Register value */ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s8 temp_max[3]; /* Register value */ 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s8 temp_tmin[3]; /* Register value */ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s8 temp_crit[3]; /* Register value */ 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s8 temp_offset[3]; /* Register value */ 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 fan[8]; /* Register value */ 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 fan_min[8]; /* Register value */ 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 fan_div[8]; /* Decoded value */ 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pwm_data pwm1; /* Pwm control values */ 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int vid; /* Decoded value */ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 vrm; /* VRM version */ 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 analog_out; /* Register value (DAC) */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long alarms; /* Register encoding, combined */ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long alarm_mask; /* Register encoding, combined */ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long gpio; /* Register encoding, combined */ 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long gpio_mask; /* Register encoding, combined */ 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 gpio_config[17]; /* Decoded value */ 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 config1; /* Register value */ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 config2; /* Register value */ 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 config3; /* Register value */ 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_attach_adapter(struct i2c_adapter *adapter); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_detect(struct i2c_adapter *adapter, int address, 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int kind); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_detach_client(struct i2c_client *client); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_read_value(struct i2c_client *client, u8 register); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_write_value(struct i2c_client *client, u8 register, 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int value); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_print_gpio(struct i2c_client *client); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_fixup_gpio(struct i2c_client *client); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_init_client(struct i2c_client *client); 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_driver adm1026_driver = { 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "adm1026", 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .flags = I2C_DF_NOTIFY, 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attach_adapter = adm1026_attach_adapter, 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .detach_client = adm1026_detach_client, 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint adm1026_attach_adapter(struct i2c_adapter *adapter) 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(adapter->class & I2C_CLASS_HWMON)) { 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i2c_detect(adapter, &addr_data, adm1026_detect); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint adm1026_detach_client(struct i2c_client *client) 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_detach_client(client); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(client); 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint adm1026_read_value(struct i2c_client *client, u8 reg) 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reg < 0x80) { 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* "RAM" locations */ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = i2c_smbus_read_byte_data(client, reg) & 0xff; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* EEPROM, do nothing */ 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = 0; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint adm1026_write_value(struct i2c_client *client, u8 reg, int value) 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reg < 0x80) { 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* "RAM" locations */ 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = i2c_smbus_write_byte_data(client, reg, value); 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* EEPROM, do nothing */ 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = 0; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid adm1026_init_client(struct i2c_client *client) 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int value, i; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Initializing device\n"); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read chip config */ 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1); 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2); 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Inform user of chip config */ 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n", 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((data->config1 & CFG1_MONITOR) == 0) { 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Monitoring not currently " 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "enabled.\n"); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config1 & CFG1_INT_ENABLE) { 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "SMBALERT interrupts are " 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "enabled.\n"); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config1 & CFG1_AIN8_9) { 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "in8 and in9 enabled. " 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "temp3 disabled.\n"); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "temp3 enabled. in8 and " 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "in9 disabled.\n"); 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config1 & CFG1_THERM_HOT) { 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Automatic THERM, PWM, " 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "and temp limits enabled.\n"); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = data->config3; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config3 & CFG3_GPIO16_ENABLE) { 396368609c5a8bd75b77721e69726ddfd3c6a30f7d4Jean Delvare dev_dbg(&client->dev, "GPIO16 enabled. THERM " 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "pin disabled.\n"); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "THERM pin enabled. " 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "GPIO16 disabled.\n"); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config3 & CFG3_VREF_250) { 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Vref is 2.50 Volts.\n"); 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Vref is 1.82 Volts.\n"); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read and pick apart the existing GPIO configuration */ 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = 0; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 15;++i) { 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((i & 0x03) == 0) { 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = adm1026_read_value(client, 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_CFG_0_3 + i/4); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] = value & 0x03; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value >>= 2; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[16] = (data->config3 >> 6) & 0x03; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ... and then print it */ 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_print_gpio(client); 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If the user asks us to reprogram the GPIO config, then 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * do it now. 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_input[0] != -1 || gpio_output[0] != -1 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || gpio_inverted[0] != -1 || gpio_normal[0] != -1 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || gpio_fan[0] != -1) { 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_fixup_gpio(client); 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* WE INTENTIONALLY make no changes to the limits, 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * offsets, pwms, fans and zones. If they were 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * configured, we don't want to mess with them. 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If they weren't, the default is 100% PWM, no 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * control and will suffice until 'sensors -s' 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can be run by the user. We DO set the default 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * value for pwm1.auto_pwm_min to its maximum 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * so that enabling automatic pwm fan control 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without first setting a value for pwm1.auto_pwm_min 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will not result in potentially dangerous fan speed decrease. 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.auto_pwm_min=255; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start monitoring */ 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = adm1026_read_value(client, ADM1026_REG_CONFIG1); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set MONITOR, clear interrupt acknowledge and s/w reset */ 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET); 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1 = value; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_CONFIG1, value); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* initialize fan_div[] to hardware defaults */ 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) | 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 7;++i) { 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[i] = DIV_FROM_REG(value & 0x03); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value >>= 2; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid adm1026_print_gpio(struct i2c_client *client) 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "GPIO config is:"); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 7;++i) { 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config2 & (1 << i)) { 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "\t%sGP%s%d\n", 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] & 0x02 ? "" : "!", 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] & 0x01 ? "OUT" : "IN", 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i); 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "\tFAN%d\n", i); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 8;i <= 15;++i) { 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "\t%sGP%s%d\n", 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] & 0x02 ? "" : "!", 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] & 0x01 ? "OUT" : "IN", 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i); 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config3 & CFG3_GPIO16_ENABLE) { 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "\t%sGP%s16\n", 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[16] & 0x02 ? "" : "!", 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[16] & 0x01 ? "OUT" : "IN"); 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* GPIO16 is THERM */ 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "\tTHERM\n"); 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid adm1026_fixup_gpio(struct i2c_client *client) 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int value; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make the changes requested. */ 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We may need to unlock/stop monitoring or soft-reset the 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * chip before we can make changes. This hasn't been 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tested much. FIXME 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make outputs */ 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_output[i] >= 0 && gpio_output[i] <= 16) { 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[gpio_output[i]] |= 0x01; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if GPIO0-7 is output, it isn't a FAN tach */ 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_output[i] >= 0 && gpio_output[i] <= 7) { 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config2 |= 1 << gpio_output[i]; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Input overrides output */ 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_input[i] >= 0 && gpio_input[i] <= 16) { 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[gpio_input[i]] &= ~ 0x01; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if GPIO0-7 is input, it isn't a FAN tach */ 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_input[i] >= 0 && gpio_input[i] <= 7) { 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config2 |= 1 << gpio_input[i]; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Inverted */ 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) { 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[gpio_inverted[i]] &= ~ 0x02; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Normal overrides inverted */ 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) { 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[gpio_normal[i]] |= 0x02; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fan overrides input and output */ 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 7;++i) { 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) { 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config2 &= ~(1 << gpio_fan[i]); 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Write new configs to registers */ 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2); 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config3 = (data->config3 & 0x3f) 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((data->gpio_config[16] & 0x03) << 6); 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3); 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 15, value = 0;i >= 0;--i) { 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value <<= 2; 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value |= data->gpio_config[i] & 0x03; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((i & 0x03) == 0) { 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_CFG_0_3 + i/4, 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value); 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = 0; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Print the new config */ 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_print_gpio(client); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev) 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long value, alarms, gpio; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!data->valid 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) { 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Things that change quickly */ 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev,"Reading sensor values\n"); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in[i] = 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_read_value(client, ADM1026_REG_IN[i]); 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 7;++i) { 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan[i] = 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_read_value(client, ADM1026_REG_FAN(i)); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 2;++i) { 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTE: temp[] is s8 and we assume 2's complement 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "conversion" in the assignment */ 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp[i] = 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_read_value(client, ADM1026_REG_TEMP[i]); 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm = adm1026_read_value(client, 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_PWM); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->analog_out = adm1026_read_value(client, 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_DAC); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* GPIO16 is MSbit of alarms, move it to gpio */ 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms = adm1026_read_value(client, ADM1026_REG_STATUS4); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms &= 0x7f; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms <<= 8; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3); 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms <<= 8; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms <<= 8; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->alarms = alarms; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the GPIO values */ 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio |= adm1026_read_value(client, 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_STATUS_8_15); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio <<= 8; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio |= adm1026_read_value(client, 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_STATUS_0_7); 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio = gpio; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->last_reading = jiffies; 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; /* last_reading */ 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!data->valid || 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) { 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Things that don't change often */ 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Reading config values\n"); 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_min[i] = adm1026_read_value(client, 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_IN_MIN[i]); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_max[i] = adm1026_read_value(client, 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_IN_MAX[i]); 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds << 8); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 7;++i) { 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[i] = adm1026_read_value(client, 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_FAN_MIN(i)); 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[i] = DIV_FROM_REG(value & 0x03); 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value >>= 2; 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i <= 2; ++i) { 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTE: temp_xxx[] are s8 and we assume 2's 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complement "conversion" in the assignment 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_min[i] = adm1026_read_value(client, 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_TEMP_MIN[i]); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_max[i] = adm1026_read_value(client, 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_TEMP_MAX[i]); 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_tmin[i] = adm1026_read_value(client, 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_TEMP_TMIN[i]); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_crit[i] = adm1026_read_value(client, 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_TEMP_THERM[i]); 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_offset[i] = adm1026_read_value(client, 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_TEMP_OFFSET[i]); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the STATUS/alarm masks */ 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms = adm1026_read_value(client, ADM1026_REG_MASK4); 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms = (alarms & 0x7f) << 8; 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_MASK3); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms <<= 8; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_MASK2); 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms <<= 8; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_MASK1); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->alarm_mask = alarms; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the GPIO values */ 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio |= adm1026_read_value(client, 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_MASK_8_15); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio <<= 8; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7); 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_mask = gpio; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read various values from CONFIG1 */ 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1 = adm1026_read_value(client, 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_CONFIG1); 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config1 & CFG1_PWM_AFC) { 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.enable = 2; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.auto_pwm_min = 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PWM_MIN_FROM_REG(data->pwm1.pwm); 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the GPIO config */ 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config2 = adm1026_read_value(client, 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_CONFIG2); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config3 = adm1026_read_value(client, 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_CONFIG3); 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[16] = (data->config3 >> 6) & 0x03; 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = 0; 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 15;++i) { 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((i & 0x03) == 0) { 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = adm1026_read_value(client, 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_CFG_0_3 + i/4); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] = value & 0x03; 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value >>= 2; 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->last_config = jiffies; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; /* last_config */ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n"); 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->vid = (data->gpio >> 11) & 0x1f; 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->valid = 1; 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return data; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 714050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in(struct device *dev, struct device_attribute *attr, 715050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 717050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 718050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr])); 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 722050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_min(struct device *dev, struct device_attribute *attr, 723050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 725050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 726050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr])); 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 730050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_min(struct device *dev, struct device_attribute *attr, 731050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 733050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 734050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_min[nr] = INS_TO_REG(nr, val); 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]); 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 745050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_max(struct device *dev, struct device_attribute *attr, 746050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 748050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 749050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr])); 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 753050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_max(struct device *dev, struct device_attribute *attr, 754050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 756050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 757050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_max[nr] = INS_TO_REG(nr, val); 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]); 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 769050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define in_reg(offset) \ 770050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \ 771050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou NULL, offset); \ 772050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ 773050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_in_min, set_in_min, offset); \ 774050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ 775050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_in_max, set_in_max, offset); 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(0); 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(1); 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(2); 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(3); 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(4); 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(5); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(6); 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(7); 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(8); 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(9); 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(10); 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(11); 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(12); 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(13); 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(14); 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(15); 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 79574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf) 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in[16]) - 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NEG12_OFFSET); 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 80174880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, char *buf) 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_min[16]) 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - NEG12_OFFSET); 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 80774880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 81974880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf) 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_max[16]) 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - NEG12_OFFSET); 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 82574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET); 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]); 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 838050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16); 839050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min, 16); 840050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max, 16); 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan read/write functions */ 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 847050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan(struct device *dev, struct device_attribute *attr, 848050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 850050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 851050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[nr])); 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 856050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, 857050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 859050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 860050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr], 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[nr])); 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 865050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, 866050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 868050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 869050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]); 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr), 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[nr]); 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 882050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define fan_offset(offset) \ 883050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ 884050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou offset - 1); \ 885050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ 886050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_fan_min, set_fan_min, offset - 1); 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(1); 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(2); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(3); 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(4); 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(5); 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(6); 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(7); 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(8); 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Adjust fan_min to account for new fan divisor */ 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fixup_fan_min(struct device *dev, int fan, int old_div) 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int new_min; 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int new_div = data->fan_div[fan]; 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0 and 0xff are special. Don't adjust them */ 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff) { 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_min = data->fan_min[fan] * old_div / new_div; 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_min = SENSORS_LIMIT(new_min, 1, 254); 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[fan] = new_min; 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min); 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan_div read/write functions */ 917050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, 918050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 920050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 921050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", data->fan_div[nr]); 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 925050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, 926050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 928050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 929050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val,orig_div,new_div,shift; 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = simple_strtol(buf, NULL, 10); 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_div = DIV_TO_REG(val); 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_div == 0) { 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds orig_div = data->fan_div[nr]; 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[nr] = DIV_FROM_REG(new_div); 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nr < 4) { /* 0 <= nr < 4 */ 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shift = 2 * nr; 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3, 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((DIV_TO_REG(orig_div) & (~(0x03 << shift))) | 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (new_div << shift))); 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* 3 < nr < 8 */ 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shift = 2 * (nr - 4); 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7, 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) | 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (new_div << shift))); 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->fan_div[nr] != orig_div) { 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fixup_fan_min(dev,nr,orig_div); 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define fan_offset_div(offset) \ 963050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ 964050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_fan_div, set_fan_div, offset - 1); 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(1); 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(2); 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(3); 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(4); 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(5); 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(6); 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(7); 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(8); 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temps */ 976050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp(struct device *dev, struct device_attribute *attr, 977050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 979050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 980050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr])); 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 984050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, 985050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 987050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 988050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr])); 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 992050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, 993050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 995050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 996050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_min[nr] = TEMP_TO_REG(val); 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr], 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_min[nr]); 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1008050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, 1009050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1011050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1012050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr])); 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1016050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, 1017050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1019050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1020050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_max[nr] = TEMP_TO_REG(val); 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr], 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_max[nr]); 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1032050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou 1033050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_reg(offset) \ 1034050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, \ 1035050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou NULL, offset - 1); \ 1036050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ 1037050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_min, set_temp_min, offset - 1); \ 1038050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ 1039050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_max, set_temp_max, offset - 1); 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(1); 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(2); 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(3); 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1046050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_offset(struct device *dev, 1047050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1049050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1050050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_offset[nr])); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1054050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_offset(struct device *dev, 1055050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, const char *buf, 1056050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou size_t count) 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1058050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1059050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_offset[nr] = TEMP_TO_REG(val); 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr], 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_offset[nr]); 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1072050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_offset_reg(offset) \ 1073050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \ 1074050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_offset, set_temp_offset, offset - 1); 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(1); 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(2); 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(3); 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1080050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp_hyst(struct device *dev, 1081050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1083050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1084050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", TEMP_FROM_REG( 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr])); 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1089050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point2_temp(struct device *dev, 1090050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1092050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1093050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr] + 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_FAN_CONTROL_TEMP_RANGE)); 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1098050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp(struct device *dev, 1099050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1101050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1102050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr])); 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1106050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_auto_point1_temp(struct device *dev, 1107050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, const char *buf, size_t count) 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1109050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1110050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_tmin[nr] = TEMP_TO_REG(val); 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr], 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_tmin[nr]); 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1123050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_auto_point(offset) \ 1124050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR, \ 1125050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_auto_point1_temp, set_temp_auto_point1_temp, \ 1126050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou offset - 1); \ 1127050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO, \ 1128050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_auto_point1_temp_hyst, NULL, offset - 1); \ 1129050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO, \ 1130050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_auto_point2_temp, NULL, offset - 1); 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(1); 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(2); 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(3); 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1136050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit_enable(struct device *dev, 1137050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", (data->config1 & CFG1_THERM_HOT) >> 4); 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1142050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit_enable(struct device *dev, 1143050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, const char *buf, size_t count) 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((val == 1) || (val==0)) { 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4); 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_CONFIG1, 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1); 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1159050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_enable(offset) \ 1160050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic DEVICE_ATTR(temp##offset##_crit_enable, S_IRUGO | S_IWUSR, \ 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_temp_crit_enable, set_temp_crit_enable); 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1163050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(1); 1164050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(2); 1165050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(3); 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1167050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit(struct device *dev, 1168050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1170050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1171050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_crit[nr])); 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1175050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, 1176050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1178050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1179050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_crit[nr] = TEMP_TO_REG(val); 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr], 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_crit[nr]); 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1192050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_reg(offset) \ 1193050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \ 1194050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_crit, set_temp_crit, offset - 1); 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(1); 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(2); 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(3); 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 120074880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_analog_out_reg(struct device *dev, struct device_attribute *attr, char *buf) 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", DAC_FROM_REG(data->analog_out)); 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 120574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *attr, const char *buf, 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->analog_out = DAC_TO_REG(val); 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out); 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg, 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_analog_out_reg); 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 122274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm)); 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1227937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coady/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */ 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL); 1229937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coadystatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 123174880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", data->vrm); 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 123674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->vrm = simple_strtol(buf, NULL, 10); 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 124874880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%ld\n", (long) (data->alarms)); 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 125674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf) 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%ld\n", data->alarm_mask); 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 126174880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, const char *buf, 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long mask; 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->alarm_mask = val & 0x7fffffff; 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = data->alarm_mask 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | (data->gpio_mask & 0x10000 ? 0x80000000 : 0); 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_MASK1, 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask & 0xff); 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask >>= 8; 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_MASK2, 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask & 0xff); 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask >>= 8; 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_MASK3, 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask & 0xff); 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask >>= 8; 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_MASK4, 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask & 0xff); 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask, 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_alarm_mask); 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 129274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf) 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%ld\n", data->gpio); 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 129774880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf, 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long gpio; 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio = val & 0x1ffff; 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio = data->gpio; 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7,gpio & 0xff); 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio >>= 8; 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15,gpio & 0xff); 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f); 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_STATUS4,gpio & 0xff); 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio); 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 132074880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, char *buf) 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%ld\n", data->gpio_mask); 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 132574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, const char *buf, 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long mask; 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_mask = val & 0x1ffff; 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = data->gpio_mask; 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7,mask & 0xff); 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask >>= 8; 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,mask & 0xff); 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f); 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_MASK1,mask & 0xff); 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask); 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 134774880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, char *buf) 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm1.pwm)); 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 135274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, const char *buf, 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->pwm1.enable == 1) { 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm = PWM_TO_REG(val); 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 136874880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf) 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", data->pwm1.auto_pwm_min); 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 137374880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf, 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.auto_pwm_min = SENSORS_LIMIT(val,0,255); 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->pwm1.enable == 2) { /* apply immediately */ 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 139074880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf) 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", ADM1026_PWM_MAX); 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 139474880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf,"%d\n", data->pwm1.enable); 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 139974880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf, 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int old_enable; 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((val >= 0) && (val < 3)) { 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&data->update_lock); 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_enable = data->pwm1.enable; 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.enable = val; 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1 = (data->config1 & ~CFG1_PWM_AFC) 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((val == 2) ? CFG1_PWM_AFC : 0); 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_CONFIG1, 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1); 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */ 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_PWM, 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm); 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!((old_enable == 1) && (val == 1))) { 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set pwm to safe value */ 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm = 255; 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_PWM, 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm); 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&data->update_lock); 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* enable PWM fan control */ 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); 14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_pwm_enable); 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_pwm_enable); 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, 14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_pwm_enable); 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR, 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_auto_pwm_min, set_auto_pwm_min); 14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR, 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_auto_pwm_min, set_auto_pwm_min); 14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR, 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_auto_pwm_min, set_auto_pwm_min); 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint adm1026_detect(struct i2c_adapter *adapter, int address, 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int kind) 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int company, verstep; 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *new_client; 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data; 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *type_name = ""; 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We need to be able to do byte I/O */ 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* OK. For now, we presume we have a valid client. We now create the 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client structure, even though we cannot fill it completely yet. 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds But it allows us to access adm1026_{read,write}_value. */ 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(data = kmalloc(sizeof(struct adm1026_data), GFP_KERNEL))) { 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOMEM; 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(data, 0, sizeof(struct adm1026_data)); 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_client = &data->client; 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_set_clientdata(new_client, data); 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_client->addr = address; 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_client->adapter = adapter; 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_client->driver = &adm1026_driver; 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_client->flags = 0; 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now, we do the remaining detection. */ 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds company = adm1026_read_value(new_client, ADM1026_REG_COMPANY); 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds verstep = adm1026_read_value(new_client, ADM1026_REG_VERSTEP); 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&new_client->dev, "Detecting device at %d,0x%02x with" 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " COMPANY: 0x%02x and VERSTEP: 0x%02x\n", 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_adapter_id(new_client->adapter), new_client->addr, 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds company, verstep); 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If auto-detecting, Determine the chip type. */ 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kind <= 0) { 14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&new_client->dev, "Autodetecting device at %d,0x%02x " 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "...\n", i2c_adapter_id(adapter), address); 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (company == ADM1026_COMPANY_ANALOG_DEV 14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && verstep == ADM1026_VERSTEP_ADM1026) { 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kind = adm1026; 15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (company == ADM1026_COMPANY_ANALOG_DEV 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&adapter->dev, ": Unrecognized stepping " 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%02x. Defaulting to ADM1026.\n", verstep); 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kind = adm1026; 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&adapter->dev, ": Found version/stepping " 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%02x. Assuming generic ADM1026.\n", 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds verstep); 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kind = any_chip; 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&new_client->dev, ": Autodetection " 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "failed\n"); 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Not an ADM1026 ... */ 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kind == 0) { /* User used force=x,y */ 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&adapter->dev, "Generic ADM1026 not " 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "found at %d,0x%02x. Try " 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "force_adm1026.\n", 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_adapter_id(adapter), address); 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = 0; 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exitfree; 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill in the chip specific driver values */ 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (kind) { 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case any_chip : 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_name = "adm1026"; 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case adm1026 : 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_name = "adm1026"; 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default : 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&adapter->dev, ": Internal error, invalid " 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "kind (%d)!", kind); 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EFAULT; 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exitfree; 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strlcpy(new_client->name, type_name, I2C_NAME_SIZE); 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill in the remaining client fields */ 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->type = kind; 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->valid = 0; 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_MUTEX(&data->update_lock); 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Tell the I2C layer a new client has arrived */ 15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = i2c_attach_client(new_client))) 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exitfree; 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set the VRM version */ 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->vrm = i2c_which_vrm(); 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the ADM1026 chip */ 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_init_client(new_client); 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Register sysfs hooks */ 1558050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr); 1559050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr); 1560050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr); 1561050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr); 1562050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr); 1563050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr); 1564050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr); 1565050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr); 1566050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr); 1567050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr); 1568050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr); 1569050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr); 1570050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr); 1571050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr); 1572050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr); 1573050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr); 1574050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr); 1575050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr); 1576050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr); 1577050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr); 1578050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr); 1579050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr); 1580050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr); 1581050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr); 1582050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr); 1583050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr); 1584050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr); 1585050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr); 1586050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr); 1587050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr); 1588050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr); 1589050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr); 1590050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr); 1591050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in11_input.dev_attr); 1592050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in11_max.dev_attr); 1593050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in11_min.dev_attr); 1594050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in12_input.dev_attr); 1595050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in12_max.dev_attr); 1596050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in12_min.dev_attr); 1597050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in13_input.dev_attr); 1598050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in13_max.dev_attr); 1599050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in13_min.dev_attr); 1600050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in14_input.dev_attr); 1601050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in14_max.dev_attr); 1602050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in14_min.dev_attr); 1603050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in15_input.dev_attr); 1604050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in15_max.dev_attr); 1605050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in15_min.dev_attr); 1606050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in16_input.dev_attr); 1607050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in16_max.dev_attr); 1608050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_in16_min.dev_attr); 1609050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr); 1610050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr); 1611050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr); 1612050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr); 1613050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr); 1614050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr); 1615050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr); 1616050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr); 1617050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr); 1618050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan4_input.dev_attr); 1619050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan4_div.dev_attr); 1620050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan4_min.dev_attr); 1621050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan5_input.dev_attr); 1622050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan5_div.dev_attr); 1623050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan5_min.dev_attr); 1624050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan6_input.dev_attr); 1625050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan6_div.dev_attr); 1626050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan6_min.dev_attr); 1627050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan7_input.dev_attr); 1628050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan7_div.dev_attr); 1629050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan7_min.dev_attr); 1630050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan8_input.dev_attr); 1631050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan8_div.dev_attr); 1632050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_fan8_min.dev_attr); 1633050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr); 1634050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); 1635050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr); 1636050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr); 1637050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr); 1638050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr); 1639050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr); 1640050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr); 1641050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr); 1642050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp1_offset.dev_attr); 1643050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp2_offset.dev_attr); 1644050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp3_offset.dev_attr); 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, 1646050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou &sensor_dev_attr_temp1_auto_point1_temp.dev_attr); 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, 1648050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou &sensor_dev_attr_temp2_auto_point1_temp.dev_attr); 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, 1650050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou &sensor_dev_attr_temp3_auto_point1_temp.dev_attr); 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, 1652050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr); 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, 1654050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou &sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr); 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, 1656050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou &sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr); 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, 1658050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou &sensor_dev_attr_temp1_auto_point2_temp.dev_attr); 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, 1660050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou &sensor_dev_attr_temp2_auto_point2_temp.dev_attr); 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, 1662050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou &sensor_dev_attr_temp3_auto_point2_temp.dev_attr); 1663050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr); 1664050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr); 1665050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr); 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable); 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable); 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable); 1669937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coady /* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */ 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_vid); 1671937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coady device_create_file(&new_client->dev, &dev_attr_cpu0_vid); 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_vrm); 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_alarms); 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_alarm_mask); 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_gpio); 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_gpio_mask); 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_pwm1); 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_pwm2); 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_pwm3); 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_pwm1_enable); 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_pwm2_enable); 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_pwm3_enable); 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_temp1_auto_point1_pwm); 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_temp2_auto_point1_pwm); 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_temp3_auto_point1_pwm); 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_temp1_auto_point2_pwm); 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_temp2_auto_point2_pwm); 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_temp3_auto_point2_pwm); 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_create_file(&new_client->dev, &dev_attr_analog_out); 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Error out and cleanup code */ 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexitfree: 16941f57ff89fee47a317e9e8ca63bf0f139802cc116Alexey Dobriyan kfree(data); 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sm_adm1026_init(void) 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i2c_add_driver(&adm1026_driver); 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sm_adm1026_exit(void) 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_del_driver(&adm1026_driver); 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, " 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Justin Thiessen <jthiessen@penguincomputing.com>"); 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ADM1026 driver"); 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sm_adm1026_init); 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sm_adm1026_exit); 1715