···11+Binding for Thermal Sensor driver for STMicroelectronics STi series of SoCs.22+33+Required parameters:44+-------------------55+66+compatible : st,<SoC>-<module>-thermal; should be one of:77+ "st,stih415-sas-thermal",88+ "st,stih415-mpe-thermal",99+ "st,stih416-sas-thermal"1010+ "st,stih416-mpe-thermal"1111+ "st,stid127-thermal" or1212+ "st,stih407-thermal"1313+ according to the SoC type (stih415, stih416, stid127, stih407)1414+ and module type (sas or mpe). On stid127 & stih407 there is only1515+ one die/module, so there is no module type in the compatible1616+ string.1717+clock-names : Should be "thermal".1818+ See: Documentation/devicetree/bindings/resource-names.txt1919+clocks : Phandle of the clock used by the thermal sensor.2020+ See: Documentation/devicetree/bindings/clock/clock-bindings.txt2121+2222+Optional parameters:2323+-------------------2424+2525+reg : For non-sysconf based sensors, this should be the physical base2626+ address and length of the sensor's registers.2727+interrupts : Standard way to define interrupt number.2828+ Interrupt is mandatory to be defined when compatible is2929+ "stih416-mpe-thermal".3030+ NB: For thermal sensor's for which no interrupt has been3131+ defined, a polling delay of 1000ms will be used to read the3232+ temperature from device.3333+3434+Example:3535+3636+ temp1@fdfe8000 {3737+ compatible = "st,stih416-mpe-thermal";3838+ reg = <0xfdfe8000 0x10>;3939+ clock-names = "thermal";4040+ clocks = <&clk_m_mpethsens>;4141+ interrupts = <GIC_SPI 23 IRQ_TYPE_NONE>;4242+ };
+6-1
drivers/thermal/Kconfig
···151151152152config DOVE_THERMAL153153 tristate "Temperature sensor on Marvell Dove SoCs"154154- depends on ARCH_DOVE154154+ depends on ARCH_DOVE || MACH_DOVE155155 depends on OF156156 help157157 Support for the Dove thermal sensor driver in the Linux thermal···241241menu "Samsung thermal drivers"242242depends on ARCH_EXYNOS243243source "drivers/thermal/samsung/Kconfig"244244+endmenu245245+246246+menu "STMicroelectronics thermal drivers"247247+depends on ARCH_STI && OF248248+source "drivers/thermal/st/Kconfig"244249endmenu245250246251endif
···305305 * @event: value showing cpufreq event for which this function invoked.306306 * @data: callback-specific data307307 *308308- * Callback to highjack the notification on cpufreq policy transition.308308+ * Callback to hijack the notification on cpufreq policy transition.309309 * Every time there is a change in policy, we will intercept and310310 * update the cpufreq policy with thermal constraints.311311 *
+60-7
drivers/thermal/int3403_thermal.c
···3333struct int3403_sensor {3434 struct thermal_zone_device *tzone;3535 unsigned long *thresholds;3636+ unsigned long crit_temp;3737+ int crit_trip_id;3838+ unsigned long psv_temp;3939+ int psv_trip_id;3640};37413842static int sys_get_curr_temp(struct thermal_zone_device *tzone,···8379 struct acpi_device *device = tzone->devdata;8480 struct int3403_sensor *obj = acpi_driver_data(device);85818686- /*8787- * get_trip_temp is a mandatory callback but8888- * PATx method doesn't return any value, so return8989- * cached value, which was last set from user space.9090- */9191- *temp = obj->thresholds[trip];8282+ if (trip == obj->crit_trip_id)8383+ *temp = obj->crit_temp;8484+ else if (trip == obj->psv_trip_id)8585+ *temp = obj->psv_temp;8686+ else {8787+ /*8888+ * get_trip_temp is a mandatory callback but8989+ * PATx method doesn't return any value, so return9090+ * cached value, which was last set from user space.9191+ */9292+ *temp = obj->thresholds[trip];9393+ }92949395 return 0;9496}···10292static int sys_get_trip_type(struct thermal_zone_device *thermal,10393 int trip, enum thermal_trip_type *type)10494{9595+ struct acpi_device *device = thermal->devdata;9696+ struct int3403_sensor *obj = acpi_driver_data(device);9797+10598 /* Mandatory callback, may not mean much here */106106- *type = THERMAL_TRIP_PASSIVE;9999+ if (trip == obj->crit_trip_id)100100+ *type = THERMAL_TRIP_CRITICAL;101101+ else102102+ *type = THERMAL_TRIP_PASSIVE;107103108104 return 0;109105}···171155 }172156}173157158158+static int sys_get_trip_crt(struct acpi_device *device, unsigned long *temp)159159+{160160+ unsigned long long crt;161161+ acpi_status status;162162+163163+ status = acpi_evaluate_integer(device->handle, "_CRT", NULL, &crt);164164+ if (ACPI_FAILURE(status))165165+ return -EIO;166166+167167+ *temp = DECI_KELVIN_TO_MILLI_CELSIUS(crt, KELVIN_OFFSET);168168+169169+ return 0;170170+}171171+172172+static int sys_get_trip_psv(struct acpi_device *device, unsigned long *temp)173173+{174174+ unsigned long long psv;175175+ acpi_status status;176176+177177+ status = acpi_evaluate_integer(device->handle, "_PSV", NULL, &psv);178178+ if (ACPI_FAILURE(status))179179+ return -EIO;180180+181181+ *temp = DECI_KELVIN_TO_MILLI_CELSIUS(psv, KELVIN_OFFSET);182182+183183+ return 0;184184+}185185+174186static int acpi_int3403_add(struct acpi_device *device)175187{176188 int result = 0;···238194 return -ENOMEM;239195 trip_mask = BIT(trip_cnt) - 1;240196 }197197+198198+ obj->psv_trip_id = -1;199199+ if (!sys_get_trip_psv(device, &obj->psv_temp))200200+ obj->psv_trip_id = trip_cnt++;201201+202202+ obj->crit_trip_id = -1;203203+ if (!sys_get_trip_crt(device, &obj->crit_temp))204204+ obj->crit_trip_id = trip_cnt++;205205+241206 obj->tzone = thermal_zone_device_register(acpi_device_bid(device),242207 trip_cnt, trip_mask, device, &tzone_ops,243208 NULL, 0, 0);
+12
drivers/thermal/st/Kconfig
···11+config ST_THERMAL22+ tristate "Thermal sensors on STMicroelectronics STi series of SoCs"33+ help44+ Support for thermal sensors on STMicroelectronics STi series of SoCs.55+66+config ST_THERMAL_SYSCFG77+ select ST_THERMAL88+ tristate "STi series syscfg register access based thermal sensors"99+1010+config ST_THERMAL_MEMMAP1111+ select ST_THERMAL1212+ tristate "STi series memory mapped access based thermal sensors"
···11+/*22+ * ST Thermal Sensor Driver core routines33+ * Author: Ajit Pal Singh <ajitpal.singh@st.com>44+ *55+ * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited66+ *77+ * This program is free software; you can redistribute it and/or modify88+ * it under the terms of the GNU General Public License as published by99+ * the Free Software Foundation; either version 2 of the License, or1010+ * (at your option) any later version.1111+ *1212+ */1313+1414+#include <linux/clk.h>1515+#include <linux/module.h>1616+#include <linux/of.h>1717+#include <linux/of_device.h>1818+1919+#include "st_thermal.h"2020+2121+/* The Thermal Framework expects millidegrees */2222+#define mcelsius(temp) ((temp) * 1000)2323+2424+/*2525+ * Function to allocate regfields which are common2626+ * between syscfg and memory mapped based sensors2727+ */2828+int st_thermal_alloc_regfields(struct st_thermal_sensor *sensor)2929+{3030+ struct device *dev = sensor->dev;3131+ struct regmap *regmap = sensor->regmap;3232+ const struct reg_field *reg_fields = sensor->cdata->reg_fields;3333+3434+ sensor->dcorrect = devm_regmap_field_alloc(dev, regmap,3535+ reg_fields[DCORRECT]);3636+3737+ sensor->overflow = devm_regmap_field_alloc(dev, regmap,3838+ reg_fields[OVERFLOW]);3939+4040+ sensor->temp_data = devm_regmap_field_alloc(dev, regmap,4141+ reg_fields[DATA]);4242+4343+ if (IS_ERR(sensor->dcorrect) ||4444+ IS_ERR(sensor->overflow) ||4545+ IS_ERR(sensor->temp_data)) {4646+ dev_err(dev, "failed to allocate common regfields\n");4747+ return -EINVAL;4848+ }4949+5050+ return sensor->ops->alloc_regfields(sensor);5151+}5252+5353+static int st_thermal_sensor_on(struct st_thermal_sensor *sensor)5454+{5555+ int ret;5656+ struct device *dev = sensor->dev;5757+5858+ ret = clk_prepare_enable(sensor->clk);5959+ if (ret) {6060+ dev_err(dev, "failed to enable clk\n");6161+ return ret;6262+ }6363+6464+ ret = sensor->ops->power_ctrl(sensor, POWER_ON);6565+ if (ret) {6666+ dev_err(dev, "failed to power on sensor\n");6767+ clk_disable_unprepare(sensor->clk);6868+ }6969+7070+ return ret;7171+}7272+7373+static int st_thermal_sensor_off(struct st_thermal_sensor *sensor)7474+{7575+ int ret;7676+7777+ ret = sensor->ops->power_ctrl(sensor, POWER_OFF);7878+ if (ret)7979+ return ret;8080+8181+ clk_disable_unprepare(sensor->clk);8282+8383+ return 0;8484+}8585+8686+static int st_thermal_calibration(struct st_thermal_sensor *sensor)8787+{8888+ int ret;8989+ unsigned int val;9090+ struct device *dev = sensor->dev;9191+9292+ /* Check if sensor calibration data is already written */9393+ ret = regmap_field_read(sensor->dcorrect, &val);9494+ if (ret) {9595+ dev_err(dev, "failed to read calibration data\n");9696+ return ret;9797+ }9898+9999+ if (!val) {100100+ /*101101+ * Sensor calibration value not set by bootloader,102102+ * default calibration data to be used103103+ */104104+ ret = regmap_field_write(sensor->dcorrect,105105+ sensor->cdata->calibration_val);106106+ if (ret)107107+ dev_err(dev, "failed to set calibration data\n");108108+ }109109+110110+ return ret;111111+}112112+113113+/* Callback to get temperature from HW*/114114+static int st_thermal_get_temp(struct thermal_zone_device *th,115115+ unsigned long *temperature)116116+{117117+ struct st_thermal_sensor *sensor = th->devdata;118118+ struct device *dev = sensor->dev;119119+ unsigned int temp;120120+ unsigned int overflow;121121+ int ret;122122+123123+ ret = regmap_field_read(sensor->overflow, &overflow);124124+ if (ret)125125+ return ret;126126+ if (overflow)127127+ return -EIO;128128+129129+ ret = regmap_field_read(sensor->temp_data, &temp);130130+ if (ret)131131+ return ret;132132+133133+ temp += sensor->cdata->temp_adjust_val;134134+ temp = mcelsius(temp);135135+136136+ dev_dbg(dev, "temperature: %d\n", temp);137137+138138+ *temperature = temp;139139+140140+ return 0;141141+}142142+143143+static int st_thermal_get_trip_type(struct thermal_zone_device *th,144144+ int trip, enum thermal_trip_type *type)145145+{146146+ struct st_thermal_sensor *sensor = th->devdata;147147+ struct device *dev = sensor->dev;148148+149149+ switch (trip) {150150+ case 0:151151+ *type = THERMAL_TRIP_CRITICAL;152152+ break;153153+ default:154154+ dev_err(dev, "invalid trip point\n");155155+ return -EINVAL;156156+ }157157+158158+ return 0;159159+}160160+161161+static int st_thermal_get_trip_temp(struct thermal_zone_device *th,162162+ int trip, unsigned long *temp)163163+{164164+ struct st_thermal_sensor *sensor = th->devdata;165165+ struct device *dev = sensor->dev;166166+167167+ switch (trip) {168168+ case 0:169169+ *temp = mcelsius(sensor->cdata->crit_temp);170170+ break;171171+ default:172172+ dev_err(dev, "Invalid trip point\n");173173+ return -EINVAL;174174+ }175175+176176+ return 0;177177+}178178+179179+static struct thermal_zone_device_ops st_tz_ops = {180180+ .get_temp = st_thermal_get_temp,181181+ .get_trip_type = st_thermal_get_trip_type,182182+ .get_trip_temp = st_thermal_get_trip_temp,183183+};184184+185185+int st_thermal_register(struct platform_device *pdev,186186+ const struct of_device_id *st_thermal_of_match)187187+{188188+ struct st_thermal_sensor *sensor;189189+ struct device *dev = &pdev->dev;190190+ struct device_node *np = dev->of_node;191191+ const struct of_device_id *match;192192+193193+ int polling_delay;194194+ int ret;195195+196196+ if (!np) {197197+ dev_err(dev, "device tree node not found\n");198198+ return -EINVAL;199199+ }200200+201201+ sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);202202+ if (!sensor)203203+ return -ENOMEM;204204+205205+ sensor->dev = dev;206206+207207+ match = of_match_device(st_thermal_of_match, dev);208208+ if (!(match && match->data))209209+ return -EINVAL;210210+211211+ sensor->cdata = match->data;212212+ if (!sensor->cdata->ops)213213+ return -EINVAL;214214+215215+ sensor->ops = sensor->cdata->ops;216216+217217+ ret = sensor->ops->regmap_init(sensor);218218+ if (ret)219219+ return ret;220220+221221+ ret = st_thermal_alloc_regfields(sensor);222222+ if (ret)223223+ return ret;224224+225225+ sensor->clk = devm_clk_get(dev, "thermal");226226+ if (IS_ERR(sensor->clk)) {227227+ dev_err(dev, "failed to fetch clock\n");228228+ return PTR_ERR(sensor->clk);229229+ }230230+231231+ if (sensor->ops->register_enable_irq) {232232+ ret = sensor->ops->register_enable_irq(sensor);233233+ if (ret)234234+ return ret;235235+ }236236+237237+ ret = st_thermal_sensor_on(sensor);238238+ if (ret)239239+ return ret;240240+241241+ ret = st_thermal_calibration(sensor);242242+ if (ret)243243+ goto sensor_off;244244+245245+ polling_delay = sensor->ops->register_enable_irq ? 0 : 1000;246246+247247+ sensor->thermal_dev =248248+ thermal_zone_device_register(dev_name(dev), 1, 0, sensor,249249+ &st_tz_ops, NULL, 0, polling_delay);250250+ if (IS_ERR(sensor->thermal_dev)) {251251+ dev_err(dev, "failed to register thermal zone device\n");252252+ ret = PTR_ERR(sensor->thermal_dev);253253+ goto sensor_off;254254+ }255255+256256+ platform_set_drvdata(pdev, sensor);257257+258258+ return 0;259259+260260+sensor_off:261261+ st_thermal_sensor_off(sensor);262262+263263+ return ret;264264+}265265+EXPORT_SYMBOL_GPL(st_thermal_register);266266+267267+int st_thermal_unregister(struct platform_device *pdev)268268+{269269+ struct st_thermal_sensor *sensor = platform_get_drvdata(pdev);270270+271271+ st_thermal_sensor_off(sensor);272272+ thermal_zone_device_unregister(sensor->thermal_dev);273273+274274+ return 0;275275+}276276+EXPORT_SYMBOL_GPL(st_thermal_unregister);277277+278278+static int st_thermal_suspend(struct device *dev)279279+{280280+ struct platform_device *pdev = to_platform_device(dev);281281+ struct st_thermal_sensor *sensor = platform_get_drvdata(pdev);282282+283283+ return st_thermal_sensor_off(sensor);284284+}285285+286286+static int st_thermal_resume(struct device *dev)287287+{288288+ int ret;289289+ struct platform_device *pdev = to_platform_device(dev);290290+ struct st_thermal_sensor *sensor = platform_get_drvdata(pdev);291291+292292+ ret = st_thermal_sensor_on(sensor);293293+ if (ret)294294+ return ret;295295+296296+ ret = st_thermal_calibration(sensor);297297+ if (ret)298298+ return ret;299299+300300+ if (sensor->ops->enable_irq) {301301+ ret = sensor->ops->enable_irq(sensor);302302+ if (ret)303303+ return ret;304304+ }305305+306306+ return 0;307307+}308308+SIMPLE_DEV_PM_OPS(st_thermal_pm_ops, st_thermal_suspend, st_thermal_resume);309309+EXPORT_SYMBOL_GPL(st_thermal_pm_ops);310310+311311+MODULE_AUTHOR("STMicroelectronics (R&D) Limited <ajitpal.singh@st.com>");312312+MODULE_DESCRIPTION("STMicroelectronics STi SoC Thermal Sensor Driver");313313+MODULE_LICENSE("GPL v2");
+104
drivers/thermal/st/st_thermal.h
···11+/*22+ * ST Thermal Sensor Driver for STi series of SoCs33+ * Author: Ajit Pal Singh <ajitpal.singh@st.com>44+ *55+ * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited66+ *77+ * This program is free software; you can redistribute it and/or modify88+ * it under the terms of the GNU General Public License as published by99+ * the Free Software Foundation; either version 2 of the License, or1010+ * (at your option) any later version.1111+ */1212+1313+#ifndef __STI_THERMAL_SYSCFG_H1414+#define __STI_THERMAL_SYSCFG_H1515+1616+#include <linux/interrupt.h>1717+#include <linux/platform_device.h>1818+#include <linux/regmap.h>1919+#include <linux/thermal.h>2020+2121+enum st_thermal_regfield_ids {2222+ INT_THRESH_HI = 0, /* Top two regfield IDs are mutually exclusive */2323+ TEMP_PWR = 0,2424+ DCORRECT,2525+ OVERFLOW,2626+ DATA,2727+ INT_ENABLE,2828+2929+ MAX_REGFIELDS3030+};3131+3232+/* Thermal sensor power states */3333+enum st_thermal_power_state {3434+ POWER_OFF = 0,3535+ POWER_ON3636+};3737+3838+struct st_thermal_sensor;3939+4040+/**4141+ * Description of private thermal sensor ops.4242+ *4343+ * @power_ctrl: Function for powering on/off a sensor. Clock to the4444+ * sensor is also controlled from this function.4545+ * @alloc_regfields: Allocate regmap register fields, specific to a sensor.4646+ * @do_memmap_regmap: Memory map the thermal register space and init regmap4747+ * instance or find regmap instance.4848+ * @register_irq: Register an interrupt handler for a sensor.4949+ */5050+struct st_thermal_sensor_ops {5151+ int (*power_ctrl)(struct st_thermal_sensor *, enum st_thermal_power_state);5252+ int (*alloc_regfields)(struct st_thermal_sensor *);5353+ int (*regmap_init)(struct st_thermal_sensor *);5454+ int (*register_enable_irq)(struct st_thermal_sensor *);5555+ int (*enable_irq)(struct st_thermal_sensor *);5656+};5757+5858+/**5959+ * Description of thermal driver compatible data.6060+ *6161+ * @reg_fields: Pointer to the regfields array for a sensor.6262+ * @sys_compat: Pointer to the syscon node compatible string.6363+ * @ops: Pointer to private thermal ops for a sensor.6464+ * @calibration_val: Default calibration value to be written to the DCORRECT6565+ * register field for a sensor.6666+ * @temp_adjust_val: Value to be added/subtracted from the data read from6767+ * the sensor. If value needs to be added please provide a6868+ * positive value and if it is to be subtracted please6969+ * provide a negative value.7070+ * @crit_temp: The temperature beyond which the SoC should be shutdown7171+ * to prevent damage.7272+ */7373+struct st_thermal_compat_data {7474+ char *sys_compat;7575+ const struct reg_field *reg_fields;7676+ const struct st_thermal_sensor_ops *ops;7777+ unsigned int calibration_val;7878+ int temp_adjust_val;7979+ int crit_temp;8080+};8181+8282+struct st_thermal_sensor {8383+ struct device *dev;8484+ struct thermal_zone_device *thermal_dev;8585+ const struct st_thermal_sensor_ops *ops;8686+ const struct st_thermal_compat_data *cdata;8787+ struct clk *clk;8888+ struct regmap *regmap;8989+ struct regmap_field *pwr;9090+ struct regmap_field *dcorrect;9191+ struct regmap_field *overflow;9292+ struct regmap_field *temp_data;9393+ struct regmap_field *int_thresh_hi;9494+ struct regmap_field *int_enable;9595+ int irq;9696+ void __iomem *mmio_base;9797+};9898+9999+extern int st_thermal_register(struct platform_device *pdev,100100+ const struct of_device_id *st_thermal_of_match);101101+extern int st_thermal_unregister(struct platform_device *pdev);102102+extern const struct dev_pm_ops st_thermal_pm_ops;103103+104104+#endif /* __STI_RESET_SYSCFG_H */
+209
drivers/thermal/st/st_thermal_memmap.c
···11+/*22+ * ST Thermal Sensor Driver for memory mapped sensors.33+ * Author: Ajit Pal Singh <ajitpal.singh@st.com>44+ *55+ * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited66+ *77+ * This program is free software; you can redistribute it and/or modify88+ * it under the terms of the GNU General Public License as published by99+ * the Free Software Foundation; either version 2 of the License, or1010+ * (at your option) any later version.1111+ */1212+1313+#include <linux/of.h>1414+#include <linux/module.h>1515+1616+#include "st_thermal.h"1717+1818+#define STIH416_MPE_CONF 0x01919+#define STIH416_MPE_STATUS 0x42020+#define STIH416_MPE_INT_THRESH 0x82121+#define STIH416_MPE_INT_EN 0xC2222+2323+/* Power control bits for the memory mapped thermal sensor */2424+#define THERMAL_PDN BIT(4)2525+#define THERMAL_SRSTN BIT(10)2626+2727+static const struct reg_field st_mmap_thermal_regfields[MAX_REGFIELDS] = {2828+ /*2929+ * According to the STIH416 MPE temp sensor data sheet -3030+ * the PDN (Power Down Bit) and SRSTN (Soft Reset Bit) need to be3131+ * written simultaneously for powering on and off the temperature3232+ * sensor. regmap_update_bits() will be used to update the register.3333+ */3434+ [INT_THRESH_HI] = REG_FIELD(STIH416_MPE_INT_THRESH, 0, 7),3535+ [DCORRECT] = REG_FIELD(STIH416_MPE_CONF, 5, 9),3636+ [OVERFLOW] = REG_FIELD(STIH416_MPE_STATUS, 9, 9),3737+ [DATA] = REG_FIELD(STIH416_MPE_STATUS, 11, 18),3838+ [INT_ENABLE] = REG_FIELD(STIH416_MPE_INT_EN, 0, 0),3939+};4040+4141+static irqreturn_t st_mmap_thermal_trip_handler(int irq, void *sdata)4242+{4343+ struct st_thermal_sensor *sensor = sdata;4444+4545+ thermal_zone_device_update(sensor->thermal_dev);4646+4747+ return IRQ_HANDLED;4848+}4949+5050+/* Private ops for the Memory Mapped based thermal sensors */5151+static int st_mmap_power_ctrl(struct st_thermal_sensor *sensor,5252+ enum st_thermal_power_state power_state)5353+{5454+ const unsigned int mask = (THERMAL_PDN | THERMAL_SRSTN);5555+ const unsigned int val = power_state ? mask : 0;5656+5757+ return regmap_update_bits(sensor->regmap, STIH416_MPE_CONF, mask, val);5858+}5959+6060+static int st_mmap_alloc_regfields(struct st_thermal_sensor *sensor)6161+{6262+ struct device *dev = sensor->dev;6363+ struct regmap *regmap = sensor->regmap;6464+ const struct reg_field *reg_fields = sensor->cdata->reg_fields;6565+6666+ sensor->int_thresh_hi = devm_regmap_field_alloc(dev, regmap,6767+ reg_fields[INT_THRESH_HI]);6868+ sensor->int_enable = devm_regmap_field_alloc(dev, regmap,6969+ reg_fields[INT_ENABLE]);7070+7171+ if (IS_ERR(sensor->int_thresh_hi) || IS_ERR(sensor->int_enable)) {7272+ dev_err(dev, "failed to alloc mmap regfields\n");7373+ return -EINVAL;7474+ }7575+7676+ return 0;7777+}7878+7979+static int st_mmap_enable_irq(struct st_thermal_sensor *sensor)8080+{8181+ int ret;8282+8383+ /* Set upper critical threshold */8484+ ret = regmap_field_write(sensor->int_thresh_hi,8585+ sensor->cdata->crit_temp -8686+ sensor->cdata->temp_adjust_val);8787+ if (ret)8888+ return ret;8989+9090+ return regmap_field_write(sensor->int_enable, 1);9191+}9292+9393+static int st_mmap_register_enable_irq(struct st_thermal_sensor *sensor)9494+{9595+ struct device *dev = sensor->dev;9696+ struct platform_device *pdev = to_platform_device(dev);9797+ int ret;9898+9999+ sensor->irq = platform_get_irq(pdev, 0);100100+ if (sensor->irq < 0) {101101+ dev_err(dev, "failed to register IRQ\n");102102+ return sensor->irq;103103+ }104104+105105+ ret = devm_request_threaded_irq(dev, sensor->irq,106106+ NULL, st_mmap_thermal_trip_handler,107107+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,108108+ dev->driver->name, sensor);109109+ if (ret) {110110+ dev_err(dev, "failed to register IRQ %d\n", sensor->irq);111111+ return ret;112112+ }113113+114114+ return st_mmap_enable_irq(sensor);115115+}116116+117117+static const struct regmap_config st_416mpe_regmap_config = {118118+ .reg_bits = 32,119119+ .val_bits = 32,120120+ .reg_stride = 4,121121+};122122+123123+static int st_mmap_regmap_init(struct st_thermal_sensor *sensor)124124+{125125+ struct device *dev = sensor->dev;126126+ struct platform_device *pdev = to_platform_device(dev);127127+ struct resource *res;128128+129129+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);130130+ if (!res) {131131+ dev_err(dev, "no memory resources defined\n");132132+ return -ENODEV;133133+ }134134+135135+ sensor->mmio_base = devm_ioremap_resource(dev, res);136136+ if (IS_ERR(sensor->mmio_base)) {137137+ dev_err(dev, "failed to remap IO\n");138138+ return PTR_ERR(sensor->mmio_base);139139+ }140140+141141+ sensor->regmap = devm_regmap_init_mmio(dev, sensor->mmio_base,142142+ &st_416mpe_regmap_config);143143+ if (IS_ERR(sensor->regmap)) {144144+ dev_err(dev, "failed to initialise regmap\n");145145+ return PTR_ERR(sensor->regmap);146146+ }147147+148148+ return 0;149149+}150150+151151+static const struct st_thermal_sensor_ops st_mmap_sensor_ops = {152152+ .power_ctrl = st_mmap_power_ctrl,153153+ .alloc_regfields = st_mmap_alloc_regfields,154154+ .regmap_init = st_mmap_regmap_init,155155+ .register_enable_irq = st_mmap_register_enable_irq,156156+ .enable_irq = st_mmap_enable_irq,157157+};158158+159159+/* Compatible device data stih416 mpe thermal sensor */160160+const struct st_thermal_compat_data st_416mpe_cdata = {161161+ .reg_fields = st_mmap_thermal_regfields,162162+ .ops = &st_mmap_sensor_ops,163163+ .calibration_val = 14,164164+ .temp_adjust_val = -95,165165+ .crit_temp = 120,166166+};167167+168168+/* Compatible device data stih407 thermal sensor */169169+const struct st_thermal_compat_data st_407_cdata = {170170+ .reg_fields = st_mmap_thermal_regfields,171171+ .ops = &st_mmap_sensor_ops,172172+ .calibration_val = 16,173173+ .temp_adjust_val = -95,174174+ .crit_temp = 120,175175+};176176+177177+static struct of_device_id st_mmap_thermal_of_match[] = {178178+ { .compatible = "st,stih416-mpe-thermal", .data = &st_416mpe_cdata },179179+ { .compatible = "st,stih407-thermal", .data = &st_407_cdata },180180+ { /* sentinel */ }181181+};182182+MODULE_DEVICE_TABLE(of, st_mmap_thermal_of_match);183183+184184+int st_mmap_probe(struct platform_device *pdev)185185+{186186+ return st_thermal_register(pdev, st_mmap_thermal_of_match);187187+}188188+189189+int st_mmap_remove(struct platform_device *pdev)190190+{191191+ return st_thermal_unregister(pdev);192192+}193193+194194+static struct platform_driver st_mmap_thermal_driver = {195195+ .driver = {196196+ .name = "st_thermal_mmap",197197+ .owner = THIS_MODULE,198198+ .pm = &st_thermal_pm_ops,199199+ .of_match_table = st_mmap_thermal_of_match,200200+ },201201+ .probe = st_mmap_probe,202202+ .remove = st_mmap_remove,203203+};204204+205205+module_platform_driver(st_mmap_thermal_driver);206206+207207+MODULE_AUTHOR("STMicroelectronics (R&D) Limited <ajitpal.singh@st.com>");208208+MODULE_DESCRIPTION("STMicroelectronics STi SoC Thermal Sensor Driver");209209+MODULE_LICENSE("GPL v2");
···158158 char name[THERMAL_NAME_LENGTH];159159};160160161161+/**162162+ * struct thermal_zone_device - structure for a thermal zone163163+ * @id: unique id number for each thermal zone164164+ * @type: the thermal zone device type165165+ * @device: &struct device for this thermal zone166166+ * @trip_temp_attrs: attributes for trip points for sysfs: trip temperature167167+ * @trip_type_attrs: attributes for trip points for sysfs: trip type168168+ * @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis169169+ * @devdata: private pointer for device private data170170+ * @trips: number of trip points the thermal zone supports171171+ * @passive_delay: number of milliseconds to wait between polls when172172+ * performing passive cooling. Currenty only used by the173173+ * step-wise governor174174+ * @polling_delay: number of milliseconds to wait between polls when175175+ * checking whether trip points have been crossed (0 for176176+ * interrupt driven systems)177177+ * @temperature: current temperature. This is only for core code,178178+ * drivers should use thermal_zone_get_temp() to get the179179+ * current temperature180180+ * @last_temperature: previous temperature read181181+ * @emul_temperature: emulated temperature when using CONFIG_THERMAL_EMULATION182182+ * @passive: 1 if you've crossed a passive trip point, 0 otherwise.183183+ * Currenty only used by the step-wise governor.184184+ * @forced_passive: If > 0, temperature at which to switch on all ACPI185185+ * processor cooling devices. Currently only used by the186186+ * step-wise governor.187187+ * @ops: operations this &thermal_zone_device supports188188+ * @tzp: thermal zone parameters189189+ * @governor: pointer to the governor for this thermal zone190190+ * @thermal_instances: list of &struct thermal_instance of this thermal zone191191+ * @idr: &struct idr to generate unique id for this zone's cooling192192+ * devices193193+ * @lock: lock to protect thermal_instances list194194+ * @node: node in thermal_tz_list (in thermal_core.c)195195+ * @poll_queue: delayed work for polling196196+ */161197struct thermal_zone_device {162198 int id;163199 char type[THERMAL_NAME_LENGTH];···215179 struct thermal_governor *governor;216180 struct list_head thermal_instances;217181 struct idr idr;218218- struct mutex lock; /* protect thermal_instances list */182182+ struct mutex lock;219183 struct list_head node;220184 struct delayed_work poll_queue;221185};222186223223-/* Structure that holds thermal governor information */187187+/**188188+ * struct thermal_governor - structure that holds thermal governor information189189+ * @name: name of the governor190190+ * @throttle: callback called for every trip point even if temperature is191191+ * below the trip point temperature192192+ * @governor_list: node in thermal_governor_list (in thermal_core.c)193193+ */224194struct thermal_governor {225195 char name[THERMAL_NAME_LENGTH];226196 int (*throttle)(struct thermal_zone_device *tz, int trip);