[PATCH 05/10] serial: max310x: improve max310x_set_ref_clk() efficiency
From: Hugo Villeneuve
Date: Fri Apr 17 2026 - 10:54:14 EST
From: Hugo Villeneuve <hvilleneuve@xxxxxxxxxxxx>
The same basic code is duplicated for each of the four PLL multiplier
values, so simplify and streamline it. Doing so allows us to avoid
some unnecessary (fdiv * factor) multiplications for some fdiv values and
replace the second "if" statement with an "else if" and avoid a useless
comparison.
Signed-off-by: Hugo Villeneuve <hvilleneuve@xxxxxxxxxxxx>
---
drivers/tty/serial/max310x.c | 91 +++++++++++++++++++++++++-------------------
1 file changed, 52 insertions(+), 39 deletions(-)
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index f689958736f71b15b7c113214cda60db4aa7c593..1cd7632831a2826ddd42127b1cde2a10dfa412f0 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -258,6 +258,17 @@
#define MAX14830_BRGCFG_CLKDIS_BIT (1 << 6) /* Clock Disable */
#define MAX14830_REV_ID (0xb0)
+struct max310x_clk_config_t {
+ u8 prediv; /* Predivider */
+ u8 pll_mult; /* PLL multiplier */
+ unsigned int fref; /*
+ * Reference clock for fractional baud rate generator:
+ * PLL enabled: (freq / prediv) x pll_mult
+ * PLL disabled: freq
+ */
+ unsigned int err; /* Computed error for selected parameters */
+};
+
struct max310x_if_cfg {
int (*extended_reg_enable)(struct device *dev, bool enable);
u8 rev_id_offset;
@@ -545,70 +556,72 @@ static int max310x_set_baud(struct uart_port *port, int baud)
return (16*port->uartclk) / (c*(16*div + frac));
}
-static int max310x_update_best_err(unsigned int f, unsigned int *besterr)
+static void max310x_try_cfg(unsigned int fdiv, u8 div, u8 pll_mult,
+ struct max310x_clk_config_t *cfg)
{
+ unsigned int fmul = fdiv * pll_mult;
+ unsigned int err;
+
/* Use high-enough baudrate to calculate error */
- unsigned int err = f % (460800 * 16);
+ err = fmul % (460800 * 16);
- if (*besterr > err) {
- *besterr = err;
- return 0;
+ if (cfg->err > err) {
+ cfg->err = err;
+ cfg->pll_mult = pll_mult;
+ cfg->prediv = div;
+ cfg->fref = fmul;
}
+}
- return 1;
+static u8 max310x_pll_mult_to_id(u8 pll_mult)
+{
+ switch (pll_mult) {
+ case 144: return 3;
+ case 96: return 2;
+ case 48: return 1;
+ case 6:
+ default: return 0;
+ }
}
static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
unsigned int freq, unsigned int *fref, bool xtal)
{
- unsigned int div, clksrc, pllcfg = 0;
- unsigned int besterr = UINT_MAX;
- unsigned int fdiv, fmul, bestfreq = freq;
+ unsigned int div, fdiv, clksrc;
+ struct max310x_clk_config_t cfg;
+
+ cfg.err = UINT_MAX;
+ cfg.prediv = 0;
+ cfg.fref = freq;
/* First, update error without PLL */
- max310x_update_best_err(freq, &besterr);
+ max310x_try_cfg(freq, 1, 1, &cfg);
/* Try all possible PLL dividers */
- for (div = 1; (div <= 63) && besterr; div++) {
+ for (div = 1; (div <= 63) && cfg.err; div++) {
fdiv = DIV_ROUND_CLOSEST(freq, div);
- /* Try multiplier 6 */
- fmul = fdiv * 6;
if ((fdiv >= 500000) && (fdiv <= 800000))
- if (!max310x_update_best_err(fmul, &besterr)) {
- pllcfg = (0 << 6) | div;
- bestfreq = fmul;
- }
- /* Try multiplier 48 */
- fmul = fdiv * 48;
- if ((fdiv >= 850000) && (fdiv <= 1200000))
- if (!max310x_update_best_err(fmul, &besterr)) {
- pllcfg = (1 << 6) | div;
- bestfreq = fmul;
- }
- /* Try multiplier 96 */
- fmul = fdiv * 96;
+ max310x_try_cfg(fdiv, div, 6, &cfg); /* PLL x6 */
+ else if ((fdiv >= 850000) && (fdiv <= 1200000))
+ max310x_try_cfg(fdiv, div, 48, &cfg); /* PLL x48 */
+
if ((fdiv >= 425000) && (fdiv <= 1000000))
- if (!max310x_update_best_err(fmul, &besterr)) {
- pllcfg = (2 << 6) | div;
- bestfreq = fmul;
- }
- /* Try multiplier 144 */
- fmul = fdiv * 144;
+ max310x_try_cfg(fdiv, div, 96, &cfg); /* PLL x96 */
+
if ((fdiv >= 390000) && (fdiv <= 667000))
- if (!max310x_update_best_err(fmul, &besterr)) {
- pllcfg = (3 << 6) | div;
- bestfreq = fmul;
- }
+ max310x_try_cfg(fdiv, div, 144, &cfg); /* PLL x144 */
}
/* Configure clock source */
clksrc = MAX310X_CLKSRC_EXTCLK_BIT | (xtal ? MAX310X_CLKSRC_CRYST_BIT : 0);
/* Configure PLL */
- if (pllcfg) {
+ if (cfg.prediv) {
+ u8 pll_id = max310x_pll_mult_to_id(cfg.pll_mult);
+
clksrc |= MAX310X_CLKSRC_PLL_BIT;
- regmap_write(s->regmap, MAX310X_PLLCFG_REG, pllcfg);
+ regmap_write(s->regmap, MAX310X_PLLCFG_REG, (pll_id << 6) | cfg.prediv);
} else
clksrc |= MAX310X_CLKSRC_PLLBYP_BIT;
@@ -632,7 +645,7 @@ static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
"clock is not stable\n");
}
- *fref = bestfreq;
+ *fref = cfg.fref;
return 0;
}
--
2.47.3