* [PATCH v2 1/9] thermal: qcom: tsens: Add a skeletal TSENS drivers
2015-09-16 6:23 [PATCH v2 0/9] qcom: Add support for TSENS driver Rajendra Nayak
@ 2015-09-16 6:23 ` Rajendra Nayak
2015-09-16 13:44 ` Punit Agrawal
2015-09-16 6:23 ` [PATCH v2 2/9] thermal: qcom: tsens-8916: Add support for 8916 family of SoCs Rajendra Nayak
` (7 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-16 6:23 UTC (permalink / raw)
To: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval
Cc: sboyd, srinivas.kandagatla, nrajan, lina.iyer, Rajendra Nayak
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>
---
.../devicetree/bindings/thermal/qcom-tsens.txt | 36 ++++
drivers/thermal/Kconfig | 5 +
drivers/thermal/Makefile | 1 +
drivers/thermal/qcom/Kconfig | 10 +
drivers/thermal/qcom/Makefile | 2 +
drivers/thermal/qcom/tsens.c | 208 +++++++++++++++++++++
drivers/thermal/qcom/tsens.h | 58 ++++++
7 files changed, 320 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.c
create mode 100644 drivers/thermal/qcom/tsens.h
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
new file mode 100644
index 0000000..3d54d37
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
@@ -0,0 +1,36 @@
+* QCOM SoC Temperature Sensor (TSENS)
+
+Required properties:
+- compatible :
+ - "qcom,msm8916-tsens" : For 8916 Family of SoCs
+ - "qcom,msm8974-tsens" : For 8974 Family of SoCs
+
+- reg: Address range of the thermal registers
+- qcom,tsens-slopes : Must contain slope value for each of the sensors controlled
+ by this device
+- #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
+
+Optional properties:
+- qcom,sensor-id: List of sensor instances used in a given SoC. A TSENS IP can
+ have a fixed number of sensors (like 11) but a given SoC can
+ use only 5 of these and they might not always the first 5. They
+ could be sensors 0, 1, 4, 8 and 9. This property is used to
+ describe the subset of the sensors used. If this property is
+ missing they are assumed to be the first 'n' sensors numbered
+ sequentially in which case the number of sensors defaults to
+ the number of slope values.
+
+Example:
+tsens: thermal-sensor@900000 {
+ compatible = "qcom,msm8916-tsens";
+ qcom,tsens-slopes = <1176 1176 1154 1176 1111
+ 1132 1132 1199 1132 1199
+ 1132>;
+ nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
+ nvmem-cell-names = "caldata", "calsel";
+ qcom,tsens-slopes = <3200 3200 3200 3200 3200>;
+ qcom,sensor-id = <0 1 2 4 5>;
+ #thermal-sensor-cells = <1>;
+ };
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 0390044..59ac3d8 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -373,4 +373,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
+source "drivers/thermal/qcom/Kconfig"
+endmenu
+
endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 26f1608..cdaa55f 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -43,5 +43,6 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
obj-$(CONFIG_ST_THERMAL) += st/
+obj-$(CONFIG_QCOM_TSENS) += qcom/
obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig
new file mode 100644
index 0000000..f7e8e40
--- /dev/null
+++ b/drivers/thermal/qcom/Kconfig
@@ -0,0 +1,10 @@
+config QCOM_TSENS
+ tristate "Qualcomm TSENS Temperature Alarm"
+ depends on THERMAL
+ depends on QCOM_QFPROM
+ 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.
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
new file mode 100644
index 0000000..401069b
--- /dev/null
+++ b/drivers/thermal/qcom/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
+qcom_tsens-y += tsens.o
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
new file mode 100644
index 0000000..9615845
--- /dev/null
+++ b/drivers/thermal/qcom/tsens.c
@@ -0,0 +1,208 @@
+/*
+ * 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 -ENOSYS;
+}
+
+#ifdef CONFIG_PM
+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);
+#define TSENS_PM_OPS (&tsens_pm_ops)
+
+#else /* CONFIG_PM_SLEEP */
+#define TSENS_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
+
+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, ret;
+ struct thermal_zone_device *tzd;
+ u32 *hw_id, n = tmdev->num_sensors;
+ struct device_node *np = tmdev->dev->of_node;
+
+ hw_id = devm_kcalloc(tmdev->dev, n, sizeof(u32), GFP_KERNEL);
+ if (!hw_id)
+ return -ENOMEM;
+
+ ret = of_property_read_u32_array(np, "qcom,sensor-id", hw_id, n);
+ if (ret)
+ for (i = 0; i < tmdev->num_sensors; i++)
+ tmdev->sensor[i].hw_id = i;
+ else
+ for (i = 0; i < tmdev->num_sensors; i++)
+ tmdev->sensor[i].hw_id = hw_id[i];
+
+ for (i = 0; i < tmdev->num_sensors; i++) {
+ tmdev->sensor[i].tmdev = tmdev;
+ tmdev->sensor[i].id = i;
+ tzd = 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, num;
+ struct device *dev;
+ struct device_node *np;
+ struct tsens_sensor *s;
+ struct tsens_device *tmdev;
+ const struct of_device_id *id;
+
+ dev = &pdev->dev;
+ np = dev->of_node;
+
+ num = of_property_count_u32_elems(np, "qcom,tsens-slopes");
+ if (num <= 0) {
+ dev_err(dev, "invalid tsens slopes\n");
+ return -EINVAL;
+ }
+
+ tmdev = devm_kzalloc(dev, sizeof(*tmdev) +
+ num * sizeof(*s), GFP_KERNEL);
+ if (!tmdev)
+ return -ENOMEM;
+
+ tmdev->dev = dev;
+ tmdev->num_sensors = num;
+
+ for (i = 0, s = tmdev->sensor; i < tmdev->num_sensors; i++, s++)
+ of_property_read_u32_index(np, "qcom,tsens-slopes", i,
+ &s->slope);
+
+ id = of_match_node(tsens_table, np);
+ if (!id)
+ return -ENODEV;
+
+ tmdev->ops = id->data;
+ if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->calibrate ||
+ !tmdev->ops->get_temp)
+ return -EINVAL;
+
+ ret = tmdev->ops->init(tmdev);
+ if (ret < 0) {
+ dev_err(dev, "tsens init failed\n");
+ return ret;
+ }
+
+ 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)
+{
+ int i;
+ struct tsens_device *tmdev = platform_get_drvdata(pdev);
+ struct thermal_zone_device *tzd;
+
+ if (tmdev->ops->disable)
+ tmdev->ops->disable(tmdev);
+
+ for (i = 0; i < tmdev->num_sensors; i++) {
+ tzd = tmdev->sensor[i].tzd;
+ thermal_zone_of_sensor_unregister(&pdev->dev, tzd);
+ }
+
+ 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");
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
new file mode 100644
index 0000000..f0fc353
--- /dev/null
+++ b/drivers/thermal/qcom/tsens.h
@@ -0,0 +1,58 @@
+/*
+ * 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__
+
+struct tsens_device;
+
+struct tsens_sensor {
+ struct tsens_device *tmdev;
+ struct thermal_zone_device *tzd;
+ int offset;
+ int id;
+ int hw_id;
+ u32 slope;
+ u32 status;
+};
+
+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 *);
+};
+
+/* 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];
+};
+
+#endif /* __QCOM_TSENS_H__ */
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/9] thermal: qcom: tsens: Add a skeletal TSENS drivers
2015-09-16 6:23 ` [PATCH v2 1/9] thermal: qcom: tsens: Add a skeletal TSENS drivers Rajendra Nayak
@ 2015-09-16 13:44 ` Punit Agrawal
2015-09-21 4:26 ` Rajendra Nayak
0 siblings, 1 reply; 18+ messages in thread
From: Punit Agrawal @ 2015-09-16 13:44 UTC (permalink / raw)
To: Rajendra Nayak
Cc: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval,
sboyd, srinivas.kandagatla, nrajan, lina.iyer
Hi Rajendra,
I have some comments on the code below (purely based on code review).
Rajendra Nayak <rnayak@codeaurora.org> writes:
> 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>
> ---
> .../devicetree/bindings/thermal/qcom-tsens.txt | 36 ++++
> drivers/thermal/Kconfig | 5 +
> drivers/thermal/Makefile | 1 +
> drivers/thermal/qcom/Kconfig | 10 +
> drivers/thermal/qcom/Makefile | 2 +
> drivers/thermal/qcom/tsens.c | 208 +++++++++++++++++++++
> drivers/thermal/qcom/tsens.h | 58 ++++++
> 7 files changed, 320 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.c
> create mode 100644 drivers/thermal/qcom/tsens.h
>
> diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
> new file mode 100644
> index 0000000..3d54d37
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
> @@ -0,0 +1,36 @@
> +* QCOM SoC Temperature Sensor (TSENS)
> +
> +Required properties:
> +- compatible :
> + - "qcom,msm8916-tsens" : For 8916 Family of SoCs
> + - "qcom,msm8974-tsens" : For 8974 Family of SoCs
> +
> +- reg: Address range of the thermal registers
> +- qcom,tsens-slopes : Must contain slope value for each of the sensors controlled
> + by this device
> +- #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
> +
> +Optional properties:
> +- qcom,sensor-id: List of sensor instances used in a given SoC. A TSENS IP can
> + have a fixed number of sensors (like 11) but a given SoC can
> + use only 5 of these and they might not always the first 5. They
> + could be sensors 0, 1, 4, 8 and 9. This property is used to
> + describe the subset of the sensors used. If this property is
> + missing they are assumed to be the first 'n' sensors numbered
> + sequentially in which case the number of sensors defaults to
> + the number of slope values.
> +
> +Example:
> +tsens: thermal-sensor@900000 {
> + compatible = "qcom,msm8916-tsens";
> + qcom,tsens-slopes = <1176 1176 1154 1176 1111
> + 1132 1132 1199 1132 1199
> + 1132>;
> + nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
> + nvmem-cell-names = "caldata", "calsel";
> + qcom,tsens-slopes = <3200 3200 3200 3200 3200>;
> + qcom,sensor-id = <0 1 2 4 5>;
> + #thermal-sensor-cells = <1>;
> + };
The qcom,tsens-slopes property appears twice in the above example.
[...]
> diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
> new file mode 100644
> index 0000000..9615845
> --- /dev/null
> +++ b/drivers/thermal/qcom/tsens.c
> @@ -0,0 +1,208 @@
> +/*
> + * 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 -ENOSYS;
> +}
> +
> +#ifdef CONFIG_PM
> +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);
> +#define TSENS_PM_OPS (&tsens_pm_ops)
> +
> +#else /* CONFIG_PM_SLEEP */
^
> +#define TSENS_PM_OPS NULL
> +#endif /* CONFIG_PM_SLEEP */
^
The comments don't match the #ifdef above. I maybe wrong but looking at
other drivers it looks like you don't need the #else part. You should be
able to use the tsens_pm_ops without having to set it to NULL.
> +
> +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, ret;
> + struct thermal_zone_device *tzd;
> + u32 *hw_id, n = tmdev->num_sensors;
> + struct device_node *np = tmdev->dev->of_node;
> +
> + hw_id = devm_kcalloc(tmdev->dev, n, sizeof(u32), GFP_KERNEL);
> + if (!hw_id)
> + return -ENOMEM;
> +
> + ret = of_property_read_u32_array(np, "qcom,sensor-id", hw_id, n);
> + if (ret)
> + for (i = 0; i < tmdev->num_sensors; i++)
> + tmdev->sensor[i].hw_id = i;
> + else
> + for (i = 0; i < tmdev->num_sensors; i++)
> + tmdev->sensor[i].hw_id = hw_id[i];
> +
You could move the check for vaild for valid sensor ids in the device
tree (ret) inside a single for loop. In that case the loop above could
be merged into the iteration over the sensors below.
> + for (i = 0; i < tmdev->num_sensors; i++) {
> + tmdev->sensor[i].tmdev = tmdev;
> + tmdev->sensor[i].id = i;
> + tzd = 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, num;
> + struct device *dev;
> + struct device_node *np;
> + struct tsens_sensor *s;
> + struct tsens_device *tmdev;
> + const struct of_device_id *id;
> +
> + dev = &pdev->dev;
> + np = dev->of_node;
These assignments can be done with the declaration above.
Thanks,
Punit
> +
> + num = of_property_count_u32_elems(np, "qcom,tsens-slopes");
> + if (num <= 0) {
> + dev_err(dev, "invalid tsens slopes\n");
> + return -EINVAL;
> + }
> +
> + tmdev = devm_kzalloc(dev, sizeof(*tmdev) +
> + num * sizeof(*s), GFP_KERNEL);
> + if (!tmdev)
> + return -ENOMEM;
> +
> + tmdev->dev = dev;
> + tmdev->num_sensors = num;
> +
> + for (i = 0, s = tmdev->sensor; i < tmdev->num_sensors; i++, s++)
> + of_property_read_u32_index(np, "qcom,tsens-slopes", i,
> + &s->slope);
> +
> + id = of_match_node(tsens_table, np);
> + if (!id)
> + return -ENODEV;
> +
> + tmdev->ops = id->data;
> + if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->calibrate ||
> + !tmdev->ops->get_temp)
> + return -EINVAL;
> +
> + ret = tmdev->ops->init(tmdev);
> + if (ret < 0) {
> + dev_err(dev, "tsens init failed\n");
> + return ret;
> + }
> +
> + 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)
> +{
> + int i;
> + struct tsens_device *tmdev = platform_get_drvdata(pdev);
> + struct thermal_zone_device *tzd;
> +
> + if (tmdev->ops->disable)
> + tmdev->ops->disable(tmdev);
> +
> + for (i = 0; i < tmdev->num_sensors; i++) {
> + tzd = tmdev->sensor[i].tzd;
> + thermal_zone_of_sensor_unregister(&pdev->dev, tzd);
> + }
> +
> + 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");
[...]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 1/9] thermal: qcom: tsens: Add a skeletal TSENS drivers
2015-09-16 13:44 ` Punit Agrawal
@ 2015-09-21 4:26 ` Rajendra Nayak
0 siblings, 0 replies; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-21 4:26 UTC (permalink / raw)
To: Punit Agrawal
Cc: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval,
sboyd, srinivas.kandagatla, nrajan, lina.iyer
[]..
>> +Example:
>> +tsens: thermal-sensor@900000 {
>> + compatible = "qcom,msm8916-tsens";
>> + qcom,tsens-slopes = <1176 1176 1154 1176 1111
>> + 1132 1132 1199 1132 1199
>> + 1132>;
>> + nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
>> + nvmem-cell-names = "caldata", "calsel";
>> + qcom,tsens-slopes = <3200 3200 3200 3200 3200>;
>> + qcom,sensor-id = <0 1 2 4 5>;
>> + #thermal-sensor-cells = <1>;
>> + };
>
> The qcom,tsens-slopes property appears twice in the above example.
sure, will fix.
>
> [...]
>> +#ifdef CONFIG_PM
>> +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);
>> +#define TSENS_PM_OPS (&tsens_pm_ops)
>> +
>> +#else /* CONFIG_PM_SLEEP */
> ^
>
>> +#define TSENS_PM_OPS NULL
>> +#endif /* CONFIG_PM_SLEEP */
> ^
>
> The comments don't match the #ifdef above. I maybe wrong but looking at
> other drivers it looks like you don't need the #else part. You should be
> able to use the tsens_pm_ops without having to set it to NULL.
yes, I should be able to avoid the #else and thanks for catching the
mismatched comments.
>
>> +
>> +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, ret;
>> + struct thermal_zone_device *tzd;
>> + u32 *hw_id, n = tmdev->num_sensors;
>> + struct device_node *np = tmdev->dev->of_node;
>> +
>> + hw_id = devm_kcalloc(tmdev->dev, n, sizeof(u32), GFP_KERNEL);
>> + if (!hw_id)
>> + return -ENOMEM;
>> +
>> + ret = of_property_read_u32_array(np, "qcom,sensor-id", hw_id, n);
>> + if (ret)
>> + for (i = 0; i < tmdev->num_sensors; i++)
>> + tmdev->sensor[i].hw_id = i;
>> + else
>> + for (i = 0; i < tmdev->num_sensors; i++)
>> + tmdev->sensor[i].hw_id = hw_id[i];
>> +
>
> You could move the check for vaild for valid sensor ids in the device
> tree (ret) inside a single for loop. In that case the loop above could
> be merged into the iteration over the sensors below.
sure, seems like a reasonable optimization to avoid a few loops.
>
>> + for (i = 0; i < tmdev->num_sensors; i++) {
>> + tmdev->sensor[i].tmdev = tmdev;
>> + tmdev->sensor[i].id = i;
>> + tzd = 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, num;
>> + struct device *dev;
>> + struct device_node *np;
>> + struct tsens_sensor *s;
>> + struct tsens_device *tmdev;
>> + const struct of_device_id *id;
>> +
>> + dev = &pdev->dev;
>> + np = dev->of_node;
>
> These assignments can be done with the declaration above.
I just have these assignments done conditionally in later patches
(5/9), so left them here.
Thanks for taking time to review.
regards,
Rajendra
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2 2/9] thermal: qcom: tsens-8916: Add support for 8916 family of SoCs
2015-09-16 6:23 [PATCH v2 0/9] qcom: Add support for TSENS driver Rajendra Nayak
2015-09-16 6:23 ` [PATCH v2 1/9] thermal: qcom: tsens: Add a skeletal TSENS drivers Rajendra Nayak
@ 2015-09-16 6:23 ` Rajendra Nayak
2015-09-16 13:46 ` Punit Agrawal
2015-09-16 6:23 ` [PATCH v2 3/9] thermal: qcom: tsens-8974: Add support for 8974 " Rajendra Nayak
` (6 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-16 6:23 UTC (permalink / raw)
To: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval
Cc: sboyd, srinivas.kandagatla, nrajan, lina.iyer, Rajendra Nayak
Add support to calibrate sensors on 8916 family and also add common
functions to read temperature from sensors (This can be reused on
other SoCs having similar TSENS device)
The calibration data is read from eeprom using the generic nvmem
framework apis.
Based on the original code by Siddartha Mohanadoss and Stephen Boyd.
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
drivers/thermal/qcom/Makefile | 2 +-
drivers/thermal/qcom/tsens-8916.c | 107 +++++++++++++++++++++++++++++
drivers/thermal/qcom/tsens-common.c | 130 ++++++++++++++++++++++++++++++++++++
drivers/thermal/qcom/tsens.c | 1 +
drivers/thermal/qcom/tsens.h | 11 +++
5 files changed, 250 insertions(+), 1 deletion(-)
create mode 100644 drivers/thermal/qcom/tsens-8916.c
create mode 100644 drivers/thermal/qcom/tsens-common.c
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 401069b..05c98e4 100644
--- 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
+qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o
diff --git a/drivers/thermal/qcom/tsens-8916.c b/drivers/thermal/qcom/tsens-8916.c
new file mode 100644
index 0000000..a69aea3
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8916.c
@@ -0,0 +1,107 @@
+/*
+ * 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 "tsens.h"
+
+/* eeprom layout data for 8916 */
+#define BASE0_MASK 0x0000007f
+#define BASE1_MASK 0xfe000000
+#define BASE0_SHIFT 0
+#define BASE1_SHIFT 25
+
+#define S0_P1_MASK 0x00000f80
+#define S1_P1_MASK 0x003e0000
+#define S2_P1_MASK 0xf8000000
+#define S3_P1_MASK 0x000003e0
+#define S4_P1_MASK 0x000f8000
+
+#define S0_P2_MASK 0x0001f000
+#define S1_P2_MASK 0x07c00000
+#define S2_P2_MASK 0x0000001f
+#define S3_P2_MASK 0x00007c00
+#define S4_P2_MASK 0x01f00000
+
+#define S0_P1_SHIFT 7
+#define S1_P1_SHIFT 17
+#define S2_P1_SHIFT 27
+#define S3_P1_SHIFT 5
+#define S4_P1_SHIFT 15
+
+#define S0_P2_SHIFT 12
+#define S1_P2_SHIFT 22
+#define S2_P2_SHIFT 0
+#define S3_P2_SHIFT 10
+#define S4_P2_SHIFT 20
+
+#define CAL_SEL_MASK 0xe0000000
+#define CAL_SEL_SHIFT 29
+
+static int calibrate_8916(struct tsens_device *tmdev)
+{
+ int base0 = 0, base1 = 0, i;
+ u32 p1[5], p2[5];
+ int mode = 0;
+ u32 *qfprom_cdata, *qfprom_csel;
+
+ qfprom_cdata = (u32 *)qfprom_read(tmdev->dev, "calib");
+ if (IS_ERR(qfprom_cdata))
+ return PTR_ERR(qfprom_cdata);
+
+ qfprom_csel = (u32 *)qfprom_read(tmdev->dev, "calib_sel");
+ if (IS_ERR(qfprom_csel))
+ return PTR_ERR(qfprom_csel);
+
+ mode = (qfprom_csel[0] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
+ dev_dbg(tmdev->dev, "calibration mode is %d\n", mode);
+
+ switch (mode) {
+ case TWO_PT_CALIB:
+ base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT;
+ p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
+ p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
+ p2[2] = (qfprom_cdata[1] & S2_P2_MASK) >> S2_P2_SHIFT;
+ p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
+ p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
+ for (i = 0; i < tmdev->num_sensors; i++)
+ p2[i] = ((base1 + p2[i]) << 3);
+ /* Fall through */
+ case ONE_PT_CALIB2:
+ base0 = (qfprom_cdata[0] & BASE0_MASK);
+ p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+ p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+ p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+ p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
+ p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
+ for (i = 0; i < tmdev->num_sensors; i++)
+ p1[i] = (((base0) + p1[i]) << 3);
+ break;
+ default:
+ for (i = 0; i < tmdev->num_sensors; i++) {
+ p1[i] = 500;
+ p2[i] = 780;
+ }
+ break;
+ }
+
+ compute_intercept_slope(tmdev, p1, p2, mode);
+
+ return 0;
+}
+
+const struct tsens_ops ops_8916 = {
+ .init = init_common,
+ .calibrate = calibrate_8916,
+ .get_temp = get_temp_common,
+};
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
new file mode 100644
index 0000000..4acf52c
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -0,0 +1,130 @@
+/*
+ * 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/nvmem-consumer.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_address.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
+
+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;
+}
+
+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]);
+
+ 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_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)
+ return -ENODEV;
+
+ return 0;
+}
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 9615845..b240fd7 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -71,6 +71,7 @@ static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume);
static const struct of_device_id tsens_table[] = {
{
.compatible = "qcom,msm8916-tsens",
+ .data = &ops_8916,
}, {
.compatible = "qcom,msm8974-tsens",
},
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index f0fc353..0923822 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -13,6 +13,10 @@
#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 {
@@ -55,4 +59,11 @@ struct tsens_device {
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 *);
+
+extern const struct tsens_ops ops_8916;
+
#endif /* __QCOM_TSENS_H__ */
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/9] thermal: qcom: tsens-8916: Add support for 8916 family of SoCs
2015-09-16 6:23 ` [PATCH v2 2/9] thermal: qcom: tsens-8916: Add support for 8916 family of SoCs Rajendra Nayak
@ 2015-09-16 13:46 ` Punit Agrawal
2015-09-21 4:28 ` Rajendra Nayak
0 siblings, 1 reply; 18+ messages in thread
From: Punit Agrawal @ 2015-09-16 13:46 UTC (permalink / raw)
To: Rajendra Nayak
Cc: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval,
sboyd, srinivas.kandagatla, nrajan, lina.iyer
Hi Rajendra,
One comment below.
Rajendra Nayak <rnayak@codeaurora.org> writes:
> Add support to calibrate sensors on 8916 family and also add common
> functions to read temperature from sensors (This can be reused on
> other SoCs having similar TSENS device)
> The calibration data is read from eeprom using the generic nvmem
> framework apis.
>
> Based on the original code by Siddartha Mohanadoss and Stephen Boyd.
>
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> ---
> drivers/thermal/qcom/Makefile | 2 +-
> drivers/thermal/qcom/tsens-8916.c | 107 +++++++++++++++++++++++++++++
> drivers/thermal/qcom/tsens-common.c | 130 ++++++++++++++++++++++++++++++++++++
> drivers/thermal/qcom/tsens.c | 1 +
> drivers/thermal/qcom/tsens.h | 11 +++
> 5 files changed, 250 insertions(+), 1 deletion(-)
> create mode 100644 drivers/thermal/qcom/tsens-8916.c
> create mode 100644 drivers/thermal/qcom/tsens-common.c
>
[...]
> diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
> new file mode 100644
> index 0000000..4acf52c
> --- /dev/null
> +++ b/drivers/thermal/qcom/tsens-common.c
> @@ -0,0 +1,130 @@
> +/*
> + * 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/nvmem-consumer.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of_address.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
> +
> +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;
> +}
> +
> +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]);
> +
> + 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;
> +}
The way this function is coded the temperature will only ever change by
1C (i.e., 1000mC). Is there a chance that you're losing precision in the
code_to_degc conversion that could be preserved perhaps?
This is useful in scenarios where you use the power allocator governor
and the greater precision allows better power budget estimation.
> +
> +static const struct regmap_config tsens_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> +};
> +
> +int 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)
> + return -ENODEV;
> +
> + return 0;
> +}
[...]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/9] thermal: qcom: tsens-8916: Add support for 8916 family of SoCs
2015-09-16 13:46 ` Punit Agrawal
@ 2015-09-21 4:28 ` Rajendra Nayak
2015-10-08 5:05 ` Rajendra Nayak
0 siblings, 1 reply; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-21 4:28 UTC (permalink / raw)
To: Punit Agrawal
Cc: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval,
sboyd, srinivas.kandagatla, nrajan, lina.iyer
[]..
>> +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;
>> +}
>
> The way this function is coded the temperature will only ever change by
> 1C (i.e., 1000mC). Is there a chance that you're losing precision in the
> code_to_degc conversion that could be preserved perhaps?
>
> This is useful in scenarios where you use the power allocator governor
> and the greater precision allows better power budget estimation.
I'll take a look to see if we can get better precision. Thanks.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/9] thermal: qcom: tsens-8916: Add support for 8916 family of SoCs
2015-09-21 4:28 ` Rajendra Nayak
@ 2015-10-08 5:05 ` Rajendra Nayak
2015-10-08 14:32 ` Punit Agrawal
0 siblings, 1 reply; 18+ messages in thread
From: Rajendra Nayak @ 2015-10-08 5:05 UTC (permalink / raw)
To: Punit Agrawal
Cc: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval,
sboyd, srinivas.kandagatla, nrajan, lina.iyer
On 09/21/2015 09:58 AM, Rajendra Nayak wrote:
> []..
>
>>> +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;
>>> +}
>>
>> The way this function is coded the temperature will only ever change by
>> 1C (i.e., 1000mC). Is there a chance that you're losing precision in the
>> code_to_degc conversion that could be preserved perhaps?
>>
>> This is useful in scenarios where you use the power allocator governor
>> and the greater precision allows better power budget estimation.
>
> I'll take a look to see if we can get better precision. Thanks.
I checked, and it does not look like these devices can support better precision
than degC.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 2/9] thermal: qcom: tsens-8916: Add support for 8916 family of SoCs
2015-10-08 5:05 ` Rajendra Nayak
@ 2015-10-08 14:32 ` Punit Agrawal
0 siblings, 0 replies; 18+ messages in thread
From: Punit Agrawal @ 2015-10-08 14:32 UTC (permalink / raw)
To: Rajendra Nayak
Cc: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval,
sboyd, srinivas.kandagatla, nrajan, lina.iyer
Rajendra Nayak <rnayak@codeaurora.org> writes:
> On 09/21/2015 09:58 AM, Rajendra Nayak wrote:
>> []..
>>
>>>> +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;
>>>> +}
>>>
>>> The way this function is coded the temperature will only ever change by
>>> 1C (i.e., 1000mC). Is there a chance that you're losing precision in the
>>> code_to_degc conversion that could be preserved perhaps?
>>>
>>> This is useful in scenarios where you use the power allocator governor
>>> and the greater precision allows better power budget estimation.
>>
>> I'll take a look to see if we can get better precision. Thanks.
>
> I checked, and it does not look like these devices can support better precision
> than degC.
Ah well. Thanks for checking!
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2 3/9] thermal: qcom: tsens-8974: Add support for 8974 family of SoCs
2015-09-16 6:23 [PATCH v2 0/9] qcom: Add support for TSENS driver Rajendra Nayak
2015-09-16 6:23 ` [PATCH v2 1/9] thermal: qcom: tsens: Add a skeletal TSENS drivers Rajendra Nayak
2015-09-16 6:23 ` [PATCH v2 2/9] thermal: qcom: tsens-8916: Add support for 8916 family of SoCs Rajendra Nayak
@ 2015-09-16 6:23 ` Rajendra Nayak
2015-09-16 6:23 ` [PATCH v2 4/9] clk: qcom: create virtual child device for TSENS Rajendra Nayak
` (5 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-16 6:23 UTC (permalink / raw)
To: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval
Cc: sboyd, srinivas.kandagatla, nrajan, lina.iyer, Rajendra Nayak
Add .calibrate support for 8974 family as part of tsens_ops.
Based on the original code by Siddartha Mohanadoss and Stephen Boyd.
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
drivers/thermal/qcom/Makefile | 2 +-
drivers/thermal/qcom/tsens-8974.c | 239 ++++++++++++++++++++++++++++++++++++++
drivers/thermal/qcom/tsens.c | 1 +
drivers/thermal/qcom/tsens.h | 2 +-
4 files changed, 242 insertions(+), 2 deletions(-)
create mode 100644 drivers/thermal/qcom/tsens-8974.c
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 05c98e4..a471100 100644
--- 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
+qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o
diff --git a/drivers/thermal/qcom/tsens-8974.c b/drivers/thermal/qcom/tsens-8974.c
new file mode 100644
index 0000000..19d9258
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8974.c
@@ -0,0 +1,239 @@
+/*
+ * 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 "tsens.h"
+
+/* eeprom layout data for 8974 */
+#define BASE1_MASK 0xff
+#define S0_P1_MASK 0x3f00
+#define S1_P1_MASK 0xfc000
+#define S2_P1_MASK 0x3f00000
+#define S3_P1_MASK 0xfc000000
+#define S4_P1_MASK 0x3f
+#define S5_P1_MASK 0xfc0
+#define S6_P1_MASK 0x3f000
+#define S7_P1_MASK 0xfc0000
+#define S8_P1_MASK 0x3f000000
+#define S8_P1_MASK_BKP 0x3f
+#define S9_P1_MASK 0x3f
+#define S9_P1_MASK_BKP 0xfc0
+#define S10_P1_MASK 0xfc0
+#define S10_P1_MASK_BKP 0x3f000
+#define CAL_SEL_0_1 0xc0000000
+#define CAL_SEL_2 0x40000000
+#define CAL_SEL_SHIFT 30
+#define CAL_SEL_SHIFT_2 28
+
+#define S0_P1_SHIFT 8
+#define S1_P1_SHIFT 14
+#define S2_P1_SHIFT 20
+#define S3_P1_SHIFT 26
+#define S5_P1_SHIFT 6
+#define S6_P1_SHIFT 12
+#define S7_P1_SHIFT 18
+#define S8_P1_SHIFT 24
+#define S9_P1_BKP_SHIFT 6
+#define S10_P1_SHIFT 6
+#define S10_P1_BKP_SHIFT 12
+
+#define BASE2_SHIFT 12
+#define BASE2_BKP_SHIFT 18
+#define S0_P2_SHIFT 20
+#define S0_P2_BKP_SHIFT 26
+#define S1_P2_SHIFT 26
+#define S2_P2_BKP_SHIFT 6
+#define S3_P2_SHIFT 6
+#define S3_P2_BKP_SHIFT 12
+#define S4_P2_SHIFT 12
+#define S4_P2_BKP_SHIFT 18
+#define S5_P2_SHIFT 18
+#define S5_P2_BKP_SHIFT 24
+#define S6_P2_SHIFT 24
+#define S7_P2_BKP_SHIFT 6
+#define S8_P2_SHIFT 6
+#define S8_P2_BKP_SHIFT 12
+#define S9_P2_SHIFT 12
+#define S9_P2_BKP_SHIFT 18
+#define S10_P2_SHIFT 18
+#define S10_P2_BKP_SHIFT 24
+
+#define BASE2_MASK 0xff000
+#define BASE2_BKP_MASK 0xfc0000
+#define S0_P2_MASK 0x3f00000
+#define S0_P2_BKP_MASK 0xfc000000
+#define S1_P2_MASK 0xfc000000
+#define S1_P2_BKP_MASK 0x3f
+#define S2_P2_MASK 0x3f
+#define S2_P2_BKP_MASK 0xfc0
+#define S3_P2_MASK 0xfc0
+#define S3_P2_BKP_MASK 0x3f000
+#define S4_P2_MASK 0x3f000
+#define S4_P2_BKP_MASK 0xfc0000
+#define S5_P2_MASK 0xfc0000
+#define S5_P2_BKP_MASK 0x3f000000
+#define S6_P2_MASK 0x3f000000
+#define S6_P2_BKP_MASK 0x3f
+#define S7_P2_MASK 0x3f
+#define S7_P2_BKP_MASK 0xfc0
+#define S8_P2_MASK 0xfc0
+#define S8_P2_BKP_MASK 0x3f000
+#define S9_P2_MASK 0x3f000
+#define S9_P2_BKP_MASK 0xfc0000
+#define S10_P2_MASK 0xfc0000
+#define S10_P2_BKP_MASK 0x3f000000
+
+#define BKP_SEL 0x3
+#define BKP_REDUN_SEL 0xe0000000
+#define BKP_REDUN_SHIFT 29
+
+#define BIT_APPEND 0x3
+
+static int calibrate_8974(struct tsens_device *tmdev)
+{
+ int base1 = 0, base2 = 0, i;
+ u32 p1[11], p2[11];
+ int mode = 0;
+ u32 *calib, *bkp;
+ u32 calib_redun_sel;
+
+ calib = (u32 *)qfprom_read(tmdev->dev, "calib");
+ if (IS_ERR(calib))
+ return PTR_ERR(calib);
+
+ bkp = (u32 *)qfprom_read(tmdev->dev, "calib_backup");
+ if (IS_ERR(bkp))
+ return PTR_ERR(bkp);
+
+ calib_redun_sel = bkp[1] & BKP_REDUN_SEL;
+ calib_redun_sel >>= BKP_REDUN_SHIFT;
+
+ if (calib_redun_sel == BKP_SEL) {
+ mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
+ mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
+
+ switch (mode) {
+ case TWO_PT_CALIB:
+ base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT;
+ p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT;
+ p2[1] = (bkp[3] & S1_P2_BKP_MASK);
+ p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT;
+ p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT;
+ p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT;
+ p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT;
+ p2[6] = (calib[5] & S6_P2_BKP_MASK);
+ p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT;
+ p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT;
+ p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT;
+ p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT;
+ /* Fall through */
+ case ONE_PT_CALIB:
+ case ONE_PT_CALIB2:
+ base1 = bkp[0] & BASE1_MASK;
+ p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+ p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+ p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+ p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT;
+ p1[4] = (bkp[1] & S4_P1_MASK);
+ p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT;
+ p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT;
+ p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT;
+ p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT;
+ p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT;
+ p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT;
+ break;
+ }
+ } else {
+ mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
+ mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
+
+ switch (mode) {
+ case TWO_PT_CALIB:
+ base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT;
+ p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT;
+ p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT;
+ p2[2] = (calib[3] & S2_P2_MASK);
+ p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT;
+ p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT;
+ p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT;
+ p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT;
+ p2[7] = (calib[4] & S7_P2_MASK);
+ p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT;
+ p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT;
+ p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT;
+ /* Fall through */
+ case ONE_PT_CALIB:
+ case ONE_PT_CALIB2:
+ base1 = calib[0] & BASE1_MASK;
+ p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+ p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+ p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+ p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT;
+ p1[4] = (calib[1] & S4_P1_MASK);
+ p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT;
+ p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT;
+ p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT;
+ p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT;
+ p1[9] = (calib[2] & S9_P1_MASK);
+ p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT;
+ break;
+ }
+ }
+
+ switch (mode) {
+ case ONE_PT_CALIB:
+ for (i = 0; i < tmdev->num_sensors; i++)
+ p1[i] += (base1 << 2) | BIT_APPEND;
+ break;
+ case TWO_PT_CALIB:
+ for (i = 0; i < tmdev->num_sensors; i++) {
+ p2[i] += base2;
+ p2[i] <<= 2;
+ p2[i] |= BIT_APPEND;
+ }
+ /* Fall through */
+ case ONE_PT_CALIB2:
+ for (i = 0; i < tmdev->num_sensors; i++) {
+ p1[i] += base1;
+ p1[i] <<= 2;
+ p1[i] |= BIT_APPEND;
+ }
+ break;
+ default:
+ for (i = 0; i < tmdev->num_sensors; i++)
+ p2[i] = 780;
+ p1[0] = 502;
+ p1[1] = 509;
+ p1[2] = 503;
+ p1[3] = 509;
+ p1[4] = 505;
+ p1[5] = 509;
+ p1[6] = 507;
+ p1[7] = 510;
+ p1[8] = 508;
+ p1[9] = 509;
+ p1[10] = 508;
+ break;
+ }
+
+ compute_intercept_slope(tmdev, p1, p2, mode);
+
+ return 0;
+}
+
+const struct tsens_ops ops_8974 = {
+ .init = init_common,
+ .calibrate = calibrate_8974,
+ .get_temp = get_temp_common,
+};
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index b240fd7..c8f8969 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -74,6 +74,7 @@ static const struct of_device_id tsens_table[] = {
.data = &ops_8916,
}, {
.compatible = "qcom,msm8974-tsens",
+ .data = &ops_8974,
},
{}
};
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 0923822..00183db 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -64,6 +64,6 @@ 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 *);
-extern const struct tsens_ops ops_8916;
+extern const struct tsens_ops ops_8916, ops_8974;
#endif /* __QCOM_TSENS_H__ */
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 4/9] clk: qcom: create virtual child device for TSENS
2015-09-16 6:23 [PATCH v2 0/9] qcom: Add support for TSENS driver Rajendra Nayak
` (2 preceding siblings ...)
2015-09-16 6:23 ` [PATCH v2 3/9] thermal: qcom: tsens-8974: Add support for 8974 " Rajendra Nayak
@ 2015-09-16 6:23 ` Rajendra Nayak
2015-09-16 22:39 ` Stephen Boyd
2015-09-16 6:23 ` [PATCH v2 5/9] thermal: qcom: tsens-8960: Add support for 8960 family of SoCs Rajendra Nayak
` (4 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-16 6:23 UTC (permalink / raw)
To: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval
Cc: sboyd, srinivas.kandagatla, nrajan, lina.iyer, Rajendra Nayak
8960 family of devices have TSENS as part of GCC in hardware.
Hence DT would represent a GCC node with GCC properties as well
as TSENS. Create a virtual platform child device here for TSENS
so the driver can probe it and use the parent (GCC) to extract DT
properties.
Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
drivers/clk/qcom/gcc-msm8960.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c
index aa294b1..51db3a5 100644
--- a/drivers/clk/qcom/gcc-msm8960.c
+++ b/drivers/clk/qcom/gcc-msm8960.c
@@ -3506,6 +3506,8 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
struct clk *clk;
struct device *dev = &pdev->dev;
const struct of_device_id *match;
+ struct platform_device *tsens;
+ int ret;
match = of_match_device(gcc_msm8960_match_table, &pdev->dev);
if (!match)
@@ -3520,7 +3522,26 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
if (IS_ERR(clk))
return PTR_ERR(clk);
- return qcom_cc_probe(pdev, match->data);
+ ret = qcom_cc_probe(pdev, match->data);
+ if (ret)
+ return ret;
+
+ tsens = platform_device_alloc("qcom-tsens", -1);
+ if (!tsens) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ tsens->dev.parent = &pdev->dev;
+ ret = platform_device_add(tsens);
+ if (ret)
+ goto err_add;
+ return 0;
+err_add:
+ platform_device_put(tsens);
+err_alloc:
+ qcom_cc_remove(pdev);
+ return ret;
}
static int gcc_msm8960_remove(struct platform_device *pdev)
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2 4/9] clk: qcom: create virtual child device for TSENS
2015-09-16 6:23 ` [PATCH v2 4/9] clk: qcom: create virtual child device for TSENS Rajendra Nayak
@ 2015-09-16 22:39 ` Stephen Boyd
2015-09-21 4:28 ` Rajendra Nayak
0 siblings, 1 reply; 18+ messages in thread
From: Stephen Boyd @ 2015-09-16 22:39 UTC (permalink / raw)
To: Rajendra Nayak
Cc: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval,
srinivas.kandagatla, nrajan, lina.iyer
On 09/16, Rajendra Nayak wrote:
> @@ -3520,7 +3522,26 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
> if (IS_ERR(clk))
> return PTR_ERR(clk);
>
> - return qcom_cc_probe(pdev, match->data);
> + ret = qcom_cc_probe(pdev, match->data);
> + if (ret)
> + return ret;
> +
> + tsens = platform_device_alloc("qcom-tsens", -1);
> + if (!tsens) {
> + ret = -ENOMEM;
> + goto err_alloc;
> + }
> +
> + tsens->dev.parent = &pdev->dev;
> + ret = platform_device_add(tsens);
> + if (ret)
> + goto err_add;
platform_device_register_data() instead of all these lines? We
should probably remove the device when this driver is removed
too.
> + return 0;
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2 4/9] clk: qcom: create virtual child device for TSENS
2015-09-16 22:39 ` Stephen Boyd
@ 2015-09-21 4:28 ` Rajendra Nayak
0 siblings, 0 replies; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-21 4:28 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval,
srinivas.kandagatla, nrajan, lina.iyer
On 09/17/2015 04:09 AM, Stephen Boyd wrote:
> On 09/16, Rajendra Nayak wrote:
>> @@ -3520,7 +3522,26 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
>> if (IS_ERR(clk))
>> return PTR_ERR(clk);
>>
>> - return qcom_cc_probe(pdev, match->data);
>> + ret = qcom_cc_probe(pdev, match->data);
>> + if (ret)
>> + return ret;
>> +
>> + tsens = platform_device_alloc("qcom-tsens", -1);
>> + if (!tsens) {
>> + ret = -ENOMEM;
>> + goto err_alloc;
>> + }
>> +
>> + tsens->dev.parent = &pdev->dev;
>> + ret = platform_device_add(tsens);
>> + if (ret)
>> + goto err_add;
>
> platform_device_register_data() instead of all these lines? We
> should probably remove the device when this driver is removed
> too.
Thanks Stephen, I'll fix it.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2 5/9] thermal: qcom: tsens-8960: Add support for 8960 family of SoCs
2015-09-16 6:23 [PATCH v2 0/9] qcom: Add support for TSENS driver Rajendra Nayak
` (3 preceding siblings ...)
2015-09-16 6:23 ` [PATCH v2 4/9] clk: qcom: create virtual child device for TSENS Rajendra Nayak
@ 2015-09-16 6:23 ` Rajendra Nayak
2015-09-16 6:23 ` [PATCH v2 6/9] arm: dts: msm8974: Add thermal zones, tsens and qfprom nodes Rajendra Nayak
` (3 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-16 6:23 UTC (permalink / raw)
To: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval
Cc: sboyd, srinivas.kandagatla, nrajan, lina.iyer, Rajendra Nayak
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>
---
drivers/thermal/qcom/Makefile | 2 +-
drivers/thermal/qcom/tsens-8960.c | 291 ++++++++++++++++++++++++++++++++++++++
drivers/thermal/qcom/tsens.c | 13 +-
drivers/thermal/qcom/tsens.h | 2 +-
4 files changed, 302 insertions(+), 6 deletions(-)
create mode 100644 drivers/thermal/qcom/tsens-8960.c
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index a471100..f3cefd1 100644
--- 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
diff --git a/drivers/thermal/qcom/tsens-8960.c b/drivers/thermal/qcom/tsens-8960.c
new file mode 100644
index 0000000..00f45e7
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8960.c
@@ -0,0 +1,291 @@
+/*
+ * 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 "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)
+
+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;
+
+ tmdev->trdy = false;
+
+ return 0;
+}
+
+static int resume_8960(struct tsens_device *tmdev)
+{
+ int ret;
+ unsigned long reg_cntl;
+ 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;
+
+ reg_cntl = tmdev->ctx.control;
+ reg_cntl >>= SENSOR0_SHIFT;
+
+ 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;
+
+ tmdev->trdy = false;
+ 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 = CAL_MDEGC - s->slope * 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)
+{
+ return adc_code * s->slope + s->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];
+
+ if (!tmdev->trdy) {
+ ret = regmap_read(tmdev->map, INT_STATUS_ADDR, &trdy);
+ if (ret)
+ return ret;
+ while (!(trdy & TRDY_MASK)) {
+ usleep_range(1000, 1100);
+ regmap_read(tmdev->map, INT_STATUS_ADDR, &trdy);
+ }
+ tmdev->trdy = true;
+ }
+
+ ret = regmap_read(tmdev->map, s->status, &code);
+ if (ret)
+ return ret;
+
+ *temp = code_to_mdegC(code, s);
+
+ dev_dbg(tmdev->dev, "Sensor%d temp is: %d", id, *temp);
+
+ return 0;
+}
+
+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,
+};
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index c8f8969..2da21f9 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -128,7 +128,11 @@ static int tsens_probe(struct platform_device *pdev)
struct tsens_device *tmdev;
const struct of_device_id *id;
- dev = &pdev->dev;
+ if (pdev->dev.of_node)
+ dev = &pdev->dev;
+ else
+ dev = pdev->dev.parent;
+
np = dev->of_node;
num = of_property_count_u32_elems(np, "qcom,tsens-slopes");
@@ -150,10 +154,11 @@ static int tsens_probe(struct platform_device *pdev)
&s->slope);
id = of_match_node(tsens_table, np);
- if (!id)
- return -ENODEV;
+ if (id)
+ tmdev->ops = id->data;
+ else
+ tmdev->ops = &ops_8960;
- tmdev->ops = id->data;
if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->calibrate ||
!tmdev->ops->get_temp)
return -EINVAL;
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 00183db..10e2e84 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -64,6 +64,6 @@ 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 *);
-extern const struct tsens_ops ops_8916, ops_8974;
+extern const struct tsens_ops ops_8960, ops_8916, ops_8974;
#endif /* __QCOM_TSENS_H__ */
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 6/9] arm: dts: msm8974: Add thermal zones, tsens and qfprom nodes
2015-09-16 6:23 [PATCH v2 0/9] qcom: Add support for TSENS driver Rajendra Nayak
` (4 preceding siblings ...)
2015-09-16 6:23 ` [PATCH v2 5/9] thermal: qcom: tsens-8960: Add support for 8960 family of SoCs Rajendra Nayak
@ 2015-09-16 6:23 ` Rajendra Nayak
2015-09-16 6:23 ` [PATCH v2 7/9] arm: dts: apq8064: " Rajendra Nayak
` (2 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-16 6:23 UTC (permalink / raw)
To: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval
Cc: sboyd, srinivas.kandagatla, nrajan, lina.iyer, Rajendra Nayak
Add thermal zones, tsens and qfprom nodes
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
arch/arm/boot/dts/qcom-msm8974.dtsi | 105 ++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index ab8e572..cc88412 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -86,6 +86,88 @@
};
};
+ thermal-zones {
+ cpu-thermal0 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 5>;
+
+ trips {
+ cpu_alert0: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit0: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu-thermal1 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 6>;
+
+ trips {
+ cpu_alert1: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit1: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu-thermal2 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 7>;
+
+ trips {
+ cpu_alert2: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit2: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu-thermal3 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 8>;
+
+ trips {
+ cpu_alert3: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit3: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
+
cpu-pmu {
compatible = "qcom,krait-pmu";
interrupts = <1 7 0xf04>;
@@ -114,6 +196,29 @@
<0xf9002000 0x1000>;
};
+ qfprom: qfprom@fc4bc000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qfprom";
+ reg = <0xfc4bc000 0x1000>;
+ tsens_calib: calib@d0 {
+ reg = <0xd0 0x18>;
+ };
+ tsens_backup: backup@440 {
+ reg = <0x440 0x10>;
+ };
+ };
+
+ tsens: thermal-sensor@fc4a8000 {
+ compatible = "qcom,msm8974-tsens";
+ reg = <0xfc4a8000 0x2000>;
+ nvmem-cells = <&tsens_calib>, <&tsens_backup>;
+ nvmem-cell-names = "calib", "calib_backup";
+ qcom,tsens-slopes = <3200 3200 3200 3200 3200 3200
+ 3200 3200 3200 3200 3200>;
+ #thermal-sensor-cells = <1>;
+ };
+
timer@f9020000 {
#address-cells = <1>;
#size-cells = <1>;
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 7/9] arm: dts: apq8064: Add thermal zones, tsens and qfprom nodes
2015-09-16 6:23 [PATCH v2 0/9] qcom: Add support for TSENS driver Rajendra Nayak
` (5 preceding siblings ...)
2015-09-16 6:23 ` [PATCH v2 6/9] arm: dts: msm8974: Add thermal zones, tsens and qfprom nodes Rajendra Nayak
@ 2015-09-16 6:23 ` Rajendra Nayak
2015-09-16 6:23 ` [PATCH v2 8/9] arm: dts: apq8084: " Rajendra Nayak
2015-09-16 6:23 ` [PATCH v2 9/9] arm64: dts: msm8916: " Rajendra Nayak
8 siblings, 0 replies; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-16 6:23 UTC (permalink / raw)
To: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval
Cc: sboyd, srinivas.kandagatla, nrajan, lina.iyer, Rajendra Nayak
TSENS is part of GCC, hence add TSENS properties as part of GCC node.
Also add thermal zones and qfprom nodes.
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
arch/arm/boot/dts/qcom-apq8064.dtsi | 101 ++++++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index d2e94d6..6a0866b 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -75,6 +75,88 @@
};
};
+ thermal-zones {
+ cpu-thermal0 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&gcc 7>;
+
+ trips {
+ cpu_alert0: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit0: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu-thermal1 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&gcc 8>;
+
+ trips {
+ cpu_alert1: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit1: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu-thermal2 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&gcc 9>;
+
+ trips {
+ cpu_alert2: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit2: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu-thermal3 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&gcc 10>;
+
+ trips {
+ cpu_alert3: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit3: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
+
cpu-pmu {
compatible = "qcom,krait-pmu";
interrupts = <1 10 0x304>;
@@ -364,11 +446,30 @@
};
};
+ qfprom: qfprom@00700000 {
+ compatible = "qcom,qfprom";
+ reg = <0x00700000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ tsens_calib: calib {
+ reg = <0x404 0x10>;
+ };
+ tsens_backup: backup_calib {
+ reg = <0x414 0x10>;
+ };
+ };
+
gcc: clock-controller@900000 {
compatible = "qcom,gcc-apq8064";
reg = <0x00900000 0x4000>;
+ nvmem-cells = <&tsens_calib>, <&tsens_backup>;
+ nvmem-cell-names = "calib", "calib_backup";
+ qcom,tsens-slopes = <1176 1176 1154 1176 1111
+ 1132 1132 1199 1132 1199 1132>;
#clock-cells = <1>;
#reset-cells = <1>;
+ #thermal-sensor-cells = <1>;
};
lcc: clock-controller@28000000 {
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 8/9] arm: dts: apq8084: Add thermal zones, tsens and qfprom nodes
2015-09-16 6:23 [PATCH v2 0/9] qcom: Add support for TSENS driver Rajendra Nayak
` (6 preceding siblings ...)
2015-09-16 6:23 ` [PATCH v2 7/9] arm: dts: apq8064: " Rajendra Nayak
@ 2015-09-16 6:23 ` Rajendra Nayak
2015-09-16 6:23 ` [PATCH v2 9/9] arm64: dts: msm8916: " Rajendra Nayak
8 siblings, 0 replies; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-16 6:23 UTC (permalink / raw)
To: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval
Cc: sboyd, srinivas.kandagatla, nrajan, lina.iyer, Rajendra Nayak
Add thermal zones, tsens and qfprom nodes
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
arch/arm/boot/dts/qcom-apq8084.dtsi | 105 ++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
diff --git a/arch/arm/boot/dts/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom-apq8084.dtsi
index 0554fbd..80570a1 100644
--- a/arch/arm/boot/dts/qcom-apq8084.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8084.dtsi
@@ -75,6 +75,88 @@
};
};
+ thermal-zones {
+ cpu-thermal0 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 5>;
+
+ trips {
+ cpu_alert0: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit0: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu-thermal1 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 6>;
+
+ trips {
+ cpu_alert1: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit1: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu-thermal2 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 7>;
+
+ trips {
+ cpu_alert2: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit2: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu-thermal3 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 8>;
+
+ trips {
+ cpu_alert3: trip@0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit3: trip@1 {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
+
cpu-pmu {
compatible = "qcom,krait-pmu";
interrupts = <1 7 0xf04>;
@@ -103,6 +185,29 @@
<0xf9002000 0x1000>;
};
+ qfprom: qfprom@fc4bc000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qfprom";
+ reg = <0xfc4bc000 0x1000>;
+ tsens_calib: calib@d0 {
+ reg = <0xd0 0x18>;
+ };
+ tsens_backup: backup@440 {
+ reg = <0x440 0x10>;
+ };
+ };
+
+ tsens: thermal-sensor@fc4a8000 {
+ compatible = "qcom,msm8974-tsens";
+ reg = <0xfc4a8000 0x2000>;
+ nvmem-cells = <&tsens_calib>, <&tsens_backup>;
+ nvmem-cell-names = "calib", "calib_backup";
+ qcom,tsens-slopes = <3200 3200 3200 3200 3200 3200
+ 3200 3200 3200 3200 3200>;
+ #thermal-sensor-cells = <1>;
+ };
+
timer@f9020000 {
#address-cells = <1>;
#size-cells = <1>;
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v2 9/9] arm64: dts: msm8916: Add thermal zones, tsens and qfprom nodes
2015-09-16 6:23 [PATCH v2 0/9] qcom: Add support for TSENS driver Rajendra Nayak
` (7 preceding siblings ...)
2015-09-16 6:23 ` [PATCH v2 8/9] arm: dts: apq8084: " Rajendra Nayak
@ 2015-09-16 6:23 ` Rajendra Nayak
8 siblings, 0 replies; 18+ messages in thread
From: Rajendra Nayak @ 2015-09-16 6:23 UTC (permalink / raw)
To: linux-arm-msm, linux-arm-kernel, linux-pm, rui.zhang, edubezval
Cc: sboyd, srinivas.kandagatla, nrajan, lina.iyer, Rajendra Nayak
Add thermal zones, tsens and qfprom nodes
Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
arch/arm64/boot/dts/qcom/msm8916.dtsi | 66 +++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 3e7083c..63b5262 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -68,6 +68,49 @@
};
};
+ thermal-zones {
+ cpu-thermal0 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 4>;
+
+ trips {
+ cpu_alert0: trip@0 {
+ temperature = <100000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit0: trip@1 {
+ temperature = <125000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu-thermal1 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 3>;
+
+ trips {
+ cpu_alert1: trip@0 {
+ temperature = <100000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit1: trip@1 {
+ temperature = <125000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ };
+
timer {
compatible = "arm,armv8-timer";
interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -392,6 +435,29 @@
interrupt-controller;
#interrupt-cells = <4>;
};
+
+ qfprom: qfprom@5c000 {
+ compatible = "qcom,qfprom";
+ reg = <0x5c000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ tsens_caldata: caldata@d0 {
+ reg = <0xd0 0x8>;
+ };
+ tsens_calsel: calsel@ec {
+ reg = <0xec 0x4>;
+ };
+ };
+
+ tsens: thermal-sensor@4a8000 {
+ compatible = "qcom,msm8916-tsens";
+ reg = <0x4a8000 0x2000>;
+ nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
+ nvmem-cell-names = "calib", "calib_sel";
+ qcom,tsens-slopes = <3200 3200 3200 3200 3200>;
+ qcom,sensor-id = <0 1 2 4 5>;
+ #thermal-sensor-cells = <1>;
+ };
};
};
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 18+ messages in thread