From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A5695CAC5AE for ; Fri, 26 Sep 2025 07:35:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:References: Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID:Date:Subject: In-Reply-To:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=cCzkhJP4gAFLyAy7z0zZkE3VcC0H11Y3P2M1GkPl27o=; b=VLWYdCn/jbk/mCavIEmqlBX8mU awjaQRsNead/wZe244ExBfXvqKB1YYk3yUL1IW7gd3GDfsvb6T12KlqrA00su2wtU0DGdaF5kCGOg Z4zNbNlwxSkwlDU9y7qf81d5ZKUjXvzOUrrPweE+PltlVst2fZtw3dY1t9EXHZeOTQjHphdqnv3hp hCZLG4fMf8VS47U07dORXqL8IZjHLR4/AuZidOvMUqUWmEb2KWteo4ql1S+T0YxNjG09rkvPj/dGg h3YhP2wTwDnpOCgli+yeiKwNuKxCftOkMTRLPqQDx8BeGyGsov/cA3npDmX9ZuLCXjIv8KxxhNOBL dCRe4JUg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux)) id 1v22yv-0000000Gpu7-48jw; Fri, 26 Sep 2025 07:35:05 +0000 Received: from mailout4.samsung.com ([203.254.224.34]) by bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1v22yr-0000000Gppo-3HUd for linux-arm-kernel@lists.infradead.org; Fri, 26 Sep 2025 07:35:04 +0000 Received: from epcas2p1.samsung.com (unknown [182.195.41.53]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20250926073453epoutp043a90145283699d8443bc896baa7eb165~oxNm8Mtoa3113831138epoutp04Z for ; Fri, 26 Sep 2025 07:34:53 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20250926073453epoutp043a90145283699d8443bc896baa7eb165~oxNm8Mtoa3113831138epoutp04Z DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1758872093; bh=cCzkhJP4gAFLyAy7z0zZkE3VcC0H11Y3P2M1GkPl27o=; h=From:To:Cc:In-Reply-To:Subject:Date:References:From; b=Dkef5MVaAUiAZr0zR2mcJJEbrAWcfS8KcQ0yw3EtZKOcjQSZ1PpyE58Kx4oL+CeO2 jzb7b+TjJ6sFIf0oBPSO6zjOEFGHytwa1vLCc+djAHWH3fzZ/ZY4GgajDpakBWrmuJ dqybLMPTfVwCnwTO8j9puqP70jU4u0k+tgUomjQw= Received: from epsnrtp03.localdomain (unknown [182.195.42.155]) by epcas2p4.samsung.com (KnoxPortal) with ESMTPS id 20250926073453epcas2p41e81c590683e7c50f87c7733c1de028c~oxNmggKR-2680326803epcas2p4c; Fri, 26 Sep 2025 07:34:53 +0000 (GMT) Received: from epcas2p2.samsung.com (unknown [182.195.36.89]) by epsnrtp03.localdomain (Postfix) with ESMTP id 4cY2RJ4vkpz3hhTD; Fri, 26 Sep 2025 07:34:52 +0000 (GMT) Received: from epsmtip1.samsung.com (unknown [182.195.34.30]) by epcas2p1.samsung.com (KnoxPortal) with ESMTPA id 20250926073451epcas2p1a3bc29b6727c323227aaff5c9e4eb97c~oxNlG2ZCU2538725387epcas2p1E; Fri, 26 Sep 2025 07:34:51 +0000 (GMT) Received: from KORCO115296 (unknown [12.80.207.128]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20250926073451epsmtip1ba67bb8ebc0bfa9c8b77e95f798726b1~oxNlBDWxP1291912919epsmtip1n; Fri, 26 Sep 2025 07:34:51 +0000 (GMT) From: =?ks_c_5601-1987?B?vNW9xQ==?= To: "'Henrik Grimler'" Cc: "'Bartlomiej Zolnierkiewicz'" , "'Krzysztof Kozlowski'" , "'Rafael J . Wysocki'" , "'Daniel Lezcano'" , "'Zhang Rui'" , "'Lukasz Luba'" , "'Rob Herring'" , "'Conor Dooley'" , "'Alim Akhtar'" , , , , , In-Reply-To: <20250925200813.GA4158@samsung-a5> Subject: RE: [PATCH v5 2/3] thermal: exynos_tmu: Support new hardware and update TMU interface Date: Fri, 26 Sep 2025 16:34:48 +0900 Message-ID: <000001dc2eb8$0bac3e90$2304bbb0$@samsung.com> MIME-Version: 1.0 Content-Type: text/plain; charset="ks_c_5601-1987" Content-Transfer-Encoding: 7bit X-Mailer: Microsoft Outlook 15.0 Thread-Index: AQFr8a09D+vvox1TVI2wHHgbl4MA7AKsiMJiAiAtT/ACDWS14LVOtzXw Content-Language: ko X-CMS-MailID: 20250926073451epcas2p1a3bc29b6727c323227aaff5c9e4eb97c X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P cpgsPolicy: CPGSC10-234,Y X-CFilter-Loop: Reflected X-CMS-RootMailID: 20250925022845epcas2p222efe02101d2f5a306ca9b7302e2c408 References: <20250925022841.2813150-1-shin.son@samsung.com> <20250925022841.2813150-3-shin.son@samsung.com> <20250925200813.GA4158@samsung-a5> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250926_003502_497092_B04BE716 X-CRM114-Status: GOOD ( 41.09 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Hello Henrik Grimler. > -----Original Message----- > From: Henrik Grimler [mailto:henrik@grimler.se] > Sent: Friday, September 26, 2025 5:08 AM > To: Shin Son > Cc: Bartlomiej Zolnierkiewicz ; Krzysztof Kozlowski > ; Rafael J . Wysocki ; Daniel Lezcano > ; Zhang Rui ; Lukasz Luba > ; Rob Herring ; Conor Dooley > ; Alim Akhtar ; linux- > pm@vger.kernel.org; linux-samsung-soc@vger.kernel.org; > devicetree@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux- > kernel@vger.kernel.org > Subject: Re: [PATCH v5 2/3] thermal: exynos_tmu: Support new hardware and > update TMU interface > > On Thu, Sep 25, 2025 at 11:28:39AM +0900, Shin Son wrote: > > The Exynos tmu driver's private data structure has been extended to > > support the exynosautov920 hardware, which requires per-sensor > > interrupt enablement and multiple-zone handling: > > > > - Add 'slope_comp' : compensation parameter below 25 degrees. > > - Add 'calib_temp' : stores the fused calibaration temperature. > > - Add 'sensor_count' : reflects the maximum sensor numbers. > > - Rename 'tzd' -> 'tzd_array' to register multiple thermal zones. > > > > Since splitting this patch causes runtime errors during temperature > > emulation or problems where the read temperature feature fails to > > retrieve values, I have submitted it as a single commit. To add > > support for the exynosautov920 to the exisiting TMU interface, the > > following changes are included: > > > > 1. Simplify "temp_to_code" and "code_to_temp" to one computation path > > by normalizing calib_temp. > > 2. Loop over 'sensor_count' in critical-point setup. > > 3. Introduce 'update_con_reg' for exynosautov920 control-register > updates. > > 4. Add exynosautov920-specific branch in 'exynos_tmu_update_temp' > function. > > 5. Skip high & low temperature threshold setup in exynosautov920. > > 6. Enable interrupts via sensor_count in exynosautov920. > > 7. Initialize all new members during 'exynosautov920_tmu_initialize'. > > 8. Clear IRQs by iterating the sensor_count in exynosautov920. > > 9. Register each zone with 'devm_thermal_of_zone_register()' > > based on 'sensor_count'. > > > > Signed-off-by: Shin Son > > Reviewed-by: Henrik Grimler > > Best regards, > Henrik Grimler Thank you for the review. I'll add your 'Reviewed-by' tag in the next version. Best regards, Shin Son > > > --- > > drivers/thermal/samsung/exynos_tmu.c | 322 > > ++++++++++++++++++++++++--- > > 1 file changed, 285 insertions(+), 37 deletions(-) > > > > diff --git a/drivers/thermal/samsung/exynos_tmu.c > > b/drivers/thermal/samsung/exynos_tmu.c > > index 47a99b3c5395..8fa188928b79 100644 > > --- a/drivers/thermal/samsung/exynos_tmu.c > > +++ b/drivers/thermal/samsung/exynos_tmu.c > > @@ -121,8 +121,51 @@ > > > > #define EXYNOS_NOISE_CANCEL_MODE 4 > > > > +/* ExynosAutov920 specific registers */ > > +#define EXYNOSAUTOV920_SLOPE_COMP 25 > > +#define EXYNOSAUTOV920_SLOPE_COMP_MASK 0xf > > +#define EXYNOSAUTOV920_CALIB_SEL_TEMP 30 > > +#define EXYNOSAUTOV920_CALIB_SEL_TEMP_MASK 0x2 > > + > > +#define EXYNOSAUTOV920_SENSOR0_TRIM_INFO 0x10 > > +#define EXYNOSAUTOV920_TRIM_MASK 0x1ff > > +#define EXYNOSAUTOV920_TRIMINFO_25_SHIFT 0 > > +#define EXYNOSAUTOV920_TRIMINFO_85_SHIFT 9 > > + > > +#define EXYNOSAUTOV920_TMU_REG_TRIMINFO2 0x04 > > + > > +#define EXYNOSAUTOV920_TMU_REG_THRESHOLD(p) (((p)) * 0x50 + 0x00d0) > > +#define EXYNOSAUTOV920_TMU_REG_INTEN(p) (((p)) * 0x50 + > 0x00f0) > > +#define EXYNOSAUTOV920_TMU_REG_INT_PEND(p) (((p)) * 0x50 + 0x00f8) > > + > > +#define EXYNOSAUTOV920_CURRENT_TEMP_P1_P0 0x084 > > +#define EXYNOSAUTOV920_TMU_REG_EMUL_CON 0x0b0 > > + > > +#define EXYNOSAUTOV920_TMU_REG_CONTROL 0x50 > > +#define EXYNOSAUTOV920_TMU_REG_CONTROL1 0x54 > > +#define EXYNOSAUTOV920_TMU_REG_AVG_CONTROL 0x58 > > +#define EXYNOSAUTOV920_TMU_SAMPLING_INTERVAL 0x70 > > +#define EXYNOSAUTOV920_TMU_REG_COUNTER_VALUE0 0x74 > > +#define EXYNOSAUTOV920_TMU_REG_COUNTER_VALUE1 0x78 > > + > > +#define EXYNOSAUTOV920_TMU_T_BUF_VREF_SEL_SHIFT 8 > > +#define EXYNOSAUTOV920_TMU_T_BUF_VREF_SEL_MASK 0x1f > > +#define EXYNOSAUTOV920_TMU_T_BUF_SLOPE_SEL_SHIFT 3 > > +#define EXYNOSAUTOV920_TMU_T_BUF_SLOPE_SEL_MASK 0xf > > +#define EXYNOSAUTOV920_TMU_NUM_PROBE_MASK 0xf > > +#define EXYNOSAUTOV920_TMU_NUM_PROBE_SHIFT 16 > > +#define EXYNOSAUTOV920_TMU_LPI_MODE_MASK 1 > > +#define EXYNOSAUTOV920_TMU_LPI_MODE_SHIFT 10 > > + > > +#define EXYNOSAUTOV920_TMU_AVG_CON_UPDATE 0x0008011a > > +#define EXYNOSAUTOV920_TMU_COUNTER_VALUE0_UPDATE 0x030003c0 > > +#define EXYNOSAUTOV920_TMU_COUNTER_VALUE1_UPDATE 0x03c0004d > > + > > #define MCELSIUS 1000 > > > > +#define EXYNOS_DEFAULT_SENSOR_COUNT 1 > > +#define EXYNOS_MAX_SENSOR_COUNT 15 > > + > > enum soc_type { > > SOC_ARCH_EXYNOS3250 = 1, > > SOC_ARCH_EXYNOS4210, > > @@ -133,6 +176,7 @@ enum soc_type { > > SOC_ARCH_EXYNOS5420_TRIMINFO, > > SOC_ARCH_EXYNOS5433, > > SOC_ARCH_EXYNOS7, > > + SOC_ARCH_EXYNOSAUTOV920, > > }; > > > > /** > > @@ -150,6 +194,8 @@ enum soc_type { > > * @efuse_value: SoC defined fuse value > > * @min_efuse_value: minimum valid trimming data > > * @max_efuse_value: maximum valid trimming data > > + * @slope_comp: allocated value of the slope compensation. > > + * @calib_temp: calibration temperature of the TMU. > > * @temp_error1: fused value of the first point trim. > > * @temp_error2: fused value of the second point trim. > > * @gain: gain of amplifier in the positive-TC generator block @@ > > -157,7 +203,8 @@ enum soc_type { > > * @reference_voltage: reference voltage of amplifier > > * in the positive-TC generator block > > * 0 < reference_voltage <= 31 > > - * @tzd: pointer to thermal_zone_device structure > > + * @sensor_count: The maximum number of the sensors > > + * @tzd_array: pointer array of thermal_zone_device structure > > * @enabled: current status of TMU device > > * @tmu_set_low_temp: SoC specific method to set trip (falling > threshold) > > * @tmu_set_high_temp: SoC specific method to set trip (rising > > threshold) @@ -174,6 +221,7 @@ struct exynos_tmu_data { > > void __iomem *base; > > void __iomem *base_second; > > int irq; > > + int sensor_count; > > enum soc_type soc; > > struct mutex lock; > > struct clk *clk, *clk_sec, *sclk; > > @@ -181,10 +229,12 @@ struct exynos_tmu_data { > > u32 efuse_value; > > u32 min_efuse_value; > > u32 max_efuse_value; > > + u16 slope_comp; > > + u16 calib_temp; > > u16 temp_error1, temp_error2; > > u8 gain; > > u8 reference_voltage; > > - struct thermal_zone_device *tzd; > > + struct thermal_zone_device *tzd_array[EXYNOS_MAX_SENSOR_COUNT]; > > bool enabled; > > > > void (*tmu_set_low_temp)(struct exynos_tmu_data *data, u8 temp); @@ > > -205,13 +255,20 @@ struct exynos_tmu_data { > > */ > > static int temp_to_code(struct exynos_tmu_data *data, u8 temp) { > > + s32 temp_diff, code; > > + > > if (data->cal_type == TYPE_ONE_POINT_TRIMMING) > > return temp + data->temp_error1 - EXYNOS_FIRST_POINT_TRIM; > > > > - return (temp - EXYNOS_FIRST_POINT_TRIM) * > > - (data->temp_error2 - data->temp_error1) / > > - (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) + > > - data->temp_error1; > > + temp_diff = temp - EXYNOS_FIRST_POINT_TRIM; > > + > > + code = temp_diff * (data->temp_error2 - data->temp_error1) * > MCELSIUS / > > + (data->calib_temp - EXYNOS_FIRST_POINT_TRIM); > > + > > + if (data->soc == SOC_ARCH_EXYNOSAUTOV920 && temp_diff < 0) > > + code = code * (57 + data->slope_comp) / 65; > > + > > + return code / MCELSIUS + data->temp_error1; > > } > > > > /* > > @@ -220,13 +277,20 @@ static int temp_to_code(struct exynos_tmu_data > *data, u8 temp) > > */ > > static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code) > > { > > + s32 code_diff, temp; > > + > > if (data->cal_type == TYPE_ONE_POINT_TRIMMING) > > return temp_code - data->temp_error1 + > EXYNOS_FIRST_POINT_TRIM; > > > > - return (temp_code - data->temp_error1) * > > - (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) / > > - (data->temp_error2 - data->temp_error1) + > > - EXYNOS_FIRST_POINT_TRIM; > > + code_diff = temp_code - data->temp_error1; > > + > > + temp = code_diff * (data->calib_temp - EXYNOS_FIRST_POINT_TRIM) * > MCELSIUS / > > + (data->temp_error2 - data->temp_error1); > > + > > + if (data->soc == SOC_ARCH_EXYNOSAUTOV920 && code_diff < 0) > > + temp = temp * 65 / (57 + data->slope_comp); > > + > > + return temp / MCELSIUS + EXYNOS_FIRST_POINT_TRIM; > > } > > > > static void sanitize_temp_error(struct exynos_tmu_data *data, u32 > > trim_info) @@ -262,6 +326,9 @@ static int exynos_tmu_initialize(struct > platform_device *pdev) > > clk_enable(data->clk_sec); > > > > status = readb(data->base + EXYNOS_TMU_REG_STATUS); > > + if (data->soc == SOC_ARCH_EXYNOSAUTOV920) > > + status = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); > > + > > if (!status) { > > ret = -EBUSY; > > } else { > > @@ -280,27 +347,34 @@ static int exynos_tmu_initialize(struct > > platform_device *pdev) static int > > exynos_thermal_zone_configure(struct platform_device *pdev) { > > struct exynos_tmu_data *data = platform_get_drvdata(pdev); > > - struct thermal_zone_device *tzd = data->tzd; > > - int ret, temp; > > + struct thermal_zone_device *tzd; > > + int ret, temp, idx; > > > > - ret = thermal_zone_get_crit_temp(tzd, &temp); > > - if (ret) { > > - /* FIXME: Remove this special case */ > > - if (data->soc == SOC_ARCH_EXYNOS5433) > > - return 0; > > + for (idx = 0; idx < data->sensor_count; idx++) { > > + tzd = data->tzd_array[idx]; > > > > - dev_err(&pdev->dev, > > - "No CRITICAL trip point defined in device tree!\n"); > > - return ret; > > - } > > + if (!tzd) > > + continue; > > > > - mutex_lock(&data->lock); > > - clk_enable(data->clk); > > + ret = thermal_zone_get_crit_temp(tzd, &temp); > > + if (ret) { > > + /* FIXME: Remove this special case */ > > + if (data->soc == SOC_ARCH_EXYNOS5433) > > + return 0; > > > > - data->tmu_set_crit_temp(data, temp / MCELSIUS); > > + dev_err(&pdev->dev, > > + "No CRITICAL trip point defined in device > tree!\n"); > > + return ret; > > + } > > > > - clk_disable(data->clk); > > - mutex_unlock(&data->lock); > > + mutex_lock(&data->lock); > > + clk_enable(data->clk); > > + > > + data->tmu_set_crit_temp(data, temp / MCELSIUS); > > + > > + clk_disable(data->clk); > > + mutex_unlock(&data->lock); > > + } > > > > return 0; > > } > > @@ -323,6 +397,37 @@ static u32 get_con_reg(struct exynos_tmu_data *data, > u32 con) > > return con; > > } > > > > +static void update_con_reg(struct exynos_tmu_data *data) { > > + u32 val, t_buf_vref_sel, t_buf_slope_sel; > > + > > + val = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); > > + t_buf_vref_sel = (val >> EXYNOSAUTOV920_TMU_T_BUF_VREF_SEL_SHIFT) > > + & EXYNOSAUTOV920_TMU_T_BUF_VREF_SEL_MASK; > > + t_buf_slope_sel = (val >> EXYNOSAUTOV920_TMU_T_BUF_SLOPE_SEL_SHIFT) > > + & EXYNOSAUTOV920_TMU_T_BUF_SLOPE_SEL_MASK; > > + > > + val = readl(data->base + EXYNOSAUTOV920_TMU_REG_CONTROL); > > + val &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << > EXYNOS_TMU_REF_VOLTAGE_SHIFT); > > + val |= (t_buf_vref_sel << EXYNOS_TMU_REF_VOLTAGE_SHIFT); > > + val &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << > EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); > > + val |= (t_buf_slope_sel << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); > > + writel(val, data->base + EXYNOSAUTOV920_TMU_REG_CONTROL); > > + > > + val = readl(data->base + EXYNOSAUTOV920_TMU_REG_CONTROL1); > > + val &= ~(EXYNOSAUTOV920_TMU_NUM_PROBE_MASK << > EXYNOSAUTOV920_TMU_NUM_PROBE_SHIFT); > > + val &= ~(EXYNOSAUTOV920_TMU_LPI_MODE_MASK << > EXYNOSAUTOV920_TMU_LPI_MODE_SHIFT); > > + val |= (data->sensor_count << EXYNOSAUTOV920_TMU_NUM_PROBE_SHIFT); > > + writel(val, data->base + EXYNOSAUTOV920_TMU_REG_CONTROL1); > > + > > + writel(1, data->base + EXYNOSAUTOV920_TMU_SAMPLING_INTERVAL); > > + writel(EXYNOSAUTOV920_TMU_AVG_CON_UPDATE, data->base + > EXYNOSAUTOV920_TMU_REG_AVG_CONTROL); > > + writel(EXYNOSAUTOV920_TMU_COUNTER_VALUE0_UPDATE, > > + data->base + EXYNOSAUTOV920_TMU_REG_COUNTER_VALUE0); > > + writel(EXYNOSAUTOV920_TMU_COUNTER_VALUE1_UPDATE, > > + data->base + EXYNOSAUTOV920_TMU_REG_COUNTER_VALUE1); > > +} > > + > > static void exynos_tmu_control(struct platform_device *pdev, bool on) > > { > > struct exynos_tmu_data *data = platform_get_drvdata(pdev); @@ - > 354,9 > > +459,8 @@ static void exynos_tmu_update_temp(struct exynos_tmu_data > *data, int reg_off, > > u16 tmu_temp_mask; > > u32 th; > > > > - tmu_temp_mask = > > - (data->soc == SOC_ARCH_EXYNOS7) ? EXYNOS7_TMU_TEMP_MASK > > - : EXYNOS_TMU_TEMP_MASK; > > + tmu_temp_mask = (data->soc == SOC_ARCH_EXYNOS7 || data->soc == > SOC_ARCH_EXYNOSAUTOV920) > > + ? EXYNOS7_TMU_TEMP_MASK : EXYNOS_TMU_TEMP_MASK; > > > > th = readl(data->base + reg_off); > > th &= ~(tmu_temp_mask << bit_off); > > @@ -582,6 +686,68 @@ static void exynos7_tmu_initialize(struct > platform_device *pdev) > > sanitize_temp_error(data, trim_info); } > > > > +static void exynosautov920_tmu_set_low_temp(struct exynos_tmu_data > > +*data, u8 temp) { > > + /* > > + * Failing thresholds are not supported on Exynosautov920. > > + * We use polling instead. > > + */ > > +} > > + > > +static void exynosautov920_tmu_set_high_temp(struct exynos_tmu_data > > +*data, u8 temp) { > > + /* > > + * Rising thresholds are not supported on Exynosautov920. > > + * We use polling instead. > > + */ > > +} > > + > > +static void exynosautov920_tmu_disable_low(struct exynos_tmu_data > > +*data) { > > + /* Again, this is handled by polling. */ } > > + > > +static void exynosautov920_tmu_disable_high(struct exynos_tmu_data > > +*data) { > > + /* Again, this is handled by polling. */ } > > + > > +static void exynosautov920_tmu_set_crit_temp(struct exynos_tmu_data > > +*data, u8 temp) { > > + unsigned int idx; > > + > > + for (idx = 0; idx < data->sensor_count; idx++) { > > + if (!data->tzd_array[idx]) > > + continue; > > + > > + exynos_tmu_update_temp(data, > EXYNOSAUTOV920_TMU_REG_THRESHOLD(idx), 16, temp); > > + exynos_tmu_update_bit(data, > EXYNOSAUTOV920_TMU_REG_INTEN(idx), 7, true); > > + } > > +} > > + > > +static void exynosautov920_tmu_initialize(struct platform_device > > +*pdev) { > > + struct exynos_tmu_data *data = platform_get_drvdata(pdev); > > + unsigned int val; > > + > > + data->tmu_control(pdev, false); > > + > > + update_con_reg(data); > > + > > + val = readl(data->base + EXYNOS_TMU_REG_TRIMINFO); > > + data->cal_type = TYPE_TWO_POINT_TRIMMING; > > + data->slope_comp = (val >> EXYNOSAUTOV920_SLOPE_COMP) & > > +EXYNOSAUTOV920_SLOPE_COMP_MASK; > > + > > + val = readl(data->base + EXYNOSAUTOV920_SENSOR0_TRIM_INFO); > > + data->temp_error1 = (val >> EXYNOSAUTOV920_TRIMINFO_25_SHIFT) & > EXYNOSAUTOV920_TRIM_MASK; > > + data->temp_error2 = (val >> EXYNOSAUTOV920_TRIMINFO_85_SHIFT) & > > +EXYNOSAUTOV920_TRIM_MASK; > > + > > + val = readl(data->base + EXYNOSAUTOV920_TMU_REG_TRIMINFO2); > > + val = (val >> EXYNOSAUTOV920_CALIB_SEL_TEMP) & > > +EXYNOSAUTOV920_CALIB_SEL_TEMP_MASK; > > + > > + data->calib_temp = (EXYNOS_SECOND_POINT_TRIM + (20 * val)); } > > + > > static void exynos4210_tmu_control(struct platform_device *pdev, bool > > on) { > > struct exynos_tmu_data *data = platform_get_drvdata(pdev); @@ - > 633,6 > > +799,24 @@ static void exynos7_tmu_control(struct platform_device *pdev, > bool on) > > writel(con, data->base + EXYNOS_TMU_REG_CONTROL); } > > > > +static void exynosautov920_tmu_control(struct platform_device *pdev, > > +bool on) { > > + struct exynos_tmu_data *data = platform_get_drvdata(pdev); > > + unsigned int con; > > + > > + con = readl(data->base + EXYNOSAUTOV920_TMU_REG_CONTROL); > > + > > + if (on) { > > + con |= BIT(EXYNOS_TMU_THERM_TRIP_EN_SHIFT); > > + con |= BIT(EXYNOS_TMU_CORE_EN_SHIFT); > > + } else { > > + con &= ~BIT(EXYNOS_TMU_THERM_TRIP_EN_SHIFT); > > + con &= ~BIT(EXYNOS_TMU_CORE_EN_SHIFT); > > + } > > + > > + writel(con, data->base + EXYNOSAUTOV920_TMU_REG_CONTROL); } > > + > > static int exynos_get_temp(struct thermal_zone_device *tz, int *temp) > > { > > struct exynos_tmu_data *data = thermal_zone_device_priv(tz); @@ > > -671,7 +855,7 @@ static u32 get_emul_con_reg(struct exynos_tmu_data > > *data, unsigned int val, > > > > val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT); > > val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT); > > - if (data->soc == SOC_ARCH_EXYNOS7) { > > + if (data->soc == SOC_ARCH_EXYNOS7 || data->soc == > > +SOC_ARCH_EXYNOSAUTOV920) { > > val &= ~(EXYNOS7_EMUL_DATA_MASK << > > EXYNOS7_EMUL_DATA_SHIFT); > > val |= (temp_to_code(data, temp) << @@ -703,6 +887,8 > @@ static > > void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data, > > emul_con = EXYNOS5433_TMU_EMUL_CON; > > else if (data->soc == SOC_ARCH_EXYNOS7) > > emul_con = EXYNOS7_TMU_REG_EMUL_CON; > > + else if (data->soc == SOC_ARCH_EXYNOSAUTOV920) > > + emul_con = EXYNOSAUTOV920_TMU_REG_EMUL_CON; > > else > > emul_con = EXYNOS_EMUL_CON; > > > > @@ -756,11 +942,23 @@ static int exynos7_tmu_read(struct exynos_tmu_data > *data) > > EXYNOS7_TMU_TEMP_MASK; > > } > > > > +static int exynosautov920_tmu_read(struct exynos_tmu_data *data) { > > + return readw(data->base + EXYNOSAUTOV920_CURRENT_TEMP_P1_P0) & > > + EXYNOS7_TMU_TEMP_MASK; > > +} > > + > > static irqreturn_t exynos_tmu_threaded_irq(int irq, void *id) { > > struct exynos_tmu_data *data = id; > > + int idx; > > > > - thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED); > > + for (idx = 0; idx < data->sensor_count; idx++) { > > + if (!data->tzd_array[idx]) > > + continue; > > + > > + thermal_zone_device_update(data->tzd_array[idx], > THERMAL_EVENT_UNSPECIFIED); > > + } > > > > mutex_lock(&data->lock); > > clk_enable(data->clk); > > @@ -805,6 +1003,19 @@ static void exynos4210_tmu_clear_irqs(struct > exynos_tmu_data *data) > > writel(val_irq, data->base + tmu_intclear); } > > > > +static void exynosautov920_tmu_clear_irqs(struct exynos_tmu_data > > +*data) { > > + unsigned int idx, val_irq; > > + > > + for (idx = 0; idx < data->sensor_count; idx++) { > > + if (!data->tzd_array[idx]) > > + continue; > > + > > + val_irq = readl(data->base + > EXYNOSAUTOV920_TMU_REG_INT_PEND(idx)); > > + writel(val_irq, data->base + > EXYNOSAUTOV920_TMU_REG_INT_PEND(idx)); > > + } > > +} > > + > > static const struct of_device_id exynos_tmu_match[] = { > > { > > .compatible = "samsung,exynos3250-tmu", @@ -833,6 +1044,9 @@ > static > > const struct of_device_id exynos_tmu_match[] = { > > }, { > > .compatible = "samsung,exynos7-tmu", > > .data = (const void *)SOC_ARCH_EXYNOS7, > > + }, { > > + .compatible = "samsung,exynosautov920-tmu", > > + .data = (const void *)SOC_ARCH_EXYNOSAUTOV920, > > }, > > { }, > > }; > > @@ -865,6 +1079,10 @@ static int exynos_map_dt_data(struct > > platform_device *pdev) > > > > data->soc = (uintptr_t)of_device_get_match_data(&pdev->dev); > > > > + data->sensor_count = EXYNOS_DEFAULT_SENSOR_COUNT; > > + > > + data->calib_temp = EXYNOS_SECOND_POINT_TRIM; > > + > > switch (data->soc) { > > case SOC_ARCH_EXYNOS4210: > > data->tmu_set_low_temp = exynos4210_tmu_set_low_temp; @@ - > 945,6 > > +1163,19 @@ static int exynos_map_dt_data(struct platform_device *pdev) > > data->min_efuse_value = 15; > > data->max_efuse_value = 100; > > break; > > + case SOC_ARCH_EXYNOSAUTOV920: > > + data->tmu_set_low_temp = exynosautov920_tmu_set_low_temp; > > + data->tmu_set_high_temp = exynosautov920_tmu_set_high_temp; > > + data->tmu_disable_low = exynosautov920_tmu_disable_low; > > + data->tmu_disable_high = exynosautov920_tmu_disable_high; > > + data->tmu_set_crit_temp = exynosautov920_tmu_set_crit_temp; > > + data->tmu_initialize = exynosautov920_tmu_initialize; > > + data->tmu_control = exynosautov920_tmu_control; > > + data->tmu_read = exynosautov920_tmu_read; > > + data->tmu_set_emulation = exynos4412_tmu_set_emulation; > > + data->tmu_clear_irqs = exynosautov920_tmu_clear_irqs; > > + data->sensor_count = EXYNOS_MAX_SENSOR_COUNT; > > + break; > > default: > > dev_err(&pdev->dev, "Platform not supported\n"); > > return -EINVAL; > > @@ -952,6 +1183,14 @@ static int exynos_map_dt_data(struct > > platform_device *pdev) > > > > data->cal_type = TYPE_ONE_POINT_TRIMMING; > > > > + if (data->soc == SOC_ARCH_EXYNOSAUTOV920) { > > + if (of_property_read_u32(pdev->dev.of_node, > "samsung,sensors", > > + &data->sensor_count)) { > > + dev_err(&pdev->dev, "failed to get sensor count\n"); > > + return -ENODEV; > > + } > > + } > > + > > /* > > * Check if the TMU shares some registers and then try to map the > > * memory of common registers. > > @@ -1006,7 +1245,8 @@ static int exynos_tmu_probe(struct > > platform_device *pdev) { > > struct device *dev = &pdev->dev; > > struct exynos_tmu_data *data; > > - int ret; > > + struct thermal_zone_device *tzd; > > + int ret, idx; > > > > data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); > > if (!data) > > @@ -1084,11 +1324,19 @@ static int exynos_tmu_probe(struct > platform_device *pdev) > > goto err_sclk; > > } > > > > - data->tzd = devm_thermal_of_zone_register(dev, 0, data, > > - &exynos_sensor_ops); > > - if (IS_ERR(data->tzd)) { > > - ret = dev_err_probe(dev, PTR_ERR(data->tzd), "Failed to > register sensor\n"); > > - goto err_sclk; > > + for (idx = 0; idx < data->sensor_count; idx++) { > > + tzd = devm_thermal_of_zone_register(dev, idx, data, > > +&exynos_sensor_ops); > > + > > + if (IS_ERR(tzd)) { > > + if (PTR_ERR(tzd) == -ENODEV) > > + continue; > > + > > + ret = dev_err_probe(dev, PTR_ERR(data- >tzd_array[idx]), > > + "Failed to register sensor\n"); > > + goto err_sclk; > > + } > > + > > + data->tzd_array[idx] = tzd; > > } > > > > ret = exynos_thermal_zone_configure(pdev); > > -- > > 2.50.1 > >