rpi: Support both UART interfaces.
A message that is not in the archive (sent off-list or not yet received): c42cb6fed95a6c1aafccc2a072fab3fcbb03106a
PATCH 1/1 rpi: Support both UART interfaces.
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;
};
};Test: Booted a rpi3 with either UART output.
--- 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(-)
board/raspberrypi/rpi/rpi.c +55 -23
@@ -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 ();
drivers/serial/serial_pl01x.c +3 -0
@@ -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)
include/configs/rpi.h +6 -2
@@ -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 */
include/dm/platform_data/serial_pl01x.h +2 -0
@@ -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
Signature · 1 line
2.12.2.564.g063fe858b8-goog
PATCH 1/1 rpi: Support both UART interfaces.
Am 02.04.2017 um 10:26 schrieb Alex Deymo:
Quoted 3 lines
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"
"enable_uart=1"
Quoted 11 lines
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
"UART modules" or "UARTs"
Quoted 17 lines
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; }; };
Quoted 8 lines
Test: Booted a rpi3 with either UART output.
Signed-off-by Alex Deymo <[email protected]>--- 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(-)
I've given this patch a shot on the Zero W with rpi_defconfig, but no luck. I tried with and without enable_uart=1, and I enabled uart1 in the -b.dts. With vanilla U-Boot I got the rainbow screen; the patched master branch shows a black screen and some activity on the ACT LED.
Does the W require a new defconfig after all?
Regards,
Andreas
Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Felix Imendörffer, Jane Smithard, Graham Norton HRB 21284 (AG Nürnberg)