aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/818-thermal-0001-thermal-Add-generic-device-cooling-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/layerscape/patches-5.4/818-thermal-0001-thermal-Add-generic-device-cooling-support.patch')
-rw-r--r--target/linux/layerscape/patches-5.4/818-thermal-0001-thermal-Add-generic-device-cooling-support.patch253
1 files changed, 253 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/818-thermal-0001-thermal-Add-generic-device-cooling-support.patch b/target/linux/layerscape/patches-5.4/818-thermal-0001-thermal-Add-generic-device-cooling-support.patch
new file mode 100644
index 0000000000..f947eb6e32
--- /dev/null
+++ b/target/linux/layerscape/patches-5.4/818-thermal-0001-thermal-Add-generic-device-cooling-support.patch
@@ -0,0 +1,253 @@
+From 97abcfc5219149ff7d4883b295c80257f0315b5e Mon Sep 17 00:00:00 2001
+From: Anson Huang <Anson.Huang@nxp.com>
+Date: Wed, 7 Aug 2019 08:40:59 +0800
+Subject: [PATCH] thermal: Add generic device cooling support
+
+To compatible with previous implementation, add generic device
+cooling support, each thermal zone will register a cooling
+device, and when temperature exceed passive trip, the device
+cooling driver will send out a system wide notification, each
+device supporting cooling will need to register device cooling
+and takes action when passive trip is exceeded;
+
+Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
+[rebase]
+Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+---
+ drivers/thermal/Kconfig | 7 ++
+ drivers/thermal/Makefile | 1 +
+ drivers/thermal/device_cooling.c | 152 +++++++++++++++++++++++++++++++++++++++
+ include/linux/device_cooling.h | 45 ++++++++++++
+ 4 files changed, 205 insertions(+)
+ create mode 100644 drivers/thermal/device_cooling.c
+ create mode 100644 include/linux/device_cooling.h
+
+--- a/drivers/thermal/Kconfig
++++ b/drivers/thermal/Kconfig
+@@ -233,6 +233,13 @@ config IMX_THERMAL
+ cpufreq is used as the cooling device to throttle CPUs when the
+ passive trip is crossed.
+
++config DEVICE_THERMAL
++ tristate "generic device cooling support"
++ help
++ Support for device cooling.
++ It supports notification of crossing passive trip for devices,
++ devices need to do their own actions to cool down the SOC.
++
+ config MAX77620_THERMAL
+ tristate "Temperature sensor driver for Maxim MAX77620 PMIC"
+ depends on MFD_MAX77620
+--- a/drivers/thermal/Makefile
++++ b/drivers/thermal/Makefile
+@@ -41,6 +41,7 @@ obj-$(CONFIG_DB8500_THERMAL) += db8500_t
+ obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
+ obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o
+ obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
++obj-$(CONFIG_DEVICE_THERMAL) += device_cooling.o
+ obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
+ obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
+ obj-$(CONFIG_DA9062_THERMAL) += da9062-thermal.o
+--- /dev/null
++++ b/drivers/thermal/device_cooling.c
+@@ -0,0 +1,152 @@
++/*
++ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/thermal.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++
++struct devfreq_cooling_device {
++ int id;
++ struct thermal_cooling_device *cool_dev;
++ unsigned int devfreq_state;
++};
++
++static DEFINE_IDR(devfreq_idr);
++static DEFINE_MUTEX(devfreq_cooling_lock);
++
++#define MAX_STATE 1
++
++static BLOCKING_NOTIFIER_HEAD(devfreq_cooling_chain_head);
++
++int register_devfreq_cooling_notifier(struct notifier_block *nb)
++{
++ return blocking_notifier_chain_register(
++ &devfreq_cooling_chain_head, nb);
++}
++EXPORT_SYMBOL_GPL(register_devfreq_cooling_notifier);
++
++int unregister_devfreq_cooling_notifier(struct notifier_block *nb)
++{
++ return blocking_notifier_chain_unregister(
++ &devfreq_cooling_chain_head, nb);
++}
++EXPORT_SYMBOL_GPL(unregister_devfreq_cooling_notifier);
++
++static int devfreq_cooling_notifier_call_chain(unsigned long val)
++{
++ return (blocking_notifier_call_chain(
++ &devfreq_cooling_chain_head, val, NULL)
++ == NOTIFY_BAD) ? -EINVAL : 0;
++}
++
++static int devfreq_set_cur_state(struct thermal_cooling_device *cdev,
++ unsigned long state)
++{
++ struct devfreq_cooling_device *devfreq_device = cdev->devdata;
++ int ret;
++
++ ret = devfreq_cooling_notifier_call_chain(state);
++ if (ret)
++ return -EINVAL;
++
++ devfreq_device->devfreq_state = state;
++
++ return 0;
++}
++
++static int devfreq_get_max_state(struct thermal_cooling_device *cdev,
++ unsigned long *state)
++{
++ *state = MAX_STATE;
++
++ return 0;
++}
++
++static int devfreq_get_cur_state(struct thermal_cooling_device *cdev,
++ unsigned long *state)
++{
++ struct devfreq_cooling_device *devfreq_device = cdev->devdata;
++
++ *state = devfreq_device->devfreq_state;
++
++ return 0;
++}
++
++static struct thermal_cooling_device_ops const devfreq_cooling_ops = {
++ .get_max_state = devfreq_get_max_state,
++ .get_cur_state = devfreq_get_cur_state,
++ .set_cur_state = devfreq_set_cur_state,
++};
++
++static int get_idr(struct idr *idr, int *id)
++{
++ int ret;
++
++ mutex_lock(&devfreq_cooling_lock);
++ ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
++ mutex_unlock(&devfreq_cooling_lock);
++ if (unlikely(ret < 0))
++ return ret;
++ *id = ret;
++
++ return 0;
++}
++
++static void release_idr(struct idr *idr, int id)
++{
++ mutex_lock(&devfreq_cooling_lock);
++ idr_remove(idr, id);
++ mutex_unlock(&devfreq_cooling_lock);
++}
++
++struct thermal_cooling_device *devfreq_cooling_register(void)
++{
++ struct thermal_cooling_device *cool_dev;
++ struct devfreq_cooling_device *devfreq_dev = NULL;
++ char dev_name[THERMAL_NAME_LENGTH];
++ int ret = 0;
++
++ devfreq_dev = kzalloc(sizeof(struct devfreq_cooling_device),
++ GFP_KERNEL);
++ if (!devfreq_dev)
++ return ERR_PTR(-ENOMEM);
++
++ ret = get_idr(&devfreq_idr, &devfreq_dev->id);
++ if (ret) {
++ kfree(devfreq_dev);
++ return ERR_PTR(-EINVAL);
++ }
++
++ snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d",
++ devfreq_dev->id);
++
++ cool_dev = thermal_cooling_device_register(dev_name, devfreq_dev,
++ &devfreq_cooling_ops);
++ if (!cool_dev) {
++ release_idr(&devfreq_idr, devfreq_dev->id);
++ kfree(devfreq_dev);
++ return ERR_PTR(-EINVAL);
++ }
++ devfreq_dev->cool_dev = cool_dev;
++ devfreq_dev->devfreq_state = 0;
++
++ return cool_dev;
++}
++EXPORT_SYMBOL_GPL(devfreq_cooling_register);
++
++void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
++{
++ struct devfreq_cooling_device *devfreq_dev = cdev->devdata;
++
++ thermal_cooling_device_unregister(devfreq_dev->cool_dev);
++ release_idr(&devfreq_idr, devfreq_dev->id);
++ kfree(devfreq_dev);
++}
++EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);
+--- /dev/null
++++ b/include/linux/device_cooling.h
+@@ -0,0 +1,45 @@
++/*
++ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#ifndef __DEVICE_THERMAL_H__
++#define __DEVICE_THERMAL_H__
++
++#include <linux/thermal.h>
++
++#ifdef CONFIG_DEVICE_THERMAL
++int register_devfreq_cooling_notifier(struct notifier_block *nb);
++int unregister_devfreq_cooling_notifier(struct notifier_block *nb);
++struct thermal_cooling_device *devfreq_cooling_register(void);
++void devfreq_cooling_unregister(struct thermal_cooling_device *cdev);
++#else
++static inline
++int register_devfreq_cooling_notifier(struct notifier_block *nb)
++{
++ return 0;
++}
++
++static inline
++int unregister_devfreq_cooling_notifier(struct notifier_block *nb)
++{
++ return 0;
++}
++
++static inline
++struct thermal_cooling_device *devfreq_cooling_register(void)
++{
++ return NULL;
++}
++
++static inline
++void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
++{
++ return;
++}
++#endif
++#endif /* __DEVICE_THERMAL_H__ */