
Newer Atmel chips (post-AT91SAM9261; including AT91SAM9260 and all AVR32 chips) have a "Fractional Part" bitfield in BRGR that allows more precise baud rate generation. Use this field to make the USART work on lower clock frequencies, for example when not using the PLL, on chips that support it.
Signed-off-by: Haavard Skinnemoen haavard.skinnemoen@atmel.com --- drivers/serial/atmel_usart.c | 14 ++++++++++++-- drivers/serial/atmel_usart.h | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c index f35b997..61ed308 100644 --- a/drivers/serial/atmel_usart.c +++ b/drivers/serial/atmel_usart.c @@ -44,6 +44,8 @@ void serial_setbrg(void) { unsigned long divisor; unsigned long usart_hz; + unsigned long cd; + unsigned long fp;
/* * Master Clock @@ -51,8 +53,16 @@ void serial_setbrg(void) * 16 * CD */ usart_hz = get_usart_clk_rate(USART_ID); - divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate; - usart3_writel(BRGR, USART3_BF(CD, divisor)); + divisor = ((usart_hz + 1) / 2 + gd->baudrate / 2) / gd->baudrate; +#if defined(CONFIG_AT91RM9200) || defined(CONFIG_AT91SAM9261) + /* Some chips don't support fractional dividers */ + cd = (divisor + 4) / 8; + fp = 0; +#else + cd = divisor / 8; + fp = divisor % 8; +#endif + usart3_writel(BRGR, USART3_BF(CD, cd) | USART3_BF(FP, fp)); }
int serial_init(void) diff --git a/drivers/serial/atmel_usart.h b/drivers/serial/atmel_usart.h index af3773a..82da20b 100644 --- a/drivers/serial/atmel_usart.h +++ b/drivers/serial/atmel_usart.h @@ -178,6 +178,8 @@ /* Bitfields in BRGR */ #define USART3_CD_OFFSET 0 #define USART3_CD_SIZE 16 +#define USART3_FP_OFFSET 16 +#define USART3_FP_SIZE 3
/* Bitfields in RTOR */ #define USART3_TO_OFFSET 0