/drivers/hwmon/adt7462.c
C | 1993 lines | 1682 code | 242 blank | 69 comment | 141 complexity | 66735519d33ca5d11ea134b8e1687da7 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- /*
- * A hwmon driver for the Analog Devices ADT7462
- * Copyright (C) 2008 IBM
- *
- * Author: Darrick J. Wong <djwong@us.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <linux/module.h>
- #include <linux/jiffies.h>
- #include <linux/i2c.h>
- #include <linux/hwmon.h>
- #include <linux/hwmon-sysfs.h>
- #include <linux/err.h>
- #include <linux/mutex.h>
- #include <linux/delay.h>
- #include <linux/log2.h>
- #include <linux/slab.h>
- /* Addresses to scan */
- static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
- /* ADT7462 registers */
- #define ADT7462_REG_DEVICE 0x3D
- #define ADT7462_REG_VENDOR 0x3E
- #define ADT7462_REG_REVISION 0x3F
- #define ADT7462_REG_MIN_TEMP_BASE_ADDR 0x44
- #define ADT7462_REG_MIN_TEMP_MAX_ADDR 0x47
- #define ADT7462_REG_MAX_TEMP_BASE_ADDR 0x48
- #define ADT7462_REG_MAX_TEMP_MAX_ADDR 0x4B
- #define ADT7462_REG_TEMP_BASE_ADDR 0x88
- #define ADT7462_REG_TEMP_MAX_ADDR 0x8F
- #define ADT7462_REG_FAN_BASE_ADDR 0x98
- #define ADT7462_REG_FAN_MAX_ADDR 0x9F
- #define ADT7462_REG_FAN2_BASE_ADDR 0xA2
- #define ADT7462_REG_FAN2_MAX_ADDR 0xA9
- #define ADT7462_REG_FAN_ENABLE 0x07
- #define ADT7462_REG_FAN_MIN_BASE_ADDR 0x78
- #define ADT7462_REG_FAN_MIN_MAX_ADDR 0x7F
- #define ADT7462_REG_CFG2 0x02
- #define ADT7462_FSPD_MASK 0x20
- #define ADT7462_REG_PWM_BASE_ADDR 0xAA
- #define ADT7462_REG_PWM_MAX_ADDR 0xAD
- #define ADT7462_REG_PWM_MIN_BASE_ADDR 0x28
- #define ADT7462_REG_PWM_MIN_MAX_ADDR 0x2B
- #define ADT7462_REG_PWM_MAX 0x2C
- #define ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR 0x5C
- #define ADT7462_REG_PWM_TEMP_MIN_MAX_ADDR 0x5F
- #define ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR 0x60
- #define ADT7462_REG_PWM_TEMP_RANGE_MAX_ADDR 0x63
- #define ADT7462_PWM_HYST_MASK 0x0F
- #define ADT7462_PWM_RANGE_MASK 0xF0
- #define ADT7462_PWM_RANGE_SHIFT 4
- #define ADT7462_REG_PWM_CFG_BASE_ADDR 0x21
- #define ADT7462_REG_PWM_CFG_MAX_ADDR 0x24
- #define ADT7462_PWM_CHANNEL_MASK 0xE0
- #define ADT7462_PWM_CHANNEL_SHIFT 5
- #define ADT7462_REG_PIN_CFG_BASE_ADDR 0x10
- #define ADT7462_REG_PIN_CFG_MAX_ADDR 0x13
- #define ADT7462_PIN7_INPUT 0x01 /* cfg0 */
- #define ADT7462_DIODE3_INPUT 0x20
- #define ADT7462_DIODE1_INPUT 0x40
- #define ADT7462_VID_INPUT 0x80
- #define ADT7462_PIN22_INPUT 0x04 /* cfg1 */
- #define ADT7462_PIN21_INPUT 0x08
- #define ADT7462_PIN19_INPUT 0x10
- #define ADT7462_PIN15_INPUT 0x20
- #define ADT7462_PIN13_INPUT 0x40
- #define ADT7462_PIN8_INPUT 0x80
- #define ADT7462_PIN23_MASK 0x03
- #define ADT7462_PIN23_SHIFT 0
- #define ADT7462_PIN26_MASK 0x0C /* cfg2 */
- #define ADT7462_PIN26_SHIFT 2
- #define ADT7462_PIN25_MASK 0x30
- #define ADT7462_PIN25_SHIFT 4
- #define ADT7462_PIN24_MASK 0xC0
- #define ADT7462_PIN24_SHIFT 6
- #define ADT7462_PIN26_VOLT_INPUT 0x08
- #define ADT7462_PIN25_VOLT_INPUT 0x20
- #define ADT7462_PIN28_SHIFT 4 /* cfg3 */
- #define ADT7462_PIN28_VOLT 0x5
- #define ADT7462_REG_ALARM1 0xB8
- #define ADT7462_LT_ALARM 0x02
- #define ADT7462_R1T_ALARM 0x04
- #define ADT7462_R2T_ALARM 0x08
- #define ADT7462_R3T_ALARM 0x10
- #define ADT7462_REG_ALARM2 0xBB
- #define ADT7462_V0_ALARM 0x01
- #define ADT7462_V1_ALARM 0x02
- #define ADT7462_V2_ALARM 0x04
- #define ADT7462_V3_ALARM 0x08
- #define ADT7462_V4_ALARM 0x10
- #define ADT7462_V5_ALARM 0x20
- #define ADT7462_V6_ALARM 0x40
- #define ADT7462_V7_ALARM 0x80
- #define ADT7462_REG_ALARM3 0xBC
- #define ADT7462_V8_ALARM 0x08
- #define ADT7462_V9_ALARM 0x10
- #define ADT7462_V10_ALARM 0x20
- #define ADT7462_V11_ALARM 0x40
- #define ADT7462_V12_ALARM 0x80
- #define ADT7462_REG_ALARM4 0xBD
- #define ADT7462_F0_ALARM 0x01
- #define ADT7462_F1_ALARM 0x02
- #define ADT7462_F2_ALARM 0x04
- #define ADT7462_F3_ALARM 0x08
- #define ADT7462_F4_ALARM 0x10
- #define ADT7462_F5_ALARM 0x20
- #define ADT7462_F6_ALARM 0x40
- #define ADT7462_F7_ALARM 0x80
- #define ADT7462_ALARM1 0x0000
- #define ADT7462_ALARM2 0x0100
- #define ADT7462_ALARM3 0x0200
- #define ADT7462_ALARM4 0x0300
- #define ADT7462_ALARM_REG_SHIFT 8
- #define ADT7462_ALARM_FLAG_MASK 0x0F
- #define ADT7462_TEMP_COUNT 4
- #define ADT7462_TEMP_REG(x) (ADT7462_REG_TEMP_BASE_ADDR + (x * 2))
- #define ADT7462_TEMP_MIN_REG(x) (ADT7462_REG_MIN_TEMP_BASE_ADDR + (x))
- #define ADT7462_TEMP_MAX_REG(x) (ADT7462_REG_MAX_TEMP_BASE_ADDR + (x))
- #define TEMP_FRAC_OFFSET 6
- #define ADT7462_FAN_COUNT 8
- #define ADT7462_REG_FAN_MIN(x) (ADT7462_REG_FAN_MIN_BASE_ADDR + (x))
- #define ADT7462_PWM_COUNT 4
- #define ADT7462_REG_PWM(x) (ADT7462_REG_PWM_BASE_ADDR + (x))
- #define ADT7462_REG_PWM_MIN(x) (ADT7462_REG_PWM_MIN_BASE_ADDR + (x))
- #define ADT7462_REG_PWM_TMIN(x) \
- (ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR + (x))
- #define ADT7462_REG_PWM_TRANGE(x) \
- (ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR + (x))
- #define ADT7462_PIN_CFG_REG_COUNT 4
- #define ADT7462_REG_PIN_CFG(x) (ADT7462_REG_PIN_CFG_BASE_ADDR + (x))
- #define ADT7462_REG_PWM_CFG(x) (ADT7462_REG_PWM_CFG_BASE_ADDR + (x))
- #define ADT7462_ALARM_REG_COUNT 4
- /*
- * The chip can measure 13 different voltage sources:
- *
- * 1. +12V1 (pin 7)
- * 2. Vccp1/+2.5V/+1.8V/+1.5V (pin 23)
- * 3. +12V3 (pin 22)
- * 4. +5V (pin 21)
- * 5. +1.25V/+0.9V (pin 19)
- * 6. +2.5V/+1.8V (pin 15)
- * 7. +3.3v (pin 13)
- * 8. +12V2 (pin 8)
- * 9. Vbatt/FSB_Vtt (pin 26)
- * A. +3.3V/+1.2V1 (pin 25)
- * B. Vccp2/+2.5V/+1.8V/+1.5V (pin 24)
- * C. +1.5V ICH (only if BOTH pin 28/29 are set to +1.5V)
- * D. +1.5V 3GPIO (only if BOTH pin 28/29 are set to +1.5V)
- *
- * Each of these 13 has a factor to convert raw to voltage. Even better,
- * the pins can be connected to other sensors (tach/gpio/hot/etc), which
- * makes the bookkeeping tricky.
- *
- * Some, but not all, of these voltages have low/high limits.
- */
- #define ADT7462_VOLT_COUNT 13
- #define ADT7462_VENDOR 0x41
- #define ADT7462_DEVICE 0x62
- /* datasheet only mentions a revision 4 */
- #define ADT7462_REVISION 0x04
- /* How often do we reread sensors values? (In jiffies) */
- #define SENSOR_REFRESH_INTERVAL (2 * HZ)
- /* How often do we reread sensor limit values? (In jiffies) */
- #define LIMIT_REFRESH_INTERVAL (60 * HZ)
- /* datasheet says to divide this number by the fan reading to get fan rpm */
- #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x))
- #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM
- #define FAN_PERIOD_INVALID 65535
- #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
- #define MASK_AND_SHIFT(value, prefix) \
- (((value) & prefix##_MASK) >> prefix##_SHIFT)
- struct adt7462_data {
- struct device *hwmon_dev;
- struct attribute_group attrs;
- struct mutex lock;
- char sensors_valid;
- char limits_valid;
- unsigned long sensors_last_updated; /* In jiffies */
- unsigned long limits_last_updated; /* In jiffies */
- u8 temp[ADT7462_TEMP_COUNT];
- /* bits 6-7 are quarter pieces of temp */
- u8 temp_frac[ADT7462_TEMP_COUNT];
- u8 temp_min[ADT7462_TEMP_COUNT];
- u8 temp_max[ADT7462_TEMP_COUNT];
- u16 fan[ADT7462_FAN_COUNT];
- u8 fan_enabled;
- u8 fan_min[ADT7462_FAN_COUNT];
- u8 cfg2;
- u8 pwm[ADT7462_PWM_COUNT];
- u8 pin_cfg[ADT7462_PIN_CFG_REG_COUNT];
- u8 voltages[ADT7462_VOLT_COUNT];
- u8 volt_max[ADT7462_VOLT_COUNT];
- u8 volt_min[ADT7462_VOLT_COUNT];
- u8 pwm_min[ADT7462_PWM_COUNT];
- u8 pwm_tmin[ADT7462_PWM_COUNT];
- u8 pwm_trange[ADT7462_PWM_COUNT];
- u8 pwm_max; /* only one per chip */
- u8 pwm_cfg[ADT7462_PWM_COUNT];
- u8 alarms[ADT7462_ALARM_REG_COUNT];
- };
- static int adt7462_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
- static int adt7462_detect(struct i2c_client *client,
- struct i2c_board_info *info);
- static int adt7462_remove(struct i2c_client *client);
- static const struct i2c_device_id adt7462_id[] = {
- { "adt7462", 0 },
- { }
- };
- MODULE_DEVICE_TABLE(i2c, adt7462_id);