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