···3Required parameters:4-------------------56-compatible: should be one of: "brcm,bcm2835-thermal",7- "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"8-reg: Address range of the thermal registers.9-clocks: Phandle of the clock used by the thermal sensor.01011Example:00000000000000000000001213thermal: thermal@7e212000 {14 compatible = "brcm,bcm2835-thermal";15 reg = <0x7e212000 0x8>;16 clocks = <&clocks BCM2835_CLOCK_TSENS>;017};
···3Required parameters:4-------------------56+compatible: should be one of: "brcm,bcm2835-thermal",7+ "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"8+reg: Address range of the thermal registers.9+clocks: Phandle of the clock used by the thermal sensor.10+#thermal-sensor-cells: should be 0 (see thermal.txt)1112Example:13+14+thermal-zones {15+ cpu_thermal: cpu-thermal {16+ polling-delay-passive = <0>;17+ polling-delay = <1000>;18+19+ thermal-sensors = <&thermal>;20+21+ trips {22+ cpu-crit {23+ temperature = <80000>;24+ hysteresis = <0>;25+ type = "critical";26+ };27+ };28+29+ coefficients = <(-538) 407000>;30+31+ cooling-maps {32+ };33+ };34+};3536thermal: thermal@7e212000 {37 compatible = "brcm,bcm2835-thermal";38 reg = <0x7e212000 0x8>;39 clocks = <&clocks BCM2835_CLOCK_TSENS>;40+ #thermal-sensor-cells = <0>;41};
···1+* Dialog DA9062/61 TJUNC Thermal Module2+3+This module is part of the DA9061/DA9062. For more details about entire4+DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt5+6+Junction temperature thermal module uses an interrupt signal to identify7+high THERMAL_TRIP_HOT temperatures for the PMIC device.8+9+Required properties:10+11+- compatible: should be one of the following valid compatible string lines:12+ "dlg,da9061-thermal", "dlg,da9062-thermal"13+ "dlg,da9062-thermal"14+15+Optional properties:16+17+- polling-delay-passive : Specify the polling period, measured in18+ milliseconds, between thermal zone device update checks.19+20+Example: DA906221+22+ pmic0: da9062@58 {23+ thermal {24+ compatible = "dlg,da9062-thermal";25+ polling-delay-passive = <3000>;26+ };27+ };28+29+Example: DA9061 using a fall-back compatible for the DA9062 onkey driver30+31+ pmic0: da9061@58 {32+ thermal {33+ compatible = "dlg,da9061-thermal", "dlg,da9062-thermal";34+ polling-delay-passive = <3000>;35+ };36+ };
+15
drivers/thermal/Kconfig
···303 bound cpufreq cooling device turns active to set CPU frequency low to304 cool down the CPU.3050000000000306config INTEL_POWERCLAMP307 tristate "Intel PowerClamp idle injection driver"308 depends on THERMAL···401 help402 Enable this option if you want to have support for thermal management403 controller present in Mediatek SoCs00000404405menu "Texas Instruments thermal drivers"406depends on ARCH_HAS_BANDGAP || COMPILE_TEST
···303 bound cpufreq cooling device turns active to set CPU frequency low to304 cool down the CPU.305306+config DA9062_THERMAL307+ tristate "DA9062/DA9061 Dialog Semiconductor thermal driver"308+ depends on MFD_DA9062 || COMPILE_TEST309+ depends on OF310+ help311+ Enable this for the Dialog Semiconductor thermal sensor driver.312+ This will report PMIC junction over-temperature for one thermal trip313+ zone.314+ Compatible with the DA9062 and DA9061 PMICs.315+316config INTEL_POWERCLAMP317 tristate "Intel PowerClamp idle injection driver"318 depends on THERMAL···391 help392 Enable this option if you want to have support for thermal management393 controller present in Mediatek SoCs394+395+menu "Broadcom thermal drivers"396+depends on ARCH_BCM || COMPILE_TEST397+source "drivers/thermal/broadcom/Kconfig"398+endmenu399400menu "Texas Instruments thermal drivers"401depends on ARCH_HAS_BANDGAP || COMPILE_TEST
···1+config BCM2835_THERMAL2+ tristate "Thermal sensors on bcm2835 SoC"3+ depends on ARCH_BCM2835 || COMPILE_TEST4+ depends on HAS_IOMEM5+ depends on THERMAL_OF6+ help7+ Support for thermal sensors on Broadcom bcm2835 SoCs.8+9+config BCM_NS_THERMAL10+ tristate "Northstar thermal driver"11+ depends on ARCH_BCM_IPROC || COMPILE_TEST12+ help13+ Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081,14+ BCM4709 and BCM47094. It contains DMU (Device Management Unit) block15+ with a thermal sensor that allows checking CPU temperature. This16+ driver provides support for it.
···1+/*2+ * Driver for Broadcom BCM2835 SoC temperature sensor3+ *4+ * Copyright (C) 2016 Martin Sperl5+ *6+ * This program is free software; you can redistribute it and/or modify7+ * it under the terms of the GNU General Public License as published by8+ * the Free Software Foundation; either version 2 of the License, or9+ * (at your option) any later version.10+ *11+ * This program is distributed in the hope that it will be useful,12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14+ * GNU General Public License for more details.15+ */16+17+#include <linux/clk.h>18+#include <linux/debugfs.h>19+#include <linux/device.h>20+#include <linux/err.h>21+#include <linux/io.h>22+#include <linux/kernel.h>23+#include <linux/module.h>24+#include <linux/of.h>25+#include <linux/of_address.h>26+#include <linux/of_device.h>27+#include <linux/platform_device.h>28+#include <linux/thermal.h>29+30+#define BCM2835_TS_TSENSCTL 0x0031+#define BCM2835_TS_TSENSSTAT 0x0432+33+#define BCM2835_TS_TSENSCTL_PRWDW BIT(0)34+#define BCM2835_TS_TSENSCTL_RSTB BIT(1)35+36+/*37+ * bandgap reference voltage in 6 mV increments38+ * 000b = 1178 mV, 001b = 1184 mV, ... 111b = 1220 mV39+ */40+#define BCM2835_TS_TSENSCTL_CTRL_BITS 341+#define BCM2835_TS_TSENSCTL_CTRL_SHIFT 242+#define BCM2835_TS_TSENSCTL_CTRL_MASK \43+ GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS + \44+ BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \45+ BCM2835_TS_TSENSCTL_CTRL_SHIFT)46+#define BCM2835_TS_TSENSCTL_CTRL_DEFAULT 147+#define BCM2835_TS_TSENSCTL_EN_INT BIT(5)48+#define BCM2835_TS_TSENSCTL_DIRECT BIT(6)49+#define BCM2835_TS_TSENSCTL_CLR_INT BIT(7)50+#define BCM2835_TS_TSENSCTL_THOLD_SHIFT 851+#define BCM2835_TS_TSENSCTL_THOLD_BITS 1052+#define BCM2835_TS_TSENSCTL_THOLD_MASK \53+ GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS + \54+ BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \55+ BCM2835_TS_TSENSCTL_THOLD_SHIFT)56+/*57+ * time how long the block to be asserted in reset58+ * which based on a clock counter (TSENS clock assumed)59+ */60+#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT 1861+#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS 862+#define BCM2835_TS_TSENSCTL_REGULEN BIT(26)63+64+#define BCM2835_TS_TSENSSTAT_DATA_BITS 1065+#define BCM2835_TS_TSENSSTAT_DATA_SHIFT 066+#define BCM2835_TS_TSENSSTAT_DATA_MASK \67+ GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS + \68+ BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \69+ BCM2835_TS_TSENSSTAT_DATA_SHIFT)70+#define BCM2835_TS_TSENSSTAT_VALID BIT(10)71+#define BCM2835_TS_TSENSSTAT_INTERRUPT BIT(11)72+73+struct bcm2835_thermal_data {74+ struct thermal_zone_device *tz;75+ void __iomem *regs;76+ struct clk *clk;77+ struct dentry *debugfsdir;78+};79+80+static int bcm2835_thermal_adc2temp(u32 adc, int offset, int slope)81+{82+ return offset + slope * adc;83+}84+85+static int bcm2835_thermal_temp2adc(int temp, int offset, int slope)86+{87+ temp -= offset;88+ temp /= slope;89+90+ if (temp < 0)91+ temp = 0;92+ if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS))93+ temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1;94+95+ return temp;96+}97+98+static int bcm2835_thermal_get_temp(void *d, int *temp)99+{100+ struct bcm2835_thermal_data *data = d;101+ u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);102+103+ if (!(val & BCM2835_TS_TSENSSTAT_VALID))104+ return -EIO;105+106+ val &= BCM2835_TS_TSENSSTAT_DATA_MASK;107+108+ *temp = bcm2835_thermal_adc2temp(109+ val,110+ thermal_zone_get_offset(data->tz),111+ thermal_zone_get_slope(data->tz));112+113+ return 0;114+}115+116+static const struct debugfs_reg32 bcm2835_thermal_regs[] = {117+ {118+ .name = "ctl",119+ .offset = 0120+ },121+ {122+ .name = "stat",123+ .offset = 4124+ }125+};126+127+static void bcm2835_thermal_debugfs(struct platform_device *pdev)128+{129+ struct thermal_zone_device *tz = platform_get_drvdata(pdev);130+ struct bcm2835_thermal_data *data = tz->devdata;131+ struct debugfs_regset32 *regset;132+133+ data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);134+ if (!data->debugfsdir)135+ return;136+137+ regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);138+ if (!regset)139+ return;140+141+ regset->regs = bcm2835_thermal_regs;142+ regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs);143+ regset->base = data->regs;144+145+ debugfs_create_regset32("regset", 0444, data->debugfsdir, regset);146+}147+148+static struct thermal_zone_of_device_ops bcm2835_thermal_ops = {149+ .get_temp = bcm2835_thermal_get_temp,150+};151+152+/*153+ * Note: as per Raspberry Foundation FAQ154+ * (https://www.raspberrypi.org/help/faqs/#performanceOperatingTemperature)155+ * the recommended temperature range for the SoC -40C to +85C156+ * so the trip limit is set to 80C.157+ * this applies to all the BCM283X SoC158+ */159+160+static const struct of_device_id bcm2835_thermal_of_match_table[] = {161+ {162+ .compatible = "brcm,bcm2835-thermal",163+ },164+ {165+ .compatible = "brcm,bcm2836-thermal",166+ },167+ {168+ .compatible = "brcm,bcm2837-thermal",169+ },170+ {},171+};172+MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);173+174+static int bcm2835_thermal_probe(struct platform_device *pdev)175+{176+ const struct of_device_id *match;177+ struct thermal_zone_device *tz;178+ struct bcm2835_thermal_data *data;179+ struct resource *res;180+ int err = 0;181+ u32 val;182+ unsigned long rate;183+184+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);185+ if (!data)186+ return -ENOMEM;187+188+ match = of_match_device(bcm2835_thermal_of_match_table,189+ &pdev->dev);190+ if (!match)191+ return -EINVAL;192+193+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);194+ data->regs = devm_ioremap_resource(&pdev->dev, res);195+ if (IS_ERR(data->regs)) {196+ err = PTR_ERR(data->regs);197+ dev_err(&pdev->dev, "Could not get registers: %d\n", err);198+ return err;199+ }200+201+ data->clk = devm_clk_get(&pdev->dev, NULL);202+ if (IS_ERR(data->clk)) {203+ err = PTR_ERR(data->clk);204+ if (err != -EPROBE_DEFER)205+ dev_err(&pdev->dev, "Could not get clk: %d\n", err);206+ return err;207+ }208+209+ err = clk_prepare_enable(data->clk);210+ if (err)211+ return err;212+213+ rate = clk_get_rate(data->clk);214+ if ((rate < 1920000) || (rate > 5000000))215+ dev_warn(&pdev->dev,216+ "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n",217+ data->clk, data->clk);218+219+ /* register of thermal sensor and get info from DT */220+ tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data,221+ &bcm2835_thermal_ops);222+ if (IS_ERR(tz)) {223+ err = PTR_ERR(tz);224+ dev_err(&pdev->dev,225+ "Failed to register the thermal device: %d\n",226+ err);227+ goto err_clk;228+ }229+230+ /*231+ * right now the FW does set up the HW-block, so we are not232+ * touching the configuration registers.233+ * But if the HW is not enabled, then set it up234+ * using "sane" values used by the firmware right now.235+ */236+ val = readl(data->regs + BCM2835_TS_TSENSCTL);237+ if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {238+ int trip_temp, offset, slope;239+240+ slope = thermal_zone_get_slope(tz);241+ offset = thermal_zone_get_offset(tz);242+ /*243+ * For now we deal only with critical, otherwise244+ * would need to iterate245+ */246+ err = tz->ops->get_trip_temp(tz, 0, &trip_temp);247+ if (err < 0) {248+ err = PTR_ERR(tz);249+ dev_err(&pdev->dev,250+ "Not able to read trip_temp: %d\n",251+ err);252+ goto err_tz;253+ }254+255+ /* set bandgap reference voltage and enable voltage regulator */256+ val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<257+ BCM2835_TS_TSENSCTL_CTRL_SHIFT) |258+ BCM2835_TS_TSENSCTL_REGULEN;259+260+ /* use the recommended reset duration */261+ val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);262+263+ /* trip_adc value from info */264+ val |= bcm2835_thermal_temp2adc(trip_temp,265+ offset,266+ slope)267+ << BCM2835_TS_TSENSCTL_THOLD_SHIFT;268+269+ /* write the value back to the register as 2 steps */270+ writel(val, data->regs + BCM2835_TS_TSENSCTL);271+ val |= BCM2835_TS_TSENSCTL_RSTB;272+ writel(val, data->regs + BCM2835_TS_TSENSCTL);273+ }274+275+ data->tz = tz;276+277+ platform_set_drvdata(pdev, tz);278+279+ bcm2835_thermal_debugfs(pdev);280+281+ return 0;282+err_tz:283+ thermal_zone_of_sensor_unregister(&pdev->dev, tz);284+err_clk:285+ clk_disable_unprepare(data->clk);286+287+ return err;288+}289+290+static int bcm2835_thermal_remove(struct platform_device *pdev)291+{292+ struct thermal_zone_device *tz = platform_get_drvdata(pdev);293+ struct bcm2835_thermal_data *data = tz->devdata;294+295+ debugfs_remove_recursive(data->debugfsdir);296+ thermal_zone_of_sensor_unregister(&pdev->dev, tz);297+ clk_disable_unprepare(data->clk);298+299+ return 0;300+}301+302+static struct platform_driver bcm2835_thermal_driver = {303+ .probe = bcm2835_thermal_probe,304+ .remove = bcm2835_thermal_remove,305+ .driver = {306+ .name = "bcm2835_thermal",307+ .of_match_table = bcm2835_thermal_of_match_table,308+ },309+};310+module_platform_driver(bcm2835_thermal_driver);311+312+MODULE_AUTHOR("Martin Sperl");313+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");314+MODULE_LICENSE("GPL");
···1+/*2+ * Thermal device driver for DA9062 and DA90613+ * Copyright (C) 2017 Dialog Semiconductor4+ *5+ * This program is free software; you can redistribute it and/or6+ * modify it under the terms of the GNU General Public License7+ * as published by the Free Software Foundation; either version 28+ * of the License, or (at your option) any later version.9+ *10+ * This program is distributed in the hope that it will be useful,11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13+ * GNU General Public License for more details.14+ */15+16+/* When over-temperature is reached, an interrupt from the device will be17+ * triggered. Following this event the interrupt will be disabled and18+ * periodic transmission of uevents (HOT trip point) should define the19+ * first level of temperature supervision. It is expected that any final20+ * implementation of the thermal driver will include a .notify() function21+ * to implement these uevents to userspace.22+ *23+ * These uevents are intended to indicate non-invasive temperature control24+ * of the system, where the necessary measures for cooling are the25+ * responsibility of the host software. Once the temperature falls again,26+ * the IRQ is re-enabled so the start of a new over-temperature event can27+ * be detected without constant software monitoring.28+ */29+30+#include <linux/errno.h>31+#include <linux/interrupt.h>32+#include <linux/module.h>33+#include <linux/of.h>34+#include <linux/platform_device.h>35+#include <linux/regmap.h>36+#include <linux/thermal.h>37+#include <linux/workqueue.h>38+39+#include <linux/mfd/da9062/core.h>40+#include <linux/mfd/da9062/registers.h>41+42+/* Minimum, maximum and default polling millisecond periods are provided43+ * here as an example. It is expected that any final implementation to also44+ * include a modification of these settings to match the required45+ * application.46+ */47+#define DA9062_DEFAULT_POLLING_MS_PERIOD 300048+#define DA9062_MAX_POLLING_MS_PERIOD 1000049+#define DA9062_MIN_POLLING_MS_PERIOD 100050+51+#define DA9062_MILLI_CELSIUS(t) ((t) * 1000)52+53+struct da9062_thermal_config {54+ const char *name;55+};56+57+struct da9062_thermal {58+ struct da9062 *hw;59+ struct delayed_work work;60+ struct thermal_zone_device *zone;61+ enum thermal_device_mode mode;62+ struct mutex lock; /* protection for da9062_thermal temperature */63+ int temperature;64+ int irq;65+ const struct da9062_thermal_config *config;66+ struct device *dev;67+};68+69+static void da9062_thermal_poll_on(struct work_struct *work)70+{71+ struct da9062_thermal *thermal = container_of(work,72+ struct da9062_thermal,73+ work.work);74+ unsigned long delay;75+ unsigned int val;76+ int ret;77+78+ /* clear E_TEMP */79+ ret = regmap_write(thermal->hw->regmap,80+ DA9062AA_EVENT_B,81+ DA9062AA_E_TEMP_MASK);82+ if (ret < 0) {83+ dev_err(thermal->dev,84+ "Cannot clear the TJUNC temperature status\n");85+ goto err_enable_irq;86+ }87+88+ /* Now read E_TEMP again: it is acting like a status bit.89+ * If over-temperature, then this status will be true.90+ * If not over-temperature, this status will be false.91+ */92+ ret = regmap_read(thermal->hw->regmap,93+ DA9062AA_EVENT_B,94+ &val);95+ if (ret < 0) {96+ dev_err(thermal->dev,97+ "Cannot check the TJUNC temperature status\n");98+ goto err_enable_irq;99+ }100+101+ if (val & DA9062AA_E_TEMP_MASK) {102+ mutex_lock(&thermal->lock);103+ thermal->temperature = DA9062_MILLI_CELSIUS(125);104+ mutex_unlock(&thermal->lock);105+ thermal_zone_device_update(thermal->zone,106+ THERMAL_EVENT_UNSPECIFIED);107+108+ delay = msecs_to_jiffies(thermal->zone->passive_delay);109+ schedule_delayed_work(&thermal->work, delay);110+ return;111+ }112+113+ mutex_lock(&thermal->lock);114+ thermal->temperature = DA9062_MILLI_CELSIUS(0);115+ mutex_unlock(&thermal->lock);116+ thermal_zone_device_update(thermal->zone,117+ THERMAL_EVENT_UNSPECIFIED);118+119+err_enable_irq:120+ enable_irq(thermal->irq);121+}122+123+static irqreturn_t da9062_thermal_irq_handler(int irq, void *data)124+{125+ struct da9062_thermal *thermal = data;126+127+ disable_irq_nosync(thermal->irq);128+ schedule_delayed_work(&thermal->work, 0);129+130+ return IRQ_HANDLED;131+}132+133+static int da9062_thermal_get_mode(struct thermal_zone_device *z,134+ enum thermal_device_mode *mode)135+{136+ struct da9062_thermal *thermal = z->devdata;137+ *mode = thermal->mode;138+ return 0;139+}140+141+static int da9062_thermal_get_trip_type(struct thermal_zone_device *z,142+ int trip,143+ enum thermal_trip_type *type)144+{145+ struct da9062_thermal *thermal = z->devdata;146+147+ switch (trip) {148+ case 0:149+ *type = THERMAL_TRIP_HOT;150+ break;151+ default:152+ dev_err(thermal->dev,153+ "Driver does not support more than 1 trip-wire\n");154+ return -EINVAL;155+ }156+157+ return 0;158+}159+160+static int da9062_thermal_get_trip_temp(struct thermal_zone_device *z,161+ int trip,162+ int *temp)163+{164+ struct da9062_thermal *thermal = z->devdata;165+166+ switch (trip) {167+ case 0:168+ *temp = DA9062_MILLI_CELSIUS(125);169+ break;170+ default:171+ dev_err(thermal->dev,172+ "Driver does not support more than 1 trip-wire\n");173+ return -EINVAL;174+ }175+176+ return 0;177+}178+179+static int da9062_thermal_get_temp(struct thermal_zone_device *z,180+ int *temp)181+{182+ struct da9062_thermal *thermal = z->devdata;183+184+ mutex_lock(&thermal->lock);185+ *temp = thermal->temperature;186+ mutex_unlock(&thermal->lock);187+188+ return 0;189+}190+191+static struct thermal_zone_device_ops da9062_thermal_ops = {192+ .get_temp = da9062_thermal_get_temp,193+ .get_mode = da9062_thermal_get_mode,194+ .get_trip_type = da9062_thermal_get_trip_type,195+ .get_trip_temp = da9062_thermal_get_trip_temp,196+};197+198+static const struct da9062_thermal_config da9062_config = {199+ .name = "da9062-thermal",200+};201+202+static const struct of_device_id da9062_compatible_reg_id_table[] = {203+ { .compatible = "dlg,da9062-thermal", .data = &da9062_config },204+ { },205+};206+207+MODULE_DEVICE_TABLE(of, da9062_compatible_reg_id_table);208+209+static int da9062_thermal_probe(struct platform_device *pdev)210+{211+ struct da9062 *chip = dev_get_drvdata(pdev->dev.parent);212+ struct da9062_thermal *thermal;213+ unsigned int pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD;214+ const struct of_device_id *match;215+ int ret = 0;216+217+ match = of_match_node(da9062_compatible_reg_id_table,218+ pdev->dev.of_node);219+ if (!match)220+ return -ENXIO;221+222+ if (pdev->dev.of_node) {223+ if (!of_property_read_u32(pdev->dev.of_node,224+ "polling-delay-passive",225+ &pp_tmp)) {226+ if (pp_tmp < DA9062_MIN_POLLING_MS_PERIOD ||227+ pp_tmp > DA9062_MAX_POLLING_MS_PERIOD) {228+ dev_warn(&pdev->dev,229+ "Out-of-range polling period %d ms\n",230+ pp_tmp);231+ pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD;232+ }233+ }234+ }235+236+ thermal = devm_kzalloc(&pdev->dev, sizeof(struct da9062_thermal),237+ GFP_KERNEL);238+ if (!thermal) {239+ ret = -ENOMEM;240+ goto err;241+ }242+243+ thermal->config = match->data;244+ thermal->hw = chip;245+ thermal->mode = THERMAL_DEVICE_ENABLED;246+ thermal->dev = &pdev->dev;247+248+ INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on);249+ mutex_init(&thermal->lock);250+251+ thermal->zone = thermal_zone_device_register(thermal->config->name,252+ 1, 0, thermal,253+ &da9062_thermal_ops, NULL, pp_tmp,254+ 0);255+ if (IS_ERR(thermal->zone)) {256+ dev_err(&pdev->dev, "Cannot register thermal zone device\n");257+ ret = PTR_ERR(thermal->zone);258+ goto err;259+ }260+261+ dev_dbg(&pdev->dev,262+ "TJUNC temperature polling period set at %d ms\n",263+ thermal->zone->passive_delay);264+265+ ret = platform_get_irq_byname(pdev, "THERMAL");266+ if (ret < 0) {267+ dev_err(&pdev->dev, "Failed to get platform IRQ.\n");268+ goto err_zone;269+ }270+ thermal->irq = ret;271+272+ ret = request_threaded_irq(thermal->irq, NULL,273+ da9062_thermal_irq_handler,274+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,275+ "THERMAL", thermal);276+ if (ret) {277+ dev_err(&pdev->dev,278+ "Failed to request thermal device IRQ.\n");279+ goto err_zone;280+ }281+282+ platform_set_drvdata(pdev, thermal);283+ return 0;284+285+err_zone:286+ thermal_zone_device_unregister(thermal->zone);287+err:288+ return ret;289+}290+291+static int da9062_thermal_remove(struct platform_device *pdev)292+{293+ struct da9062_thermal *thermal = platform_get_drvdata(pdev);294+295+ free_irq(thermal->irq, thermal);296+ cancel_delayed_work_sync(&thermal->work);297+ thermal_zone_device_unregister(thermal->zone);298+ return 0;299+}300+301+static struct platform_driver da9062_thermal_driver = {302+ .probe = da9062_thermal_probe,303+ .remove = da9062_thermal_remove,304+ .driver = {305+ .name = "da9062-thermal",306+ .of_match_table = da9062_compatible_reg_id_table,307+ },308+};309+310+module_platform_driver(da9062_thermal_driver);311+312+MODULE_AUTHOR("Steve Twiss");313+MODULE_DESCRIPTION("Thermal TJUNC device driver for Dialog DA9062 and DA9061");314+MODULE_LICENSE("GPL");315+MODULE_ALIAS("platform:da9062-thermal");
+1-1
drivers/thermal/mtk_thermal.c
···191};192193static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = {194- TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR2195};196197static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
···191};192193static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = {194+ TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3195};196197static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
···254 * @ts_data: pointer to struct with thresholds, limits of temperature sensor255 * @registers: pointer to the list of register offsets and bitfields256 * @domain: the name of the domain where the sensor is located257- * @slope: sensor gradient slope info for hotspot extrapolation equation258- * @constant: sensor gradient const info for hotspot extrapolation equation259 * @slope_pcb: sensor gradient slope info for hotspot extrapolation equation260 * with no external influence261 * @constant_pcb: sensor gradient const info for hotspot extrapolation equation···272 struct temp_sensor_registers *registers;273 char *domain;274 /* for hotspot extrapolation */275- const int slope;276- const int constant;277 const int slope_pcb;278 const int constant_pcb;279 int (*register_cooling)(struct ti_bandgap *bgp, int id);
···254 * @ts_data: pointer to struct with thresholds, limits of temperature sensor255 * @registers: pointer to the list of register offsets and bitfields256 * @domain: the name of the domain where the sensor is located00257 * @slope_pcb: sensor gradient slope info for hotspot extrapolation equation258 * with no external influence259 * @constant_pcb: sensor gradient const info for hotspot extrapolation equation···274 struct temp_sensor_registers *registers;275 char *domain;276 /* for hotspot extrapolation */00277 const int slope_pcb;278 const int constant_pcb;279 int (*register_cooling)(struct ti_bandgap *bgp, int id);