From: Andrei Simion Date: Wed, 9 Nov 2011 02:16:51 +0000 (-0800) Subject: Xilinx: ARM: Flexible baud rate calculation. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=025346c3a3268af318aae925a617d49786a84756;p=thirdparty%2Fu-boot.git Xilinx: ARM: Flexible baud rate calculation. 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'. --- diff --git a/drivers/serial/serial_xpssuart.c b/drivers/serial/serial_xpssuart.c index ad9428e1733..dffae7d1486 100644 --- a/drivers/serial/serial_xpssuart.c +++ b/drivers/serial/serial_xpssuart.c @@ -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); } diff --git a/drivers/serial/serial_xpssuart.h b/drivers/serial/serial_xpssuart.h index 1b871411c8b..cd0295407d1 100644 --- a/drivers/serial/serial_xpssuart.h +++ b/drivers/serial/serial_xpssuart.h @@ -12,18 +12,15 @@ #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] */