]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
Xilinx: ARM: Flexible baud rate calculation.
authorAndrei Simion <andreis@xilinx.com>
Wed, 9 Nov 2011 02:16:51 +0000 (18:16 -0800)
committerJohn Linn <john.linn@xilinx.com>
Fri, 11 Nov 2011 18:18:04 +0000 (10:18 -0800)
Values used in U-boot's baud rate calculation are chosen in such
a way to keep the error between the target and calculated baud
rate under 3%.

The header was changed to avoid hardcoding values such as the ones
used in the baud rate calculation. The UART input frequency uses
the value defined in 'xparameters.h'.

drivers/serial/serial_xpssuart.c
drivers/serial/serial_xpssuart.h

index ad9428e1733ae5580c1e232384c8bdc020e93ff7..dffae7d1486dd41fbd5f02740fb3b3533ec4fd81 100644 (file)
@@ -15,26 +15,38 @@ void serial_setbrg(void)
        /*              master clock
         * Baud rate = ---------------
         *              bgen*(bdiv+1)
-        *
-        * master clock = 50MHz (I think?)
-        * bdiv remains at default (reset) 15
-        *
-        * Simplify RHS to base/bgen, where base == master/16
         */
-       long base = XDFUART_BASECLK;
        long baud = gd->baudrate;
-       long bgen = base / baud;
-       long base_err = base - (bgen*baud);
-       long mod_bgen = bgen + (base_err >= 0 ? 1 : -1);
-       long mod_err = base - (mod_bgen*baud);
 
-       /* you'd think there'd be an abs() macro somewhere in include/... */
-       mod_err = mod_err < 0 ? -mod_err : mod_err;
-       base_err = base_err < 0 ? -base_err : base_err;
+       /* Variables to vary. */
+       unsigned int bdiv, bgen;
 
-       bgen = mod_err < base_err ? mod_bgen : bgen;
+       /* Calculation results. */
+       long calc_baud = 0;
+       unsigned int calc_bauderror;
 
-       xdfuart_writel(BAUDDIV,XDFUART_BDIV); /* Ensure it's 15 */
+       /* Find acceptable values for baud generation. */
+       for (bdiv = 4; bdiv < 255; bdiv++) {
+
+               bgen = XDFUART_MASTER / (baud * (bdiv + 1));
+               if (bgen < 2 || bgen > 65535)
+                       continue;
+
+               calc_baud = XDFUART_MASTER / (bgen * (bdiv + 1));
+
+               /* Use first calculated baudrate with an acceptable
+                * (<3%) error.
+                */
+               if (baud > calc_baud)
+                       calc_bauderror = baud - calc_baud;
+               else
+                       calc_bauderror = calc_baud - baud;
+               if ( ((calc_bauderror * 100) / baud) < 3 )
+                       break;
+
+       }
+
+       xdfuart_writel(BAUDDIV,bdiv);
        xdfuart_writel(BAUDGEN,bgen);
 }
 
index 1b871411c8bb892694c1380a89f42a5602dae729..cd0295407d1c5176d1d91a9796cb904efe2ebf54 100644 (file)
 #if defined(CONFIG_UART0)
 # define UART_ID   0
 # define UART_BASE XPSS_UART0_BASEADDR
+# define XDFUART_MASTER XPAR_XUARTPSS_0_CLOCK_HZ
 #elif defined(CONFIG_UART1)
 # define UART_ID   1
 # define UART_BASE XPSS_UART1_BASEADDR
+# define XDFUART_MASTER XPAR_XUARTPSS_1_CLOCK_HZ
 #else
 # error "Need to configure a UART (0 or 1)"
 #endif
 
-/* Some clock/baud constants */
-#define XDFUART_MASTER 50000000L /* Master clock source for UART */
-#define XDFUART_BDIV          15 /* Default/reset BDIV value */
-#define XDFUART_BASECLK 3125000L /* master/(bdiv+1) */
-
 /* UART register offsets */
 #define XDFUART_CR_OFFSET          0x00  /* Control Register [8:0] */
 #define XDFUART_MR_OFFSET          0x04  /* Mode Register [10:0] */