amc6821.c revision b5430a04e995081a308b4419bd0940f2badc6e6b
1b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/* 2b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj amc6821.c - Part of lm_sensors, Linux kernel modules for hardware 3b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj monitoring 4b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si> 5b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 6b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj Based on max6650.c: 7b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj Copyright (C) 2007 Hans J. Koch <hjk@linutronix.de> 8b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 9b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj This program is free software; you can redistribute it and/or modify 10b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj it under the terms of the GNU General Public License as published by 11b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj the Free Software Foundation; either version 2 of the License, or 12b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj (at your option) any later version. 13b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 14b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj This program is distributed in the hope that it will be useful, 15b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj but WITHOUT ANY WARRANTY; without even the implied warranty of 16b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj GNU General Public License for more details. 18b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 19b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj You should have received a copy of the GNU General Public License 20b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj along with this program; if not, write to the Free Software 21b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj*/ 23b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 24b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 25b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/kernel.h> /* Needed for KERN_INFO */ 26b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/module.h> 27b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/init.h> 28b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/slab.h> 29b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/jiffies.h> 30b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/i2c.h> 31b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/hwmon.h> 32b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/hwmon-sysfs.h> 33b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/err.h> 34b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/mutex.h> 35b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 36b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 37b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/* 38b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj * Addresses to scan. 39b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj */ 40b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 41b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e, 42b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 0x4c, 0x4d, 0x4e, I2C_CLIENT_END}; 43b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 44b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 45b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 46b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/* 47b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj * Insmod parameters 48b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj */ 49b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 50b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int pwminv = 0; /*Inverted PWM output. */ 51b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljmodule_param(pwminv, int, S_IRUGO); 52b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 53b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int init = 1; /*Power-on initialization.*/ 54b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljmodule_param(init, int, S_IRUGO); 55b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 56b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 57b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljenum chips { amc6821 }; 58b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 59b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_DEV_ID 0x3D 60b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_COMP_ID 0x3E 61b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_CONF1 0x00 62b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_CONF2 0x01 63b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_CONF3 0x3F 64b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_CONF4 0x04 65b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_STAT1 0x02 66b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_STAT2 0x03 67b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TDATA_LOW 0x08 68b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TDATA_HI 0x09 69b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_LTEMP_HI 0x0A 70b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_RTEMP_HI 0x0B 71b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_LTEMP_LIMIT_MIN 0x15 72b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_LTEMP_LIMIT_MAX 0x14 73b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_RTEMP_LIMIT_MIN 0x19 74b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_RTEMP_LIMIT_MAX 0x18 75b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_LTEMP_CRIT 0x1B 76b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_RTEMP_CRIT 0x1D 77b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_PSV_TEMP 0x1C 78b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_DCY 0x22 79b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_LTEMP_FAN_CTRL 0x24 80b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_RTEMP_FAN_CTRL 0x25 81b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_DCY_LOW_TEMP 0x21 82b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 83b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TACH_LLIMITL 0x10 84b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TACH_LLIMITH 0x11 85b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TACH_HLIMITL 0x12 86b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TACH_HLIMITH 0x13 87b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 88b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_START 0x01 89b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_FAN_INT_EN 0x02 90b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_FANIE 0x04 91b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_PWMINV 0x08 92b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_FAN_FAULT_EN 0x10 93b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_FDRC0 0x20 94b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_FDRC1 0x40 95b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_THERMOVIE 0x80 96b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 97b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_PWM_EN 0x01 98b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_TACH_MODE 0x02 99b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_TACH_EN 0x04 100b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_RTFIE 0x08 101b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_LTOIE 0x10 102b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_RTOIE 0x20 103b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_PSVIE 0x40 104b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_RST 0x80 105b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 106b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF3_THERM_FAN_EN 0x80 107b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF3_REV_MASK 0x0F 108b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 109b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF4_OVREN 0x10 110b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF4_TACH_FAST 0x20 111b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF4_PSPR 0x40 112b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF4_MODE 0x80 113b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 114b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_RPM_ALARM 0x01 115b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_FANS 0x02 116b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_RTH 0x04 117b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_RTL 0x08 118b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_R_THERM 0x10 119b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_RTF 0x20 120b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_LTH 0x40 121b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_LTL 0x80 122b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 123b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT2_RTC 0x08 124b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT2_LTC 0x10 125b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT2_LPSV 0x20 126b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT2_L_THERM 0x40 127b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT2_THERM_IN 0x80 128b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 129b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljenum {IDX_TEMP1_INPUT = 0, IDX_TEMP1_MIN, IDX_TEMP1_MAX, 130b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj IDX_TEMP1_CRIT, IDX_TEMP2_INPUT, IDX_TEMP2_MIN, 131b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj IDX_TEMP2_MAX, IDX_TEMP2_CRIT, 132b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj TEMP_IDX_LEN, }; 133b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 134b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic const u8 temp_reg[] = {AMC6821_REG_LTEMP_HI, 135b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_LTEMP_LIMIT_MIN, 136b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_LTEMP_LIMIT_MAX, 137b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_LTEMP_CRIT, 138b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_RTEMP_HI, 139b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_RTEMP_LIMIT_MIN, 140b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_RTEMP_LIMIT_MAX, 141b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_RTEMP_CRIT, }; 142b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 143b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljenum {IDX_FAN1_INPUT = 0, IDX_FAN1_MIN, IDX_FAN1_MAX, 144b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj FAN1_IDX_LEN, }; 145b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 146b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic const u8 fan_reg_low[] = {AMC6821_REG_TDATA_LOW, 147b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_TACH_LLIMITL, 148b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_TACH_HLIMITL, }; 149b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 150b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 151b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI, 152b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_TACH_LLIMITH, 153b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_TACH_HLIMITH, }; 154b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 155b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int amc6821_probe( 156b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client, 157b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj const struct i2c_device_id *id); 158b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int amc6821_detect( 159b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client, 160b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_board_info *info); 161b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int amc6821_init_client(struct i2c_client *client); 162b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int amc6821_remove(struct i2c_client *client); 163b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic struct amc6821_data *amc6821_update_device(struct device *dev); 164b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 165b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/* 166b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj * Driver data (common to all clients) 167b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj */ 168b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 169b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic const struct i2c_device_id amc6821_id[] = { 170b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj { "amc6821", amc6821 }, 171b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj { } 172b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}; 173b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 174b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljMODULE_DEVICE_TABLE(i2c, amc6821_id); 175b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 176b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic struct i2c_driver amc6821_driver = { 177b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj .class = I2C_CLASS_HWMON, 178b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj .driver = { 179b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj .name = "amc6821", 180b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj }, 181b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj .probe = amc6821_probe, 182b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj .remove = amc6821_remove, 183b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj .id_table = amc6821_id, 184b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj .detect = amc6821_detect, 185b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj .address_list = normal_i2c, 186b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}; 187b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 188b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 189b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/* 190b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj * Client data (each client gets its own) 191b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj */ 192b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 193b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstruct amc6821_data { 194b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *hwmon_dev; 195b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct mutex update_lock; 196b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char valid; /* zero until following fields are valid */ 197b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj unsigned long last_updated; /* in jiffies */ 198b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 199b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj /* register values */ 200b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int temp[TEMP_IDX_LEN]; 201b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 202b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u16 fan[FAN1_IDX_LEN]; 203b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 fan1_div; 204b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 205b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 pwm1; 206b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 temp1_auto_point_temp[3]; 207b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 temp2_auto_point_temp[3]; 208b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 pwm1_auto_point_pwm[3]; 209b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 pwm1_enable; 210b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 pwm1_auto_channels_temp; 211b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 212b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 stat1; 213b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 stat2; 214b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}; 215b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 216b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 217b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_temp( 218b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 219b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 220b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 221b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 222b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 223b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ix = to_sensor_dev_attr(devattr)->index; 224b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 225b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "%d\n", data->temp[ix] * 1000); 226b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 227b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 228b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 229b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 230b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_temp( 231b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 232b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *attr, 233b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj const char *buf, 234b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj size_t count) 235b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 236b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client = to_i2c_client(dev); 237b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = i2c_get_clientdata(client); 238b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ix = to_sensor_dev_attr(attr)->index; 239b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj long val; 240b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 241b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ret = strict_strtol(buf, 10, &val); 242b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (ret) 243b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return ret; 244b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj val = SENSORS_LIMIT(val / 1000, -128, 127); 245b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 246b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_lock(&data->update_lock); 247b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp[ix] = val; 248b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data(client, temp_reg[ix], data->temp[ix])) { 249b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, "Register write error, aborting.\n"); 250b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EIO; 251b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 252b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_unlock(&data->update_lock); 253b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return count; 254b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 255b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 256b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 257b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 258b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 259b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_temp_alarm( 260b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 261b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 262b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 263b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 264b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 265b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ix = to_sensor_dev_attr(devattr)->index; 266b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 flag; 267b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 268b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj switch (ix) { 269b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case IDX_TEMP1_MIN: 270b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj flag = data->stat1 & AMC6821_STAT1_LTL; 271b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 272b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case IDX_TEMP1_MAX: 273b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj flag = data->stat1 & AMC6821_STAT1_LTH; 274b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 275b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case IDX_TEMP1_CRIT: 276b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj flag = data->stat2 & AMC6821_STAT2_LTC; 277b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 278b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case IDX_TEMP2_MIN: 279b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj flag = data->stat1 & AMC6821_STAT1_RTL; 280b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 281b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case IDX_TEMP2_MAX: 282b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj flag = data->stat1 & AMC6821_STAT1_RTH; 283b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 284b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case IDX_TEMP2_CRIT: 285b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj flag = data->stat2 & AMC6821_STAT2_RTC; 286b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 287b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj default: 288b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_dbg(dev, "Unknown attr->index (%d).\n", ix); 289b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -EINVAL; 290b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 291b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (flag) 292b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "1"); 293b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj else 294b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "0"); 295b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 296b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 297b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 298b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 299b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 300b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_temp2_fault( 301b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 302b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 303b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 304b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 305b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 306b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (data->stat1 & AMC6821_STAT1_RTF) 307b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "1"); 308b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj else 309b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "0"); 310b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 311b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 312b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_pwm1( 313b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 314b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 315b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 316b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 317b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 318b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "%d\n", data->pwm1); 319b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 320b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 321b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_pwm1( 322b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 323b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 324b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj const char *buf, 325b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj size_t count) 326b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 327b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client = to_i2c_client(dev); 328b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = i2c_get_clientdata(client); 329b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj long val; 330b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ret = strict_strtol(buf, 10, &val); 331b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (ret) 332b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return ret; 333b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 334b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_lock(&data->update_lock); 335b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1 = SENSORS_LIMIT(val , 0, 255); 336b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj i2c_smbus_write_byte_data(client, AMC6821_REG_DCY, data->pwm1); 337b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_unlock(&data->update_lock); 338b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return count; 339b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 340b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 341b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_pwm1_enable( 342b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 343b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 344b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 345b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 346b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 347b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "%d\n", data->pwm1_enable); 348b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 349b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 350b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_pwm1_enable( 351b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 352b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *attr, 353b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj const char *buf, 354b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj size_t count) 355b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 356b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client = to_i2c_client(dev); 357b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = i2c_get_clientdata(client); 358b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj long val; 359b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int config = strict_strtol(buf, 10, &val); 360b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (config) 361b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return config; 362b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 363b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); 364b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (config < 0) { 365b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 366b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Error reading configuration register, aborting.\n"); 367b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -EIO; 368b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 369b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 370b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj switch (val) { 371b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 1: 372b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF1_FDRC0; 373b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF1_FDRC1; 374b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 375b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 2: 376b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF1_FDRC0; 377b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config |= AMC6821_CONF1_FDRC1; 378b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 379b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 3: 380b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config |= AMC6821_CONF1_FDRC0; 381b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config |= AMC6821_CONF1_FDRC1; 382b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 383b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj default: 384b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -EINVAL; 385b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 386b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_lock(&data->update_lock); 387b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) { 388b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 389b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Configuration register write error, aborting.\n"); 390b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EIO; 391b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 392b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_unlock(&data->update_lock); 393b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return count; 394b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 395b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 396b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 397b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_pwm1_auto_channels_temp( 398b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 399b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 400b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 401b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 402b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 403b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp); 404b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 405b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 406b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 407b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_temp_auto_point_temp( 408b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 409b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 410b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 411b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 412b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ix = to_sensor_dev_attr_2(devattr)->index; 413b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int nr = to_sensor_dev_attr_2(devattr)->nr; 414b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 415b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj switch (nr) { 416b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 1: 417b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "%d\n", 418b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp1_auto_point_temp[ix] * 1000); 419b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 420b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 2: 421b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "%d\n", 422b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp2_auto_point_temp[ix] * 1000); 423b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 424b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj default: 425b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_dbg(dev, "Unknown attr->nr (%d).\n", nr); 426b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -EINVAL; 427b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 428b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 429b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 430b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 431b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_pwm1_auto_point_pwm( 432b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 433b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 434b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 435b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 436b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ix = to_sensor_dev_attr(devattr)->index; 437b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 438b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]); 439b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 440b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 441b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 442b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic inline ssize_t set_slope_register(struct i2c_client *client, 443b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 reg, 444b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 dpwm, 445b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 *ptemp) 446b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 447b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int dt; 448b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 tmp; 449b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 450b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dt = ptemp[2]-ptemp[1]; 451b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj for (tmp = 4; tmp > 0; tmp--) { 452b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (dt * (0x20 >> tmp) >= dpwm) 453b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 454b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 455b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj tmp |= (ptemp[1] & 0x7C) << 1; 456b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data(client, 457b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg, tmp)) { 458b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, "Register write error, aborting.\n"); 459b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -EIO; 460b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 461b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return 0; 462b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 463b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 464b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 465b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 466b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_temp_auto_point_temp( 467b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 468b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *attr, 469b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj const char *buf, 470b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj size_t count) 471b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 472b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client = to_i2c_client(dev); 473b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 474b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ix = to_sensor_dev_attr_2(attr)->index; 475b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int nr = to_sensor_dev_attr_2(attr)->nr; 476b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 *ptemp; 477b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 reg; 478b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int dpwm; 479b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj long val; 480b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ret = strict_strtol(buf, 10, &val); 481b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (ret) 482b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return ret; 483b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 484b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj switch (nr) { 485b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 1: 486b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp = data->temp1_auto_point_temp; 487b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg = AMC6821_REG_LTEMP_FAN_CTRL; 488b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 489b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 2: 490b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp = data->temp2_auto_point_temp; 491b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg = AMC6821_REG_RTEMP_FAN_CTRL; 492b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 493b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj default: 494b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_dbg(dev, "Unknown attr->nr (%d).\n", nr); 495b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -EINVAL; 496b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 497b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 498b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->valid = 0; 499b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_lock(&data->update_lock); 500b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj switch (ix) { 501b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 0: 502b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp[0] = SENSORS_LIMIT(val / 1000, 0, 503b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp1_auto_point_temp[1]); 504b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, 505b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp2_auto_point_temp[1]); 506b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, 63); 507b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data( 508b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj client, 509b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_PSV_TEMP, 510b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp[0])) { 511b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 512b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Register write error, aborting.\n"); 513b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EIO; 514b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 515b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj goto EXIT; 516b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 517b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 1: 518b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp[1] = SENSORS_LIMIT( 519b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj val / 1000, 520b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj (ptemp[0] & 0x7C) + 4, 521b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 124); 522b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp[1] &= 0x7C; 523b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp[2] = SENSORS_LIMIT( 524b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp[2], ptemp[1] + 1, 525b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 255); 526b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 527b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 2: 528b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp[2] = SENSORS_LIMIT( 529b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj val / 1000, 530b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ptemp[1]+1, 531b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 255); 532b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 533b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj default: 534b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_dbg(dev, "Unknown attr->index (%d).\n", ix); 535b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EINVAL; 536b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj goto EXIT; 537b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 538b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1]; 539b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (set_slope_register(client, reg, dpwm, ptemp)) 540b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EIO; 541b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 542b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljEXIT: 543b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_unlock(&data->update_lock); 544b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return count; 545b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 546b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 547b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 548b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 549b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_pwm1_auto_point_pwm( 550b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 551b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *attr, 552b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj const char *buf, 553b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj size_t count) 554b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 555b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client = to_i2c_client(dev); 556b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = i2c_get_clientdata(client); 557b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int dpwm; 558b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj long val; 559b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ret = strict_strtol(buf, 10, &val); 560b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (ret) 561b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return ret; 562b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 563b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_lock(&data->update_lock); 564b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_point_pwm[1] = SENSORS_LIMIT(val, 0, 254); 565b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data(client, AMC6821_REG_DCY_LOW_TEMP, 566b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_point_pwm[1])) { 567b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, "Register write error, aborting.\n"); 568b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EIO; 569b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj goto EXIT; 570b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 571b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1]; 572b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (set_slope_register(client, AMC6821_REG_LTEMP_FAN_CTRL, dpwm, 573b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp1_auto_point_temp)) { 574b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EIO; 575b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj goto EXIT; 576b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 577b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (set_slope_register(client, AMC6821_REG_RTEMP_FAN_CTRL, dpwm, 578b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp2_auto_point_temp)) { 579b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EIO; 580b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj goto EXIT; 581b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 582b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 583b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljEXIT: 584b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->valid = 0; 585b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_unlock(&data->update_lock); 586b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return count; 587b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 588b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 589b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_fan( 590b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 591b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 592b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 593b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 594b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 595b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ix = to_sensor_dev_attr(devattr)->index; 596b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (0 == data->fan[ix]) 597b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "0"); 598b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix])); 599b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 600b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 601b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 602b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 603b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_fan1_fault( 604b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 605b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 606b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 607b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 608b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 609b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (data->stat1 & AMC6821_STAT1_FANS) 610b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "1"); 611b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj else 612b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "0"); 613b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 614b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 615b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 616b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 617b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_fan( 618b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 619b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *attr, 620b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj const char *buf, size_t count) 621b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 622b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client = to_i2c_client(dev); 623b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = i2c_get_clientdata(client); 624b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj long val; 625b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ix = to_sensor_dev_attr(attr)->index; 626b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int ret = strict_strtol(buf, 10, &val); 627b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (ret) 628b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return ret; 629b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj val = 1 > val ? 0xFFFF : 6000000/val; 630b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 631b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_lock(&data->update_lock); 632b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->fan[ix] = (u16) SENSORS_LIMIT(val, 1, 0xFFFF); 633b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data(client, fan_reg_low[ix], 634b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->fan[ix] & 0xFF)) { 635b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, "Register write error, aborting.\n"); 636b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EIO; 637b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj goto EXIT; 638b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 639b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data(client, 640b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj fan_reg_hi[ix], data->fan[ix] >> 8)) { 641b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, "Register write error, aborting.\n"); 642b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EIO; 643b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 644b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljEXIT: 645b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_unlock(&data->update_lock); 646b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return count; 647b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 648b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 649b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 650b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 651b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_fan1_div( 652b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 653b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *devattr, 654b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj char *buf) 655b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 656b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = amc6821_update_device(dev); 657b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return sprintf(buf, "%d\n", data->fan1_div); 658b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 659b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 660b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_fan1_div( 661b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device *dev, 662b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct device_attribute *attr, 663b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj const char *buf, size_t count) 664b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 665b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client = to_i2c_client(dev); 666b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = i2c_get_clientdata(client); 667b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj long val; 668b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int config = strict_strtol(buf, 10, &val); 669b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (config) 670b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return config; 671b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 672b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); 673b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (config < 0) { 674b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 675b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Error reading configuration register, aborting.\n"); 676b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -EIO; 677b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 678b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_lock(&data->update_lock); 679b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj switch (val) { 680b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 2: 681b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF4_PSPR; 682b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->fan1_div = 2; 683b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 684b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 4: 685b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config |= AMC6821_CONF4_PSPR; 686b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->fan1_div = 4; 687b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 688b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj default: 689b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_unlock(&data->update_lock); 690b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EINVAL; 691b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj goto EXIT; 692b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 693b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, config)) { 694b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 695b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Configuration register write error, aborting.\n"); 696b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj count = -EIO; 697b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 698b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljEXIT: 699b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_unlock(&data->update_lock); 700b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return count; 701b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 702b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 703b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 704b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 705b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, 706b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp, NULL, IDX_TEMP1_INPUT); 707b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp, 708b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj set_temp, IDX_TEMP1_MIN); 709b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, get_temp, 710b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj set_temp, IDX_TEMP1_MAX); 711b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, get_temp, 712b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj set_temp, IDX_TEMP1_CRIT); 713b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, 714b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_alarm, NULL, IDX_TEMP1_MIN); 715b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, 716b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_alarm, NULL, IDX_TEMP1_MAX); 717b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, 718b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_alarm, NULL, IDX_TEMP1_CRIT); 719b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO | S_IWUSR, 720b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp, NULL, IDX_TEMP2_INPUT); 721b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, get_temp, 722b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj set_temp, IDX_TEMP2_MIN); 723b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, get_temp, 724b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj set_temp, IDX_TEMP2_MAX); 725b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR, get_temp, 726b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj set_temp, IDX_TEMP2_CRIT); 727b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, 728b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp2_fault, NULL, 0); 729b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, 730b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_alarm, NULL, IDX_TEMP2_MIN); 731b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, 732b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_alarm, NULL, IDX_TEMP2_MAX); 733b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, 734b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_alarm, NULL, IDX_TEMP2_CRIT); 735b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, IDX_FAN1_INPUT); 736b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, 737b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_fan, set_fan, IDX_FAN1_MIN); 738b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO | S_IWUSR, 739b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_fan, set_fan, IDX_FAN1_MAX); 740b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan1_fault, NULL, 0); 741b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, 742b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_fan1_div, set_fan1_div, 0); 743b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 744b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm1, set_pwm1, 0); 745b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, 746b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_pwm1_enable, set_pwm1_enable, 0); 747b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, 748b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_pwm1_auto_point_pwm, NULL, 0); 749b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, 750b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_pwm1_auto_point_pwm, set_pwm1_auto_point_pwm, 1); 751b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, 752b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_pwm1_auto_point_pwm, NULL, 2); 753b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO, 754b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_pwm1_auto_channels_temp, NULL, 0); 755b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO, 756b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_auto_point_temp, NULL, 1, 0); 757b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, 758b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 1); 759b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp1_auto_point3_temp, S_IWUSR | S_IRUGO, 760b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 2); 761b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 762b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, 763b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 0); 764b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, 765b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 1); 766b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO, 767b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2); 768b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 769b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 770b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 771b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic struct attribute *amc6821_attrs[] = { 772b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp1_input.dev_attr.attr, 773b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp1_min.dev_attr.attr, 774b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp1_max.dev_attr.attr, 775b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp1_crit.dev_attr.attr, 776b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 777b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 778b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 779b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_input.dev_attr.attr, 780b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_min.dev_attr.attr, 781b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_max.dev_attr.attr, 782b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_crit.dev_attr.attr, 783b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, 784b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, 785b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, 786b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_fault.dev_attr.attr, 787b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_fan1_input.dev_attr.attr, 788b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_fan1_min.dev_attr.attr, 789b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_fan1_max.dev_attr.attr, 790b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_fan1_fault.dev_attr.attr, 791b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_fan1_div.dev_attr.attr, 792b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_pwm1.dev_attr.attr, 793b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_pwm1_enable.dev_attr.attr, 794b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, 795b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, 796b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, 797b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, 798b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, 799b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, 800b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp1_auto_point3_temp.dev_attr.attr, 801b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, 802b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, 803b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj &sensor_dev_attr_temp2_auto_point3_temp.dev_attr.attr, 804b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj NULL 805b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}; 806b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 807b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic struct attribute_group amc6821_attr_grp = { 808b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj .attrs = amc6821_attrs, 809b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}; 810b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 811b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 812b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 813b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/* Return 0 if detection is successful, -ENODEV otherwise */ 814b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int amc6821_detect( 815b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client, 816b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_board_info *info) 817b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 818b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_adapter *adapter = client->adapter; 819b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int address = client->addr; 820b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int dev_id, comp_id; 821b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 822b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_dbg(&adapter->dev, "amc6821_detect called.\n"); 823b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 824b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 825b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_dbg(&adapter->dev, 826b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "amc6821: I2C bus doesn't support byte mode, " 827b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "skipping.\n"); 828b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -ENODEV; 829b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 830b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 831b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_id = i2c_smbus_read_byte_data(client, AMC6821_REG_DEV_ID); 832b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj comp_id = i2c_smbus_read_byte_data(client, AMC6821_REG_COMP_ID); 833b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (dev_id != 0x21 || comp_id != 0x49) { 834b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_dbg(&adapter->dev, 835b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "amc6821: detection failed at 0x%02x.\n", 836b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj address); 837b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -ENODEV; 838b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 839b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 840b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj /* Bit 7 of the address register is ignored, so we can check the 841b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj ID registers again */ 842b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_DEV_ID); 843b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj comp_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_COMP_ID); 844b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (dev_id != 0x21 || comp_id != 0x49) { 845b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_dbg(&adapter->dev, 846b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "amc6821: detection failed at 0x%02x.\n", 847b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj address); 848b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -ENODEV; 849b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 850b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 851b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_info(&adapter->dev, "amc6821: chip found at 0x%02x.\n", address); 852b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj strlcpy(info->type, "amc6821", I2C_NAME_SIZE); 853b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 854b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return 0; 855b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 856b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 857b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int amc6821_probe( 858b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client, 859b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj const struct i2c_device_id *id) 860b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 861b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data; 862b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int err; 863b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 864b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data = kzalloc(sizeof(struct amc6821_data), GFP_KERNEL); 865b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (!data) { 866b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, "out of memory.\n"); 867b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return -ENOMEM; 868b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 869b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 870b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 871b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj i2c_set_clientdata(client, data); 872b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_init(&data->update_lock); 873b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 874b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj /* 875b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj * Initialize the amc6821 chip 876b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj */ 877b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj err = amc6821_init_client(client); 878b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (err) 879b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj goto err_free; 880b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 881b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp); 882b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (err) 883b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj goto err_free; 884b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 885b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->hwmon_dev = hwmon_device_register(&client->dev); 886b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (!IS_ERR(data->hwmon_dev)) 887b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return 0; 888b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 889b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj err = PTR_ERR(data->hwmon_dev); 890b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, "error registering hwmon device.\n"); 891b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); 892b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljerr_free: 893b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj kfree(data); 894b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return err; 895b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 896b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 897b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int amc6821_remove(struct i2c_client *client) 898b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 899b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = i2c_get_clientdata(client); 900b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 901b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj hwmon_device_unregister(data->hwmon_dev); 902b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); 903b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 904b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj kfree(data); 905b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 906b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return 0; 907b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 908b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 909b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 910b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int amc6821_init_client(struct i2c_client *client) 911b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 912b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int config; 913b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int err = -EIO; 914b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 915b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (init) { 916b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); 917b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 918b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (config < 0) { 919b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 920b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Error reading configuration register, aborting.\n"); 921b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return err; 922b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 923b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 924b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config |= AMC6821_CONF4_MODE; 925b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 926b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, 927b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config)) { 928b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 929b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Configuration register write error, aborting.\n"); 930b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return err; 931b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 932b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 933b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF3); 934b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 935b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (config < 0) { 936b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 937b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Error reading configuration register, aborting.\n"); 938b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return err; 939b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 940b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 941b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_info(&client->dev, "Revision %d\n", config & 0x0f); 942b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 943b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF3_THERM_FAN_EN; 944b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 945b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF3, 946b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config)) { 947b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 948b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Configuration register write error, aborting.\n"); 949b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return err; 950b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 951b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 952b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF2); 953b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 954b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (config < 0) { 955b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 956b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Error reading configuration register, aborting.\n"); 957b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return err; 958b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 959b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 960b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF2_RTFIE; 961b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF2_LTOIE; 962b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF2_RTOIE; 963b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data(client, 964b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_CONF2, config)) { 965b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 966b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Configuration register write error, aborting.\n"); 967b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return err; 968b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 969b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 970b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); 971b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 972b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (config < 0) { 973b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 974b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Error reading configuration register, aborting.\n"); 975b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return err; 976b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 977b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 978b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF1_THERMOVIE; 979b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF1_FANIE; 980b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config |= AMC6821_CONF1_START; 981b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (pwminv) 982b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config |= AMC6821_CONF1_PWMINV; 983b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj else 984b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj config &= ~AMC6821_CONF1_PWMINV; 985b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 986b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (i2c_smbus_write_byte_data( 987b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj client, AMC6821_REG_CONF1, config)) { 988b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj dev_err(&client->dev, 989b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj "Configuration register write error, aborting.\n"); 990b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return err; 991b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 992b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 993b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return 0; 994b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 995b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 996b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 997b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic struct amc6821_data *amc6821_update_device(struct device *dev) 998b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 999b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct i2c_client *client = to_i2c_client(dev); 1000b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj struct amc6821_data *data = i2c_get_clientdata(client); 1001b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int timeout = HZ; 1002b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj u8 reg; 1003b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj int i; 1004b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1005b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_lock(&data->update_lock); 1006b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1007b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (time_after(jiffies, data->last_updated + timeout) || 1008b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj !data->valid) { 1009b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1010b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj for (i = 0; i < TEMP_IDX_LEN; i++) 1011b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp[i] = i2c_smbus_read_byte_data(client, 1012b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj temp_reg[i]); 1013b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1014b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->stat1 = i2c_smbus_read_byte_data(client, 1015b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_STAT1); 1016b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->stat2 = i2c_smbus_read_byte_data(client, 1017b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_STAT2); 1018b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1019b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1 = i2c_smbus_read_byte_data(client, 1020b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_DCY); 1021b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj for (i = 0; i < FAN1_IDX_LEN; i++) { 1022b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->fan[i] = i2c_smbus_read_byte_data( 1023b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj client, 1024b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj fan_reg_low[i]); 1025b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->fan[i] += i2c_smbus_read_byte_data( 1026b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj client, 1027b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj fan_reg_hi[i]) << 8; 1028b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 1029b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->fan1_div = i2c_smbus_read_byte_data(client, 1030b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_CONF4); 1031b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2; 1032b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1033b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_point_pwm[0] = 0; 1034b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_point_pwm[2] = 255; 1035b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client, 1036b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_DCY_LOW_TEMP); 1037b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1038b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp1_auto_point_temp[0] = 1039b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj i2c_smbus_read_byte_data(client, 1040b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_PSV_TEMP); 1041b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp2_auto_point_temp[0] = 1042b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp1_auto_point_temp[0]; 1043b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg = i2c_smbus_read_byte_data(client, 1044b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_LTEMP_FAN_CTRL); 1045b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1; 1046b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg &= 0x07; 1047b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg = 0x20 >> reg; 1048b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (reg > 0) 1049b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp1_auto_point_temp[2] = 1050b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp1_auto_point_temp[1] + 1051b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj (data->pwm1_auto_point_pwm[2] - 1052b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_point_pwm[1]) / reg; 1053b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj else 1054b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp1_auto_point_temp[2] = 255; 1055b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1056b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg = i2c_smbus_read_byte_data(client, 1057b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj AMC6821_REG_RTEMP_FAN_CTRL); 1058b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1; 1059b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg &= 0x07; 1060b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg = 0x20 >> reg; 1061b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj if (reg > 0) 1062b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp2_auto_point_temp[2] = 1063b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp2_auto_point_temp[1] + 1064b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj (data->pwm1_auto_point_pwm[2] - 1065b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_point_pwm[1]) / reg; 1066b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj else 1067b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->temp2_auto_point_temp[2] = 255; 1068b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1069b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); 1070b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj reg = (reg >> 5) & 0x3; 1071b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj switch (reg) { 1072b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 0: /*open loop: software sets pwm1*/ 1073b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_channels_temp = 0; 1074b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_enable = 1; 1075b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 1076b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 2: /*closed loop: remote T (temp2)*/ 1077b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_channels_temp = 2; 1078b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_enable = 2; 1079b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 1080b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 3: /*closed loop: local and remote T (temp2)*/ 1081b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_channels_temp = 3; 1082b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_enable = 3; 1083b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 1084b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj case 1: /*semi-open loop: software sets rpm, chip controls pwm1, 1085b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj *currently not implemented 1086b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj */ 1087b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_auto_channels_temp = 0; 1088b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->pwm1_enable = 0; 1089b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj break; 1090b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 1091b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1092b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->last_updated = jiffies; 1093b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj data->valid = 1; 1094b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj } 1095b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj mutex_unlock(&data->update_lock); 1096b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return data; 1097b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 1098b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1099b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1100b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int __init amc6821_init(void) 1101b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 1102b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj return i2c_add_driver(&amc6821_driver); 1103b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 1104b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1105b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic void __exit amc6821_exit(void) 1106b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{ 1107b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj i2c_del_driver(&amc6821_driver); 1108b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj} 1109b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1110b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljmodule_init(amc6821_init); 1111b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljmodule_exit(amc6821_exit); 1112b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1113b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj 1114b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljMODULE_LICENSE("GPL"); 1115b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljMODULE_AUTHOR("T. Mertelj <tomaz.mertelj@guest.arnes.si>"); 1116b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljMODULE_DESCRIPTION("Texas Instruments amc6821 hwmon driver"); 1117