earlycon: Let users set the clock frequency

Some platforms, namely AMD Picasso, use non standard uart clocks (48M),
witch makes it impossible to use with earlycon.

Let the user select its own frequency.

Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
Link: https://lore.kernel.org/r/20221123-serial-clk-v3-1-49c516980ae0@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ricardo Ribalda 2022-11-24 13:39:07 +01:00 committed by Greg Kroah-Hartman
parent 5dc4c995db
commit 374b30f27f
2 changed files with 15 additions and 6 deletions

View File

@ -1195,10 +1195,10 @@
specified, the serial port must already be setup and specified, the serial port must already be setup and
configured. configured.
uart[8250],io,<addr>[,options] uart[8250],io,<addr>[,options[,uartclk]]
uart[8250],mmio,<addr>[,options] uart[8250],mmio,<addr>[,options[,uartclk]]
uart[8250],mmio32,<addr>[,options] uart[8250],mmio32,<addr>[,options[,uartclk]]
uart[8250],mmio32be,<addr>[,options] uart[8250],mmio32be,<addr>[,options[,uartclk]]
uart[8250],0x<addr>[,options] uart[8250],0x<addr>[,options]
Start an early, polled-mode console on the 8250/16550 Start an early, polled-mode console on the 8250/16550
UART at the specified I/O port or MMIO address. UART at the specified I/O port or MMIO address.
@ -1207,7 +1207,9 @@
If none of [io|mmio|mmio32|mmio32be], <addr> is assumed If none of [io|mmio|mmio32|mmio32be], <addr> is assumed
to be equivalent to 'mmio'. 'options' are specified to be equivalent to 'mmio'. 'options' are specified
in the same format described for "console=ttyS<n>"; if in the same format described for "console=ttyS<n>"; if
unspecified, the h/w is not initialized. unspecified, the h/w is not initialized. 'uartclk' is
the uart clock frequency; if unspecified, it is set
to 'BASE_BAUD' * 16.
pl011,<addr> pl011,<addr>
pl011,mmio32,<addr> pl011,mmio32,<addr>

View File

@ -120,7 +120,13 @@ static int __init parse_options(struct earlycon_device *device, char *options)
} }
if (options) { if (options) {
char *uartclk;
device->baud = simple_strtoul(options, NULL, 0); device->baud = simple_strtoul(options, NULL, 0);
uartclk = strchr(options, ',');
if (uartclk && kstrtouint(uartclk + 1, 0, &port->uartclk) < 0)
pr_warn("[%s] unsupported earlycon uart clkrate option\n",
options);
length = min(strcspn(options, " ") + 1, length = min(strcspn(options, " ") + 1,
(size_t)(sizeof(device->options))); (size_t)(sizeof(device->options)));
strscpy(device->options, options, length); strscpy(device->options, options, length);
@ -139,7 +145,8 @@ static int __init register_earlycon(char *buf, const struct earlycon_id *match)
buf = NULL; buf = NULL;
spin_lock_init(&port->lock); spin_lock_init(&port->lock);
port->uartclk = BASE_BAUD * 16; if (!port->uartclk)
port->uartclk = BASE_BAUD * 16;
if (port->mapbase) if (port->mapbase)
port->membase = earlycon_map(port->mapbase, 64); port->membase = earlycon_map(port->mapbase, 64);