diff options
Diffstat (limited to 'recipes/linux/linux-2.6.24/ts72xx/ep93xx-serial-uartbaud.diff')
-rw-r--r-- | recipes/linux/linux-2.6.24/ts72xx/ep93xx-serial-uartbaud.diff | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.24/ts72xx/ep93xx-serial-uartbaud.diff b/recipes/linux/linux-2.6.24/ts72xx/ep93xx-serial-uartbaud.diff new file mode 100644 index 0000000000..7183ab626e --- /dev/null +++ b/recipes/linux/linux-2.6.24/ts72xx/ep93xx-serial-uartbaud.diff @@ -0,0 +1,66 @@ + +Force UARTBAUD on before uncompressing. + +Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> + +Index: linux-2.6.22/include/asm-arm/arch-ep93xx/uncompress.h +=================================================================== +--- linux-2.6.22.orig/include/asm-arm/arch-ep93xx/uncompress.h ++++ linux-2.6.22/include/asm-arm/arch-ep93xx/uncompress.h +@@ -77,9 +77,56 @@ static void ethernet_reset(void) + } + + ++/* ++ * Some bootloaders don't turn on the UARTBAUD bit, which means that ++ * the UARTs will be running off a divided 7.3728 MHz clock instead of ++ * the 14.7456 MHz peripheral clock when linux boots. ++ * ++ * We detect that condition here and fix it by turning on UARTBAUD, and ++ * then reprogramming the divisors on all enabled UARTs to twice what ++ * they were before we turned UARTBAUD on, to preserve the programmed ++ * baud rate. ++ */ ++#define PHYS_SYSCON_CLOCK_CONTROL 0x80930004 ++#define SYSCON_CLOCK_UARTBAUD 0x20000000 ++#define PHYS_UART1_BASE 0x808c0000 ++#define PHYS_UART2_BASE 0x808d0000 ++#define PHYS_UART3_BASE 0x808e0000 ++ ++static void uart_divisor_times_two(unsigned int base) ++{ ++ u16 divisor; ++ ++ divisor = __raw_readb(base + 0x0c) << 8; ++ divisor |= __raw_readb(base + 0x10); ++ if (divisor) { ++ divisor = (2 * (divisor + 1)) - 1; ++ __raw_writeb(divisor >> 8, base + 0x0c); ++ __raw_writeb(divisor & 0xff, base + 0x10); ++ __raw_writeb(__raw_readb(base + 0x08), base + 0x08); ++ } ++} ++ ++static void fix_uart_base(void) ++{ ++ unsigned int v; ++ ++ v = __raw_readl(PHYS_SYSCON_CLOCK_CONTROL); ++ if ((v & SYSCON_CLOCK_UARTBAUD) == 0) { ++ v |= SYSCON_CLOCK_UARTBAUD; ++ __raw_writel(v, PHYS_SYSCON_CLOCK_CONTROL); ++ ++ uart_divisor_times_two(PHYS_UART1_BASE); ++ uart_divisor_times_two(PHYS_UART2_BASE); ++ uart_divisor_times_two(PHYS_UART3_BASE); ++ } ++} ++ ++ + static void arch_decomp_setup(void) + { + ethernet_reset(); ++ fix_uart_base(); + } + + #define arch_decomp_wdog() |