From patchwork Mon Apr 8 10:14:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksandr Tyshchenko X-Patchwork-Id: 10889237 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6F68B1805 for ; Mon, 8 Apr 2019 10:16:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 551B0285A4 for ; Mon, 8 Apr 2019 10:16:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 49C39285E8; Mon, 8 Apr 2019 10:16:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7B2CC285A4 for ; Mon, 8 Apr 2019 10:16:57 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hDRIu-0003ng-TR; Mon, 08 Apr 2019 10:15:04 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hDRIt-0003mk-Jv for xen-devel@lists.xenproject.org; Mon, 08 Apr 2019 10:15:03 +0000 X-Inumbo-ID: 2b87595f-59e7-11e9-92d7-bc764e045a96 Received: from mail-lf1-x142.google.com (unknown [2a00:1450:4864:20::142]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 2b87595f-59e7-11e9-92d7-bc764e045a96; Mon, 08 Apr 2019 10:15:02 +0000 (UTC) Received: by mail-lf1-x142.google.com with SMTP id a28so9028378lfo.7 for ; Mon, 08 Apr 2019 03:15:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MHk+ZsNFhbgNEh1E9NW6377RCFWJiyede3RFe1N4FJA=; b=aSVltA+YXUXlJfu7J62qtR77rIQMm3eUleelcPAwV9axlqX8MuGo7JzyJbAabF8j+5 +lIQ9Reru5KHim3hcFS50up3t6l7WngcAbxiaKy8aiJco3HomXK3A2I63uFCHGwiogBJ gi9C3empQrqSh7eDxRofa3dt96Z4EHXWerIZ0x7OjIuU4SvNV5uawAjM6HL6XsH7lJCD QKhf9CM59jEvL+laj7vKAWq2ZoPVfviVEQyn7QzQB/Jedcf35CxjDo8dDTW4+nam+R/E G3QAQbJ8TAWMACa+CZJ9TstOJVbEwk4lX9XwnmMf+fa9RAywcx34daqm5fSwD3ktlDax U2ag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=MHk+ZsNFhbgNEh1E9NW6377RCFWJiyede3RFe1N4FJA=; b=HoyJUJr11fqC+vYAQ3awgGRYTspOXbHmokQskTy6rOuQClkMLWWZfI9aKXGE78gktx 1jOoyYBm0/tbS/sMAvA1wIt3t56a0ZCnBuqbP1OGXznWQqumzZa4dbQQ0Cr2z0zbZZ99 ldkeIzoKWoasdwosdz7HWmLH7IVgrGtTQiUbtjHfSwbu84RhaEnBgUTxzP7mzbwQ3EbI LY46G1uFluECvjwZlnNTC8d0WjKTu8rztoU6ZrwtqG/YDFJxseqSU4qi/JO4nv3RcFEL Vzo2lWvYNBjteiapYJCVpKTggp8TBh0oTA8gMO14v+dAz/v5FC1EDfawLPhGxWx/c9pW 2NwQ== X-Gm-Message-State: APjAAAUQRLhAAv6LZWspyrTxN0Q6bjmoXDFsoSpghkWhxBoBFttT/nJN 7rvWygFMnrNcHfZs56kjy9cwwLuq0Jk= X-Google-Smtp-Source: APXvYqwJW1DI7lmHVZvogNLBAqm4TddNmXfyIrZHwMuMD8p1WgcvBzefRIOz1Q/dVLKRXs0mVUVGQA== X-Received: by 2002:ac2:4303:: with SMTP id l3mr1376778lfh.61.1554718500622; Mon, 08 Apr 2019 03:15:00 -0700 (PDT) Received: from otyshchenko.kyiv.epam.com (ll-22.209.223.85.sovam.net.ua. [85.223.209.22]) by smtp.gmail.com with ESMTPSA id x30sm6275717ljd.38.2019.04.08.03.14.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 08 Apr 2019 03:15:00 -0700 (PDT) From: Oleksandr Tyshchenko To: xen-devel@lists.xenproject.org Date: Mon, 8 Apr 2019 13:14:46 +0300 Message-Id: <1554718489-11318-3-git-send-email-olekstysh@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1554718489-11318-1-git-send-email-olekstysh@gmail.com> References: <1554718489-11318-1-git-send-email-olekstysh@gmail.com> Subject: [Xen-devel] [PATCH V3 2/5] xen/arm: drivers: scif: Extend driver to handle other interfaces X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Oleksandr Tyshchenko , julien.grall@arm.com, sstabellini@kernel.org MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Oleksandr Tyshchenko Extend driver to be able to handle other SCIF(X) compatible interfaces as well. These interfaces have lot in common, but mostly differ in offsets and bits for some registers. Introduce "port_params" array to keep interface specific things. The "data" field in struct dt_device_match is used for recognizing what interface is present on a target board. Please note, nothing has been technically changed for Renesas "Lager" and other supported boards (SCIF). Signed-off-by: Oleksandr Tyshchenko CC: Julien Grall --- Changes in v2: - Name a enum for describing interfaces this driver supports - Use local variable for "params" where appropriate - Use "data" field in struct dt_device_match instead of calling dt_device_is_compatible() - Don't check for "overrun_reg != status_reg" condition during initialization Changes in v3: - This patch is a result of splitting an initial patch "xen/arm: drivers: scif: Add support for SCIFA compatible UARTs" and only reworks a driver - Drop "port_type" variable from scif_uart_init(), pass a pointer directly --- xen/drivers/char/scif-uart.c | 119 ++++++++++++++++++++++++++++------------ xen/include/asm-arm/scif-uart.h | 4 -- 2 files changed, 85 insertions(+), 38 deletions(-) diff --git a/xen/drivers/char/scif-uart.c b/xen/drivers/char/scif-uart.c index 465fb34..958f717 100644 --- a/xen/drivers/char/scif-uart.c +++ b/xen/drivers/char/scif-uart.c @@ -40,16 +40,51 @@ static struct scif_uart { char __iomem *regs; struct irqaction irqaction; struct vuart_info vuart; + const struct port_params *params; } scif_com = {0}; +enum port_types +{ + SCIF_PORT, + NR_PORTS, +}; + +struct port_params +{ + unsigned int status_reg; + unsigned int tx_fifo_reg; + unsigned int rx_fifo_reg; + unsigned int overrun_reg; + unsigned int overrun_mask; + unsigned int error_mask; + unsigned int irq_flags; + unsigned int fifo_size; +}; + +static const struct port_params port_params[NR_PORTS] = +{ + [SCIF_PORT] = + { + .status_reg = SCIF_SCFSR, + .tx_fifo_reg = SCIF_SCFTDR, + .rx_fifo_reg = SCIF_SCFRDR, + .overrun_reg = SCIF_SCLSR, + .overrun_mask = SCLSR_ORER, + .error_mask = SCFSR_PER | SCFSR_FER | SCFSR_BRK | SCFSR_ER, + .irq_flags = SCSCR_RIE | SCSCR_TIE | SCSCR_REIE, + .fifo_size = 16, + }, +}; + static void scif_uart_interrupt(int irq, void *data, struct cpu_user_regs *regs) { struct serial_port *port = data; struct scif_uart *uart = port->uart; + const struct port_params *params = uart->params; uint16_t status, ctrl; ctrl = scif_readw(uart, SCIF_SCSCR); - status = scif_readw(uart, SCIF_SCFSR) & ~SCFSR_TEND; + status = scif_readw(uart, params->status_reg) & ~SCFSR_TEND; /* Ignore next flag if TX Interrupt is disabled */ if ( !(ctrl & SCSCR_TIE) ) status &= ~SCFSR_TDFE; @@ -65,13 +100,16 @@ static void scif_uart_interrupt(int irq, void *data, struct cpu_user_regs *regs) serial_rx_interrupt(port, regs); /* Error Interrupt */ - if ( status & SCIF_ERRORS ) - scif_writew(uart, SCIF_SCFSR, ~SCIF_ERRORS); - if ( scif_readw(uart, SCIF_SCLSR) & SCLSR_ORER ) - scif_writew(uart, SCIF_SCLSR, 0); + if ( status & params->error_mask ) + scif_writew(uart, params->status_reg, ~params->error_mask); + if ( params->overrun_reg != params->status_reg ) + { + if ( scif_readw(uart, params->overrun_reg) & params->overrun_mask ) + scif_writew(uart, params->overrun_reg, ~params->overrun_mask); + } ctrl = scif_readw(uart, SCIF_SCSCR); - status = scif_readw(uart, SCIF_SCFSR) & ~SCFSR_TEND; + status = scif_readw(uart, params->status_reg) & ~SCFSR_TEND; /* Ignore next flag if TX Interrupt is disabled */ if ( !(ctrl & SCSCR_TIE) ) status &= ~SCFSR_TDFE; @@ -81,12 +119,13 @@ static void scif_uart_interrupt(int irq, void *data, struct cpu_user_regs *regs) static void __init scif_uart_init_preirq(struct serial_port *port) { struct scif_uart *uart = port->uart; + const struct port_params *params = uart->params; /* * Wait until last bit has been transmitted. This is needed for a smooth * transition when we come from early printk */ - while ( !(scif_readw(uart, SCIF_SCFSR) & SCFSR_TEND) ); + while ( !(scif_readw(uart, params->status_reg) & SCFSR_TEND) ); /* Disable TX/RX parts and all interrupts */ scif_writew(uart, SCIF_SCSCR, 0); @@ -95,10 +134,10 @@ static void __init scif_uart_init_preirq(struct serial_port *port) scif_writew(uart, SCIF_SCFCR, SCFCR_RFRST | SCFCR_TFRST); /* Clear all errors and flags */ - scif_readw(uart, SCIF_SCFSR); - scif_writew(uart, SCIF_SCFSR, 0); - scif_readw(uart, SCIF_SCLSR); - scif_writew(uart, SCIF_SCLSR, 0); + scif_readw(uart, params->status_reg); + scif_writew(uart, params->status_reg, 0); + scif_readw(uart, params->overrun_reg); + scif_writew(uart, params->overrun_reg, 0); /* Setup trigger level for TX/RX FIFOs */ scif_writew(uart, SCIF_SCFCR, SCFCR_RTRG11 | SCFCR_TTRG11); @@ -111,6 +150,7 @@ static void __init scif_uart_init_preirq(struct serial_port *port) static void __init scif_uart_init_postirq(struct serial_port *port) { struct scif_uart *uart = port->uart; + const struct port_params *params = uart->params; int rc; uart->irqaction.handler = scif_uart_interrupt; @@ -122,14 +162,17 @@ static void __init scif_uart_init_postirq(struct serial_port *port) uart->irq); /* Clear all errors */ - if ( scif_readw(uart, SCIF_SCFSR) & SCIF_ERRORS ) - scif_writew(uart, SCIF_SCFSR, ~SCIF_ERRORS); - if ( scif_readw(uart, SCIF_SCLSR) & SCLSR_ORER ) - scif_writew(uart, SCIF_SCLSR, 0); + if ( scif_readw(uart, params->status_reg) & params->error_mask ) + scif_writew(uart, params->status_reg, ~params->error_mask); + if ( params->overrun_reg != params->status_reg ) + { + if ( scif_readw(uart, params->overrun_reg) & params->overrun_mask ) + scif_writew(uart, params->overrun_reg, ~params->overrun_mask); + } /* Enable TX/RX and Error Interrupts */ scif_writew(uart, SCIF_SCSCR, scif_readw(uart, SCIF_SCSCR) | - SCSCR_TIE | SCSCR_RIE | SCSCR_REIE); + params->irq_flags); } static void scif_uart_suspend(struct serial_port *port) @@ -145,43 +188,47 @@ static void scif_uart_resume(struct serial_port *port) static int scif_uart_tx_ready(struct serial_port *port) { struct scif_uart *uart = port->uart; + const struct port_params *params = uart->params; uint16_t cnt; /* Check for empty space in TX FIFO */ - if ( !(scif_readw(uart, SCIF_SCFSR) & SCFSR_TDFE) ) + if ( !(scif_readw(uart, params->status_reg) & SCFSR_TDFE) ) return 0; /* Check number of data bytes stored in TX FIFO */ cnt = scif_readw(uart, SCIF_SCFDR) >> 8; - ASSERT( cnt >= 0 && cnt <= SCIF_FIFO_MAX_SIZE ); + ASSERT( cnt >= 0 && cnt <= params->fifo_size ); - return (SCIF_FIFO_MAX_SIZE - cnt); + return (params->fifo_size - cnt); } static void scif_uart_putc(struct serial_port *port, char c) { struct scif_uart *uart = port->uart; + const struct port_params *params = uart->params; - scif_writeb(uart, SCIF_SCFTDR, c); + scif_writeb(uart, params->tx_fifo_reg, c); /* Clear required TX flags */ - scif_writew(uart, SCIF_SCFSR, scif_readw(uart, SCIF_SCFSR) & - ~(SCFSR_TEND | SCFSR_TDFE)); + scif_writew(uart, params->status_reg, + scif_readw(uart, params->status_reg) & + ~(SCFSR_TEND | SCFSR_TDFE)); } static int scif_uart_getc(struct serial_port *port, char *pc) { struct scif_uart *uart = port->uart; + const struct port_params *params = uart->params; /* Check for available data bytes in RX FIFO */ - if ( !(scif_readw(uart, SCIF_SCFSR) & (SCFSR_RDF | SCFSR_DR)) ) + if ( !(scif_readw(uart, params->status_reg) & (SCFSR_RDF | SCFSR_DR)) ) return 0; - *pc = scif_readb(uart, SCIF_SCFRDR); + *pc = scif_readb(uart, params->rx_fifo_reg); /* dummy read */ - scif_readw(uart, SCIF_SCFSR); + scif_readw(uart, params->status_reg); /* Clear required RX flags */ - scif_writew(uart, SCIF_SCFSR, ~(SCFSR_RDF | SCFSR_DR)); + scif_writew(uart, params->status_reg, ~(SCFSR_RDF | SCFSR_DR)); return 1; } @@ -229,9 +276,16 @@ static struct uart_driver __read_mostly scif_uart_driver = { .vuart_info = scif_vuart_info, }; +static const struct dt_device_match scif_uart_dt_match[] __initconst = +{ + { .compatible = "renesas,scif", .data = (void *)SCIF_PORT }, + { /* sentinel */ }, +}; + static int __init scif_uart_init(struct dt_device_node *dev, const void *data) { + const struct dt_device_match *match; const char *config = data; struct scif_uart *uart; int res; @@ -265,10 +319,13 @@ static int __init scif_uart_init(struct dt_device_node *dev, return -ENOMEM; } + match = dt_match_node(scif_uart_dt_match, dev); + uart->params = &port_params[(enum port_types)match->data]; + uart->vuart.base_addr = addr; uart->vuart.size = size; - uart->vuart.data_off = SCIF_SCFTDR; - uart->vuart.status_off = SCIF_SCFSR; + uart->vuart.data_off = uart->params->tx_fifo_reg; + uart->vuart.status_off = uart->params->status_reg; uart->vuart.status = SCFSR_TDFE; /* Register with generic serial driver */ @@ -279,12 +336,6 @@ static int __init scif_uart_init(struct dt_device_node *dev, return 0; } -static const struct dt_device_match scif_uart_dt_match[] __initconst = -{ - DT_MATCH_COMPATIBLE("renesas,scif"), - { /* sentinel */ }, -}; - DT_DEVICE_START(scif_uart, "SCIF UART", DEVICE_SERIAL) .dt_match = scif_uart_dt_match, .init = scif_uart_init, diff --git a/xen/include/asm-arm/scif-uart.h b/xen/include/asm-arm/scif-uart.h index 8137850..c343f2f 100644 --- a/xen/include/asm-arm/scif-uart.h +++ b/xen/include/asm-arm/scif-uart.h @@ -21,8 +21,6 @@ #ifndef __ASM_ARM_SCIF_UART_H #define __ASM_ARM_SCIF_UART_H -#define SCIF_FIFO_MAX_SIZE 16 - /* Register offsets */ #define SCIF_SCSMR (0x00) /* Serial mode register */ #define SCIF_SCBRR (0x04) /* Bit rate register */ @@ -57,8 +55,6 @@ #define SCFSR_RDF (1 << 1) /* Receive FIFO Data Full */ #define SCFSR_DR (1 << 0) /* Receive Data Ready */ -#define SCIF_ERRORS (SCFSR_PER | SCFSR_FER | SCFSR_ER | SCFSR_BRK) - /* Line Status Register (SCLSR) */ #define SCLSR_TO (1 << 2) /* Timeout */ #define SCLSR_ORER (1 << 0) /* Overrun Error */