mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
7b52b200cf
This driver adds support for Dynamic Platform and Thermal Framework battery participant device support. These attributes are presented via sysfs interface under the platform device for the battery participant: $ls /sys/bus/platform/devices/INT3532:00/dptf_battery current_discharge_capbility_ma max_platform_power_mw no_load_voltage_mv high_freq_impedance_mohm max_steady_state_power_mw Refer to the documentation at Documentation/ABI/testing/sysfs-platform-dptf for details. Here the implementation reuses existing dptf-power.c as the motivation and processing is same. It also shares one ACPI method. Here this change is using participant type, "PTYP" method to identify and do different processing. By using participant type, create/delete either "dptf_power" or "dptf_battery" attribute group and send notifications. The particpant type for for the battery participant is 0x0C. ACPI methods description: PMAX (Intel(R) Dynamic Tuning Platform Max Power Supplied by Battery): This object evaluates to the maximum platform power that can be supported by the battery in milli watts. PBSS (Intel(R) Dynamic Tuning Power Battery Steady State): This object returns the max sustained power for battery in milli watts. RBHF (Intel(R) Dynamic Tuning High Frequency Impedance): This object returns high frequency impedance value that can be obtained from battery fuel gauge. VBNL (Intel(R) Dynamic Tuning No-Load Voltage) This object returns battery instantaneous no-load voltage that can be obtained from battery fuel gauge in milli volts CMPP (Intel(R) Dynamic Tuning Current Discharge Capability) This object returns battery discharge current capability obtained from battery fuel gauge milli amps. Notifications: 0x80: PMAX change. Used to notify Intel(R)Dynamic Tuning Battery participant driver when the PMAX has changed by 250mw. 0x83: PBSS change. Used to notify Intel(R) Dynamic Tuning Battery participant driver when the power source has changed. 0x85: RBHF change. Used to notify Intel(R)Dynamic Tuning Battery participant driver when the RBHF has changed over a threshold by 5mOhm. 0x86: Battery Capability change. Used to notify Intel(R)Dynamic Tuning Battery participant driver when the battery capability has changed. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> [ rjw: Subject ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
249 lines
6.4 KiB
C
249 lines
6.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* dptf_power: DPTF platform power driver
|
|
* Copyright (c) 2016, Intel Corporation.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/acpi.h>
|
|
#include <linux/platform_device.h>
|
|
|
|
/*
|
|
* Presentation of attributes which are defined for INT3407 and INT3532.
|
|
* They are:
|
|
* PMAX : Maximum platform powe
|
|
* PSRC : Platform power source
|
|
* ARTG : Adapter rating
|
|
* CTYP : Charger type
|
|
* PBSS : Battery steady power
|
|
* PROP : Rest of worst case platform Power
|
|
* PBSS : Power Battery Steady State
|
|
* PBSS : Power Battery Steady State
|
|
* RBHF : High Frequency Impedance
|
|
* VBNL : Instantaneous No-Load Voltage
|
|
* CMPP : Current Discharge Capability
|
|
*/
|
|
#define DPTF_POWER_SHOW(name, object) \
|
|
static ssize_t name##_show(struct device *dev,\
|
|
struct device_attribute *attr,\
|
|
char *buf)\
|
|
{\
|
|
struct acpi_device *acpi_dev = dev_get_drvdata(dev);\
|
|
unsigned long long val;\
|
|
acpi_status status;\
|
|
\
|
|
status = acpi_evaluate_integer(acpi_dev->handle, #object,\
|
|
NULL, &val);\
|
|
if (ACPI_SUCCESS(status))\
|
|
return sprintf(buf, "%d\n", (int)val);\
|
|
else \
|
|
return -EINVAL;\
|
|
}
|
|
|
|
DPTF_POWER_SHOW(max_platform_power_mw, PMAX)
|
|
DPTF_POWER_SHOW(platform_power_source, PSRC)
|
|
DPTF_POWER_SHOW(adapter_rating_mw, ARTG)
|
|
DPTF_POWER_SHOW(battery_steady_power_mw, PBSS)
|
|
DPTF_POWER_SHOW(charger_type, CTYP)
|
|
DPTF_POWER_SHOW(rest_of_platform_power_mw, PROP)
|
|
DPTF_POWER_SHOW(max_steady_state_power_mw, PBSS)
|
|
DPTF_POWER_SHOW(high_freq_impedance_mohm, RBHF)
|
|
DPTF_POWER_SHOW(no_load_voltage_mv, VBNL)
|
|
DPTF_POWER_SHOW(current_discharge_capbility_ma, CMPP);
|
|
|
|
static DEVICE_ATTR_RO(max_platform_power_mw);
|
|
static DEVICE_ATTR_RO(platform_power_source);
|
|
static DEVICE_ATTR_RO(adapter_rating_mw);
|
|
static DEVICE_ATTR_RO(battery_steady_power_mw);
|
|
static DEVICE_ATTR_RO(charger_type);
|
|
static DEVICE_ATTR_RO(rest_of_platform_power_mw);
|
|
static DEVICE_ATTR_RO(max_steady_state_power_mw);
|
|
static DEVICE_ATTR_RO(high_freq_impedance_mohm);
|
|
static DEVICE_ATTR_RO(no_load_voltage_mv);
|
|
static DEVICE_ATTR_RO(current_discharge_capbility_ma);
|
|
|
|
static ssize_t prochot_confirm_store(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
struct acpi_device *acpi_dev = dev_get_drvdata(dev);
|
|
acpi_status status;
|
|
int seq_no;
|
|
|
|
if (kstrtouint(buf, 0, &seq_no) < 0)
|
|
return -EINVAL;
|
|
|
|
status = acpi_execute_simple_method(acpi_dev->handle, "PBOK", seq_no);
|
|
if (ACPI_SUCCESS(status))
|
|
return count;
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
static DEVICE_ATTR_WO(prochot_confirm);
|
|
|
|
static struct attribute *dptf_power_attrs[] = {
|
|
&dev_attr_max_platform_power_mw.attr,
|
|
&dev_attr_platform_power_source.attr,
|
|
&dev_attr_adapter_rating_mw.attr,
|
|
&dev_attr_battery_steady_power_mw.attr,
|
|
&dev_attr_charger_type.attr,
|
|
&dev_attr_rest_of_platform_power_mw.attr,
|
|
&dev_attr_prochot_confirm.attr,
|
|
NULL
|
|
};
|
|
|
|
static const struct attribute_group dptf_power_attribute_group = {
|
|
.attrs = dptf_power_attrs,
|
|
.name = "dptf_power"
|
|
};
|
|
|
|
static struct attribute *dptf_battery_attrs[] = {
|
|
&dev_attr_max_platform_power_mw.attr,
|
|
&dev_attr_max_steady_state_power_mw.attr,
|
|
&dev_attr_high_freq_impedance_mohm.attr,
|
|
&dev_attr_no_load_voltage_mv.attr,
|
|
&dev_attr_current_discharge_capbility_ma.attr,
|
|
NULL
|
|
};
|
|
|
|
static const struct attribute_group dptf_battery_attribute_group = {
|
|
.attrs = dptf_battery_attrs,
|
|
.name = "dptf_battery"
|
|
};
|
|
|
|
#define MAX_POWER_CHANGED 0x80
|
|
#define POWER_STATE_CHANGED 0x81
|
|
#define STEADY_STATE_POWER_CHANGED 0x83
|
|
#define POWER_PROP_CHANGE_EVENT 0x84
|
|
#define IMPEDANCED_CHNGED 0x85
|
|
#define VOLTAGE_CURRENT_CHANGED 0x86
|
|
|
|
static long long dptf_participant_type(acpi_handle handle)
|
|
{
|
|
unsigned long long ptype;
|
|
acpi_status status;
|
|
|
|
status = acpi_evaluate_integer(handle, "PTYP", NULL, &ptype);
|
|
if (ACPI_FAILURE(status))
|
|
return -ENODEV;
|
|
|
|
return ptype;
|
|
}
|
|
|
|
static void dptf_power_notify(acpi_handle handle, u32 event, void *data)
|
|
{
|
|
struct platform_device *pdev = data;
|
|
char *attr;
|
|
|
|
switch (event) {
|
|
case POWER_STATE_CHANGED:
|
|
attr = "platform_power_source";
|
|
break;
|
|
case POWER_PROP_CHANGE_EVENT:
|
|
attr = "rest_of_platform_power_mw";
|
|
break;
|
|
case MAX_POWER_CHANGED:
|
|
attr = "max_platform_power_mw";
|
|
break;
|
|
case STEADY_STATE_POWER_CHANGED:
|
|
attr = "max_steady_state_power_mw";
|
|
break;
|
|
case VOLTAGE_CURRENT_CHANGED:
|
|
attr = "no_load_voltage_mv";
|
|
break;
|
|
default:
|
|
dev_err(&pdev->dev, "Unsupported event [0x%x]\n", event);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Notify that an attribute is changed, so that user space can read
|
|
* again.
|
|
*/
|
|
if (dptf_participant_type(handle) == 0x0CULL)
|
|
sysfs_notify(&pdev->dev.kobj, "dptf_battery", attr);
|
|
else
|
|
sysfs_notify(&pdev->dev.kobj, "dptf_power", attr);
|
|
}
|
|
|
|
static int dptf_power_add(struct platform_device *pdev)
|
|
{
|
|
const struct attribute_group *attr_group;
|
|
struct acpi_device *acpi_dev;
|
|
unsigned long long ptype;
|
|
int result;
|
|
|
|
acpi_dev = ACPI_COMPANION(&(pdev->dev));
|
|
if (!acpi_dev)
|
|
return -ENODEV;
|
|
|
|
ptype = dptf_participant_type(acpi_dev->handle);
|
|
if (ptype == 0x11)
|
|
attr_group = &dptf_power_attribute_group;
|
|
else if (ptype == 0x0C)
|
|
attr_group = &dptf_battery_attribute_group;
|
|
else
|
|
return -ENODEV;
|
|
|
|
result = acpi_install_notify_handler(acpi_dev->handle,
|
|
ACPI_DEVICE_NOTIFY,
|
|
dptf_power_notify,
|
|
(void *)pdev);
|
|
if (result)
|
|
return result;
|
|
|
|
result = sysfs_create_group(&pdev->dev.kobj,
|
|
attr_group);
|
|
if (result) {
|
|
acpi_remove_notify_handler(acpi_dev->handle,
|
|
ACPI_DEVICE_NOTIFY,
|
|
dptf_power_notify);
|
|
return result;
|
|
}
|
|
|
|
platform_set_drvdata(pdev, acpi_dev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dptf_power_remove(struct platform_device *pdev)
|
|
{
|
|
struct acpi_device *acpi_dev = platform_get_drvdata(pdev);
|
|
|
|
acpi_remove_notify_handler(acpi_dev->handle,
|
|
ACPI_DEVICE_NOTIFY,
|
|
dptf_power_notify);
|
|
|
|
if (dptf_participant_type(acpi_dev->handle) == 0x0CULL)
|
|
sysfs_remove_group(&pdev->dev.kobj, &dptf_battery_attribute_group);
|
|
else
|
|
sysfs_remove_group(&pdev->dev.kobj, &dptf_power_attribute_group);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct acpi_device_id int3407_device_ids[] = {
|
|
{"INT3407", 0},
|
|
{"INT3532", 0},
|
|
{"INTC1047", 0},
|
|
{"", 0},
|
|
};
|
|
MODULE_DEVICE_TABLE(acpi, int3407_device_ids);
|
|
|
|
static struct platform_driver dptf_power_driver = {
|
|
.probe = dptf_power_add,
|
|
.remove = dptf_power_remove,
|
|
.driver = {
|
|
.name = "DPTF Platform Power",
|
|
.acpi_match_table = int3407_device_ids,
|
|
},
|
|
};
|
|
|
|
module_platform_driver(dptf_power_driver);
|
|
|
|
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
|
|
MODULE_LICENSE("GPL v2");
|
|
MODULE_DESCRIPTION("ACPI DPTF platform power driver");
|