mirror of
https://github.com/lm-sensors/lm-sensors
synced 2025-09-06 01:05:32 +00:00
Initial support for the Fintek F71805F/FG chip.
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@3169 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -26,6 +26,7 @@ ask CVS about it:
|
||||
Drop I2C_FUNC_SMBUS_EMUL
|
||||
Library: Big update to use libsysfs. More TODO though.
|
||||
Fix bus matching code for Linux 2.6 (Karsten Petersen)
|
||||
Add f71805f support
|
||||
Makefile: Compile user-space programs with -Wundef
|
||||
Module i2c-i810: Documentation update, PCI IDs cleanup
|
||||
Module i2c-keywest: Remove bus probing code (2.6 backport)
|
||||
@@ -41,6 +42,7 @@ ask CVS about it:
|
||||
not initialize i2c_adapter name to "unset" (2.6
|
||||
backport)
|
||||
Module adm9240: Cleanups (2.6 backport)
|
||||
Module f71805f: New, supports the Fintek F71805F/FG Super-I/O
|
||||
Module it87: Minor cleanups
|
||||
Module lm90: Support the ADM1032-2 and ADT7461-2 (2.6 backport)
|
||||
Module via686a: Cleanups
|
||||
@@ -62,6 +64,7 @@ ask CVS about it:
|
||||
Drop EEPROM support (Aurelien Jarno)
|
||||
Program sensors: Drop free_the_label
|
||||
Fix compilation with uclibc (no iconv)
|
||||
Add f71805f support
|
||||
Program sensors-detect: Drop algorithm names
|
||||
Do not rely on i2cdetect -l printing algo names
|
||||
Simplify adapter name matching mechanism
|
||||
|
@@ -78,7 +78,8 @@ if you have questions, suggestions or problems.
|
||||
Author of the i2c-sis630 bus driver.
|
||||
Added Onsemi MC1066 support to the adm1021 driver.
|
||||
* Jean Delvare <khali@linux-fr.org>
|
||||
Author of the lm63, lm83, lm90, pc87360 and w83l785ts chip drivers.
|
||||
Author of the lm63, lm83, lm90 and w83l785ts SMBus chip drivers.
|
||||
Author of the f71805f and pc87360 Super-I/O chip drivers.
|
||||
Author of the i2c-amd756-s4882 and pca9540 SMBus multiplexing drivers.
|
||||
Author of the decode-vaio.pl Vaio EEPROM decoder.
|
||||
Author of the decode-edid.pl EDID data decoder.
|
||||
|
1
README
1
README
@@ -78,6 +78,7 @@ At least the following hardware sensor chips are supported:
|
||||
Asus AS99127F, ASB100 Bach
|
||||
Dallas Semiconductor DS75, DS1621, DS1625, DS1775, and DS1780
|
||||
Hewlett Packard Maxilife (several revisions including '99 NBA)
|
||||
Fintek F71805F/FG
|
||||
Fujitsu Siemens Poseidon, Scylla, Hermes
|
||||
Genesys Logic GL518SM, GL520SM, GL523SM
|
||||
Intel Xeon processor embedded sensors
|
||||
|
@@ -97,6 +97,9 @@ ds1621
|
||||
(the following chip is detected as a ds1621)
|
||||
ds1625 1 - - - yes no
|
||||
|
||||
f71805f
|
||||
f71805f 9 3 3 - no yes
|
||||
|
||||
fscher
|
||||
fscher 3 3 3 - yes no
|
||||
|
||||
|
107
doc/chips/f71805f
Normal file
107
doc/chips/f71805f
Normal file
@@ -0,0 +1,107 @@
|
||||
Kernel driver `f71805f.o'
|
||||
=========================
|
||||
|
||||
Status: Beta.
|
||||
|
||||
Supported chips:
|
||||
* Fintek F71805F/FG
|
||||
Addresses scanned: none, address read from Super I/O config space
|
||||
Prefix: 'f71805f'
|
||||
Datasheet: Provided by Fintek on request
|
||||
|
||||
Author: Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
Thanks to Denis Kieft from Barracuda Networks for the donation of a
|
||||
test system (custom Jetway K8M8MS motherboard, with CPU and RAM) and
|
||||
for providing initial documentation.
|
||||
|
||||
Thanks to Kris Chen from Fintek for answering technical questions and
|
||||
providing additional documentation.
|
||||
|
||||
Thanks to Chris Lin from Jetway for providing wiring schematics and
|
||||
anwsering technical questions.
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The Fintek F71805F/FG Super I/O chip includes complete hardware monitoring
|
||||
capabilities. It can monitor up to 9 voltages (counting its own power
|
||||
source), 3 fans and 3 temperature sensors.
|
||||
|
||||
This chip also has fan controlling features, using either DC or PWM, in
|
||||
three different modes (one manual, two automatic). The driver doesn't
|
||||
support these features yet.
|
||||
|
||||
The driver assumes that no more than one chip is present, which seems
|
||||
reasonable.
|
||||
|
||||
|
||||
Voltage Monitoring
|
||||
------------------
|
||||
|
||||
Voltages are sampled by an 8-bit ADC with a LSB of 8 mV. The supported
|
||||
range is thus from 0 to 2.040 V. Voltage values outside of this range
|
||||
need external resistors. An exception is in0, which is used to monitor
|
||||
the chip's own power source (+3.3V), and is divided internally by a
|
||||
factor 2.
|
||||
|
||||
The two LSB of the voltage limit registers are not used (always 0), so
|
||||
you can only set the limits in steps of 32 mV (before scaling).
|
||||
|
||||
The wirings and resistor values suggested by Fintek are as follow:
|
||||
|
||||
pin expected
|
||||
name use R1 R2 divider raw val.
|
||||
|
||||
in0 VCC VCC3.3V int. int. 2.00 1.65 V
|
||||
in1 VIN1 VTT1.2V 10K - 1.00 1.20 V
|
||||
in2 VIN2 VRAM 100K 100K 2.00 ~1.25 V (1)
|
||||
in3 VIN3 VCHIPSET 47K 100K 1.47 2.24 V (2)
|
||||
in4 VIN4 VCC5V 200K 47K 5.25 0.95 V
|
||||
in5 VIN5 +12V 200K 20K 11.00 1.05 V
|
||||
in6 VIN6 VCC1.5V 10K - 1.00 1.50 V
|
||||
in7 VIN7 VCORE 10K - 1.00 ~1.40 V (1)
|
||||
in8 VIN8 VSB5V 200K 47K 1.00 0.95 V
|
||||
|
||||
(1) Depends on your hardware setup.
|
||||
(2) Obviously not correct, swapping R1 and R2 would make more sense.
|
||||
|
||||
These values can be used as hints at best, as motherboard manufacturers
|
||||
are free to use a completely different setup. As a matter of fact, the
|
||||
Jetway K8M8MS uses a significantly different setup. You will have to
|
||||
find out documentation about your own motherboard, and edit sensors.conf
|
||||
accordingly.
|
||||
|
||||
Each voltage measured has associated low and high limits, each of which
|
||||
triggers an alarm when crossed.
|
||||
|
||||
|
||||
Fan Monitoring
|
||||
--------------
|
||||
|
||||
Fan rotation speeds are reported as 12-bit values from a gated clock
|
||||
signal. Speeds down to 366 RPM can be measured. There is no theoretical
|
||||
high limit, but values over 6000 RPM seem to cause problem. The effective
|
||||
resolution is much lower than you would expect, the step between different
|
||||
register values being 10 rather than 1.
|
||||
|
||||
The chip assumes 2 pulse-per-revolution fans.
|
||||
|
||||
An alarm is triggered if the rotation speed drops below a programmable
|
||||
limit or is too low to be measured.
|
||||
|
||||
|
||||
Temperature Monitoring
|
||||
----------------------
|
||||
|
||||
Temperatures are reported in degrees Celsius. Each temperature measured
|
||||
has a high limit, those crossing triggers an alarm. There is an associated
|
||||
hysteresis value, below which the temperature has to drop before the
|
||||
alarm is cleared.
|
||||
|
||||
All temperature channels are external, there is no embedded temperature
|
||||
sensor. Each channel can be used for connecting either a thermal diode
|
||||
or a thermistor. The driver reports the currently selected mode, but
|
||||
doesn't allow changing it. In theory, the BIOS should have configured
|
||||
everything properly.
|
@@ -85,3 +85,6 @@ Wincor Nixdorf Seagate Barracuda 7200.7 160GB harddisk drive 2004-10
|
||||
|
||||
Aweta Intel Server system 2005-09
|
||||
Drivers developed: PC87431 (IPMI SMB) MDS
|
||||
|
||||
Barracuda Jetway K8M8MS, Sempron 2600+, 256 MB RAM 2005-10
|
||||
Networks Drivers developed: f71805f Jean Delvare
|
||||
|
@@ -2366,3 +2366,67 @@ chip "w83627ehf-*"
|
||||
set temp2_over 45
|
||||
set temp2_hyst 40
|
||||
|
||||
|
||||
# Fintek F71805F/FG configuration
|
||||
# This is the recommended wiring and resistor values from the F71805F/FG
|
||||
# datasheet. Your motherboard manufacturer may or may not have followed
|
||||
# these.
|
||||
chip "f71805f-*"
|
||||
# Voltages
|
||||
label in0 "+3.3V"
|
||||
label in1 "Vtt1.2V"
|
||||
label in2 "Vram"
|
||||
label in3 "Vchip"
|
||||
label in4 "+5V"
|
||||
label in5 "+12V"
|
||||
label in6 "Vcc1.5V"
|
||||
label in7 "Vcore"
|
||||
label in8 "5VSB"
|
||||
|
||||
# in0 is scaled internally
|
||||
compute in2 @*(1+100/100), @/(1+100/100)
|
||||
compute in3 @*(1+100/47), @/(1+100/47)
|
||||
compute in4 @*(1+200/47), @/(1+200/47)
|
||||
compute in5 @*(1+200/20), @/(1+200/20)
|
||||
compute in8 @*(1+200/47), @/(1+200/47)
|
||||
|
||||
set in0_min 3.3 * 0.95
|
||||
set in0_max 3.3 * 1.05
|
||||
#set in1_min 1.2 * 0.95
|
||||
#set in1_max 1.2 * 1.05
|
||||
#set in2_min 2.5 * 0.95
|
||||
#set in2_max 2.6 * 1.05
|
||||
#set in3_min 3.3 * 0.95
|
||||
#set in3_max 3.3 * 1.05
|
||||
#set in4_min 5.0 * 0.95
|
||||
#set in4_max 5.0 * 1.05
|
||||
#set in5_min 12.0 * 0.95
|
||||
#set in5_max 12.0 * 1.05
|
||||
#set in6_min 1.5 * 0.95
|
||||
#set in6_max 1.5 * 1.05
|
||||
# in7 nominal value depends on the CPU model
|
||||
#set in7_min 1.4 * 0.95
|
||||
#set in7_max 1.4 * 1.05
|
||||
#set in8_min 5.0 * 0.95
|
||||
#set in8_max 5.0 * 1.05
|
||||
|
||||
# Fans
|
||||
label fan1 "CPU Fan"
|
||||
label fan2 "Sys Fan"
|
||||
label fan3 "Aux Fan"
|
||||
|
||||
#set fan1_min 2100
|
||||
#set fan2_min 1400
|
||||
#set fan3_min 1400
|
||||
|
||||
# Temperatures
|
||||
label temp1 "CPU Temp"
|
||||
label temp2 "Sys Temp"
|
||||
label temp3 "Aux Temp"
|
||||
|
||||
#set temp1_max 60
|
||||
#set temp1_hyst 58
|
||||
#set temp2_max 50
|
||||
#set temp2_hyst 48
|
||||
#set temp3_max 50
|
||||
#set temp3_hyst 48
|
||||
|
@@ -71,6 +71,9 @@ endif
|
||||
ifneq ($(shell if grep -q '^CONFIG_SENSORS_EEPROM=y' $(LINUX)/.config; then echo 1; fi),1)
|
||||
KERNELCHIPSTARGETS += $(MODULE_DIR)/eeprom.o
|
||||
endif
|
||||
ifneq ($(shell if grep -q '^CONFIG_SENSORS_F71805F=y' $(LINUX)/.config; then echo 1; fi),1)
|
||||
KERNELCHIPSTARGETS += $(MODULE_DIR)/f71805f.o
|
||||
endif
|
||||
ifneq ($(shell if grep -q '^CONFIG_SENSORS_FSCHER=y' $(LINUX)/.config; then echo 1; fi),1)
|
||||
KERNELCHIPSTARGETS += $(MODULE_DIR)/fscher.o
|
||||
endif
|
||||
|
751
kernel/chips/f71805f.c
Normal file
751
kernel/chips/f71805f.c
Normal file
@@ -0,0 +1,751 @@
|
||||
/*
|
||||
* f71805f.c - driver for the Fintek F71805F Super-I/O chip integrated
|
||||
* hardware monitoring features
|
||||
* Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
|
||||
*
|
||||
* The F71805F is a LPC Super-I/O chip made by Fintek. It integrates
|
||||
* complete hardware monitoring features: voltage, fan and temperature
|
||||
* sensors, and manual and automatic fan speed control.
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-proc.h>
|
||||
#include <asm/io.h>
|
||||
#include "version.h"
|
||||
|
||||
/* ISA address is read from Super-I/O configuration space */
|
||||
static unsigned short normal_i2c[] = { SENSORS_I2C_END };
|
||||
static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
|
||||
static unsigned int normal_isa[] = { 0, SENSORS_ISA_END };
|
||||
static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
|
||||
|
||||
SENSORS_INSMOD_1(f71805f);
|
||||
|
||||
#define DRVNAME "f71805f"
|
||||
|
||||
/*
|
||||
* Super-I/O constants and functions
|
||||
*/
|
||||
|
||||
static int REG; /* The register to read from/write to */
|
||||
static int VAL; /* The value to read/write */
|
||||
|
||||
#define F71805F_LD_HWM 0x04
|
||||
|
||||
#define SIO_REG_LDSEL 0x07 /* Logical device select */
|
||||
#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
|
||||
#define SIO_REG_DEVREV 0x22 /* Device revision */
|
||||
#define SIO_REG_ENABLE 0x30 /* Logical device enable */
|
||||
#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
|
||||
|
||||
#define SIO_F71805F_ID 0x0406
|
||||
|
||||
static inline int
|
||||
superio_inb(int reg)
|
||||
{
|
||||
outb(reg, REG);
|
||||
return inb(VAL);
|
||||
}
|
||||
|
||||
static int
|
||||
superio_inw(int reg)
|
||||
{
|
||||
int val;
|
||||
outb(reg++, REG);
|
||||
val = inb(VAL) << 8;
|
||||
outb(reg, REG);
|
||||
val |= inb(VAL);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void
|
||||
superio_select(int ld)
|
||||
{
|
||||
outb(SIO_REG_LDSEL, REG);
|
||||
outb(ld, VAL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
superio_enter(void)
|
||||
{
|
||||
outb(0x87, REG);
|
||||
outb(0x87, REG);
|
||||
}
|
||||
|
||||
static inline void
|
||||
superio_exit(void)
|
||||
{
|
||||
outb(0xaa, REG);
|
||||
}
|
||||
|
||||
/*
|
||||
* ISA constants
|
||||
*/
|
||||
|
||||
#define REGION_LENGTH 2
|
||||
#define ADDR_REG_OFFSET 0
|
||||
#define DATA_REG_OFFSET 1
|
||||
|
||||
/*
|
||||
* Registers
|
||||
*/
|
||||
|
||||
/* in nr from 0 to 8 (8-bit values) */
|
||||
#define F71805F_REG_IN(nr) (0x10 + (nr))
|
||||
#define F71805F_REG_IN_HIGH(nr) (0x40 + 2 * (nr))
|
||||
#define F71805F_REG_IN_LOW(nr) (0x41 + 2 * (nr))
|
||||
/* fan nr from 0 to 2 (12-bit values, two registers) */
|
||||
#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr))
|
||||
#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr))
|
||||
#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr))
|
||||
/* temp nr from 0 to 2 (8-bit values) */
|
||||
#define F71805F_REG_TEMP(nr) (0x1B + (nr))
|
||||
#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr))
|
||||
#define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr))
|
||||
#define F71805F_REG_TEMP_MODE 0x01
|
||||
|
||||
#define F71805F_REG_START 0x00
|
||||
/* status nr from 0 to 2 */
|
||||
#define F71805F_REG_STATUS(nr) (0x36 + (nr))
|
||||
|
||||
/*
|
||||
* Data structures and manipulation thereof
|
||||
*/
|
||||
|
||||
struct f71805f_data {
|
||||
struct i2c_client client;
|
||||
struct semaphore lock;
|
||||
int sysctl_id;
|
||||
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
unsigned long last_limits; /* In jiffies */
|
||||
|
||||
/* Register values */
|
||||
u8 in[9];
|
||||
u8 in_high[9];
|
||||
u8 in_low[9];
|
||||
u16 fan[3];
|
||||
u16 fan_low[3];
|
||||
u8 fan_enabled; /* Read once at init time */
|
||||
u8 temp[3];
|
||||
u8 temp_high[3];
|
||||
u8 temp_hyst[3];
|
||||
u8 temp_mode;
|
||||
u8 alarms[3];
|
||||
};
|
||||
|
||||
static inline long in_from_reg(u8 reg)
|
||||
{
|
||||
return (reg * 8);
|
||||
}
|
||||
|
||||
/* The 2 least significant bits are not used */
|
||||
static inline u8 in_to_reg(long val)
|
||||
{
|
||||
if (val <= 0)
|
||||
return 0;
|
||||
if (val >= 2016)
|
||||
return 0xfc;
|
||||
return (((val + 16) / 32) << 2);
|
||||
}
|
||||
|
||||
/* in0 is downscaled by a factor 2 internally */
|
||||
static inline long in0_from_reg(u8 reg)
|
||||
{
|
||||
return (reg * 16);
|
||||
}
|
||||
|
||||
static inline u8 in0_to_reg(long val)
|
||||
{
|
||||
if (val <= 0)
|
||||
return 0;
|
||||
if (val >= 4032)
|
||||
return 0xfc;
|
||||
return (((val + 32) / 64) << 2);
|
||||
}
|
||||
|
||||
/* The 4 most significant bits are not used */
|
||||
static inline long fan_from_reg(u16 reg)
|
||||
{
|
||||
reg &= 0xfff;
|
||||
if (!reg || reg == 0xfff)
|
||||
return 0;
|
||||
return (1500000 / reg);
|
||||
}
|
||||
|
||||
static inline u16 fan_to_reg(long rpm)
|
||||
{
|
||||
/* If the low limit is set below what the chip can measure,
|
||||
store the largest possible 12-bit value in the registers,
|
||||
so that no alarm will ever trigger. */
|
||||
if (rpm < 367)
|
||||
return 0xfff;
|
||||
return (1500000 / rpm);
|
||||
}
|
||||
|
||||
static inline u8 temp_to_reg(long val)
|
||||
{
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
else if (val > 0xff)
|
||||
val = 0xff;
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Driver and client management
|
||||
*/
|
||||
|
||||
static u8 f71805f_read8(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
u8 val;
|
||||
|
||||
down(&data->lock);
|
||||
outb_p(reg, client->addr + ADDR_REG_OFFSET);
|
||||
val = inb_p(client->addr + DATA_REG_OFFSET);
|
||||
up(&data->lock);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void f71805f_write8(struct i2c_client *client, u8 reg, u8 val)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
|
||||
down(&data->lock);
|
||||
outb_p(reg, client->addr + ADDR_REG_OFFSET);
|
||||
outb_p(val, client->addr + DATA_REG_OFFSET);
|
||||
up(&data->lock);
|
||||
}
|
||||
|
||||
/* It is important to read the MSB first, because doing so latches the
|
||||
value of the LSB, so we are sure both bytes belong to the same value. */
|
||||
static u16 f71805f_read16(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
u16 val;
|
||||
|
||||
down(&data->lock);
|
||||
outb_p(reg, client->addr + ADDR_REG_OFFSET);
|
||||
val = inb_p(client->addr + DATA_REG_OFFSET) << 8;
|
||||
outb_p(++reg, client->addr + ADDR_REG_OFFSET);
|
||||
val |= inb_p(client->addr + DATA_REG_OFFSET);
|
||||
up(&data->lock);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void f71805f_write16(struct i2c_client *client, u8 reg, u16 val)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
|
||||
down(&data->lock);
|
||||
outb_p(reg, client->addr + ADDR_REG_OFFSET);
|
||||
outb_p(val >> 8, client->addr + DATA_REG_OFFSET);
|
||||
outb_p(++reg, client->addr + ADDR_REG_OFFSET);
|
||||
outb_p(val & 0xff, client->addr + DATA_REG_OFFSET);
|
||||
up(&data->lock);
|
||||
}
|
||||
|
||||
static struct i2c_driver f71805f_driver;
|
||||
static ctl_table f71805f_dir_table_template[];
|
||||
|
||||
static void f71805f_init_client(struct i2c_client *client)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
u8 reg;
|
||||
int i;
|
||||
|
||||
reg = f71805f_read8(client, F71805F_REG_START);
|
||||
if ((reg & 0x41) != 0x01) {
|
||||
printk(KERN_DEBUG "%s: Starting monitoring operations\n",
|
||||
DRVNAME);
|
||||
f71805f_write8(client,
|
||||
F71805F_REG_START, (reg | 0x01) & ~0x40);
|
||||
}
|
||||
|
||||
/* Fan monitoring can be disabled. If it is, we won't be polling
|
||||
the register values, and instead set the cache to return 0 RPM. */
|
||||
for (i = 0; i < 3; i++) {
|
||||
reg = f71805f_read8(client, F71805F_REG_FAN_CTRL(i));
|
||||
if (!(reg & 0x80))
|
||||
data->fan_enabled |= (1 << i);
|
||||
else
|
||||
data->fan[i] = data->fan_low[i] = 0xfff;
|
||||
}
|
||||
}
|
||||
|
||||
static int f71805f_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
{
|
||||
struct i2c_client *client;
|
||||
struct f71805f_data *data;
|
||||
int err = 0;
|
||||
|
||||
if (!request_region(address, REGION_LENGTH, f71805f_driver.name)) {
|
||||
err = -EBUSY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(data = kmalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto exit_release;
|
||||
}
|
||||
memset(data, 0, sizeof(struct f71805f_data));
|
||||
|
||||
/* Fill in the client fields */
|
||||
client = &data->client;
|
||||
client->addr = address;
|
||||
client->data = data;
|
||||
client->adapter = adapter;
|
||||
client->driver = &f71805f_driver;
|
||||
strcpy(client->name, "F71805F chip");
|
||||
|
||||
init_MUTEX(&data->lock);
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Tell the i2c core a new client has arrived */
|
||||
if ((err = i2c_attach_client(client)))
|
||||
goto exit_free;
|
||||
|
||||
/* Register a new directory entry in /proc */
|
||||
err = i2c_register_entry(client, "f71805f",
|
||||
f71805f_dir_table_template, THIS_MODULE);
|
||||
if (err < 0)
|
||||
goto exit_detach;
|
||||
data->sysctl_id = err;
|
||||
|
||||
/* Initialize the F71805F chip */
|
||||
f71805f_init_client(client);
|
||||
return 0;
|
||||
|
||||
exit_detach:
|
||||
i2c_detach_client(client);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit_release:
|
||||
release_region(address, REGION_LENGTH);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int f71805f_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_detect(adapter, &addr_data, f71805f_detect);
|
||||
}
|
||||
|
||||
static int f71805f_detach_client(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
struct f71805f_data *data = client->data;
|
||||
|
||||
i2c_deregister_entry(data->sysctl_id);
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk(KERN_ERR "%s: Client deregistration failed, "
|
||||
"client not detached\n", DRVNAME);
|
||||
return err;
|
||||
}
|
||||
|
||||
release_region(client->addr, REGION_LENGTH);
|
||||
kfree(client->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void f71805f_update_client(struct i2c_client *client)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
int nr;
|
||||
|
||||
down(&data->update_lock);
|
||||
|
||||
/* Limit registers cache is refreshed after 60 seconds */
|
||||
if ((jiffies - data->last_limits > 60 * HZ)
|
||||
|| (jiffies < data->last_limits)
|
||||
|| !data->valid) {
|
||||
for (nr = 0; nr < 9; nr++) {
|
||||
data->in_high[nr] = f71805f_read8(client,
|
||||
F71805F_REG_IN_HIGH(nr));
|
||||
data->in_low[nr] = f71805f_read8(client,
|
||||
F71805F_REG_IN_LOW(nr));
|
||||
}
|
||||
for (nr = 0; nr < 3; nr++) {
|
||||
if (data->fan_enabled & (1 << nr))
|
||||
data->fan_low[nr] = f71805f_read16(client,
|
||||
F71805F_REG_FAN_LOW(nr));
|
||||
}
|
||||
for (nr = 0; nr < 3; nr++) {
|
||||
data->temp_high[nr] = f71805f_read8(client,
|
||||
F71805F_REG_TEMP_HIGH(nr));
|
||||
data->temp_hyst[nr] = f71805f_read8(client,
|
||||
F71805F_REG_TEMP_HYST(nr));
|
||||
}
|
||||
data->temp_mode = f71805f_read8(client, F71805F_REG_TEMP_MODE);
|
||||
|
||||
data->last_limits = jiffies;
|
||||
}
|
||||
|
||||
/* Measurement registers cache is refreshed after 1 second */
|
||||
if ((jiffies - data->last_updated > HZ)
|
||||
|| (jiffies < data->last_updated)
|
||||
|| !data->valid) {
|
||||
for (nr = 0; nr < 9; nr++) {
|
||||
data->in[nr] = f71805f_read8(client,
|
||||
F71805F_REG_IN(nr));
|
||||
}
|
||||
for (nr = 0; nr < 3; nr++) {
|
||||
if (data->fan_enabled & (1 << nr))
|
||||
data->fan[nr] = f71805f_read16(client,
|
||||
F71805F_REG_FAN(nr));
|
||||
}
|
||||
for (nr = 0; nr < 3; nr++) {
|
||||
data->temp[nr] = f71805f_read8(client,
|
||||
F71805F_REG_TEMP(nr));
|
||||
}
|
||||
for (nr = 0; nr < 3; nr++) {
|
||||
data->alarms[nr] = f71805f_read8(client,
|
||||
F71805F_REG_STATUS(nr));
|
||||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
|
||||
up(&data->update_lock);
|
||||
}
|
||||
|
||||
/* -- SENSORS SYSCTL START -- */
|
||||
#define F71805F_SYSCTL_IN0 1000
|
||||
#define F71805F_SYSCTL_IN1 1001
|
||||
#define F71805F_SYSCTL_IN2 1002
|
||||
#define F71805F_SYSCTL_IN3 1003
|
||||
#define F71805F_SYSCTL_IN4 1004
|
||||
#define F71805F_SYSCTL_IN5 1005
|
||||
#define F71805F_SYSCTL_IN6 1006
|
||||
#define F71805F_SYSCTL_IN7 1007
|
||||
#define F71805F_SYSCTL_IN8 1008
|
||||
#define F71805F_SYSCTL_FAN1 1101
|
||||
#define F71805F_SYSCTL_FAN2 1102
|
||||
#define F71805F_SYSCTL_FAN3 1103
|
||||
#define F71805F_SYSCTL_TEMP1 1201
|
||||
#define F71805F_SYSCTL_TEMP2 1202
|
||||
#define F71805F_SYSCTL_TEMP3 1203
|
||||
#define F71805F_SYSCTL_SENSOR1 1211
|
||||
#define F71805F_SYSCTL_SENSOR2 1212
|
||||
#define F71805F_SYSCTL_SENSOR3 1213
|
||||
#define F71805F_SYSCTL_ALARMS_IN 1090
|
||||
#define F71805F_SYSCTL_ALARMS_FAN 1190
|
||||
#define F71805F_SYSCTL_ALARMS_TEMP 1290
|
||||
/* -- SENSORS SYSCTL END -- */
|
||||
|
||||
static void f71805f_in(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
int nr = ctl_name - F71805F_SYSCTL_IN0;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 3;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
f71805f_update_client(client);
|
||||
results[0] = in_from_reg(data->in_low[nr]);
|
||||
results[1] = in_from_reg(data->in_high[nr]);
|
||||
results[2] = in_from_reg(data->in[nr]);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag < 1)
|
||||
return;
|
||||
|
||||
down(&data->update_lock);
|
||||
data->in_low[nr] = in_to_reg(results[0]);
|
||||
f71805f_write8(client, F71805F_REG_IN_LOW(nr),
|
||||
data->in_low[nr]);
|
||||
|
||||
if (*nrels_mag >= 2) {
|
||||
data->in_high[nr] = in_to_reg(results[1]);
|
||||
f71805f_write8(client, F71805F_REG_IN_HIGH(nr),
|
||||
data->in_high[nr]);
|
||||
}
|
||||
up(&data->update_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void f71805f_in0(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 3;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
f71805f_update_client(client);
|
||||
results[0] = in0_from_reg(data->in_low[0]);
|
||||
results[1] = in0_from_reg(data->in_high[0]);
|
||||
results[2] = in0_from_reg(data->in[0]);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag < 1)
|
||||
return;
|
||||
|
||||
down(&data->update_lock);
|
||||
data->in_low[0] = in0_to_reg(results[0]);
|
||||
f71805f_write8(client, F71805F_REG_IN_LOW(0),
|
||||
data->in_low[0]);
|
||||
|
||||
if (*nrels_mag >= 2) {
|
||||
data->in_high[0] = in0_to_reg(results[1]);
|
||||
f71805f_write8(client, F71805F_REG_IN_HIGH(0),
|
||||
data->in_high[0]);
|
||||
}
|
||||
up(&data->update_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void f71805f_fan(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
int nr = ctl_name - F71805F_SYSCTL_FAN1;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
f71805f_update_client(client);
|
||||
results[0] = fan_from_reg(data->fan_low[nr]);
|
||||
results[1] = fan_from_reg(data->fan[nr]);
|
||||
*nrels_mag = 2;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag < 1)
|
||||
return;
|
||||
|
||||
down(&data->update_lock);
|
||||
data->fan_low[nr] = fan_to_reg(results[0]);
|
||||
f71805f_write16(client, F71805F_REG_FAN_LOW(nr),
|
||||
data->fan_low[nr]);
|
||||
up(&data->update_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void f71805f_temp(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
int nr = ctl_name - F71805F_SYSCTL_TEMP1;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
f71805f_update_client(client);
|
||||
results[0] = data->temp_high[nr];
|
||||
results[1] = data->temp_hyst[nr];
|
||||
results[2] = data->temp[nr];
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag < 1)
|
||||
return;
|
||||
|
||||
down(&data->update_lock);
|
||||
data->temp_high[nr] = temp_to_reg(results[0]);
|
||||
f71805f_write8(client, F71805F_REG_TEMP_HIGH(nr),
|
||||
data->temp_high[nr]);
|
||||
|
||||
if (*nrels_mag >= 2) {
|
||||
data->temp_hyst[nr] = temp_to_reg(results[1]);
|
||||
f71805f_write8(client, F71805F_REG_TEMP_HYST(nr),
|
||||
data->temp_hyst[nr]);
|
||||
}
|
||||
up(&data->update_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void f71805f_sensor(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
int nr = ctl_name - F71805F_SYSCTL_SENSOR1;
|
||||
|
||||
f71805f_update_client(client);
|
||||
results[0] = (data->temp_mode & (1 << nr)) ? 3 : 4;
|
||||
*nrels_mag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void f71805f_alarms_in(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
f71805f_update_client(client);
|
||||
results[0] = data->alarms[0]
|
||||
| ((data->alarms[1] & 0x01) << 8);
|
||||
*nrels_mag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void f71805f_alarms_fan(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
f71805f_update_client(client);
|
||||
results[0] = data->alarms[2] & 0x07;
|
||||
*nrels_mag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void f71805f_alarms_temp(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct f71805f_data *data = client->data;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
f71805f_update_client(client);
|
||||
results[0] = (data->alarms[1] >> 3) & 0x07;
|
||||
*nrels_mag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static ctl_table f71805f_dir_table_template[] = {
|
||||
{ F71805F_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_in0 },
|
||||
{ F71805F_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_in },
|
||||
{ F71805F_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_in },
|
||||
{ F71805F_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_in },
|
||||
{ F71805F_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_in },
|
||||
{ F71805F_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_in },
|
||||
{ F71805F_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_in },
|
||||
{ F71805F_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_in },
|
||||
{ F71805F_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_in },
|
||||
{ F71805F_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_fan },
|
||||
{ F71805F_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_fan },
|
||||
{ F71805F_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_fan },
|
||||
{ F71805F_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_temp },
|
||||
{ F71805F_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_temp },
|
||||
{ F71805F_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_temp },
|
||||
{ F71805F_SYSCTL_SENSOR1, "sensor1", NULL, 0, 0444, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_sensor },
|
||||
{ F71805F_SYSCTL_SENSOR2, "sensor2", NULL, 0, 0444, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_sensor },
|
||||
{ F71805F_SYSCTL_SENSOR3, "sensor3", NULL, 0, 0444, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_sensor },
|
||||
{ F71805F_SYSCTL_ALARMS_IN, "alarms_in", NULL, 0, 0444, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_alarms_in },
|
||||
{ F71805F_SYSCTL_ALARMS_FAN, "alarms_fan", NULL, 0, 0444, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_alarms_fan },
|
||||
{ F71805F_SYSCTL_ALARMS_TEMP, "alarms_temp", NULL, 0, 0444, NULL,
|
||||
&i2c_proc_real, &i2c_sysctl_real, NULL, &f71805f_alarms_temp },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static struct i2c_driver f71805f_driver = {
|
||||
.name = "F71805F sensor driver",
|
||||
.flags = I2C_DF_NOTIFY,
|
||||
.attach_adapter = f71805f_attach_adapter,
|
||||
.detach_client = f71805f_detach_client,
|
||||
};
|
||||
|
||||
static int __init f71805f_find(int sioaddr, unsigned int *address)
|
||||
{
|
||||
int err = -ENODEV;
|
||||
u16 devid;
|
||||
|
||||
REG = sioaddr;
|
||||
VAL = sioaddr + 1;
|
||||
superio_enter();
|
||||
|
||||
devid = superio_inw(SIO_REG_DEVID);
|
||||
if (devid != SIO_F71805F_ID)
|
||||
goto exit;
|
||||
|
||||
superio_select(F71805F_LD_HWM);
|
||||
if (!(superio_inb(SIO_REG_ENABLE) & 0x01)) {
|
||||
printk(KERN_WARNING "%s: Device not activated, skipping\n",
|
||||
DRVNAME);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
*address = superio_inw(SIO_REG_ADDR);
|
||||
if (*address == 0) {
|
||||
printk(KERN_WARNING "%s: Base address not set, skipping\n",
|
||||
DRVNAME);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
printk(KERN_INFO "%s: Found F71805F chip at %#x, revision %u\n",
|
||||
DRVNAME, *address, superio_inb(SIO_REG_DEVREV));
|
||||
|
||||
exit:
|
||||
superio_exit();
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __init f71805f_init(void)
|
||||
{
|
||||
printk("%s: Driver version %s (%s)\n", DRVNAME, LM_VERSION, LM_DATE);
|
||||
|
||||
if (f71805f_find(0x2e, &normal_isa[0])
|
||||
&& f71805f_find(0x4e, &normal_isa[0]))
|
||||
return -ENODEV;
|
||||
|
||||
return i2c_add_driver(&f71805f_driver);
|
||||
}
|
||||
|
||||
static void __exit f71805f_exit(void)
|
||||
{
|
||||
i2c_del_driver(&f71805f_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("F71805F hardware monitoring driver");
|
||||
|
||||
module_init(f71805f_init);
|
||||
module_exit(f71805f_exit);
|
133
lib/chips.c
133
lib/chips.c
@@ -5418,6 +5418,138 @@ static sensors_chip_feature smsc47b397_features[] =
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static sensors_chip_feature f71805f_features[] =
|
||||
{
|
||||
/* 9 voltage inputs */
|
||||
{ SENSORS_F71805F_IN(0), "in0", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_IN0, VALUE(3), 3 },
|
||||
{ SENSORS_F71805F_IN(1), "in1", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_IN1, VALUE(3), 3 },
|
||||
{ SENSORS_F71805F_IN(2), "in2", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_IN2, VALUE(3), 3 },
|
||||
{ SENSORS_F71805F_IN(3), "in3", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_IN3, VALUE(3), 3 },
|
||||
{ SENSORS_F71805F_IN(4), "in4", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_IN4, VALUE(3), 3 },
|
||||
{ SENSORS_F71805F_IN(5), "in5", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_IN5, VALUE(3), 3 },
|
||||
{ SENSORS_F71805F_IN(6), "in6", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_IN6, VALUE(3), 3 },
|
||||
{ SENSORS_F71805F_IN(7), "in7", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_IN7, VALUE(3), 3 },
|
||||
{ SENSORS_F71805F_IN(8), "in8", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_IN8, VALUE(3), 3 },
|
||||
{ SENSORS_F71805F_IN_MIN(0), "in0_min",
|
||||
SENSORS_F71805F_IN(0), SENSORS_F71805F_IN(0), RW,
|
||||
F71805F_SYSCTL_IN0, VALUE(1), 3 },
|
||||
{ SENSORS_F71805F_IN_MIN(1), "in1_min",
|
||||
SENSORS_F71805F_IN(1), SENSORS_F71805F_IN(1), RW,
|
||||
F71805F_SYSCTL_IN1, VALUE(1), 3 },
|
||||
{ SENSORS_F71805F_IN_MIN(2), "in2_min",
|
||||
SENSORS_F71805F_IN(2), SENSORS_F71805F_IN(2), RW,
|
||||
F71805F_SYSCTL_IN2, VALUE(1), 3 },
|
||||
{ SENSORS_F71805F_IN_MIN(3), "in3_min",
|
||||
SENSORS_F71805F_IN(3), SENSORS_F71805F_IN(3), RW,
|
||||
F71805F_SYSCTL_IN3, VALUE(1), 3 },
|
||||
{ SENSORS_F71805F_IN_MIN(4), "in4_min",
|
||||
SENSORS_F71805F_IN(4), SENSORS_F71805F_IN(4), RW,
|
||||
F71805F_SYSCTL_IN4, VALUE(1), 3 },
|
||||
{ SENSORS_F71805F_IN_MIN(5), "in5_min",
|
||||
SENSORS_F71805F_IN(5), SENSORS_F71805F_IN(5), RW,
|
||||
F71805F_SYSCTL_IN5, VALUE(1), 3 },
|
||||
{ SENSORS_F71805F_IN_MIN(6), "in6_min",
|
||||
SENSORS_F71805F_IN(6), SENSORS_F71805F_IN(6), RW,
|
||||
F71805F_SYSCTL_IN6, VALUE(1), 3 },
|
||||
{ SENSORS_F71805F_IN_MIN(7), "in7_min",
|
||||
SENSORS_F71805F_IN(7), SENSORS_F71805F_IN(7), RW,
|
||||
F71805F_SYSCTL_IN7, VALUE(1), 3 },
|
||||
{ SENSORS_F71805F_IN_MIN(8), "in8_min",
|
||||
SENSORS_F71805F_IN(8), SENSORS_F71805F_IN(8), RW,
|
||||
F71805F_SYSCTL_IN8, VALUE(1), 3 },
|
||||
{ SENSORS_F71805F_IN_MAX(0), "in0_max",
|
||||
SENSORS_F71805F_IN(0), SENSORS_F71805F_IN(0), RW,
|
||||
F71805F_SYSCTL_IN0, VALUE(2), 3 },
|
||||
{ SENSORS_F71805F_IN_MAX(1), "in1_max",
|
||||
SENSORS_F71805F_IN(1), SENSORS_F71805F_IN(1), RW,
|
||||
F71805F_SYSCTL_IN1, VALUE(2), 3 },
|
||||
{ SENSORS_F71805F_IN_MAX(2), "in2_max",
|
||||
SENSORS_F71805F_IN(2), SENSORS_F71805F_IN(2), RW,
|
||||
F71805F_SYSCTL_IN2, VALUE(2), 3 },
|
||||
{ SENSORS_F71805F_IN_MAX(3), "in3_max",
|
||||
SENSORS_F71805F_IN(3), SENSORS_F71805F_IN(3), RW,
|
||||
F71805F_SYSCTL_IN3, VALUE(2), 3 },
|
||||
{ SENSORS_F71805F_IN_MAX(4), "in4_max",
|
||||
SENSORS_F71805F_IN(4), SENSORS_F71805F_IN(4), RW,
|
||||
F71805F_SYSCTL_IN4, VALUE(2), 3 },
|
||||
{ SENSORS_F71805F_IN_MAX(5), "in5_max",
|
||||
SENSORS_F71805F_IN(5), SENSORS_F71805F_IN(5), RW,
|
||||
F71805F_SYSCTL_IN5, VALUE(2), 3 },
|
||||
{ SENSORS_F71805F_IN_MAX(6), "in6_max",
|
||||
SENSORS_F71805F_IN(6), SENSORS_F71805F_IN(6), RW,
|
||||
F71805F_SYSCTL_IN6, VALUE(2), 3 },
|
||||
{ SENSORS_F71805F_IN_MAX(7), "in7_max",
|
||||
SENSORS_F71805F_IN(7), SENSORS_F71805F_IN(7), RW,
|
||||
F71805F_SYSCTL_IN7, VALUE(2), 3 },
|
||||
{ SENSORS_F71805F_IN_MAX(8), "in8_max",
|
||||
SENSORS_F71805F_IN(8), SENSORS_F71805F_IN(8), RW,
|
||||
F71805F_SYSCTL_IN8, VALUE(2), 3 },
|
||||
/* 3 fan tachometers */
|
||||
{ SENSORS_F71805F_FAN(1), "fan1", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_FAN1, VALUE(2), 0 },
|
||||
{ SENSORS_F71805F_FAN(2), "fan2", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_FAN2, VALUE(2), 0 },
|
||||
{ SENSORS_F71805F_FAN(3), "fan3", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_FAN3, VALUE(2), 0 },
|
||||
{ SENSORS_F71805F_FAN_MIN(1), "fan1_min",
|
||||
SENSORS_F71805F_FAN(1), SENSORS_F71805F_FAN(1), RW,
|
||||
F71805F_SYSCTL_FAN1, VALUE(1), 0 },
|
||||
{ SENSORS_F71805F_FAN_MIN(2), "fan2_min",
|
||||
SENSORS_F71805F_FAN(2), SENSORS_F71805F_FAN(2), RW,
|
||||
F71805F_SYSCTL_FAN2, VALUE(1), 0 },
|
||||
{ SENSORS_F71805F_FAN_MIN(3), "fan3_min",
|
||||
SENSORS_F71805F_FAN(3), SENSORS_F71805F_FAN(3), RW,
|
||||
F71805F_SYSCTL_FAN3, VALUE(1), 0 },
|
||||
/* 3 temperature inputs */
|
||||
{ SENSORS_F71805F_TEMP(1), "temp1", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_TEMP1, VALUE(3), 0 },
|
||||
{ SENSORS_F71805F_TEMP(2), "temp2", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_TEMP2, VALUE(3), 0 },
|
||||
{ SENSORS_F71805F_TEMP(3), "temp3", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_TEMP3, VALUE(3), 0 },
|
||||
{ SENSORS_F71805F_TEMP_MAX(1), "temp1_max",
|
||||
SENSORS_F71805F_TEMP(1), SENSORS_F71805F_TEMP(1), RW,
|
||||
F71805F_SYSCTL_TEMP1, VALUE(1), 0 },
|
||||
{ SENSORS_F71805F_TEMP_MAX(2), "temp2_max",
|
||||
SENSORS_F71805F_TEMP(2), SENSORS_F71805F_TEMP(2), RW,
|
||||
F71805F_SYSCTL_TEMP2, VALUE(1), 0 },
|
||||
{ SENSORS_F71805F_TEMP_MAX(3), "temp3_max",
|
||||
SENSORS_F71805F_TEMP(3), SENSORS_F71805F_TEMP(3), RW,
|
||||
F71805F_SYSCTL_TEMP3, VALUE(1), 0 },
|
||||
{ SENSORS_F71805F_TEMP_HYST(1), "temp1_hyst",
|
||||
SENSORS_F71805F_TEMP(1), SENSORS_F71805F_TEMP(1), RW,
|
||||
F71805F_SYSCTL_TEMP1, VALUE(2), 0 },
|
||||
{ SENSORS_F71805F_TEMP_HYST(2), "temp2_hyst",
|
||||
SENSORS_F71805F_TEMP(2), SENSORS_F71805F_TEMP(2), RW,
|
||||
F71805F_SYSCTL_TEMP2, VALUE(2), 0 },
|
||||
{ SENSORS_F71805F_TEMP_HYST(3), "temp3_hyst",
|
||||
SENSORS_F71805F_TEMP(3), SENSORS_F71805F_TEMP(3), RW,
|
||||
F71805F_SYSCTL_TEMP3, VALUE(2), 0 },
|
||||
{ SENSORS_F71805F_TEMP_TYPE(1), "sensor1", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_SENSOR1, VALUE(1), 0 },
|
||||
{ SENSORS_F71805F_TEMP_TYPE(2), "sensor2", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_SENSOR2, VALUE(1), 0 },
|
||||
{ SENSORS_F71805F_TEMP_TYPE(3), "sensor3", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_SENSOR3, VALUE(1), 0 },
|
||||
/* 3 alarm bitvectors */
|
||||
{ SENSORS_F71805F_ALARMS_IN, "alarms_in", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_ALARMS_IN, VALUE(1), 0 },
|
||||
{ SENSORS_F71805F_ALARMS_FAN, "alarms_fan", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_ALARMS_FAN, VALUE(1), 0 },
|
||||
{ SENSORS_F71805F_ALARMS_TEMP, "alarms_temp", NOMAP, NOMAP, R,
|
||||
F71805F_SYSCTL_ALARMS_TEMP, VALUE(1), 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
sensors_chip_features sensors_chip_features_list[] =
|
||||
{
|
||||
{ SENSORS_LM78_PREFIX, lm78_features },
|
||||
@@ -5516,5 +5648,6 @@ sensors_chip_features sensors_chip_features_list[] =
|
||||
{ SENSORS_ADM1031_PREFIX, adm1031_features },
|
||||
{ SENSORS_LM93_PREFIX, lm93_features },
|
||||
{ SENSORS_SMSC47B397_PREFIX, smsc47b397_features },
|
||||
{ SENSORS_F71805F_PREFIX, f71805f_features },
|
||||
{ 0 }
|
||||
};
|
||||
|
20
lib/chips.h
20
lib/chips.h
@@ -2090,4 +2090,24 @@
|
||||
#define SENSORS_SMSC47B397_FAN3 0x13 /* R */
|
||||
#define SENSORS_SMSC47B397_FAN4 0x14 /* R */
|
||||
|
||||
/* Fintek F71805F chip */
|
||||
#define SENSORS_F71805F_PREFIX "f71805f"
|
||||
|
||||
/* in n from 0 to 8 */
|
||||
#define SENSORS_F71805F_IN(n) (1 + (n))
|
||||
#define SENSORS_F71805F_IN_MIN(n) (16 + (n))
|
||||
#define SENSORS_F71805F_IN_MAX(n) (31 + (n))
|
||||
/* fan n from 1 to 3 */
|
||||
#define SENSORS_F71805F_FAN(n) (50 + (n))
|
||||
#define SENSORS_F71805F_FAN_MIN(n) (60 + (n))
|
||||
/* temp n from 1 to 3 */
|
||||
#define SENSORS_F71805F_TEMP(n) (80 + (n))
|
||||
#define SENSORS_F71805F_TEMP_MAX(n) (90 + (n))
|
||||
#define SENSORS_F71805F_TEMP_HYST(n) (100 + (n))
|
||||
#define SENSORS_F71805F_TEMP_TYPE(n) (110 + (n))
|
||||
/* alarms */
|
||||
#define SENSORS_F71805F_ALARMS_IN 200
|
||||
#define SENSORS_F71805F_ALARMS_FAN 201
|
||||
#define SENSORS_F71805F_ALARMS_TEMP 202
|
||||
|
||||
#endif /* def LIB_SENSORS_CHIPS_H */
|
||||
|
@@ -20,6 +20,7 @@ if [ "$CONFIG_I2C_PROC" = "m" -o "$CONFIG_I2C_PROC" = "y" ] ; then
|
||||
dep_tristate ' Analog Devices ADM9240 and compatibles' CONFIG_SENSORS_ADM9240 $CONFIG_I2C $CONFIG_I2C_PROC
|
||||
dep_tristate ' Asus ASB100' CONFIG_SENSORS_ASB100 $CONFIG_I2C $CONFIG_I2C_PROC
|
||||
dep_tristate ' Dallas DS1621 and DS1625' CONFIG_SENSORS_DS1621 $CONFIG_I2C $CONFIG_I2C_PROC
|
||||
dep_tristate ' Fintek F71805F' CONFIG_SENSORS_F71805F $CONFIG_I2C $CONFIG_I2C_PROC
|
||||
dep_tristate ' Fujitsu-Siemens Hermes' CONFIG_SENSORS_FSCHER $CONFIG_I2C $CONFIG_I2C_PROC
|
||||
dep_tristate ' Fujitsu-Siemens Poseidon' CONFIG_SENSORS_FSCPOS $CONFIG_I2C $CONFIG_I2C_PROC
|
||||
dep_tristate ' Fujitsu-Siemens Scylla' CONFIG_SENSORS_FSCSCY $CONFIG_I2C $CONFIG_I2C_PROC
|
||||
|
@@ -29,6 +29,7 @@ kernel/chips/bt869.c drivers/sensors/bt869.c
|
||||
kernel/chips/ddcmon.c drivers/sensors/ddcmon.c
|
||||
kernel/chips/ds1621.c drivers/sensors/ds1621.c
|
||||
kernel/chips/eeprom.c drivers/sensors/eeprom.c
|
||||
kernel/chips/f71805f.c drivers/sensors/f71805f.c
|
||||
kernel/chips/fscher.c drivers/sensors/fscher.c
|
||||
kernel/chips/fscpos.c drivers/sensors/fscpos.c
|
||||
kernel/chips/fscscy.c drivers/sensors/fscscy.c
|
||||
|
@@ -106,6 +106,7 @@ sub gen_Documentation_Configure_help
|
||||
m@Analog Devices ADM9240 and compatibles@ or
|
||||
m@Asus ASB100@ or
|
||||
m@Dallas DS1621 and DS1625@ or
|
||||
m@Fintek F71805F@ or
|
||||
m@Fujitsu-Siemens Hermes@ or
|
||||
m@Fujitsu-Siemens Poseidon@ or
|
||||
m@Fujitsu-Siemens Scylla@ or
|
||||
@@ -378,6 +379,16 @@ CONFIG_SENSORS_DS1621
|
||||
in the lm_sensors package, which you can download at
|
||||
http://www.lm-sensors.nu/
|
||||
|
||||
Fintek F71805F
|
||||
CONFIG_SENSORS_F71805F
|
||||
If you say yes here you get support for the hardware monitoring
|
||||
features of the Fintek F71805F/FG Super-I/O chip. This can also be
|
||||
built as a module.
|
||||
|
||||
You will also need the latest user-space utilities: you can find them
|
||||
in the lm_sensors package, which you can download at
|
||||
http://www.lm-sensors.nu/
|
||||
|
||||
Fujitsu-Siemens Hermes
|
||||
CONFIG_SENSORS_FSCHER
|
||||
If you say yes here you get support for the Fujitsu-Siemens Hermes
|
||||
@@ -1016,6 +1027,7 @@ obj-$(CONFIG_SENSORS_BT869) += bt869.o
|
||||
obj-$(CONFIG_SENSORS_DDCMON) += ddcmon.o
|
||||
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
|
||||
obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
|
||||
obj-$(CONFIG_SENSORS_FSCHER) += f71085f.o
|
||||
obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
|
||||
obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
|
||||
obj-$(CONFIG_SENSORS_FSCSCY) += fscscy.o
|
||||
|
@@ -5768,6 +5768,86 @@ void print_smsc47b397(const sensors_chip_name *name)
|
||||
PRINT_SMSC47B397_FAN(ii, name);
|
||||
}
|
||||
|
||||
void print_f71805f(const sensors_chip_name *name)
|
||||
{
|
||||
char *label;
|
||||
double cur, min, max;
|
||||
int alarms, valid, i;
|
||||
|
||||
if (!sensors_get_feature(*name, SENSORS_F71805F_ALARMS_IN, &cur))
|
||||
alarms = cur + 0.5;
|
||||
else {
|
||||
printf("ERROR: Can't get alarms_in data!\n");
|
||||
alarms = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
if (!sensors_get_label_and_valid(*name, SENSORS_F71805F_IN(i),
|
||||
&label, &valid)
|
||||
&& !sensors_get_feature(*name, SENSORS_F71805F_IN(i), &cur)
|
||||
&& !sensors_get_feature(*name, SENSORS_F71805F_IN_MIN(i), &min)
|
||||
&& !sensors_get_feature(*name, SENSORS_F71805F_IN_MAX(i), &max)) {
|
||||
if (valid) {
|
||||
print_label(label, 10);
|
||||
printf("%+6.2f V (min = %+6.2f V, max = %+6.2f V) %s\n",
|
||||
cur, min, max, (alarms & (1 << i)) ? "ALARM" : "");
|
||||
}
|
||||
} else
|
||||
printf("ERROR: Can't get in%d data!\n", i);
|
||||
free(label);
|
||||
}
|
||||
|
||||
if (!sensors_get_feature(*name, SENSORS_F71805F_ALARMS_FAN, &cur))
|
||||
alarms = cur + 0.5;
|
||||
else {
|
||||
printf("ERROR: Can't get alarms_fan data!\n");
|
||||
alarms = 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= 3; i++) {
|
||||
if (!sensors_get_label_and_valid(*name, SENSORS_F71805F_FAN(i),
|
||||
&label, &valid)
|
||||
&& !sensors_get_feature(*name, SENSORS_F71805F_FAN(i), &cur)
|
||||
&& !sensors_get_feature(*name, SENSORS_F71805F_FAN_MIN(i), &min)) {
|
||||
if (valid) {
|
||||
print_label(label, 10);
|
||||
printf("%4.0f RPM (min = %4.0f RPM) %s\n",
|
||||
cur, min, (alarms & (1 << (i - 1))) ? "ALARM" : "");
|
||||
}
|
||||
} else
|
||||
printf("ERROR: Can't get fan%d data!\n", i);
|
||||
free(label);
|
||||
}
|
||||
|
||||
if (!sensors_get_feature(*name, SENSORS_F71805F_ALARMS_TEMP, &cur))
|
||||
alarms = cur + 0.5;
|
||||
else {
|
||||
printf("ERROR: Can't get alarms_temp data!\n");
|
||||
alarms = 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= 3; i++) {
|
||||
if (!sensors_get_label_and_valid(*name, SENSORS_F71805F_TEMP(i),
|
||||
&label, &valid)
|
||||
&& !sensors_get_feature(*name, SENSORS_F71805F_TEMP(i), &cur)
|
||||
&& !sensors_get_feature(*name, SENSORS_F71805F_TEMP_MAX(i), &max)
|
||||
&& !sensors_get_feature(*name, SENSORS_F71805F_TEMP_HYST(i), &min)) {
|
||||
if (valid) {
|
||||
print_label(label, 10);
|
||||
print_temp_info(cur, max, min, HYST, 0, 0);
|
||||
printf("%5s", (alarms & (1 << (i - 1))) ? "ALARM" : "");
|
||||
if (!sensors_get_feature(*name, SENSORS_F71805F_TEMP_TYPE(i), &cur)) {
|
||||
int sensor = cur + 0.5;
|
||||
printf(" [%s]", sensor == 3 ? "diode" : "thermistor");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
} else
|
||||
printf("ERROR: Can't get temp%d data!\n", i);
|
||||
free(label);
|
||||
}
|
||||
}
|
||||
|
||||
void print_unknown_chip(const sensors_chip_name *name)
|
||||
{
|
||||
int a,b,valid;
|
||||
|
@@ -70,5 +70,6 @@ extern void print_xeontemp(const sensors_chip_name *name);
|
||||
extern void print_max6650(const sensors_chip_name *name);
|
||||
extern void print_adm1031(const sensors_chip_name *name);
|
||||
extern void print_smsc47b397(const sensors_chip_name *name);
|
||||
extern void print_f71805f(const sensors_chip_name *name);
|
||||
|
||||
#endif /* def PROG_SENSORS_CHIPS_H */
|
||||
|
@@ -412,6 +412,7 @@ struct match matches[] = {
|
||||
{ "adm1031", print_adm1031 },
|
||||
{ "lm93", print_lm93 },
|
||||
{ "smsc47b397", print_smsc47b397 },
|
||||
{ "f71805f", print_f71805f },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user