Skip to contentSkip to conversation

Round the serial port clock divisor value returned by calc_divisor()

PATCH New Jerry Van Baren 3 participants 3 messages Jul 11, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Round the serial port clock divisor value returned by calc_divisor()

This formula is better at avoiding integer overflow.

---

(try 2)

The formula I proposed previously in this thread compiles OK. I cannot verify it is correct on real hardware, however.
<http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/43499/focus=43506>

Best regards,
gvb

 drivers/serial/serial.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)
drivers/serial/serial.c +3 -1
index 182ca2d..48579ae 100644
@@ -150,7 +150,9 @@ static int calc_divisor (NS16550_t port)
 	 * but we need to round that value by adding 0.5 or 8/16.
 	 * Rounding is especially important at high baud rates.
 	 */
-	return (((16 * CFG_NS16550_CLK) / MODE_X_DIV / gd->baudrate) + 8) / 16;
+	return (CFG_NS16550_CLK + (gd->baudrate / 2)) /
+		(MODE_X_DIV * gd->baudrate);
+
 }
 
 #if !defined(CONFIG_SERIAL_MULTI)
Signature · 1 line
1.5.6
#1 lore raw

PATCH 1/1 Round the serial port clock divisor valuereturned by calc_divisor()

Quoted 1 line · u-boot-users-bounces at lists.sourceforge.net

This formula is better at avoiding integer overflow.

This patch doesn?t round the value correctly.

Wolfgang, I will resubmit a new patch shortly today to fix the problem.

Hugo V.

#2 lore raw

PATCH 1/1 Round the serial port clock divisor valuereturned by calc_divisor()

Quoted 8 lines · Hugo Villeneuve
Quoted 1 line · u-boot-users-bounces at lists.sourceforge.net

This formula is better at avoiding integer overflow.

This patch doesn?t round the value correctly.

Wolfgang, I will resubmit a new patch shortly today to fix the problem.

Hugo V.

Arrgh, you are right. I know you solved it already, but for the record I oversimplified:
(gd->baudrate / 2)
should have been:
(gd->baudrate * (MODE_X_DIV / 2))

WRONG:
+ return (CFG_NS16550_CLK + (gd->baudrate / 2)) /
+ (MODE_X_DIV * gd->baudrate);

should have been
+ return (CFG_NS16550_CLK + (gd->baudrate * (MODE_X_DIV / 2))) /
+ (MODE_X_DIV * gd->baudrate);

Sorry,
gvb