mirror of
https://github.com/torvalds/linux.git
synced 2024-12-31 23:31:29 +00:00
hwmon updates for v4.18
- asus_atk0110 driver modified to use new API - k10temp supports new CPUs and reports both Tctl and Tdie - minor fixes in gpio-fan, ltc2990, fschmd, and mc13783 drivers -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJbFJmsAAoJEMsfJm/On5mBPeYP/1tU0jGQmPdO97DGCRm5MyYZ XoI3BGP42BIxgBx27WqJIybRwTzBONN/Kmv6Y9aS821T78hNtVD5FnbDGBy8Mx5j EKQHc3HHqFZ3YF4NRl9Q590O6HM4H7rhXGFbaG+NmmoTG/X7TRI0ItgafhHMl6E0 E3GbDdW7kUa5fAL3gavs/ckykAn+BedFc5BqdEq4aD7Hfzgjq3Sm2TAuj9AT/K4D 6CPFyhZ0Jc4503ayDPhm+4HFN0wXYCxmyD0rxpoPmx6mcEY+5dBXQjQoMjqd3kpZ zEbvTgo2FF+vWnktIXPKQk0dPIhfl6eqWfXS6cLA6zWkRhv/nfSVtqwlKlQWiOSj rs2JlprYjZG0OxaYexFAQcsOKWdlP7XgVCf0wXSWLc38BgKumD+Zk6PJo8sT0ZnW b6ypvO13/R+X5kvTPmSHT5jDEY/6QVuhYBrHX5HkVRv2svNErgwCFzboJKzZMhyI xsNdiYBRw6NwdSge2vbgeHXubM3hUN1GY923y7cI3z2XcptzHIqKSgYkpVrrLXMm PTmW68gnFwQxHb+/jb8K3e9q9Cq+LnGo7LGOvetSabUhGPmpGtTTRKy9FNtJnYen Hkfv4yZ4hE4uHExSNHXrjI5YRQg/f0UE1lOoPgFLFuGd0TiOOpzkKaAHBcXEfOnT VU7PeaM3haBgx5cy5u11 =3w3p -----END PGP SIGNATURE----- Merge tag 'hwmon-for-linus-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull hwmon updates from Guenter Roeck: - asus_atk0110 driver modified to use new API - k10temp supports new CPUs and reports both Tctl and Tdie - minor fixes in gpio-fan, ltc2990, fschmd, and mc13783 drivers * tag 'hwmon-for-linus-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: hwmon: (asus_atk0110) Make use of device managed memory hwmon: (asus_atk0110) Replace deprecated device register call hwmon: (k10temp) Make function get_raw_temp static hwmon: (gpio-fan) Fix "#cooling-cells" property name in bindings MAINTAINERS: hwmon: Add Documentation/devicetree/bindings/hwmon hwmon: (ltc2990) support all measurement modes hwmon: (ltc2990) add devicetree binding hwmon: (ltc2990) Fix incorrect conversion of negative temperatures hwmon: (core) check parent dev != NULL when chip != NULL hwmon: (fschmd) fix typo 'can by' to 'can be' hwmon: (k10temp) Display both Tctl and Tdie hwmon: (k10temp) Add support for Stoney Ridge and Bristol Ridge CPUs hwmon: MC13783: Add uid and die temperature sensor inputs
This commit is contained in:
commit
bef82f812c
@ -11,7 +11,7 @@ Optional properties:
|
||||
must have the RPM values in ascending order.
|
||||
- alarm-gpios: This pin going active indicates something is wrong with
|
||||
the fan, and a udev event will be fired.
|
||||
- cooling-cells: If used as a cooling device, must be <2>
|
||||
- #cooling-cells: If used as a cooling device, must be <2>
|
||||
Also see: Documentation/devicetree/bindings/thermal/thermal.txt
|
||||
min and max states are derived from the speed-map of the fan.
|
||||
|
||||
|
36
Documentation/devicetree/bindings/hwmon/ltc2990.txt
Normal file
36
Documentation/devicetree/bindings/hwmon/ltc2990.txt
Normal file
@ -0,0 +1,36 @@
|
||||
ltc2990: Linear Technology LTC2990 power monitor
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "lltc,ltc2990"
|
||||
- reg: I2C slave address
|
||||
- lltc,meas-mode:
|
||||
An array of two integers for configuring the chip measurement mode.
|
||||
|
||||
The first integer defines the bits 2..0 in the control register. In all
|
||||
cases the internal temperature and supply voltage are measured. In
|
||||
addition the following input measurements are enabled per mode:
|
||||
|
||||
0: V1, V2, TR2
|
||||
1: V1-V2, TR2
|
||||
2: V1-V2, V3, V4
|
||||
3: TR1, V3, V4
|
||||
4: TR1, V3-V4
|
||||
5: TR1, TR2
|
||||
6: V1-V2, V3-V4
|
||||
7: V1, V2, V3, V4
|
||||
|
||||
The second integer defines the bits 4..3 in the control register. This
|
||||
allows a subset of the measurements to be enabled:
|
||||
|
||||
0: Internal temperature and supply voltage only
|
||||
1: TR1, V1 or V1-V2 only per mode
|
||||
2: TR2, V3 or V3-V4 only per mode
|
||||
3: All measurements per mode
|
||||
|
||||
Example:
|
||||
|
||||
ltc2990@4c {
|
||||
compatible = "lltc,ltc2990";
|
||||
reg = <0x4c>;
|
||||
lltc,meas-mode = <7 3>; /* V1, V2, V3, V4 */
|
||||
};
|
@ -71,7 +71,8 @@ hwmon_device_register_with_info is the most comprehensive and preferred means
|
||||
to register a hardware monitoring device. It creates the standard sysfs
|
||||
attributes in the hardware monitoring core, letting the driver focus on reading
|
||||
from and writing to the chip instead of having to bother with sysfs attributes.
|
||||
Its parameters are described in more detail below.
|
||||
The parent device parameter cannot be NULL with non-NULL chip info. Its
|
||||
parameters are described in more detail below.
|
||||
|
||||
devm_hwmon_device_register_with_info is similar to
|
||||
hwmon_device_register_with_info. However, it is device managed, meaning the
|
||||
|
@ -8,6 +8,7 @@ Supported chips:
|
||||
Datasheet: http://www.linear.com/product/ltc2990
|
||||
|
||||
Author: Mike Looijmans <mike.looijmans@topic.nl>
|
||||
Tom Levens <tom.levens@cern.ch>
|
||||
|
||||
|
||||
Description
|
||||
@ -16,10 +17,8 @@ Description
|
||||
LTC2990 is a Quad I2C Voltage, Current and Temperature Monitor.
|
||||
The chip's inputs can measure 4 voltages, or two inputs together (1+2 and 3+4)
|
||||
can be combined to measure a differential voltage, which is typically used to
|
||||
measure current through a series resistor, or a temperature.
|
||||
|
||||
This driver currently uses the 2x differential mode only. In order to support
|
||||
other modes, the driver will need to be expanded.
|
||||
measure current through a series resistor, or a temperature with an external
|
||||
diode.
|
||||
|
||||
|
||||
Usage Notes
|
||||
@ -32,12 +31,19 @@ devices explicitly.
|
||||
Sysfs attributes
|
||||
----------------
|
||||
|
||||
in0_input Voltage at Vcc pin in millivolt (range 2.5V to 5V)
|
||||
temp1_input Internal chip temperature in millidegrees Celcius
|
||||
|
||||
A subset of the following attributes are visible, depending on the measurement
|
||||
mode of the chip.
|
||||
|
||||
in[1-4]_input Voltage at V[1-4] pin in millivolt
|
||||
temp2_input External temperature sensor TR1 in millidegrees Celcius
|
||||
temp3_input External temperature sensor TR2 in millidegrees Celcius
|
||||
curr1_input Current in mA across V1-V2 assuming a 1mOhm sense resistor
|
||||
curr2_input Current in mA across V3-V4 assuming a 1mOhm sense resistor
|
||||
|
||||
The "curr*_input" measurements actually report the voltage drop across the
|
||||
input pins in microvolts. This is equivalent to the current through a 1mOhm
|
||||
sense resistor. Divide the reported value by the actual sense resistor value
|
||||
in mOhm to get the actual value.
|
||||
|
||||
in0_input Voltage at Vcc pin in millivolt (range 2.5V to 5V)
|
||||
temp1_input Internal chip temperature in millidegrees Celcius
|
||||
curr1_input Current in mA across v1-v2 assuming a 1mOhm sense resistor.
|
||||
curr2_input Current in mA across v3-v4 assuming a 1mOhm sense resistor.
|
||||
|
@ -6219,6 +6219,7 @@ L: linux-hwmon@vger.kernel.org
|
||||
W: http://hwmon.wiki.kernel.org/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/hwmon/
|
||||
F: Documentation/hwmon/
|
||||
F: drivers/hwmon/
|
||||
F: include/linux/hwmon*.h
|
||||
|
@ -717,15 +717,12 @@ config SENSORS_LTC2945
|
||||
be called ltc2945.
|
||||
|
||||
config SENSORS_LTC2990
|
||||
tristate "Linear Technology LTC2990 (current monitoring mode only)"
|
||||
tristate "Linear Technology LTC2990"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for Linear Technology LTC2990
|
||||
I2C System Monitor. The LTC2990 supports a combination of voltage,
|
||||
current and temperature monitoring, but in addition to the Vcc supply
|
||||
voltage and chip temperature, this driver currently only supports
|
||||
reading two currents by measuring two differential voltages across
|
||||
series resistors.
|
||||
current and temperature monitoring.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called ltc2990.
|
||||
|
@ -125,6 +125,8 @@ struct atk_data {
|
||||
int temperature_count;
|
||||
int fan_count;
|
||||
struct list_head sensor_list;
|
||||
struct attribute_group attr_group;
|
||||
const struct attribute_group *attr_groups[2];
|
||||
|
||||
struct {
|
||||
struct dentry *root;
|
||||
@ -188,7 +190,6 @@ static int atk_add(struct acpi_device *device);
|
||||
static int atk_remove(struct acpi_device *device);
|
||||
static void atk_print_sensor(struct atk_data *data, union acpi_object *obj);
|
||||
static int atk_read_value(struct atk_sensor_data *sensor, u64 *value);
|
||||
static void atk_free_sensors(struct atk_data *data);
|
||||
|
||||
static struct acpi_driver atk_driver = {
|
||||
.name = ATK_HID,
|
||||
@ -262,14 +263,6 @@ static ssize_t atk_limit2_show(struct device *dev,
|
||||
return sprintf(buf, "%lld\n", value);
|
||||
}
|
||||
|
||||
static ssize_t atk_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "atk0110\n");
|
||||
}
|
||||
static struct device_attribute atk_name_attr =
|
||||
__ATTR(name, 0444, atk_name_show, NULL);
|
||||
|
||||
static void atk_init_attribute(struct device_attribute *attr, char *name,
|
||||
sysfs_show_func show)
|
||||
{
|
||||
@ -912,15 +905,13 @@ static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
|
||||
limit1 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT1);
|
||||
limit2 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT2);
|
||||
|
||||
sensor = kzalloc(sizeof(*sensor), GFP_KERNEL);
|
||||
sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
|
||||
if (!sensor)
|
||||
return -ENOMEM;
|
||||
|
||||
sensor->acpi_name = kstrdup(name->string.pointer, GFP_KERNEL);
|
||||
if (!sensor->acpi_name) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
sensor->acpi_name = devm_kstrdup(dev, name->string.pointer, GFP_KERNEL);
|
||||
if (!sensor->acpi_name)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&sensor->list);
|
||||
sensor->type = type;
|
||||
@ -961,9 +952,6 @@ static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
|
||||
(*num)++;
|
||||
|
||||
return 1;
|
||||
out:
|
||||
kfree(sensor);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int atk_enumerate_old_hwmon(struct atk_data *data)
|
||||
@ -1004,8 +992,7 @@ static int atk_enumerate_old_hwmon(struct atk_data *data)
|
||||
dev_warn(dev, METHOD_OLD_ENUM_TMP ": ACPI exception: %s\n",
|
||||
acpi_format_exception(status));
|
||||
|
||||
ret = -ENODEV;
|
||||
goto cleanup;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pack = buf.pointer;
|
||||
@ -1026,8 +1013,7 @@ static int atk_enumerate_old_hwmon(struct atk_data *data)
|
||||
dev_warn(dev, METHOD_OLD_ENUM_FAN ": ACPI exception: %s\n",
|
||||
acpi_format_exception(status));
|
||||
|
||||
ret = -ENODEV;
|
||||
goto cleanup;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pack = buf.pointer;
|
||||
@ -1041,9 +1027,6 @@ static int atk_enumerate_old_hwmon(struct atk_data *data)
|
||||
ACPI_FREE(buf.pointer);
|
||||
|
||||
return count;
|
||||
cleanup:
|
||||
atk_free_sensors(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int atk_ec_present(struct atk_data *data)
|
||||
@ -1193,76 +1176,44 @@ static int atk_enumerate_new_hwmon(struct atk_data *data)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int atk_create_files(struct atk_data *data)
|
||||
static int atk_init_attribute_groups(struct atk_data *data)
|
||||
{
|
||||
struct device *dev = &data->acpi_dev->dev;
|
||||
struct atk_sensor_data *s;
|
||||
int err;
|
||||
struct attribute **attrs;
|
||||
int i = 0;
|
||||
int len = (data->voltage_count + data->temperature_count
|
||||
+ data->fan_count) * 4 + 1;
|
||||
|
||||
attrs = devm_kcalloc(dev, len, sizeof(struct attribute *), GFP_KERNEL);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
list_for_each_entry(s, &data->sensor_list, list) {
|
||||
err = device_create_file(data->hwmon_dev, &s->input_attr);
|
||||
if (err)
|
||||
return err;
|
||||
err = device_create_file(data->hwmon_dev, &s->label_attr);
|
||||
if (err)
|
||||
return err;
|
||||
err = device_create_file(data->hwmon_dev, &s->limit1_attr);
|
||||
if (err)
|
||||
return err;
|
||||
err = device_create_file(data->hwmon_dev, &s->limit2_attr);
|
||||
if (err)
|
||||
return err;
|
||||
attrs[i++] = &s->input_attr.attr;
|
||||
attrs[i++] = &s->label_attr.attr;
|
||||
attrs[i++] = &s->limit1_attr.attr;
|
||||
attrs[i++] = &s->limit2_attr.attr;
|
||||
}
|
||||
|
||||
err = device_create_file(data->hwmon_dev, &atk_name_attr);
|
||||
data->attr_group.attrs = attrs;
|
||||
data->attr_groups[0] = &data->attr_group;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void atk_remove_files(struct atk_data *data)
|
||||
{
|
||||
struct atk_sensor_data *s;
|
||||
|
||||
list_for_each_entry(s, &data->sensor_list, list) {
|
||||
device_remove_file(data->hwmon_dev, &s->input_attr);
|
||||
device_remove_file(data->hwmon_dev, &s->label_attr);
|
||||
device_remove_file(data->hwmon_dev, &s->limit1_attr);
|
||||
device_remove_file(data->hwmon_dev, &s->limit2_attr);
|
||||
}
|
||||
device_remove_file(data->hwmon_dev, &atk_name_attr);
|
||||
}
|
||||
|
||||
static void atk_free_sensors(struct atk_data *data)
|
||||
{
|
||||
struct list_head *head = &data->sensor_list;
|
||||
struct atk_sensor_data *s, *tmp;
|
||||
|
||||
list_for_each_entry_safe(s, tmp, head, list) {
|
||||
kfree(s->acpi_name);
|
||||
kfree(s);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atk_register_hwmon(struct atk_data *data)
|
||||
{
|
||||
struct device *dev = &data->acpi_dev->dev;
|
||||
int err;
|
||||
|
||||
dev_dbg(dev, "registering hwmon device\n");
|
||||
data->hwmon_dev = hwmon_device_register(dev);
|
||||
data->hwmon_dev = hwmon_device_register_with_groups(dev, "atk0110",
|
||||
data,
|
||||
data->attr_groups);
|
||||
if (IS_ERR(data->hwmon_dev))
|
||||
return PTR_ERR(data->hwmon_dev);
|
||||
|
||||
dev_dbg(dev, "populating sysfs directory\n");
|
||||
err = atk_create_files(data);
|
||||
if (err)
|
||||
goto remove;
|
||||
|
||||
return 0;
|
||||
remove:
|
||||
/* Cleanup the registered files */
|
||||
atk_remove_files(data);
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int atk_probe_if(struct atk_data *data)
|
||||
@ -1350,7 +1301,7 @@ static int atk_add(struct acpi_device *device)
|
||||
|
||||
dev_dbg(&device->dev, "adding...\n");
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&device->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1397,20 +1348,20 @@ static int atk_add(struct acpi_device *device)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = atk_init_attribute_groups(data);
|
||||
if (err)
|
||||
goto out;
|
||||
err = atk_register_hwmon(data);
|
||||
if (err)
|
||||
goto cleanup;
|
||||
goto out;
|
||||
|
||||
atk_debugfs_init(data);
|
||||
|
||||
device->driver_data = data;
|
||||
return 0;
|
||||
cleanup:
|
||||
atk_free_sensors(data);
|
||||
out:
|
||||
if (data->disable_ec)
|
||||
atk_ec_ctl(data, 0);
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1423,8 +1374,6 @@ static int atk_remove(struct acpi_device *device)
|
||||
|
||||
atk_debugfs_cleanup(data);
|
||||
|
||||
atk_remove_files(data);
|
||||
atk_free_sensors(data);
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
|
||||
if (data->disable_ec) {
|
||||
@ -1432,8 +1381,6 @@ static int atk_remove(struct acpi_device *device)
|
||||
dev_err(&device->dev, "Failed to disable EC\n");
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ static const u8 FSCHMD_REG_VOLT[7][6] = {
|
||||
static const int FSCHMD_NO_VOLT_SENSORS[7] = { 3, 3, 3, 3, 3, 3, 6 };
|
||||
|
||||
/*
|
||||
* minimum pwm at which the fan is driven (pwm can by increased depending on
|
||||
* minimum pwm at which the fan is driven (pwm can be increased depending on
|
||||
* the temp. Notice that for the scy some fans share there minimum speed.
|
||||
* Also notice that with the scy the sensor order is different than with the
|
||||
* other chips, this order was in the 2.4 driver and kept for consistency.
|
||||
|
@ -698,6 +698,9 @@ hwmon_device_register_with_info(struct device *dev, const char *name,
|
||||
if (chip && (!chip->ops || !chip->ops->is_visible || !chip->info))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (chip && !dev)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return __hwmon_device_register(dev, name, drvdata, chip, extra_groups);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hwmon_device_register_with_info);
|
||||
|
@ -37,6 +37,10 @@ MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
|
||||
/* Provide lock for writing to NB_SMU_IND_ADDR */
|
||||
static DEFINE_MUTEX(nb_smu_ind_mutex);
|
||||
|
||||
#ifndef PCI_DEVICE_ID_AMD_15H_M70H_NB_F3
|
||||
#define PCI_DEVICE_ID_AMD_15H_M70H_NB_F3 0x15b3
|
||||
#endif
|
||||
|
||||
#ifndef PCI_DEVICE_ID_AMD_17H_DF_F3
|
||||
#define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463
|
||||
#endif
|
||||
@ -81,6 +85,7 @@ struct k10temp_data {
|
||||
void (*read_tempreg)(struct pci_dev *pdev, u32 *regval);
|
||||
int temp_offset;
|
||||
u32 temp_adjust_mask;
|
||||
bool show_tdie;
|
||||
};
|
||||
|
||||
struct tctl_offset {
|
||||
@ -141,17 +146,24 @@ static void read_tempreg_nb_f17(struct pci_dev *pdev, u32 *regval)
|
||||
F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, regval);
|
||||
}
|
||||
|
||||
static ssize_t temp1_input_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static unsigned int get_raw_temp(struct k10temp_data *data)
|
||||
{
|
||||
struct k10temp_data *data = dev_get_drvdata(dev);
|
||||
u32 regval;
|
||||
unsigned int temp;
|
||||
u32 regval;
|
||||
|
||||
data->read_tempreg(data->pdev, ®val);
|
||||
temp = (regval >> 21) * 125;
|
||||
if (regval & data->temp_adjust_mask)
|
||||
temp -= 49000;
|
||||
return temp;
|
||||
}
|
||||
|
||||
static ssize_t temp1_input_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct k10temp_data *data = dev_get_drvdata(dev);
|
||||
unsigned int temp = get_raw_temp(data);
|
||||
|
||||
if (temp > data->temp_offset)
|
||||
temp -= data->temp_offset;
|
||||
else
|
||||
@ -160,6 +172,23 @@ static ssize_t temp1_input_show(struct device *dev,
|
||||
return sprintf(buf, "%u\n", temp);
|
||||
}
|
||||
|
||||
static ssize_t temp2_input_show(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct k10temp_data *data = dev_get_drvdata(dev);
|
||||
unsigned int temp = get_raw_temp(data);
|
||||
|
||||
return sprintf(buf, "%u\n", temp);
|
||||
}
|
||||
|
||||
static ssize_t temp_label_show(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
|
||||
return sprintf(buf, "%s\n", attr->index ? "Tctl" : "Tdie");
|
||||
}
|
||||
|
||||
static ssize_t temp1_max_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@ -187,16 +216,23 @@ static DEVICE_ATTR_RO(temp1_max);
|
||||
static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_label, 0444, temp_label_show, NULL, 0);
|
||||
static DEVICE_ATTR_RO(temp2_input);
|
||||
static SENSOR_DEVICE_ATTR(temp2_label, 0444, temp_label_show, NULL, 1);
|
||||
|
||||
static umode_t k10temp_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int index)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct k10temp_data *data = dev_get_drvdata(dev);
|
||||
struct pci_dev *pdev = data->pdev;
|
||||
u32 reg;
|
||||
|
||||
if (index >= 2) {
|
||||
u32 reg;
|
||||
|
||||
switch (index) {
|
||||
case 0 ... 1: /* temp1_input, temp1_max */
|
||||
default:
|
||||
break;
|
||||
case 2 ... 3: /* temp1_crit, temp1_crit_hyst */
|
||||
if (!data->read_htcreg)
|
||||
return 0;
|
||||
|
||||
@ -208,6 +244,11 @@ static umode_t k10temp_is_visible(struct kobject *kobj,
|
||||
data->read_htcreg(data->pdev, ®);
|
||||
if (!(reg & HTC_ENABLE))
|
||||
return 0;
|
||||
break;
|
||||
case 4 ... 6: /* temp1_label, temp2_input, temp2_label */
|
||||
if (!data->show_tdie)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
return attr->mode;
|
||||
}
|
||||
@ -217,6 +258,9 @@ static struct attribute *k10temp_attrs[] = {
|
||||
&dev_attr_temp1_max.attr,
|
||||
&sensor_dev_attr_temp1_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_label.dev_attr.attr,
|
||||
&dev_attr_temp2_input.attr,
|
||||
&sensor_dev_attr_temp2_label.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -292,6 +336,7 @@ static int k10temp_probe(struct pci_dev *pdev,
|
||||
} else if (boot_cpu_data.x86 == 0x17) {
|
||||
data->temp_adjust_mask = 0x80000;
|
||||
data->read_tempreg = read_tempreg_nb_f17;
|
||||
data->show_tdie = true;
|
||||
} else {
|
||||
data->read_htcreg = read_htcreg_pci;
|
||||
data->read_tempreg = read_tempreg_pci;
|
||||
@ -320,6 +365,7 @@ static const struct pci_device_id k10temp_id_table[] = {
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M70H_NB_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
|
||||
|
@ -5,18 +5,16 @@
|
||||
* Author: Mike Looijmans <mike.looijmans@topic.nl>
|
||||
*
|
||||
* License: GPLv2
|
||||
*
|
||||
* This driver assumes the chip is wired as a dual current monitor, and
|
||||
* reports the voltage drop across two series resistors. It also reports
|
||||
* the chip's internal temperature and Vcc power supply voltage.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#define LTC2990_STATUS 0x00
|
||||
#define LTC2990_CONTROL 0x01
|
||||
@ -28,45 +26,108 @@
|
||||
#define LTC2990_V4_MSB 0x0C
|
||||
#define LTC2990_VCC_MSB 0x0E
|
||||
|
||||
#define LTC2990_CONTROL_KELVIN BIT(7)
|
||||
#define LTC2990_CONTROL_SINGLE BIT(6)
|
||||
#define LTC2990_CONTROL_MEASURE_ALL (0x3 << 3)
|
||||
#define LTC2990_CONTROL_MODE_CURRENT 0x06
|
||||
#define LTC2990_CONTROL_MODE_VOLTAGE 0x07
|
||||
#define LTC2990_IN0 BIT(0)
|
||||
#define LTC2990_IN1 BIT(1)
|
||||
#define LTC2990_IN2 BIT(2)
|
||||
#define LTC2990_IN3 BIT(3)
|
||||
#define LTC2990_IN4 BIT(4)
|
||||
#define LTC2990_CURR1 BIT(5)
|
||||
#define LTC2990_CURR2 BIT(6)
|
||||
#define LTC2990_TEMP1 BIT(7)
|
||||
#define LTC2990_TEMP2 BIT(8)
|
||||
#define LTC2990_TEMP3 BIT(9)
|
||||
#define LTC2990_NONE 0
|
||||
#define LTC2990_ALL GENMASK(9, 0)
|
||||
|
||||
/* convert raw register value to sign-extended integer in 16-bit range */
|
||||
static int ltc2990_voltage_to_int(int raw)
|
||||
{
|
||||
if (raw & BIT(14))
|
||||
return -(0x4000 - (raw & 0x3FFF)) << 2;
|
||||
else
|
||||
return (raw & 0x3FFF) << 2;
|
||||
}
|
||||
#define LTC2990_MODE0_SHIFT 0
|
||||
#define LTC2990_MODE0_MASK GENMASK(2, 0)
|
||||
#define LTC2990_MODE1_SHIFT 3
|
||||
#define LTC2990_MODE1_MASK GENMASK(1, 0)
|
||||
|
||||
/* Enabled measurements for mode bits 2..0 */
|
||||
static const int ltc2990_attrs_ena_0[] = {
|
||||
LTC2990_IN1 | LTC2990_IN2 | LTC2990_TEMP3,
|
||||
LTC2990_CURR1 | LTC2990_TEMP3,
|
||||
LTC2990_CURR1 | LTC2990_IN3 | LTC2990_IN4,
|
||||
LTC2990_TEMP2 | LTC2990_IN3 | LTC2990_IN4,
|
||||
LTC2990_TEMP2 | LTC2990_CURR2,
|
||||
LTC2990_TEMP2 | LTC2990_TEMP3,
|
||||
LTC2990_CURR1 | LTC2990_CURR2,
|
||||
LTC2990_IN1 | LTC2990_IN2 | LTC2990_IN3 | LTC2990_IN4
|
||||
};
|
||||
|
||||
/* Enabled measurements for mode bits 4..3 */
|
||||
static const int ltc2990_attrs_ena_1[] = {
|
||||
LTC2990_NONE,
|
||||
LTC2990_TEMP2 | LTC2990_IN1 | LTC2990_CURR1,
|
||||
LTC2990_TEMP3 | LTC2990_IN3 | LTC2990_CURR2,
|
||||
LTC2990_ALL
|
||||
};
|
||||
|
||||
struct ltc2990_data {
|
||||
struct i2c_client *i2c;
|
||||
u32 mode[2];
|
||||
};
|
||||
|
||||
/* Return the converted value from the given register in uV or mC */
|
||||
static int ltc2990_get_value(struct i2c_client *i2c, u8 reg, int *result)
|
||||
static int ltc2990_get_value(struct i2c_client *i2c, int index, int *result)
|
||||
{
|
||||
int val;
|
||||
u8 reg;
|
||||
|
||||
switch (index) {
|
||||
case LTC2990_IN0:
|
||||
reg = LTC2990_VCC_MSB;
|
||||
break;
|
||||
case LTC2990_IN1:
|
||||
case LTC2990_CURR1:
|
||||
case LTC2990_TEMP2:
|
||||
reg = LTC2990_V1_MSB;
|
||||
break;
|
||||
case LTC2990_IN2:
|
||||
reg = LTC2990_V2_MSB;
|
||||
break;
|
||||
case LTC2990_IN3:
|
||||
case LTC2990_CURR2:
|
||||
case LTC2990_TEMP3:
|
||||
reg = LTC2990_V3_MSB;
|
||||
break;
|
||||
case LTC2990_IN4:
|
||||
reg = LTC2990_V4_MSB;
|
||||
break;
|
||||
case LTC2990_TEMP1:
|
||||
reg = LTC2990_TINT_MSB;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = i2c_smbus_read_word_swapped(i2c, reg);
|
||||
if (unlikely(val < 0))
|
||||
return val;
|
||||
|
||||
switch (reg) {
|
||||
case LTC2990_TINT_MSB:
|
||||
/* internal temp, 0.0625 degrees/LSB, 13-bit */
|
||||
val = (val & 0x1FFF) << 3;
|
||||
*result = (val * 1000) >> 7;
|
||||
switch (index) {
|
||||
case LTC2990_TEMP1:
|
||||
case LTC2990_TEMP2:
|
||||
case LTC2990_TEMP3:
|
||||
/* temp, 0.0625 degrees/LSB */
|
||||
*result = sign_extend32(val, 12) * 1000 / 16;
|
||||
break;
|
||||
case LTC2990_V1_MSB:
|
||||
case LTC2990_V3_MSB:
|
||||
/* Vx-Vy, 19.42uV/LSB. Depends on mode. */
|
||||
*result = ltc2990_voltage_to_int(val) * 1942 / (4 * 100);
|
||||
case LTC2990_CURR1:
|
||||
case LTC2990_CURR2:
|
||||
/* Vx-Vy, 19.42uV/LSB */
|
||||
*result = sign_extend32(val, 14) * 1942 / 100;
|
||||
break;
|
||||
case LTC2990_VCC_MSB:
|
||||
/* Vcc, 305.18μV/LSB, 2.5V offset */
|
||||
*result = (ltc2990_voltage_to_int(val) * 30518 /
|
||||
(4 * 100 * 1000)) + 2500;
|
||||
case LTC2990_IN0:
|
||||
/* Vcc, 305.18uV/LSB, 2.5V offset */
|
||||
*result = sign_extend32(val, 14) * 30518 / (100 * 1000) + 2500;
|
||||
break;
|
||||
case LTC2990_IN1:
|
||||
case LTC2990_IN2:
|
||||
case LTC2990_IN3:
|
||||
case LTC2990_IN4:
|
||||
/* Vx, 305.18uV/LSB */
|
||||
*result = sign_extend32(val, 14) * 30518 / (100 * 1000);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL; /* won't happen, keep compiler happy */
|
||||
@ -79,48 +140,117 @@ static ssize_t ltc2990_show_value(struct device *dev,
|
||||
struct device_attribute *da, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct ltc2990_data *data = dev_get_drvdata(dev);
|
||||
int value;
|
||||
int ret;
|
||||
|
||||
ret = ltc2990_get_value(dev_get_drvdata(dev), attr->index, &value);
|
||||
ret = ltc2990_get_value(data->i2c, attr->index, &value);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", value);
|
||||
}
|
||||
|
||||
static umode_t ltc2990_attrs_visible(struct kobject *kobj,
|
||||
struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct ltc2990_data *data = dev_get_drvdata(dev);
|
||||
struct device_attribute *da =
|
||||
container_of(a, struct device_attribute, attr);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
|
||||
int attrs_mask = LTC2990_IN0 | LTC2990_TEMP1 |
|
||||
(ltc2990_attrs_ena_0[data->mode[0]] &
|
||||
ltc2990_attrs_ena_1[data->mode[1]]);
|
||||
|
||||
if (attr->index & attrs_mask)
|
||||
return a->mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL,
|
||||
LTC2990_TINT_MSB);
|
||||
LTC2990_TEMP1);
|
||||
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, ltc2990_show_value, NULL,
|
||||
LTC2990_TEMP2);
|
||||
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, ltc2990_show_value, NULL,
|
||||
LTC2990_TEMP3);
|
||||
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc2990_show_value, NULL,
|
||||
LTC2990_V1_MSB);
|
||||
LTC2990_CURR1);
|
||||
static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc2990_show_value, NULL,
|
||||
LTC2990_V3_MSB);
|
||||
LTC2990_CURR2);
|
||||
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ltc2990_show_value, NULL,
|
||||
LTC2990_VCC_MSB);
|
||||
LTC2990_IN0);
|
||||
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc2990_show_value, NULL,
|
||||
LTC2990_IN1);
|
||||
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc2990_show_value, NULL,
|
||||
LTC2990_IN2);
|
||||
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc2990_show_value, NULL,
|
||||
LTC2990_IN3);
|
||||
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc2990_show_value, NULL,
|
||||
LTC2990_IN4);
|
||||
|
||||
static struct attribute *ltc2990_attrs[] = {
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_curr1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_curr2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_input.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ltc2990);
|
||||
|
||||
static const struct attribute_group ltc2990_group = {
|
||||
.attrs = ltc2990_attrs,
|
||||
.is_visible = ltc2990_attrs_visible,
|
||||
};
|
||||
__ATTRIBUTE_GROUPS(ltc2990);
|
||||
|
||||
static int ltc2990_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct device *hwmon_dev;
|
||||
struct ltc2990_data *data;
|
||||
struct device_node *of_node = i2c->dev.of_node;
|
||||
|
||||
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
/* Setup continuous mode, current monitor */
|
||||
data = devm_kzalloc(&i2c->dev, sizeof(struct ltc2990_data), GFP_KERNEL);
|
||||
if (unlikely(!data))
|
||||
return -ENOMEM;
|
||||
|
||||
data->i2c = i2c;
|
||||
|
||||
if (of_node) {
|
||||
ret = of_property_read_u32_array(of_node, "lltc,meas-mode",
|
||||
data->mode, 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (data->mode[0] & ~LTC2990_MODE0_MASK ||
|
||||
data->mode[1] & ~LTC2990_MODE1_MASK)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
ret = i2c_smbus_read_byte_data(i2c, LTC2990_CONTROL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data->mode[0] = ret >> LTC2990_MODE0_SHIFT & LTC2990_MODE0_MASK;
|
||||
data->mode[1] = ret >> LTC2990_MODE1_SHIFT & LTC2990_MODE1_MASK;
|
||||
}
|
||||
|
||||
/* Setup continuous mode */
|
||||
ret = i2c_smbus_write_byte_data(i2c, LTC2990_CONTROL,
|
||||
LTC2990_CONTROL_MEASURE_ALL |
|
||||
LTC2990_CONTROL_MODE_CURRENT);
|
||||
data->mode[0] << LTC2990_MODE0_SHIFT |
|
||||
data->mode[1] << LTC2990_MODE1_SHIFT);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c->dev, "Error: Failed to set control mode.\n");
|
||||
return ret;
|
||||
@ -134,7 +264,7 @@ static int ltc2990_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_groups(&i2c->dev,
|
||||
i2c->name,
|
||||
i2c,
|
||||
data,
|
||||
ltc2990_groups);
|
||||
|
||||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
|
@ -63,6 +63,10 @@ static int mc13783_adc_read(struct device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* ADIN7 subchannels */
|
||||
if (channel >= 16)
|
||||
channel = 7;
|
||||
|
||||
channel &= 0x7;
|
||||
|
||||
*val = (sample[channel % 4] >> (channel > 3 ? 14 : 2)) & 0x3ff;
|
||||
@ -111,6 +115,57 @@ static ssize_t mc13783_adc_read_gp(struct device *dev,
|
||||
return sprintf(buf, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t mc13783_adc_read_uid(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
unsigned int val;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data;
|
||||
int ret = mc13783_adc_read(dev, devattr, &val);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (driver_data & MC13783_ADC_BPDIV2)
|
||||
/* MC13892 have 1/2 divider, input range is [0, 4.800V] */
|
||||
val = DIV_ROUND_CLOSEST(val * 4800, 1024);
|
||||
else
|
||||
/* MC13783 have 0.9 divider, input range is [0, 2.555V] */
|
||||
val = DIV_ROUND_CLOSEST(val * 2555, 1024);
|
||||
|
||||
return sprintf(buf, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t mc13783_adc_read_temp(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
unsigned int val;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data;
|
||||
int ret = mc13783_adc_read(dev, devattr, &val);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (driver_data & MC13783_ADC_BPDIV2) {
|
||||
/*
|
||||
* MC13892:
|
||||
* Die Temperature Read Out Code at 25C 680
|
||||
* Temperature change per LSB +0.4244C
|
||||
*/
|
||||
ret = DIV_ROUND_CLOSEST(-2635920 + val * 4244, 10);
|
||||
} else {
|
||||
/*
|
||||
* MC13783:
|
||||
* Die Temperature Read Out Code at 25C 282
|
||||
* Temperature change per LSB -1.14C
|
||||
*/
|
||||
ret = 346480 - 1140 * val;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%d\n", ret);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(name);
|
||||
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, mc13783_adc_read_bp, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, mc13783_adc_read_gp, NULL, 5);
|
||||
@ -124,6 +179,9 @@ static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, mc13783_adc_read_gp, NULL, 12);
|
||||
static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, mc13783_adc_read_gp, NULL, 13);
|
||||
static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, mc13783_adc_read_gp, NULL, 14);
|
||||
static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, mc13783_adc_read_gp, NULL, 15);
|
||||
static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, mc13783_adc_read_uid, NULL, 16);
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
|
||||
mc13783_adc_read_temp, NULL, 17);
|
||||
|
||||
static struct attribute *mc13783_attr_base[] = {
|
||||
&dev_attr_name.attr,
|
||||
@ -131,6 +189,8 @@ static struct attribute *mc13783_attr_base[] = {
|
||||
&sensor_dev_attr_in5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in16_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -279,8 +279,21 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
|
||||
adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2;
|
||||
adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC;
|
||||
|
||||
if (channel > 7)
|
||||
/*
|
||||
* Channels mapped through ADIN7:
|
||||
* 7 - General purpose ADIN7
|
||||
* 16 - UID
|
||||
* 17 - Die temperature
|
||||
*/
|
||||
if (channel > 7 && channel < 16) {
|
||||
adc1 |= MC13XXX_ADC1_ADSEL;
|
||||
} else if (channel == 16) {
|
||||
adc0 |= MC13XXX_ADC0_ADIN7SEL_UID;
|
||||
channel = 7;
|
||||
} else if (channel == 17) {
|
||||
adc0 |= MC13XXX_ADC0_ADIN7SEL_DIE;
|
||||
channel = 7;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case MC13XXX_ADC_MODE_TS:
|
||||
|
@ -243,6 +243,8 @@ struct mc13xxx_platform_data {
|
||||
#define MC13XXX_ADC0_LICELLCON (1 << 0)
|
||||
#define MC13XXX_ADC0_CHRGICON (1 << 1)
|
||||
#define MC13XXX_ADC0_BATICON (1 << 2)
|
||||
#define MC13XXX_ADC0_ADIN7SEL_DIE (1 << 4)
|
||||
#define MC13XXX_ADC0_ADIN7SEL_UID (2 << 4)
|
||||
#define MC13XXX_ADC0_ADREFEN (1 << 10)
|
||||
#define MC13XXX_ADC0_TSMOD0 (1 << 12)
|
||||
#define MC13XXX_ADC0_TSMOD1 (1 << 13)
|
||||
|
Loading…
Reference in New Issue
Block a user