diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2023-01-26 19:21:24 +0300 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2023-01-26 19:21:24 +0300 |
commit | 02be605946b64df6d328811eb2488f7a245a5206 (patch) | |
tree | 78d02dd9125d8aab2f5151a61688a160554b1951 /drivers/thermal | |
parent | a2c81dc59d41e92362ab7d41d0c15471ea50637d (diff) | |
parent | 8c5ee9155f8ae133070b40ee4be03cafb35c188d (diff) | |
download | linux-02be605946b64df6d328811eb2488f7a245a5206.tar.xz |
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
...
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/armada_thermal.c | 42 | ||||
-rw-r--r-- | drivers/thermal/broadcom/bcm2835_thermal.c | 4 | ||||
-rw-r--r-- | drivers/thermal/broadcom/brcmstb_thermal.c | 4 | ||||
-rw-r--r-- | drivers/thermal/dove_thermal.c | 7 | ||||
-rw-r--r-- | drivers/thermal/imx_sc_thermal.c | 8 | ||||
-rw-r--r-- | drivers/thermal/kirkwood_thermal.c | 4 | ||||
-rw-r--r-- | drivers/thermal/mtk_thermal.c | 149 | ||||
-rw-r--r-- | drivers/thermal/qcom/qcom-spmi-adc-tm5.c | 3 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-v0_1.c | 655 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens-v1.c | 340 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens.c | 219 | ||||
-rw-r--r-- | drivers/thermal/qcom/tsens.h | 46 | ||||
-rw-r--r-- | drivers/thermal/rockchip_thermal.c | 10 | ||||
-rw-r--r-- | drivers/thermal/spear_thermal.c | 4 | ||||
-rw-r--r-- | drivers/thermal/sun8i_thermal.c | 4 | ||||
-rw-r--r-- | drivers/thermal/thermal_mmio.c | 4 | ||||
-rw-r--r-- | drivers/thermal/uniphier_thermal.c | 2 |
17 files changed, 656 insertions, 849 deletions
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index db040dbdaa0a..99e86484a55c 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -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) diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c index 5485e59d03a9..3d0710c6e004 100644 --- a/drivers/thermal/broadcom/bcm2835_thermal.c +++ b/drivers/thermal/broadcom/bcm2835_thermal.c @@ -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; diff --git a/drivers/thermal/broadcom/brcmstb_thermal.c b/drivers/thermal/broadcom/brcmstb_thermal.c index c79c6cfdd74d..4d02c28331e3 100644 --- a/drivers/thermal/broadcom/brcmstb_thermal.c +++ b/drivers/thermal/broadcom/brcmstb_thermal.c @@ -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); diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c index 73182eb94bc0..056622a58d00 100644 --- a/drivers/thermal/dove_thermal.c +++ b/drivers/thermal/dove_thermal.c @@ -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); diff --git a/drivers/thermal/imx_sc_thermal.c b/drivers/thermal/imx_sc_thermal.c index 4df925e3a80b..378f574607f7 100644 --- a/drivers/thermal/imx_sc_thermal.c +++ b/drivers/thermal/imx_sc_thermal.c @@ -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 }, diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c index 7fb6e476c82a..bec7ec20e79d 100644 --- a/drivers/thermal/kirkwood_thermal.c +++ b/drivers/thermal/kirkwood_thermal.c @@ -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); diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 8440692e3890..3c633584a88e 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -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"); @@ -956,6 +1068,10 @@ static const struct of_device_id mtk_thermal_of_match[] = { .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, diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c index ff47fc9ac9c5..31164ade2dd1 100644 --- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c +++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c @@ -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" diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c index 04d012e4f728..e89c6f39a3ae 100644 --- a/drivers/thermal/qcom/tsens-v0_1.c +++ b/drivers/thermal/qcom/tsens-v0_1.c @@ -3,6 +3,8 @@ * Copyright (c) 2015, The Linux Foundation. All rights reserved. */ +#include <linux/bitfield.h> +#include <linux/nvmem-consumer.h> #include <linux/platform_device.h> #include "tsens.h" @@ -15,220 +17,117 @@ #define TM_Sn_STATUS_OFF 0x0030 #define TM_TRDY_OFF 0x005c -/* eeprom layout data for 8916 */ -#define MSM8916_BASE0_MASK 0x0000007f -#define MSM8916_BASE1_MASK 0xfe000000 -#define MSM8916_BASE0_SHIFT 0 -#define MSM8916_BASE1_SHIFT 25 - -#define MSM8916_S0_P1_MASK 0x00000f80 -#define MSM8916_S1_P1_MASK 0x003e0000 -#define MSM8916_S2_P1_MASK 0xf8000000 -#define MSM8916_S3_P1_MASK 0x000003e0 -#define MSM8916_S4_P1_MASK 0x000f8000 - -#define MSM8916_S0_P2_MASK 0x0001f000 -#define MSM8916_S1_P2_MASK 0x07c00000 -#define MSM8916_S2_P2_MASK 0x0000001f -#define MSM8916_S3_P2_MASK 0x00007c00 -#define MSM8916_S4_P2_MASK 0x01f00000 - -#define MSM8916_S0_P1_SHIFT 7 -#define MSM8916_S1_P1_SHIFT 17 -#define MSM8916_S2_P1_SHIFT 27 -#define MSM8916_S3_P1_SHIFT 5 -#define MSM8916_S4_P1_SHIFT 15 - -#define MSM8916_S0_P2_SHIFT 12 -#define MSM8916_S1_P2_SHIFT 22 -#define MSM8916_S2_P2_SHIFT 0 -#define MSM8916_S3_P2_SHIFT 10 -#define MSM8916_S4_P2_SHIFT 20 - -#define MSM8916_CAL_SEL_MASK 0xe0000000 -#define MSM8916_CAL_SEL_SHIFT 29 - -/* eeprom layout data for 8939 */ -#define MSM8939_BASE0_MASK 0x000000ff -#define MSM8939_BASE1_MASK 0xff000000 -#define MSM8939_BASE0_SHIFT 0 -#define MSM8939_BASE1_SHIFT 24 - -#define MSM8939_S0_P1_MASK 0x000001f8 -#define MSM8939_S1_P1_MASK 0x001f8000 -#define MSM8939_S2_P1_MASK_0_4 0xf8000000 -#define MSM8939_S2_P1_MASK_5 0x00000001 -#define MSM8939_S3_P1_MASK 0x00001f80 -#define MSM8939_S4_P1_MASK 0x01f80000 -#define MSM8939_S5_P1_MASK 0x00003f00 -#define MSM8939_S6_P1_MASK 0x03f00000 -#define MSM8939_S7_P1_MASK 0x0000003f -#define MSM8939_S8_P1_MASK 0x0003f000 -#define MSM8939_S9_P1_MASK 0x07e00000 - -#define MSM8939_S0_P2_MASK 0x00007e00 -#define MSM8939_S1_P2_MASK 0x07e00000 -#define MSM8939_S2_P2_MASK 0x0000007e -#define MSM8939_S3_P2_MASK 0x0007e000 -#define MSM8939_S4_P2_MASK 0x7e000000 -#define MSM8939_S5_P2_MASK 0x000fc000 -#define MSM8939_S6_P2_MASK 0xfc000000 -#define MSM8939_S7_P2_MASK 0x00000fc0 -#define MSM8939_S8_P2_MASK 0x00fc0000 -#define MSM8939_S9_P2_MASK_0_4 0xf8000000 -#define MSM8939_S9_P2_MASK_5 0x00002000 - -#define MSM8939_S0_P1_SHIFT 3 -#define MSM8939_S1_P1_SHIFT 15 -#define MSM8939_S2_P1_SHIFT_0_4 27 -#define MSM8939_S2_P1_SHIFT_5 0 -#define MSM8939_S3_P1_SHIFT 7 -#define MSM8939_S4_P1_SHIFT 19 -#define MSM8939_S5_P1_SHIFT 8 -#define MSM8939_S6_P1_SHIFT 20 -#define MSM8939_S7_P1_SHIFT 0 -#define MSM8939_S8_P1_SHIFT 12 -#define MSM8939_S9_P1_SHIFT 21 - -#define MSM8939_S0_P2_SHIFT 9 -#define MSM8939_S1_P2_SHIFT 21 -#define MSM8939_S2_P2_SHIFT 1 -#define MSM8939_S3_P2_SHIFT 13 -#define MSM8939_S4_P2_SHIFT 25 -#define MSM8939_S5_P2_SHIFT 14 -#define MSM8939_S6_P2_SHIFT 26 -#define MSM8939_S7_P2_SHIFT 6 -#define MSM8939_S8_P2_SHIFT 18 -#define MSM8939_S9_P2_SHIFT_0_4 27 -#define MSM8939_S9_P2_SHIFT_5 13 - -#define MSM8939_CAL_SEL_MASK 0x7 -#define MSM8939_CAL_SEL_SHIFT 0 - -/* eeprom layout data for 8974 */ -#define BASE1_MASK 0xff -#define S0_P1_MASK 0x3f00 -#define S1_P1_MASK 0xfc000 -#define S2_P1_MASK 0x3f00000 -#define S3_P1_MASK 0xfc000000 -#define S4_P1_MASK 0x3f -#define S5_P1_MASK 0xfc0 -#define S6_P1_MASK 0x3f000 -#define S7_P1_MASK 0xfc0000 -#define S8_P1_MASK 0x3f000000 -#define S8_P1_MASK_BKP 0x3f -#define S9_P1_MASK 0x3f -#define S9_P1_MASK_BKP 0xfc0 -#define S10_P1_MASK 0xfc0 -#define S10_P1_MASK_BKP 0x3f000 -#define CAL_SEL_0_1 0xc0000000 -#define CAL_SEL_2 0x40000000 -#define CAL_SEL_SHIFT 30 -#define CAL_SEL_SHIFT_2 28 - -#define S0_P1_SHIFT 8 -#define S1_P1_SHIFT 14 -#define S2_P1_SHIFT 20 -#define S3_P1_SHIFT 26 -#define S5_P1_SHIFT 6 -#define S6_P1_SHIFT 12 -#define S7_P1_SHIFT 18 -#define S8_P1_SHIFT 24 -#define S9_P1_BKP_SHIFT 6 -#define S10_P1_SHIFT 6 -#define S10_P1_BKP_SHIFT 12 - -#define BASE2_SHIFT 12 -#define BASE2_BKP_SHIFT 18 -#define S0_P2_SHIFT 20 -#define S0_P2_BKP_SHIFT 26 -#define S1_P2_SHIFT 26 -#define S2_P2_BKP_SHIFT 6 -#define S3_P2_SHIFT 6 -#define S3_P2_BKP_SHIFT 12 -#define S4_P2_SHIFT 12 -#define S4_P2_BKP_SHIFT 18 -#define S5_P2_SHIFT 18 -#define S5_P2_BKP_SHIFT 24 -#define S6_P2_SHIFT 24 -#define S7_P2_BKP_SHIFT 6 -#define S8_P2_SHIFT 6 -#define S8_P2_BKP_SHIFT 12 -#define S9_P2_SHIFT 12 -#define S9_P2_BKP_SHIFT 18 -#define S10_P2_SHIFT 18 -#define S10_P2_BKP_SHIFT 24 - -#define BASE2_MASK 0xff000 -#define BASE2_BKP_MASK 0xfc0000 -#define S0_P2_MASK 0x3f00000 -#define S0_P2_BKP_MASK 0xfc000000 -#define S1_P2_MASK 0xfc000000 -#define S1_P2_BKP_MASK 0x3f -#define S2_P2_MASK 0x3f -#define S2_P2_BKP_MASK 0xfc0 -#define S3_P2_MASK 0xfc0 -#define S3_P2_BKP_MASK 0x3f000 -#define S4_P2_MASK 0x3f000 -#define S4_P2_BKP_MASK 0xfc0000 -#define S5_P2_MASK 0xfc0000 -#define S5_P2_BKP_MASK 0x3f000000 -#define S6_P2_MASK 0x3f000000 -#define S6_P2_BKP_MASK 0x3f -#define S7_P2_MASK 0x3f -#define S7_P2_BKP_MASK 0xfc0 -#define S8_P2_MASK 0xfc0 -#define S8_P2_BKP_MASK 0x3f000 -#define S9_P2_MASK 0x3f000 -#define S9_P2_BKP_MASK 0xfc0000 -#define S10_P2_MASK 0xfc0000 -#define S10_P2_BKP_MASK 0x3f000000 - +/* extra data for 8974 */ #define BKP_SEL 0x3 #define BKP_REDUN_SEL 0xe0000000 -#define BKP_REDUN_SHIFT 29 #define BIT_APPEND 0x3 -/* eeprom layout data for mdm9607 */ -#define MDM9607_BASE0_MASK 0x000000ff -#define MDM9607_BASE1_MASK 0x000ff000 -#define MDM9607_BASE0_SHIFT 0 -#define MDM9607_BASE1_SHIFT 12 - -#define MDM9607_S0_P1_MASK 0x00003f00 -#define MDM9607_S1_P1_MASK 0x03f00000 -#define MDM9607_S2_P1_MASK 0x0000003f -#define MDM9607_S3_P1_MASK 0x0003f000 -#define MDM9607_S4_P1_MASK 0x0000003f - -#define MDM9607_S0_P2_MASK 0x000fc000 -#define MDM9607_S1_P2_MASK 0xfc000000 -#define MDM9607_S2_P2_MASK 0x00000fc0 -#define MDM9607_S3_P2_MASK 0x00fc0000 -#define MDM9607_S4_P2_MASK 0x00000fc0 - -#define MDM9607_S0_P1_SHIFT 8 -#define MDM9607_S1_P1_SHIFT 20 -#define MDM9607_S2_P1_SHIFT 0 -#define MDM9607_S3_P1_SHIFT 12 -#define MDM9607_S4_P1_SHIFT 0 - -#define MDM9607_S0_P2_SHIFT 14 -#define MDM9607_S1_P2_SHIFT 26 -#define MDM9607_S2_P2_SHIFT 6 -#define MDM9607_S3_P2_SHIFT 18 -#define MDM9607_S4_P2_SHIFT 6 - -#define MDM9607_CAL_SEL_MASK 0x00700000 -#define MDM9607_CAL_SEL_SHIFT 20 +struct tsens_legacy_calibration_format tsens_8916_nvmem = { + .base_len = 7, + .base_shift = 3, + .sp_len = 5, + .mode = { 0, 29, 1 }, + .invalid = { 0, 31, 1 }, + .base = { { 0, 0 }, { 1, 25 } }, + .sp = { + { { 0, 7 }, { 0, 12 } }, + { { 0, 17 }, { 0, 22 } }, + { { 0, 27 }, { 1, 0 } }, + { { 1, 5 }, { 1, 10 } }, + { { 1, 15 }, { 1, 20 } }, + }, +}; + +struct tsens_legacy_calibration_format tsens_8939_nvmem = { + .base_len = 8, + .base_shift = 2, + .sp_len = 6, + .mode = { 12, 0 }, + .invalid = { 12, 2 }, + .base = { { 0, 0 }, { 1, 24 } }, + .sp = { + { { 12, 3 }, { 12, 9 } }, + { { 12, 15 }, { 12, 21 } }, + { { 12, 27 }, { 13, 1 } }, + { { 13, 7 }, { 13, 13 } }, + { { 13, 19 }, { 13, 25 } }, + { { 0, 8 }, { 0, 14 } }, + { { 0, 20 }, { 0, 26 } }, + { { 1, 0 }, { 1, 6 } }, + { { 1, 12 }, { 1, 18 } }, + }, +}; + +struct tsens_legacy_calibration_format tsens_8974_nvmem = { + .base_len = 8, + .base_shift = 2, + .sp_len = 6, + .mode = { 1, 30 }, + .invalid = { 3, 30 }, + .base = { { 0, 0 }, { 2, 12 } }, + .sp = { + { { 0, 8 }, { 2, 20 } }, + { { 0, 14 }, { 2, 26 } }, + { { 0, 20 }, { 3, 0 } }, + { { 0, 26 }, { 3, 6 } }, + { { 1, 0 }, { 3, 12 } }, + { { 1, 6 }, { 3, 18 } }, + { { 1, 12 }, { 3, 24 } }, + { { 1, 18 }, { 4, 0 } }, + { { 1, 24 }, { 4, 6 } }, + { { 2, 0 }, { 4, 12 } }, + { { 2, 6 }, { 4, 18 } }, + }, +}; + +struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = { + .base_len = 8, + .base_shift = 2, + .sp_len = 6, + .mode = { 4, 30, 1 }, + .invalid = { 5, 30, 1 }, + .base = { { 0, 0 }, { 2, 18 } }, + .sp = { + { { 0, 8 }, { 2, 26 } }, + { { 0, 14 }, { 3, 0 } }, + { { 0, 20 }, { 3, 6 } }, + { { 0, 26 }, { 3, 12 } }, + { { 1, 0 }, { 3, 18 } }, + { { 1, 6 }, { 3, 24, 1 } }, + { { 1, 12 }, { 4, 0, 1 } }, + { { 1, 18 }, { 4, 6, 1 } }, + { { 2, 0 }, { 4, 12, 1 } }, + { { 2, 6 }, { 4, 18, 1 } }, + { { 2, 12 }, { 4, 24, 1 } }, + }, +}; + +struct tsens_legacy_calibration_format tsens_9607_nvmem = { + .base_len = 8, + .base_shift = 2, + .sp_len = 6, + .mode = { 2, 20 }, + .invalid = { 2, 22 }, + .base = { { 0, 0 }, { 2, 12 } }, + .sp = { + { { 0, 8 }, { 0, 14 } }, + { { 0, 20 }, { 0, 26 } }, + { { 1, 0 }, { 1, 6 } }, + { { 1, 12 }, { 1, 18 } }, + { { 2, 0 }, { 2, 6 } }, + }, +}; static int calibrate_8916(struct tsens_priv *priv) { - int base0 = 0, base1 = 0, i; u32 p1[5], p2[5]; - int mode = 0; u32 *qfprom_cdata, *qfprom_csel; + int mode, ret; + + ret = tsens_calibrate_nvmem(priv, 3); + if (!ret) + return 0; qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); if (IS_ERR(qfprom_cdata)) @@ -240,37 +139,9 @@ static int calibrate_8916(struct tsens_priv *priv) return PTR_ERR(qfprom_csel); } - mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT; - dev_dbg(priv->dev, "calibration mode is %d\n", mode); - - switch (mode) { - case TWO_PT_CALIB: - base1 = (qfprom_cdata[1] & MSM8916_BASE1_MASK) >> MSM8916_BASE1_SHIFT; - p2[0] = (qfprom_cdata[0] & MSM8916_S0_P2_MASK) >> MSM8916_S0_P2_SHIFT; - p2[1] = (qfprom_cdata[0] & MSM8916_S1_P2_MASK) >> MSM8916_S1_P2_SHIFT; - p2[2] = (qfprom_cdata[1] & MSM8916_S2_P2_MASK) >> MSM8916_S2_P2_SHIFT; - p2[3] = (qfprom_cdata[1] & MSM8916_S3_P2_MASK) >> MSM8916_S3_P2_SHIFT; - p2[4] = (qfprom_cdata[1] & MSM8916_S4_P2_MASK) >> MSM8916_S4_P2_SHIFT; - for (i = 0; i < priv->num_sensors; i++) - p2[i] = ((base1 + p2[i]) << 3); - fallthrough; - case ONE_PT_CALIB2: - base0 = (qfprom_cdata[0] & MSM8916_BASE0_MASK); - p1[0] = (qfprom_cdata[0] & MSM8916_S0_P1_MASK) >> MSM8916_S0_P1_SHIFT; - p1[1] = (qfprom_cdata[0] & MSM8916_S1_P1_MASK) >> MSM8916_S1_P1_SHIFT; - p1[2] = (qfprom_cdata[0] & MSM8916_S2_P1_MASK) >> MSM8916_S2_P1_SHIFT; - p1[3] = (qfprom_cdata[1] & MSM8916_S3_P1_MASK) >> MSM8916_S3_P1_SHIFT; - p1[4] = (qfprom_cdata[1] & MSM8916_S4_P1_MASK) >> MSM8916_S4_P1_SHIFT; - for (i = 0; i < priv->num_sensors; i++) - p1[i] = (((base0) + p1[i]) << 3); - break; - default: - for (i = 0; i < priv->num_sensors; i++) { - p1[i] = 500; - p2[i] = 780; - } - break; - } + mode = tsens_read_calibration_legacy(priv, &tsens_8916_nvmem, + p1, p2, + qfprom_cdata, qfprom_csel); compute_intercept_slope(priv, p1, p2, mode); kfree(qfprom_cdata); @@ -279,83 +150,68 @@ static int calibrate_8916(struct tsens_priv *priv) return 0; } -static int calibrate_8939(struct tsens_priv *priv) +static void fixup_8974_points(int mode, u32 *p1, u32 *p2) { - int base0 = 0, base1 = 0, i; - u32 p1[10], p2[10]; - int mode = 0; - u32 *qfprom_cdata; - u32 cdata[6]; - - qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); - if (IS_ERR(qfprom_cdata)) - return PTR_ERR(qfprom_cdata); - - /* Mapping between qfprom nvmem and calibration data */ - cdata[0] = qfprom_cdata[12]; - cdata[1] = qfprom_cdata[13]; - cdata[2] = qfprom_cdata[0]; - cdata[3] = qfprom_cdata[1]; - cdata[4] = qfprom_cdata[22]; - cdata[5] = qfprom_cdata[21]; - - mode = (cdata[0] & MSM8939_CAL_SEL_MASK) >> MSM8939_CAL_SEL_SHIFT; - dev_dbg(priv->dev, "calibration mode is %d\n", mode); - - switch (mode) { - case TWO_PT_CALIB: - base1 = (cdata[3] & MSM8939_BASE1_MASK) >> MSM8939_BASE1_SHIFT; - p2[0] = (cdata[0] & MSM8939_S0_P2_MASK) >> MSM8939_S0_P2_SHIFT; - p2[1] = (cdata[0] & MSM8939_S1_P2_MASK) >> MSM8939_S1_P2_SHIFT; - p2[2] = (cdata[1] & MSM8939_S2_P2_MASK) >> MSM8939_S2_P2_SHIFT; - p2[3] = (cdata[1] & MSM8939_S3_P2_MASK) >> MSM8939_S3_P2_SHIFT; - p2[4] = (cdata[1] & MSM8939_S4_P2_MASK) >> MSM8939_S4_P2_SHIFT; - p2[5] = (cdata[2] & MSM8939_S5_P2_MASK) >> MSM8939_S5_P2_SHIFT; - p2[6] = (cdata[2] & MSM8939_S6_P2_MASK) >> MSM8939_S6_P2_SHIFT; - p2[7] = (cdata[3] & MSM8939_S7_P2_MASK) >> MSM8939_S7_P2_SHIFT; - p2[8] = (cdata[3] & MSM8939_S8_P2_MASK) >> MSM8939_S8_P2_SHIFT; - p2[9] = (cdata[4] & MSM8939_S9_P2_MASK_0_4) >> MSM8939_S9_P2_SHIFT_0_4; - p2[9] |= ((cdata[5] & MSM8939_S9_P2_MASK_5) >> MSM8939_S9_P2_SHIFT_5) << 5; - for (i = 0; i < priv->num_sensors; i++) - p2[i] = (base1 + p2[i]) << 2; - fallthrough; - case ONE_PT_CALIB2: - base0 = (cdata[2] & MSM8939_BASE0_MASK) >> MSM8939_BASE0_SHIFT; - p1[0] = (cdata[0] & MSM8939_S0_P1_MASK) >> MSM8939_S0_P1_SHIFT; - p1[1] = (cdata[0] & MSM8939_S1_P1_MASK) >> MSM8939_S1_P1_SHIFT; - p1[2] = (cdata[0] & MSM8939_S2_P1_MASK_0_4) >> MSM8939_S2_P1_SHIFT_0_4; - p1[2] |= ((cdata[1] & MSM8939_S2_P1_MASK_5) >> MSM8939_S2_P1_SHIFT_5) << 5; - p1[3] = (cdata[1] & MSM8939_S3_P1_MASK) >> MSM8939_S3_P1_SHIFT; - p1[4] = (cdata[1] & MSM8939_S4_P1_MASK) >> MSM8939_S4_P1_SHIFT; - p1[5] = (cdata[2] & MSM8939_S5_P1_MASK) >> MSM8939_S5_P1_SHIFT; - p1[6] = (cdata[2] & MSM8939_S6_P1_MASK) >> MSM8939_S6_P1_SHIFT; - p1[7] = (cdata[3] & MSM8939_S7_P1_MASK) >> MSM8939_S7_P1_SHIFT; - p1[8] = (cdata[3] & MSM8939_S8_P1_MASK) >> MSM8939_S8_P1_SHIFT; - p1[9] = (cdata[4] & MSM8939_S9_P1_MASK) >> MSM8939_S9_P1_SHIFT; - for (i = 0; i < priv->num_sensors; i++) - p1[i] = ((base0) + p1[i]) << 2; - break; - default: - for (i = 0; i < priv->num_sensors; i++) { - p1[i] = 500; - p2[i] = 780; + int i; + + if (mode == NO_PT_CALIB) { + p1[0] += 2; + p1[1] += 9; + p1[2] += 3; + p1[3] += 9; + p1[4] += 5; + p1[5] += 9; + p1[6] += 7; + p1[7] += 10; + p1[8] += 8; + p1[9] += 9; + p1[10] += 8; + } else { + for (i = 0; i < 11; i++) { + /* + * ONE_PT_CALIB requires using addition here instead of + * using OR operation. + */ + p1[i] += BIT_APPEND; + p2[i] += BIT_APPEND; } - break; } +} + +static int calibrate_8974_nvmem(struct tsens_priv *priv) +{ + u32 p1[11], p2[11]; + u32 backup; + int ret, mode; + + ret = nvmem_cell_read_variable_le_u32(priv->dev, "use_backup", &backup); + if (ret == -ENOENT) + dev_warn(priv->dev, "Please migrate to separate nvmem cells for calibration data\n"); + if (ret < 0) + return ret; + + mode = tsens_read_calibration(priv, 2, p1, p2, backup == BKP_SEL); + if (mode < 0) + return mode; + + fixup_8974_points(mode, p1, p2); + compute_intercept_slope(priv, p1, p2, mode); - kfree(qfprom_cdata); return 0; } static int calibrate_8974(struct tsens_priv *priv) { - int base1 = 0, base2 = 0, i; u32 p1[11], p2[11]; - int mode = 0; u32 *calib, *bkp; u32 calib_redun_sel; + int mode, ret; + + ret = calibrate_8974_nvmem(priv); + if (ret == 0) + return 0; calib = (u32 *)qfprom_read(priv->dev, "calib"); if (IS_ERR(calib)) @@ -367,116 +223,18 @@ static int calibrate_8974(struct tsens_priv *priv) return PTR_ERR(bkp); } - calib_redun_sel = bkp[1] & BKP_REDUN_SEL; - calib_redun_sel >>= BKP_REDUN_SHIFT; - - if (calib_redun_sel == BKP_SEL) { - mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT; - mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2; - - switch (mode) { - case TWO_PT_CALIB: - base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT; - p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT; - p2[1] = (bkp[3] & S1_P2_BKP_MASK); - p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT; - p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT; - p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT; - p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT; - p2[6] = (calib[5] & S6_P2_BKP_MASK); - p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT; - p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT; - p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT; - p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT; - fallthrough; - case ONE_PT_CALIB: - case ONE_PT_CALIB2: - base1 = bkp[0] & BASE1_MASK; - p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT; - p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT; - p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT; - p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT; - p1[4] = (bkp[1] & S4_P1_MASK); - p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT; - p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT; - p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT; - p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT; - p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT; - p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT; - break; - } - } else { - mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT; - mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2; - - switch (mode) { - case TWO_PT_CALIB: - base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT; - p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT; - p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT; - p2[2] = (calib[3] & S2_P2_MASK); - p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT; - p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT; - p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT; - p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT; - p2[7] = (calib[4] & S7_P2_MASK); - p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT; - p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT; - p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT; - fallthrough; - case ONE_PT_CALIB: - case ONE_PT_CALIB2: - base1 = calib[0] & BASE1_MASK; - p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT; - p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT; - p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT; - p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT; - p1[4] = (calib[1] & S4_P1_MASK); - p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT; - p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT; - p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT; - p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT; - p1[9] = (calib[2] & S9_P1_MASK); - p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT; - break; - } - } + calib_redun_sel = FIELD_GET(BKP_REDUN_SEL, bkp[1]); - switch (mode) { - case ONE_PT_CALIB: - for (i = 0; i < priv->num_sensors; i++) - p1[i] += (base1 << 2) | BIT_APPEND; - break; - case TWO_PT_CALIB: - for (i = 0; i < priv->num_sensors; i++) { - p2[i] += base2; - p2[i] <<= 2; - p2[i] |= BIT_APPEND; - } - fallthrough; - case ONE_PT_CALIB2: - for (i = 0; i < priv->num_sensors; i++) { - p1[i] += base1; - p1[i] <<= 2; - p1[i] |= BIT_APPEND; - } - break; - default: - for (i = 0; i < priv->num_sensors; i++) - p2[i] = 780; - p1[0] = 502; - p1[1] = 509; - p1[2] = 503; - p1[3] = 509; - p1[4] = 505; - p1[5] = 509; - p1[6] = 507; - p1[7] = 510; - p1[8] = 508; - p1[9] = 509; - p1[10] = 508; - break; - } + if (calib_redun_sel == BKP_SEL) + mode = tsens_read_calibration_legacy(priv, &tsens_8974_backup_nvmem, + p1, p2, + bkp, calib); + else + mode = tsens_read_calibration_legacy(priv, &tsens_8974_nvmem, + p1, p2, + calib, NULL); + + fixup_8974_points(mode, p1, p2); compute_intercept_slope(priv, p1, p2, mode); kfree(calib); @@ -485,53 +243,19 @@ static int calibrate_8974(struct tsens_priv *priv) return 0; } -static int calibrate_9607(struct tsens_priv *priv) -{ - int base, i; - u32 p1[5], p2[5]; - int mode = 0; - u32 *qfprom_cdata; - - qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); - if (IS_ERR(qfprom_cdata)) - return PTR_ERR(qfprom_cdata); - - mode = (qfprom_cdata[2] & MDM9607_CAL_SEL_MASK) >> MDM9607_CAL_SEL_SHIFT; - dev_dbg(priv->dev, "calibration mode is %d\n", mode); - - switch (mode) { - case TWO_PT_CALIB: - base = (qfprom_cdata[2] & MDM9607_BASE1_MASK) >> MDM9607_BASE1_SHIFT; - p2[0] = (qfprom_cdata[0] & MDM9607_S0_P2_MASK) >> MDM9607_S0_P2_SHIFT; - p2[1] = (qfprom_cdata[0] & MDM9607_S1_P2_MASK) >> MDM9607_S1_P2_SHIFT; - p2[2] = (qfprom_cdata[1] & MDM9607_S2_P2_MASK) >> MDM9607_S2_P2_SHIFT; - p2[3] = (qfprom_cdata[1] & MDM9607_S3_P2_MASK) >> MDM9607_S3_P2_SHIFT; - p2[4] = (qfprom_cdata[2] & MDM9607_S4_P2_MASK) >> MDM9607_S4_P2_SHIFT; - for (i = 0; i < priv->num_sensors; i++) - p2[i] = ((base + p2[i]) << 2); - fallthrough; - case ONE_PT_CALIB2: - base = (qfprom_cdata[0] & MDM9607_BASE0_MASK); - p1[0] = (qfprom_cdata[0] & MDM9607_S0_P1_MASK) >> MDM9607_S0_P1_SHIFT; - p1[1] = (qfprom_cdata[0] & MDM9607_S1_P1_MASK) >> MDM9607_S1_P1_SHIFT; - p1[2] = (qfprom_cdata[1] & MDM9607_S2_P1_MASK) >> MDM9607_S2_P1_SHIFT; - p1[3] = (qfprom_cdata[1] & MDM9607_S3_P1_MASK) >> MDM9607_S3_P1_SHIFT; - p1[4] = (qfprom_cdata[2] & MDM9607_S4_P1_MASK) >> MDM9607_S4_P1_SHIFT; - for (i = 0; i < priv->num_sensors; i++) - p1[i] = ((base + p1[i]) << 2); - break; - default: - for (i = 0; i < priv->num_sensors; i++) { - p1[i] = 500; - p2[i] = 780; - } - break; - } - - compute_intercept_slope(priv, p1, p2, mode); - kfree(qfprom_cdata); - - return 0; +static int __init init_8939(struct tsens_priv *priv) { + priv->sensor[0].slope = 2911; + priv->sensor[1].slope = 2789; + priv->sensor[2].slope = 2906; + priv->sensor[3].slope = 2763; + priv->sensor[4].slope = 2922; + priv->sensor[5].slope = 2867; + priv->sensor[6].slope = 2833; + priv->sensor[7].slope = 2838; + priv->sensor[8].slope = 2840; + /* priv->sensor[9].slope = 2852; */ + + return init_common(priv); } /* v0.1: 8916, 8939, 8974, 9607 */ @@ -583,6 +307,12 @@ static const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = { [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), }; +static const struct tsens_ops ops_v0_1 = { + .init = init_common, + .calibrate = tsens_calibrate_common, + .get_temp = get_temp_common, +}; + static const struct tsens_ops ops_8916 = { .init = init_common, .calibrate = calibrate_8916, @@ -599,15 +329,15 @@ struct tsens_plat_data data_8916 = { }; static const struct tsens_ops ops_8939 = { - .init = init_common, - .calibrate = calibrate_8939, + .init = init_8939, + .calibrate = tsens_calibrate_common, .get_temp = get_temp_common, }; struct tsens_plat_data data_8939 = { - .num_sensors = 10, + .num_sensors = 9, .ops = &ops_8939, - .hw_ids = (unsigned int []){ 0, 1, 2, 3, 5, 6, 7, 8, 9, 10 }, + .hw_ids = (unsigned int []){ 0, 1, 2, 3, 5, 6, 7, 8, 9, /* 10 */ }, .feat = &tsens_v0_1_feat, .fields = tsens_v0_1_regfields, @@ -626,16 +356,9 @@ struct tsens_plat_data data_8974 = { .fields = tsens_v0_1_regfields, }; -static const struct tsens_ops ops_9607 = { - .init = init_common, - .calibrate = calibrate_9607, - .get_temp = get_temp_common, -}; - struct tsens_plat_data data_9607 = { .num_sensors = 5, - .ops = &ops_9607, - .hw_ids = (unsigned int []){ 0, 1, 2, 3, 4 }, + .ops = &ops_v0_1, .feat = &tsens_v0_1_feat, .fields = tsens_v0_1_regfields, }; diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c index 1d7f8a80bd13..b822a426066d 100644 --- a/drivers/thermal/qcom/tsens-v1.c +++ b/drivers/thermal/qcom/tsens-v1.c @@ -21,277 +21,68 @@ #define TM_HIGH_LOW_INT_STATUS_OFF 0x0088 #define TM_HIGH_LOW_Sn_INT_THRESHOLD_OFF 0x0090 -/* eeprom layout data for msm8956/76 (v1) */ -#define MSM8976_BASE0_MASK 0xff -#define MSM8976_BASE1_MASK 0xff -#define MSM8976_BASE1_SHIFT 8 - -#define MSM8976_S0_P1_MASK 0x3f00 -#define MSM8976_S1_P1_MASK 0x3f00000 -#define MSM8976_S2_P1_MASK 0x3f -#define MSM8976_S3_P1_MASK 0x3f000 -#define MSM8976_S4_P1_MASK 0x3f00 -#define MSM8976_S5_P1_MASK 0x3f00000 -#define MSM8976_S6_P1_MASK 0x3f -#define MSM8976_S7_P1_MASK 0x3f000 -#define MSM8976_S8_P1_MASK 0x1f8 -#define MSM8976_S9_P1_MASK 0x1f8000 -#define MSM8976_S10_P1_MASK 0xf8000000 -#define MSM8976_S10_P1_MASK_1 0x1 - -#define MSM8976_S0_P2_MASK 0xfc000 -#define MSM8976_S1_P2_MASK 0xfc000000 -#define MSM8976_S2_P2_MASK 0xfc0 -#define MSM8976_S3_P2_MASK 0xfc0000 -#define MSM8976_S4_P2_MASK 0xfc000 -#define MSM8976_S5_P2_MASK 0xfc000000 -#define MSM8976_S6_P2_MASK 0xfc0 -#define MSM8976_S7_P2_MASK 0xfc0000 -#define MSM8976_S8_P2_MASK 0x7e00 -#define MSM8976_S9_P2_MASK 0x7e00000 -#define MSM8976_S10_P2_MASK 0x7e - -#define MSM8976_S0_P1_SHIFT 8 -#define MSM8976_S1_P1_SHIFT 20 -#define MSM8976_S2_P1_SHIFT 0 -#define MSM8976_S3_P1_SHIFT 12 -#define MSM8976_S4_P1_SHIFT 8 -#define MSM8976_S5_P1_SHIFT 20 -#define MSM8976_S6_P1_SHIFT 0 -#define MSM8976_S7_P1_SHIFT 12 -#define MSM8976_S8_P1_SHIFT 3 -#define MSM8976_S9_P1_SHIFT 15 -#define MSM8976_S10_P1_SHIFT 27 -#define MSM8976_S10_P1_SHIFT_1 0 - -#define MSM8976_S0_P2_SHIFT 14 -#define MSM8976_S1_P2_SHIFT 26 -#define MSM8976_S2_P2_SHIFT 6 -#define MSM8976_S3_P2_SHIFT 18 -#define MSM8976_S4_P2_SHIFT 14 -#define MSM8976_S5_P2_SHIFT 26 -#define MSM8976_S6_P2_SHIFT 6 -#define MSM8976_S7_P2_SHIFT 18 -#define MSM8976_S8_P2_SHIFT 9 -#define MSM8976_S9_P2_SHIFT 21 -#define MSM8976_S10_P2_SHIFT 1 - -#define MSM8976_CAL_SEL_MASK 0x3 - -#define MSM8976_CAL_DEGC_PT1 30 -#define MSM8976_CAL_DEGC_PT2 120 -#define MSM8976_SLOPE_FACTOR 1000 -#define MSM8976_SLOPE_DEFAULT 3200 - -/* eeprom layout data for qcs404/405 (v1) */ -#define BASE0_MASK 0x000007f8 -#define BASE1_MASK 0x0007f800 -#define BASE0_SHIFT 3 -#define BASE1_SHIFT 11 - -#define S0_P1_MASK 0x0000003f -#define S1_P1_MASK 0x0003f000 -#define S2_P1_MASK 0x3f000000 -#define S3_P1_MASK 0x000003f0 -#define S4_P1_MASK 0x003f0000 -#define S5_P1_MASK 0x0000003f -#define S6_P1_MASK 0x0003f000 -#define S7_P1_MASK 0x3f000000 -#define S8_P1_MASK 0x000003f0 -#define S9_P1_MASK 0x003f0000 - -#define S0_P2_MASK 0x00000fc0 -#define S1_P2_MASK 0x00fc0000 -#define S2_P2_MASK_1_0 0xc0000000 -#define S2_P2_MASK_5_2 0x0000000f -#define S3_P2_MASK 0x0000fc00 -#define S4_P2_MASK 0x0fc00000 -#define S5_P2_MASK 0x00000fc0 -#define S6_P2_MASK 0x00fc0000 -#define S7_P2_MASK_1_0 0xc0000000 -#define S7_P2_MASK_5_2 0x0000000f -#define S8_P2_MASK 0x0000fc00 -#define S9_P2_MASK 0x0fc00000 - -#define S0_P1_SHIFT 0 -#define S0_P2_SHIFT 6 -#define S1_P1_SHIFT 12 -#define S1_P2_SHIFT 18 -#define S2_P1_SHIFT 24 -#define S2_P2_SHIFT_1_0 30 - -#define S2_P2_SHIFT_5_2 0 -#define S3_P1_SHIFT 4 -#define S3_P2_SHIFT 10 -#define S4_P1_SHIFT 16 -#define S4_P2_SHIFT 22 - -#define S5_P1_SHIFT 0 -#define S5_P2_SHIFT 6 -#define S6_P1_SHIFT 12 -#define S6_P2_SHIFT 18 -#define S7_P1_SHIFT 24 -#define S7_P2_SHIFT_1_0 30 - -#define S7_P2_SHIFT_5_2 0 -#define S8_P1_SHIFT 4 -#define S8_P2_SHIFT 10 -#define S9_P1_SHIFT 16 -#define S9_P2_SHIFT 22 - -#define CAL_SEL_MASK 7 -#define CAL_SEL_SHIFT 0 - -static void compute_intercept_slope_8976(struct tsens_priv *priv, - u32 *p1, u32 *p2, u32 mode) -{ - int i; - - priv->sensor[0].slope = 3313; - priv->sensor[1].slope = 3275; - priv->sensor[2].slope = 3320; - priv->sensor[3].slope = 3246; - priv->sensor[4].slope = 3279; - priv->sensor[5].slope = 3257; - priv->sensor[6].slope = 3234; - priv->sensor[7].slope = 3269; - priv->sensor[8].slope = 3255; - priv->sensor[9].slope = 3239; - priv->sensor[10].slope = 3286; +struct tsens_legacy_calibration_format tsens_qcs404_nvmem = { + .base_len = 8, + .base_shift = 2, + .sp_len = 6, + .mode = { 4, 0 }, + .invalid = { 4, 2 }, + .base = { { 4, 3 }, { 4, 11 } }, + .sp = { + { { 0, 0 }, { 0, 6 } }, + { { 0, 12 }, { 0, 18 } }, + { { 0, 24 }, { 0, 30 } }, + { { 1, 4 }, { 1, 10 } }, + { { 1, 16 }, { 1, 22 } }, + { { 2, 0 }, { 2, 6 } }, + { { 2, 12 }, { 2, 18 } }, + { { 2, 24 }, { 2, 30 } }, + { { 3, 4 }, { 3, 10 } }, + { { 3, 16 }, { 3, 22 } }, + }, +}; - for (i = 0; i < priv->num_sensors; i++) { - priv->sensor[i].offset = (p1[i] * MSM8976_SLOPE_FACTOR) - - (MSM8976_CAL_DEGC_PT1 * - priv->sensor[i].slope); - } -} +struct tsens_legacy_calibration_format tsens_8976_nvmem = { + .base_len = 8, + .base_shift = 2, + .sp_len = 6, + .mode = { 4, 0 }, + .invalid = { 4, 2 }, + .base = { { 0, 0 }, { 2, 8 } }, + .sp = { + { { 0, 8 }, { 0, 14 } }, + { { 0, 20 }, { 0, 26 } }, + { { 1, 0 }, { 1, 6 } }, + { { 1, 12 }, { 1, 18 } }, + { { 2, 8 }, { 2, 14 } }, + { { 2, 20 }, { 2, 26 } }, + { { 3, 0 }, { 3, 6 } }, + { { 3, 12 }, { 3, 18 } }, + { { 4, 2 }, { 4, 9 } }, + { { 4, 14 }, { 4, 21 } }, + { { 4, 26 }, { 5, 1 } }, + }, +}; static int calibrate_v1(struct tsens_priv *priv) { - u32 base0 = 0, base1 = 0; u32 p1[10], p2[10]; - u32 mode = 0, lsb = 0, msb = 0; u32 *qfprom_cdata; - int i; - - qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); - if (IS_ERR(qfprom_cdata)) - return PTR_ERR(qfprom_cdata); - - mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT; - dev_dbg(priv->dev, "calibration mode is %d\n", mode); + int mode, ret; - switch (mode) { - case TWO_PT_CALIB: - base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT; - p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT; - p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT; - /* This value is split over two registers, 2 bits and 4 bits */ - lsb = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0; - msb = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2; - p2[2] = msb << 2 | lsb; - p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT; - p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT; - p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT; - p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT; - /* This value is split over two registers, 2 bits and 4 bits */ - lsb = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0; - msb = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2; - p2[7] = msb << 2 | lsb; - p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT; - p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT; - for (i = 0; i < priv->num_sensors; i++) - p2[i] = ((base1 + p2[i]) << 2); - fallthrough; - case ONE_PT_CALIB2: - base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT; - p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT; - p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT; - p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT; - p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT; - p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT; - p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT; - p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT; - p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT; - p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT; - p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT; - for (i = 0; i < priv->num_sensors; i++) - p1[i] = (((base0) + p1[i]) << 2); - break; - default: - for (i = 0; i < priv->num_sensors; i++) { - p1[i] = 500; - p2[i] = 780; - } - break; - } - - compute_intercept_slope(priv, p1, p2, mode); - kfree(qfprom_cdata); - - return 0; -} - -static int calibrate_8976(struct tsens_priv *priv) -{ - int base0 = 0, base1 = 0, i; - u32 p1[11], p2[11]; - int mode = 0, tmp = 0; - u32 *qfprom_cdata; + ret = tsens_calibrate_common(priv); + if (!ret) + return 0; qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); if (IS_ERR(qfprom_cdata)) return PTR_ERR(qfprom_cdata); - mode = (qfprom_cdata[4] & MSM8976_CAL_SEL_MASK); - dev_dbg(priv->dev, "calibration mode is %d\n", mode); + mode = tsens_read_calibration_legacy(priv, &tsens_qcs404_nvmem, + p1, p2, + qfprom_cdata, NULL); - switch (mode) { - case TWO_PT_CALIB: - base1 = (qfprom_cdata[2] & MSM8976_BASE1_MASK) >> MSM8976_BASE1_SHIFT; - p2[0] = (qfprom_cdata[0] & MSM8976_S0_P2_MASK) >> MSM8976_S0_P2_SHIFT; - p2[1] = (qfprom_cdata[0] & MSM8976_S1_P2_MASK) >> MSM8976_S1_P2_SHIFT; - p2[2] = (qfprom_cdata[1] & MSM8976_S2_P2_MASK) >> MSM8976_S2_P2_SHIFT; - p2[3] = (qfprom_cdata[1] & MSM8976_S3_P2_MASK) >> MSM8976_S3_P2_SHIFT; - p2[4] = (qfprom_cdata[2] & MSM8976_S4_P2_MASK) >> MSM8976_S4_P2_SHIFT; - p2[5] = (qfprom_cdata[2] & MSM8976_S5_P2_MASK) >> MSM8976_S5_P2_SHIFT; - p2[6] = (qfprom_cdata[3] & MSM8976_S6_P2_MASK) >> MSM8976_S6_P2_SHIFT; - p2[7] = (qfprom_cdata[3] & MSM8976_S7_P2_MASK) >> MSM8976_S7_P2_SHIFT; - p2[8] = (qfprom_cdata[4] & MSM8976_S8_P2_MASK) >> MSM8976_S8_P2_SHIFT; - p2[9] = (qfprom_cdata[4] & MSM8976_S9_P2_MASK) >> MSM8976_S9_P2_SHIFT; - p2[10] = (qfprom_cdata[5] & MSM8976_S10_P2_MASK) >> MSM8976_S10_P2_SHIFT; - - for (i = 0; i < priv->num_sensors; i++) - p2[i] = ((base1 + p2[i]) << 2); - fallthrough; - case ONE_PT_CALIB2: - base0 = qfprom_cdata[0] & MSM8976_BASE0_MASK; - p1[0] = (qfprom_cdata[0] & MSM8976_S0_P1_MASK) >> MSM8976_S0_P1_SHIFT; - p1[1] = (qfprom_cdata[0] & MSM8976_S1_P1_MASK) >> MSM8976_S1_P1_SHIFT; - p1[2] = (qfprom_cdata[1] & MSM8976_S2_P1_MASK) >> MSM8976_S2_P1_SHIFT; - p1[3] = (qfprom_cdata[1] & MSM8976_S3_P1_MASK) >> MSM8976_S3_P1_SHIFT; - p1[4] = (qfprom_cdata[2] & MSM8976_S4_P1_MASK) >> MSM8976_S4_P1_SHIFT; - p1[5] = (qfprom_cdata[2] & MSM8976_S5_P1_MASK) >> MSM8976_S5_P1_SHIFT; - p1[6] = (qfprom_cdata[3] & MSM8976_S6_P1_MASK) >> MSM8976_S6_P1_SHIFT; - p1[7] = (qfprom_cdata[3] & MSM8976_S7_P1_MASK) >> MSM8976_S7_P1_SHIFT; - p1[8] = (qfprom_cdata[4] & MSM8976_S8_P1_MASK) >> MSM8976_S8_P1_SHIFT; - p1[9] = (qfprom_cdata[4] & MSM8976_S9_P1_MASK) >> MSM8976_S9_P1_SHIFT; - p1[10] = (qfprom_cdata[4] & MSM8976_S10_P1_MASK) >> MSM8976_S10_P1_SHIFT; - tmp = (qfprom_cdata[5] & MSM8976_S10_P1_MASK_1) << MSM8976_S10_P1_SHIFT_1; - p1[10] |= tmp; - - for (i = 0; i < priv->num_sensors; i++) - p1[i] = (((base0) + p1[i]) << 2); - break; - default: - for (i = 0; i < priv->num_sensors; i++) { - p1[i] = 500; - p2[i] = 780; - } - break; - } - - compute_intercept_slope_8976(priv, p1, p2, mode); + compute_intercept_slope(priv, p1, p2, mode); kfree(qfprom_cdata); return 0; @@ -365,6 +156,22 @@ static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = { [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), }; +static int __init init_8956(struct tsens_priv *priv) { + priv->sensor[0].slope = 3313; + priv->sensor[1].slope = 3275; + priv->sensor[2].slope = 3320; + priv->sensor[3].slope = 3246; + priv->sensor[4].slope = 3279; + priv->sensor[5].slope = 3257; + priv->sensor[6].slope = 3234; + priv->sensor[7].slope = 3269; + priv->sensor[8].slope = 3255; + priv->sensor[9].slope = 3239; + priv->sensor[10].slope = 3286; + + return init_common(priv); +} + static const struct tsens_ops ops_generic_v1 = { .init = init_common, .calibrate = calibrate_v1, @@ -377,17 +184,28 @@ struct tsens_plat_data data_tsens_v1 = { .fields = tsens_v1_regfields, }; +static const struct tsens_ops ops_8956 = { + .init = init_8956, + .calibrate = tsens_calibrate_common, + .get_temp = get_temp_tsens_valid, +}; + +struct tsens_plat_data data_8956 = { + .num_sensors = 11, + .ops = &ops_8956, + .feat = &tsens_v1_feat, + .fields = tsens_v1_regfields, +}; + static const struct tsens_ops ops_8976 = { .init = init_common, - .calibrate = calibrate_8976, + .calibrate = tsens_calibrate_common, .get_temp = get_temp_tsens_valid, }; -/* Valid for both MSM8956 and MSM8976. */ struct tsens_plat_data data_8976 = { .num_sensors = 11, .ops = &ops_8976, - .hw_ids = (unsigned int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, .feat = &tsens_v1_feat, .fields = tsens_v1_regfields, }; diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index b5b136ff323f..8020ead2794e 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -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 @@ -984,6 +1102,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, }, { diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 899af128855f..dba9cd38f637 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -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; diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 819e059cde71..4b7c43f34d1a 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -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); diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index ee33ed692e4f..6a722b10d738 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -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); diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index e64d06d1328c..497beac63e5d 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -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); } diff --git a/drivers/thermal/thermal_mmio.c b/drivers/thermal/thermal_mmio.c index 39c921415989..ea616731066c 100644 --- a/drivers/thermal/thermal_mmio.c +++ b/drivers/thermal/thermal_mmio.c @@ -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); diff --git a/drivers/thermal/uniphier_thermal.c b/drivers/thermal/uniphier_thermal.c index 277ae300c5b1..f8ab2ca76184 100644 --- a/drivers/thermal/uniphier_thermal.c +++ b/drivers/thermal/uniphier_thermal.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/** +/* * uniphier_thermal.c - Socionext UniPhier thermal driver * Copyright 2014 Panasonic Corporation * Copyright 2016-2017 Socionext Inc. |