linux/drivers/hwmon/via686a.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * via686a.c - Part of lm_sensors, Linux kernel modules
 *	       for hardware monitoring
 *
 * Copyright (c) 1998 - 2002  Frodo Looijaard <[email protected]>,
 *			      Kyösti Mälkki <[email protected]>,
 *			      Mark Studebaker <[email protected]>,
 *			      and Bob Dougherty <[email protected]>
 *
 * (Some conversion-factor data were contributed by Jonathan Teh Soon Yew
 * <[email protected]> and Alex van Kaam <[email protected]>.)
 */

/*
 * Supports the Via VT82C686A, VT82C686B south bridges.
 * Reports all as a 686A.
 * Warning - only supports a single device.
 */

#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/acpi.h>
#include <linux/io.h>

#define DRIVER_NAME

/*
 * If force_addr is set to anything different from 0, we forcibly enable
 * the device at the given address.
 */
static unsigned short force_addr;
module_param(force_addr, ushort, 0);
MODULE_PARM_DESC();

static struct platform_device *pdev;

/*
 * The Via 686a southbridge has a LM78-like chip integrated on the same IC.
 * This driver is a customized copy of lm78.c
 */

/* Many VIA686A constants specified below */

/* Length of ISA address segment */
#define VIA686A_EXTENT
#define VIA686A_BASE_REG
#define VIA686A_ENABLE_REG

/* The VIA686A registers */
/* ins numbered 0-4 */
#define VIA686A_REG_IN_MAX(nr)
#define VIA686A_REG_IN_MIN(nr)
#define VIA686A_REG_IN(nr)

/* fans numbered 1-2 */
#define VIA686A_REG_FAN_MIN(nr)
#define VIA686A_REG_FAN(nr)

/* temps numbered 1-3 */
static const u8 VIA686A_REG_TEMP[]	=;
static const u8 VIA686A_REG_TEMP_OVER[]	=;
static const u8 VIA686A_REG_TEMP_HYST[]	=;
/* bits 7-6 */
#define VIA686A_REG_TEMP_LOW1
/* 2 = bits 5-4, 3 = bits 7-6 */
#define VIA686A_REG_TEMP_LOW23

#define VIA686A_REG_ALARM1
#define VIA686A_REG_ALARM2
#define VIA686A_REG_FANDIV
#define VIA686A_REG_CONFIG
/*
 * The following register sets temp interrupt mode (bits 1-0 for temp1,
 * 3-2 for temp2, 5-4 for temp3).  Modes are:
 * 00 interrupt stays as long as value is out-of-range
 * 01 interrupt is cleared once register is read (default)
 * 10 comparator mode- like 00, but ignores hysteresis
 * 11 same as 00
 */
#define VIA686A_REG_TEMP_MODE
/* We'll just assume that you want to set all 3 simultaneously: */
#define VIA686A_TEMP_MODE_MASK
#define VIA686A_TEMP_MODE_CONTINUOUS

/*
 * Conversions. Limit checking is only done on the TO_REG
 * variants.
 *
 ******** VOLTAGE CONVERSIONS (Bob Dougherty) ********
 * From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
 * voltagefactor[0]=1.25/2628; (2628/1.25=2102.4)   // Vccp
 * voltagefactor[1]=1.25/2628; (2628/1.25=2102.4)   // +2.5V
 * voltagefactor[2]=1.67/2628; (2628/1.67=1573.7)   // +3.3V
 * voltagefactor[3]=2.6/2628;  (2628/2.60=1010.8)   // +5V
 * voltagefactor[4]=6.3/2628;  (2628/6.30=417.14)   // +12V
 * in[i]=(data[i+2]*25.0+133)*voltagefactor[i];
 * That is:
 * volts = (25*regVal+133)*factor
 * regVal = (volts/factor-133)/25
 * (These conversions were contributed by Jonathan Teh Soon Yew
 * <[email protected]>)
 */
static inline u8 IN_TO_REG(long val, int in_num)
{}

static inline long IN_FROM_REG(u8 val, int in_num)
{}

/********* FAN RPM CONVERSIONS ********/
/*
 * Higher register values = slower fans (the fan's strobe gates a counter).
 * But this chip saturates back at 0, not at 255 like all the other chips.
 * So, 0 means 0 RPM
 */
static inline u8 FAN_TO_REG(long rpm, int div)
{}

#define FAN_FROM_REG(val, div)

/******** TEMP CONVERSIONS (Bob Dougherty) *********/
/*
 * linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
 *	if(temp<169)
 *		return double(temp)*0.427-32.08;
 *	else if(temp>=169 && temp<=202)
 *		return double(temp)*0.582-58.16;
 *	else
 *		return double(temp)*0.924-127.33;
 *
 * A fifth-order polynomial fits the unofficial data (provided by Alex van
 * Kaam <[email protected]>) a bit better.  It also give more reasonable
 * numbers on my machine (ie. they agree with what my BIOS tells me).
 * Here's the fifth-order fit to the 8-bit data:
 * temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
 *	2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
 *
 * (2000-10-25- RFD: thanks to Uwe Andersen <[email protected]> for
 * finding my typos in this formula!)
 *
 * Alas, none of the elegant function-fit solutions will work because we
 * aren't allowed to use floating point in the kernel and doing it with
 * integers doesn't provide enough precision.  So we'll do boring old
 * look-up table stuff.  The unofficial data (see below) have effectively
 * 7-bit resolution (they are rounded to the nearest degree).  I'm assuming
 * that the transfer function of the device is monotonic and smooth, so a
 * smooth function fit to the data will allow us to get better precision.
 * I used the 5th-order poly fit described above and solved for
 * VIA register values 0-255.  I *10 before rounding, so we get tenth-degree
 * precision.  (I could have done all 1024 values for our 10-bit readings,
 * but the function is very linear in the useful range (0-80 deg C), so
 * we'll just use linear interpolation for 10-bit readings.)  So, temp_lut
 * is the temp at via register values 0-255:
 */
static const s16 temp_lut[] =;

/*
 * the original LUT values from Alex van Kaam <[email protected]>
 * (for via register values 12-240):
 * {-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
 * -30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
 * -15,-14,-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,
 * -3,-2,-2,-1,-1,0,0,1,1,1,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,9,10,10,11,11,12,
 * 12,12,13,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,21,21,21,22,22,
 * 22,23,23,24,24,25,25,26,26,26,27,27,27,28,28,29,29,30,30,30,31,31,32,32,33,
 * 33,34,34,35,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,
 * 45,46,46,47,48,48,49,49,50,51,51,52,52,53,53,54,55,55,56,57,57,58,59,59,60,
 * 61,62,62,63,64,65,66,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,83,84,
 * 85,86,88,89,91,92,94,96,97,99,101,103,105,107,109,110};
 *
 *
 * Here's the reverse LUT.  I got it by doing a 6-th order poly fit (needed
 * an extra term for a good fit to these inverse data!) and then
 * solving for each temp value from -50 to 110 (the useable range for
 * this chip).  Here's the fit:
 * viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
 * - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
 * Note that n=161:
 */
static const u8 via_lut[] =;

/*
 * Converting temps to (8-bit) hyst and over registers
 * No interpolation here.
 * The +50 is because the temps start at -50
 */
static inline u8 TEMP_TO_REG(long val)
{}

/* for 8-bit temperature hyst and over registers */
#define TEMP_FROM_REG(val)

/* for 10-bit temperature readings */
static inline long TEMP_FROM_REG10(u16 val)
{}

#define DIV_FROM_REG(val)
#define DIV_TO_REG(val)

/*
 * For each registered chip, we need to keep some data in memory.
 * The structure is dynamically allocated.
 */
struct via686a_data {};

static struct pci_dev *s_bridge;	/* pointer to the (only) via686a */

static inline int via686a_read_value(struct via686a_data *data, u8 reg)
{}

static inline void via686a_write_value(struct via686a_data *data, u8 reg,
				       u8 value)
{}

static void via686a_update_fan_div(struct via686a_data *data)
{}

static struct via686a_data *via686a_update_device(struct device *dev)
{}

/* following are the sysfs callback functions */

/* 7 voltage sensors */
static ssize_t in_show(struct device *dev, struct device_attribute *da,
		       char *buf) {}

static ssize_t in_min_show(struct device *dev, struct device_attribute *da,
			   char *buf) {}

static ssize_t in_max_show(struct device *dev, struct device_attribute *da,
			   char *buf) {}

static ssize_t in_min_store(struct device *dev, struct device_attribute *da,
			    const char *buf, size_t count) {}
static ssize_t in_max_store(struct device *dev, struct device_attribute *da,
			    const char *buf, size_t count) {}

static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0);
static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0);
static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0);
static SENSOR_DEVICE_ATTR_RO(in1_input, in, 1);
static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1);
static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1);
static SENSOR_DEVICE_ATTR_RO(in2_input, in, 2);
static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2);
static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2);
static SENSOR_DEVICE_ATTR_RO(in3_input, in, 3);
static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3);
static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3);
static SENSOR_DEVICE_ATTR_RO(in4_input, in, 4);
static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4);
static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4);

/* 3 temperatures */
static ssize_t temp_show(struct device *dev, struct device_attribute *da,
			 char *buf) {}
static ssize_t temp_over_show(struct device *dev, struct device_attribute *da,
			      char *buf) {}
static ssize_t temp_hyst_show(struct device *dev, struct device_attribute *da,
			      char *buf) {}
static ssize_t temp_over_store(struct device *dev,
			       struct device_attribute *da, const char *buf,
			       size_t count) {}
static ssize_t temp_hyst_store(struct device *dev,
			       struct device_attribute *da, const char *buf,
			       size_t count) {}

static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_over, 0);
static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp_hyst, 0);
static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_over, 1);
static SENSOR_DEVICE_ATTR_RW(temp2_max_hyst, temp_hyst, 1);
static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_over, 2);
static SENSOR_DEVICE_ATTR_RW(temp3_max_hyst, temp_hyst, 2);

/* 2 Fans */
static ssize_t fan_show(struct device *dev, struct device_attribute *da,
			char *buf) {}
static ssize_t fan_min_show(struct device *dev, struct device_attribute *da,
			    char *buf) {}
static ssize_t fan_div_show(struct device *dev, struct device_attribute *da,
			    char *buf) {}
static ssize_t fan_min_store(struct device *dev, struct device_attribute *da,
			     const char *buf, size_t count) {}
static ssize_t fan_div_store(struct device *dev, struct device_attribute *da,
			     const char *buf, size_t count) {}

static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);

/* Alarms */
static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
			   char *buf)
{}

static DEVICE_ATTR_RO(alarms);

static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
			  char *buf)
{}
static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0);
static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1);
static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2);
static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3);
static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 8);
static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4);
static SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, 11);
static SENSOR_DEVICE_ATTR_RO(temp3_alarm, alarm, 15);
static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 6);
static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 7);

static ssize_t name_show(struct device *dev, struct device_attribute
			 *devattr, char *buf)
{}
static DEVICE_ATTR_RO(name);

static struct attribute *via686a_attributes[] =;

static const struct attribute_group via686a_group =;

static void via686a_init_device(struct via686a_data *data)
{}

/* This is called when the module is loaded */
static int via686a_probe(struct platform_device *pdev)
{}

static void via686a_remove(struct platform_device *pdev)
{}

static struct platform_driver via686a_driver =;

static const struct pci_device_id via686a_pci_ids[] =;
MODULE_DEVICE_TABLE(pci, via686a_pci_ids);

static int via686a_device_add(unsigned short address)
{}

static int via686a_pci_probe(struct pci_dev *dev,
				       const struct pci_device_id *id)
{}

static struct pci_driver via686a_pci_driver =;

static int __init sm_via686a_init(void)
{}

static void __exit sm_via686a_exit(void)
{}

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

module_init();
module_exit(sm_via686a_exit);