summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/acpi_lpat.c161
-rw-r--r--drivers/acpi/acpi_lpss.c21
-rw-r--r--drivers/acpi/ec.c4
-rw-r--r--drivers/acpi/pmic/intel_pmic.c133
-rw-r--r--drivers/acpi/resource.c2
-rw-r--r--drivers/acpi/video.c9
7 files changed, 210 insertions, 121 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/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 02e835f3cf8a..657964e8ab7e 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -105,7 +105,7 @@ static void lpss_uart_setup(struct lpss_private_data *pdata)
}
}
-static void byt_i2c_setup(struct lpss_private_data *pdata)
+static void lpss_deassert_reset(struct lpss_private_data *pdata)
{
unsigned int offset;
u32 val;
@@ -114,9 +114,18 @@ static void byt_i2c_setup(struct lpss_private_data *pdata)
val = readl(pdata->mmio_base + offset);
val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC;
writel(val, pdata->mmio_base + offset);
+}
+
+#define LPSS_I2C_ENABLE 0x6c
+
+static void byt_i2c_setup(struct lpss_private_data *pdata)
+{
+ lpss_deassert_reset(pdata);
if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset))
pdata->fixed_clk_rate = 133000000;
+
+ writel(0, pdata->mmio_base + LPSS_I2C_ENABLE);
}
static struct lpss_device_desc lpt_dev_desc = {
@@ -125,7 +134,7 @@ static struct lpss_device_desc lpt_dev_desc = {
};
static struct lpss_device_desc lpt_i2c_dev_desc = {
- .flags = LPSS_CLK | LPSS_LTR,
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR,
.prv_offset = 0x800,
};
@@ -166,6 +175,12 @@ static struct lpss_device_desc byt_i2c_dev_desc = {
.setup = byt_i2c_setup,
};
+static struct lpss_device_desc bsw_spi_dev_desc = {
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
+ .prv_offset = 0x400,
+ .setup = lpss_deassert_reset,
+};
+
#else
#define LPSS_ADDR(desc) (0UL)
@@ -198,7 +213,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
/* Braswell LPSS devices */
{ "80862288", LPSS_ADDR(byt_pwm_dev_desc) },
{ "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
- { "8086228E", LPSS_ADDR(byt_spi_dev_desc) },
+ { "8086228E", LPSS_ADDR(bsw_spi_dev_desc) },
{ "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
{ "INT3430", LPSS_ADDR(lpt_dev_desc) },
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 982b67faaaf3..a8dd2f763382 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -680,7 +680,7 @@ static void acpi_ec_start(struct acpi_ec *ec, bool resuming)
/* Enable GPE for event processing (SCI_EVT=1) */
if (!resuming)
acpi_ec_submit_request(ec);
- pr_info("+++++ EC started +++++\n");
+ pr_debug("EC started\n");
}
spin_unlock_irqrestore(&ec->lock, flags);
}
@@ -712,7 +712,7 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
acpi_ec_complete_request(ec);
clear_bit(EC_FLAGS_STARTED, &ec->flags);
clear_bit(EC_FLAGS_STOPPED, &ec->flags);
- pr_info("+++++ EC stopped +++++\n");
+ pr_debug("EC stopped\n");
}
spin_unlock_irqrestore(&ec->lock, flags);
}
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);
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 4752b9939987..c723668e3e27 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -46,7 +46,7 @@ static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
if (len && reslen && reslen == len && start <= end)
return true;
- pr_info("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
+ pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
io ? "io" : "mem", start, end, len);
return false;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 88a4f99dd2a7..debd30917010 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -540,6 +540,15 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "730U3E/740U3E"),
},
},
+ {
+ /* https://bugs.freedesktop.org/show_bug.cgi?id=87286 */
+ .callback = video_disable_native_backlight,
+ .ident = "SAMSUNG 900X3C/900X3D/900X3E/900X4C/900X4D",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "900X3C/900X3D/900X3E/900X4C/900X4D"),
+ },
+ },
{
/* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */