linux/drivers/hwmon/fschmd.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * fschmd.c
 *
 * Copyright (C) 2007 - 2009 Hans de Goede <[email protected]>
 */

/*
 *  Merged Fujitsu Siemens hwmon driver, supporting the Poseidon, Hermes,
 *  Scylla, Heracles, Heimdall, Hades and Syleus chips
 *
 *  Based on the original 2.4 fscscy, 2.6 fscpos, 2.6 fscher and 2.6
 *  (candidate) fschmd drivers:
 *  Copyright (C) 2006 Thilo Cestonaro
 *			<[email protected]>
 *  Copyright (C) 2004, 2005 Stefan Ott <[email protected]>
 *  Copyright (C) 2003, 2004 Reinhard Nissl <[email protected]>
 *  Copyright (c) 2001 Martin Knoblauch <[email protected], [email protected]>
 *  Copyright (C) 2000 Hermann Jung <[email protected]>
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.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/sysfs.h>
#include <linux/dmi.h>
#include <linux/fs.h>
#include <linux/watchdog.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/kref.h>

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

/* Insmod parameters */
static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC();

enum chips {};

/*
 * The FSCHMD registers and other defines
 */

/* chip identification */
#define FSCHMD_REG_IDENT_0
#define FSCHMD_REG_IDENT_1
#define FSCHMD_REG_IDENT_2
#define FSCHMD_REG_REVISION

/* global control and status */
#define FSCHMD_REG_EVENT_STATE
#define FSCHMD_REG_CONTROL

#define FSCHMD_CONTROL_ALERT_LED

/* watchdog */
static const u8 FSCHMD_REG_WDOG_CONTROL[7] =;
static const u8 FSCHMD_REG_WDOG_STATE[7] =;
static const u8 FSCHMD_REG_WDOG_PRESET[7] =;

#define FSCHMD_WDOG_CONTROL_TRIGGER
#define FSCHMD_WDOG_CONTROL_STARTED
#define FSCHMD_WDOG_CONTROL_STOP
#define FSCHMD_WDOG_CONTROL_RESOLUTION

#define FSCHMD_WDOG_STATE_CARDRESET

/* voltages, weird order is to keep the same order as the old drivers */
static const u8 FSCHMD_REG_VOLT[7][6] =;

static const int FSCHMD_NO_VOLT_SENSORS[7] =;

/*
 * minimum pwm at which the fan is driven (pwm can be increased depending on
 * the temp. Notice that for the scy some fans share there minimum speed.
 * Also notice that with the scy the sensor order is different than with the
 * other chips, this order was in the 2.4 driver and kept for consistency.
 */
static const u8 FSCHMD_REG_FAN_MIN[7][7] =;

/* actual fan speed */
static const u8 FSCHMD_REG_FAN_ACT[7][7] =;

/* fan status registers */
static const u8 FSCHMD_REG_FAN_STATE[7][7] =;

/* fan ripple / divider registers */
static const u8 FSCHMD_REG_FAN_RIPPLE[7][7] =;

static const int FSCHMD_NO_FAN_SENSORS[7] =;

/* Fan status register bitmasks */
#define FSCHMD_FAN_ALARM
#define FSCHMD_FAN_NOT_PRESENT
#define FSCHMD_FAN_DISABLED


/* actual temperature registers */
static const u8 FSCHMD_REG_TEMP_ACT[7][11] =;

/* temperature state registers */
static const u8 FSCHMD_REG_TEMP_STATE[7][11] =;

/*
 * temperature high limit registers, FSC does not document these. Proven to be
 * there with field testing on the fscher and fschrc, already supported / used
 * in the fscscy 2.4 driver. FSC has confirmed that the fschmd has registers
 * at these addresses, but doesn't want to confirm they are the same as with
 * the fscher??
 */
static const u8 FSCHMD_REG_TEMP_LIMIT[7][11] =;

/*
 * These were found through experimenting with an fscher, currently they are
 * not used, but we keep them around for future reference.
 * On the fscsyl AUTOP1 lives at 0x#c (so 0x5c for fan1, 0x6c for fan2, etc),
 * AUTOP2 lives at 0x#e, and 0x#1 is a bitmask defining which temps influence
 * the fan speed.
 * static const u8 FSCHER_REG_TEMP_AUTOP1[] =	{ 0x73, 0x83, 0x93 };
 * static const u8 FSCHER_REG_TEMP_AUTOP2[] =	{ 0x75, 0x85, 0x95 };
 */

static const int FSCHMD_NO_TEMP_SENSORS[7] =;

/* temp status register bitmasks */
#define FSCHMD_TEMP_WORKING
#define FSCHMD_TEMP_ALERT
#define FSCHMD_TEMP_DISABLED
/* there only really is an alarm if the sensor is working and alert == 1 */
#define FSCHMD_TEMP_ALARM_MASK

/*
 * Functions declarations
 */

static int fschmd_probe(struct i2c_client *client);
static int fschmd_detect(struct i2c_client *client,
			 struct i2c_board_info *info);
static void fschmd_remove(struct i2c_client *client);
static struct fschmd_data *fschmd_update_device(struct device *dev);

/*
 * Driver data (common to all clients)
 */

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

static struct i2c_driver fschmd_driver =;

/*
 * Client data (each client gets its own)
 */

struct fschmd_data {};

/*
 * Global variables to hold information read from special DMI tables, which are
 * available on FSC machines with an fscher or later chip. There is no need to
 * protect these with a lock as they are only modified from our attach function
 * which always gets called with the i2c-core lock held and never accessed
 * before the attach function is done with them.
 */
static int dmi_mult[6] =;
static int dmi_offset[6] =;
static int dmi_vref =;

/*
 * Somewhat ugly :( global data pointer list with all fschmd devices, so that
 * we can find our device data as when using misc_register there is no other
 * method to get to ones device data from the open fop.
 */
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 fschmd_release_resources(struct kref *ref)
{}

/*
 * Sysfs attr show / store functions
 */

static ssize_t in_value_show(struct device *dev,
			     struct device_attribute *devattr, char *buf)
{}


#define TEMP_FROM_REG(val)

static ssize_t temp_value_show(struct device *dev,
			       struct device_attribute *devattr, char *buf)
{}

static ssize_t temp_max_show(struct device *dev,
			     struct device_attribute *devattr, char *buf)
{}

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

static ssize_t temp_fault_show(struct device *dev,
			       struct device_attribute *devattr, char *buf)
{}

static ssize_t temp_alarm_show(struct device *dev,
			       struct device_attribute *devattr, char *buf)
{}


#define RPM_FROM_REG(val)

static ssize_t fan_value_show(struct device *dev,
			      struct device_attribute *devattr, char *buf)
{}

static ssize_t fan_div_show(struct device *dev,
			    struct device_attribute *devattr, char *buf)
{}

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

static ssize_t fan_alarm_show(struct device *dev,
			      struct device_attribute *devattr, char *buf)
{}

static ssize_t fan_fault_show(struct device *dev,
			      struct device_attribute *devattr, char *buf)
{}


static ssize_t pwm_auto_point1_pwm_show(struct device *dev,
					struct device_attribute *devattr,
					char *buf)
{}

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


/*
 * The FSC hwmon family has the ability to force an attached alert led to flash
 * from software, we export this as an alert_led sysfs attr
 */
static ssize_t alert_led_show(struct device *dev,
	struct device_attribute *devattr, char *buf)
{}

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

static DEVICE_ATTR_RW(alert_led);

static struct sensor_device_attribute fschmd_attr[] =;

static struct sensor_device_attribute fschmd_temp_attr[] =;

static struct sensor_device_attribute fschmd_fan_attr[] =;


/*
 * Watchdog routines
 */

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

static int watchdog_get_timeout(struct fschmd_data *data)
{}

static int watchdog_trigger(struct fschmd_data *data)
{}

static int watchdog_stop(struct fschmd_data *data)
{}

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

static int watchdog_release(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 =;


/*
 * Detect, register, unregister and update device functions
 */

/*
 * DMI decode routine to read voltage scaling factors from special DMI tables,
 * which are available on FSC machines with an fscher or later chip.
 */
static void fschmd_dmi_decode(const struct dmi_header *header, void *dummy)
{}

static int fschmd_detect(struct i2c_client *client,
			 struct i2c_board_info *info)
{}

static int fschmd_probe(struct i2c_client *client)
{}

static void fschmd_remove(struct i2c_client *client)
{}

static struct fschmd_data *fschmd_update_device(struct device *dev)
{}

module_i2c_driver();

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