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@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 <de...@google.com>

Acked-by: Fabian Vogt <fv...@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
> 


_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to