devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: 손신 <shin.son@samsung.com>
To: "'Daniel Lezcano'" <daniel.lezcano@linaro.org>,
	"'Bartlomiej Zolnierkiewicz'" <bzolnier@gmail.com>,
	"'Krzysztof Kozlowski'" <krzk@kernel.org>,
	"'Rafael J . Wysocki'" <rafael@kernel.org>,
	"'Zhang Rui'" <rui.zhang@intel.com>,
	"'Lukasz Luba'" <lukasz.luba@arm.com>,
	"'Rob Herring'" <robh@kernel.org>,
	"'Conor Dooley'" <conor+dt@kernel.org>,
	"'Alim Akhtar'" <alim.akhtar@samsung.com>
Cc: "'Henrik Grimler'" <henrik@grimler.se>,
	<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>, <shin.son@samsung.com>
Subject: RE: [PATCH v7 RESEND 2/3] thermal: exynos_tmu: Support new hardware and update TMU interface
Date: Mon, 24 Nov 2025 19:06:33 +0900	[thread overview]
Message-ID: <000001dc5d2a$0697bf10$13c73d30$@samsung.com> (raw)
In-Reply-To: <2180a854-8ba6-4424-add2-eb34637530c1@linaro.org>

Hello, Daniel Lezcano

> On 11/13/25 07:40, Shin Son wrote:
> > +	if (data->soc == SOC_ARCH_EXYNOSAUTOV920 && code_diff < 0)
> > +		temp = temp * 65 / (57 + data->slope_comp);
> 
> No litterals, comments, etc ...

I'll move those fomulas into the variant data via the .data field in the of_device_id match table.

> > +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);
> > +}
> > +
> 
> This is unreadable; please make it understandable for those who don’t have
> the documentation (explicit static inline functions, comments, etc ...).

I'll restructure this code by introducing explicit static inline helper functions and proper comments to improve readability.

> > +static void exynosautov920_tmu_disable_high(struct exynos_tmu_data
> > +*data) {
> > +	/* Again, this is handled by polling. */ }
> 
> The driver would deserve some cleanups. Instead of having empty callbacks,
> check in exynos_set_trips() if the ops is !NULL. Then remove all no-op ops.

Ok, I'll update exynos_set_trips() to check for NULL ops and remove the no-op callbacks accordingly.

> > +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);
> > +	}
> > +}
> 
> There is something wrong in the driver design.
> 
> exynosautov920_tmu_set_crit_temp() is called from
> exynos_thermal_zone_configure() and the routine above sets the temperature
> on all the thermal zone while this one is retrieved from one thermal zone.
> 
> Which results in:
> 
> 	for all tz do;
> 		for all tz do;
> 			if !tz then continue;
> 			set_crit_temp(tz)
> 
> No, this driver needs to be revisited and cleanup before sending changes
> for multiple sensors support.
> 
> What percentage of code sharing is there with the existing driver ?

Overall, I would say that roughly 60% of the logic can be shared.
The temperature reading and emulation paths are similar, but the initialization sequence differs significantly.

Given this level of divergence, would introducing a separate driver 
(instead of extending the current one with many special-case paths) be acceptable?

> > +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)); }
> > +
> 
> This is unreadable; please make it understandable for those who don’t have
> the documentation (explicit static inline functions, comments, etc ...).

Ok, I'll refactor this code using explicit static inline helpers and comments.

> > +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); }
> 
> Document a bit the code please.

Sure, I’ll document this part properly by adding clear comments and splitting the register options into explicit helper functions.

> >   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);
> I understand the main reason is to keep a common isr but you should
> *not* update all the thermal zones. There is an amount of processing
> behind this function adding a significant overhead.
> 
> So somehow readl(data->base + EXYNOSAUTOV920_TMU_REG_INT_PEND(idx));
> should be used here to know if the thermal zone has to be updated or not.

OK, I'll update the ISR so that it checks the pending register before calling 'thermal_zone_device_update()',
And only update the relevant thermal zones. 

> >   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,
> 
> Time to do cleanups in the driver. Use at your advantage the .data to
> store the relevant info instead of a awful else-if in the different
> functions above.

OK, I'll refactor this by using the .data field.
However, since ExynosAutov920 diverges significantly from the existing driver,
Would introducing a separate driver instead of unifying everything be acceptable?

> >   	},
> >   	{ },
> >   };
> > @@ -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;
> 
> Same comment as above.

Ok, I'll refactor this by using the .data field to move the SoC-specific callbacks into a proper
variant structure.

> --

Thank you for your detailed feedback. I appreciate it.




  reply	other threads:[~2025-11-24 10:06 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20251113064032epcas2p316f2b271e581d03b729a5944d9624d49@epcas2p3.samsung.com>
2025-11-13  6:40 ` [PATCH v7 RESEND 0/3] Add exynosautov920 thermal support Shin Son
     [not found]   ` <CGME20251113064040epcas2p2df8da3f9c5a2c41c6aedc37d37b366de@epcas2p2.samsung.com>
2025-11-13  6:40     ` [PATCH v7 RESEND 1/3] dt-bindings: thermal: samsung: Adjust '#thermal-sensor-cells' to 1 Shin Son
     [not found]   ` <CGME20251113064044epcas2p1b87addb21473eca7cc52052e4e2e9237@epcas2p1.samsung.com>
2025-11-13  6:40     ` [PATCH v7 RESEND 2/3] thermal: exynos_tmu: Support new hardware and update TMU interface Shin Son
2025-11-20 19:43       ` Daniel Lezcano
2025-11-24 10:06         ` 손신 [this message]
2025-11-24 10:35           ` Daniel Lezcano
2025-11-24 11:04             ` 손신
2025-11-24 11:08               ` Daniel Lezcano
2025-11-24 11:42                 ` 손신
2025-11-24 10:43           ` Tudor Ambarus
2025-11-24 11:16             ` Daniel Lezcano
2025-11-24 11:41             ` 손신
2025-11-24 12:24               ` Tudor Ambarus
2025-11-25  8:23                 ` 손신
2025-11-25  9:15       ` Tudor Ambarus
2025-11-26  7:19         ` 손신
2025-11-26  9:21           ` Tudor Ambarus
2025-11-27  3:07             ` 손신
2025-11-27  9:04               ` Tudor Ambarus
2025-12-01  1:38                 ` 손신
2025-12-01  9:54             ` Youngmin Nam
2025-12-02  0:31               ` 손신
     [not found]   ` <CGME20251113064049epcas2p2194df7393ea60912eec18077bbddf637@epcas2p2.samsung.com>
2025-11-13  6:40     ` [PATCH v7 RESEND 3/3] arm64: dts: exynosautov920: Add multiple sensors Shin Son
2025-10-30  7:07 [PATCH v7 RESEND 0/3] Add exynosautov920 thermal support Shin Son
     [not found] ` <CGME20251030070716epcas2p2d51319c14272c316bd6b581a3fdcb512@epcas2p2.samsung.com>
2025-10-30  7:07   ` [PATCH v7 RESEND 2/3] thermal: exynos_tmu: Support new hardware and update TMU interface Shin Son

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='000001dc5d2a$0697bf10$13c73d30$@samsung.com' \
    --to=shin.son@samsung.com \
    --cc=alim.akhtar@samsung.com \
    --cc=bzolnier@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=daniel.lezcano@linaro.org \
    --cc=devicetree@vger.kernel.org \
    --cc=henrik@grimler.se \
    --cc=krzk@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=lukasz.luba@arm.com \
    --cc=rafael@kernel.org \
    --cc=robh@kernel.org \
    --cc=rui.zhang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).