[U-Boot] [PATCH v4 04/11] serial: Use a more precise baud rate generation for serial_s3c24x0

José Miguel Gonçalves jose.goncalves at inov.pt
Wed Sep 19 13:25:20 CEST 2012


The values stored in the baud rate divisor register (UBRDIVn) and dividing
slot register (UDIVSLOTn), are used to determine the serial baudrate.
Previously only UBRDIVn was set. This patch initializes also UDIVSLOTn
which allows to obtain a more precise baudrate.

Signed-off-by: José Miguel Gonçalves <jose.goncalves at inov.pt>
---
Changes for v2:
   - New patch

Changes for v3:
   - Verbose patch description

Changes for v4:
   - None
---
 drivers/serial/serial_s3c24x0.c |   24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c24x0.c
index 280cd2d..c9bc121 100644
--- a/drivers/serial/serial_s3c24x0.c
+++ b/drivers/serial/serial_s3c24x0.c
@@ -92,16 +92,32 @@ DECLARE_GLOBAL_DATA_PTR;
 static int hwflow;
 #endif
 
+/*
+ * The values stored in the baud rate divisor register (UBRDIVn) and dividing
+ * slot register (UDIVSLOTn), are used to determine the serial Tx/Rx clock rate
+ * (baud rate) as follows:
+ *     DIV_VAL = UBRDIVn + (num of 1’s in UDIVSLOTn) / 16
+ * Using UDIVSLOT, which is the factor of floating point divisor, you can make
+ * more accurate baud rate. Section 2.1.10 of the S3C2416 User's Manual suggests
+ * using the constants on the following table.
+ */
+static const int udivslot[] = {
+	0x0000, 0x0080, 0x0808, 0x0888, 0x2222, 0x4924, 0x4A52, 0x54AA,
+	0x5555, 0xD555, 0xD5D5, 0xDDD5, 0xDDDD, 0xDFDD, 0xDFDF, 0xFFDF,
+};
+
 void _serial_setbrg(const int dev_index)
 {
 	struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
-	unsigned int reg = 0;
+	u32 pclk;
+	u32 baudrate;
 	int i;
 
-	/* value is calculated so : (int)(PCLK/16./baudrate) -1 */
-	reg = get_PCLK() / (16 * gd->baudrate) - 1;
+	pclk = get_PCLK();
+	baudrate = gd->baudrate;
 
-	writel(reg, &uart->ubrdiv);
+	writel((pclk / baudrate / 16) - 1, &uart->ubrdiv);
+	writel(udivslot[(pclk / baudrate) % 16], &uart->udivslot);
 	for (i = 0; i < 100; i++)
 		/* Delay */ ;
 }
-- 
1.7.9.5



More information about the U-Boot mailing list