linux/drivers/hwmon/abituguru.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * abituguru.c Copyright (c) 2005-2006 Hans de Goede <[email protected]>
 */
/*
 * This driver supports the sensor part of the first and second revision of
 * the custom Abit uGuru chip found on Abit uGuru motherboards. Note: because
 * of lack of specs the CPU/RAM voltage & frequency control is not supported!
 */

#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/dmi.h>
#include <linux/io.h>

/* Banks */
#define ABIT_UGURU_ALARM_BANK
#define ABIT_UGURU_SENSOR_BANK1
#define ABIT_UGURU_FAN_PWM
#define ABIT_UGURU_SENSOR_BANK2
/* max nr of sensors in bank1, a bank1 sensor can be in, temp or nc */
#define ABIT_UGURU_MAX_BANK1_SENSORS
/*
 * Warning if you increase one of the 2 MAX defines below to 10 or higher you
 * should adjust the belonging _NAMES_LENGTH macro for the 2 digit number!
 */
/* max nr of sensors in bank2, currently mb's with max 6 fans are known */
#define ABIT_UGURU_MAX_BANK2_SENSORS
/* max nr of pwm outputs, currently mb's with max 5 pwm outputs are known */
#define ABIT_UGURU_MAX_PWMS
/* uGuru sensor bank 1 flags */			     /* Alarm if: */
#define ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE
#define ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE
#define ABIT_UGURU_VOLT_LOW_ALARM_ENABLE
#define ABIT_UGURU_TEMP_HIGH_ALARM_FLAG
#define ABIT_UGURU_VOLT_HIGH_ALARM_FLAG
#define ABIT_UGURU_VOLT_LOW_ALARM_FLAG
/* uGuru sensor bank 2 flags */			     /* Alarm if: */
#define ABIT_UGURU_FAN_LOW_ALARM_ENABLE
/* uGuru sensor bank common flags */
#define ABIT_UGURU_BEEP_ENABLE
#define ABIT_UGURU_SHUTDOWN_ENABLE
/* uGuru fan PWM (speed control) flags */
#define ABIT_UGURU_FAN_PWM_ENABLE
/* Values used for conversion */
#define ABIT_UGURU_FAN_MAX
/* Bank1 sensor types */
#define ABIT_UGURU_IN_SENSOR
#define ABIT_UGURU_TEMP_SENSOR
#define ABIT_UGURU_NC
/*
 * In many cases we need to wait for the uGuru to reach a certain status, most
 * of the time it will reach this status within 30 - 90 ISA reads, and thus we
 * can best busy wait. This define gives the total amount of reads to try.
 */
#define ABIT_UGURU_WAIT_TIMEOUT
/*
 * However sometimes older versions of the uGuru seem to be distracted and they
 * do not respond for a long time. To handle this we sleep before each of the
 * last ABIT_UGURU_WAIT_TIMEOUT_SLEEP tries.
 */
#define ABIT_UGURU_WAIT_TIMEOUT_SLEEP
/*
 * Normally all expected status in abituguru_ready, are reported after the
 * first read, but sometimes not and we need to poll.
 */
#define ABIT_UGURU_READY_TIMEOUT
/* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */
#define ABIT_UGURU_MAX_RETRIES
#define ABIT_UGURU_RETRY_DELAY
/* Maximum 2 timeouts in abituguru_update_device, iow 3 in a row is an error */
#define ABIT_UGURU_MAX_TIMEOUTS
/* utility macros */
#define ABIT_UGURU_NAME
#define ABIT_UGURU_DEBUG(level, format, arg...)

/* Macros to help calculate the sysfs_names array length */
/*
 * sum of strlen of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0,
 * in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0
 */
#define ABITUGURU_IN_NAMES_LENGTH
/*
 * sum of strlen of: temp??_input\0, temp??_max\0, temp??_crit\0,
 * temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0
 */
#define ABITUGURU_TEMP_NAMES_LENGTH
/*
 * sum of strlen of: fan?_input\0, fan?_min\0, fan?_alarm\0,
 * fan?_alarm_enable\0, fan?_beep\0, fan?_shutdown\0
 */
#define ABITUGURU_FAN_NAMES_LENGTH
/*
 * sum of strlen of: pwm?_enable\0, pwm?_auto_channels_temp\0,
 * pwm?_auto_point{1,2}_pwm\0, pwm?_auto_point{1,2}_temp\0
 */
#define ABITUGURU_PWM_NAMES_LENGTH
/* IN_NAMES_LENGTH > TEMP_NAMES_LENGTH so assume all bank1 sensors are in */
#define ABITUGURU_SYSFS_NAMES_LENGTH

/*
 * All the macros below are named identical to the oguru and oguru2 programs
 * reverse engineered by Olle Sandberg, hence the names might not be 100%
 * logical. I could come up with better names, but I prefer keeping the names
 * identical so that this driver can be compared with his work more easily.
 */
/* Two i/o-ports are used by uGuru */
#define ABIT_UGURU_BASE
/* Used to tell uGuru what to read and to read the actual data */
#define ABIT_UGURU_CMD
/* Mostly used to check if uGuru is busy */
#define ABIT_UGURU_DATA
#define ABIT_UGURU_REGION_LENGTH
/* uGuru status' */
#define ABIT_UGURU_STATUS_WRITE
#define ABIT_UGURU_STATUS_READ
#define ABIT_UGURU_STATUS_INPUT
#define ABIT_UGURU_STATUS_READY

/* Constants */
/* in (Volt) sensors go up to 3494 mV, temp to 255000 millidegrees Celsius */
static const int abituguru_bank1_max_value[2] =;
/*
 * Min / Max allowed values for sensor2 (fan) alarm threshold, these values
 * correspond to 300-3000 RPM
 */
static const u8 abituguru_bank2_min_threshold =;
static const u8 abituguru_bank2_max_threshold =;
/*
 * Register 0 is a bitfield, 1 and 2 are pwm settings (255 = 100%), 3 and 4
 * are temperature trip points.
 */
static const int abituguru_pwm_settings_multiplier[5] =;
/*
 * Min / Max allowed values for pwm_settings. Note: pwm1 (CPU fan) is a
 * special case the minimum allowed pwm% setting for this is 30% (77) on
 * some MB's this special case is handled in the code!
 */
static const u8 abituguru_pwm_min[5] =;
static const u8 abituguru_pwm_max[5] =;


/* Insmod parameters */
static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC();
static int bank1_types[ABIT_UGURU_MAX_BANK1_SENSORS] =;
module_param_array();
MODULE_PARM_DESC();
static int fan_sensors;
module_param(fan_sensors, int, 0);
MODULE_PARM_DESC();
static int pwms;
module_param(pwms, int, 0);
MODULE_PARM_DESC();

/* Default verbose is 2, since this driver is still in the testing phase */
static int verbose =;
module_param(verbose, int, 0644);
MODULE_PARM_DESC();


/*
 * For the Abit uGuru, we need to keep some data in memory.
 * The structure is dynamically allocated, at the same time when a new
 * abituguru device is allocated.
 */
struct abituguru_data {};

static const char *never_happen =;
static const char *report_this =;

/* wait till the uguru is in the specified state */
static int abituguru_wait(struct abituguru_data *data, u8 state)
{}

/* Put the uguru in ready for input state */
static int abituguru_ready(struct abituguru_data *data)
{}

/*
 * Send the bank and then sensor address to the uGuru for the next read/write
 * cycle. This function gets called as the first part of a read/write by
 * abituguru_read and abituguru_write. This function should never be
 * called by any other function.
 */
static int abituguru_send_address(struct abituguru_data *data,
	u8 bank_addr, u8 sensor_addr, int retries)
{}

/*
 * Read count bytes from sensor sensor_addr in bank bank_addr and store the
 * result in buf, retry the send address part of the read retries times.
 */
static int abituguru_read(struct abituguru_data *data,
	u8 bank_addr, u8 sensor_addr, u8 *buf, int count, int retries)
{}

/*
 * Write count bytes from buf to sensor sensor_addr in bank bank_addr, the send
 * address part of the write is always retried ABIT_UGURU_MAX_RETRIES times.
 */
static int abituguru_write(struct abituguru_data *data,
	u8 bank_addr, u8 sensor_addr, u8 *buf, int count)
{}

/*
 * Detect sensor type. Temp and Volt sensors are enabled with
 * different masks and will ignore enable masks not meant for them.
 * This enables us to test what kind of sensor we're dealing with.
 * By setting the alarm thresholds so that we will always get an
 * alarm for sensor type X and then enabling the sensor as sensor type
 * X, if we then get an alarm it is a sensor of type X.
 */
static int
abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
				   u8 sensor_addr)
{}

/*
 * These functions try to find out how many sensors there are in bank2 and how
 * many pwms there are. The purpose of this is to make sure that we don't give
 * the user the possibility to change settings for non-existent sensors / pwm.
 * The uGuru will happily read / write whatever memory happens to be after the
 * memory storing the PWM settings when reading/writing to a PWM which is not
 * there. Notice even if we detect a PWM which doesn't exist we normally won't
 * write to it, unless the user tries to change the settings.
 *
 * Although the uGuru allows reading (settings) from non existing bank2
 * sensors, my version of the uGuru does seem to stop writing to them, the
 * write function above aborts in this case with:
 * "CMD reg does not hold 0xAC after write"
 *
 * Notice these 2 tests are non destructive iow read-only tests, otherwise
 * they would defeat their purpose. Although for the bank2_sensors detection a
 * read/write test would be feasible because of the reaction above, I've
 * however opted to stay on the safe side.
 */
static void
abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
{}

static void
abituguru_detect_no_pwms(struct abituguru_data *data)
{}

/*
 * Following are the sysfs callback functions. These functions expect:
 * sensor_device_attribute_2->index:   sensor address/offset in the bank
 * sensor_device_attribute_2->nr:      register offset, bitmask or NA.
 */
static struct abituguru_data *abituguru_update_device(struct device *dev);

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

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

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

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

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

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

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

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

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

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

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

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

/* Fan PWM (speed control) */
static ssize_t show_pwm_setting(struct device *dev,
	struct device_attribute *devattr, char *buf)
{}

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

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

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

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

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

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

/* Sysfs attr templates, the real entries are generated automatically. */
static const
struct sensor_device_attribute_2 abituguru_sysfs_bank1_templ[2][9] =;

static const struct sensor_device_attribute_2 abituguru_sysfs_fan_templ[6] =;

static const struct sensor_device_attribute_2 abituguru_sysfs_pwm_templ[6] =;

static struct sensor_device_attribute_2 abituguru_sysfs_attr[] =;

static int abituguru_probe(struct platform_device *pdev)
{}

static void abituguru_remove(struct platform_device *pdev)
{}

static struct abituguru_data *abituguru_update_device(struct device *dev)
{}

static int abituguru_suspend(struct device *dev)
{}

static int abituguru_resume(struct device *dev)
{}

static DEFINE_SIMPLE_DEV_PM_OPS(abituguru_pm, abituguru_suspend, abituguru_resume);

static struct platform_driver abituguru_driver =;

static int __init abituguru_detect(void)
{}

static struct platform_device *abituguru_pdev;

static int __init abituguru_init(void)
{}

static void __exit abituguru_exit(void)
{}

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

module_init();
module_exit(abituguru_exit);