[U-Boot] [PATCH] rpi: Support both UART interfaces.
Fabian Vogt
fvogt at suse.com
Sun Apr 2 09:29:42 UTC 2017
Hi,
Am Sonntag, 2. April 2017, 09:20:06 CEST schrieb Alex Deymo:
> The Raspberry Pi 3 has two UART interfaces that can be pinmuxed to the
> header pins. The PL011 is by default muxed to the Bluetooth chip and
> the mini-UART can be muxed to the pin headers passing "enabled_uart=1"
> in the config.txt file.
>
> Passing "enable_uart=1" has other implications, since the baudrate of
> the miniuart depends on the clock frequency of the main core, which
> is normally dynamic unless enable_uart=1 is set.
> If Bluetooth is not
> used or not required, it is possible to set the PL011 UART to the
> header pins passing either "dtoverlay=pi3-disable-bt" or
> "dtoverlay=pi3-miniuart-bt" to disable Bluetooth or use it via the
> miniuart respectively.
>
> This patch disables (for U-Boot) the UARTs modules not muxed to the
> header pins so the serial port is used only if available in the
> header pins, avoiding writing to the Bluetooth chip if needed. This
> allows to enable the PL01X driver for the Raspberry Pi 3, previously
> disabled for that board, which can be used for the U-Boot console if
> properly configured in the device tree.
>
> Note that in order to get the PL01X driver in the Raspberry Pi 3 to
> work with U-Boot the device tree must set "skip-init" in the uart0
> block, for example this device tree fragment would do it:
>
> fragment at 0 {
> target = <&uart0>;
> __overlay__ {
> skip-init;
> };
> };
This is already done in arch/arm/dts/bcm283x-uboot.dtsi:
&uart0 {
skip-init;
u-boot,dm-pre-reloc;
};
&uart1 {
skip-init;
u-boot,dm-pre-reloc;
};
> Test: Booted a rpi3 with either UART output.
> Signed-off-by: Alex Deymo <deymo at google.com>
Acked-by: Fabian Vogt <fvogt at suse.com>
Cheers,
Fabian
> ---
> board/raspberrypi/rpi/rpi.c | 78 +++++++++++++++++++++++----------
> drivers/serial/serial_pl01x.c | 3 ++
> include/configs/rpi.h | 8 +++-
> include/dm/platform_data/serial_pl01x.h | 2 +
> 4 files changed, 66 insertions(+), 25 deletions(-)
>
> diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
> index 2146534b36..58f07953f5 100644
> --- a/board/raspberrypi/rpi/rpi.c
> +++ b/board/raspberrypi/rpi/rpi.c
> @@ -18,6 +18,7 @@
> #include <asm/arch/mbox.h>
> #include <asm/arch/sdhci.h>
> #include <asm/global_data.h>
> +#include <dm/platform_data/serial_pl01x.h>
> #include <dm/platform_data/serial_bcm283x_mu.h>
> #ifdef CONFIG_ARM64
> #include <asm/armv8/mmu.h>
> @@ -442,8 +443,19 @@ static void get_board_rev(void)
> printf("RPI %s (0x%x)\n", model->name, revision);
> }
>
> -#ifndef CONFIG_PL01X_SERIAL
> -static bool rpi_is_serial_active(void)
> +/* An enum describing the pin muxing selection for the UART RX/TX pins. */
> +enum rpi_uart_mux {
> + /* The pin is associated with the internal "miniuart" block. */
> + RPI_UART_BCM283X_MU,
> +
> + /* The pin is associated with the PL01X uart driver. */
> + RPI_UART_PL01X,
> +
> + /* The pin is associated with a different function. */
> + RPI_UART_OTHER,
> +};
> +
> +static enum rpi_uart_mux rpi_get_uart_mux_setting(void)
> {
> int serial_gpio = 15;
> struct udevice *dev;
> @@ -452,41 +464,61 @@ static bool rpi_is_serial_active(void)
> * The RPi3 disables the mini uart by default. The easiest way to find
> * out whether it is available is to check if the RX pin is muxed.
> */
> -
> if (uclass_first_device(UCLASS_GPIO, &dev) || !dev)
> - return true;
> -
> - if (bcm2835_gpio_get_func_id(dev, serial_gpio) != BCM2835_GPIO_ALT5)
> - return false;
> + return RPI_UART_OTHER;
>
> - return true;
> + switch (bcm2835_gpio_get_func_id(dev, serial_gpio)) {
> + case BCM2835_GPIO_ALT5:
> + return RPI_UART_BCM283X_MU;
> + case BCM2835_GPIO_ALT0:
> + return RPI_UART_PL01X;
> + }
> + return RPI_UART_OTHER;
> }
>
> -/* Disable mini-UART I/O if it's not pinmuxed to our pins.
> - * The firmware only enables it if explicitly done in config.txt: enable_uart=1
> +/* Disable UART I/O for the mini-UART and PL01X UART if they are not pinmuxed to
> + * the Raspberry Pi header. The mini-UART is only enabled in the header if
> + * explicitly done in config.txt: enable_uart=1, and the PL01X is only enabled
> + * if not used for Bluetooth and explicitly exposed in config.txt as either
> + * dtoverlay=pi3-disable-bt or dtoverlay=pi3-miniuart-bt.
> */
> -static void rpi_disable_inactive_uart(void)
> +static void rpi_disable_inactive_uarts(void)
> {
> struct udevice *dev;
> - struct bcm283x_mu_serial_platdata *plat;
> + enum rpi_uart_mux mux;
>
> - if (uclass_get_device_by_driver(UCLASS_SERIAL,
> - DM_GET_DRIVER(serial_bcm283x_mu),
> - &dev) || !dev)
> - return;
> + mux = rpi_get_uart_mux_setting();
> +
> +#ifdef CONFIG_BCM283X_MU_SERIAL
> + struct bcm283x_mu_serial_platdata *bcm283x_mu_plat;
>
> - if (!rpi_is_serial_active()) {
> - plat = dev_get_platdata(dev);
> - plat->disabled = true;
> + if (mux != RPI_UART_BCM283X_MU &&
> + !uclass_get_device_by_driver(UCLASS_SERIAL,
> + DM_GET_DRIVER(serial_bcm283x_mu),
> + &dev) &&
> + dev) {
> + bcm283x_mu_plat = dev_get_platdata(dev);
> + bcm283x_mu_plat->disabled = true;
> }
> +#endif /* CONFIG_BCM283X_MU_SERIAL */
> +
> +#ifdef CONFIG_PL01X_SERIAL
> + struct pl01x_serial_platdata *pl01x_plat;
> +
> + if (mux != RPI_UART_PL01X &&
> + !uclass_get_device_by_driver(UCLASS_SERIAL,
> + DM_GET_DRIVER(serial_pl01x),
> + &dev) &&
> + dev) {
> + pl01x_plat = dev_get_platdata(dev);
> + pl01x_plat->disabled = true;
> + }
> +#endif /* CONFIG_PL01X_SERIAL */
> }
> -#endif
>
> int board_init(void)
> {
> -#ifndef CONFIG_PL01X_SERIAL
> - rpi_disable_inactive_uart();
> -#endif
> + rpi_disable_inactive_uarts();
>
> get_board_rev();
>
> diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
> index a49134a95a..7748e7632b 100644
> --- a/drivers/serial/serial_pl01x.c
> +++ b/drivers/serial/serial_pl01x.c
> @@ -297,6 +297,9 @@ static int pl01x_serial_probe(struct udevice *dev)
> struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
> struct pl01x_priv *priv = dev_get_priv(dev);
>
> + if (plat->disabled)
> + return -ENODEV;
> +
> priv->regs = (struct pl01x_regs *)plat->base;
> priv->type = plat->type;
> if (!plat->skip_init)
> diff --git a/include/configs/rpi.h b/include/configs/rpi.h
> index 92eb792989..767d5d8e0d 100644
> --- a/include/configs/rpi.h
> +++ b/include/configs/rpi.h
> @@ -94,10 +94,14 @@
>
> /* Console UART */
> #ifdef CONFIG_BCM2837
> +/*
> + * Raspberry Pi 3 uses the miniuart by default unless the device tree re-assigns
> + * the PL01X from Bluetooth to the header pins. We enable support for both in
> + * the Raspberry Pi 3 only and disable the unused one at runtime.
> + */
> #define CONFIG_BCM283X_MU_SERIAL
> -#else
> -#define CONFIG_PL01X_SERIAL
> #endif
> +#define CONFIG_PL01X_SERIAL
> #define CONFIG_CONS_INDEX 0
>
> /* Console configuration */
> diff --git a/include/dm/platform_data/serial_pl01x.h b/include/dm/platform_data/serial_pl01x.h
> index ccfa808e23..1396137d26 100644
> --- a/include/dm/platform_data/serial_pl01x.h
> +++ b/include/dm/platform_data/serial_pl01x.h
> @@ -19,12 +19,14 @@ enum pl01x_type {
> * @clock: Input clock rate, used for calculating the baud rate divisor
> * @skip_init: Don't attempt to change port configuration (also means @clock
> * is ignored)
> + * @disabled: Whether the driver should be disabled and not report any device.
> */
> struct pl01x_serial_platdata {
> unsigned long base;
> enum pl01x_type type;
> unsigned int clock;
> bool skip_init;
> + bool disabled;
> };
>
> #endif
>
More information about the U-Boot
mailing list