4acb3fe902
* Update emulators and cores. * Improve logging in some scripts.
2732 lines
85 KiB
Diff
2732 lines
85 KiB
Diff
diff -rupN linux-6.1.2.orig/Documentation/hwmon/aquacomputer_d5next.rst linux-6.1.2/Documentation/hwmon/aquacomputer_d5next.rst
|
|
--- linux-6.1.2.orig/Documentation/hwmon/aquacomputer_d5next.rst 2022-12-31 16:12:05.774603120 -0500
|
|
+++ linux-6.1.2/Documentation/hwmon/aquacomputer_d5next.rst 2022-12-31 16:19:55.381168081 -0500
|
|
@@ -39,7 +39,7 @@ current.
|
|
|
|
The Quadro exposes four physical and sixteen virtual temperature sensors, a flow
|
|
sensor and four PWM controllable fans, along with their speed (in RPM), power,
|
|
-voltage and current.
|
|
+voltage and current. Flow sensor pulses are also available.
|
|
|
|
The Farbwerk and Farbwerk 360 expose four temperature sensors. Additionally,
|
|
sixteen virtual temperature sensors of the Farbwerk 360 are exposed.
|
|
@@ -62,7 +62,9 @@ Sysfs entries
|
|
|
|
================ ==============================================================
|
|
temp[1-20]_input Physical/virtual temperature sensors (in millidegrees Celsius)
|
|
+temp[1-4]_offset Temperature sensor correction offset (in millidegrees Celsius)
|
|
fan[1-8]_input Pump/fan speed (in RPM) / Flow speed (in dL/h)
|
|
+fan5_pulses Quadro flow sensor pulses
|
|
power[1-8]_input Pump/fan power (in micro Watts)
|
|
in[0-7]_input Pump/fan voltage (in milli Volts)
|
|
curr[1-8]_input Pump/fan current (in milli Amperes)
|
|
diff -rupN linux-6.1.2.orig/Documentation/hwmon/index.rst linux-6.1.2/Documentation/hwmon/index.rst
|
|
--- linux-6.1.2.orig/Documentation/hwmon/index.rst 2022-12-31 16:12:05.774603120 -0500
|
|
+++ linux-6.1.2/Documentation/hwmon/index.rst 2022-12-31 16:19:53.949181008 -0500
|
|
@@ -160,6 +160,7 @@ Hardware Monitoring Kernel Drivers
|
|
nzxt-kraken2
|
|
nzxt-smart2
|
|
occ
|
|
+ oxp-sensors
|
|
pc87360
|
|
pc87427
|
|
pcf8591
|
|
@@ -187,6 +188,7 @@ Hardware Monitoring Kernel Drivers
|
|
sis5595
|
|
sl28cpld
|
|
smm665
|
|
+ smpro-hwmon
|
|
smsc47b397
|
|
smsc47m192
|
|
smsc47m1
|
|
diff -rupN linux-6.1.2.orig/Documentation/hwmon/oxp-sensors.rst linux-6.1.2/Documentation/hwmon/oxp-sensors.rst
|
|
--- linux-6.1.2.orig/Documentation/hwmon/oxp-sensors.rst 1969-12-31 19:00:00.000000000 -0500
|
|
+++ linux-6.1.2/Documentation/hwmon/oxp-sensors.rst 2022-12-31 16:19:55.381168081 -0500
|
|
@@ -0,0 +1,44 @@
|
|
+.. SPDX-License-Identifier: GPL-2.0-or-later
|
|
+
|
|
+Kernel driver oxp-sensors
|
|
+=========================
|
|
+
|
|
+Author:
|
|
+ - Joaquín Ignacio Aramendía <samsagax@gmail.com>
|
|
+
|
|
+Description:
|
|
+------------
|
|
+
|
|
+One X Player devices from One Netbook provide fan readings and fan control
|
|
+through its Embedded Controller.
|
|
+
|
|
+Currently only supports AMD boards from the One X Player and AOK ZOE lineup.
|
|
+Intel boards could be supported if we could figure out the EC registers and
|
|
+values to write to since the EC layout and model is different.
|
|
+
|
|
+Supported devices
|
|
+-----------------
|
|
+
|
|
+Currently the driver supports the following handhelds:
|
|
+
|
|
+ - AOK ZOE A1
|
|
+ - OneXPlayer AMD
|
|
+ - OneXPlayer mini AMD
|
|
+ - OneXPlayer mini AMD PRO
|
|
+
|
|
+Sysfs entries
|
|
+-------------
|
|
+
|
|
+The following attributes are supported:
|
|
+
|
|
+fan1_input
|
|
+ Read Only. Reads current fan RMP.
|
|
+
|
|
+pwm1_enable
|
|
+ Read Write. Enable manual fan control. Write "1" to set to manual, write "0"
|
|
+ to let the EC control de fan speed. Read this attribute to see current status.
|
|
+
|
|
+pwm1
|
|
+ Read Write. Read this attribute to see current duty cycle in the range [0-255].
|
|
+ When pwm1_enable is set to "1" (manual) write any value in the range [0-255]
|
|
+ to set fan speed.
|
|
diff -rupN linux-6.1.2.orig/Documentation/hwmon/smpro-hwmon.rst linux-6.1.2/Documentation/hwmon/smpro-hwmon.rst
|
|
--- linux-6.1.2.orig/Documentation/hwmon/smpro-hwmon.rst 1969-12-31 19:00:00.000000000 -0500
|
|
+++ linux-6.1.2/Documentation/hwmon/smpro-hwmon.rst 2022-12-31 16:19:53.945181044 -0500
|
|
@@ -0,0 +1,102 @@
|
|
+.. SPDX-License-Identifier: GPL-2.0-only
|
|
+
|
|
+Kernel driver Ampere(R)'s Altra(R) SMpro hwmon
|
|
+==============================================
|
|
+
|
|
+Supported chips:
|
|
+
|
|
+ * Ampere(R) Altra(R)
|
|
+
|
|
+ Prefix: ``smpro``
|
|
+
|
|
+ Reference: `Altra SoC BMC Interface Specification`
|
|
+
|
|
+Author: Thu Nguyen <thu@os.amperecomputing.com>
|
|
+
|
|
+Description
|
|
+-----------
|
|
+The smpro-hwmon driver supports hardware monitoring for Ampere(R) Altra(R)
|
|
+SoCs based on the SMpro co-processor (SMpro). The following sensor metrics
|
|
+are supported by the driver:
|
|
+
|
|
+ * temperature
|
|
+ * voltage
|
|
+ * current
|
|
+ * power
|
|
+
|
|
+The interface provides the registers to query the various sensors and
|
|
+their values which are then exported to userspace by this driver.
|
|
+
|
|
+Usage Notes
|
|
+-----------
|
|
+
|
|
+The driver creates at least two sysfs files for each sensor.
|
|
+
|
|
+* ``<sensor_type><idx>_label`` reports the sensor label.
|
|
+* ``<sensor_type><idx>_input`` returns the sensor value.
|
|
+
|
|
+The sysfs files are allocated in the SMpro rootfs folder, with one root
|
|
+directory for each instance.
|
|
+
|
|
+When the SoC is turned off, the driver will fail to read registers and
|
|
+return ``-ENXIO``.
|
|
+
|
|
+Sysfs entries
|
|
+-------------
|
|
+
|
|
+The following sysfs files are supported:
|
|
+
|
|
+* Ampere(R) Altra(R):
|
|
+
|
|
+ ============ ============= ====== ===============================================
|
|
+ Name Unit Perm Description
|
|
+ ============ ============= ====== ===============================================
|
|
+ temp1_input millicelsius RO SoC temperature
|
|
+ temp2_input millicelsius RO Max temperature reported among SoC VRDs
|
|
+ temp2_crit millicelsius RO SoC VRD HOT Threshold temperature
|
|
+ temp3_input millicelsius RO Max temperature reported among DIMM VRDs
|
|
+ temp4_input millicelsius RO Max temperature reported among Core VRDs
|
|
+ temp5_input millicelsius RO Temperature of DIMM0 on CH0
|
|
+ temp5_crit millicelsius RO MEM HOT Threshold for all DIMMs
|
|
+ temp6_input millicelsius RO Temperature of DIMM0 on CH1
|
|
+ temp6_crit millicelsius RO MEM HOT Threshold for all DIMMs
|
|
+ temp7_input millicelsius RO Temperature of DIMM0 on CH2
|
|
+ temp7_crit millicelsius RO MEM HOT Threshold for all DIMMs
|
|
+ temp8_input millicelsius RO Temperature of DIMM0 on CH3
|
|
+ temp8_crit millicelsius RO MEM HOT Threshold for all DIMMs
|
|
+ temp9_input millicelsius RO Temperature of DIMM0 on CH4
|
|
+ temp9_crit millicelsius RO MEM HOT Threshold for all DIMMs
|
|
+ temp10_input millicelsius RO Temperature of DIMM0 on CH5
|
|
+ temp10_crit millicelsius RO MEM HOT Threshold for all DIMMs
|
|
+ temp11_input millicelsius RO Temperature of DIMM0 on CH6
|
|
+ temp11_crit millicelsius RO MEM HOT Threshold for all DIMMs
|
|
+ temp12_input millicelsius RO Temperature of DIMM0 on CH7
|
|
+ temp12_crit millicelsius RO MEM HOT Threshold for all DIMMs
|
|
+ temp13_input millicelsius RO Max temperature reported among RCA VRDs
|
|
+ in0_input millivolts RO Core voltage
|
|
+ in1_input millivolts RO SoC voltage
|
|
+ in2_input millivolts RO DIMM VRD1 voltage
|
|
+ in3_input millivolts RO DIMM VRD2 voltage
|
|
+ in4_input millivolts RO RCA VRD voltage
|
|
+ cur1_input milliamperes RO Core VRD current
|
|
+ cur2_input milliamperes RO SoC VRD current
|
|
+ cur3_input milliamperes RO DIMM VRD1 current
|
|
+ cur4_input milliamperes RO DIMM VRD2 current
|
|
+ cur5_input milliamperes RO RCA VRD current
|
|
+ power1_input microwatts RO Core VRD power
|
|
+ power2_input microwatts RO SoC VRD power
|
|
+ power3_input microwatts RO DIMM VRD1 power
|
|
+ power4_input microwatts RO DIMM VRD2 power
|
|
+ power5_input microwatts RO RCA VRD power
|
|
+ ============ ============= ====== ===============================================
|
|
+
|
|
+ Example::
|
|
+
|
|
+ # cat in0_input
|
|
+ 830
|
|
+ # cat temp1_input
|
|
+ 37000
|
|
+ # cat curr1_input
|
|
+ 9000
|
|
+ # cat power5_input
|
|
+ 19500000
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/adm1177.c linux-6.1.2/drivers/hwmon/adm1177.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/adm1177.c 2022-12-31 16:12:06.934585693 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/adm1177.c 2022-12-31 16:19:46.457248898 -0500
|
|
@@ -26,14 +26,12 @@
|
|
/**
|
|
* struct adm1177_state - driver instance specific data
|
|
* @client: pointer to i2c client
|
|
- * @reg: regulator info for the power supply of the device
|
|
* @r_sense_uohm: current sense resistor value
|
|
* @alert_threshold_ua: current limit for shutdown
|
|
* @vrange_high: internal voltage divider
|
|
*/
|
|
struct adm1177_state {
|
|
struct i2c_client *client;
|
|
- struct regulator *reg;
|
|
u32 r_sense_uohm;
|
|
u32 alert_threshold_ua;
|
|
bool vrange_high;
|
|
@@ -189,13 +187,6 @@ static const struct hwmon_chip_info adm1
|
|
.info = adm1177_info,
|
|
};
|
|
|
|
-static void adm1177_remove(void *data)
|
|
-{
|
|
- struct adm1177_state *st = data;
|
|
-
|
|
- regulator_disable(st->reg);
|
|
-}
|
|
-
|
|
static int adm1177_probe(struct i2c_client *client)
|
|
{
|
|
struct device *dev = &client->dev;
|
|
@@ -210,21 +201,9 @@ static int adm1177_probe(struct i2c_clie
|
|
|
|
st->client = client;
|
|
|
|
- st->reg = devm_regulator_get_optional(&client->dev, "vref");
|
|
- if (IS_ERR(st->reg)) {
|
|
- if (PTR_ERR(st->reg) == -EPROBE_DEFER)
|
|
- return -EPROBE_DEFER;
|
|
-
|
|
- st->reg = NULL;
|
|
- } else {
|
|
- ret = regulator_enable(st->reg);
|
|
- if (ret)
|
|
- return ret;
|
|
- ret = devm_add_action_or_reset(&client->dev, adm1177_remove,
|
|
- st);
|
|
- if (ret)
|
|
- return ret;
|
|
- }
|
|
+ ret = devm_regulator_get_enable_optional(&client->dev, "vref");
|
|
+ if (ret == -EPROBE_DEFER)
|
|
+ return -EPROBE_DEFER;
|
|
|
|
if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",
|
|
&st->r_sense_uohm))
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/aht10.c linux-6.1.2/drivers/hwmon/aht10.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/aht10.c 2022-12-31 16:12:06.934585693 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/aht10.c 2022-12-31 16:19:46.453248935 -0500
|
|
@@ -289,8 +289,7 @@ static const struct hwmon_chip_info aht1
|
|
.info = aht10_info,
|
|
};
|
|
|
|
-static int aht10_probe(struct i2c_client *client,
|
|
- const struct i2c_device_id *aht10_id)
|
|
+static int aht10_probe(struct i2c_client *client)
|
|
{
|
|
struct device *device = &client->dev;
|
|
struct device *hwmon_dev;
|
|
@@ -336,7 +335,7 @@ static struct i2c_driver aht10_driver =
|
|
.driver = {
|
|
.name = "aht10",
|
|
},
|
|
- .probe = aht10_probe,
|
|
+ .probe_new = aht10_probe,
|
|
.id_table = aht10_id,
|
|
};
|
|
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/aquacomputer_d5next.c linux-6.1.2/drivers/hwmon/aquacomputer_d5next.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/aquacomputer_d5next.c 2022-12-31 16:12:06.934585693 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/aquacomputer_d5next.c 2022-12-31 16:19:55.385168045 -0500
|
|
@@ -59,7 +59,7 @@ static u8 secondary_ctrl_report[] = {
|
|
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x34, 0xC6
|
|
};
|
|
|
|
-/* Register offsets for all Aquacomputer devices */
|
|
+/* Sensor sizes and offsets for all Aquacomputer devices */
|
|
#define AQC_TEMP_SENSOR_SIZE 0x02
|
|
#define AQC_TEMP_SENSOR_DISCONNECTED 0x7FFF
|
|
#define AQC_FAN_PERCENT_OFFSET 0x00
|
|
@@ -68,62 +68,81 @@ static u8 secondary_ctrl_report[] = {
|
|
#define AQC_FAN_POWER_OFFSET 0x06
|
|
#define AQC_FAN_SPEED_OFFSET 0x08
|
|
|
|
-/* Register offsets for the D5 Next pump */
|
|
-#define D5NEXT_POWER_CYCLES 0x18
|
|
-#define D5NEXT_COOLANT_TEMP 0x57
|
|
+/* Specs of the D5 Next pump */
|
|
#define D5NEXT_NUM_FANS 2
|
|
#define D5NEXT_NUM_SENSORS 1
|
|
#define D5NEXT_NUM_VIRTUAL_SENSORS 8
|
|
-#define D5NEXT_VIRTUAL_SENSORS_START 0x3f
|
|
+#define D5NEXT_CTRL_REPORT_SIZE 0x329
|
|
+
|
|
+/* Sensor report offsets for the D5 Next pump */
|
|
+#define D5NEXT_POWER_CYCLES 0x18
|
|
+#define D5NEXT_COOLANT_TEMP 0x57
|
|
#define D5NEXT_PUMP_OFFSET 0x6c
|
|
#define D5NEXT_FAN_OFFSET 0x5f
|
|
#define D5NEXT_5V_VOLTAGE 0x39
|
|
#define D5NEXT_12V_VOLTAGE 0x37
|
|
-#define D5NEXT_CTRL_REPORT_SIZE 0x329
|
|
+#define D5NEXT_VIRTUAL_SENSORS_START 0x3f
|
|
static u8 d5next_sensor_fan_offsets[] = { D5NEXT_PUMP_OFFSET, D5NEXT_FAN_OFFSET };
|
|
|
|
-/* Pump and fan speed registers in D5 Next control report (from 0-100%) */
|
|
-static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 };
|
|
+/* Control report offsets for the D5 Next pump */
|
|
+#define D5NEXT_TEMP_CTRL_OFFSET 0x2D /* Temperature sensor offsets location */
|
|
+static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 }; /* Pump and fan speed (from 0-100%) */
|
|
|
|
-/* Register offsets for the Farbwerk RGB controller */
|
|
+/* Spec and sensor report offset for the Farbwerk RGB controller */
|
|
#define FARBWERK_NUM_SENSORS 4
|
|
#define FARBWERK_SENSOR_START 0x2f
|
|
|
|
-/* Register offsets for the Farbwerk 360 RGB controller */
|
|
+/* Specs of the Farbwerk 360 RGB controller */
|
|
#define FARBWERK360_NUM_SENSORS 4
|
|
-#define FARBWERK360_SENSOR_START 0x32
|
|
#define FARBWERK360_NUM_VIRTUAL_SENSORS 16
|
|
+#define FARBWERK360_CTRL_REPORT_SIZE 0x682
|
|
+
|
|
+/* Sensor report offsets for the Farbwerk 360 */
|
|
+#define FARBWERK360_SENSOR_START 0x32
|
|
#define FARBWERK360_VIRTUAL_SENSORS_START 0x3a
|
|
|
|
-/* Register offsets for the Octo fan controller */
|
|
-#define OCTO_POWER_CYCLES 0x18
|
|
+/* Control report offsets for the Farbwerk 360 */
|
|
+#define FARBWERK360_TEMP_CTRL_OFFSET 0x8
|
|
+
|
|
+/* Specs of the Octo fan controller */
|
|
#define OCTO_NUM_FANS 8
|
|
#define OCTO_NUM_SENSORS 4
|
|
-#define OCTO_SENSOR_START 0x3D
|
|
#define OCTO_NUM_VIRTUAL_SENSORS 16
|
|
-#define OCTO_VIRTUAL_SENSORS_START 0x45
|
|
#define OCTO_CTRL_REPORT_SIZE 0x65F
|
|
+
|
|
+/* Sensor report offsets for the Octo */
|
|
+#define OCTO_POWER_CYCLES 0x18
|
|
+#define OCTO_SENSOR_START 0x3D
|
|
+#define OCTO_VIRTUAL_SENSORS_START 0x45
|
|
static u8 octo_sensor_fan_offsets[] = { 0x7D, 0x8A, 0x97, 0xA4, 0xB1, 0xBE, 0xCB, 0xD8 };
|
|
|
|
-/* Fan speed registers in Octo control report (from 0-100%) */
|
|
+/* Control report offsets for the Octo */
|
|
+#define OCTO_TEMP_CTRL_OFFSET 0xA
|
|
+/* Fan speed offsets (0-100%) */
|
|
static u16 octo_ctrl_fan_offsets[] = { 0x5B, 0xB0, 0x105, 0x15A, 0x1AF, 0x204, 0x259, 0x2AE };
|
|
|
|
-/* Register offsets for the Quadro fan controller */
|
|
-#define QUADRO_POWER_CYCLES 0x18
|
|
+/* Specs of Quadro fan controller */
|
|
#define QUADRO_NUM_FANS 4
|
|
#define QUADRO_NUM_SENSORS 4
|
|
-#define QUADRO_SENSOR_START 0x34
|
|
#define QUADRO_NUM_VIRTUAL_SENSORS 16
|
|
-#define QUADRO_VIRTUAL_SENSORS_START 0x3c
|
|
#define QUADRO_CTRL_REPORT_SIZE 0x3c1
|
|
+
|
|
+/* Sensor report offsets for the Quadro */
|
|
+#define QUADRO_POWER_CYCLES 0x18
|
|
+#define QUADRO_SENSOR_START 0x34
|
|
+#define QUADRO_VIRTUAL_SENSORS_START 0x3c
|
|
#define QUADRO_FLOW_SENSOR_OFFSET 0x6e
|
|
static u8 quadro_sensor_fan_offsets[] = { 0x70, 0x7D, 0x8A, 0x97 };
|
|
|
|
-/* Fan speed registers in Quadro control report (from 0-100%) */
|
|
-static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 };
|
|
+/* Control report offsets for the Quadro */
|
|
+#define QUADRO_TEMP_CTRL_OFFSET 0xA
|
|
+#define QUADRO_FLOW_PULSES_CTRL_OFFSET 0x6
|
|
+static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 }; /* Fan speed offsets (0-100%) */
|
|
|
|
-/* Register offsets for the High Flow Next */
|
|
+/* Specs of High Flow Next flow sensor */
|
|
#define HIGHFLOWNEXT_NUM_SENSORS 2
|
|
+
|
|
+/* Sensor report offsets for the High Flow Next */
|
|
#define HIGHFLOWNEXT_SENSOR_START 85
|
|
#define HIGHFLOWNEXT_FLOW 81
|
|
#define HIGHFLOWNEXT_WATER_QUALITY 89
|
|
@@ -282,8 +301,10 @@ struct aqc_data {
|
|
int temp_sensor_start_offset;
|
|
int num_virtual_temp_sensors;
|
|
int virtual_temp_sensor_start_offset;
|
|
+ u16 temp_ctrl_offset;
|
|
u16 power_cycle_count_offset;
|
|
u8 flow_sensor_offset;
|
|
+ u8 flow_pulses_ctrl_offset;
|
|
|
|
/* General info, same across all devices */
|
|
u32 serial_number[2];
|
|
@@ -365,8 +386,8 @@ static int aqc_send_ctrl_data(struct aqc
|
|
return ret;
|
|
}
|
|
|
|
-/* Refreshes the control buffer and returns value at offset */
|
|
-static int aqc_get_ctrl_val(struct aqc_data *priv, int offset)
|
|
+/* Refreshes the control buffer and stores value at offset in val */
|
|
+static int aqc_get_ctrl_val(struct aqc_data *priv, int offset, long *val)
|
|
{
|
|
int ret;
|
|
|
|
@@ -376,7 +397,7 @@ static int aqc_get_ctrl_val(struct aqc_d
|
|
if (ret < 0)
|
|
goto unlock_and_return;
|
|
|
|
- ret = get_unaligned_be16(priv->buffer + offset);
|
|
+ *val = (s16)get_unaligned_be16(priv->buffer + offset);
|
|
|
|
unlock_and_return:
|
|
mutex_unlock(&priv->mutex);
|
|
@@ -393,7 +414,7 @@ static int aqc_set_ctrl_val(struct aqc_d
|
|
if (ret < 0)
|
|
goto unlock_and_return;
|
|
|
|
- put_unaligned_be16((u16)val, priv->buffer + offset);
|
|
+ put_unaligned_be16((s16)val, priv->buffer + offset);
|
|
|
|
ret = aqc_send_ctrl_data(priv);
|
|
|
|
@@ -408,8 +429,28 @@ static umode_t aqc_is_visible(const void
|
|
|
|
switch (type) {
|
|
case hwmon_temp:
|
|
+ if (channel < priv->num_temp_sensors) {
|
|
+ switch (attr) {
|
|
+ case hwmon_temp_label:
|
|
+ case hwmon_temp_input:
|
|
+ return 0444;
|
|
+ case hwmon_temp_offset:
|
|
+ if (priv->temp_ctrl_offset != 0)
|
|
+ return 0644;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (channel < priv->num_temp_sensors + priv->num_virtual_temp_sensors)
|
|
- return 0444;
|
|
+ switch (attr) {
|
|
+ case hwmon_temp_label:
|
|
+ case hwmon_temp_input:
|
|
+ return 0444;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
break;
|
|
case hwmon_pwm:
|
|
if (priv->fan_ctrl_offsets && channel < priv->num_fans) {
|
|
@@ -422,20 +463,34 @@ static umode_t aqc_is_visible(const void
|
|
}
|
|
break;
|
|
case hwmon_fan:
|
|
- switch (priv->kind) {
|
|
- case highflownext:
|
|
- /* Special case to support flow sensor, water quality and conductivity */
|
|
- if (channel < 3)
|
|
- return 0444;
|
|
+ switch (attr) {
|
|
+ case hwmon_fan_input:
|
|
+ case hwmon_fan_label:
|
|
+ switch (priv->kind) {
|
|
+ case highflownext:
|
|
+ /* Special case to support flow sensor, water quality
|
|
+ * and conductivity
|
|
+ */
|
|
+ if (channel < 3)
|
|
+ return 0444;
|
|
+ break;
|
|
+ case quadro:
|
|
+ /* Special case to support flow sensor */
|
|
+ if (channel < priv->num_fans + 1)
|
|
+ return 0444;
|
|
+ break;
|
|
+ default:
|
|
+ if (channel < priv->num_fans)
|
|
+ return 0444;
|
|
+ break;
|
|
+ }
|
|
break;
|
|
- case quadro:
|
|
- /* Special case to support flow sensor */
|
|
- if (channel < priv->num_fans + 1)
|
|
- return 0444;
|
|
+ case hwmon_fan_pulses:
|
|
+ /* Special case for Quadro flow sensor */
|
|
+ if (priv->kind == quadro && channel == priv->num_fans)
|
|
+ return 0644;
|
|
break;
|
|
default:
|
|
- if (channel < priv->num_fans)
|
|
- return 0444;
|
|
break;
|
|
}
|
|
break;
|
|
@@ -492,20 +547,46 @@ static int aqc_read(struct device *dev,
|
|
|
|
switch (type) {
|
|
case hwmon_temp:
|
|
- if (priv->temp_input[channel] == -ENODATA)
|
|
- return -ENODATA;
|
|
+ switch (attr) {
|
|
+ case hwmon_temp_input:
|
|
+ if (priv->temp_input[channel] == -ENODATA)
|
|
+ return -ENODATA;
|
|
|
|
- *val = priv->temp_input[channel];
|
|
+ *val = priv->temp_input[channel];
|
|
+ break;
|
|
+ case hwmon_temp_offset:
|
|
+ ret =
|
|
+ aqc_get_ctrl_val(priv, priv->temp_ctrl_offset +
|
|
+ channel * AQC_TEMP_SENSOR_SIZE, val);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ *val *= 10;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
break;
|
|
case hwmon_fan:
|
|
- *val = priv->speed_input[channel];
|
|
+ switch (attr) {
|
|
+ case hwmon_fan_input:
|
|
+ *val = priv->speed_input[channel];
|
|
+ break;
|
|
+ case hwmon_fan_pulses:
|
|
+ ret = aqc_get_ctrl_val(priv, priv->flow_pulses_ctrl_offset, val);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
break;
|
|
case hwmon_power:
|
|
*val = priv->power_input[channel];
|
|
break;
|
|
case hwmon_pwm:
|
|
if (priv->fan_ctrl_offsets) {
|
|
- ret = aqc_get_ctrl_val(priv, priv->fan_ctrl_offsets[channel]);
|
|
+ ret = aqc_get_ctrl_val(priv, priv->fan_ctrl_offsets[channel], val);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
@@ -563,6 +644,33 @@ static int aqc_write(struct device *dev,
|
|
struct aqc_data *priv = dev_get_drvdata(dev);
|
|
|
|
switch (type) {
|
|
+ case hwmon_temp:
|
|
+ switch (attr) {
|
|
+ case hwmon_temp_offset:
|
|
+ /* Limit temp offset to +/- 15K as in the official software */
|
|
+ val = clamp_val(val, -15000, 15000) / 10;
|
|
+ ret =
|
|
+ aqc_set_ctrl_val(priv, priv->temp_ctrl_offset +
|
|
+ channel * AQC_TEMP_SENSOR_SIZE, val);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ break;
|
|
+ default:
|
|
+ return -EOPNOTSUPP;
|
|
+ }
|
|
+ break;
|
|
+ case hwmon_fan:
|
|
+ switch (attr) {
|
|
+ case hwmon_fan_pulses:
|
|
+ val = clamp_val(val, 10, 1000);
|
|
+ ret = aqc_set_ctrl_val(priv, priv->flow_pulses_ctrl_offset, val);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
case hwmon_pwm:
|
|
switch (attr) {
|
|
case hwmon_pwm_input:
|
|
@@ -597,10 +705,10 @@ static const struct hwmon_ops aqc_hwmon_
|
|
|
|
static const struct hwmon_channel_info *aqc_info[] = {
|
|
HWMON_CHANNEL_INFO(temp,
|
|
- HWMON_T_INPUT | HWMON_T_LABEL,
|
|
- HWMON_T_INPUT | HWMON_T_LABEL,
|
|
- HWMON_T_INPUT | HWMON_T_LABEL,
|
|
- HWMON_T_INPUT | HWMON_T_LABEL,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
|
@@ -622,7 +730,7 @@ static const struct hwmon_channel_info *
|
|
HWMON_F_INPUT | HWMON_F_LABEL,
|
|
HWMON_F_INPUT | HWMON_F_LABEL,
|
|
HWMON_F_INPUT | HWMON_F_LABEL,
|
|
- HWMON_F_INPUT | HWMON_F_LABEL,
|
|
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_PULSES,
|
|
HWMON_F_INPUT | HWMON_F_LABEL,
|
|
HWMON_F_INPUT | HWMON_F_LABEL,
|
|
HWMON_F_INPUT | HWMON_F_LABEL),
|
|
@@ -847,13 +955,17 @@ static int aqc_probe(struct hid_device *
|
|
priv->num_fans = D5NEXT_NUM_FANS;
|
|
priv->fan_sensor_offsets = d5next_sensor_fan_offsets;
|
|
priv->fan_ctrl_offsets = d5next_ctrl_fan_offsets;
|
|
+
|
|
priv->num_temp_sensors = D5NEXT_NUM_SENSORS;
|
|
priv->temp_sensor_start_offset = D5NEXT_COOLANT_TEMP;
|
|
priv->num_virtual_temp_sensors = D5NEXT_NUM_VIRTUAL_SENSORS;
|
|
priv->virtual_temp_sensor_start_offset = D5NEXT_VIRTUAL_SENSORS_START;
|
|
- priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
|
|
+ priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET;
|
|
+
|
|
priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
|
|
|
|
+ priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
|
|
+
|
|
priv->temp_label = label_d5next_temp;
|
|
priv->virtual_temp_label = label_virtual_temp_sensors;
|
|
priv->speed_label = label_d5next_speeds;
|
|
@@ -865,18 +977,24 @@ static int aqc_probe(struct hid_device *
|
|
priv->kind = farbwerk;
|
|
|
|
priv->num_fans = 0;
|
|
+
|
|
priv->num_temp_sensors = FARBWERK_NUM_SENSORS;
|
|
priv->temp_sensor_start_offset = FARBWERK_SENSOR_START;
|
|
+
|
|
priv->temp_label = label_temp_sensors;
|
|
break;
|
|
case USB_PRODUCT_ID_FARBWERK360:
|
|
priv->kind = farbwerk360;
|
|
|
|
priv->num_fans = 0;
|
|
+
|
|
priv->num_temp_sensors = FARBWERK360_NUM_SENSORS;
|
|
priv->temp_sensor_start_offset = FARBWERK360_SENSOR_START;
|
|
priv->num_virtual_temp_sensors = FARBWERK360_NUM_VIRTUAL_SENSORS;
|
|
priv->virtual_temp_sensor_start_offset = FARBWERK360_VIRTUAL_SENSORS_START;
|
|
+ priv->temp_ctrl_offset = FARBWERK360_TEMP_CTRL_OFFSET;
|
|
+
|
|
+ priv->buffer_size = FARBWERK360_CTRL_REPORT_SIZE;
|
|
|
|
priv->temp_label = label_temp_sensors;
|
|
priv->virtual_temp_label = label_virtual_temp_sensors;
|
|
@@ -887,13 +1005,17 @@ static int aqc_probe(struct hid_device *
|
|
priv->num_fans = OCTO_NUM_FANS;
|
|
priv->fan_sensor_offsets = octo_sensor_fan_offsets;
|
|
priv->fan_ctrl_offsets = octo_ctrl_fan_offsets;
|
|
+
|
|
priv->num_temp_sensors = OCTO_NUM_SENSORS;
|
|
priv->temp_sensor_start_offset = OCTO_SENSOR_START;
|
|
priv->num_virtual_temp_sensors = OCTO_NUM_VIRTUAL_SENSORS;
|
|
priv->virtual_temp_sensor_start_offset = OCTO_VIRTUAL_SENSORS_START;
|
|
- priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
|
|
+ priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET;
|
|
+
|
|
priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
|
|
|
|
+ priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
|
|
+
|
|
priv->temp_label = label_temp_sensors;
|
|
priv->virtual_temp_label = label_virtual_temp_sensors;
|
|
priv->speed_label = label_fan_speed;
|
|
@@ -907,13 +1029,18 @@ static int aqc_probe(struct hid_device *
|
|
priv->num_fans = QUADRO_NUM_FANS;
|
|
priv->fan_sensor_offsets = quadro_sensor_fan_offsets;
|
|
priv->fan_ctrl_offsets = quadro_ctrl_fan_offsets;
|
|
+
|
|
priv->num_temp_sensors = QUADRO_NUM_SENSORS;
|
|
priv->temp_sensor_start_offset = QUADRO_SENSOR_START;
|
|
priv->num_virtual_temp_sensors = QUADRO_NUM_VIRTUAL_SENSORS;
|
|
priv->virtual_temp_sensor_start_offset = QUADRO_VIRTUAL_SENSORS_START;
|
|
- priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
|
|
+ priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET;
|
|
+
|
|
priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
|
|
+
|
|
priv->flow_sensor_offset = QUADRO_FLOW_SENSOR_OFFSET;
|
|
+ priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;
|
|
+ priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
|
|
|
|
priv->temp_label = label_temp_sensors;
|
|
priv->virtual_temp_label = label_virtual_temp_sensors;
|
|
@@ -926,8 +1053,10 @@ static int aqc_probe(struct hid_device *
|
|
priv->kind = highflownext;
|
|
|
|
priv->num_fans = 0;
|
|
+
|
|
priv->num_temp_sensors = HIGHFLOWNEXT_NUM_SENSORS;
|
|
priv->temp_sensor_start_offset = HIGHFLOWNEXT_SENSOR_START;
|
|
+
|
|
priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
|
|
|
|
priv->temp_label = label_highflownext_temp_sensors;
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/atxp1.c linux-6.1.2/drivers/hwmon/atxp1.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/atxp1.c 2022-12-31 16:12:06.934585693 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/atxp1.c 2022-12-31 16:19:53.945181044 -0500
|
|
@@ -16,6 +16,7 @@
|
|
#include <linux/hwmon.h>
|
|
#include <linux/hwmon-vid.h>
|
|
#include <linux/err.h>
|
|
+#include <linux/kstrtox.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/sysfs.h>
|
|
#include <linux/slab.h>
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/coretemp.c linux-6.1.2/drivers/hwmon/coretemp.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/coretemp.c 2022-12-31 16:12:06.934585693 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/coretemp.c 2022-12-31 16:19:53.953180971 -0500
|
|
@@ -55,6 +55,8 @@ MODULE_PARM_DESC(tjmax, "TjMax value in
|
|
|
|
/*
|
|
* Per-Core Temperature Data
|
|
+ * @tjmax: The static tjmax value when tjmax cannot be retrieved from
|
|
+ * IA32_TEMPERATURE_TARGET MSR.
|
|
* @last_updated: The time when the current temperature value was updated
|
|
* earlier (in jiffies).
|
|
* @cpu_core_id: The CPU Core from which temperature values should be read
|
|
@@ -64,11 +66,9 @@ MODULE_PARM_DESC(tjmax, "TjMax value in
|
|
* @attr_size: Total number of pre-core attrs displayed in the sysfs.
|
|
* @is_pkg_data: If this is 1, the temp_data holds pkgtemp data.
|
|
* Otherwise, temp_data holds coretemp data.
|
|
- * @valid: If this is 1, the current temperature is valid.
|
|
*/
|
|
struct temp_data {
|
|
int temp;
|
|
- int ttarget;
|
|
int tjmax;
|
|
unsigned long last_updated;
|
|
unsigned int cpu;
|
|
@@ -76,7 +76,6 @@ struct temp_data {
|
|
u32 status_reg;
|
|
int attr_size;
|
|
bool is_pkg_data;
|
|
- bool valid;
|
|
struct sensor_device_attribute sd_attrs[TOTAL_ATTRS];
|
|
char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH];
|
|
struct attribute *attrs[TOTAL_ATTRS + 1];
|
|
@@ -95,85 +94,6 @@ struct platform_data {
|
|
struct device_attribute name_attr;
|
|
};
|
|
|
|
-/* Keep track of how many zone pointers we allocated in init() */
|
|
-static int max_zones __read_mostly;
|
|
-/* Array of zone pointers. Serialized by cpu hotplug lock */
|
|
-static struct platform_device **zone_devices;
|
|
-
|
|
-static ssize_t show_label(struct device *dev,
|
|
- struct device_attribute *devattr, char *buf)
|
|
-{
|
|
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
|
- struct platform_data *pdata = dev_get_drvdata(dev);
|
|
- struct temp_data *tdata = pdata->core_data[attr->index];
|
|
-
|
|
- if (tdata->is_pkg_data)
|
|
- return sprintf(buf, "Package id %u\n", pdata->pkg_id);
|
|
-
|
|
- return sprintf(buf, "Core %u\n", tdata->cpu_core_id);
|
|
-}
|
|
-
|
|
-static ssize_t show_crit_alarm(struct device *dev,
|
|
- struct device_attribute *devattr, char *buf)
|
|
-{
|
|
- u32 eax, edx;
|
|
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
|
- struct platform_data *pdata = dev_get_drvdata(dev);
|
|
- struct temp_data *tdata = pdata->core_data[attr->index];
|
|
-
|
|
- mutex_lock(&tdata->update_lock);
|
|
- rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
|
|
- mutex_unlock(&tdata->update_lock);
|
|
-
|
|
- return sprintf(buf, "%d\n", (eax >> 5) & 1);
|
|
-}
|
|
-
|
|
-static ssize_t show_tjmax(struct device *dev,
|
|
- struct device_attribute *devattr, char *buf)
|
|
-{
|
|
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
|
- struct platform_data *pdata = dev_get_drvdata(dev);
|
|
-
|
|
- return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tjmax);
|
|
-}
|
|
-
|
|
-static ssize_t show_ttarget(struct device *dev,
|
|
- struct device_attribute *devattr, char *buf)
|
|
-{
|
|
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
|
- struct platform_data *pdata = dev_get_drvdata(dev);
|
|
-
|
|
- return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget);
|
|
-}
|
|
-
|
|
-static ssize_t show_temp(struct device *dev,
|
|
- struct device_attribute *devattr, char *buf)
|
|
-{
|
|
- u32 eax, edx;
|
|
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
|
- struct platform_data *pdata = dev_get_drvdata(dev);
|
|
- struct temp_data *tdata = pdata->core_data[attr->index];
|
|
-
|
|
- mutex_lock(&tdata->update_lock);
|
|
-
|
|
- /* Check whether the time interval has elapsed */
|
|
- if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) {
|
|
- rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
|
|
- /*
|
|
- * Ignore the valid bit. In all observed cases the register
|
|
- * value is either low or zero if the valid bit is 0.
|
|
- * Return it instead of reporting an error which doesn't
|
|
- * really help at all.
|
|
- */
|
|
- tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000;
|
|
- tdata->valid = true;
|
|
- tdata->last_updated = jiffies;
|
|
- }
|
|
-
|
|
- mutex_unlock(&tdata->update_lock);
|
|
- return sprintf(buf, "%d\n", tdata->temp);
|
|
-}
|
|
-
|
|
struct tjmax_pci {
|
|
unsigned int device;
|
|
int tjmax;
|
|
@@ -340,20 +260,25 @@ static bool cpu_has_tjmax(struct cpuinfo
|
|
model != 0x36;
|
|
}
|
|
|
|
-static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
|
|
+static int get_tjmax(struct temp_data *tdata, struct device *dev)
|
|
{
|
|
+ struct cpuinfo_x86 *c = &cpu_data(tdata->cpu);
|
|
int err;
|
|
u32 eax, edx;
|
|
u32 val;
|
|
|
|
+ /* use static tjmax once it is set */
|
|
+ if (tdata->tjmax)
|
|
+ return tdata->tjmax;
|
|
+
|
|
/*
|
|
* A new feature of current Intel(R) processors, the
|
|
* IA32_TEMPERATURE_TARGET contains the TjMax value
|
|
*/
|
|
- err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
|
|
+ err = rdmsr_safe_on_cpu(tdata->cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
|
|
if (err) {
|
|
if (cpu_has_tjmax(c))
|
|
- dev_warn(dev, "Unable to read TjMax from CPU %u\n", id);
|
|
+ dev_warn(dev, "Unable to read TjMax from CPU %u\n", tdata->cpu);
|
|
} else {
|
|
val = (eax >> 16) & 0xff;
|
|
/*
|
|
@@ -369,14 +294,133 @@ static int get_tjmax(struct cpuinfo_x86
|
|
if (force_tjmax) {
|
|
dev_notice(dev, "TjMax forced to %d degrees C by user\n",
|
|
force_tjmax);
|
|
- return force_tjmax * 1000;
|
|
+ tdata->tjmax = force_tjmax * 1000;
|
|
+ } else {
|
|
+ /*
|
|
+ * An assumption is made for early CPUs and unreadable MSR.
|
|
+ * NOTE: the calculated value may not be correct.
|
|
+ */
|
|
+ tdata->tjmax = adjust_tjmax(c, tdata->cpu, dev);
|
|
}
|
|
+ return tdata->tjmax;
|
|
+}
|
|
+
|
|
+static int get_ttarget(struct temp_data *tdata, struct device *dev)
|
|
+{
|
|
+ u32 eax, edx;
|
|
+ int tjmax, ttarget_offset, ret;
|
|
|
|
/*
|
|
- * An assumption is made for early CPUs and unreadable MSR.
|
|
- * NOTE: the calculated value may not be correct.
|
|
+ * ttarget is valid only if tjmax can be retrieved from
|
|
+ * MSR_IA32_TEMPERATURE_TARGET
|
|
*/
|
|
- return adjust_tjmax(c, id, dev);
|
|
+ if (tdata->tjmax)
|
|
+ return -ENODEV;
|
|
+
|
|
+ ret = rdmsr_safe_on_cpu(tdata->cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ tjmax = (eax >> 16) & 0xff;
|
|
+
|
|
+ /* Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET. */
|
|
+ ttarget_offset = (eax >> 8) & 0xff;
|
|
+
|
|
+ return (tjmax - ttarget_offset) * 1000;
|
|
+}
|
|
+
|
|
+/* Keep track of how many zone pointers we allocated in init() */
|
|
+static int max_zones __read_mostly;
|
|
+/* Array of zone pointers. Serialized by cpu hotplug lock */
|
|
+static struct platform_device **zone_devices;
|
|
+
|
|
+static ssize_t show_label(struct device *dev,
|
|
+ struct device_attribute *devattr, char *buf)
|
|
+{
|
|
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
|
+ struct platform_data *pdata = dev_get_drvdata(dev);
|
|
+ struct temp_data *tdata = pdata->core_data[attr->index];
|
|
+
|
|
+ if (tdata->is_pkg_data)
|
|
+ return sprintf(buf, "Package id %u\n", pdata->pkg_id);
|
|
+
|
|
+ return sprintf(buf, "Core %u\n", tdata->cpu_core_id);
|
|
+}
|
|
+
|
|
+static ssize_t show_crit_alarm(struct device *dev,
|
|
+ struct device_attribute *devattr, char *buf)
|
|
+{
|
|
+ u32 eax, edx;
|
|
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
|
+ struct platform_data *pdata = dev_get_drvdata(dev);
|
|
+ struct temp_data *tdata = pdata->core_data[attr->index];
|
|
+
|
|
+ mutex_lock(&tdata->update_lock);
|
|
+ rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
|
|
+ mutex_unlock(&tdata->update_lock);
|
|
+
|
|
+ return sprintf(buf, "%d\n", (eax >> 5) & 1);
|
|
+}
|
|
+
|
|
+static ssize_t show_tjmax(struct device *dev,
|
|
+ struct device_attribute *devattr, char *buf)
|
|
+{
|
|
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
|
+ struct platform_data *pdata = dev_get_drvdata(dev);
|
|
+ struct temp_data *tdata = pdata->core_data[attr->index];
|
|
+ int tjmax;
|
|
+
|
|
+ mutex_lock(&tdata->update_lock);
|
|
+ tjmax = get_tjmax(tdata, dev);
|
|
+ mutex_unlock(&tdata->update_lock);
|
|
+
|
|
+ return sprintf(buf, "%d\n", tjmax);
|
|
+}
|
|
+
|
|
+static ssize_t show_ttarget(struct device *dev,
|
|
+ struct device_attribute *devattr, char *buf)
|
|
+{
|
|
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
|
+ struct platform_data *pdata = dev_get_drvdata(dev);
|
|
+ struct temp_data *tdata = pdata->core_data[attr->index];
|
|
+ int ttarget;
|
|
+
|
|
+ mutex_lock(&tdata->update_lock);
|
|
+ ttarget = get_ttarget(tdata, dev);
|
|
+ mutex_unlock(&tdata->update_lock);
|
|
+
|
|
+ if (ttarget < 0)
|
|
+ return ttarget;
|
|
+ return sprintf(buf, "%d\n", ttarget);
|
|
+}
|
|
+
|
|
+static ssize_t show_temp(struct device *dev,
|
|
+ struct device_attribute *devattr, char *buf)
|
|
+{
|
|
+ u32 eax, edx;
|
|
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
|
+ struct platform_data *pdata = dev_get_drvdata(dev);
|
|
+ struct temp_data *tdata = pdata->core_data[attr->index];
|
|
+ int tjmax;
|
|
+
|
|
+ mutex_lock(&tdata->update_lock);
|
|
+
|
|
+ tjmax = get_tjmax(tdata, dev);
|
|
+ /* Check whether the time interval has elapsed */
|
|
+ if (time_after(jiffies, tdata->last_updated + HZ)) {
|
|
+ rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
|
|
+ /*
|
|
+ * Ignore the valid bit. In all observed cases the register
|
|
+ * value is either low or zero if the valid bit is 0.
|
|
+ * Return it instead of reporting an error which doesn't
|
|
+ * really help at all.
|
|
+ */
|
|
+ tdata->temp = tjmax - ((eax >> 16) & 0x7f) * 1000;
|
|
+ tdata->last_updated = jiffies;
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&tdata->update_lock);
|
|
+ return sprintf(buf, "%d\n", tdata->temp);
|
|
}
|
|
|
|
static int create_core_attrs(struct temp_data *tdata, struct device *dev,
|
|
@@ -490,23 +534,17 @@ static int create_core_data(struct platf
|
|
if (err)
|
|
goto exit_free;
|
|
|
|
- /* We can access status register. Get Critical Temperature */
|
|
- tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);
|
|
+ /* Make sure tdata->tjmax is a valid indicator for dynamic/static tjmax */
|
|
+ get_tjmax(tdata, &pdev->dev);
|
|
|
|
/*
|
|
- * Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET.
|
|
- * The target temperature is available on older CPUs but not in this
|
|
- * register. Atoms don't have the register at all.
|
|
+ * The target temperature is available on older CPUs but not in the
|
|
+ * MSR_IA32_TEMPERATURE_TARGET register. Atoms don't have the register
|
|
+ * at all.
|
|
*/
|
|
- if (c->x86_model > 0xe && c->x86_model != 0x1c) {
|
|
- err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET,
|
|
- &eax, &edx);
|
|
- if (!err) {
|
|
- tdata->ttarget
|
|
- = tdata->tjmax - ((eax >> 8) & 0xff) * 1000;
|
|
+ if (c->x86_model > 0xe && c->x86_model != 0x1c)
|
|
+ if (get_ttarget(tdata, &pdev->dev) >= 0)
|
|
tdata->attr_size++;
|
|
- }
|
|
- }
|
|
|
|
pdata->core_data[attr_no] = tdata;
|
|
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/dell-smm-hwmon.c linux-6.1.2/drivers/hwmon/dell-smm-hwmon.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/dell-smm-hwmon.c 2022-12-31 16:12:06.934585693 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/dell-smm-hwmon.c 2022-12-31 16:19:55.385168045 -0500
|
|
@@ -1447,9 +1447,10 @@ static int __init i8k_init(void)
|
|
*/
|
|
if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&
|
|
i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {
|
|
- pr_err("unable to get SMM Dell signature\n");
|
|
if (!force)
|
|
return -ENODEV;
|
|
+
|
|
+ pr_err("Unable to get Dell SMM signature\n");
|
|
}
|
|
|
|
dell_smm_device = platform_create_bundle(&dell_smm_driver, dell_smm_probe, NULL, 0, NULL,
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/ds1621.c linux-6.1.2/drivers/hwmon/ds1621.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/ds1621.c 2022-12-31 16:12:06.934585693 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/ds1621.c 2022-12-31 16:19:55.385168045 -0500
|
|
@@ -269,7 +269,7 @@ static ssize_t update_interval_show(stru
|
|
struct device_attribute *da, char *buf)
|
|
{
|
|
struct ds1621_data *data = dev_get_drvdata(dev);
|
|
- return scnprintf(buf, PAGE_SIZE, "%hu\n", data->update_interval);
|
|
+ return sysfs_emit(buf, "%hu\n", data->update_interval);
|
|
}
|
|
|
|
static ssize_t update_interval_store(struct device *dev,
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/emc2305.c linux-6.1.2/drivers/hwmon/emc2305.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/emc2305.c 2022-12-31 16:12:06.934585693 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/emc2305.c 2022-12-31 16:19:46.453248935 -0500
|
|
@@ -528,7 +528,7 @@ static int emc2305_identify(struct devic
|
|
return 0;
|
|
}
|
|
|
|
-static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|
+static int emc2305_probe(struct i2c_client *client)
|
|
{
|
|
struct i2c_adapter *adapter = client->adapter;
|
|
struct device *dev = &client->dev;
|
|
@@ -613,7 +613,7 @@ static struct i2c_driver emc2305_driver
|
|
.driver = {
|
|
.name = "emc2305",
|
|
},
|
|
- .probe = emc2305_probe,
|
|
+ .probe_new = emc2305_probe,
|
|
.remove = emc2305_remove,
|
|
.id_table = emc2305_ids,
|
|
.address_list = emc2305_normal_i2c,
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/fschmd.c linux-6.1.2/drivers/hwmon/fschmd.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/fschmd.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/fschmd.c 2022-12-31 16:19:46.453248935 -0500
|
|
@@ -1083,9 +1083,9 @@ static int fschmd_detect(struct i2c_clie
|
|
static int fschmd_probe(struct i2c_client *client)
|
|
{
|
|
struct fschmd_data *data;
|
|
- const char * const names[7] = { "Poseidon", "Hermes", "Scylla",
|
|
+ static const char * const names[7] = { "Poseidon", "Hermes", "Scylla",
|
|
"Heracles", "Heimdall", "Hades", "Syleus" };
|
|
- const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
|
|
+ static const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
|
|
int i, err;
|
|
enum chips kind = i2c_match_id(fschmd_id, client)->driver_data;
|
|
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/gpio-fan.c linux-6.1.2/drivers/hwmon/gpio-fan.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/gpio-fan.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/gpio-fan.c 2022-12-31 16:19:53.945181044 -0500
|
|
@@ -14,6 +14,7 @@
|
|
#include <linux/irq.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/err.h>
|
|
+#include <linux/kstrtox.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/hwmon.h>
|
|
#include <linux/gpio/consumer.h>
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/gsc-hwmon.c linux-6.1.2/drivers/hwmon/gsc-hwmon.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/gsc-hwmon.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/gsc-hwmon.c 2022-12-31 16:19:55.381168081 -0500
|
|
@@ -257,13 +257,10 @@ gsc_hwmon_get_devtree_pdata(struct devic
|
|
if (nchannels == 0)
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
- pdata = devm_kzalloc(dev,
|
|
- sizeof(*pdata) + nchannels * sizeof(*ch),
|
|
+ pdata = devm_kzalloc(dev, struct_size(pdata, channels, nchannels),
|
|
GFP_KERNEL);
|
|
if (!pdata)
|
|
return ERR_PTR(-ENOMEM);
|
|
- ch = (struct gsc_hwmon_channel *)(pdata + 1);
|
|
- pdata->channels = ch;
|
|
pdata->nchannels = nchannels;
|
|
|
|
/* fan controller base address */
|
|
@@ -277,6 +274,7 @@ gsc_hwmon_get_devtree_pdata(struct devic
|
|
|
|
of_node_put(fan);
|
|
|
|
+ ch = pdata->channels;
|
|
/* allocate structures for channels and count instances of each type */
|
|
device_for_each_child_node(dev, child) {
|
|
if (fwnode_property_read_string(child, "label", &ch->name)) {
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/hwmon.c linux-6.1.2/drivers/hwmon/hwmon.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/hwmon.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/hwmon.c 2022-12-31 16:19:53.945181044 -0500
|
|
@@ -15,6 +15,7 @@
|
|
#include <linux/gfp.h>
|
|
#include <linux/hwmon.h>
|
|
#include <linux/idr.h>
|
|
+#include <linux/kstrtox.h>
|
|
#include <linux/list.h>
|
|
#include <linux/module.h>
|
|
#include <linux/pci.h>
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/it87.c linux-6.1.2/drivers/hwmon/it87.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/it87.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/it87.c 2022-12-31 16:19:53.949181008 -0500
|
|
@@ -69,6 +69,10 @@ static unsigned short force_id;
|
|
module_param(force_id, ushort, 0);
|
|
MODULE_PARM_DESC(force_id, "Override the detected device ID");
|
|
|
|
+static bool ignore_resource_conflict;
|
|
+module_param(ignore_resource_conflict, bool, 0);
|
|
+MODULE_PARM_DESC(ignore_resource_conflict, "Ignore ACPI resource conflict");
|
|
+
|
|
static struct platform_device *it87_pdev[2];
|
|
|
|
#define REG_2E 0x2e /* The register to read/write */
|
|
@@ -563,6 +567,14 @@ struct it87_data {
|
|
s8 auto_temp[NUM_AUTO_PWM][5]; /* [nr][0] is point1_temp_hyst */
|
|
};
|
|
|
|
+/* Board specific settings from DMI matching */
|
|
+struct it87_dmi_data {
|
|
+ u8 skip_pwm; /* pwm channels to skip for this board */
|
|
+};
|
|
+
|
|
+/* Global for results from DMI matching, if needed */
|
|
+static struct it87_dmi_data *dmi_data;
|
|
+
|
|
static int adc_lsb(const struct it87_data *data, int nr)
|
|
{
|
|
int lsb;
|
|
@@ -2389,7 +2401,6 @@ static int __init it87_find(int sioaddr,
|
|
{
|
|
int err;
|
|
u16 chip_type;
|
|
- const char *board_vendor, *board_name;
|
|
const struct it87_devices *config;
|
|
|
|
err = superio_enter(sioaddr);
|
|
@@ -2397,7 +2408,13 @@ static int __init it87_find(int sioaddr,
|
|
return err;
|
|
|
|
err = -ENODEV;
|
|
- chip_type = force_id ? force_id : superio_inw(sioaddr, DEVID);
|
|
+ chip_type = superio_inw(sioaddr, DEVID);
|
|
+ /* check first for a valid chip before forcing chip id */
|
|
+ if (chip_type == 0xffff)
|
|
+ goto exit;
|
|
+
|
|
+ if (force_id)
|
|
+ chip_type = force_id;
|
|
|
|
switch (chip_type) {
|
|
case IT8705F_DEVID:
|
|
@@ -2802,24 +2819,9 @@ static int __init it87_find(int sioaddr,
|
|
if (sio_data->beep_pin)
|
|
pr_info("Beeping is supported\n");
|
|
|
|
- /* Disable specific features based on DMI strings */
|
|
- board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
|
|
- board_name = dmi_get_system_info(DMI_BOARD_NAME);
|
|
- if (board_vendor && board_name) {
|
|
- if (strcmp(board_vendor, "nVIDIA") == 0 &&
|
|
- strcmp(board_name, "FN68PT") == 0) {
|
|
- /*
|
|
- * On the Shuttle SN68PT, FAN_CTL2 is apparently not
|
|
- * connected to a fan, but to something else. One user
|
|
- * has reported instant system power-off when changing
|
|
- * the PWM2 duty cycle, so we disable it.
|
|
- * I use the board name string as the trigger in case
|
|
- * the same board is ever used in other systems.
|
|
- */
|
|
- pr_info("Disabling pwm2 due to hardware constraints\n");
|
|
- sio_data->skip_pwm = BIT(1);
|
|
- }
|
|
- }
|
|
+ /* Set values based on DMI matches */
|
|
+ if (dmi_data)
|
|
+ sio_data->skip_pwm |= dmi_data->skip_pwm;
|
|
|
|
exit:
|
|
superio_exit(sioaddr);
|
|
@@ -3261,8 +3263,10 @@ static int __init it87_device_add(int in
|
|
int err;
|
|
|
|
err = acpi_check_resource_conflict(&res);
|
|
- if (err)
|
|
- return err;
|
|
+ if (err) {
|
|
+ if (!ignore_resource_conflict)
|
|
+ return err;
|
|
+ }
|
|
|
|
pdev = platform_device_alloc(DRVNAME, address);
|
|
if (!pdev)
|
|
@@ -3295,6 +3299,46 @@ exit_device_put:
|
|
return err;
|
|
}
|
|
|
|
+/* callback function for DMI */
|
|
+static int it87_dmi_cb(const struct dmi_system_id *dmi_entry)
|
|
+{
|
|
+ dmi_data = dmi_entry->driver_data;
|
|
+
|
|
+ if (dmi_data && dmi_data->skip_pwm)
|
|
+ pr_info("Disabling pwm2 due to hardware constraints\n");
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * On the Shuttle SN68PT, FAN_CTL2 is apparently not
|
|
+ * connected to a fan, but to something else. One user
|
|
+ * has reported instant system power-off when changing
|
|
+ * the PWM2 duty cycle, so we disable it.
|
|
+ * I use the board name string as the trigger in case
|
|
+ * the same board is ever used in other systems.
|
|
+ */
|
|
+static struct it87_dmi_data nvidia_fn68pt = {
|
|
+ .skip_pwm = BIT(1),
|
|
+};
|
|
+
|
|
+#define IT87_DMI_MATCH_VND(vendor, name, cb, data) \
|
|
+ { \
|
|
+ .callback = cb, \
|
|
+ .matches = { \
|
|
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, vendor), \
|
|
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \
|
|
+ }, \
|
|
+ .driver_data = data, \
|
|
+ }
|
|
+
|
|
+static const struct dmi_system_id it87_dmi_table[] __initconst = {
|
|
+ IT87_DMI_MATCH_VND("nVIDIA", "FN68PT", it87_dmi_cb, &nvidia_fn68pt),
|
|
+ { }
|
|
+
|
|
+};
|
|
+MODULE_DEVICE_TABLE(dmi, it87_dmi_table);
|
|
+
|
|
static int __init sm_it87_init(void)
|
|
{
|
|
int sioaddr[2] = { REG_2E, REG_4E };
|
|
@@ -3307,6 +3351,8 @@ static int __init sm_it87_init(void)
|
|
if (err)
|
|
return err;
|
|
|
|
+ dmi_check_system(it87_dmi_table);
|
|
+
|
|
for (i = 0; i < ARRAY_SIZE(sioaddr); i++) {
|
|
memset(&sio_data, 0, sizeof(struct it87_sio_data));
|
|
isa_address[i] = 0;
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/jc42.c linux-6.1.2/drivers/hwmon/jc42.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/jc42.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/jc42.c 2022-12-31 16:19:53.945181044 -0500
|
|
@@ -10,6 +10,7 @@
|
|
*/
|
|
|
|
#include <linux/bitops.h>
|
|
+#include <linux/bitfield.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/slab.h>
|
|
@@ -37,20 +38,19 @@ static const unsigned short normal_i2c[]
|
|
#define JC42_REG_SMBUS 0x22 /* NXP and Atmel, possibly others? */
|
|
|
|
/* Status bits in temperature register */
|
|
-#define JC42_ALARM_CRIT_BIT 15
|
|
-#define JC42_ALARM_MAX_BIT 14
|
|
-#define JC42_ALARM_MIN_BIT 13
|
|
+#define JC42_ALARM_CRIT BIT(15)
|
|
+#define JC42_ALARM_MAX BIT(14)
|
|
+#define JC42_ALARM_MIN BIT(13)
|
|
|
|
/* Configuration register defines */
|
|
-#define JC42_CFG_CRIT_ONLY (1 << 2)
|
|
-#define JC42_CFG_TCRIT_LOCK (1 << 6)
|
|
-#define JC42_CFG_EVENT_LOCK (1 << 7)
|
|
-#define JC42_CFG_SHUTDOWN (1 << 8)
|
|
-#define JC42_CFG_HYST_SHIFT 9
|
|
-#define JC42_CFG_HYST_MASK (0x03 << 9)
|
|
+#define JC42_CFG_CRIT_ONLY BIT(2)
|
|
+#define JC42_CFG_TCRIT_LOCK BIT(6)
|
|
+#define JC42_CFG_EVENT_LOCK BIT(7)
|
|
+#define JC42_CFG_SHUTDOWN BIT(8)
|
|
+#define JC42_CFG_HYST_MASK GENMASK(10, 9)
|
|
|
|
/* Capabilities */
|
|
-#define JC42_CAP_RANGE (1 << 2)
|
|
+#define JC42_CAP_RANGE BIT(2)
|
|
|
|
/* Manufacturer IDs */
|
|
#define ADT_MANID 0x11d4 /* Analog Devices */
|
|
@@ -277,8 +277,8 @@ static int jc42_read(struct device *dev,
|
|
break;
|
|
|
|
temp = jc42_temp_from_reg(regval);
|
|
- hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK)
|
|
- >> JC42_CFG_HYST_SHIFT];
|
|
+ hyst = jc42_hysteresis[FIELD_GET(JC42_CFG_HYST_MASK,
|
|
+ data->config)];
|
|
*val = temp - hyst;
|
|
break;
|
|
case hwmon_temp_crit_hyst:
|
|
@@ -288,8 +288,8 @@ static int jc42_read(struct device *dev,
|
|
break;
|
|
|
|
temp = jc42_temp_from_reg(regval);
|
|
- hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK)
|
|
- >> JC42_CFG_HYST_SHIFT];
|
|
+ hyst = jc42_hysteresis[FIELD_GET(JC42_CFG_HYST_MASK,
|
|
+ data->config)];
|
|
*val = temp - hyst;
|
|
break;
|
|
case hwmon_temp_min_alarm:
|
|
@@ -297,21 +297,21 @@ static int jc42_read(struct device *dev,
|
|
if (ret)
|
|
break;
|
|
|
|
- *val = (regval >> JC42_ALARM_MIN_BIT) & 1;
|
|
+ *val = FIELD_GET(JC42_ALARM_MIN, regval);
|
|
break;
|
|
case hwmon_temp_max_alarm:
|
|
ret = regmap_read(data->regmap, JC42_REG_TEMP, ®val);
|
|
if (ret)
|
|
break;
|
|
|
|
- *val = (regval >> JC42_ALARM_MAX_BIT) & 1;
|
|
+ *val = FIELD_GET(JC42_ALARM_MAX, regval);
|
|
break;
|
|
case hwmon_temp_crit_alarm:
|
|
ret = regmap_read(data->regmap, JC42_REG_TEMP, ®val);
|
|
if (ret)
|
|
break;
|
|
|
|
- *val = (regval >> JC42_ALARM_CRIT_BIT) & 1;
|
|
+ *val = FIELD_GET(JC42_ALARM_CRIT, regval);
|
|
break;
|
|
default:
|
|
ret = -EOPNOTSUPP;
|
|
@@ -370,7 +370,7 @@ static int jc42_write(struct device *dev
|
|
hyst = 3; /* 6.0 degrees C */
|
|
}
|
|
data->config = (data->config & ~JC42_CFG_HYST_MASK) |
|
|
- (hyst << JC42_CFG_HYST_SHIFT);
|
|
+ FIELD_PREP(JC42_CFG_HYST_MASK, hyst);
|
|
ret = regmap_write(data->regmap, JC42_REG_CONFIG,
|
|
data->config);
|
|
break;
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/Kconfig linux-6.1.2/drivers/hwmon/Kconfig
|
|
--- linux-6.1.2.orig/drivers/hwmon/Kconfig 2022-12-31 16:12:06.934585693 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/Kconfig 2022-12-31 16:19:53.953180971 -0500
|
|
@@ -67,6 +67,14 @@ config SENSORS_ABITUGURU3
|
|
This driver can also be built as a module. If so, the module
|
|
will be called abituguru3.
|
|
|
|
+config SENSORS_SMPRO
|
|
+ tristate "Ampere's Altra SMpro hardware monitoring driver"
|
|
+ depends on MFD_SMPRO
|
|
+ help
|
|
+ If you say yes here you get support for the thermal, voltage,
|
|
+ current and power sensors of Ampere's Altra processor family SoC
|
|
+ with SMpro co-processor.
|
|
+
|
|
config SENSORS_AD7314
|
|
tristate "Analog Devices AD7314 and compatibles"
|
|
depends on SPI
|
|
@@ -1608,6 +1616,17 @@ config SENSORS_NZXT_SMART2
|
|
|
|
source "drivers/hwmon/occ/Kconfig"
|
|
|
|
+config SENSORS_OXP
|
|
+ tristate "OneXPlayer EC fan control"
|
|
+ depends on ACPI
|
|
+ depends on X86
|
|
+ help
|
|
+ If you say yes here you get support for fan readings and control over
|
|
+ OneXPlayer handheld devices. Only OneXPlayer mini AMD handheld variant
|
|
+ boards are supported.
|
|
+
|
|
+ Can also be built as a module. In that case it will be called oxp-sensors.
|
|
+
|
|
config SENSORS_PCF8591
|
|
tristate "Philips PCF8591 ADC/DAC"
|
|
depends on I2C
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/lm73.c linux-6.1.2/drivers/hwmon/lm73.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/lm73.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/lm73.c 2022-12-31 16:19:55.385168045 -0500
|
|
@@ -92,7 +92,7 @@ static ssize_t temp_show(struct device *
|
|
/* use integer division instead of equivalent right shift to
|
|
guarantee arithmetic shift and preserve the sign */
|
|
temp = (((s16) err) * 250) / 32;
|
|
- return scnprintf(buf, PAGE_SIZE, "%d\n", temp);
|
|
+ return sysfs_emit(buf, "%d\n", temp);
|
|
}
|
|
|
|
static ssize_t convrate_store(struct device *dev, struct device_attribute *da,
|
|
@@ -137,7 +137,7 @@ static ssize_t convrate_show(struct devi
|
|
int res;
|
|
|
|
res = (data->ctrl & LM73_CTRL_RES_MASK) >> LM73_CTRL_RES_SHIFT;
|
|
- return scnprintf(buf, PAGE_SIZE, "%hu\n", lm73_convrates[res]);
|
|
+ return sysfs_emit(buf, "%hu\n", lm73_convrates[res]);
|
|
}
|
|
|
|
static ssize_t maxmin_alarm_show(struct device *dev,
|
|
@@ -154,7 +154,7 @@ static ssize_t maxmin_alarm_show(struct
|
|
data->ctrl = ctrl;
|
|
mutex_unlock(&data->lock);
|
|
|
|
- return scnprintf(buf, PAGE_SIZE, "%d\n", (ctrl >> attr->index) & 1);
|
|
+ return sysfs_emit(buf, "%d\n", (ctrl >> attr->index) & 1);
|
|
|
|
abort:
|
|
mutex_unlock(&data->lock);
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/lm90.c linux-6.1.2/drivers/hwmon/lm90.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/lm90.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/lm90.c 2022-12-31 16:19:53.945181044 -0500
|
|
@@ -103,6 +103,7 @@
|
|
#include <linux/interrupt.h>
|
|
#include <linux/jiffies.h>
|
|
#include <linux/hwmon.h>
|
|
+#include <linux/kstrtox.h>
|
|
#include <linux/module.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/of_device.h>
|
|
@@ -2663,11 +2664,6 @@ static void lm90_remove_pec(void *dev)
|
|
device_remove_file(dev, &dev_attr_pec);
|
|
}
|
|
|
|
-static void lm90_regulator_disable(void *regulator)
|
|
-{
|
|
- regulator_disable(regulator);
|
|
-}
|
|
-
|
|
static int lm90_probe_channel_from_dt(struct i2c_client *client,
|
|
struct device_node *child,
|
|
struct lm90_data *data)
|
|
@@ -2749,24 +2745,13 @@ static int lm90_probe(struct i2c_client
|
|
struct device *dev = &client->dev;
|
|
struct i2c_adapter *adapter = client->adapter;
|
|
struct hwmon_channel_info *info;
|
|
- struct regulator *regulator;
|
|
struct device *hwmon_dev;
|
|
struct lm90_data *data;
|
|
int err;
|
|
|
|
- regulator = devm_regulator_get(dev, "vcc");
|
|
- if (IS_ERR(regulator))
|
|
- return PTR_ERR(regulator);
|
|
-
|
|
- err = regulator_enable(regulator);
|
|
- if (err < 0) {
|
|
- dev_err(dev, "Failed to enable regulator: %d\n", err);
|
|
- return err;
|
|
- }
|
|
-
|
|
- err = devm_add_action_or_reset(dev, lm90_regulator_disable, regulator);
|
|
+ err = devm_regulator_get_enable(dev, "vcc");
|
|
if (err)
|
|
- return err;
|
|
+ return dev_err_probe(dev, err, "Failed to enable regulator\n");
|
|
|
|
data = devm_kzalloc(dev, sizeof(struct lm90_data), GFP_KERNEL);
|
|
if (!data)
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/ltc2992.c linux-6.1.2/drivers/hwmon/ltc2992.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/ltc2992.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/ltc2992.c 2022-12-31 16:19:46.453248935 -0500
|
|
@@ -881,7 +881,7 @@ static int ltc2992_parse_dt(struct ltc29
|
|
return 0;
|
|
}
|
|
|
|
-static int ltc2992_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|
+static int ltc2992_i2c_probe(struct i2c_client *client)
|
|
{
|
|
struct device *hwmon_dev;
|
|
struct ltc2992_state *st;
|
|
@@ -927,7 +927,7 @@ static struct i2c_driver ltc2992_i2c_dri
|
|
.name = "ltc2992",
|
|
.of_match_table = ltc2992_of_match,
|
|
},
|
|
- .probe = ltc2992_i2c_probe,
|
|
+ .probe_new = ltc2992_i2c_probe,
|
|
.id_table = ltc2992_i2c_id,
|
|
};
|
|
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/Makefile linux-6.1.2/drivers/hwmon/Makefile
|
|
--- linux-6.1.2.orig/drivers/hwmon/Makefile 2022-12-31 16:12:06.934585693 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/Makefile 2022-12-31 16:19:53.953180971 -0500
|
|
@@ -167,6 +167,7 @@ obj-$(CONFIG_SENSORS_NSA320) += nsa320-h
|
|
obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
|
|
obj-$(CONFIG_SENSORS_NZXT_KRAKEN2) += nzxt-kraken2.o
|
|
obj-$(CONFIG_SENSORS_NZXT_SMART2) += nzxt-smart2.o
|
|
+obj-$(CONFIG_SENSORS_OXP) += oxp-sensors.o
|
|
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
|
|
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
|
|
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
|
|
@@ -187,6 +188,7 @@ obj-$(CONFIG_SENSORS_SHT4x) += sht4x.o
|
|
obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o
|
|
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
|
|
obj-$(CONFIG_SENSORS_SMM665) += smm665.o
|
|
+obj-$(CONFIG_SENSORS_SMPRO) += smpro-hwmon.o
|
|
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
|
|
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
|
|
obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/max127.c linux-6.1.2/drivers/hwmon/max127.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/max127.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/max127.c 2022-12-31 16:19:46.453248935 -0500
|
|
@@ -303,8 +303,7 @@ static const struct hwmon_chip_info max1
|
|
.info = max127_info,
|
|
};
|
|
|
|
-static int max127_probe(struct i2c_client *client,
|
|
- const struct i2c_device_id *id)
|
|
+static int max127_probe(struct i2c_client *client)
|
|
{
|
|
int i;
|
|
struct device *hwmon_dev;
|
|
@@ -340,7 +339,7 @@ static struct i2c_driver max127_driver =
|
|
.driver = {
|
|
.name = "max127",
|
|
},
|
|
- .probe = max127_probe,
|
|
+ .probe_new = max127_probe,
|
|
.id_table = max127_id,
|
|
};
|
|
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/mr75203.c linux-6.1.2/drivers/hwmon/mr75203.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/mr75203.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/mr75203.c 2022-12-31 16:19:53.945181044 -0500
|
|
@@ -11,6 +11,7 @@
|
|
#include <linux/clk.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/hwmon.h>
|
|
+#include <linux/kstrtox.h>
|
|
#include <linux/module.h>
|
|
#include <linux/mod_devicetable.h>
|
|
#include <linux/mutex.h>
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/occ/Kconfig linux-6.1.2/drivers/hwmon/occ/Kconfig
|
|
--- linux-6.1.2.orig/drivers/hwmon/occ/Kconfig 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/occ/Kconfig 2022-12-31 16:19:46.457248898 -0500
|
|
@@ -6,7 +6,6 @@
|
|
config SENSORS_OCC_P8_I2C
|
|
tristate "POWER8 OCC through I2C"
|
|
depends on I2C
|
|
- depends on ARM || ARM64 || COMPILE_TEST
|
|
select SENSORS_OCC
|
|
help
|
|
This option enables support for monitoring sensors provided by the
|
|
@@ -21,7 +20,6 @@ config SENSORS_OCC_P8_I2C
|
|
config SENSORS_OCC_P9_SBE
|
|
tristate "POWER9 OCC through SBE"
|
|
depends on FSI_OCC
|
|
- depends on ARM || ARM64 || COMPILE_TEST
|
|
select SENSORS_OCC
|
|
help
|
|
This option enables support for monitoring sensors provided by the
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/oxp-sensors.c linux-6.1.2/drivers/hwmon/oxp-sensors.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/oxp-sensors.c 1969-12-31 19:00:00.000000000 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/oxp-sensors.c 2022-12-31 16:19:55.385168045 -0500
|
|
@@ -0,0 +1,284 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * Platform driver for OXP Handhelds that expose fan reading and control
|
|
+ * via hwmon sysfs.
|
|
+ *
|
|
+ * Old boards have the same DMI strings and they are told appart by the
|
|
+ * boot cpu vendor (Intel/AMD). Currently only AMD boards are supported
|
|
+ * but the code is made to be simple to add other handheld boards in the
|
|
+ * future.
|
|
+ * Fan control is provided via pwm interface in the range [0-255].
|
|
+ * Old AMD boards use [0-100] as range in the EC, the written value is
|
|
+ * scaled to accommodate for that. Newer boards like the mini PRO and
|
|
+ * AOK ZOE are not scaled but have the same EC layout.
|
|
+ *
|
|
+ * Copyright (C) 2022 Joaquín I. Aramendía <samsagax@gmail.com>
|
|
+ */
|
|
+
|
|
+#include <linux/acpi.h>
|
|
+#include <linux/dev_printk.h>
|
|
+#include <linux/dmi.h>
|
|
+#include <linux/hwmon.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/processor.h>
|
|
+
|
|
+/* Handle ACPI lock mechanism */
|
|
+static u32 oxp_mutex;
|
|
+
|
|
+#define ACPI_LOCK_DELAY_MS 500
|
|
+
|
|
+static bool lock_global_acpi_lock(void)
|
|
+{
|
|
+ return ACPI_SUCCESS(acpi_acquire_global_lock(ACPI_LOCK_DELAY_MS, &oxp_mutex));
|
|
+}
|
|
+
|
|
+static bool unlock_global_acpi_lock(void)
|
|
+{
|
|
+ return ACPI_SUCCESS(acpi_release_global_lock(oxp_mutex));
|
|
+}
|
|
+
|
|
+enum oxp_board {
|
|
+ aok_zoe_a1 = 1,
|
|
+ oxp_mini_amd,
|
|
+ oxp_mini_amd_pro,
|
|
+};
|
|
+
|
|
+static enum oxp_board board;
|
|
+
|
|
+#define OXP_SENSOR_FAN_REG 0x76 /* Fan reading is 2 registers long */
|
|
+#define OXP_SENSOR_PWM_ENABLE_REG 0x4A /* PWM enable is 1 register long */
|
|
+#define OXP_SENSOR_PWM_REG 0x4B /* PWM reading is 1 register long */
|
|
+
|
|
+static const struct dmi_system_id dmi_table[] = {
|
|
+ {
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "AOKZOE"),
|
|
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "AOKZOE A1 AR07"),
|
|
+ },
|
|
+ .driver_data = (void *) &(enum oxp_board) {aok_zoe_a1},
|
|
+ },
|
|
+ {
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
|
|
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONE XPLAYER"),
|
|
+ },
|
|
+ .driver_data = (void *) &(enum oxp_board) {oxp_mini_amd},
|
|
+ },
|
|
+ {
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
|
|
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER Mini Pro"),
|
|
+ },
|
|
+ .driver_data = (void *) &(enum oxp_board) {oxp_mini_amd_pro},
|
|
+ },
|
|
+ {},
|
|
+};
|
|
+
|
|
+/* Helper functions to handle EC read/write */
|
|
+static int read_from_ec(u8 reg, int size, long *val)
|
|
+{
|
|
+ int i;
|
|
+ int ret;
|
|
+ u8 buffer;
|
|
+
|
|
+ if (!lock_global_acpi_lock())
|
|
+ return -EBUSY;
|
|
+
|
|
+ *val = 0;
|
|
+ for (i = 0; i < size; i++) {
|
|
+ ret = ec_read(reg + i, &buffer);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ *val <<= i * 8;
|
|
+ *val += buffer;
|
|
+ }
|
|
+
|
|
+ if (!unlock_global_acpi_lock())
|
|
+ return -EBUSY;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int write_to_ec(const struct device *dev, u8 reg, u8 value)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ if (!lock_global_acpi_lock())
|
|
+ return -EBUSY;
|
|
+
|
|
+ ret = ec_write(reg, value);
|
|
+
|
|
+ if (!unlock_global_acpi_lock())
|
|
+ return -EBUSY;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int oxp_pwm_enable(const struct device *dev)
|
|
+{
|
|
+ return write_to_ec(dev, OXP_SENSOR_PWM_ENABLE_REG, 0x01);
|
|
+}
|
|
+
|
|
+static int oxp_pwm_disable(const struct device *dev)
|
|
+{
|
|
+ return write_to_ec(dev, OXP_SENSOR_PWM_ENABLE_REG, 0x00);
|
|
+}
|
|
+
|
|
+/* Callbacks for hwmon interface */
|
|
+static umode_t oxp_ec_hwmon_is_visible(const void *drvdata,
|
|
+ enum hwmon_sensor_types type, u32 attr, int channel)
|
|
+{
|
|
+ switch (type) {
|
|
+ case hwmon_fan:
|
|
+ return 0444;
|
|
+ case hwmon_pwm:
|
|
+ return 0644;
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int oxp_platform_read(struct device *dev, enum hwmon_sensor_types type,
|
|
+ u32 attr, int channel, long *val)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ switch (type) {
|
|
+ case hwmon_fan:
|
|
+ switch (attr) {
|
|
+ case hwmon_fan_input:
|
|
+ return read_from_ec(OXP_SENSOR_FAN_REG, 2, val);
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case hwmon_pwm:
|
|
+ switch (attr) {
|
|
+ case hwmon_pwm_input:
|
|
+ ret = read_from_ec(OXP_SENSOR_PWM_REG, 1, val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ if (board == oxp_mini_amd)
|
|
+ *val = (*val * 255) / 100;
|
|
+ return 0;
|
|
+ case hwmon_pwm_enable:
|
|
+ return read_from_ec(OXP_SENSOR_PWM_ENABLE_REG, 1, val);
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ return -EOPNOTSUPP;
|
|
+}
|
|
+
|
|
+static int oxp_platform_write(struct device *dev, enum hwmon_sensor_types type,
|
|
+ u32 attr, int channel, long val)
|
|
+{
|
|
+ switch (type) {
|
|
+ case hwmon_pwm:
|
|
+ switch (attr) {
|
|
+ case hwmon_pwm_enable:
|
|
+ if (val == 1)
|
|
+ return oxp_pwm_enable(dev);
|
|
+ else if (val == 0)
|
|
+ return oxp_pwm_disable(dev);
|
|
+ return -EINVAL;
|
|
+ case hwmon_pwm_input:
|
|
+ if (val < 0 || val > 255)
|
|
+ return -EINVAL;
|
|
+ if (board == oxp_mini_amd)
|
|
+ val = (val * 100) / 255;
|
|
+ return write_to_ec(dev, OXP_SENSOR_PWM_REG, val);
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ return -EOPNOTSUPP;
|
|
+}
|
|
+
|
|
+/* Known sensors in the OXP EC controllers */
|
|
+static const struct hwmon_channel_info *oxp_platform_sensors[] = {
|
|
+ HWMON_CHANNEL_INFO(fan,
|
|
+ HWMON_F_INPUT),
|
|
+ HWMON_CHANNEL_INFO(pwm,
|
|
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE),
|
|
+ NULL,
|
|
+};
|
|
+
|
|
+static const struct hwmon_ops oxp_ec_hwmon_ops = {
|
|
+ .is_visible = oxp_ec_hwmon_is_visible,
|
|
+ .read = oxp_platform_read,
|
|
+ .write = oxp_platform_write,
|
|
+};
|
|
+
|
|
+static const struct hwmon_chip_info oxp_ec_chip_info = {
|
|
+ .ops = &oxp_ec_hwmon_ops,
|
|
+ .info = oxp_platform_sensors,
|
|
+};
|
|
+
|
|
+/* Initialization logic */
|
|
+static int oxp_platform_probe(struct platform_device *pdev)
|
|
+{
|
|
+ const struct dmi_system_id *dmi_entry;
|
|
+ struct device *dev = &pdev->dev;
|
|
+ struct device *hwdev;
|
|
+
|
|
+ /*
|
|
+ * Have to check for AMD processor here because DMI strings are the
|
|
+ * same between Intel and AMD boards, the only way to tell them appart
|
|
+ * is the CPU.
|
|
+ * Intel boards seem to have different EC registers and values to
|
|
+ * read/write.
|
|
+ */
|
|
+ dmi_entry = dmi_first_match(dmi_table);
|
|
+ if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
|
|
+ return -ENODEV;
|
|
+
|
|
+ board = *((enum oxp_board *) dmi_entry->driver_data);
|
|
+
|
|
+ hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL,
|
|
+ &oxp_ec_chip_info, NULL);
|
|
+
|
|
+ return PTR_ERR_OR_ZERO(hwdev);
|
|
+}
|
|
+
|
|
+static struct platform_driver oxp_platform_driver = {
|
|
+ .driver = {
|
|
+ .name = "oxp-platform",
|
|
+ },
|
|
+ .probe = oxp_platform_probe,
|
|
+};
|
|
+
|
|
+static struct platform_device *oxp_platform_device;
|
|
+
|
|
+static int __init oxp_platform_init(void)
|
|
+{
|
|
+ oxp_platform_device =
|
|
+ platform_create_bundle(&oxp_platform_driver,
|
|
+ oxp_platform_probe, NULL, 0, NULL, 0);
|
|
+
|
|
+ return PTR_ERR_OR_ZERO(oxp_platform_device);
|
|
+}
|
|
+
|
|
+static void __exit oxp_platform_exit(void)
|
|
+{
|
|
+ platform_device_unregister(oxp_platform_device);
|
|
+ platform_driver_unregister(&oxp_platform_driver);
|
|
+}
|
|
+
|
|
+MODULE_DEVICE_TABLE(dmi, dmi_table);
|
|
+
|
|
+module_init(oxp_platform_init);
|
|
+module_exit(oxp_platform_exit);
|
|
+
|
|
+MODULE_AUTHOR("Joaquín Ignacio Aramendía <samsagax@gmail.com>");
|
|
+MODULE_DESCRIPTION("Platform driver that handles EC sensors of OneXPlayer devices");
|
|
+MODULE_LICENSE("GPL");
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/pcf8591.c linux-6.1.2/drivers/hwmon/pcf8591.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/pcf8591.c 2022-12-31 16:12:06.938585633 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/pcf8591.c 2022-12-31 16:19:53.949181008 -0500
|
|
@@ -14,6 +14,7 @@
|
|
#include <linux/mutex.h>
|
|
#include <linux/err.h>
|
|
#include <linux/hwmon.h>
|
|
+#include <linux/kstrtox.h>
|
|
|
|
/* Insmod parameters */
|
|
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/pmbus/ltc2978.c linux-6.1.2/drivers/hwmon/pmbus/ltc2978.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/pmbus/ltc2978.c 2022-12-31 16:12:06.942585573 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/pmbus/ltc2978.c 2022-12-31 16:19:53.945181044 -0500
|
|
@@ -23,7 +23,7 @@ enum chips {
|
|
/* Managers */
|
|
ltc2972, ltc2974, ltc2975, ltc2977, ltc2978, ltc2979, ltc2980,
|
|
/* Controllers */
|
|
- ltc3880, ltc3882, ltc3883, ltc3884, ltc3886, ltc3887, ltc3889, ltc7880,
|
|
+ ltc3880, ltc3882, ltc3883, ltc3884, ltc3886, ltc3887, ltc3889, ltc7132, ltc7880,
|
|
/* Modules */
|
|
ltm2987, ltm4664, ltm4675, ltm4676, ltm4677, ltm4678, ltm4680, ltm4686,
|
|
ltm4700,
|
|
@@ -45,15 +45,14 @@ enum chips {
|
|
#define LTC2974_MFR_IOUT_PEAK 0xd7
|
|
#define LTC2974_MFR_IOUT_MIN 0xd8
|
|
|
|
-/* LTC3880, LTC3882, LTC3883, LTC3887, LTM4675, and LTM4676 */
|
|
+/* LTC3880, LTC3882, LTC3883, LTC3887, LTM4675, LTM4676, LTC7132 */
|
|
#define LTC3880_MFR_IOUT_PEAK 0xd7
|
|
#define LTC3880_MFR_CLEAR_PEAKS 0xe3
|
|
#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
|
|
|
|
-/* LTC3883, LTC3884, LTC3886, LTC3889 and LTC7880 only */
|
|
+/* LTC3883, LTC3884, LTC3886, LTC3889, LTC7132, LTC7880 */
|
|
#define LTC3883_MFR_IIN_PEAK 0xe1
|
|
|
|
-
|
|
/* LTC2975 only */
|
|
#define LTC2975_MFR_IIN_PEAK 0xc4
|
|
#define LTC2975_MFR_IIN_MIN 0xc5
|
|
@@ -79,10 +78,11 @@ enum chips {
|
|
#define LTC3884_ID 0x4C00
|
|
#define LTC3886_ID 0x4600
|
|
#define LTC3887_ID 0x4700
|
|
-#define LTM2987_ID_A 0x8010 /* A/B for two die IDs */
|
|
-#define LTM2987_ID_B 0x8020
|
|
#define LTC3889_ID 0x4900
|
|
+#define LTC7132_ID 0x4CE0
|
|
#define LTC7880_ID 0x49E0
|
|
+#define LTM2987_ID_A 0x8010 /* A/B for two die IDs */
|
|
+#define LTM2987_ID_B 0x8020
|
|
#define LTM4664_ID 0x4120
|
|
#define LTM4675_ID 0x47a0
|
|
#define LTM4676_ID_REV1 0x4400
|
|
@@ -547,6 +547,7 @@ static const struct i2c_device_id ltc297
|
|
{"ltc3886", ltc3886},
|
|
{"ltc3887", ltc3887},
|
|
{"ltc3889", ltc3889},
|
|
+ {"ltc7132", ltc7132},
|
|
{"ltc7880", ltc7880},
|
|
{"ltm2987", ltm2987},
|
|
{"ltm4664", ltm4664},
|
|
@@ -651,6 +652,8 @@ static int ltc2978_get_id(struct i2c_cli
|
|
return ltc3887;
|
|
else if (chip_id == LTC3889_ID)
|
|
return ltc3889;
|
|
+ else if (chip_id == LTC7132_ID)
|
|
+ return ltc7132;
|
|
else if (chip_id == LTC7880_ID)
|
|
return ltc7880;
|
|
else if (chip_id == LTM2987_ID_A || chip_id == LTM2987_ID_B)
|
|
@@ -831,6 +834,7 @@ static int ltc2978_probe(struct i2c_clie
|
|
case ltc3884:
|
|
case ltc3886:
|
|
case ltc3889:
|
|
+ case ltc7132:
|
|
case ltc7880:
|
|
case ltm4664:
|
|
case ltm4678:
|
|
@@ -902,6 +906,7 @@ static const struct of_device_id ltc2978
|
|
{ .compatible = "lltc,ltc3886" },
|
|
{ .compatible = "lltc,ltc3887" },
|
|
{ .compatible = "lltc,ltc3889" },
|
|
+ { .compatible = "lltc,ltc7132" },
|
|
{ .compatible = "lltc,ltc7880" },
|
|
{ .compatible = "lltc,ltm2987" },
|
|
{ .compatible = "lltc,ltm4664" },
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/pmbus/pmbus_core.c linux-6.1.2/drivers/hwmon/pmbus/pmbus_core.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/pmbus/pmbus_core.c 2022-12-31 16:12:06.942585573 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/pmbus/pmbus_core.c 2022-12-31 16:19:55.381168081 -0500
|
|
@@ -2827,9 +2827,13 @@ static int pmbus_regulator_get_error_fla
|
|
if (status < 0)
|
|
return status;
|
|
|
|
- if (pmbus_regulator_is_enabled(rdev) && (status & PB_STATUS_OFF))
|
|
- *flags |= REGULATOR_ERROR_FAIL;
|
|
+ if (pmbus_regulator_is_enabled(rdev)) {
|
|
+ if (status & PB_STATUS_OFF)
|
|
+ *flags |= REGULATOR_ERROR_FAIL;
|
|
|
|
+ if (status & PB_STATUS_POWER_GOOD_N)
|
|
+ *flags |= REGULATOR_ERROR_REGULATION_OUT;
|
|
+ }
|
|
/*
|
|
* Unlike most other status bits, PB_STATUS_{IOUT_OC,VOUT_OV} are
|
|
* defined strictly as fault indicators (not warnings).
|
|
@@ -2851,6 +2855,49 @@ static int pmbus_regulator_get_error_fla
|
|
return 0;
|
|
}
|
|
|
|
+static int pmbus_regulator_get_status(struct regulator_dev *rdev)
|
|
+{
|
|
+ struct device *dev = rdev_get_dev(rdev);
|
|
+ struct i2c_client *client = to_i2c_client(dev->parent);
|
|
+ struct pmbus_data *data = i2c_get_clientdata(client);
|
|
+ u8 page = rdev_get_id(rdev);
|
|
+ int status, ret;
|
|
+
|
|
+ mutex_lock(&data->update_lock);
|
|
+ status = pmbus_get_status(client, page, PMBUS_STATUS_WORD);
|
|
+ if (status < 0) {
|
|
+ ret = status;
|
|
+ goto unlock;
|
|
+ }
|
|
+
|
|
+ if (status & PB_STATUS_OFF) {
|
|
+ ret = REGULATOR_STATUS_OFF;
|
|
+ goto unlock;
|
|
+ }
|
|
+
|
|
+ /* If regulator is ON & reports power good then return ON */
|
|
+ if (!(status & PB_STATUS_POWER_GOOD_N)) {
|
|
+ ret = REGULATOR_STATUS_ON;
|
|
+ goto unlock;
|
|
+ }
|
|
+
|
|
+ ret = pmbus_regulator_get_error_flags(rdev, &status);
|
|
+ if (ret)
|
|
+ goto unlock;
|
|
+
|
|
+ if (status & (REGULATOR_ERROR_UNDER_VOLTAGE | REGULATOR_ERROR_OVER_CURRENT |
|
|
+ REGULATOR_ERROR_REGULATION_OUT | REGULATOR_ERROR_FAIL | REGULATOR_ERROR_OVER_TEMP)) {
|
|
+ ret = REGULATOR_STATUS_ERROR;
|
|
+ goto unlock;
|
|
+ }
|
|
+
|
|
+ ret = REGULATOR_STATUS_UNDEFINED;
|
|
+
|
|
+unlock:
|
|
+ mutex_unlock(&data->update_lock);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int pmbus_regulator_get_low_margin(struct i2c_client *client, int page)
|
|
{
|
|
struct pmbus_data *data = i2c_get_clientdata(client);
|
|
@@ -2991,6 +3038,7 @@ const struct regulator_ops pmbus_regulat
|
|
.disable = pmbus_regulator_disable,
|
|
.is_enabled = pmbus_regulator_is_enabled,
|
|
.get_error_flags = pmbus_regulator_get_error_flags,
|
|
+ .get_status = pmbus_regulator_get_status,
|
|
.get_voltage = pmbus_regulator_get_voltage,
|
|
.set_voltage = pmbus_regulator_set_voltage,
|
|
.list_voltage = pmbus_regulator_list_voltage,
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/pmbus/q54sj108a2.c linux-6.1.2/drivers/hwmon/pmbus/q54sj108a2.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/pmbus/q54sj108a2.c 2022-12-31 16:12:06.942585573 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/pmbus/q54sj108a2.c 2022-12-31 16:19:53.949181008 -0500
|
|
@@ -8,6 +8,7 @@
|
|
|
|
#include <linux/debugfs.h>
|
|
#include <linux/i2c.h>
|
|
+#include <linux/kstrtox.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of_device.h>
|
|
#include "pmbus.h"
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/sbrmi.c linux-6.1.2/drivers/hwmon/sbrmi.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/sbrmi.c 2022-12-31 16:12:06.942585573 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/sbrmi.c 2022-12-31 16:19:46.453248935 -0500
|
|
@@ -297,8 +297,7 @@ static int sbrmi_get_max_pwr_limit(struc
|
|
return ret;
|
|
}
|
|
|
|
-static int sbrmi_probe(struct i2c_client *client,
|
|
- const struct i2c_device_id *id)
|
|
+static int sbrmi_probe(struct i2c_client *client)
|
|
{
|
|
struct device *dev = &client->dev;
|
|
struct device *hwmon_dev;
|
|
@@ -348,7 +347,7 @@ static struct i2c_driver sbrmi_driver =
|
|
.name = "sbrmi",
|
|
.of_match_table = of_match_ptr(sbrmi_of_match),
|
|
},
|
|
- .probe = sbrmi_probe,
|
|
+ .probe_new = sbrmi_probe,
|
|
.id_table = sbrmi_id,
|
|
};
|
|
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/sbtsi_temp.c linux-6.1.2/drivers/hwmon/sbtsi_temp.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/sbtsi_temp.c 2022-12-31 16:12:06.942585573 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/sbtsi_temp.c 2022-12-31 16:19:46.453248935 -0500
|
|
@@ -199,8 +199,7 @@ static const struct hwmon_chip_info sbts
|
|
.info = sbtsi_info,
|
|
};
|
|
|
|
-static int sbtsi_probe(struct i2c_client *client,
|
|
- const struct i2c_device_id *id)
|
|
+static int sbtsi_probe(struct i2c_client *client)
|
|
{
|
|
struct device *dev = &client->dev;
|
|
struct device *hwmon_dev;
|
|
@@ -239,7 +238,7 @@ static struct i2c_driver sbtsi_driver =
|
|
.name = "sbtsi",
|
|
.of_match_table = of_match_ptr(sbtsi_of_match),
|
|
},
|
|
- .probe = sbtsi_probe,
|
|
+ .probe_new = sbtsi_probe,
|
|
.id_table = sbtsi_id,
|
|
};
|
|
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/sht3x.c linux-6.1.2/drivers/hwmon/sht3x.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/sht3x.c 2022-12-31 16:12:06.942585573 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/sht3x.c 2022-12-31 16:19:55.385168045 -0500
|
|
@@ -320,7 +320,7 @@ static ssize_t temp1_limit_show(struct d
|
|
u8 index = to_sensor_dev_attr(attr)->index;
|
|
int temperature_limit = data->temperature_limits[index];
|
|
|
|
- return scnprintf(buf, PAGE_SIZE, "%d\n", temperature_limit);
|
|
+ return sysfs_emit(buf, "%d\n", temperature_limit);
|
|
}
|
|
|
|
static ssize_t humidity1_limit_show(struct device *dev,
|
|
@@ -331,7 +331,7 @@ static ssize_t humidity1_limit_show(stru
|
|
u8 index = to_sensor_dev_attr(attr)->index;
|
|
u32 humidity_limit = data->humidity_limits[index];
|
|
|
|
- return scnprintf(buf, PAGE_SIZE, "%u\n", humidity_limit);
|
|
+ return sysfs_emit(buf, "%u\n", humidity_limit);
|
|
}
|
|
|
|
/*
|
|
@@ -483,7 +483,7 @@ static ssize_t temp1_alarm_show(struct d
|
|
if (ret)
|
|
return ret;
|
|
|
|
- return scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x04));
|
|
+ return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x04));
|
|
}
|
|
|
|
static ssize_t humidity1_alarm_show(struct device *dev,
|
|
@@ -498,7 +498,7 @@ static ssize_t humidity1_alarm_show(stru
|
|
if (ret)
|
|
return ret;
|
|
|
|
- return scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x08));
|
|
+ return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x08));
|
|
}
|
|
|
|
static ssize_t heater_enable_show(struct device *dev,
|
|
@@ -513,7 +513,7 @@ static ssize_t heater_enable_show(struct
|
|
if (ret)
|
|
return ret;
|
|
|
|
- return scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x20));
|
|
+ return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x20));
|
|
}
|
|
|
|
static ssize_t heater_enable_store(struct device *dev,
|
|
@@ -550,7 +550,7 @@ static ssize_t update_interval_show(stru
|
|
{
|
|
struct sht3x_data *data = dev_get_drvdata(dev);
|
|
|
|
- return scnprintf(buf, PAGE_SIZE, "%u\n",
|
|
+ return sysfs_emit(buf, "%u\n",
|
|
mode_to_update_interval[data->mode]);
|
|
}
|
|
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/sht4x.c linux-6.1.2/drivers/hwmon/sht4x.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/sht4x.c 2022-12-31 16:12:06.942585573 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/sht4x.c 2022-12-31 16:19:46.457248898 -0500
|
|
@@ -232,8 +232,7 @@ static const struct hwmon_chip_info sht4
|
|
.info = sht4x_info,
|
|
};
|
|
|
|
-static int sht4x_probe(struct i2c_client *client,
|
|
- const struct i2c_device_id *sht4x_id)
|
|
+static int sht4x_probe(struct i2c_client *client)
|
|
{
|
|
struct device *device = &client->dev;
|
|
struct device *hwmon_dev;
|
|
@@ -292,7 +291,7 @@ static struct i2c_driver sht4x_driver =
|
|
.name = "sht4x",
|
|
.of_match_table = sht4x_of_match,
|
|
},
|
|
- .probe = sht4x_probe,
|
|
+ .probe_new = sht4x_probe,
|
|
.id_table = sht4x_id,
|
|
};
|
|
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/smpro-hwmon.c linux-6.1.2/drivers/hwmon/smpro-hwmon.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/smpro-hwmon.c 1969-12-31 19:00:00.000000000 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/smpro-hwmon.c 2022-12-31 16:19:53.945181044 -0500
|
|
@@ -0,0 +1,466 @@
|
|
+// SPDX-License-Identifier: GPL-2.0-only
|
|
+/*
|
|
+ * Ampere Computing SoC's SMPro Hardware Monitoring Driver
|
|
+ *
|
|
+ * Copyright (c) 2022, Ampere Computing LLC
|
|
+ */
|
|
+#include <linux/bitfield.h>
|
|
+#include <linux/bitops.h>
|
|
+#include <linux/hwmon.h>
|
|
+#include <linux/hwmon-sysfs.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/mod_devicetable.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/property.h>
|
|
+#include <linux/regmap.h>
|
|
+
|
|
+/* Logical Power Sensor Registers */
|
|
+#define SOC_TEMP 0x10
|
|
+#define SOC_VRD_TEMP 0x11
|
|
+#define DIMM_VRD_TEMP 0x12
|
|
+#define CORE_VRD_TEMP 0x13
|
|
+#define CH0_DIMM_TEMP 0x14
|
|
+#define CH1_DIMM_TEMP 0x15
|
|
+#define CH2_DIMM_TEMP 0x16
|
|
+#define CH3_DIMM_TEMP 0x17
|
|
+#define CH4_DIMM_TEMP 0x18
|
|
+#define CH5_DIMM_TEMP 0x19
|
|
+#define CH6_DIMM_TEMP 0x1A
|
|
+#define CH7_DIMM_TEMP 0x1B
|
|
+#define RCA_VRD_TEMP 0x1C
|
|
+
|
|
+#define CORE_VRD_PWR 0x20
|
|
+#define SOC_PWR 0x21
|
|
+#define DIMM_VRD1_PWR 0x22
|
|
+#define DIMM_VRD2_PWR 0x23
|
|
+#define CORE_VRD_PWR_MW 0x26
|
|
+#define SOC_PWR_MW 0x27
|
|
+#define DIMM_VRD1_PWR_MW 0x28
|
|
+#define DIMM_VRD2_PWR_MW 0x29
|
|
+#define RCA_VRD_PWR 0x2A
|
|
+#define RCA_VRD_PWR_MW 0x2B
|
|
+
|
|
+#define MEM_HOT_THRESHOLD 0x32
|
|
+#define SOC_VR_HOT_THRESHOLD 0x33
|
|
+#define CORE_VRD_VOLT 0x34
|
|
+#define SOC_VRD_VOLT 0x35
|
|
+#define DIMM_VRD1_VOLT 0x36
|
|
+#define DIMM_VRD2_VOLT 0x37
|
|
+#define RCA_VRD_VOLT 0x38
|
|
+
|
|
+#define CORE_VRD_CURR 0x39
|
|
+#define SOC_VRD_CURR 0x3A
|
|
+#define DIMM_VRD1_CURR 0x3B
|
|
+#define DIMM_VRD2_CURR 0x3C
|
|
+#define RCA_VRD_CURR 0x3D
|
|
+
|
|
+struct smpro_hwmon {
|
|
+ struct regmap *regmap;
|
|
+};
|
|
+
|
|
+struct smpro_sensor {
|
|
+ const u8 reg;
|
|
+ const u8 reg_ext;
|
|
+ const char *label;
|
|
+};
|
|
+
|
|
+static const struct smpro_sensor temperature[] = {
|
|
+ {
|
|
+ .reg = SOC_TEMP,
|
|
+ .label = "temp1 SoC"
|
|
+ },
|
|
+ {
|
|
+ .reg = SOC_VRD_TEMP,
|
|
+ .reg_ext = SOC_VR_HOT_THRESHOLD,
|
|
+ .label = "temp2 SoC VRD"
|
|
+ },
|
|
+ {
|
|
+ .reg = DIMM_VRD_TEMP,
|
|
+ .label = "temp3 DIMM VRD"
|
|
+ },
|
|
+ {
|
|
+ .reg = CORE_VRD_TEMP,
|
|
+ .label = "temp4 CORE VRD"
|
|
+ },
|
|
+ {
|
|
+ .reg = CH0_DIMM_TEMP,
|
|
+ .reg_ext = MEM_HOT_THRESHOLD,
|
|
+ .label = "temp5 CH0 DIMM"
|
|
+ },
|
|
+ {
|
|
+ .reg = CH1_DIMM_TEMP,
|
|
+ .reg_ext = MEM_HOT_THRESHOLD,
|
|
+ .label = "temp6 CH1 DIMM"
|
|
+ },
|
|
+ {
|
|
+ .reg = CH2_DIMM_TEMP,
|
|
+ .reg_ext = MEM_HOT_THRESHOLD,
|
|
+ .label = "temp7 CH2 DIMM"
|
|
+ },
|
|
+ {
|
|
+ .reg = CH3_DIMM_TEMP,
|
|
+ .reg_ext = MEM_HOT_THRESHOLD,
|
|
+ .label = "temp8 CH3 DIMM"
|
|
+ },
|
|
+ {
|
|
+ .reg = CH4_DIMM_TEMP,
|
|
+ .reg_ext = MEM_HOT_THRESHOLD,
|
|
+ .label = "temp9 CH4 DIMM"
|
|
+ },
|
|
+ {
|
|
+ .reg = CH5_DIMM_TEMP,
|
|
+ .reg_ext = MEM_HOT_THRESHOLD,
|
|
+ .label = "temp10 CH5 DIMM"
|
|
+ },
|
|
+ {
|
|
+ .reg = CH6_DIMM_TEMP,
|
|
+ .reg_ext = MEM_HOT_THRESHOLD,
|
|
+ .label = "temp11 CH6 DIMM"
|
|
+ },
|
|
+ {
|
|
+ .reg = CH7_DIMM_TEMP,
|
|
+ .reg_ext = MEM_HOT_THRESHOLD,
|
|
+ .label = "temp12 CH7 DIMM"
|
|
+ },
|
|
+ {
|
|
+ .reg = RCA_VRD_TEMP,
|
|
+ .label = "temp13 RCA VRD"
|
|
+ },
|
|
+};
|
|
+
|
|
+static const struct smpro_sensor voltage[] = {
|
|
+ {
|
|
+ .reg = CORE_VRD_VOLT,
|
|
+ .label = "vout0 CORE VRD"
|
|
+ },
|
|
+ {
|
|
+ .reg = SOC_VRD_VOLT,
|
|
+ .label = "vout1 SoC VRD"
|
|
+ },
|
|
+ {
|
|
+ .reg = DIMM_VRD1_VOLT,
|
|
+ .label = "vout2 DIMM VRD1"
|
|
+ },
|
|
+ {
|
|
+ .reg = DIMM_VRD2_VOLT,
|
|
+ .label = "vout3 DIMM VRD2"
|
|
+ },
|
|
+ {
|
|
+ .reg = RCA_VRD_VOLT,
|
|
+ .label = "vout4 RCA VRD"
|
|
+ },
|
|
+};
|
|
+
|
|
+static const struct smpro_sensor curr_sensor[] = {
|
|
+ {
|
|
+ .reg = CORE_VRD_CURR,
|
|
+ .label = "iout1 CORE VRD"
|
|
+ },
|
|
+ {
|
|
+ .reg = SOC_VRD_CURR,
|
|
+ .label = "iout2 SoC VRD"
|
|
+ },
|
|
+ {
|
|
+ .reg = DIMM_VRD1_CURR,
|
|
+ .label = "iout3 DIMM VRD1"
|
|
+ },
|
|
+ {
|
|
+ .reg = DIMM_VRD2_CURR,
|
|
+ .label = "iout4 DIMM VRD2"
|
|
+ },
|
|
+ {
|
|
+ .reg = RCA_VRD_CURR,
|
|
+ .label = "iout5 RCA VRD"
|
|
+ },
|
|
+};
|
|
+
|
|
+static const struct smpro_sensor power[] = {
|
|
+ {
|
|
+ .reg = CORE_VRD_PWR,
|
|
+ .reg_ext = CORE_VRD_PWR_MW,
|
|
+ .label = "power1 CORE VRD"
|
|
+ },
|
|
+ {
|
|
+ .reg = SOC_PWR,
|
|
+ .reg_ext = SOC_PWR_MW,
|
|
+ .label = "power2 SoC"
|
|
+ },
|
|
+ {
|
|
+ .reg = DIMM_VRD1_PWR,
|
|
+ .reg_ext = DIMM_VRD1_PWR_MW,
|
|
+ .label = "power3 DIMM VRD1"
|
|
+ },
|
|
+ {
|
|
+ .reg = DIMM_VRD2_PWR,
|
|
+ .reg_ext = DIMM_VRD2_PWR_MW,
|
|
+ .label = "power4 DIMM VRD2"
|
|
+ },
|
|
+ {
|
|
+ .reg = RCA_VRD_PWR,
|
|
+ .reg_ext = RCA_VRD_PWR_MW,
|
|
+ .label = "power5 RCA VRD"
|
|
+ },
|
|
+};
|
|
+
|
|
+static int smpro_read_temp(struct device *dev, u32 attr, int channel, long *val)
|
|
+{
|
|
+ struct smpro_hwmon *hwmon = dev_get_drvdata(dev);
|
|
+ unsigned int value;
|
|
+ int ret;
|
|
+
|
|
+ switch (attr) {
|
|
+ case hwmon_temp_input:
|
|
+ ret = regmap_read(hwmon->regmap, temperature[channel].reg, &value);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ break;
|
|
+ case hwmon_temp_crit:
|
|
+ ret = regmap_read(hwmon->regmap, temperature[channel].reg_ext, &value);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ break;
|
|
+ default:
|
|
+ return -EOPNOTSUPP;
|
|
+ }
|
|
+
|
|
+ *val = sign_extend32(value, 8) * 1000;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int smpro_read_in(struct device *dev, u32 attr, int channel, long *val)
|
|
+{
|
|
+ struct smpro_hwmon *hwmon = dev_get_drvdata(dev);
|
|
+ unsigned int value;
|
|
+ int ret;
|
|
+
|
|
+ switch (attr) {
|
|
+ case hwmon_in_input:
|
|
+ ret = regmap_read(hwmon->regmap, voltage[channel].reg, &value);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ /* 15-bit value in 1mV */
|
|
+ *val = value & 0x7fff;
|
|
+ return 0;
|
|
+ default:
|
|
+ return -EOPNOTSUPP;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int smpro_read_curr(struct device *dev, u32 attr, int channel, long *val)
|
|
+{
|
|
+ struct smpro_hwmon *hwmon = dev_get_drvdata(dev);
|
|
+ unsigned int value;
|
|
+ int ret;
|
|
+
|
|
+ switch (attr) {
|
|
+ case hwmon_curr_input:
|
|
+ ret = regmap_read(hwmon->regmap, curr_sensor[channel].reg, &value);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ /* Scale reported by the hardware is 1mA */
|
|
+ *val = value & 0x7fff;
|
|
+ return 0;
|
|
+ default:
|
|
+ return -EOPNOTSUPP;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int smpro_read_power(struct device *dev, u32 attr, int channel, long *val_pwr)
|
|
+{
|
|
+ struct smpro_hwmon *hwmon = dev_get_drvdata(dev);
|
|
+ unsigned int val = 0, val_mw = 0;
|
|
+ int ret;
|
|
+
|
|
+ switch (attr) {
|
|
+ case hwmon_power_input:
|
|
+ ret = regmap_read(hwmon->regmap, power[channel].reg, &val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = regmap_read(hwmon->regmap, power[channel].reg_ext, &val_mw);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ /* 10-bit value */
|
|
+ *val_pwr = (val & 0x3ff) * 1000000 + (val_mw & 0x3ff) * 1000;
|
|
+ return 0;
|
|
+
|
|
+ default:
|
|
+ return -EOPNOTSUPP;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int smpro_read(struct device *dev, enum hwmon_sensor_types type,
|
|
+ u32 attr, int channel, long *val)
|
|
+{
|
|
+ switch (type) {
|
|
+ case hwmon_temp:
|
|
+ return smpro_read_temp(dev, attr, channel, val);
|
|
+ case hwmon_in:
|
|
+ return smpro_read_in(dev, attr, channel, val);
|
|
+ case hwmon_power:
|
|
+ return smpro_read_power(dev, attr, channel, val);
|
|
+ case hwmon_curr:
|
|
+ return smpro_read_curr(dev, attr, channel, val);
|
|
+ default:
|
|
+ return -EOPNOTSUPP;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int smpro_read_string(struct device *dev, enum hwmon_sensor_types type,
|
|
+ u32 attr, int channel, const char **str)
|
|
+{
|
|
+ switch (type) {
|
|
+ case hwmon_temp:
|
|
+ switch (attr) {
|
|
+ case hwmon_temp_label:
|
|
+ *str = temperature[channel].label;
|
|
+ return 0;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case hwmon_in:
|
|
+ switch (attr) {
|
|
+ case hwmon_in_label:
|
|
+ *str = voltage[channel].label;
|
|
+ return 0;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case hwmon_curr:
|
|
+ switch (attr) {
|
|
+ case hwmon_curr_label:
|
|
+ *str = curr_sensor[channel].label;
|
|
+ return 0;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case hwmon_power:
|
|
+ switch (attr) {
|
|
+ case hwmon_power_label:
|
|
+ *str = power[channel].label;
|
|
+ return 0;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return -EOPNOTSUPP;
|
|
+}
|
|
+
|
|
+static umode_t smpro_is_visible(const void *data, enum hwmon_sensor_types type,
|
|
+ u32 attr, int channel)
|
|
+{
|
|
+ const struct smpro_hwmon *hwmon = data;
|
|
+ unsigned int value;
|
|
+ int ret;
|
|
+
|
|
+ switch (type) {
|
|
+ case hwmon_temp:
|
|
+ switch (attr) {
|
|
+ case hwmon_temp_input:
|
|
+ case hwmon_temp_label:
|
|
+ case hwmon_temp_crit:
|
|
+ ret = regmap_read(hwmon->regmap, temperature[channel].reg, &value);
|
|
+ if (ret || value == 0xFFFF)
|
|
+ return 0;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return 0444;
|
|
+}
|
|
+
|
|
+static const struct hwmon_channel_info *smpro_info[] = {
|
|
+ HWMON_CHANNEL_INFO(temp,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
|
|
+ HWMON_T_INPUT | HWMON_T_LABEL),
|
|
+ HWMON_CHANNEL_INFO(in,
|
|
+ HWMON_I_INPUT | HWMON_I_LABEL,
|
|
+ HWMON_I_INPUT | HWMON_I_LABEL,
|
|
+ HWMON_I_INPUT | HWMON_I_LABEL,
|
|
+ HWMON_I_INPUT | HWMON_I_LABEL,
|
|
+ HWMON_I_INPUT | HWMON_I_LABEL),
|
|
+ HWMON_CHANNEL_INFO(power,
|
|
+ HWMON_P_INPUT | HWMON_P_LABEL,
|
|
+ HWMON_P_INPUT | HWMON_P_LABEL,
|
|
+ HWMON_P_INPUT | HWMON_P_LABEL,
|
|
+ HWMON_P_INPUT | HWMON_P_LABEL,
|
|
+ HWMON_P_INPUT | HWMON_P_LABEL),
|
|
+ HWMON_CHANNEL_INFO(curr,
|
|
+ HWMON_C_INPUT | HWMON_C_LABEL,
|
|
+ HWMON_C_INPUT | HWMON_C_LABEL,
|
|
+ HWMON_C_INPUT | HWMON_C_LABEL,
|
|
+ HWMON_C_INPUT | HWMON_C_LABEL,
|
|
+ HWMON_C_INPUT | HWMON_C_LABEL),
|
|
+ NULL
|
|
+};
|
|
+
|
|
+static const struct hwmon_ops smpro_hwmon_ops = {
|
|
+ .is_visible = smpro_is_visible,
|
|
+ .read = smpro_read,
|
|
+ .read_string = smpro_read_string,
|
|
+};
|
|
+
|
|
+static const struct hwmon_chip_info smpro_chip_info = {
|
|
+ .ops = &smpro_hwmon_ops,
|
|
+ .info = smpro_info,
|
|
+};
|
|
+
|
|
+static int smpro_hwmon_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct smpro_hwmon *hwmon;
|
|
+ struct device *hwmon_dev;
|
|
+
|
|
+ hwmon = devm_kzalloc(&pdev->dev, sizeof(struct smpro_hwmon), GFP_KERNEL);
|
|
+ if (!hwmon)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ hwmon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
|
+ if (!hwmon->regmap)
|
|
+ return -ENODEV;
|
|
+
|
|
+ hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, "smpro_hwmon",
|
|
+ hwmon, &smpro_chip_info, NULL);
|
|
+
|
|
+ return PTR_ERR_OR_ZERO(hwmon_dev);
|
|
+}
|
|
+
|
|
+static struct platform_driver smpro_hwmon_driver = {
|
|
+ .probe = smpro_hwmon_probe,
|
|
+ .driver = {
|
|
+ .name = "smpro-hwmon",
|
|
+ },
|
|
+};
|
|
+
|
|
+module_platform_driver(smpro_hwmon_driver);
|
|
+
|
|
+MODULE_AUTHOR("Thu Nguyen <thu@os.amperecomputing.com>");
|
|
+MODULE_AUTHOR("Quan Nguyen <quan@os.amperecomputing.com>");
|
|
+MODULE_DESCRIPTION("Ampere Altra SMPro hwmon driver");
|
|
+MODULE_LICENSE("GPL");
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/vt8231.c linux-6.1.2/drivers/hwmon/vt8231.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/vt8231.c 2022-12-31 16:12:06.942585573 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/vt8231.c 2022-12-31 16:19:53.953180971 -0500
|
|
@@ -22,7 +22,6 @@
|
|
#include <linux/platform_device.h>
|
|
#include <linux/hwmon.h>
|
|
#include <linux/hwmon-sysfs.h>
|
|
-#include <linux/hwmon-vid.h>
|
|
#include <linux/err.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/acpi.h>
|
|
diff -rupN linux-6.1.2.orig/drivers/hwmon/w83l786ng.c linux-6.1.2/drivers/hwmon/w83l786ng.c
|
|
--- linux-6.1.2.orig/drivers/hwmon/w83l786ng.c 2022-12-31 16:12:06.942585573 -0500
|
|
+++ linux-6.1.2/drivers/hwmon/w83l786ng.c 2022-12-31 16:19:53.953180971 -0500
|
|
@@ -16,7 +16,6 @@
|
|
#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>
|
|
diff -rupN linux-6.1.2.orig/include/linux/hwmon-sysfs.h linux-6.1.2/include/linux/hwmon-sysfs.h
|
|
--- linux-6.1.2.orig/include/linux/hwmon-sysfs.h 2022-12-31 16:12:07.878571532 -0500
|
|
+++ linux-6.1.2/include/linux/hwmon-sysfs.h 2022-12-31 16:19:53.949181008 -0500
|
|
@@ -8,6 +8,7 @@
|
|
#define _LINUX_HWMON_SYSFS_H
|
|
|
|
#include <linux/device.h>
|
|
+#include <linux/kstrtox.h>
|
|
|
|
struct sensor_device_attribute{
|
|
struct device_attribute dev_attr;
|
|
diff -rupN linux-6.1.2.orig/include/linux/platform_data/gsc_hwmon.h linux-6.1.2/include/linux/platform_data/gsc_hwmon.h
|
|
--- linux-6.1.2.orig/include/linux/platform_data/gsc_hwmon.h 2022-12-31 16:12:07.910571053 -0500
|
|
+++ linux-6.1.2/include/linux/platform_data/gsc_hwmon.h 2022-12-31 16:19:55.381168081 -0500
|
|
@@ -29,18 +29,17 @@ struct gsc_hwmon_channel {
|
|
|
|
/**
|
|
* struct gsc_hwmon_platform_data - platform data for gsc_hwmon driver
|
|
- * @channels: pointer to array of gsc_hwmon_channel structures
|
|
- * describing channels
|
|
* @nchannels: number of elements in @channels array
|
|
* @vreference: voltage reference (mV)
|
|
* @resolution: ADC bit resolution
|
|
* @fan_base: register base for FAN controller
|
|
+ * @channels: array of gsc_hwmon_channel structures describing channels
|
|
*/
|
|
struct gsc_hwmon_platform_data {
|
|
- const struct gsc_hwmon_channel *channels;
|
|
int nchannels;
|
|
unsigned int resolution;
|
|
unsigned int vreference;
|
|
unsigned int fan_base;
|
|
+ struct gsc_hwmon_channel channels[];
|
|
};
|
|
#endif
|
|
diff -rupN linux-6.1.2.orig/MAINTAINERS linux-6.1.2/MAINTAINERS
|
|
--- linux-6.1.2.orig/MAINTAINERS 2022-12-31 16:12:05.838602157 -0500
|
|
+++ linux-6.1.2/MAINTAINERS 2022-12-31 16:19:53.953180971 -0500
|
|
@@ -15345,6 +15345,12 @@ S: Maintained
|
|
F: drivers/mtd/nand/onenand/
|
|
F: include/linux/mtd/onenand*.h
|
|
|
|
+ONEXPLAYER FAN DRIVER
|
|
+M: Joaquín Ignacio Aramendía <samsagax@gmail.com>
|
|
+L: linux-hwmon@vger.kernel.org
|
|
+S: Maintained
|
|
+F: drivers/hwmon/oxp-sensors.c
|
|
+
|
|
ONION OMEGA2+ BOARD
|
|
M: Harvey Hunt <harveyhuntnexus@gmail.com>
|
|
L: linux-mips@vger.kernel.org
|