From 120aec0902663d2ed942c1542217791c46b8e406 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Wed, 22 Oct 2014 14:12:50 -0700 Subject: serial: Combine Tegra and Rockchip UARTs to generic 8250_mmio32 We have two drivers for a 100%-identical peripheral right now, mostly because we couldn't come up with a good common name for it back when we checked it in. That seems like a pretty silly reason in the long run. Both Tegra and Rockchip SoCs contain UARTs that use the common 8250 register interface (at least for the very basic byte-per-byte transmit and receive parts we care about), memory-mapped with a 32-bit register stride. This patch combines them to a single 8250_mmio32 driver (which also fixes a problem when booting Rockchip without serial enabled, since that driver forgot to check for serial initialization when registering its console drivers). The register accesses are done using readl/writel (as Rockchip did before), since the registers are documented as 32-bit length (with top 24 bits RAZ/WI), although the Tegra SoC doesn't enforce APB accesses to have the full word length. Also fixed checkpatch stuff. A day may come when we can also merge this driver into the (completely different, with more complicated features and #ifdefs) 8250 driver for x86 (which has MMIO support for 8-bit register stride only), both here and in coreboot. But it is not this day. This day I just want to get rid of a 99% identical file without expending too much effort. BUG=None TEST=Booted on Veyron_Pinky and Nyan_Blaze with and without serial enabled, both worked fine (although Veyron has another kernel issue). Change-Id: I85c004a75cc5aa7cb40098002d3e00a62c1c5f2d Signed-off-by: Patrick Georgi Original-Commit-Id: e7959c19356d2922aa414866016540ad9ee2ffa8 Original-Change-Id: Ib84d00f52ff2c48398c75f77f6a245e658ffdeb9 Original-Signed-off-by: Julius Werner Original-Reviewed-on: https://chromium-review.googlesource.com/225102 Original-Reviewed-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/9387 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- payloads/libpayload/Config.in | 9 +- payloads/libpayload/configs/defconfig | 3 +- payloads/libpayload/configs/defconfig-arm | 3 +- payloads/libpayload/configs/defconfig-mips | 3 +- payloads/libpayload/drivers/Makefile.inc | 3 +- payloads/libpayload/drivers/serial/8250_mmio32.c | 113 ++++++++++++++++++++++ payloads/libpayload/drivers/serial/rk_serial.c | 115 ----------------------- payloads/libpayload/drivers/serial/tegra.c | 113 ---------------------- 8 files changed, 119 insertions(+), 243 deletions(-) create mode 100644 payloads/libpayload/drivers/serial/8250_mmio32.c delete mode 100644 payloads/libpayload/drivers/serial/rk_serial.c delete mode 100644 payloads/libpayload/drivers/serial/tegra.c diff --git a/payloads/libpayload/Config.in b/payloads/libpayload/Config.in index cb1d529402..2efd5d673c 100644 --- a/payloads/libpayload/Config.in +++ b/payloads/libpayload/Config.in @@ -199,13 +199,8 @@ config S5P_SERIAL_CONSOLE depends on SERIAL_CONSOLE default n -config TEGRA_SERIAL_CONSOLE - bool "Tegra SOC compatible serial port driver" - depends on SERIAL_CONSOLE - default n - -config RK_SERIAL_CONSOLE - bool "Rockchip SOC serial port driver" +config 8250_MMIO32_SERIAL_CONSOLE + bool "Memory-mapped 8250-compatible serial port driver with 32-bit regs" depends on SERIAL_CONSOLE default n diff --git a/payloads/libpayload/configs/defconfig b/payloads/libpayload/configs/defconfig index f5e13d5535..556b6198b7 100644 --- a/payloads/libpayload/configs/defconfig +++ b/payloads/libpayload/configs/defconfig @@ -41,8 +41,7 @@ CONFIG_LP_CBMEM_CONSOLE=y CONFIG_LP_SERIAL_CONSOLE=y CONFIG_LP_8250_SERIAL_CONSOLE=y # CONFIG_LP_S5P_SERIAL_CONSOLE is not set -# CONFIG_LP_TEGRA_SERIAL_CONSOLE is not set -# CONFIG_LP_RK_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set # CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set # CONFIG_LP_PL011_SERIAL_CONSOLE is not set CONFIG_LP_SERIAL_IOBASE=0x3f8 diff --git a/payloads/libpayload/configs/defconfig-arm b/payloads/libpayload/configs/defconfig-arm index ea467ecd40..ff2225f3dc 100644 --- a/payloads/libpayload/configs/defconfig-arm +++ b/payloads/libpayload/configs/defconfig-arm @@ -40,8 +40,7 @@ CONFIG_LP_CBMEM_CONSOLE=y CONFIG_LP_SERIAL_CONSOLE=y # CONFIG_LP_8250_SERIAL_CONSOLE is not set # CONFIG_LP_S5P_SERIAL_CONSOLE is not set -# CONFIG_LP_TEGRA_SERIAL_CONSOLE is not set -# CONFIG_LP_RK_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set # CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set # CONFIG_LP_SERIAL_SET_SPEED is not set # CONFIG_LP_SERIAL_ACS_FALLBACK is not set diff --git a/payloads/libpayload/configs/defconfig-mips b/payloads/libpayload/configs/defconfig-mips index 0af1a91706..76b8474010 100644 --- a/payloads/libpayload/configs/defconfig-mips +++ b/payloads/libpayload/configs/defconfig-mips @@ -40,8 +40,7 @@ CONFIG_LP_CBMEM_CONSOLE=y CONFIG_LP_SERIAL_CONSOLE=y CONFIG_LP_8250_SERIAL_CONSOLE=y # CONFIG_LP_S5P_SERIAL_CONSOLE is not set -# CONFIG_LP_TEGRA_SERIAL_CONSOLE is not set -# CONFIG_LP_RK_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set # CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set # CONFIG_LP_PL011_SERIAL_CONSOLE is not set # CONFIG_LP_SERIAL_SET_SPEED is not set diff --git a/payloads/libpayload/drivers/Makefile.inc b/payloads/libpayload/drivers/Makefile.inc index 6dc1403f2f..f3b147de36 100644 --- a/payloads/libpayload/drivers/Makefile.inc +++ b/payloads/libpayload/drivers/Makefile.inc @@ -35,9 +35,8 @@ libc-$(CONFIG_LP_SPEAKER) += speaker.c libc-$(CONFIG_LP_8250_SERIAL_CONSOLE) += serial/8250.c libc-$(CONFIG_LP_S5P_SERIAL_CONSOLE) += serial/s5p.c -libc-$(CONFIG_LP_TEGRA_SERIAL_CONSOLE) += serial/tegra.c +libc-$(CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE) += serial/8250_mmio32.c libc-$(CONFIG_LP_IPQ806X_SERIAL_CONSOLE) += serial/ipq806x.c -libc-$(CONFIG_LP_RK_SERIAL_CONSOLE) += serial/rk_serial.c libc-$(CONFIG_LP_BG4CD_SERIAL_CONSOLE) += serial/bg4cd.c libc-$(CONFIG_LP_PC_KEYBOARD) += keyboard.c diff --git a/payloads/libpayload/drivers/serial/8250_mmio32.c b/payloads/libpayload/drivers/serial/8250_mmio32.c new file mode 100644 index 0000000000..285f7f6dac --- /dev/null +++ b/payloads/libpayload/drivers/serial/8250_mmio32.c @@ -0,0 +1,113 @@ +/* + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +struct mmio32_uart { + union { + uint32_t thr; // Transmit holding register. + uint32_t rbr; // Receive buffer register. + uint32_t dll; // Divisor latch lsb. + }; + union { + uint32_t ier; // Interrupt enable register. + uint32_t dlm; // Divisor latch msb. + }; + union { + uint32_t iir; // Interrupt identification register. + uint32_t fcr; // FIFO control register. + }; + uint32_t lcr; // Line control register. + uint32_t mcr; // Modem control register. + uint32_t lsr; // Line status register. + uint32_t msr; // Modem status register. +} __attribute__ ((packed)); + +enum { + LSR_DR = 0x1 << 0, // Data ready. + LSR_OE = 0x1 << 1, // Overrun. + LSR_PE = 0x1 << 2, // Parity error. + LSR_FE = 0x1 << 3, // Framing error. + LSR_BI = 0x1 << 4, // Break. + LSR_THRE = 0x1 << 5, // Xmit holding register empty. + LSR_TEMT = 0x1 << 6, // Xmitter empty. + LSR_ERR = 0x1 << 7 // Error. +}; + +static struct mmio32_uart *uart = NULL; + +void serial_putchar(unsigned int c) +{ + while (!(readl(&uart->lsr) & LSR_THRE)) + /* wait for transmit register to clear */; + + writel((char)c, &uart->thr); + if (c == '\n') + serial_putchar('\r'); +} + +int serial_havechar(void) +{ + uint8_t lsr = readl(&uart->lsr); + return (lsr & LSR_DR) == LSR_DR; +} + +int serial_getchar(void) +{ + while (!serial_havechar()) + /* wait for character */; + + return readl(&uart->rbr); +} + +static struct console_output_driver mmio32_serial_output = { + .putchar = &serial_putchar +}; + +static struct console_input_driver mmio32_serial_input = { + .havekey = &serial_havechar, + .getchar = &serial_getchar +}; + +void serial_init(void) +{ + if (!lib_sysinfo.serial || !lib_sysinfo.serial->baseaddr) + return; + + uart = (struct mmio32_uart *)(uintptr_t)lib_sysinfo.serial->baseaddr; +} + +void serial_console_init(void) +{ + serial_init(); + + if (uart) { + console_add_output_driver(&mmio32_serial_output); + console_add_input_driver(&mmio32_serial_input); + } +} diff --git a/payloads/libpayload/drivers/serial/rk_serial.c b/payloads/libpayload/drivers/serial/rk_serial.c deleted file mode 100644 index 91a6e1bde9..0000000000 --- a/payloads/libpayload/drivers/serial/rk_serial.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2014 Rockchip Electronics - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include -struct rk_uart { - union { - u32 uart_thr; /* Transmit holding register. */ - u32 uart_rbr; /* Receive buffer register. */ - u32 uart_dll; /* Divisor latch lsb. */ - }; - union { - u32 uart_ier; /* Interrupt enable register. */ - u32 uart_dlh; /* Divisor latch msb. */ - }; - union { - uint32_t uart_iir; /* Interrupt identification register. */ - uint32_t uart_fcr; /* FIFO control register. */ - }; - u32 uart_lcr; - u32 uart_mcr; - u32 uart_lsr; - u32 uart_msr; - u32 uart_scr; - u32 reserved1[(0x30 - 0x20) / 4]; - u32 uart_srbr[(0x70 - 0x30) / 4]; - u32 uart_far; - u32 uart_tfr; - u32 uart_rfw; - u32 uart_usr; - u32 uart_tfl; - u32 uart_rfl; - u32 uart_srr; - u32 uart_srts; - u32 uart_sbcr; - u32 uart_sdmam; - u32 uart_sfe; - u32 uart_srt; - u32 uart_stet; - u32 uart_htx; - u32 uart_dmasa; - u32 reserver2[(0xf4 - 0xac) / 4]; - u32 uart_cpr; - u32 uart_ucv; - u32 uart_ctr; -}; -enum { - UART_LSR_DR = 0x1 << 0, /* Data ready. */ - UART_LSR_OE = 0x1 << 1, /* Overrun. */ - UART_LSR_PE = 0x1 << 2, /* Parity error. */ - UART_LSR_FE = 0x1 << 3, /* Framing error. */ - UART_LSR_BI = 0x1 << 4, /* Break. */ - UART_LSR_THRE = 0x1 << 5, /* Xmit holding register empty. */ - UART_LSR_TEMT = 0x1 << 6, /* Xmitter empty. */ - UART_LSR_ERR = 0x1 << 7 /* Error. */ -}; - -static struct rk_uart *uart_regs; -void serial_putchar(unsigned int c) -{ - while (!(readl(&uart_regs->uart_lsr) & UART_LSR_THRE)); - writel((c & 0xff), &uart_regs->uart_thr); - if (c == '\n') - serial_putchar('\r'); -} - -int serial_havechar(void) -{ - uint8_t lsr = readl(&uart_regs->uart_lsr); - return (lsr & UART_LSR_DR) == UART_LSR_DR; -} - -int serial_getchar(void) -{ - while (!serial_havechar()); - return readl(&uart_regs->uart_rbr)&0xff; -} - -static struct console_input_driver consin = { - .havekey = &serial_havechar, - .getchar = &serial_getchar -}; - -static struct console_output_driver consout = {.putchar = &serial_putchar -}; - -void serial_init(void) -{ - if (!lib_sysinfo.serial || !lib_sysinfo.serial->baseaddr) - return; - - uart_regs = (struct rk_uart *)lib_sysinfo.serial->baseaddr; -} - -void serial_console_init(void) -{ - serial_init(); - console_add_input_driver(&consin); - console_add_output_driver(&consout); -} diff --git a/payloads/libpayload/drivers/serial/tegra.c b/payloads/libpayload/drivers/serial/tegra.c deleted file mode 100644 index a3dad2b09f..0000000000 --- a/payloads/libpayload/drivers/serial/tegra.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -struct tegra_uart { - union { - uint32_t thr; // Transmit holding register. - uint32_t rbr; // Receive buffer register. - uint32_t dll; // Divisor latch lsb. - }; - union { - uint32_t ier; // Interrupt enable register. - uint32_t dlm; // Divisor latch msb. - }; - union { - uint32_t iir; // Interrupt identification register. - uint32_t fcr; // FIFO control register. - }; - uint32_t lcr; // Line control register. - uint32_t mcr; // Modem control register. - uint32_t lsr; // Line status register. - uint32_t msr; // Modem status register. -} __attribute__ ((packed)); - -enum { - TEGRA_UART_LSR_DR = 0x1 << 0, // Data ready. - TEGRA_UART_LSR_OE = 0x1 << 1, // Overrun. - TEGRA_UART_LSR_PE = 0x1 << 2, // Parity error. - TEGRA_UART_LSR_FE = 0x1 << 3, // Framing error. - TEGRA_UART_LSR_BI = 0x1 << 4, // Break. - TEGRA_UART_LSR_THRE = 0x1 << 5, // Xmit holding register empty. - TEGRA_UART_LSR_TEMT = 0x1 << 6, // Xmitter empty. - TEGRA_UART_LSR_ERR = 0x1 << 7 // Error. -}; - -static struct tegra_uart *uart_regs; - -void serial_putchar(unsigned int c) -{ - while (!(readb(&uart_regs->lsr) & TEGRA_UART_LSR_THRE)); - writeb(c, &uart_regs->thr); - if (c == '\n') - serial_putchar('\r'); -} - -int serial_havechar(void) -{ - uint8_t lsr = readb(&uart_regs->lsr); - return (lsr & TEGRA_UART_LSR_DR) == TEGRA_UART_LSR_DR; -} - -int serial_getchar(void) -{ - while (!serial_havechar()) - {;} - - return readb(&uart_regs->rbr); -} - -static struct console_output_driver tegra_serial_output = -{ - .putchar = &serial_putchar -}; - -static struct console_input_driver tegra_serial_input = -{ - .havekey = &serial_havechar, - .getchar = &serial_getchar -}; - -void serial_init(void) -{ - if (!lib_sysinfo.serial || !lib_sysinfo.serial->baseaddr) - return; - - uart_regs = (struct tegra_uart *)(uintptr_t)lib_sysinfo.serial->baseaddr; -} - -void serial_console_init(void) -{ - serial_init(); - - if (uart_regs) { - console_add_output_driver(&tegra_serial_output); - console_add_input_driver(&tegra_serial_input); - } -} -- cgit v1.2.3