diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2026-01-29 15:30:03 +0100 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2026-01-29 15:30:03 +0100 |
| commit | 74dd4d1f4c7d2e49bbeb1374f1ebea95d963eac0 (patch) | |
| tree | 5c72dd15804467a53d6e7cc4bbff53487b845f60 | |
| parent | a1fe789a96fe47733c133134fd264cb7ca832395 (diff) | |
| parent | 0061030929e2d09398ade9fae320528bdcba2bed (diff) | |
Merge tag 'thermal-v7.0' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux
Pull thermal control updates for 6.20/7.0 from Daniel Lezcano:
"- Fix CFLAGS and LDFLAGS in the pkg-config template fir the libthermal
(Romain Gantois)
- Support multiple temp to raw conversion functions for the Mediatek
LVTS thermal driver and add the MT8196 and MT6991 support (Laura
Nao)
- Add support for the Mediatek LVTS driver for MT7987 (Frank
Wunderlich)
- Use the existing HZ_PER_MHZ macro on STM32 (Andy Shevchenko)
- Use the existing clamp() macro in BCM2835 (Thorsten Blum)
- Make the reset line optional in order to support new Renesas Soc
where it is not available. Add the RZ/T2H and RZ/N2H suppport
(Cosmin Tanislav)"
* tag 'thermal-v7.0' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux:
thermal: renesas: rzg3e: add support for RZ/T2H and RZ/N2H
dt-bindings: thermal: r9a09g047-tsu: document RZ/T2H and RZ/N2H
thermal: renesas: rzg3e: make calibration value retrieval per-chip
thermal: renesas: rzg3e: make min and max temperature per-chip
thermal: renesas: rzg3e: make reset optional
dt-bindings: thermal: r9a09g047-tsu: Document RZ/V2N TSU
thermal/drivers/broadcom: Use clamp to simplify bcm2835_thermal_temp2adc
thermal/drivers/stm32: Use predefined HZ_PER_MHZ instead of a custom one
thermal/drivers/mediatek/lvts_thermal: Add mt7987 support
dt-bindings: thermal: mediatek: Add LVTS thermal controller definition for MT7987
dt-bindings: nvmem: mediatek: efuse: Add support for MT8196
thermal/drivers/mediatek/lvts_thermal: Add MT8196 support
thermal/drivers/mediatek/lvts: Support MSR offset for 16-bit calibration data
thermal/drivers/mediatek/lvts: Add support for ATP mode
thermal/drivers/mediatek/lvts: Add lvts_temp_to_raw variant
thermal/drivers/mediatek/lvts: Add platform ops to support alternative conversion logic
thermal/drivers/mediatek/lvts: Make number of calibration offsets configurable
dt-bindings: thermal: mediatek: Add LVTS thermal controller support for MT8196
tools: lib: thermal: Correct CFLAGS and LDFLAGS in pkg-config template
| -rw-r--r-- | Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml | 1 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml | 3 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml | 34 | ||||
| -rw-r--r-- | drivers/thermal/broadcom/bcm2835_thermal.c | 8 | ||||
| -rw-r--r-- | drivers/thermal/mediatek/lvts_thermal.c | 362 | ||||
| -rw-r--r-- | drivers/thermal/renesas/rzg3e_thermal.c | 123 | ||||
| -rw-r--r-- | drivers/thermal/st/stm_thermal.c | 4 | ||||
| -rw-r--r-- | include/dt-bindings/thermal/mediatek,lvts-thermal.h | 29 | ||||
| -rw-r--r-- | tools/lib/thermal/libthermal.pc.template | 4 |
9 files changed, 483 insertions, 85 deletions
diff --git a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml index c9bf34ee0efb..f9323b3ecfc8 100644 --- a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml +++ b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml @@ -28,6 +28,7 @@ properties: - enum: - mediatek,mt8188-efuse - mediatek,mt8189-efuse + - mediatek,mt8196-efuse - const: mediatek,mt8186-efuse - const: mediatek,mt8186-efuse diff --git a/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml index 0259cd3ce9c5..975235130670 100644 --- a/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml @@ -18,6 +18,7 @@ description: | properties: compatible: enum: + - mediatek,mt7987-lvts-ap - mediatek,mt7988-lvts-ap - mediatek,mt8186-lvts - mediatek,mt8188-lvts-ap @@ -26,6 +27,8 @@ properties: - mediatek,mt8192-lvts-mcu - mediatek,mt8195-lvts-ap - mediatek,mt8195-lvts-mcu + - mediatek,mt8196-lvts-ap + - mediatek,mt8196-lvts-mcu reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml b/Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml index befdc8b7a082..d560c58be4d6 100644 --- a/Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml +++ b/Documentation/devicetree/bindings/thermal/renesas,r9a09g047-tsu.yaml @@ -17,10 +17,17 @@ description: properties: compatible: oneOf: - - const: renesas,r9a09g047-tsu # RZ/G3E + - enum: + - renesas,r9a09g047-tsu # RZ/G3E + - renesas,r9a09g077-tsu # RZ/T2H - items: - - const: renesas,r9a09g057-tsu # RZ/V2H + - enum: + - renesas,r9a09g056-tsu # RZ/V2N + - renesas,r9a09g057-tsu # RZ/V2H - const: renesas,r9a09g047-tsu # RZ/G3E + - items: + - const: renesas,r9a09g087-tsu # RZ/N2H + - const: renesas,r9a09g077-tsu # RZ/T2H reg: maxItems: 1 @@ -63,12 +70,31 @@ required: - compatible - reg - clocks - - resets - power-domains - interrupts - interrupt-names - "#thermal-sensor-cells" - - renesas,tsu-trim + +allOf: + - if: + properties: + compatible: + contains: + const: renesas,r9a09g047-tsu + then: + required: + - resets + - renesas,tsu-trim + + - if: + properties: + compatible: + contains: + const: renesas,r9a09g077-tsu + then: + properties: + resets: false + renesas,tsu-trim: false additionalProperties: false diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c index 685a5aee5e0d..c5105dfc6ec9 100644 --- a/drivers/thermal/broadcom/bcm2835_thermal.c +++ b/drivers/thermal/broadcom/bcm2835_thermal.c @@ -11,6 +11,7 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/kernel.h> +#include <linux/minmax.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> @@ -80,12 +81,7 @@ static int bcm2835_thermal_temp2adc(int temp, int offset, int slope) temp -= offset; temp /= slope; - if (temp < 0) - temp = 0; - if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS)) - temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1; - - return temp; + return clamp(temp, 0, (int)BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1); } static int bcm2835_thermal_get_temp(struct thermal_zone_device *tz, int *temp) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index ab55b20cda47..a9617d5e0077 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -44,6 +44,11 @@ #define LVTS_EDATA01(__base) (__base + 0x0058) #define LVTS_EDATA02(__base) (__base + 0x005C) #define LVTS_EDATA03(__base) (__base + 0x0060) +#define LVTS_MSROFT(__base) (__base + 0x006C) +#define LVTS_ATP0(__base) (__base + 0x0070) +#define LVTS_ATP1(__base) (__base + 0x0074) +#define LVTS_ATP2(__base) (__base + 0x0078) +#define LVTS_ATP3(__base) (__base + 0x007C) #define LVTS_MSR0(__base) (__base + 0x0090) #define LVTS_MSR1(__base) (__base + 0x0094) #define LVTS_MSR2(__base) (__base + 0x0098) @@ -85,30 +90,43 @@ #define LVTS_GOLDEN_TEMP_DEFAULT 50 #define LVTS_COEFF_A_MT8195 -250460 #define LVTS_COEFF_B_MT8195 250460 +#define LVTS_COEFF_A_MT7987 -204650 +#define LVTS_COEFF_B_MT7987 204650 #define LVTS_COEFF_A_MT7988 -204650 #define LVTS_COEFF_B_MT7988 204650 +#define LVTS_COEFF_A_MT8196 391460 +#define LVTS_COEFF_B_MT8196 -391460 -#define LVTS_MSR_IMMEDIATE_MODE 0 -#define LVTS_MSR_FILTERED_MODE 1 +#define LVTS_MSR_OFFSET_MT8196 -984 #define LVTS_MSR_READ_TIMEOUT_US 400 #define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) #define LVTS_MINIMUM_THRESHOLD 20000 +#define LVTS_MAX_CAL_OFFSETS 3 +#define LVTS_NUM_CAL_OFFSETS_MT7988 3 +#define LVTS_NUM_CAL_OFFSETS_MT8196 2 + static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; static int golden_temp_offset; +enum lvts_msr_mode { + LVTS_MSR_IMMEDIATE_MODE, + LVTS_MSR_FILTERED_MODE, + LVTS_MSR_ATP_MODE, +}; + struct lvts_sensor_data { int dt_id; - u8 cal_offsets[3]; + u8 cal_offsets[LVTS_MAX_CAL_OFFSETS]; }; struct lvts_ctrl_data { struct lvts_sensor_data lvts_sensor[LVTS_SENSOR_MAX]; u8 valid_sensor_mask; int offset; - int mode; + enum lvts_msr_mode mode; }; #define VALID_SENSOR_MAP(s0, s1, s2, s3) \ @@ -123,10 +141,17 @@ struct lvts_ctrl_data { continue; \ else +struct lvts_platform_ops { + int (*lvts_raw_to_temp)(u32 raw_temp, int temp_factor); + u32 (*lvts_temp_to_raw)(int temperature, int temp_factor); +}; + struct lvts_data { const struct lvts_ctrl_data *lvts_ctrl; + const struct lvts_platform_ops *ops; const u32 *conn_cmd; const u32 *init_cmd; + int num_cal_offsets; int num_lvts_ctrl; int num_conn_cmd; int num_init_cmd; @@ -134,6 +159,7 @@ struct lvts_data { int temp_offset; int gt_calib_bit_offset; unsigned int def_calibration; + u16 msr_offset; }; struct lvts_sensor { @@ -202,6 +228,11 @@ static const struct debugfs_reg32 lvts_regs[] = { LVTS_DEBUG_FS_REGS(LVTS_EDATA01), LVTS_DEBUG_FS_REGS(LVTS_EDATA02), LVTS_DEBUG_FS_REGS(LVTS_EDATA03), + LVTS_DEBUG_FS_REGS(LVTS_MSROFT), + LVTS_DEBUG_FS_REGS(LVTS_ATP0), + LVTS_DEBUG_FS_REGS(LVTS_ATP1), + LVTS_DEBUG_FS_REGS(LVTS_ATP2), + LVTS_DEBUG_FS_REGS(LVTS_ATP3), LVTS_DEBUG_FS_REGS(LVTS_MSR0), LVTS_DEBUG_FS_REGS(LVTS_MSR1), LVTS_DEBUG_FS_REGS(LVTS_MSR2), @@ -269,7 +300,17 @@ static inline int lvts_debugfs_init(struct device *dev, #endif -static int lvts_raw_to_temp(u32 raw_temp, int temp_factor) +static int lvts_raw_to_temp(u32 raw_temp, const struct lvts_data *lvts_data) +{ + return lvts_data->ops->lvts_raw_to_temp(raw_temp & 0xFFFF, lvts_data->temp_factor); +} + +static u32 lvts_temp_to_raw(int temperature, const struct lvts_data *lvts_data) +{ + return lvts_data->ops->lvts_temp_to_raw(temperature, lvts_data->temp_factor); +} + +static int lvts_raw_to_temp_mt7988(u32 raw_temp, int temp_factor) { int temperature; @@ -279,7 +320,7 @@ static int lvts_raw_to_temp(u32 raw_temp, int temp_factor) return temperature; } -static u32 lvts_temp_to_raw(int temperature, int temp_factor) +static u32 lvts_temp_to_raw_mt7988(int temperature, int temp_factor) { u32 raw_temp = ((s64)(golden_temp_offset - temperature)) << 14; @@ -288,6 +329,15 @@ static u32 lvts_temp_to_raw(int temperature, int temp_factor) return raw_temp; } +static u32 lvts_temp_to_raw_mt8196(int temperature, int temp_factor) +{ + u32 raw_temp; + + raw_temp = temperature - golden_temp_offset; + + return div_s64((s64)temp_factor << 14, raw_temp); +} + static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) { struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); @@ -326,7 +376,7 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) if (rc) return -EAGAIN; - *temp = lvts_raw_to_temp(value & 0xFFFF, lvts_data->temp_factor); + *temp = lvts_raw_to_temp(value, lvts_data); return 0; } @@ -396,8 +446,8 @@ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) const struct lvts_data *lvts_data = lvts_ctrl->lvts_data; void __iomem *base = lvts_sensor->base; u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD, - lvts_data->temp_factor); - u32 raw_high = lvts_temp_to_raw(high, lvts_data->temp_factor); + lvts_data); + u32 raw_high = lvts_temp_to_raw(high, lvts_data); bool should_update_thresh; lvts_sensor->low_thresh = low; @@ -599,6 +649,13 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, LVTS_IMMD3(lvts_ctrl->base) }; + void __iomem *atp_regs[] = { + LVTS_ATP0(lvts_ctrl->base), + LVTS_ATP1(lvts_ctrl->base), + LVTS_ATP2(lvts_ctrl->base), + LVTS_ATP3(lvts_ctrl->base) + }; + int i; lvts_for_each_valid_sensor(i, lvts_ctrl_data) { @@ -634,8 +691,20 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, /* * Each sensor has its own register address to read from. */ - lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ? - imm_regs[i] : msr_regs[i]; + switch (lvts_ctrl_data->mode) { + case LVTS_MSR_IMMEDIATE_MODE: + lvts_sensor[i].msr = imm_regs[i]; + break; + case LVTS_MSR_FILTERED_MODE: + lvts_sensor[i].msr = msr_regs[i]; + break; + case LVTS_MSR_ATP_MODE: + lvts_sensor[i].msr = atp_regs[i]; + break; + default: + lvts_sensor[i].msr = imm_regs[i]; + break; + } lvts_sensor[i].low_thresh = INT_MIN; lvts_sensor[i].high_thresh = INT_MIN; @@ -646,6 +715,26 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, return 0; } +static int lvts_decode_sensor_calibration(const struct lvts_sensor_data *sensor, + const u8 *efuse_calibration, u32 calib_len, + u8 num_offsets, u32 *calib) +{ + int i; + u32 calib_val = 0; + + for (i = 0; i < num_offsets; i++) { + u8 offset = sensor->cal_offsets[i]; + + if (offset >= calib_len) + return -EINVAL; + // Pack each calibration byte into the correct position + calib_val |= efuse_calibration[offset] << (8 * i); + } + + *calib = calib_val; + return 0; +} + /* * The efuse blob values follows the sensor enumeration per thermal * controller. The decoding of the stream is as follow: @@ -702,6 +791,39 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, * <-----ap--tc#3-----> <-----sensor#7-----> <-----sensor#8-----> * 0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 | 0x48 * + * MT8196 : + * Stream index map for MCU Domain mt8196 : + * + * <-sensor#1--> <-sensor#0--> <-sensor#3--> <-sensor#2--> + * 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 | 0x0A | 0x0B + * + * <-sensor#5--> <-sensor#4--> <-sensor#7--> <-sensor#6--> + * 0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12 | 0x13 + * + * <-sensor#9--> <-sensor#8--> <-sensor#11-> <-sensor#10-> + * 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0X1B + * + * <-sensor#13-> <-sensor#12-> <-sensor#15-> <-sensor#14-> + * 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 | 0x22 | 0x23 + * + * Stream index map for APU Domain mt8196 : + * + * <-sensor#1--> <-sensor#0--> <-sensor#3--> <-sensor#2--> + * 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A | 0x2B + * + * Stream index map for GPU Domain mt8196 : + * + * <-sensor#1--> <-sensor#0--> + * 0x2C | 0x2D | 0x2E | 0x2F + * + * Stream index map for AP Domain mt8196 : + * + * <-sensor#1--> <-sensor#0--> <-sensor#3--> <-sensor#2--> + * 0x30 | 0x31 | 0x32 | 0x33 | 0x34 | 0x35 | 0x36 | 0x37 + * + * <-sensor#5--> <-sensor#4--> <-sensor#6--> <-sensor#7--> + * 0x38 | 0x39 | 0x3A | 0x3B | 0x3C | 0x3D | 0x3E | 0x3F + * * Note: In some cases, values don't strictly follow a little endian ordering. * The data description gives byte offsets constituting each calibration value * for each sensor. @@ -711,26 +833,29 @@ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl u8 *efuse_calibration, size_t calib_len) { - int i; + const struct lvts_data *lvts_data = lvts_ctrl->lvts_data; + int i, ret; u32 gt; /* A zero value for gt means that device has invalid efuse data */ - gt = (((u32 *)efuse_calibration)[0] >> lvts_ctrl->lvts_data->gt_calib_bit_offset) & 0xff; + gt = (((u32 *)efuse_calibration)[0] >> lvts_data->gt_calib_bit_offset) & 0xff; lvts_for_each_valid_sensor(i, lvts_ctrl_data) { const struct lvts_sensor_data *sensor = &lvts_ctrl_data->lvts_sensor[i]; + u32 calib = 0; - if (sensor->cal_offsets[0] >= calib_len || - sensor->cal_offsets[1] >= calib_len || - sensor->cal_offsets[2] >= calib_len) - return -EINVAL; + ret = lvts_decode_sensor_calibration(sensor, efuse_calibration, + calib_len, + lvts_data->num_cal_offsets, + &calib); + if (ret) + return ret; if (gt) { - lvts_ctrl->calibration[i] = - (efuse_calibration[sensor->cal_offsets[0]] << 0) + - (efuse_calibration[sensor->cal_offsets[1]] << 8) + - (efuse_calibration[sensor->cal_offsets[2]] << 16); + lvts_ctrl->calibration[i] = calib; + if (lvts_ctrl->lvts_data->msr_offset) + lvts_ctrl->calibration[i] += lvts_ctrl->lvts_data->msr_offset; } else if (lvts_ctrl->lvts_data->def_calibration) { lvts_ctrl->calibration[i] = lvts_ctrl->lvts_data->def_calibration; } else { @@ -884,7 +1009,7 @@ static void lvts_ctrl_monitor_enable(struct device *dev, struct lvts_ctrl *lvts_ u32 sensor_map = 0; int i; - if (lvts_ctrl->mode != LVTS_MSR_FILTERED_MODE) + if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) return; if (enable) { @@ -1038,6 +1163,17 @@ static int lvts_ctrl_calibrate(struct device *dev, struct lvts_ctrl *lvts_ctrl) for (i = 0; i < LVTS_SENSOR_MAX; i++) writel(lvts_ctrl->calibration[i], lvts_edata[i]); + /* LVTS_MSROFT : Constant offset applied to MSR values + * for post-processing + * + * Bits: + * + * 20-0 : Constant data added to MSR values + */ + if (lvts_ctrl->lvts_data->msr_offset) + writel(lvts_ctrl->lvts_data->msr_offset, + LVTS_MSROFT(lvts_ctrl->base)); + return 0; } @@ -1373,6 +1509,20 @@ static void lvts_remove(struct platform_device *pdev) lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); } +static const struct lvts_ctrl_data mt7987_lvts_ap_data_ctrl[] = { + { + .lvts_sensor = { + { .dt_id = MT7987_CPU, + .cal_offsets = { 0x04, 0x05, 0x06 } }, + { .dt_id = MT7987_ETH2P5G, + .cal_offsets = { 0x08, 0x09, 0x0a } }, + }, + VALID_SENSOR_MAP(1, 1, 0, 0), + .offset = 0x0, + .mode = LVTS_MSR_FILTERED_MODE, + }, +}; + static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { { .lvts_sensor = { @@ -1455,6 +1605,12 @@ static const u32 default_init_cmds[] = { 0xC10300FC, 0xC103009D, 0xC10300F1, 0xC10300E1 }; +static const u32 mt7987_init_cmds[] = { + 0xC1030300, 0xC1030420, 0xC1030500, 0xC10307A6, 0xC10308C7, + 0xC103098D, 0xC1030C7C, 0xC1030AA8, 0xC10308CE, 0xC10308C7, + 0xC1030B04, 0xC1030E01, 0xC10306B8 +}; + static const u32 mt7988_init_cmds[] = { 0xC1030300, 0xC1030420, 0xC1030500, 0xC10307A6, 0xC1030CFC, 0xC1030A8C, 0xC103098D, 0xC10308F1, 0xC1030B04, 0xC1030E01, @@ -1753,6 +1909,125 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { } }; +static const struct lvts_ctrl_data mt8196_lvts_mcu_data_ctrl[] = { + { + .lvts_sensor = { + { .dt_id = MT8196_MCU_MEDIUM_CPU6_0, + .cal_offsets = { 0x06, 0x07 } }, + { .dt_id = MT8196_MCU_MEDIUM_CPU6_1, + .cal_offsets = { 0x04, 0x05 } }, + { .dt_id = MT8196_MCU_DSU2, + .cal_offsets = { 0x0A, 0x0B } }, + { .dt_id = MT8196_MCU_DSU3, + .cal_offsets = { 0x08, 0x09 } } + }, + VALID_SENSOR_MAP(1, 1, 1, 1), + .offset = 0x0, + .mode = LVTS_MSR_ATP_MODE, + }, + { + .lvts_sensor = { + { .dt_id = MT8196_MCU_LITTLE_CPU3, + .cal_offsets = { 0x0E, 0x0F } }, + { .dt_id = MT8196_MCU_LITTLE_CPU0, + .cal_offsets = { 0x0C, 0x0D } }, + { .dt_id = MT8196_MCU_LITTLE_CPU1, + .cal_offsets = { 0x12, 0x13 } }, + { .dt_id = MT8196_MCU_LITTLE_CPU2, + .cal_offsets = { 0x10, 0x11 } } + }, + VALID_SENSOR_MAP(1, 1, 1, 1), + .offset = 0x100, + .mode = LVTS_MSR_ATP_MODE, + }, + { + .lvts_sensor = { + { .dt_id = MT8196_MCU_MEDIUM_CPU4_0, + .cal_offsets = { 0x16, 0x17 } }, + { .dt_id = MT8196_MCU_MEDIUM_CPU4_1, + .cal_offsets = { 0x14, 0x15 } }, + { .dt_id = MT8196_MCU_MEDIUM_CPU5_0, + .cal_offsets = { 0x1A, 0x1B } }, + { .dt_id = MT8196_MCU_MEDIUM_CPU5_1, + .cal_offsets = { 0x18, 0x19 } } + }, + VALID_SENSOR_MAP(1, 1, 1, 1), + .offset = 0x200, + .mode = LVTS_MSR_ATP_MODE, + }, + { + .lvts_sensor = { + { .dt_id = MT8196_MCU_DSU0, + .cal_offsets = { 0x1E, 0x1F } }, + { .dt_id = MT8196_MCU_DSU1, + .cal_offsets = { 0x1C, 0x1D } }, + { .dt_id = MT8196_MCU_BIG_CPU7_0, + .cal_offsets = { 0x22, 0x23 } }, + { .dt_id = MT8196_MCU_BIG_CPU7_1, + .cal_offsets = { 0x20, 0x21 } } + }, + VALID_SENSOR_MAP(1, 1, 1, 1), + .offset = 0x300, + .mode = LVTS_MSR_ATP_MODE, + } +}; + +static const struct lvts_ctrl_data mt8196_lvts_ap_data_ctrl[] = { + { + .lvts_sensor = { + { .dt_id = MT8196_AP_TOP0, + .cal_offsets = { 0x32, 0x33 } }, + { .dt_id = MT8196_AP_TOP1, + .cal_offsets = { 0x30, 0x31 } }, + { .dt_id = MT8196_AP_TOP2, + .cal_offsets = { 0x36, 0x37 } }, + { .dt_id = MT8196_AP_TOP3, + .cal_offsets = { 0x34, 0x35 } } + }, + VALID_SENSOR_MAP(1, 1, 1, 1), + .offset = 0x0, + .mode = LVTS_MSR_ATP_MODE, + }, + { + .lvts_sensor = { + { .dt_id = MT8196_AP_BOT0, + .cal_offsets = { 0x3A, 0x3B } }, + { .dt_id = MT8196_AP_BOT1, + .cal_offsets = { 0x38, 0x39 } }, + { .dt_id = MT8196_AP_BOT2, + .cal_offsets = { 0x3E, 0x3F } }, + { .dt_id = MT8196_AP_BOT3, + .cal_offsets = { 0x3C, 0x3D } } + }, + VALID_SENSOR_MAP(1, 1, 1, 1), + .offset = 0x100, + .mode = LVTS_MSR_ATP_MODE, + } +}; + +static const struct lvts_platform_ops lvts_platform_ops_mt7988 = { + .lvts_raw_to_temp = lvts_raw_to_temp_mt7988, + .lvts_temp_to_raw = lvts_temp_to_raw_mt7988, +}; + +static const struct lvts_platform_ops lvts_platform_ops_mt8196 = { + .lvts_raw_to_temp = lvts_raw_to_temp_mt7988, + .lvts_temp_to_raw = lvts_temp_to_raw_mt8196, +}; + +static const struct lvts_data mt7987_lvts_ap_data = { + .lvts_ctrl = mt7987_lvts_ap_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt7987_lvts_ap_data_ctrl), + .conn_cmd = mt7988_conn_cmds, + .init_cmd = mt7987_init_cmds, + .num_conn_cmd = ARRAY_SIZE(mt7988_conn_cmds), + .num_init_cmd = ARRAY_SIZE(mt7987_init_cmds), + .temp_factor = LVTS_COEFF_A_MT7987, + .temp_offset = LVTS_COEFF_B_MT7987, + .gt_calib_bit_offset = 32, + .def_calibration = 19380, +}; + static const struct lvts_data mt7988_lvts_ap_data = { .lvts_ctrl = mt7988_lvts_ap_data_ctrl, .conn_cmd = mt7988_conn_cmds, @@ -1763,6 +2038,8 @@ static const struct lvts_data mt7988_lvts_ap_data = { .temp_factor = LVTS_COEFF_A_MT7988, .temp_offset = LVTS_COEFF_B_MT7988, .gt_calib_bit_offset = 24, + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, + .ops = &lvts_platform_ops_mt7988, }; static const struct lvts_data mt8186_lvts_data = { @@ -1776,6 +2053,8 @@ static const struct lvts_data mt8186_lvts_data = { .temp_offset = LVTS_COEFF_B_MT7988, .gt_calib_bit_offset = 24, .def_calibration = 19000, + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, + .ops = &lvts_platform_ops_mt7988, }; static const struct lvts_data mt8188_lvts_mcu_data = { @@ -1789,6 +2068,8 @@ static const struct lvts_data mt8188_lvts_mcu_data = { .temp_offset = LVTS_COEFF_B_MT8195, .gt_calib_bit_offset = 20, .def_calibration = 35000, + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, + .ops = &lvts_platform_ops_mt7988, }; static const struct lvts_data mt8188_lvts_ap_data = { @@ -1802,6 +2083,8 @@ static const struct lvts_data mt8188_lvts_ap_data = { .temp_offset = LVTS_COEFF_B_MT8195, .gt_calib_bit_offset = 20, .def_calibration = 35000, + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, + .ops = &lvts_platform_ops_mt7988, }; static const struct lvts_data mt8192_lvts_mcu_data = { @@ -1815,6 +2098,8 @@ static const struct lvts_data mt8192_lvts_mcu_data = { .temp_offset = LVTS_COEFF_B_MT8195, .gt_calib_bit_offset = 24, .def_calibration = 35000, + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, + .ops = &lvts_platform_ops_mt7988, }; static const struct lvts_data mt8192_lvts_ap_data = { @@ -1828,6 +2113,8 @@ static const struct lvts_data mt8192_lvts_ap_data = { .temp_offset = LVTS_COEFF_B_MT8195, .gt_calib_bit_offset = 24, .def_calibration = 35000, + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, + .ops = &lvts_platform_ops_mt7988, }; static const struct lvts_data mt8195_lvts_mcu_data = { @@ -1841,6 +2128,8 @@ static const struct lvts_data mt8195_lvts_mcu_data = { .temp_offset = LVTS_COEFF_B_MT8195, .gt_calib_bit_offset = 24, .def_calibration = 35000, + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, + .ops = &lvts_platform_ops_mt7988, }; static const struct lvts_data mt8195_lvts_ap_data = { @@ -1854,9 +2143,36 @@ static const struct lvts_data mt8195_lvts_ap_data = { .temp_offset = LVTS_COEFF_B_MT8195, .gt_calib_bit_offset = 24, .def_calibration = 35000, + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT7988, + .ops = &lvts_platform_ops_mt7988, +}; + +static const struct lvts_data mt8196_lvts_mcu_data = { + .lvts_ctrl = mt8196_lvts_mcu_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8196_lvts_mcu_data_ctrl), + .temp_factor = LVTS_COEFF_A_MT8196, + .temp_offset = LVTS_COEFF_B_MT8196, + .gt_calib_bit_offset = 0, + .def_calibration = 14437, + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT8196, + .msr_offset = LVTS_MSR_OFFSET_MT8196, + .ops = &lvts_platform_ops_mt8196, +}; + +static const struct lvts_data mt8196_lvts_ap_data = { + .lvts_ctrl = mt8196_lvts_ap_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8196_lvts_ap_data_ctrl), + .temp_factor = LVTS_COEFF_A_MT8196, + .temp_offset = LVTS_COEFF_B_MT8196, + .gt_calib_bit_offset = 0, + .def_calibration = 14437, + .num_cal_offsets = LVTS_NUM_CAL_OFFSETS_MT8196, + .msr_offset = LVTS_MSR_OFFSET_MT8196, + .ops = &lvts_platform_ops_mt8196, }; static const struct of_device_id lvts_of_match[] = { + { .compatible = "mediatek,mt7987-lvts-ap", .data = &mt7987_lvts_ap_data }, { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data }, { .compatible = "mediatek,mt8186-lvts", .data = &mt8186_lvts_data }, { .compatible = "mediatek,mt8188-lvts-mcu", .data = &mt8188_lvts_mcu_data }, @@ -1865,6 +2181,8 @@ static const struct of_device_id lvts_of_match[] = { { .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data }, { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data }, + { .compatible = "mediatek,mt8196-lvts-mcu", .data = &mt8196_lvts_mcu_data }, + { .compatible = "mediatek,mt8196-lvts-ap", .data = &mt8196_lvts_ap_data }, {}, }; MODULE_DEVICE_TABLE(of, lvts_of_match); diff --git a/drivers/thermal/renesas/rzg3e_thermal.c b/drivers/thermal/renesas/rzg3e_thermal.c index e66d73ca6752..dde021e283b7 100644 --- a/drivers/thermal/renesas/rzg3e_thermal.c +++ b/drivers/thermal/renesas/rzg3e_thermal.c @@ -4,6 +4,7 @@ * * Copyright (C) 2025 Renesas Electronics Corporation */ +#include <linux/arm-smccc.h> #include <linux/clk.h> #include <linux/cleanup.h> #include <linux/delay.h> @@ -62,8 +63,6 @@ #define TSU_SICR_CMPCLR BIT(1) /* Temperature calculation constants from datasheet */ -#define TSU_TEMP_D (-41) -#define TSU_TEMP_E 126 #define TSU_CODE_MAX 0xFFF /* Timing specifications from datasheet */ @@ -72,6 +71,18 @@ #define TSU_POLL_DELAY_US 10 /* Polling interval */ #define TSU_MIN_CLOCK_RATE 24000000 /* TSU_PCLK minimum 24MHz */ +#define RZ_SIP_SVC_GET_SYSTSU 0x82000022 +#define OTP_TSU_REG_ADR_TEMPHI 0x01DC +#define OTP_TSU_REG_ADR_TEMPLO 0x01DD + +struct rzg3e_thermal_priv; + +struct rzg3e_thermal_info { + int (*get_trim)(struct rzg3e_thermal_priv *priv); + int temp_d_mc; + int temp_e_mc; +}; + /** * struct rzg3e_thermal_priv - RZ/G3E TSU private data * @base: TSU register base @@ -79,6 +90,7 @@ * @syscon: regmap for calibration values * @zone: thermal zone device * @rstc: reset control + * @info: chip type specific information * @trmval0: calibration value 0 (b) * @trmval1: calibration value 1 (c) * @trim_offset: offset for trim registers in syscon @@ -87,12 +99,11 @@ struct rzg3e_thermal_priv { void __iomem *base; struct device *dev; - struct regmap *syscon; struct thermal_zone_device *zone; struct reset_control *rstc; + const struct rzg3e_thermal_info *info; u16 trmval0; u16 trmval1; - u32 trim_offset; struct mutex lock; }; @@ -161,17 +172,17 @@ static void rzg3e_thermal_power_off(struct rzg3e_thermal_priv *priv) */ static int rzg3e_thermal_code_to_temp(struct rzg3e_thermal_priv *priv, u16 code) { - int temp_e_mc = TSU_TEMP_E * MILLIDEGREE_PER_DEGREE; - int temp_d_mc = TSU_TEMP_D * MILLIDEGREE_PER_DEGREE; + const struct rzg3e_thermal_info *info = priv->info; s64 numerator, denominator; int temp_mc; - numerator = (temp_e_mc - temp_d_mc) * (s64)(code - priv->trmval0); + numerator = (info->temp_e_mc - info->temp_d_mc) * + (s64)(code - priv->trmval0); denominator = priv->trmval1 - priv->trmval0; - temp_mc = div64_s64(numerator, denominator) + temp_d_mc; + temp_mc = div64_s64(numerator, denominator) + info->temp_d_mc; - return clamp(temp_mc, temp_d_mc, temp_e_mc); + return clamp(temp_mc, info->temp_d_mc, info->temp_e_mc); } /* @@ -180,13 +191,12 @@ static int rzg3e_thermal_code_to_temp(struct rzg3e_thermal_priv *priv, u16 code) */ static u16 rzg3e_thermal_temp_to_code(struct rzg3e_thermal_priv *priv, int temp_mc) { - int temp_e_mc = TSU_TEMP_E * MILLIDEGREE_PER_DEGREE; - int temp_d_mc = TSU_TEMP_D * MILLIDEGREE_PER_DEGREE; + const struct rzg3e_thermal_info *info = priv->info; s64 numerator, denominator; s64 code; - numerator = (temp_mc - temp_d_mc) * (priv->trmval1 - priv->trmval0); - denominator = temp_e_mc - temp_d_mc; + numerator = (temp_mc - info->temp_d_mc) * (priv->trmval1 - priv->trmval0); + denominator = info->temp_e_mc - info->temp_d_mc; code = div64_s64(numerator, denominator) + priv->trmval0; @@ -330,48 +340,45 @@ static const struct thermal_zone_device_ops rzg3e_tz_ops = { .set_trips = rzg3e_thermal_set_trips, }; -static int rzg3e_thermal_get_calibration(struct rzg3e_thermal_priv *priv) +static int rzg3e_thermal_get_syscon_trim(struct rzg3e_thermal_priv *priv) { - u32 val; + struct device_node *np = priv->dev->of_node; + struct regmap *syscon; + u32 offset; int ret; + u32 val; + + syscon = syscon_regmap_lookup_by_phandle_args(np, "renesas,tsu-trim", 1, &offset); + if (IS_ERR(syscon)) + return dev_err_probe(priv->dev, PTR_ERR(syscon), + "Failed to parse renesas,tsu-trim\n"); /* Read calibration values from syscon */ - ret = regmap_read(priv->syscon, priv->trim_offset, &val); + ret = regmap_read(syscon, offset, &val); if (ret) return ret; - priv->trmval0 = val & GENMASK(11, 0); + priv->trmval0 = val & TSU_CODE_MAX; - ret = regmap_read(priv->syscon, priv->trim_offset + 4, &val); + ret = regmap_read(syscon, offset + 4, &val); if (ret) return ret; - priv->trmval1 = val & GENMASK(11, 0); - - /* Validate calibration data */ - if (!priv->trmval0 || !priv->trmval1 || - priv->trmval0 == priv->trmval1 || - priv->trmval0 == 0xFFF || priv->trmval1 == 0xFFF) { - dev_err(priv->dev, "Invalid calibration: b=0x%03x, c=0x%03x\n", - priv->trmval0, priv->trmval1); - return -EINVAL; - } - - dev_dbg(priv->dev, "Calibration: b=0x%03x (%u), c=0x%03x (%u)\n", - priv->trmval0, priv->trmval0, priv->trmval1, priv->trmval1); + priv->trmval1 = val & TSU_CODE_MAX; return 0; } -static int rzg3e_thermal_parse_dt(struct rzg3e_thermal_priv *priv) +static int rzg3e_thermal_get_smc_trim(struct rzg3e_thermal_priv *priv) { - struct device_node *np = priv->dev->of_node; - u32 offset; + struct arm_smccc_res local_res; - priv->syscon = syscon_regmap_lookup_by_phandle_args(np, "renesas,tsu-trim", 1, &offset); - if (IS_ERR(priv->syscon)) - return dev_err_probe(priv->dev, PTR_ERR(priv->syscon), - "Failed to parse renesas,tsu-trim\n"); + arm_smccc_smc(RZ_SIP_SVC_GET_SYSTSU, OTP_TSU_REG_ADR_TEMPLO, + 0, 0, 0, 0, 0, 0, &local_res); + priv->trmval0 = local_res.a0 & TSU_CODE_MAX; + + arm_smccc_smc(RZ_SIP_SVC_GET_SYSTSU, OTP_TSU_REG_ADR_TEMPHI, + 0, 0, 0, 0, 0, 0, &local_res); + priv->trmval1 = local_res.a0 & TSU_CODE_MAX; - priv->trim_offset = offset; return 0; } @@ -392,15 +399,26 @@ static int rzg3e_thermal_probe(struct platform_device *pdev) return ret; platform_set_drvdata(pdev, priv); + priv->info = device_get_match_data(dev); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - /* Parse device tree for trim register info */ - ret = rzg3e_thermal_parse_dt(priv); + ret = priv->info->get_trim(priv); if (ret) return ret; + if (!priv->trmval0 || !priv->trmval1 || + priv->trmval0 == priv->trmval1 || + priv->trmval0 == TSU_CODE_MAX || priv->trmval1 == TSU_CODE_MAX) + return dev_err_probe(priv->dev, -EINVAL, + "Invalid calibration: b=0x%03x, c=0x%03x\n", + priv->trmval0, priv->trmval1); + + dev_dbg(priv->dev, "Calibration: b=0x%03x (%u), c=0x%03x (%u)\n", + priv->trmval0, priv->trmval0, priv->trmval1, priv->trmval1); + /* Get clock to verify frequency - clock is managed by power domain */ clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) @@ -412,17 +430,11 @@ static int rzg3e_thermal_probe(struct platform_device *pdev) "Clock rate %lu Hz too low (min %u Hz)\n", clk_get_rate(clk), TSU_MIN_CLOCK_RATE); - priv->rstc = devm_reset_control_get_exclusive_deasserted(dev, NULL); + priv->rstc = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL); if (IS_ERR(priv->rstc)) return dev_err_probe(dev, PTR_ERR(priv->rstc), "Failed to get/deassert reset control\n"); - /* Get calibration data */ - ret = rzg3e_thermal_get_calibration(priv); - if (ret) - return dev_err_probe(dev, ret, - "Failed to get valid calibration data\n"); - /* Get comparison interrupt */ irq = platform_get_irq_byname(pdev, "adcmpi"); if (irq < 0) @@ -526,8 +538,21 @@ static const struct dev_pm_ops rzg3e_thermal_pm_ops = { SYSTEM_SLEEP_PM_OPS(rzg3e_thermal_suspend, rzg3e_thermal_resume) }; +static const struct rzg3e_thermal_info rzg3e_thermal_info = { + .get_trim = rzg3e_thermal_get_syscon_trim, + .temp_d_mc = -41000, + .temp_e_mc = 126000, +}; + +static const struct rzg3e_thermal_info rzt2h_thermal_info = { + .get_trim = rzg3e_thermal_get_smc_trim, + .temp_d_mc = -40000, + .temp_e_mc = 125000, +}; + static const struct of_device_id rzg3e_thermal_dt_ids[] = { - { .compatible = "renesas,r9a09g047-tsu" }, + { .compatible = "renesas,r9a09g047-tsu", .data = &rzg3e_thermal_info }, + { .compatible = "renesas,r9a09g077-tsu", .data = &rzt2h_thermal_info }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, rzg3e_thermal_dt_ids); diff --git a/drivers/thermal/st/stm_thermal.c b/drivers/thermal/st/stm_thermal.c index 6e90eb9f414d..5d8170bfb382 100644 --- a/drivers/thermal/st/stm_thermal.c +++ b/drivers/thermal/st/stm_thermal.c @@ -16,6 +16,7 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/thermal.h> +#include <linux/units.h> #include "../thermal_hwmon.h" @@ -76,7 +77,6 @@ /* Constants */ #define ADJUST 100 -#define ONE_MHZ 1000000 #define POLL_TIMEOUT 5000 #define STARTUP_TIME 40 #define TS1_T0_VAL0 30000 /* 30 celsius */ @@ -205,7 +205,7 @@ static int stm_thermal_calibration(struct stm_thermal_sensor *sensor) return -EINVAL; prescaler = 0; - clk_freq /= ONE_MHZ; + clk_freq /= HZ_PER_MHZ; if (clk_freq) { while (prescaler <= clk_freq) prescaler++; diff --git a/include/dt-bindings/thermal/mediatek,lvts-thermal.h b/include/dt-bindings/thermal/mediatek,lvts-thermal.h index ddc7302a510a..350f98178b26 100644 --- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h +++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h @@ -7,6 +7,9 @@ #ifndef __MEDIATEK_LVTS_DT_H #define __MEDIATEK_LVTS_DT_H +#define MT7987_CPU 0 +#define MT7987_ETH2P5G 1 + #define MT7988_CPU_0 0 #define MT7988_CPU_1 1 #define MT7988_ETH2P5G_0 2 @@ -80,4 +83,30 @@ #define MT8192_AP_MD1 15 #define MT8192_AP_MD2 16 +#define MT8196_MCU_MEDIUM_CPU6_0 0 +#define MT8196_MCU_MEDIUM_CPU6_1 1 +#define MT8196_MCU_DSU2 2 +#define MT8196_MCU_DSU3 3 +#define MT8196_MCU_LITTLE_CPU3 4 +#define MT8196_MCU_LITTLE_CPU0 5 +#define MT8196_MCU_LITTLE_CPU1 6 +#define MT8196_MCU_LITTLE_CPU2 7 +#define MT8196_MCU_MEDIUM_CPU4_0 8 +#define MT8196_MCU_MEDIUM_CPU4_1 9 +#define MT8196_MCU_MEDIUM_CPU5_0 10 +#define MT8196_MCU_MEDIUM_CPU5_1 11 +#define MT8196_MCU_DSU0 12 +#define MT8196_MCU_DSU1 13 +#define MT8196_MCU_BIG_CPU7_0 14 +#define MT8196_MCU_BIG_CPU7_1 15 + +#define MT8196_AP_TOP0 0 +#define MT8196_AP_TOP1 1 +#define MT8196_AP_TOP2 2 +#define MT8196_AP_TOP3 3 +#define MT8196_AP_BOT0 4 +#define MT8196_AP_BOT1 5 +#define MT8196_AP_BOT2 6 +#define MT8196_AP_BOT3 7 + #endif /* __MEDIATEK_LVTS_DT_H */ diff --git a/tools/lib/thermal/libthermal.pc.template b/tools/lib/thermal/libthermal.pc.template index ac24d0ab17f5..3b8a24d0a8b8 100644 --- a/tools/lib/thermal/libthermal.pc.template +++ b/tools/lib/thermal/libthermal.pc.template @@ -8,5 +8,5 @@ Name: libthermal Description: thermal library Requires: libnl-3.0 libnl-genl-3.0 Version: @VERSION@ -Libs: -L${libdir} -lnl-genl-3 -lnl-3 -Cflags: -I${includedir} -I${include}/libnl3 +Libs: -L${libdir} -lnl-genl-3 -lnl-3 -lthermal +Cflags: -I${includedir} -I${includedir}/libnl3 |
