Commit 19785cf9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal

Pull thermal SoC updates from Zhang Rui:
 "Thermal SoC management updates:

   - imx thermal driver now supports i.MX7 thermal sensor (Anson Huang)

   - exynos thermal driver dropped support for exynos 5440 (Krzysztof
     Kozlowski)

   - rcar_thermal now supports r8a77995 (Yoshihiro Kaneko)

   - rcar_gen3_thermal now supports r8a77965 (Niklas Söderlund)

   - qcom-spmi-temp-alarm now supports GEN2 PMIC peripherals (David
     Collins)

   - uniphier thermal now supports UniPhier PXs3 (Kunihiko Hayashi)

   - mediatek thermal now supports MT7622 SoC (Sean Wang)

   - considerable refactoring of exynos driver (Bartlomiej
     Zolnierkiewicz)

   - small fixes all over the place on different drivers"

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal: (50 commits)
  thermal: qcom: tsens: Allow number of sensors to come from DT
  thermal: tegra: soctherm: add const to struct thermal_cooling_device_ops
  thermal: exynos: Reduce severity of too early temperature read
  thermal: imx: Switch to SPDX identifier
  thermal: qcom-spmi-temp-alarm: add support for GEN2 PMIC peripherals
  thermal: ti-soc-thermal: fix incorrect entry in omap5430_adc_to_temp[]
  thermal: rcar_thermal: add r8a77995 support
  dt-bindings: thermal: rcar-thermal: add R8A77995 support
  thermal: mediatek: use of_device_get_match_data()
  thermal: exynos: remove trip reporting to user-space
  thermal: exynos: remove unused defines for Exynos5433
  thermal: exynos: cleanup code for enabling threshold interrupts
  thermal: exynos: check return values of ->get_trip_[temp, hyst] methods
  thermal: exynos: move trips setting to exynos_tmu_initialize()
  thermal: exynos: set trips in ascending order in exynos7_tmu_initialize()
  thermal: exynos: do not use trips structure directly in ->tmu_initialize
  thermal: exynos: add exynos*_tmu_set_[trip,hyst]() helpers
  thermal: exynos: move IRQs clearing to exynos_tmu_initialize()
  thermal: exynos: clear IRQs later in exynos4412_tmu_initialize()
  thermal: exynos: make ->tmu_initialize method void
  ...
parents 98db5e55 6d7c70d1
......@@ -12,7 +12,6 @@
"samsung,exynos5420-tmu-ext-triminfo" for TMU channels 2, 3 and 4
Exynos5420 (Must pass triminfo base and triminfo clock)
"samsung,exynos5433-tmu"
"samsung,exynos5440-tmu"
"samsung,exynos7-tmu"
- interrupt-parent : The phandle for the interrupt controller
- reg : Address range of the thermal registers. For soc's which has multiple
......@@ -68,18 +67,7 @@ Example 1):
#thermal-sensor-cells = <0>;
};
Example 2):
tmuctrl_0: tmuctrl@160118 {
compatible = "samsung,exynos5440-tmu";
reg = <0x160118 0x230>, <0x160368 0x10>;
interrupts = <0 58 0>;
clocks = <&clock 21>;
clock-names = "tmu_apbif";
#thermal-sensor-cells = <0>;
};
Example 3): (In case of Exynos5420 "with misplaced TRIMINFO register")
Example 2): (In case of Exynos5420 "with misplaced TRIMINFO register")
tmu_cpu2: tmu@10068000 {
compatible = "samsung,exynos5420-tmu-ext-triminfo";
reg = <0x10068000 0x100>, <0x1006c000 0x4>;
......
* Temperature Monitor (TEMPMON) on Freescale i.MX SoCs
Required properties:
- compatible : "fsl,imx6q-tempmon" for i.MX6Q, "fsl,imx6sx-tempmon" for i.MX6SX.
i.MX6SX has two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC,
- compatible : must be one of following:
- "fsl,imx6q-tempmon" for i.MX6Q,
- "fsl,imx6sx-tempmon" for i.MX6SX,
- "fsl,imx7d-tempmon" for i.MX7S/D.
- interrupts : the interrupt output of the controller:
i.MX6Q has one IRQ which will be triggered when temperature is higher than high threshold,
i.MX6SX and i.MX7S/D have two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC,
when temperature is below than low threshold, IRQ_LOW will be triggered, when temperature
is higher than panic threshold, system will auto reboot by SRC module.
- fsl,tempmon : phandle pointer to system controller that contains TEMPMON
......
......@@ -12,6 +12,7 @@ Required properties:
- "mediatek,mt8173-thermal" : For MT8173 family of SoCs
- "mediatek,mt2701-thermal" : For MT2701 family of SoCs
- "mediatek,mt2712-thermal" : For MT2712 family of SoCs
- "mediatek,mt7622-thermal" : For MT7622 SoC
- reg: Address range of the thermal controller
- interrupts: IRQ for the thermal controller
- clocks, clock-names: Clocks needed for the thermal controller. required
......
......@@ -8,6 +8,7 @@ Required properties:
- reg: Address range of the thermal registers
- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
- #qcom,sensors: Number of sensors in tsens block
- Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify
nvmem cells
......
......@@ -9,6 +9,7 @@ Required properties:
Examples with soctypes are:
- "renesas,r8a7795-thermal" (R-Car H3)
- "renesas,r8a7796-thermal" (R-Car M3-W)
- "renesas,r8a77965-thermal" (R-Car M3-N)
- reg : Address ranges of the thermal registers. Each sensor
needs one address range. Sorting must be done in
increasing order according to datasheet, i.e.
......@@ -18,7 +19,7 @@ Required properties:
Optional properties:
- interrupts : interrupts routed to the TSC (3 for H3 and M3-W)
- interrupts : interrupts routed to the TSC (3 for H3, M3-W and M3-N)
- power-domain : Must contain a reference to the power domain. This
property is mandatory if the thermal sensor instance
is part of a controllable power domain.
......
......@@ -3,7 +3,8 @@
Required properties:
- compatible : "renesas,thermal-<soctype>",
"renesas,rcar-gen2-thermal" (with thermal-zone) or
"renesas,rcar-thermal" (without thermal-zone) as fallback.
"renesas,rcar-thermal" (without thermal-zone) as
fallback except R-Car D3.
Examples with soctypes are:
- "renesas,thermal-r8a73a4" (R-Mobile APE6)
- "renesas,thermal-r8a7743" (RZ/G1M)
......@@ -12,13 +13,15 @@ Required properties:
- "renesas,thermal-r8a7791" (R-Car M2-W)
- "renesas,thermal-r8a7792" (R-Car V2H)
- "renesas,thermal-r8a7793" (R-Car M2-N)
- "renesas,thermal-r8a77995" (R-Car D3)
- reg : Address range of the thermal registers.
The 1st reg will be recognized as common register
if it has "interrupts".
Option properties:
- interrupts : use interrupt
- interrupts : If present should contain 3 interrupts for
R-Car D3 or 1 interrupt otherwise.
Example (non interrupt support):
......
......@@ -8,6 +8,7 @@ Required properties:
- compatible :
- "socionext,uniphier-pxs2-thermal" : For UniPhier PXs2 SoC
- "socionext,uniphier-ld20-thermal" : For UniPhier LD20 SoC
- "socionext,uniphier-pxs3-thermal" : For UniPhier PXs3 SoC
- interrupts : IRQ for the temperature alarm
- #thermal-sensor-cells : Should be 0. See ./thermal.txt for details.
......
This diff is collapsed.
......@@ -153,6 +153,12 @@
/* The number of sensing points per bank */
#define MT2712_NUM_SENSORS_PER_ZONE 4
#define MT7622_TEMP_AUXADC_CHANNEL 11
#define MT7622_NUM_SENSORS 1
#define MT7622_NUM_ZONES 1
#define MT7622_NUM_SENSORS_PER_ZONE 1
#define MT7622_TS1 0
struct mtk_thermal;
struct thermal_bank_cfg {
......@@ -242,6 +248,12 @@ static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = {
static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 };
/* MT7622 thermal sensor data */
static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, };
static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, };
static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, };
static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, };
/**
* The MT8173 thermal controller has four banks. Each bank can read up to
* four temperature sensors simultaneously. The MT8173 has a total of 5
......@@ -329,6 +341,25 @@ static const struct mtk_thermal_data mt2712_thermal_data = {
.sensor_mux_values = mt2712_mux_values,
};
/*
* MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data
* access.
*/
static const struct mtk_thermal_data mt7622_thermal_data = {
.auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL,
.num_banks = MT7622_NUM_ZONES,
.num_sensors = MT7622_NUM_SENSORS,
.bank_data = {
{
.num_sensors = 1,
.sensors = mt7622_bank_data,
},
},
.msr = mt7622_msr,
.adcpnp = mt7622_adcpnp,
.sensor_mux_values = mt7622_mux_values,
};
/**
* raw_to_mcelsius - convert a raw ADC value to mcelsius
* @mt: The thermal controller
......@@ -631,6 +662,10 @@ static const struct of_device_id mtk_thermal_of_match[] = {
{
.compatible = "mediatek,mt2712-thermal",
.data = (void *)&mt2712_thermal_data,
},
{
.compatible = "mediatek,mt7622-thermal",
.data = (void *)&mt7622_thermal_data,
}, {
},
};
......@@ -642,7 +677,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
struct mtk_thermal *mt;
struct resource *res;
const struct of_device_id *of_id;
u64 auxadc_phys_base, apmixed_phys_base;
struct thermal_zone_device *tzdev;
......@@ -650,9 +684,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
if (!mt)
return -ENOMEM;
of_id = of_match_device(mtk_thermal_of_match, &pdev->dev);
if (of_id)
mt->conf = (const struct mtk_thermal_data *)of_id->data;
mt->conf = of_device_get_match_data(&pdev->dev);
mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
if (IS_ERR(mt->clk_peri_therm))
......
/*
* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
* Copyright (c) 2011-2015, 2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
......@@ -11,6 +11,7 @@
* GNU General Public License for more details.
*/
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/iio/consumer.h>
......@@ -29,13 +30,17 @@
#define QPNP_TM_REG_ALARM_CTRL 0x46
#define QPNP_TM_TYPE 0x09
#define QPNP_TM_SUBTYPE 0x08
#define QPNP_TM_SUBTYPE_GEN1 0x08
#define QPNP_TM_SUBTYPE_GEN2 0x09
#define STATUS_STAGE_MASK 0x03
#define STATUS_GEN1_STAGE_MASK GENMASK(1, 0)
#define STATUS_GEN2_STATE_MASK GENMASK(6, 4)
#define STATUS_GEN2_STATE_SHIFT 4
#define SHUTDOWN_CTRL1_THRESHOLD_MASK 0x03
#define SHUTDOWN_CTRL1_OVERRIDE_MASK GENMASK(7, 6)
#define SHUTDOWN_CTRL1_THRESHOLD_MASK GENMASK(1, 0)
#define ALARM_CTRL_FORCE_ENABLE 0x80
#define ALARM_CTRL_FORCE_ENABLE BIT(7)
/*
* Trip point values based on threshold control
......@@ -58,6 +63,7 @@
struct qpnp_tm_chip {
struct regmap *map;
struct thermal_zone_device *tz_dev;
unsigned int subtype;
long temp;
unsigned int thresh;
unsigned int stage;
......@@ -66,6 +72,9 @@ struct qpnp_tm_chip {
struct iio_channel *adc;
};
/* This array maps from GEN2 alarm state to GEN1 alarm stage */
static const unsigned int alarm_state_map[8] = {0, 1, 1, 2, 2, 3, 3, 3};
static int qpnp_tm_read(struct qpnp_tm_chip *chip, u16 addr, u8 *data)
{
unsigned int val;
......@@ -84,30 +93,59 @@ static int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 data)
return regmap_write(chip->map, chip->base + addr, data);
}
/**
* qpnp_tm_get_temp_stage() - return over-temperature stage
* @chip: Pointer to the qpnp_tm chip
*
* Return: stage (GEN1) or state (GEN2) on success, or errno on failure.
*/
static int qpnp_tm_get_temp_stage(struct qpnp_tm_chip *chip)
{
int ret;
u8 reg = 0;
ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg);
if (ret < 0)
return ret;
if (chip->subtype == QPNP_TM_SUBTYPE_GEN1)
ret = reg & STATUS_GEN1_STAGE_MASK;
else
ret = (reg & STATUS_GEN2_STATE_MASK) >> STATUS_GEN2_STATE_SHIFT;
return ret;
}
/*
* This function updates the internal temp value based on the
* current thermal stage and threshold as well as the previous stage
*/
static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
{
unsigned int stage;
unsigned int stage, stage_new, stage_old;
int ret;
u8 reg = 0;
ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg);
ret = qpnp_tm_get_temp_stage(chip);
if (ret < 0)
return ret;
stage = ret;
stage = reg & STATUS_STAGE_MASK;
if (chip->subtype == QPNP_TM_SUBTYPE_GEN1) {
stage_new = stage;
stage_old = chip->stage;
} else {
stage_new = alarm_state_map[stage];
stage_old = alarm_state_map[chip->stage];
}
if (stage > chip->stage) {
if (stage_new > stage_old) {
/* increasing stage, use lower bound */
chip->temp = (stage - 1) * TEMP_STAGE_STEP +
chip->temp = (stage_new - 1) * TEMP_STAGE_STEP +
chip->thresh * TEMP_THRESH_STEP +
TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
} else if (stage < chip->stage) {
} else if (stage_new < stage_old) {
/* decreasing stage, use upper bound */
chip->temp = stage * TEMP_STAGE_STEP +
chip->temp = stage_new * TEMP_STAGE_STEP +
chip->thresh * TEMP_THRESH_STEP -
TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
}
......@@ -162,28 +200,37 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
*/
static int qpnp_tm_init(struct qpnp_tm_chip *chip)
{
unsigned int stage;
int ret;
u8 reg;
u8 reg = 0;
chip->thresh = THRESH_MIN;
ret = qpnp_tm_read(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, &reg);
if (ret < 0)
return ret;
chip->thresh = reg & SHUTDOWN_CTRL1_THRESHOLD_MASK;
chip->temp = DEFAULT_TEMP;
ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg);
ret = qpnp_tm_get_temp_stage(chip);
if (ret < 0)
return ret;
chip->stage = ret;
chip->stage = reg & STATUS_STAGE_MASK;
stage = chip->subtype == QPNP_TM_SUBTYPE_GEN1
? chip->stage : alarm_state_map[chip->stage];
if (chip->stage)
if (stage)
chip->temp = chip->thresh * TEMP_THRESH_STEP +
(chip->stage - 1) * TEMP_STAGE_STEP +
(stage - 1) * TEMP_STAGE_STEP +
TEMP_THRESH_MIN;
/*
* Set threshold and disable software override of stage 2 and 3
* shutdowns.
*/
reg = chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK;
chip->thresh = THRESH_MIN;
reg &= ~(SHUTDOWN_CTRL1_OVERRIDE_MASK | SHUTDOWN_CTRL1_THRESHOLD_MASK);
reg |= chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK;
ret = qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg);
if (ret < 0)
return ret;
......@@ -246,12 +293,15 @@ static int qpnp_tm_probe(struct platform_device *pdev)
return ret;
}
if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) {
if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1
&& subtype != QPNP_TM_SUBTYPE_GEN2)) {
dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n",
type, subtype);
return -ENODEV;
}
chip->subtype = subtype;
ret = qpnp_tm_init(chip);
if (ret < 0) {
dev_err(&pdev->dev, "init failed\n");
......
......@@ -115,6 +115,7 @@ static int tsens_probe(struct platform_device *pdev)
struct tsens_device *tmdev;
const struct tsens_data *data;
const struct of_device_id *id;
u32 num_sensors;
if (pdev->dev.of_node)
dev = &pdev->dev;
......@@ -129,19 +130,24 @@ static int tsens_probe(struct platform_device *pdev)
else
data = &data_8960;
if (data->num_sensors <= 0) {
num_sensors = data->num_sensors;
if (np)
of_property_read_u32(np, "#qcom,sensors", &num_sensors);
if (num_sensors <= 0) {
dev_err(dev, "invalid number of sensors\n");
return -EINVAL;
}
tmdev = devm_kzalloc(dev,
struct_size(tmdev, sensor, data->num_sensors),
struct_size(tmdev, sensor, num_sensors),
GFP_KERNEL);
if (!tmdev)
return -ENOMEM;
tmdev->dev = dev;
tmdev->num_sensors = data->num_sensors;
tmdev->num_sensors = num_sensors;
tmdev->ops = data->ops;
for (i = 0; i < tmdev->num_sensors; i++) {
if (data->hw_ids)
......
......@@ -132,7 +132,7 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
#define RCAR3_THERMAL_GRAN 500 /* mili Celsius */
/* no idea where these constants come from */
#define TJ_1 96
#define TJ_1 116
#define TJ_3 -41
static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef,
......@@ -146,7 +146,7 @@ static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef,
* Division is not scaled in BSP and if scaled it might overflow
* the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled
*/
tj_2 = (FIXPT_INT((ptat[1] - ptat[2]) * 137)
tj_2 = (FIXPT_INT((ptat[1] - ptat[2]) * 157)
/ (ptat[0] - ptat[2])) - FIXPT_INT(41);
coef->a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]),
......@@ -207,8 +207,8 @@ static int rcar_gen3_thermal_set_trips(void *devdata, int low, int high)
{
struct rcar_gen3_thermal_tsc *tsc = devdata;
low = clamp_val(low, -40000, 125000);
high = clamp_val(high, -40000, 125000);
low = clamp_val(low, -40000, 120000);
high = clamp_val(high, -40000, 120000);
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1,
rcar_gen3_thermal_mcelsius_to_temp(tsc, low));
......@@ -329,6 +329,7 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
{ .compatible = "renesas,r8a7795-thermal", },
{ .compatible = "renesas,r8a7796-thermal", },
{ .compatible = "renesas,r8a77965-thermal", },
{},
};
MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids);
......@@ -354,11 +355,11 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
/* default values if FUSEs are missing */
/* TODO: Read values from hardware on supported platforms */
int ptat[3] = { 2351, 1509, 435 };
int ptat[3] = { 2631, 1509, 435 };
int thcode[TSC_MAX_NUM][3] = {
{ 3248, 2800, 2221 },
{ 3245, 2795, 2216 },
{ 3250, 2805, 2237 },
{ 3397, 2800, 2221 },
{ 3393, 2795, 2216 },
{ 3389, 2805, 2237 },
};
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
......
......@@ -58,10 +58,47 @@ struct rcar_thermal_common {
spinlock_t lock;
};
struct rcar_thermal_chip {
unsigned int use_of_thermal : 1;
unsigned int has_filonoff : 1;
unsigned int irq_per_ch : 1;
unsigned int needs_suspend_resume : 1;
unsigned int nirqs;
};
static const struct rcar_thermal_chip rcar_thermal = {
.use_of_thermal = 0,
.has_filonoff = 1,
.irq_per_ch = 0,
.needs_suspend_resume = 0,
.nirqs = 1,
};
static const struct rcar_thermal_chip rcar_gen2_thermal = {
.use_of_thermal = 1,
.has_filonoff = 1,
.irq_per_ch = 0,
.needs_suspend_resume = 0,
.nirqs = 1,
};
static const struct rcar_thermal_chip rcar_gen3_thermal = {
.use_of_thermal = 1,
.has_filonoff = 0,
.irq_per_ch = 1,
.needs_suspend_resume = 1,
/*
* The Gen3 chip has 3 interrupts, but this driver uses only 2
* interrupts to detect a temperature change, rise or fall.
*/
.nirqs = 2,
};
struct rcar_thermal_priv {
void __iomem *base;
struct rcar_thermal_common *common;
struct thermal_zone_device *zone;
const struct rcar_thermal_chip *chip;
struct delayed_work work;
struct mutex lock;
struct list_head list;
......@@ -77,13 +114,20 @@ struct rcar_thermal_priv {
#define rcar_priv_to_dev(priv) ((priv)->common->dev)
#define rcar_has_irq_support(priv) ((priv)->common->base)
#define rcar_id_to_shift(priv) ((priv)->id * 8)
#define rcar_of_data(dev) ((unsigned long)of_device_get_match_data(dev))
#define rcar_use_of_thermal(dev) (rcar_of_data(dev) == USE_OF_THERMAL)
#define USE_OF_THERMAL 1
static const struct of_device_id rcar_thermal_dt_ids[] = {
{ .compatible = "renesas,rcar-thermal", },
{ .compatible = "renesas,rcar-gen2-thermal", .data = (void *)USE_OF_THERMAL },
{
.compatible = "renesas,rcar-thermal",
.data = &rcar_thermal,
},
{
.compatible = "renesas,rcar-gen2-thermal",
.data = &rcar_gen2_thermal,
},
{
.compatible = "renesas,thermal-r8a77995",
.data = &rcar_gen3_thermal,
},
{},
};
MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
......@@ -190,7 +234,8 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)
* enable IRQ
*/
if (rcar_has_irq_support(priv)) {
rcar_thermal_write(priv, FILONOFF, 0);
if (priv->chip->has_filonoff)
rcar_thermal_write(priv, FILONOFF, 0);
/* enable Rising/Falling edge interrupt */
rcar_thermal_write(priv, POSNEG, 0x1);
......@@ -420,7 +465,7 @@ static int rcar_thermal_remove(struct platform_device *pdev)
rcar_thermal_for_each_priv(priv, common) {
rcar_thermal_irq_disable(priv);
if (rcar_use_of_thermal(dev))
if (priv->chip->use_of_thermal)
thermal_remove_hwmon_sysfs(priv->zone);
else
thermal_zone_device_unregister(priv->zone);
......@@ -438,6 +483,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
struct rcar_thermal_priv *priv;
struct device *dev = &pdev->dev;
struct resource *res, *irq;
const struct rcar_thermal_chip *chip = of_device_get_match_data(dev);
int mres = 0;
int i;
int ret = -ENODEV;
......@@ -457,19 +503,35 @@ static int rcar_thermal_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq) {
/*
* platform has IRQ support.
* Then, driver uses common registers
* rcar_has_irq_support() will be enabled
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
common->base = devm_ioremap_resource(dev, res);
if (IS_ERR(common->base))
return PTR_ERR(common->base);
for (i = 0; i < chip->nirqs; i++) {
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq)
continue;
if (!common->base) {
/*
* platform has IRQ support.
* Then, driver uses common registers
* rcar_has_irq_support() will be enabled
*/
res = platform_get_resource(pdev, IORESOURCE_MEM,
mres++);
common->base = devm_ioremap_resource(dev, res);
if (IS_ERR(common->base))
return PTR_ERR(common->base);
idle = 0; /* polling delay is not needed */
}
idle = 0; /* polling delay is not needed */
ret = devm_request_irq(dev, irq->start, rcar_thermal_irq,
IRQF_SHARED, dev_name(dev), common);
if (ret) {
dev_err(dev, "irq request failed\n ");
goto error_unregister;
}
/* update ENR bits */
if (chip->irq_per_ch)
enr_bits |= 1 << i;
}
for (i = 0;; i++) {
......@@ -491,6 +553,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
priv->common = common;
priv->id = i;
priv->chip = chip;
mutex_init(&priv->lock);
INIT_LIST_HEAD(&priv->list);
INIT_DELAYED_WORK(&priv->work, rcar_thermal_work);
......@@ -498,7 +561,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
if (ret < 0)
goto error_unregister;
if (rcar_use_of_thermal(dev))
if (chip->use_of_thermal)
priv->zone = devm_thermal_zone_of_sensor_register(
dev, i, priv,
&rcar_thermal_zone_of_ops);
......@@ -515,7 +578,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
goto error_unregister;
}
if (rcar_use_of_thermal(dev)) {
if (chip->use_of_thermal) {
/*
* thermal_zone doesn't enable hwmon as default,
* but, enable it here to keep compatible
......@@ -531,20 +594,12 @@ static int rcar_thermal_probe(struct platform_device *pdev)
list_move_tail(&priv->list, &common->head);
/* update ENR bits */
enr_bits |= 3 << (i * 8);
if (!chip->irq_per_ch)
enr_bits |= 3 << (i * 8);
}
/* enable temperature comparation */
if (irq) {
ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0,
dev_name(dev), common);
if (ret) {
dev_err(dev, "irq request failed\n ");
goto error_unregister;
}
if (enr_bits)
rcar_thermal_common_write(common, ENR, enr_bits);
}
dev_info(dev, "%d sensor probed\n", i);
......@@ -556,9 +611,48 @@ static int rcar_thermal_probe(struct platform_device *pdev)
return ret;
}
#ifdef CONFIG_PM_SLEEP
static int rcar_thermal_suspend(struct device *dev)
{
struct rcar_thermal_common *common = dev_get_drvdata(dev);
struct rcar_thermal_priv *priv = list_first_entry(&common->head,
typeof(*priv), list);
if (priv->chip->needs_suspend_resume) {
rcar_thermal_common_write(common, ENR, 0);
rcar_thermal_irq_disable(priv);
rcar_thermal_bset(priv, THSCR, CPCTL, 0);
}
return 0;
}
static int rcar_thermal_resume(struct device *dev)
{
struct rcar_thermal_common *common = dev_get_drvdata(dev);
struct rcar_thermal_priv *priv = list_first_entry(&common->head,
typeof(*priv), list);
int ret;
if (priv->chip->needs_suspend_resume) {
ret = rcar_thermal_update_temp(priv);
if (ret < 0)
return ret;
rcar_thermal_irq_enable(priv);
rcar_thermal_common_write(common, ENR, 0x03);
}
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend,
rcar_thermal_resume);
static struct platform_driver rcar_thermal_driver = {
.driver = {
.name = "rcar_thermal",
.pm = &rcar_thermal_pm_ops,
.of_match_table = rcar_thermal_dt_ids,
},
.probe = rcar_thermal_probe,
......
This diff is collapsed.
/*
* exynos_tmu.h - Samsung EXYNOS TMU (Thermal Management Unit)
*
* Copyright (C) 2011 Samsung Electronics
* Donggeun Kim <dg77.kim@samsung.com>
* Amit Daniel Kachhap <amit.daniel@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _EXYNOS_TMU_H
#define _EXYNOS_TMU_H
#include <linux/cpu_cooling.h>
#include <dt-bindings/thermal/thermal_exynos.h>
enum soc_type {
SOC_ARCH_EXYNOS3250 = 1,
SOC_ARCH_EXYNOS4210,
SOC_ARCH_EXYNOS4412,
SOC_ARCH_EXYNOS5250,
SOC_ARCH_EXYNOS5260,
SOC_ARCH_EXYNOS5420,
SOC_ARCH_EXYNOS5420_TRIMINFO,
SOC_ARCH_EXYNOS5433,
SOC_ARCH_EXYNOS5440,
SOC_ARCH_EXYNOS7,
};
/**
* struct exynos_tmu_platform_data
* @gain: gain of amplifier in the positive-TC generator block
* 0 < gain <= 15
* @reference_voltage: reference voltage of amplifier
* in the positive-TC generator block
* 0 < reference_voltage <= 31
* @noise_cancel_mode: noise cancellation mode
* 000, 100, 101, 110 and 111 can be different modes
* @type: determines the type of SOC
* @efuse_value: platform defined fuse value
* @min_efuse_value: minimum valid trimming data
* @max_efuse_value: maximum valid trimming data
* @default_temp_offset: default temperature offset in case of no trimming
* @cal_type: calibration type for temperature
*
* This structure is required for configuration of exynos_tmu driver.
*/
struct exynos_tmu_platform_data {
u8 gain;
u8 reference_voltage;
u8 noise_cancel_mode;
u32 efuse_value;
u32 min_efuse_value;
u32 max_efuse_value;
u8 first_point_trim;
u8 second_point_trim;
u8 default_temp_offset;
enum soc_type type;
u32 cal_type;
};
#endif /* _EXYNOS_TMU_H */
......@@ -240,31 +240,6 @@ struct tegra_soctherm {
struct dentry *debugfs_dir;
};
/**
* clk_writel() - writes a value to a CAR register
* @ts: pointer to a struct tegra_soctherm
* @v: the value to write
* @reg: the register offset
*
* Writes @v to @reg. No return value.
*/
static inline void clk_writel(struct tegra_soctherm *ts, u32 value, u32 reg)
{
writel(value, (ts->clk_regs + reg));
}
/**
* clk_readl() - reads specified register from CAR IP block
* @ts: pointer to a struct tegra_soctherm
* @reg: register address to be read
*
* Return: the value of the register
*/
static inline u32 clk_readl(struct tegra_soctherm *ts, u32 reg)
{
return readl(ts->clk_regs + reg);
}
/**
* ccroc_writel() - writes a value to a CCROC register
* @ts: pointer to a struct tegra_soctherm
......@@ -926,7 +901,7 @@ static int throt_set_cdev_state(struct thermal_cooling_device *cdev,
return 0;
}
static struct thermal_cooling_device_ops throt_cooling_ops = {
static const struct thermal_cooling_device_ops throt_cooling_ops = {
.get_max_state = throt_get_cdev_max_state,
.get_cur_state = throt_get_cdev_cur_state,
.set_cur_state = throt_set_cdev_state,
......@@ -1207,9 +1182,9 @@ static void tegra_soctherm_throttle(struct device *dev)
} else {
writel(v, ts->regs + THROT_GLOBAL_CFG);
v = clk_readl(ts, CAR_SUPER_CCLKG_DIVIDER);
v = readl(ts->clk_regs + CAR_SUPER_CCLKG_DIVIDER);
v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);
clk_writel(ts, v, CAR_SUPER_CCLKG_DIVIDER);
writel(v, ts->clk_regs + CAR_SUPER_CCLKG_DIVIDER);
}
/* initialize stats collection */
......
......@@ -310,7 +310,7 @@ omap5430_adc_to_temp[
119800, 120200, 120600, 121000, 121400, 121800, 122400, 122600, 123000,
123400,
/* Index 940 - 945 */
123800, 1242000, 124600, 124900, 125000, 125000,
123800, 124200, 124600, 124900, 125000, 125000,
};
/* OMAP54xx ES2.0 data */
......
......@@ -365,6 +365,10 @@ static const struct of_device_id uniphier_tm_dt_ids[] = {
.compatible = "socionext,uniphier-ld20-thermal",
.data = &uniphier_ld20_tm_data,
},
{
.compatible = "socionext,uniphier-pxs3-thermal",
.data = &uniphier_ld20_tm_data,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, uniphier_tm_dt_ids);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment