The series add the devm_ version of thermal_zone_of_sensor_register/
unregister, interface details, and use this in new thermal driver
for max77620.
The header file for max77620 is part of MFD patch
https://lkml.org/lkml/2016/2/11/186
Changes from V1:
- Run checkpatch with --strict and fix all warnings.
- Added details of interfaces in spifs-api.txt
- Added DT binding doc.
Laxman Dewangan (6):
thermal: doc: Add details of
thermal_zone_of_sensor_{register,unregister}
thermal: of-thermal: Add devm version of
thermal_zone_of_sensor_register
thermal: Add devm_thermal_zone_of_sensor_register() in managed devices
list
thermal: doc: Add details of
devm_thermal_zone_of_sensor_{register,unregister}
thermal: max77620: Add thermal driver for reporting junction temp
thermal: Add DT binding doc for thermal of PMIC max77620
.../bindings/thermal/thermal-max77620.txt | 43 ++++++
Documentation/driver-model/devres.txt | 4 +
Documentation/thermal/sysfs-api.txt | 68 ++++++++++
drivers/thermal/Kconfig | 10 ++
drivers/thermal/Makefile | 1 +
drivers/thermal/of-thermal.c | 81 +++++++++++
drivers/thermal/thermal-max77620.c | 151 +++++++++++++++++++++
include/linux/thermal.h | 18 +++
8 files changed, 376 insertions(+)
create mode 100644 Documentation/devicetree/bindings/thermal/thermal-max77620.txt
create mode 100644 drivers/thermal/thermal-max77620.c
--
2.1.4
Add details of the interface thermal_zone_of_sensor_register() and
thermal_zone_of_sensor_unregister() in the thermal/sysfs-api.txt.
The details describes the functionality and parameter which
are passed to these interfaces.
Signed-off-by: Laxman Dewangan <[email protected]>
---
Changes from V1:
- This is new in series per review comment from V1.
Documentation/thermal/sysfs-api.txt | 45 +++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index 8c745c8..18a3a5e 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -72,6 +72,51 @@ temperature) and throttle appropriate devices.
It deletes the corresponding entry form /sys/class/thermal folder and
unbind all the thermal cooling devices it uses.
+1.1.3 struct thermal_zone_device *thermal_zone_of_sensor_register(
+ struct device *dev, int sensor_id, void *data,
+ const struct thermal_zone_of_device_ops *ops)
+
+ This interface adds a new sensor to a DT thermal zone.
+ This function will search the list of thermal zones described in
+ device tree and look for the zone that refer to the sensor device
+ pointed by dev->of_node as temperature providers. For the zone
+ pointing to the sensor node, the sensor will be added to the DT
+ thermal zone device.
+
+ The parameters for this interface are:
+ dev: Device node of sensor containing valid node pointer in
+ dev->of_node.
+ sensor_id: a sensor identifier, in case the sensor IP has more
+ than one sensors
+ data: a private pointer (owned by the caller) that will be
+ passed back, when a temperature reading is needed.
+ ops: struct thermal_zone_of_device_ops *.
+
+ get_temp: a pointer to a function that reads the
+ sensor temperature. This is mandatory
+ callback provided by sensor driver.
+ get_trend: a pointer to a function that reads the
+ sensor temperature trend.
+ set_emul_temp: a pointer to a function that sets
+ sensor emulated temperature.
+ The thermal zone temperature is provided by the get_temp() function
+ pointer of thermal_zone_of_device_ops. When called, it will
+ have the private pointer @data back.
+
+ It returns error pointer if fails otherwise valid thermal zone device
+ handle. Caller should check the return handle with IS_ERR() for finding
+ whether success or not.
+
+1.1.4 void thermal_zone_of_sensor_unregister(struct device *dev,
+ struct thermal_zone_device *tzd)
+
+ This interface unregisters a sensor from a DT thermal zone which was
+ successfully added by interface thermal_zone_of_sensor_register().
+ This function removes the sensor callbacks and private data from the
+ thermal zone device registered with thermal_zone_of_sensor_register()
+ interface. It will also silent the zone by remove the .get_temp() and
+ get_trend() thermal zone device callbacks.
+
1.2 thermal cooling device interface
1.2.1 struct thermal_cooling_device *thermal_cooling_device_register(char *name,
void *devdata, struct thermal_cooling_device_ops *)
--
2.1.4
The interface thermal_zone_of_sensor_register() and
thermal_zone_of_sensor_unregister() gained their devm_
wrappers. Add these APIs in the list of managed devices.
Signed-off-by: Laxman Dewangan <[email protected]>
---
Changes from V1:
- No change.
Documentation/driver-model/devres.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 5930d9a..dd7ce58 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -342,6 +342,10 @@ SLAVE DMA ENGINE
SPI
devm_spi_register_master()
+THERMAL
+ devm_thermal_zone_of_sensor_register()
+ devm_thermal_zone_of_sensor_unregister()
+
WATCHDOG
devm_watchdog_register_device()
devm_watchdog_unregister_device()
--
2.1.4
Maxim Semiconductor MAX77620 supports alarm interrupts when
its die temperature crosses 120C and 140C. These threshold
temperatures are not configurable.
Add DT binding document to details out the DT property related
to MAX77620 thermal functionality.
Signed-off-by: Laxman Dewangan <[email protected]>
---
Changes from V1:
- New in series to add DT binding doc per V1 review.
.../bindings/thermal/thermal-max77620.txt | 43 ++++++++++++++++++++++
1 file changed, 43 insertions(+)
create mode 100644 Documentation/devicetree/bindings/thermal/thermal-max77620.txt
diff --git a/Documentation/devicetree/bindings/thermal/thermal-max77620.txt b/Documentation/devicetree/bindings/thermal/thermal-max77620.txt
new file mode 100644
index 0000000..d76412f
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/thermal-max77620.txt
@@ -0,0 +1,43 @@
+Thermal driver for MAX77620 Power management IC from Maxim Semiconductor.
+
+Maxim Semiconductor MAX77620 supports alarm interrupts when its
+die temperature crosses 120C and 140C. These threshold temperatures
+are not configurable. Device does not provide the real temperature
+of die other than just indicating whether temperature is above or
+below threshold level.
+
+Required properties:
+-------------------
+#thermal-sensor-cells: Please refer <devicetree/bindings/thermal/thermal.txt>
+ for more details.
+ The value must be 0.
+
+For more details, please refer generic thermal DT binding document
+<devicetree/bindings/thermal/thermal.txt>.
+
+Please refer <devicetree/bindings/mfd/max77620.txt> for mfd DT binding
+document for the MAX77620.
+
+Example:
+--------
+#include <dt-bindings/mfd/max77620.h>
+...
+spmic: max77620@3c {
+ compatible = "maxim,max77620";
+
+ #thermal-sensor-cells = <0>;
+};
+
+thermal-zones {
+ PMIC-Die {
+ thermal-sensors = <&spmic>;
+ trips {
+ die_temp_thresh: hot-die {
+ temperature = <120000>;
+ type = "active";
+ hysteresis = <0>;
+ };
+ };
+ };
+};
+
--
2.1.4
Add details of the interface devm_thermal_zone_of_sensor_register()
and devm_thermal_zone_of_sensor_unregister() in the
<thermal/sysfs-api.txt>.
Signed-off-by: Laxman Dewangan <[email protected]>
---
Changes from V1:
- New in series.
Documentation/thermal/sysfs-api.txt | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index 18a3a5e..ed419d6 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -117,6 +117,29 @@ temperature) and throttle appropriate devices.
interface. It will also silent the zone by remove the .get_temp() and
get_trend() thermal zone device callbacks.
+1.1.5 struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
+ struct device *dev, int sensor_id,
+ void *data, const struct thermal_zone_of_device_ops *ops)
+
+ This interface is resource managed version of
+ thermal_zone_of_sensor_register().
+ All details of thermal_zone_of_sensor_register() described in
+ section 1.1.3 is applicable here.
+ The benefit of using this interface to register sensor is that it
+ is not require to explicitly call thermal_zone_of_sensor_unregister()
+ in error path or during driver unbinding as this is done by driver
+ resource manager.
+
+1.1.6 void devm_thermal_zone_of_sensor_unregister(struct device *dev,
+ struct thermal_zone_device *tzd)
+
+ This interface is resource managed version of
+ thermal_zone_of_sensor_unregister().
+ All details of thermal_zone_of_sensor_unregister() described in
+ section 1.1.4 is applicable here.
+ Normally this function will not need to be called and the resource
+ management code will ensure that the resource is freed.
+
1.2 thermal cooling device interface
1.2.1 struct thermal_cooling_device *thermal_cooling_device_register(char *name,
void *devdata, struct thermal_cooling_device_ops *)
--
2.1.4
Maxim Semiconductor Max77620 supports alarm interrupts when
its die temperature crosses 120C and 140C. These threshold
temperatures are not configurable.
Add thermal driver to register PMIC die temperature as thermal
zone sensor and capture the die temperature warning interrupts
to notifying the client.
Signed-off-by: Laxman Dewangan <[email protected]>
---
Changes from V1:
- checkpatch warning fix and simplifying the dev.of_node
initialisation.
drivers/thermal/Kconfig | 10 +++
drivers/thermal/Makefile | 1 +
drivers/thermal/thermal-max77620.c | 151 +++++++++++++++++++++++++++++++++++++
3 files changed, 162 insertions(+)
create mode 100644 drivers/thermal/thermal-max77620.c
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 5e7c97a..fc856eb 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -194,6 +194,16 @@ config IMX_THERMAL
cpufreq is used as the cooling device to throttle CPUs when the
passive trip is crossed.
+config MAX77620_THERMAL
+ tristate "Temperature sensor driver for Maxim MAX77620 PMIC"
+ depends on MFD_MAX77620
+ depends on OF
+ help
+ Support for die junction temperature warning alarm for Maxim
+ Semiconductor PMIC MAX77620 device. Device generates two alarm
+ interrupts when PMIC die temperature cross the threshold of
+ 120 degC and 140 degC.
+
config SPEAR_THERMAL
tristate "SPEAr thermal sensor driver"
depends on PLAT_SPEAR || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 8e9cbc3..c6bc2bd 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
+obj-$(CONFIG_MAX77620_THERMAL) += thermal-max77620.o
obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
diff --git a/drivers/thermal/thermal-max77620.c b/drivers/thermal/thermal-max77620.c
new file mode 100644
index 0000000..5fba00f
--- /dev/null
+++ b/drivers/thermal/thermal-max77620.c
@@ -0,0 +1,151 @@
+/*
+ * Junction temperature thermal driver for Maxim Max77620.
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Author: Laxman Dewangan <[email protected]>
+ * Mallikarjun Kasoju <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max77620.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+
+#define MAX77620_NORMAL_OPERATING_TEMP 100000
+#define MAX77620_TJALARM1_TEMP 120000
+#define MAX77620_TJALARM2_TEMP 140000
+
+struct max77620_therm_info {
+ struct device *dev;
+ struct regmap *rmap;
+ struct thermal_zone_device *tz_device;
+ int irq_tjalarm1;
+ int irq_tjalarm2;
+};
+
+static int max77620_thermal_read_temp(void *data, int *temp)
+{
+ struct max77620_therm_info *mtherm = data;
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(mtherm->rmap, MAX77620_REG_STATLBT, &val);
+ if (ret < 0) {
+ dev_err(mtherm->dev, "Failed to read STATLBT, %d\n", ret);
+ return -EINVAL;
+ }
+
+ if (val & MAX77620_IRQ_TJALRM2_MASK)
+ *temp = MAX77620_TJALARM2_TEMP;
+ else if (val & MAX77620_IRQ_TJALRM1_MASK)
+ *temp = MAX77620_TJALARM1_TEMP;
+ else
+ *temp = MAX77620_NORMAL_OPERATING_TEMP;
+ return 0;
+}
+
+static const struct thermal_zone_of_device_ops max77620_thermal_ops = {
+ .get_temp = max77620_thermal_read_temp,
+};
+
+static irqreturn_t max77620_thermal_irq(int irq, void *data)
+{
+ struct max77620_therm_info *mtherm = data;
+
+ if (irq == mtherm->irq_tjalarm1)
+ dev_warn(mtherm->dev, "Junction Temp Alarm1(120C) occurred\n");
+ else if (irq == mtherm->irq_tjalarm2)
+ dev_warn(mtherm->dev, "Junction Temp Alarm2(140C) occurred\n");
+
+ thermal_zone_device_update(mtherm->tz_device);
+
+ return IRQ_HANDLED;
+}
+
+static int max77620_thermal_probe(struct platform_device *pdev)
+{
+ struct max77620_therm_info *mtherm;
+ int ret;
+
+ pdev->dev.of_node = pdev->dev.parent->of_node;
+
+ mtherm = devm_kzalloc(&pdev->dev, sizeof(*mtherm), GFP_KERNEL);
+ if (!mtherm)
+ return -ENOMEM;
+
+ mtherm->irq_tjalarm1 = platform_get_irq(pdev, 0);
+ mtherm->irq_tjalarm2 = platform_get_irq(pdev, 1);
+ if ((mtherm->irq_tjalarm1 < 0) || (mtherm->irq_tjalarm2 < 0)) {
+ dev_err(&pdev->dev, "Alarm irq number not available\n");
+ return -EINVAL;
+ }
+
+ mtherm->dev = &pdev->dev;
+ mtherm->rmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!mtherm->rmap) {
+ dev_err(&pdev->dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+
+ mtherm->tz_device = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
+ mtherm, &max77620_thermal_ops);
+ if (IS_ERR(mtherm->tz_device)) {
+ ret = PTR_ERR(mtherm->tz_device);
+ dev_err(&pdev->dev, "Failed to register thermal zone, %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm1, NULL,
+ max77620_thermal_irq,
+ IRQF_ONESHOT | IRQF_SHARED,
+ dev_name(&pdev->dev), mtherm);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to request irq1, %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm2, NULL,
+ max77620_thermal_irq,
+ IRQF_ONESHOT | IRQF_SHARED,
+ dev_name(&pdev->dev), mtherm);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to request irq2, %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, mtherm);
+
+ return 0;
+}
+
+static struct platform_device_id max77620_thermal_devtype[] = {
+ { .name = "max77620-thermal", },
+ {},
+};
+
+static struct platform_driver max77620_thermal_driver = {
+ .driver = {
+ .name = "max77620-thermal",
+ },
+ .probe = max77620_thermal_probe,
+ .id_table = max77620_thermal_devtype,
+};
+
+module_platform_driver(max77620_thermal_driver);
+
+MODULE_DESCRIPTION("Max77620 Junction temperature Thermal driver");
+MODULE_ALIAS("platform:max77620-thermal");
+MODULE_AUTHOR("Laxman Dewangan <[email protected]>");
+MODULE_AUTHOR("Mallikarjun Kasoju <[email protected]>");
+MODULE_LICENSE("GPL v2");
--
2.1.4
Add resource managed version of thermal_zone_of_sensor_register() and
thermal_zone_of_sensor_unregister().
This helps in reducing the code size in error path, remove of
driver remove callbacks and making proper sequence for deallocations.
Signed-off-by: Laxman Dewangan <[email protected]>
---
Changes from V1:
- Run checkpatch --strict and fix the issue.
drivers/thermal/of-thermal.c | 81 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/thermal.h | 18 ++++++++++
2 files changed, 99 insertions(+)
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index 9043f8f..49ac23d 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -555,6 +555,87 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
}
EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister);
+static void devm_thermal_zone_of_sensor_release(struct device *dev, void *res)
+{
+ thermal_zone_of_sensor_unregister(dev,
+ *(struct thermal_zone_device **)res);
+}
+
+static int devm_thermal_zone_of_sensor_match(struct device *dev, void *res,
+ void *data)
+{
+ struct thermal_zone_device **r = res;
+
+ if (WARN_ON(!r || !*r))
+ return 0;
+
+ return *r == data;
+}
+
+/**
+ * devm_thermal_zone_of_sensor_register - Resource managed version of
+ * thermal_zone_of_sensor_register()
+ * @dev: a valid struct device pointer of a sensor device. Must contain
+ * a valid .of_node, for the sensor node.
+ * @sensor_id: a sensor identifier, in case the sensor IP has more
+ * than one sensors
+ * @data: a private pointer (owned by the caller) that will be passed
+ * back, when a temperature reading is needed.
+ * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
+ *
+ * Refer thermal_zone_of_sensor_register() for more details.
+ *
+ * Return: On success returns a valid struct thermal_zone_device,
+ * otherwise, it returns a corresponding ERR_PTR(). Caller must
+ * check the return value with help of IS_ERR() helper.
+ * Registered hermal_zone_device device will automatically be
+ * released when device is unbounded.
+ */
+struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
+ struct device *dev, int sensor_id,
+ void *data, const struct thermal_zone_of_device_ops *ops)
+{
+ struct thermal_zone_device **ptr, *tzd;
+
+ ptr = devres_alloc(devm_thermal_zone_of_sensor_release, sizeof(*ptr),
+ GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ tzd = thermal_zone_of_sensor_register(dev, sensor_id, data, ops);
+ if (IS_ERR(tzd)) {
+ devres_free(ptr);
+ return tzd;
+ }
+
+ *ptr = tzd;
+ devres_add(dev, ptr);
+
+ return tzd;
+}
+EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_register);
+
+/**
+ * devm_thermal_zone_of_sensor_unregister - Resource managed version of
+ * thermal_zone_of_sensor_unregister().
+ * @dev: Device for which which resource was allocated.
+ * @tzd: a pointer to struct thermal_zone_device where the sensor is registered.
+ *
+ * This function removes the sensor callbacks and private data from the
+ * thermal zone device registered with devm_thermal_zone_of_sensor_register()
+ * API. It will also silent the zone by remove the .get_temp() and .get_trend()
+ * thermal zone device callbacks.
+ * Normally this function will not need to be called and the resource
+ * management code will ensure that the resource is freed.
+ */
+void devm_thermal_zone_of_sensor_unregister(struct device *dev,
+ struct thermal_zone_device *tzd)
+{
+ WARN_ON(devres_release(dev, devm_thermal_zone_of_sensor_release,
+ devm_thermal_zone_of_sensor_match, tzd));
+}
+EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister);
+
/*** functions parsing device tree nodes ***/
/**
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index e13a1ac..9c48199 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -362,6 +362,11 @@ thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
const struct thermal_zone_of_device_ops *ops);
void thermal_zone_of_sensor_unregister(struct device *dev,
struct thermal_zone_device *tz);
+struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
+ struct device *dev, int id, void *data,
+ const struct thermal_zone_of_device_ops *ops);
+void devm_thermal_zone_of_sensor_unregister(struct device *dev,
+ struct thermal_zone_device *tz);
#else
static inline struct thermal_zone_device *
thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
@@ -376,6 +381,19 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
{
}
+static inline struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
+ struct device *dev, int id, void *data,
+ const struct thermal_zone_of_device_ops *ops)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline
+void devm_thermal_zone_of_sensor_unregister(struct device *dev,
+ struct thermal_zone_device *tz)
+{
+}
+
#endif
#if IS_ENABLED(CONFIG_THERMAL)
--
2.1.4
Laxman,
On Wed, Mar 09, 2016 at 06:40:04PM +0530, Laxman Dewangan wrote:
> The series add the devm_ version of thermal_zone_of_sensor_register/
> unregister, interface details, and use this in new thermal driver
> for max77620.
>
> The header file for max77620 is part of MFD patch
> https://lkml.org/lkml/2016/2/11/186
>
> Changes from V1:
> - Run checkpatch with --strict and fix all warnings.
> - Added details of interfaces in spifs-api.txt
> - Added DT binding doc.
Thanks a lot for working on the comments. I don't see anything specific
right now. So, I am starting a couple of automated testing on this
series. If I find something, I will let you know.
On Wed, Mar 09, 2016 at 06:40:09PM +0530, Laxman Dewangan wrote:
> Maxim Semiconductor Max77620 supports alarm interrupts when
> its die temperature crosses 120C and 140C. These threshold
> temperatures are not configurable.
>
> Add thermal driver to register PMIC die temperature as thermal
> zone sensor and capture the die temperature warning interrupts
> to notifying the client.
>
> Signed-off-by: Laxman Dewangan <[email protected]>
>
> ---
> Changes from V1:
> - checkpatch warning fix and simplifying the dev.of_node
> initialisation.
>
> drivers/thermal/Kconfig | 10 +++
> drivers/thermal/Makefile | 1 +
> drivers/thermal/thermal-max77620.c | 151 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 162 insertions(+)
> create mode 100644 drivers/thermal/thermal-max77620.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 5e7c97a..fc856eb 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -194,6 +194,16 @@ config IMX_THERMAL
> cpufreq is used as the cooling device to throttle CPUs when the
> passive trip is crossed.
>
> +config MAX77620_THERMAL
> + tristate "Temperature sensor driver for Maxim MAX77620 PMIC"
> + depends on MFD_MAX77620
> + depends on OF
The previous question on compile test was more if we could add depends
on COMPILE_TEST flag. Sorry if I was not clear enough.
I am adding the flag here:
config MAX77620_THERMAL
tristate "Temperature sensor driver for Maxim MAX77620 PMIC"
- depends on MFD_MAX77620
+ depends on MFD_MAX77620 || COMPILE_TEST
+ depends on HAS_IOMEM
depends on OF
help
Support for die junction temperature
warning alarm for Maxim
but I still cannot compile test the file because of the missing header.
drivers/thermal/thermal-max77620.c:16:32: fatal error:
linux/mfd/max77620.h: No such file or directory
#include <linux/mfd/max77620.h>
I wont be able to merge this as it is. We need to sort out the
dependency first.
The patches with devm_ helpers could go, though.
> + help
> + Support for die junction temperature warning alarm for Maxim
> + Semiconductor PMIC MAX77620 device. Device generates two alarm
> + interrupts when PMIC die temperature cross the threshold of
> + 120 degC and 140 degC.
> +
> config SPEAR_THERMAL
> tristate "SPEAr thermal sensor driver"
> depends on PLAT_SPEAR || COMPILE_TEST
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 8e9cbc3..c6bc2bd 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -36,6 +36,7 @@ obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
> obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
> obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
> obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
> +obj-$(CONFIG_MAX77620_THERMAL) += thermal-max77620.o
> obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
> obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
> obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
> diff --git a/drivers/thermal/thermal-max77620.c b/drivers/thermal/thermal-max77620.c
> new file mode 100644
> index 0000000..5fba00f
> --- /dev/null
> +++ b/drivers/thermal/thermal-max77620.c
> @@ -0,0 +1,151 @@
> +/*
> + * Junction temperature thermal driver for Maxim Max77620.
> + *
> + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
> + *
> + * Author: Laxman Dewangan <[email protected]>
> + * Mallikarjun Kasoju <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + */
> +
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/max77620.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <linux/thermal.h>
> +
> +#define MAX77620_NORMAL_OPERATING_TEMP 100000
> +#define MAX77620_TJALARM1_TEMP 120000
> +#define MAX77620_TJALARM2_TEMP 140000
> +
> +struct max77620_therm_info {
> + struct device *dev;
> + struct regmap *rmap;
> + struct thermal_zone_device *tz_device;
> + int irq_tjalarm1;
> + int irq_tjalarm2;
> +};
> +
> +static int max77620_thermal_read_temp(void *data, int *temp)
> +{
> + struct max77620_therm_info *mtherm = data;
> + unsigned int val;
> + int ret;
> +
> + ret = regmap_read(mtherm->rmap, MAX77620_REG_STATLBT, &val);
> + if (ret < 0) {
> + dev_err(mtherm->dev, "Failed to read STATLBT, %d\n", ret);
> + return -EINVAL;
> + }
> +
> + if (val & MAX77620_IRQ_TJALRM2_MASK)
> + *temp = MAX77620_TJALARM2_TEMP;
> + else if (val & MAX77620_IRQ_TJALRM1_MASK)
> + *temp = MAX77620_TJALARM1_TEMP;
> + else
> + *temp = MAX77620_NORMAL_OPERATING_TEMP;
> + return 0;
> +}
> +
> +static const struct thermal_zone_of_device_ops max77620_thermal_ops = {
> + .get_temp = max77620_thermal_read_temp,
> +};
> +
> +static irqreturn_t max77620_thermal_irq(int irq, void *data)
> +{
> + struct max77620_therm_info *mtherm = data;
> +
> + if (irq == mtherm->irq_tjalarm1)
> + dev_warn(mtherm->dev, "Junction Temp Alarm1(120C) occurred\n");
> + else if (irq == mtherm->irq_tjalarm2)
> + dev_warn(mtherm->dev, "Junction Temp Alarm2(140C) occurred\n");
> +
> + thermal_zone_device_update(mtherm->tz_device);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int max77620_thermal_probe(struct platform_device *pdev)
> +{
> + struct max77620_therm_info *mtherm;
> + int ret;
> +
> + pdev->dev.of_node = pdev->dev.parent->of_node;
> +
> + mtherm = devm_kzalloc(&pdev->dev, sizeof(*mtherm), GFP_KERNEL);
> + if (!mtherm)
> + return -ENOMEM;
> +
> + mtherm->irq_tjalarm1 = platform_get_irq(pdev, 0);
> + mtherm->irq_tjalarm2 = platform_get_irq(pdev, 1);
> + if ((mtherm->irq_tjalarm1 < 0) || (mtherm->irq_tjalarm2 < 0)) {
> + dev_err(&pdev->dev, "Alarm irq number not available\n");
> + return -EINVAL;
> + }
> +
> + mtherm->dev = &pdev->dev;
> + mtherm->rmap = dev_get_regmap(pdev->dev.parent, NULL);
> + if (!mtherm->rmap) {
> + dev_err(&pdev->dev, "Failed to get parent regmap\n");
> + return -ENODEV;
> + }
> +
> + mtherm->tz_device = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
> + mtherm, &max77620_thermal_ops);
> + if (IS_ERR(mtherm->tz_device)) {
> + ret = PTR_ERR(mtherm->tz_device);
> + dev_err(&pdev->dev, "Failed to register thermal zone, %d\n",
> + ret);
> + return ret;
> + }
> +
> + ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm1, NULL,
> + max77620_thermal_irq,
> + IRQF_ONESHOT | IRQF_SHARED,
> + dev_name(&pdev->dev), mtherm);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to request irq1, %d\n", ret);
> + return ret;
> + }
> +
> + ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm2, NULL,
> + max77620_thermal_irq,
> + IRQF_ONESHOT | IRQF_SHARED,
> + dev_name(&pdev->dev), mtherm);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to request irq2, %d\n", ret);
> + return ret;
> + }
> +
> + platform_set_drvdata(pdev, mtherm);
> +
> + return 0;
> +}
> +
> +static struct platform_device_id max77620_thermal_devtype[] = {
> + { .name = "max77620-thermal", },
> + {},
> +};
> +
> +static struct platform_driver max77620_thermal_driver = {
> + .driver = {
> + .name = "max77620-thermal",
> + },
> + .probe = max77620_thermal_probe,
> + .id_table = max77620_thermal_devtype,
> +};
> +
> +module_platform_driver(max77620_thermal_driver);
> +
> +MODULE_DESCRIPTION("Max77620 Junction temperature Thermal driver");
> +MODULE_ALIAS("platform:max77620-thermal");
> +MODULE_AUTHOR("Laxman Dewangan <[email protected]>");
> +MODULE_AUTHOR("Mallikarjun Kasoju <[email protected]>");
> +MODULE_LICENSE("GPL v2");
> --
> 2.1.4
>
On Wed, Mar 09, 2016 at 06:40:10PM +0530, Laxman Dewangan wrote:
> Maxim Semiconductor MAX77620 supports alarm interrupts when
> its die temperature crosses 120C and 140C. These threshold
> temperatures are not configurable.
>
> Add DT binding document to details out the DT property related
> to MAX77620 thermal functionality.
>
> Signed-off-by: Laxman Dewangan <[email protected]>
>
> ---
> Changes from V1:
> - New in series to add DT binding doc per V1 review.
>
> .../bindings/thermal/thermal-max77620.txt | 43 ++++++++++++++++++++++
> 1 file changed, 43 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/thermal/thermal-max77620.txt
>
> diff --git a/Documentation/devicetree/bindings/thermal/thermal-max77620.txt b/Documentation/devicetree/bindings/thermal/thermal-max77620.txt
> new file mode 100644
> index 0000000..d76412f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/thermal-max77620.txt
> @@ -0,0 +1,43 @@
> +Thermal driver for MAX77620 Power management IC from Maxim Semiconductor.
> +
> +Maxim Semiconductor MAX77620 supports alarm interrupts when its
> +die temperature crosses 120C and 140C. These threshold temperatures
> +are not configurable. Device does not provide the real temperature
> +of die other than just indicating whether temperature is above or
> +below threshold level.
> +
> +Required properties:
> +-------------------
> +#thermal-sensor-cells: Please refer <devicetree/bindings/thermal/thermal.txt>
> + for more details.
> + The value must be 0.
> +
> +For more details, please refer generic thermal DT binding document
> +<devicetree/bindings/thermal/thermal.txt>.
> +
> +Please refer <devicetree/bindings/mfd/max77620.txt> for mfd DT binding
> +document for the MAX77620.
> +
> +Example:
> +--------
> +#include <dt-bindings/mfd/max77620.h>
> +...
> +spmic: max77620@3c {
> + compatible = "maxim,max77620";
> +
> + #thermal-sensor-cells = <0>;
> +};
> +
> +thermal-zones {
> + PMIC-Die {
> + thermal-sensors = <&spmic>;
> + trips {
> + die_temp_thresh: hot-die {
> + temperature = <120000>;
> + type = "active";
> + hysteresis = <0>;
> + };
> + };
> + };
> +};
Considering that this is an example (and people will copy and paste it),
please add all the required DT properties for a thermal-zone node.
> +
> --
> 2.1.4
>
On Wed, Mar 09, 2016 at 06:40:07PM +0530, Laxman Dewangan wrote:
> The interface thermal_zone_of_sensor_register() and
> thermal_zone_of_sensor_unregister() gained their devm_
> wrappers. Add these APIs in the list of managed devices.
>
> Signed-off-by: Laxman Dewangan <[email protected]>
Acked-by: Eduardo Valentin <[email protected]>
This should probably go via the documentation tree.
>
> ---
> Changes from V1:
> - No change.
>
> Documentation/driver-model/devres.txt | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
> index 5930d9a..dd7ce58 100644
> --- a/Documentation/driver-model/devres.txt
> +++ b/Documentation/driver-model/devres.txt
> @@ -342,6 +342,10 @@ SLAVE DMA ENGINE
> SPI
> devm_spi_register_master()
>
> +THERMAL
> + devm_thermal_zone_of_sensor_register()
> + devm_thermal_zone_of_sensor_unregister()
> +
> WATCHDOG
> devm_watchdog_register_device()
> devm_watchdog_unregister_device()
> --
> 2.1.4
>
On Wed, Mar 09, 2016 at 06:40:04PM +0530, Laxman Dewangan wrote:
> The series add the devm_ version of thermal_zone_of_sensor_register/
> unregister, interface details, and use this in new thermal driver
> for max77620.
>
> The header file for max77620 is part of MFD patch
> https://lkml.org/lkml/2016/2/11/186
>
> Changes from V1:
> - Run checkpatch with --strict and fix all warnings.
> - Added details of interfaces in spifs-api.txt
> - Added DT binding doc.
>
> Laxman Dewangan (6):
> thermal: doc: Add details of
> thermal_zone_of_sensor_{register,unregister}
> thermal: of-thermal: Add devm version of
> thermal_zone_of_sensor_register
> thermal: Add devm_thermal_zone_of_sensor_register() in managed devices
> list
> thermal: doc: Add details of
> devm_thermal_zone_of_sensor_{register,unregister}
> thermal: max77620: Add thermal driver for reporting junction temp
> thermal: Add DT binding doc for thermal of PMIC max77620
Add patches 1-3 in my tree. Patch 4 should probably go via documentation
tree. And patch 5 needs dependency to be sorted, and 6 need minor changes.
On Thursday 10 March 2016 01:02 AM, Eduardo Valentin wrote:
> * PGP Signed by an unknown key
>
> On Wed, Mar 09, 2016 at 06:40:04PM +0530, Laxman Dewangan wrote:
>> The series add the devm_ version of thermal_zone_of_sensor_register/
>> unregister, interface details, and use this in new thermal driver
>> for max77620.
>>
>> The header file for max77620 is part of MFD patch
>> https://lkml.org/lkml/2016/2/11/186
>>
>> Changes from V1:
>> - Run checkpatch with --strict and fix all warnings.
>> - Added details of interfaces in spifs-api.txt
>> - Added DT binding doc.
>>
>> Laxman Dewangan (6):
>> thermal: doc: Add details of
>> thermal_zone_of_sensor_{register,unregister}
>> thermal: of-thermal: Add devm version of
>> thermal_zone_of_sensor_register
>> thermal: Add devm_thermal_zone_of_sensor_register() in managed devices
>> list
>> thermal: doc: Add details of
>> devm_thermal_zone_of_sensor_{register,unregister}
>> thermal: max77620: Add thermal driver for reporting junction temp
>> thermal: Add DT binding doc for thermal of PMIC max77620
>
> Add patches 1-3 in my tree. Patch 4 should probably go via documentation
> tree. And patch 5 needs dependency to be sorted, and 6 need minor changes.
>
Thanks for accepting patches.
patch 5 needs mfd patches which is under review. So until that is
merged, compilation will fail due to header dependency.
Will add complete information on example of patch 6.
On Thursday 10 March 2016 12:57 AM, Eduardo Valentin wrote:
> * PGP Signed by an unknown key
>
> On Wed, Mar 09, 2016 at 06:40:09PM +0530, Laxman Dewangan wrote:
>> Maxim Semiconductor Max77620 supports alarm interrupts when
>> its die temperature crosses 120C and 140C. These threshold
>> temperatures are not configurable.
>>
>> Add thermal driver to register PMIC die temperature as thermal
>> zone sensor and capture the die temperature warning interrupts
>> to notifying the client.
>>
>> Signed-off-by: Laxman Dewangan <[email protected]>
>>
>> ---
>> Changes from V1:
>> - checkpatch warning fix and simplifying the dev.of_node
>> initialisation.
>>
>> drivers/thermal/Kconfig | 10 +++
>> drivers/thermal/Makefile | 1 +
>> drivers/thermal/thermal-max77620.c | 151 +++++++++++++++++++++++++++++++++++++
>> 3 files changed, 162 insertions(+)
>> create mode 100644 drivers/thermal/thermal-max77620.c
>>
>> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
>> index 5e7c97a..fc856eb 100644
>> --- a/drivers/thermal/Kconfig
>> +++ b/drivers/thermal/Kconfig
>> @@ -194,6 +194,16 @@ config IMX_THERMAL
>> cpufreq is used as the cooling device to throttle CPUs when the
>> passive trip is crossed.
>>
>> +config MAX77620_THERMAL
>> + tristate "Temperature sensor driver for Maxim MAX77620 PMIC"
>> + depends on MFD_MAX77620
>> + depends on OF
> The previous question on compile test was more if we could add depends
> on COMPILE_TEST flag. Sorry if I was not clear enough.
>
>
> I am adding the flag here:
>
>
> config MAX77620_THERMAL
> tristate "Temperature sensor driver for Maxim MAX77620 PMIC"
> - depends on MFD_MAX77620
> + depends on MFD_MAX77620 || COMPILE_TEST
> + depends on HAS_IOMEM
> depends on OF
> help
> Support for die junction temperature
> warning alarm for Maxim
>
>
> but I still cannot compile test the file because of the missing header.
> drivers/thermal/thermal-max77620.c:16:32: fatal error:
> linux/mfd/max77620.h: No such file or directory
> #include <linux/mfd/max77620.h>
>
>
> I wont be able to merge this as it is. We need to sort out the
> dependency first.
>
I will update you once the mfd patches will merge as this header is on
that patch.