diff options
Diffstat (limited to 'target/linux/ipq806x/patches-4.4/015-4-thermal-qcom-tsens-8960-Add-support-for-8960-family-of-SoCs.patch')
-rw-r--r-- | target/linux/ipq806x/patches-4.4/015-4-thermal-qcom-tsens-8960-Add-support-for-8960-family-of-SoCs.patch | 364 |
1 files changed, 0 insertions, 364 deletions
diff --git a/target/linux/ipq806x/patches-4.4/015-4-thermal-qcom-tsens-8960-Add-support-for-8960-family-of-SoCs.patch b/target/linux/ipq806x/patches-4.4/015-4-thermal-qcom-tsens-8960-Add-support-for-8960-family-of-SoCs.patch deleted file mode 100644 index 05490cd97d..0000000000 --- a/target/linux/ipq806x/patches-4.4/015-4-thermal-qcom-tsens-8960-Add-support-for-8960-family-of-SoCs.patch +++ /dev/null @@ -1,364 +0,0 @@ -From 20d4fd84bf524ad91e2cc3e4ab4020c27cfc0081 Mon Sep 17 00:00:00 2001 -From: Rajendra Nayak <rnayak@codeaurora.org> -Date: Thu, 5 May 2016 14:21:43 +0530 -Subject: thermal: qcom: tsens-8960: Add support for 8960 family of SoCs - -8960 family of SoCs have the TSENS device as part of GCC, hence -the driver probes the virtual child device created by GCC and -uses the parent to extract all DT properties and reuses the GCC -regmap. - -Also GCC/TSENS are part of a domain thats not always ON. -Hence add .suspend and .resume hooks to save and restore some of -the inited register context. - -Also 8960 family have some of the TSENS init sequence thats -required to be done by the HLOS driver (some later versions of TSENS -do not export these registers to non-secure world, and hence need -these initializations to be done by secure bootloaders) - -8660 from the same family has just one sensor and hence some register -offset/layout differences which need special handling in the driver. - -Based on the original code from Siddartha Mohanadoss, Stephen Boyd and -Narendran Rajan. - -Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org> -Signed-off-by: Eduardo Valentin <edubezval@gmail.com> -Signed-off-by: Zhang Rui <rui.zhang@intel.com> ---- - drivers/thermal/qcom/Makefile | 2 +- - drivers/thermal/qcom/tsens-8960.c | 292 ++++++++++++++++++++++++++++++++++++++ - drivers/thermal/qcom/tsens.c | 8 +- - drivers/thermal/qcom/tsens.h | 2 +- - 4 files changed, 298 insertions(+), 6 deletions(-) - create mode 100644 drivers/thermal/qcom/tsens-8960.c - ---- a/drivers/thermal/qcom/Makefile -+++ b/drivers/thermal/qcom/Makefile -@@ -1,2 +1,2 @@ - obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o --qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o -+qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o ---- /dev/null -+++ b/drivers/thermal/qcom/tsens-8960.c -@@ -0,0 +1,292 @@ -+/* -+ * Copyright (c) 2015, The Linux Foundation. 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 and -+ * only 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/platform_device.h> -+#include <linux/delay.h> -+#include <linux/bitops.h> -+#include <linux/regmap.h> -+#include <linux/thermal.h> -+#include "tsens.h" -+ -+#define CAL_MDEGC 30000 -+ -+#define CONFIG_ADDR 0x3640 -+#define CONFIG_ADDR_8660 0x3620 -+/* CONFIG_ADDR bitmasks */ -+#define CONFIG 0x9b -+#define CONFIG_MASK 0xf -+#define CONFIG_8660 1 -+#define CONFIG_SHIFT_8660 28 -+#define CONFIG_MASK_8660 (3 << CONFIG_SHIFT_8660) -+ -+#define STATUS_CNTL_ADDR_8064 0x3660 -+#define CNTL_ADDR 0x3620 -+/* CNTL_ADDR bitmasks */ -+#define EN BIT(0) -+#define SW_RST BIT(1) -+#define SENSOR0_EN BIT(3) -+#define SLP_CLK_ENA BIT(26) -+#define SLP_CLK_ENA_8660 BIT(24) -+#define MEASURE_PERIOD 1 -+#define SENSOR0_SHIFT 3 -+ -+/* INT_STATUS_ADDR bitmasks */ -+#define MIN_STATUS_MASK BIT(0) -+#define LOWER_STATUS_CLR BIT(1) -+#define UPPER_STATUS_CLR BIT(2) -+#define MAX_STATUS_MASK BIT(3) -+ -+#define THRESHOLD_ADDR 0x3624 -+/* THRESHOLD_ADDR bitmasks */ -+#define THRESHOLD_MAX_LIMIT_SHIFT 24 -+#define THRESHOLD_MIN_LIMIT_SHIFT 16 -+#define THRESHOLD_UPPER_LIMIT_SHIFT 8 -+#define THRESHOLD_LOWER_LIMIT_SHIFT 0 -+ -+/* Initial temperature threshold values */ -+#define LOWER_LIMIT_TH 0x50 -+#define UPPER_LIMIT_TH 0xdf -+#define MIN_LIMIT_TH 0x0 -+#define MAX_LIMIT_TH 0xff -+ -+#define S0_STATUS_ADDR 0x3628 -+#define INT_STATUS_ADDR 0x363c -+#define TRDY_MASK BIT(7) -+#define TIMEOUT_US 100 -+ -+static int suspend_8960(struct tsens_device *tmdev) -+{ -+ int ret; -+ unsigned int mask; -+ struct regmap *map = tmdev->map; -+ -+ ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold); -+ if (ret) -+ return ret; -+ -+ ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control); -+ if (ret) -+ return ret; -+ -+ if (tmdev->num_sensors > 1) -+ mask = SLP_CLK_ENA | EN; -+ else -+ mask = SLP_CLK_ENA_8660 | EN; -+ -+ ret = regmap_update_bits(map, CNTL_ADDR, mask, 0); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static int resume_8960(struct tsens_device *tmdev) -+{ -+ int ret; -+ struct regmap *map = tmdev->map; -+ -+ ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST); -+ if (ret) -+ return ret; -+ -+ /* -+ * Separate CONFIG restore is not needed only for 8660 as -+ * config is part of CTRL Addr and its restored as such -+ */ -+ if (tmdev->num_sensors > 1) { -+ ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG); -+ if (ret) -+ return ret; -+ } -+ -+ ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold); -+ if (ret) -+ return ret; -+ -+ ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static int enable_8960(struct tsens_device *tmdev, int id) -+{ -+ int ret; -+ u32 reg, mask; -+ -+ ret = regmap_read(tmdev->map, CNTL_ADDR, ®); -+ if (ret) -+ return ret; -+ -+ mask = BIT(id + SENSOR0_SHIFT); -+ ret = regmap_write(tmdev->map, CNTL_ADDR, reg | SW_RST); -+ if (ret) -+ return ret; -+ -+ if (tmdev->num_sensors > 1) -+ reg |= mask | SLP_CLK_ENA | EN; -+ else -+ reg |= mask | SLP_CLK_ENA_8660 | EN; -+ -+ ret = regmap_write(tmdev->map, CNTL_ADDR, reg); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static void disable_8960(struct tsens_device *tmdev) -+{ -+ int ret; -+ u32 reg_cntl; -+ u32 mask; -+ -+ mask = GENMASK(tmdev->num_sensors - 1, 0); -+ mask <<= SENSOR0_SHIFT; -+ mask |= EN; -+ -+ ret = regmap_read(tmdev->map, CNTL_ADDR, ®_cntl); -+ if (ret) -+ return; -+ -+ reg_cntl &= ~mask; -+ -+ if (tmdev->num_sensors > 1) -+ reg_cntl &= ~SLP_CLK_ENA; -+ else -+ reg_cntl &= ~SLP_CLK_ENA_8660; -+ -+ regmap_write(tmdev->map, CNTL_ADDR, reg_cntl); -+} -+ -+static int init_8960(struct tsens_device *tmdev) -+{ -+ int ret, i; -+ u32 reg_cntl; -+ -+ tmdev->map = dev_get_regmap(tmdev->dev, NULL); -+ if (!tmdev->map) -+ return -ENODEV; -+ -+ /* -+ * The status registers for each sensor are discontiguous -+ * because some SoCs have 5 sensors while others have more -+ * but the control registers stay in the same place, i.e -+ * directly after the first 5 status registers. -+ */ -+ for (i = 0; i < tmdev->num_sensors; i++) { -+ if (i >= 5) -+ tmdev->sensor[i].status = S0_STATUS_ADDR + 40; -+ tmdev->sensor[i].status += i * 4; -+ } -+ -+ reg_cntl = SW_RST; -+ ret = regmap_update_bits(tmdev->map, CNTL_ADDR, SW_RST, reg_cntl); -+ if (ret) -+ return ret; -+ -+ if (tmdev->num_sensors > 1) { -+ reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18); -+ reg_cntl &= ~SW_RST; -+ ret = regmap_update_bits(tmdev->map, CONFIG_ADDR, -+ CONFIG_MASK, CONFIG); -+ } else { -+ reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16); -+ reg_cntl &= ~CONFIG_MASK_8660; -+ reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660; -+ } -+ -+ reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT; -+ ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl); -+ if (ret) -+ return ret; -+ -+ reg_cntl |= EN; -+ ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static int calibrate_8960(struct tsens_device *tmdev) -+{ -+ int i; -+ char *data; -+ -+ ssize_t num_read = tmdev->num_sensors; -+ struct tsens_sensor *s = tmdev->sensor; -+ -+ data = qfprom_read(tmdev->dev, "calib"); -+ if (IS_ERR(data)) -+ data = qfprom_read(tmdev->dev, "calib_backup"); -+ if (IS_ERR(data)) -+ return PTR_ERR(data); -+ -+ for (i = 0; i < num_read; i++, s++) -+ s->offset = data[i]; -+ -+ return 0; -+} -+ -+/* Temperature on y axis and ADC-code on x-axis */ -+static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s) -+{ -+ int slope, offset; -+ -+ slope = thermal_zone_get_slope(s->tzd); -+ offset = CAL_MDEGC - slope * s->offset; -+ -+ return adc_code * slope + offset; -+} -+ -+static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp) -+{ -+ int ret; -+ u32 code, trdy; -+ const struct tsens_sensor *s = &tmdev->sensor[id]; -+ unsigned long timeout; -+ -+ timeout = jiffies + usecs_to_jiffies(TIMEOUT_US); -+ do { -+ ret = regmap_read(tmdev->map, INT_STATUS_ADDR, &trdy); -+ if (ret) -+ return ret; -+ if (!(trdy & TRDY_MASK)) -+ continue; -+ ret = regmap_read(tmdev->map, s->status, &code); -+ if (ret) -+ return ret; -+ *temp = code_to_mdegC(code, s); -+ return 0; -+ } while (time_before(jiffies, timeout)); -+ -+ return -ETIMEDOUT; -+} -+ -+const struct tsens_ops ops_8960 = { -+ .init = init_8960, -+ .calibrate = calibrate_8960, -+ .get_temp = get_temp_8960, -+ .enable = enable_8960, -+ .disable = disable_8960, -+ .suspend = suspend_8960, -+ .resume = resume_8960, -+}; -+ -+const struct tsens_data data_8960 = { -+ .num_sensors = 11, -+ .ops = &ops_8960, -+}; ---- a/drivers/thermal/qcom/tsens.c -+++ b/drivers/thermal/qcom/tsens.c -@@ -122,10 +122,10 @@ static int tsens_probe(struct platform_d - np = dev->of_node; - - id = of_match_node(tsens_table, np); -- if (!id) -- return -EINVAL; -- -- data = id->data; -+ if (id) -+ data = id->data; -+ else -+ data = &data_8960; - - if (data->num_sensors <= 0) { - dev_err(dev, "invalid number of sensors\n"); ---- a/drivers/thermal/qcom/tsens.h -+++ b/drivers/thermal/qcom/tsens.h -@@ -87,6 +87,6 @@ void compute_intercept_slope(struct tsen - int init_common(struct tsens_device *); - int get_temp_common(struct tsens_device *, int, int *); - --extern const struct tsens_data data_8916, data_8974; -+extern const struct tsens_data data_8916, data_8974, data_8960; - - #endif /* __QCOM_TSENS_H__ */ |