From 0f8487f29ddede98067b7c0a6fbc6228cbc076fe Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Sat, 17 Feb 2018 16:49:01 +0800 Subject: [PATCH 01/50] dt-bindings: thermal: add binding for MT7622 SoC Add devicetree bindings for MediaTek MT7622 thermal controller Changes v1 -> v2: add tag from Rob Signed-off-by: Sean Wang Signed-off-by: Shunli Wang Reviewed-by: Rob Herring Signed-off-by: Eduardo Valentin --- Documentation/devicetree/bindings/thermal/mediatek-thermal.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt index 0d73ea5e9c0c..41d6a443ad66 100644 --- a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt @@ -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 From 3966be3c08c3be6d32deb6ae81d67ee08b86b50b Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Sat, 17 Feb 2018 16:49:02 +0800 Subject: [PATCH 02/50] thermal: mediatek: add support for MT7622 SoC MT7622 SoC has built-in thermal controller with one sensing point, the patch just is to extend the functionality of the existing logic. Changes v1 -> v2: rebase to 4.16-rc1 Signed-off-by: Sean Wang Signed-off-by: Shunli Wang Signed-off-by: Eduardo Valentin --- drivers/thermal/mtk_thermal.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index c75661a3801a..e709acb2235e 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -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, }, { }, }; From f085f672b7d4033ea40db8c4b6929324833ce7b2 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 2 Mar 2018 09:59:30 +0800 Subject: [PATCH 03/50] thermal: imx: add i.MX7 thermal sensor support This patch adds i.MX7 thermal sensor support, most of the i.MX7 thermal sensor functions are same with i.MX6 except the registers offset/layout, so we move those registers offset/layout definitions to soc data structure. i.MX7 uses single calibration data @25C, the calibration data is located at OCOTP offset 0x4F0, bit[17:9], the formula is as below: Tmeas = (Nmeas - n1) + 25; n1 is the fuse value for 25C. Signed-off-by: Anson Huang Signed-off-by: Bai Ping Acked-by: Dong Aisheng Acked-by: Shawn Guo Reviewed-by: Rob Herring Signed-off-by: Eduardo Valentin --- .../bindings/thermal/imx-thermal.txt | 9 +- drivers/thermal/imx_thermal.c | 291 ++++++++++++++---- 2 files changed, 237 insertions(+), 63 deletions(-) diff --git a/Documentation/devicetree/bindings/thermal/imx-thermal.txt b/Documentation/devicetree/bindings/thermal/imx-thermal.txt index 379eb763073e..823e4176eef8 100644 --- a/Documentation/devicetree/bindings/thermal/imx-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/imx-thermal.txt @@ -1,8 +1,13 @@ * 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 diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index ee3a215b333a..c30dc21c3b5d 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -31,35 +31,57 @@ #define REG_CLR 0x8 #define REG_TOG 0xc -#define MISC0 0x0150 -#define MISC0_REFTOP_SELBIASOFF (1 << 3) -#define MISC1 0x0160 -#define MISC1_IRQ_TEMPHIGH (1 << 29) +/* i.MX6 specific */ +#define IMX6_MISC0 0x0150 +#define IMX6_MISC0_REFTOP_SELBIASOFF (1 << 3) +#define IMX6_MISC1 0x0160 +#define IMX6_MISC1_IRQ_TEMPHIGH (1 << 29) /* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */ -#define MISC1_IRQ_TEMPLOW (1 << 28) -#define MISC1_IRQ_TEMPPANIC (1 << 27) +#define IMX6_MISC1_IRQ_TEMPLOW (1 << 28) +#define IMX6_MISC1_IRQ_TEMPPANIC (1 << 27) -#define TEMPSENSE0 0x0180 -#define TEMPSENSE0_ALARM_VALUE_SHIFT 20 -#define TEMPSENSE0_ALARM_VALUE_MASK (0xfff << TEMPSENSE0_ALARM_VALUE_SHIFT) -#define TEMPSENSE0_TEMP_CNT_SHIFT 8 -#define TEMPSENSE0_TEMP_CNT_MASK (0xfff << TEMPSENSE0_TEMP_CNT_SHIFT) -#define TEMPSENSE0_FINISHED (1 << 2) -#define TEMPSENSE0_MEASURE_TEMP (1 << 1) -#define TEMPSENSE0_POWER_DOWN (1 << 0) +#define IMX6_TEMPSENSE0 0x0180 +#define IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT 20 +#define IMX6_TEMPSENSE0_ALARM_VALUE_MASK (0xfff << 20) +#define IMX6_TEMPSENSE0_TEMP_CNT_SHIFT 8 +#define IMX6_TEMPSENSE0_TEMP_CNT_MASK (0xfff << 8) +#define IMX6_TEMPSENSE0_FINISHED (1 << 2) +#define IMX6_TEMPSENSE0_MEASURE_TEMP (1 << 1) +#define IMX6_TEMPSENSE0_POWER_DOWN (1 << 0) -#define TEMPSENSE1 0x0190 -#define TEMPSENSE1_MEASURE_FREQ 0xffff -/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */ -#define TEMPSENSE2 0x0290 -#define TEMPSENSE2_LOW_VALUE_SHIFT 0 -#define TEMPSENSE2_LOW_VALUE_MASK 0xfff -#define TEMPSENSE2_PANIC_VALUE_SHIFT 16 -#define TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000 +#define IMX6_TEMPSENSE1 0x0190 +#define IMX6_TEMPSENSE1_MEASURE_FREQ 0xffff +#define IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT 0 #define OCOTP_MEM0 0x0480 #define OCOTP_ANA1 0x04e0 +/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */ +#define IMX6_TEMPSENSE2 0x0290 +#define IMX6_TEMPSENSE2_LOW_VALUE_SHIFT 0 +#define IMX6_TEMPSENSE2_LOW_VALUE_MASK 0xfff +#define IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT 16 +#define IMX6_TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000 + +/* i.MX7 specific */ +#define IMX7_ANADIG_DIGPROG 0x800 +#define IMX7_TEMPSENSE0 0x300 +#define IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT 18 +#define IMX7_TEMPSENSE0_PANIC_ALARM_MASK (0x1ff << 18) +#define IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT 9 +#define IMX7_TEMPSENSE0_HIGH_ALARM_MASK (0x1ff << 9) +#define IMX7_TEMPSENSE0_LOW_ALARM_SHIFT 0 +#define IMX7_TEMPSENSE0_LOW_ALARM_MASK 0x1ff + +#define IMX7_TEMPSENSE1 0x310 +#define IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT 16 +#define IMX7_TEMPSENSE1_MEASURE_FREQ_MASK (0xffff << 16) +#define IMX7_TEMPSENSE1_FINISHED (1 << 11) +#define IMX7_TEMPSENSE1_MEASURE_TEMP (1 << 10) +#define IMX7_TEMPSENSE1_POWER_DOWN (1 << 9) +#define IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT 0 +#define IMX7_TEMPSENSE1_TEMP_VALUE_MASK 0x1ff + /* The driver supports 1 passive trip point and 1 critical trip point */ enum imx_thermal_trip { IMX_TRIP_PASSIVE, @@ -72,17 +94,114 @@ enum imx_thermal_trip { #define TEMPMON_IMX6Q 1 #define TEMPMON_IMX6SX 2 +#define TEMPMON_IMX7D 3 struct thermal_soc_data { u32 version; + + u32 sensor_ctrl; + u32 power_down_mask; + u32 measure_temp_mask; + + u32 measure_freq_ctrl; + u32 measure_freq_mask; + u32 measure_freq_shift; + + u32 temp_data; + u32 temp_value_mask; + u32 temp_value_shift; + u32 temp_valid_mask; + + u32 panic_alarm_ctrl; + u32 panic_alarm_mask; + u32 panic_alarm_shift; + + u32 high_alarm_ctrl; + u32 high_alarm_mask; + u32 high_alarm_shift; + + u32 low_alarm_ctrl; + u32 low_alarm_mask; + u32 low_alarm_shift; }; static struct thermal_soc_data thermal_imx6q_data = { .version = TEMPMON_IMX6Q, + + .sensor_ctrl = IMX6_TEMPSENSE0, + .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN, + .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP, + + .measure_freq_ctrl = IMX6_TEMPSENSE1, + .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT, + .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ, + + .temp_data = IMX6_TEMPSENSE0, + .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK, + .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT, + .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED, + + .high_alarm_ctrl = IMX6_TEMPSENSE0, + .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK, + .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT, }; static struct thermal_soc_data thermal_imx6sx_data = { .version = TEMPMON_IMX6SX, + + .sensor_ctrl = IMX6_TEMPSENSE0, + .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN, + .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP, + + .measure_freq_ctrl = IMX6_TEMPSENSE1, + .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT, + .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ, + + .temp_data = IMX6_TEMPSENSE0, + .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK, + .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT, + .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED, + + .high_alarm_ctrl = IMX6_TEMPSENSE0, + .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK, + .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT, + + .panic_alarm_ctrl = IMX6_TEMPSENSE2, + .panic_alarm_mask = IMX6_TEMPSENSE2_PANIC_VALUE_MASK, + .panic_alarm_shift = IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT, + + .low_alarm_ctrl = IMX6_TEMPSENSE2, + .low_alarm_mask = IMX6_TEMPSENSE2_LOW_VALUE_MASK, + .low_alarm_shift = IMX6_TEMPSENSE2_LOW_VALUE_SHIFT, +}; + +static struct thermal_soc_data thermal_imx7d_data = { + .version = TEMPMON_IMX7D, + + .sensor_ctrl = IMX7_TEMPSENSE1, + .power_down_mask = IMX7_TEMPSENSE1_POWER_DOWN, + .measure_temp_mask = IMX7_TEMPSENSE1_MEASURE_TEMP, + + .measure_freq_ctrl = IMX7_TEMPSENSE1, + .measure_freq_shift = IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT, + .measure_freq_mask = IMX7_TEMPSENSE1_MEASURE_FREQ_MASK, + + .temp_data = IMX7_TEMPSENSE1, + .temp_value_mask = IMX7_TEMPSENSE1_TEMP_VALUE_MASK, + .temp_value_shift = IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT, + .temp_valid_mask = IMX7_TEMPSENSE1_FINISHED, + + .panic_alarm_ctrl = IMX7_TEMPSENSE1, + .panic_alarm_mask = IMX7_TEMPSENSE0_PANIC_ALARM_MASK, + .panic_alarm_shift = IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT, + + .high_alarm_ctrl = IMX7_TEMPSENSE0, + .high_alarm_mask = IMX7_TEMPSENSE0_HIGH_ALARM_MASK, + .high_alarm_shift = IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT, + + .low_alarm_ctrl = IMX7_TEMPSENSE0, + .low_alarm_mask = IMX7_TEMPSENSE0_LOW_ALARM_MASK, + .low_alarm_shift = IMX7_TEMPSENSE0_LOW_ALARM_SHIFT, }; struct imx_thermal_data { @@ -107,31 +226,42 @@ struct imx_thermal_data { static void imx_set_panic_temp(struct imx_thermal_data *data, int panic_temp) { + const struct thermal_soc_data *soc_data = data->socdata; struct regmap *map = data->tempmon; int critical_value; critical_value = (data->c2 - panic_temp) / data->c1; - regmap_write(map, TEMPSENSE2 + REG_CLR, TEMPSENSE2_PANIC_VALUE_MASK); - regmap_write(map, TEMPSENSE2 + REG_SET, critical_value << - TEMPSENSE2_PANIC_VALUE_SHIFT); + + regmap_write(map, soc_data->panic_alarm_ctrl + REG_CLR, + soc_data->panic_alarm_mask); + regmap_write(map, soc_data->panic_alarm_ctrl + REG_SET, + critical_value << soc_data->panic_alarm_shift); } static void imx_set_alarm_temp(struct imx_thermal_data *data, int alarm_temp) { struct regmap *map = data->tempmon; + const struct thermal_soc_data *soc_data = data->socdata; int alarm_value; data->alarm_temp = alarm_temp; - alarm_value = (data->c2 - alarm_temp) / data->c1; - regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK); - regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value << - TEMPSENSE0_ALARM_VALUE_SHIFT); + + if (data->socdata->version == TEMPMON_IMX7D) + alarm_value = alarm_temp / 1000 + data->c1 - 25; + else + alarm_value = (data->c2 - alarm_temp) / data->c1; + + regmap_write(map, soc_data->high_alarm_ctrl + REG_CLR, + soc_data->high_alarm_mask); + regmap_write(map, soc_data->high_alarm_ctrl + REG_SET, + alarm_value << soc_data->high_alarm_shift); } static int imx_get_temp(struct thermal_zone_device *tz, int *temp) { struct imx_thermal_data *data = tz->devdata; + const struct thermal_soc_data *soc_data = data->socdata; struct regmap *map = data->tempmon; unsigned int n_meas; bool wait; @@ -139,16 +269,18 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) if (data->mode == THERMAL_DEVICE_ENABLED) { /* Check if a measurement is currently in progress */ - regmap_read(map, TEMPSENSE0, &val); - wait = !(val & TEMPSENSE0_FINISHED); + regmap_read(map, soc_data->temp_data, &val); + wait = !(val & soc_data->temp_valid_mask); } else { /* * Every time we measure the temperature, we will power on the * temperature sensor, enable measurements, take a reading, * disable measurements, power off the temperature sensor. */ - regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); - regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); + regmap_write(map, soc_data->sensor_ctrl + REG_CLR, + soc_data->power_down_mask); + regmap_write(map, soc_data->sensor_ctrl + REG_SET, + soc_data->measure_temp_mask); wait = true; } @@ -160,22 +292,28 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) if (wait) usleep_range(20, 50); - regmap_read(map, TEMPSENSE0, &val); + regmap_read(map, soc_data->temp_data, &val); if (data->mode != THERMAL_DEVICE_ENABLED) { - regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP); - regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); + regmap_write(map, soc_data->sensor_ctrl + REG_CLR, + soc_data->measure_temp_mask); + regmap_write(map, soc_data->sensor_ctrl + REG_SET, + soc_data->power_down_mask); } - if ((val & TEMPSENSE0_FINISHED) == 0) { + if ((val & soc_data->temp_valid_mask) == 0) { dev_dbg(&tz->device, "temp measurement never finished\n"); return -EAGAIN; } - n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT; + n_meas = (val & soc_data->temp_value_mask) + >> soc_data->temp_value_shift; /* See imx_init_calib() for formula derivation */ - *temp = data->c2 - n_meas * data->c1; + if (data->socdata->version == TEMPMON_IMX7D) + *temp = (n_meas - data->c1 + 25) * 1000; + else + *temp = data->c2 - n_meas * data->c1; /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */ if (data->socdata->version == TEMPMON_IMX6Q) { @@ -219,21 +357,26 @@ static int imx_set_mode(struct thermal_zone_device *tz, { struct imx_thermal_data *data = tz->devdata; struct regmap *map = data->tempmon; + const struct thermal_soc_data *soc_data = data->socdata; if (mode == THERMAL_DEVICE_ENABLED) { tz->polling_delay = IMX_POLLING_DELAY; tz->passive_delay = IMX_PASSIVE_DELAY; - regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); - regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); + regmap_write(map, soc_data->sensor_ctrl + REG_CLR, + soc_data->power_down_mask); + regmap_write(map, soc_data->sensor_ctrl + REG_SET, + soc_data->measure_temp_mask); if (!data->irq_enabled) { data->irq_enabled = true; enable_irq(data->irq); } } else { - regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP); - regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); + regmap_write(map, soc_data->sensor_ctrl + REG_CLR, + soc_data->measure_temp_mask); + regmap_write(map, soc_data->sensor_ctrl + REG_SET, + soc_data->power_down_mask); tz->polling_delay = 0; tz->passive_delay = 0; @@ -354,6 +497,15 @@ static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1) return -EINVAL; } + /* + * On i.MX7D, we only use the calibration data at 25C to get the temp, + * Tmeas = ( Nmeas - n1) + 25; n1 is the fuse value for 25C. + */ + if (data->socdata->version == TEMPMON_IMX7D) { + data->c1 = (ocotp_ana1 >> 9) & 0x1ff; + return 0; + } + /* * The sensor is calibrated at 25 °C (aka T1) and the value measured * (aka N1) at this temperature is provided in bits [31:20] in the @@ -492,6 +644,7 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev) static const struct of_device_id of_imx_thermal_match[] = { { .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, }, { .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, }, + { .compatible = "fsl,imx7d-tempmon", .data = &thermal_imx7d_data, }, { /* end */ } }; MODULE_DEVICE_TABLE(of, of_imx_thermal_match); @@ -523,14 +676,15 @@ static int imx_thermal_probe(struct platform_device *pdev) /* make sure the IRQ flag is clear before enabling irq on i.MX6SX */ if (data->socdata->version == TEMPMON_IMX6SX) { - regmap_write(map, MISC1 + REG_CLR, MISC1_IRQ_TEMPHIGH | - MISC1_IRQ_TEMPLOW | MISC1_IRQ_TEMPPANIC); + regmap_write(map, IMX6_MISC1 + REG_CLR, + IMX6_MISC1_IRQ_TEMPHIGH | IMX6_MISC1_IRQ_TEMPLOW + | IMX6_MISC1_IRQ_TEMPPANIC); /* * reset value of LOW ALARM is incorrect, set it to lowest * value to avoid false trigger of low alarm. */ - regmap_write(map, TEMPSENSE2 + REG_SET, - TEMPSENSE2_LOW_VALUE_MASK); + regmap_write(map, data->socdata->low_alarm_ctrl + REG_SET, + data->socdata->low_alarm_mask); } data->irq = platform_get_irq(pdev, 0); @@ -557,11 +711,17 @@ static int imx_thermal_probe(struct platform_device *pdev) } /* Make sure sensor is in known good state for measurements */ - regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); - regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP); - regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ); - regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF); - regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); + regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, + data->socdata->power_down_mask); + regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, + data->socdata->measure_temp_mask); + regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR, + data->socdata->measure_freq_mask); + if (data->socdata->version != TEMPMON_IMX7D) + regmap_write(map, IMX6_MISC0 + REG_SET, + IMX6_MISC0_REFTOP_SELBIASOFF); + regmap_write(map, data->socdata->sensor_ctrl + REG_SET, + data->socdata->power_down_mask); data->policy = cpufreq_cpu_get(0); if (!data->policy) { @@ -626,16 +786,20 @@ static int imx_thermal_probe(struct platform_device *pdev) data->temp_passive / 1000); /* Enable measurements at ~ 10 Hz */ - regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ); + regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR, + data->socdata->measure_freq_mask); measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */ - regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq); + regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET, + measure_freq << data->socdata->measure_freq_shift); imx_set_alarm_temp(data, data->temp_passive); if (data->socdata->version == TEMPMON_IMX6SX) imx_set_panic_temp(data, data->temp_critical); - regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); - regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); + regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, + data->socdata->power_down_mask); + regmap_write(map, data->socdata->sensor_ctrl + REG_SET, + data->socdata->measure_temp_mask); data->irq_enabled = true; data->mode = THERMAL_DEVICE_ENABLED; @@ -661,7 +825,8 @@ static int imx_thermal_remove(struct platform_device *pdev) struct regmap *map = data->tempmon; /* Disable measurements */ - regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); + regmap_write(map, data->socdata->sensor_ctrl + REG_SET, + data->socdata->power_down_mask); if (!IS_ERR(data->thermal_clk)) clk_disable_unprepare(data->thermal_clk); @@ -684,8 +849,10 @@ static int imx_thermal_suspend(struct device *dev) * temperature will be read as the thermal sensor is powered * down. */ - regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP); - regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); + regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, + data->socdata->measure_temp_mask); + regmap_write(map, data->socdata->sensor_ctrl + REG_SET, + data->socdata->power_down_mask); data->mode = THERMAL_DEVICE_DISABLED; clk_disable_unprepare(data->thermal_clk); @@ -702,8 +869,10 @@ static int imx_thermal_resume(struct device *dev) if (ret) return ret; /* Enabled thermal sensor after resume */ - regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); - regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); + regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, + data->socdata->power_down_mask); + regmap_write(map, data->socdata->sensor_ctrl + REG_SET, + data->socdata->measure_temp_mask); data->mode = THERMAL_DEVICE_ENABLED; return 0; From 0eb875d88aaa98ceb7134cb54638e49b35ab0946 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 16 Apr 2018 12:11:52 +0200 Subject: [PATCH 04/50] thermal: exynos: Reading temperature makes sense only when TMU is turned on When thermal sensor is not yet enabled, reading temperature might return random value. This might even result in stopping system booting when such temperature is higher than the critical value. Fix this by checking if TMU has been actually enabled before reading the temperature. This change fixes booting of Exynos4210-based board with TMU enabled (for example Samsung Trats board), which was broken since v4.4 kernel release. Signed-off-by: Marek Szyprowski Fixes: 9e4249b40340 ("thermal: exynos: Fix first temperature read after registering sensor") CC: stable@vger.kernel.org # v4.6+ Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index ed805c7c5ace..986cbd01aaaa 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -185,6 +185,7 @@ * @regulator: pointer to the TMU regulator structure. * @reg_conf: pointer to structure to register with core thermal. * @ntrip: number of supported trip points. + * @enabled: current status of TMU device * @tmu_initialize: SoC specific TMU initialization method * @tmu_control: SoC specific TMU control method * @tmu_read: SoC specific TMU temperature read method @@ -205,6 +206,7 @@ struct exynos_tmu_data { struct regulator *regulator; struct thermal_zone_device *tzd; unsigned int ntrip; + bool enabled; int (*tmu_initialize)(struct platform_device *pdev); void (*tmu_control)(struct platform_device *pdev, bool on); @@ -398,6 +400,7 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on) mutex_lock(&data->lock); clk_enable(data->clk); data->tmu_control(pdev, on); + data->enabled = on; clk_disable(data->clk); mutex_unlock(&data->lock); } @@ -890,7 +893,7 @@ static int exynos_get_temp(void *p, int *temp) { struct exynos_tmu_data *data = p; - if (!data || !data->tmu_read) + if (!data || !data->tmu_read || !data->enabled) return -EINVAL; mutex_lock(&data->lock); From 08d725cd93602312df2bc4208e4672a34c107d89 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 16 Apr 2018 12:11:53 +0200 Subject: [PATCH 05/50] thermal: exynos: Propagate error value from tmu_read() tmu_read() in case of Exynos4210 might return error for out of bound values. Current code ignores such value, what leads to reporting critical temperature value. Add proper error code propagation to exynos_get_temp() function. Signed-off-by: Marek Szyprowski CC: stable@vger.kernel.org # v4.6+ Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 986cbd01aaaa..ac83f721db24 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -892,6 +892,7 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on) static int exynos_get_temp(void *p, int *temp) { struct exynos_tmu_data *data = p; + int value, ret = 0; if (!data || !data->tmu_read || !data->enabled) return -EINVAL; @@ -899,12 +900,16 @@ static int exynos_get_temp(void *p, int *temp) mutex_lock(&data->lock); clk_enable(data->clk); - *temp = code_to_temp(data, data->tmu_read(data)) * MCELSIUS; + value = data->tmu_read(data); + if (value < 0) + ret = value; + else + *temp = code_to_temp(data, value) * MCELSIUS; clk_disable(data->clk); mutex_unlock(&data->lock); - return 0; + return ret; } #ifdef CONFIG_THERMAL_EMULATION From fee88e2b04f11cda53a34988d53565b53d1d3e18 Mon Sep 17 00:00:00 2001 From: Maciej Purski Date: Mon, 16 Apr 2018 12:11:54 +0200 Subject: [PATCH 06/50] thermal: exynos: Read soc_type from match data Device context's field data->soc is currently obtained by comparing of_compatible's. Provide soc_type as .data field in device's match table, as it is done in most drivers. Signed-off-by: Maciej Purski Signed-off-by: Bartlomiej Zolnierkiewicz Acked-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 74 +++++++++++++--------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index ac83f721db24..d7a3c3cd08a1 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -1105,47 +1105,41 @@ static irqreturn_t exynos_tmu_irq(int irq, void *id) } static const struct of_device_id exynos_tmu_match[] = { - { .compatible = "samsung,exynos3250-tmu", }, - { .compatible = "samsung,exynos4210-tmu", }, - { .compatible = "samsung,exynos4412-tmu", }, - { .compatible = "samsung,exynos5250-tmu", }, - { .compatible = "samsung,exynos5260-tmu", }, - { .compatible = "samsung,exynos5420-tmu", }, - { .compatible = "samsung,exynos5420-tmu-ext-triminfo", }, - { .compatible = "samsung,exynos5433-tmu", }, - { .compatible = "samsung,exynos5440-tmu", }, - { .compatible = "samsung,exynos7-tmu", }, - { /* sentinel */ }, + { + .compatible = "samsung,exynos3250-tmu", + .data = (const void *)SOC_ARCH_EXYNOS3250, + }, { + .compatible = "samsung,exynos4210-tmu", + .data = (const void *)SOC_ARCH_EXYNOS4210, + }, { + .compatible = "samsung,exynos4412-tmu", + .data = (const void *)SOC_ARCH_EXYNOS4412, + }, { + .compatible = "samsung,exynos5250-tmu", + .data = (const void *)SOC_ARCH_EXYNOS5250, + }, { + .compatible = "samsung,exynos5260-tmu", + .data = (const void *)SOC_ARCH_EXYNOS5260, + }, { + .compatible = "samsung,exynos5420-tmu", + .data = (const void *)SOC_ARCH_EXYNOS5420, + }, { + .compatible = "samsung,exynos5420-tmu-ext-triminfo", + .data = (const void *)SOC_ARCH_EXYNOS5420_TRIMINFO, + }, { + .compatible = "samsung,exynos5433-tmu", + .data = (const void *)SOC_ARCH_EXYNOS5433, + }, { + .compatible = "samsung,exynos5440-tmu", + .data = (const void *)SOC_ARCH_EXYNOS5440, + }, { + .compatible = "samsung,exynos7-tmu", + .data = (const void *)SOC_ARCH_EXYNOS7, + }, + { }, }; MODULE_DEVICE_TABLE(of, exynos_tmu_match); -static int exynos_of_get_soc_type(struct device_node *np) -{ - if (of_device_is_compatible(np, "samsung,exynos3250-tmu")) - return SOC_ARCH_EXYNOS3250; - else if (of_device_is_compatible(np, "samsung,exynos4210-tmu")) - return SOC_ARCH_EXYNOS4210; - else if (of_device_is_compatible(np, "samsung,exynos4412-tmu")) - return SOC_ARCH_EXYNOS4412; - else if (of_device_is_compatible(np, "samsung,exynos5250-tmu")) - return SOC_ARCH_EXYNOS5250; - else if (of_device_is_compatible(np, "samsung,exynos5260-tmu")) - return SOC_ARCH_EXYNOS5260; - else if (of_device_is_compatible(np, "samsung,exynos5420-tmu")) - return SOC_ARCH_EXYNOS5420; - else if (of_device_is_compatible(np, - "samsung,exynos5420-tmu-ext-triminfo")) - return SOC_ARCH_EXYNOS5420_TRIMINFO; - else if (of_device_is_compatible(np, "samsung,exynos5433-tmu")) - return SOC_ARCH_EXYNOS5433; - else if (of_device_is_compatible(np, "samsung,exynos5440-tmu")) - return SOC_ARCH_EXYNOS5440; - else if (of_device_is_compatible(np, "samsung,exynos7-tmu")) - return SOC_ARCH_EXYNOS7; - - return -EINVAL; -} - static int exynos_of_sensor_conf(struct device_node *np, struct exynos_tmu_platform_data *pdata) { @@ -1219,7 +1213,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) exynos_of_sensor_conf(pdev->dev.of_node, pdata); data->pdata = pdata; - data->soc = exynos_of_get_soc_type(pdev->dev.of_node); + data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev); switch (data->soc) { case SOC_ARCH_EXYNOS4210: From 3ab9e4175f634bef69c960e8a95db466c4c9178b Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 16 Apr 2018 12:11:55 +0200 Subject: [PATCH 07/50] thermal: exynos: remove unused "type" field from struct exynos_tmu_platform_data Remove unused "type" field from struct exynos_tmu_platform_data. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index 5149c2a3030c..8c468b678bda 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h @@ -47,7 +47,6 @@ enum soc_type { * 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 @@ -68,7 +67,6 @@ struct exynos_tmu_platform_data { u8 second_point_trim; u8 default_temp_offset; - enum soc_type type; u32 cal_type; }; From 9c933b1be58637b7ba05bab35953f1b976c12394 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 16 Apr 2018 12:11:56 +0200 Subject: [PATCH 08/50] thermal: exynos: remove parsing of samsung, tmu_default_temp_offset property Trimming (one point based or two points based) is always used for the temperature calibration and the default non-trimming code is never reached. Remove it and then remove no longer needed parsing of samsung,tmu_default_temp_offset property. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 46 ++++++++-------------------- drivers/thermal/samsung/exynos_tmu.h | 2 -- 2 files changed, 12 insertions(+), 36 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index d7a3c3cd08a1..958a7c430b9f 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -249,24 +249,14 @@ static void exynos_report_trigger(struct exynos_tmu_data *p) static int temp_to_code(struct exynos_tmu_data *data, u8 temp) { struct exynos_tmu_platform_data *pdata = data->pdata; - int temp_code; - switch (pdata->cal_type) { - case TYPE_TWO_POINT_TRIMMING: - temp_code = (temp - pdata->first_point_trim) * - (data->temp_error2 - data->temp_error1) / - (pdata->second_point_trim - pdata->first_point_trim) + - data->temp_error1; - break; - case TYPE_ONE_POINT_TRIMMING: - temp_code = temp + data->temp_error1 - pdata->first_point_trim; - break; - default: - temp_code = temp + pdata->default_temp_offset; - break; - } + if (pdata->cal_type == TYPE_ONE_POINT_TRIMMING) + return temp + data->temp_error1 - pdata->first_point_trim; - return temp_code; + return (temp - pdata->first_point_trim) * + (data->temp_error2 - data->temp_error1) / + (pdata->second_point_trim - pdata->first_point_trim) + + data->temp_error1; } /* @@ -276,24 +266,14 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp) static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code) { struct exynos_tmu_platform_data *pdata = data->pdata; - int temp; - switch (pdata->cal_type) { - case TYPE_TWO_POINT_TRIMMING: - temp = (temp_code - data->temp_error1) * - (pdata->second_point_trim - pdata->first_point_trim) / - (data->temp_error2 - data->temp_error1) + - pdata->first_point_trim; - break; - case TYPE_ONE_POINT_TRIMMING: - temp = temp_code - data->temp_error1 + pdata->first_point_trim; - break; - default: - temp = temp_code - pdata->default_temp_offset; - break; - } + if (pdata->cal_type == TYPE_ONE_POINT_TRIMMING) + return temp_code - data->temp_error1 + pdata->first_point_trim; - return temp; + return (temp_code - data->temp_error1) * + (pdata->second_point_trim - pdata->first_point_trim) / + (data->temp_error2 - data->temp_error1) + + pdata->first_point_trim; } static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) @@ -1166,8 +1146,6 @@ static int exynos_of_sensor_conf(struct device_node *np, pdata->first_point_trim = (u8)value; of_property_read_u32(np, "samsung,tmu_second_point_trim", &value); pdata->second_point_trim = (u8)value; - of_property_read_u32(np, "samsung,tmu_default_temp_offset", &value); - pdata->default_temp_offset = (u8)value; of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type); diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index 8c468b678bda..a7e81b4cd7b9 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h @@ -50,7 +50,6 @@ enum soc_type { * @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. @@ -65,7 +64,6 @@ struct exynos_tmu_platform_data { u32 max_efuse_value; u8 first_point_trim; u8 second_point_trim; - u8 default_temp_offset; u32 cal_type; }; From 718b4ca160cfabf8913b44b50f9903755e82f166 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 16 Apr 2018 12:11:57 +0200 Subject: [PATCH 09/50] thermal: exynos: remove parsing of samsung, tmu_[first, second]_point_trim properties All SoCs use the same values (25, 85) for trim points (except Exynos5440 which currently specifices value 70 for the second trim point -> it seems to be a mistake because documentation uses value 85 and two points based trimming has never been used by the driver for this SoC anyway) so just make it explicit and remove parsing of samsung,tmu_[first,second]_point_trim properties. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 20 +++++++++----------- drivers/thermal/samsung/exynos_tmu.h | 2 -- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 958a7c430b9f..7ec806170c12 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -165,6 +165,9 @@ #define EXYNOS7_EMUL_DATA_SHIFT 7 #define EXYNOS7_EMUL_DATA_MASK 0x1ff +#define EXYNOS_FIRST_POINT_TRIM 25 +#define EXYNOS_SECOND_POINT_TRIM 85 + #define MCELSIUS 1000 /** * struct exynos_tmu_data : A structure to hold the private data of the TMU @@ -251,11 +254,11 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp) struct exynos_tmu_platform_data *pdata = data->pdata; if (pdata->cal_type == TYPE_ONE_POINT_TRIMMING) - return temp + data->temp_error1 - pdata->first_point_trim; + return temp + data->temp_error1 - EXYNOS_FIRST_POINT_TRIM; - return (temp - pdata->first_point_trim) * + return (temp - EXYNOS_FIRST_POINT_TRIM) * (data->temp_error2 - data->temp_error1) / - (pdata->second_point_trim - pdata->first_point_trim) + + (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) + data->temp_error1; } @@ -268,12 +271,12 @@ static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code) struct exynos_tmu_platform_data *pdata = data->pdata; if (pdata->cal_type == TYPE_ONE_POINT_TRIMMING) - return temp_code - data->temp_error1 + pdata->first_point_trim; + return temp_code - data->temp_error1 + EXYNOS_FIRST_POINT_TRIM; return (temp_code - data->temp_error1) * - (pdata->second_point_trim - pdata->first_point_trim) / + (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) / (data->temp_error2 - data->temp_error1) + - pdata->first_point_trim; + EXYNOS_FIRST_POINT_TRIM; } static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) @@ -1142,11 +1145,6 @@ static int exynos_of_sensor_conf(struct device_node *np, of_property_read_u32(np, "samsung,tmu_max_efuse_value", &pdata->max_efuse_value); - of_property_read_u32(np, "samsung,tmu_first_point_trim", &value); - pdata->first_point_trim = (u8)value; - of_property_read_u32(np, "samsung,tmu_second_point_trim", &value); - pdata->second_point_trim = (u8)value; - of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type); of_node_put(np); diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index a7e81b4cd7b9..a5d8c9c36648 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h @@ -62,8 +62,6 @@ struct exynos_tmu_platform_data { u32 efuse_value; u32 min_efuse_value; u32 max_efuse_value; - u8 first_point_trim; - u8 second_point_trim; u32 cal_type; }; From 09d29426bce847330440ba735880ab0ef595cad2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 16 Apr 2018 12:11:58 +0200 Subject: [PATCH 10/50] thermal: exynos: remove parsing of samsung, tmu_noise_cancel_mode property All SoCs use the same value (4) for the noise cancel mode so just make it explicit and remove parsing of samsung,tmu_noise_cancel_mode property. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 10 ++++------ drivers/thermal/samsung/exynos_tmu.h | 3 --- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 7ec806170c12..1fa162dcdf6b 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -168,6 +168,8 @@ #define EXYNOS_FIRST_POINT_TRIM 25 #define EXYNOS_SECOND_POINT_TRIM 85 +#define EXYNOS_NOISE_CANCEL_MODE 4 + #define MCELSIUS 1000 /** * struct exynos_tmu_data : A structure to hold the private data of the TMU @@ -368,10 +370,8 @@ static u32 get_con_reg(struct exynos_tmu_data *data, u32 con) con &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); - if (pdata->noise_cancel_mode) { - con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT); - con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT); - } + con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT); + con |= (EXYNOS_NOISE_CANCEL_MODE << EXYNOS_TMU_TRIP_MODE_SHIFT); return con; } @@ -1135,8 +1135,6 @@ static int exynos_of_sensor_conf(struct device_node *np, pdata->gain = (u8)value; of_property_read_u32(np, "samsung,tmu_reference_voltage", &value); pdata->reference_voltage = (u8)value; - of_property_read_u32(np, "samsung,tmu_noise_cancel_mode", &value); - pdata->noise_cancel_mode = (u8)value; of_property_read_u32(np, "samsung,tmu_efuse_value", &pdata->efuse_value); diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index a5d8c9c36648..b111a01fd5c1 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h @@ -45,8 +45,6 @@ enum soc_type { * @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 * @efuse_value: platform defined fuse value * @min_efuse_value: minimum valid trimming data * @max_efuse_value: maximum valid trimming data @@ -57,7 +55,6 @@ enum soc_type { struct exynos_tmu_platform_data { u8 gain; u8 reference_voltage; - u8 noise_cancel_mode; u32 efuse_value; u32 min_efuse_value; From e3ed36499bc95658c28557c0f4a6364f30e51bd0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 16 Apr 2018 12:11:59 +0200 Subject: [PATCH 11/50] thermal: exynos: remove parsing of samsung, tmu[_min, _max]_efuse_value properties Since pdata efuse values are SoC (not platform) specific just move them from platform data to struct exynos_tmu_data instance. Then remove parsing of samsung,tmu[_,min_,max]_efuse_value properties. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 49 ++++++++++++++++++---------- drivers/thermal/samsung/exynos_tmu.h | 7 ---- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 1fa162dcdf6b..9a0e9610f5e6 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -185,6 +185,9 @@ * @clk: pointer to the clock structure. * @clk_sec: pointer to the clock structure for accessing the base_second. * @sclk: pointer to the clock structure for accessing the tmu special clk. + * @efuse_value: SoC defined fuse value + * @min_efuse_value: minimum valid trimming data + * @max_efuse_value: maximum valid trimming data * @temp_error1: fused value of the first point trim. * @temp_error2: fused value of the second point trim. * @regulator: pointer to the TMU regulator structure. @@ -207,6 +210,9 @@ struct exynos_tmu_data { struct work_struct irq_work; struct mutex lock; struct clk *clk, *clk_sec, *sclk; + u32 efuse_value; + u32 min_efuse_value; + u32 max_efuse_value; u16 temp_error1, temp_error2; struct regulator *regulator; struct thermal_zone_device *tzd; @@ -283,20 +289,18 @@ static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code) static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) { - struct exynos_tmu_platform_data *pdata = data->pdata; - data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK; data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) & EXYNOS_TMU_TEMP_MASK); if (!data->temp_error1 || - (pdata->min_efuse_value > data->temp_error1) || - (data->temp_error1 > pdata->max_efuse_value)) - data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK; + (data->min_efuse_value > data->temp_error1) || + (data->temp_error1 > data->max_efuse_value)) + data->temp_error1 = data->efuse_value & EXYNOS_TMU_TEMP_MASK; if (!data->temp_error2) data->temp_error2 = - (pdata->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) & + (data->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) & EXYNOS_TMU_TEMP_MASK; } @@ -655,7 +659,6 @@ static int exynos7_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; - struct exynos_tmu_platform_data *pdata = data->pdata; unsigned int status, trim_info; unsigned int rising_threshold = 0, falling_threshold = 0; int ret = 0, threshold_code, i; @@ -672,9 +675,9 @@ static int exynos7_tmu_initialize(struct platform_device *pdev) data->temp_error1 = trim_info & EXYNOS7_TMU_TEMP_MASK; if (!data->temp_error1 || - (pdata->min_efuse_value > data->temp_error1) || - (data->temp_error1 > pdata->max_efuse_value)) - data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK; + (data->min_efuse_value > data->temp_error1) || + (data->temp_error1 > data->max_efuse_value)) + data->temp_error1 = data->efuse_value & EXYNOS_TMU_TEMP_MASK; /* Write temperature code for rising and falling threshold */ for (i = (of_thermal_get_ntrips(tz) - 1); i >= 0; i--) { @@ -1136,13 +1139,6 @@ static int exynos_of_sensor_conf(struct device_node *np, of_property_read_u32(np, "samsung,tmu_reference_voltage", &value); pdata->reference_voltage = (u8)value; - of_property_read_u32(np, "samsung,tmu_efuse_value", - &pdata->efuse_value); - of_property_read_u32(np, "samsung,tmu_min_efuse_value", - &pdata->min_efuse_value); - of_property_read_u32(np, "samsung,tmu_max_efuse_value", - &pdata->max_efuse_value); - of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type); of_node_put(np); @@ -1196,6 +1192,9 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_read = exynos4210_tmu_read; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 4; + data->efuse_value = 55; + data->min_efuse_value = 40; + data->max_efuse_value = 100; break; case SOC_ARCH_EXYNOS3250: case SOC_ARCH_EXYNOS4412: @@ -1209,6 +1208,13 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 4; + data->efuse_value = 55; + if (data->soc != SOC_ARCH_EXYNOS5420 && + data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO) + data->min_efuse_value = 40; + else + data->min_efuse_value = 0; + data->max_efuse_value = 100; break; case SOC_ARCH_EXYNOS5433: data->tmu_initialize = exynos5433_tmu_initialize; @@ -1217,6 +1223,9 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 8; + data->efuse_value = 75; + data->min_efuse_value = 40; + data->max_efuse_value = 150; break; case SOC_ARCH_EXYNOS5440: data->tmu_initialize = exynos5440_tmu_initialize; @@ -1225,6 +1234,9 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos5440_tmu_set_emulation; data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; data->ntrip = 4; + data->efuse_value = 0x5d2d; + data->min_efuse_value = 16; + data->max_efuse_value = 76; break; case SOC_ARCH_EXYNOS7: data->tmu_initialize = exynos7_tmu_initialize; @@ -1233,6 +1245,9 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 8; + data->efuse_value = 75; + data->min_efuse_value = 15; + data->max_efuse_value = 100; break; default: dev_err(&pdev->dev, "Platform not supported\n"); diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index b111a01fd5c1..4c49312b0063 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h @@ -45,9 +45,6 @@ enum soc_type { * @reference_voltage: reference voltage of amplifier * in the positive-TC generator block * 0 < reference_voltage <= 31 - * @efuse_value: platform defined fuse value - * @min_efuse_value: minimum valid trimming data - * @max_efuse_value: maximum valid trimming data * @cal_type: calibration type for temperature * * This structure is required for configuration of exynos_tmu driver. @@ -56,10 +53,6 @@ struct exynos_tmu_platform_data { u8 gain; u8 reference_voltage; - u32 efuse_value; - u32 min_efuse_value; - u32 max_efuse_value; - u32 cal_type; }; From 61020d189dbc4a7b7c4b7c3b22ee0970351ce32b Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 16 Apr 2018 12:12:00 +0200 Subject: [PATCH 12/50] thermal: exynos: remove parsing of samsung, tmu_reference_voltage property Since pdata reference_voltage values are SoC (not platform) specific just move it from platform data to struct exynos_tmu_data instance. Then remove parsing of samsung,tmu_reference_voltage property. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 18 +++++++++++++++--- drivers/thermal/samsung/exynos_tmu.h | 4 ---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 9a0e9610f5e6..6db6ef638fb6 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -123,6 +123,8 @@ #define EXYNOS5433_PD_DET_EN 1 +#define EXYNOS5433_G3D_BASE 0x10070000 + /*exynos5440 specific registers*/ #define EXYNOS5440_TMU_S0_7_TRIM 0x000 #define EXYNOS5440_TMU_S0_7_CTRL 0x020 @@ -190,6 +192,9 @@ * @max_efuse_value: maximum valid trimming data * @temp_error1: fused value of the first point trim. * @temp_error2: fused value of the second point trim. + * @reference_voltage: reference voltage of amplifier + * in the positive-TC generator block + * 0 < reference_voltage <= 31 * @regulator: pointer to the TMU regulator structure. * @reg_conf: pointer to structure to register with core thermal. * @ntrip: number of supported trip points. @@ -214,6 +219,7 @@ struct exynos_tmu_data { u32 min_efuse_value; u32 max_efuse_value; u16 temp_error1, temp_error2; + u8 reference_voltage; struct regulator *regulator; struct thermal_zone_device *tzd; unsigned int ntrip; @@ -369,7 +375,7 @@ static u32 get_con_reg(struct exynos_tmu_data *data, u32 con) con |= (EXYNOS4412_MUX_ADDR_VALUE << EXYNOS4412_MUX_ADDR_SHIFT); con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT); - con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT; + con |= data->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT; con &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); @@ -1136,8 +1142,6 @@ static int exynos_of_sensor_conf(struct device_node *np, ret = of_property_read_u32(np, "samsung,tmu_gain", &value); pdata->gain = (u8)value; - of_property_read_u32(np, "samsung,tmu_reference_voltage", &value); - pdata->reference_voltage = (u8)value; of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type); @@ -1192,6 +1196,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_read = exynos4210_tmu_read; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 4; + data->reference_voltage = 7; data->efuse_value = 55; data->min_efuse_value = 40; data->max_efuse_value = 100; @@ -1208,6 +1213,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 4; + data->reference_voltage = 16; data->efuse_value = 55; if (data->soc != SOC_ARCH_EXYNOS5420 && data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO) @@ -1223,6 +1229,10 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 8; + if (res.start == EXYNOS5433_G3D_BASE) + data->reference_voltage = 23; + else + data->reference_voltage = 16; data->efuse_value = 75; data->min_efuse_value = 40; data->max_efuse_value = 150; @@ -1234,6 +1244,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos5440_tmu_set_emulation; data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; data->ntrip = 4; + data->reference_voltage = 16; data->efuse_value = 0x5d2d; data->min_efuse_value = 16; data->max_efuse_value = 76; @@ -1245,6 +1256,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 8; + data->reference_voltage = 17; data->efuse_value = 75; data->min_efuse_value = 15; data->max_efuse_value = 100; diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index 4c49312b0063..9f4318c501c1 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h @@ -42,16 +42,12 @@ enum soc_type { * 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 * @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; u32 cal_type; }; From fccfe0993b5dc550e5f9fbb716fb0b588c5fdbc1 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 16 Apr 2018 12:12:01 +0200 Subject: [PATCH 13/50] thermal: exynos: remove parsing of samsung,tmu_gain property Since pdata gain values are SoC (not platform) specific just move it from platform data to struct exynos_tmu_data instance. Then remove parsing of samsung,tmu_gain property. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 18 +++++++++--------- drivers/thermal/samsung/exynos_tmu.h | 4 ---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 6db6ef638fb6..3cdbc0981008 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -192,6 +192,8 @@ * @max_efuse_value: maximum valid trimming data * @temp_error1: fused value of the first point trim. * @temp_error2: fused value of the second point trim. + * @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 @@ -219,6 +221,7 @@ struct exynos_tmu_data { u32 min_efuse_value; u32 max_efuse_value; u16 temp_error1, temp_error2; + u8 gain; u8 reference_voltage; struct regulator *regulator; struct thermal_zone_device *tzd; @@ -368,8 +371,6 @@ static int exynos_tmu_initialize(struct platform_device *pdev) static u32 get_con_reg(struct exynos_tmu_data *data, u32 con) { - struct exynos_tmu_platform_data *pdata = data->pdata; - if (data->soc == SOC_ARCH_EXYNOS4412 || data->soc == SOC_ARCH_EXYNOS3250) con |= (EXYNOS4412_MUX_ADDR_VALUE << EXYNOS4412_MUX_ADDR_SHIFT); @@ -378,7 +379,7 @@ static u32 get_con_reg(struct exynos_tmu_data *data, u32 con) con |= data->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT; con &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); - con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); + con |= (data->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT); con |= (EXYNOS_NOISE_CANCEL_MODE << EXYNOS_TMU_TRIP_MODE_SHIFT); @@ -1135,14 +1136,8 @@ MODULE_DEVICE_TABLE(of, exynos_tmu_match); static int exynos_of_sensor_conf(struct device_node *np, struct exynos_tmu_platform_data *pdata) { - u32 value; - int ret; - of_node_get(np); - ret = of_property_read_u32(np, "samsung,tmu_gain", &value); - pdata->gain = (u8)value; - of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type); of_node_put(np); @@ -1196,6 +1191,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_read = exynos4210_tmu_read; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 4; + data->gain = 15; data->reference_voltage = 7; data->efuse_value = 55; data->min_efuse_value = 40; @@ -1213,6 +1209,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 4; + data->gain = 8; data->reference_voltage = 16; data->efuse_value = 55; if (data->soc != SOC_ARCH_EXYNOS5420 && @@ -1229,6 +1226,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 8; + data->gain = 8; if (res.start == EXYNOS5433_G3D_BASE) data->reference_voltage = 23; else @@ -1244,6 +1242,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos5440_tmu_set_emulation; data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; data->ntrip = 4; + data->gain = 5; data->reference_voltage = 16; data->efuse_value = 0x5d2d; data->min_efuse_value = 16; @@ -1256,6 +1255,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; data->ntrip = 8; + data->gain = 9; data->reference_voltage = 17; data->efuse_value = 75; data->min_efuse_value = 15; diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index 9f4318c501c1..689453ddb3a8 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h @@ -40,15 +40,11 @@ enum soc_type { /** * struct exynos_tmu_platform_data - * @gain: gain of amplifier in the positive-TC generator block - * 0 < gain <= 15 * @cal_type: calibration type for temperature * * This structure is required for configuration of exynos_tmu driver. */ struct exynos_tmu_platform_data { - u8 gain; - u32 cal_type; }; From 199b3e3c860cdf3f092e7cbb2bf08b8a96ed4beb Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 16 Apr 2018 12:12:02 +0200 Subject: [PATCH 14/50] thermal: exynos: remove parsing of samsung, tmu_cal_type property Since calibration type for temperature is SoC (not platform) specific just move it from platform data to struct exynos_tmu_data instance. Then remove parsing of samsung,tmu_cal_type property. Also remove no longer needed platform data structure. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 43 ++++++---------------------- drivers/thermal/samsung/exynos_tmu.h | 10 ------- 2 files changed, 9 insertions(+), 44 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 3cdbc0981008..7975f3360e98 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -177,7 +177,6 @@ * struct exynos_tmu_data : A structure to hold the private data of the TMU driver * @id: identifier of the one instance of the TMU controller. - * @pdata: pointer to the tmu platform/configuration data * @base: base address of the single instance of the TMU controller. * @base_second: base address of the common registers of the TMU controller. * @irq: irq number of the TMU controller. @@ -187,6 +186,7 @@ * @clk: pointer to the clock structure. * @clk_sec: pointer to the clock structure for accessing the base_second. * @sclk: pointer to the clock structure for accessing the tmu special clk. + * @cal_type: calibration type for temperature * @efuse_value: SoC defined fuse value * @min_efuse_value: minimum valid trimming data * @max_efuse_value: maximum valid trimming data @@ -209,7 +209,6 @@ */ struct exynos_tmu_data { int id; - struct exynos_tmu_platform_data *pdata; void __iomem *base; void __iomem *base_second; int irq; @@ -217,6 +216,7 @@ struct exynos_tmu_data { struct work_struct irq_work; struct mutex lock; struct clk *clk, *clk_sec, *sclk; + u32 cal_type; u32 efuse_value; u32 min_efuse_value; u32 max_efuse_value; @@ -268,9 +268,7 @@ static void exynos_report_trigger(struct exynos_tmu_data *p) */ static int temp_to_code(struct exynos_tmu_data *data, u8 temp) { - struct exynos_tmu_platform_data *pdata = data->pdata; - - if (pdata->cal_type == TYPE_ONE_POINT_TRIMMING) + if (data->cal_type == TYPE_ONE_POINT_TRIMMING) return temp + data->temp_error1 - EXYNOS_FIRST_POINT_TRIM; return (temp - EXYNOS_FIRST_POINT_TRIM) * @@ -285,9 +283,7 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp) */ static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code) { - struct exynos_tmu_platform_data *pdata = data->pdata; - - if (pdata->cal_type == TYPE_ONE_POINT_TRIMMING) + if (data->cal_type == TYPE_ONE_POINT_TRIMMING) return temp_code - data->temp_error1 + EXYNOS_FIRST_POINT_TRIM; return (temp_code - data->temp_error1) * @@ -519,7 +515,6 @@ out: static int exynos5433_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); - struct exynos_tmu_platform_data *pdata = data->pdata; struct thermal_zone_device *tz = data->tzd; unsigned int status, trim_info; unsigned int rising_threshold = 0, falling_threshold = 0; @@ -546,14 +541,12 @@ static int exynos5433_tmu_initialize(struct platform_device *pdev) >> EXYNOS5433_TRIMINFO_CALIB_SEL_SHIFT; switch (cal_type) { - case EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING: - pdata->cal_type = TYPE_ONE_POINT_TRIMMING; - break; case EXYNOS5433_TRIMINFO_TWO_POINT_TRIMMING: - pdata->cal_type = TYPE_TWO_POINT_TRIMMING; + data->cal_type = TYPE_TWO_POINT_TRIMMING; break; + case EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING: default: - pdata->cal_type = TYPE_ONE_POINT_TRIMMING; + data->cal_type = TYPE_ONE_POINT_TRIMMING; break; } @@ -1133,21 +1126,9 @@ static const struct of_device_id exynos_tmu_match[] = { }; MODULE_DEVICE_TABLE(of, exynos_tmu_match); -static int exynos_of_sensor_conf(struct device_node *np, - struct exynos_tmu_platform_data *pdata) -{ - of_node_get(np); - - of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type); - - of_node_put(np); - return 0; -} - static int exynos_map_dt_data(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); - struct exynos_tmu_platform_data *pdata; struct resource res; if (!data || !pdev->dev.of_node) @@ -1174,14 +1155,6 @@ static int exynos_map_dt_data(struct platform_device *pdev) return -EADDRNOTAVAIL; } - pdata = devm_kzalloc(&pdev->dev, - sizeof(struct exynos_tmu_platform_data), - GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - exynos_of_sensor_conf(pdev->dev.of_node, pdata); - data->pdata = pdata; data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev); switch (data->soc) { @@ -1266,6 +1239,8 @@ static int exynos_map_dt_data(struct platform_device *pdev) return -EINVAL; } + data->cal_type = TYPE_ONE_POINT_TRIMMING; + /* * Check if the TMU shares some registers and then try to map the * memory of common registers. diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index 689453ddb3a8..8f56f8656e67 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h @@ -38,14 +38,4 @@ enum soc_type { SOC_ARCH_EXYNOS7, }; -/** - * struct exynos_tmu_platform_data - * @cal_type: calibration type for temperature - * - * This structure is required for configuration of exynos_tmu driver. - */ -struct exynos_tmu_platform_data { - u32 cal_type; -}; - #endif /* _EXYNOS_TMU_H */ From 7efd18a2a18155184c2100fee0beb8cb1a9a57e0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 16 Apr 2018 16:22:19 +0200 Subject: [PATCH 15/50] thermal: exynos: remove separate exynos_tmu.h header file exynos_tmu.h is used only by exynos_tmu.c so there is no need for a separate include file. Also while at it remove no longer needed cpu_cooling.h include. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Acked-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 17 +++++++++++- drivers/thermal/samsung/exynos_tmu.h | 41 ---------------------------- 2 files changed, 16 insertions(+), 42 deletions(-) delete mode 100644 drivers/thermal/samsung/exynos_tmu.h diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 7975f3360e98..b6e2f0e1cd85 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -35,7 +35,8 @@ #include #include -#include "exynos_tmu.h" +#include + #include "../thermal_core.h" /* Exynos generic registers */ @@ -173,6 +174,20 @@ #define EXYNOS_NOISE_CANCEL_MODE 4 #define MCELSIUS 1000 + +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_data : A structure to hold the private data of the TMU driver diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h deleted file mode 100644 index 8f56f8656e67..000000000000 --- a/drivers/thermal/samsung/exynos_tmu.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * exynos_tmu.h - Samsung EXYNOS TMU (Thermal Management Unit) - * - * Copyright (C) 2011 Samsung Electronics - * Donggeun Kim - * Amit Daniel Kachhap - * - * 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 -#include - -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, -}; - -#endif /* _EXYNOS_TMU_H */ From e855ec0845704383151a21198b27f75b86b07f05 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Fri, 30 Mar 2018 12:51:19 +0900 Subject: [PATCH 16/50] dt-bindings: thermal: uniphier: add a compatible string for PXs3 Add a compatible string for thermal monitor implemented on UniPhier PXs3 SoC. Signed-off-by: Kunihiko Hayashi Signed-off-by: Eduardo Valentin --- Documentation/devicetree/bindings/thermal/uniphier-thermal.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt b/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt index 686c0b42ed3f..ceb92a95727a 100644 --- a/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt @@ -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. From 2d3c4cfd56d8629bde279492d462f2167eafad5f Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Fri, 30 Mar 2018 12:51:20 +0900 Subject: [PATCH 17/50] thermal: uniphier: add UniPhier PXs3 support Add support for UniPhier PXs3 SoC. It is equivalent to LD20. Signed-off-by: Kunihiko Hayashi Signed-off-by: Eduardo Valentin --- drivers/thermal/uniphier_thermal.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/thermal/uniphier_thermal.c b/drivers/thermal/uniphier_thermal.c index 95704732f760..55477d74d591 100644 --- a/drivers/thermal/uniphier_thermal.c +++ b/drivers/thermal/uniphier_thermal.c @@ -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); From 34283724475699f261983afdfe72dcec0ae3096a Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Fri, 30 Mar 2018 21:10:04 -0300 Subject: [PATCH 18/50] thermal: tegra: Nuke clk_{readl,writel} helpers Naming driver-specific register accessors with generic names, such as clk_writel and clk_readl, is bad. Moreover, clk_writel and clk_readl are part of the common clock framework api, so readers and code grep'ers get confused by this collision. The helpers are used once, so just remove them. Signed-off-by: Ezequiel Garcia Acked-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/tegra/soctherm.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 455b58ce2652..1f87bbe7618b 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -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 @@ -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 */ From fc66ddff3840232ed102250551d7b6031a49ff17 Mon Sep 17 00:00:00 2001 From: Hien Dang Date: Tue, 17 Apr 2018 22:57:46 +0200 Subject: [PATCH 19/50] thermal: rcar_gen3_thermal: Update calculation formula due to HW evaluation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to hardware evaluation result, Max temperature is changed from 96 to 116 degree Celsius. Also, calculation formula and pseudo FUSE values are changed accordingly. Signed-off-by: Dien Pham Signed-off-by: Hien Dang Signed-off-by: Niklas Söderlund Reviewed-by: Simon Horman Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_gen3_thermal.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 561a0a332208..79c2cdb4105f 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -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]), @@ -354,11 +354,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); From 270ba432003f4cdaf136f1dc736b9fe6dc9d5537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 17 Apr 2018 22:57:47 +0200 Subject: [PATCH 20/50] thermal: rcar_gen3_thermal: update max temperature clamp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the upper limit to clamp the high temperature value to 120C when setting trip points. Signed-off-by: Niklas Söderlund Reviewed-by: Simon Horman Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_gen3_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 79c2cdb4105f..3905ec8b2689 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -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)); From 0706cb152daf56b8bc39965b108b0ff48f0c1c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 26 Apr 2018 21:42:01 +0200 Subject: [PATCH 21/50] dt-bindings: thermal: rcar-gen3-thermal: add r8a77965 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on previous work by Ryo Kataoka . Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Reviewed-by: Simon Horman Reviewed-by: Rob Herring Signed-off-by: Eduardo Valentin --- .../devicetree/bindings/thermal/rcar-gen3-thermal.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt index fdf5caa6229b..32c63ffef2e3 100644 --- a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt @@ -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. From 2e7db3eceb41416ac9633ea58c28760b3c01cfcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 26 Apr 2018 21:42:02 +0200 Subject: [PATCH 22/50] thermal: rcar_gen3_thermal: add r8a77965 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Reviewed-by: Simon Horman Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_gen3_thermal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 3905ec8b2689..766521eb7071 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -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); From 8014220d48e7231c2316381af73ebcc237cd0e48 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 26 Apr 2018 13:21:12 +0200 Subject: [PATCH 23/50] thermal: samsung: Remove support for Exynos5440 The Exynos5440 is not actively developed, there are no development boards available and probably there are no real products with it. Remove wide-tree support for Exynos5440. Signed-off-by: Krzysztof Kozlowski [b.zolnierkie: ported over driver changes] Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Rob Herring Signed-off-by: Eduardo Valentin --- .../bindings/thermal/exynos-thermal.txt | 14 +- drivers/thermal/samsung/exynos_tmu.c | 161 +----------------- 2 files changed, 4 insertions(+), 171 deletions(-) diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt index b957acff57aa..ad648d93d961 100644 --- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt @@ -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>; diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index b6e2f0e1cd85..cda716ce84be 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -126,28 +126,6 @@ #define EXYNOS5433_G3D_BASE 0x10070000 -/*exynos5440 specific registers*/ -#define EXYNOS5440_TMU_S0_7_TRIM 0x000 -#define EXYNOS5440_TMU_S0_7_CTRL 0x020 -#define EXYNOS5440_TMU_S0_7_DEBUG 0x040 -#define EXYNOS5440_TMU_S0_7_TEMP 0x0f0 -#define EXYNOS5440_TMU_S0_7_TH0 0x110 -#define EXYNOS5440_TMU_S0_7_TH1 0x130 -#define EXYNOS5440_TMU_S0_7_TH2 0x150 -#define EXYNOS5440_TMU_S0_7_IRQEN 0x210 -#define EXYNOS5440_TMU_S0_7_IRQ 0x230 -/* exynos5440 common registers */ -#define EXYNOS5440_TMU_IRQ_STATUS 0x000 -#define EXYNOS5440_TMU_PMIN 0x004 - -#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT 0 -#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT 1 -#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT 2 -#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT 3 -#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT 4 -#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24 -#define EXYNOS5440_EFUSE_SWAP_OFFSET 8 - /* Exynos7 specific registers */ #define EXYNOS7_THD_TEMP_RISE7_6 0x50 #define EXYNOS7_THD_TEMP_FALL7_6 0x60 @@ -184,7 +162,6 @@ enum soc_type { SOC_ARCH_EXYNOS5420, SOC_ARCH_EXYNOS5420_TRIMINFO, SOC_ARCH_EXYNOS5433, - SOC_ARCH_EXYNOS5440, SOC_ARCH_EXYNOS7, }; @@ -619,57 +596,6 @@ out: return ret; } -static int exynos5440_tmu_initialize(struct platform_device *pdev) -{ - struct exynos_tmu_data *data = platform_get_drvdata(pdev); - unsigned int trim_info = 0, con, rising_threshold; - int threshold_code; - int crit_temp = 0; - - /* - * For exynos5440 soc triminfo value is swapped between TMU0 and - * TMU2, so the below logic is needed. - */ - switch (data->id) { - case 0: - trim_info = readl(data->base + EXYNOS5440_EFUSE_SWAP_OFFSET + - EXYNOS5440_TMU_S0_7_TRIM); - break; - case 1: - trim_info = readl(data->base + EXYNOS5440_TMU_S0_7_TRIM); - break; - case 2: - trim_info = readl(data->base - EXYNOS5440_EFUSE_SWAP_OFFSET + - EXYNOS5440_TMU_S0_7_TRIM); - } - sanitize_temp_error(data, trim_info); - - /* Write temperature code for rising and falling threshold */ - rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0); - rising_threshold = get_th_reg(data, rising_threshold, false); - writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0); - writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1); - - data->tmu_clear_irqs(data); - - /* if last threshold limit is also present */ - if (!data->tzd->ops->get_crit_temp(data->tzd, &crit_temp)) { - threshold_code = temp_to_code(data, crit_temp / MCELSIUS); - /* 5th level to be assigned in th2 reg */ - rising_threshold = - threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT; - writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH2); - con = readl(data->base + EXYNOS5440_TMU_S0_7_CTRL); - con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT); - writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL); - } - /* Clear the PMIN in the common TMU register */ - if (!data->id) - writel(0, data->base_second + EXYNOS5440_TMU_PMIN); - - return 0; -} - static int exynos7_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); @@ -820,35 +746,6 @@ static void exynos5433_tmu_control(struct platform_device *pdev, bool on) writel(con, data->base + EXYNOS_TMU_REG_CONTROL); } -static void exynos5440_tmu_control(struct platform_device *pdev, bool on) -{ - struct exynos_tmu_data *data = platform_get_drvdata(pdev); - struct thermal_zone_device *tz = data->tzd; - unsigned int con, interrupt_en; - - con = get_con_reg(data, readl(data->base + EXYNOS5440_TMU_S0_7_CTRL)); - - if (on) { - con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); - interrupt_en = - (of_thermal_is_trip_valid(tz, 3) - << EXYNOS5440_TMU_INTEN_RISE3_SHIFT) | - (of_thermal_is_trip_valid(tz, 2) - << EXYNOS5440_TMU_INTEN_RISE2_SHIFT) | - (of_thermal_is_trip_valid(tz, 1) - << EXYNOS5440_TMU_INTEN_RISE1_SHIFT) | - (of_thermal_is_trip_valid(tz, 0) - << EXYNOS5440_TMU_INTEN_RISE0_SHIFT); - interrupt_en |= - interrupt_en << EXYNOS5440_TMU_INTEN_FALL0_SHIFT; - } else { - con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); - interrupt_en = 0; /* Disable all interrupts */ - } - writel(interrupt_en, data->base + EXYNOS5440_TMU_S0_7_IRQEN); - writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL); -} - static void exynos7_tmu_control(struct platform_device *pdev, bool on) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); @@ -920,10 +817,8 @@ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val, if (temp) { temp /= MCELSIUS; - if (data->soc != SOC_ARCH_EXYNOS5440) { - val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT); - val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT); - } + val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT); + val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT); if (data->soc == SOC_ARCH_EXYNOS7) { val &= ~(EXYNOS7_EMUL_DATA_MASK << EXYNOS7_EMUL_DATA_SHIFT); @@ -964,16 +859,6 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data, writel(val, data->base + emul_con); } -static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data, - int temp) -{ - unsigned int val; - - val = readl(data->base + EXYNOS5440_TMU_S0_7_DEBUG); - val = get_emul_con_reg(data, val, temp); - writel(val, data->base + EXYNOS5440_TMU_S0_7_DEBUG); -} - static int exynos_tmu_set_emulation(void *drv_data, int temp) { struct exynos_tmu_data *data = drv_data; @@ -996,7 +881,6 @@ out: } #else #define exynos4412_tmu_set_emulation NULL -#define exynos5440_tmu_set_emulation NULL static int exynos_tmu_set_emulation(void *drv_data, int temp) { return -EINVAL; } #endif /* CONFIG_THERMAL_EMULATION */ @@ -1014,11 +898,6 @@ static int exynos4412_tmu_read(struct exynos_tmu_data *data) return readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP); } -static int exynos5440_tmu_read(struct exynos_tmu_data *data) -{ - return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP); -} - static int exynos7_tmu_read(struct exynos_tmu_data *data) { return readw(data->base + EXYNOS_TMU_REG_CURRENT_TEMP) & @@ -1029,16 +908,9 @@ static void exynos_tmu_work(struct work_struct *work) { struct exynos_tmu_data *data = container_of(work, struct exynos_tmu_data, irq_work); - unsigned int val_type; if (!IS_ERR(data->clk_sec)) clk_enable(data->clk_sec); - /* Find which sensor generated this interrupt */ - if (data->soc == SOC_ARCH_EXYNOS5440) { - val_type = readl(data->base_second + EXYNOS5440_TMU_IRQ_STATUS); - if (!((val_type >> data->id) & 0x1)) - goto out; - } if (!IS_ERR(data->clk_sec)) clk_disable(data->clk_sec); @@ -1051,7 +923,6 @@ static void exynos_tmu_work(struct work_struct *work) clk_disable(data->clk); mutex_unlock(&data->lock); -out: enable_irq(data->irq); } @@ -1086,15 +957,6 @@ static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data) writel(val_irq, data->base + tmu_intclear); } -static void exynos5440_tmu_clear_irqs(struct exynos_tmu_data *data) -{ - unsigned int val_irq; - - val_irq = readl(data->base + EXYNOS5440_TMU_S0_7_IRQ); - /* clear the interrupts */ - writel(val_irq, data->base + EXYNOS5440_TMU_S0_7_IRQ); -} - static irqreturn_t exynos_tmu_irq(int irq, void *id) { struct exynos_tmu_data *data = id; @@ -1130,9 +992,6 @@ static const struct of_device_id exynos_tmu_match[] = { }, { .compatible = "samsung,exynos5433-tmu", .data = (const void *)SOC_ARCH_EXYNOS5433, - }, { - .compatible = "samsung,exynos5440-tmu", - .data = (const void *)SOC_ARCH_EXYNOS5440, }, { .compatible = "samsung,exynos7-tmu", .data = (const void *)SOC_ARCH_EXYNOS7, @@ -1223,19 +1082,6 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->min_efuse_value = 40; data->max_efuse_value = 150; break; - case SOC_ARCH_EXYNOS5440: - data->tmu_initialize = exynos5440_tmu_initialize; - data->tmu_control = exynos5440_tmu_control; - data->tmu_read = exynos5440_tmu_read; - data->tmu_set_emulation = exynos5440_tmu_set_emulation; - data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; - data->ntrip = 4; - data->gain = 5; - data->reference_voltage = 16; - data->efuse_value = 0x5d2d; - data->min_efuse_value = 16; - data->max_efuse_value = 76; - break; case SOC_ARCH_EXYNOS7: data->tmu_initialize = exynos7_tmu_initialize; data->tmu_control = exynos7_tmu_control; @@ -1260,8 +1106,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) * Check if the TMU shares some registers and then try to map the * memory of common registers. */ - if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO && - data->soc != SOC_ARCH_EXYNOS5440) + if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO) return 0; if (of_address_to_resource(pdev->dev.of_node, 1, &res)) { From 8bfc218d0ebbabcba8ed2b8ec1831e0cf1f71629 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:16 +0200 Subject: [PATCH 24/50] thermal: exynos: fix setting rising_threshold for Exynos5433 Add missing clearing of the previous value when setting rising temperature threshold. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index cda716ce84be..523d26e2ee87 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -577,6 +577,7 @@ static int exynos5433_tmu_initialize(struct platform_device *pdev) threshold_code = temp_to_code(data, temp); rising_threshold = readl(data->base + rising_reg_offset); + rising_threshold &= ~(0xff << j * 8); rising_threshold |= (threshold_code << j * 8); writel(rising_threshold, data->base + rising_reg_offset); From 75e0f100774f84db43a1a14a3b6a8d3375bed321 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:17 +0200 Subject: [PATCH 25/50] thermal: exynos: always check for trips points existence * Check for trip points existence in exynos_tmu_initialize() so it is checked on all SoCs. * Use dev_err() instead of pr_err(). * Fix dev_err() to reference "device tree" not "of-thermal.c". * Remove no longer needed checks from exynos4210_tmu_initialize() and get_th_reg(). Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 523d26e2ee87..9e040ebece33 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -309,12 +309,6 @@ static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling) unsigned long temp; int i; - if (!trips) { - pr_err("%s: Cannot get trip points from of-thermal.c!\n", - __func__); - return 0; - } - for (i = 0; i < of_thermal_get_ntrips(tz); i++) { if (trips[i].type == THERMAL_TRIP_CRITICAL) continue; @@ -334,14 +328,23 @@ static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling) static int exynos_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); + struct thermal_zone_device *tzd = data->tzd; + const struct thermal_trip * const trips = + of_thermal_get_trip_points(tzd); int ret; - if (of_thermal_get_ntrips(data->tzd) > data->ntrip) { + if (!trips) { + dev_err(&pdev->dev, + "Cannot get trip points from device tree!\n"); + return -ENODEV; + } + + if (of_thermal_get_ntrips(tzd) > data->ntrip) { dev_info(&pdev->dev, "More trip points than supported by this TMU.\n"); dev_info(&pdev->dev, "%d trip points should be configured in polling mode.\n", - (of_thermal_get_ntrips(data->tzd) - data->ntrip)); + (of_thermal_get_ntrips(tzd) - data->ntrip)); } mutex_lock(&data->lock); @@ -397,13 +400,6 @@ static int exynos4210_tmu_initialize(struct platform_device *pdev) unsigned long reference, temp; unsigned int status; - if (!trips) { - pr_err("%s: Cannot get trip points from of-thermal.c!\n", - __func__); - ret = -ENODEV; - goto out; - } - status = readb(data->base + EXYNOS_TMU_REG_STATUS); if (!status) { ret = -EBUSY; From 8f1c404b212baec2f7cb46182a45067066aed131 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:18 +0200 Subject: [PATCH 26/50] thermal: exynos: always check for critical trip points existence * Check for critical trip point existence in exynos_tmu_initialize() so it is checked on all SoCs (except Exynos5433 for now). * Use dev_err() instead of pr_err(). * Fix dev_err() to reference "device tree" not "of-thermal.c". * Remove no longer needed check from exynos4412_tmu_initialize(). Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 9e040ebece33..a0c16044d20a 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -331,7 +331,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev) struct thermal_zone_device *tzd = data->tzd; const struct thermal_trip * const trips = of_thermal_get_trip_points(tzd); - int ret; + int ret = 0, temp; if (!trips) { dev_err(&pdev->dev, @@ -339,6 +339,14 @@ static int exynos_tmu_initialize(struct platform_device *pdev) return -ENODEV; } + if (data->soc != SOC_ARCH_EXYNOS5433) /* FIXME */ + ret = tzd->ops->get_crit_temp(tzd, &temp); + if (ret) { + dev_err(&pdev->dev, + "No CRITICAL trip point defined in device tree!\n"); + goto out; + } + if (of_thermal_get_ntrips(tzd) > data->ntrip) { dev_info(&pdev->dev, "More trip points than supported by this TMU.\n"); @@ -356,7 +364,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev) mutex_unlock(&data->lock); if (!IS_ERR(data->clk_sec)) clk_disable(data->clk_sec); - +out: return ret; } @@ -480,13 +488,6 @@ static int exynos4412_tmu_initialize(struct platform_device *pdev) } } - if (i == of_thermal_get_ntrips(data->tzd)) { - pr_err("%s: No CRITICAL trip point defined at of-thermal.c!\n", - __func__); - ret = -EINVAL; - goto out; - } - threshold_code = temp_to_code(data, crit_temp / MCELSIUS); /* 1-4 level to be assigned in th0 reg */ rising_threshold &= ~(0xff << 8 * i); From 97b3881b8bc5f49a276b5265539f244bf507f42d Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:19 +0200 Subject: [PATCH 27/50] thermal: exynos: check STATUS register in exynos_tmu_initialize() STATUS register is present on all SoCs so move its checking into exynos_tmu_initialize(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 45 ++++++++-------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index a0c16044d20a..3b41666b2f13 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -331,6 +331,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev) struct thermal_zone_device *tzd = data->tzd; const struct thermal_trip * const trips = of_thermal_get_trip_points(tzd); + unsigned int status; int ret = 0, temp; if (!trips) { @@ -359,7 +360,13 @@ static int exynos_tmu_initialize(struct platform_device *pdev) clk_enable(data->clk); if (!IS_ERR(data->clk_sec)) clk_enable(data->clk_sec); - ret = data->tmu_initialize(pdev); + + status = readb(data->base + EXYNOS_TMU_REG_STATUS); + if (!status) + ret = -EBUSY; + else + ret = data->tmu_initialize(pdev); + clk_disable(data->clk); mutex_unlock(&data->lock); if (!IS_ERR(data->clk_sec)) @@ -406,13 +413,6 @@ static int exynos4210_tmu_initialize(struct platform_device *pdev) of_thermal_get_trip_points(tz); int ret = 0, threshold_code, i; unsigned long reference, temp; - unsigned int status; - - status = readb(data->base + EXYNOS_TMU_REG_STATUS); - if (!status) { - ret = -EBUSY; - goto out; - } sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO)); @@ -441,16 +441,10 @@ static int exynos4412_tmu_initialize(struct platform_device *pdev) struct exynos_tmu_data *data = platform_get_drvdata(pdev); const struct thermal_trip * const trips = of_thermal_get_trip_points(data->tzd); - unsigned int status, trim_info, con, ctrl, rising_threshold; + unsigned int trim_info, con, ctrl, rising_threshold; int ret = 0, threshold_code, i; unsigned long crit_temp = 0; - status = readb(data->base + EXYNOS_TMU_REG_STATUS); - if (!status) { - ret = -EBUSY; - goto out; - } - if (data->soc == SOC_ARCH_EXYNOS3250 || data->soc == SOC_ARCH_EXYNOS4412 || data->soc == SOC_ARCH_EXYNOS5250) { @@ -497,7 +491,6 @@ static int exynos4412_tmu_initialize(struct platform_device *pdev) con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT); writel(con, data->base + EXYNOS_TMU_REG_CONTROL); -out: return ret; } @@ -505,17 +498,11 @@ static int exynos5433_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; - unsigned int status, trim_info; + unsigned int trim_info; unsigned int rising_threshold = 0, falling_threshold = 0; int temp, temp_hist; int ret = 0, threshold_code, i, sensor_id, cal_type; - status = readb(data->base + EXYNOS_TMU_REG_STATUS); - if (!status) { - ret = -EBUSY; - goto out; - } - trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); sanitize_temp_error(data, trim_info); @@ -590,7 +577,7 @@ static int exynos5433_tmu_initialize(struct platform_device *pdev) } data->tmu_clear_irqs(data); -out: + return ret; } @@ -598,18 +585,12 @@ static int exynos7_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; - unsigned int status, trim_info; + unsigned int trim_info; unsigned int rising_threshold = 0, falling_threshold = 0; int ret = 0, threshold_code, i; int temp, temp_hist; unsigned int reg_off, bit_off; - status = readb(data->base + EXYNOS_TMU_REG_STATUS); - if (!status) { - ret = -EBUSY; - goto out; - } - trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); data->temp_error1 = trim_info & EXYNOS7_TMU_TEMP_MASK; @@ -667,7 +648,7 @@ static int exynos7_tmu_initialize(struct platform_device *pdev) } data->tmu_clear_irqs(data); -out: + return ret; } From aef27b658b43aab1239f8eece52ce505fda0ffd4 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:20 +0200 Subject: [PATCH 28/50] thermal: exynos: use sanitize_temp_error() in exynos7_tmu_initialize() Fix sanitize_temp_error() to handle Exynos7 SoCs and then use it in exynos7_tmu_initialize(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 3b41666b2f13..5a648794b667 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -286,7 +286,11 @@ static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code) static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) { - data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK; + u16 tmu_temp_mask = + (data->soc == SOC_ARCH_EXYNOS7) ? EXYNOS7_TMU_TEMP_MASK + : EXYNOS_TMU_TEMP_MASK; + + data->temp_error1 = trim_info & tmu_temp_mask; data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) & EXYNOS_TMU_TEMP_MASK); @@ -592,12 +596,7 @@ static int exynos7_tmu_initialize(struct platform_device *pdev) unsigned int reg_off, bit_off; trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); - - data->temp_error1 = trim_info & EXYNOS7_TMU_TEMP_MASK; - if (!data->temp_error1 || - (data->min_efuse_value > data->temp_error1) || - (data->temp_error1 > data->max_efuse_value)) - data->temp_error1 = data->efuse_value & EXYNOS_TMU_TEMP_MASK; + sanitize_temp_error(data, trim_info); /* Write temperature code for rising and falling threshold */ for (i = (of_thermal_get_ntrips(tz) - 1); i >= 0; i--) { From 3c2651349bc66e4fd5a6949199a9e95fe0088f96 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:21 +0200 Subject: [PATCH 29/50] thermal: exynos: fix trips limit checking in get_th_reg() of_thermal_get_ntrips() may return value bigger than supported by a given SoC (i.e. on Exynos5422/5800) so fix the code to not iterate the loop for i values >= data->ntrip. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 5a648794b667..58cd68e9bc1c 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -311,9 +311,9 @@ static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling) const struct thermal_trip * const trips = of_thermal_get_trip_points(tz); unsigned long temp; - int i; + int i, ntrips = min_t(int, of_thermal_get_ntrips(tz), data->ntrip); - for (i = 0; i < of_thermal_get_ntrips(tz); i++) { + for (i = 0; i < ntrips; i++) { if (trips[i].type == THERMAL_TRIP_CRITICAL) continue; From 0a79ba5290eaeb0eeae0fc6f5add9cbbc76e69a9 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:22 +0200 Subject: [PATCH 30/50] thermal: exynos: remove threshold_code checking from exynos4210_tmu_initialize() On Exynos4210 one-point trimming is always used and data->temp_error1 is equal to 75. Therefore temp_to_code() will never return negative value for the reference temperature conversion. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 58cd68e9bc1c..26a0cb9fb2f4 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -423,10 +423,6 @@ static int exynos4210_tmu_initialize(struct platform_device *pdev) /* Write temperature code for threshold */ reference = trips[0].temperature / MCELSIUS; threshold_code = temp_to_code(data, reference); - if (threshold_code < 0) { - ret = threshold_code; - goto out; - } writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); for (i = 0; i < of_thermal_get_ntrips(tz); i++) { @@ -436,7 +432,7 @@ static int exynos4210_tmu_initialize(struct platform_device *pdev) } data->tmu_clear_irqs(data); -out: + return ret; } From c35268f589d545fb4da5f4231fdc6c523a3724d3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:23 +0200 Subject: [PATCH 31/50] thermal: exynos: make ->tmu_initialize method void All implementations of ->tmu_initialize always return 0 so make the method void and convert all implementations accordingly. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 26a0cb9fb2f4..44a426a607d1 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -220,7 +220,7 @@ struct exynos_tmu_data { unsigned int ntrip; bool enabled; - int (*tmu_initialize)(struct platform_device *pdev); + void (*tmu_initialize)(struct platform_device *pdev); void (*tmu_control)(struct platform_device *pdev, bool on); int (*tmu_read)(struct exynos_tmu_data *data); void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp); @@ -369,7 +369,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev) if (!status) ret = -EBUSY; else - ret = data->tmu_initialize(pdev); + data->tmu_initialize(pdev); clk_disable(data->clk); mutex_unlock(&data->lock); @@ -409,13 +409,13 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on) mutex_unlock(&data->lock); } -static int exynos4210_tmu_initialize(struct platform_device *pdev) +static void exynos4210_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; const struct thermal_trip * const trips = of_thermal_get_trip_points(tz); - int ret = 0, threshold_code, i; + int threshold_code, i; unsigned long reference, temp; sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO)); @@ -432,17 +432,15 @@ static int exynos4210_tmu_initialize(struct platform_device *pdev) } data->tmu_clear_irqs(data); - - return ret; } -static int exynos4412_tmu_initialize(struct platform_device *pdev) +static void exynos4412_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); const struct thermal_trip * const trips = of_thermal_get_trip_points(data->tzd); unsigned int trim_info, con, ctrl, rising_threshold; - int ret = 0, threshold_code, i; + int threshold_code, i; unsigned long crit_temp = 0; if (data->soc == SOC_ARCH_EXYNOS3250 || @@ -490,18 +488,16 @@ static int exynos4412_tmu_initialize(struct platform_device *pdev) con = readl(data->base + EXYNOS_TMU_REG_CONTROL); con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT); writel(con, data->base + EXYNOS_TMU_REG_CONTROL); - - return ret; } -static int exynos5433_tmu_initialize(struct platform_device *pdev) +static void exynos5433_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; unsigned int trim_info; unsigned int rising_threshold = 0, falling_threshold = 0; int temp, temp_hist; - int ret = 0, threshold_code, i, sensor_id, cal_type; + int threshold_code, i, sensor_id, cal_type; trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); sanitize_temp_error(data, trim_info); @@ -577,17 +573,15 @@ static int exynos5433_tmu_initialize(struct platform_device *pdev) } data->tmu_clear_irqs(data); - - return ret; } -static int exynos7_tmu_initialize(struct platform_device *pdev) +static void exynos7_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; unsigned int trim_info; unsigned int rising_threshold = 0, falling_threshold = 0; - int ret = 0, threshold_code, i; + int threshold_code, i; int temp, temp_hist; unsigned int reg_off, bit_off; @@ -643,8 +637,6 @@ static int exynos7_tmu_initialize(struct platform_device *pdev) } data->tmu_clear_irqs(data); - - return ret; } static void exynos4210_tmu_control(struct platform_device *pdev, bool on) From 736b11d1d37cd02f3ddd7072fa4fd8adb2fa245d Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:24 +0200 Subject: [PATCH 32/50] thermal: exynos: clear IRQs later in exynos4412_tmu_initialize() Clear IRQs after enabling thermal tripping (it should make no difference in driver operation). This prepares the driver code to moving IRQs clearing call from ->tmu_initialize method to exynos_tmu_initialize(). Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 44a426a607d1..1664d37ce84d 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -470,8 +470,6 @@ static void exynos4412_tmu_initialize(struct platform_device *pdev) writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE); writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL); - data->tmu_clear_irqs(data); - /* if last threshold limit is also present */ for (i = 0; i < of_thermal_get_ntrips(data->tzd); i++) { if (trips[i].type == THERMAL_TRIP_CRITICAL) { @@ -488,6 +486,8 @@ static void exynos4412_tmu_initialize(struct platform_device *pdev) con = readl(data->base + EXYNOS_TMU_REG_CONTROL); con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT); writel(con, data->base + EXYNOS_TMU_REG_CONTROL); + + data->tmu_clear_irqs(data); } static void exynos5433_tmu_initialize(struct platform_device *pdev) From fac36bac4b6f79e3f6e827fc0aaaee2c8b840d4a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:25 +0200 Subject: [PATCH 33/50] thermal: exynos: move IRQs clearing to exynos_tmu_initialize() Move ->tmu_clear_irqs call from ->tmu_initialize method to exynos_tmu_initialize(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 1664d37ce84d..46438b864002 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -366,10 +366,12 @@ static int exynos_tmu_initialize(struct platform_device *pdev) clk_enable(data->clk_sec); status = readb(data->base + EXYNOS_TMU_REG_STATUS); - if (!status) + if (!status) { ret = -EBUSY; - else + } else { data->tmu_initialize(pdev); + data->tmu_clear_irqs(data); + } clk_disable(data->clk); mutex_unlock(&data->lock); @@ -430,8 +432,6 @@ static void exynos4210_tmu_initialize(struct platform_device *pdev) writeb(temp - reference, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4); } - - data->tmu_clear_irqs(data); } static void exynos4412_tmu_initialize(struct platform_device *pdev) @@ -486,8 +486,6 @@ static void exynos4412_tmu_initialize(struct platform_device *pdev) con = readl(data->base + EXYNOS_TMU_REG_CONTROL); con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT); writel(con, data->base + EXYNOS_TMU_REG_CONTROL); - - data->tmu_clear_irqs(data); } static void exynos5433_tmu_initialize(struct platform_device *pdev) @@ -571,8 +569,6 @@ static void exynos5433_tmu_initialize(struct platform_device *pdev) falling_threshold |= (threshold_code << j * 8); writel(falling_threshold, data->base + falling_reg_offset); } - - data->tmu_clear_irqs(data); } static void exynos7_tmu_initialize(struct platform_device *pdev) @@ -635,8 +631,6 @@ static void exynos7_tmu_initialize(struct platform_device *pdev) writel(falling_threshold, data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off); } - - data->tmu_clear_irqs(data); } static void exynos4210_tmu_control(struct platform_device *pdev, bool on) From a503a10ff3d7b5998337693dd6f7547bf886201f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:26 +0200 Subject: [PATCH 34/50] thermal: exynos: add exynos*_tmu_set_[trip,hyst]() helpers Add exynos*_tmu_set_[trip,hyst]() helpers and convert all ->tmu_initialize implementations accordingly. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 280 +++++++++++++-------------- 1 file changed, 139 insertions(+), 141 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 46438b864002..91b8d12d43f7 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -305,30 +305,6 @@ static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info) EXYNOS_TMU_TEMP_MASK; } -static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling) -{ - struct thermal_zone_device *tz = data->tzd; - const struct thermal_trip * const trips = - of_thermal_get_trip_points(tz); - unsigned long temp; - int i, ntrips = min_t(int, of_thermal_get_ntrips(tz), data->ntrip); - - for (i = 0; i < ntrips; i++) { - if (trips[i].type == THERMAL_TRIP_CRITICAL) - continue; - - temp = trips[i].temperature / MCELSIUS; - if (falling) - temp -= (trips[i].hysteresis / MCELSIUS); - else - threshold &= ~(0xff << 8 * i); - - threshold |= temp_to_code(data, temp) << 8 * i; - } - - return threshold; -} - static int exynos_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); @@ -411,37 +387,79 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on) mutex_unlock(&data->lock); } +static void exynos4210_tmu_set_trip_temp(struct exynos_tmu_data *data, + int trip, u8 temp) +{ + const struct thermal_trip * const trips = + of_thermal_get_trip_points(data->tzd); + u8 ref, th_code; + + ref = trips[0].temperature / MCELSIUS; + + if (trip == 0) { + th_code = temp_to_code(data, ref); + writeb(th_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); + } + + temp -= ref; + writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip * 4); +} + static void exynos4210_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; const struct thermal_trip * const trips = of_thermal_get_trip_points(tz); - int threshold_code, i; - unsigned long reference, temp; + unsigned long temp; + int i; sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO)); - /* Write temperature code for threshold */ - reference = trips[0].temperature / MCELSIUS; - threshold_code = temp_to_code(data, reference); - writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP); - for (i = 0; i < of_thermal_get_ntrips(tz); i++) { temp = trips[i].temperature / MCELSIUS; - writeb(temp - reference, data->base + - EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4); + exynos4210_tmu_set_trip_temp(data, i, temp); } } +static void exynos4412_tmu_set_trip_temp(struct exynos_tmu_data *data, + int trip, u8 temp) +{ + u32 th, con; + + th = readl(data->base + EXYNOS_THD_TEMP_RISE); + th &= ~(0xff << 8 * trip); + th |= temp_to_code(data, temp) << 8 * trip; + writel(th, data->base + EXYNOS_THD_TEMP_RISE); + + if (trip == 3) { + con = readl(data->base + EXYNOS_TMU_REG_CONTROL); + con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT); + writel(con, data->base + EXYNOS_TMU_REG_CONTROL); + } +} + +static void exynos4412_tmu_set_trip_hyst(struct exynos_tmu_data *data, + int trip, u8 temp, u8 hyst) +{ + u32 th; + + th = readl(data->base + EXYNOS_THD_TEMP_FALL); + th &= ~(0xff << 8 * trip); + if (hyst) + th |= temp_to_code(data, temp - hyst) << 8 * trip; + writel(th, data->base + EXYNOS_THD_TEMP_FALL); +} + static void exynos4412_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); + struct thermal_zone_device *tz = data->tzd; const struct thermal_trip * const trips = - of_thermal_get_trip_points(data->tzd); - unsigned int trim_info, con, ctrl, rising_threshold; - int threshold_code, i; - unsigned long crit_temp = 0; + of_thermal_get_trip_points(tz); + unsigned long temp, hyst; + unsigned int trim_info, ctrl; + int i, ntrips = min_t(int, of_thermal_get_ntrips(tz), data->ntrip); if (data->soc == SOC_ARCH_EXYNOS3250 || data->soc == SOC_ARCH_EXYNOS4412 || @@ -465,27 +483,53 @@ static void exynos4412_tmu_initialize(struct platform_device *pdev) sanitize_temp_error(data, trim_info); /* Write temperature code for rising and falling threshold */ - rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE); - rising_threshold = get_th_reg(data, rising_threshold, false); - writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE); - writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL); + for (i = 0; i < ntrips; i++) { + temp = trips[i].temperature / MCELSIUS; + exynos4412_tmu_set_trip_temp(data, i, temp); - /* if last threshold limit is also present */ - for (i = 0; i < of_thermal_get_ntrips(data->tzd); i++) { - if (trips[i].type == THERMAL_TRIP_CRITICAL) { - crit_temp = trips[i].temperature; - break; - } + hyst = trips[i].hysteresis / MCELSIUS; + exynos4412_tmu_set_trip_hyst(data, i, temp, hyst); + } +} + +static void exynos5433_tmu_set_trip_temp(struct exynos_tmu_data *data, + int trip, u8 temp) +{ + unsigned int reg_off, j; + u32 th; + + if (trip > 3) { + reg_off = EXYNOS5433_THD_TEMP_RISE7_4; + j = trip - 4; + } else { + reg_off = EXYNOS5433_THD_TEMP_RISE3_0; + j = trip; } - threshold_code = temp_to_code(data, crit_temp / MCELSIUS); - /* 1-4 level to be assigned in th0 reg */ - rising_threshold &= ~(0xff << 8 * i); - rising_threshold |= threshold_code << 8 * i; - writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE); - con = readl(data->base + EXYNOS_TMU_REG_CONTROL); - con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT); - writel(con, data->base + EXYNOS_TMU_REG_CONTROL); + th = readl(data->base + reg_off); + th &= ~(0xff << j * 8); + th |= (temp_to_code(data, temp) << j * 8); + writel(th, data->base + reg_off); +} + +static void exynos5433_tmu_set_trip_hyst(struct exynos_tmu_data *data, + int trip, u8 temp, u8 hyst) +{ + unsigned int reg_off, j; + u32 th; + + if (trip > 3) { + reg_off = EXYNOS5433_THD_TEMP_FALL7_4; + j = trip - 4; + } else { + reg_off = EXYNOS5433_THD_TEMP_FALL3_0; + j = trip; + } + + th = readl(data->base + reg_off); + th &= ~(0xff << j * 8); + th |= (temp_to_code(data, temp - hyst) << j * 8); + writel(th, data->base + reg_off); } static void exynos5433_tmu_initialize(struct platform_device *pdev) @@ -493,9 +537,7 @@ static void exynos5433_tmu_initialize(struct platform_device *pdev) struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; unsigned int trim_info; - unsigned int rising_threshold = 0, falling_threshold = 0; - int temp, temp_hist; - int threshold_code, i, sensor_id, cal_type; + int sensor_id, cal_type, i, temp, hyst; trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); sanitize_temp_error(data, trim_info); @@ -525,111 +567,67 @@ static void exynos5433_tmu_initialize(struct platform_device *pdev) /* Write temperature code for rising and falling threshold */ for (i = 0; i < of_thermal_get_ntrips(tz); i++) { - int rising_reg_offset, falling_reg_offset; - int j = 0; - - switch (i) { - case 0: - case 1: - case 2: - case 3: - rising_reg_offset = EXYNOS5433_THD_TEMP_RISE3_0; - falling_reg_offset = EXYNOS5433_THD_TEMP_FALL3_0; - j = i; - break; - case 4: - case 5: - case 6: - case 7: - rising_reg_offset = EXYNOS5433_THD_TEMP_RISE7_4; - falling_reg_offset = EXYNOS5433_THD_TEMP_FALL7_4; - j = i - 4; - break; - default: - continue; - } - /* Write temperature code for rising threshold */ tz->ops->get_trip_temp(tz, i, &temp); temp /= MCELSIUS; - threshold_code = temp_to_code(data, temp); - - rising_threshold = readl(data->base + rising_reg_offset); - rising_threshold &= ~(0xff << j * 8); - rising_threshold |= (threshold_code << j * 8); - writel(rising_threshold, data->base + rising_reg_offset); + exynos5433_tmu_set_trip_temp(data, i, temp); /* Write temperature code for falling threshold */ - tz->ops->get_trip_hyst(tz, i, &temp_hist); - temp_hist = temp - (temp_hist / MCELSIUS); - threshold_code = temp_to_code(data, temp_hist); - - falling_threshold = readl(data->base + falling_reg_offset); - falling_threshold &= ~(0xff << j * 8); - falling_threshold |= (threshold_code << j * 8); - writel(falling_threshold, data->base + falling_reg_offset); + tz->ops->get_trip_hyst(tz, i, &hyst); + hyst /= MCELSIUS; + exynos5433_tmu_set_trip_hyst(data, i, temp, hyst); } } +static void exynos7_tmu_set_trip_temp(struct exynos_tmu_data *data, + int trip, u8 temp) +{ + unsigned int reg_off, bit_off; + u32 th; + + reg_off = ((7 - trip) / 2) * 4; + bit_off = ((8 - trip) % 2); + + th = readl(data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off); + th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off)); + th |= temp_to_code(data, temp) << (16 * bit_off); + writel(th, data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off); +} + +static void exynos7_tmu_set_trip_hyst(struct exynos_tmu_data *data, + int trip, u8 temp, u8 hyst) +{ + unsigned int reg_off, bit_off; + u32 th; + + reg_off = ((7 - trip) / 2) * 4; + bit_off = ((8 - trip) % 2); + + th = readl(data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off); + th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off)); + th |= temp_to_code(data, temp - hyst) << (16 * bit_off); + writel(th, data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off); +} + static void exynos7_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; unsigned int trim_info; - unsigned int rising_threshold = 0, falling_threshold = 0; - int threshold_code, i; - int temp, temp_hist; - unsigned int reg_off, bit_off; + int i, temp, hyst; trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); sanitize_temp_error(data, trim_info); /* Write temperature code for rising and falling threshold */ for (i = (of_thermal_get_ntrips(tz) - 1); i >= 0; i--) { - /* - * On exynos7 there are 4 rising and 4 falling threshold - * registers (0x50-0x5c and 0x60-0x6c respectively). Each - * register holds the value of two threshold levels (at bit - * offsets 0 and 16). Based on the fact that there are atmost - * eight possible trigger levels, calculate the register and - * bit offsets where the threshold levels are to be written. - * - * e.g. EXYNOS7_THD_TEMP_RISE7_6 (0x50) - * [24:16] - Threshold level 7 - * [8:0] - Threshold level 6 - * e.g. EXYNOS7_THD_TEMP_RISE5_4 (0x54) - * [24:16] - Threshold level 5 - * [8:0] - Threshold level 4 - * - * and similarly for falling thresholds. - * - * Based on the above, calculate the register and bit offsets - * for rising/falling threshold levels and populate them. - */ - reg_off = ((7 - i) / 2) * 4; - bit_off = ((8 - i) % 2); - tz->ops->get_trip_temp(tz, i, &temp); temp /= MCELSIUS; + exynos7_tmu_set_trip_temp(data, i, temp); - tz->ops->get_trip_hyst(tz, i, &temp_hist); - temp_hist = temp - (temp_hist / MCELSIUS); - - /* Set 9-bit temperature code for rising threshold levels */ - threshold_code = temp_to_code(data, temp); - rising_threshold = readl(data->base + - EXYNOS7_THD_TEMP_RISE7_6 + reg_off); - rising_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off)); - rising_threshold |= threshold_code << (16 * bit_off); - writel(rising_threshold, - data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off); - - /* Set 9-bit temperature code for falling threshold levels */ - threshold_code = temp_to_code(data, temp_hist); - falling_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off)); - falling_threshold |= threshold_code << (16 * bit_off); - writel(falling_threshold, - data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off); + tz->ops->get_trip_hyst(tz, i, &hyst); + hyst /= MCELSIUS; + exynos7_tmu_set_trip_hyst(data, i, temp, hyst); } } From ab1b7ada95c61a22a125c9ee5c75d32844b37d82 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:27 +0200 Subject: [PATCH 35/50] thermal: exynos: do not use trips structure directly in ->tmu_initialize Use ->get_trip_[temp,hyst] methods instead of using trips structure directly in all ->tmu_initialize method implementations. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 91b8d12d43f7..f24215a09a02 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -409,15 +409,13 @@ static void exynos4210_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; - const struct thermal_trip * const trips = - of_thermal_get_trip_points(tz); - unsigned long temp; - int i; + int i, temp; sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO)); for (i = 0; i < of_thermal_get_ntrips(tz); i++) { - temp = trips[i].temperature / MCELSIUS; + tz->ops->get_trip_temp(tz, i, &temp); + temp /= MCELSIUS; exynos4210_tmu_set_trip_temp(data, i, temp); } } @@ -455,11 +453,9 @@ static void exynos4412_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; - const struct thermal_trip * const trips = - of_thermal_get_trip_points(tz); - unsigned long temp, hyst; unsigned int trim_info, ctrl; int i, ntrips = min_t(int, of_thermal_get_ntrips(tz), data->ntrip); + int temp, hyst; if (data->soc == SOC_ARCH_EXYNOS3250 || data->soc == SOC_ARCH_EXYNOS4412 || @@ -484,10 +480,12 @@ static void exynos4412_tmu_initialize(struct platform_device *pdev) /* Write temperature code for rising and falling threshold */ for (i = 0; i < ntrips; i++) { - temp = trips[i].temperature / MCELSIUS; + tz->ops->get_trip_temp(tz, i, &temp); + temp /= MCELSIUS; exynos4412_tmu_set_trip_temp(data, i, temp); - hyst = trips[i].hysteresis / MCELSIUS; + tz->ops->get_trip_hyst(tz, i, &hyst); + hyst /= MCELSIUS; exynos4412_tmu_set_trip_hyst(data, i, temp, hyst); } } From 0c1554a6d868a89928c03be0be081f0249eb50f5 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:28 +0200 Subject: [PATCH 36/50] thermal: exynos: set trips in ascending order in exynos7_tmu_initialize() Set trips in ascending order in exynos7_tmu_initialize() (it should make no difference in driver operation). This prepares the driver code to moving trips setting from ->tmu_initialize method to exynos_tmu_initialize(). Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index f24215a09a02..1c6c335ad0ed 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -618,7 +618,7 @@ static void exynos7_tmu_initialize(struct platform_device *pdev) sanitize_temp_error(data, trim_info); /* Write temperature code for rising and falling threshold */ - for (i = (of_thermal_get_ntrips(tz) - 1); i >= 0; i--) { + for (i = 0; i < of_thermal_get_ntrips(tz); i++) { tz->ops->get_trip_temp(tz, i, &temp); temp /= MCELSIUS; exynos7_tmu_set_trip_temp(data, i, temp); From c8f8f7682e13d219699f6980cd0ba067f06d0dcf Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:29 +0200 Subject: [PATCH 37/50] thermal: exynos: move trips setting to exynos_tmu_initialize() * Add dummy exynos4210_tmu_set_trip_hyst() helper. * Add ->tmu_set_trip_temp and ->tmu_set_trip_hyst methods to struct exynos_tmu_data and set them in exynos_map_dt_data(). * Move trips setting to exynos_tmu_initialize(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 88 ++++++++++++---------------- 1 file changed, 37 insertions(+), 51 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 1c6c335ad0ed..8cb8601a80ca 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -220,6 +220,10 @@ struct exynos_tmu_data { unsigned int ntrip; bool enabled; + void (*tmu_set_trip_temp)(struct exynos_tmu_data *data, int trip, + u8 temp); + void (*tmu_set_trip_hyst)(struct exynos_tmu_data *data, int trip, + u8 temp, u8 hyst); void (*tmu_initialize)(struct platform_device *pdev); void (*tmu_control)(struct platform_device *pdev, bool on); int (*tmu_read)(struct exynos_tmu_data *data); @@ -312,7 +316,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev) const struct thermal_trip * const trips = of_thermal_get_trip_points(tzd); unsigned int status; - int ret = 0, temp; + int ret = 0, temp, hyst; if (!trips) { dev_err(&pdev->dev, @@ -345,7 +349,24 @@ static int exynos_tmu_initialize(struct platform_device *pdev) if (!status) { ret = -EBUSY; } else { + int i, ntrips = + min_t(int, of_thermal_get_ntrips(tzd), data->ntrip); + data->tmu_initialize(pdev); + + /* Write temperature code for rising and falling threshold */ + for (i = 0; i < ntrips; i++) { + /* Write temperature code for rising threshold */ + tzd->ops->get_trip_temp(tzd, i, &temp); + temp /= MCELSIUS; + data->tmu_set_trip_temp(data, i, temp); + + /* Write temperature code for falling threshold */ + tzd->ops->get_trip_hyst(tzd, i, &hyst); + hyst /= MCELSIUS; + data->tmu_set_trip_hyst(data, i, temp, hyst); + } + data->tmu_clear_irqs(data); } @@ -405,19 +426,17 @@ static void exynos4210_tmu_set_trip_temp(struct exynos_tmu_data *data, writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip * 4); } +/* failing thresholds are not supported on Exynos4210 */ +static void exynos4210_tmu_set_trip_hyst(struct exynos_tmu_data *data, + int trip, u8 temp, u8 hyst) +{ +} + static void exynos4210_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); - struct thermal_zone_device *tz = data->tzd; - int i, temp; sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO)); - - for (i = 0; i < of_thermal_get_ntrips(tz); i++) { - tz->ops->get_trip_temp(tz, i, &temp); - temp /= MCELSIUS; - exynos4210_tmu_set_trip_temp(data, i, temp); - } } static void exynos4412_tmu_set_trip_temp(struct exynos_tmu_data *data, @@ -452,10 +471,7 @@ static void exynos4412_tmu_set_trip_hyst(struct exynos_tmu_data *data, static void exynos4412_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); - struct thermal_zone_device *tz = data->tzd; unsigned int trim_info, ctrl; - int i, ntrips = min_t(int, of_thermal_get_ntrips(tz), data->ntrip); - int temp, hyst; if (data->soc == SOC_ARCH_EXYNOS3250 || data->soc == SOC_ARCH_EXYNOS4412 || @@ -477,17 +493,6 @@ static void exynos4412_tmu_initialize(struct platform_device *pdev) trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); sanitize_temp_error(data, trim_info); - - /* Write temperature code for rising and falling threshold */ - for (i = 0; i < ntrips; i++) { - tz->ops->get_trip_temp(tz, i, &temp); - temp /= MCELSIUS; - exynos4412_tmu_set_trip_temp(data, i, temp); - - tz->ops->get_trip_hyst(tz, i, &hyst); - hyst /= MCELSIUS; - exynos4412_tmu_set_trip_hyst(data, i, temp, hyst); - } } static void exynos5433_tmu_set_trip_temp(struct exynos_tmu_data *data, @@ -533,9 +538,8 @@ static void exynos5433_tmu_set_trip_hyst(struct exynos_tmu_data *data, static void exynos5433_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); - struct thermal_zone_device *tz = data->tzd; unsigned int trim_info; - int sensor_id, cal_type, i, temp, hyst; + int sensor_id, cal_type; trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); sanitize_temp_error(data, trim_info); @@ -562,19 +566,6 @@ static void exynos5433_tmu_initialize(struct platform_device *pdev) dev_info(&pdev->dev, "Calibration type is %d-point calibration\n", cal_type ? 2 : 1); - - /* Write temperature code for rising and falling threshold */ - for (i = 0; i < of_thermal_get_ntrips(tz); i++) { - /* Write temperature code for rising threshold */ - tz->ops->get_trip_temp(tz, i, &temp); - temp /= MCELSIUS; - exynos5433_tmu_set_trip_temp(data, i, temp); - - /* Write temperature code for falling threshold */ - tz->ops->get_trip_hyst(tz, i, &hyst); - hyst /= MCELSIUS; - exynos5433_tmu_set_trip_hyst(data, i, temp, hyst); - } } static void exynos7_tmu_set_trip_temp(struct exynos_tmu_data *data, @@ -610,23 +601,10 @@ static void exynos7_tmu_set_trip_hyst(struct exynos_tmu_data *data, static void exynos7_tmu_initialize(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); - struct thermal_zone_device *tz = data->tzd; unsigned int trim_info; - int i, temp, hyst; trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); sanitize_temp_error(data, trim_info); - - /* Write temperature code for rising and falling threshold */ - for (i = 0; i < of_thermal_get_ntrips(tz); i++) { - tz->ops->get_trip_temp(tz, i, &temp); - temp /= MCELSIUS; - exynos7_tmu_set_trip_temp(data, i, temp); - - tz->ops->get_trip_hyst(tz, i, &hyst); - hyst /= MCELSIUS; - exynos7_tmu_set_trip_hyst(data, i, temp, hyst); - } } static void exynos4210_tmu_control(struct platform_device *pdev, bool on) @@ -989,6 +967,8 @@ static int exynos_map_dt_data(struct platform_device *pdev) switch (data->soc) { case SOC_ARCH_EXYNOS4210: + data->tmu_set_trip_temp = exynos4210_tmu_set_trip_temp; + data->tmu_set_trip_hyst = exynos4210_tmu_set_trip_hyst; data->tmu_initialize = exynos4210_tmu_initialize; data->tmu_control = exynos4210_tmu_control; data->tmu_read = exynos4210_tmu_read; @@ -1006,6 +986,8 @@ static int exynos_map_dt_data(struct platform_device *pdev) case SOC_ARCH_EXYNOS5260: case SOC_ARCH_EXYNOS5420: case SOC_ARCH_EXYNOS5420_TRIMINFO: + data->tmu_set_trip_temp = exynos4412_tmu_set_trip_temp; + data->tmu_set_trip_hyst = exynos4412_tmu_set_trip_hyst; data->tmu_initialize = exynos4412_tmu_initialize; data->tmu_control = exynos4210_tmu_control; data->tmu_read = exynos4412_tmu_read; @@ -1023,6 +1005,8 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->max_efuse_value = 100; break; case SOC_ARCH_EXYNOS5433: + data->tmu_set_trip_temp = exynos5433_tmu_set_trip_temp; + data->tmu_set_trip_hyst = exynos5433_tmu_set_trip_hyst; data->tmu_initialize = exynos5433_tmu_initialize; data->tmu_control = exynos5433_tmu_control; data->tmu_read = exynos4412_tmu_read; @@ -1039,6 +1023,8 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->max_efuse_value = 150; break; case SOC_ARCH_EXYNOS7: + data->tmu_set_trip_temp = exynos7_tmu_set_trip_temp; + data->tmu_set_trip_hyst = exynos7_tmu_set_trip_hyst; data->tmu_initialize = exynos7_tmu_initialize; data->tmu_control = exynos7_tmu_control; data->tmu_read = exynos7_tmu_read; From 89335c203a8d45a9380c9fec4cdc8cda404569ad Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:30 +0200 Subject: [PATCH 38/50] thermal: exynos: check return values of ->get_trip_[temp, hyst] methods Check return values of ->get_trip_[temp,hyst] methods in exynos_tmu_initialize(). Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 8cb8601a80ca..ff72f71a0078 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -357,19 +357,23 @@ static int exynos_tmu_initialize(struct platform_device *pdev) /* Write temperature code for rising and falling threshold */ for (i = 0; i < ntrips; i++) { /* Write temperature code for rising threshold */ - tzd->ops->get_trip_temp(tzd, i, &temp); + ret = tzd->ops->get_trip_temp(tzd, i, &temp); + if (ret) + goto err; temp /= MCELSIUS; data->tmu_set_trip_temp(data, i, temp); /* Write temperature code for falling threshold */ - tzd->ops->get_trip_hyst(tzd, i, &hyst); + ret = tzd->ops->get_trip_hyst(tzd, i, &hyst); + if (ret) + goto err; hyst /= MCELSIUS; data->tmu_set_trip_hyst(data, i, temp, hyst); } data->tmu_clear_irqs(data); } - +err: clk_disable(data->clk); mutex_unlock(&data->lock); if (!IS_ERR(data->clk_sec)) From 64e94192451ea5810768797e002021950f671ae0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:31 +0200 Subject: [PATCH 39/50] thermal: exynos: cleanup code for enabling threshold interrupts Cleanup code for enabling threshold interrupts in ->tmu_control method implementations. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 98 ++++++++++------------------ 1 file changed, 33 insertions(+), 65 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index ff72f71a0078..f72b5ed15926 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -76,9 +76,6 @@ #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12 #define EXYNOS_TMU_INTEN_RISE0_SHIFT 0 -#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4 -#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8 -#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12 #define EXYNOS_TMU_INTEN_FALL0_SHIFT 16 #define EXYNOS_EMUL_TIME 0x57F0 @@ -136,13 +133,6 @@ #define EXYNOS7_TMU_TEMP_MASK 0x1ff #define EXYNOS7_PD_DET_EN_SHIFT 23 #define EXYNOS7_TMU_INTEN_RISE0_SHIFT 0 -#define EXYNOS7_TMU_INTEN_RISE1_SHIFT 1 -#define EXYNOS7_TMU_INTEN_RISE2_SHIFT 2 -#define EXYNOS7_TMU_INTEN_RISE3_SHIFT 3 -#define EXYNOS7_TMU_INTEN_RISE4_SHIFT 4 -#define EXYNOS7_TMU_INTEN_RISE5_SHIFT 5 -#define EXYNOS7_TMU_INTEN_RISE6_SHIFT 6 -#define EXYNOS7_TMU_INTEN_RISE7_SHIFT 7 #define EXYNOS7_EMUL_DATA_SHIFT 7 #define EXYNOS7_EMUL_DATA_MASK 0x1ff @@ -615,29 +605,28 @@ static void exynos4210_tmu_control(struct platform_device *pdev, bool on) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; - unsigned int con, interrupt_en; + unsigned int con, interrupt_en = 0, i; con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); if (on) { - con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); - interrupt_en = - (of_thermal_is_trip_valid(tz, 3) - << EXYNOS_TMU_INTEN_RISE3_SHIFT) | - (of_thermal_is_trip_valid(tz, 2) - << EXYNOS_TMU_INTEN_RISE2_SHIFT) | - (of_thermal_is_trip_valid(tz, 1) - << EXYNOS_TMU_INTEN_RISE1_SHIFT) | - (of_thermal_is_trip_valid(tz, 0) - << EXYNOS_TMU_INTEN_RISE0_SHIFT); + for (i = 0; i < data->ntrip; i++) { + if (!of_thermal_is_trip_valid(tz, i)) + continue; + + interrupt_en |= + (1 << (EXYNOS_TMU_INTEN_RISE0_SHIFT + i * 4)); + } if (data->soc != SOC_ARCH_EXYNOS4210) interrupt_en |= interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; + + con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); } else { con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); - interrupt_en = 0; /* Disable all interrupts */ } + writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN); writel(con, data->base + EXYNOS_TMU_REG_CONTROL); } @@ -646,36 +635,25 @@ static void exynos5433_tmu_control(struct platform_device *pdev, bool on) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; - unsigned int con, interrupt_en, pd_det_en; + unsigned int con, interrupt_en = 0, pd_det_en, i; con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); if (on) { - con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); - interrupt_en = - (of_thermal_is_trip_valid(tz, 7) - << EXYNOS7_TMU_INTEN_RISE7_SHIFT) | - (of_thermal_is_trip_valid(tz, 6) - << EXYNOS7_TMU_INTEN_RISE6_SHIFT) | - (of_thermal_is_trip_valid(tz, 5) - << EXYNOS7_TMU_INTEN_RISE5_SHIFT) | - (of_thermal_is_trip_valid(tz, 4) - << EXYNOS7_TMU_INTEN_RISE4_SHIFT) | - (of_thermal_is_trip_valid(tz, 3) - << EXYNOS7_TMU_INTEN_RISE3_SHIFT) | - (of_thermal_is_trip_valid(tz, 2) - << EXYNOS7_TMU_INTEN_RISE2_SHIFT) | - (of_thermal_is_trip_valid(tz, 1) - << EXYNOS7_TMU_INTEN_RISE1_SHIFT) | - (of_thermal_is_trip_valid(tz, 0) - << EXYNOS7_TMU_INTEN_RISE0_SHIFT); + for (i = 0; i < data->ntrip; i++) { + if (!of_thermal_is_trip_valid(tz, i)) + continue; + + interrupt_en |= + (1 << (EXYNOS7_TMU_INTEN_RISE0_SHIFT + i)); + } interrupt_en |= interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; - } else { + + con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); + } else con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); - interrupt_en = 0; /* Disable all interrupts */ - } pd_det_en = on ? EXYNOS5433_PD_DET_EN : 0; @@ -688,37 +666,27 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tz = data->tzd; - unsigned int con, interrupt_en; + unsigned int con, interrupt_en = 0, i; con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL)); if (on) { - con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); - con |= (1 << EXYNOS7_PD_DET_EN_SHIFT); - interrupt_en = - (of_thermal_is_trip_valid(tz, 7) - << EXYNOS7_TMU_INTEN_RISE7_SHIFT) | - (of_thermal_is_trip_valid(tz, 6) - << EXYNOS7_TMU_INTEN_RISE6_SHIFT) | - (of_thermal_is_trip_valid(tz, 5) - << EXYNOS7_TMU_INTEN_RISE5_SHIFT) | - (of_thermal_is_trip_valid(tz, 4) - << EXYNOS7_TMU_INTEN_RISE4_SHIFT) | - (of_thermal_is_trip_valid(tz, 3) - << EXYNOS7_TMU_INTEN_RISE3_SHIFT) | - (of_thermal_is_trip_valid(tz, 2) - << EXYNOS7_TMU_INTEN_RISE2_SHIFT) | - (of_thermal_is_trip_valid(tz, 1) - << EXYNOS7_TMU_INTEN_RISE1_SHIFT) | - (of_thermal_is_trip_valid(tz, 0) - << EXYNOS7_TMU_INTEN_RISE0_SHIFT); + for (i = 0; i < data->ntrip; i++) { + if (!of_thermal_is_trip_valid(tz, i)) + continue; + + interrupt_en |= + (1 << (EXYNOS7_TMU_INTEN_RISE0_SHIFT + i)); + } interrupt_en |= interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT; + + con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); + con |= (1 << EXYNOS7_PD_DET_EN_SHIFT); } else { con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); con &= ~(1 << EXYNOS7_PD_DET_EN_SHIFT); - interrupt_en = 0; /* Disable all interrupts */ } writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN); From 2b2426a72702b04fffe359bfbabeec4a4e41d9c7 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:32 +0200 Subject: [PATCH 40/50] thermal: exynos: remove unused defines for Exynos5433 Remove unused defines for Exynos5433. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index f72b5ed15926..223f9466dfb0 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -96,11 +96,6 @@ #define EXYNOS4412_MUX_ADDR_SHIFT 20 /* Exynos5433 specific registers */ -#define EXYNOS5433_TMU_REG_CONTROL1 0x024 -#define EXYNOS5433_TMU_SAMPLING_INTERVAL 0x02c -#define EXYNOS5433_TMU_COUNTER_VALUE0 0x030 -#define EXYNOS5433_TMU_COUNTER_VALUE1 0x034 -#define EXYNOS5433_TMU_REG_CURRENT_TEMP1 0x044 #define EXYNOS5433_THD_TEMP_RISE3_0 0x050 #define EXYNOS5433_THD_TEMP_RISE7_4 0x054 #define EXYNOS5433_THD_TEMP_FALL3_0 0x060 From b43e3cfe232ab01f7cf1f60179a1d005f62d6cc0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:33 +0200 Subject: [PATCH 41/50] thermal: exynos: remove trip reporting to user-space Remove trip reporting to user-space - I'm not aware of any user-space program which relies on it and there is a thermal user-space governor which does it in proper way nowadays. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 30 ++-------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 223f9466dfb0..3b20309789e3 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -216,33 +216,6 @@ struct exynos_tmu_data { void (*tmu_clear_irqs)(struct exynos_tmu_data *data); }; -static void exynos_report_trigger(struct exynos_tmu_data *p) -{ - char data[10], *envp[] = { data, NULL }; - struct thermal_zone_device *tz = p->tzd; - int temp; - unsigned int i; - - if (!tz) { - pr_err("No thermal zone device defined\n"); - return; - } - - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); - - mutex_lock(&tz->lock); - /* Find the level for which trip happened */ - for (i = 0; i < of_thermal_get_ntrips(tz); i++) { - tz->ops->get_trip_temp(tz, i, &temp); - if (tz->last_temperature < temp) - break; - } - - snprintf(data, sizeof(data), "%u", i); - kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, envp); - mutex_unlock(&tz->lock); -} - /* * TMU treats temperature as a mapped temperature code. * The temperature is converted differently depending on the calibration type. @@ -815,7 +788,8 @@ static void exynos_tmu_work(struct work_struct *work) if (!IS_ERR(data->clk_sec)) clk_disable(data->clk_sec); - exynos_report_trigger(data); + thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED); + mutex_lock(&data->lock); clk_enable(data->clk); From 9efc58dfa14a200efd5c005dd25ca95c686c1d8a Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Mon, 16 Apr 2018 10:34:16 +0800 Subject: [PATCH 42/50] thermal: mediatek: use of_device_get_match_data() The usage of of_device_get_match_data() reduce the code size a bit. Also, the only way to call mtk_thermal_probe() is to match an entry in mtk_thermal_of_match[], so of_id cannot be NULL. Signed-off-by: Ryder Lee Signed-off-by: Eduardo Valentin --- drivers/thermal/mtk_thermal.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index e709acb2235e..0691f260f6ea 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -677,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; @@ -685,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)) From 31db453bd4bd2aaf5385fc2dbeab256cfc343fee Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Sun, 20 May 2018 18:26:18 +0900 Subject: [PATCH 43/50] dt-bindings: thermal: rcar-thermal: add R8A77995 support Update rcar thermal dt-binding to add R8A77995 info. Signed-off-by: Yoshihiro Kaneko Reviewed-by: Geert Uytterhoeven Reviewed-by: Rob Herring Reviewed-by: Simon Horman Signed-off-by: Eduardo Valentin --- Documentation/devicetree/bindings/thermal/rcar-thermal.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt index 349e635f2d87..67c563f1b4c4 100644 --- a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt @@ -3,7 +3,8 @@ Required properties: - compatible : "renesas,thermal-", "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): From 1969d9dc2079e4b551712e9f0c1c69403aee9769 Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Sun, 20 May 2018 18:26:17 +0900 Subject: [PATCH 44/50] thermal: rcar_thermal: add r8a77995 support Add support for R-Car D3 (r8a77995) thermal sensor. Signed-off-by: Yoshihiro Kaneko Tested-by: Ulrich Hecht Reviewed-by: Simon Horman Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_thermal.c | 158 ++++++++++++++++++++++++++------- 1 file changed, 126 insertions(+), 32 deletions(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 73e5fee6cf1d..45fb284d4c11 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -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 @@ error_unregister: 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, From d86910b9141e16f2bbe38e53429f63f13569624b Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 2 May 2018 16:14:32 +0200 Subject: [PATCH 45/50] thermal: ti-soc-thermal: fix incorrect entry in omap5430_adc_to_temp[] Entry for Index 941 has one zero too much. Fix it. Signed-off-by: Bartlomiej Zolnierkiewicz Acked-by: Keerthy Signed-off-by: Eduardo Valentin --- drivers/thermal/ti-soc-thermal/omap5-thermal-data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c index cd9a304fb571..6ac037098b52 100644 --- a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c @@ -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 */ From 10c8251cce3380823c755a63f97cca432fcc4aec Mon Sep 17 00:00:00 2001 From: David Collins Date: Thu, 24 May 2018 12:49:02 +0530 Subject: [PATCH 46/50] thermal: qcom-spmi-temp-alarm: add support for GEN2 PMIC peripherals Add support for the TEMP_ALARM GEN2 PMIC peripheral subtype. The GEN2 subtype defines an over temperature state with hysteresis instead of stage in the status register. There are two GEN2 states corresponding to stages 1 and 2. Signed-off-by: David Collins Signed-off-by: Kiran Gunda Reviewed-by: Stephen Boyd Signed-off-by: Eduardo Valentin --- drivers/thermal/qcom-spmi-temp-alarm.c | 100 ++++++++++++++++++------- 1 file changed, 75 insertions(+), 25 deletions(-) diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom-spmi-temp-alarm.c index 95f987d5aa71..ad4f3a8d6560 100644 --- a/drivers/thermal/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom-spmi-temp-alarm.c @@ -1,5 +1,5 @@ /* - * 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 #include #include #include @@ -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,13 +93,14 @@ static int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 data) return regmap_write(chip->map, chip->base + addr, data); } -/* - * This function updates the internal temp value based on the - * current thermal stage and threshold as well as the previous stage +/** + * 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_update_temp_no_adc(struct qpnp_tm_chip *chip) +static int qpnp_tm_get_temp_stage(struct qpnp_tm_chip *chip) { - unsigned int stage; int ret; u8 reg = 0; @@ -98,16 +108,44 @@ static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip) if (ret < 0) return ret; - stage = reg & STATUS_STAGE_MASK; + if (chip->subtype == QPNP_TM_SUBTYPE_GEN1) + ret = reg & STATUS_GEN1_STAGE_MASK; + else + ret = (reg & STATUS_GEN2_STATE_MASK) >> STATUS_GEN2_STATE_SHIFT; - if (stage > chip->stage) { + 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, stage_new, stage_old; + int ret; + + ret = qpnp_tm_get_temp_stage(chip); + if (ret < 0) + return ret; + stage = ret; + + 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_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; - chip->temp = DEFAULT_TEMP; - - ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, ®); + ret = qpnp_tm_read(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, ®); if (ret < 0) return ret; - chip->stage = reg & STATUS_STAGE_MASK; + chip->thresh = reg & SHUTDOWN_CTRL1_THRESHOLD_MASK; + chip->temp = DEFAULT_TEMP; - if (chip->stage) + ret = qpnp_tm_get_temp_stage(chip); + if (ret < 0) + return ret; + chip->stage = ret; + + stage = chip->subtype == QPNP_TM_SUBTYPE_GEN1 + ? chip->stage : alarm_state_map[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"); From 45f8b0dde3c4e5445aebeb950de1dffacd94d4a6 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 23 May 2018 16:24:40 -0300 Subject: [PATCH 47/50] thermal: imx: Switch to SPDX identifier Adopt the SPDX license identifier headers to ease license compliance management. Signed-off-by: Fabio Estevam Signed-off-by: Eduardo Valentin --- drivers/thermal/imx_thermal.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index c30dc21c3b5d..334d98be03b9 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -1,11 +1,6 @@ -/* - * Copyright 2013 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2013 Freescale Semiconductor, Inc. #include #include From ffe6e16f14faf5af6bae7293ebddb481a1d77ae6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 13 May 2018 19:54:02 +0200 Subject: [PATCH 48/50] thermal: exynos: Reduce severity of too early temperature read Thermal core tries to read temperature during sensor registering in thermal_zone_of_sensor_register(). In that time Exynos TMU driver and hardware are not yet initialized. Commit 0eb875d88aaa ("thermal: exynos: Reading temperature makes sense only when TMU is turned on") added a boolean flag to prevent reading bogus temperature in such case but it exposed warning message during boot: [ 3.864913] thermal thermal_zone0: failed to read out thermal zone (-22) Return EAGAIN in such case to skip omitting such message because it might mislead user. Signed-off-by: Krzysztof Kozlowski Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Eduardo Valentin --- drivers/thermal/samsung/exynos_tmu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 3b20309789e3..c24969d740d1 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -666,8 +666,14 @@ static int exynos_get_temp(void *p, int *temp) struct exynos_tmu_data *data = p; int value, ret = 0; - if (!data || !data->tmu_read || !data->enabled) + if (!data || !data->tmu_read) return -EINVAL; + else if (!data->enabled) + /* + * Called too early, probably + * from thermal_zone_of_sensor_register(). + */ + return -EAGAIN; mutex_lock(&data->lock); clk_enable(data->clk); From cc50ba5e67da6dc7d554271470a566cc111e0456 Mon Sep 17 00:00:00 2001 From: srplinux2008 Date: Sat, 12 May 2018 23:17:08 +0530 Subject: [PATCH 49/50] thermal: tegra: soctherm: add const to struct thermal_cooling_device_ops Correct the typecast with const to struct thermal_cooling_device_ops. It is the last argument to the function thermal_of_cooling_device_register and this argument is of type const. So, declare this structure thermal_cooling_device_ops as constant. Signed-off-by: sumeet p Acked-by: Thierry Reding Signed-off-by: Eduardo Valentin --- drivers/thermal/tegra/soctherm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 1f87bbe7618b..207a79838643 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -901,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, From 6d7c70d1cd6526dc79e3d3b3faae1c40c1681168 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 7 May 2018 16:53:39 -0700 Subject: [PATCH 50/50] thermal: qcom: tsens: Allow number of sensors to come from DT For platforms that has multiple copies of the TSENS hardware block it's necessary to be able to specify the number of sensors per block in DeviceTree. Signed-off-by: Bjorn Andersson Reviewed-by: Amit Kucheria Reviewed-by: Rob Herring Signed-off-by: Eduardo Valentin --- .../devicetree/bindings/thermal/qcom-tsens.txt | 1 + drivers/thermal/qcom/tsens.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt index 292ed89d900b..06195e8f35e2 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt @@ -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 diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 3f9fe6aa51cc..20f3b87d7667 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -116,6 +116,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; @@ -130,18 +131,23 @@ 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, sizeof(*tmdev) + - data->num_sensors * sizeof(*s), GFP_KERNEL); + num_sensors * sizeof(*s), 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)