diff --git a/arch/arm/include/asm/arch-lpc32xx/clk.h b/arch/arm/include/asm/arch-lpc32xx/clk.h
index 5ab48a9d3c..75dce06104 100644
--- a/arch/arm/include/asm/arch-lpc32xx/clk.h
+++ b/arch/arm/include/asm/arch-lpc32xx/clk.h
@@ -8,8 +8,7 @@
 
 #include <asm/types.h>
 
-#define OSC_CLK_FREQUENCY	13000000
-#define RTC_CLK_FREQUENCY	32768
+#define LPC32XX_RTC_CLK_FREQUENCY	32768
 
 /* Clocking and Power Control Registers */
 struct clk_pm_regs {
diff --git a/arch/arm/include/asm/arch-lpc32xx/config.h b/arch/arm/include/asm/arch-lpc32xx/config.h
index 41160384a4..836e29bd96 100644
--- a/arch/arm/include/asm/arch-lpc32xx/config.h
+++ b/arch/arm/include/asm/arch-lpc32xx/config.h
@@ -12,7 +12,7 @@
 /* Basic CPU architecture */
 
 #if !defined(CFG_SYS_NS16550_CLK)
-#define CFG_SYS_NS16550_CLK		13000000
+#define CFG_SYS_NS16550_CLK		get_serial_clock()
 #endif
 
 #define CFG_SYS_BAUDRATE_TABLE	\
diff --git a/arch/arm/mach-lpc32xx/Kconfig b/arch/arm/mach-lpc32xx/Kconfig
index 185bda41c2..6b54ec6220 100644
--- a/arch/arm/mach-lpc32xx/Kconfig
+++ b/arch/arm/mach-lpc32xx/Kconfig
@@ -17,6 +17,29 @@ config TARGET_EA_LPC3250DEVKITV2
 
 endchoice
 
+choice
+	prompt "LPC32xx clock source for standard UARTs"
+	help
+		Select clock source for standard UART baudrate divider.
+
+config LPC32XX_UART_PERIPH_CLK
+	bool "PERIPH as clock source"
+	help
+		Slower than HCLK, less resolution, lower power consumption.
+
+config LPC32XX_UART_HCLK_CLK
+	bool "HCLK as clock source"
+	help
+		Faster than PERIPH, better resolution, higher power consumption.
+
+endchoice
+
+config LPC32XX_OSC_CLK_FREQUENCY
+	int "LPC32xx external XTAL OSC or clock source frequency"
+	default 13000000
+	help
+		LPC32xx external XTAL OSC or clock source frequency.
+
 source "board/timll/devkit3250/Kconfig"
 source "board/work-microwave/work_92105/Kconfig"
 source "board/ea/ea-lpc3250devkitv2/Kconfig"
diff --git a/arch/arm/mach-lpc32xx/clk.c b/arch/arm/mach-lpc32xx/clk.c
index cb2344d79f..f327e0e876 100644
--- a/arch/arm/mach-lpc32xx/clk.c
+++ b/arch/arm/mach-lpc32xx/clk.c
@@ -15,9 +15,9 @@ static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
 unsigned int get_sys_clk_rate(void)
 {
 	if (readl(&clk->sysclk_ctrl) & CLK_SYSCLK_PLL397)
-		return RTC_CLK_FREQUENCY * 397;
+		return LPC32XX_RTC_CLK_FREQUENCY * 397;
 	else
-		return OSC_CLK_FREQUENCY;
+		return CONFIG_LPC32XX_OSC_CLK_FREQUENCY;
 }
 
 unsigned int get_hclk_pll_rate(void)
@@ -134,5 +134,9 @@ unsigned int get_sdram_clk_rate(void)
 
 int get_serial_clock(void)
 {
+#if IS_ENABLED(CONFIG_LPC32XX_UART_HCLK_CLK)
+	return get_hclk_clk_rate();
+#else
 	return get_periph_clk_rate();
+#endif
 }
diff --git a/arch/arm/mach-lpc32xx/devices.c b/arch/arm/mach-lpc32xx/devices.c
index 6a67a3591a..27061b6212 100644
--- a/arch/arm/mach-lpc32xx/devices.c
+++ b/arch/arm/mach-lpc32xx/devices.c
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <dm.h>
 #include <ns16550.h>
+#include <clock_legacy.h>
 
 #include <asm/arch/clk.h>
 #include <asm/arch/uart.h>
@@ -16,6 +17,13 @@ static struct clk_pm_regs    *clk  = (struct clk_pm_regs *)CLK_PM_BASE;
 static struct uart_ctrl_regs *ctrl = (struct uart_ctrl_regs *)UART_CTRL_BASE;
 static struct mux_regs *mux = (struct mux_regs *)MUX_BASE;
 
+#define LPC32XX_USB_RATE 1000000
+#define LPC32XX_USB_DIV ((CONFIG_LPC32XX_OSC_CLK_FREQUENCY/LPC32XX_USB_RATE)-1)
+
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+static struct ns16550_plat lpc32xx_uart[4];
+#endif
+
 void lpc32xx_uart_init(unsigned int uart_id)
 {
 	if (uart_id < 1 || uart_id > 7)
@@ -36,20 +44,30 @@ void lpc32xx_uart_init(unsigned int uart_id)
 			UART_CLKMODE_AUTO(uart_id));
 
 	/* Bypass pre-divider of UART clock */
+#if IS_ENABLED(CONFIG_LPC32XX_UART_HCLK_CLK)
+	/* Use HCLK as input for baudrate divider */
+	writel(CLK_UART_HCLK | CLK_UART_X_DIV(1) | CLK_UART_Y_DIV(1),
+	       &clk->u3clk + (uart_id - 3));
+#else
+	/* Use PERIPH as input for baudrate divider */
 	writel(CLK_UART_X_DIV(1) | CLK_UART_Y_DIV(1),
 	       &clk->u3clk + (uart_id - 3));
+#endif
+
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+	int i;
+	for (i = 0; i < ARRAY_SIZE(lpc32xx_uart); i++) {
+		lpc32xx_uart[i].clock = get_serial_clock();
+	}
+#endif
 }
 
 #if !CONFIG_IS_ENABLED(OF_CONTROL)
-static const struct ns16550_plat lpc32xx_uart[] = {
-	{ .base = UART3_BASE, .reg_shift = 2,
-	  .clock = CFG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
-	{ .base = UART4_BASE, .reg_shift = 2,
-	  .clock = CFG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
-	{ .base = UART5_BASE, .reg_shift = 2,
-	  .clock = CFG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
-	{ .base = UART6_BASE, .reg_shift = 2,
-	  .clock = CFG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, },
+static struct ns16550_plat lpc32xx_uart[] = {
+	{ .base = UART3_BASE, .reg_shift = 2, .fcr = UART_FCR_DEFVAL, },
+	{ .base = UART4_BASE, .reg_shift = 2, .fcr = UART_FCR_DEFVAL, },
+	{ .base = UART5_BASE, .reg_shift = 2, .fcr = UART_FCR_DEFVAL, },
+	{ .base = UART6_BASE, .reg_shift = 2, .fcr = UART_FCR_DEFVAL, },
 };
 
 U_BOOT_DRVINFOS(lpc32xx_uarts) = {
@@ -94,6 +112,8 @@ void lpc32xx_usb_init(void)
 {
 	/* Do not route the UART 5 Tx/Rx pins to the USB D+ and USB D- pins. */
 	clrbits_le32(&ctrl->ctrl, UART_CTRL_UART5_USB_MODE);
+
+	writel(LPC32XX_USB_DIV, &clk->usbdiv_ctrl);
 }
 
 void lpc32xx_i2c_init(unsigned int devnum)
