linux-tegra.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] Cleanup Tegra210 EMC frequency scaling
@ 2024-04-09  9:46 Diogo Ivo
  2024-04-09  9:46 ` [PATCH 1/7] memory: tegra: Remove periodic compensation duplicate calls Diogo Ivo
                   ` (6 more replies)
  0 siblings, 7 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-04-09  9:46 UTC (permalink / raw)
  To: krzysztof.kozlowski, thierry.reding, jonathanh, linux-tegra; +Cc: Diogo Ivo

Hello,

This patch series consists of a general cleanup of the Tegra210 EMC
frequency scaling code for revision 7.

Currently the code is relying heavily on a function, update_clock_tree_delay(),
that is responsible for too many things, making it long and confusing.
The general idea with these patches is to simplify this function and its
surrounding code, making it more modular.

The motivation behind these changes (besides improving readability and
maintainability) is to make it simpler to add support in the future for
frequency change revisions other than 7, where we can reuse a large
portion of the modularized code rather than essentially repeating 2k
lines of code with minimal changes.

There are no functional changes with this patch set, as it is only meant
as preparation for following patches where revision 6 support is added.

Diogo Ivo (7):
  memory: tegra: Remove periodic compensation duplicate calls
  memory: tegra: Move DQSOSC measurement to common place
  memory: tegra: Reword and correct comments
  memory: tegra: Change macros to interpret parameter as integer
  memory: tegra: Loop update_clock_tree_delay()
  memory: tegra: Move compare/update current delay values to a function
  memory: tegra: Rework update_clock_tree_delay()

 drivers/memory/tegra/tegra210-emc-cc-r21021.c | 427 ++++--------------
 1 file changed, 84 insertions(+), 343 deletions(-)

-- 
2.44.0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/7] memory: tegra: Remove periodic compensation duplicate calls
  2024-04-09  9:46 [PATCH 0/7] Cleanup Tegra210 EMC frequency scaling Diogo Ivo
@ 2024-04-09  9:46 ` Diogo Ivo
  2024-04-09  9:46 ` [PATCH 2/7] memory: tegra: Move DQSOSC measurement to common place Diogo Ivo
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-04-09  9:46 UTC (permalink / raw)
  To: krzysztof.kozlowski, thierry.reding, jonathanh, linux-tegra; +Cc: Diogo Ivo

Prior to calling periodic_compensation_handler() the code is doing one
extra DRAM delay reading which is unnecessary as this is already done
in periodic_compensation_handler(), so remove these extra calls.

Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
 drivers/memory/tegra/tegra210-emc-cc-r21021.c | 19 ++-----------------
 1 file changed, 2 insertions(+), 17 deletions(-)

diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
index 4cb608c71ead..9ec49ced8f91 100644
--- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
+++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
@@ -492,7 +492,6 @@ static u32 tegra210_emc_r21021_periodic_compensation(struct tegra210_emc *emc)
 	};
 	struct tegra210_emc_timing *last = emc->last;
 	unsigned int items = ARRAY_SIZE(list), i;
-	unsigned long delay;
 
 	if (last->periodic_training) {
 		emc_dbg(emc, PER_TRAIN, "Periodic training starting\n");
@@ -530,18 +529,9 @@ static u32 tegra210_emc_r21021_periodic_compensation(struct tegra210_emc *emc)
 		/*
 		 * 2. osc kick off - this assumes training and dvfs have set
 		 *    correct MR23.
-		 */
-		tegra210_emc_start_periodic_compensation(emc);
-
-		/*
+		 *
 		 * 3. Let dram capture its clock tree delays.
-		 */
-		delay = tegra210_emc_actual_osc_clocks(last->run_clocks);
-		delay *= 1000;
-		delay /= last->rate + 1;
-		udelay(delay);
-
-		/*
+		 *
 		 * 4. Check delta wrt previous values (save value if margin
 		 *    exceeds what is set in table).
 		 */
@@ -734,11 +724,6 @@ static void tegra210_emc_r21021_set_clock(struct tegra210_emc *emc, u32 clksrc)
 						     EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_MASK,
 						     0);
 
-		tegra210_emc_start_periodic_compensation(emc);
-
-		delay = 1000 * tegra210_emc_actual_osc_clocks(last->run_clocks);
-		udelay((delay / last->rate) + 2);
-
 		value = periodic_compensation_handler(emc, DVFS_SEQUENCE, fake,
 						      next);
 		value = (value * 128 * next->rate / 1000) / 1000000;
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/7] memory: tegra: Move DQSOSC measurement to common place
  2024-04-09  9:46 [PATCH 0/7] Cleanup Tegra210 EMC frequency scaling Diogo Ivo
  2024-04-09  9:46 ` [PATCH 1/7] memory: tegra: Remove periodic compensation duplicate calls Diogo Ivo
@ 2024-04-09  9:46 ` Diogo Ivo
  2024-04-09  9:46 ` [PATCH 3/7] memory: tegra: Reword and correct comments Diogo Ivo
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-04-09  9:46 UTC (permalink / raw)
  To: krzysztof.kozlowski, thierry.reding, jonathanh, linux-tegra; +Cc: Diogo Ivo

Move the calls that instruct the RAM to capture its clock tree delays
to update_clock_tree_delay() in order to avoid code duplication.

Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
 drivers/memory/tegra/tegra210-emc-cc-r21021.c | 25 ++++++++-----------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
index 9ec49ced8f91..15048f542367 100644
--- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
+++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
@@ -123,10 +123,19 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
 	bool dvfs_update = type == DVFS_UPDATE;
 	s32 tdel = 0, tmdel = 0, adel = 0;
 	bool dvfs_pt1 = type == DVFS_PT1;
+	u32 temp[2][2], value, udelay;
 	unsigned long cval = 0;
-	u32 temp[2][2], value;
 	unsigned int i;
 
+	if (dvfs_pt1 || periodic_training_update) {
+		udelay = tegra210_emc_actual_osc_clocks(last->run_clocks);
+		udelay *= 1000;
+		udelay = 2 + (udelay / last->rate);
+
+		tegra210_emc_start_periodic_compensation(emc);
+		udelay(udelay);
+	}
+
 	/*
 	 * Dev0 MSB.
 	 */
@@ -409,11 +418,6 @@ static u32 periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
 	   (nt)->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; })
 
 	u32 i, adel = 0, samples = next->ptfv_list[PTFV_DVFS_SAMPLES_INDEX];
-	u32 delay;
-
-	delay = tegra210_emc_actual_osc_clocks(last->run_clocks);
-	delay *= 1000;
-	delay = 2 + (delay / last->rate);
 
 	if (!next->periodic_training)
 		return 0;
@@ -447,9 +451,6 @@ static u32 periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
 			__MOVAVG(next, C1D1U1) = 0;
 
 			for (i = 0; i < samples; i++) {
-				tegra210_emc_start_periodic_compensation(emc);
-				udelay(delay);
-
 				/*
 				 * Generate next sample of data.
 				 */
@@ -465,12 +466,8 @@ static u32 periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
 		adel = update_clock_tree_delay(emc, DVFS_UPDATE);
 	}
 
-	if (type == PERIODIC_TRAINING_SEQUENCE) {
-		tegra210_emc_start_periodic_compensation(emc);
-		udelay(delay);
-
+	if (type == PERIODIC_TRAINING_SEQUENCE)
 		adel = update_clock_tree_delay(emc, PERIODIC_TRAINING_UPDATE);
-	}
 
 	return adel;
 }
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/7] memory: tegra: Reword and correct comments
  2024-04-09  9:46 [PATCH 0/7] Cleanup Tegra210 EMC frequency scaling Diogo Ivo
  2024-04-09  9:46 ` [PATCH 1/7] memory: tegra: Remove periodic compensation duplicate calls Diogo Ivo
  2024-04-09  9:46 ` [PATCH 2/7] memory: tegra: Move DQSOSC measurement to common place Diogo Ivo
@ 2024-04-09  9:46 ` Diogo Ivo
  2024-04-09  9:46 ` [PATCH 4/7] memory: tegra: Change macros to interpret parameter as integer Diogo Ivo
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-04-09  9:46 UTC (permalink / raw)
  To: krzysztof.kozlowski, thierry.reding, jonathanh, linux-tegra; +Cc: Diogo Ivo

Fix incorrect comment on periodic_compensation_handler() as the call
update_clock_tree_delay() with DVFS_UPDATE is responsible for dividing
the samples accumulated up to that point and comparing the computed
values with the currently programmed ones. While at it fix the
indentation of a nearby comment.

Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
 drivers/memory/tegra/tegra210-emc-cc-r21021.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
index 15048f542367..a80c3b575612 100644
--- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
+++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
@@ -451,18 +451,12 @@ static u32 periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
 			__MOVAVG(next, C1D1U1) = 0;
 
 			for (i = 0; i < samples; i++) {
-				/*
-				 * Generate next sample of data.
-				 */
+				/* Generate next sample of data. */
 				adel = update_clock_tree_delay(emc, DVFS_PT1);
 			}
 		}
 
-		/*
-		 * Seems like it should be part of the
-		 * 'if (last_timing->periodic_training)' conditional
-		 * since is already done for the else clause.
-		 */
+		/* Do the division part of the moving average */
 		adel = update_clock_tree_delay(emc, DVFS_UPDATE);
 	}
 
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/7] memory: tegra: Change macros to interpret parameter as integer
  2024-04-09  9:46 [PATCH 0/7] Cleanup Tegra210 EMC frequency scaling Diogo Ivo
                   ` (2 preceding siblings ...)
  2024-04-09  9:46 ` [PATCH 3/7] memory: tegra: Reword and correct comments Diogo Ivo
@ 2024-04-09  9:46 ` Diogo Ivo
  2024-04-13  8:02   ` Krzysztof Kozlowski
  2024-04-09  9:46 ` [PATCH 5/7] memory: tegra: Loop update_clock_tree_delay() Diogo Ivo
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Diogo Ivo @ 2024-04-09  9:46 UTC (permalink / raw)
  To: krzysztof.kozlowski, thierry.reding, jonathanh, linux-tegra; +Cc: Diogo Ivo

Convert the macros that manipulate the delay values to interpret their
index parameter as an integer to allow the introduction of loops.

Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
 drivers/memory/tegra/tegra210-emc-cc-r21021.c | 33 +++++++------------
 1 file changed, 11 insertions(+), 22 deletions(-)

diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
index a80c3b575612..65157bd5dc24 100644
--- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
+++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
@@ -75,29 +75,29 @@ enum {
  * The division portion of the average operation.
  */
 #define __AVERAGE_PTFV(dev)						\
-	({ next->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] =	\
-	   next->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] /	\
+	({ next->ptfv_list[dev] =					\
+	   next->ptfv_list[dev] /					\
 	   next->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; })
 
 /*
  * Convert val to fixed point and add it to the temporary average.
  */
 #define __INCREMENT_PTFV(dev, val)					\
-	({ next->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] +=	\
+	({ next->ptfv_list[dev] +=					\
 	   ((val) * MOVAVG_PRECISION_FACTOR); })
 
 /*
  * Convert a moving average back to integral form and return the value.
  */
 #define __MOVAVG_AC(timing, dev)					\
-	((timing)->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] /	\
+	((timing)->ptfv_list[dev] /					\
 	 MOVAVG_PRECISION_FACTOR)
 
 /* Weighted update. */
 #define __WEIGHTED_UPDATE_PTFV(dev, nval)				\
 	do {								\
 		int w = PTFV_MOVAVG_WEIGHT_INDEX;			\
-		int dqs = PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX;		\
+		int dqs = dev;						\
 									\
 		next->ptfv_list[dqs] =					\
 			((nval * MOVAVG_PRECISION_FACTOR) +		\
@@ -111,7 +111,7 @@ enum {
 
 /* Access a particular average. */
 #define __MOVAVG(timing, dev)                      \
-	((timing)->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX])
+	((timing)->ptfv_list[dev])
 
 static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
 {
@@ -418,6 +418,7 @@ static u32 periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
 	   (nt)->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; })
 
 	u32 i, adel = 0, samples = next->ptfv_list[PTFV_DVFS_SAMPLES_INDEX];
+	u32 idx;
 
 	if (!next->periodic_training)
 		return 0;
@@ -431,24 +432,12 @@ static u32 periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
 			 * calibration then we can reuse the previous
 			 * frequencies EMA data.
 			 */
-			__COPY_EMA(next, last, C0D0U0);
-			__COPY_EMA(next, last, C0D0U1);
-			__COPY_EMA(next, last, C1D0U0);
-			__COPY_EMA(next, last, C1D0U1);
-			__COPY_EMA(next, last, C0D1U0);
-			__COPY_EMA(next, last, C0D1U1);
-			__COPY_EMA(next, last, C1D1U0);
-			__COPY_EMA(next, last, C1D1U1);
+			for (idx = 0; idx < DRAM_CLKTREE_NUM; idx++)
+				__COPY_EMA(next, last, idx);
 		} else {
 			/* Reset the EMA.*/
-			__MOVAVG(next, C0D0U0) = 0;
-			__MOVAVG(next, C0D0U1) = 0;
-			__MOVAVG(next, C1D0U0) = 0;
-			__MOVAVG(next, C1D0U1) = 0;
-			__MOVAVG(next, C0D1U0) = 0;
-			__MOVAVG(next, C0D1U1) = 0;
-			__MOVAVG(next, C1D1U0) = 0;
-			__MOVAVG(next, C1D1U1) = 0;
+			for (idx = 0; idx < DRAM_CLKTREE_NUM; idx++)
+				__MOVAVG(next, idx) = 0;
 
 			for (i = 0; i < samples; i++) {
 				/* Generate next sample of data. */
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/7] memory: tegra: Loop update_clock_tree_delay()
  2024-04-09  9:46 [PATCH 0/7] Cleanup Tegra210 EMC frequency scaling Diogo Ivo
                   ` (3 preceding siblings ...)
  2024-04-09  9:46 ` [PATCH 4/7] memory: tegra: Change macros to interpret parameter as integer Diogo Ivo
@ 2024-04-09  9:46 ` Diogo Ivo
  2024-04-09  9:46 ` [PATCH 6/7] memory: tegra: Move compare/update current delay values to a function Diogo Ivo
  2024-04-09  9:46 ` [PATCH 7/7] memory: tegra: Rework update_clock_tree_delay() Diogo Ivo
  6 siblings, 0 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-04-09  9:46 UTC (permalink / raw)
  To: krzysztof.kozlowski, thierry.reding, jonathanh, linux-tegra; +Cc: Diogo Ivo

As the current form of this function in a completely unrolled loop
over the RAM channels roll it up two levels to improve readability.

Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
 drivers/memory/tegra/tegra210-emc-cc-r21021.c | 322 ++++--------------
 1 file changed, 67 insertions(+), 255 deletions(-)

diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
index 65157bd5dc24..566e5c65c854 100644
--- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
+++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
@@ -125,7 +125,7 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
 	bool dvfs_pt1 = type == DVFS_PT1;
 	u32 temp[2][2], value, udelay;
 	unsigned long cval = 0;
-	unsigned int i;
+	unsigned int c, d, idx;
 
 	if (dvfs_pt1 || periodic_training_update) {
 		udelay = tegra210_emc_actual_osc_clocks(last->run_clocks);
@@ -136,276 +136,88 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
 		udelay(udelay);
 	}
 
-	/*
-	 * Dev0 MSB.
-	 */
-	if (dvfs_pt1 || periodic_training_update) {
-		value = tegra210_emc_mrr_read(emc, 2, 19);
-
-		for (i = 0; i < emc->num_channels; i++) {
-			temp[i][0] = (value & 0x00ff) << 8;
-			temp[i][1] = (value & 0xff00) << 0;
-			value >>= 16;
-		}
-
-		/*
-		 * Dev0 LSB.
-		 */
-		value = tegra210_emc_mrr_read(emc, 2, 18);
-
-		for (i = 0; i < emc->num_channels; i++) {
-			temp[i][0] |= (value & 0x00ff) >> 0;
-			temp[i][1] |= (value & 0xff00) >> 8;
-			value >>= 16;
-		}
-	}
-
-	if (dvfs_pt1 || periodic_training_update) {
-		cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
-		cval *= 1000000;
-		cval /= last_timing_rate_mhz * 2 * temp[0][0];
-	}
-
-	if (dvfs_pt1)
-		__INCREMENT_PTFV(C0D0U0, cval);
-	else if (dvfs_update)
-		__AVERAGE_PTFV(C0D0U0);
-	else if (periodic_training_update)
-		__WEIGHTED_UPDATE_PTFV(C0D0U0, cval);
-
-	if (dvfs_update || periodic_training_update) {
-		tdel = next->current_dram_clktree[C0D0U0] -
-				__MOVAVG_AC(next, C0D0U0);
-		tmdel = (tdel < 0) ? -1 * tdel : tdel;
-		adel = tmdel;
-
-		if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
-		    next->tree_margin)
-			next->current_dram_clktree[C0D0U0] =
-				__MOVAVG_AC(next, C0D0U0);
-	}
-
-	if (dvfs_pt1 || periodic_training_update) {
-		cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
-		cval *= 1000000;
-		cval /= last_timing_rate_mhz * 2 * temp[0][1];
-	}
-
-	if (dvfs_pt1)
-		__INCREMENT_PTFV(C0D0U1, cval);
-	else if (dvfs_update)
-		__AVERAGE_PTFV(C0D0U1);
-	else if (periodic_training_update)
-		__WEIGHTED_UPDATE_PTFV(C0D0U1, cval);
-
-	if (dvfs_update || periodic_training_update) {
-		tdel = next->current_dram_clktree[C0D0U1] -
-				__MOVAVG_AC(next, C0D0U1);
-		tmdel = (tdel < 0) ? -1 * tdel : tdel;
-
-		if (tmdel > adel)
-			adel = tmdel;
-
-		if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
-		    next->tree_margin)
-			next->current_dram_clktree[C0D0U1] =
-				__MOVAVG_AC(next, C0D0U1);
-	}
-
-	if (emc->num_channels > 1) {
-		if (dvfs_pt1 || periodic_training_update) {
-			cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
-			cval *= 1000000;
-			cval /= last_timing_rate_mhz * 2 * temp[1][0];
-		}
-
-		if (dvfs_pt1)
-			__INCREMENT_PTFV(C1D0U0, cval);
-		else if (dvfs_update)
-			__AVERAGE_PTFV(C1D0U0);
-		else if (periodic_training_update)
-			__WEIGHTED_UPDATE_PTFV(C1D0U0, cval);
-
-		if (dvfs_update || periodic_training_update) {
-			tdel = next->current_dram_clktree[C1D0U0] -
-					__MOVAVG_AC(next, C1D0U0);
-			tmdel = (tdel < 0) ? -1 * tdel : tdel;
-
-			if (tmdel > adel)
-				adel = tmdel;
-
-			if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
-			    next->tree_margin)
-				next->current_dram_clktree[C1D0U0] =
-					__MOVAVG_AC(next, C1D0U0);
-		}
-
+	for (d = 0; d < emc->num_devices; d++) {
 		if (dvfs_pt1 || periodic_training_update) {
-			cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
-			cval *= 1000000;
-			cval /= last_timing_rate_mhz * 2 * temp[1][1];
-		}
-
-		if (dvfs_pt1)
-			__INCREMENT_PTFV(C1D0U1, cval);
-		else if (dvfs_update)
-			__AVERAGE_PTFV(C1D0U1);
-		else if (periodic_training_update)
-			__WEIGHTED_UPDATE_PTFV(C1D0U1, cval);
-
-		if (dvfs_update || periodic_training_update) {
-			tdel = next->current_dram_clktree[C1D0U1] -
-					__MOVAVG_AC(next, C1D0U1);
-			tmdel = (tdel < 0) ? -1 * tdel : tdel;
-
-			if (tmdel > adel)
-				adel = tmdel;
+			/* Dev[d] MSB */
+			value = tegra210_emc_mrr_read(emc, 2 - d, 19);
 
-			if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
-			    next->tree_margin)
-				next->current_dram_clktree[C1D0U1] =
-					__MOVAVG_AC(next, C1D0U1);
-		}
-	}
-
-	if (emc->num_devices < 2)
-		goto done;
-
-	/*
-	 * Dev1 MSB.
-	 */
-	if (dvfs_pt1 || periodic_training_update) {
-		value = tegra210_emc_mrr_read(emc, 1, 19);
-
-		for (i = 0; i < emc->num_channels; i++) {
-			temp[i][0] = (value & 0x00ff) << 8;
-			temp[i][1] = (value & 0xff00) << 0;
-			value >>= 16;
-		}
-
-		/*
-		 * Dev1 LSB.
-		 */
-		value = tegra210_emc_mrr_read(emc, 1, 18);
-
-		for (i = 0; i < emc->num_channels; i++) {
-			temp[i][0] |= (value & 0x00ff) >> 0;
-			temp[i][1] |= (value & 0xff00) >> 8;
-			value >>= 16;
-		}
-	}
-
-	if (dvfs_pt1 || periodic_training_update) {
-		cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
-		cval *= 1000000;
-		cval /= last_timing_rate_mhz * 2 * temp[0][0];
-	}
-
-	if (dvfs_pt1)
-		__INCREMENT_PTFV(C0D1U0, cval);
-	else if (dvfs_update)
-		__AVERAGE_PTFV(C0D1U0);
-	else if (periodic_training_update)
-		__WEIGHTED_UPDATE_PTFV(C0D1U0, cval);
-
-	if (dvfs_update || periodic_training_update) {
-		tdel = next->current_dram_clktree[C0D1U0] -
-				__MOVAVG_AC(next, C0D1U0);
-		tmdel = (tdel < 0) ? -1 * tdel : tdel;
-
-		if (tmdel > adel)
-			adel = tmdel;
-
-		if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
-		    next->tree_margin)
-			next->current_dram_clktree[C0D1U0] =
-				__MOVAVG_AC(next, C0D1U0);
-	}
+			for (c = 0; c < emc->num_channels; c++) {
+				temp[c][0] = (value & 0x00ff) << 8;
+				temp[c][1] = (value & 0xff00) << 0;
+				value >>= 16;
+			}
 
-	if (dvfs_pt1 || periodic_training_update) {
-		cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
-		cval *= 1000000;
-		cval /= last_timing_rate_mhz * 2 * temp[0][1];
-	}
+			/* Dev[d] LSB */
+			value = tegra210_emc_mrr_read(emc, 2 - d, 18);
 
-	if (dvfs_pt1)
-		__INCREMENT_PTFV(C0D1U1, cval);
-	else if (dvfs_update)
-		__AVERAGE_PTFV(C0D1U1);
-	else if (periodic_training_update)
-		__WEIGHTED_UPDATE_PTFV(C0D1U1, cval);
-
-	if (dvfs_update || periodic_training_update) {
-		tdel = next->current_dram_clktree[C0D1U1] -
-				__MOVAVG_AC(next, C0D1U1);
-		tmdel = (tdel < 0) ? -1 * tdel : tdel;
-
-		if (tmdel > adel)
-			adel = tmdel;
-
-		if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
-		    next->tree_margin)
-			next->current_dram_clktree[C0D1U1] =
-				__MOVAVG_AC(next, C0D1U1);
-	}
-
-	if (emc->num_channels > 1) {
-		if (dvfs_pt1 || periodic_training_update) {
-			cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
-			cval *= 1000000;
-			cval /= last_timing_rate_mhz * 2 * temp[1][0];
+			for (c = 0; c < emc->num_channels; c++) {
+				temp[c][0] |= (value & 0x00ff) >> 0;
+				temp[c][1] |= (value & 0xff00) >> 8;
+				value >>= 16;
+			}
 		}
 
-		if (dvfs_pt1)
-			__INCREMENT_PTFV(C1D1U0, cval);
-		else if (dvfs_update)
-			__AVERAGE_PTFV(C1D1U0);
-		else if (periodic_training_update)
-			__WEIGHTED_UPDATE_PTFV(C1D1U0, cval);
+		for (c = 0; c < emc->num_channels; c++) {
+			/* C[c]D[d]U[0] */
+			idx = c * 4 + d * 2;
 
-		if (dvfs_update || periodic_training_update) {
-			tdel = next->current_dram_clktree[C1D1U0] -
-					__MOVAVG_AC(next, C1D1U0);
-			tmdel = (tdel < 0) ? -1 * tdel : tdel;
+			if (dvfs_pt1 || periodic_training_update) {
+				cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
+				cval *= 1000000;
+				cval /= last_timing_rate_mhz * 2 * temp[c][0];
+			}
 
-			if (tmdel > adel)
+			if (dvfs_pt1)
+				__INCREMENT_PTFV(idx, cval);
+			else if (dvfs_update)
+				__AVERAGE_PTFV(idx);
+			else if (periodic_training_update)
+				__WEIGHTED_UPDATE_PTFV(idx, cval);
+
+			if (dvfs_update || periodic_training_update) {
+				tdel = next->current_dram_clktree[idx] -
+						__MOVAVG_AC(next, idx);
+				tmdel = (tdel < 0) ? -1 * tdel : tdel;
 				adel = tmdel;
 
-			if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
-			    next->tree_margin)
-				next->current_dram_clktree[C1D1U0] =
-					__MOVAVG_AC(next, C1D1U0);
-		}
-
-		if (dvfs_pt1 || periodic_training_update) {
-			cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
-			cval *= 1000000;
-			cval /= last_timing_rate_mhz * 2 * temp[1][1];
-		}
-
-		if (dvfs_pt1)
-			__INCREMENT_PTFV(C1D1U1, cval);
-		else if (dvfs_update)
-			__AVERAGE_PTFV(C1D1U1);
-		else if (periodic_training_update)
-			__WEIGHTED_UPDATE_PTFV(C1D1U1, cval);
+				if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
+				    next->tree_margin)
+					next->current_dram_clktree[idx] =
+						__MOVAVG_AC(next, idx);
+			}
 
-		if (dvfs_update || periodic_training_update) {
-			tdel = next->current_dram_clktree[C1D1U1] -
-					__MOVAVG_AC(next, C1D1U1);
-			tmdel = (tdel < 0) ? -1 * tdel : tdel;
+			/* C[c]D[d]U[1] */
+			idx++;
 
-			if (tmdel > adel)
-				adel = tmdel;
+			if (dvfs_pt1 || periodic_training_update) {
+				cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
+				cval *= 1000000;
+				cval /= last_timing_rate_mhz * 2 * temp[c][1];
+			}
 
-			if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
-			    next->tree_margin)
-				next->current_dram_clktree[C1D1U1] =
-					__MOVAVG_AC(next, C1D1U1);
+			if (dvfs_pt1)
+				__INCREMENT_PTFV(idx, cval);
+			else if (dvfs_update)
+				__AVERAGE_PTFV(idx);
+			else if (periodic_training_update)
+				__WEIGHTED_UPDATE_PTFV(idx, cval);
+
+			if (dvfs_update || periodic_training_update) {
+				tdel = next->current_dram_clktree[idx] -
+						__MOVAVG_AC(next, idx);
+				tmdel = (tdel < 0) ? -1 * tdel : tdel;
+
+				if (tmdel > adel)
+					adel = tmdel;
+
+				if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
+				    next->tree_margin)
+					next->current_dram_clktree[idx] =
+						__MOVAVG_AC(next, idx);
+			}
 		}
 	}
 
-done:
 	return adel;
 }
 
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/7] memory: tegra: Move compare/update current delay values to a function
  2024-04-09  9:46 [PATCH 0/7] Cleanup Tegra210 EMC frequency scaling Diogo Ivo
                   ` (4 preceding siblings ...)
  2024-04-09  9:46 ` [PATCH 5/7] memory: tegra: Loop update_clock_tree_delay() Diogo Ivo
@ 2024-04-09  9:46 ` Diogo Ivo
  2024-04-13  8:07   ` Krzysztof Kozlowski
  2024-04-09  9:46 ` [PATCH 7/7] memory: tegra: Rework update_clock_tree_delay() Diogo Ivo
  6 siblings, 1 reply; 15+ messages in thread
From: Diogo Ivo @ 2024-04-09  9:46 UTC (permalink / raw)
  To: krzysztof.kozlowski, thierry.reding, jonathanh, linux-tegra; +Cc: Diogo Ivo

Separate the comparison/updating of the measured delay values with the
values currently programmed into a separate function to simplify the
code.

Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
 drivers/memory/tegra/tegra210-emc-cc-r21021.c | 84 +++++++++----------
 1 file changed, 38 insertions(+), 46 deletions(-)

diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
index 566e5c65c854..ec2f84758d55 100644
--- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
+++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
@@ -113,19 +113,35 @@ enum {
 #define __MOVAVG(timing, dev)                      \
 	((timing)->ptfv_list[dev])
 
+static bool tegra210_emc_compare_update_delay(struct tegra210_emc_timing *timing,
+					      u32 measured, u32 idx)
+{
+	u32 *curr = &timing->current_dram_clktree[idx];
+	u32 rate_mhz = timing->rate / 1000;
+	u32 tmdel;
+
+	tmdel = abs(*curr - measured);
+
+	if (tmdel * 128 * rate_mhz / 1000000 > timing->tree_margin) {
+		*curr = measured;
+		return true;
+	}
+
+	return false;
+}
+
 static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
 {
 	bool periodic_training_update = type == PERIODIC_TRAINING_UPDATE;
 	struct tegra210_emc_timing *last = emc->last;
 	struct tegra210_emc_timing *next = emc->next;
 	u32 last_timing_rate_mhz = last->rate / 1000;
-	u32 next_timing_rate_mhz = next->rate / 1000;
 	bool dvfs_update = type == DVFS_UPDATE;
-	s32 tdel = 0, tmdel = 0, adel = 0;
 	bool dvfs_pt1 = type == DVFS_PT1;
 	u32 temp[2][2], value, udelay;
 	unsigned long cval = 0;
 	unsigned int c, d, idx;
+	bool over = false;
 
 	if (dvfs_pt1 || periodic_training_update) {
 		udelay = tegra210_emc_actual_osc_clocks(last->run_clocks);
@@ -174,17 +190,9 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
 			else if (periodic_training_update)
 				__WEIGHTED_UPDATE_PTFV(idx, cval);
 
-			if (dvfs_update || periodic_training_update) {
-				tdel = next->current_dram_clktree[idx] -
-						__MOVAVG_AC(next, idx);
-				tmdel = (tdel < 0) ? -1 * tdel : tdel;
-				adel = tmdel;
-
-				if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
-				    next->tree_margin)
-					next->current_dram_clktree[idx] =
-						__MOVAVG_AC(next, idx);
-			}
+			if (dvfs_update || periodic_training_update)
+				over |= tegra210_emc_compare_update_delay(next,
+							__MOVAVG_AC(next, idx), idx);
 
 			/* C[c]D[d]U[1] */
 			idx++;
@@ -202,35 +210,26 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
 			else if (periodic_training_update)
 				__WEIGHTED_UPDATE_PTFV(idx, cval);
 
-			if (dvfs_update || periodic_training_update) {
-				tdel = next->current_dram_clktree[idx] -
-						__MOVAVG_AC(next, idx);
-				tmdel = (tdel < 0) ? -1 * tdel : tdel;
-
-				if (tmdel > adel)
-					adel = tmdel;
-
-				if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
-				    next->tree_margin)
-					next->current_dram_clktree[idx] =
-						__MOVAVG_AC(next, idx);
-			}
+			if (dvfs_update || periodic_training_update)
+				over |= tegra210_emc_compare_update_delay(next,
+							__MOVAVG_AC(next, idx), idx);
 		}
 	}
 
-	return adel;
+	return over;
 }
 
-static u32 periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
-					 struct tegra210_emc_timing *last,
-					 struct tegra210_emc_timing *next)
+static bool periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
+					  struct tegra210_emc_timing *last,
+					  struct tegra210_emc_timing *next)
 {
 #define __COPY_EMA(nt, lt, dev)						\
 	({ __MOVAVG(nt, dev) = __MOVAVG(lt, dev) *			\
 	   (nt)->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; })
 
-	u32 i, adel = 0, samples = next->ptfv_list[PTFV_DVFS_SAMPLES_INDEX];
+	u32 i, samples = next->ptfv_list[PTFV_DVFS_SAMPLES_INDEX];
 	u32 idx;
+	bool over = false;
 
 	if (!next->periodic_training)
 		return 0;
@@ -253,23 +252,23 @@ static u32 periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
 
 			for (i = 0; i < samples; i++) {
 				/* Generate next sample of data. */
-				adel = update_clock_tree_delay(emc, DVFS_PT1);
+				update_clock_tree_delay(emc, DVFS_PT1);
 			}
 		}
 
 		/* Do the division part of the moving average */
-		adel = update_clock_tree_delay(emc, DVFS_UPDATE);
+		over = update_clock_tree_delay(emc, DVFS_UPDATE);
 	}
 
 	if (type == PERIODIC_TRAINING_SEQUENCE)
-		adel = update_clock_tree_delay(emc, PERIODIC_TRAINING_UPDATE);
+		over = update_clock_tree_delay(emc, PERIODIC_TRAINING_UPDATE);
 
-	return adel;
+	return over;
 }
 
 static u32 tegra210_emc_r21021_periodic_compensation(struct tegra210_emc *emc)
 {
-	u32 emc_cfg, emc_cfg_o, emc_cfg_update, del, value;
+	u32 emc_cfg, emc_cfg_o, emc_cfg_update, value;
 	static const u32 list[] = {
 		EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0,
 		EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1,
@@ -327,15 +326,12 @@ static u32 tegra210_emc_r21021_periodic_compensation(struct tegra210_emc *emc)
 		 * 4. Check delta wrt previous values (save value if margin
 		 *    exceeds what is set in table).
 		 */
-		del = periodic_compensation_handler(emc,
-						    PERIODIC_TRAINING_SEQUENCE,
-						    last, last);
-
+		if (periodic_compensation_handler(emc, PERIODIC_TRAINING_SEQUENCE,
+						  last, last)) {
 		/*
 		 * 5. Apply compensation w.r.t. trained values (if clock tree
 		 *    has drifted more than the set margin).
 		 */
-		if (last->tree_margin < ((del * 128 * (last->rate / 1000)) / 1000000)) {
 			for (i = 0; i < items; i++) {
 				value = tegra210_emc_compensate(last, list[i]);
 				emc_dbg(emc, EMA_WRITES, "0x%08x <= 0x%08x\n",
@@ -516,11 +512,7 @@ static void tegra210_emc_r21021_set_clock(struct tegra210_emc *emc, u32 clksrc)
 						     EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_MASK,
 						     0);
 
-		value = periodic_compensation_handler(emc, DVFS_SEQUENCE, fake,
-						      next);
-		value = (value * 128 * next->rate / 1000) / 1000000;
-
-		if (next->periodic_training && value > next->tree_margin)
+		if (periodic_compensation_handler(emc, DVFS_SEQUENCE, fake, next))
 			compensate_trimmer_applicable = true;
 	}
 
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/7] memory: tegra: Rework update_clock_tree_delay()
  2024-04-09  9:46 [PATCH 0/7] Cleanup Tegra210 EMC frequency scaling Diogo Ivo
                   ` (5 preceding siblings ...)
  2024-04-09  9:46 ` [PATCH 6/7] memory: tegra: Move compare/update current delay values to a function Diogo Ivo
@ 2024-04-09  9:46 ` Diogo Ivo
  2024-04-13  8:08   ` Krzysztof Kozlowski
  6 siblings, 1 reply; 15+ messages in thread
From: Diogo Ivo @ 2024-04-09  9:46 UTC (permalink / raw)
  To: krzysztof.kozlowski, thierry.reding, jonathanh, linux-tegra; +Cc: Diogo Ivo

Further streamline this function by moving the delay post-processing
to the callers, leaving it only with the task of returing the measured
delay values.

Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
---
 drivers/memory/tegra/tegra210-emc-cc-r21021.c | 120 +++++++-----------
 1 file changed, 46 insertions(+), 74 deletions(-)

diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
index ec2f84758d55..5e2c84fc835c 100644
--- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
+++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
@@ -105,7 +105,7 @@ enum {
 			  next->ptfv_list[w])) /			\
 			(next->ptfv_list[w] + 1);			\
 									\
-		emc_dbg(emc, EMA_UPDATES, "%s: (s=%lu) EMA: %u\n",	\
+		emc_dbg(emc, EMA_UPDATES, "%s: (s=%u) EMA: %u\n",	\
 			__stringify(dev), nval, next->ptfv_list[dqs]);	\
 	} while (0)
 
@@ -130,93 +130,51 @@ static bool tegra210_emc_compare_update_delay(struct tegra210_emc_timing *timing
 	return false;
 }
 
-static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
+static void tegra210_emc_get_clktree_delay(struct tegra210_emc *emc,
+					  u32 delay[DRAM_CLKTREE_NUM])
 {
-	bool periodic_training_update = type == PERIODIC_TRAINING_UPDATE;
-	struct tegra210_emc_timing *last = emc->last;
-	struct tegra210_emc_timing *next = emc->next;
-	u32 last_timing_rate_mhz = last->rate / 1000;
-	bool dvfs_update = type == DVFS_UPDATE;
-	bool dvfs_pt1 = type == DVFS_PT1;
-	u32 temp[2][2], value, udelay;
-	unsigned long cval = 0;
+	struct tegra210_emc_timing *curr = emc->last;
+	u32 rate_mhz = curr->rate / 1000;
+	u32 msb, lsb, dqsosc, udelay;
+	unsigned long clocks = 0;
 	unsigned int c, d, idx;
-	bool over = false;
 
-	if (dvfs_pt1 || periodic_training_update) {
-		udelay = tegra210_emc_actual_osc_clocks(last->run_clocks);
-		udelay *= 1000;
-		udelay = 2 + (udelay / last->rate);
+	clocks = tegra210_emc_actual_osc_clocks(curr->run_clocks);
+	udelay = 2 + (clocks / rate_mhz);
 
-		tegra210_emc_start_periodic_compensation(emc);
-		udelay(udelay);
-	}
+	tegra210_emc_start_periodic_compensation(emc);
+	udelay(udelay);
 
 	for (d = 0; d < emc->num_devices; d++) {
-		if (dvfs_pt1 || periodic_training_update) {
-			/* Dev[d] MSB */
-			value = tegra210_emc_mrr_read(emc, 2 - d, 19);
-
-			for (c = 0; c < emc->num_channels; c++) {
-				temp[c][0] = (value & 0x00ff) << 8;
-				temp[c][1] = (value & 0xff00) << 0;
-				value >>= 16;
-			}
-
-			/* Dev[d] LSB */
-			value = tegra210_emc_mrr_read(emc, 2 - d, 18);
-
-			for (c = 0; c < emc->num_channels; c++) {
-				temp[c][0] |= (value & 0x00ff) >> 0;
-				temp[c][1] |= (value & 0xff00) >> 8;
-				value >>= 16;
-			}
-		}
+		/* Read DQSOSC from MRR18/19 */
+		msb = tegra210_emc_mrr_read(emc, 2 - d, 19);
+		lsb = tegra210_emc_mrr_read(emc, 2 - d, 18);
 
 		for (c = 0; c < emc->num_channels; c++) {
 			/* C[c]D[d]U[0] */
 			idx = c * 4 + d * 2;
 
-			if (dvfs_pt1 || periodic_training_update) {
-				cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
-				cval *= 1000000;
-				cval /= last_timing_rate_mhz * 2 * temp[c][0];
-			}
-
-			if (dvfs_pt1)
-				__INCREMENT_PTFV(idx, cval);
-			else if (dvfs_update)
-				__AVERAGE_PTFV(idx);
-			else if (periodic_training_update)
-				__WEIGHTED_UPDATE_PTFV(idx, cval);
+			dqsosc = (msb & 0x00ff) << 8;
+			dqsosc |= (lsb & 0x00ff) >> 0;
 
-			if (dvfs_update || periodic_training_update)
-				over |= tegra210_emc_compare_update_delay(next,
-							__MOVAVG_AC(next, idx), idx);
+			/* Check for unpopulated channels */
+			if (dqsosc)
+				delay[idx] = clocks * 1000000 / rate_mhz * 2 * dqsosc;
 
 			/* C[c]D[d]U[1] */
 			idx++;
 
-			if (dvfs_pt1 || periodic_training_update) {
-				cval = tegra210_emc_actual_osc_clocks(last->run_clocks);
-				cval *= 1000000;
-				cval /= last_timing_rate_mhz * 2 * temp[c][1];
-			}
+			dqsosc = (msb & 0xff00) << 0;
+			dqsosc |= (lsb & 0xff00) >> 8;
 
-			if (dvfs_pt1)
-				__INCREMENT_PTFV(idx, cval);
-			else if (dvfs_update)
-				__AVERAGE_PTFV(idx);
-			else if (periodic_training_update)
-				__WEIGHTED_UPDATE_PTFV(idx, cval);
+			/* Check for unpopulated channels */
+			if (dqsosc)
+				delay[idx] = clocks * 1000000 / rate_mhz * 2 * dqsosc;
 
-			if (dvfs_update || periodic_training_update)
-				over |= tegra210_emc_compare_update_delay(next,
-							__MOVAVG_AC(next, idx), idx);
+			msb >>= 16;
+			lsb >>= 16;
 		}
 	}
-
-	return over;
 }
 
 static bool periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
@@ -228,7 +186,7 @@ static bool periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
 	   (nt)->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; })
 
 	u32 i, samples = next->ptfv_list[PTFV_DVFS_SAMPLES_INDEX];
-	u32 idx;
+	u32 delay[DRAM_CLKTREE_NUM], idx;
 	bool over = false;
 
 	if (!next->periodic_training)
@@ -252,16 +210,30 @@ static bool periodic_compensation_handler(struct tegra210_emc *emc, u32 type,
 
 			for (i = 0; i < samples; i++) {
 				/* Generate next sample of data. */
-				update_clock_tree_delay(emc, DVFS_PT1);
+				tegra210_emc_get_clktree_delay(emc, delay);
+
+				for (idx = 0; idx < DRAM_CLKTREE_NUM; idx++)
+					__INCREMENT_PTFV(idx, delay[idx]);
 			}
 		}
 
-		/* Do the division part of the moving average */
-		over = update_clock_tree_delay(emc, DVFS_UPDATE);
+		for (idx = 0; idx < DRAM_CLKTREE_NUM; idx++) {
+			/* Do the division part of the moving average */
+			__AVERAGE_PTFV(idx);
+			over |= tegra210_emc_compare_update_delay(next,
+						__MOVAVG_AC(next, idx), idx);
+		}
 	}
 
-	if (type == PERIODIC_TRAINING_SEQUENCE)
-		over = update_clock_tree_delay(emc, PERIODIC_TRAINING_UPDATE);
+	if (type == PERIODIC_TRAINING_SEQUENCE) {
+		tegra210_emc_get_clktree_delay(emc, delay);
+
+		for (idx = 0; idx < DRAM_CLKTREE_NUM; idx++) {
+			__WEIGHTED_UPDATE_PTFV(idx, delay[idx]);
+			over |= tegra210_emc_compare_update_delay(next,
+						__MOVAVG_AC(next, idx), idx);
+		}
+	}
 
 	return over;
 }
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/7] memory: tegra: Change macros to interpret parameter as integer
  2024-04-09  9:46 ` [PATCH 4/7] memory: tegra: Change macros to interpret parameter as integer Diogo Ivo
@ 2024-04-13  8:02   ` Krzysztof Kozlowski
  2024-04-15 11:07     ` Diogo Ivo
  0 siblings, 1 reply; 15+ messages in thread
From: Krzysztof Kozlowski @ 2024-04-13  8:02 UTC (permalink / raw)
  To: Diogo Ivo, thierry.reding, jonathanh, linux-tegra

On 09/04/2024 11:46, Diogo Ivo wrote:
> Convert the macros that manipulate the delay values to interpret their
> index parameter as an integer to allow the introduction of loops.
> 
> Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
> ---
>  drivers/memory/tegra/tegra210-emc-cc-r21021.c | 33 +++++++------------
>  1 file changed, 11 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> index a80c3b575612..65157bd5dc24 100644
> --- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> +++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> @@ -75,29 +75,29 @@ enum {
>   * The division portion of the average operation.
>   */
>  #define __AVERAGE_PTFV(dev)						\
> -	({ next->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] =	\
> -	   next->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] /	\
> +	({ next->ptfv_list[dev] =					\
> +	   next->ptfv_list[dev] /					\

Aren't you missing now () over dev?

Are you sure this passes checkpatch --strict?

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 6/7] memory: tegra: Move compare/update current delay values to a function
  2024-04-09  9:46 ` [PATCH 6/7] memory: tegra: Move compare/update current delay values to a function Diogo Ivo
@ 2024-04-13  8:07   ` Krzysztof Kozlowski
  2024-04-15 11:17     ` Diogo Ivo
  0 siblings, 1 reply; 15+ messages in thread
From: Krzysztof Kozlowski @ 2024-04-13  8:07 UTC (permalink / raw)
  To: Diogo Ivo, thierry.reding, jonathanh, linux-tegra

On 09/04/2024 11:46, Diogo Ivo wrote:
> Separate the comparison/updating of the measured delay values with the
> values currently programmed into a separate function to simplify the
> code.
> 
> Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
> ---
>  drivers/memory/tegra/tegra210-emc-cc-r21021.c | 84 +++++++++----------
>  1 file changed, 38 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> index 566e5c65c854..ec2f84758d55 100644
> --- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> +++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> @@ -113,19 +113,35 @@ enum {
>  #define __MOVAVG(timing, dev)                      \
>  	((timing)->ptfv_list[dev])
>  
> +static bool tegra210_emc_compare_update_delay(struct tegra210_emc_timing *timing,
> +					      u32 measured, u32 idx)
> +{
> +	u32 *curr = &timing->current_dram_clktree[idx];
> +	u32 rate_mhz = timing->rate / 1000;
> +	u32 tmdel;
> +
> +	tmdel = abs(*curr - measured);
> +
> +	if (tmdel * 128 * rate_mhz / 1000000 > timing->tree_margin) {
> +		*curr = measured;
> +		return true;
> +	}
> +
> +	return false;
> +}
> +
>  static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
>  {
>  	bool periodic_training_update = type == PERIODIC_TRAINING_UPDATE;
>  	struct tegra210_emc_timing *last = emc->last;
>  	struct tegra210_emc_timing *next = emc->next;
>  	u32 last_timing_rate_mhz = last->rate / 1000;
> -	u32 next_timing_rate_mhz = next->rate / 1000;
>  	bool dvfs_update = type == DVFS_UPDATE;
> -	s32 tdel = 0, tmdel = 0, adel = 0;
>  	bool dvfs_pt1 = type == DVFS_PT1;
>  	u32 temp[2][2], value, udelay;
>  	unsigned long cval = 0;
>  	unsigned int c, d, idx;
> +	bool over = false;
>  
>  	if (dvfs_pt1 || periodic_training_update) {
>  		udelay = tegra210_emc_actual_osc_clocks(last->run_clocks);
> @@ -174,17 +190,9 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
>  			else if (periodic_training_update)
>  				__WEIGHTED_UPDATE_PTFV(idx, cval);
>  
> -			if (dvfs_update || periodic_training_update) {
> -				tdel = next->current_dram_clktree[idx] -
> -						__MOVAVG_AC(next, idx);
> -				tmdel = (tdel < 0) ? -1 * tdel : tdel;
> -				adel = tmdel;
> -
> -				if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
> -				    next->tree_margin)
> -					next->current_dram_clktree[idx] =
> -						__MOVAVG_AC(next, idx);
> -			}
> +			if (dvfs_update || periodic_training_update)
> +				over |= tegra210_emc_compare_update_delay(next,
> +							__MOVAVG_AC(next, idx), idx);
>  
>  			/* C[c]D[d]U[1] */
>  			idx++;
> @@ -202,35 +210,26 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
>  			else if (periodic_training_update)
>  				__WEIGHTED_UPDATE_PTFV(idx, cval);
>  
> -			if (dvfs_update || periodic_training_update) {
> -				tdel = next->current_dram_clktree[idx] -
> -						__MOVAVG_AC(next, idx);
> -				tmdel = (tdel < 0) ? -1 * tdel : tdel;
> -
> -				if (tmdel > adel)
> -					adel = tmdel;
> -
> -				if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
> -				    next->tree_margin)
> -					next->current_dram_clktree[idx] =
> -						__MOVAVG_AC(next, idx);
> -			}
> +			if (dvfs_update || periodic_training_update)
> +				over |= tegra210_emc_compare_update_delay(next,
> +							__MOVAVG_AC(next, idx), idx);
>  		}
>  	}
>  
> -	return adel;
> +	return over;

You are now returning always 0 or 1, while previously it was tmdel,
which I suppose is not 0/1.

This looks odd, especially that function prototype did not change.



Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 7/7] memory: tegra: Rework update_clock_tree_delay()
  2024-04-09  9:46 ` [PATCH 7/7] memory: tegra: Rework update_clock_tree_delay() Diogo Ivo
@ 2024-04-13  8:08   ` Krzysztof Kozlowski
  2024-04-15 11:22     ` Diogo Ivo
  0 siblings, 1 reply; 15+ messages in thread
From: Krzysztof Kozlowski @ 2024-04-13  8:08 UTC (permalink / raw)
  To: Diogo Ivo, thierry.reding, jonathanh, linux-tegra

On 09/04/2024 11:46, Diogo Ivo wrote:
> Further streamline this function by moving the delay post-processing
> to the callers, leaving it only with the task of returing the measured
> delay values.
> 
> Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
> ---
>  drivers/memory/tegra/tegra210-emc-cc-r21021.c | 120 +++++++-----------
>  1 file changed, 46 insertions(+), 74 deletions(-)
> 
> diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> index ec2f84758d55..5e2c84fc835c 100644
> --- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> +++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> @@ -105,7 +105,7 @@ enum {
>  			  next->ptfv_list[w])) /			\
>  			(next->ptfv_list[w] + 1);			\
>  									\
> -		emc_dbg(emc, EMA_UPDATES, "%s: (s=%lu) EMA: %u\n",	\
> +		emc_dbg(emc, EMA_UPDATES, "%s: (s=%u) EMA: %u\n",	\

Does not look related.



Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/7] memory: tegra: Change macros to interpret parameter as integer
  2024-04-13  8:02   ` Krzysztof Kozlowski
@ 2024-04-15 11:07     ` Diogo Ivo
  0 siblings, 0 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-04-15 11:07 UTC (permalink / raw)
  To: Krzysztof Kozlowski; +Cc: thierry.reding, jonathanh, linux-tegra

Hi Krzysztof,

On Sat, Apr 13, 2024 at 10:02:07AM +0200, Krzysztof Kozlowski wrote:
> On 09/04/2024 11:46, Diogo Ivo wrote:
> > Convert the macros that manipulate the delay values to interpret their
> > index parameter as an integer to allow the introduction of loops.
> > 
> > Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
> > ---
> >  drivers/memory/tegra/tegra210-emc-cc-r21021.c | 33 +++++++------------
> >  1 file changed, 11 insertions(+), 22 deletions(-)
> > 
> > diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> > index a80c3b575612..65157bd5dc24 100644
> > --- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> > +++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> > @@ -75,29 +75,29 @@ enum {
> >   * The division portion of the average operation.
> >   */
> >  #define __AVERAGE_PTFV(dev)						\
> > -	({ next->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] =	\
> > -	   next->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] /	\
> > +	({ next->ptfv_list[dev] =					\
> > +	   next->ptfv_list[dev] /					\
> 
> Aren't you missing now () over dev?

Yes I am, I'll add it for v2.

> Are you sure this passes checkpatch --strict?

It did :)

Thank you for the review!

Best regards,
Diogo

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 6/7] memory: tegra: Move compare/update current delay values to a function
  2024-04-13  8:07   ` Krzysztof Kozlowski
@ 2024-04-15 11:17     ` Diogo Ivo
  0 siblings, 0 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-04-15 11:17 UTC (permalink / raw)
  To: Krzysztof Kozlowski; +Cc: thierry.reding, jonathanh, linux-tegra

On Sat, Apr 13, 2024 at 10:07:44AM +0200, Krzysztof Kozlowski wrote:
> On 09/04/2024 11:46, Diogo Ivo wrote:
> > Separate the comparison/updating of the measured delay values with the
> > values currently programmed into a separate function to simplify the
> > code.
> > 
> > Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
> > ---
> >  drivers/memory/tegra/tegra210-emc-cc-r21021.c | 84 +++++++++----------
> >  1 file changed, 38 insertions(+), 46 deletions(-)
> > 
> > diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> > index 566e5c65c854..ec2f84758d55 100644
> > --- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> > +++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> > @@ -113,19 +113,35 @@ enum {
> >  #define __MOVAVG(timing, dev)                      \
> >  	((timing)->ptfv_list[dev])
> >  
> > +static bool tegra210_emc_compare_update_delay(struct tegra210_emc_timing *timing,
> > +					      u32 measured, u32 idx)
> > +{
> > +	u32 *curr = &timing->current_dram_clktree[idx];
> > +	u32 rate_mhz = timing->rate / 1000;
> > +	u32 tmdel;
> > +
> > +	tmdel = abs(*curr - measured);
> > +
> > +	if (tmdel * 128 * rate_mhz / 1000000 > timing->tree_margin) {
> > +		*curr = measured;
> > +		return true;
> > +	}
> > +
> > +	return false;
> > +}
> > +
> >  static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
> >  {
> >  	bool periodic_training_update = type == PERIODIC_TRAINING_UPDATE;
> >  	struct tegra210_emc_timing *last = emc->last;
> >  	struct tegra210_emc_timing *next = emc->next;
> >  	u32 last_timing_rate_mhz = last->rate / 1000;
> > -	u32 next_timing_rate_mhz = next->rate / 1000;
> >  	bool dvfs_update = type == DVFS_UPDATE;
> > -	s32 tdel = 0, tmdel = 0, adel = 0;
> >  	bool dvfs_pt1 = type == DVFS_PT1;
> >  	u32 temp[2][2], value, udelay;
> >  	unsigned long cval = 0;
> >  	unsigned int c, d, idx;
> > +	bool over = false;
> >  
> >  	if (dvfs_pt1 || periodic_training_update) {
> >  		udelay = tegra210_emc_actual_osc_clocks(last->run_clocks);
> > @@ -174,17 +190,9 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
> >  			else if (periodic_training_update)
> >  				__WEIGHTED_UPDATE_PTFV(idx, cval);
> >  
> > -			if (dvfs_update || periodic_training_update) {
> > -				tdel = next->current_dram_clktree[idx] -
> > -						__MOVAVG_AC(next, idx);
> > -				tmdel = (tdel < 0) ? -1 * tdel : tdel;
> > -				adel = tmdel;
> > -
> > -				if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
> > -				    next->tree_margin)
> > -					next->current_dram_clktree[idx] =
> > -						__MOVAVG_AC(next, idx);
> > -			}
> > +			if (dvfs_update || periodic_training_update)
> > +				over |= tegra210_emc_compare_update_delay(next,
> > +							__MOVAVG_AC(next, idx), idx);
> >  
> >  			/* C[c]D[d]U[1] */
> >  			idx++;
> > @@ -202,35 +210,26 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
> >  			else if (periodic_training_update)
> >  				__WEIGHTED_UPDATE_PTFV(idx, cval);
> >  
> > -			if (dvfs_update || periodic_training_update) {
> > -				tdel = next->current_dram_clktree[idx] -
> > -						__MOVAVG_AC(next, idx);
> > -				tmdel = (tdel < 0) ? -1 * tdel : tdel;
> > -
> > -				if (tmdel > adel)
> > -					adel = tmdel;
> > -
> > -				if (tmdel * 128 * next_timing_rate_mhz / 1000000 >
> > -				    next->tree_margin)
> > -					next->current_dram_clktree[idx] =
> > -						__MOVAVG_AC(next, idx);
> > -			}
> > +			if (dvfs_update || periodic_training_update)
> > +				over |= tegra210_emc_compare_update_delay(next,
> > +							__MOVAVG_AC(next, idx), idx);
> >  		}
> >  	}
> >  
> > -	return adel;
> > +	return over;
> 
> You are now returning always 0 or 1, while previously it was tmdel,
> which I suppose is not 0/1.
> 
> This looks odd, especially that function prototype did not change.

I completely forgot to change the return type of update_clock_tree_delay(),
it should now be bool instead of u32.

Before, tmdel was the largest difference between the current measurements
of delay values and the values that are programmed in the hardware.

All the callers of this function were taking this tmdel return value and
repeating the calculation that I moved to tegra210_emc_compare_update_delay(),
so this return value now simply reflects if the largest measured delay is over
the set margin or not to avoid this repetition.

Best regards,
Diogo

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 7/7] memory: tegra: Rework update_clock_tree_delay()
  2024-04-13  8:08   ` Krzysztof Kozlowski
@ 2024-04-15 11:22     ` Diogo Ivo
  2024-04-18 17:19       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 15+ messages in thread
From: Diogo Ivo @ 2024-04-15 11:22 UTC (permalink / raw)
  To: Krzysztof Kozlowski; +Cc: thierry.reding, jonathanh, linux-tegra

On Sat, Apr 13, 2024 at 10:08:40AM +0200, Krzysztof Kozlowski wrote:
> On 09/04/2024 11:46, Diogo Ivo wrote:
> > Further streamline this function by moving the delay post-processing
> > to the callers, leaving it only with the task of returing the measured
> > delay values.
> > 
> > Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
> > ---
> >  drivers/memory/tegra/tegra210-emc-cc-r21021.c | 120 +++++++-----------
> >  1 file changed, 46 insertions(+), 74 deletions(-)
> > 
> > diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> > index ec2f84758d55..5e2c84fc835c 100644
> > --- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> > +++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
> > @@ -105,7 +105,7 @@ enum {
> >  			  next->ptfv_list[w])) /			\
> >  			(next->ptfv_list[w] + 1);			\
> >  									\
> > -		emc_dbg(emc, EMA_UPDATES, "%s: (s=%lu) EMA: %u\n",	\
> > +		emc_dbg(emc, EMA_UPDATES, "%s: (s=%u) EMA: %u\n",	\
> 
> Does not look related.

This was necessary to avoid compiler warnings as before when we were calling
this macro from update_clock_tree_delay() the value we were passing in was
declared as an unsigned long and now it is declared as u32, which it still
big enough for the values we are dealing with here.

Best regards,
Diogo

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 7/7] memory: tegra: Rework update_clock_tree_delay()
  2024-04-15 11:22     ` Diogo Ivo
@ 2024-04-18 17:19       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 15+ messages in thread
From: Krzysztof Kozlowski @ 2024-04-18 17:19 UTC (permalink / raw)
  To: Diogo Ivo; +Cc: thierry.reding, jonathanh, linux-tegra

On 15/04/2024 13:22, Diogo Ivo wrote:
> On Sat, Apr 13, 2024 at 10:08:40AM +0200, Krzysztof Kozlowski wrote:
>> On 09/04/2024 11:46, Diogo Ivo wrote:
>>> Further streamline this function by moving the delay post-processing
>>> to the callers, leaving it only with the task of returing the measured
>>> delay values.
>>>
>>> Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
>>> ---
>>>  drivers/memory/tegra/tegra210-emc-cc-r21021.c | 120 +++++++-----------
>>>  1 file changed, 46 insertions(+), 74 deletions(-)
>>>
>>> diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
>>> index ec2f84758d55..5e2c84fc835c 100644
>>> --- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c
>>> +++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c
>>> @@ -105,7 +105,7 @@ enum {
>>>  			  next->ptfv_list[w])) /			\
>>>  			(next->ptfv_list[w] + 1);			\
>>>  									\
>>> -		emc_dbg(emc, EMA_UPDATES, "%s: (s=%lu) EMA: %u\n",	\
>>> +		emc_dbg(emc, EMA_UPDATES, "%s: (s=%u) EMA: %u\n",	\
>>
>> Does not look related.
> 
> This was necessary to avoid compiler warnings as before when we were calling
> this macro from update_clock_tree_delay() the value we were passing in was
> declared as an unsigned long and now it is declared as u32, which it still
> big enough for the values we are dealing with here.

OK, that's difficult to see from the patch context but looks right.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2024-04-18 17:19 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-09  9:46 [PATCH 0/7] Cleanup Tegra210 EMC frequency scaling Diogo Ivo
2024-04-09  9:46 ` [PATCH 1/7] memory: tegra: Remove periodic compensation duplicate calls Diogo Ivo
2024-04-09  9:46 ` [PATCH 2/7] memory: tegra: Move DQSOSC measurement to common place Diogo Ivo
2024-04-09  9:46 ` [PATCH 3/7] memory: tegra: Reword and correct comments Diogo Ivo
2024-04-09  9:46 ` [PATCH 4/7] memory: tegra: Change macros to interpret parameter as integer Diogo Ivo
2024-04-13  8:02   ` Krzysztof Kozlowski
2024-04-15 11:07     ` Diogo Ivo
2024-04-09  9:46 ` [PATCH 5/7] memory: tegra: Loop update_clock_tree_delay() Diogo Ivo
2024-04-09  9:46 ` [PATCH 6/7] memory: tegra: Move compare/update current delay values to a function Diogo Ivo
2024-04-13  8:07   ` Krzysztof Kozlowski
2024-04-15 11:17     ` Diogo Ivo
2024-04-09  9:46 ` [PATCH 7/7] memory: tegra: Rework update_clock_tree_delay() Diogo Ivo
2024-04-13  8:08   ` Krzysztof Kozlowski
2024-04-15 11:22     ` Diogo Ivo
2024-04-18 17:19       ` Krzysztof Kozlowski

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).