summaryrefslogtreecommitdiff
path: root/drivers/acpi/pmic/intel_pmic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-27 00:56:45 (GMT)
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-27 00:56:45 (GMT)
commite663107fa1edda4d8a0d5b8ce704d71f8e27de43 (patch)
tree2ca367a9cdeb97ce613e792256b64831189af7b3 /drivers/acpi/pmic/intel_pmic.c
parent6453dbdda30428a3c56568c96fe70ea3612f07e2 (diff)
parent54d0b14ad7cc4ff3c710f092a93638f359c1b14b (diff)
downloadlinux-e663107fa1edda4d8a0d5b8ce704d71f8e27de43.tar.xz
Merge tag 'acpi-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI updates from Rafael Wysocki: "The new feaures here are the support for ACPI overlays (allowing ACPI tables to be loaded at any time from EFI variables or via configfs) and the LPI (Low-Power Idle) support. Also notable is the ACPI-based NUMA support for ARM64. Apart from that we have two new drivers, for the DPTF (Dynamic Power and Thermal Framework) power participant device and for the Intel Broxton WhiskeyCove PMIC, some more PMIC-related changes, support for the Boot Error Record Table (BERT) in APEI and support for platform-initiated graceful shutdown. Plus two new pieces of documentation and usual assorted fixes and cleanups in quite a few places. Specifics: - Support for ACPI SSDT overlays allowing Secondary System Description Tables (SSDTs) to be loaded at any time from EFI variables or via configfs (Octavian Purdila, Mika Westerberg). - Support for the ACPI LPI (Low-Power Idle) feature introduced in ACPI 6.0 and allowing processor idle states to be represented in ACPI tables in a hierarchical way (with the help of Processor Container objects) and support for ACPI idle states management on ARM64, based on LPI (Sudeep Holla). - General improvements of ACPI support for NUMA and ARM64 support for ACPI-based NUMA (Hanjun Guo, David Daney, Robert Richter). - General improvements of the ACPI table upgrade mechanism and ARM64 support for that feature (Aleksey Makarov, Jon Masters). - Support for the Boot Error Record Table (BERT) in APEI and improvements of kernel messages printed by the error injection code (Huang Ying, Borislav Petkov). - New driver for the Intel Broxton WhiskeyCove PMIC operation region and support for the REGS operation region on Broxton, PMIC code cleanups (Bin Gao, Felipe Balbi, Paul Gortmaker). - New driver for the power participant device which is part of the Dynamic Power and Thermal Framework (DPTF) and DPTF-related code reorganization (Srinivas Pandruvada). - Support for the platform-initiated graceful shutdown feature introduced in ACPI 6.1 (Prashanth Prakash). - ACPI button driver update related to lid input events generated automatically on initialization and system resume that have been problematic for some time (Lv Zheng). - ACPI EC driver cleanups (Lv Zheng). - Documentation of the ACPICA release automation process and the in-kernel ACPI AML debugger (Lv Zheng). - New blacklist entry and two fixes for the ACPI backlight driver (Alex Hung, Arvind Yadav, Ralf Gerbig). - Cleanups of the ACPI pci_slot driver (Joe Perches, Paul Gortmaker). - ACPI CPPC code changes to make it more robust against possible defects in ACPI tables and new symbol definitions for PCC (Hoan Tran). - System reboot code modification to execute the ACPI _PTS (Prepare To Sleep) method in addition to _TTS (Ocean He). - ACPICA-related change to carry out lock ordering checks in ACPICA if ACPICA debug is enabled in the kernel (Lv Zheng). - Assorted minor fixes and cleanups (Andy Shevchenko, Baoquan He, Bhaktipriya Shridhar, Paul Gortmaker, Rafael Wysocki)" * tag 'acpi-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (71 commits) ACPI: enable ACPI_PROCESSOR_IDLE on ARM64 arm64: add support for ACPI Low Power Idle(LPI) drivers: firmware: psci: initialise idle states using ACPI LPI cpuidle: introduce CPU_PM_CPU_IDLE_ENTER macro for ARM{32, 64} arm64: cpuidle: drop __init section marker to arm_cpuidle_init ACPI / processor_idle: Add support for Low Power Idle(LPI) states ACPI / processor_idle: introduce ACPI_PROCESSOR_CSTATE ACPI / DPTF: move int340x_thermal.c to the DPTF folder ACPI / DPTF: Add DPTF power participant driver ACPI / lpat: make it explicitly non-modular ACPI / dock: make dock explicitly non-modular ACPI / PCI: make pci_slot explicitly non-modular ACPI / PMIC: remove modular references from non-modular code ACPICA: Linux: Enable ACPI_MUTEX_DEBUG for Linux kernel ACPI: Rename configfs.c to acpi_configfs.c to prevent link error ACPI / debugger: Add AML debugger documentation ACPI: Add documentation describing ACPICA release automation ACPI: add support for loading SSDTs via configfs ACPI: add support for configfs efi / ACPI: load SSTDs from EFI variables ...
Diffstat (limited to 'drivers/acpi/pmic/intel_pmic.c')
-rw-r--r--drivers/acpi/pmic/intel_pmic.c84
1 files changed, 74 insertions, 10 deletions
diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c
index bd772cd..ca18e0d 100644
--- a/drivers/acpi/pmic/intel_pmic.c
+++ b/drivers/acpi/pmic/intel_pmic.c
@@ -13,7 +13,7 @@
* GNU General Public License for more details.
*/
-#include <linux/module.h>
+#include <linux/export.h>
#include <linux/acpi.h>
#include <linux/regmap.h>
#include <acpi/acpi_lpat.h>
@@ -21,12 +21,19 @@
#define PMIC_POWER_OPREGION_ID 0x8d
#define PMIC_THERMAL_OPREGION_ID 0x8c
+#define PMIC_REGS_OPREGION_ID 0x8f
+
+struct intel_pmic_regs_handler_ctx {
+ unsigned int val;
+ u16 addr;
+};
struct intel_pmic_opregion {
struct mutex lock;
struct acpi_lpat_conversion_table *lpat_table;
struct regmap *regmap;
struct intel_pmic_opregion_data *data;
+ struct intel_pmic_regs_handler_ctx ctx;
};
static int pmic_get_reg_bit(int address, struct pmic_table *table,
@@ -131,7 +138,7 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg,
}
static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg,
- u32 function, u64 *value)
+ int bit, u32 function, u64 *value)
{
struct intel_pmic_opregion_data *d = opregion->data;
struct regmap *regmap = opregion->regmap;
@@ -140,12 +147,12 @@ static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg,
return -ENXIO;
if (function == ACPI_READ)
- return d->get_policy(regmap, reg, value);
+ return d->get_policy(regmap, reg, bit, value);
if (*value != 0 && *value != 1)
return -EINVAL;
- return d->update_policy(regmap, reg, *value);
+ return d->update_policy(regmap, reg, bit, *value);
}
static bool pmic_thermal_is_temp(int address)
@@ -170,13 +177,13 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
{
struct intel_pmic_opregion *opregion = region_context;
struct intel_pmic_opregion_data *d = opregion->data;
- int reg, result;
+ int reg, bit, result;
if (bits != 32 || !value64)
return AE_BAD_PARAMETER;
result = pmic_get_reg_bit(address, d->thermal_table,
- d->thermal_table_count, &reg, NULL);
+ d->thermal_table_count, &reg, &bit);
if (result == -ENOENT)
return AE_BAD_PARAMETER;
@@ -187,7 +194,8 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
else if (pmic_thermal_is_aux(address))
result = pmic_thermal_aux(opregion, reg, function, value64);
else if (pmic_thermal_is_pen(address))
- result = pmic_thermal_pen(opregion, reg, function, value64);
+ result = pmic_thermal_pen(opregion, reg, bit,
+ function, value64);
else
result = -EINVAL;
@@ -203,6 +211,48 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
return AE_OK;
}
+static acpi_status intel_pmic_regs_handler(u32 function,
+ acpi_physical_address address, u32 bits, u64 *value64,
+ void *handler_context, void *region_context)
+{
+ struct intel_pmic_opregion *opregion = region_context;
+ int result = 0;
+
+ switch (address) {
+ case 0:
+ return AE_OK;
+ case 1:
+ opregion->ctx.addr |= (*value64 & 0xff) << 8;
+ return AE_OK;
+ case 2:
+ opregion->ctx.addr |= *value64 & 0xff;
+ return AE_OK;
+ case 3:
+ opregion->ctx.val = *value64 & 0xff;
+ return AE_OK;
+ case 4:
+ if (*value64) {
+ result = regmap_write(opregion->regmap, opregion->ctx.addr,
+ opregion->ctx.val);
+ } else {
+ result = regmap_read(opregion->regmap, opregion->ctx.addr,
+ &opregion->ctx.val);
+ if (result == 0)
+ *value64 = opregion->ctx.val;
+ }
+ memset(&opregion->ctx, 0x00, sizeof(opregion->ctx));
+ }
+
+ if (result < 0) {
+ if (result == -EINVAL)
+ return AE_BAD_PARAMETER;
+ else
+ return AE_ERROR;
+ }
+
+ return AE_OK;
+}
+
int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
struct regmap *regmap,
struct intel_pmic_opregion_data *d)
@@ -242,16 +292,30 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID,
intel_pmic_power_handler);
ret = -ENODEV;
- goto out_error;
+ goto out_remove_power_handler;
+ }
+
+ status = acpi_install_address_space_handler(handle,
+ PMIC_REGS_OPREGION_ID, intel_pmic_regs_handler, NULL,
+ opregion);
+ if (ACPI_FAILURE(status)) {
+ ret = -ENODEV;
+ goto out_remove_thermal_handler;
}
opregion->data = d;
return 0;
+out_remove_thermal_handler:
+ acpi_remove_address_space_handler(handle, PMIC_THERMAL_OPREGION_ID,
+ intel_pmic_thermal_handler);
+
+out_remove_power_handler:
+ acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID,
+ intel_pmic_power_handler);
+
out_error:
acpi_lpat_free_conversion_table(opregion->lpat_table);
return ret;
}
EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler);
-
-MODULE_LICENSE("GPL");