2019-05-20 10:19:02 +03:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
2011-01-27 07:09:02 +03:00
|
|
|
/*
|
|
|
|
* pmbus.h - Common defines and structures for PMBus devices
|
|
|
|
*
|
|
|
|
* Copyright (c) 2010, 2011 Ericsson AB.
|
2013-01-16 22:31:32 +04:00
|
|
|
* Copyright (c) 2012 Guenter Roeck
|
2011-01-27 07:09:02 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef PMBUS_H
|
|
|
|
#define PMBUS_H
|
|
|
|
|
2015-08-18 02:17:24 +03:00
|
|
|
#include <linux/bitops.h>
|
|
|
|
#include <linux/regulator/driver.h>
|
|
|
|
|
2011-01-27 07:09:02 +03:00
|
|
|
/*
|
|
|
|
* Registers
|
|
|
|
*/
|
2015-08-13 07:05:38 +03:00
|
|
|
enum pmbus_regs {
|
|
|
|
PMBUS_PAGE = 0x00,
|
|
|
|
PMBUS_OPERATION = 0x01,
|
|
|
|
PMBUS_ON_OFF_CONFIG = 0x02,
|
|
|
|
PMBUS_CLEAR_FAULTS = 0x03,
|
|
|
|
PMBUS_PHASE = 0x04,
|
|
|
|
|
|
|
|
PMBUS_CAPABILITY = 0x19,
|
|
|
|
PMBUS_QUERY = 0x1A,
|
|
|
|
|
|
|
|
PMBUS_VOUT_MODE = 0x20,
|
|
|
|
PMBUS_VOUT_COMMAND = 0x21,
|
|
|
|
PMBUS_VOUT_TRIM = 0x22,
|
|
|
|
PMBUS_VOUT_CAL_OFFSET = 0x23,
|
|
|
|
PMBUS_VOUT_MAX = 0x24,
|
|
|
|
PMBUS_VOUT_MARGIN_HIGH = 0x25,
|
|
|
|
PMBUS_VOUT_MARGIN_LOW = 0x26,
|
|
|
|
PMBUS_VOUT_TRANSITION_RATE = 0x27,
|
|
|
|
PMBUS_VOUT_DROOP = 0x28,
|
|
|
|
PMBUS_VOUT_SCALE_LOOP = 0x29,
|
|
|
|
PMBUS_VOUT_SCALE_MONITOR = 0x2A,
|
|
|
|
|
|
|
|
PMBUS_COEFFICIENTS = 0x30,
|
|
|
|
PMBUS_POUT_MAX = 0x31,
|
|
|
|
|
|
|
|
PMBUS_FAN_CONFIG_12 = 0x3A,
|
|
|
|
PMBUS_FAN_COMMAND_1 = 0x3B,
|
|
|
|
PMBUS_FAN_COMMAND_2 = 0x3C,
|
|
|
|
PMBUS_FAN_CONFIG_34 = 0x3D,
|
|
|
|
PMBUS_FAN_COMMAND_3 = 0x3E,
|
|
|
|
PMBUS_FAN_COMMAND_4 = 0x3F,
|
|
|
|
|
|
|
|
PMBUS_VOUT_OV_FAULT_LIMIT = 0x40,
|
|
|
|
PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41,
|
|
|
|
PMBUS_VOUT_OV_WARN_LIMIT = 0x42,
|
|
|
|
PMBUS_VOUT_UV_WARN_LIMIT = 0x43,
|
|
|
|
PMBUS_VOUT_UV_FAULT_LIMIT = 0x44,
|
|
|
|
PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45,
|
|
|
|
PMBUS_IOUT_OC_FAULT_LIMIT = 0x46,
|
|
|
|
PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47,
|
|
|
|
PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48,
|
|
|
|
PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49,
|
|
|
|
PMBUS_IOUT_OC_WARN_LIMIT = 0x4A,
|
|
|
|
PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B,
|
|
|
|
PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C,
|
|
|
|
|
|
|
|
PMBUS_OT_FAULT_LIMIT = 0x4F,
|
|
|
|
PMBUS_OT_FAULT_RESPONSE = 0x50,
|
|
|
|
PMBUS_OT_WARN_LIMIT = 0x51,
|
|
|
|
PMBUS_UT_WARN_LIMIT = 0x52,
|
|
|
|
PMBUS_UT_FAULT_LIMIT = 0x53,
|
|
|
|
PMBUS_UT_FAULT_RESPONSE = 0x54,
|
|
|
|
PMBUS_VIN_OV_FAULT_LIMIT = 0x55,
|
|
|
|
PMBUS_VIN_OV_FAULT_RESPONSE = 0x56,
|
|
|
|
PMBUS_VIN_OV_WARN_LIMIT = 0x57,
|
|
|
|
PMBUS_VIN_UV_WARN_LIMIT = 0x58,
|
|
|
|
PMBUS_VIN_UV_FAULT_LIMIT = 0x59,
|
|
|
|
|
|
|
|
PMBUS_IIN_OC_FAULT_LIMIT = 0x5B,
|
|
|
|
PMBUS_IIN_OC_WARN_LIMIT = 0x5D,
|
|
|
|
|
|
|
|
PMBUS_POUT_OP_FAULT_LIMIT = 0x68,
|
|
|
|
PMBUS_POUT_OP_WARN_LIMIT = 0x6A,
|
|
|
|
PMBUS_PIN_OP_WARN_LIMIT = 0x6B,
|
|
|
|
|
|
|
|
PMBUS_STATUS_BYTE = 0x78,
|
|
|
|
PMBUS_STATUS_WORD = 0x79,
|
|
|
|
PMBUS_STATUS_VOUT = 0x7A,
|
|
|
|
PMBUS_STATUS_IOUT = 0x7B,
|
|
|
|
PMBUS_STATUS_INPUT = 0x7C,
|
|
|
|
PMBUS_STATUS_TEMPERATURE = 0x7D,
|
|
|
|
PMBUS_STATUS_CML = 0x7E,
|
|
|
|
PMBUS_STATUS_OTHER = 0x7F,
|
|
|
|
PMBUS_STATUS_MFR_SPECIFIC = 0x80,
|
|
|
|
PMBUS_STATUS_FAN_12 = 0x81,
|
|
|
|
PMBUS_STATUS_FAN_34 = 0x82,
|
|
|
|
|
|
|
|
PMBUS_READ_VIN = 0x88,
|
|
|
|
PMBUS_READ_IIN = 0x89,
|
|
|
|
PMBUS_READ_VCAP = 0x8A,
|
|
|
|
PMBUS_READ_VOUT = 0x8B,
|
|
|
|
PMBUS_READ_IOUT = 0x8C,
|
|
|
|
PMBUS_READ_TEMPERATURE_1 = 0x8D,
|
|
|
|
PMBUS_READ_TEMPERATURE_2 = 0x8E,
|
|
|
|
PMBUS_READ_TEMPERATURE_3 = 0x8F,
|
|
|
|
PMBUS_READ_FAN_SPEED_1 = 0x90,
|
|
|
|
PMBUS_READ_FAN_SPEED_2 = 0x91,
|
|
|
|
PMBUS_READ_FAN_SPEED_3 = 0x92,
|
|
|
|
PMBUS_READ_FAN_SPEED_4 = 0x93,
|
|
|
|
PMBUS_READ_DUTY_CYCLE = 0x94,
|
|
|
|
PMBUS_READ_FREQUENCY = 0x95,
|
|
|
|
PMBUS_READ_POUT = 0x96,
|
|
|
|
PMBUS_READ_PIN = 0x97,
|
|
|
|
|
|
|
|
PMBUS_REVISION = 0x98,
|
|
|
|
PMBUS_MFR_ID = 0x99,
|
|
|
|
PMBUS_MFR_MODEL = 0x9A,
|
|
|
|
PMBUS_MFR_REVISION = 0x9B,
|
|
|
|
PMBUS_MFR_LOCATION = 0x9C,
|
|
|
|
PMBUS_MFR_DATE = 0x9D,
|
|
|
|
PMBUS_MFR_SERIAL = 0x9E,
|
2011-01-27 07:09:02 +03:00
|
|
|
|
2011-07-09 19:30:26 +04:00
|
|
|
/*
|
|
|
|
* Virtual registers.
|
|
|
|
* Useful to support attributes which are not supported by standard PMBus
|
|
|
|
* registers but exist as manufacturer specific registers on individual chips.
|
|
|
|
* Must be mapped to real registers in device specific code.
|
|
|
|
*
|
|
|
|
* Semantics:
|
|
|
|
* Virtual registers are all word size.
|
|
|
|
* READ registers are read-only; writes are either ignored or return an error.
|
2011-08-26 19:01:51 +04:00
|
|
|
* RESET registers are read/write. Reading reset registers returns zero
|
|
|
|
* (used for detection), writing any value causes the associated history to be
|
|
|
|
* reset.
|
|
|
|
* Virtual registers have to be handled in device specific driver code. Chip
|
|
|
|
* driver code returns non-negative register values if a virtual register is
|
|
|
|
* supported, or a negative error code if not. The chip driver may return
|
|
|
|
* -ENODATA or any other error code in this case, though an error code other
|
|
|
|
* than -ENODATA is handled more efficiently and thus preferred. Either case,
|
|
|
|
* the calling PMBus core code will abort if the chip driver returns an error
|
|
|
|
* code when reading or writing virtual registers.
|
2011-07-09 19:30:26 +04:00
|
|
|
*/
|
2015-08-13 07:05:38 +03:00
|
|
|
PMBUS_VIRT_BASE = 0x100,
|
|
|
|
PMBUS_VIRT_READ_TEMP_AVG,
|
|
|
|
PMBUS_VIRT_READ_TEMP_MIN,
|
|
|
|
PMBUS_VIRT_READ_TEMP_MAX,
|
|
|
|
PMBUS_VIRT_RESET_TEMP_HISTORY,
|
|
|
|
PMBUS_VIRT_READ_VIN_AVG,
|
|
|
|
PMBUS_VIRT_READ_VIN_MIN,
|
|
|
|
PMBUS_VIRT_READ_VIN_MAX,
|
|
|
|
PMBUS_VIRT_RESET_VIN_HISTORY,
|
|
|
|
PMBUS_VIRT_READ_IIN_AVG,
|
|
|
|
PMBUS_VIRT_READ_IIN_MIN,
|
|
|
|
PMBUS_VIRT_READ_IIN_MAX,
|
|
|
|
PMBUS_VIRT_RESET_IIN_HISTORY,
|
|
|
|
PMBUS_VIRT_READ_PIN_AVG,
|
|
|
|
PMBUS_VIRT_READ_PIN_MIN,
|
|
|
|
PMBUS_VIRT_READ_PIN_MAX,
|
|
|
|
PMBUS_VIRT_RESET_PIN_HISTORY,
|
|
|
|
PMBUS_VIRT_READ_POUT_AVG,
|
|
|
|
PMBUS_VIRT_READ_POUT_MIN,
|
|
|
|
PMBUS_VIRT_READ_POUT_MAX,
|
|
|
|
PMBUS_VIRT_RESET_POUT_HISTORY,
|
|
|
|
PMBUS_VIRT_READ_VOUT_AVG,
|
|
|
|
PMBUS_VIRT_READ_VOUT_MIN,
|
|
|
|
PMBUS_VIRT_READ_VOUT_MAX,
|
|
|
|
PMBUS_VIRT_RESET_VOUT_HISTORY,
|
|
|
|
PMBUS_VIRT_READ_IOUT_AVG,
|
|
|
|
PMBUS_VIRT_READ_IOUT_MIN,
|
|
|
|
PMBUS_VIRT_READ_IOUT_MAX,
|
|
|
|
PMBUS_VIRT_RESET_IOUT_HISTORY,
|
|
|
|
PMBUS_VIRT_READ_TEMP2_AVG,
|
|
|
|
PMBUS_VIRT_READ_TEMP2_MIN,
|
|
|
|
PMBUS_VIRT_READ_TEMP2_MAX,
|
|
|
|
PMBUS_VIRT_RESET_TEMP2_HISTORY,
|
|
|
|
|
|
|
|
PMBUS_VIRT_READ_VMON,
|
|
|
|
PMBUS_VIRT_VMON_UV_WARN_LIMIT,
|
|
|
|
PMBUS_VIRT_VMON_OV_WARN_LIMIT,
|
|
|
|
PMBUS_VIRT_VMON_UV_FAULT_LIMIT,
|
|
|
|
PMBUS_VIRT_VMON_OV_FAULT_LIMIT,
|
|
|
|
PMBUS_VIRT_STATUS_VMON,
|
hwmon: (pmbus) Add fan control support
Expose fanX_target, pwmX and pwmX_enable hwmon sysfs attributes.
Fans in a PMBus device are driven by the configuration of two registers,
FAN_CONFIG_x_y and FAN_COMMAND_x: FAN_CONFIG_x_y dictates how the fan
and the tacho operate (if installed), while FAN_COMMAND_x sets the
desired fan rate. The unit of FAN_COMMAND_x is dependent on the
operational fan mode, RPM or PWM percent duty, as determined by the
corresponding configuration in FAN_CONFIG_x_y.
The mapping of fanX_target, pwmX and pwmX_enable onto FAN_CONFIG_x_y and
FAN_COMMAND_x is implemented with the addition of virtual registers to
facilitate the necessary side-effects of each access:
1. PMBUS_VIRT_FAN_TARGET_x
2. PMBUS_VIRT_PWM_x
3. PMBUS_VIRT_PWM_ENABLE_x
Some complexity arises with the fanX_target and pwmX attributes both mapping
onto FAN_COMMAND_x: There is no general mapping between PWM percent duty and
RPM, so we can't display values in either attribute in terms of the other
(which in my mind is the intuitive, if impossible, behaviour). This problem
also affects the pwmX_enable attribute which allows userspace to switch between
full speed, manual PWM and a number of automatic control modes, possibly
including a switch to RPM behaviour (e.g. automatically adjusting PWM duty to
reach a RPM target, the behaviour of fanX_target).
The next most intuitive behaviour is for fanX_target and pwmX to simply be
independent, to retain their most recently set value even if that value is not
active on the hardware (due to switching to the alternative control mode). This
property of retaining the value independent of the hardware state has useful
results for both userspace and the kernel: Userspace always sees a sensible
value in the attribute (the last thing it was set to, as opposed to 0 or
receiving an error on read), and the kernel can use the attributes as a value
cache. This latter point eases the implementation of pwmX_enable, which can
look up the associated pmbus_sensor object, take its cached value and apply it
to hardware on changing control mode. This ensures we will not arbitrarily set
a PWM value as an RPM value or vice versa, and we can assume that the RPM or
PWM value set was sensible at least at some point in the past.
Finally, the DIRECT mode coefficients of some controllers is different between
RPM and PWM percent duty control modes, so PSC_PWM is introduced to capture the
necessary coefficients. As pmbus core had no PWM support previously PSC_FAN
continues to be used to capture the RPM DIRECT coefficients, but in order to
avoid falsely applying RPM scaling to PWM values I have introduced the
PMBUS_HAVE_PWM12 and PMB_BUS_HAVE_PWM34 feature bits. These feature bits allow
drivers to explicitly declare PWM support in order to have the attributes
exposed.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2017-11-20 07:42:03 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* RPM and PWM Fan control
|
|
|
|
*
|
|
|
|
* Drivers wanting to expose PWM control must define the behaviour of
|
|
|
|
* PMBUS_VIRT_PWM_[1-4] and PMBUS_VIRT_PWM_ENABLE_[1-4] in the
|
|
|
|
* {read,write}_word_data callback.
|
|
|
|
*
|
|
|
|
* pmbus core provides a default implementation for
|
|
|
|
* PMBUS_VIRT_FAN_TARGET_[1-4].
|
|
|
|
*
|
|
|
|
* TARGET, PWM and PWM_ENABLE members must be defined sequentially;
|
|
|
|
* pmbus core uses the difference between the provided register and
|
|
|
|
* it's _1 counterpart to calculate the FAN/PWM ID.
|
|
|
|
*/
|
|
|
|
PMBUS_VIRT_FAN_TARGET_1,
|
|
|
|
PMBUS_VIRT_FAN_TARGET_2,
|
|
|
|
PMBUS_VIRT_FAN_TARGET_3,
|
|
|
|
PMBUS_VIRT_FAN_TARGET_4,
|
|
|
|
PMBUS_VIRT_PWM_1,
|
|
|
|
PMBUS_VIRT_PWM_2,
|
|
|
|
PMBUS_VIRT_PWM_3,
|
|
|
|
PMBUS_VIRT_PWM_4,
|
|
|
|
PMBUS_VIRT_PWM_ENABLE_1,
|
|
|
|
PMBUS_VIRT_PWM_ENABLE_2,
|
|
|
|
PMBUS_VIRT_PWM_ENABLE_3,
|
|
|
|
PMBUS_VIRT_PWM_ENABLE_4,
|
2019-04-15 00:58:18 +03:00
|
|
|
|
|
|
|
/* Samples for average
|
|
|
|
*
|
|
|
|
* Drivers wanting to expose functionality for changing the number of
|
|
|
|
* samples used for average values should implement support in
|
|
|
|
* {read,write}_word_data callback for either PMBUS_VIRT_SAMPLES if it
|
|
|
|
* applies to all types of measurements, or any number of specific
|
|
|
|
* PMBUS_VIRT_*_SAMPLES registers to allow for individual control.
|
|
|
|
*/
|
|
|
|
PMBUS_VIRT_SAMPLES,
|
|
|
|
PMBUS_VIRT_IN_SAMPLES,
|
|
|
|
PMBUS_VIRT_CURR_SAMPLES,
|
|
|
|
PMBUS_VIRT_POWER_SAMPLES,
|
|
|
|
PMBUS_VIRT_TEMP_SAMPLES,
|
2015-08-13 07:05:38 +03:00
|
|
|
};
|
2013-01-16 22:31:32 +04:00
|
|
|
|
2014-10-15 22:55:09 +04:00
|
|
|
/*
|
|
|
|
* OPERATION
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_OPERATION_CONTROL_ON BIT(7)
|
2014-10-15 22:55:09 +04:00
|
|
|
|
2011-01-27 07:09:02 +03:00
|
|
|
/*
|
|
|
|
* CAPABILITY
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_CAPABILITY_SMBALERT BIT(4)
|
|
|
|
#define PB_CAPABILITY_ERROR_CHECK BIT(7)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* VOUT_MODE
|
|
|
|
*/
|
|
|
|
#define PB_VOUT_MODE_MODE_MASK 0xe0
|
|
|
|
#define PB_VOUT_MODE_PARAM_MASK 0x1f
|
|
|
|
|
|
|
|
#define PB_VOUT_MODE_LINEAR 0x00
|
|
|
|
#define PB_VOUT_MODE_VID 0x20
|
|
|
|
#define PB_VOUT_MODE_DIRECT 0x40
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fan configuration
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1))
|
|
|
|
#define PB_FAN_2_RPM BIT(2)
|
|
|
|
#define PB_FAN_2_INSTALLED BIT(3)
|
|
|
|
#define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5))
|
|
|
|
#define PB_FAN_1_RPM BIT(6)
|
|
|
|
#define PB_FAN_1_INSTALLED BIT(7)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
hwmon: (pmbus) Add fan control support
Expose fanX_target, pwmX and pwmX_enable hwmon sysfs attributes.
Fans in a PMBus device are driven by the configuration of two registers,
FAN_CONFIG_x_y and FAN_COMMAND_x: FAN_CONFIG_x_y dictates how the fan
and the tacho operate (if installed), while FAN_COMMAND_x sets the
desired fan rate. The unit of FAN_COMMAND_x is dependent on the
operational fan mode, RPM or PWM percent duty, as determined by the
corresponding configuration in FAN_CONFIG_x_y.
The mapping of fanX_target, pwmX and pwmX_enable onto FAN_CONFIG_x_y and
FAN_COMMAND_x is implemented with the addition of virtual registers to
facilitate the necessary side-effects of each access:
1. PMBUS_VIRT_FAN_TARGET_x
2. PMBUS_VIRT_PWM_x
3. PMBUS_VIRT_PWM_ENABLE_x
Some complexity arises with the fanX_target and pwmX attributes both mapping
onto FAN_COMMAND_x: There is no general mapping between PWM percent duty and
RPM, so we can't display values in either attribute in terms of the other
(which in my mind is the intuitive, if impossible, behaviour). This problem
also affects the pwmX_enable attribute which allows userspace to switch between
full speed, manual PWM and a number of automatic control modes, possibly
including a switch to RPM behaviour (e.g. automatically adjusting PWM duty to
reach a RPM target, the behaviour of fanX_target).
The next most intuitive behaviour is for fanX_target and pwmX to simply be
independent, to retain their most recently set value even if that value is not
active on the hardware (due to switching to the alternative control mode). This
property of retaining the value independent of the hardware state has useful
results for both userspace and the kernel: Userspace always sees a sensible
value in the attribute (the last thing it was set to, as opposed to 0 or
receiving an error on read), and the kernel can use the attributes as a value
cache. This latter point eases the implementation of pwmX_enable, which can
look up the associated pmbus_sensor object, take its cached value and apply it
to hardware on changing control mode. This ensures we will not arbitrarily set
a PWM value as an RPM value or vice versa, and we can assume that the RPM or
PWM value set was sensible at least at some point in the past.
Finally, the DIRECT mode coefficients of some controllers is different between
RPM and PWM percent duty control modes, so PSC_PWM is introduced to capture the
necessary coefficients. As pmbus core had no PWM support previously PSC_FAN
continues to be used to capture the RPM DIRECT coefficients, but in order to
avoid falsely applying RPM scaling to PWM values I have introduced the
PMBUS_HAVE_PWM12 and PMB_BUS_HAVE_PWM34 feature bits. These feature bits allow
drivers to explicitly declare PWM support in order to have the attributes
exposed.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2017-11-20 07:42:03 +03:00
|
|
|
enum pmbus_fan_mode { percent = 0, rpm };
|
|
|
|
|
2011-01-27 07:09:02 +03:00
|
|
|
/*
|
|
|
|
* STATUS_BYTE, STATUS_WORD (lower)
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_STATUS_NONE_ABOVE BIT(0)
|
|
|
|
#define PB_STATUS_CML BIT(1)
|
|
|
|
#define PB_STATUS_TEMPERATURE BIT(2)
|
|
|
|
#define PB_STATUS_VIN_UV BIT(3)
|
|
|
|
#define PB_STATUS_IOUT_OC BIT(4)
|
|
|
|
#define PB_STATUS_VOUT_OV BIT(5)
|
|
|
|
#define PB_STATUS_OFF BIT(6)
|
|
|
|
#define PB_STATUS_BUSY BIT(7)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* STATUS_WORD (upper)
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_STATUS_UNKNOWN BIT(8)
|
|
|
|
#define PB_STATUS_OTHER BIT(9)
|
|
|
|
#define PB_STATUS_FANS BIT(10)
|
|
|
|
#define PB_STATUS_POWER_GOOD_N BIT(11)
|
|
|
|
#define PB_STATUS_WORD_MFR BIT(12)
|
|
|
|
#define PB_STATUS_INPUT BIT(13)
|
|
|
|
#define PB_STATUS_IOUT_POUT BIT(14)
|
|
|
|
#define PB_STATUS_VOUT BIT(15)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* STATUS_IOUT
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_POUT_OP_WARNING BIT(0)
|
|
|
|
#define PB_POUT_OP_FAULT BIT(1)
|
|
|
|
#define PB_POWER_LIMITING BIT(2)
|
|
|
|
#define PB_CURRENT_SHARE_FAULT BIT(3)
|
|
|
|
#define PB_IOUT_UC_FAULT BIT(4)
|
|
|
|
#define PB_IOUT_OC_WARNING BIT(5)
|
|
|
|
#define PB_IOUT_OC_LV_FAULT BIT(6)
|
|
|
|
#define PB_IOUT_OC_FAULT BIT(7)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* STATUS_VOUT, STATUS_INPUT
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_VOLTAGE_UV_FAULT BIT(4)
|
|
|
|
#define PB_VOLTAGE_UV_WARNING BIT(5)
|
|
|
|
#define PB_VOLTAGE_OV_WARNING BIT(6)
|
|
|
|
#define PB_VOLTAGE_OV_FAULT BIT(7)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* STATUS_INPUT
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_PIN_OP_WARNING BIT(0)
|
|
|
|
#define PB_IIN_OC_WARNING BIT(1)
|
|
|
|
#define PB_IIN_OC_FAULT BIT(2)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* STATUS_TEMPERATURE
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_TEMP_UT_FAULT BIT(4)
|
|
|
|
#define PB_TEMP_UT_WARNING BIT(5)
|
|
|
|
#define PB_TEMP_OT_WARNING BIT(6)
|
|
|
|
#define PB_TEMP_OT_FAULT BIT(7)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* STATUS_FAN
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_FAN_AIRFLOW_WARNING BIT(0)
|
|
|
|
#define PB_FAN_AIRFLOW_FAULT BIT(1)
|
|
|
|
#define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2)
|
|
|
|
#define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3)
|
|
|
|
#define PB_FAN_FAN2_WARNING BIT(4)
|
|
|
|
#define PB_FAN_FAN1_WARNING BIT(5)
|
|
|
|
#define PB_FAN_FAN2_FAULT BIT(6)
|
|
|
|
#define PB_FAN_FAN1_FAULT BIT(7)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* CML_FAULT_STATUS
|
|
|
|
*/
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0)
|
|
|
|
#define PB_CML_FAULT_OTHER_COMM BIT(1)
|
|
|
|
#define PB_CML_FAULT_PROCESSOR BIT(3)
|
|
|
|
#define PB_CML_FAULT_MEMORY BIT(4)
|
|
|
|
#define PB_CML_FAULT_PACKET_ERROR BIT(5)
|
|
|
|
#define PB_CML_FAULT_INVALID_DATA BIT(6)
|
|
|
|
#define PB_CML_FAULT_INVALID_COMMAND BIT(7)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
|
|
|
enum pmbus_sensor_classes {
|
|
|
|
PSC_VOLTAGE_IN = 0,
|
|
|
|
PSC_VOLTAGE_OUT,
|
|
|
|
PSC_CURRENT_IN,
|
|
|
|
PSC_CURRENT_OUT,
|
|
|
|
PSC_POWER,
|
|
|
|
PSC_TEMPERATURE,
|
|
|
|
PSC_FAN,
|
hwmon: (pmbus) Add fan control support
Expose fanX_target, pwmX and pwmX_enable hwmon sysfs attributes.
Fans in a PMBus device are driven by the configuration of two registers,
FAN_CONFIG_x_y and FAN_COMMAND_x: FAN_CONFIG_x_y dictates how the fan
and the tacho operate (if installed), while FAN_COMMAND_x sets the
desired fan rate. The unit of FAN_COMMAND_x is dependent on the
operational fan mode, RPM or PWM percent duty, as determined by the
corresponding configuration in FAN_CONFIG_x_y.
The mapping of fanX_target, pwmX and pwmX_enable onto FAN_CONFIG_x_y and
FAN_COMMAND_x is implemented with the addition of virtual registers to
facilitate the necessary side-effects of each access:
1. PMBUS_VIRT_FAN_TARGET_x
2. PMBUS_VIRT_PWM_x
3. PMBUS_VIRT_PWM_ENABLE_x
Some complexity arises with the fanX_target and pwmX attributes both mapping
onto FAN_COMMAND_x: There is no general mapping between PWM percent duty and
RPM, so we can't display values in either attribute in terms of the other
(which in my mind is the intuitive, if impossible, behaviour). This problem
also affects the pwmX_enable attribute which allows userspace to switch between
full speed, manual PWM and a number of automatic control modes, possibly
including a switch to RPM behaviour (e.g. automatically adjusting PWM duty to
reach a RPM target, the behaviour of fanX_target).
The next most intuitive behaviour is for fanX_target and pwmX to simply be
independent, to retain their most recently set value even if that value is not
active on the hardware (due to switching to the alternative control mode). This
property of retaining the value independent of the hardware state has useful
results for both userspace and the kernel: Userspace always sees a sensible
value in the attribute (the last thing it was set to, as opposed to 0 or
receiving an error on read), and the kernel can use the attributes as a value
cache. This latter point eases the implementation of pwmX_enable, which can
look up the associated pmbus_sensor object, take its cached value and apply it
to hardware on changing control mode. This ensures we will not arbitrarily set
a PWM value as an RPM value or vice versa, and we can assume that the RPM or
PWM value set was sensible at least at some point in the past.
Finally, the DIRECT mode coefficients of some controllers is different between
RPM and PWM percent duty control modes, so PSC_PWM is introduced to capture the
necessary coefficients. As pmbus core had no PWM support previously PSC_FAN
continues to be used to capture the RPM DIRECT coefficients, but in order to
avoid falsely applying RPM scaling to PWM values I have introduced the
PMBUS_HAVE_PWM12 and PMB_BUS_HAVE_PWM34 feature bits. These feature bits allow
drivers to explicitly declare PWM support in order to have the attributes
exposed.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2017-11-20 07:42:03 +03:00
|
|
|
PSC_PWM,
|
2011-01-27 07:09:02 +03:00
|
|
|
PSC_NUM_CLASSES /* Number of power sensor classes */
|
|
|
|
};
|
|
|
|
|
|
|
|
#define PMBUS_PAGES 32 /* Per PMBus specification */
|
|
|
|
|
|
|
|
/* Functionality bit mask */
|
2015-08-18 02:17:24 +03:00
|
|
|
#define PMBUS_HAVE_VIN BIT(0)
|
|
|
|
#define PMBUS_HAVE_VCAP BIT(1)
|
|
|
|
#define PMBUS_HAVE_VOUT BIT(2)
|
|
|
|
#define PMBUS_HAVE_IIN BIT(3)
|
|
|
|
#define PMBUS_HAVE_IOUT BIT(4)
|
|
|
|
#define PMBUS_HAVE_PIN BIT(5)
|
|
|
|
#define PMBUS_HAVE_POUT BIT(6)
|
|
|
|
#define PMBUS_HAVE_FAN12 BIT(7)
|
|
|
|
#define PMBUS_HAVE_FAN34 BIT(8)
|
|
|
|
#define PMBUS_HAVE_TEMP BIT(9)
|
|
|
|
#define PMBUS_HAVE_TEMP2 BIT(10)
|
|
|
|
#define PMBUS_HAVE_TEMP3 BIT(11)
|
|
|
|
#define PMBUS_HAVE_STATUS_VOUT BIT(12)
|
|
|
|
#define PMBUS_HAVE_STATUS_IOUT BIT(13)
|
|
|
|
#define PMBUS_HAVE_STATUS_INPUT BIT(14)
|
|
|
|
#define PMBUS_HAVE_STATUS_TEMP BIT(15)
|
|
|
|
#define PMBUS_HAVE_STATUS_FAN12 BIT(16)
|
|
|
|
#define PMBUS_HAVE_STATUS_FAN34 BIT(17)
|
|
|
|
#define PMBUS_HAVE_VMON BIT(18)
|
|
|
|
#define PMBUS_HAVE_STATUS_VMON BIT(19)
|
hwmon: (pmbus) Add fan control support
Expose fanX_target, pwmX and pwmX_enable hwmon sysfs attributes.
Fans in a PMBus device are driven by the configuration of two registers,
FAN_CONFIG_x_y and FAN_COMMAND_x: FAN_CONFIG_x_y dictates how the fan
and the tacho operate (if installed), while FAN_COMMAND_x sets the
desired fan rate. The unit of FAN_COMMAND_x is dependent on the
operational fan mode, RPM or PWM percent duty, as determined by the
corresponding configuration in FAN_CONFIG_x_y.
The mapping of fanX_target, pwmX and pwmX_enable onto FAN_CONFIG_x_y and
FAN_COMMAND_x is implemented with the addition of virtual registers to
facilitate the necessary side-effects of each access:
1. PMBUS_VIRT_FAN_TARGET_x
2. PMBUS_VIRT_PWM_x
3. PMBUS_VIRT_PWM_ENABLE_x
Some complexity arises with the fanX_target and pwmX attributes both mapping
onto FAN_COMMAND_x: There is no general mapping between PWM percent duty and
RPM, so we can't display values in either attribute in terms of the other
(which in my mind is the intuitive, if impossible, behaviour). This problem
also affects the pwmX_enable attribute which allows userspace to switch between
full speed, manual PWM and a number of automatic control modes, possibly
including a switch to RPM behaviour (e.g. automatically adjusting PWM duty to
reach a RPM target, the behaviour of fanX_target).
The next most intuitive behaviour is for fanX_target and pwmX to simply be
independent, to retain their most recently set value even if that value is not
active on the hardware (due to switching to the alternative control mode). This
property of retaining the value independent of the hardware state has useful
results for both userspace and the kernel: Userspace always sees a sensible
value in the attribute (the last thing it was set to, as opposed to 0 or
receiving an error on read), and the kernel can use the attributes as a value
cache. This latter point eases the implementation of pwmX_enable, which can
look up the associated pmbus_sensor object, take its cached value and apply it
to hardware on changing control mode. This ensures we will not arbitrarily set
a PWM value as an RPM value or vice versa, and we can assume that the RPM or
PWM value set was sensible at least at some point in the past.
Finally, the DIRECT mode coefficients of some controllers is different between
RPM and PWM percent duty control modes, so PSC_PWM is introduced to capture the
necessary coefficients. As pmbus core had no PWM support previously PSC_FAN
continues to be used to capture the RPM DIRECT coefficients, but in order to
avoid falsely applying RPM scaling to PWM values I have introduced the
PMBUS_HAVE_PWM12 and PMB_BUS_HAVE_PWM34 feature bits. These feature bits allow
drivers to explicitly declare PWM support in order to have the attributes
exposed.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2017-11-20 07:42:03 +03:00
|
|
|
#define PMBUS_HAVE_PWM12 BIT(20)
|
|
|
|
#define PMBUS_HAVE_PWM34 BIT(21)
|
2019-04-15 00:58:18 +03:00
|
|
|
#define PMBUS_HAVE_SAMPLES BIT(22)
|
2011-01-27 07:09:02 +03:00
|
|
|
|
2017-11-20 07:42:05 +03:00
|
|
|
#define PMBUS_PAGE_VIRTUAL BIT(31)
|
|
|
|
|
2011-06-25 22:21:49 +04:00
|
|
|
enum pmbus_data_format { linear = 0, direct, vid };
|
2017-08-29 23:06:21 +03:00
|
|
|
enum vrm_version { vr11 = 0, vr12, vr13 };
|
2011-06-25 22:21:49 +04:00
|
|
|
|
2011-01-27 07:09:02 +03:00
|
|
|
struct pmbus_driver_info {
|
|
|
|
int pages; /* Total number of pages */
|
2011-06-25 22:21:49 +04:00
|
|
|
enum pmbus_data_format format[PSC_NUM_CLASSES];
|
2015-07-20 19:47:33 +03:00
|
|
|
enum vrm_version vrm_version;
|
2011-01-27 07:09:02 +03:00
|
|
|
/*
|
|
|
|
* Support one set of coefficients for each sensor type
|
|
|
|
* Used for chips providing data in direct mode.
|
|
|
|
*/
|
|
|
|
int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */
|
|
|
|
int b[PSC_NUM_CLASSES]; /* offset */
|
|
|
|
int R[PSC_NUM_CLASSES]; /* exponent */
|
|
|
|
|
|
|
|
u32 func[PMBUS_PAGES]; /* Functionality, per page */
|
|
|
|
/*
|
2011-03-09 10:00:10 +03:00
|
|
|
* The following functions map manufacturing specific register values
|
|
|
|
* to PMBus standard register values. Specify only if mapping is
|
|
|
|
* necessary.
|
2011-08-26 19:01:51 +04:00
|
|
|
* Functions return the register value (read) or zero (write) if
|
|
|
|
* successful. A return value of -ENODATA indicates that there is no
|
|
|
|
* manufacturer specific register, but that a standard PMBus register
|
|
|
|
* may exist. Any other negative return value indicates that the
|
|
|
|
* register does not exist, and that no attempt should be made to read
|
|
|
|
* the standard register.
|
2011-01-27 07:09:02 +03:00
|
|
|
*/
|
2011-03-09 10:00:10 +03:00
|
|
|
int (*read_byte_data)(struct i2c_client *client, int page, int reg);
|
2011-07-08 21:41:24 +04:00
|
|
|
int (*read_word_data)(struct i2c_client *client, int page, int reg);
|
|
|
|
int (*write_word_data)(struct i2c_client *client, int page, int reg,
|
|
|
|
u16 word);
|
2011-07-30 09:08:07 +04:00
|
|
|
int (*write_byte)(struct i2c_client *client, int page, u8 value);
|
2011-01-27 07:09:02 +03:00
|
|
|
/*
|
|
|
|
* The identify function determines supported PMBus functionality.
|
|
|
|
* This function is only necessary if a chip driver supports multiple
|
|
|
|
* chips, and the chip functionality is not pre-determined.
|
|
|
|
*/
|
|
|
|
int (*identify)(struct i2c_client *client,
|
|
|
|
struct pmbus_driver_info *info);
|
2014-10-15 22:55:09 +04:00
|
|
|
|
|
|
|
/* Regulator functionality, if supported by this chip driver. */
|
|
|
|
int num_regulators;
|
|
|
|
const struct regulator_desc *reg_desc;
|
2019-04-16 00:44:05 +03:00
|
|
|
|
|
|
|
/* custom attributes */
|
|
|
|
const struct attribute_group **groups;
|
2011-01-27 07:09:02 +03:00
|
|
|
};
|
|
|
|
|
2014-10-15 22:55:09 +04:00
|
|
|
/* Regulator ops */
|
|
|
|
|
2015-07-10 08:00:08 +03:00
|
|
|
extern const struct regulator_ops pmbus_regulator_ops;
|
2014-10-15 22:55:09 +04:00
|
|
|
|
|
|
|
/* Macro for filling in array of struct regulator_desc */
|
|
|
|
#define PMBUS_REGULATOR(_name, _id) \
|
|
|
|
[_id] = { \
|
|
|
|
.name = (_name # _id), \
|
|
|
|
.id = (_id), \
|
|
|
|
.of_match = of_match_ptr(_name # _id), \
|
|
|
|
.regulators_node = of_match_ptr("regulators"), \
|
|
|
|
.ops = &pmbus_regulator_ops, \
|
2015-07-10 07:59:13 +03:00
|
|
|
.type = REGULATOR_VOLTAGE, \
|
2014-10-15 22:55:09 +04:00
|
|
|
.owner = THIS_MODULE, \
|
|
|
|
}
|
|
|
|
|
2011-01-27 07:09:02 +03:00
|
|
|
/* Function declarations */
|
|
|
|
|
2013-01-27 03:15:37 +04:00
|
|
|
void pmbus_clear_cache(struct i2c_client *client);
|
2017-10-27 19:55:05 +03:00
|
|
|
int pmbus_set_page(struct i2c_client *client, int page);
|
|
|
|
int pmbus_read_word_data(struct i2c_client *client, int page, u8 reg);
|
|
|
|
int pmbus_write_word_data(struct i2c_client *client, int page, u8 reg, u16 word);
|
2011-07-09 18:41:01 +04:00
|
|
|
int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
|
2011-07-08 21:43:57 +04:00
|
|
|
int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
|
2014-10-15 22:55:08 +04:00
|
|
|
int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg,
|
|
|
|
u8 value);
|
|
|
|
int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
|
|
|
|
u8 mask, u8 value);
|
2011-01-27 07:09:02 +03:00
|
|
|
void pmbus_clear_faults(struct i2c_client *client);
|
|
|
|
bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
|
|
|
|
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
|
|
|
|
int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
|
|
|
|
struct pmbus_driver_info *info);
|
2012-02-22 20:56:44 +04:00
|
|
|
int pmbus_do_remove(struct i2c_client *client);
|
2011-01-27 07:09:02 +03:00
|
|
|
const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
|
|
|
|
*client);
|
hwmon: (pmbus) Add fan control support
Expose fanX_target, pwmX and pwmX_enable hwmon sysfs attributes.
Fans in a PMBus device are driven by the configuration of two registers,
FAN_CONFIG_x_y and FAN_COMMAND_x: FAN_CONFIG_x_y dictates how the fan
and the tacho operate (if installed), while FAN_COMMAND_x sets the
desired fan rate. The unit of FAN_COMMAND_x is dependent on the
operational fan mode, RPM or PWM percent duty, as determined by the
corresponding configuration in FAN_CONFIG_x_y.
The mapping of fanX_target, pwmX and pwmX_enable onto FAN_CONFIG_x_y and
FAN_COMMAND_x is implemented with the addition of virtual registers to
facilitate the necessary side-effects of each access:
1. PMBUS_VIRT_FAN_TARGET_x
2. PMBUS_VIRT_PWM_x
3. PMBUS_VIRT_PWM_ENABLE_x
Some complexity arises with the fanX_target and pwmX attributes both mapping
onto FAN_COMMAND_x: There is no general mapping between PWM percent duty and
RPM, so we can't display values in either attribute in terms of the other
(which in my mind is the intuitive, if impossible, behaviour). This problem
also affects the pwmX_enable attribute which allows userspace to switch between
full speed, manual PWM and a number of automatic control modes, possibly
including a switch to RPM behaviour (e.g. automatically adjusting PWM duty to
reach a RPM target, the behaviour of fanX_target).
The next most intuitive behaviour is for fanX_target and pwmX to simply be
independent, to retain their most recently set value even if that value is not
active on the hardware (due to switching to the alternative control mode). This
property of retaining the value independent of the hardware state has useful
results for both userspace and the kernel: Userspace always sees a sensible
value in the attribute (the last thing it was set to, as opposed to 0 or
receiving an error on read), and the kernel can use the attributes as a value
cache. This latter point eases the implementation of pwmX_enable, which can
look up the associated pmbus_sensor object, take its cached value and apply it
to hardware on changing control mode. This ensures we will not arbitrarily set
a PWM value as an RPM value or vice versa, and we can assume that the RPM or
PWM value set was sensible at least at some point in the past.
Finally, the DIRECT mode coefficients of some controllers is different between
RPM and PWM percent duty control modes, so PSC_PWM is introduced to capture the
necessary coefficients. As pmbus core had no PWM support previously PSC_FAN
continues to be used to capture the RPM DIRECT coefficients, but in order to
avoid falsely applying RPM scaling to PWM values I have introduced the
PMBUS_HAVE_PWM12 and PMB_BUS_HAVE_PWM34 feature bits. These feature bits allow
drivers to explicitly declare PWM support in order to have the attributes
exposed.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2017-11-20 07:42:03 +03:00
|
|
|
int pmbus_get_fan_rate_device(struct i2c_client *client, int page, int id,
|
|
|
|
enum pmbus_fan_mode mode);
|
|
|
|
int pmbus_get_fan_rate_cached(struct i2c_client *client, int page, int id,
|
|
|
|
enum pmbus_fan_mode mode);
|
|
|
|
int pmbus_update_fan(struct i2c_client *client, int page, int id,
|
|
|
|
u8 config, u8 mask, u16 command);
|
2017-12-12 00:32:49 +03:00
|
|
|
struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client);
|
|
|
|
|
2011-01-27 07:09:02 +03:00
|
|
|
#endif /* PMBUS_H */
|