|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 2/3] drivers: serial: add Qualcomm GENI-based serial driver
Hello,
On 29/03/2024 01:08, Volodymyr Babchuk wrote:
>
>
> Generic Interface (GENI) is a newer interface for low speed interfaces
> like UART, I2C or SPI. This patch adds the simple driver for the UART
> instance of GENI. Code is based on similar drivers in U-Boot and Linux
> kernel.
Do you have a link to a manual?
>
> This driver implements only simple synchronous mode, because although
> GENI supports FIFO mode, it needs to know number of
> characters **before** starting TX transaction. This is a stark
> contrast when compared to other UART peripherals, which allow adding
> characters to a FIFO while TX operation is running.
>
> The patch adds both normal UART driver and earlyprintk version.
>
> Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>
> ---
> xen/arch/arm/Kconfig.debug | 19 +-
> xen/arch/arm/arm64/debug-qcom.inc | 76 +++++++
Shouldn't all the files (+ other places) have geni in their names? Could qcom
refer to other type of serial device?
> xen/arch/arm/include/asm/qcom-uart.h | 48 +++++
> xen/drivers/char/Kconfig | 8 +
> xen/drivers/char/Makefile | 1 +
> xen/drivers/char/qcom-uart.c | 288 +++++++++++++++++++++++++++
> 6 files changed, 439 insertions(+), 1 deletion(-)
> create mode 100644 xen/arch/arm/arm64/debug-qcom.inc
> create mode 100644 xen/arch/arm/include/asm/qcom-uart.h
> create mode 100644 xen/drivers/char/qcom-uart.c
>
> diff --git a/xen/arch/arm/Kconfig.debug b/xen/arch/arm/Kconfig.debug
> index eec860e88e..f6ab0bb30e 100644
> --- a/xen/arch/arm/Kconfig.debug
> +++ b/xen/arch/arm/Kconfig.debug
> @@ -119,6 +119,19 @@ choice
> selecting one of the platform specific options below
> if
> you know the parameters for the port.
>
> + This option is preferred over the platform specific
> + options; the platform specific options are deprecated
> + and will soon be removed.
> + config EARLY_UART_CHOICE_QCOM
The list is sorted alphabetically. Please adhere to that.
> + select EARLY_UART_QCOM
> + bool "Early printk via Qualcomm debug UART"
Shouldn't you add depends on ARM_64? Isn't this device Arm64 specific like in
Linux?
> + help
> + Say Y here if you wish the early printk to direct
> their
help text here should be indented by 2 tabs and 2 spaces (do not take example
from surrounding code)
> + output to a Qualcomm debug UART. You can use this
> option to
> + provide the parameters for the debug UART rather than
> + selecting one of the platform specific options below
> if
> + you know the parameters for the port.
> +
> This option is preferred over the platform specific
> options; the platform specific options are deprecated
> and will soon be removed.
> @@ -211,6 +224,9 @@ config EARLY_UART_PL011
> config EARLY_UART_SCIF
> select EARLY_PRINTK
> bool
> +config EARLY_UART_QCOM
> + select EARLY_PRINTK
> + bool
The list is sorted alphabetically. Please adhere to that.
>
> config EARLY_PRINTK
> bool
> @@ -261,7 +277,7 @@ config EARLY_UART_PL011_MMIO32
> will be done using 32-bit only accessors.
>
> config EARLY_UART_INIT
> - depends on EARLY_UART_PL011 && EARLY_UART_PL011_BAUD_RATE != 0
> + depends on (EARLY_UART_PL011 && EARLY_UART_PL011_BAUD_RATE != 0) ||
> EARLY_UART_QCOM
> def_bool y
>
> config EARLY_UART_8250_REG_SHIFT
> @@ -308,3 +324,4 @@ config EARLY_PRINTK_INC
> default "debug-mvebu.inc" if EARLY_UART_MVEBU
> default "debug-pl011.inc" if EARLY_UART_PL011
> default "debug-scif.inc" if EARLY_UART_SCIF
> + default "debug-qcom.inc" if EARLY_UART_QCOM
> diff --git a/xen/arch/arm/arm64/debug-qcom.inc
> b/xen/arch/arm/arm64/debug-qcom.inc
> new file mode 100644
> index 0000000000..130d08d6e9
> --- /dev/null
> +++ b/xen/arch/arm/arm64/debug-qcom.inc
> @@ -0,0 +1,76 @@
> +/*
> + * xen/arch/arm/arm64/debug-qcom.inc
> + *
> + * Qualcomm debug UART specific debug code
> + *
> + * Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>
> + * Copyright (C) 2024, EPAM Systems.
> + *
> + * 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; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * 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.
No need for the license text. You should use SPDX identifier instead at the top
of the file:
/* SPDX-License-Identifier: GPL-2.0-or-later */
> + */
> +
> +#include <asm/qcom-uart.h>
> +
> +.macro early_uart_init xb c
Separate macro parameters with comma (here and elsewhere) and please add a
comment on top clarifying the use
Also, do we really need to initialize uart every time? What if firmware does
that?
> + mov w\c, #M_GENI_CMD_ABORT
> + str w\c, [\xb, #SE_GENI_M_CMD_CTRL_REG]
> +1:
> + ldr w\c, [\xb, #SE_GENI_M_IRQ_STATUS] /* Load IRQ status */
> + tst w\c, #M_CMD_ABORT_EN /* Check TX_FIFI_WATERMARK_EN bit
> */
The comment does not correspond to the code. Shouldn't this be the same as in
early_uart_ready?
> + beq 1b /* Wait for the UART to be ready */
> + mov w\c, #M_CMD_ABORT_EN
> + orr w\c, w\c, #M_CMD_DONE_EN
> + str w\c, [\xb, #SE_GENI_M_IRQ_CLEAR]
> +
> + mov w\c, #1
> + str w\c, [\xb, #SE_UART_TX_TRANS_LEN] /* write len */
> +
> + mov w\c, #(UART_START_TX << M_OPCODE_SHFT) /* Prepare cmd */
> + str w\c, [\xb, #SE_GENI_M_CMD0] /* write cmd */
> +.endm
> +/*
> + * wait for UART to be ready to transmit
> + * xb: register which contains the UART base address
> + * c: scratch register
> + */
> +.macro early_uart_ready xb c
> +1:
> + ldr w\c, [\xb, #SE_GENI_M_IRQ_STATUS] /* Load IRQ status */
> + tst w\c, #M_TX_FIFO_WATERMARK_EN /* Check TX_FIFI_WATERMARK_EN
> bit */
> + beq 1b /* Wait for the UART to be ready
> */
> +.endm
> +
> +/*
> + * UART transmit character
> + * xb: register which contains the UART base address
> + * wt: register which contains the character to transmit
> + */
> +.macro early_uart_transmit xb wt
> + str \wt, [\xb, #SE_GENI_TX_FIFOn] /* Put char to FIFO
> */
> + mov \wt, #M_TX_FIFO_WATERMARK_EN /* Prepare to FIFO */
> + str \wt, [\xb, #SE_GENI_M_IRQ_CLEAR] /* Kick FIFO */
> +95:
> + ldr \wt, [\xb, #SE_GENI_M_IRQ_STATUS] /* Load IRQ status */
> + tst \wt, #M_CMD_DONE_EN /* Check TX_FIFO_WATERMARK_EN
> bit */
> + beq 95b /* Wait for the UART to be ready
> */
> + mov \wt, #M_CMD_DONE_EN
> + str \wt, [\xb, #SE_GENI_M_IRQ_CLEAR]
> +
> + mov \wt, #(UART_START_TX << M_OPCODE_SHFT) /* Prepare next cmd
> */
> + str \wt, [\xb, #SE_GENI_M_CMD0] /* write cmd */
> +.endm
> +
> +/*
> + * Local variables:
> + * mode: ASM
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/include/asm/qcom-uart.h
> b/xen/arch/arm/include/asm/qcom-uart.h
> new file mode 100644
> index 0000000000..dc9579374c
> --- /dev/null
> +++ b/xen/arch/arm/include/asm/qcom-uart.h
> @@ -0,0 +1,48 @@
> +/*
> + * xen/include/asm-arm/qcom-uart.h
What's the use of this pseudo path? I would drop it or provide a correct path.
> + *
> + * Common constant definition between early printk and the UART driver
> + * for the Qualcomm debug UART
> + *
> + * Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>
> + * Copyright (C) 2024, EPAM Systems.
> + *
> + * 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; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * 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.
No need for the license text. You should use SPDX identifier instead at the top
of the file:
/* SPDX-License-Identifier: GPL-2.0-or-later */
> + */
> +
> +#ifndef __ASM_ARM_QCOM_UART_H
> +#define __ASM_ARM_QCOM_UART_H
> +
> +#define SE_UART_TX_TRANS_LEN 0x270
> +#define SE_GENI_M_CMD0 0x600
> +#define UART_START_TX 0x1
> +#define M_OPCODE_SHFT 27
> +
> +#define SE_GENI_M_CMD_CTRL_REG 0x604
> +#define M_GENI_CMD_ABORT BIT(1, U)
> +#define SE_GENI_M_IRQ_STATUS 0x610
> +#define M_CMD_DONE_EN BIT(0, U)
> +#define M_CMD_ABORT_EN BIT(5, U)
> +#define M_TX_FIFO_WATERMARK_EN BIT(30, U)
> +#define SE_GENI_M_IRQ_CLEAR 0x618
> +#define SE_GENI_TX_FIFOn 0x700
> +#define SE_GENI_TX_WATERMARK_REG 0x80c
AFAICT, in this header you listed only regs used both by assembly and c code.
However, SE_GENI_TX_WATERMARK_REG is not used in assembly.
Also, my personal opinion is that it would make more sense to list here all the
regs.
> +
> +#endif /* __ASM_ARM_QCOM_UART_H */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/drivers/char/Kconfig b/xen/drivers/char/Kconfig
> index e18ec3788c..52c3934d06 100644
> --- a/xen/drivers/char/Kconfig
> +++ b/xen/drivers/char/Kconfig
> @@ -68,6 +68,14 @@ config HAS_SCIF
> This selects the SuperH SCI(F) UART. If you have a SuperH based
> board,
> or Renesas R-Car Gen 2/3 based board say Y.
>
> +config HAS_QCOM_UART
> + bool "Qualcomm GENI UART driver"
> + default y
> + depends on ARM
Isn't is Arm64 specific device?
> + help
> + This selects the Qualcomm GENI-based UART driver. If you
> + have a Qualcomm-based board board say Y here.
> +
> config HAS_EHCI
> bool
> depends on X86
> diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile
> index e7e374775d..698ad0578c 100644
> --- a/xen/drivers/char/Makefile
> +++ b/xen/drivers/char/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_HAS_MESON) += meson-uart.o
> obj-$(CONFIG_HAS_MVEBU) += mvebu-uart.o
> obj-$(CONFIG_HAS_OMAP) += omap-uart.o
> obj-$(CONFIG_HAS_SCIF) += scif-uart.o
> +obj-$(CONFIG_HAS_QCOM_UART) += qcom-uart.o
Q comes before S
> obj-$(CONFIG_HAS_EHCI) += ehci-dbgp.o
> obj-$(CONFIG_XHCI) += xhci-dbc.o
> obj-$(CONFIG_HAS_IMX_LPUART) += imx-lpuart.o
> diff --git a/xen/drivers/char/qcom-uart.c b/xen/drivers/char/qcom-uart.c
> new file mode 100644
> index 0000000000..2614051ca0
> --- /dev/null
> +++ b/xen/drivers/char/qcom-uart.c
> @@ -0,0 +1,288 @@
> +/*
> + * xen/drivers/char/qcom-uart.c
> + *
> + * Driver for Qualcomm GENI-based UART interface
> + *
> + * Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>
> + *
> + * Copyright (C) EPAM Systems 2024
> + *
> + * 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; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * 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.
No need for the license text. You should use SPDX identifier instead at the top
of the file:
/* SPDX-License-Identifier: GPL-2.0-or-later */
> + */
> +
> +#include <xen/console.h>
> +#include <xen/const.h>
> +#include <xen/errno.h>
> +#include <xen/serial.h>
> +#include <xen/init.h>
> +#include <xen/irq.h>
> +#include <xen/mm.h>
> +#include <xen/delay.h>
> +#include <asm/device.h>
> +#include <asm/qcom-uart.h>
> +#include <asm/io.h>
> +
> +#define GENI_FORCE_DEFAULT_REG 0x20
> +#define FORCE_DEFAULT BIT(0, U)
> +#define DEF_TX_WM 2
> +#define SE_GENI_TX_PACKING_CFG0 0x260
> +#define SE_GENI_TX_PACKING_CFG1 0x264
> +#define SE_GENI_RX_PACKING_CFG0 0x284
> +#define SE_GENI_RX_PACKING_CFG1 0x288
> +#define SE_GENI_M_IRQ_EN 0x614
> +#define M_SEC_IRQ_EN BIT(31, U)
> +#define M_RX_FIFO_WATERMARK_EN BIT(26, U)
> +#define M_RX_FIFO_LAST_EN BIT(27, U)
> +#define SE_GENI_S_CMD0 0x630
> +#define UART_START_READ 0x1
> +#define S_OPCODE_SHFT 27
> +#define SE_GENI_S_CMD_CTRL_REG 0x634
> +#define S_GENI_CMD_ABORT BIT(1, U)
> +#define SE_GENI_S_IRQ_STATUS 0x640
> +#define SE_GENI_S_IRQ_EN 0x644
> +#define S_RX_FIFO_LAST_EN BIT(27, U)
> +#define S_RX_FIFO_WATERMARK_EN BIT(26, U)
> +#define S_CMD_ABORT_EN BIT(5, U)
> +#define S_CMD_DONE_EN BIT(0, U)
> +#define SE_GENI_S_IRQ_CLEAR 0x648
> +#define SE_GENI_RX_FIFOn 0x780
> +#define SE_GENI_TX_FIFO_STATUS 0x800
> +#define TX_FIFO_WC GENMASK(27, 0)
> +#define SE_GENI_RX_FIFO_STATUS 0x804
> +#define RX_LAST BIT(31, U)
> +#define RX_LAST_BYTE_VALID_MSK GENMASK(30, 28)
> +#define RX_LAST_BYTE_VALID_SHFT 28
> +#define RX_FIFO_WC_MSK GENMASK(24, 0)
> +#define SE_GENI_TX_WATERMARK_REG 0x80c
> +
> +static struct qcom_uart {
> + unsigned int irq;
> + char __iomem *regs;
> + struct irqaction irqaction;
> +} qcom_com = {0};
> +
> +static bool qcom_uart_poll_bit(void *addr, uint32_t mask, bool set)
> +{
> + unsigned long timeout_us = 20000;
Why UL and not U?
> + uint32_t reg;
> +
> + while ( timeout_us ) {
Brace should be placed on its own line
> + reg = readl(addr);
> + if ( (bool)(reg & mask) == set )
> + return true;
> + udelay(10);
> + timeout_us -= 10;
> + }
> +
> + return false;
> +}
> +
> +static void __init qcom_uart_init_preirq(struct serial_port *port)
> +{
> + struct qcom_uart *uart = port->uart;
> +
> + /* Stop anything in TX that earlyprintk configured and clear all errors
> */
> + writel(M_GENI_CMD_ABORT, uart->regs + SE_GENI_M_CMD_CTRL_REG);
It would be easier to creare wrappers that would improve readability:
#define qcom_write(uart, off, val) writel((val), (uart)->regs + (off))
#define qcom_read(uart, off) readl((uart)->regs + (off))
> + qcom_uart_poll_bit(uart->regs + SE_GENI_M_IRQ_STATUS, M_CMD_ABORT_EN,
> + true);
> + writel(M_CMD_ABORT_EN, uart->regs + SE_GENI_M_IRQ_CLEAR);
> +
> + /*
> + * Configure FIFO length: 1 byte per FIFO entry. This is terribly
> + * ineffective, as it is possible to cram 4 bytes per FIFO word,
> + * like Linux does. But using one byte per FIFO entry makes this
> + * driver much simpler.
> + */
> + writel(0xf, uart->regs + SE_GENI_TX_PACKING_CFG0);
> + writel(0x0, uart->regs + SE_GENI_TX_PACKING_CFG1);
> + writel(0xf, uart->regs + SE_GENI_RX_PACKING_CFG0);
> + writel(0x0, uart->regs + SE_GENI_RX_PACKING_CFG1);
> +
> + /* Reset RX state machine */
> + writel(S_GENI_CMD_ABORT, uart->regs + SE_GENI_S_CMD_CTRL_REG);
> + qcom_uart_poll_bit(uart->regs + SE_GENI_S_CMD_CTRL_REG,
> + S_GENI_CMD_ABORT, false);
> + writel(S_CMD_DONE_EN | S_CMD_ABORT_EN, uart->regs + SE_GENI_S_IRQ_CLEAR);
> + writel(FORCE_DEFAULT, uart->regs + GENI_FORCE_DEFAULT_REG);
> +}
> +
> +static void qcom_uart_interrupt(int irq, void *data, struct cpu_user_regs
> *regs)
serial_rx_interrupt has been modified not to take regs as parameter. Your patch
breaks the build here.
You need to remove regs from here and ...
> +{
> + struct serial_port *port = data;
> + struct qcom_uart *uart = port->uart;
> + uint32_t m_irq_status, s_irq_status;
> +
> + m_irq_status = readl(uart->regs + SE_GENI_M_IRQ_STATUS);
> + s_irq_status = readl(uart->regs + SE_GENI_S_IRQ_STATUS);
> + writel(m_irq_status, uart->regs + SE_GENI_M_IRQ_CLEAR);
> + writel(s_irq_status, uart->regs + SE_GENI_S_IRQ_CLEAR);
> +
> + if ( s_irq_status & (S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN) )
> + serial_rx_interrupt(port, regs);
here.
> +}
> +
> +static void __init qcom_uart_init_postirq(struct serial_port *port)
> +{
> + struct qcom_uart *uart = port->uart;
> + int rc;
> + uint32_t val;
> +
> + uart->irqaction.handler = qcom_uart_interrupt;
> + uart->irqaction.name = "qcom_uart";
> + uart->irqaction.dev_id = port;
> +
> + if ( (rc = setup_irq(uart->irq, 0, &uart->irqaction)) != 0 )
Value assigned to rc does not seem to be used at all
> + dprintk(XENLOG_ERR, "Failed to allocated qcom_uart IRQ %d\n",
> + uart->irq);
> +
> + /* Enable TX/RX and Error Interrupts */
> + writel(S_GENI_CMD_ABORT, uart->regs + SE_GENI_S_CMD_CTRL_REG);
> + qcom_uart_poll_bit(uart->regs + SE_GENI_S_CMD_CTRL_REG,
> + S_GENI_CMD_ABORT, false);
> + writel(S_CMD_DONE_EN | S_CMD_ABORT_EN, uart->regs + SE_GENI_S_IRQ_CLEAR);
> + writel(FORCE_DEFAULT, uart->regs + GENI_FORCE_DEFAULT_REG);
> +
> + val = readl(uart->regs + SE_GENI_S_IRQ_EN);
> + val = S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN;
> + writel(val, uart->regs + SE_GENI_S_IRQ_EN);
> +
> + val = readl(uart->regs + SE_GENI_M_IRQ_EN);
> + val = M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
> + writel(val, uart->regs + SE_GENI_M_IRQ_EN);
> +
> + /* Send RX command */
> + writel(UART_START_READ << S_OPCODE_SHFT, uart->regs + SE_GENI_S_CMD0);
> + qcom_uart_poll_bit(uart->regs + SE_GENI_M_IRQ_STATUS, M_SEC_IRQ_EN,
> + true);
> +}
> +
> +static void qcom_uart_putc(struct serial_port *port, char c)
> +{
> + struct qcom_uart *uart = port->uart;
> + uint32_t irq_clear = M_CMD_DONE_EN;
> + uint32_t m_cmd;
> + bool done;
> +
> + /* Setup TX */
> + writel(1, uart->regs + SE_UART_TX_TRANS_LEN);
> +
> + writel(DEF_TX_WM, uart->regs + SE_GENI_TX_WATERMARK_REG);
> +
> + m_cmd = UART_START_TX << M_OPCODE_SHFT;
> + writel(m_cmd, uart->regs + SE_GENI_M_CMD0);
> +
> + qcom_uart_poll_bit(uart->regs + SE_GENI_M_IRQ_STATUS,
> + M_TX_FIFO_WATERMARK_EN, true);
> +
> + writel(c, uart->regs + SE_GENI_TX_FIFOn);
> + writel(M_TX_FIFO_WATERMARK_EN, uart->regs + SE_GENI_M_IRQ_CLEAR);
> +
> + /* Check for TX done */
> + done = qcom_uart_poll_bit(uart->regs + SE_GENI_M_IRQ_STATUS,
> M_CMD_DONE_EN,
> + true);
> + if ( !done )
> + {
> + writel(M_GENI_CMD_ABORT, uart->regs + SE_GENI_M_CMD_CTRL_REG);
> + irq_clear |= M_CMD_ABORT_EN;
> + qcom_uart_poll_bit(uart->regs + SE_GENI_M_IRQ_STATUS, M_CMD_ABORT_EN,
> + true);
> +
> + }
> + writel(irq_clear, uart->regs + SE_GENI_M_IRQ_CLEAR);
> +}
> +
> +static int qcom_uart_getc(struct serial_port *port, char *pc)
> +{
> + struct qcom_uart *uart = port->uart;
> +
> + if ( !readl(uart->regs + SE_GENI_RX_FIFO_STATUS) )
> + return 0;
> +
> + *pc = readl(uart->regs + SE_GENI_RX_FIFOn) & 0xFF;
> +
> + writel(UART_START_READ << S_OPCODE_SHFT, uart->regs + SE_GENI_S_CMD0);
> + qcom_uart_poll_bit(uart->regs + SE_GENI_M_IRQ_STATUS, M_SEC_IRQ_EN,
> + true);
> +
> + return 1;
> +
> +}
> +
> +static struct uart_driver __read_mostly qcom_uart_driver = {
> + .init_preirq = qcom_uart_init_preirq,
> + .init_postirq = qcom_uart_init_postirq,
> + .putc = qcom_uart_putc,
> + .getc = qcom_uart_getc,
> +};
> +
> +static const struct dt_device_match qcom_uart_dt_match[] __initconst =
> +{
> + { .compatible = "qcom,geni-debug-uart"},
> + { /* sentinel */ },
> +};
Can you move it right before DT_DEVICE_START?.
> +
> +static int __init qcom_uart_init(struct dt_device_node *dev,
> + const void *data)
> +{
> + const char *config = data;
> + struct qcom_uart *uart;
> + int res;
> + paddr_t addr, size;
> +
> + if ( strcmp(config, "") )
> + printk("WARNING: UART configuration is not supported\n");
> +
> + uart = &qcom_com;
> +
> + res = dt_device_get_paddr(dev, 0, &addr, &size);
> + if ( res )
> + {
> + printk("qcom-uart: Unable to retrieve the base"
> + " address of the UART\n");
> + return res;
> + }
> +
> + res = platform_get_irq(dev, 0);
> + if ( res < 0 )
> + {
> + printk("qcom-uart: Unable to retrieve the IRQ\n");
> + return res;
> + }
> + uart->irq = res;
> +
> + uart->regs = ioremap_nocache(addr, size);
> + if ( !uart->regs )
> + {
> + printk("qcom-uart: Unable to map the UART memory\n");
> + return -ENOMEM;
> + }
> +
> + /* Register with generic serial driver */
> + serial_register_uart(SERHND_DTUART, &qcom_uart_driver, uart);
> +
> + dt_device_set_used_by(dev, DOMID_XEN);
> +
> + return 0;
> +}
> +
> +DT_DEVICE_START(qcom_uart, "QCOM UART", DEVICE_SERIAL)
> + .dt_match = qcom_uart_dt_match,
> + .init = qcom_uart_init,
> +DT_DEVICE_END
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> --
> 2.43.0
What about vUART? You don't seem to set vuart information that is used by
vuart.c and vpl011.c
~Michal
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |