summaryrefslogtreecommitdiff
path: root/drivers/serial
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2020-04-27 21:17:59 +0300
committerTom Rini <trini@konsulko.com>2020-05-07 16:01:42 +0300
commite3e2d662a273d5ac67998f390529966a8d8c8a3b (patch)
tree960e608c449f56aa82277bf96fbc83253590a35d /drivers/serial
parent7d6dae0dfb4b056850cde6ff91d06bb5cbda8fd3 (diff)
downloadu-boot-e3e2d662a273d5ac67998f390529966a8d8c8a3b.tar.xz
uart: pl011: Add proper DM clock support
Even though the PL011 UART driver claims to be DM compliant, it does not really a good job with parsing DT nodes. U-Boot seems to adhere to a non-standard binding, either requiring to have a "skip-init" property in the node, or to have an extra "clock" property holding the base *frequency* value for the baud rate generator. DTs in the U-Boot tree seem to have been hacked to match this requirement. The official binding does not mention any of these properties, instead recommends a standard "clocks" property to point to the baud base clock. Some boards use simple "fixed-clock" providers, which U-Boot readily supports, so let's add some simple DM clock code to the PL011 driver to learn the rate of the first clock, as described by the official binding. These clock nodes seem to be not ready very early in the boot process, so provide a fallback value, by re-using the already existing CONFIG_PL011_CLOCK variable. Signed-off-by: Andre Przywara <andre.przywara@arm.com> [trini: Add <clock_legacy.h> for get_bus_freq() for layerscape platforms] Signed-off-by: Tom Rini <trini@konsulko.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/serial_pl01x.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 2a5f256184..6e5d81ce34 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -11,7 +11,10 @@
/* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */
#include <common.h>
+/* For get_bus_freq() */
+#include <clock_legacy.h>
#include <dm.h>
+#include <clk.h>
#include <errno.h>
#include <watchdog.h>
#include <asm/io.h>
@@ -149,21 +152,24 @@ static int pl01x_generic_setbrg(struct pl01x_regs *regs, enum pl01x_type type,
unsigned int remainder;
unsigned int fraction;
- /*
- * Set baud rate
- *
- * IBRD = UART_CLK / (16 * BAUD_RATE)
- * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
- * / (16 * BAUD_RATE))
- */
- temp = 16 * baudrate;
- divider = clock / temp;
- remainder = clock % temp;
- temp = (8 * remainder) / baudrate;
- fraction = (temp >> 1) + (temp & 1);
-
- writel(divider, &regs->pl011_ibrd);
- writel(fraction, &regs->pl011_fbrd);
+ /* Without a valid clock rate we cannot set up the baudrate. */
+ if (clock) {
+ /*
+ * Set baud rate
+ *
+ * IBRD = UART_CLK / (16 * BAUD_RATE)
+ * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
+ * / (16 * BAUD_RATE))
+ */
+ temp = 16 * baudrate;
+ divider = clock / temp;
+ remainder = clock % temp;
+ temp = (8 * remainder) / baudrate;
+ fraction = (temp >> 1) + (temp & 1);
+
+ writel(divider, &regs->pl011_ibrd);
+ writel(fraction, &regs->pl011_fbrd);
+ }
pl011_set_line_control(regs);
/* Finally, enable the UART */
@@ -337,17 +343,28 @@ static const struct udevice_id pl01x_serial_id[] ={
{}
};
+#ifndef CONFIG_PL011_CLOCK
+#define CONFIG_PL011_CLOCK 0
+#endif
+
int pl01x_serial_ofdata_to_platdata(struct udevice *dev)
{
struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
+ struct clk clk;
fdt_addr_t addr;
+ int ret;
addr = devfdt_get_addr(dev);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
plat->base = addr;
- plat->clock = dev_read_u32_default(dev, "clock", 1);
+ plat->clock = dev_read_u32_default(dev, "clock", CONFIG_PL011_CLOCK);
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (!ret) {
+ clk_enable(&clk);
+ plat->clock = clk_get_rate(&clk);
+ }
plat->type = dev_get_driver_data(dev);
plat->skip_init = dev_read_bool(dev, "skip-init");