linux/drivers/hwmon/w83793.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * w83793.c - Linux kernel driver for hardware monitoring
 * Copyright (C) 2006 Winbond Electronics Corp.
 *	      Yuan Mu
 *	      Rudolf Marek <[email protected]>
 * Copyright (C) 2009-2010 Sven Anders <[email protected]>, ANDURAS AG.
 *		Watchdog driver part
 *		(Based partially on fschmd driver,
 *		 Copyright 2007-2008 by Hans de Goede)
 */

/*
 * Supports following chips:
 *
 * Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
 * w83793	10	12	8	6	0x7b	0x5ca3	yes	no
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-vid.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/fs.h>
#include <linux/watchdog.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/kref.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/jiffies.h>

/* Default values */
#define WATCHDOG_TIMEOUT

/* Addresses to scan */
static const unsigned short normal_i2c[] =;

/* Insmod parameters */

static unsigned short force_subclients[4];
module_param_array();
MODULE_PARM_DESC();

static bool reset;
module_param(reset, bool, 0);
MODULE_PARM_DESC();

static int timeout =;	/* default timeout in minutes */
module_param(timeout, int, 0);
MODULE_PARM_DESC();

static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC();

/*
 * Address 0x00, 0x0d, 0x0e, 0x0f in all three banks are reserved
 * as ID, Bank Select registers
 */
#define W83793_REG_BANKSEL
#define W83793_REG_VENDORID
#define W83793_REG_CHIPID
#define W83793_REG_DEVICEID

#define W83793_REG_CONFIG
#define W83793_REG_MFC
#define W83793_REG_FANIN_CTRL
#define W83793_REG_FANIN_SEL
#define W83793_REG_I2C_ADDR
#define W83793_REG_I2C_SUBADDR
#define W83793_REG_VID_INA
#define W83793_REG_VID_INB
#define W83793_REG_VID_LATCHA
#define W83793_REG_VID_LATCHB
#define W83793_REG_VID_CTRL

#define W83793_REG_WDT_LOCK
#define W83793_REG_WDT_ENABLE
#define W83793_REG_WDT_STATUS
#define W83793_REG_WDT_TIMEOUT

static u16 W83793_REG_TEMP_MODE[2] =;

#define TEMP_READ
#define TEMP_CRIT
#define TEMP_CRIT_HYST
#define TEMP_WARN
#define TEMP_WARN_HYST
/*
 * only crit and crit_hyst affect real-time alarm status
 * current crit crit_hyst warn warn_hyst
 */
static u16 W83793_REG_TEMP[][5] =;

#define W83793_REG_TEMP_LOW_BITS

#define W83793_REG_BEEP(index)
#define W83793_REG_ALARM(index)

#define W83793_REG_CLR_CHASSIS
#define W83793_REG_IRQ_CTRL
#define W83793_REG_OVT_CTRL
#define W83793_REG_OVT_BEEP

#define IN_READ
#define IN_MAX
#define IN_LOW
static const u16 W83793_REG_IN[][3] =;

/* Low Bits of Vcore A/B Vtt Read/High/Low */
static const u16 W83793_REG_IN_LOW_BITS[] =;
static u8 scale_in[] =;
static u8 scale_in_add[] =;

#define W83793_REG_FAN(index)
#define W83793_REG_FAN_MIN(index)

#define W83793_REG_PWM_DEFAULT
#define W83793_REG_PWM_ENABLE
#define W83793_REG_PWM_UPTIME
#define W83793_REG_PWM_DOWNTIME
#define W83793_REG_TEMP_CRITICAL

#define PWM_DUTY
#define PWM_START
#define PWM_NONSTOP
#define PWM_STOP_TIME
#define W83793_REG_PWM(index, nr)

/* bit field, fan1 is bit0, fan2 is bit1 ... */
#define W83793_REG_TEMP_FAN_MAP(index)
#define W83793_REG_TEMP_TOL(index)
#define W83793_REG_TEMP_CRUISE(index)
#define W83793_REG_PWM_STOP_TIME(index)
#define W83793_REG_SF2_TEMP(index, nr)
#define W83793_REG_SF2_PWM(index, nr)

static inline unsigned long FAN_FROM_REG(u16 val)
{}

static inline u16 FAN_TO_REG(long rpm)
{}

static inline unsigned long TIME_FROM_REG(u8 reg)
{}

static inline u8 TIME_TO_REG(unsigned long val)
{}

static inline long TEMP_FROM_REG(s8 reg)
{}

static inline s8 TEMP_TO_REG(long val, s8 min, s8 max)
{}

struct w83793_data {};

/*
 * Somewhat ugly :( global data pointer list with all devices, so that
 * we can find our device data as when using misc_register. There is no
 * other method to get to one's device data from the open file-op and
 * for usage in the reboot notifier callback.
 */
static LIST_HEAD(watchdog_data_list);

/* Note this lock not only protect list access, but also data.kref access */
static DEFINE_MUTEX(watchdog_data_mutex);

/*
 * Release our data struct when we're detached from the i2c client *and* all
 * references to our watchdog device are released
 */
static void w83793_release_resources(struct kref *ref)
{}

static u8 w83793_read_value(struct i2c_client *client, u16 reg);
static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value);
static int w83793_probe(struct i2c_client *client);
static int w83793_detect(struct i2c_client *client,
			 struct i2c_board_info *info);
static void w83793_remove(struct i2c_client *client);
static void w83793_init_client(struct i2c_client *client);
static void w83793_update_nonvolatile(struct device *dev);
static struct w83793_data *w83793_update_device(struct device *dev);

static const struct i2c_device_id w83793_id[] =;
MODULE_DEVICE_TABLE(i2c, w83793_id);

static struct i2c_driver w83793_driver =;

static ssize_t
vrm_show(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
vrm_store(struct device *dev, struct device_attribute *attr,
	  const char *buf, size_t count)
{}

#define ALARM_STATUS
#define BEEP_ENABLE
static ssize_t
show_alarm_beep(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_beep(struct device *dev, struct device_attribute *attr,
	   const char *buf, size_t count)
{}

static ssize_t
show_beep_enable(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_beep_enable(struct device *dev, struct device_attribute *attr,
		  const char *buf, size_t count)
{}

/* Write 0 to clear chassis alarm */
static ssize_t
store_chassis_clear(struct device *dev,
		    struct device_attribute *attr, const char *buf,
		    size_t count)
{}

#define FAN_INPUT
#define FAN_MIN
static ssize_t
show_fan(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_fan_min(struct device *dev, struct device_attribute *attr,
	      const char *buf, size_t count)
{}

static ssize_t
show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_pwm(struct device *dev, struct device_attribute *attr,
	  const char *buf, size_t count)
{}

static ssize_t
show_temp(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_temp(struct device *dev, struct device_attribute *attr,
	   const char *buf, size_t count)
{}

/*
 * TD1-TD4
 * each has 4 mode:(2 bits)
 * 0:	Stop monitor
 * 1:	Use internal temp sensor(default)
 * 2:	Reserved
 * 3:	Use sensor in Intel CPU and get result by PECI
 *
 * TR1-TR2
 * each has 2 mode:(1 bit)
 * 0:	Disable temp sensor monitor
 * 1:	To enable temp sensors monitor
 */

/* 0 disable, 6 PECI */
static u8 TO_TEMP_MODE[] =;

static ssize_t
show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_temp_mode(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{}

#define SETUP_PWM_DEFAULT
#define SETUP_PWM_UPTIME
#define SETUP_PWM_DOWNTIME
#define SETUP_TEMP_CRITICAL
static ssize_t
show_sf_setup(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_sf_setup(struct device *dev, struct device_attribute *attr,
	       const char *buf, size_t count)
{}

/*
 * Temp SmartFan control
 * TEMP_FAN_MAP
 * Temp channel control which pwm fan, bitfield, bit 0 indicate pwm1...
 * It's possible two or more temp channels control the same fan, w83793
 * always prefers to pick the most critical request and applies it to
 * the related Fan.
 * It's possible one fan is not in any mapping of 6 temp channels, this
 * means the fan is manual mode
 *
 * TEMP_PWM_ENABLE
 * Each temp channel has its own SmartFan mode, and temp channel
 * control fans that are set by TEMP_FAN_MAP
 * 0:	SmartFanII mode
 * 1:	Thermal Cruise Mode
 *
 * TEMP_CRUISE
 * Target temperature in thermal cruise mode, w83793 will try to turn
 * fan speed to keep the temperature of target device around this
 * temperature.
 *
 * TEMP_TOLERANCE
 * If Temp higher or lower than target with this tolerance, w83793
 * will take actions to speed up or slow down the fan to keep the
 * temperature within the tolerance range.
 */

#define TEMP_FAN_MAP
#define TEMP_PWM_ENABLE
#define TEMP_CRUISE
#define TEMP_TOLERANCE
static ssize_t
show_sf_ctrl(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_sf_ctrl(struct device *dev, struct device_attribute *attr,
	      const char *buf, size_t count)
{}

static ssize_t
show_sf2_pwm(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_sf2_pwm(struct device *dev, struct device_attribute *attr,
	      const char *buf, size_t count)
{}

static ssize_t
show_sf2_temp(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_sf2_temp(struct device *dev, struct device_attribute *attr,
	       const char *buf, size_t count)
{}

/* only Vcore A/B and Vtt have additional 2 bits precision */
static ssize_t
show_in(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t
store_in(struct device *dev, struct device_attribute *attr,
	 const char *buf, size_t count)
{}

#define NOT_USED

#define SENSOR_ATTR_IN(index)

#define SENSOR_ATTR_FAN(index)

#define SENSOR_ATTR_PWM(index)

#define SENSOR_ATTR_TEMP(index)

static struct sensor_device_attribute_2 w83793_sensor_attr_2[] =;

static struct sensor_device_attribute_2 w83793_temp[] =;

/* Fan6-Fan12 */
static struct sensor_device_attribute_2 w83793_left_fan[] =;

/* Pwm4-Pwm8 */
static struct sensor_device_attribute_2 w83793_left_pwm[] =;

static struct sensor_device_attribute_2 w83793_vid[] =;
static DEVICE_ATTR_RW(vrm);

static struct sensor_device_attribute_2 sda_single_files[] =;

static void w83793_init_client(struct i2c_client *client)
{}

/*
 * Watchdog routines
 */

static int watchdog_set_timeout(struct w83793_data *data, int timeout)
{}

static int watchdog_get_timeout(struct w83793_data *data)
{}

static int watchdog_trigger(struct w83793_data *data)
{}

static int watchdog_enable(struct w83793_data *data)
{}

static int watchdog_disable(struct w83793_data *data)
{}

static int watchdog_open(struct inode *inode, struct file *filp)
{}

static int watchdog_close(struct inode *inode, struct file *filp)
{}

static ssize_t watchdog_write(struct file *filp, const char __user *buf,
	size_t count, loff_t *offset)
{}

static long watchdog_ioctl(struct file *filp, unsigned int cmd,
			   unsigned long arg)
{}

static const struct file_operations watchdog_fops =;

/*
 *	Notifier for system down
 */

static int watchdog_notify_sys(struct notifier_block *this, unsigned long code,
			       void *unused)
{}

/*
 *	The WDT needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block watchdog_notifier =;

/*
 * Init / remove routines
 */

static void w83793_remove(struct i2c_client *client)
{}

static int
w83793_detect_subclients(struct i2c_client *client)
{}

/* Return 0 if detection is successful, -ENODEV otherwise */
static int w83793_detect(struct i2c_client *client,
			 struct i2c_board_info *info)
{}

static int w83793_probe(struct i2c_client *client)
{}

static void w83793_update_nonvolatile(struct device *dev)
{}

static struct w83793_data *w83793_update_device(struct device *dev)
{}

/*
 * Ignore the possibility that somebody change bank outside the driver
 * Must be called with data->update_lock held, except during initialization
 */
static u8 w83793_read_value(struct i2c_client *client, u16 reg)
{}

/* Must be called with data->update_lock held, except during initialization */
static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value)
{}

module_i2c_driver();

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