
Program udivslot register in order to obtain a more precise baudrate.
Signed-off-by: José Miguel Gonçalves jose.goncalves@inov.pt --- Changes for v2: - New patch --- 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 */ ; }