···10101111Required properties:1212- compatible : Should be:1313+ - "ti,omap34xx-bandgap" : for OMAP34xx bandgap1414+ - "ti,omap36xx-bandgap" : for OMAP36xx bandgap1315 - "ti,omap4430-bandgap" : for OMAP4430 bandgap1416 - "ti,omap4460-bandgap" : for OMAP4460 bandgap1517 - "ti,omap4470-bandgap" : for OMAP4470 bandgap···2725soc to soc, apart of depending on available features.28262927Example:2828+OMAP34xx:2929+bandgap {3030+ reg = <0x48002524 0x4>;3131+ compatible = "ti,omap34xx-bandgap";3232+};3333+3434+OMAP36xx:3535+bandgap {3636+ reg = <0x48002524 0x4>;3737+ compatible = "ti,omap36xx-bandgap";3838+};3939+3040OMAP4430:3141bandgap {3242 reg = <0x4a002260 0x4 0x4a00232C 0x4>;
+2-2
drivers/base/power/opp.c
···217217}218218219219/**220220- * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an available opp220220+ * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp221221 * @opp: opp for which voltage has to be returned for222222 *223223 * Return: voltage in micro volt corresponding to the opp, else···239239 opp_rcu_lockdep_assert();240240241241 tmp_opp = rcu_dereference(opp);242242- if (IS_ERR_OR_NULL(tmp_opp) || !tmp_opp->available)242242+ if (IS_ERR_OR_NULL(tmp_opp))243243 pr_err("%s: Invalid parameters\n", __func__);244244 else245245 v = tmp_opp->u_volt;
+14
drivers/thermal/Kconfig
···147147 device that is configured to use this cooling mechanism will be148148 controlled to reduce clock frequency whenever temperature is high.149149150150+config DEVFREQ_THERMAL151151+ bool "Generic device cooling support"152152+ depends on PM_DEVFREQ153153+ depends on PM_OPP154154+ help155155+ This implements the generic devfreq cooling mechanism through156156+ frequency reduction for devices using devfreq.157157+158158+ This will throttle the device by limiting the maximum allowed DVFS159159+ frequency corresponding to the cooling level.160160+161161+ In order to use the power extensions of the cooling device,162162+ devfreq should use the simple_ondemand governor.163163+150164 If you want this support, you should say Y here.151165152166config THERMAL_EMULATION
···11+/*22+ * devfreq_cooling: Thermal cooling device implementation for devices using33+ * devfreq44+ *55+ * Copyright (C) 2014-2015 ARM Limited66+ *77+ * This program is free software; you can redistribute it and/or modify88+ * it under the terms of the GNU General Public License version 2 as99+ * published by the Free Software Foundation.1010+ *1111+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any1212+ * kind, whether express or implied; without even the implied warranty1313+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414+ * GNU General Public License for more details.1515+ *1616+ * TODO:1717+ * - If OPPs are added or removed after devfreq cooling has1818+ * registered, the devfreq cooling won't react to it.1919+ */2020+2121+#include <linux/devfreq.h>2222+#include <linux/devfreq_cooling.h>2323+#include <linux/export.h>2424+#include <linux/slab.h>2525+#include <linux/pm_opp.h>2626+#include <linux/thermal.h>2727+2828+#include <trace/events/thermal.h>2929+3030+static DEFINE_MUTEX(devfreq_lock);3131+static DEFINE_IDR(devfreq_idr);3232+3333+/**3434+ * struct devfreq_cooling_device - Devfreq cooling device3535+ * @id: unique integer value corresponding to each3636+ * devfreq_cooling_device registered.3737+ * @cdev: Pointer to associated thermal cooling device.3838+ * @devfreq: Pointer to associated devfreq device.3939+ * @cooling_state: Current cooling state.4040+ * @power_table: Pointer to table with maximum power draw for each4141+ * cooling state. State is the index into the table, and4242+ * the power is in mW.4343+ * @freq_table: Pointer to a table with the frequencies sorted in descending4444+ * order. You can index the table by cooling device state4545+ * @freq_table_size: Size of the @freq_table and @power_table4646+ * @power_ops: Pointer to devfreq_cooling_power, used to generate the4747+ * @power_table.4848+ */4949+struct devfreq_cooling_device {5050+ int id;5151+ struct thermal_cooling_device *cdev;5252+ struct devfreq *devfreq;5353+ unsigned long cooling_state;5454+ u32 *power_table;5555+ u32 *freq_table;5656+ size_t freq_table_size;5757+ struct devfreq_cooling_power *power_ops;5858+};5959+6060+/**6161+ * get_idr - function to get a unique id.6262+ * @idr: struct idr * handle used to create a id.6363+ * @id: int * value generated by this function.6464+ *6565+ * This function will populate @id with an unique6666+ * id, using the idr API.6767+ *6868+ * Return: 0 on success, an error code on failure.6969+ */7070+static int get_idr(struct idr *idr, int *id)7171+{7272+ int ret;7373+7474+ mutex_lock(&devfreq_lock);7575+ ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);7676+ mutex_unlock(&devfreq_lock);7777+ if (unlikely(ret < 0))7878+ return ret;7979+ *id = ret;8080+8181+ return 0;8282+}8383+8484+/**8585+ * release_idr - function to free the unique id.8686+ * @idr: struct idr * handle used for creating the id.8787+ * @id: int value representing the unique id.8888+ */8989+static void release_idr(struct idr *idr, int id)9090+{9191+ mutex_lock(&devfreq_lock);9292+ idr_remove(idr, id);9393+ mutex_unlock(&devfreq_lock);9494+}9595+9696+/**9797+ * partition_enable_opps() - disable all opps above a given state9898+ * @dfc: Pointer to devfreq we are operating on9999+ * @cdev_state: cooling device state we're setting100100+ *101101+ * Go through the OPPs of the device, enabling all OPPs until102102+ * @cdev_state and disabling those frequencies above it.103103+ */104104+static int partition_enable_opps(struct devfreq_cooling_device *dfc,105105+ unsigned long cdev_state)106106+{107107+ int i;108108+ struct device *dev = dfc->devfreq->dev.parent;109109+110110+ for (i = 0; i < dfc->freq_table_size; i++) {111111+ struct dev_pm_opp *opp;112112+ int ret = 0;113113+ unsigned int freq = dfc->freq_table[i];114114+ bool want_enable = i >= cdev_state ? true : false;115115+116116+ rcu_read_lock();117117+ opp = dev_pm_opp_find_freq_exact(dev, freq, !want_enable);118118+ rcu_read_unlock();119119+120120+ if (PTR_ERR(opp) == -ERANGE)121121+ continue;122122+ else if (IS_ERR(opp))123123+ return PTR_ERR(opp);124124+125125+ if (want_enable)126126+ ret = dev_pm_opp_enable(dev, freq);127127+ else128128+ ret = dev_pm_opp_disable(dev, freq);129129+130130+ if (ret)131131+ return ret;132132+ }133133+134134+ return 0;135135+}136136+137137+static int devfreq_cooling_get_max_state(struct thermal_cooling_device *cdev,138138+ unsigned long *state)139139+{140140+ struct devfreq_cooling_device *dfc = cdev->devdata;141141+142142+ *state = dfc->freq_table_size - 1;143143+144144+ return 0;145145+}146146+147147+static int devfreq_cooling_get_cur_state(struct thermal_cooling_device *cdev,148148+ unsigned long *state)149149+{150150+ struct devfreq_cooling_device *dfc = cdev->devdata;151151+152152+ *state = dfc->cooling_state;153153+154154+ return 0;155155+}156156+157157+static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev,158158+ unsigned long state)159159+{160160+ struct devfreq_cooling_device *dfc = cdev->devdata;161161+ struct devfreq *df = dfc->devfreq;162162+ struct device *dev = df->dev.parent;163163+ int ret;164164+165165+ if (state == dfc->cooling_state)166166+ return 0;167167+168168+ dev_dbg(dev, "Setting cooling state %lu\n", state);169169+170170+ if (state >= dfc->freq_table_size)171171+ return -EINVAL;172172+173173+ ret = partition_enable_opps(dfc, state);174174+ if (ret)175175+ return ret;176176+177177+ dfc->cooling_state = state;178178+179179+ return 0;180180+}181181+182182+/**183183+ * freq_get_state() - get the cooling state corresponding to a frequency184184+ * @dfc: Pointer to devfreq cooling device185185+ * @freq: frequency in Hz186186+ *187187+ * Return: the cooling state associated with the @freq, or188188+ * THERMAL_CSTATE_INVALID if it wasn't found.189189+ */190190+static unsigned long191191+freq_get_state(struct devfreq_cooling_device *dfc, unsigned long freq)192192+{193193+ int i;194194+195195+ for (i = 0; i < dfc->freq_table_size; i++) {196196+ if (dfc->freq_table[i] == freq)197197+ return i;198198+ }199199+200200+ return THERMAL_CSTATE_INVALID;201201+}202202+203203+/**204204+ * get_static_power() - calculate the static power205205+ * @dfc: Pointer to devfreq cooling device206206+ * @freq: Frequency in Hz207207+ *208208+ * Calculate the static power in milliwatts using the supplied209209+ * get_static_power(). The current voltage is calculated using the210210+ * OPP library. If no get_static_power() was supplied, assume the211211+ * static power is negligible.212212+ */213213+static unsigned long214214+get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)215215+{216216+ struct devfreq *df = dfc->devfreq;217217+ struct device *dev = df->dev.parent;218218+ unsigned long voltage;219219+ struct dev_pm_opp *opp;220220+221221+ if (!dfc->power_ops->get_static_power)222222+ return 0;223223+224224+ rcu_read_lock();225225+226226+ opp = dev_pm_opp_find_freq_exact(dev, freq, true);227227+ if (IS_ERR(opp) && (PTR_ERR(opp) == -ERANGE))228228+ opp = dev_pm_opp_find_freq_exact(dev, freq, false);229229+230230+ voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */231231+232232+ rcu_read_unlock();233233+234234+ if (voltage == 0) {235235+ dev_warn_ratelimited(dev,236236+ "Failed to get voltage for frequency %lu: %ld\n",237237+ freq, IS_ERR(opp) ? PTR_ERR(opp) : 0);238238+ return 0;239239+ }240240+241241+ return dfc->power_ops->get_static_power(voltage);242242+}243243+244244+/**245245+ * get_dynamic_power - calculate the dynamic power246246+ * @dfc: Pointer to devfreq cooling device247247+ * @freq: Frequency in Hz248248+ * @voltage: Voltage in millivolts249249+ *250250+ * Calculate the dynamic power in milliwatts consumed by the device at251251+ * frequency @freq and voltage @voltage. If the get_dynamic_power()252252+ * was supplied as part of the devfreq_cooling_power struct, then that253253+ * function is used. Otherwise, a simple power model (Pdyn = Coeff *254254+ * Voltage^2 * Frequency) is used.255255+ */256256+static unsigned long257257+get_dynamic_power(struct devfreq_cooling_device *dfc, unsigned long freq,258258+ unsigned long voltage)259259+{260260+ unsigned long power;261261+ u32 freq_mhz;262262+ struct devfreq_cooling_power *dfc_power = dfc->power_ops;263263+264264+ if (dfc_power->get_dynamic_power)265265+ return dfc_power->get_dynamic_power(freq, voltage);266266+267267+ freq_mhz = freq / 1000000;268268+ power = (u64)dfc_power->dyn_power_coeff * freq_mhz * voltage * voltage;269269+ do_div(power, 1000000000);270270+271271+ return power;272272+}273273+274274+static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev,275275+ struct thermal_zone_device *tz,276276+ u32 *power)277277+{278278+ struct devfreq_cooling_device *dfc = cdev->devdata;279279+ struct devfreq *df = dfc->devfreq;280280+ struct devfreq_dev_status *status = &df->last_status;281281+ unsigned long state;282282+ unsigned long freq = status->current_frequency;283283+ u32 dyn_power, static_power;284284+285285+ /* Get dynamic power for state */286286+ state = freq_get_state(dfc, freq);287287+ if (state == THERMAL_CSTATE_INVALID)288288+ return -EAGAIN;289289+290290+ dyn_power = dfc->power_table[state];291291+292292+ /* Scale dynamic power for utilization */293293+ dyn_power = (dyn_power * status->busy_time) / status->total_time;294294+295295+ /* Get static power */296296+ static_power = get_static_power(dfc, freq);297297+298298+ trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power,299299+ static_power);300300+301301+ *power = dyn_power + static_power;302302+303303+ return 0;304304+}305305+306306+static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev,307307+ struct thermal_zone_device *tz,308308+ unsigned long state,309309+ u32 *power)310310+{311311+ struct devfreq_cooling_device *dfc = cdev->devdata;312312+ unsigned long freq;313313+ u32 static_power;314314+315315+ if (state < 0 || state >= dfc->freq_table_size)316316+ return -EINVAL;317317+318318+ freq = dfc->freq_table[state];319319+ static_power = get_static_power(dfc, freq);320320+321321+ *power = dfc->power_table[state] + static_power;322322+ return 0;323323+}324324+325325+static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,326326+ struct thermal_zone_device *tz,327327+ u32 power, unsigned long *state)328328+{329329+ struct devfreq_cooling_device *dfc = cdev->devdata;330330+ struct devfreq *df = dfc->devfreq;331331+ struct devfreq_dev_status *status = &df->last_status;332332+ unsigned long freq = status->current_frequency;333333+ unsigned long busy_time;334334+ s32 dyn_power;335335+ u32 static_power;336336+ int i;337337+338338+ static_power = get_static_power(dfc, freq);339339+340340+ dyn_power = power - static_power;341341+ dyn_power = dyn_power > 0 ? dyn_power : 0;342342+343343+ /* Scale dynamic power for utilization */344344+ busy_time = status->busy_time ?: 1;345345+ dyn_power = (dyn_power * status->total_time) / busy_time;346346+347347+ /*348348+ * Find the first cooling state that is within the power349349+ * budget for dynamic power.350350+ */351351+ for (i = 0; i < dfc->freq_table_size - 1; i++)352352+ if (dyn_power >= dfc->power_table[i])353353+ break;354354+355355+ *state = i;356356+ trace_thermal_power_devfreq_limit(cdev, freq, *state, power);357357+ return 0;358358+}359359+360360+static struct thermal_cooling_device_ops devfreq_cooling_ops = {361361+ .get_max_state = devfreq_cooling_get_max_state,362362+ .get_cur_state = devfreq_cooling_get_cur_state,363363+ .set_cur_state = devfreq_cooling_set_cur_state,364364+};365365+366366+/**367367+ * devfreq_cooling_gen_tables() - Generate power and freq tables.368368+ * @dfc: Pointer to devfreq cooling device.369369+ *370370+ * Generate power and frequency tables: the power table hold the371371+ * device's maximum power usage at each cooling state (OPP). The372372+ * static and dynamic power using the appropriate voltage and373373+ * frequency for the state, is acquired from the struct374374+ * devfreq_cooling_power, and summed to make the maximum power draw.375375+ *376376+ * The frequency table holds the frequencies in descending order.377377+ * That way its indexed by cooling device state.378378+ *379379+ * The tables are malloced, and pointers put in dfc. They must be380380+ * freed when unregistering the devfreq cooling device.381381+ *382382+ * Return: 0 on success, negative error code on failure.383383+ */384384+static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc)385385+{386386+ struct devfreq *df = dfc->devfreq;387387+ struct device *dev = df->dev.parent;388388+ int ret, num_opps;389389+ unsigned long freq;390390+ u32 *power_table = NULL;391391+ u32 *freq_table;392392+ int i;393393+394394+ num_opps = dev_pm_opp_get_opp_count(dev);395395+396396+ if (dfc->power_ops) {397397+ power_table = kcalloc(num_opps, sizeof(*power_table),398398+ GFP_KERNEL);399399+ if (!power_table)400400+ ret = -ENOMEM;401401+ }402402+403403+ freq_table = kcalloc(num_opps, sizeof(*freq_table),404404+ GFP_KERNEL);405405+ if (!freq_table) {406406+ ret = -ENOMEM;407407+ goto free_power_table;408408+ }409409+410410+ for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) {411411+ unsigned long power_dyn, voltage;412412+ struct dev_pm_opp *opp;413413+414414+ rcu_read_lock();415415+416416+ opp = dev_pm_opp_find_freq_floor(dev, &freq);417417+ if (IS_ERR(opp)) {418418+ rcu_read_unlock();419419+ ret = PTR_ERR(opp);420420+ goto free_tables;421421+ }422422+423423+ voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */424424+425425+ rcu_read_unlock();426426+427427+ if (dfc->power_ops) {428428+ power_dyn = get_dynamic_power(dfc, freq, voltage);429429+430430+ dev_dbg(dev, "Dynamic power table: %lu MHz @ %lu mV: %lu = %lu mW\n",431431+ freq / 1000000, voltage, power_dyn, power_dyn);432432+433433+ power_table[i] = power_dyn;434434+ }435435+436436+ freq_table[i] = freq;437437+ }438438+439439+ if (dfc->power_ops)440440+ dfc->power_table = power_table;441441+442442+ dfc->freq_table = freq_table;443443+ dfc->freq_table_size = num_opps;444444+445445+ return 0;446446+447447+free_tables:448448+ kfree(freq_table);449449+free_power_table:450450+ kfree(power_table);451451+452452+ return ret;453453+}454454+455455+/**456456+ * of_devfreq_cooling_register_power() - Register devfreq cooling device,457457+ * with OF and power information.458458+ * @np: Pointer to OF device_node.459459+ * @df: Pointer to devfreq device.460460+ * @dfc_power: Pointer to devfreq_cooling_power.461461+ *462462+ * Register a devfreq cooling device. The available OPPs must be463463+ * registered on the device.464464+ *465465+ * If @dfc_power is provided, the cooling device is registered with the466466+ * power extensions. For the power extensions to work correctly,467467+ * devfreq should use the simple_ondemand governor, other governors468468+ * are not currently supported.469469+ */470470+struct devfreq_cooling_device *471471+of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,472472+ struct devfreq_cooling_power *dfc_power)473473+{474474+ struct thermal_cooling_device *cdev;475475+ struct devfreq_cooling_device *dfc;476476+ char dev_name[THERMAL_NAME_LENGTH];477477+ int err;478478+479479+ dfc = kzalloc(sizeof(*dfc), GFP_KERNEL);480480+ if (!dfc)481481+ return ERR_PTR(-ENOMEM);482482+483483+ dfc->devfreq = df;484484+485485+ if (dfc_power) {486486+ dfc->power_ops = dfc_power;487487+488488+ devfreq_cooling_ops.get_requested_power =489489+ devfreq_cooling_get_requested_power;490490+ devfreq_cooling_ops.state2power = devfreq_cooling_state2power;491491+ devfreq_cooling_ops.power2state = devfreq_cooling_power2state;492492+ }493493+494494+ err = devfreq_cooling_gen_tables(dfc);495495+ if (err)496496+ goto free_dfc;497497+498498+ err = get_idr(&devfreq_idr, &dfc->id);499499+ if (err)500500+ goto free_tables;501501+502502+ snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id);503503+504504+ cdev = thermal_of_cooling_device_register(np, dev_name, dfc,505505+ &devfreq_cooling_ops);506506+ if (IS_ERR(cdev)) {507507+ err = PTR_ERR(cdev);508508+ dev_err(df->dev.parent,509509+ "Failed to register devfreq cooling device (%d)\n",510510+ err);511511+ goto release_idr;512512+ }513513+514514+ dfc->cdev = cdev;515515+516516+ return dfc;517517+518518+release_idr:519519+ release_idr(&devfreq_idr, dfc->id);520520+free_tables:521521+ kfree(dfc->power_table);522522+ kfree(dfc->freq_table);523523+free_dfc:524524+ kfree(dfc);525525+526526+ return ERR_PTR(err);527527+}528528+EXPORT_SYMBOL_GPL(of_devfreq_cooling_register_power);529529+530530+/**531531+ * of_devfreq_cooling_register() - Register devfreq cooling device,532532+ * with OF information.533533+ * @np: Pointer to OF device_node.534534+ * @df: Pointer to devfreq device.535535+ */536536+struct devfreq_cooling_device *537537+of_devfreq_cooling_register(struct device_node *np, struct devfreq *df)538538+{539539+ return of_devfreq_cooling_register_power(np, df, NULL);540540+}541541+EXPORT_SYMBOL_GPL(of_devfreq_cooling_register);542542+543543+/**544544+ * devfreq_cooling_register() - Register devfreq cooling device.545545+ * @df: Pointer to devfreq device.546546+ */547547+struct devfreq_cooling_device *devfreq_cooling_register(struct devfreq *df)548548+{549549+ return of_devfreq_cooling_register(NULL, df);550550+}551551+EXPORT_SYMBOL_GPL(devfreq_cooling_register);552552+553553+/**554554+ * devfreq_cooling_unregister() - Unregister devfreq cooling device.555555+ * @dfc: Pointer to devfreq cooling device to unregister.556556+ */557557+void devfreq_cooling_unregister(struct devfreq_cooling_device *dfc)558558+{559559+ if (!dfc)560560+ return;561561+562562+ thermal_cooling_device_unregister(dfc->cdev);563563+ release_idr(&devfreq_idr, dfc->id);564564+ kfree(dfc->power_table);565565+ kfree(dfc->freq_table);566566+567567+ kfree(dfc);568568+}569569+EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);
+12-9
drivers/thermal/imx_thermal.c
···288288 if (trip == IMX_TRIP_CRITICAL)289289 return -EPERM;290290291291- if (temp > IMX_TEMP_PASSIVE)291291+ if (temp < 0 || temp > IMX_TEMP_PASSIVE)292292 return -EINVAL;293293294294 data->temp_passive = temp;···487487 if (data->irq < 0)488488 return data->irq;489489490490- ret = devm_request_threaded_irq(&pdev->dev, data->irq,491491- imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,492492- 0, "imx_thermal", data);493493- if (ret < 0) {494494- dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);495495- return ret;496496- }497497-498490 platform_set_drvdata(pdev, data);499491500492 ret = imx_get_sensor_data(pdev);···562570563571 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);564572 regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);573573+574574+ ret = devm_request_threaded_irq(&pdev->dev, data->irq,575575+ imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,576576+ 0, "imx_thermal", data);577577+ if (ret < 0) {578578+ dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);579579+ clk_disable_unprepare(data->thermal_clk);580580+ thermal_zone_device_unregister(data->tz);581581+ cpufreq_cooling_unregister(data->cdev);582582+ return ret;583583+ }565584566585 data->irq_enabled = true;567586 data->mode = THERMAL_DEVICE_ENABLED;
+17-21
drivers/thermal/rockchip_thermal.c
···106106#define TSADCV2_AUTO_PERIOD_HT 0x6c107107108108#define TSADCV2_AUTO_EN BIT(0)109109-#define TSADCV2_AUTO_DISABLE ~BIT(0)110109#define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn))111110#define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8)112112-#define TSADCV2_AUTO_TSHUT_POLARITY_LOW ~BIT(8)113111114112#define TSADCV2_INT_SRC_EN(chn) BIT(chn)115113#define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn))116114#define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn))117115118118-#define TSADCV2_INT_PD_CLEAR ~BIT(8)116116+#define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8)119117120118#define TSADCV2_DATA_MASK 0xfff121119#define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4···122124#define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* msec */123125124126struct tsadc_table {125125- unsigned long code;127127+ u32 code;126128 long temp;127129};128130···162164 {3452, 115000},163165 {3437, 120000},164166 {3421, 125000},165165- {0, 125000},166167};167168168169static u32 rk_tsadcv2_temp_to_code(long temp)···188191 return 0;189192}190193191191-static int rk_tsadcv2_code_to_temp(u32 code)194194+static int rk_tsadcv2_code_to_temp(u32 code, int *temp)192195{193193- unsigned int low = 0;196196+ unsigned int low = 1;194197 unsigned int high = ARRAY_SIZE(v2_code_table) - 1;195198 unsigned int mid = (low + high) / 2;196199 unsigned int num;197200 unsigned long denom;198201199199- /* Invalid code, return -EAGAIN */200200- if (code > TSADCV2_DATA_MASK)201201- return -EAGAIN;202202+ BUILD_BUG_ON(ARRAY_SIZE(v2_code_table) < 2);202203203203- while (low <= high && mid) {204204+ code &= TSADCV2_DATA_MASK;205205+ if (code < v2_code_table[high].code)206206+ return -EAGAIN; /* Incorrect reading */207207+208208+ while (low <= high) {204209 if (code >= v2_code_table[mid].code &&205210 code < v2_code_table[mid - 1].code)206211 break;···222223 num = v2_code_table[mid].temp - v2_code_table[mid - 1].temp;223224 num *= v2_code_table[mid - 1].code - code;224225 denom = v2_code_table[mid - 1].code - v2_code_table[mid].code;225225- return v2_code_table[mid - 1].temp + (num / denom);226226+ *temp = v2_code_table[mid - 1].temp + (num / denom);227227+228228+ return 0;226229}227230228231/**···242241 enum tshut_polarity tshut_polarity)243242{244243 if (tshut_polarity == TSHUT_HIGH_ACTIVE)245245- writel_relaxed(0 | (TSADCV2_AUTO_TSHUT_POLARITY_HIGH),244244+ writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,246245 regs + TSADCV2_AUTO_CON);247246 else248248- writel_relaxed(0 | (TSADCV2_AUTO_TSHUT_POLARITY_LOW),247247+ writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,249248 regs + TSADCV2_AUTO_CON);250249251250 writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);···262261 u32 val;263262264263 val = readl_relaxed(regs + TSADCV2_INT_PD);265265- writel_relaxed(val & TSADCV2_INT_PD_CLEAR, regs + TSADCV2_INT_PD);264264+ writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);266265}267266268267static void rk_tsadcv2_control(void __iomem *regs, bool enable)···282281{283282 u32 val;284283285285- /* the A/D value of the channel last conversion need some time */286284 val = readl_relaxed(regs + TSADCV2_DATA(chn));287287- if (val == 0)288288- return -EAGAIN;289285290290- *temp = rk_tsadcv2_code_to_temp(val);291291-292292- return 0;286286+ return rk_tsadcv2_code_to_temp(val, temp);293287}294288295289static void rk_tsadcv2_tshut_temp(int chn, void __iomem *regs, long temp)
+15
drivers/thermal/ti-soc-thermal/Kconfig
···1919 This includes trip points definitions, extrapolation rules and2020 CPU cooling device bindings.21212222+config OMAP3_THERMAL2323+ bool "Texas Instruments OMAP3 thermal support"2424+ depends on TI_SOC_THERMAL2525+ depends on ARCH_OMAP3 || COMPILE_TEST2626+ help2727+ If you say yes here you get thermal support for the Texas Instruments2828+ OMAP3 SoC family. The current chips supported are:2929+ - OMAP34303030+3131+ OMAP3 chips normally don't need thermal management, and sensors in3232+ this generation are not accurate, nor they are very close to3333+ the important hotspots.3434+3535+ Say 'N' here.3636+2237config OMAP4_THERMAL2338 bool "Texas Instruments OMAP4 thermal support"2439 depends on TI_SOC_THERMAL
···11+/*22+ * OMAP3 thermal driver.33+ *44+ * Copyright (C) 2011-2012 Texas Instruments Inc.55+ * Copyright (C) 2014 Pavel Machek <pavel@ucw.cz>66+ *77+ * This software is licensed under the terms of the GNU General Public88+ * License version 2, as published by the Free Software Foundation, and99+ * may be copied, distributed, and modified under those terms.1010+ *1111+ * This program is distributed in the hope that it will be useful,1212+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1313+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414+ * GNU General Public License for more details.1515+ *1616+ * Note1717+ * http://www.ti.com/lit/er/sprz278f/sprz278f.pdf "Advisory1818+ * 3.1.1.186 MMC OCP Clock Not Gated When Thermal Sensor Is Used"1919+ *2020+ * Also TI says:2121+ * Just be careful when you try to make thermal policy like decisions2222+ * based on this sensor. Placement of the sensor w.r.t the actual logic2323+ * generating heat has to be a factor as well. If you are just looking2424+ * for an approximation temperature (thermometerish kind), you might be2525+ * ok with this. I am not sure we'd find any TI data around this.. just a2626+ * heads up.2727+ */2828+2929+#include "ti-thermal.h"3030+#include "ti-bandgap.h"3131+3232+/*3333+ * OMAP34XX has one instance of thermal sensor for MPU3434+ * need to describe the individual bit fields3535+ */3636+static struct temp_sensor_registers3737+omap34xx_mpu_temp_sensor_registers = {3838+ .temp_sensor_ctrl = 0,3939+ .bgap_soc_mask = BIT(8),4040+ .bgap_eocz_mask = BIT(7),4141+ .bgap_dtemp_mask = 0x7f,4242+4343+ .bgap_mode_ctrl = 0,4444+ .mode_ctrl_mask = BIT(9),4545+};4646+4747+/* Thresholds and limits for OMAP34XX MPU temperature sensor */4848+static struct temp_sensor_data omap34xx_mpu_temp_sensor_data = {4949+ .min_freq = 32768,5050+ .max_freq = 32768,5151+ .max_temp = 125000,5252+ .min_temp = -40000,5353+ .hyst_val = 5000,5454+};5555+5656+/*5757+ * Temperature values in milli degree celsius5858+ */5959+static const int6060+omap34xx_adc_to_temp[128] = {6161+ -40000, -40000, -40000, -40000, -40000, -39000, -38000, -36000,6262+ -34000, -32000, -31000, -29000, -28000, -26000, -25000, -24000,6363+ -22000, -21000, -19000, -18000, -17000, -15000, -14000, -12000,6464+ -11000, -9000, -8000, -7000, -5000, -4000, -2000, -1000, 0000,6565+ 1000, 3000, 4000, 5000, 7000, 8000, 10000, 11000, 13000, 14000,6666+ 15000, 17000, 18000, 20000, 21000, 22000, 24000, 25000, 27000,6767+ 28000, 30000, 31000, 32000, 34000, 35000, 37000, 38000, 39000,6868+ 41000, 42000, 44000, 45000, 47000, 48000, 49000, 51000, 52000,6969+ 53000, 55000, 56000, 58000, 59000, 60000, 62000, 63000, 65000,7070+ 66000, 67000, 69000, 70000, 72000, 73000, 74000, 76000, 77000,7171+ 79000, 80000, 81000, 83000, 84000, 85000, 87000, 88000, 89000,7272+ 91000, 92000, 94000, 95000, 96000, 98000, 99000, 100000,7373+ 102000, 103000, 105000, 106000, 107000, 109000, 110000, 111000,7474+ 113000, 114000, 116000, 117000, 118000, 120000, 121000, 122000,7575+ 124000, 124000, 125000, 125000, 125000, 125000, 1250007676+};7777+7878+/* OMAP34XX data */7979+const struct ti_bandgap_data omap34xx_data = {8080+ .features = TI_BANDGAP_FEATURE_CLK_CTRL | TI_BANDGAP_FEATURE_UNRELIABLE,8181+ .fclock_name = "ts_fck",8282+ .div_ck_name = "ts_fck",8383+ .conv_table = omap34xx_adc_to_temp,8484+ .adc_start_val = 0,8585+ .adc_end_val = 127,8686+ .expose_sensor = ti_thermal_expose_sensor,8787+ .remove_sensor = ti_thermal_remove_sensor,8888+8989+ .sensors = {9090+ {9191+ .registers = &omap34xx_mpu_temp_sensor_registers,9292+ .ts_data = &omap34xx_mpu_temp_sensor_data,9393+ .domain = "cpu",9494+ .slope = 0,9595+ .constant = 20000,9696+ .slope_pcb = 0,9797+ .constant_pcb = 20000,9898+ .register_cooling = NULL,9999+ .unregister_cooling = NULL,100100+ },101101+ },102102+ .sensor_count = 1,103103+};104104+105105+/*106106+ * OMAP36XX has one instance of thermal sensor for MPU107107+ * need to describe the individual bit fields108108+ */109109+static struct temp_sensor_registers110110+omap36xx_mpu_temp_sensor_registers = {111111+ .temp_sensor_ctrl = 0,112112+ .bgap_soc_mask = BIT(9),113113+ .bgap_eocz_mask = BIT(8),114114+ .bgap_dtemp_mask = 0xFF,115115+116116+ .bgap_mode_ctrl = 0,117117+ .mode_ctrl_mask = BIT(10),118118+};119119+120120+/* Thresholds and limits for OMAP36XX MPU temperature sensor */121121+static struct temp_sensor_data omap36xx_mpu_temp_sensor_data = {122122+ .min_freq = 32768,123123+ .max_freq = 32768,124124+ .max_temp = 125000,125125+ .min_temp = -40000,126126+ .hyst_val = 5000,127127+};128128+129129+/*130130+ * Temperature values in milli degree celsius131131+ */132132+static const int133133+omap36xx_adc_to_temp[128] = {134134+ -40000, -40000, -40000, -40000, -40000, -40000, -40000, -40000,135135+ -40000, -40000, -40000, -40000, -40000, -38000, -35000, -34000,136136+ -32000, -30000, -28000, -26000, -24000, -22000, -20000, -18500,137137+ -17000, -15000, -13500, -12000, -10000, -8000, -6500, -5000, -3500,138138+ -1500, 0, 2000, 3500, 5000, 6500, 8500, 10000, 12000, 13500,139139+ 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28500, 30000,140140+ 32000, 33500, 35000, 37000, 38500, 40000, 42000, 43500, 45000,141141+ 47000, 48500, 50000, 52000, 53500, 55000, 57000, 58500, 60000,142142+ 62000, 64000, 66000, 68000, 70000, 71500, 73500, 75000, 77000,143143+ 78500, 80000, 82000, 83500, 85000, 87000, 88500, 90000, 92000,144144+ 93500, 95000, 97000, 98500, 100000, 102000, 103500, 105000, 107000,145145+ 109000, 111000, 113000, 115000, 117000, 118500, 120000, 122000,146146+ 123500, 125000, 125000, 125000, 125000, 125000, 125000, 125000,147147+ 125000, 125000, 125000, 125000, 125000, 125000, 125000, 125000,148148+ 125000, 125000, 125000, 125000, 125000, 125000, 125000149149+};150150+151151+/* OMAP36XX data */152152+const struct ti_bandgap_data omap36xx_data = {153153+ .features = TI_BANDGAP_FEATURE_CLK_CTRL | TI_BANDGAP_FEATURE_UNRELIABLE,154154+ .fclock_name = "ts_fck",155155+ .div_ck_name = "ts_fck",156156+ .conv_table = omap36xx_adc_to_temp,157157+ .adc_start_val = 0,158158+ .adc_end_val = 127,159159+ .expose_sensor = ti_thermal_expose_sensor,160160+ .remove_sensor = ti_thermal_remove_sensor,161161+162162+ .sensors = {163163+ {164164+ .registers = &omap36xx_mpu_temp_sensor_registers,165165+ .ts_data = &omap36xx_mpu_temp_sensor_data,166166+ .domain = "cpu",167167+ .slope = 0,168168+ .constant = 20000,169169+ .slope_pcb = 0,170170+ .constant_pcb = 20000,171171+ .register_cooling = NULL,172172+ .unregister_cooling = NULL,173173+ },174174+ },175175+ .sensor_count = 1,176176+};
+14
drivers/thermal/ti-soc-thermal/ti-bandgap.c
···12741274 }12751275 bgp->dev = &pdev->dev;1276127612771277+ if (TI_BANDGAP_HAS(bgp, UNRELIABLE))12781278+ dev_warn(&pdev->dev,12791279+ "This OMAP thermal sensor is unreliable. You've been warned\n");12801280+12771281 if (TI_BANDGAP_HAS(bgp, TSHUT)) {12781282 ret = ti_bandgap_tshut_init(bgp, pdev);12791283 if (ret) {···15831579#endif1584158015851581static const struct of_device_id of_ti_bandgap_match[] = {15821582+#ifdef CONFIG_OMAP3_THERMAL15831583+ {15841584+ .compatible = "ti,omap34xx-bandgap",15851585+ .data = (void *)&omap34xx_data,15861586+ },15871587+ {15881588+ .compatible = "ti,omap36xx-bandgap",15891589+ .data = (void *)&omap36xx_data,15901590+ },15911591+#endif15861592#ifdef CONFIG_OMAP4_THERMAL15871593 {15881594 .compatible = "ti,omap4430-bandgap",
+11
drivers/thermal/ti-soc-thermal/ti-bandgap.h
···322322 * has Errata 814323323 * TI_BANDGAP_FEATURE_ERRATA_813 - used to workaorund when the bandgap device324324 * has Errata 813325325+ * TI_BANDGAP_FEATURE_UNRELIABLE - used when the sensor readings are too326326+ * inaccurate.325327 * TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a326328 * specific feature (above) or not. Return non-zero, if yes.327329 */···339337#define TI_BANDGAP_FEATURE_HISTORY_BUFFER BIT(9)340338#define TI_BANDGAP_FEATURE_ERRATA_814 BIT(10)341339#define TI_BANDGAP_FEATURE_ERRATA_813 BIT(11)340340+#define TI_BANDGAP_FEATURE_UNRELIABLE BIT(12)342341#define TI_BANDGAP_HAS(b, f) \343342 ((b)->conf->features & TI_BANDGAP_FEATURE_ ## f)344343···392389int ti_bandgap_set_sensor_data(struct ti_bandgap *bgp, int id, void *data);393390void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id);394391int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend);392392+393393+#ifdef CONFIG_OMAP3_THERMAL394394+extern const struct ti_bandgap_data omap34xx_data;395395+extern const struct ti_bandgap_data omap36xx_data;396396+#else397397+#define omap34xx_data NULL398398+#define omap36xx_data NULL399399+#endif395400396401#ifdef CONFIG_OMAP4_THERMAL397402extern const struct ti_bandgap_data omap4430_data;
+81
include/linux/devfreq_cooling.h
···11+/*22+ * devfreq_cooling: Thermal cooling device implementation for devices using33+ * devfreq44+ *55+ * Copyright (C) 2014-2015 ARM Limited66+ *77+ * This program is free software; you can redistribute it and/or modify88+ * it under the terms of the GNU General Public License version 2 as99+ * published by the Free Software Foundation.1010+ *1111+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any1212+ * kind, whether express or implied; without even the implied warranty1313+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414+ * GNU General Public License for more details.1515+ */1616+1717+#ifndef __DEVFREQ_COOLING_H__1818+#define __DEVFREQ_COOLING_H__1919+2020+#include <linux/devfreq.h>2121+#include <linux/thermal.h>2222+2323+#ifdef CONFIG_DEVFREQ_THERMAL2424+2525+/**2626+ * struct devfreq_cooling_power - Devfreq cooling power ops2727+ * @get_static_power: Take voltage, in mV, and return the static power2828+ * in mW. If NULL, the static power is assumed2929+ * to be 0.3030+ * @get_dynamic_power: Take voltage, in mV, and frequency, in HZ, and3131+ * return the dynamic power draw in mW. If NULL,3232+ * a simple power model is used.3333+ * @dyn_power_coeff: Coefficient for the simple dynamic power model in3434+ * mW/(MHz mV mV).3535+ * If get_dynamic_power() is NULL, then the3636+ * dynamic power is calculated as3737+ * @dyn_power_coeff * frequency * voltage^23838+ */3939+struct devfreq_cooling_power {4040+ unsigned long (*get_static_power)(unsigned long voltage);4141+ unsigned long (*get_dynamic_power)(unsigned long freq,4242+ unsigned long voltage);4343+ unsigned long dyn_power_coeff;4444+};4545+4646+struct devfreq_cooling_device *4747+of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,4848+ struct devfreq_cooling_power *dfc_power);4949+struct devfreq_cooling_device *5050+of_devfreq_cooling_register(struct device_node *np, struct devfreq *df);5151+struct devfreq_cooling_device *devfreq_cooling_register(struct devfreq *df);5252+void devfreq_cooling_unregister(struct devfreq_cooling_device *dfc);5353+5454+#else /* !CONFIG_DEVFREQ_THERMAL */5555+5656+struct devfreq_cooling_device *5757+of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,5858+ struct devfreq_cooling_power *dfc_power)5959+{6060+ return ERR_PTR(-EINVAL);6161+}6262+6363+static inline struct devfreq_cooling_device *6464+of_devfreq_cooling_register(struct device_node *np, struct devfreq *df)6565+{6666+ return ERR_PTR(-EINVAL);6767+}6868+6969+static inline struct devfreq_cooling_device *7070+devfreq_cooling_register(struct devfreq *df)7171+{7272+ return ERR_PTR(-EINVAL);7373+}7474+7575+static inline void7676+devfreq_cooling_unregister(struct devfreq_cooling_device *dfc)7777+{7878+}7979+8080+#endif /* CONFIG_DEVFREQ_THERMAL */8181+#endif /* __DEVFREQ_COOLING_H__ */