From patchwork Fri Sep 21 18:47:41 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [U-Boot, v5, 04/11] serial: Use a more precise baud rate generation for serial_s3c24x0 Date: Fri, 21 Sep 2012 08:47:41 -0000 From: =?utf-8?q?Jos=C3=A9_Miguel_Gon=C3=A7alves_=3Cjose=2Egoncalves=40inov?= =?utf-8?q?=2Ept=3E?= X-Patchwork-Id: 185875 Message-Id: <1348253268-21812-5-git-send-email-jose.goncalves@inov.pt> To: u-boot@lists.denx.de Cc: marex@denx.de, trini@ti.com, =?UTF-8?q?Jos=C3=A9=20Miguel=20Gon=C3=A7alves?= , scottwood@freescale.com 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 --- Changes for v2: - New patch Changes for v3: - Verbose patch description Changes for v4: - None Changes for v5: - 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 */ ; }