From: Hugo Villeneuve Date: Fri, 17 Apr 2026 14:53:32 +0000 (-0400) Subject: serial: max310x: improve max310x_set_ref_clk() efficiency X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d0001adcd1f838d97bc23a20375f60bb3304aa5c;p=thirdparty%2Flinux.git serial: max310x: improve max310x_set_ref_clk() efficiency 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 Link: https://patch.msgid.link/20260417-max310x-2-v1-5-b424e105ecac@dimonoff.com Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index f689958736f71..1cd7632831a28 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; }