Commit 02be6059 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge tag 'thermal-v6.3-rc1' of...

Merge tag 'thermal-v6.3-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux into thermal-next

Pull thermal control material for 6.3-rc1 from Daniel Lezcano:

"- Fix kerneldoc format errors for Rockchip, Mediatek and Uniphier
   (Randy Dunlap)

 - Add the missing 'qcom,adc-tm7' compatible string in the dt-bindings
   (Krzysztof Kozlowski)

 - Improve the calibration routine by relying on the nvmem to read the
   values and provide a set of fixes for the QCom tsens driver (Dmitry
   Baryshkov)

 - Remove the duplicate interrupt setting routine in the QCom tsens
   driver (Daniel Lezcano)

 - Fix a wrong loop condition in the i.MX SC thermal driver and add the
   iMX8QM sensors (Viorel Suman)

 - Fix header inclusion asm-generic.h by asm.h for the
   qcom-spmi-adc-tm5 driver (Andy Shevchenko)

 - Use the devm_platform_get_and_ioremap_resource() combo function in
   all the drivers where the conversion applies (Ye Xingchen)

 - Replace a literal mask by an existing corresponding macro (Yangtao
   Li)

 - Add support for MT7986 and MT7981 (Daniel Golle)

 - Use thermal_zone_get_crit_temp() for the Armada thermal driver
   (Daniel Lezcano)"

* tag 'thermal-v6.3-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux: (35 commits)
  thermal/drivers/armada: Use the thermal_zone_get_crit_temp()
  thermal/drivers/mtk: Add support for MT7986 and MT7981
  thermal/drivers/mtk: Use function pointer for raw_to_mcelsius
  thermal/drivers/sun8i: Convert to use macro
  thermal/drivers/spear: Use devm_platform_get_and_ioremap_resource()
  thermal/drivers/kirkwood: Use devm_platform_get_and_ioremap_resource()
  thermal/drivers/thermal_mmio: Use devm_platform_get_and_ioremap_resource()
  thermal/drivers/rockchip: Use devm_platform_get_and_ioremap_resource()
  thermal/drivers/mtk_thermal: Use devm_platform_get_and_ioremap_resource()
  thermal/drivers/armada: Use devm_platform_get_and_ioremap_resource()
  thermal/drivers/dove: Use devm_platform_get_and_ioremap_resource()
  thermal/drivers/bcm2835: Use devm_platform_get_and_ioremap_resource()
  thermal/drivers/brcmstb_thermal: Use devm_platform_get_and_ioremap_resource()
  thermal/drivers/qcom-spmi-adc-tm5: Use asm intead of asm-generic
  thermal/drivers/imx_sc_thermal: Add iMX8QM sensors
  thermal/drivers/imx_sc_thermal: Fix the loop condition
  thermal/drivers/qcom: Remove duplicate set next trip point interrupt code
  thermal/drivers/tsens: Drop single-cell code for msm8976/msm8956
  thermal/drivers/tsens: Drop single-cell code for msm8939
  thermal/drivers/tsens: Drop single-cell code for mdm9607
  ...
parents a2c81dc5 8c5ee915
......@@ -13,6 +13,7 @@ properties:
enum:
- qcom,spmi-adc-tm5
- qcom,spmi-adc-tm5-gen2
- qcom,adc-tm7 # Incomplete / subject to change
reg:
maxItems: 1
......
......@@ -37,6 +37,7 @@ properties:
- description: v1 of TSENS
items:
- enum:
- qcom,msm8956-tsens
- qcom,msm8976-tsens
- qcom,qcs404-tsens
- const: qcom,tsens-v1
......@@ -80,18 +81,120 @@ properties:
maxItems: 2
nvmem-cells:
minItems: 1
maxItems: 2
description:
Reference to an nvmem node for the calibration data
oneOf:
- minItems: 1
maxItems: 2
description:
Reference to an nvmem node for the calibration data
- minItems: 5
maxItems: 35
description: |
Reference to nvmem cells for the calibration mode, two calibration
bases and two cells per each sensor
# special case for msm8974 / apq8084
- maxItems: 51
description: |
Reference to nvmem cells for the calibration mode, two calibration
bases and two cells per each sensor, main and backup copies, plus use_backup cell
nvmem-cell-names:
minItems: 1
items:
- const: calib
- enum:
- calib_backup
- calib_sel
oneOf:
- minItems: 1
items:
- const: calib
- enum:
- calib_backup
- calib_sel
- minItems: 5
items:
- const: mode
- const: base1
- const: base2
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
- pattern: '^s[0-9]+_p1$'
- pattern: '^s[0-9]+_p2$'
# special case for msm8974 / apq8084
- items:
- const: mode
- const: base1
- const: base2
- const: use_backup
- const: mode_backup
- const: base1_backup
- const: base2_backup
- const: s0_p1
- const: s0_p2
- const: s1_p1
- const: s1_p2
- const: s2_p1
- const: s2_p2
- const: s3_p1
- const: s3_p2
- const: s4_p1
- const: s4_p2
- const: s5_p1
- const: s5_p2
- const: s6_p1
- const: s6_p2
- const: s7_p1
- const: s7_p2
- const: s8_p1
- const: s8_p2
- const: s9_p1
- const: s9_p2
- const: s10_p1
- const: s10_p2
- const: s0_p1_backup
- const: s0_p2_backup
- const: s1_p1_backup
- const: s1_p2_backup
- const: s2_p1_backup
- const: s2_p2_backup
- const: s3_p1_backup
- const: s3_p2_backup
- const: s4_p1_backup
- const: s4_p2_backup
- const: s5_p1_backup
- const: s5_p2_backup
- const: s6_p1_backup
- const: s6_p2_backup
- const: s7_p1_backup
- const: s7_p2_backup
- const: s8_p1_backup
- const: s8_p2_backup
- const: s9_p1_backup
- const: s9_p2_backup
- const: s10_p1_backup
- const: s10_p2_backup
"#qcom,sensors":
description:
......@@ -220,6 +323,36 @@ examples:
};
};
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
// Example 1 (new calbiration data: for pre v1 IP):
thermal-sensor@900000 {
compatible = "qcom,msm8916-tsens", "qcom,tsens-v0_1";
reg = <0x4a9000 0x1000>, /* TM */
<0x4a8000 0x1000>; /* SROT */
nvmem-cells = <&tsens_mode>,
<&tsens_base1>, <&tsens_base2>,
<&tsens_s0_p1>, <&tsens_s0_p2>,
<&tsens_s1_p1>, <&tsens_s1_p2>,
<&tsens_s2_p1>, <&tsens_s2_p2>,
<&tsens_s4_p1>, <&tsens_s4_p2>,
<&tsens_s5_p1>, <&tsens_s5_p2>;
nvmem-cell-names = "mode",
"base1", "base2",
"s0_p1", "s0_p2",
"s1_p1", "s1_p2",
"s2_p1", "s2_p2",
"s4_p1", "s4_p2",
"s5_p1", "s5_p2";
interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "uplow";
#qcom,sensors = <5>;
#thermal-sensor-cells = <1>;
};
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
// Example 1 (legacy: for pre v1 IP):
......
......@@ -709,12 +709,10 @@ static int armada_thermal_probe_legacy(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
struct armada_thermal_data *data = priv->data;
struct resource *res;
void __iomem *base;
/* First memory region points towards the status register */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(base))
return PTR_ERR(base);
......@@ -784,34 +782,26 @@ static int armada_configure_overheat_int(struct armada_thermal_priv *priv,
int sensor_id)
{
/* Retrieve the critical trip point to enable the overheat interrupt */
struct thermal_trip trip;
int temperature;
int ret;
int i;
for (i = 0; i < thermal_zone_get_num_trips(tz); i++) {
ret = thermal_zone_get_trip(tz, i, &trip);
if (ret)
return ret;
if (trip.type != THERMAL_TRIP_CRITICAL)
continue;
ret = armada_select_channel(priv, sensor_id);
if (ret)
return ret;
armada_set_overheat_thresholds(priv, trip.temperature,
trip.hysteresis);
priv->overheat_sensor = tz;
priv->interrupt_source = sensor_id;
ret = thermal_zone_get_crit_temp(tz, &temperature);
if (ret)
return ret;
armada_enable_overheat_interrupt(priv);
ret = armada_select_channel(priv, sensor_id);
if (ret)
return ret;
return 0;
}
/*
* A critical temperature does not have a hysteresis
*/
armada_set_overheat_thresholds(priv, temperature, 0);
priv->overheat_sensor = tz;
priv->interrupt_source = sensor_id;
armada_enable_overheat_interrupt(priv);
return -EINVAL;
return 0;
}
static int armada_thermal_probe(struct platform_device *pdev)
......
......@@ -167,7 +167,6 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
const struct of_device_id *match;
struct thermal_zone_device *tz;
struct bcm2835_thermal_data *data;
struct resource *res;
int err = 0;
u32 val;
unsigned long rate;
......@@ -181,8 +180,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
if (!match)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->regs = devm_ioremap_resource(&pdev->dev, res);
data->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(data->regs)) {
err = PTR_ERR(data->regs);
return err;
......
......@@ -321,7 +321,6 @@ static int brcmstb_thermal_probe(struct platform_device *pdev)
const struct thermal_zone_device_ops *of_ops;
struct thermal_zone_device *thermal;
struct brcmstb_thermal_priv *priv;
struct resource *res;
int irq, ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
......@@ -332,8 +331,7 @@ static int brcmstb_thermal_probe(struct platform_device *pdev)
if (!priv->temp_params)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->tmon_base = devm_ioremap_resource(&pdev->dev, res);
priv->tmon_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(priv->tmon_base))
return PTR_ERR(priv->tmon_base);
......
......@@ -122,20 +122,17 @@ static int dove_thermal_probe(struct platform_device *pdev)
{
struct thermal_zone_device *thermal = NULL;
struct dove_thermal_priv *priv;
struct resource *res;
int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->sensor = devm_ioremap_resource(&pdev->dev, res);
priv->sensor = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(priv->sensor))
return PTR_ERR(priv->sensor);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
priv->control = devm_ioremap_resource(&pdev->dev, res);
priv->control = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);
if (IS_ERR(priv->control))
return PTR_ERR(priv->control);
......
......@@ -88,7 +88,7 @@ static int imx_sc_thermal_probe(struct platform_device *pdev)
if (!resource_id)
return -EINVAL;
for (i = 0; resource_id[i] > 0; i++) {
for (i = 0; resource_id[i] >= 0; i++) {
sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
if (!sensor)
......@@ -127,7 +127,11 @@ static int imx_sc_thermal_probe(struct platform_device *pdev)
return 0;
}
static int imx_sc_sensors[] = { IMX_SC_R_SYSTEM, IMX_SC_R_PMIC_0, -1 };
static const int imx_sc_sensors[] = {
IMX_SC_R_SYSTEM, IMX_SC_R_PMIC_0,
IMX_SC_R_AP_0, IMX_SC_R_AP_1,
IMX_SC_R_GPU_0_PID0, IMX_SC_R_GPU_1_PID0,
IMX_SC_R_DRC_0, -1 };
static const struct of_device_id imx_sc_thermal_table[] = {
{ .compatible = "fsl,imx-sc-thermal", .data = imx_sc_sensors },
......
......@@ -64,15 +64,13 @@ static int kirkwood_thermal_probe(struct platform_device *pdev)
{
struct thermal_zone_device *thermal = NULL;
struct kirkwood_thermal_priv *priv;
struct resource *res;
int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->sensor = devm_ioremap_resource(&pdev->dev, res);
priv->sensor = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(priv->sensor))
return PTR_ERR(priv->sensor);
......
......@@ -150,6 +150,20 @@
#define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1)
#define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1)
/*
* Layout of the fuses providing the calibration data
* These macros can be used for MT7981 and MT7986.
*/
#define CALIB_BUF0_ADC_GE_V3(x) (((x) >> 0) & 0x3ff)
#define CALIB_BUF0_DEGC_CALI_V3(x) (((x) >> 20) & 0x3f)
#define CALIB_BUF0_O_SLOPE_V3(x) (((x) >> 26) & 0x3f)
#define CALIB_BUF1_VTS_TS1_V3(x) (((x) >> 0) & 0x1ff)
#define CALIB_BUF1_VTS_TS2_V3(x) (((x) >> 21) & 0x1ff)
#define CALIB_BUF1_VTS_TSABB_V3(x) (((x) >> 9) & 0x1ff)
#define CALIB_BUF1_VALID_V3(x) (((x) >> 18) & 0x1)
#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1)
#define CALIB_BUF1_ID_V3(x) (((x) >> 20) & 0x1)
enum {
VTS1,
VTS2,
......@@ -163,6 +177,7 @@ enum {
enum mtk_thermal_version {
MTK_THERMAL_V1 = 1,
MTK_THERMAL_V2,
MTK_THERMAL_V3,
};
/* MT2701 thermal sensors */
......@@ -245,6 +260,27 @@ enum mtk_thermal_version {
/* The calibration coefficient of sensor */
#define MT8183_CALIBRATION 153
/* AUXADC channel 11 is used for the temperature sensors */
#define MT7986_TEMP_AUXADC_CHANNEL 11
/* The total number of temperature sensors in the MT7986 */
#define MT7986_NUM_SENSORS 1
/* The number of banks in the MT7986 */
#define MT7986_NUM_ZONES 1
/* The number of sensing points per bank */
#define MT7986_NUM_SENSORS_PER_ZONE 1
/* MT7986 thermal sensors */
#define MT7986_TS1 0
/* The number of controller in the MT7986 */
#define MT7986_NUM_CONTROLLER 1
/* The calibration coefficient of sensor */
#define MT7986_CALIBRATION 165
struct mtk_thermal;
struct thermal_bank_cfg {
......@@ -292,6 +328,8 @@ struct mtk_thermal {
const struct mtk_thermal_data *conf;
struct mtk_thermal_bank banks[MAX_NUM_ZONES];
int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
};
/* MT8183 thermal sensor data */
......@@ -386,6 +424,14 @@ static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, };
static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 };
static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, };
/* MT7986 thermal sensor data */
static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, };
static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, };
static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, };
static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, };
static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 };
static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, };
/*
* The MT8173 thermal controller has four banks. Each bank can read up to
* four temperature sensors simultaneously. The MT8173 has a total of 5
......@@ -549,8 +595,32 @@ static const struct mtk_thermal_data mt8183_thermal_data = {
.version = MTK_THERMAL_V1,
};
/*
* MT7986 uses AUXADC Channel 11 for raw data access.
*/
static const struct mtk_thermal_data mt7986_thermal_data = {
.auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL,
.num_banks = MT7986_NUM_ZONES,
.num_sensors = MT7986_NUM_SENSORS,
.vts_index = mt7986_vts_index,
.cali_val = MT7986_CALIBRATION,
.num_controller = MT7986_NUM_CONTROLLER,
.controller_offset = mt7986_tc_offset,
.need_switch_bank = true,
.bank_data = {
{
.num_sensors = 1,
.sensors = mt7986_bank_data,
},
},
.msr = mt7986_msr,
.adcpnp = mt7986_adcpnp,
.sensor_mux_values = mt7986_mux_values,
.version = MTK_THERMAL_V3,
};
/**
* raw_to_mcelsius - convert a raw ADC value to mcelsius
* raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius
* @mt: The thermal controller
* @sensno: sensor number
* @raw: raw ADC value
......@@ -603,6 +673,22 @@ static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw)
return (format_2 - tmp) * 100;
}
static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw)
{
s32 tmp;
if (raw == 0)
return 0;
raw &= 0xfff;
tmp = 100000 * 15 / 16 * 10000;
tmp /= 4096 - 512 + mt->adc_ge;
tmp /= 1490;
tmp *= raw - mt->vts[sensno] - 2900;
return mt->degc_cali * 500 - tmp;
}
/**
* mtk_thermal_get_bank - get bank
* @bank: The bank
......@@ -656,13 +742,9 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
raw = readl(mt->thermal_base + conf->msr[i]);
if (mt->conf->version == MTK_THERMAL_V1) {
temp = raw_to_mcelsius_v1(
mt, conf->bank_data[bank->id].sensors[i], raw);
} else {
temp = raw_to_mcelsius_v2(
mt, conf->bank_data[bank->id].sensors[i], raw);
}
temp = mt->raw_to_mcelsius(
mt, conf->bank_data[bank->id].sensors[i], raw);
/*
* The first read of a sensor often contains very high bogus
......@@ -887,6 +969,25 @@ static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf)
return 0;
}
static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf)
{
if (!CALIB_BUF1_VALID_V3(buf[1]))
return -EINVAL;
mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]);
mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]);
mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]);
mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]);
mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]);
mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]);
mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]);
if (CALIB_BUF1_ID_V3(buf[1]) == 0)
mt->o_slope = 0;
return 0;
}
static int mtk_thermal_get_calibration_data(struct device *dev,
struct mtk_thermal *mt)
{
......@@ -897,6 +998,7 @@ static int mtk_thermal_get_calibration_data(struct device *dev,
/* Start with default values */
mt->adc_ge = 512;
mt->adc_oe = 512;
for (i = 0; i < mt->conf->num_sensors; i++)
mt->vts[i] = 260;
mt->degc_cali = 40;
......@@ -922,10 +1024,20 @@ static int mtk_thermal_get_calibration_data(struct device *dev,
goto out;
}
if (mt->conf->version == MTK_THERMAL_V1)
switch (mt->conf->version) {
case MTK_THERMAL_V1:
ret = mtk_thermal_extract_efuse_v1(mt, buf);
else
break;
case MTK_THERMAL_V2:
ret = mtk_thermal_extract_efuse_v2(mt, buf);
break;
case MTK_THERMAL_V3:
ret = mtk_thermal_extract_efuse_v3(mt, buf);
break;
default:
ret = -EINVAL;
break;
}
if (ret) {
dev_info(dev, "Device not calibrated, using default calibration values\n");
......@@ -955,6 +1067,10 @@ static const struct of_device_id mtk_thermal_of_match[] = {
.compatible = "mediatek,mt7622-thermal",
.data = (void *)&mt7622_thermal_data,
},
{
.compatible = "mediatek,mt7986-thermal",
.data = (void *)&mt7986_thermal_data,
},
{
.compatible = "mediatek,mt8183-thermal",
.data = (void *)&mt8183_thermal_data,
......@@ -990,7 +1106,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
int ret, i, ctrl_id;
struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
struct mtk_thermal *mt;
struct resource *res;
u64 auxadc_phys_base, apmixed_phys_base;
struct thermal_zone_device *tzdev;
void __iomem *apmixed_base, *auxadc_base;
......@@ -1009,8 +1124,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
if (IS_ERR(mt->clk_auxadc))
return PTR_ERR(mt->clk_auxadc);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mt->thermal_base = devm_ioremap_resource(&pdev->dev, res);
mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(mt->thermal_base))
return PTR_ERR(mt->thermal_base);
......@@ -1070,11 +1184,18 @@ static int mtk_thermal_probe(struct platform_device *pdev)
goto err_disable_clk_auxadc;
}
if (mt->conf->version == MTK_THERMAL_V2) {
if (mt->conf->version != MTK_THERMAL_V1) {
mtk_thermal_turn_on_buffer(apmixed_base);
mtk_thermal_release_periodic_ts(mt, auxadc_base);
}
if (mt->conf->version == MTK_THERMAL_V1)
mt->raw_to_mcelsius = raw_to_mcelsius_v1;
else if (mt->conf->version == MTK_THERMAL_V2)
mt->raw_to_mcelsius = raw_to_mcelsius_v2;
else
mt->raw_to_mcelsius = raw_to_mcelsius_v3;
for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
for (i = 0; i < mt->conf->num_banks; i++)
mtk_thermal_init_bank(mt, i, apmixed_phys_base,
......
......@@ -18,7 +18,8 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/thermal.h>
#include <asm-generic/unaligned.h>
#include <asm/unaligned.h>
#include "../thermal_hwmon.h"
......
This diff is collapsed.
This diff is collapsed.
......@@ -70,6 +70,171 @@ char *qfprom_read(struct device *dev, const char *cname)
return ret;
}
int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2, bool backup)
{
u32 mode;
u32 base1, base2;
char name[] = "sXX_pY_backup"; /* s10_p1_backup */
int i, ret;
if (priv->num_sensors > MAX_SENSORS)
return -EINVAL;
ret = snprintf(name, sizeof(name), "mode%s", backup ? "_backup" : "");
if (ret < 0)
return ret;
ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &mode);
if (ret == -ENOENT)
dev_warn(priv->dev, "Please migrate to separate nvmem cells for calibration data\n");
if (ret < 0)
return ret;
dev_dbg(priv->dev, "calibration mode is %d\n", mode);
ret = snprintf(name, sizeof(name), "base1%s", backup ? "_backup" : "");
if (ret < 0)
return ret;
ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &base1);
if (ret < 0)
return ret;
ret = snprintf(name, sizeof(name), "base2%s", backup ? "_backup" : "");
if (ret < 0)
return ret;
ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &base2);
if (ret < 0)
return ret;
for (i = 0; i < priv->num_sensors; i++) {
ret = snprintf(name, sizeof(name), "s%d_p1%s", priv->sensor[i].hw_id,
backup ? "_backup" : "");
if (ret < 0)
return ret;
ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &p1[i]);
if (ret)
return ret;
ret = snprintf(name, sizeof(name), "s%d_p2%s", priv->sensor[i].hw_id,
backup ? "_backup" : "");
if (ret < 0)
return ret;
ret = nvmem_cell_read_variable_le_u32(priv->dev, name, &p2[i]);
if (ret)
return ret;
}
switch (mode) {
case ONE_PT_CALIB:
for (i = 0; i < priv->num_sensors; i++)
p1[i] = p1[i] + (base1 << shift);
break;
case TWO_PT_CALIB:
for (i = 0; i < priv->num_sensors; i++)
p2[i] = (p2[i] + base2) << shift;
fallthrough;
case ONE_PT_CALIB2:
for (i = 0; i < priv->num_sensors; i++)
p1[i] = (p1[i] + base1) << shift;
break;
default:
dev_dbg(priv->dev, "calibrationless mode\n");
for (i = 0; i < priv->num_sensors; i++) {
p1[i] = 500;
p2[i] = 780;
}
}
return mode;
}
int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift)
{
u32 p1[MAX_SENSORS], p2[MAX_SENSORS];
int mode;
mode = tsens_read_calibration(priv, shift, p1, p2, false);
if (mode < 0)
return mode;
compute_intercept_slope(priv, p1, p2, mode);
return 0;
}
int tsens_calibrate_common(struct tsens_priv *priv)
{
return tsens_calibrate_nvmem(priv, 2);
}
static u32 tsens_read_cell(const struct tsens_single_value *cell, u8 len, u32 *data0, u32 *data1)
{
u32 val;
u32 *data = cell->blob ? data1 : data0;
if (cell->shift + len <= 32) {
val = data[cell->idx] >> cell->shift;
} else {
u8 part = 32 - cell->shift;
val = data[cell->idx] >> cell->shift;
val |= data[cell->idx + 1] << part;
}
return val & ((1 << len) - 1);
}
int tsens_read_calibration_legacy(struct tsens_priv *priv,
const struct tsens_legacy_calibration_format *format,
u32 *p1, u32 *p2,
u32 *cdata0, u32 *cdata1)
{
u32 mode, invalid;
u32 base1, base2;
int i;
mode = tsens_read_cell(&format->mode, 2, cdata0, cdata1);
invalid = tsens_read_cell(&format->invalid, 1, cdata0, cdata1);
if (invalid)
mode = NO_PT_CALIB;
dev_dbg(priv->dev, "calibration mode is %d\n", mode);
base1 = tsens_read_cell(&format->base[0], format->base_len, cdata0, cdata1);
base2 = tsens_read_cell(&format->base[1], format->base_len, cdata0, cdata1);
for (i = 0; i < priv->num_sensors; i++) {
p1[i] = tsens_read_cell(&format->sp[i][0], format->sp_len, cdata0, cdata1);
p2[i] = tsens_read_cell(&format->sp[i][1], format->sp_len, cdata0, cdata1);
}
switch (mode) {
case ONE_PT_CALIB:
for (i = 0; i < priv->num_sensors; i++)
p1[i] = p1[i] + (base1 << format->base_shift);
break;
case TWO_PT_CALIB:
for (i = 0; i < priv->num_sensors; i++)
p2[i] = (p2[i] + base2) << format->base_shift;
fallthrough;
case ONE_PT_CALIB2:
for (i = 0; i < priv->num_sensors; i++)
p1[i] = (p1[i] + base1) << format->base_shift;
break;
default:
dev_dbg(priv->dev, "calibrationless mode\n");
for (i = 0; i < priv->num_sensors; i++) {
p1[i] = 500;
p2[i] = 780;
}
}
return mode;
}
/*
* Use this function on devices where slope and offset calculations
* depend on calibration data read from qfprom. On others the slope
......@@ -459,12 +624,9 @@ static irqreturn_t tsens_irq_thread(int irq, void *data)
{
struct tsens_priv *priv = data;
struct tsens_irq_data d;
bool enable = true, disable = false;
unsigned long flags;
int temp, ret, i;
int i;
for (i = 0; i < priv->num_sensors; i++) {
bool trigger = false;
const struct tsens_sensor *s = &priv->sensor[i];
u32 hw_id = s->hw_id;
......@@ -472,52 +634,8 @@ static irqreturn_t tsens_irq_thread(int irq, void *data)
continue;
if (!tsens_threshold_violated(priv, hw_id, &d))
continue;
ret = get_temp_tsens_valid(s, &temp);
if (ret) {
dev_err(priv->dev, "[%u] %s: error reading sensor\n",
hw_id, __func__);
continue;
}
spin_lock_irqsave(&priv->ul_lock, flags);
tsens_read_irq_state(priv, hw_id, s, &d);
if (d.up_viol &&
!masked_irq(hw_id, d.up_irq_mask, tsens_version(priv))) {
tsens_set_interrupt(priv, hw_id, UPPER, disable);
if (d.up_thresh > temp) {
dev_dbg(priv->dev, "[%u] %s: re-arm upper\n",
hw_id, __func__);
tsens_set_interrupt(priv, hw_id, UPPER, enable);
} else {
trigger = true;
/* Keep irq masked */
}
} else if (d.low_viol &&
!masked_irq(hw_id, d.low_irq_mask, tsens_version(priv))) {
tsens_set_interrupt(priv, hw_id, LOWER, disable);
if (d.low_thresh < temp) {
dev_dbg(priv->dev, "[%u] %s: re-arm low\n",
hw_id, __func__);
tsens_set_interrupt(priv, hw_id, LOWER, enable);
} else {
trigger = true;
/* Keep irq masked */
}
}
spin_unlock_irqrestore(&priv->ul_lock, flags);
if (trigger) {
dev_dbg(priv->dev, "[%u] %s: TZ update trigger (%d mC)\n",
hw_id, __func__, temp);
thermal_zone_device_update(s->tzd,
THERMAL_EVENT_UNSPECIFIED);
} else {
dev_dbg(priv->dev, "[%u] %s: no violation: %d\n",
hw_id, __func__, temp);
}
thermal_zone_device_update(s->tzd, THERMAL_EVENT_UNSPECIFIED);
if (tsens_version(priv) < VER_0_1) {
/* Constraint: There is only 1 interrupt control register for all
......@@ -983,6 +1101,9 @@ static const struct of_device_id tsens_table[] = {
}, {
.compatible = "qcom,msm8939-tsens",
.data = &data_8939,
}, {
.compatible = "qcom,msm8956-tsens",
.data = &data_8956,
}, {
.compatible = "qcom,msm8960-tsens",
.data = &data_8960,
......
......@@ -6,6 +6,7 @@
#ifndef __QCOM_TSENS_H__
#define __QCOM_TSENS_H__
#define NO_PT_CALIB 0x0
#define ONE_PT_CALIB 0x1
#define ONE_PT_CALIB2 0x2
#define TWO_PT_CALIB 0x3
......@@ -17,6 +18,8 @@
#define THRESHOLD_MAX_ADC_CODE 0x3ff
#define THRESHOLD_MIN_ADC_CODE 0x0
#define MAX_SENSORS 16
#include <linux/interrupt.h>
#include <linux/thermal.h>
#include <linux/regmap.h>
......@@ -581,7 +584,48 @@ struct tsens_priv {
struct tsens_sensor sensor[];
};
/**
* struct tsens_single_value - internal representation of a single field inside nvmem calibration data
* @idx: index into the u32 data array
* @shift: the shift of the first bit in the value
* @blob: index of the data blob to use for this cell
*/
struct tsens_single_value {
u8 idx;
u8 shift;
u8 blob;
};
/**
* struct tsens_legacy_calibration_format - description of calibration data used when parsing the legacy nvmem blob
* @base_len: the length of the base fields inside calibration data
* @base_shift: the shift to be applied to base data
* @sp_len: the length of the sN_pM fields inside calibration data
* @mode: descriptor of the calibration mode field
* @invalid: descriptor of the calibration mode invalid field
* @base: descriptors of the base0 and base1 fields
* @sp: descriptors of the sN_pM fields
*/
struct tsens_legacy_calibration_format {
unsigned int base_len;
unsigned int base_shift;
unsigned int sp_len;
/* just two bits */
struct tsens_single_value mode;
/* on all platforms except 8974 invalid is the third bit of what downstream calls 'mode' */
struct tsens_single_value invalid;
struct tsens_single_value base[2];
struct tsens_single_value sp[][2];
};
char *qfprom_read(struct device *dev, const char *cname);
int tsens_read_calibration_legacy(struct tsens_priv *priv,
const struct tsens_legacy_calibration_format *format,
u32 *p1, u32 *p2,
u32 *cdata, u32 *csel);
int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2, bool backup);
int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift);
int tsens_calibrate_common(struct tsens_priv *priv);
void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode);
int init_common(struct tsens_priv *priv);
int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp);
......@@ -594,7 +638,7 @@ extern struct tsens_plat_data data_8960;
extern struct tsens_plat_data data_8916, data_8939, data_8974, data_9607;
/* TSENS v1 targets */
extern struct tsens_plat_data data_tsens_v1, data_8976;
extern struct tsens_plat_data data_tsens_v1, data_8976, data_8956;
/* TSENS v2 targets */
extern struct tsens_plat_data data_8996, data_ipq8074, data_tsens_v2;
......
......@@ -60,7 +60,7 @@ enum adc_sort_mode {
#include "thermal_hwmon.h"
/**
/*
* The max sensors is two in rockchip SoCs.
* Two sensors: CPU and GPU sensor.
*/
......@@ -169,7 +169,7 @@ struct rockchip_thermal_data {
enum tshut_polarity tshut_polarity;
};
/**
/*
* TSADC Sensor Register description:
*
* TSADCV2_* are used for RK3288 SoCs, the other chips can reuse it.
......@@ -1339,7 +1339,7 @@ rockchip_thermal_register_sensor(struct platform_device *pdev,
}
/**
* Reset TSADC Controller, reset all tsadc registers.
* rockchip_thermal_reset_controller - Reset TSADC Controller, reset all tsadc registers.
* @reset: the reset controller of tsadc
*/
static void rockchip_thermal_reset_controller(struct reset_control *reset)
......@@ -1354,7 +1354,6 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct rockchip_thermal_data *thermal;
const struct of_device_id *match;
struct resource *res;
int irq;
int i;
int error;
......@@ -1378,8 +1377,7 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
if (!thermal->chip)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
thermal->regs = devm_ioremap_resource(&pdev->dev, res);
thermal->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(thermal->regs))
return PTR_ERR(thermal->regs);
......
......@@ -91,7 +91,6 @@ static int spear_thermal_probe(struct platform_device *pdev)
struct thermal_zone_device *spear_thermal = NULL;
struct spear_thermal_dev *stdev;
struct device_node *np = pdev->dev.of_node;
struct resource *res;
int ret = 0, val;
if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) {
......@@ -104,8 +103,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
return -ENOMEM;
/* Enable thermal sensor */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
stdev->thermal_base = devm_ioremap_resource(&pdev->dev, res);
stdev->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(stdev->thermal_base))
return PTR_ERR(stdev->thermal_base);
......
......@@ -210,7 +210,7 @@ static int sun8i_h3_ths_calibrate(struct ths_device *tmdev,
regmap_update_bits(tmdev->regmap,
SUN8I_THS_TEMP_CALIB + (4 * (i >> 1)),
0xfff << offset,
TEMP_CALIB_MASK << offset,
caldata[i] << offset);
}
......@@ -271,7 +271,7 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
offset = (i % 2) * 16;
regmap_update_bits(tmdev->regmap,
SUN50I_H6_THS_TEMP_CALIB + (i / 2 * 4),
0xfff << offset,
TEMP_CALIB_MASK << offset,
cdata << offset);
}
......
......@@ -39,7 +39,6 @@ static const struct thermal_zone_device_ops thermal_mmio_ops = {
static int thermal_mmio_probe(struct platform_device *pdev)
{
struct resource *resource;
struct thermal_mmio *sensor;
int (*sensor_init_func)(struct platform_device *pdev,
struct thermal_mmio *sensor);
......@@ -51,8 +50,7 @@ static int thermal_mmio_probe(struct platform_device *pdev)
if (!sensor)
return -ENOMEM;
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sensor->mmio_base = devm_ioremap_resource(&pdev->dev, resource);
sensor->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(sensor->mmio_base))
return PTR_ERR(sensor->mmio_base);
......
// SPDX-License-Identifier: GPL-2.0
/**
/*
* uniphier_thermal.c - Socionext UniPhier thermal driver
* Copyright 2014 Panasonic Corporation
* Copyright 2016-2017 Socionext Inc.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment