Hi,
Earlier this year I noticed the CBUS UART, a discrete TI16C550C part
wired directly to the system controller's device bus and supposed to come
up as ttyS2 in addition to ttyS0 and ttyS1 ports from a Super I/O device
behind the PCI southbridge, is not recognised with my MIPS Malta board
booting big-endian.
I got to the bottom of the problem now and as it turns out we have two
long-standing bugs causing it, one in generic 8250 code and another in
Malta platform code, and this has never worked in the big-endian mode.
Here's v2 of the series, addressing minor issues with 1/2 pointed out in
the review.
Please apply.
Maciej
Correct big-endian accesses to the CBUS UART, a Malta on-board discrete
TI16C550C part wired directly to the system controller's device bus, and
do not use byte swapping with the 32-bit accesses to the device.
The CBUS is used for devices such as the boot flash memory needed early
on in system bootstrap even before PCI has been initialised. Therefore
it uses the system controller's device bus, which follows the endianness
set with the CPU, which means no byte-swapping is ever required for data
accesses to CBUS, unlike with PCI.
The CBUS UART uses the UPIO_MEM32 access method, that is the `readl' and
`writel' MMIO accessors, which on the MIPS platform imply byte-swapping
with PCI systems. Consequently the wrong byte lane is accessed with the
big-endian configuration and the UART is not correctly accessed.
As it happens the UPIO_MEM32BE access method makes use of the `ioread32'
and `iowrite32' MMIO accessors, which still use `readl' and `writel'
respectively, however they byte-swap data passed, effectively cancelling
swapping done with the accessors themselves and making it suitable for
the CBUS UART.
Make the CBUS UART switch between UPIO_MEM32 and UPIO_MEM32BE then,
based on the endianness selected. With this change in place the device
is correctly recognised with big-endian Malta at boot, along with the
Super I/O devices behind PCI:
Serial: 8250/16550 driver, 5 ports, IRQ sharing enabled
printk: console [ttyS0] disabled
serial8250.0: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
printk: console [ttyS0] enabled
printk: bootconsole [uart8250] disabled
serial8250.0: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A
serial8250.0: ttyS2 at MMIO 0x1f000900 (irq = 20, base_baud = 230400) is a 16550A
Signed-off-by: Maciej W. Rozycki <[email protected]>
Fixes: e7c4782f92fc ("[MIPS] Put an end to <asm/serial.h>'s long and annyoing existence")
Cc: [email protected] # v2.6.23+
---
Changes from v1:
- Remove console message duplicates from the commit description.
---
arch/mips/mti-malta/malta-platform.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
linux-mips-malta-cbus-uart-be.diff
Index: linux-macro-ide-tty/arch/mips/mti-malta/malta-platform.c
===================================================================
--- linux-macro-ide-tty.orig/arch/mips/mti-malta/malta-platform.c
+++ linux-macro-ide-tty/arch/mips/mti-malta/malta-platform.c
@@ -48,7 +48,8 @@ static struct plat_serial8250_port uart8
.mapbase = 0x1f000900, /* The CBUS UART */
.irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2,
.uartclk = 3686400, /* Twice the usual clk! */
- .iotype = UPIO_MEM32,
+ .iotype = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ?
+ UPIO_MEM32BE : UPIO_MEM32,
.flags = CBUS_UART_FLAGS,
.regshift = 3,
},
On Sat, Jun 26, 2021 at 6:11 AM Maciej W. Rozycki <[email protected]> wrote:
>
> Correct big-endian accesses to the CBUS UART, a Malta on-board discrete
> TI16C550C part wired directly to the system controller's device bus, and
> do not use byte swapping with the 32-bit accesses to the device.
>
> The CBUS is used for devices such as the boot flash memory needed early
> on in system bootstrap even before PCI has been initialised. Therefore
> it uses the system controller's device bus, which follows the endianness
> set with the CPU, which means no byte-swapping is ever required for data
> accesses to CBUS, unlike with PCI.
>
> The CBUS UART uses the UPIO_MEM32 access method, that is the `readl' and
> `writel' MMIO accessors, which on the MIPS platform imply byte-swapping
> with PCI systems. Consequently the wrong byte lane is accessed with the
> big-endian configuration and the UART is not correctly accessed.
>
> As it happens the UPIO_MEM32BE access method makes use of the `ioread32'
> and `iowrite32' MMIO accessors, which still use `readl' and `writel'
> respectively, however they byte-swap data passed, effectively cancelling
> swapping done with the accessors themselves and making it suitable for
> the CBUS UART.
>
> Make the CBUS UART switch between UPIO_MEM32 and UPIO_MEM32BE then,
> based on the endianness selected. With this change in place the device
> is correctly recognised with big-endian Malta at boot, along with the
> Super I/O devices behind PCI:
>
> Serial: 8250/16550 driver, 5 ports, IRQ sharing enabled
> printk: console [ttyS0] disabled
> serial8250.0: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
> printk: console [ttyS0] enabled
> printk: bootconsole [uart8250] disabled
> serial8250.0: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A
> serial8250.0: ttyS2 at MMIO 0x1f000900 (irq = 20, base_baud = 230400) is a 16550A
>
> Signed-off-by: Maciej W. Rozycki <[email protected]>
> Fixes: e7c4782f92fc ("[MIPS] Put an end to <asm/serial.h>'s long and annyoing existence")
> Cc: [email protected] # v2.6.23+
> ---
> Changes from v1:
>
> - Remove console message duplicates from the commit description.
> ---
> arch/mips/mti-malta/malta-platform.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>