diff mbox

[2/3] acpi: dptf_power: Add DPTF power participant

Message ID 1462589984-27253-3-git-send-email-srinivas.pandruvada@linux.intel.com (mailing list archive)
State Superseded, archived
Delegated to: Rafael Wysocki
Headers show

Commit Message

Srinivas Pandruvada May 7, 2016, 2:59 a.m. UTC
This driver adds support for Dynamic Platform and Thermal Framework
(DPTF) Platform Power Participant device support.
This participant is responsible for exposing platform telemetry such as
platform Power, battery Information such as state of Charge, estimated
maximum sustainable power (PMax), SMART battery spec information.

This driver is implemented as a platform driver for INT3407 and presented
as power_supply device. Since this has common features with the ACPI
battery, existing interface provide by battery_common driver are reused
to present as a battery power supply device.

Since this driver will also register a battery power supply device,this
driver will exit if CONFIG_ACPI_BATTERY is defined.

There are two types of objects in INT3407:
- Same as ACPI Battery objects: _BST and _BIX. These are exposed as
standard power supply attributes.
- Specific to INT3407, which are related to platform power
There are some objects, for which it doesn't make sense to enhance
power_supply class and add attributes there. They are represented as
sysfs attribute under acpi device. Here the bid for INT3407 is TPWR
in the following example.
/sys/class/power_supply/TPWR
??? alarm
??? capacity
??? capacity_level
??? cycle_count
??? device -> ../../../INT3407:00
?   ??? dptf_power
?   ?   ??? adapter_rating
?   ?   ??? battery_steady_power
?   ?   ??? charger_type
?   ?   ??? max_platform_power
?   ?   ??? platform_power_source
?   ?   ??? power_sampling_period

For example representing AC/adapter properties as a power_supply
properties will not make sense for a battery device. In some case
when there is an existing property, the meaning is different.
For example charger_type has a equivalent power_supply property,
which has different symantics than INT3407.

ACPI methods description used in this driver:
PSOC: Platform Battery State Of Charge as a percentage.
PMAX: Maximum platform power that can be supported by the battery in mW.
PSRC: System charge source,
	0x00 = DC
	0x01 = AC
	0x02 = USB
	0x03 = Wireless Charger
ARTG: Adapter rating in mW (Maximum Adapter power) Must be 0 if no AC
	Adaptor is plugged in.
CTYP: Charger Type,
	Traditional : 0x01
	Hybrid: 0x02
	NVDC: 0x03
PBSS: Returns max sustained power for battery in milliWatts.
DPSP: Sets the polling interval in 10ths of seconds. A value of 0 tells
	the driver to use event notification for PMAX and PBSS

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
 drivers/acpi/Kconfig      |  19 ++++++
 drivers/acpi/Makefile     |   1 +
 drivers/acpi/dptf_power.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 177 insertions(+)
 create mode 100644 drivers/acpi/dptf_power.c

Comments

Rafael J. Wysocki June 21, 2016, 4:15 p.m. UTC | #1
On Friday, May 06, 2016 07:59:43 PM Srinivas Pandruvada wrote:
> This driver adds support for Dynamic Platform and Thermal Framework
> (DPTF) Platform Power Participant device support.
> This participant is responsible for exposing platform telemetry such as
> platform Power, battery Information such as state of Charge, estimated
> maximum sustainable power (PMax), SMART battery spec information.
> 
> This driver is implemented as a platform driver for INT3407 and presented
> as power_supply device. Since this has common features with the ACPI
> battery, existing interface provide by battery_common driver are reused
> to present as a battery power supply device.
> 
> Since this driver will also register a battery power supply device,this
> driver will exit if CONFIG_ACPI_BATTERY is defined.
> 
> There are two types of objects in INT3407:
> - Same as ACPI Battery objects: _BST and _BIX. These are exposed as
> standard power supply attributes.
> - Specific to INT3407, which are related to platform power
> There are some objects, for which it doesn't make sense to enhance
> power_supply class and add attributes there. They are represented as
> sysfs attribute under acpi device. Here the bid for INT3407 is TPWR
> in the following example.
> /sys/class/power_supply/TPWR
> ├── alarm
> ├── capacity
> ├── capacity_level
> ├── cycle_count
> ├── device -> ../../../INT3407:00
> │   ├── dptf_power
> │   │   ├── adapter_rating
> │   │   ├── battery_steady_power
> │   │   ├── charger_type
> │   │   ├── max_platform_power
> │   │   ├── platform_power_source
> │   │   ├── power_sampling_period
> 
> For example representing AC/adapter properties as a power_supply
> properties will not make sense for a battery device. In some case
> when there is an existing property, the meaning is different.
> For example charger_type has a equivalent power_supply property,
> which has different symantics than INT3407.
> 
> ACPI methods description used in this driver:
> PSOC: Platform Battery State Of Charge as a percentage.
> PMAX: Maximum platform power that can be supported by the battery in mW.
> PSRC: System charge source,
> 	0x00 = DC
> 	0x01 = AC
> 	0x02 = USB
> 	0x03 = Wireless Charger
> ARTG: Adapter rating in mW (Maximum Adapter power) Must be 0 if no AC
> 	Adaptor is plugged in.
> CTYP: Charger Type,
> 	Traditional : 0x01
> 	Hybrid: 0x02
> 	NVDC: 0x03
> PBSS: Returns max sustained power for battery in milliWatts.
> DPSP: Sets the polling interval in 10ths of seconds. A value of 0 tells
> 	the driver to use event notification for PMAX and PBSS
> 
> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> ---
>  drivers/acpi/Kconfig      |  19 ++++++
>  drivers/acpi/Makefile     |   1 +
>  drivers/acpi/dptf_power.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 177 insertions(+)
>  create mode 100644 drivers/acpi/dptf_power.c
> 
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index bc5af2c..ac5cfe8 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -526,4 +526,23 @@ config XPOWER_PMIC_OPREGION
>  
>  endif
>  
> +config DPTF_POWER
> +	tristate "DPTF Platform Power Participant"
> +	depends on X86 && !ACPI_BATTERY

After a closer look, distros won't like this.

They need to have a binary image that will work on all systems, so they need
to be able to build both modules at the same time.

I guess the DPTF one can be made look if there is a driver attached to the
battery device object already and bail out if that's the case.

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index bc5af2c..ac5cfe8 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -526,4 +526,23 @@  config XPOWER_PMIC_OPREGION
 
 endif
 
+config DPTF_POWER
+	tristate "DPTF Platform Power Participant"
+	depends on X86 && !ACPI_BATTERY
+	select ACPI_BATTERY_COMMON
+	select POWER_SUPPLY
+	default y
+	help
+	  This driver adds support for Dynamic Platform and Thermal Framework
+	  (DPTF) Platform Power Participant device support.
+	  This participant is responsible for exposing platform telemetry such
+	  as platform Power, battery Information such as state of Charge,
+	  estimated maximum sustainable power (PMax), SMART battery spec
+	  information.
+	  Since this driver will also register a battery device, this driver
+	  will exit if ACPI_BATTERY is defined.
+
+	  To compile this driver as a module, choose M here:
+	  the module will be called dptf_power.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 0ea5fd1..3aebdbc 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -74,6 +74,7 @@  obj-$(CONFIG_ACPI)		+= acpi_memhotplug.o
 obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
 obj-$(CONFIG_ACPI_BATTERY_COMMON) += battery_common.o
 obj-$(CONFIG_ACPI_BATTERY)	+= battery.o
+obj-$(CONFIG_DPTF_POWER)	+= dptf_power.o
 obj-$(CONFIG_ACPI_SBS)		+= sbshc.o
 obj-$(CONFIG_ACPI_SBS)		+= sbs.o
 obj-$(CONFIG_ACPI_HED)		+= hed.o
diff --git a/drivers/acpi/dptf_power.c b/drivers/acpi/dptf_power.c
new file mode 100644
index 0000000..7bea100
--- /dev/null
+++ b/drivers/acpi/dptf_power.c
@@ -0,0 +1,157 @@ 
+/*
+ * dptf_power:  DPTF platform power driver
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+#include "battery.h"
+
+#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 = to_acpi_device(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, "%llu\n", val);\
+	else\
+		return -EINVAL;\
+}
+
+DPTF_POWER_SHOW(max_platform_power, PMAX)
+DPTF_POWER_SHOW(platform_power_source, PSRC)
+DPTF_POWER_SHOW(adapter_rating, ARTG)
+DPTF_POWER_SHOW(charger_type, CTYP)
+DPTF_POWER_SHOW(battery_steady_power, PBSS)
+DPTF_POWER_SHOW(power_sampling_period, DPSP)
+
+
+static DEVICE_ATTR_RO(max_platform_power);
+static DEVICE_ATTR_RO(platform_power_source);
+static DEVICE_ATTR_RO(adapter_rating);
+static DEVICE_ATTR_RO(battery_steady_power);
+static DEVICE_ATTR_RO(power_sampling_period);
+static DEVICE_ATTR_RO(charger_type);
+
+static struct attribute *dptf_power_attrs[] = {
+	&dev_attr_max_platform_power.attr,
+	&dev_attr_platform_power_source.attr,
+	&dev_attr_adapter_rating.attr,
+	&dev_attr_charger_type.attr,
+	&dev_attr_battery_steady_power.attr,
+	&dev_attr_power_sampling_period.attr,
+	NULL
+};
+
+static struct attribute_group dptf_power_attribute_group = {
+	.attrs = dptf_power_attrs,
+	.name = "dptf_power"
+};
+
+static void dptf_power_notify(acpi_handle handle, u32 event, void *data)
+{
+	struct acpi_device *device = data;
+
+	acpi_battery_common_notify(device, event);
+}
+
+static int dptf_power_add(struct platform_device *pdev)
+{
+	struct acpi_device *acpi_dev;
+	acpi_status status;
+	unsigned long long ptype;
+	int result;
+
+#if IS_ENABLED(CONFIG_ACPI_BATTERY)
+	/* Don't register two battery devices with power supply class */
+	return -ENODEV;
+#endif
+	acpi_dev = ACPI_COMPANION(&(pdev->dev));
+	if (!acpi_dev)
+		return -ENODEV;
+
+	status = acpi_evaluate_integer(acpi_dev->handle, "PTYP", NULL, &ptype);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	if (ptype != 0x11)
+		return -ENODEV;
+
+
+	result = acpi_battery_common_add(acpi_dev);
+	if (result)
+		return result;
+
+	result = sysfs_create_group(&acpi_dev->dev.kobj,
+				    &dptf_power_attribute_group);
+	if (result)
+		goto error_remove_battery;
+
+	result = acpi_install_notify_handler(acpi_dev->handle,
+					     ACPI_DEVICE_NOTIFY,
+					     dptf_power_notify,
+					     (void *)acpi_dev);
+	if (result)
+		goto error_remove_sysfs;
+
+	platform_set_drvdata(pdev, acpi_dev);
+
+	return 0;
+
+error_remove_sysfs:
+	sysfs_remove_group(&acpi_dev->dev.kobj, &dptf_power_attribute_group);
+error_remove_battery:
+	acpi_battery_common_remove(acpi_dev);
+	return result;
+}
+
+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);
+	sysfs_remove_group(&acpi_dev->dev.kobj, &dptf_power_attribute_group);
+	acpi_battery_common_remove(acpi_dev);
+
+	return 0;
+}
+
+static const struct acpi_device_id int3407_device_ids[] = {
+	{"INT3407", 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");