|
|
@@ -491,37 +491,48 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
|
|
|
|
|
|
static int max310x_set_baud(struct uart_port *port, int baud)
|
|
|
{
|
|
|
- unsigned int mode = 0, clk = port->uartclk, div = clk / baud;
|
|
|
+ unsigned int mode = 0, div = 0, frac = 0, c = 0, F = 0;
|
|
|
|
|
|
- /* Check for minimal value for divider */
|
|
|
- if (div < 16)
|
|
|
- div = 16;
|
|
|
-
|
|
|
- if (clk % baud && (div / 16) < 0x8000) {
|
|
|
+ /*
|
|
|
+ * Calculate the integer divisor first. Select a proper mode
|
|
|
+ * in case if the requested baud is too high for the pre-defined
|
|
|
+ * clocks frequency.
|
|
|
+ */
|
|
|
+ div = port->uartclk / baud;
|
|
|
+ if (div < 8) {
|
|
|
+ /* Mode x4 */
|
|
|
+ c = 4;
|
|
|
+ mode = MAX310X_BRGCFG_4XMODE_BIT;
|
|
|
+ } else if (div < 16) {
|
|
|
/* Mode x2 */
|
|
|
+ c = 8;
|
|
|
mode = MAX310X_BRGCFG_2XMODE_BIT;
|
|
|
- clk = port->uartclk * 2;
|
|
|
- div = clk / baud;
|
|
|
-
|
|
|
- if (clk % baud && (div / 16) < 0x8000) {
|
|
|
- /* Mode x4 */
|
|
|
- mode = MAX310X_BRGCFG_4XMODE_BIT;
|
|
|
- clk = port->uartclk * 4;
|
|
|
- div = clk / baud;
|
|
|
- }
|
|
|
+ } else {
|
|
|
+ c = 16;
|
|
|
}
|
|
|
|
|
|
- max310x_port_write(port, MAX310X_BRGDIVMSB_REG, (div / 16) >> 8);
|
|
|
- max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div / 16);
|
|
|
- max310x_port_write(port, MAX310X_BRGCFG_REG, (div % 16) | mode);
|
|
|
+ /* Calculate the divisor in accordance with the fraction coefficient */
|
|
|
+ div /= c;
|
|
|
+ F = c*baud;
|
|
|
+
|
|
|
+ /* Calculate the baud rate fraction */
|
|
|
+ if (div > 0)
|
|
|
+ frac = (16*(port->uartclk % F)) / F;
|
|
|
+ else
|
|
|
+ div = 1;
|
|
|
+
|
|
|
+ max310x_port_write(port, MAX310X_BRGDIVMSB_REG, div >> 8);
|
|
|
+ max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div);
|
|
|
+ max310x_port_write(port, MAX310X_BRGCFG_REG, frac | mode);
|
|
|
|
|
|
- return DIV_ROUND_CLOSEST(clk, div);
|
|
|
+ /* Return the actual baud rate we just programmed */
|
|
|
+ return (16*port->uartclk) / (c*(16*div + frac));
|
|
|
}
|
|
|
|
|
|
static int max310x_update_best_err(unsigned long f, long *besterr)
|
|
|
{
|
|
|
/* Use baudrate 115200 for calculate error */
|
|
|
- long err = f % (115200 * 16);
|
|
|
+ long err = f % (460800 * 16);
|
|
|
|
|
|
if ((*besterr < 0) || (*besterr > err)) {
|
|
|
*besterr = err;
|