Commit 4d03390b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'hwmon-for-v6.2-rc1' of...

Merge tag 'hwmon-for-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging

Pull hwmon updates from Guenter Roeck:
 "New drivers:

   - Driver for OneXPlayer mini AMD sensors

   - Ampere's Altra smpro-hwmon driver

  New chip and attribute support in existing drivers:

   - nct6775: Support for ASUS CROSSHAIR VIII/TUF/ProArt B550M

   - pmbus/ltc2978: Support for LTC7132

   - aquacomputer_d5next: Support for temperature sensor offsets and
     flow sensor pulses

   - coretemp: Support for dynamic ttarget and tjmax

  Improvements:

   - Use devm_regulator_get_enable() where appropriate

   - Use sysfs_emit() instead of scnprintf()

   - Remove some useless #include <linux/hwmon-vid.h>

   - Include <linux/kstrtox.h> when appropriate

   - Use simple i2c probe

   - it87: Check for a valid chip before using force_id, and new new
     module parameter to ignore ACPI resource conflicts

   - jc42: Use regmap, and restore min/max/critical temperatures on
     resume

   - Add reporting power good and status to PMBus based regulators

  Last minute fixes:

   - emc2305: Fix probing of emc2301/2/3, and fix setting pwm values
     manually if THERMAL is enabled

  And various other minor fixes and improvements"

* tag 'hwmon-for-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (37 commits)
  hwmon: (emc2305) fix pwm never being able to set lower
  hwmon: (emc2305) fix unable to probe emc2301/2/3
  hwmon: (dell-smm) Move error message to make probing silent
  hwmon: use sysfs_emit() to instead of scnprintf()
  hwmon: (oxp-sensors) Fix pwm reading
  hwmon: (aquacomputer_d5next) Add support for Quadro flow sensor pulses
  hwmon: (pmbus/core) Implement regulator get_status
  hwmon: (oxp-sensors) Add AOK ZOE and Mini PRO
  hwmon: (gsc-hwmon) Switch to flexible array to simplify code
  hwmon: (pmbus) Add power good support
  hwmon: (nct6775) add ASUS CROSSHAIR VIII/TUF/ProArt B550M
  hwmon: (coretemp) Add support for dynamic ttarget
  hwmon: (coretemp) Add support for dynamic tjmax
  hwmon: (coretemp) rearrange tjmax handing code
  hwmon: Remove some useless #include <linux/hwmon-vid.h>
  hwmon: (coretemp) Remove obsolete temp_data->valid
  hwmon: add OneXPlayer mini AMD sensors driver
  hwmon: (aquacomputer_d5next) Clear up macros and comments
  hwmon: (it87) Add DMI table for future extensions
  hwmon: Include <linux/kstrtox.h> when appropriate
  ...
parents 361c89a0 364ffd25
...@@ -39,7 +39,7 @@ current. ...@@ -39,7 +39,7 @@ current.
The Quadro exposes four physical and sixteen virtual temperature sensors, a flow 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, 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, The Farbwerk and Farbwerk 360 expose four temperature sensors. Additionally,
sixteen virtual temperature sensors of the Farbwerk 360 are exposed. sixteen virtual temperature sensors of the Farbwerk 360 are exposed.
...@@ -62,7 +62,9 @@ Sysfs entries ...@@ -62,7 +62,9 @@ Sysfs entries
================ ============================================================== ================ ==============================================================
temp[1-20]_input Physical/virtual temperature sensors (in millidegrees Celsius) 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) 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) power[1-8]_input Pump/fan power (in micro Watts)
in[0-7]_input Pump/fan voltage (in milli Volts) in[0-7]_input Pump/fan voltage (in milli Volts)
curr[1-8]_input Pump/fan current (in milli Amperes) curr[1-8]_input Pump/fan current (in milli Amperes)
......
...@@ -160,6 +160,7 @@ Hardware Monitoring Kernel Drivers ...@@ -160,6 +160,7 @@ Hardware Monitoring Kernel Drivers
nzxt-kraken2 nzxt-kraken2
nzxt-smart2 nzxt-smart2
occ occ
oxp-sensors
pc87360 pc87360
pc87427 pc87427
pcf8591 pcf8591
...@@ -187,6 +188,7 @@ Hardware Monitoring Kernel Drivers ...@@ -187,6 +188,7 @@ Hardware Monitoring Kernel Drivers
sis5595 sis5595
sl28cpld sl28cpld
smm665 smm665
smpro-hwmon
smsc47b397 smsc47b397
smsc47m192 smsc47m192
smsc47m1 smsc47m1
......
.. 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.
.. 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
...@@ -15452,6 +15452,12 @@ S: Maintained ...@@ -15452,6 +15452,12 @@ S: Maintained
F: drivers/mtd/nand/onenand/ F: drivers/mtd/nand/onenand/
F: include/linux/mtd/onenand*.h 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 ONION OMEGA2+ BOARD
M: Harvey Hunt <harveyhuntnexus@gmail.com> M: Harvey Hunt <harveyhuntnexus@gmail.com>
L: linux-mips@vger.kernel.org L: linux-mips@vger.kernel.org
......
...@@ -67,6 +67,14 @@ config SENSORS_ABITUGURU3 ...@@ -67,6 +67,14 @@ config SENSORS_ABITUGURU3
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called abituguru3. 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 config SENSORS_AD7314
tristate "Analog Devices AD7314 and compatibles" tristate "Analog Devices AD7314 and compatibles"
depends on SPI depends on SPI
...@@ -799,6 +807,7 @@ config SENSORS_IT87 ...@@ -799,6 +807,7 @@ config SENSORS_IT87
config SENSORS_JC42 config SENSORS_JC42
tristate "JEDEC JC42.4 compliant memory module temperature sensors" tristate "JEDEC JC42.4 compliant memory module temperature sensors"
depends on I2C depends on I2C
select REGMAP_I2C
help help
If you say yes here, you get support for JEDEC JC42.4 compliant If you say yes here, you get support for JEDEC JC42.4 compliant
temperature sensors, which are used on many DDR3 memory modules for temperature sensors, which are used on many DDR3 memory modules for
...@@ -1607,6 +1616,17 @@ config SENSORS_NZXT_SMART2 ...@@ -1607,6 +1616,17 @@ config SENSORS_NZXT_SMART2
source "drivers/hwmon/occ/Kconfig" 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 config SENSORS_PCF8591
tristate "Philips PCF8591 ADC/DAC" tristate "Philips PCF8591 ADC/DAC"
depends on I2C depends on I2C
......
...@@ -167,6 +167,7 @@ obj-$(CONFIG_SENSORS_NSA320) += nsa320-hwmon.o ...@@ -167,6 +167,7 @@ obj-$(CONFIG_SENSORS_NSA320) += nsa320-hwmon.o
obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
obj-$(CONFIG_SENSORS_NZXT_KRAKEN2) += nzxt-kraken2.o obj-$(CONFIG_SENSORS_NZXT_KRAKEN2) += nzxt-kraken2.o
obj-$(CONFIG_SENSORS_NZXT_SMART2) += nzxt-smart2.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_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
...@@ -187,6 +188,7 @@ obj-$(CONFIG_SENSORS_SHT4x) += sht4x.o ...@@ -187,6 +188,7 @@ obj-$(CONFIG_SENSORS_SHT4x) += sht4x.o
obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
obj-$(CONFIG_SENSORS_SMM665) += smm665.o obj-$(CONFIG_SENSORS_SMM665) += smm665.o
obj-$(CONFIG_SENSORS_SMPRO) += smpro-hwmon.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
......
...@@ -26,14 +26,12 @@ ...@@ -26,14 +26,12 @@
/** /**
* struct adm1177_state - driver instance specific data * struct adm1177_state - driver instance specific data
* @client: pointer to i2c client * @client: pointer to i2c client
* @reg: regulator info for the power supply of the device
* @r_sense_uohm: current sense resistor value * @r_sense_uohm: current sense resistor value
* @alert_threshold_ua: current limit for shutdown * @alert_threshold_ua: current limit for shutdown
* @vrange_high: internal voltage divider * @vrange_high: internal voltage divider
*/ */
struct adm1177_state { struct adm1177_state {
struct i2c_client *client; struct i2c_client *client;
struct regulator *reg;
u32 r_sense_uohm; u32 r_sense_uohm;
u32 alert_threshold_ua; u32 alert_threshold_ua;
bool vrange_high; bool vrange_high;
...@@ -189,13 +187,6 @@ static const struct hwmon_chip_info adm1177_chip_info = { ...@@ -189,13 +187,6 @@ static const struct hwmon_chip_info adm1177_chip_info = {
.info = adm1177_info, .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) static int adm1177_probe(struct i2c_client *client)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
...@@ -210,21 +201,9 @@ static int adm1177_probe(struct i2c_client *client) ...@@ -210,21 +201,9 @@ static int adm1177_probe(struct i2c_client *client)
st->client = client; st->client = client;
st->reg = devm_regulator_get_optional(&client->dev, "vref"); ret = devm_regulator_get_enable_optional(&client->dev, "vref");
if (IS_ERR(st->reg)) { if (ret == -EPROBE_DEFER)
if (PTR_ERR(st->reg) == -EPROBE_DEFER) return -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;
}
if (device_property_read_u32(dev, "shunt-resistor-micro-ohms", if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",
&st->r_sense_uohm)) &st->r_sense_uohm))
......
...@@ -289,8 +289,7 @@ static const struct hwmon_chip_info aht10_chip_info = { ...@@ -289,8 +289,7 @@ static const struct hwmon_chip_info aht10_chip_info = {
.info = aht10_info, .info = aht10_info,
}; };
static int aht10_probe(struct i2c_client *client, static int aht10_probe(struct i2c_client *client)
const struct i2c_device_id *aht10_id)
{ {
struct device *device = &client->dev; struct device *device = &client->dev;
struct device *hwmon_dev; struct device *hwmon_dev;
...@@ -336,7 +335,7 @@ static struct i2c_driver aht10_driver = { ...@@ -336,7 +335,7 @@ static struct i2c_driver aht10_driver = {
.driver = { .driver = {
.name = "aht10", .name = "aht10",
}, },
.probe = aht10_probe, .probe_new = aht10_probe,
.id_table = aht10_id, .id_table = aht10_id,
}; };
......
This diff is collapsed.
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h> #include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/kstrtox.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/slab.h> #include <linux/slab.h>
......
This diff is collapsed.
...@@ -1447,9 +1447,10 @@ static int __init i8k_init(void) ...@@ -1447,9 +1447,10 @@ static int __init i8k_init(void)
*/ */
if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) && if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&
i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) { i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {
pr_err("unable to get SMM Dell signature\n");
if (!force) if (!force)
return -ENODEV; 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, dell_smm_device = platform_create_bundle(&dell_smm_driver, dell_smm_probe, NULL, 0, NULL,
......
...@@ -269,7 +269,7 @@ static ssize_t update_interval_show(struct device *dev, ...@@ -269,7 +269,7 @@ static ssize_t update_interval_show(struct device *dev,
struct device_attribute *da, char *buf) struct device_attribute *da, char *buf)
{ {
struct ds1621_data *data = dev_get_drvdata(dev); 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, static ssize_t update_interval_store(struct device *dev,
......
...@@ -16,7 +16,6 @@ static const unsigned short ...@@ -16,7 +16,6 @@ static const unsigned short
emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_END }; emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_END };
#define EMC2305_REG_DRIVE_FAIL_STATUS 0x27 #define EMC2305_REG_DRIVE_FAIL_STATUS 0x27
#define EMC2305_REG_DEVICE 0xfd
#define EMC2305_REG_VENDOR 0xfe #define EMC2305_REG_VENDOR 0xfe
#define EMC2305_FAN_MAX 0xff #define EMC2305_FAN_MAX 0xff
#define EMC2305_FAN_MIN 0x00 #define EMC2305_FAN_MIN 0x00
...@@ -172,22 +171,12 @@ static int emc2305_get_max_state(struct thermal_cooling_device *cdev, unsigned l ...@@ -172,22 +171,12 @@ static int emc2305_get_max_state(struct thermal_cooling_device *cdev, unsigned l
return 0; return 0;
} }
static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) static int __emc2305_set_cur_state(struct emc2305_data *data, int cdev_idx, unsigned long state)
{ {
int cdev_idx, ret; int ret;
struct emc2305_data *data = cdev->devdata;
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
u8 val, i; u8 val, i;
if (state > data->max_state)
return -EINVAL;
cdev_idx = emc2305_get_cdev_idx(cdev);
if (cdev_idx < 0)
return cdev_idx;
/* Save thermal state. */
data->cdev_data[cdev_idx].last_thermal_state = state;
state = max_t(unsigned long, state, data->cdev_data[cdev_idx].last_hwmon_state); state = max_t(unsigned long, state, data->cdev_data[cdev_idx].last_hwmon_state);
val = EMC2305_PWM_STATE2DUTY(state, data->max_state, EMC2305_FAN_MAX); val = EMC2305_PWM_STATE2DUTY(state, data->max_state, EMC2305_FAN_MAX);
...@@ -212,6 +201,27 @@ static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned l ...@@ -212,6 +201,27 @@ static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned l
return 0; return 0;
} }
static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
{
int cdev_idx, ret;
struct emc2305_data *data = cdev->devdata;
if (state > data->max_state)
return -EINVAL;
cdev_idx = emc2305_get_cdev_idx(cdev);
if (cdev_idx < 0)
return cdev_idx;
/* Save thermal state. */
data->cdev_data[cdev_idx].last_thermal_state = state;
ret = __emc2305_set_cur_state(data, cdev_idx, state);
if (ret < 0)
return ret;
return 0;
}
static const struct thermal_cooling_device_ops emc2305_cooling_ops = { static const struct thermal_cooling_device_ops emc2305_cooling_ops = {
.get_max_state = emc2305_get_max_state, .get_max_state = emc2305_get_max_state,
.get_cur_state = emc2305_get_cur_state, .get_cur_state = emc2305_get_cur_state,
...@@ -402,7 +412,7 @@ emc2305_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int ch ...@@ -402,7 +412,7 @@ emc2305_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int ch
*/ */
if (data->cdev_data[cdev_idx].last_hwmon_state >= if (data->cdev_data[cdev_idx].last_hwmon_state >=
data->cdev_data[cdev_idx].last_thermal_state) data->cdev_data[cdev_idx].last_thermal_state)
return emc2305_set_cur_state(data->cdev_data[cdev_idx].cdev, return __emc2305_set_cur_state(data, cdev_idx,
data->cdev_data[cdev_idx].last_hwmon_state); data->cdev_data[cdev_idx].last_hwmon_state);
return 0; return 0;
} }
...@@ -518,13 +528,13 @@ static int emc2305_identify(struct device *dev) ...@@ -518,13 +528,13 @@ static int emc2305_identify(struct device *dev)
return 0; 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 i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct emc2305_data *data; struct emc2305_data *data;
struct emc2305_platform_data *pdata; struct emc2305_platform_data *pdata;
int vendor, device; int vendor;
int ret; int ret;
int i; int i;
...@@ -535,10 +545,6 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id * ...@@ -535,10 +545,6 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id *
if (vendor != EMC2305_VENDOR) if (vendor != EMC2305_VENDOR)
return -ENODEV; return -ENODEV;
device = i2c_smbus_read_byte_data(client, EMC2305_REG_DEVICE);
if (device != EMC2305_DEVICE)
return -ENODEV;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
...@@ -607,7 +613,7 @@ static struct i2c_driver emc2305_driver = { ...@@ -607,7 +613,7 @@ static struct i2c_driver emc2305_driver = {
.driver = { .driver = {
.name = "emc2305", .name = "emc2305",
}, },
.probe = emc2305_probe, .probe_new = emc2305_probe,
.remove = emc2305_remove, .remove = emc2305_remove,
.id_table = emc2305_ids, .id_table = emc2305_ids,
.address_list = emc2305_normal_i2c, .address_list = emc2305_normal_i2c,
......
...@@ -1083,9 +1083,9 @@ static int fschmd_detect(struct i2c_client *client, ...@@ -1083,9 +1083,9 @@ static int fschmd_detect(struct i2c_client *client,
static int fschmd_probe(struct i2c_client *client) static int fschmd_probe(struct i2c_client *client)
{ {
struct fschmd_data *data; 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" }; "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; int i, err;
enum chips kind = i2c_match_id(fschmd_id, client)->driver_data; enum chips kind = i2c_match_id(fschmd_id, client)->driver_data;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/kstrtox.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
......
...@@ -257,13 +257,10 @@ gsc_hwmon_get_devtree_pdata(struct device *dev) ...@@ -257,13 +257,10 @@ gsc_hwmon_get_devtree_pdata(struct device *dev)
if (nchannels == 0) if (nchannels == 0)
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
pdata = devm_kzalloc(dev, pdata = devm_kzalloc(dev, struct_size(pdata, channels, nchannels),
sizeof(*pdata) + nchannels * sizeof(*ch),
GFP_KERNEL); GFP_KERNEL);
if (!pdata) if (!pdata)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ch = (struct gsc_hwmon_channel *)(pdata + 1);
pdata->channels = ch;
pdata->nchannels = nchannels; pdata->nchannels = nchannels;
/* fan controller base address */ /* fan controller base address */
...@@ -277,6 +274,7 @@ gsc_hwmon_get_devtree_pdata(struct device *dev) ...@@ -277,6 +274,7 @@ gsc_hwmon_get_devtree_pdata(struct device *dev)
of_node_put(fan); of_node_put(fan);
ch = pdata->channels;
/* allocate structures for channels and count instances of each type */ /* allocate structures for channels and count instances of each type */
device_for_each_child_node(dev, child) { device_for_each_child_node(dev, child) {
if (fwnode_property_read_string(child, "label", &ch->name)) { if (fwnode_property_read_string(child, "label", &ch->name)) {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/kstrtox.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
......
...@@ -69,6 +69,10 @@ static unsigned short force_id; ...@@ -69,6 +69,10 @@ static unsigned short force_id;
module_param(force_id, ushort, 0); module_param(force_id, ushort, 0);
MODULE_PARM_DESC(force_id, "Override the detected device ID"); 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]; static struct platform_device *it87_pdev[2];
#define REG_2E 0x2e /* The register to read/write */ #define REG_2E 0x2e /* The register to read/write */
...@@ -563,6 +567,14 @@ struct it87_data { ...@@ -563,6 +567,14 @@ struct it87_data {
s8 auto_temp[NUM_AUTO_PWM][5]; /* [nr][0] is point1_temp_hyst */ 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) static int adc_lsb(const struct it87_data *data, int nr)
{ {
int lsb; int lsb;
...@@ -2389,7 +2401,6 @@ static int __init it87_find(int sioaddr, unsigned short *address, ...@@ -2389,7 +2401,6 @@ static int __init it87_find(int sioaddr, unsigned short *address,
{ {
int err; int err;
u16 chip_type; u16 chip_type;
const char *board_vendor, *board_name;
const struct it87_devices *config; const struct it87_devices *config;
err = superio_enter(sioaddr); err = superio_enter(sioaddr);
...@@ -2397,7 +2408,13 @@ static int __init it87_find(int sioaddr, unsigned short *address, ...@@ -2397,7 +2408,13 @@ static int __init it87_find(int sioaddr, unsigned short *address,
return err; return err;
err = -ENODEV; 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) { switch (chip_type) {
case IT8705F_DEVID: case IT8705F_DEVID:
...@@ -2802,24 +2819,9 @@ static int __init it87_find(int sioaddr, unsigned short *address, ...@@ -2802,24 +2819,9 @@ static int __init it87_find(int sioaddr, unsigned short *address,
if (sio_data->beep_pin) if (sio_data->beep_pin)
pr_info("Beeping is supported\n"); pr_info("Beeping is supported\n");
/* Disable specific features based on DMI strings */ /* Set values based on DMI matches */
board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); if (dmi_data)
board_name = dmi_get_system_info(DMI_BOARD_NAME); sio_data->skip_pwm |= dmi_data->skip_pwm;
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);
}
}
exit: exit:
superio_exit(sioaddr); superio_exit(sioaddr);
...@@ -3261,8 +3263,10 @@ static int __init it87_device_add(int index, unsigned short address, ...@@ -3261,8 +3263,10 @@ static int __init it87_device_add(int index, unsigned short address,
int err; int err;
err = acpi_check_resource_conflict(&res); err = acpi_check_resource_conflict(&res);
if (err) if (err) {
return err; if (!ignore_resource_conflict)
return err;
}
pdev = platform_device_alloc(DRVNAME, address); pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) if (!pdev)
...@@ -3295,6 +3299,46 @@ static int __init it87_device_add(int index, unsigned short address, ...@@ -3295,6 +3299,46 @@ static int __init it87_device_add(int index, unsigned short address,
return err; 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) static int __init sm_it87_init(void)
{ {
int sioaddr[2] = { REG_2E, REG_4E }; int sioaddr[2] = { REG_2E, REG_4E };
...@@ -3307,6 +3351,8 @@ static int __init sm_it87_init(void) ...@@ -3307,6 +3351,8 @@ static int __init sm_it87_init(void)
if (err) if (err)
return err; return err;
dmi_check_system(it87_dmi_table);
for (i = 0; i < ARRAY_SIZE(sioaddr); i++) { for (i = 0; i < ARRAY_SIZE(sioaddr); i++) {
memset(&sio_data, 0, sizeof(struct it87_sio_data)); memset(&sio_data, 0, sizeof(struct it87_sio_data));
isa_address[i] = 0; isa_address[i] = 0;
......
This diff is collapsed.
...@@ -92,7 +92,7 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *da, ...@@ -92,7 +92,7 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *da,
/* use integer division instead of equivalent right shift to /* use integer division instead of equivalent right shift to
guarantee arithmetic shift and preserve the sign */ guarantee arithmetic shift and preserve the sign */
temp = (((s16) err) * 250) / 32; 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, static ssize_t convrate_store(struct device *dev, struct device_attribute *da,
...@@ -137,7 +137,7 @@ static ssize_t convrate_show(struct device *dev, struct device_attribute *da, ...@@ -137,7 +137,7 @@ static ssize_t convrate_show(struct device *dev, struct device_attribute *da,
int res; int res;
res = (data->ctrl & LM73_CTRL_RES_MASK) >> LM73_CTRL_RES_SHIFT; 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, static ssize_t maxmin_alarm_show(struct device *dev,
...@@ -154,7 +154,7 @@ static ssize_t maxmin_alarm_show(struct device *dev, ...@@ -154,7 +154,7 @@ static ssize_t maxmin_alarm_show(struct device *dev,
data->ctrl = ctrl; data->ctrl = ctrl;
mutex_unlock(&data->lock); 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: abort:
mutex_unlock(&data->lock); mutex_unlock(&data->lock);
......
...@@ -103,6 +103,7 @@ ...@@ -103,6 +103,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/kstrtox.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/of_device.h> #include <linux/of_device.h>
...@@ -2663,11 +2664,6 @@ static void lm90_remove_pec(void *dev) ...@@ -2663,11 +2664,6 @@ static void lm90_remove_pec(void *dev)
device_remove_file(dev, &dev_attr_pec); 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, static int lm90_probe_channel_from_dt(struct i2c_client *client,
struct device_node *child, struct device_node *child,
struct lm90_data *data) struct lm90_data *data)
...@@ -2749,24 +2745,13 @@ static int lm90_probe(struct i2c_client *client) ...@@ -2749,24 +2745,13 @@ static int lm90_probe(struct i2c_client *client)
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
struct hwmon_channel_info *info; struct hwmon_channel_info *info;
struct regulator *regulator;
struct device *hwmon_dev; struct device *hwmon_dev;
struct lm90_data *data; struct lm90_data *data;
int err; int err;
regulator = devm_regulator_get(dev, "vcc"); err = devm_regulator_get_enable(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);
if (err) 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); data = devm_kzalloc(dev, sizeof(struct lm90_data), GFP_KERNEL);
if (!data) if (!data)
......
...@@ -881,7 +881,7 @@ static int ltc2992_parse_dt(struct ltc2992_state *st) ...@@ -881,7 +881,7 @@ static int ltc2992_parse_dt(struct ltc2992_state *st)
return 0; 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 device *hwmon_dev;
struct ltc2992_state *st; struct ltc2992_state *st;
...@@ -927,7 +927,7 @@ static struct i2c_driver ltc2992_i2c_driver = { ...@@ -927,7 +927,7 @@ static struct i2c_driver ltc2992_i2c_driver = {
.name = "ltc2992", .name = "ltc2992",
.of_match_table = ltc2992_of_match, .of_match_table = ltc2992_of_match,
}, },
.probe = ltc2992_i2c_probe, .probe_new = ltc2992_i2c_probe,
.id_table = ltc2992_i2c_id, .id_table = ltc2992_i2c_id,
}; };
......
...@@ -303,8 +303,7 @@ static const struct hwmon_chip_info max127_chip_info = { ...@@ -303,8 +303,7 @@ static const struct hwmon_chip_info max127_chip_info = {
.info = max127_info, .info = max127_info,
}; };
static int max127_probe(struct i2c_client *client, static int max127_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
int i; int i;
struct device *hwmon_dev; struct device *hwmon_dev;
...@@ -340,7 +339,7 @@ static struct i2c_driver max127_driver = { ...@@ -340,7 +339,7 @@ static struct i2c_driver max127_driver = {
.driver = { .driver = {
.name = "max127", .name = "max127",
}, },
.probe = max127_probe, .probe_new = max127_probe,
.id_table = max127_id, .id_table = max127_id,
}; };
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/kstrtox.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/mutex.h> #include <linux/mutex.h>
......
...@@ -1043,7 +1043,9 @@ static struct platform_device *pdev[2]; ...@@ -1043,7 +1043,9 @@ static struct platform_device *pdev[2];
static const char * const asus_wmi_boards[] = { static const char * const asus_wmi_boards[] = {
"PRO H410T", "PRO H410T",
"ProArt B550-CREATOR",
"ProArt X570-CREATOR WIFI", "ProArt X570-CREATOR WIFI",
"ProArt Z490-CREATOR 10G",
"Pro B550M-C", "Pro B550M-C",
"Pro WS X570-ACE", "Pro WS X570-ACE",
"PRIME B360-PLUS", "PRIME B360-PLUS",
...@@ -1055,8 +1057,10 @@ static const char * const asus_wmi_boards[] = { ...@@ -1055,8 +1057,10 @@ static const char * const asus_wmi_boards[] = {
"PRIME X570-P", "PRIME X570-P",
"PRIME X570-PRO", "PRIME X570-PRO",
"ROG CROSSHAIR VIII DARK HERO", "ROG CROSSHAIR VIII DARK HERO",
"ROG CROSSHAIR VIII EXTREME",
"ROG CROSSHAIR VIII FORMULA", "ROG CROSSHAIR VIII FORMULA",
"ROG CROSSHAIR VIII HERO", "ROG CROSSHAIR VIII HERO",
"ROG CROSSHAIR VIII HERO (WI-FI)",
"ROG CROSSHAIR VIII IMPACT", "ROG CROSSHAIR VIII IMPACT",
"ROG STRIX B550-A GAMING", "ROG STRIX B550-A GAMING",
"ROG STRIX B550-E GAMING", "ROG STRIX B550-E GAMING",
...@@ -1080,8 +1084,11 @@ static const char * const asus_wmi_boards[] = { ...@@ -1080,8 +1084,11 @@ static const char * const asus_wmi_boards[] = {
"ROG STRIX Z490-G GAMING (WI-FI)", "ROG STRIX Z490-G GAMING (WI-FI)",
"ROG STRIX Z490-H GAMING", "ROG STRIX Z490-H GAMING",
"ROG STRIX Z490-I GAMING", "ROG STRIX Z490-I GAMING",
"TUF GAMING B550M-E",
"TUF GAMING B550M-E (WI-FI)",
"TUF GAMING B550M-PLUS", "TUF GAMING B550M-PLUS",
"TUF GAMING B550M-PLUS (WI-FI)", "TUF GAMING B550M-PLUS (WI-FI)",
"TUF GAMING B550M-PLUS WIFI II",
"TUF GAMING B550-PLUS", "TUF GAMING B550-PLUS",
"TUF GAMING B550-PLUS WIFI II", "TUF GAMING B550-PLUS WIFI II",
"TUF GAMING B550-PRO", "TUF GAMING B550-PRO",
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
config SENSORS_OCC_P8_I2C config SENSORS_OCC_P8_I2C
tristate "POWER8 OCC through I2C" tristate "POWER8 OCC through I2C"
depends on I2C depends on I2C
depends on ARM || ARM64 || COMPILE_TEST
select SENSORS_OCC select SENSORS_OCC
help help
This option enables support for monitoring sensors provided by the This option enables support for monitoring sensors provided by the
...@@ -21,7 +20,6 @@ config SENSORS_OCC_P8_I2C ...@@ -21,7 +20,6 @@ config SENSORS_OCC_P8_I2C
config SENSORS_OCC_P9_SBE config SENSORS_OCC_P9_SBE
tristate "POWER9 OCC through SBE" tristate "POWER9 OCC through SBE"
depends on FSI_OCC depends on FSI_OCC
depends on ARM || ARM64 || COMPILE_TEST
select SENSORS_OCC select SENSORS_OCC
help help
This option enables support for monitoring sensors provided by the This option enables support for monitoring sensors provided by the
......
// 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");
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/kstrtox.h>
/* Insmod parameters */ /* Insmod parameters */
......
...@@ -23,7 +23,7 @@ enum chips { ...@@ -23,7 +23,7 @@ enum chips {
/* Managers */ /* Managers */
ltc2972, ltc2974, ltc2975, ltc2977, ltc2978, ltc2979, ltc2980, ltc2972, ltc2974, ltc2975, ltc2977, ltc2978, ltc2979, ltc2980,
/* Controllers */ /* Controllers */
ltc3880, ltc3882, ltc3883, ltc3884, ltc3886, ltc3887, ltc3889, ltc7880, ltc3880, ltc3882, ltc3883, ltc3884, ltc3886, ltc3887, ltc3889, ltc7132, ltc7880,
/* Modules */ /* Modules */
ltm2987, ltm4664, ltm4675, ltm4676, ltm4677, ltm4678, ltm4680, ltm4686, ltm2987, ltm4664, ltm4675, ltm4676, ltm4677, ltm4678, ltm4680, ltm4686,
ltm4700, ltm4700,
...@@ -45,15 +45,14 @@ enum chips { ...@@ -45,15 +45,14 @@ enum chips {
#define LTC2974_MFR_IOUT_PEAK 0xd7 #define LTC2974_MFR_IOUT_PEAK 0xd7
#define LTC2974_MFR_IOUT_MIN 0xd8 #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_IOUT_PEAK 0xd7
#define LTC3880_MFR_CLEAR_PEAKS 0xe3 #define LTC3880_MFR_CLEAR_PEAKS 0xe3
#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4 #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 #define LTC3883_MFR_IIN_PEAK 0xe1
/* LTC2975 only */ /* LTC2975 only */
#define LTC2975_MFR_IIN_PEAK 0xc4 #define LTC2975_MFR_IIN_PEAK 0xc4
#define LTC2975_MFR_IIN_MIN 0xc5 #define LTC2975_MFR_IIN_MIN 0xc5
...@@ -79,10 +78,11 @@ enum chips { ...@@ -79,10 +78,11 @@ enum chips {
#define LTC3884_ID 0x4C00 #define LTC3884_ID 0x4C00
#define LTC3886_ID 0x4600 #define LTC3886_ID 0x4600
#define LTC3887_ID 0x4700 #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 LTC3889_ID 0x4900
#define LTC7132_ID 0x4CE0
#define LTC7880_ID 0x49E0 #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 LTM4664_ID 0x4120
#define LTM4675_ID 0x47a0 #define LTM4675_ID 0x47a0
#define LTM4676_ID_REV1 0x4400 #define LTM4676_ID_REV1 0x4400
...@@ -547,6 +547,7 @@ static const struct i2c_device_id ltc2978_id[] = { ...@@ -547,6 +547,7 @@ static const struct i2c_device_id ltc2978_id[] = {
{"ltc3886", ltc3886}, {"ltc3886", ltc3886},
{"ltc3887", ltc3887}, {"ltc3887", ltc3887},
{"ltc3889", ltc3889}, {"ltc3889", ltc3889},
{"ltc7132", ltc7132},
{"ltc7880", ltc7880}, {"ltc7880", ltc7880},
{"ltm2987", ltm2987}, {"ltm2987", ltm2987},
{"ltm4664", ltm4664}, {"ltm4664", ltm4664},
...@@ -651,6 +652,8 @@ static int ltc2978_get_id(struct i2c_client *client) ...@@ -651,6 +652,8 @@ static int ltc2978_get_id(struct i2c_client *client)
return ltc3887; return ltc3887;
else if (chip_id == LTC3889_ID) else if (chip_id == LTC3889_ID)
return ltc3889; return ltc3889;
else if (chip_id == LTC7132_ID)
return ltc7132;
else if (chip_id == LTC7880_ID) else if (chip_id == LTC7880_ID)
return ltc7880; return ltc7880;
else if (chip_id == LTM2987_ID_A || chip_id == LTM2987_ID_B) else if (chip_id == LTM2987_ID_A || chip_id == LTM2987_ID_B)
...@@ -831,6 +834,7 @@ static int ltc2978_probe(struct i2c_client *client) ...@@ -831,6 +834,7 @@ static int ltc2978_probe(struct i2c_client *client)
case ltc3884: case ltc3884:
case ltc3886: case ltc3886:
case ltc3889: case ltc3889:
case ltc7132:
case ltc7880: case ltc7880:
case ltm4664: case ltm4664:
case ltm4678: case ltm4678:
...@@ -902,6 +906,7 @@ static const struct of_device_id ltc2978_of_match[] = { ...@@ -902,6 +906,7 @@ static const struct of_device_id ltc2978_of_match[] = {
{ .compatible = "lltc,ltc3886" }, { .compatible = "lltc,ltc3886" },
{ .compatible = "lltc,ltc3887" }, { .compatible = "lltc,ltc3887" },
{ .compatible = "lltc,ltc3889" }, { .compatible = "lltc,ltc3889" },
{ .compatible = "lltc,ltc7132" },
{ .compatible = "lltc,ltc7880" }, { .compatible = "lltc,ltc7880" },
{ .compatible = "lltc,ltm2987" }, { .compatible = "lltc,ltm2987" },
{ .compatible = "lltc,ltm4664" }, { .compatible = "lltc,ltm4664" },
......
...@@ -2827,9 +2827,13 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned ...@@ -2827,9 +2827,13 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
if (status < 0) if (status < 0)
return status; return status;
if (pmbus_regulator_is_enabled(rdev) && (status & PB_STATUS_OFF)) if (pmbus_regulator_is_enabled(rdev)) {
*flags |= REGULATOR_ERROR_FAIL; 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 * Unlike most other status bits, PB_STATUS_{IOUT_OC,VOUT_OV} are
* defined strictly as fault indicators (not warnings). * defined strictly as fault indicators (not warnings).
...@@ -2851,6 +2855,49 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned ...@@ -2851,6 +2855,49 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
return 0; 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) static int pmbus_regulator_get_low_margin(struct i2c_client *client, int page)
{ {
struct pmbus_data *data = i2c_get_clientdata(client); struct pmbus_data *data = i2c_get_clientdata(client);
...@@ -2991,6 +3038,7 @@ const struct regulator_ops pmbus_regulator_ops = { ...@@ -2991,6 +3038,7 @@ const struct regulator_ops pmbus_regulator_ops = {
.disable = pmbus_regulator_disable, .disable = pmbus_regulator_disable,
.is_enabled = pmbus_regulator_is_enabled, .is_enabled = pmbus_regulator_is_enabled,
.get_error_flags = pmbus_regulator_get_error_flags, .get_error_flags = pmbus_regulator_get_error_flags,
.get_status = pmbus_regulator_get_status,
.get_voltage = pmbus_regulator_get_voltage, .get_voltage = pmbus_regulator_get_voltage,
.set_voltage = pmbus_regulator_set_voltage, .set_voltage = pmbus_regulator_set_voltage,
.list_voltage = pmbus_regulator_list_voltage, .list_voltage = pmbus_regulator_list_voltage,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/kstrtox.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include "pmbus.h" #include "pmbus.h"
......
...@@ -297,8 +297,7 @@ static int sbrmi_get_max_pwr_limit(struct sbrmi_data *data) ...@@ -297,8 +297,7 @@ static int sbrmi_get_max_pwr_limit(struct sbrmi_data *data)
return ret; return ret;
} }
static int sbrmi_probe(struct i2c_client *client, static int sbrmi_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct device *hwmon_dev; struct device *hwmon_dev;
...@@ -348,7 +347,7 @@ static struct i2c_driver sbrmi_driver = { ...@@ -348,7 +347,7 @@ static struct i2c_driver sbrmi_driver = {
.name = "sbrmi", .name = "sbrmi",
.of_match_table = of_match_ptr(sbrmi_of_match), .of_match_table = of_match_ptr(sbrmi_of_match),
}, },
.probe = sbrmi_probe, .probe_new = sbrmi_probe,
.id_table = sbrmi_id, .id_table = sbrmi_id,
}; };
......
...@@ -199,8 +199,7 @@ static const struct hwmon_chip_info sbtsi_chip_info = { ...@@ -199,8 +199,7 @@ static const struct hwmon_chip_info sbtsi_chip_info = {
.info = sbtsi_info, .info = sbtsi_info,
}; };
static int sbtsi_probe(struct i2c_client *client, static int sbtsi_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct device *hwmon_dev; struct device *hwmon_dev;
...@@ -239,7 +238,7 @@ static struct i2c_driver sbtsi_driver = { ...@@ -239,7 +238,7 @@ static struct i2c_driver sbtsi_driver = {
.name = "sbtsi", .name = "sbtsi",
.of_match_table = of_match_ptr(sbtsi_of_match), .of_match_table = of_match_ptr(sbtsi_of_match),
}, },
.probe = sbtsi_probe, .probe_new = sbtsi_probe,
.id_table = sbtsi_id, .id_table = sbtsi_id,
}; };
......
...@@ -320,7 +320,7 @@ static ssize_t temp1_limit_show(struct device *dev, ...@@ -320,7 +320,7 @@ static ssize_t temp1_limit_show(struct device *dev,
u8 index = to_sensor_dev_attr(attr)->index; u8 index = to_sensor_dev_attr(attr)->index;
int temperature_limit = data->temperature_limits[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, static ssize_t humidity1_limit_show(struct device *dev,
...@@ -331,7 +331,7 @@ static ssize_t humidity1_limit_show(struct device *dev, ...@@ -331,7 +331,7 @@ static ssize_t humidity1_limit_show(struct device *dev,
u8 index = to_sensor_dev_attr(attr)->index; u8 index = to_sensor_dev_attr(attr)->index;
u32 humidity_limit = data->humidity_limits[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 device *dev, ...@@ -483,7 +483,7 @@ static ssize_t temp1_alarm_show(struct device *dev,
if (ret) if (ret)
return 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, static ssize_t humidity1_alarm_show(struct device *dev,
...@@ -498,7 +498,7 @@ static ssize_t humidity1_alarm_show(struct device *dev, ...@@ -498,7 +498,7 @@ static ssize_t humidity1_alarm_show(struct device *dev,
if (ret) if (ret)
return 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, static ssize_t heater_enable_show(struct device *dev,
...@@ -513,7 +513,7 @@ static ssize_t heater_enable_show(struct device *dev, ...@@ -513,7 +513,7 @@ static ssize_t heater_enable_show(struct device *dev,
if (ret) if (ret)
return 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, static ssize_t heater_enable_store(struct device *dev,
...@@ -550,7 +550,7 @@ static ssize_t update_interval_show(struct device *dev, ...@@ -550,7 +550,7 @@ static ssize_t update_interval_show(struct device *dev,
{ {
struct sht3x_data *data = dev_get_drvdata(dev); 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]); mode_to_update_interval[data->mode]);
} }
......
...@@ -232,8 +232,7 @@ static const struct hwmon_chip_info sht4x_chip_info = { ...@@ -232,8 +232,7 @@ static const struct hwmon_chip_info sht4x_chip_info = {
.info = sht4x_info, .info = sht4x_info,
}; };
static int sht4x_probe(struct i2c_client *client, static int sht4x_probe(struct i2c_client *client)
const struct i2c_device_id *sht4x_id)
{ {
struct device *device = &client->dev; struct device *device = &client->dev;
struct device *hwmon_dev; struct device *hwmon_dev;
...@@ -292,7 +291,7 @@ static struct i2c_driver sht4x_driver = { ...@@ -292,7 +291,7 @@ static struct i2c_driver sht4x_driver = {
.name = "sht4x", .name = "sht4x",
.of_match_table = sht4x_of_match, .of_match_table = sht4x_of_match,
}, },
.probe = sht4x_probe, .probe_new = sht4x_probe,
.id_table = sht4x_id, .id_table = sht4x_id,
}; };
......
This diff is collapsed.
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/acpi.h> #include <linux/acpi.h>
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-vid.h>
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h> #include <linux/mutex.h>
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define _LINUX_HWMON_SYSFS_H #define _LINUX_HWMON_SYSFS_H
#include <linux/device.h> #include <linux/device.h>
#include <linux/kstrtox.h>
struct sensor_device_attribute{ struct sensor_device_attribute{
struct device_attribute dev_attr; struct device_attribute dev_attr;
......
...@@ -29,18 +29,17 @@ struct gsc_hwmon_channel { ...@@ -29,18 +29,17 @@ struct gsc_hwmon_channel {
/** /**
* struct gsc_hwmon_platform_data - platform data for gsc_hwmon driver * 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 * @nchannels: number of elements in @channels array
* @vreference: voltage reference (mV) * @vreference: voltage reference (mV)
* @resolution: ADC bit resolution * @resolution: ADC bit resolution
* @fan_base: register base for FAN controller * @fan_base: register base for FAN controller
* @channels: array of gsc_hwmon_channel structures describing channels
*/ */
struct gsc_hwmon_platform_data { struct gsc_hwmon_platform_data {
const struct gsc_hwmon_channel *channels;
int nchannels; int nchannels;
unsigned int resolution; unsigned int resolution;
unsigned int vreference; unsigned int vreference;
unsigned int fan_base; unsigned int fan_base;
struct gsc_hwmon_channel channels[];
}; };
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment