* [PATCH V2] QorIQ/TMU: add thermal management support based on TMU @ 2015-07-29 6:19 Jia Hongtao 2015-07-30 6:55 ` Eduardo Valentin 0 siblings, 1 reply; 8+ messages in thread From: Jia Hongtao @ 2015-07-29 6:19 UTC (permalink / raw) To: edubezval; +Cc: linux-pm, linuxppc-dev, scottwood, hongtao.jia It supports one critical trip point and one passive trip point. The cpufreq is used as the cooling device to throttle CPUs when the passive trip is crossed. Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com> --- This patch based on: http://patchwork.ozlabs.org/patch/482987/ Changes for V2: * Add tmu-range parse. * Use default trend hook. * Using latest thermal_zone_bind_cooling_device API. * Add calibration check during initialization. * Disable/enalbe device when suspend/resume. drivers/thermal/Kconfig | 11 ++ drivers/thermal/Makefile | 1 + drivers/thermal/qoriq_thermal.c | 406 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 418 insertions(+) create mode 100644 drivers/thermal/qoriq_thermal.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 118938e..a200745 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -180,6 +180,17 @@ config IMX_THERMAL cpufreq is used as the cooling device to throttle CPUs when the passive trip is crossed. +config QORIQ_THERMAL + tristate "Freescale QorIQ Thermal Monitoring Unit" + depends on CPU_THERMAL + depends on OF + default n + help + Enable thermal management based on Freescale QorIQ Thermal Monitoring + Unit (TMU). It supports one critical trip point and one passive trip + point. The cpufreq is used as the cooling device to throttle CPUs when + the passive trip is crossed. + config SPEAR_THERMAL bool "SPEAr thermal sensor driver" depends on PLAT_SPEAR diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 535dfee..8c25859 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -33,6 +33,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_QORIQ_THERMAL) += qoriq_thermal.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/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c new file mode 100644 index 0000000..0694f42 --- /dev/null +++ b/drivers/thermal/qoriq_thermal.c @@ -0,0 +1,406 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * 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. + * + * This program is distributed in the hope 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. + * + */ + +/* + * Based on Freescale QorIQ Thermal Monitoring Unit (TMU) + */ +#include <linux/cpufreq.h> +#include <linux/cpu_cooling.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/thermal.h> + +#define SITES_MAX 16 + +#define TMU_TEMP_PASSIVE 85000 +#define TMU_TEMP_CRITICAL 95000 + +#define TMU_PASSIVE_DELAY 1000 /* Milliseconds */ +#define TMU_POLLING_DELAY 5000 + +/* The driver supports 1 passive trip point and 1 critical trip point */ +enum tmu_thermal_trip { + TMU_TRIP_PASSIVE, + TMU_TRIP_CRITICAL, + TMU_TRIP_NUM, +}; + +/* + * QorIQ TMU Registers + */ +struct qoriq_tmu_site_regs { + __be32 tritsr; /* Immediate Temperature Site Register */ + __be32 tratsr; /* Average Temperature Site Register */ + u8 res0[0x8]; +} __packed; + +struct qoriq_tmu_regs { + __be32 tmr; /* Mode Register */ +#define TMR_DISABLE 0x0 +#define TMR_ME 0x80000000 +#define TMR_ALPF 0x0c000000 +#define TMR_MSITE 0x00008000 +#define TMR_ALL (TMR_ME | TMR_ALPF | TMR_MSITE) + __be32 tsr; /* Status Register */ + __be32 tmtmir; /* Temperature measurement interval Register */ +#define TMTMIR_DEFAULT 0x00000007 + u8 res0[0x14]; + __be32 tier; /* Interrupt Enable Register */ +#define TIER_DISABLE 0x0 + __be32 tidr; /* Interrupt Detect Register */ + __be32 tiscr; /* Interrupt Site Capture Register */ + __be32 ticscr; /* Interrupt Critical Site Capture Register */ + u8 res1[0x10]; + __be32 tmhtcrh; /* High Temperature Capture Register */ + __be32 tmhtcrl; /* Low Temperature Capture Register */ + u8 res2[0x8]; + __be32 tmhtitr; /* High Temperature Immediate Threshold */ + __be32 tmhtatr; /* High Temperature Average Threshold */ + __be32 tmhtactr; /* High Temperature Average Crit Threshold */ + u8 res3[0x24]; + __be32 ttcfgr; /* Temperature Configuration Register */ + __be32 tscfgr; /* Sensor Configuration Register */ + u8 res4[0x78]; + struct qoriq_tmu_site_regs site[SITES_MAX]; + u8 res5[0x9f8]; + __be32 ipbrr0; /* IP Block Revision Register 0 */ + __be32 ipbrr1; /* IP Block Revision Register 1 */ + u8 res6[0x310]; + __be32 ttr0cr; /* Temperature Range 0 Control Register */ + __be32 ttr1cr; /* Temperature Range 1 Control Register */ + __be32 ttr2cr; /* Temperature Range 2 Control Register */ + __be32 ttr3cr; /* Temperature Range 3 Control Register */ +}; + +/* + * Thermal zone data + */ +struct qoriq_tmu_data { + struct thermal_zone_device *tz; + struct thermal_cooling_device *cdev; + enum thermal_device_mode mode; + unsigned long temp_passive; + unsigned long temp_critical; + struct qoriq_tmu_regs __iomem *regs; +}; + +static int tmu_get_mode(struct thermal_zone_device *tz, + enum thermal_device_mode *mode) +{ + struct qoriq_tmu_data *data = tz->devdata; + + *mode = data->mode; + + return 0; +} + +static int tmu_set_mode(struct thermal_zone_device *tz, + enum thermal_device_mode mode) +{ + struct qoriq_tmu_data *data = tz->devdata; + + if (mode == THERMAL_DEVICE_ENABLED) { + tz->polling_delay = TMU_POLLING_DELAY; + tz->passive_delay = TMU_PASSIVE_DELAY; + thermal_zone_device_update(tz); + } else { + tz->polling_delay = 0; + tz->passive_delay = 0; + } + + data->mode = mode; + + return 0; +} + +static int tmu_get_temp(struct thermal_zone_device *tz, unsigned long *temp) +{ + u8 val; + struct qoriq_tmu_data *data = tz->devdata; + + val = ioread32be(&data->regs->site[0].tritsr); + *temp = (unsigned long)val * 1000; + + return 0; +} + +static int tmu_get_trip_type(struct thermal_zone_device *tz, int trip, + enum thermal_trip_type *type) +{ + *type = (trip == TMU_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE : + THERMAL_TRIP_CRITICAL; + + return 0; +} + +static int tmu_get_trip_temp(struct thermal_zone_device *tz, int trip, + unsigned long *temp) +{ + struct qoriq_tmu_data *data = tz->devdata; + + *temp = (trip == TMU_TRIP_PASSIVE) ? data->temp_passive : + data->temp_critical; + + return 0; +} + +static int tmu_get_crit_temp(struct thermal_zone_device *tz, + unsigned long *temp) +{ + struct qoriq_tmu_data *data = tz->devdata; + + *temp = data->temp_critical; + + return 0; +} + +static int tmu_bind(struct thermal_zone_device *tz, + struct thermal_cooling_device *cdev) +{ + int ret; + + ret = thermal_zone_bind_cooling_device(tz, TMU_TRIP_PASSIVE, cdev, + THERMAL_NO_LIMIT, + THERMAL_NO_LIMIT, + THERMAL_WEIGHT_DEFAULT); + if (ret) { + dev_err(&tz->device, + "Binding zone %s with cdev %s failed:%d\n", + tz->type, cdev->type, ret); + } + + return ret; +} + +static int tmu_unbind(struct thermal_zone_device *tz, + struct thermal_cooling_device *cdev) +{ + int ret; + + ret = thermal_zone_unbind_cooling_device(tz, TMU_TRIP_PASSIVE, cdev); + if (ret) { + dev_err(&tz->device, + "Unbinding zone %s with cdev %s failed:%d\n", + tz->type, cdev->type, ret); + } + + return ret; +} + +static int qoriq_tmu_calibration(struct platform_device *pdev) +{ + int i, val, len; + u32 range[4]; + const __be32 *calibration; + struct device_node *node = pdev->dev.of_node; + struct qoriq_tmu_data *data = dev_get_drvdata(&pdev->dev); + + /* Disable monitoring before calibration */ + iowrite32be(TMR_DISABLE, &data->regs->tmr); + + if (of_property_read_u32_array(node, "fsl,tmu-range", range, 4)) + return -1; + + /* Init temperature range registers */ + iowrite32be(range[0], &data->regs->ttr0cr); + iowrite32be(range[1], &data->regs->ttr1cr); + iowrite32be(range[2], &data->regs->ttr2cr); + iowrite32be(range[3], &data->regs->ttr3cr); + + calibration = of_get_property(node, "fsl,tmu-calibration", &len); + if (calibration == NULL) + return -1; + + for (i = 0; i < len; i += 8, calibration += 2) { + val = (int)of_read_number(calibration, 1); + iowrite32be(val, &data->regs->ttcfgr); + val = (int)of_read_number(calibration + 1, 1); + iowrite32be(val, &data->regs->tscfgr); + } + + return 0; +} + +static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) +{ + /* Disable interrupt, using polling instead */ + iowrite32be(TIER_DISABLE, &data->regs->tier); + + /* Set update_interval */ + iowrite32be(TMTMIR_DEFAULT, &data->regs->tmtmir); + + /* Enable monitoring */ + iowrite32be(TMR_ALL, &data->regs->tmr); +} + +static struct thermal_zone_device_ops tmu_tz_ops = { + .bind = tmu_bind, + .unbind = tmu_unbind, + .get_temp = tmu_get_temp, + .get_mode = tmu_get_mode, + .set_mode = tmu_set_mode, + .get_trip_type = tmu_get_trip_type, + .get_trip_temp = tmu_get_trip_temp, + .get_crit_temp = tmu_get_crit_temp, +}; + +static int qoriq_tmu_probe(struct platform_device *pdev) +{ + int ret; + struct cpumask clip_cpus; + struct qoriq_tmu_data *data; + + if (!cpufreq_get_current_driver()) { + dev_dbg(&pdev->dev, "No cpufreq driver yet\n"); + return -EPROBE_DEFER; + } + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "Device OF-Node is NULL"); + return -EFAULT; + } + + data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + dev_set_drvdata(&pdev->dev, data); + data->regs = of_iomap(pdev->dev.of_node, 0); + + if (!data->regs) { + dev_err(&pdev->dev, "Failed to get memory region\n"); + ret = -ENODEV; + goto err_iomap; + } + + ret = qoriq_tmu_calibration(pdev); /* TMU calibration */ + if (ret < 0) { + dev_err(&pdev->dev, "TMU calibration failed.\n"); + ret = -ENODEV; + goto err_iomap; + } + + qoriq_tmu_init_device(data); /* TMU initialization */ + + cpumask_setall(&clip_cpus); + data->cdev = cpufreq_cooling_register(&clip_cpus); + if (IS_ERR(data->cdev)) { + ret = PTR_ERR(data->cdev); + dev_err(&data->cdev->device, + "Failed to register cpufreq cooling device: %d\n", ret); + goto err_cooling; + } + + data->temp_passive = TMU_TEMP_PASSIVE; + data->temp_critical = TMU_TEMP_CRITICAL; + data->tz = thermal_zone_device_register("tmu_thermal_zone", + TMU_TRIP_NUM, + 0, data, + &tmu_tz_ops, NULL, + TMU_PASSIVE_DELAY, + TMU_POLLING_DELAY); + + if (IS_ERR(data->tz)) { + ret = PTR_ERR(data->tz); + dev_err(&pdev->dev, + "Failed to register thermal zone device %d\n", ret); + goto err_thermal; + } + + data->mode = THERMAL_DEVICE_ENABLED; + + return 0; + +err_thermal: + cpufreq_cooling_unregister(data->cdev); + +err_cooling: + iounmap(data->regs); + +err_iomap: + dev_set_drvdata(&pdev->dev, NULL); + devm_kfree(&pdev->dev, data); + + return ret; +} + +static int qoriq_tmu_remove(struct platform_device *pdev) +{ + struct qoriq_tmu_data *data = dev_get_drvdata(&pdev->dev); + + /* Disable monitoring */ + iowrite32be(TMR_DISABLE, &data->regs->tmr); + + thermal_zone_device_unregister(data->tz); + cpufreq_cooling_unregister(data->cdev); + iounmap(data->regs); + + dev_set_drvdata(&pdev->dev, NULL); + devm_kfree(&pdev->dev, data); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int qoriq_tmu_suspend(struct device *dev) +{ + struct qoriq_tmu_data *data = dev_get_drvdata(dev); + + /* Disable monitoring */ + iowrite32be(TMR_DISABLE, &data->regs->tmr); + data->mode = THERMAL_DEVICE_DISABLED; + + return 0; +} + +static int qoriq_tmu_resume(struct device *dev) +{ + struct qoriq_tmu_data *data = dev_get_drvdata(dev); + + /* Enable monitoring */ + iowrite32be(TMR_ALL, &data->regs->tmr); + data->mode = THERMAL_DEVICE_ENABLED; + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops, + qoriq_tmu_suspend, qoriq_tmu_resume); + +static const struct of_device_id qoriq_tmu_match[] = { + { .compatible = "fsl,qoriq-tmu", }, + {}, +}; + +static struct platform_driver qoriq_tmu = { + .driver = { + .owner = THIS_MODULE, + .name = "qoriq_thermal", + .pm = &qoriq_tmu_pm_ops, + .of_match_table = qoriq_tmu_match, + }, + .probe = qoriq_tmu_probe, + .remove = qoriq_tmu_remove, +}; +module_platform_driver(qoriq_tmu); + +MODULE_AUTHOR("Jia Hongtao <hongtao.jia@freescale.com>"); +MODULE_DESCRIPTION("Freescale QorIQ Thermal Monitoring Unit driver"); +MODULE_LICENSE("GPL v2"); -- 2.1.0.27.g96db324 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH V2] QorIQ/TMU: add thermal management support based on TMU 2015-07-29 6:19 [PATCH V2] QorIQ/TMU: add thermal management support based on TMU Jia Hongtao @ 2015-07-30 6:55 ` Eduardo Valentin 2015-07-30 8:13 ` Hongtao Jia 0 siblings, 1 reply; 8+ messages in thread From: Eduardo Valentin @ 2015-07-30 6:55 UTC (permalink / raw) To: Jia Hongtao; +Cc: linux-pm, linuxppc-dev, scottwood [-- Attachment #1: Type: text/plain, Size: 14364 bytes --] On Wed, Jul 29, 2015 at 02:19:39PM +0800, Jia Hongtao wrote: > It supports one critical trip point and one passive trip point. > The cpufreq is used as the cooling device to throttle CPUs when > the passive trip is crossed. > > Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com> > --- > This patch based on: > http://patchwork.ozlabs.org/patch/482987/ > > Changes for V2: > * Add tmu-range parse. > * Use default trend hook. > * Using latest thermal_zone_bind_cooling_device API. > * Add calibration check during initialization. > * Disable/enalbe device when suspend/resume. > > drivers/thermal/Kconfig | 11 ++ > drivers/thermal/Makefile | 1 + > drivers/thermal/qoriq_thermal.c | 406 ++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 418 insertions(+) > create mode 100644 drivers/thermal/qoriq_thermal.c > > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig > index 118938e..a200745 100644 > --- a/drivers/thermal/Kconfig > +++ b/drivers/thermal/Kconfig > @@ -180,6 +180,17 @@ config IMX_THERMAL > cpufreq is used as the cooling device to throttle CPUs when the > passive trip is crossed. > > +config QORIQ_THERMAL > + tristate "Freescale QorIQ Thermal Monitoring Unit" > + depends on CPU_THERMAL > + depends on OF > + default n > + help > + Enable thermal management based on Freescale QorIQ Thermal Monitoring > + Unit (TMU). It supports one critical trip point and one passive trip > + point. The cpufreq is used as the cooling device to throttle CPUs when > + the passive trip is crossed. > + > config SPEAR_THERMAL > bool "SPEAr thermal sensor driver" > depends on PLAT_SPEAR > diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile > index 535dfee..8c25859 100644 > --- a/drivers/thermal/Makefile > +++ b/drivers/thermal/Makefile > @@ -33,6 +33,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_QORIQ_THERMAL) += qoriq_thermal.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/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c > new file mode 100644 > index 0000000..0694f42 > --- /dev/null > +++ b/drivers/thermal/qoriq_thermal.c > @@ -0,0 +1,406 @@ > +/* > + * Copyright 2015 Freescale Semiconductor, Inc. > + * > + * 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. > + * > + * This program is distributed in the hope 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. > + * > + */ > + > +/* > + * Based on Freescale QorIQ Thermal Monitoring Unit (TMU) > + */ > +#include <linux/cpufreq.h> > +#include <linux/cpu_cooling.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/err.h> > +#include <linux/io.h> > +#include <linux/of.h> > +#include <linux/of_address.h> > +#include <linux/thermal.h> > + > +#define SITES_MAX 16 > + > +#define TMU_TEMP_PASSIVE 85000 > +#define TMU_TEMP_CRITICAL 95000 > + > +#define TMU_PASSIVE_DELAY 1000 /* Milliseconds */ > +#define TMU_POLLING_DELAY 5000 > + > +/* The driver supports 1 passive trip point and 1 critical trip point */ > +enum tmu_thermal_trip { > + TMU_TRIP_PASSIVE, > + TMU_TRIP_CRITICAL, > + TMU_TRIP_NUM, > +}; > + > +/* > + * QorIQ TMU Registers > + */ > +struct qoriq_tmu_site_regs { > + __be32 tritsr; /* Immediate Temperature Site Register */ > + __be32 tratsr; /* Average Temperature Site Register */ > + u8 res0[0x8]; > +} __packed; > + > +struct qoriq_tmu_regs { > + __be32 tmr; /* Mode Register */ > +#define TMR_DISABLE 0x0 > +#define TMR_ME 0x80000000 > +#define TMR_ALPF 0x0c000000 > +#define TMR_MSITE 0x00008000 > +#define TMR_ALL (TMR_ME | TMR_ALPF | TMR_MSITE) > + __be32 tsr; /* Status Register */ > + __be32 tmtmir; /* Temperature measurement interval Register */ > +#define TMTMIR_DEFAULT 0x00000007 > + u8 res0[0x14]; > + __be32 tier; /* Interrupt Enable Register */ > +#define TIER_DISABLE 0x0 > + __be32 tidr; /* Interrupt Detect Register */ > + __be32 tiscr; /* Interrupt Site Capture Register */ > + __be32 ticscr; /* Interrupt Critical Site Capture Register */ > + u8 res1[0x10]; > + __be32 tmhtcrh; /* High Temperature Capture Register */ > + __be32 tmhtcrl; /* Low Temperature Capture Register */ > + u8 res2[0x8]; > + __be32 tmhtitr; /* High Temperature Immediate Threshold */ > + __be32 tmhtatr; /* High Temperature Average Threshold */ > + __be32 tmhtactr; /* High Temperature Average Crit Threshold */ > + u8 res3[0x24]; > + __be32 ttcfgr; /* Temperature Configuration Register */ > + __be32 tscfgr; /* Sensor Configuration Register */ > + u8 res4[0x78]; > + struct qoriq_tmu_site_regs site[SITES_MAX]; > + u8 res5[0x9f8]; > + __be32 ipbrr0; /* IP Block Revision Register 0 */ > + __be32 ipbrr1; /* IP Block Revision Register 1 */ > + u8 res6[0x310]; > + __be32 ttr0cr; /* Temperature Range 0 Control Register */ > + __be32 ttr1cr; /* Temperature Range 1 Control Register */ > + __be32 ttr2cr; /* Temperature Range 2 Control Register */ > + __be32 ttr3cr; /* Temperature Range 3 Control Register */ > +}; > + > +/* > + * Thermal zone data > + */ > +struct qoriq_tmu_data { > + struct thermal_zone_device *tz; > + struct thermal_cooling_device *cdev; > + enum thermal_device_mode mode; > + unsigned long temp_passive; > + unsigned long temp_critical; > + struct qoriq_tmu_regs __iomem *regs; > +}; > + > +static int tmu_get_mode(struct thermal_zone_device *tz, > + enum thermal_device_mode *mode) > +{ > + struct qoriq_tmu_data *data = tz->devdata; > + > + *mode = data->mode; > + > + return 0; > +} > + > +static int tmu_set_mode(struct thermal_zone_device *tz, > + enum thermal_device_mode mode) > +{ > + struct qoriq_tmu_data *data = tz->devdata; > + > + if (mode == THERMAL_DEVICE_ENABLED) { > + tz->polling_delay = TMU_POLLING_DELAY; > + tz->passive_delay = TMU_PASSIVE_DELAY; > + thermal_zone_device_update(tz); > + } else { > + tz->polling_delay = 0; > + tz->passive_delay = 0; > + } > + > + data->mode = mode; > + > + return 0; > +} > + > +static int tmu_get_temp(struct thermal_zone_device *tz, unsigned long *temp) > +{ > + u8 val; > + struct qoriq_tmu_data *data = tz->devdata; > + > + val = ioread32be(&data->regs->site[0].tritsr); > + *temp = (unsigned long)val * 1000; > + > + return 0; > +} > + > +static int tmu_get_trip_type(struct thermal_zone_device *tz, int trip, > + enum thermal_trip_type *type) > +{ > + *type = (trip == TMU_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE : > + THERMAL_TRIP_CRITICAL; > + > + return 0; > +} > + > +static int tmu_get_trip_temp(struct thermal_zone_device *tz, int trip, > + unsigned long *temp) > +{ > + struct qoriq_tmu_data *data = tz->devdata; > + > + *temp = (trip == TMU_TRIP_PASSIVE) ? data->temp_passive : > + data->temp_critical; > + > + return 0; > +} > + > +static int tmu_get_crit_temp(struct thermal_zone_device *tz, > + unsigned long *temp) > +{ > + struct qoriq_tmu_data *data = tz->devdata; > + > + *temp = data->temp_critical; > + > + return 0; > +} > + > +static int tmu_bind(struct thermal_zone_device *tz, > + struct thermal_cooling_device *cdev) > +{ > + int ret; > + > + ret = thermal_zone_bind_cooling_device(tz, TMU_TRIP_PASSIVE, cdev, > + THERMAL_NO_LIMIT, > + THERMAL_NO_LIMIT, > + THERMAL_WEIGHT_DEFAULT); > + if (ret) { > + dev_err(&tz->device, > + "Binding zone %s with cdev %s failed:%d\n", > + tz->type, cdev->type, ret); > + } > + > + return ret; > +} > + > +static int tmu_unbind(struct thermal_zone_device *tz, > + struct thermal_cooling_device *cdev) > +{ > + int ret; > + > + ret = thermal_zone_unbind_cooling_device(tz, TMU_TRIP_PASSIVE, cdev); > + if (ret) { > + dev_err(&tz->device, > + "Unbinding zone %s with cdev %s failed:%d\n", > + tz->type, cdev->type, ret); > + } > + > + return ret; > +} > + > +static int qoriq_tmu_calibration(struct platform_device *pdev) > +{ > + int i, val, len; > + u32 range[4]; > + const __be32 *calibration; > + struct device_node *node = pdev->dev.of_node; > + struct qoriq_tmu_data *data = dev_get_drvdata(&pdev->dev); > + > + /* Disable monitoring before calibration */ > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > + > + if (of_property_read_u32_array(node, "fsl,tmu-range", range, 4)) > + return -1; > + > + /* Init temperature range registers */ > + iowrite32be(range[0], &data->regs->ttr0cr); > + iowrite32be(range[1], &data->regs->ttr1cr); > + iowrite32be(range[2], &data->regs->ttr2cr); > + iowrite32be(range[3], &data->regs->ttr3cr); > + > + calibration = of_get_property(node, "fsl,tmu-calibration", &len); > + if (calibration == NULL) > + return -1; > + > + for (i = 0; i < len; i += 8, calibration += 2) { > + val = (int)of_read_number(calibration, 1); > + iowrite32be(val, &data->regs->ttcfgr); > + val = (int)of_read_number(calibration + 1, 1); > + iowrite32be(val, &data->regs->tscfgr); > + } > + > + return 0; > +} > + > +static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) > +{ > + /* Disable interrupt, using polling instead */ > + iowrite32be(TIER_DISABLE, &data->regs->tier); > + > + /* Set update_interval */ > + iowrite32be(TMTMIR_DEFAULT, &data->regs->tmtmir); > + > + /* Enable monitoring */ > + iowrite32be(TMR_ALL, &data->regs->tmr); > +} > + > +static struct thermal_zone_device_ops tmu_tz_ops = { > + .bind = tmu_bind, > + .unbind = tmu_unbind, > + .get_temp = tmu_get_temp, > + .get_mode = tmu_get_mode, > + .set_mode = tmu_set_mode, > + .get_trip_type = tmu_get_trip_type, > + .get_trip_temp = tmu_get_trip_temp, > + .get_crit_temp = tmu_get_crit_temp, > +}; > + > +static int qoriq_tmu_probe(struct platform_device *pdev) > +{ > + int ret; > + struct cpumask clip_cpus; > + struct qoriq_tmu_data *data; > + > + if (!cpufreq_get_current_driver()) { > + dev_dbg(&pdev->dev, "No cpufreq driver yet\n"); > + return -EPROBE_DEFER; > + } > + > + if (!pdev->dev.of_node) { > + dev_err(&pdev->dev, "Device OF-Node is NULL"); > + return -EFAULT; > + } > + > + data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data), > + GFP_KERNEL); > + if (!data) > + return -ENOMEM; > + > + dev_set_drvdata(&pdev->dev, data); > + data->regs = of_iomap(pdev->dev.of_node, 0); > + > + if (!data->regs) { > + dev_err(&pdev->dev, "Failed to get memory region\n"); > + ret = -ENODEV; > + goto err_iomap; > + } > + > + ret = qoriq_tmu_calibration(pdev); /* TMU calibration */ > + if (ret < 0) { > + dev_err(&pdev->dev, "TMU calibration failed.\n"); > + ret = -ENODEV; > + goto err_iomap; > + } > + > + qoriq_tmu_init_device(data); /* TMU initialization */ > + > + cpumask_setall(&clip_cpus); > + data->cdev = cpufreq_cooling_register(&clip_cpus); > + if (IS_ERR(data->cdev)) { > + ret = PTR_ERR(data->cdev); > + dev_err(&data->cdev->device, > + "Failed to register cpufreq cooling device: %d\n", ret); > + goto err_cooling; > + } > + > + data->temp_passive = TMU_TEMP_PASSIVE; > + data->temp_critical = TMU_TEMP_CRITICAL; > + data->tz = thermal_zone_device_register("tmu_thermal_zone", Any specific reason why not using OF thermal? > + TMU_TRIP_NUM, > + 0, data, > + &tmu_tz_ops, NULL, > + TMU_PASSIVE_DELAY, > + TMU_POLLING_DELAY); > + > + if (IS_ERR(data->tz)) { > + ret = PTR_ERR(data->tz); > + dev_err(&pdev->dev, > + "Failed to register thermal zone device %d\n", ret); > + goto err_thermal; > + } > + > + data->mode = THERMAL_DEVICE_ENABLED; > + > + return 0; > + > +err_thermal: > + cpufreq_cooling_unregister(data->cdev); > + > +err_cooling: > + iounmap(data->regs); > + > +err_iomap: > + dev_set_drvdata(&pdev->dev, NULL); > + devm_kfree(&pdev->dev, data); > + > + return ret; > +} > + > +static int qoriq_tmu_remove(struct platform_device *pdev) > +{ > + struct qoriq_tmu_data *data = dev_get_drvdata(&pdev->dev); > + > + /* Disable monitoring */ > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > + > + thermal_zone_device_unregister(data->tz); > + cpufreq_cooling_unregister(data->cdev); > + iounmap(data->regs); > + > + dev_set_drvdata(&pdev->dev, NULL); > + devm_kfree(&pdev->dev, data); > + > + return 0; > +} > + > +#ifdef CONFIG_PM_SLEEP > +static int qoriq_tmu_suspend(struct device *dev) > +{ > + struct qoriq_tmu_data *data = dev_get_drvdata(dev); > + > + /* Disable monitoring */ > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > + data->mode = THERMAL_DEVICE_DISABLED; > + > + return 0; > +} > + > +static int qoriq_tmu_resume(struct device *dev) > +{ > + struct qoriq_tmu_data *data = dev_get_drvdata(dev); > + > + /* Enable monitoring */ > + iowrite32be(TMR_ALL, &data->regs->tmr); > + data->mode = THERMAL_DEVICE_ENABLED; > + > + return 0; > +} > +#endif > + > +static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops, > + qoriq_tmu_suspend, qoriq_tmu_resume); > + > +static const struct of_device_id qoriq_tmu_match[] = { > + { .compatible = "fsl,qoriq-tmu", }, > + {}, > +}; > + > +static struct platform_driver qoriq_tmu = { > + .driver = { > + .owner = THIS_MODULE, > + .name = "qoriq_thermal", > + .pm = &qoriq_tmu_pm_ops, > + .of_match_table = qoriq_tmu_match, > + }, > + .probe = qoriq_tmu_probe, > + .remove = qoriq_tmu_remove, > +}; > +module_platform_driver(qoriq_tmu); > + > +MODULE_AUTHOR("Jia Hongtao <hongtao.jia@freescale.com>"); > +MODULE_DESCRIPTION("Freescale QorIQ Thermal Monitoring Unit driver"); > +MODULE_LICENSE("GPL v2"); > -- > 2.1.0.27.g96db324 > [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 490 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH V2] QorIQ/TMU: add thermal management support based on TMU 2015-07-30 6:55 ` Eduardo Valentin @ 2015-07-30 8:13 ` Hongtao Jia 2015-08-05 19:42 ` Eduardo Valentin 0 siblings, 1 reply; 8+ messages in thread From: Hongtao Jia @ 2015-07-30 8:13 UTC (permalink / raw) To: Eduardo Valentin Cc: linux-pm@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Scott Wood - "Any specific reason why not using OF thermal?" - No, actually. I'd like to use OF thermal after some clarification. Regarding to "cooling-maps". For some cases there should be more than one c= pus as cooling device and they are independent. 1. Let's say 4. So we need to provide 4 maps like map0-map3. Right? 2. "cooling-max-level" may vary depend on switch settings or firmware. Is t= hat OK if I do not provide "cooling-min-level" and "cooling-max-level" prope= rty? =20 Thanks. -Hongtao > -----Original Message----- > From: Eduardo Valentin [mailto:edubezval@gmail.com] > Sent: Thursday, July 30, 2015 2:56 PM > To: Jia Hongtao-B38951 > Cc: linux-pm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood Scott- > B07421 > Subject: Re: [PATCH V2] QorIQ/TMU: add thermal management support based > on TMU >=20 > On Wed, Jul 29, 2015 at 02:19:39PM +0800, Jia Hongtao wrote: > > It supports one critical trip point and one passive trip point. > > The cpufreq is used as the cooling device to throttle CPUs when the > > passive trip is crossed. > > > > Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com> > > --- > > This patch based on: > > http://patchwork.ozlabs.org/patch/482987/ > > > > Changes for V2: > > * Add tmu-range parse. > > * Use default trend hook. > > * Using latest thermal_zone_bind_cooling_device API. > > * Add calibration check during initialization. > > * Disable/enalbe device when suspend/resume. > > > > drivers/thermal/Kconfig | 11 ++ > > drivers/thermal/Makefile | 1 + > > drivers/thermal/qoriq_thermal.c | 406 > > ++++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 418 insertions(+) > > create mode 100644 drivers/thermal/qoriq_thermal.c > > > > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index > > 118938e..a200745 100644 > > --- a/drivers/thermal/Kconfig > > +++ b/drivers/thermal/Kconfig > > @@ -180,6 +180,17 @@ config IMX_THERMAL > > cpufreq is used as the cooling device to throttle CPUs when the > > passive trip is crossed. > > > > +config QORIQ_THERMAL > > + tristate "Freescale QorIQ Thermal Monitoring Unit" > > + depends on CPU_THERMAL > > + depends on OF > > + default n > > + help > > + Enable thermal management based on Freescale QorIQ Thermal > Monitoring > > + Unit (TMU). It supports one critical trip point and one passive > trip > > + point. The cpufreq is used as the cooling device to throttle CPUs > when > > + the passive trip is crossed. > > + > > config SPEAR_THERMAL > > bool "SPEAr thermal sensor driver" > > depends on PLAT_SPEAR > > diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index > > 535dfee..8c25859 100644 > > --- a/drivers/thermal/Makefile > > +++ b/drivers/thermal/Makefile > > @@ -33,6 +33,7 @@ obj-$(CONFIG_DOVE_THERMAL) +=3D dove_thermal.o > > obj-$(CONFIG_DB8500_THERMAL) +=3D db8500_thermal.o > > obj-$(CONFIG_ARMADA_THERMAL) +=3D armada_thermal.o > > obj-$(CONFIG_IMX_THERMAL) +=3D imx_thermal.o > > +obj-$(CONFIG_QORIQ_THERMAL) +=3D qoriq_thermal.o > > obj-$(CONFIG_DB8500_CPUFREQ_COOLING) +=3D db8500_cpufreq_cooling.o > > obj-$(CONFIG_INTEL_POWERCLAMP) +=3D intel_powerclamp.o > > obj-$(CONFIG_X86_PKG_TEMP_THERMAL) +=3D x86_pkg_temp_thermal.o > > diff --git a/drivers/thermal/qoriq_thermal.c > > b/drivers/thermal/qoriq_thermal.c new file mode 100644 index > > 0000000..0694f42 > > --- /dev/null > > +++ b/drivers/thermal/qoriq_thermal.c > > @@ -0,0 +1,406 @@ > > +/* > > + * Copyright 2015 Freescale Semiconductor, Inc. > > + * > > + * 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. > > + * > > + * This program is distributed in the hope 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. > > + * > > + */ > > + > > +/* > > + * Based on Freescale QorIQ Thermal Monitoring Unit (TMU) */ > > +#include <linux/cpufreq.h> #include <linux/cpu_cooling.h> #include > > +<linux/module.h> #include <linux/platform_device.h> #include > > +<linux/err.h> #include <linux/io.h> #include <linux/of.h> #include > > +<linux/of_address.h> #include <linux/thermal.h> > > + > > +#define SITES_MAX 16 > > + > > +#define TMU_TEMP_PASSIVE 85000 > > +#define TMU_TEMP_CRITICAL 95000 > > + > > +#define TMU_PASSIVE_DELAY 1000 /* Milliseconds */ > > +#define TMU_POLLING_DELAY 5000 > > + > > +/* The driver supports 1 passive trip point and 1 critical trip point > > +*/ enum tmu_thermal_trip { > > + TMU_TRIP_PASSIVE, > > + TMU_TRIP_CRITICAL, > > + TMU_TRIP_NUM, > > +}; > > + > > +/* > > + * QorIQ TMU Registers > > + */ > > +struct qoriq_tmu_site_regs { > > + __be32 tritsr; /* Immediate Temperature Site Register */ > > + __be32 tratsr; /* Average Temperature Site Register */ > > + u8 res0[0x8]; > > +} __packed; > > + > > +struct qoriq_tmu_regs { > > + __be32 tmr; /* Mode Register */ > > +#define TMR_DISABLE 0x0 > > +#define TMR_ME 0x80000000 > > +#define TMR_ALPF 0x0c000000 > > +#define TMR_MSITE 0x00008000 > > +#define TMR_ALL (TMR_ME | TMR_ALPF | TMR_MSITE) > > + __be32 tsr; /* Status Register */ > > + __be32 tmtmir; /* Temperature measurement interval > Register */ > > +#define TMTMIR_DEFAULT 0x00000007 > > + u8 res0[0x14]; > > + __be32 tier; /* Interrupt Enable Register */ > > +#define TIER_DISABLE 0x0 > > + __be32 tidr; /* Interrupt Detect Register */ > > + __be32 tiscr; /* Interrupt Site Capture Register */ > > + __be32 ticscr; /* Interrupt Critical Site Capture Register > */ > > + u8 res1[0x10]; > > + __be32 tmhtcrh; /* High Temperature Capture Register */ > > + __be32 tmhtcrl; /* Low Temperature Capture Register */ > > + u8 res2[0x8]; > > + __be32 tmhtitr; /* High Temperature Immediate Threshold */ > > + __be32 tmhtatr; /* High Temperature Average Threshold */ > > + __be32 tmhtactr; /* High Temperature Average Crit Threshold */ > > + u8 res3[0x24]; > > + __be32 ttcfgr; /* Temperature Configuration Register */ > > + __be32 tscfgr; /* Sensor Configuration Register */ > > + u8 res4[0x78]; > > + struct qoriq_tmu_site_regs site[SITES_MAX]; > > + u8 res5[0x9f8]; > > + __be32 ipbrr0; /* IP Block Revision Register 0 */ > > + __be32 ipbrr1; /* IP Block Revision Register 1 */ > > + u8 res6[0x310]; > > + __be32 ttr0cr; /* Temperature Range 0 Control Register */ > > + __be32 ttr1cr; /* Temperature Range 1 Control Register */ > > + __be32 ttr2cr; /* Temperature Range 2 Control Register */ > > + __be32 ttr3cr; /* Temperature Range 3 Control Register */ > > +}; > > + > > +/* > > + * Thermal zone data > > + */ > > +struct qoriq_tmu_data { > > + struct thermal_zone_device *tz; > > + struct thermal_cooling_device *cdev; > > + enum thermal_device_mode mode; > > + unsigned long temp_passive; > > + unsigned long temp_critical; > > + struct qoriq_tmu_regs __iomem *regs; }; > > + > > +static int tmu_get_mode(struct thermal_zone_device *tz, > > + enum thermal_device_mode *mode) > > +{ > > + struct qoriq_tmu_data *data =3D tz->devdata; > > + > > + *mode =3D data->mode; > > + > > + return 0; > > +} > > + > > +static int tmu_set_mode(struct thermal_zone_device *tz, > > + enum thermal_device_mode mode) > > +{ > > + struct qoriq_tmu_data *data =3D tz->devdata; > > + > > + if (mode =3D=3D THERMAL_DEVICE_ENABLED) { > > + tz->polling_delay =3D TMU_POLLING_DELAY; > > + tz->passive_delay =3D TMU_PASSIVE_DELAY; > > + thermal_zone_device_update(tz); > > + } else { > > + tz->polling_delay =3D 0; > > + tz->passive_delay =3D 0; > > + } > > + > > + data->mode =3D mode; > > + > > + return 0; > > +} > > + > > +static int tmu_get_temp(struct thermal_zone_device *tz, unsigned long > > +*temp) { > > + u8 val; > > + struct qoriq_tmu_data *data =3D tz->devdata; > > + > > + val =3D ioread32be(&data->regs->site[0].tritsr); > > + *temp =3D (unsigned long)val * 1000; > > + > > + return 0; > > +} > > + > > +static int tmu_get_trip_type(struct thermal_zone_device *tz, int trip, > > + enum thermal_trip_type *type) { > > + *type =3D (trip =3D=3D TMU_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE : > > + THERMAL_TRIP_CRITICAL; > > + > > + return 0; > > +} > > + > > +static int tmu_get_trip_temp(struct thermal_zone_device *tz, int trip, > > + unsigned long *temp) > > +{ > > + struct qoriq_tmu_data *data =3D tz->devdata; > > + > > + *temp =3D (trip =3D=3D TMU_TRIP_PASSIVE) ? data->temp_passive : > > + data->temp_critical; > > + > > + return 0; > > +} > > + > > +static int tmu_get_crit_temp(struct thermal_zone_device *tz, > > + unsigned long *temp) > > +{ > > + struct qoriq_tmu_data *data =3D tz->devdata; > > + > > + *temp =3D data->temp_critical; > > + > > + return 0; > > +} > > + > > +static int tmu_bind(struct thermal_zone_device *tz, > > + struct thermal_cooling_device *cdev) { > > + int ret; > > + > > + ret =3D thermal_zone_bind_cooling_device(tz, TMU_TRIP_PASSIVE, cdev, > > + THERMAL_NO_LIMIT, > > + THERMAL_NO_LIMIT, > > + THERMAL_WEIGHT_DEFAULT); > > + if (ret) { > > + dev_err(&tz->device, > > + "Binding zone %s with cdev %s failed:%d\n", > > + tz->type, cdev->type, ret); > > + } > > + > > + return ret; > > +} > > + > > +static int tmu_unbind(struct thermal_zone_device *tz, > > + struct thermal_cooling_device *cdev) { > > + int ret; > > + > > + ret =3D thermal_zone_unbind_cooling_device(tz, TMU_TRIP_PASSIVE, > cdev); > > + if (ret) { > > + dev_err(&tz->device, > > + "Unbinding zone %s with cdev %s failed:%d\n", > > + tz->type, cdev->type, ret); > > + } > > + > > + return ret; > > +} > > + > > +static int qoriq_tmu_calibration(struct platform_device *pdev) { > > + int i, val, len; > > + u32 range[4]; > > + const __be32 *calibration; > > + struct device_node *node =3D pdev->dev.of_node; > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(&pdev->dev); > > + > > + /* Disable monitoring before calibration */ > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > + > > + if (of_property_read_u32_array(node, "fsl,tmu-range", range, 4)) > > + return -1; > > + > > + /* Init temperature range registers */ > > + iowrite32be(range[0], &data->regs->ttr0cr); > > + iowrite32be(range[1], &data->regs->ttr1cr); > > + iowrite32be(range[2], &data->regs->ttr2cr); > > + iowrite32be(range[3], &data->regs->ttr3cr); > > + > > + calibration =3D of_get_property(node, "fsl,tmu-calibration", &len); > > + if (calibration =3D=3D NULL) > > + return -1; > > + > > + for (i =3D 0; i < len; i +=3D 8, calibration +=3D 2) { > > + val =3D (int)of_read_number(calibration, 1); > > + iowrite32be(val, &data->regs->ttcfgr); > > + val =3D (int)of_read_number(calibration + 1, 1); > > + iowrite32be(val, &data->regs->tscfgr); > > + } > > + > > + return 0; > > +} > > + > > +static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) { > > + /* Disable interrupt, using polling instead */ > > + iowrite32be(TIER_DISABLE, &data->regs->tier); > > + > > + /* Set update_interval */ > > + iowrite32be(TMTMIR_DEFAULT, &data->regs->tmtmir); > > + > > + /* Enable monitoring */ > > + iowrite32be(TMR_ALL, &data->regs->tmr); } > > + > > +static struct thermal_zone_device_ops tmu_tz_ops =3D { > > + .bind =3D tmu_bind, > > + .unbind =3D tmu_unbind, > > + .get_temp =3D tmu_get_temp, > > + .get_mode =3D tmu_get_mode, > > + .set_mode =3D tmu_set_mode, > > + .get_trip_type =3D tmu_get_trip_type, > > + .get_trip_temp =3D tmu_get_trip_temp, > > + .get_crit_temp =3D tmu_get_crit_temp, > > +}; > > + > > +static int qoriq_tmu_probe(struct platform_device *pdev) { > > + int ret; > > + struct cpumask clip_cpus; > > + struct qoriq_tmu_data *data; > > + > > + if (!cpufreq_get_current_driver()) { > > + dev_dbg(&pdev->dev, "No cpufreq driver yet\n"); > > + return -EPROBE_DEFER; > > + } > > + > > + if (!pdev->dev.of_node) { > > + dev_err(&pdev->dev, "Device OF-Node is NULL"); > > + return -EFAULT; > > + } > > + > > + data =3D devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data), > > + GFP_KERNEL); > > + if (!data) > > + return -ENOMEM; > > + > > + dev_set_drvdata(&pdev->dev, data); > > + data->regs =3D of_iomap(pdev->dev.of_node, 0); > > + > > + if (!data->regs) { > > + dev_err(&pdev->dev, "Failed to get memory region\n"); > > + ret =3D -ENODEV; > > + goto err_iomap; > > + } > > + > > + ret =3D qoriq_tmu_calibration(pdev); /* TMU calibration */ > > + if (ret < 0) { > > + dev_err(&pdev->dev, "TMU calibration failed.\n"); > > + ret =3D -ENODEV; > > + goto err_iomap; > > + } > > + > > + qoriq_tmu_init_device(data); /* TMU initialization */ > > + > > + cpumask_setall(&clip_cpus); > > + data->cdev =3D cpufreq_cooling_register(&clip_cpus); > > + if (IS_ERR(data->cdev)) { > > + ret =3D PTR_ERR(data->cdev); > > + dev_err(&data->cdev->device, > > + "Failed to register cpufreq cooling device: %d\n", ret); > > + goto err_cooling; > > + } > > + > > + data->temp_passive =3D TMU_TEMP_PASSIVE; > > + data->temp_critical =3D TMU_TEMP_CRITICAL; > > + data->tz =3D thermal_zone_device_register("tmu_thermal_zone", >=20 > Any specific reason why not using OF thermal? >=20 > > + TMU_TRIP_NUM, > > + 0, data, > > + &tmu_tz_ops, NULL, > > + TMU_PASSIVE_DELAY, > > + TMU_POLLING_DELAY); > > + > > + if (IS_ERR(data->tz)) { > > + ret =3D PTR_ERR(data->tz); > > + dev_err(&pdev->dev, > > + "Failed to register thermal zone device %d\n", ret); > > + goto err_thermal; > > + } > > + > > + data->mode =3D THERMAL_DEVICE_ENABLED; > > + > > + return 0; > > + > > +err_thermal: > > + cpufreq_cooling_unregister(data->cdev); > > + > > +err_cooling: > > + iounmap(data->regs); > > + > > +err_iomap: > > + dev_set_drvdata(&pdev->dev, NULL); > > + devm_kfree(&pdev->dev, data); > > + > > + return ret; > > +} > > + > > +static int qoriq_tmu_remove(struct platform_device *pdev) { > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(&pdev->dev); > > + > > + /* Disable monitoring */ > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > + > > + thermal_zone_device_unregister(data->tz); > > + cpufreq_cooling_unregister(data->cdev); > > + iounmap(data->regs); > > + > > + dev_set_drvdata(&pdev->dev, NULL); > > + devm_kfree(&pdev->dev, data); > > + > > + return 0; > > +} > > + > > +#ifdef CONFIG_PM_SLEEP > > +static int qoriq_tmu_suspend(struct device *dev) { > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(dev); > > + > > + /* Disable monitoring */ > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > + data->mode =3D THERMAL_DEVICE_DISABLED; > > + > > + return 0; > > +} > > + > > +static int qoriq_tmu_resume(struct device *dev) { > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(dev); > > + > > + /* Enable monitoring */ > > + iowrite32be(TMR_ALL, &data->regs->tmr); > > + data->mode =3D THERMAL_DEVICE_ENABLED; > > + > > + return 0; > > +} > > +#endif > > + > > +static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops, > > + qoriq_tmu_suspend, qoriq_tmu_resume); > > + > > +static const struct of_device_id qoriq_tmu_match[] =3D { > > + { .compatible =3D "fsl,qoriq-tmu", }, > > + {}, > > +}; > > + > > +static struct platform_driver qoriq_tmu =3D { > > + .driver =3D { > > + .owner =3D THIS_MODULE, > > + .name =3D "qoriq_thermal", > > + .pm =3D &qoriq_tmu_pm_ops, > > + .of_match_table =3D qoriq_tmu_match, > > + }, > > + .probe =3D qoriq_tmu_probe, > > + .remove =3D qoriq_tmu_remove, > > +}; > > +module_platform_driver(qoriq_tmu); > > + > > +MODULE_AUTHOR("Jia Hongtao <hongtao.jia@freescale.com>"); > > +MODULE_DESCRIPTION("Freescale QorIQ Thermal Monitoring Unit driver"); > > +MODULE_LICENSE("GPL v2"); > > -- > > 2.1.0.27.g96db324 > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH V2] QorIQ/TMU: add thermal management support based on TMU 2015-07-30 8:13 ` Hongtao Jia @ 2015-08-05 19:42 ` Eduardo Valentin 2015-08-07 8:14 ` Hongtao Jia 0 siblings, 1 reply; 8+ messages in thread From: Eduardo Valentin @ 2015-08-05 19:42 UTC (permalink / raw) To: Hongtao Jia Cc: linux-pm@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Scott Wood [-- Attachment #1: Type: text/plain, Size: 17738 bytes --] On Thu, Jul 30, 2015 at 08:13:09AM +0000, Hongtao Jia wrote: > - "Any specific reason why not using OF thermal?" > - No, actually. > > I'd like to use OF thermal after some clarification. > > Regarding to "cooling-maps". For some cases there should be more than one cpus > as cooling device and they are independent. > 1. Let's say 4. So we need to provide 4 maps like map0-map3. Right? That would depend on the amount of sensors you have. Do you have one sensor per cpu? if the answer is yes, then you probably want to have four different map entries, yes, but one on each thermal zone of each cpu temperature sensor. if the answer is no, then you would need to have all the maps in the same thermal zone. > 2. "cooling-max-level" may vary depend on switch settings or firmware. Is that > OK if I do not provide "cooling-min-level" and "cooling-max-level" property? That is already achievable by using the cooling-device property of a cooling map. Please have a look in the example section of the Documentation/devicetree/bindings/thermal/thermal.txt Let me know if you need further clarification. BR, Eduardo Valentin > > Thanks. > -Hongtao > > > > -----Original Message----- > > From: Eduardo Valentin [mailto:edubezval@gmail.com] > > Sent: Thursday, July 30, 2015 2:56 PM > > To: Jia Hongtao-B38951 > > Cc: linux-pm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood Scott- > > B07421 > > Subject: Re: [PATCH V2] QorIQ/TMU: add thermal management support based > > on TMU > > > > On Wed, Jul 29, 2015 at 02:19:39PM +0800, Jia Hongtao wrote: > > > It supports one critical trip point and one passive trip point. > > > The cpufreq is used as the cooling device to throttle CPUs when the > > > passive trip is crossed. > > > > > > Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com> > > > --- > > > This patch based on: > > > http://patchwork.ozlabs.org/patch/482987/ > > > > > > Changes for V2: > > > * Add tmu-range parse. > > > * Use default trend hook. > > > * Using latest thermal_zone_bind_cooling_device API. > > > * Add calibration check during initialization. > > > * Disable/enalbe device when suspend/resume. > > > > > > drivers/thermal/Kconfig | 11 ++ > > > drivers/thermal/Makefile | 1 + > > > drivers/thermal/qoriq_thermal.c | 406 > > > ++++++++++++++++++++++++++++++++++++++++ > > > 3 files changed, 418 insertions(+) > > > create mode 100644 drivers/thermal/qoriq_thermal.c > > > > > > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index > > > 118938e..a200745 100644 > > > --- a/drivers/thermal/Kconfig > > > +++ b/drivers/thermal/Kconfig > > > @@ -180,6 +180,17 @@ config IMX_THERMAL > > > cpufreq is used as the cooling device to throttle CPUs when the > > > passive trip is crossed. > > > > > > +config QORIQ_THERMAL > > > + tristate "Freescale QorIQ Thermal Monitoring Unit" > > > + depends on CPU_THERMAL > > > + depends on OF > > > + default n > > > + help > > > + Enable thermal management based on Freescale QorIQ Thermal > > Monitoring > > > + Unit (TMU). It supports one critical trip point and one passive > > trip > > > + point. The cpufreq is used as the cooling device to throttle CPUs > > when > > > + the passive trip is crossed. > > > + > > > config SPEAR_THERMAL > > > bool "SPEAr thermal sensor driver" > > > depends on PLAT_SPEAR > > > diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index > > > 535dfee..8c25859 100644 > > > --- a/drivers/thermal/Makefile > > > +++ b/drivers/thermal/Makefile > > > @@ -33,6 +33,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_QORIQ_THERMAL) += qoriq_thermal.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/qoriq_thermal.c > > > b/drivers/thermal/qoriq_thermal.c new file mode 100644 index > > > 0000000..0694f42 > > > --- /dev/null > > > +++ b/drivers/thermal/qoriq_thermal.c > > > @@ -0,0 +1,406 @@ > > > +/* > > > + * Copyright 2015 Freescale Semiconductor, Inc. > > > + * > > > + * 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. > > > + * > > > + * This program is distributed in the hope 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. > > > + * > > > + */ > > > + > > > +/* > > > + * Based on Freescale QorIQ Thermal Monitoring Unit (TMU) */ > > > +#include <linux/cpufreq.h> #include <linux/cpu_cooling.h> #include > > > +<linux/module.h> #include <linux/platform_device.h> #include > > > +<linux/err.h> #include <linux/io.h> #include <linux/of.h> #include > > > +<linux/of_address.h> #include <linux/thermal.h> > > > + > > > +#define SITES_MAX 16 > > > + > > > +#define TMU_TEMP_PASSIVE 85000 > > > +#define TMU_TEMP_CRITICAL 95000 > > > + > > > +#define TMU_PASSIVE_DELAY 1000 /* Milliseconds */ > > > +#define TMU_POLLING_DELAY 5000 > > > + > > > +/* The driver supports 1 passive trip point and 1 critical trip point > > > +*/ enum tmu_thermal_trip { > > > + TMU_TRIP_PASSIVE, > > > + TMU_TRIP_CRITICAL, > > > + TMU_TRIP_NUM, > > > +}; > > > + > > > +/* > > > + * QorIQ TMU Registers > > > + */ > > > +struct qoriq_tmu_site_regs { > > > + __be32 tritsr; /* Immediate Temperature Site Register */ > > > + __be32 tratsr; /* Average Temperature Site Register */ > > > + u8 res0[0x8]; > > > +} __packed; > > > + > > > +struct qoriq_tmu_regs { > > > + __be32 tmr; /* Mode Register */ > > > +#define TMR_DISABLE 0x0 > > > +#define TMR_ME 0x80000000 > > > +#define TMR_ALPF 0x0c000000 > > > +#define TMR_MSITE 0x00008000 > > > +#define TMR_ALL (TMR_ME | TMR_ALPF | TMR_MSITE) > > > + __be32 tsr; /* Status Register */ > > > + __be32 tmtmir; /* Temperature measurement interval > > Register */ > > > +#define TMTMIR_DEFAULT 0x00000007 > > > + u8 res0[0x14]; > > > + __be32 tier; /* Interrupt Enable Register */ > > > +#define TIER_DISABLE 0x0 > > > + __be32 tidr; /* Interrupt Detect Register */ > > > + __be32 tiscr; /* Interrupt Site Capture Register */ > > > + __be32 ticscr; /* Interrupt Critical Site Capture Register > > */ > > > + u8 res1[0x10]; > > > + __be32 tmhtcrh; /* High Temperature Capture Register */ > > > + __be32 tmhtcrl; /* Low Temperature Capture Register */ > > > + u8 res2[0x8]; > > > + __be32 tmhtitr; /* High Temperature Immediate Threshold */ > > > + __be32 tmhtatr; /* High Temperature Average Threshold */ > > > + __be32 tmhtactr; /* High Temperature Average Crit Threshold */ > > > + u8 res3[0x24]; > > > + __be32 ttcfgr; /* Temperature Configuration Register */ > > > + __be32 tscfgr; /* Sensor Configuration Register */ > > > + u8 res4[0x78]; > > > + struct qoriq_tmu_site_regs site[SITES_MAX]; > > > + u8 res5[0x9f8]; > > > + __be32 ipbrr0; /* IP Block Revision Register 0 */ > > > + __be32 ipbrr1; /* IP Block Revision Register 1 */ > > > + u8 res6[0x310]; > > > + __be32 ttr0cr; /* Temperature Range 0 Control Register */ > > > + __be32 ttr1cr; /* Temperature Range 1 Control Register */ > > > + __be32 ttr2cr; /* Temperature Range 2 Control Register */ > > > + __be32 ttr3cr; /* Temperature Range 3 Control Register */ > > > +}; > > > + > > > +/* > > > + * Thermal zone data > > > + */ > > > +struct qoriq_tmu_data { > > > + struct thermal_zone_device *tz; > > > + struct thermal_cooling_device *cdev; > > > + enum thermal_device_mode mode; > > > + unsigned long temp_passive; > > > + unsigned long temp_critical; > > > + struct qoriq_tmu_regs __iomem *regs; }; > > > + > > > +static int tmu_get_mode(struct thermal_zone_device *tz, > > > + enum thermal_device_mode *mode) > > > +{ > > > + struct qoriq_tmu_data *data = tz->devdata; > > > + > > > + *mode = data->mode; > > > + > > > + return 0; > > > +} > > > + > > > +static int tmu_set_mode(struct thermal_zone_device *tz, > > > + enum thermal_device_mode mode) > > > +{ > > > + struct qoriq_tmu_data *data = tz->devdata; > > > + > > > + if (mode == THERMAL_DEVICE_ENABLED) { > > > + tz->polling_delay = TMU_POLLING_DELAY; > > > + tz->passive_delay = TMU_PASSIVE_DELAY; > > > + thermal_zone_device_update(tz); > > > + } else { > > > + tz->polling_delay = 0; > > > + tz->passive_delay = 0; > > > + } > > > + > > > + data->mode = mode; > > > + > > > + return 0; > > > +} > > > + > > > +static int tmu_get_temp(struct thermal_zone_device *tz, unsigned long > > > +*temp) { > > > + u8 val; > > > + struct qoriq_tmu_data *data = tz->devdata; > > > + > > > + val = ioread32be(&data->regs->site[0].tritsr); > > > + *temp = (unsigned long)val * 1000; > > > + > > > + return 0; > > > +} > > > + > > > +static int tmu_get_trip_type(struct thermal_zone_device *tz, int trip, > > > + enum thermal_trip_type *type) { > > > + *type = (trip == TMU_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE : > > > + THERMAL_TRIP_CRITICAL; > > > + > > > + return 0; > > > +} > > > + > > > +static int tmu_get_trip_temp(struct thermal_zone_device *tz, int trip, > > > + unsigned long *temp) > > > +{ > > > + struct qoriq_tmu_data *data = tz->devdata; > > > + > > > + *temp = (trip == TMU_TRIP_PASSIVE) ? data->temp_passive : > > > + data->temp_critical; > > > + > > > + return 0; > > > +} > > > + > > > +static int tmu_get_crit_temp(struct thermal_zone_device *tz, > > > + unsigned long *temp) > > > +{ > > > + struct qoriq_tmu_data *data = tz->devdata; > > > + > > > + *temp = data->temp_critical; > > > + > > > + return 0; > > > +} > > > + > > > +static int tmu_bind(struct thermal_zone_device *tz, > > > + struct thermal_cooling_device *cdev) { > > > + int ret; > > > + > > > + ret = thermal_zone_bind_cooling_device(tz, TMU_TRIP_PASSIVE, cdev, > > > + THERMAL_NO_LIMIT, > > > + THERMAL_NO_LIMIT, > > > + THERMAL_WEIGHT_DEFAULT); > > > + if (ret) { > > > + dev_err(&tz->device, > > > + "Binding zone %s with cdev %s failed:%d\n", > > > + tz->type, cdev->type, ret); > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static int tmu_unbind(struct thermal_zone_device *tz, > > > + struct thermal_cooling_device *cdev) { > > > + int ret; > > > + > > > + ret = thermal_zone_unbind_cooling_device(tz, TMU_TRIP_PASSIVE, > > cdev); > > > + if (ret) { > > > + dev_err(&tz->device, > > > + "Unbinding zone %s with cdev %s failed:%d\n", > > > + tz->type, cdev->type, ret); > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static int qoriq_tmu_calibration(struct platform_device *pdev) { > > > + int i, val, len; > > > + u32 range[4]; > > > + const __be32 *calibration; > > > + struct device_node *node = pdev->dev.of_node; > > > + struct qoriq_tmu_data *data = dev_get_drvdata(&pdev->dev); > > > + > > > + /* Disable monitoring before calibration */ > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > + > > > + if (of_property_read_u32_array(node, "fsl,tmu-range", range, 4)) > > > + return -1; > > > + > > > + /* Init temperature range registers */ > > > + iowrite32be(range[0], &data->regs->ttr0cr); > > > + iowrite32be(range[1], &data->regs->ttr1cr); > > > + iowrite32be(range[2], &data->regs->ttr2cr); > > > + iowrite32be(range[3], &data->regs->ttr3cr); > > > + > > > + calibration = of_get_property(node, "fsl,tmu-calibration", &len); > > > + if (calibration == NULL) > > > + return -1; > > > + > > > + for (i = 0; i < len; i += 8, calibration += 2) { > > > + val = (int)of_read_number(calibration, 1); > > > + iowrite32be(val, &data->regs->ttcfgr); > > > + val = (int)of_read_number(calibration + 1, 1); > > > + iowrite32be(val, &data->regs->tscfgr); > > > + } > > > + > > > + return 0; > > > +} > > > + > > > +static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) { > > > + /* Disable interrupt, using polling instead */ > > > + iowrite32be(TIER_DISABLE, &data->regs->tier); > > > + > > > + /* Set update_interval */ > > > + iowrite32be(TMTMIR_DEFAULT, &data->regs->tmtmir); > > > + > > > + /* Enable monitoring */ > > > + iowrite32be(TMR_ALL, &data->regs->tmr); } > > > + > > > +static struct thermal_zone_device_ops tmu_tz_ops = { > > > + .bind = tmu_bind, > > > + .unbind = tmu_unbind, > > > + .get_temp = tmu_get_temp, > > > + .get_mode = tmu_get_mode, > > > + .set_mode = tmu_set_mode, > > > + .get_trip_type = tmu_get_trip_type, > > > + .get_trip_temp = tmu_get_trip_temp, > > > + .get_crit_temp = tmu_get_crit_temp, > > > +}; > > > + > > > +static int qoriq_tmu_probe(struct platform_device *pdev) { > > > + int ret; > > > + struct cpumask clip_cpus; > > > + struct qoriq_tmu_data *data; > > > + > > > + if (!cpufreq_get_current_driver()) { > > > + dev_dbg(&pdev->dev, "No cpufreq driver yet\n"); > > > + return -EPROBE_DEFER; > > > + } > > > + > > > + if (!pdev->dev.of_node) { > > > + dev_err(&pdev->dev, "Device OF-Node is NULL"); > > > + return -EFAULT; > > > + } > > > + > > > + data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data), > > > + GFP_KERNEL); > > > + if (!data) > > > + return -ENOMEM; > > > + > > > + dev_set_drvdata(&pdev->dev, data); > > > + data->regs = of_iomap(pdev->dev.of_node, 0); > > > + > > > + if (!data->regs) { > > > + dev_err(&pdev->dev, "Failed to get memory region\n"); > > > + ret = -ENODEV; > > > + goto err_iomap; > > > + } > > > + > > > + ret = qoriq_tmu_calibration(pdev); /* TMU calibration */ > > > + if (ret < 0) { > > > + dev_err(&pdev->dev, "TMU calibration failed.\n"); > > > + ret = -ENODEV; > > > + goto err_iomap; > > > + } > > > + > > > + qoriq_tmu_init_device(data); /* TMU initialization */ > > > + > > > + cpumask_setall(&clip_cpus); > > > + data->cdev = cpufreq_cooling_register(&clip_cpus); > > > + if (IS_ERR(data->cdev)) { > > > + ret = PTR_ERR(data->cdev); > > > + dev_err(&data->cdev->device, > > > + "Failed to register cpufreq cooling device: %d\n", ret); > > > + goto err_cooling; > > > + } > > > + > > > + data->temp_passive = TMU_TEMP_PASSIVE; > > > + data->temp_critical = TMU_TEMP_CRITICAL; > > > + data->tz = thermal_zone_device_register("tmu_thermal_zone", > > > > Any specific reason why not using OF thermal? > > > > > + TMU_TRIP_NUM, > > > + 0, data, > > > + &tmu_tz_ops, NULL, > > > + TMU_PASSIVE_DELAY, > > > + TMU_POLLING_DELAY); > > > + > > > + if (IS_ERR(data->tz)) { > > > + ret = PTR_ERR(data->tz); > > > + dev_err(&pdev->dev, > > > + "Failed to register thermal zone device %d\n", ret); > > > + goto err_thermal; > > > + } > > > + > > > + data->mode = THERMAL_DEVICE_ENABLED; > > > + > > > + return 0; > > > + > > > +err_thermal: > > > + cpufreq_cooling_unregister(data->cdev); > > > + > > > +err_cooling: > > > + iounmap(data->regs); > > > + > > > +err_iomap: > > > + dev_set_drvdata(&pdev->dev, NULL); > > > + devm_kfree(&pdev->dev, data); > > > + > > > + return ret; > > > +} > > > + > > > +static int qoriq_tmu_remove(struct platform_device *pdev) { > > > + struct qoriq_tmu_data *data = dev_get_drvdata(&pdev->dev); > > > + > > > + /* Disable monitoring */ > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > + > > > + thermal_zone_device_unregister(data->tz); > > > + cpufreq_cooling_unregister(data->cdev); > > > + iounmap(data->regs); > > > + > > > + dev_set_drvdata(&pdev->dev, NULL); > > > + devm_kfree(&pdev->dev, data); > > > + > > > + return 0; > > > +} > > > + > > > +#ifdef CONFIG_PM_SLEEP > > > +static int qoriq_tmu_suspend(struct device *dev) { > > > + struct qoriq_tmu_data *data = dev_get_drvdata(dev); > > > + > > > + /* Disable monitoring */ > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > + data->mode = THERMAL_DEVICE_DISABLED; > > > + > > > + return 0; > > > +} > > > + > > > +static int qoriq_tmu_resume(struct device *dev) { > > > + struct qoriq_tmu_data *data = dev_get_drvdata(dev); > > > + > > > + /* Enable monitoring */ > > > + iowrite32be(TMR_ALL, &data->regs->tmr); > > > + data->mode = THERMAL_DEVICE_ENABLED; > > > + > > > + return 0; > > > +} > > > +#endif > > > + > > > +static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops, > > > + qoriq_tmu_suspend, qoriq_tmu_resume); > > > + > > > +static const struct of_device_id qoriq_tmu_match[] = { > > > + { .compatible = "fsl,qoriq-tmu", }, > > > + {}, > > > +}; > > > + > > > +static struct platform_driver qoriq_tmu = { > > > + .driver = { > > > + .owner = THIS_MODULE, > > > + .name = "qoriq_thermal", > > > + .pm = &qoriq_tmu_pm_ops, > > > + .of_match_table = qoriq_tmu_match, > > > + }, > > > + .probe = qoriq_tmu_probe, > > > + .remove = qoriq_tmu_remove, > > > +}; > > > +module_platform_driver(qoriq_tmu); > > > + > > > +MODULE_AUTHOR("Jia Hongtao <hongtao.jia@freescale.com>"); > > > +MODULE_DESCRIPTION("Freescale QorIQ Thermal Monitoring Unit driver"); > > > +MODULE_LICENSE("GPL v2"); > > > -- > > > 2.1.0.27.g96db324 > > > [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 490 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH V2] QorIQ/TMU: add thermal management support based on TMU 2015-08-05 19:42 ` Eduardo Valentin @ 2015-08-07 8:14 ` Hongtao Jia 2015-08-14 3:15 ` Hongtao Jia 0 siblings, 1 reply; 8+ messages in thread From: Hongtao Jia @ 2015-08-07 8:14 UTC (permalink / raw) To: Eduardo Valentin Cc: linux-pm@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Scott Wood Thanks for your comments. Please see my questions inline. Thanks. --- Best Regards, Hongtao > -----Original Message----- > From: Eduardo Valentin [mailto:edubezval@gmail.com] > Sent: Thursday, August 06, 2015 3:43 AM > To: Jia Hongtao-B38951 > Cc: linux-pm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood Scott- > B07421 > Subject: Re: [PATCH V2] QorIQ/TMU: add thermal management support based > on TMU >=20 > On Thu, Jul 30, 2015 at 08:13:09AM +0000, Hongtao Jia wrote: > > - "Any specific reason why not using OF thermal?" > > - No, actually. > > > > I'd like to use OF thermal after some clarification. > > > > Regarding to "cooling-maps". For some cases there should be more than > > one cpus as cooling device and they are independent. > > 1. Let's say 4. So we need to provide 4 maps like map0-map3. Right? >=20 > That would depend on the amount of sensors you have. Do you have one > sensor per cpu? if the answer is yes, then you probably want to have four > different map entries, yes, but one on each thermal zone of each cpu > temperature sensor. if the answer is no, then you would need to have all > the maps in the same thermal zone. >=20 > > 2. "cooling-max-level" may vary depend on switch settings or firmware. > Is that > > OK if I do not provide "cooling-min-level" and "cooling-max-level" > property? >=20 > That is already achievable by using the cooling-device property of a > cooling map. >=20 > Please have a look in the example section of the > Documentation/devicetree/bindings/thermal/thermal.txt Yes, I read this file. So in my understanding: There is no need to provide "cooling-min-level" and "cooling-max-level" pro= perty. THERMAL_NO_LIMIT value in cooling device node will indicate the driver to automatically parse the min and max state, right? Talking about THERMAL_NO_LIMIT, I need to #include <dt-bindings/thermal/the= rmal.h> to provide the definition. But I got compiling error when build dtb file. I did some research and using "make t1040qds.dtb" in order to involve prepr= ocessor. But with simply adding "#include <dt-bindings/thermal/thermal.h>" to t1040s= i-post.dtsi at line 35 I still got error like this: Error: arch/powerpc/boot/dts/fsl/t1040si-post.dtsi:35.1-9 syntax error FATAL ERROR: Unable to parse input tree Could you help me out here. Thanks. >=20 > Let me know if you need further clarification. >=20 >=20 > BR, >=20 > Eduardo Valentin >=20 > > > > Thanks. > > -Hongtao > > > > > > > -----Original Message----- > > > From: Eduardo Valentin [mailto:edubezval@gmail.com] > > > Sent: Thursday, July 30, 2015 2:56 PM > > > To: Jia Hongtao-B38951 > > > Cc: linux-pm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood > > > Scott- > > > B07421 > > > Subject: Re: [PATCH V2] QorIQ/TMU: add thermal management support > > > based on TMU > > > > > > On Wed, Jul 29, 2015 at 02:19:39PM +0800, Jia Hongtao wrote: > > > > It supports one critical trip point and one passive trip point. > > > > The cpufreq is used as the cooling device to throttle CPUs when > > > > the passive trip is crossed. > > > > > > > > Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com> > > > > --- > > > > This patch based on: > > > > http://patchwork.ozlabs.org/patch/482987/ > > > > > > > > Changes for V2: > > > > * Add tmu-range parse. > > > > * Use default trend hook. > > > > * Using latest thermal_zone_bind_cooling_device API. > > > > * Add calibration check during initialization. > > > > * Disable/enalbe device when suspend/resume. > > > > > > > > drivers/thermal/Kconfig | 11 ++ > > > > drivers/thermal/Makefile | 1 + > > > > drivers/thermal/qoriq_thermal.c | 406 > > > > ++++++++++++++++++++++++++++++++++++++++ > > > > 3 files changed, 418 insertions(+) create mode 100644 > > > > drivers/thermal/qoriq_thermal.c > > > > > > > > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig > > > > index > > > > 118938e..a200745 100644 > > > > --- a/drivers/thermal/Kconfig > > > > +++ b/drivers/thermal/Kconfig > > > > @@ -180,6 +180,17 @@ config IMX_THERMAL > > > > cpufreq is used as the cooling device to throttle CPUs when > the > > > > passive trip is crossed. > > > > > > > > +config QORIQ_THERMAL > > > > + tristate "Freescale QorIQ Thermal Monitoring Unit" > > > > + depends on CPU_THERMAL > > > > + depends on OF > > > > + default n > > > > + help > > > > + Enable thermal management based on Freescale QorIQ Thermal > > > Monitoring > > > > + Unit (TMU). It supports one critical trip point and one > > > > +passive > > > trip > > > > + point. The cpufreq is used as the cooling device to > throttle > > > > +CPUs > > > when > > > > + the passive trip is crossed. > > > > + > > > > config SPEAR_THERMAL > > > > bool "SPEAr thermal sensor driver" > > > > depends on PLAT_SPEAR > > > > diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile > > > > index > > > > 535dfee..8c25859 100644 > > > > --- a/drivers/thermal/Makefile > > > > +++ b/drivers/thermal/Makefile > > > > @@ -33,6 +33,7 @@ obj-$(CONFIG_DOVE_THERMAL) +=3D dove_thermal.o > > > > obj-$(CONFIG_DB8500_THERMAL) +=3D db8500_thermal.o > > > > obj-$(CONFIG_ARMADA_THERMAL) +=3D armada_thermal.o > > > > obj-$(CONFIG_IMX_THERMAL) +=3D imx_thermal.o > > > > +obj-$(CONFIG_QORIQ_THERMAL) +=3D qoriq_thermal.o > > > > obj-$(CONFIG_DB8500_CPUFREQ_COOLING) +=3D > db8500_cpufreq_cooling.o > > > > obj-$(CONFIG_INTEL_POWERCLAMP) +=3D intel_powerclamp.o > > > > obj-$(CONFIG_X86_PKG_TEMP_THERMAL) +=3D x86_pkg_temp_thermal.o > > > > diff --git a/drivers/thermal/qoriq_thermal.c > > > > b/drivers/thermal/qoriq_thermal.c new file mode 100644 index > > > > 0000000..0694f42 > > > > --- /dev/null > > > > +++ b/drivers/thermal/qoriq_thermal.c > > > > @@ -0,0 +1,406 @@ > > > > +/* > > > > + * Copyright 2015 Freescale Semiconductor, Inc. > > > > + * > > > > + * 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. > > > > + * > > > > + * This program is distributed in the hope 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. > > > > + * > > > > + */ > > > > + > > > > +/* > > > > + * Based on Freescale QorIQ Thermal Monitoring Unit (TMU) */ > > > > +#include <linux/cpufreq.h> #include <linux/cpu_cooling.h> > > > > +#include <linux/module.h> #include <linux/platform_device.h> > > > > +#include <linux/err.h> #include <linux/io.h> #include > > > > +<linux/of.h> #include <linux/of_address.h> #include > > > > +<linux/thermal.h> > > > > + > > > > +#define SITES_MAX 16 > > > > + > > > > +#define TMU_TEMP_PASSIVE 85000 > > > > +#define TMU_TEMP_CRITICAL 95000 > > > > + > > > > +#define TMU_PASSIVE_DELAY 1000 /* Milliseconds */ > > > > +#define TMU_POLLING_DELAY 5000 > > > > + > > > > +/* The driver supports 1 passive trip point and 1 critical trip > > > > +point */ enum tmu_thermal_trip { > > > > + TMU_TRIP_PASSIVE, > > > > + TMU_TRIP_CRITICAL, > > > > + TMU_TRIP_NUM, > > > > +}; > > > > + > > > > +/* > > > > + * QorIQ TMU Registers > > > > + */ > > > > +struct qoriq_tmu_site_regs { > > > > + __be32 tritsr; /* Immediate Temperature Site > Register */ > > > > + __be32 tratsr; /* Average Temperature Site Register > */ > > > > + u8 res0[0x8]; > > > > +} __packed; > > > > + > > > > +struct qoriq_tmu_regs { > > > > + __be32 tmr; /* Mode Register */ > > > > +#define TMR_DISABLE 0x0 > > > > +#define TMR_ME 0x80000000 > > > > +#define TMR_ALPF 0x0c000000 > > > > +#define TMR_MSITE 0x00008000 > > > > +#define TMR_ALL (TMR_ME | TMR_ALPF | TMR_MSITE) > > > > + __be32 tsr; /* Status Register */ > > > > + __be32 tmtmir; /* Temperature measurement interval > > > Register */ > > > > +#define TMTMIR_DEFAULT 0x00000007 > > > > + u8 res0[0x14]; > > > > + __be32 tier; /* Interrupt Enable Register */ > > > > +#define TIER_DISABLE 0x0 > > > > + __be32 tidr; /* Interrupt Detect Register */ > > > > + __be32 tiscr; /* Interrupt Site Capture Register */ > > > > + __be32 ticscr; /* Interrupt Critical Site Capture > Register > > > */ > > > > + u8 res1[0x10]; > > > > + __be32 tmhtcrh; /* High Temperature Capture Register > */ > > > > + __be32 tmhtcrl; /* Low Temperature Capture Register > */ > > > > + u8 res2[0x8]; > > > > + __be32 tmhtitr; /* High Temperature Immediate > Threshold */ > > > > + __be32 tmhtatr; /* High Temperature Average Threshold > */ > > > > + __be32 tmhtactr; /* High Temperature Average Crit Threshold > */ > > > > + u8 res3[0x24]; > > > > + __be32 ttcfgr; /* Temperature Configuration Register > */ > > > > + __be32 tscfgr; /* Sensor Configuration Register */ > > > > + u8 res4[0x78]; > > > > + struct qoriq_tmu_site_regs site[SITES_MAX]; > > > > + u8 res5[0x9f8]; > > > > + __be32 ipbrr0; /* IP Block Revision Register 0 */ > > > > + __be32 ipbrr1; /* IP Block Revision Register 1 */ > > > > + u8 res6[0x310]; > > > > + __be32 ttr0cr; /* Temperature Range 0 Control > Register */ > > > > + __be32 ttr1cr; /* Temperature Range 1 Control > Register */ > > > > + __be32 ttr2cr; /* Temperature Range 2 Control > Register */ > > > > + __be32 ttr3cr; /* Temperature Range 3 Control > Register */ > > > > +}; > > > > + > > > > +/* > > > > + * Thermal zone data > > > > + */ > > > > +struct qoriq_tmu_data { > > > > + struct thermal_zone_device *tz; > > > > + struct thermal_cooling_device *cdev; > > > > + enum thermal_device_mode mode; > > > > + unsigned long temp_passive; > > > > + unsigned long temp_critical; > > > > + struct qoriq_tmu_regs __iomem *regs; }; > > > > + > > > > +static int tmu_get_mode(struct thermal_zone_device *tz, > > > > + enum thermal_device_mode *mode) { > > > > + struct qoriq_tmu_data *data =3D tz->devdata; > > > > + > > > > + *mode =3D data->mode; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int tmu_set_mode(struct thermal_zone_device *tz, > > > > + enum thermal_device_mode mode) { > > > > + struct qoriq_tmu_data *data =3D tz->devdata; > > > > + > > > > + if (mode =3D=3D THERMAL_DEVICE_ENABLED) { > > > > + tz->polling_delay =3D TMU_POLLING_DELAY; > > > > + tz->passive_delay =3D TMU_PASSIVE_DELAY; > > > > + thermal_zone_device_update(tz); > > > > + } else { > > > > + tz->polling_delay =3D 0; > > > > + tz->passive_delay =3D 0; > > > > + } > > > > + > > > > + data->mode =3D mode; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int tmu_get_temp(struct thermal_zone_device *tz, unsigned > > > > +long > > > > +*temp) { > > > > + u8 val; > > > > + struct qoriq_tmu_data *data =3D tz->devdata; > > > > + > > > > + val =3D ioread32be(&data->regs->site[0].tritsr); > > > > + *temp =3D (unsigned long)val * 1000; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int tmu_get_trip_type(struct thermal_zone_device *tz, int > trip, > > > > + enum thermal_trip_type *type) { > > > > + *type =3D (trip =3D=3D TMU_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE : > > > > + THERMAL_TRIP_CRITICAL; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int tmu_get_trip_temp(struct thermal_zone_device *tz, int > trip, > > > > + unsigned long *temp) > > > > +{ > > > > + struct qoriq_tmu_data *data =3D tz->devdata; > > > > + > > > > + *temp =3D (trip =3D=3D TMU_TRIP_PASSIVE) ? data->temp_passive : > > > > + data->temp_critical; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int tmu_get_crit_temp(struct thermal_zone_device *tz, > > > > + unsigned long *temp) > > > > +{ > > > > + struct qoriq_tmu_data *data =3D tz->devdata; > > > > + > > > > + *temp =3D data->temp_critical; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int tmu_bind(struct thermal_zone_device *tz, > > > > + struct thermal_cooling_device *cdev) { > > > > + int ret; > > > > + > > > > + ret =3D thermal_zone_bind_cooling_device(tz, TMU_TRIP_PASSIVE, > cdev, > > > > + THERMAL_NO_LIMIT, > > > > + THERMAL_NO_LIMIT, > > > > + THERMAL_WEIGHT_DEFAULT); > > > > + if (ret) { > > > > + dev_err(&tz->device, > > > > + "Binding zone %s with cdev %s failed:%d\n", > > > > + tz->type, cdev->type, ret); > > > > + } > > > > + > > > > + return ret; > > > > +} > > > > + > > > > +static int tmu_unbind(struct thermal_zone_device *tz, > > > > + struct thermal_cooling_device *cdev) { > > > > + int ret; > > > > + > > > > + ret =3D thermal_zone_unbind_cooling_device(tz, TMU_TRIP_PASSIVE, > > > cdev); > > > > + if (ret) { > > > > + dev_err(&tz->device, > > > > + "Unbinding zone %s with cdev %s failed:%d\n", > > > > + tz->type, cdev->type, ret); > > > > + } > > > > + > > > > + return ret; > > > > +} > > > > + > > > > +static int qoriq_tmu_calibration(struct platform_device *pdev) { > > > > + int i, val, len; > > > > + u32 range[4]; > > > > + const __be32 *calibration; > > > > + struct device_node *node =3D pdev->dev.of_node; > > > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(&pdev->dev); > > > > + > > > > + /* Disable monitoring before calibration */ > > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > > + > > > > + if (of_property_read_u32_array(node, "fsl,tmu-range", range, > 4)) > > > > + return -1; > > > > + > > > > + /* Init temperature range registers */ > > > > + iowrite32be(range[0], &data->regs->ttr0cr); > > > > + iowrite32be(range[1], &data->regs->ttr1cr); > > > > + iowrite32be(range[2], &data->regs->ttr2cr); > > > > + iowrite32be(range[3], &data->regs->ttr3cr); > > > > + > > > > + calibration =3D of_get_property(node, "fsl,tmu-calibration", > &len); > > > > + if (calibration =3D=3D NULL) > > > > + return -1; > > > > + > > > > + for (i =3D 0; i < len; i +=3D 8, calibration +=3D 2) { > > > > + val =3D (int)of_read_number(calibration, 1); > > > > + iowrite32be(val, &data->regs->ttcfgr); > > > > + val =3D (int)of_read_number(calibration + 1, 1); > > > > + iowrite32be(val, &data->regs->tscfgr); > > > > + } > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) { > > > > + /* Disable interrupt, using polling instead */ > > > > + iowrite32be(TIER_DISABLE, &data->regs->tier); > > > > + > > > > + /* Set update_interval */ > > > > + iowrite32be(TMTMIR_DEFAULT, &data->regs->tmtmir); > > > > + > > > > + /* Enable monitoring */ > > > > + iowrite32be(TMR_ALL, &data->regs->tmr); } > > > > + > > > > +static struct thermal_zone_device_ops tmu_tz_ops =3D { > > > > + .bind =3D tmu_bind, > > > > + .unbind =3D tmu_unbind, > > > > + .get_temp =3D tmu_get_temp, > > > > + .get_mode =3D tmu_get_mode, > > > > + .set_mode =3D tmu_set_mode, > > > > + .get_trip_type =3D tmu_get_trip_type, > > > > + .get_trip_temp =3D tmu_get_trip_temp, > > > > + .get_crit_temp =3D tmu_get_crit_temp, }; > > > > + > > > > +static int qoriq_tmu_probe(struct platform_device *pdev) { > > > > + int ret; > > > > + struct cpumask clip_cpus; > > > > + struct qoriq_tmu_data *data; > > > > + > > > > + if (!cpufreq_get_current_driver()) { > > > > + dev_dbg(&pdev->dev, "No cpufreq driver yet\n"); > > > > + return -EPROBE_DEFER; > > > > + } > > > > + > > > > + if (!pdev->dev.of_node) { > > > > + dev_err(&pdev->dev, "Device OF-Node is NULL"); > > > > + return -EFAULT; > > > > + } > > > > + > > > > + data =3D devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data), > > > > + GFP_KERNEL); > > > > + if (!data) > > > > + return -ENOMEM; > > > > + > > > > + dev_set_drvdata(&pdev->dev, data); > > > > + data->regs =3D of_iomap(pdev->dev.of_node, 0); > > > > + > > > > + if (!data->regs) { > > > > + dev_err(&pdev->dev, "Failed to get memory region\n"); > > > > + ret =3D -ENODEV; > > > > + goto err_iomap; > > > > + } > > > > + > > > > + ret =3D qoriq_tmu_calibration(pdev); /* TMU calibration */ > > > > + if (ret < 0) { > > > > + dev_err(&pdev->dev, "TMU calibration failed.\n"); > > > > + ret =3D -ENODEV; > > > > + goto err_iomap; > > > > + } > > > > + > > > > + qoriq_tmu_init_device(data); /* TMU initialization */ > > > > + > > > > + cpumask_setall(&clip_cpus); > > > > + data->cdev =3D cpufreq_cooling_register(&clip_cpus); > > > > + if (IS_ERR(data->cdev)) { > > > > + ret =3D PTR_ERR(data->cdev); > > > > + dev_err(&data->cdev->device, > > > > + "Failed to register cpufreq cooling device: %d\n", > ret); > > > > + goto err_cooling; > > > > + } > > > > + > > > > + data->temp_passive =3D TMU_TEMP_PASSIVE; > > > > + data->temp_critical =3D TMU_TEMP_CRITICAL; > > > > + data->tz =3D thermal_zone_device_register("tmu_thermal_zone", > > > > > > Any specific reason why not using OF thermal? > > > > > > > + TMU_TRIP_NUM, > > > > + 0, data, > > > > + &tmu_tz_ops, NULL, > > > > + TMU_PASSIVE_DELAY, > > > > + TMU_POLLING_DELAY); > > > > + > > > > + if (IS_ERR(data->tz)) { > > > > + ret =3D PTR_ERR(data->tz); > > > > + dev_err(&pdev->dev, > > > > + "Failed to register thermal zone device %d\n", > ret); > > > > + goto err_thermal; > > > > + } > > > > + > > > > + data->mode =3D THERMAL_DEVICE_ENABLED; > > > > + > > > > + return 0; > > > > + > > > > +err_thermal: > > > > + cpufreq_cooling_unregister(data->cdev); > > > > + > > > > +err_cooling: > > > > + iounmap(data->regs); > > > > + > > > > +err_iomap: > > > > + dev_set_drvdata(&pdev->dev, NULL); > > > > + devm_kfree(&pdev->dev, data); > > > > + > > > > + return ret; > > > > +} > > > > + > > > > +static int qoriq_tmu_remove(struct platform_device *pdev) { > > > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(&pdev->dev); > > > > + > > > > + /* Disable monitoring */ > > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > > + > > > > + thermal_zone_device_unregister(data->tz); > > > > + cpufreq_cooling_unregister(data->cdev); > > > > + iounmap(data->regs); > > > > + > > > > + dev_set_drvdata(&pdev->dev, NULL); > > > > + devm_kfree(&pdev->dev, data); > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +#ifdef CONFIG_PM_SLEEP > > > > +static int qoriq_tmu_suspend(struct device *dev) { > > > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(dev); > > > > + > > > > + /* Disable monitoring */ > > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > > + data->mode =3D THERMAL_DEVICE_DISABLED; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int qoriq_tmu_resume(struct device *dev) { > > > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(dev); > > > > + > > > > + /* Enable monitoring */ > > > > + iowrite32be(TMR_ALL, &data->regs->tmr); > > > > + data->mode =3D THERMAL_DEVICE_ENABLED; > > > > + > > > > + return 0; > > > > +} > > > > +#endif > > > > + > > > > +static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops, > > > > + qoriq_tmu_suspend, qoriq_tmu_resume); > > > > + > > > > +static const struct of_device_id qoriq_tmu_match[] =3D { > > > > + { .compatible =3D "fsl,qoriq-tmu", }, > > > > + {}, > > > > +}; > > > > + > > > > +static struct platform_driver qoriq_tmu =3D { > > > > + .driver =3D { > > > > + .owner =3D THIS_MODULE, > > > > + .name =3D "qoriq_thermal", > > > > + .pm =3D &qoriq_tmu_pm_ops, > > > > + .of_match_table =3D qoriq_tmu_match, > > > > + }, > > > > + .probe =3D qoriq_tmu_probe, > > > > + .remove =3D qoriq_tmu_remove, > > > > +}; > > > > +module_platform_driver(qoriq_tmu); > > > > + > > > > +MODULE_AUTHOR("Jia Hongtao <hongtao.jia@freescale.com>"); > > > > +MODULE_DESCRIPTION("Freescale QorIQ Thermal Monitoring Unit > > > > +driver"); MODULE_LICENSE("GPL v2"); > > > > -- > > > > 2.1.0.27.g96db324 > > > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH V2] QorIQ/TMU: add thermal management support based on TMU 2015-08-07 8:14 ` Hongtao Jia @ 2015-08-14 3:15 ` Hongtao Jia 2015-08-14 4:29 ` Eduardo Valentin 0 siblings, 1 reply; 8+ messages in thread From: Hongtao Jia @ 2015-08-14 3:15 UTC (permalink / raw) To: Eduardo Valentin Cc: Scott Wood, linuxppc-dev@lists.ozlabs.org, linux-pm@vger.kernel.org, Hongtao Jia SGkgRWR1YXJkbywNCg0KSW4gcHJldmlvdXMgbWFpbCBJIGFza2VkIHF1ZXN0aW9ucyBhYm91dCBp bmNsdWRpbmcgaGVhZGVyIGZpbGVzIGluIGRldmljZSB0cmVlLg0KRG9uJ3QgYm90aGVyLCBJIGhh dmUgYWxyZWFkeSBmaWd1cmVkIG91dCB0aGUgc29sdXRpb24uDQoNCkFub3RoZXIgcXVlc3Rpb25z IGlzIGFib3V0IGNwdSBjb29saW5nOg0KSSBmb3VuZCBvdXQgdGhhdCB0aGVyZSBpcyBubyBleHBs aWNpdCBjYWxsaW5nIGZvciByZWdpc3RlcmluZyBjcHUgY29vbGluZw0KZGV2aWNlIGluIHRoZSBv Zi10aGVybWFsIHN0eWxlIGRyaXZlcnMuDQoNCkFuZCBTYW1zdW5nIGRpZCBpdCBpbiBjcHVmcmVx IGRyaXZlcjogZHJpdmVycy9jcHVmcmVxL2V4eW5vcy1jcHVmcmVxLmMNCg0KU2hvdWxkIGFsbCB0 aGUgb2YtdGhlcm1hbCBkcml2ZXIgdXNlIHRoZSBzYW1lIHdheT8NCk9yIGlzIHRoZXJlIGFueSBy ZWNvbW1lbmRhdGlvbiBmb3IgcmVnaXN0ZXJpbmcgY3B1IGNvb2xpbmcgZGV2aWNlPw0KKEkgZW5h YmxlZCB0aGUgQ09ORklHX0NQVUZSRVFfRFQgYW5kIHN0aWxsIGdvdCBubyBjb29saW5nIGRldmlj ZSByZWdpc3RlcmVkKQ0KDQpUaGFua3MuDQoNCi0tLQ0KQmVzdCBSZWdhcmRzLA0KSG9uZ3Rhbw0K DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogTGludXhwcGMtZGV2IFtt YWlsdG86bGludXhwcGMtZGV2LQ0KPiBib3VuY2VzK2IzODk1MT1mcmVlc2NhbGUuY29tQGxpc3Rz Lm96bGFicy5vcmddIE9uIEJlaGFsZiBPZiBIb25ndGFvIEppYQ0KPiBTZW50OiBGcmlkYXksIEF1 Z3VzdCAwNywgMjAxNSA0OjE1IFBNDQo+IFRvOiBFZHVhcmRvIFZhbGVudGluDQo+IENjOiBXb29k IFNjb3R0LUIwNzQyMTsgbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmc7IGxpbnV4LQ0KPiBw bUB2Z2VyLmtlcm5lbC5vcmcNCj4gU3ViamVjdDogUkU6IFtQQVRDSCBWMl0gUW9ySVEvVE1VOiBh ZGQgdGhlcm1hbCBtYW5hZ2VtZW50IHN1cHBvcnQgYmFzZWQNCj4gb24gVE1VDQo+IA0KPiBUaGFu a3MgZm9yIHlvdXIgY29tbWVudHMuDQo+IFBsZWFzZSBzZWUgbXkgcXVlc3Rpb25zIGlubGluZS4N Cj4gDQo+IFRoYW5rcy4NCj4gLS0tDQo+IEJlc3QgUmVnYXJkcywNCj4gSG9uZ3Rhbw0KPiANCj4g DQo+ID4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiBGcm9tOiBFZHVhcmRvIFZhbGVu dGluIFttYWlsdG86ZWR1YmV6dmFsQGdtYWlsLmNvbV0NCj4gPiBTZW50OiBUaHVyc2RheSwgQXVn dXN0IDA2LCAyMDE1IDM6NDMgQU0NCj4gPiBUbzogSmlhIEhvbmd0YW8tQjM4OTUxDQo+ID4gQ2M6 IGxpbnV4LXBtQHZnZXIua2VybmVsLm9yZzsgbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmc7 IFdvb2QNCj4gPiBTY290dC0NCj4gPiBCMDc0MjENCj4gPiBTdWJqZWN0OiBSZTogW1BBVENIIFYy XSBRb3JJUS9UTVU6IGFkZCB0aGVybWFsIG1hbmFnZW1lbnQgc3VwcG9ydA0KPiA+IGJhc2VkIG9u IFRNVQ0KPiA+DQo+ID4gT24gVGh1LCBKdWwgMzAsIDIwMTUgYXQgMDg6MTM6MDlBTSArMDAwMCwg SG9uZ3RhbyBKaWEgd3JvdGU6DQo+ID4gPiAtICJBbnkgc3BlY2lmaWMgcmVhc29uIHdoeSBub3Qg dXNpbmcgT0YgdGhlcm1hbD8iDQo+ID4gPiAtIE5vLCBhY3R1YWxseS4NCj4gPiA+DQo+ID4gPiBJ J2QgbGlrZSB0byB1c2UgT0YgdGhlcm1hbCBhZnRlciBzb21lIGNsYXJpZmljYXRpb24uDQo+ID4g Pg0KPiA+ID4gUmVnYXJkaW5nIHRvICJjb29saW5nLW1hcHMiLiBGb3Igc29tZSBjYXNlcyB0aGVy ZSBzaG91bGQgYmUgbW9yZQ0KPiA+ID4gdGhhbiBvbmUgY3B1cyBhcyBjb29saW5nIGRldmljZSBh bmQgdGhleSBhcmUgaW5kZXBlbmRlbnQuDQo+ID4gPiAxLiBMZXQncyBzYXkgNC4gU28gd2UgbmVl ZCB0byBwcm92aWRlIDQgbWFwcyBsaWtlIG1hcDAtbWFwMy4gUmlnaHQ/DQo+ID4NCj4gPiBUaGF0 IHdvdWxkIGRlcGVuZCBvbiB0aGUgYW1vdW50IG9mIHNlbnNvcnMgeW91IGhhdmUuIERvIHlvdSBo YXZlIG9uZQ0KPiA+IHNlbnNvciBwZXIgY3B1PyBpZiB0aGUgYW5zd2VyIGlzIHllcywgdGhlbiB5 b3UgcHJvYmFibHkgd2FudCB0byBoYXZlDQo+ID4gZm91ciBkaWZmZXJlbnQgbWFwIGVudHJpZXMs IHllcywgYnV0IG9uZSBvbiBlYWNoIHRoZXJtYWwgem9uZSBvZiBlYWNoDQo+ID4gY3B1IHRlbXBl cmF0dXJlIHNlbnNvci4gaWYgdGhlIGFuc3dlciBpcyBubywgdGhlbiB5b3Ugd291bGQgbmVlZCB0 bw0KPiA+IGhhdmUgYWxsIHRoZSBtYXBzIGluIHRoZSBzYW1lIHRoZXJtYWwgem9uZS4NCj4gPg0K PiA+ID4gMi4gImNvb2xpbmctbWF4LWxldmVsIiBtYXkgdmFyeSBkZXBlbmQgb24gc3dpdGNoIHNl dHRpbmdzIG9yIGZpcm13YXJlLg0KPiA+IElzIHRoYXQNCj4gPiA+ICAgIE9LIGlmIEkgZG8gbm90 IHByb3ZpZGUgImNvb2xpbmctbWluLWxldmVsIiBhbmQgImNvb2xpbmctbWF4LWxldmVsIg0KPiA+ IHByb3BlcnR5Pw0KPiA+DQo+ID4gVGhhdCBpcyBhbHJlYWR5IGFjaGlldmFibGUgYnkgdXNpbmcg dGhlIGNvb2xpbmctZGV2aWNlIHByb3BlcnR5IG9mIGENCj4gPiBjb29saW5nIG1hcC4NCj4gPg0K PiA+IFBsZWFzZSBoYXZlIGEgbG9vayBpbiB0aGUgZXhhbXBsZSBzZWN0aW9uIG9mIHRoZQ0KPiA+ IERvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy90aGVybWFsL3RoZXJtYWwudHh0DQo+ IA0KPiBZZXMsIEkgcmVhZCB0aGlzIGZpbGUuDQo+IFNvIGluIG15IHVuZGVyc3RhbmRpbmc6DQo+ IFRoZXJlIGlzIG5vIG5lZWQgdG8gcHJvdmlkZSAiY29vbGluZy1taW4tbGV2ZWwiIGFuZCAiY29v bGluZy1tYXgtbGV2ZWwiDQo+IHByb3BlcnR5Lg0KPiBUSEVSTUFMX05PX0xJTUlUIHZhbHVlIGlu IGNvb2xpbmcgZGV2aWNlIG5vZGUgd2lsbCBpbmRpY2F0ZSB0aGUgZHJpdmVyIHRvDQo+IGF1dG9t YXRpY2FsbHkgcGFyc2UgdGhlIG1pbiBhbmQgbWF4IHN0YXRlLCByaWdodD8NCj4gDQo+IFRhbGtp bmcgYWJvdXQgVEhFUk1BTF9OT19MSU1JVCwgSSBuZWVkIHRvICNpbmNsdWRlIDxkdC0NCj4gYmlu ZGluZ3MvdGhlcm1hbC90aGVybWFsLmg+IHRvIHByb3ZpZGUgdGhlIGRlZmluaXRpb24uIEJ1dCBJ IGdvdA0KPiBjb21waWxpbmcgZXJyb3Igd2hlbiBidWlsZCBkdGIgZmlsZS4NCj4gSSBkaWQgc29t ZSByZXNlYXJjaCBhbmQgdXNpbmcgIm1ha2UgdDEwNDBxZHMuZHRiIiBpbiBvcmRlciB0byBpbnZv bHZlDQo+IHByZXByb2Nlc3Nvci4NCj4gQnV0IHdpdGggc2ltcGx5IGFkZGluZyAiI2luY2x1ZGUg PGR0LWJpbmRpbmdzL3RoZXJtYWwvdGhlcm1hbC5oPiIgdG8NCj4gdDEwNDBzaS1wb3N0LmR0c2kg YXQgbGluZSAzNSBJIHN0aWxsIGdvdCBlcnJvciBsaWtlIHRoaXM6DQo+IEVycm9yOiBhcmNoL3Bv d2VycGMvYm9vdC9kdHMvZnNsL3QxMDQwc2ktcG9zdC5kdHNpOjM1LjEtOSBzeW50YXggZXJyb3IN Cj4gRkFUQUwgRVJST1I6IFVuYWJsZSB0byBwYXJzZSBpbnB1dCB0cmVlDQo+IA0KPiBDb3VsZCB5 b3UgaGVscCBtZSBvdXQgaGVyZS4NCj4gVGhhbmtzLg0KPiANCj4gPg0KPiA+IExldCBtZSBrbm93 IGlmIHlvdSBuZWVkIGZ1cnRoZXIgY2xhcmlmaWNhdGlvbi4NCj4gPg0KPiA+DQo+ID4gQlIsDQo+ ID4NCj4gPiBFZHVhcmRvIFZhbGVudGluDQo+ID4NCj4gPiA+DQo+ID4gPiBUaGFua3MuDQo+ID4g PiAtSG9uZ3Rhbw0KPiA+ID4NCj4gPiA+DQo+ID4gPiA+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0t LS0tDQo+ID4gPiA+IEZyb206IEVkdWFyZG8gVmFsZW50aW4gW21haWx0bzplZHViZXp2YWxAZ21h aWwuY29tXQ0KPiA+ID4gPiBTZW50OiBUaHVyc2RheSwgSnVseSAzMCwgMjAxNSAyOjU2IFBNDQo+ ID4gPiA+IFRvOiBKaWEgSG9uZ3Rhby1CMzg5NTENCj4gPiA+ID4gQ2M6IGxpbnV4LXBtQHZnZXIu a2VybmVsLm9yZzsgbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmc7IFdvb2QNCj4gPiA+ID4g U2NvdHQtDQo+ID4gPiA+IEIwNzQyMQ0KPiA+ID4gPiBTdWJqZWN0OiBSZTogW1BBVENIIFYyXSBR b3JJUS9UTVU6IGFkZCB0aGVybWFsIG1hbmFnZW1lbnQgc3VwcG9ydA0KPiA+ID4gPiBiYXNlZCBv biBUTVUNCj4gPiA+ID4NCj4gPiA+ID4gT24gV2VkLCBKdWwgMjksIDIwMTUgYXQgMDI6MTk6MzlQ TSArMDgwMCwgSmlhIEhvbmd0YW8gd3JvdGU6DQo+ID4gPiA+ID4gSXQgc3VwcG9ydHMgb25lIGNy aXRpY2FsIHRyaXAgcG9pbnQgYW5kIG9uZSBwYXNzaXZlIHRyaXAgcG9pbnQuDQo+ID4gPiA+ID4g VGhlIGNwdWZyZXEgaXMgdXNlZCBhcyB0aGUgY29vbGluZyBkZXZpY2UgdG8gdGhyb3R0bGUgQ1BV cyB3aGVuDQo+ID4gPiA+ID4gdGhlIHBhc3NpdmUgdHJpcCBpcyBjcm9zc2VkLg0KPiA+ID4gPiA+ DQo+ID4gPiA+ID4gU2lnbmVkLW9mZi1ieTogSmlhIEhvbmd0YW8gPGhvbmd0YW8uamlhQGZyZWVz Y2FsZS5jb20+DQo+ID4gPiA+ID4gLS0tDQo+ID4gPiA+ID4gVGhpcyBwYXRjaCBiYXNlZCBvbjoN Cj4gPiA+ID4gPiBodHRwOi8vcGF0Y2h3b3JrLm96bGFicy5vcmcvcGF0Y2gvNDgyOTg3Lw0KPiA+ ID4gPiA+DQo+ID4gPiA+ID4gQ2hhbmdlcyBmb3IgVjI6DQo+ID4gPiA+ID4gKiBBZGQgdG11LXJh bmdlIHBhcnNlLg0KPiA+ID4gPiA+ICogVXNlIGRlZmF1bHQgdHJlbmQgaG9vay4NCj4gPiA+ID4g PiAqIFVzaW5nIGxhdGVzdCB0aGVybWFsX3pvbmVfYmluZF9jb29saW5nX2RldmljZSBBUEkuDQo+ ID4gPiA+ID4gKiBBZGQgY2FsaWJyYXRpb24gY2hlY2sgZHVyaW5nIGluaXRpYWxpemF0aW9uLg0K PiA+ID4gPiA+ICogRGlzYWJsZS9lbmFsYmUgZGV2aWNlIHdoZW4gc3VzcGVuZC9yZXN1bWUuDQo+ ID4gPiA+ID4NCj4gPiA+ID4gPiAgZHJpdmVycy90aGVybWFsL0tjb25maWcgICAgICAgICB8ICAx MSArKw0KPiA+ID4gPiA+ICBkcml2ZXJzL3RoZXJtYWwvTWFrZWZpbGUgICAgICAgIHwgICAxICsN Cj4gPiA+ID4gPiAgZHJpdmVycy90aGVybWFsL3FvcmlxX3RoZXJtYWwuYyB8IDQwNg0KPiA+ID4g PiA+ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysNCj4gPiA+ID4gPiAg MyBmaWxlcyBjaGFuZ2VkLCA0MTggaW5zZXJ0aW9ucygrKSAgY3JlYXRlIG1vZGUgMTAwNjQ0DQo+ ID4gPiA+ID4gZHJpdmVycy90aGVybWFsL3FvcmlxX3RoZXJtYWwuYw0KPiA+ID4gPiA+DQo+ID4g PiA+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdGhlcm1hbC9LY29uZmlnIGIvZHJpdmVycy90aGVy bWFsL0tjb25maWcNCj4gPiA+ID4gPiBpbmRleA0KPiA+ID4gPiA+IDExODkzOGUuLmEyMDA3NDUg MTAwNjQ0DQo+ID4gPiA+ID4gLS0tIGEvZHJpdmVycy90aGVybWFsL0tjb25maWcNCj4gPiA+ID4g PiArKysgYi9kcml2ZXJzL3RoZXJtYWwvS2NvbmZpZw0KPiA+ID4gPiA+IEBAIC0xODAsNiArMTgw LDE3IEBAIGNvbmZpZyBJTVhfVEhFUk1BTA0KPiA+ID4gPiA+ICAJICBjcHVmcmVxIGlzIHVzZWQg YXMgdGhlIGNvb2xpbmcgZGV2aWNlIHRvIHRocm90dGxlIENQVXMgd2hlbg0KPiA+IHRoZQ0KPiA+ ID4gPiA+ICAJICBwYXNzaXZlIHRyaXAgaXMgY3Jvc3NlZC4NCj4gPiA+ID4gPg0KPiA+ID4gPiA+ ICtjb25maWcgUU9SSVFfVEhFUk1BTA0KPiA+ID4gPiA+ICsJdHJpc3RhdGUgIkZyZWVzY2FsZSBR b3JJUSBUaGVybWFsIE1vbml0b3JpbmcgVW5pdCINCj4gPiA+ID4gPiArCWRlcGVuZHMgb24gQ1BV X1RIRVJNQUwNCj4gPiA+ID4gPiArCWRlcGVuZHMgb24gT0YNCj4gPiA+ID4gPiArCWRlZmF1bHQg bg0KPiA+ID4gPiA+ICsJaGVscA0KPiA+ID4gPiA+ICsJICBFbmFibGUgdGhlcm1hbCBtYW5hZ2Vt ZW50IGJhc2VkIG9uIEZyZWVzY2FsZSBRb3JJUSBUaGVybWFsDQo+ID4gPiA+IE1vbml0b3JpbmcN Cj4gPiA+ID4gPiArCSAgVW5pdCAoVE1VKS4gSXQgc3VwcG9ydHMgb25lIGNyaXRpY2FsIHRyaXAg cG9pbnQgYW5kIG9uZQ0KPiA+ID4gPiA+ICtwYXNzaXZlDQo+ID4gPiA+IHRyaXANCj4gPiA+ID4g PiArCSAgcG9pbnQuIFRoZSBjcHVmcmVxIGlzIHVzZWQgYXMgdGhlIGNvb2xpbmcgZGV2aWNlIHRv DQo+ID4gdGhyb3R0bGUNCj4gPiA+ID4gPiArQ1BVcw0KPiA+ID4gPiB3aGVuDQo+ID4gPiA+ID4g KwkgIHRoZSBwYXNzaXZlIHRyaXAgaXMgY3Jvc3NlZC4NCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4g IGNvbmZpZyBTUEVBUl9USEVSTUFMDQo+ID4gPiA+ID4gIAlib29sICJTUEVBciB0aGVybWFsIHNl bnNvciBkcml2ZXIiDQo+ID4gPiA+ID4gIAlkZXBlbmRzIG9uIFBMQVRfU1BFQVINCj4gPiA+ID4g PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy90aGVybWFsL01ha2VmaWxlIGIvZHJpdmVycy90aGVybWFs L01ha2VmaWxlDQo+ID4gPiA+ID4gaW5kZXgNCj4gPiA+ID4gPiA1MzVkZmVlLi44YzI1ODU5IDEw MDY0NA0KPiA+ID4gPiA+IC0tLSBhL2RyaXZlcnMvdGhlcm1hbC9NYWtlZmlsZQ0KPiA+ID4gPiA+ ICsrKyBiL2RyaXZlcnMvdGhlcm1hbC9NYWtlZmlsZQ0KPiA+ID4gPiA+IEBAIC0zMyw2ICszMyw3 IEBAIG9iai0kKENPTkZJR19ET1ZFX1RIRVJNQUwpICAJKz0NCj4gZG92ZV90aGVybWFsLm8NCj4g PiA+ID4gPiAgb2JqLSQoQ09ORklHX0RCODUwMF9USEVSTUFMKQkrPSBkYjg1MDBfdGhlcm1hbC5v DQo+ID4gPiA+ID4gIG9iai0kKENPTkZJR19BUk1BREFfVEhFUk1BTCkJKz0gYXJtYWRhX3RoZXJt YWwubw0KPiA+ID4gPiA+ICBvYmotJChDT05GSUdfSU1YX1RIRVJNQUwpCSs9IGlteF90aGVybWFs Lm8NCj4gPiA+ID4gPiArb2JqLSQoQ09ORklHX1FPUklRX1RIRVJNQUwpCSs9IHFvcmlxX3RoZXJt YWwubw0KPiA+ID4gPiA+ICBvYmotJChDT05GSUdfREI4NTAwX0NQVUZSRVFfQ09PTElORykJKz0N Cj4gPiBkYjg1MDBfY3B1ZnJlcV9jb29saW5nLm8NCj4gPiA+ID4gPiAgb2JqLSQoQ09ORklHX0lO VEVMX1BPV0VSQ0xBTVApCSs9IGludGVsX3Bvd2VyY2xhbXAubw0KPiA+ID4gPiA+ICBvYmotJChD T05GSUdfWDg2X1BLR19URU1QX1RIRVJNQUwpCSs9IHg4Nl9wa2dfdGVtcF90aGVybWFsLm8NCj4g PiA+ID4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy90aGVybWFsL3FvcmlxX3RoZXJtYWwuYw0KPiA+ ID4gPiA+IGIvZHJpdmVycy90aGVybWFsL3FvcmlxX3RoZXJtYWwuYyBuZXcgZmlsZSBtb2RlIDEw MDY0NCBpbmRleA0KPiA+ID4gPiA+IDAwMDAwMDAuLjA2OTRmNDINCj4gPiA+ID4gPiAtLS0gL2Rl di9udWxsDQo+ID4gPiA+ID4gKysrIGIvZHJpdmVycy90aGVybWFsL3FvcmlxX3RoZXJtYWwuYw0K PiA+ID4gPiA+IEBAIC0wLDAgKzEsNDA2IEBADQo+ID4gPiA+ID4gKy8qDQo+ID4gPiA+ID4gKyAq IENvcHlyaWdodCAyMDE1IEZyZWVzY2FsZSBTZW1pY29uZHVjdG9yLCBJbmMuDQo+ID4gPiA+ID4g KyAqDQo+ID4gPiA+ID4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2Fu IHJlZGlzdHJpYnV0ZSBpdA0KPiA+ID4gPiA+ICthbmQvb3IgbW9kaWZ5IGl0DQo+ID4gPiA+ID4g KyAqIHVuZGVyIHRoZSB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB0aGUgR05VIEdlbmVyYWwgUHVi bGljDQo+ID4gPiA+ID4gK0xpY2Vuc2UsDQo+ID4gPiA+ID4gKyAqIHZlcnNpb24gMiwgYXMgcHVi bGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24uDQo+ID4gPiA+ID4gKyAqDQo+ ID4gPiA+ID4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSBpdCB3 aWxsIGJlIHVzZWZ1bCwNCj4gPiA+ID4gPiArYnV0IFdJVEhPVVQNCj4gPiA+ID4gPiArICogQU5Z IFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YNCj4gPiA+ID4g PiArTUVSQ0hBTlRBQklMSVRZIG9yDQo+ID4gPiA+ID4gKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElD VUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUgR2VuZXJhbA0KPiA+ID4gPiA+ICtQdWJsaWMgTGlj ZW5zZSBmb3INCj4gPiA+ID4gPiArICogbW9yZSBkZXRhaWxzLg0KPiA+ID4gPiA+ICsgKg0KPiA+ ID4gPiA+ICsgKi8NCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gKy8qDQo+ID4gPiA+ID4gKyAqIEJh c2VkIG9uIEZyZWVzY2FsZSBRb3JJUSBUaGVybWFsIE1vbml0b3JpbmcgVW5pdCAoVE1VKSAgKi8N Cj4gPiA+ID4gPiArI2luY2x1ZGUgPGxpbnV4L2NwdWZyZXEuaD4gI2luY2x1ZGUgPGxpbnV4L2Nw dV9jb29saW5nLmg+DQo+ID4gPiA+ID4gKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4gI2luY2x1 ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPg0KPiA+ID4gPiA+ICsjaW5jbHVkZSA8bGludXgv ZXJyLmg+ICNpbmNsdWRlIDxsaW51eC9pby5oPiAjaW5jbHVkZQ0KPiA+ID4gPiA+ICs8bGludXgv b2YuaD4gI2luY2x1ZGUgPGxpbnV4L29mX2FkZHJlc3MuaD4gI2luY2x1ZGUNCj4gPiA+ID4gPiAr PGxpbnV4L3RoZXJtYWwuaD4NCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gKyNkZWZpbmUgU0lURVNf TUFYCQkxNg0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArI2RlZmluZSBUTVVfVEVNUF9QQVNTSVZF CTg1MDAwDQo+ID4gPiA+ID4gKyNkZWZpbmUgVE1VX1RFTVBfQ1JJVElDQUwJOTUwMDANCj4gPiA+ ID4gPiArDQo+ID4gPiA+ID4gKyNkZWZpbmUgVE1VX1BBU1NJVkVfREVMQVkJMTAwMAkvKiBNaWxs aXNlY29uZHMgKi8NCj4gPiA+ID4gPiArI2RlZmluZSBUTVVfUE9MTElOR19ERUxBWQk1MDAwDQo+ ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsvKiBUaGUgZHJpdmVyIHN1cHBvcnRzIDEgcGFzc2l2ZSB0 cmlwIHBvaW50IGFuZCAxIGNyaXRpY2FsIHRyaXANCj4gPiA+ID4gPiArcG9pbnQgKi8gZW51bSB0 bXVfdGhlcm1hbF90cmlwIHsNCj4gPiA+ID4gPiArCVRNVV9UUklQX1BBU1NJVkUsDQo+ID4gPiA+ ID4gKwlUTVVfVFJJUF9DUklUSUNBTCwNCj4gPiA+ID4gPiArCVRNVV9UUklQX05VTSwNCj4gPiA+ ID4gPiArfTsNCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gKy8qDQo+ID4gPiA+ID4gKyAqIFFvcklR IFRNVSBSZWdpc3RlcnMNCj4gPiA+ID4gPiArICovDQo+ID4gPiA+ID4gK3N0cnVjdCBxb3JpcV90 bXVfc2l0ZV9yZWdzIHsNCj4gPiA+ID4gPiArCV9fYmUzMiB0cml0c3I7CQkvKiBJbW1lZGlhdGUg VGVtcGVyYXR1cmUgU2l0ZQ0KPiA+IFJlZ2lzdGVyICovDQo+ID4gPiA+ID4gKwlfX2JlMzIgdHJh dHNyOwkJLyogQXZlcmFnZSBUZW1wZXJhdHVyZSBTaXRlIFJlZ2lzdGVyDQo+ID4gKi8NCj4gPiA+ ID4gPiArCXU4IHJlczBbMHg4XTsNCj4gPiA+ID4gPiArfSBfX3BhY2tlZDsNCj4gPiA+ID4gPiAr DQo+ID4gPiA+ID4gK3N0cnVjdCBxb3JpcV90bXVfcmVncyB7DQo+ID4gPiA+ID4gKwlfX2JlMzIg dG1yOwkJLyogTW9kZSBSZWdpc3RlciAqLw0KPiA+ID4gPiA+ICsjZGVmaW5lIFRNUl9ESVNBQkxF CTB4MA0KPiA+ID4gPiA+ICsjZGVmaW5lIFRNUl9NRQkJMHg4MDAwMDAwMA0KPiA+ID4gPiA+ICsj ZGVmaW5lIFRNUl9BTFBGCTB4MGMwMDAwMDANCj4gPiA+ID4gPiArI2RlZmluZSBUTVJfTVNJVEUJ MHgwMDAwODAwMA0KPiA+ID4gPiA+ICsjZGVmaW5lIFRNUl9BTEwJCShUTVJfTUUgfCBUTVJfQUxQ RiB8IFRNUl9NU0lURSkNCj4gPiA+ID4gPiArCV9fYmUzMiB0c3I7CQkvKiBTdGF0dXMgUmVnaXN0 ZXIgKi8NCj4gPiA+ID4gPiArCV9fYmUzMiB0bXRtaXI7CQkvKiBUZW1wZXJhdHVyZSBtZWFzdXJl bWVudCBpbnRlcnZhbA0KPiA+ID4gPiBSZWdpc3RlciAqLw0KPiA+ID4gPiA+ICsjZGVmaW5lIFRN VE1JUl9ERUZBVUxUCTB4MDAwMDAwMDcNCj4gPiA+ID4gPiArCXU4IHJlczBbMHgxNF07DQo+ID4g PiA+ID4gKwlfX2JlMzIgdGllcjsJCS8qIEludGVycnVwdCBFbmFibGUgUmVnaXN0ZXIgKi8NCj4g PiA+ID4gPiArI2RlZmluZSBUSUVSX0RJU0FCTEUJMHgwDQo+ID4gPiA+ID4gKwlfX2JlMzIgdGlk cjsJCS8qIEludGVycnVwdCBEZXRlY3QgUmVnaXN0ZXIgKi8NCj4gPiA+ID4gPiArCV9fYmUzMiB0 aXNjcjsJCS8qIEludGVycnVwdCBTaXRlIENhcHR1cmUgUmVnaXN0ZXIgKi8NCj4gPiA+ID4gPiAr CV9fYmUzMiB0aWNzY3I7CQkvKiBJbnRlcnJ1cHQgQ3JpdGljYWwgU2l0ZSBDYXB0dXJlDQo+ID4g UmVnaXN0ZXINCj4gPiA+ID4gKi8NCj4gPiA+ID4gPiArCXU4IHJlczFbMHgxMF07DQo+ID4gPiA+ ID4gKwlfX2JlMzIgdG1odGNyaDsJCS8qIEhpZ2ggVGVtcGVyYXR1cmUgQ2FwdHVyZSBSZWdpc3Rl cg0KPiA+ICovDQo+ID4gPiA+ID4gKwlfX2JlMzIgdG1odGNybDsJCS8qIExvdyBUZW1wZXJhdHVy ZSBDYXB0dXJlIFJlZ2lzdGVyDQo+ID4gKi8NCj4gPiA+ID4gPiArCXU4IHJlczJbMHg4XTsNCj4g PiA+ID4gPiArCV9fYmUzMiB0bWh0aXRyOwkJLyogSGlnaCBUZW1wZXJhdHVyZSBJbW1lZGlhdGUN Cj4gPiBUaHJlc2hvbGQgKi8NCj4gPiA+ID4gPiArCV9fYmUzMiB0bWh0YXRyOwkJLyogSGlnaCBU ZW1wZXJhdHVyZSBBdmVyYWdlIFRocmVzaG9sZA0KPiA+ICovDQo+ID4gPiA+ID4gKwlfX2JlMzIg dG1odGFjdHI7CS8qIEhpZ2ggVGVtcGVyYXR1cmUgQXZlcmFnZSBDcml0IFRocmVzaG9sZA0KPiA+ ICovDQo+ID4gPiA+ID4gKwl1OCByZXMzWzB4MjRdOw0KPiA+ID4gPiA+ICsJX19iZTMyIHR0Y2Zn cjsJCS8qIFRlbXBlcmF0dXJlIENvbmZpZ3VyYXRpb24gUmVnaXN0ZXINCj4gPiAqLw0KPiA+ID4g PiA+ICsJX19iZTMyIHRzY2ZncjsJCS8qIFNlbnNvciBDb25maWd1cmF0aW9uIFJlZ2lzdGVyICov DQo+ID4gPiA+ID4gKwl1OCByZXM0WzB4NzhdOw0KPiA+ID4gPiA+ICsJc3RydWN0IHFvcmlxX3Rt dV9zaXRlX3JlZ3Mgc2l0ZVtTSVRFU19NQVhdOw0KPiA+ID4gPiA+ICsJdTggcmVzNVsweDlmOF07 DQo+ID4gPiA+ID4gKwlfX2JlMzIgaXBicnIwOwkJLyogSVAgQmxvY2sgUmV2aXNpb24gUmVnaXN0 ZXIgMCAqLw0KPiA+ID4gPiA+ICsJX19iZTMyIGlwYnJyMTsJCS8qIElQIEJsb2NrIFJldmlzaW9u IFJlZ2lzdGVyIDEgKi8NCj4gPiA+ID4gPiArCXU4IHJlczZbMHgzMTBdOw0KPiA+ID4gPiA+ICsJ X19iZTMyIHR0cjBjcjsJCS8qIFRlbXBlcmF0dXJlIFJhbmdlIDAgQ29udHJvbA0KPiA+IFJlZ2lz dGVyICovDQo+ID4gPiA+ID4gKwlfX2JlMzIgdHRyMWNyOwkJLyogVGVtcGVyYXR1cmUgUmFuZ2Ug MSBDb250cm9sDQo+ID4gUmVnaXN0ZXIgKi8NCj4gPiA+ID4gPiArCV9fYmUzMiB0dHIyY3I7CQkv KiBUZW1wZXJhdHVyZSBSYW5nZSAyIENvbnRyb2wNCj4gPiBSZWdpc3RlciAqLw0KPiA+ID4gPiA+ ICsJX19iZTMyIHR0cjNjcjsJCS8qIFRlbXBlcmF0dXJlIFJhbmdlIDMgQ29udHJvbA0KPiA+IFJl Z2lzdGVyICovDQo+ID4gPiA+ID4gK307DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsvKg0KPiA+ ID4gPiA+ICsgKiBUaGVybWFsIHpvbmUgZGF0YQ0KPiA+ID4gPiA+ICsgKi8NCj4gPiA+ID4gPiAr c3RydWN0IHFvcmlxX3RtdV9kYXRhIHsNCj4gPiA+ID4gPiArCXN0cnVjdCB0aGVybWFsX3pvbmVf ZGV2aWNlICp0ejsNCj4gPiA+ID4gPiArCXN0cnVjdCB0aGVybWFsX2Nvb2xpbmdfZGV2aWNlICpj ZGV2Ow0KPiA+ID4gPiA+ICsJZW51bSB0aGVybWFsX2RldmljZV9tb2RlIG1vZGU7DQo+ID4gPiA+ ID4gKwl1bnNpZ25lZCBsb25nIHRlbXBfcGFzc2l2ZTsNCj4gPiA+ID4gPiArCXVuc2lnbmVkIGxv bmcgdGVtcF9jcml0aWNhbDsNCj4gPiA+ID4gPiArCXN0cnVjdCBxb3JpcV90bXVfcmVncyBfX2lv bWVtICpyZWdzOyB9Ow0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArc3RhdGljIGludCB0bXVfZ2V0 X21vZGUoc3RydWN0IHRoZXJtYWxfem9uZV9kZXZpY2UgKnR6LA0KPiA+ID4gPiA+ICsJCQllbnVt IHRoZXJtYWxfZGV2aWNlX21vZGUgKm1vZGUpIHsNCj4gPiA+ID4gPiArCXN0cnVjdCBxb3JpcV90 bXVfZGF0YSAqZGF0YSA9IHR6LT5kZXZkYXRhOw0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArCSpt b2RlID0gZGF0YS0+bW9kZTsNCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gKwlyZXR1cm4gMDsNCj4g PiA+ID4gPiArfQ0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArc3RhdGljIGludCB0bXVfc2V0X21v ZGUoc3RydWN0IHRoZXJtYWxfem9uZV9kZXZpY2UgKnR6LA0KPiA+ID4gPiA+ICsJCQllbnVtIHRo ZXJtYWxfZGV2aWNlX21vZGUgbW9kZSkgew0KPiA+ID4gPiA+ICsJc3RydWN0IHFvcmlxX3RtdV9k YXRhICpkYXRhID0gdHotPmRldmRhdGE7DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJaWYgKG1v ZGUgPT0gVEhFUk1BTF9ERVZJQ0VfRU5BQkxFRCkgew0KPiA+ID4gPiA+ICsJCXR6LT5wb2xsaW5n X2RlbGF5ID0gVE1VX1BPTExJTkdfREVMQVk7DQo+ID4gPiA+ID4gKwkJdHotPnBhc3NpdmVfZGVs YXkgPSBUTVVfUEFTU0lWRV9ERUxBWTsNCj4gPiA+ID4gPiArCQl0aGVybWFsX3pvbmVfZGV2aWNl X3VwZGF0ZSh0eik7DQo+ID4gPiA+ID4gKwl9IGVsc2Ugew0KPiA+ID4gPiA+ICsJCXR6LT5wb2xs aW5nX2RlbGF5ID0gMDsNCj4gPiA+ID4gPiArCQl0ei0+cGFzc2l2ZV9kZWxheSA9IDA7DQo+ID4g PiA+ID4gKwl9DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJZGF0YS0+bW9kZSA9IG1vZGU7DQo+ ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJcmV0dXJuIDA7DQo+ID4gPiA+ID4gK30NCj4gPiA+ID4g PiArDQo+ID4gPiA+ID4gK3N0YXRpYyBpbnQgdG11X2dldF90ZW1wKHN0cnVjdCB0aGVybWFsX3pv bmVfZGV2aWNlICp0eiwNCj4gPiA+ID4gPiArdW5zaWduZWQgbG9uZw0KPiA+ID4gPiA+ICsqdGVt cCkgew0KPiA+ID4gPiA+ICsJdTggdmFsOw0KPiA+ID4gPiA+ICsJc3RydWN0IHFvcmlxX3RtdV9k YXRhICpkYXRhID0gdHotPmRldmRhdGE7DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJdmFsID0g aW9yZWFkMzJiZSgmZGF0YS0+cmVncy0+c2l0ZVswXS50cml0c3IpOw0KPiA+ID4gPiA+ICsJKnRl bXAgPSAodW5zaWduZWQgbG9uZyl2YWwgKiAxMDAwOw0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiAr CXJldHVybiAwOw0KPiA+ID4gPiA+ICt9DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICtzdGF0aWMg aW50IHRtdV9nZXRfdHJpcF90eXBlKHN0cnVjdCB0aGVybWFsX3pvbmVfZGV2aWNlICp0eiwNCj4g PiA+ID4gPiAraW50DQo+ID4gdHJpcCwNCj4gPiA+ID4gPiArCQkJICAgICBlbnVtIHRoZXJtYWxf dHJpcF90eXBlICp0eXBlKSB7DQo+ID4gPiA+ID4gKwkqdHlwZSA9ICh0cmlwID09IFRNVV9UUklQ X1BBU1NJVkUpID8gVEhFUk1BTF9UUklQX1BBU1NJVkUgOg0KPiA+ID4gPiA+ICsJCQkJCSAgICAg VEhFUk1BTF9UUklQX0NSSVRJQ0FMOw0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArCXJldHVybiAw Ow0KPiA+ID4gPiA+ICt9DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICtzdGF0aWMgaW50IHRtdV9n ZXRfdHJpcF90ZW1wKHN0cnVjdCB0aGVybWFsX3pvbmVfZGV2aWNlICp0eiwNCj4gPiA+ID4gPiAr aW50DQo+ID4gdHJpcCwNCj4gPiA+ID4gPiArCQkJICAgICB1bnNpZ25lZCBsb25nICp0ZW1wKQ0K PiA+ID4gPiA+ICt7DQo+ID4gPiA+ID4gKwlzdHJ1Y3QgcW9yaXFfdG11X2RhdGEgKmRhdGEgPSB0 ei0+ZGV2ZGF0YTsNCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gKwkqdGVtcCA9ICh0cmlwID09IFRN VV9UUklQX1BBU1NJVkUpID8gZGF0YS0+dGVtcF9wYXNzaXZlIDoNCj4gPiA+ID4gPiArCQkJCQkg ICAgIGRhdGEtPnRlbXBfY3JpdGljYWw7DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJcmV0dXJu IDA7DQo+ID4gPiA+ID4gK30NCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gK3N0YXRpYyBpbnQgdG11 X2dldF9jcml0X3RlbXAoc3RydWN0IHRoZXJtYWxfem9uZV9kZXZpY2UgKnR6LA0KPiA+ID4gPiA+ ICsJCQkgICAgIHVuc2lnbmVkIGxvbmcgKnRlbXApDQo+ID4gPiA+ID4gK3sNCj4gPiA+ID4gPiAr CXN0cnVjdCBxb3JpcV90bXVfZGF0YSAqZGF0YSA9IHR6LT5kZXZkYXRhOw0KPiA+ID4gPiA+ICsN Cj4gPiA+ID4gPiArCSp0ZW1wID0gZGF0YS0+dGVtcF9jcml0aWNhbDsNCj4gPiA+ID4gPiArDQo+ ID4gPiA+ID4gKwlyZXR1cm4gMDsNCj4gPiA+ID4gPiArfQ0KPiA+ID4gPiA+ICsNCj4gPiA+ID4g PiArc3RhdGljIGludCB0bXVfYmluZChzdHJ1Y3QgdGhlcm1hbF96b25lX2RldmljZSAqdHosDQo+ ID4gPiA+ID4gKwkJICAgIHN0cnVjdCB0aGVybWFsX2Nvb2xpbmdfZGV2aWNlICpjZGV2KSB7DQo+ ID4gPiA+ID4gKwlpbnQgcmV0Ow0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArCXJldCA9IHRoZXJt YWxfem9uZV9iaW5kX2Nvb2xpbmdfZGV2aWNlKHR6LCBUTVVfVFJJUF9QQVNTSVZFLA0KPiA+IGNk ZXYsDQo+ID4gPiA+ID4gKwkJCQkJICAgICAgIFRIRVJNQUxfTk9fTElNSVQsDQo+ID4gPiA+ID4g KwkJCQkJICAgICAgIFRIRVJNQUxfTk9fTElNSVQsDQo+ID4gPiA+ID4gKwkJCQkJICAgICAgIFRI RVJNQUxfV0VJR0hUX0RFRkFVTFQpOw0KPiA+ID4gPiA+ICsJaWYgKHJldCkgew0KPiA+ID4gPiA+ ICsJCWRldl9lcnIoJnR6LT5kZXZpY2UsDQo+ID4gPiA+ID4gKwkJCSJCaW5kaW5nIHpvbmUgJXMg d2l0aCBjZGV2ICVzIGZhaWxlZDolZFxuIiwNCj4gPiA+ID4gPiArCQkJdHotPnR5cGUsIGNkZXYt PnR5cGUsIHJldCk7DQo+ID4gPiA+ID4gKwl9DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJcmV0 dXJuIHJldDsNCj4gPiA+ID4gPiArfQ0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArc3RhdGljIGlu dCB0bXVfdW5iaW5kKHN0cnVjdCB0aGVybWFsX3pvbmVfZGV2aWNlICp0eiwNCj4gPiA+ID4gPiAr CQkgICAgICBzdHJ1Y3QgdGhlcm1hbF9jb29saW5nX2RldmljZSAqY2Rldikgew0KPiA+ID4gPiA+ ICsJaW50IHJldDsNCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gKwlyZXQgPSB0aGVybWFsX3pvbmVf dW5iaW5kX2Nvb2xpbmdfZGV2aWNlKHR6LCBUTVVfVFJJUF9QQVNTSVZFLA0KPiA+ID4gPiBjZGV2 KTsNCj4gPiA+ID4gPiArCWlmIChyZXQpIHsNCj4gPiA+ID4gPiArCQlkZXZfZXJyKCZ0ei0+ZGV2 aWNlLA0KPiA+ID4gPiA+ICsJCQkiVW5iaW5kaW5nIHpvbmUgJXMgd2l0aCBjZGV2ICVzIGZhaWxl ZDolZFxuIiwNCj4gPiA+ID4gPiArCQkJdHotPnR5cGUsIGNkZXYtPnR5cGUsIHJldCk7DQo+ID4g PiA+ID4gKwl9DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJcmV0dXJuIHJldDsNCj4gPiA+ID4g PiArfQ0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArc3RhdGljIGludCBxb3JpcV90bXVfY2FsaWJy YXRpb24oc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikgew0KPiA+ID4gPiA+ICsJaW50IGks IHZhbCwgbGVuOw0KPiA+ID4gPiA+ICsJdTMyIHJhbmdlWzRdOw0KPiA+ID4gPiA+ICsJY29uc3Qg X19iZTMyICpjYWxpYnJhdGlvbjsNCj4gPiA+ID4gPiArCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbm9k ZSA9IHBkZXYtPmRldi5vZl9ub2RlOw0KPiA+ID4gPiA+ICsJc3RydWN0IHFvcmlxX3RtdV9kYXRh ICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKCZwZGV2LT5kZXYpOw0KPiA+ID4gPiA+ICsNCj4gPiA+ ID4gPiArCS8qIERpc2FibGUgbW9uaXRvcmluZyBiZWZvcmUgY2FsaWJyYXRpb24gKi8NCj4gPiA+ ID4gPiArCWlvd3JpdGUzMmJlKFRNUl9ESVNBQkxFLCAmZGF0YS0+cmVncy0+dG1yKTsNCj4gPiA+ ID4gPiArDQo+ID4gPiA+ID4gKwlpZiAob2ZfcHJvcGVydHlfcmVhZF91MzJfYXJyYXkobm9kZSwg ImZzbCx0bXUtcmFuZ2UiLCByYW5nZSwNCj4gPiA0KSkNCj4gPiA+ID4gPiArCQlyZXR1cm4gLTE7 DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJLyogSW5pdCB0ZW1wZXJhdHVyZSByYW5nZSByZWdp c3RlcnMgKi8NCj4gPiA+ID4gPiArCWlvd3JpdGUzMmJlKHJhbmdlWzBdLCAmZGF0YS0+cmVncy0+ dHRyMGNyKTsNCj4gPiA+ID4gPiArCWlvd3JpdGUzMmJlKHJhbmdlWzFdLCAmZGF0YS0+cmVncy0+ dHRyMWNyKTsNCj4gPiA+ID4gPiArCWlvd3JpdGUzMmJlKHJhbmdlWzJdLCAmZGF0YS0+cmVncy0+ dHRyMmNyKTsNCj4gPiA+ID4gPiArCWlvd3JpdGUzMmJlKHJhbmdlWzNdLCAmZGF0YS0+cmVncy0+ dHRyM2NyKTsNCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gKwljYWxpYnJhdGlvbiA9IG9mX2dldF9w cm9wZXJ0eShub2RlLCAiZnNsLHRtdS1jYWxpYnJhdGlvbiIsDQo+ID4gJmxlbik7DQo+ID4gPiA+ ID4gKwlpZiAoY2FsaWJyYXRpb24gPT0gTlVMTCkNCj4gPiA+ID4gPiArCQlyZXR1cm4gLTE7DQo+ ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJZm9yIChpID0gMDsgaSA8IGxlbjsgaSArPSA4LCBjYWxp YnJhdGlvbiArPSAyKSB7DQo+ID4gPiA+ID4gKwkJdmFsID0gKGludClvZl9yZWFkX251bWJlcihj YWxpYnJhdGlvbiwgMSk7DQo+ID4gPiA+ID4gKwkJaW93cml0ZTMyYmUodmFsLCAmZGF0YS0+cmVn cy0+dHRjZmdyKTsNCj4gPiA+ID4gPiArCQl2YWwgPSAoaW50KW9mX3JlYWRfbnVtYmVyKGNhbGli cmF0aW9uICsgMSwgMSk7DQo+ID4gPiA+ID4gKwkJaW93cml0ZTMyYmUodmFsLCAmZGF0YS0+cmVn cy0+dHNjZmdyKTsNCj4gPiA+ID4gPiArCX0NCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gKwlyZXR1 cm4gMDsNCj4gPiA+ID4gPiArfQ0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArc3RhdGljIHZvaWQg cW9yaXFfdG11X2luaXRfZGV2aWNlKHN0cnVjdCBxb3JpcV90bXVfZGF0YSAqZGF0YSkgew0KPiA+ ID4gPiA+ICsJLyogRGlzYWJsZSBpbnRlcnJ1cHQsIHVzaW5nIHBvbGxpbmcgaW5zdGVhZCAqLw0K PiA+ID4gPiA+ICsJaW93cml0ZTMyYmUoVElFUl9ESVNBQkxFLCAmZGF0YS0+cmVncy0+dGllcik7 DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJLyogU2V0IHVwZGF0ZV9pbnRlcnZhbCAqLw0KPiA+ ID4gPiA+ICsJaW93cml0ZTMyYmUoVE1UTUlSX0RFRkFVTFQsICZkYXRhLT5yZWdzLT50bXRtaXIp Ow0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArCS8qIEVuYWJsZSBtb25pdG9yaW5nICovDQo+ID4g PiA+ID4gKwlpb3dyaXRlMzJiZShUTVJfQUxMLCAmZGF0YS0+cmVncy0+dG1yKTsgfQ0KPiA+ID4g PiA+ICsNCj4gPiA+ID4gPiArc3RhdGljIHN0cnVjdCB0aGVybWFsX3pvbmVfZGV2aWNlX29wcyB0 bXVfdHpfb3BzID0gew0KPiA+ID4gPiA+ICsJLmJpbmQgPSB0bXVfYmluZCwNCj4gPiA+ID4gPiAr CS51bmJpbmQgPSB0bXVfdW5iaW5kLA0KPiA+ID4gPiA+ICsJLmdldF90ZW1wID0gdG11X2dldF90 ZW1wLA0KPiA+ID4gPiA+ICsJLmdldF9tb2RlID0gdG11X2dldF9tb2RlLA0KPiA+ID4gPiA+ICsJ LnNldF9tb2RlID0gdG11X3NldF9tb2RlLA0KPiA+ID4gPiA+ICsJLmdldF90cmlwX3R5cGUgPSB0 bXVfZ2V0X3RyaXBfdHlwZSwNCj4gPiA+ID4gPiArCS5nZXRfdHJpcF90ZW1wID0gdG11X2dldF90 cmlwX3RlbXAsDQo+ID4gPiA+ID4gKwkuZ2V0X2NyaXRfdGVtcCA9IHRtdV9nZXRfY3JpdF90ZW1w LCB9Ow0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArc3RhdGljIGludCBxb3JpcV90bXVfcHJvYmUo c3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikgew0KPiA+ID4gPiA+ICsJaW50IHJldDsNCj4g PiA+ID4gPiArCXN0cnVjdCBjcHVtYXNrIGNsaXBfY3B1czsNCj4gPiA+ID4gPiArCXN0cnVjdCBx b3JpcV90bXVfZGF0YSAqZGF0YTsNCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gKwlpZiAoIWNwdWZy ZXFfZ2V0X2N1cnJlbnRfZHJpdmVyKCkpIHsNCj4gPiA+ID4gPiArCQlkZXZfZGJnKCZwZGV2LT5k ZXYsICJObyBjcHVmcmVxIGRyaXZlciB5ZXRcbiIpOw0KPiA+ID4gPiA+ICsJCXJldHVybiAtRVBS T0JFX0RFRkVSOw0KPiA+ID4gPiA+ICsJfQ0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArCWlmICgh cGRldi0+ZGV2Lm9mX25vZGUpIHsNCj4gPiA+ID4gPiArCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJE ZXZpY2UgT0YtTm9kZSBpcyBOVUxMIik7DQo+ID4gPiA+ID4gKwkJcmV0dXJuIC1FRkFVTFQ7DQo+ ID4gPiA+ID4gKwl9DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJZGF0YSA9IGRldm1fa3phbGxv YygmcGRldi0+ZGV2LCBzaXplb2Yoc3RydWN0IHFvcmlxX3RtdV9kYXRhKSwNCj4gPiA+ID4gPiAr CQkJICAgIEdGUF9LRVJORUwpOw0KPiA+ID4gPiA+ICsJaWYgKCFkYXRhKQ0KPiA+ID4gPiA+ICsJ CXJldHVybiAtRU5PTUVNOw0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArCWRldl9zZXRfZHJ2ZGF0 YSgmcGRldi0+ZGV2LCBkYXRhKTsNCj4gPiA+ID4gPiArCWRhdGEtPnJlZ3MgPSBvZl9pb21hcChw ZGV2LT5kZXYub2Zfbm9kZSwgMCk7DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJaWYgKCFkYXRh LT5yZWdzKSB7DQo+ID4gPiA+ID4gKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiRmFpbGVkIHRvIGdl dCBtZW1vcnkgcmVnaW9uXG4iKTsNCj4gPiA+ID4gPiArCQlyZXQgPSAtRU5PREVWOw0KPiA+ID4g PiA+ICsJCWdvdG8gZXJyX2lvbWFwOw0KPiA+ID4gPiA+ICsJfQ0KPiA+ID4gPiA+ICsNCj4gPiA+ ID4gPiArCXJldCA9IHFvcmlxX3RtdV9jYWxpYnJhdGlvbihwZGV2KTsJLyogVE1VIGNhbGlicmF0 aW9uICovDQo+ID4gPiA+ID4gKwlpZiAocmV0IDwgMCkgew0KPiA+ID4gPiA+ICsJCWRldl9lcnIo JnBkZXYtPmRldiwgIlRNVSBjYWxpYnJhdGlvbiBmYWlsZWQuXG4iKTsNCj4gPiA+ID4gPiArCQly ZXQgPSAtRU5PREVWOw0KPiA+ID4gPiA+ICsJCWdvdG8gZXJyX2lvbWFwOw0KPiA+ID4gPiA+ICsJ fQ0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArCXFvcmlxX3RtdV9pbml0X2RldmljZShkYXRhKTsJ LyogVE1VIGluaXRpYWxpemF0aW9uICovDQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJY3B1bWFz a19zZXRhbGwoJmNsaXBfY3B1cyk7DQo+ID4gPiA+ID4gKwlkYXRhLT5jZGV2ID0gY3B1ZnJlcV9j b29saW5nX3JlZ2lzdGVyKCZjbGlwX2NwdXMpOw0KPiA+ID4gPiA+ICsJaWYgKElTX0VSUihkYXRh LT5jZGV2KSkgew0KPiA+ID4gPiA+ICsJCXJldCA9IFBUUl9FUlIoZGF0YS0+Y2Rldik7DQo+ID4g PiA+ID4gKwkJZGV2X2VycigmZGF0YS0+Y2Rldi0+ZGV2aWNlLA0KPiA+ID4gPiA+ICsJCQkiRmFp bGVkIHRvIHJlZ2lzdGVyIGNwdWZyZXEgY29vbGluZyBkZXZpY2U6ICVkXG4iLA0KPiA+IHJldCk7 DQo+ID4gPiA+ID4gKwkJZ290byBlcnJfY29vbGluZzsNCj4gPiA+ID4gPiArCX0NCj4gPiA+ID4g PiArDQo+ID4gPiA+ID4gKwlkYXRhLT50ZW1wX3Bhc3NpdmUgPSBUTVVfVEVNUF9QQVNTSVZFOw0K PiA+ID4gPiA+ICsJZGF0YS0+dGVtcF9jcml0aWNhbCA9IFRNVV9URU1QX0NSSVRJQ0FMOw0KPiA+ ID4gPiA+ICsJZGF0YS0+dHogPSB0aGVybWFsX3pvbmVfZGV2aWNlX3JlZ2lzdGVyKCJ0bXVfdGhl cm1hbF96b25lIiwNCj4gPiA+ID4NCj4gPiA+ID4gQW55IHNwZWNpZmljIHJlYXNvbiB3aHkgbm90 IHVzaW5nIE9GIHRoZXJtYWw/DQo+ID4gPiA+DQo+ID4gPiA+ID4gKwkJCQkJCVRNVV9UUklQX05V TSwNCj4gPiA+ID4gPiArCQkJCQkJMCwgZGF0YSwNCj4gPiA+ID4gPiArCQkJCQkJJnRtdV90el9v cHMsIE5VTEwsDQo+ID4gPiA+ID4gKwkJCQkJCVRNVV9QQVNTSVZFX0RFTEFZLA0KPiA+ID4gPiA+ ICsJCQkJCQlUTVVfUE9MTElOR19ERUxBWSk7DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJaWYg KElTX0VSUihkYXRhLT50eikpIHsNCj4gPiA+ID4gPiArCQlyZXQgPSBQVFJfRVJSKGRhdGEtPnR6 KTsNCj4gPiA+ID4gPiArCQlkZXZfZXJyKCZwZGV2LT5kZXYsDQo+ID4gPiA+ID4gKwkJCSJGYWls ZWQgdG8gcmVnaXN0ZXIgdGhlcm1hbCB6b25lIGRldmljZSAlZFxuIiwNCj4gPiByZXQpOw0KPiA+ ID4gPiA+ICsJCWdvdG8gZXJyX3RoZXJtYWw7DQo+ID4gPiA+ID4gKwl9DQo+ID4gPiA+ID4gKw0K PiA+ID4gPiA+ICsJZGF0YS0+bW9kZSA9IFRIRVJNQUxfREVWSUNFX0VOQUJMRUQ7DQo+ID4gPiA+ ID4gKw0KPiA+ID4gPiA+ICsJcmV0dXJuIDA7DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICtlcnJf dGhlcm1hbDoNCj4gPiA+ID4gPiArCWNwdWZyZXFfY29vbGluZ191bnJlZ2lzdGVyKGRhdGEtPmNk ZXYpOw0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArZXJyX2Nvb2xpbmc6DQo+ID4gPiA+ID4gKwlp b3VubWFwKGRhdGEtPnJlZ3MpOw0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArZXJyX2lvbWFwOg0K PiA+ID4gPiA+ICsJZGV2X3NldF9kcnZkYXRhKCZwZGV2LT5kZXYsIE5VTEwpOw0KPiA+ID4gPiA+ ICsJZGV2bV9rZnJlZSgmcGRldi0+ZGV2LCBkYXRhKTsNCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4g KwlyZXR1cm4gcmV0Ow0KPiA+ID4gPiA+ICt9DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICtzdGF0 aWMgaW50IHFvcmlxX3RtdV9yZW1vdmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikgew0K PiA+ID4gPiA+ICsJc3RydWN0IHFvcmlxX3RtdV9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRh KCZwZGV2LT5kZXYpOw0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArCS8qIERpc2FibGUgbW9uaXRv cmluZyAqLw0KPiA+ID4gPiA+ICsJaW93cml0ZTMyYmUoVE1SX0RJU0FCTEUsICZkYXRhLT5yZWdz LT50bXIpOw0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArCXRoZXJtYWxfem9uZV9kZXZpY2VfdW5y ZWdpc3RlcihkYXRhLT50eik7DQo+ID4gPiA+ID4gKwljcHVmcmVxX2Nvb2xpbmdfdW5yZWdpc3Rl cihkYXRhLT5jZGV2KTsNCj4gPiA+ID4gPiArCWlvdW5tYXAoZGF0YS0+cmVncyk7DQo+ID4gPiA+ ID4gKw0KPiA+ID4gPiA+ICsJZGV2X3NldF9kcnZkYXRhKCZwZGV2LT5kZXYsIE5VTEwpOw0KPiA+ ID4gPiA+ICsJZGV2bV9rZnJlZSgmcGRldi0+ZGV2LCBkYXRhKTsNCj4gPiA+ID4gPiArDQo+ID4g PiA+ID4gKwlyZXR1cm4gMDsNCj4gPiA+ID4gPiArfQ0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiAr I2lmZGVmIENPTkZJR19QTV9TTEVFUA0KPiA+ID4gPiA+ICtzdGF0aWMgaW50IHFvcmlxX3RtdV9z dXNwZW5kKHN0cnVjdCBkZXZpY2UgKmRldikgew0KPiA+ID4gPiA+ICsJc3RydWN0IHFvcmlxX3Rt dV9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7DQo+ID4gPiA+ID4gKw0KPiA+ID4g PiA+ICsJLyogRGlzYWJsZSBtb25pdG9yaW5nICovDQo+ID4gPiA+ID4gKwlpb3dyaXRlMzJiZShU TVJfRElTQUJMRSwgJmRhdGEtPnJlZ3MtPnRtcik7DQo+ID4gPiA+ID4gKwlkYXRhLT5tb2RlID0g VEhFUk1BTF9ERVZJQ0VfRElTQUJMRUQ7DQo+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ICsJcmV0dXJu IDA7DQo+ID4gPiA+ID4gK30NCj4gPiA+ID4gPiArDQo+ID4gPiA+ID4gK3N0YXRpYyBpbnQgcW9y aXFfdG11X3Jlc3VtZShzdHJ1Y3QgZGV2aWNlICpkZXYpIHsNCj4gPiA+ID4gPiArCXN0cnVjdCBx b3JpcV90bXVfZGF0YSAqZGF0YSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOw0KPiA+ID4gPiA+ICsN Cj4gPiA+ID4gPiArCS8qIEVuYWJsZSBtb25pdG9yaW5nICovDQo+ID4gPiA+ID4gKwlpb3dyaXRl MzJiZShUTVJfQUxMLCAmZGF0YS0+cmVncy0+dG1yKTsNCj4gPiA+ID4gPiArCWRhdGEtPm1vZGUg PSBUSEVSTUFMX0RFVklDRV9FTkFCTEVEOw0KPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiArCXJldHVy biAwOw0KPiA+ID4gPiA+ICt9DQo+ID4gPiA+ID4gKyNlbmRpZg0KPiA+ID4gPiA+ICsNCj4gPiA+ ID4gPiArc3RhdGljIFNJTVBMRV9ERVZfUE1fT1BTKHFvcmlxX3RtdV9wbV9vcHMsDQo+ID4gPiA+ ID4gKwkJCSBxb3JpcV90bXVfc3VzcGVuZCwgcW9yaXFfdG11X3Jlc3VtZSk7DQo+ID4gPiA+ID4g Kw0KPiA+ID4gPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBxb3JpcV90bXVf bWF0Y2hbXSA9IHsNCj4gPiA+ID4gPiArCXsgLmNvbXBhdGlibGUgPSAiZnNsLHFvcmlxLXRtdSIs IH0sDQo+ID4gPiA+ID4gKwl7fSwNCj4gPiA+ID4gPiArfTsNCj4gPiA+ID4gPiArDQo+ID4gPiA+ ID4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIHFvcmlxX3RtdSA9IHsNCj4gPiA+ID4g PiArCS5kcml2ZXIJPSB7DQo+ID4gPiA+ID4gKwkJLm93bmVyCQk9IFRISVNfTU9EVUxFLA0KPiA+ ID4gPiA+ICsJCS5uYW1lCQk9ICJxb3JpcV90aGVybWFsIiwNCj4gPiA+ID4gPiArCQkucG0gPSAm cW9yaXFfdG11X3BtX29wcywNCj4gPiA+ID4gPiArCQkub2ZfbWF0Y2hfdGFibGUJPSBxb3JpcV90 bXVfbWF0Y2gsDQo+ID4gPiA+ID4gKwl9LA0KPiA+ID4gPiA+ICsJLnByb2JlCT0gcW9yaXFfdG11 X3Byb2JlLA0KPiA+ID4gPiA+ICsJLnJlbW92ZQk9IHFvcmlxX3RtdV9yZW1vdmUsDQo+ID4gPiA+ ID4gK307DQo+ID4gPiA+ID4gK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIocW9yaXFfdG11KTsNCj4g PiA+ID4gPiArDQo+ID4gPiA+ID4gK01PRFVMRV9BVVRIT1IoIkppYSBIb25ndGFvIDxob25ndGFv LmppYUBmcmVlc2NhbGUuY29tPiIpOw0KPiA+ID4gPiA+ICtNT0RVTEVfREVTQ1JJUFRJT04oIkZy ZWVzY2FsZSBRb3JJUSBUaGVybWFsIE1vbml0b3JpbmcgVW5pdA0KPiA+ID4gPiA+ICtkcml2ZXIi KTsgTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOw0KPiA+ID4gPiA+IC0tDQo+ID4gPiA+ID4gMi4x LjAuMjcuZzk2ZGIzMjQNCj4gPiA+ID4gPg0KPiBfX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fXw0KPiBMaW51eHBwYy1kZXYgbWFpbGluZyBsaXN0DQo+IExpbnV4 cHBjLWRldkBsaXN0cy5vemxhYnMub3JnDQo+IGh0dHBzOi8vbGlzdHMub3psYWJzLm9yZy9saXN0 aW5mby9saW51eHBwYy1kZXYNCg== ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH V2] QorIQ/TMU: add thermal management support based on TMU 2015-08-14 3:15 ` Hongtao Jia @ 2015-08-14 4:29 ` Eduardo Valentin 2015-08-14 6:40 ` Hongtao Jia 0 siblings, 1 reply; 8+ messages in thread From: Eduardo Valentin @ 2015-08-14 4:29 UTC (permalink / raw) To: Hongtao Jia Cc: Scott Wood, linuxppc-dev@lists.ozlabs.org, linux-pm@vger.kernel.org Hello Hongtao, On Fri, Aug 14, 2015 at 03:15:22AM +0000, Hongtao Jia wrote: > Hi Eduardo, > > In previous mail I asked questions about including header files in device tree. > Don't bother, I have already figured out the solution. > > Another questions is about cpu cooling: > I found out that there is no explicit calling for registering cpu cooling > device in the of-thermal style drivers. Your understanding is correct. > > And Samsung did it in cpufreq driver: drivers/cpufreq/exynos-cpufreq.c > Yes. > Should all the of-thermal driver use the same way? of-thermal won't handle the cooling device registering. It is typically registered by the cpufreq driver. Have a look in drivers/cpufreq/cpufreq-dt.c > Or is there any recommendation for registering cpu cooling device? > (I enabled the CONFIG_CPUFREQ_DT and still got no cooling device registered) If your system supports using cpufreq-dt, then it will handle registering the cpucooling for you, if you configures the cooling dt properties in your DT files. How does your DT entry look like? BR, Eduardo > > Thanks. > > --- > Best Regards, > Hongtao > > > > -----Original Message----- > > From: Linuxppc-dev [mailto:linuxppc-dev- > > bounces+b38951=freescale.com@lists.ozlabs.org] On Behalf Of Hongtao Jia > > Sent: Friday, August 07, 2015 4:15 PM > > To: Eduardo Valentin > > Cc: Wood Scott-B07421; linuxppc-dev@lists.ozlabs.org; linux- > > pm@vger.kernel.org > > Subject: RE: [PATCH V2] QorIQ/TMU: add thermal management support based > > on TMU > > > > Thanks for your comments. > > Please see my questions inline. > > > > Thanks. > > --- > > Best Regards, > > Hongtao > > > > > > > -----Original Message----- > > > From: Eduardo Valentin [mailto:edubezval@gmail.com] > > > Sent: Thursday, August 06, 2015 3:43 AM > > > To: Jia Hongtao-B38951 > > > Cc: linux-pm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood > > > Scott- > > > B07421 > > > Subject: Re: [PATCH V2] QorIQ/TMU: add thermal management support > > > based on TMU > > > > > > On Thu, Jul 30, 2015 at 08:13:09AM +0000, Hongtao Jia wrote: > > > > - "Any specific reason why not using OF thermal?" > > > > - No, actually. > > > > > > > > I'd like to use OF thermal after some clarification. > > > > > > > > Regarding to "cooling-maps". For some cases there should be more > > > > than one cpus as cooling device and they are independent. > > > > 1. Let's say 4. So we need to provide 4 maps like map0-map3. Right? > > > > > > That would depend on the amount of sensors you have. Do you have one > > > sensor per cpu? if the answer is yes, then you probably want to have > > > four different map entries, yes, but one on each thermal zone of each > > > cpu temperature sensor. if the answer is no, then you would need to > > > have all the maps in the same thermal zone. > > > > > > > 2. "cooling-max-level" may vary depend on switch settings or firmware. > > > Is that > > > > OK if I do not provide "cooling-min-level" and "cooling-max-level" > > > property? > > > > > > That is already achievable by using the cooling-device property of a > > > cooling map. > > > > > > Please have a look in the example section of the > > > Documentation/devicetree/bindings/thermal/thermal.txt > > > > Yes, I read this file. > > So in my understanding: > > There is no need to provide "cooling-min-level" and "cooling-max-level" > > property. > > THERMAL_NO_LIMIT value in cooling device node will indicate the driver to > > automatically parse the min and max state, right? > > > > Talking about THERMAL_NO_LIMIT, I need to #include <dt- > > bindings/thermal/thermal.h> to provide the definition. But I got > > compiling error when build dtb file. > > I did some research and using "make t1040qds.dtb" in order to involve > > preprocessor. > > But with simply adding "#include <dt-bindings/thermal/thermal.h>" to > > t1040si-post.dtsi at line 35 I still got error like this: > > Error: arch/powerpc/boot/dts/fsl/t1040si-post.dtsi:35.1-9 syntax error > > FATAL ERROR: Unable to parse input tree > > > > Could you help me out here. > > Thanks. > > > > > > > > Let me know if you need further clarification. > > > > > > > > > BR, > > > > > > Eduardo Valentin > > > > > > > > > > > Thanks. > > > > -Hongtao > > > > > > > > > > > > > -----Original Message----- > > > > > From: Eduardo Valentin [mailto:edubezval@gmail.com] > > > > > Sent: Thursday, July 30, 2015 2:56 PM > > > > > To: Jia Hongtao-B38951 > > > > > Cc: linux-pm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood > > > > > Scott- > > > > > B07421 > > > > > Subject: Re: [PATCH V2] QorIQ/TMU: add thermal management support > > > > > based on TMU > > > > > > > > > > On Wed, Jul 29, 2015 at 02:19:39PM +0800, Jia Hongtao wrote: > > > > > > It supports one critical trip point and one passive trip point. > > > > > > The cpufreq is used as the cooling device to throttle CPUs when > > > > > > the passive trip is crossed. > > > > > > > > > > > > Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com> > > > > > > --- > > > > > > This patch based on: > > > > > > http://patchwork.ozlabs.org/patch/482987/ > > > > > > > > > > > > Changes for V2: > > > > > > * Add tmu-range parse. > > > > > > * Use default trend hook. > > > > > > * Using latest thermal_zone_bind_cooling_device API. > > > > > > * Add calibration check during initialization. > > > > > > * Disable/enalbe device when suspend/resume. > > > > > > > > > > > > drivers/thermal/Kconfig | 11 ++ > > > > > > drivers/thermal/Makefile | 1 + > > > > > > drivers/thermal/qoriq_thermal.c | 406 > > > > > > ++++++++++++++++++++++++++++++++++++++++ > > > > > > 3 files changed, 418 insertions(+) create mode 100644 > > > > > > drivers/thermal/qoriq_thermal.c > > > > > > > > > > > > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig > > > > > > index > > > > > > 118938e..a200745 100644 > > > > > > --- a/drivers/thermal/Kconfig > > > > > > +++ b/drivers/thermal/Kconfig > > > > > > @@ -180,6 +180,17 @@ config IMX_THERMAL > > > > > > cpufreq is used as the cooling device to throttle CPUs when > > > the > > > > > > passive trip is crossed. > > > > > > > > > > > > +config QORIQ_THERMAL > > > > > > + tristate "Freescale QorIQ Thermal Monitoring Unit" > > > > > > + depends on CPU_THERMAL > > > > > > + depends on OF > > > > > > + default n > > > > > > + help > > > > > > + Enable thermal management based on Freescale QorIQ Thermal > > > > > Monitoring > > > > > > + Unit (TMU). It supports one critical trip point and one > > > > > > +passive > > > > > trip > > > > > > + point. The cpufreq is used as the cooling device to > > > throttle > > > > > > +CPUs > > > > > when > > > > > > + the passive trip is crossed. > > > > > > + > > > > > > config SPEAR_THERMAL > > > > > > bool "SPEAr thermal sensor driver" > > > > > > depends on PLAT_SPEAR > > > > > > diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile > > > > > > index > > > > > > 535dfee..8c25859 100644 > > > > > > --- a/drivers/thermal/Makefile > > > > > > +++ b/drivers/thermal/Makefile > > > > > > @@ -33,6 +33,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_QORIQ_THERMAL) += qoriq_thermal.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/qoriq_thermal.c > > > > > > b/drivers/thermal/qoriq_thermal.c new file mode 100644 index > > > > > > 0000000..0694f42 > > > > > > --- /dev/null > > > > > > +++ b/drivers/thermal/qoriq_thermal.c > > > > > > @@ -0,0 +1,406 @@ > > > > > > +/* > > > > > > + * Copyright 2015 Freescale Semiconductor, Inc. > > > > > > + * > > > > > > + * 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. > > > > > > + * > > > > > > + * This program is distributed in the hope 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. > > > > > > + * > > > > > > + */ > > > > > > + > > > > > > +/* > > > > > > + * Based on Freescale QorIQ Thermal Monitoring Unit (TMU) */ > > > > > > +#include <linux/cpufreq.h> #include <linux/cpu_cooling.h> > > > > > > +#include <linux/module.h> #include <linux/platform_device.h> > > > > > > +#include <linux/err.h> #include <linux/io.h> #include > > > > > > +<linux/of.h> #include <linux/of_address.h> #include > > > > > > +<linux/thermal.h> > > > > > > + > > > > > > +#define SITES_MAX 16 > > > > > > + > > > > > > +#define TMU_TEMP_PASSIVE 85000 > > > > > > +#define TMU_TEMP_CRITICAL 95000 > > > > > > + > > > > > > +#define TMU_PASSIVE_DELAY 1000 /* Milliseconds */ > > > > > > +#define TMU_POLLING_DELAY 5000 > > > > > > + > > > > > > +/* The driver supports 1 passive trip point and 1 critical trip > > > > > > +point */ enum tmu_thermal_trip { > > > > > > + TMU_TRIP_PASSIVE, > > > > > > + TMU_TRIP_CRITICAL, > > > > > > + TMU_TRIP_NUM, > > > > > > +}; > > > > > > + > > > > > > +/* > > > > > > + * QorIQ TMU Registers > > > > > > + */ > > > > > > +struct qoriq_tmu_site_regs { > > > > > > + __be32 tritsr; /* Immediate Temperature Site > > > Register */ > > > > > > + __be32 tratsr; /* Average Temperature Site Register > > > */ > > > > > > + u8 res0[0x8]; > > > > > > +} __packed; > > > > > > + > > > > > > +struct qoriq_tmu_regs { > > > > > > + __be32 tmr; /* Mode Register */ > > > > > > +#define TMR_DISABLE 0x0 > > > > > > +#define TMR_ME 0x80000000 > > > > > > +#define TMR_ALPF 0x0c000000 > > > > > > +#define TMR_MSITE 0x00008000 > > > > > > +#define TMR_ALL (TMR_ME | TMR_ALPF | TMR_MSITE) > > > > > > + __be32 tsr; /* Status Register */ > > > > > > + __be32 tmtmir; /* Temperature measurement interval > > > > > Register */ > > > > > > +#define TMTMIR_DEFAULT 0x00000007 > > > > > > + u8 res0[0x14]; > > > > > > + __be32 tier; /* Interrupt Enable Register */ > > > > > > +#define TIER_DISABLE 0x0 > > > > > > + __be32 tidr; /* Interrupt Detect Register */ > > > > > > + __be32 tiscr; /* Interrupt Site Capture Register */ > > > > > > + __be32 ticscr; /* Interrupt Critical Site Capture > > > Register > > > > > */ > > > > > > + u8 res1[0x10]; > > > > > > + __be32 tmhtcrh; /* High Temperature Capture Register > > > */ > > > > > > + __be32 tmhtcrl; /* Low Temperature Capture Register > > > */ > > > > > > + u8 res2[0x8]; > > > > > > + __be32 tmhtitr; /* High Temperature Immediate > > > Threshold */ > > > > > > + __be32 tmhtatr; /* High Temperature Average Threshold > > > */ > > > > > > + __be32 tmhtactr; /* High Temperature Average Crit Threshold > > > */ > > > > > > + u8 res3[0x24]; > > > > > > + __be32 ttcfgr; /* Temperature Configuration Register > > > */ > > > > > > + __be32 tscfgr; /* Sensor Configuration Register */ > > > > > > + u8 res4[0x78]; > > > > > > + struct qoriq_tmu_site_regs site[SITES_MAX]; > > > > > > + u8 res5[0x9f8]; > > > > > > + __be32 ipbrr0; /* IP Block Revision Register 0 */ > > > > > > + __be32 ipbrr1; /* IP Block Revision Register 1 */ > > > > > > + u8 res6[0x310]; > > > > > > + __be32 ttr0cr; /* Temperature Range 0 Control > > > Register */ > > > > > > + __be32 ttr1cr; /* Temperature Range 1 Control > > > Register */ > > > > > > + __be32 ttr2cr; /* Temperature Range 2 Control > > > Register */ > > > > > > + __be32 ttr3cr; /* Temperature Range 3 Control > > > Register */ > > > > > > +}; > > > > > > + > > > > > > +/* > > > > > > + * Thermal zone data > > > > > > + */ > > > > > > +struct qoriq_tmu_data { > > > > > > + struct thermal_zone_device *tz; > > > > > > + struct thermal_cooling_device *cdev; > > > > > > + enum thermal_device_mode mode; > > > > > > + unsigned long temp_passive; > > > > > > + unsigned long temp_critical; > > > > > > + struct qoriq_tmu_regs __iomem *regs; }; > > > > > > + > > > > > > +static int tmu_get_mode(struct thermal_zone_device *tz, > > > > > > + enum thermal_device_mode *mode) { > > > > > > + struct qoriq_tmu_data *data = tz->devdata; > > > > > > + > > > > > > + *mode = data->mode; > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +static int tmu_set_mode(struct thermal_zone_device *tz, > > > > > > + enum thermal_device_mode mode) { > > > > > > + struct qoriq_tmu_data *data = tz->devdata; > > > > > > + > > > > > > + if (mode == THERMAL_DEVICE_ENABLED) { > > > > > > + tz->polling_delay = TMU_POLLING_DELAY; > > > > > > + tz->passive_delay = TMU_PASSIVE_DELAY; > > > > > > + thermal_zone_device_update(tz); > > > > > > + } else { > > > > > > + tz->polling_delay = 0; > > > > > > + tz->passive_delay = 0; > > > > > > + } > > > > > > + > > > > > > + data->mode = mode; > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +static int tmu_get_temp(struct thermal_zone_device *tz, > > > > > > +unsigned long > > > > > > +*temp) { > > > > > > + u8 val; > > > > > > + struct qoriq_tmu_data *data = tz->devdata; > > > > > > + > > > > > > + val = ioread32be(&data->regs->site[0].tritsr); > > > > > > + *temp = (unsigned long)val * 1000; > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +static int tmu_get_trip_type(struct thermal_zone_device *tz, > > > > > > +int > > > trip, > > > > > > + enum thermal_trip_type *type) { > > > > > > + *type = (trip == TMU_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE : > > > > > > + THERMAL_TRIP_CRITICAL; > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +static int tmu_get_trip_temp(struct thermal_zone_device *tz, > > > > > > +int > > > trip, > > > > > > + unsigned long *temp) > > > > > > +{ > > > > > > + struct qoriq_tmu_data *data = tz->devdata; > > > > > > + > > > > > > + *temp = (trip == TMU_TRIP_PASSIVE) ? data->temp_passive : > > > > > > + data->temp_critical; > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +static int tmu_get_crit_temp(struct thermal_zone_device *tz, > > > > > > + unsigned long *temp) > > > > > > +{ > > > > > > + struct qoriq_tmu_data *data = tz->devdata; > > > > > > + > > > > > > + *temp = data->temp_critical; > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +static int tmu_bind(struct thermal_zone_device *tz, > > > > > > + struct thermal_cooling_device *cdev) { > > > > > > + int ret; > > > > > > + > > > > > > + ret = thermal_zone_bind_cooling_device(tz, TMU_TRIP_PASSIVE, > > > cdev, > > > > > > + THERMAL_NO_LIMIT, > > > > > > + THERMAL_NO_LIMIT, > > > > > > + THERMAL_WEIGHT_DEFAULT); > > > > > > + if (ret) { > > > > > > + dev_err(&tz->device, > > > > > > + "Binding zone %s with cdev %s failed:%d\n", > > > > > > + tz->type, cdev->type, ret); > > > > > > + } > > > > > > + > > > > > > + return ret; > > > > > > +} > > > > > > + > > > > > > +static int tmu_unbind(struct thermal_zone_device *tz, > > > > > > + struct thermal_cooling_device *cdev) { > > > > > > + int ret; > > > > > > + > > > > > > + ret = thermal_zone_unbind_cooling_device(tz, TMU_TRIP_PASSIVE, > > > > > cdev); > > > > > > + if (ret) { > > > > > > + dev_err(&tz->device, > > > > > > + "Unbinding zone %s with cdev %s failed:%d\n", > > > > > > + tz->type, cdev->type, ret); > > > > > > + } > > > > > > + > > > > > > + return ret; > > > > > > +} > > > > > > + > > > > > > +static int qoriq_tmu_calibration(struct platform_device *pdev) { > > > > > > + int i, val, len; > > > > > > + u32 range[4]; > > > > > > + const __be32 *calibration; > > > > > > + struct device_node *node = pdev->dev.of_node; > > > > > > + struct qoriq_tmu_data *data = dev_get_drvdata(&pdev->dev); > > > > > > + > > > > > > + /* Disable monitoring before calibration */ > > > > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > > > > + > > > > > > + if (of_property_read_u32_array(node, "fsl,tmu-range", range, > > > 4)) > > > > > > + return -1; > > > > > > + > > > > > > + /* Init temperature range registers */ > > > > > > + iowrite32be(range[0], &data->regs->ttr0cr); > > > > > > + iowrite32be(range[1], &data->regs->ttr1cr); > > > > > > + iowrite32be(range[2], &data->regs->ttr2cr); > > > > > > + iowrite32be(range[3], &data->regs->ttr3cr); > > > > > > + > > > > > > + calibration = of_get_property(node, "fsl,tmu-calibration", > > > &len); > > > > > > + if (calibration == NULL) > > > > > > + return -1; > > > > > > + > > > > > > + for (i = 0; i < len; i += 8, calibration += 2) { > > > > > > + val = (int)of_read_number(calibration, 1); > > > > > > + iowrite32be(val, &data->regs->ttcfgr); > > > > > > + val = (int)of_read_number(calibration + 1, 1); > > > > > > + iowrite32be(val, &data->regs->tscfgr); > > > > > > + } > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) { > > > > > > + /* Disable interrupt, using polling instead */ > > > > > > + iowrite32be(TIER_DISABLE, &data->regs->tier); > > > > > > + > > > > > > + /* Set update_interval */ > > > > > > + iowrite32be(TMTMIR_DEFAULT, &data->regs->tmtmir); > > > > > > + > > > > > > + /* Enable monitoring */ > > > > > > + iowrite32be(TMR_ALL, &data->regs->tmr); } > > > > > > + > > > > > > +static struct thermal_zone_device_ops tmu_tz_ops = { > > > > > > + .bind = tmu_bind, > > > > > > + .unbind = tmu_unbind, > > > > > > + .get_temp = tmu_get_temp, > > > > > > + .get_mode = tmu_get_mode, > > > > > > + .set_mode = tmu_set_mode, > > > > > > + .get_trip_type = tmu_get_trip_type, > > > > > > + .get_trip_temp = tmu_get_trip_temp, > > > > > > + .get_crit_temp = tmu_get_crit_temp, }; > > > > > > + > > > > > > +static int qoriq_tmu_probe(struct platform_device *pdev) { > > > > > > + int ret; > > > > > > + struct cpumask clip_cpus; > > > > > > + struct qoriq_tmu_data *data; > > > > > > + > > > > > > + if (!cpufreq_get_current_driver()) { > > > > > > + dev_dbg(&pdev->dev, "No cpufreq driver yet\n"); > > > > > > + return -EPROBE_DEFER; > > > > > > + } > > > > > > + > > > > > > + if (!pdev->dev.of_node) { > > > > > > + dev_err(&pdev->dev, "Device OF-Node is NULL"); > > > > > > + return -EFAULT; > > > > > > + } > > > > > > + > > > > > > + data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data), > > > > > > + GFP_KERNEL); > > > > > > + if (!data) > > > > > > + return -ENOMEM; > > > > > > + > > > > > > + dev_set_drvdata(&pdev->dev, data); > > > > > > + data->regs = of_iomap(pdev->dev.of_node, 0); > > > > > > + > > > > > > + if (!data->regs) { > > > > > > + dev_err(&pdev->dev, "Failed to get memory region\n"); > > > > > > + ret = -ENODEV; > > > > > > + goto err_iomap; > > > > > > + } > > > > > > + > > > > > > + ret = qoriq_tmu_calibration(pdev); /* TMU calibration */ > > > > > > + if (ret < 0) { > > > > > > + dev_err(&pdev->dev, "TMU calibration failed.\n"); > > > > > > + ret = -ENODEV; > > > > > > + goto err_iomap; > > > > > > + } > > > > > > + > > > > > > + qoriq_tmu_init_device(data); /* TMU initialization */ > > > > > > + > > > > > > + cpumask_setall(&clip_cpus); > > > > > > + data->cdev = cpufreq_cooling_register(&clip_cpus); > > > > > > + if (IS_ERR(data->cdev)) { > > > > > > + ret = PTR_ERR(data->cdev); > > > > > > + dev_err(&data->cdev->device, > > > > > > + "Failed to register cpufreq cooling device: %d\n", > > > ret); > > > > > > + goto err_cooling; > > > > > > + } > > > > > > + > > > > > > + data->temp_passive = TMU_TEMP_PASSIVE; > > > > > > + data->temp_critical = TMU_TEMP_CRITICAL; > > > > > > + data->tz = thermal_zone_device_register("tmu_thermal_zone", > > > > > > > > > > Any specific reason why not using OF thermal? > > > > > > > > > > > + TMU_TRIP_NUM, > > > > > > + 0, data, > > > > > > + &tmu_tz_ops, NULL, > > > > > > + TMU_PASSIVE_DELAY, > > > > > > + TMU_POLLING_DELAY); > > > > > > + > > > > > > + if (IS_ERR(data->tz)) { > > > > > > + ret = PTR_ERR(data->tz); > > > > > > + dev_err(&pdev->dev, > > > > > > + "Failed to register thermal zone device %d\n", > > > ret); > > > > > > + goto err_thermal; > > > > > > + } > > > > > > + > > > > > > + data->mode = THERMAL_DEVICE_ENABLED; > > > > > > + > > > > > > + return 0; > > > > > > + > > > > > > +err_thermal: > > > > > > + cpufreq_cooling_unregister(data->cdev); > > > > > > + > > > > > > +err_cooling: > > > > > > + iounmap(data->regs); > > > > > > + > > > > > > +err_iomap: > > > > > > + dev_set_drvdata(&pdev->dev, NULL); > > > > > > + devm_kfree(&pdev->dev, data); > > > > > > + > > > > > > + return ret; > > > > > > +} > > > > > > + > > > > > > +static int qoriq_tmu_remove(struct platform_device *pdev) { > > > > > > + struct qoriq_tmu_data *data = dev_get_drvdata(&pdev->dev); > > > > > > + > > > > > > + /* Disable monitoring */ > > > > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > > > > + > > > > > > + thermal_zone_device_unregister(data->tz); > > > > > > + cpufreq_cooling_unregister(data->cdev); > > > > > > + iounmap(data->regs); > > > > > > + > > > > > > + dev_set_drvdata(&pdev->dev, NULL); > > > > > > + devm_kfree(&pdev->dev, data); > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +#ifdef CONFIG_PM_SLEEP > > > > > > +static int qoriq_tmu_suspend(struct device *dev) { > > > > > > + struct qoriq_tmu_data *data = dev_get_drvdata(dev); > > > > > > + > > > > > > + /* Disable monitoring */ > > > > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > > > > + data->mode = THERMAL_DEVICE_DISABLED; > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +static int qoriq_tmu_resume(struct device *dev) { > > > > > > + struct qoriq_tmu_data *data = dev_get_drvdata(dev); > > > > > > + > > > > > > + /* Enable monitoring */ > > > > > > + iowrite32be(TMR_ALL, &data->regs->tmr); > > > > > > + data->mode = THERMAL_DEVICE_ENABLED; > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > +#endif > > > > > > + > > > > > > +static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops, > > > > > > + qoriq_tmu_suspend, qoriq_tmu_resume); > > > > > > + > > > > > > +static const struct of_device_id qoriq_tmu_match[] = { > > > > > > + { .compatible = "fsl,qoriq-tmu", }, > > > > > > + {}, > > > > > > +}; > > > > > > + > > > > > > +static struct platform_driver qoriq_tmu = { > > > > > > + .driver = { > > > > > > + .owner = THIS_MODULE, > > > > > > + .name = "qoriq_thermal", > > > > > > + .pm = &qoriq_tmu_pm_ops, > > > > > > + .of_match_table = qoriq_tmu_match, > > > > > > + }, > > > > > > + .probe = qoriq_tmu_probe, > > > > > > + .remove = qoriq_tmu_remove, > > > > > > +}; > > > > > > +module_platform_driver(qoriq_tmu); > > > > > > + > > > > > > +MODULE_AUTHOR("Jia Hongtao <hongtao.jia@freescale.com>"); > > > > > > +MODULE_DESCRIPTION("Freescale QorIQ Thermal Monitoring Unit > > > > > > +driver"); MODULE_LICENSE("GPL v2"); > > > > > > -- > > > > > > 2.1.0.27.g96db324 > > > > > > > > _______________________________________________ > > Linuxppc-dev mailing list > > Linuxppc-dev@lists.ozlabs.org > > https://lists.ozlabs.org/listinfo/linuxppc-dev ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH V2] QorIQ/TMU: add thermal management support based on TMU 2015-08-14 4:29 ` Eduardo Valentin @ 2015-08-14 6:40 ` Hongtao Jia 0 siblings, 0 replies; 8+ messages in thread From: Hongtao Jia @ 2015-08-14 6:40 UTC (permalink / raw) To: Eduardo Valentin Cc: Scott Wood, linuxppc-dev@lists.ozlabs.org, linux-pm@vger.kernel.org > -----Original Message----- > From: Eduardo Valentin [mailto:edubezval@gmail.com] > Sent: Friday, August 14, 2015 12:29 PM > To: Jia Hongtao-B38951 > Cc: Wood Scott-B07421; linuxppc-dev@lists.ozlabs.org; linux- > pm@vger.kernel.org > Subject: Re: [PATCH V2] QorIQ/TMU: add thermal management support based > on TMU >=20 > Hello Hongtao, >=20 > On Fri, Aug 14, 2015 at 03:15:22AM +0000, Hongtao Jia wrote: > > Hi Eduardo, > > > > In previous mail I asked questions about including header files in > device tree. > > Don't bother, I have already figured out the solution. > > > > Another questions is about cpu cooling: > > I found out that there is no explicit calling for registering cpu > > cooling device in the of-thermal style drivers. >=20 > Your understanding is correct. >=20 > > > > And Samsung did it in cpufreq driver: drivers/cpufreq/exynos-cpufreq.c > > >=20 > Yes. >=20 > > Should all the of-thermal driver use the same way? >=20 > of-thermal won't handle the cooling device registering. It is typically > registered by the cpufreq driver. Have a look in > drivers/cpufreq/cpufreq-dt.c >=20 > > Or is there any recommendation for registering cpu cooling device? > > (I enabled the CONFIG_CPUFREQ_DT and still got no cooling device > > registered) >=20 > If your system supports using cpufreq-dt, then it will handle registering > the cpucooling for you, if you configures the cooling dt properties in > your DT files. >=20 > How does your DT entry look like? Here is the related code snippet: cpus { #address-cells =3D <1>; #size-cells =3D <0>; cpu0: PowerPC,e5500@0 { device_type =3D "cpu"; reg =3D <0>; clocks =3D <&mux0>; next-level-cache =3D <&L2_1>; /*cooling-min-level =3D <0>;*/ /*cooling-max-level =3D <1>;*/ #cooling-cells =3D <2>; L2_1: l2-cache { next-level-cache =3D <&cpc>; }; }; cpu1: PowerPC,e5500@1 { device_type =3D "cpu"; reg =3D <1>; clocks =3D <&mux1>; next-level-cache =3D <&L2_2>; /*cooling-min-level =3D <0>;*/ /*cooling-max-level =3D <1>;*/ #cooling-cells =3D <2>; L2_2: l2-cache { next-level-cache =3D <&cpc>; }; }; cpu2: PowerPC,e5500@2 { device_type =3D "cpu"; reg =3D <2>; clocks =3D <&mux2>; next-level-cache =3D <&L2_3>; /*cooling-min-level =3D <0>;*/ /*cooling-max-level =3D <1>;*/ #cooling-cells =3D <2>; L2_3: l2-cache { next-level-cache =3D <&cpc>; }; }; cpu3: PowerPC,e5500@3 { device_type =3D "cpu"; reg =3D <3>; clocks =3D <&mux3>; next-level-cache =3D <&L2_4>; /*cooling-min-level =3D <0>;*/ /*cooling-max-level =3D <1>;*/ #cooling-cells =3D <2>; L2_4: l2-cache { next-level-cache =3D <&cpc>; }; }; ...... thermal-zones { cpu_thermal: cpu-thermal { polling-delay-passive =3D <1000>; polling-delay =3D <5000>; thermal-sensors =3D <&tmu>; trips { cpu_alert: cpu-alert { temperature =3D <45000>; hysteresis =3D <2000>; type =3D "passive"; }; cpu_crit: cpu-crit { temperature =3D <95000>; hysteresis =3D <2000>; type =3D "critical"; }; }; cooling-maps { map0 { trip =3D <&cpu_alert>; cooling-device =3D <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; }; map1 { trip =3D <&cpu_alert>; cooling-device =3D <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; }; map2 { trip =3D <&cpu_alert>; cooling-device =3D <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; }; map3 { trip =3D <&cpu_alert>; cooling-device =3D <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; }; }; }; }; Please note that I comment out the cooling-min-level and cooling-max-level property. I'd like to let cpufreq driver parse these two property. I don't quite clear if this is OK. You said if the system support cpufreq-dt it will handle the cooling device registration. Then how to support cpufreq-dt? Do I need to update qoriq-cpufreq.c? Do you have a quick answer for me? Thanks. -Hongtao. >=20 > BR, >=20 > Eduardo > > > > Thanks. > > > > --- > > Best Regards, > > Hongtao > > > > > > > -----Original Message----- > > > From: Linuxppc-dev [mailto:linuxppc-dev- > > > bounces+b38951=3Dfreescale.com@lists.ozlabs.org] On Behalf Of Hongtao > > > bounces+Jia > > > Sent: Friday, August 07, 2015 4:15 PM > > > To: Eduardo Valentin > > > Cc: Wood Scott-B07421; linuxppc-dev@lists.ozlabs.org; linux- > > > pm@vger.kernel.org > > > Subject: RE: [PATCH V2] QorIQ/TMU: add thermal management support > > > based on TMU > > > > > > Thanks for your comments. > > > Please see my questions inline. > > > > > > Thanks. > > > --- > > > Best Regards, > > > Hongtao > > > > > > > > > > -----Original Message----- > > > > From: Eduardo Valentin [mailto:edubezval@gmail.com] > > > > Sent: Thursday, August 06, 2015 3:43 AM > > > > To: Jia Hongtao-B38951 > > > > Cc: linux-pm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood > > > > Scott- > > > > B07421 > > > > Subject: Re: [PATCH V2] QorIQ/TMU: add thermal management support > > > > based on TMU > > > > > > > > On Thu, Jul 30, 2015 at 08:13:09AM +0000, Hongtao Jia wrote: > > > > > - "Any specific reason why not using OF thermal?" > > > > > - No, actually. > > > > > > > > > > I'd like to use OF thermal after some clarification. > > > > > > > > > > Regarding to "cooling-maps". For some cases there should be more > > > > > than one cpus as cooling device and they are independent. > > > > > 1. Let's say 4. So we need to provide 4 maps like map0-map3. > Right? > > > > > > > > That would depend on the amount of sensors you have. Do you have > > > > one sensor per cpu? if the answer is yes, then you probably want > > > > to have four different map entries, yes, but one on each thermal > > > > zone of each cpu temperature sensor. if the answer is no, then you > > > > would need to have all the maps in the same thermal zone. > > > > > > > > > 2. "cooling-max-level" may vary depend on switch settings or > firmware. > > > > Is that > > > > > OK if I do not provide "cooling-min-level" and "cooling-max- > level" > > > > property? > > > > > > > > That is already achievable by using the cooling-device property of > > > > a cooling map. > > > > > > > > Please have a look in the example section of the > > > > Documentation/devicetree/bindings/thermal/thermal.txt > > > > > > Yes, I read this file. > > > So in my understanding: > > > There is no need to provide "cooling-min-level" and "cooling-max- > level" > > > property. > > > THERMAL_NO_LIMIT value in cooling device node will indicate the > > > driver to automatically parse the min and max state, right? > > > > > > Talking about THERMAL_NO_LIMIT, I need to #include <dt- > > > bindings/thermal/thermal.h> to provide the definition. But I got > > > compiling error when build dtb file. > > > I did some research and using "make t1040qds.dtb" in order to > > > involve preprocessor. > > > But with simply adding "#include <dt-bindings/thermal/thermal.h>" to > > > t1040si-post.dtsi at line 35 I still got error like this: > > > Error: arch/powerpc/boot/dts/fsl/t1040si-post.dtsi:35.1-9 syntax > > > error FATAL ERROR: Unable to parse input tree > > > > > > Could you help me out here. > > > Thanks. > > > > > > > > > > > Let me know if you need further clarification. > > > > > > > > > > > > BR, > > > > > > > > Eduardo Valentin > > > > > > > > > > > > > > Thanks. > > > > > -Hongtao > > > > > > > > > > > > > > > > -----Original Message----- > > > > > > From: Eduardo Valentin [mailto:edubezval@gmail.com] > > > > > > Sent: Thursday, July 30, 2015 2:56 PM > > > > > > To: Jia Hongtao-B38951 > > > > > > Cc: linux-pm@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; > > > > > > Wood > > > > > > Scott- > > > > > > B07421 > > > > > > Subject: Re: [PATCH V2] QorIQ/TMU: add thermal management > > > > > > support based on TMU > > > > > > > > > > > > On Wed, Jul 29, 2015 at 02:19:39PM +0800, Jia Hongtao wrote: > > > > > > > It supports one critical trip point and one passive trip > point. > > > > > > > The cpufreq is used as the cooling device to throttle CPUs > > > > > > > when the passive trip is crossed. > > > > > > > > > > > > > > Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com> > > > > > > > --- > > > > > > > This patch based on: > > > > > > > http://patchwork.ozlabs.org/patch/482987/ > > > > > > > > > > > > > > Changes for V2: > > > > > > > * Add tmu-range parse. > > > > > > > * Use default trend hook. > > > > > > > * Using latest thermal_zone_bind_cooling_device API. > > > > > > > * Add calibration check during initialization. > > > > > > > * Disable/enalbe device when suspend/resume. > > > > > > > > > > > > > > drivers/thermal/Kconfig | 11 ++ > > > > > > > drivers/thermal/Makefile | 1 + > > > > > > > drivers/thermal/qoriq_thermal.c | 406 > > > > > > > ++++++++++++++++++++++++++++++++++++++++ > > > > > > > 3 files changed, 418 insertions(+) create mode 100644 > > > > > > > drivers/thermal/qoriq_thermal.c > > > > > > > > > > > > > > diff --git a/drivers/thermal/Kconfig > > > > > > > b/drivers/thermal/Kconfig index > > > > > > > 118938e..a200745 100644 > > > > > > > --- a/drivers/thermal/Kconfig > > > > > > > +++ b/drivers/thermal/Kconfig > > > > > > > @@ -180,6 +180,17 @@ config IMX_THERMAL > > > > > > > cpufreq is used as the cooling device to throttle > CPUs > > > > > > > when > > > > the > > > > > > > passive trip is crossed. > > > > > > > > > > > > > > +config QORIQ_THERMAL > > > > > > > + tristate "Freescale QorIQ Thermal Monitoring Unit" > > > > > > > + depends on CPU_THERMAL > > > > > > > + depends on OF > > > > > > > + default n > > > > > > > + help > > > > > > > + Enable thermal management based on Freescale QorIQ > > > > > > > +Thermal > > > > > > Monitoring > > > > > > > + Unit (TMU). It supports one critical trip point and > one > > > > > > > +passive > > > > > > trip > > > > > > > + point. The cpufreq is used as the cooling device to > > > > throttle > > > > > > > +CPUs > > > > > > when > > > > > > > + the passive trip is crossed. > > > > > > > + > > > > > > > config SPEAR_THERMAL > > > > > > > bool "SPEAr thermal sensor driver" > > > > > > > depends on PLAT_SPEAR > > > > > > > diff --git a/drivers/thermal/Makefile > > > > > > > b/drivers/thermal/Makefile index > > > > > > > 535dfee..8c25859 100644 > > > > > > > --- a/drivers/thermal/Makefile > > > > > > > +++ b/drivers/thermal/Makefile > > > > > > > @@ -33,6 +33,7 @@ obj-$(CONFIG_DOVE_THERMAL) +=3D > > > dove_thermal.o > > > > > > > obj-$(CONFIG_DB8500_THERMAL) +=3D db8500_thermal.o > > > > > > > obj-$(CONFIG_ARMADA_THERMAL) +=3D armada_thermal.o > > > > > > > obj-$(CONFIG_IMX_THERMAL) +=3D imx_thermal.o > > > > > > > +obj-$(CONFIG_QORIQ_THERMAL) +=3D qoriq_thermal.o > > > > > > > obj-$(CONFIG_DB8500_CPUFREQ_COOLING) +=3D > > > > db8500_cpufreq_cooling.o > > > > > > > obj-$(CONFIG_INTEL_POWERCLAMP) +=3D intel_powerclamp.o > > > > > > > obj-$(CONFIG_X86_PKG_TEMP_THERMAL) +=3D x86_pkg_temp_thermal= .o > > > > > > > diff --git a/drivers/thermal/qoriq_thermal.c > > > > > > > b/drivers/thermal/qoriq_thermal.c new file mode 100644 index > > > > > > > 0000000..0694f42 > > > > > > > --- /dev/null > > > > > > > +++ b/drivers/thermal/qoriq_thermal.c > > > > > > > @@ -0,0 +1,406 @@ > > > > > > > +/* > > > > > > > + * Copyright 2015 Freescale Semiconductor, Inc. > > > > > > > + * > > > > > > > + * 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. > > > > > > > + * > > > > > > > + * This program is distributed in the hope 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. > > > > > > > + * > > > > > > > + */ > > > > > > > + > > > > > > > +/* > > > > > > > + * Based on Freescale QorIQ Thermal Monitoring Unit (TMU) > > > > > > > +*/ #include <linux/cpufreq.h> #include > > > > > > > +<linux/cpu_cooling.h> #include <linux/module.h> #include > > > > > > > +<linux/platform_device.h> #include <linux/err.h> #include > > > > > > > +<linux/io.h> #include <linux/of.h> #include > > > > > > > +<linux/of_address.h> #include <linux/thermal.h> > > > > > > > + > > > > > > > +#define SITES_MAX 16 > > > > > > > + > > > > > > > +#define TMU_TEMP_PASSIVE 85000 > > > > > > > +#define TMU_TEMP_CRITICAL 95000 > > > > > > > + > > > > > > > +#define TMU_PASSIVE_DELAY 1000 /* Milliseconds */ > > > > > > > +#define TMU_POLLING_DELAY 5000 > > > > > > > + > > > > > > > +/* The driver supports 1 passive trip point and 1 critical > > > > > > > +trip point */ enum tmu_thermal_trip { > > > > > > > + TMU_TRIP_PASSIVE, > > > > > > > + TMU_TRIP_CRITICAL, > > > > > > > + TMU_TRIP_NUM, > > > > > > > +}; > > > > > > > + > > > > > > > +/* > > > > > > > + * QorIQ TMU Registers > > > > > > > + */ > > > > > > > +struct qoriq_tmu_site_regs { > > > > > > > + __be32 tritsr; /* Immediate Temperature Site > > > > Register */ > > > > > > > + __be32 tratsr; /* Average Temperature Site > Register > > > > */ > > > > > > > + u8 res0[0x8]; > > > > > > > +} __packed; > > > > > > > + > > > > > > > +struct qoriq_tmu_regs { > > > > > > > + __be32 tmr; /* Mode Register */ > > > > > > > +#define TMR_DISABLE 0x0 > > > > > > > +#define TMR_ME 0x80000000 > > > > > > > +#define TMR_ALPF 0x0c000000 > > > > > > > +#define TMR_MSITE 0x00008000 > > > > > > > +#define TMR_ALL (TMR_ME | TMR_ALPF | TMR_MSITE) > > > > > > > + __be32 tsr; /* Status Register */ > > > > > > > + __be32 tmtmir; /* Temperature measurement > interval > > > > > > Register */ > > > > > > > +#define TMTMIR_DEFAULT 0x00000007 > > > > > > > + u8 res0[0x14]; > > > > > > > + __be32 tier; /* Interrupt Enable Register */ > > > > > > > +#define TIER_DISABLE 0x0 > > > > > > > + __be32 tidr; /* Interrupt Detect Register */ > > > > > > > + __be32 tiscr; /* Interrupt Site Capture > Register */ > > > > > > > + __be32 ticscr; /* Interrupt Critical Site > Capture > > > > Register > > > > > > */ > > > > > > > + u8 res1[0x10]; > > > > > > > + __be32 tmhtcrh; /* High Temperature Capture > Register > > > > */ > > > > > > > + __be32 tmhtcrl; /* Low Temperature Capture > Register > > > > */ > > > > > > > + u8 res2[0x8]; > > > > > > > + __be32 tmhtitr; /* High Temperature Immediate > > > > Threshold */ > > > > > > > + __be32 tmhtatr; /* High Temperature Average > Threshold > > > > */ > > > > > > > + __be32 tmhtactr; /* High Temperature Average Crit > Threshold > > > > */ > > > > > > > + u8 res3[0x24]; > > > > > > > + __be32 ttcfgr; /* Temperature Configuration > Register > > > > */ > > > > > > > + __be32 tscfgr; /* Sensor Configuration > Register */ > > > > > > > + u8 res4[0x78]; > > > > > > > + struct qoriq_tmu_site_regs site[SITES_MAX]; > > > > > > > + u8 res5[0x9f8]; > > > > > > > + __be32 ipbrr0; /* IP Block Revision Register 0 > */ > > > > > > > + __be32 ipbrr1; /* IP Block Revision Register 1 > */ > > > > > > > + u8 res6[0x310]; > > > > > > > + __be32 ttr0cr; /* Temperature Range 0 Control > > > > Register */ > > > > > > > + __be32 ttr1cr; /* Temperature Range 1 Control > > > > Register */ > > > > > > > + __be32 ttr2cr; /* Temperature Range 2 Control > > > > Register */ > > > > > > > + __be32 ttr3cr; /* Temperature Range 3 Control > > > > Register */ > > > > > > > +}; > > > > > > > + > > > > > > > +/* > > > > > > > + * Thermal zone data > > > > > > > + */ > > > > > > > +struct qoriq_tmu_data { > > > > > > > + struct thermal_zone_device *tz; > > > > > > > + struct thermal_cooling_device *cdev; > > > > > > > + enum thermal_device_mode mode; > > > > > > > + unsigned long temp_passive; > > > > > > > + unsigned long temp_critical; > > > > > > > + struct qoriq_tmu_regs __iomem *regs; }; > > > > > > > + > > > > > > > +static int tmu_get_mode(struct thermal_zone_device *tz, > > > > > > > + enum thermal_device_mode *mode) { > > > > > > > + struct qoriq_tmu_data *data =3D tz->devdata; > > > > > > > + > > > > > > > + *mode =3D data->mode; > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > + > > > > > > > +static int tmu_set_mode(struct thermal_zone_device *tz, > > > > > > > + enum thermal_device_mode mode) { > > > > > > > + struct qoriq_tmu_data *data =3D tz->devdata; > > > > > > > + > > > > > > > + if (mode =3D=3D THERMAL_DEVICE_ENABLED) { > > > > > > > + tz->polling_delay =3D TMU_POLLING_DELAY; > > > > > > > + tz->passive_delay =3D TMU_PASSIVE_DELAY; > > > > > > > + thermal_zone_device_update(tz); > > > > > > > + } else { > > > > > > > + tz->polling_delay =3D 0; > > > > > > > + tz->passive_delay =3D 0; > > > > > > > + } > > > > > > > + > > > > > > > + data->mode =3D mode; > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > + > > > > > > > +static int tmu_get_temp(struct thermal_zone_device *tz, > > > > > > > +unsigned long > > > > > > > +*temp) { > > > > > > > + u8 val; > > > > > > > + struct qoriq_tmu_data *data =3D tz->devdata; > > > > > > > + > > > > > > > + val =3D ioread32be(&data->regs->site[0].tritsr); > > > > > > > + *temp =3D (unsigned long)val * 1000; > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > + > > > > > > > +static int tmu_get_trip_type(struct thermal_zone_device > > > > > > > +*tz, int > > > > trip, > > > > > > > + enum thermal_trip_type *type) { > > > > > > > + *type =3D (trip =3D=3D TMU_TRIP_PASSIVE) ? > THERMAL_TRIP_PASSIVE : > > > > > > > + THERMAL_TRIP_CRITICAL; > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > + > > > > > > > +static int tmu_get_trip_temp(struct thermal_zone_device > > > > > > > +*tz, int > > > > trip, > > > > > > > + unsigned long *temp) { > > > > > > > + struct qoriq_tmu_data *data =3D tz->devdata; > > > > > > > + > > > > > > > + *temp =3D (trip =3D=3D TMU_TRIP_PASSIVE) ? data- > >temp_passive : > > > > > > > + data->temp_critical; > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > + > > > > > > > +static int tmu_get_crit_temp(struct thermal_zone_device *tz, > > > > > > > + unsigned long *temp) { > > > > > > > + struct qoriq_tmu_data *data =3D tz->devdata; > > > > > > > + > > > > > > > + *temp =3D data->temp_critical; > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > + > > > > > > > +static int tmu_bind(struct thermal_zone_device *tz, > > > > > > > + struct thermal_cooling_device *cdev) { > > > > > > > + int ret; > > > > > > > + > > > > > > > + ret =3D thermal_zone_bind_cooling_device(tz, > > > > > > > +TMU_TRIP_PASSIVE, > > > > cdev, > > > > > > > + THERMAL_NO_LIMIT, > > > > > > > + THERMAL_NO_LIMIT, > > > > > > > + THERMAL_WEIGHT_DEFAULT); > > > > > > > + if (ret) { > > > > > > > + dev_err(&tz->device, > > > > > > > + "Binding zone %s with cdev %s failed:%d\n", > > > > > > > + tz->type, cdev->type, ret); > > > > > > > + } > > > > > > > + > > > > > > > + return ret; > > > > > > > +} > > > > > > > + > > > > > > > +static int tmu_unbind(struct thermal_zone_device *tz, > > > > > > > + struct thermal_cooling_device *cdev) { > > > > > > > + int ret; > > > > > > > + > > > > > > > + ret =3D thermal_zone_unbind_cooling_device(tz, > > > > > > > +TMU_TRIP_PASSIVE, > > > > > > cdev); > > > > > > > + if (ret) { > > > > > > > + dev_err(&tz->device, > > > > > > > + "Unbinding zone %s with cdev %s > failed:%d\n", > > > > > > > + tz->type, cdev->type, ret); > > > > > > > + } > > > > > > > + > > > > > > > + return ret; > > > > > > > +} > > > > > > > + > > > > > > > +static int qoriq_tmu_calibration(struct platform_device > *pdev) { > > > > > > > + int i, val, len; > > > > > > > + u32 range[4]; > > > > > > > + const __be32 *calibration; > > > > > > > + struct device_node *node =3D pdev->dev.of_node; > > > > > > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(&pdev- > >dev); > > > > > > > + > > > > > > > + /* Disable monitoring before calibration */ > > > > > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > > > > > + > > > > > > > + if (of_property_read_u32_array(node, "fsl,tmu-range", > > > > > > > +range, > > > > 4)) > > > > > > > + return -1; > > > > > > > + > > > > > > > + /* Init temperature range registers */ > > > > > > > + iowrite32be(range[0], &data->regs->ttr0cr); > > > > > > > + iowrite32be(range[1], &data->regs->ttr1cr); > > > > > > > + iowrite32be(range[2], &data->regs->ttr2cr); > > > > > > > + iowrite32be(range[3], &data->regs->ttr3cr); > > > > > > > + > > > > > > > + calibration =3D of_get_property(node, "fsl,tmu- > calibration", > > > > &len); > > > > > > > + if (calibration =3D=3D NULL) > > > > > > > + return -1; > > > > > > > + > > > > > > > + for (i =3D 0; i < len; i +=3D 8, calibration +=3D 2) { > > > > > > > + val =3D (int)of_read_number(calibration, 1); > > > > > > > + iowrite32be(val, &data->regs->ttcfgr); > > > > > > > + val =3D (int)of_read_number(calibration + 1, 1); > > > > > > > + iowrite32be(val, &data->regs->tscfgr); > > > > > > > + } > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > + > > > > > > > +static void qoriq_tmu_init_device(struct qoriq_tmu_data > *data) { > > > > > > > + /* Disable interrupt, using polling instead */ > > > > > > > + iowrite32be(TIER_DISABLE, &data->regs->tier); > > > > > > > + > > > > > > > + /* Set update_interval */ > > > > > > > + iowrite32be(TMTMIR_DEFAULT, &data->regs->tmtmir); > > > > > > > + > > > > > > > + /* Enable monitoring */ > > > > > > > + iowrite32be(TMR_ALL, &data->regs->tmr); } > > > > > > > + > > > > > > > +static struct thermal_zone_device_ops tmu_tz_ops =3D { > > > > > > > + .bind =3D tmu_bind, > > > > > > > + .unbind =3D tmu_unbind, > > > > > > > + .get_temp =3D tmu_get_temp, > > > > > > > + .get_mode =3D tmu_get_mode, > > > > > > > + .set_mode =3D tmu_set_mode, > > > > > > > + .get_trip_type =3D tmu_get_trip_type, > > > > > > > + .get_trip_temp =3D tmu_get_trip_temp, > > > > > > > + .get_crit_temp =3D tmu_get_crit_temp, }; > > > > > > > + > > > > > > > +static int qoriq_tmu_probe(struct platform_device *pdev) { > > > > > > > + int ret; > > > > > > > + struct cpumask clip_cpus; > > > > > > > + struct qoriq_tmu_data *data; > > > > > > > + > > > > > > > + if (!cpufreq_get_current_driver()) { > > > > > > > + dev_dbg(&pdev->dev, "No cpufreq driver yet\n"); > > > > > > > + return -EPROBE_DEFER; > > > > > > > + } > > > > > > > + > > > > > > > + if (!pdev->dev.of_node) { > > > > > > > + dev_err(&pdev->dev, "Device OF-Node is NULL"); > > > > > > > + return -EFAULT; > > > > > > > + } > > > > > > > + > > > > > > > + data =3D devm_kzalloc(&pdev->dev, sizeof(struct > qoriq_tmu_data), > > > > > > > + GFP_KERNEL); > > > > > > > + if (!data) > > > > > > > + return -ENOMEM; > > > > > > > + > > > > > > > + dev_set_drvdata(&pdev->dev, data); > > > > > > > + data->regs =3D of_iomap(pdev->dev.of_node, 0); > > > > > > > + > > > > > > > + if (!data->regs) { > > > > > > > + dev_err(&pdev->dev, "Failed to get memory > region\n"); > > > > > > > + ret =3D -ENODEV; > > > > > > > + goto err_iomap; > > > > > > > + } > > > > > > > + > > > > > > > + ret =3D qoriq_tmu_calibration(pdev); /* TMU calibration > */ > > > > > > > + if (ret < 0) { > > > > > > > + dev_err(&pdev->dev, "TMU calibration failed.\n"); > > > > > > > + ret =3D -ENODEV; > > > > > > > + goto err_iomap; > > > > > > > + } > > > > > > > + > > > > > > > + qoriq_tmu_init_device(data); /* TMU initialization */ > > > > > > > + > > > > > > > + cpumask_setall(&clip_cpus); > > > > > > > + data->cdev =3D cpufreq_cooling_register(&clip_cpus); > > > > > > > + if (IS_ERR(data->cdev)) { > > > > > > > + ret =3D PTR_ERR(data->cdev); > > > > > > > + dev_err(&data->cdev->device, > > > > > > > + "Failed to register cpufreq cooling > device: %d\n", > > > > ret); > > > > > > > + goto err_cooling; > > > > > > > + } > > > > > > > + > > > > > > > + data->temp_passive =3D TMU_TEMP_PASSIVE; > > > > > > > + data->temp_critical =3D TMU_TEMP_CRITICAL; > > > > > > > + data->tz =3D > > > > > > > +thermal_zone_device_register("tmu_thermal_zone", > > > > > > > > > > > > Any specific reason why not using OF thermal? > > > > > > > > > > > > > + TMU_TRIP_NUM, > > > > > > > + 0, data, > > > > > > > + &tmu_tz_ops, NULL, > > > > > > > + TMU_PASSIVE_DELAY, > > > > > > > + TMU_POLLING_DELAY); > > > > > > > + > > > > > > > + if (IS_ERR(data->tz)) { > > > > > > > + ret =3D PTR_ERR(data->tz); > > > > > > > + dev_err(&pdev->dev, > > > > > > > + "Failed to register thermal zone > device %d\n", > > > > ret); > > > > > > > + goto err_thermal; > > > > > > > + } > > > > > > > + > > > > > > > + data->mode =3D THERMAL_DEVICE_ENABLED; > > > > > > > + > > > > > > > + return 0; > > > > > > > + > > > > > > > +err_thermal: > > > > > > > + cpufreq_cooling_unregister(data->cdev); > > > > > > > + > > > > > > > +err_cooling: > > > > > > > + iounmap(data->regs); > > > > > > > + > > > > > > > +err_iomap: > > > > > > > + dev_set_drvdata(&pdev->dev, NULL); > > > > > > > + devm_kfree(&pdev->dev, data); > > > > > > > + > > > > > > > + return ret; > > > > > > > +} > > > > > > > + > > > > > > > +static int qoriq_tmu_remove(struct platform_device *pdev) { > > > > > > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(&pdev- > >dev); > > > > > > > + > > > > > > > + /* Disable monitoring */ > > > > > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > > > > > + > > > > > > > + thermal_zone_device_unregister(data->tz); > > > > > > > + cpufreq_cooling_unregister(data->cdev); > > > > > > > + iounmap(data->regs); > > > > > > > + > > > > > > > + dev_set_drvdata(&pdev->dev, NULL); > > > > > > > + devm_kfree(&pdev->dev, data); > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > + > > > > > > > +#ifdef CONFIG_PM_SLEEP > > > > > > > +static int qoriq_tmu_suspend(struct device *dev) { > > > > > > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(dev); > > > > > > > + > > > > > > > + /* Disable monitoring */ > > > > > > > + iowrite32be(TMR_DISABLE, &data->regs->tmr); > > > > > > > + data->mode =3D THERMAL_DEVICE_DISABLED; > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > + > > > > > > > +static int qoriq_tmu_resume(struct device *dev) { > > > > > > > + struct qoriq_tmu_data *data =3D dev_get_drvdata(dev); > > > > > > > + > > > > > > > + /* Enable monitoring */ > > > > > > > + iowrite32be(TMR_ALL, &data->regs->tmr); > > > > > > > + data->mode =3D THERMAL_DEVICE_ENABLED; > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > +#endif > > > > > > > + > > > > > > > +static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops, > > > > > > > + qoriq_tmu_suspend, qoriq_tmu_resume); > > > > > > > + > > > > > > > +static const struct of_device_id qoriq_tmu_match[] =3D { > > > > > > > + { .compatible =3D "fsl,qoriq-tmu", }, > > > > > > > + {}, > > > > > > > +}; > > > > > > > + > > > > > > > +static struct platform_driver qoriq_tmu =3D { > > > > > > > + .driver =3D { > > > > > > > + .owner =3D THIS_MODULE, > > > > > > > + .name =3D "qoriq_thermal", > > > > > > > + .pm =3D &qoriq_tmu_pm_ops, > > > > > > > + .of_match_table =3D qoriq_tmu_match, > > > > > > > + }, > > > > > > > + .probe =3D qoriq_tmu_probe, > > > > > > > + .remove =3D qoriq_tmu_remove, > > > > > > > +}; > > > > > > > +module_platform_driver(qoriq_tmu); > > > > > > > + > > > > > > > +MODULE_AUTHOR("Jia Hongtao <hongtao.jia@freescale.com>"); > > > > > > > +MODULE_DESCRIPTION("Freescale QorIQ Thermal Monitoring Unit > > > > > > > +driver"); MODULE_LICENSE("GPL v2"); > > > > > > > -- > > > > > > > 2.1.0.27.g96db324 > > > > > > > > > > _______________________________________________ > > > Linuxppc-dev mailing list > > > Linuxppc-dev@lists.ozlabs.org > > > https://lists.ozlabs.org/listinfo/linuxppc-dev ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-08-14 7:14 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-07-29 6:19 [PATCH V2] QorIQ/TMU: add thermal management support based on TMU Jia Hongtao 2015-07-30 6:55 ` Eduardo Valentin 2015-07-30 8:13 ` Hongtao Jia 2015-08-05 19:42 ` Eduardo Valentin 2015-08-07 8:14 ` Hongtao Jia 2015-08-14 3:15 ` Hongtao Jia 2015-08-14 4:29 ` Eduardo Valentin 2015-08-14 6:40 ` Hongtao Jia
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).