summary refs log tree commit diff
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-19 11:28:36 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-19 11:28:36 -0800
commit89d3fa45b4add00cd0056361a2498e978cb1e119 (patch)
treeb717ab79c3258c3838d7d0753c5aeae61984e17c /drivers/acpi
parent477ea1169667a88d8ee12d83a0b0863091fb8670 (diff)
parent31908f45a583e8f21db37f402b6e8d5739945afd (diff)
downloadlinux-89d3fa45b4add00cd0056361a2498e978cb1e119.tar.gz
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal managament updates from Zhang Rui:
 "Specifics:

   - Abstract the code and introduce helper functions for all int340x
     thermal drivers.  From: Srinivas Pandruvada.

   - Reorganize the ACPI LPAT table support code so that it can be
     shared for both ACPI PMIC driver and int340x thermal driver.

   - Add support for Braswell in intel_soc_dts thermal driver.

   - a couple of small fixes/cleanups for step_wise governor and int340x
     thermal driver"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux:
  Thermal/int340x_thermal: remove unused uuids.
  thermal: step_wise: spelling fixes
  thermal: int340x: fix sparse warning
  Thermal/int340x: LPAT conversion for temperature
  ACPI / PMIC: Use common LPAT table handling functions
  ACPI / LPAT: Common table processing functions
  thermal: Intel SoC DTS: Add Braswell support
  Thermal/int340x/int3402: Provide notification support
  Thermal/int340x/processor_thermal: Add thermal zone support
  Thermal/int340x/int3403: Use int340x thermal API
  Thermal/int340x/int3402: Use int340x thermal API
  Thermal/int340x: Add common thermal zone handler
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/acpi_lpat.c161
-rw-r--r--drivers/acpi/pmic/intel_pmic.c133
3 files changed, 180 insertions, 115 deletions
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index b18cd2151ddb..623b117ad1a2 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -55,6 +55,7 @@ acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
 ifdef CONFIG_ACPI_VIDEO
 acpi-y				+= video_detect.o
 endif
+acpi-y				+= acpi_lpat.o
 
 # These are (potentially) separate modules
 
diff --git a/drivers/acpi/acpi_lpat.c b/drivers/acpi/acpi_lpat.c
new file mode 100644
index 000000000000..feb61c1630eb
--- /dev/null
+++ b/drivers/acpi/acpi_lpat.c
@@ -0,0 +1,161 @@
+/*
+ * acpi_lpat.c - LPAT table processing functions
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that 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/module.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_lpat.h>
+
+/**
+ * acpi_lpat_raw_to_temp(): Return temperature from raw value through
+ * LPAT conversion table
+ *
+ * @lpat_table: the temperature_raw mapping table structure
+ * @raw: the raw value, used as a key to get the temerature from the
+ *       above mapping table
+ *
+ * A positive converted temperarure value will be returned on success,
+ * a negative errno will be returned in error cases.
+ */
+int acpi_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table,
+			  int raw)
+{
+	int i, delta_temp, delta_raw, temp;
+	struct acpi_lpat *lpat = lpat_table->lpat;
+
+	for (i = 0; i < lpat_table->lpat_count - 1; i++) {
+		if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) ||
+		    (raw <= lpat[i].raw && raw >= lpat[i+1].raw))
+			break;
+	}
+
+	if (i == lpat_table->lpat_count - 1)
+		return -ENOENT;
+
+	delta_temp = lpat[i+1].temp - lpat[i].temp;
+	delta_raw = lpat[i+1].raw - lpat[i].raw;
+	temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw;
+
+	return temp;
+}
+EXPORT_SYMBOL_GPL(acpi_lpat_raw_to_temp);
+
+/**
+ * acpi_lpat_temp_to_raw(): Return raw value from temperature through
+ * LPAT conversion table
+ *
+ * @lpat: the temperature_raw mapping table
+ * @temp: the temperature, used as a key to get the raw value from the
+ *        above mapping table
+ *
+ * A positive converted temperature value will be returned on success,
+ * a negative errno will be returned in error cases.
+ */
+int acpi_lpat_temp_to_raw(struct acpi_lpat_conversion_table *lpat_table,
+			  int temp)
+{
+	int i, delta_temp, delta_raw, raw;
+	struct acpi_lpat *lpat = lpat_table->lpat;
+
+	for (i = 0; i < lpat_table->lpat_count - 1; i++) {
+		if (temp >= lpat[i].temp && temp <= lpat[i+1].temp)
+			break;
+	}
+
+	if (i ==  lpat_table->lpat_count - 1)
+		return -ENOENT;
+
+	delta_temp = lpat[i+1].temp - lpat[i].temp;
+	delta_raw = lpat[i+1].raw - lpat[i].raw;
+	raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp;
+
+	return raw;
+}
+EXPORT_SYMBOL_GPL(acpi_lpat_temp_to_raw);
+
+/**
+ * acpi_lpat_get_conversion_table(): Parse ACPI LPAT table if present.
+ *
+ * @handle: Handle to acpi device
+ *
+ * Parse LPAT table to a struct of type acpi_lpat_table. On success
+ * it returns a pointer to newly allocated table. This table must
+ * be freed by the caller when finished processing, using a call to
+ * acpi_lpat_free_conversion_table.
+ */
+struct acpi_lpat_conversion_table *acpi_lpat_get_conversion_table(acpi_handle
+								  handle)
+{
+	struct acpi_lpat_conversion_table *lpat_table = NULL;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj_p, *obj_e;
+	int *lpat, i;
+	acpi_status status;
+
+	status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer);
+	if (ACPI_FAILURE(status))
+		return NULL;
+
+	obj_p = (union acpi_object *)buffer.pointer;
+	if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) ||
+	    (obj_p->package.count % 2) || (obj_p->package.count < 4))
+		goto out;
+
+	lpat = kcalloc(obj_p->package.count, sizeof(int), GFP_KERNEL);
+	if (!lpat)
+		goto out;
+
+	for (i = 0; i < obj_p->package.count; i++) {
+		obj_e = &obj_p->package.elements[i];
+		if (obj_e->type != ACPI_TYPE_INTEGER) {
+			kfree(lpat);
+			goto out;
+		}
+		lpat[i] = (s64)obj_e->integer.value;
+	}
+
+	lpat_table = kzalloc(sizeof(*lpat_table), GFP_KERNEL);
+	if (!lpat_table) {
+		kfree(lpat);
+		goto out;
+	}
+
+	lpat_table->lpat = (struct acpi_lpat *)lpat;
+	lpat_table->lpat_count = obj_p->package.count / 2;
+
+out:
+	kfree(buffer.pointer);
+	return lpat_table;
+}
+EXPORT_SYMBOL_GPL(acpi_lpat_get_conversion_table);
+
+/**
+ * acpi_lpat_free_conversion_table(): Free LPAT table.
+ *
+ * @lpat_table: the temperature_raw mapping table structure
+ *
+ * Frees the LPAT table previously allocated by a call to
+ * acpi_lpat_get_conversion_table.
+ */
+void acpi_lpat_free_conversion_table(struct acpi_lpat_conversion_table
+				     *lpat_table)
+{
+	if (lpat_table) {
+		kfree(lpat_table->lpat);
+		kfree(lpat_table);
+	}
+}
+EXPORT_SYMBOL_GPL(acpi_lpat_free_conversion_table);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c
index a732e5d7e322..bd772cd56494 100644
--- a/drivers/acpi/pmic/intel_pmic.c
+++ b/drivers/acpi/pmic/intel_pmic.c
@@ -16,20 +16,15 @@
 #include <linux/module.h>
 #include <linux/acpi.h>
 #include <linux/regmap.h>
+#include <acpi/acpi_lpat.h>
 #include "intel_pmic.h"
 
 #define PMIC_POWER_OPREGION_ID		0x8d
 #define PMIC_THERMAL_OPREGION_ID	0x8c
 
-struct acpi_lpat {
-	int temp;
-	int raw;
-};
-
 struct intel_pmic_opregion {
 	struct mutex lock;
-	struct acpi_lpat *lpat;
-	int lpat_count;
+	struct acpi_lpat_conversion_table *lpat_table;
 	struct regmap *regmap;
 	struct intel_pmic_opregion_data *data;
 };
@@ -50,105 +45,6 @@ static int pmic_get_reg_bit(int address, struct pmic_table *table,
 	return -ENOENT;
 }
 
-/**
- * raw_to_temp(): Return temperature from raw value through LPAT table
- *
- * @lpat: the temperature_raw mapping table
- * @count: the count of the above mapping table
- * @raw: the raw value, used as a key to get the temerature from the
- *       above mapping table
- *
- * A positive value will be returned on success, a negative errno will
- * be returned in error cases.
- */
-static int raw_to_temp(struct acpi_lpat *lpat, int count, int raw)
-{
-	int i, delta_temp, delta_raw, temp;
-
-	for (i = 0; i < count - 1; i++) {
-		if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) ||
-		    (raw <= lpat[i].raw && raw >= lpat[i+1].raw))
-			break;
-	}
-
-	if (i == count - 1)
-		return -ENOENT;
-
-	delta_temp = lpat[i+1].temp - lpat[i].temp;
-	delta_raw = lpat[i+1].raw - lpat[i].raw;
-	temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw;
-
-	return temp;
-}
-
-/**
- * temp_to_raw(): Return raw value from temperature through LPAT table
- *
- * @lpat: the temperature_raw mapping table
- * @count: the count of the above mapping table
- * @temp: the temperature, used as a key to get the raw value from the
- *        above mapping table
- *
- * A positive value will be returned on success, a negative errno will
- * be returned in error cases.
- */
-static int temp_to_raw(struct acpi_lpat *lpat, int count, int temp)
-{
-	int i, delta_temp, delta_raw, raw;
-
-	for (i = 0; i < count - 1; i++) {
-		if (temp >= lpat[i].temp && temp <= lpat[i+1].temp)
-			break;
-	}
-
-	if (i == count - 1)
-		return -ENOENT;
-
-	delta_temp = lpat[i+1].temp - lpat[i].temp;
-	delta_raw = lpat[i+1].raw - lpat[i].raw;
-	raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp;
-
-	return raw;
-}
-
-static void pmic_thermal_lpat(struct intel_pmic_opregion *opregion,
-			      acpi_handle handle, struct device *dev)
-{
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-	union acpi_object *obj_p, *obj_e;
-	int *lpat, i;
-	acpi_status status;
-
-	status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer);
-	if (ACPI_FAILURE(status))
-		return;
-
-	obj_p = (union acpi_object *)buffer.pointer;
-	if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) ||
-	    (obj_p->package.count % 2) || (obj_p->package.count < 4))
-		goto out;
-
-	lpat = devm_kmalloc(dev, sizeof(int) * obj_p->package.count,
-			    GFP_KERNEL);
-	if (!lpat)
-		goto out;
-
-	for (i = 0; i < obj_p->package.count; i++) {
-		obj_e = &obj_p->package.elements[i];
-		if (obj_e->type != ACPI_TYPE_INTEGER) {
-			devm_kfree(dev, lpat);
-			goto out;
-		}
-		lpat[i] = (s64)obj_e->integer.value;
-	}
-
-	opregion->lpat = (struct acpi_lpat *)lpat;
-	opregion->lpat_count = obj_p->package.count / 2;
-
-out:
-	kfree(buffer.pointer);
-}
-
 static acpi_status intel_pmic_power_handler(u32 function,
 		acpi_physical_address address, u32 bits, u64 *value64,
 		void *handler_context, void *region_context)
@@ -192,12 +88,12 @@ static int pmic_read_temp(struct intel_pmic_opregion *opregion,
 	if (raw_temp < 0)
 		return raw_temp;
 
-	if (!opregion->lpat) {
+	if (!opregion->lpat_table) {
 		*value = raw_temp;
 		return 0;
 	}
 
-	temp = raw_to_temp(opregion->lpat, opregion->lpat_count, raw_temp);
+	temp = acpi_lpat_raw_to_temp(opregion->lpat_table, raw_temp);
 	if (temp < 0)
 		return temp;
 
@@ -223,9 +119,8 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg,
 	if (!opregion->data->update_aux)
 		return -ENXIO;
 
-	if (opregion->lpat) {
-		raw_temp = temp_to_raw(opregion->lpat, opregion->lpat_count,
-				       *value);
+	if (opregion->lpat_table) {
+		raw_temp = acpi_lpat_temp_to_raw(opregion->lpat_table, *value);
 		if (raw_temp < 0)
 			return raw_temp;
 	} else {
@@ -314,6 +209,7 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
 {
 	acpi_status status;
 	struct intel_pmic_opregion *opregion;
+	int ret;
 
 	if (!dev || !regmap || !d)
 		return -EINVAL;
@@ -327,14 +223,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
 
 	mutex_init(&opregion->lock);
 	opregion->regmap = regmap;
-	pmic_thermal_lpat(opregion, handle, dev);
+	opregion->lpat_table = acpi_lpat_get_conversion_table(handle);
 
 	status = acpi_install_address_space_handler(handle,
 						    PMIC_POWER_OPREGION_ID,
 						    intel_pmic_power_handler,
 						    NULL, opregion);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
+	if (ACPI_FAILURE(status)) {
+		ret = -ENODEV;
+		goto out_error;
+	}
 
 	status = acpi_install_address_space_handler(handle,
 						    PMIC_THERMAL_OPREGION_ID,
@@ -343,11 +241,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
 	if (ACPI_FAILURE(status)) {
 		acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID,
 						  intel_pmic_power_handler);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out_error;
 	}
 
 	opregion->data = d;
 	return 0;
+
+out_error:
+	acpi_lpat_free_conversion_table(opregion->lpat_table);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler);