aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches-4.4/015-1-thermal-qcom-tsens-Add-a-skeletal-TSENS-drivers.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ipq806x/patches-4.4/015-1-thermal-qcom-tsens-Add-a-skeletal-TSENS-drivers.patch')
-rw-r--r--target/linux/ipq806x/patches-4.4/015-1-thermal-qcom-tsens-Add-a-skeletal-TSENS-drivers.patch536
1 files changed, 0 insertions, 536 deletions
diff --git a/target/linux/ipq806x/patches-4.4/015-1-thermal-qcom-tsens-Add-a-skeletal-TSENS-drivers.patch b/target/linux/ipq806x/patches-4.4/015-1-thermal-qcom-tsens-Add-a-skeletal-TSENS-drivers.patch
deleted file mode 100644
index ef7e2f4152..0000000000
--- a/target/linux/ipq806x/patches-4.4/015-1-thermal-qcom-tsens-Add-a-skeletal-TSENS-drivers.patch
+++ /dev/null
@@ -1,536 +0,0 @@
-From 9066073c6c27994a30187abf3b674770b4088348 Mon Sep 17 00:00:00 2001
-From: Rajendra Nayak <rnayak@codeaurora.org>
-Date: Thu, 5 May 2016 14:21:39 +0530
-Subject: thermal: qcom: tsens: Add a skeletal TSENS drivers
-
-TSENS is Qualcomms' thermal temperature sensor device. It
-supports reading temperatures from multiple thermal sensors
-present on various QCOM SoCs.
-Calibration data is generally read from a non-volatile memory
-(eeprom) device.
-
-Add a skeleton driver with all the necessary abstractions so
-a variety of qcom device families which support TSENS can
-add driver extensions.
-
-Also add the required device tree bindings which can be used
-to describe the TSENS device in DT.
-
-Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
-Reviewed-by: Lina Iyer <lina.iyer@linaro.org>
-Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
-Signed-off-by: Zhang Rui <rui.zhang@intel.com>
----
- .../devicetree/bindings/thermal/qcom-tsens.txt | 21 +++
- drivers/thermal/Kconfig | 5 +
- drivers/thermal/Makefile | 1 +
- drivers/thermal/qcom/Kconfig | 11 ++
- drivers/thermal/qcom/Makefile | 2 +
- drivers/thermal/qcom/tsens-common.c | 141 +++++++++++++++
- drivers/thermal/qcom/tsens.c | 195 +++++++++++++++++++++
- drivers/thermal/qcom/tsens.h | 90 ++++++++++
- 8 files changed, 466 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/thermal/qcom-tsens.txt
- create mode 100644 drivers/thermal/qcom/Kconfig
- create mode 100644 drivers/thermal/qcom/Makefile
- create mode 100644 drivers/thermal/qcom/tsens-common.c
- create mode 100644 drivers/thermal/qcom/tsens.c
- create mode 100644 drivers/thermal/qcom/tsens.h
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
-@@ -0,0 +1,21 @@
-+* QCOM SoC Temperature Sensor (TSENS)
-+
-+Required properties:
-+- compatible :
-+ - "qcom,msm8916-tsens" : For 8916 Family of SoCs
-+ - "qcom,msm8974-tsens" : For 8974 Family of SoCs
-+ - "qcom,msm8996-tsens" : For 8996 Family of SoCs
-+
-+- reg: Address range of the thermal registers
-+- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
-+- Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify
-+nvmem cells
-+
-+Example:
-+tsens: thermal-sensor@900000 {
-+ compatible = "qcom,msm8916-tsens";
-+ reg = <0x4a8000 0x2000>;
-+ nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
-+ nvmem-cell-names = "caldata", "calsel";
-+ #thermal-sensor-cells = <1>;
-+ };
---- a/drivers/thermal/Kconfig
-+++ b/drivers/thermal/Kconfig
-@@ -391,4 +391,9 @@ config QCOM_SPMI_TEMP_ALARM
- real time die temperature if an ADC is present or an estimate of the
- temperature based upon the over temperature stage value.
-
-+menu "Qualcomm thermal drivers"
-+depends on (ARCH_QCOM && OF) || COMPILE_TEST
-+source "drivers/thermal/qcom/Kconfig"
-+endmenu
-+
- endif
---- a/drivers/thermal/Makefile
-+++ b/drivers/thermal/Makefile
-@@ -48,3 +48,4 @@ obj-$(CONFIG_INTEL_PCH_THERMAL) += intel
- obj-$(CONFIG_ST_THERMAL) += st/
- obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o
- obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
-+obj-$(CONFIG_QCOM_TSENS) += qcom/
---- /dev/null
-+++ b/drivers/thermal/qcom/Kconfig
-@@ -0,0 +1,11 @@
-+config QCOM_TSENS
-+ tristate "Qualcomm TSENS Temperature Alarm"
-+ depends on THERMAL
-+ depends on QCOM_QFPROM
-+ depends on ARCH_QCOM || COMPILE_TEST
-+ help
-+ This enables the thermal sysfs driver for the TSENS device. It shows
-+ up in Sysfs as a thermal zone with multiple trip points. Disabling the
-+ thermal zone device via the mode file results in disabling the sensor.
-+ Also able to set threshold temperature for both hot and cold and update
-+ when a threshold is reached.
---- /dev/null
-+++ b/drivers/thermal/qcom/Makefile
-@@ -0,0 +1,2 @@
-+obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
-+qcom_tsens-y += tsens.o tsens-common.o
---- /dev/null
-+++ b/drivers/thermal/qcom/tsens-common.c
-@@ -0,0 +1,141 @@
-+/*
-+ * 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/err.h>
-+#include <linux/io.h>
-+#include <linux/nvmem-consumer.h>
-+#include <linux/of_address.h>
-+#include <linux/platform_device.h>
-+#include <linux/regmap.h>
-+#include "tsens.h"
-+
-+#define S0_ST_ADDR 0x1030
-+#define SN_ADDR_OFFSET 0x4
-+#define SN_ST_TEMP_MASK 0x3ff
-+#define CAL_DEGC_PT1 30
-+#define CAL_DEGC_PT2 120
-+#define SLOPE_FACTOR 1000
-+#define SLOPE_DEFAULT 3200
-+
-+char *qfprom_read(struct device *dev, const char *cname)
-+{
-+ struct nvmem_cell *cell;
-+ ssize_t data;
-+ char *ret;
-+
-+ cell = nvmem_cell_get(dev, cname);
-+ if (IS_ERR(cell))
-+ return ERR_CAST(cell);
-+
-+ ret = nvmem_cell_read(cell, &data);
-+ nvmem_cell_put(cell);
-+
-+ return ret;
-+}
-+
-+/*
-+ * Use this function on devices where slope and offset calculations
-+ * depend on calibration data read from qfprom. On others the slope
-+ * and offset values are derived from tz->tzp->slope and tz->tzp->offset
-+ * resp.
-+ */
-+void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
-+ u32 *p2, u32 mode)
-+{
-+ int i;
-+ int num, den;
-+
-+ for (i = 0; i < tmdev->num_sensors; i++) {
-+ dev_dbg(tmdev->dev,
-+ "sensor%d - data_point1:%#x data_point2:%#x\n",
-+ i, p1[i], p2[i]);
-+
-+ tmdev->sensor[i].slope = SLOPE_DEFAULT;
-+ if (mode == TWO_PT_CALIB) {
-+ /*
-+ * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
-+ * temp_120_degc - temp_30_degc (x2 - x1)
-+ */
-+ num = p2[i] - p1[i];
-+ num *= SLOPE_FACTOR;
-+ den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
-+ tmdev->sensor[i].slope = num / den;
-+ }
-+
-+ tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
-+ (CAL_DEGC_PT1 *
-+ tmdev->sensor[i].slope);
-+ dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset);
-+ }
-+}
-+
-+static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
-+{
-+ int degc, num, den;
-+
-+ num = (adc_code * SLOPE_FACTOR) - s->offset;
-+ den = s->slope;
-+
-+ if (num > 0)
-+ degc = num + (den / 2);
-+ else if (num < 0)
-+ degc = num - (den / 2);
-+ else
-+ degc = num;
-+
-+ degc /= den;
-+
-+ return degc;
-+}
-+
-+int get_temp_common(struct tsens_device *tmdev, int id, int *temp)
-+{
-+ struct tsens_sensor *s = &tmdev->sensor[id];
-+ u32 code;
-+ unsigned int sensor_addr;
-+ int last_temp = 0, ret;
-+
-+ sensor_addr = S0_ST_ADDR + s->hw_id * SN_ADDR_OFFSET;
-+ ret = regmap_read(tmdev->map, sensor_addr, &code);
-+ if (ret)
-+ return ret;
-+ last_temp = code & SN_ST_TEMP_MASK;
-+
-+ *temp = code_to_degc(last_temp, s) * 1000;
-+
-+ return 0;
-+}
-+
-+static const struct regmap_config tsens_config = {
-+ .reg_bits = 32,
-+ .val_bits = 32,
-+ .reg_stride = 4,
-+};
-+
-+int __init init_common(struct tsens_device *tmdev)
-+{
-+ void __iomem *base;
-+
-+ base = of_iomap(tmdev->dev->of_node, 0);
-+ if (IS_ERR(base))
-+ return -EINVAL;
-+
-+ tmdev->map = devm_regmap_init_mmio(tmdev->dev, base, &tsens_config);
-+ if (!tmdev->map) {
-+ iounmap(base);
-+ return -ENODEV;
-+ }
-+
-+ return 0;
-+}
---- /dev/null
-+++ b/drivers/thermal/qcom/tsens.c
-@@ -0,0 +1,195 @@
-+/*
-+ * 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/err.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm.h>
-+#include <linux/slab.h>
-+#include <linux/thermal.h>
-+#include "tsens.h"
-+
-+static int tsens_get_temp(void *data, int *temp)
-+{
-+ const struct tsens_sensor *s = data;
-+ struct tsens_device *tmdev = s->tmdev;
-+
-+ return tmdev->ops->get_temp(tmdev, s->id, temp);
-+}
-+
-+static int tsens_get_trend(void *data, long *temp)
-+{
-+ const struct tsens_sensor *s = data;
-+ struct tsens_device *tmdev = s->tmdev;
-+
-+ if (tmdev->ops->get_trend)
-+ return tmdev->ops->get_trend(tmdev, s->id, temp);
-+
-+ return -ENOTSUPP;
-+}
-+
-+static int tsens_suspend(struct device *dev)
-+{
-+ struct tsens_device *tmdev = dev_get_drvdata(dev);
-+
-+ if (tmdev->ops && tmdev->ops->suspend)
-+ return tmdev->ops->suspend(tmdev);
-+
-+ return 0;
-+}
-+
-+static int tsens_resume(struct device *dev)
-+{
-+ struct tsens_device *tmdev = dev_get_drvdata(dev);
-+
-+ if (tmdev->ops && tmdev->ops->resume)
-+ return tmdev->ops->resume(tmdev);
-+
-+ return 0;
-+}
-+
-+static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume);
-+
-+static const struct of_device_id tsens_table[] = {
-+ {
-+ .compatible = "qcom,msm8916-tsens",
-+ }, {
-+ .compatible = "qcom,msm8974-tsens",
-+ },
-+ {}
-+};
-+MODULE_DEVICE_TABLE(of, tsens_table);
-+
-+static const struct thermal_zone_of_device_ops tsens_of_ops = {
-+ .get_temp = tsens_get_temp,
-+ .get_trend = tsens_get_trend,
-+};
-+
-+static int tsens_register(struct tsens_device *tmdev)
-+{
-+ int i;
-+ struct thermal_zone_device *tzd;
-+ u32 *hw_id, n = tmdev->num_sensors;
-+
-+ hw_id = devm_kcalloc(tmdev->dev, n, sizeof(u32), GFP_KERNEL);
-+ if (!hw_id)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < tmdev->num_sensors; i++) {
-+ tmdev->sensor[i].tmdev = tmdev;
-+ tmdev->sensor[i].id = i;
-+ tzd = devm_thermal_zone_of_sensor_register(tmdev->dev, i,
-+ &tmdev->sensor[i],
-+ &tsens_of_ops);
-+ if (IS_ERR(tzd))
-+ continue;
-+ tmdev->sensor[i].tzd = tzd;
-+ if (tmdev->ops->enable)
-+ tmdev->ops->enable(tmdev, i);
-+ }
-+ return 0;
-+}
-+
-+static int tsens_probe(struct platform_device *pdev)
-+{
-+ int ret, i;
-+ struct device *dev;
-+ struct device_node *np;
-+ struct tsens_sensor *s;
-+ struct tsens_device *tmdev;
-+ const struct tsens_data *data;
-+ const struct of_device_id *id;
-+
-+ if (pdev->dev.of_node)
-+ dev = &pdev->dev;
-+ else
-+ dev = pdev->dev.parent;
-+
-+ np = dev->of_node;
-+
-+ id = of_match_node(tsens_table, np);
-+ if (!id)
-+ return -EINVAL;
-+
-+ data = id->data;
-+
-+ if (data->num_sensors <= 0) {
-+ dev_err(dev, "invalid number of sensors\n");
-+ return -EINVAL;
-+ }
-+
-+ tmdev = devm_kzalloc(dev, sizeof(*tmdev) +
-+ data->num_sensors * sizeof(*s), GFP_KERNEL);
-+ if (!tmdev)
-+ return -ENOMEM;
-+
-+ tmdev->dev = dev;
-+ tmdev->num_sensors = data->num_sensors;
-+ tmdev->ops = data->ops;
-+ for (i = 0; i < tmdev->num_sensors; i++) {
-+ if (data->hw_ids)
-+ tmdev->sensor[i].hw_id = data->hw_ids[i];
-+ else
-+ tmdev->sensor[i].hw_id = i;
-+ }
-+
-+ if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->get_temp)
-+ return -EINVAL;
-+
-+ ret = tmdev->ops->init(tmdev);
-+ if (ret < 0) {
-+ dev_err(dev, "tsens init failed\n");
-+ return ret;
-+ }
-+
-+ if (tmdev->ops->calibrate) {
-+ ret = tmdev->ops->calibrate(tmdev);
-+ if (ret < 0) {
-+ dev_err(dev, "tsens calibration failed\n");
-+ return ret;
-+ }
-+ }
-+
-+ ret = tsens_register(tmdev);
-+
-+ platform_set_drvdata(pdev, tmdev);
-+
-+ return ret;
-+}
-+
-+static int tsens_remove(struct platform_device *pdev)
-+{
-+ struct tsens_device *tmdev = platform_get_drvdata(pdev);
-+
-+ if (tmdev->ops->disable)
-+ tmdev->ops->disable(tmdev);
-+
-+ return 0;
-+}
-+
-+static struct platform_driver tsens_driver = {
-+ .probe = tsens_probe,
-+ .remove = tsens_remove,
-+ .driver = {
-+ .name = "qcom-tsens",
-+ .pm = &tsens_pm_ops,
-+ .of_match_table = tsens_table,
-+ },
-+};
-+module_platform_driver(tsens_driver);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_DESCRIPTION("QCOM Temperature Sensor driver");
-+MODULE_ALIAS("platform:qcom-tsens");
---- /dev/null
-+++ b/drivers/thermal/qcom/tsens.h
-@@ -0,0 +1,90 @@
-+/*
-+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
-+ *
-+ * This software is licensed under the terms of the GNU General Public
-+ * License version 2, as published by the Free Software Foundation, and
-+ * may be copied, distributed, and modified under those terms.
-+ *
-+ * 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.
-+ */
-+#ifndef __QCOM_TSENS_H__
-+#define __QCOM_TSENS_H__
-+
-+#define ONE_PT_CALIB 0x1
-+#define ONE_PT_CALIB2 0x2
-+#define TWO_PT_CALIB 0x3
-+
-+struct tsens_device;
-+
-+struct tsens_sensor {
-+ struct tsens_device *tmdev;
-+ struct thermal_zone_device *tzd;
-+ int offset;
-+ int id;
-+ int hw_id;
-+ int slope;
-+ u32 status;
-+};
-+
-+/**
-+ * struct tsens_ops - operations as supported by the tsens device
-+ * @init: Function to initialize the tsens device
-+ * @calibrate: Function to calibrate the tsens device
-+ * @get_temp: Function which returns the temp in millidegC
-+ * @enable: Function to enable (clocks/power) tsens device
-+ * @disable: Function to disable the tsens device
-+ * @suspend: Function to suspend the tsens device
-+ * @resume: Function to resume the tsens device
-+ * @get_trend: Function to get the thermal/temp trend
-+ */
-+struct tsens_ops {
-+ /* mandatory callbacks */
-+ int (*init)(struct tsens_device *);
-+ int (*calibrate)(struct tsens_device *);
-+ int (*get_temp)(struct tsens_device *, int, int *);
-+ /* optional callbacks */
-+ int (*enable)(struct tsens_device *, int);
-+ void (*disable)(struct tsens_device *);
-+ int (*suspend)(struct tsens_device *);
-+ int (*resume)(struct tsens_device *);
-+ int (*get_trend)(struct tsens_device *, int, long *);
-+};
-+
-+/**
-+ * struct tsens_data - tsens instance specific data
-+ * @num_sensors: Max number of sensors supported by platform
-+ * @ops: operations the tsens instance supports
-+ * @hw_ids: Subset of sensors ids supported by platform, if not the first n
-+ */
-+struct tsens_data {
-+ const u32 num_sensors;
-+ const struct tsens_ops *ops;
-+ unsigned int *hw_ids;
-+};
-+
-+/* Registers to be saved/restored across a context loss */
-+struct tsens_context {
-+ int threshold;
-+ int control;
-+};
-+
-+struct tsens_device {
-+ struct device *dev;
-+ u32 num_sensors;
-+ struct regmap *map;
-+ struct regmap_field *status_field;
-+ struct tsens_context ctx;
-+ bool trdy;
-+ const struct tsens_ops *ops;
-+ struct tsens_sensor sensor[0];
-+};
-+
-+char *qfprom_read(struct device *, const char *);
-+void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
-+int init_common(struct tsens_device *);
-+int get_temp_common(struct tsens_device *, int, int *);
-+
-+#endif /* __QCOM_TSENS_H__ */