Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

memory: tegra: Move compare/update current delay values to a function

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>
Link: https://lore.kernel.org/r/20240704-tegra210_emcfreq-v4-6-3e450503c555@tecnico.ulisboa.pt
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

authored by

Diogo Ivo and committed by
Krzysztof Kozlowski
b109656e adc72082

+39 -47
+39 -47
drivers/memory/tegra/tegra210-emc-cc-r21021.c
··· 113 113 #define __MOVAVG(timing, dev) \ 114 114 ((timing)->ptfv_list[(dev)]) 115 115 116 - static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type) 116 + static bool tegra210_emc_compare_update_delay(struct tegra210_emc_timing *timing, 117 + u32 measured, u32 idx) 118 + { 119 + u32 *curr = &timing->current_dram_clktree[idx]; 120 + u32 rate_mhz = timing->rate / 1000; 121 + u32 tmdel; 122 + 123 + tmdel = abs(*curr - measured); 124 + 125 + if (tmdel * 128 * rate_mhz / 1000000 > timing->tree_margin) { 126 + *curr = measured; 127 + return true; 128 + } 129 + 130 + return false; 131 + } 132 + 133 + static bool update_clock_tree_delay(struct tegra210_emc *emc, int type) 117 134 { 118 135 bool periodic_training_update = type == PERIODIC_TRAINING_UPDATE; 119 136 struct tegra210_emc_timing *last = emc->last; 120 137 struct tegra210_emc_timing *next = emc->next; 121 138 u32 last_timing_rate_mhz = last->rate / 1000; 122 - u32 next_timing_rate_mhz = next->rate / 1000; 123 139 bool dvfs_update = type == DVFS_UPDATE; 124 - s32 tdel = 0, tmdel = 0, adel = 0; 125 140 bool dvfs_pt1 = type == DVFS_PT1; 126 141 u32 temp[2][2], value, delay_us; 127 142 unsigned long cval = 0; 128 143 unsigned int c, d, idx; 144 + bool over = false; 129 145 130 146 if (dvfs_pt1 || periodic_training_update) { 131 147 delay_us = tegra210_emc_actual_osc_clocks(last->run_clocks); ··· 190 174 else if (periodic_training_update) 191 175 __WEIGHTED_UPDATE_PTFV(idx, cval); 192 176 193 - if (dvfs_update || periodic_training_update) { 194 - tdel = next->current_dram_clktree[idx] - 195 - __MOVAVG_AC(next, idx); 196 - tmdel = (tdel < 0) ? -1 * tdel : tdel; 197 - adel = tmdel; 198 - 199 - if (tmdel * 128 * next_timing_rate_mhz / 1000000 > 200 - next->tree_margin) 201 - next->current_dram_clktree[idx] = 202 - __MOVAVG_AC(next, idx); 203 - } 177 + if (dvfs_update || periodic_training_update) 178 + over |= tegra210_emc_compare_update_delay(next, 179 + __MOVAVG_AC(next, idx), idx); 204 180 205 181 /* C[c]D[d]U[1] */ 206 182 idx++; ··· 210 202 else if (periodic_training_update) 211 203 __WEIGHTED_UPDATE_PTFV(idx, cval); 212 204 213 - if (dvfs_update || periodic_training_update) { 214 - tdel = next->current_dram_clktree[idx] - 215 - __MOVAVG_AC(next, idx); 216 - tmdel = (tdel < 0) ? -1 * tdel : tdel; 217 - 218 - if (tmdel > adel) 219 - adel = tmdel; 220 - 221 - if (tmdel * 128 * next_timing_rate_mhz / 1000000 > 222 - next->tree_margin) 223 - next->current_dram_clktree[idx] = 224 - __MOVAVG_AC(next, idx); 225 - } 205 + if (dvfs_update || periodic_training_update) 206 + over |= tegra210_emc_compare_update_delay(next, 207 + __MOVAVG_AC(next, idx), idx); 226 208 } 227 209 } 228 210 229 - return adel; 211 + return over; 230 212 } 231 213 232 - static u32 periodic_compensation_handler(struct tegra210_emc *emc, u32 type, 233 - struct tegra210_emc_timing *last, 234 - struct tegra210_emc_timing *next) 214 + static bool periodic_compensation_handler(struct tegra210_emc *emc, u32 type, 215 + struct tegra210_emc_timing *last, 216 + struct tegra210_emc_timing *next) 235 217 { 236 218 #define __COPY_EMA(nt, lt, dev) \ 237 219 ({ __MOVAVG(nt, dev) = __MOVAVG(lt, dev) * \ 238 220 (nt)->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; }) 239 221 240 - u32 i, adel = 0, samples = next->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; 222 + u32 i, samples = next->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; 223 + bool over = false; 241 224 u32 idx; 242 225 243 226 if (!next->periodic_training) ··· 252 253 253 254 for (i = 0; i < samples; i++) { 254 255 /* Generate next sample of data. */ 255 - adel = update_clock_tree_delay(emc, DVFS_PT1); 256 + update_clock_tree_delay(emc, DVFS_PT1); 256 257 } 257 258 } 258 259 259 260 /* Do the division part of the moving average */ 260 - adel = update_clock_tree_delay(emc, DVFS_UPDATE); 261 + over = update_clock_tree_delay(emc, DVFS_UPDATE); 261 262 } 262 263 263 264 if (type == PERIODIC_TRAINING_SEQUENCE) 264 - adel = update_clock_tree_delay(emc, PERIODIC_TRAINING_UPDATE); 265 + over = update_clock_tree_delay(emc, PERIODIC_TRAINING_UPDATE); 265 266 266 - return adel; 267 + return over; 267 268 } 268 269 269 270 static u32 tegra210_emc_r21021_periodic_compensation(struct tegra210_emc *emc) 270 271 { 271 - u32 emc_cfg, emc_cfg_o, emc_cfg_update, del, value; 272 + u32 emc_cfg, emc_cfg_o, emc_cfg_update, value; 272 273 static const u32 list[] = { 273 274 EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0, 274 275 EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1, ··· 326 327 * 4. Check delta wrt previous values (save value if margin 327 328 * exceeds what is set in table). 328 329 */ 329 - del = periodic_compensation_handler(emc, 330 - PERIODIC_TRAINING_SEQUENCE, 331 - last, last); 332 - 330 + if (periodic_compensation_handler(emc, PERIODIC_TRAINING_SEQUENCE, 331 + last, last)) { 333 332 /* 334 333 * 5. Apply compensation w.r.t. trained values (if clock tree 335 334 * has drifted more than the set margin). 336 335 */ 337 - if (last->tree_margin < ((del * 128 * (last->rate / 1000)) / 1000000)) { 338 336 for (i = 0; i < items; i++) { 339 337 value = tegra210_emc_compensate(last, list[i]); 340 338 emc_dbg(emc, EMA_WRITES, "0x%08x <= 0x%08x\n", ··· 512 516 EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_MASK, 513 517 0); 514 518 515 - value = periodic_compensation_handler(emc, DVFS_SEQUENCE, fake, 516 - next); 517 - value = (value * 128 * next->rate / 1000) / 1000000; 518 - 519 - if (next->periodic_training && value > next->tree_margin) 519 + if (periodic_compensation_handler(emc, DVFS_SEQUENCE, fake, next)) 520 520 compensate_trimmer_applicable = true; 521 521 } 522 522