xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Oleksandr Tyshchenko <olekstysh@gmail.com>
To: xen-devel@lists.xenproject.org
Cc: Artem_Mygaiev@epam.com, olekstysh@gmail.com,
	Julien Grall <julien.grall@arm.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Subject: [PATCH v1 2/4] xen/arm: drivers: scif: Add support for SCIFA compatible UARTs
Date: Mon,  6 Aug 2018 21:35:50 +0300	[thread overview]
Message-ID: <1533580552-938-3-git-send-email-olekstysh@gmail.com> (raw)
In-Reply-To: <1533580552-938-1-git-send-email-olekstysh@gmail.com>

From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>

Extend existing driver to be able to handle SCIFA interface as well.
SCIF and SCIFA have lot in common, though SCIFA has different
offsets and bits for some registers.

Use compatible string to recognize what interface is present
on a target board.

Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>
---
 xen/drivers/char/scif-uart.c    | 129 +++++++++++++++++++++++++++++++---------
 xen/include/asm-arm/scif-uart.h |  44 ++++++++++++--
 2 files changed, 138 insertions(+), 35 deletions(-)

diff --git a/xen/drivers/char/scif-uart.c b/xen/drivers/char/scif-uart.c
index 465fb34..d1eb713 100644
--- a/xen/drivers/char/scif-uart.c
+++ b/xen/drivers/char/scif-uart.c
@@ -1,7 +1,7 @@
 /*
  * xen/drivers/char/scif-uart.c
  *
- * Driver for SCIF (Serial communication interface with FIFO)
+ * Driver for SCIF(A) (Serial communication interface with FIFO (A))
  * compatible UART.
  *
  * Oleksandr Tyshchenko <oleksandr.tyshchenko@globallogic.com>
@@ -40,8 +40,57 @@ static struct scif_uart {
     char __iomem *regs;
     struct irqaction irqaction;
     struct vuart_info vuart;
+    const struct port_params *params;
 } scif_com = {0};
 
+enum
+{
+    SCIF_PORT,
+    SCIFA_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,
+    },
+
+    [SCIFA_PORT] =
+    {
+        .status_reg   = SCIFA_SCASSR,
+        .tx_fifo_reg  = SCIFA_SCAFTDR,
+        .rx_fifo_reg  = SCIFA_SCAFRDR,
+        .overrun_reg  = SCIFA_SCASSR,
+        .overrun_mask = SCASSR_ORER,
+        .error_mask   = SCASSR_PER | SCASSR_FER | SCASSR_BRK | SCASSR_ER |
+                        SCASSR_ORER,
+        .irq_flags    = SCASCR_RIE | SCASCR_TIE | SCASCR_DRIE | SCASCR_ERIE |
+                        SCASCR_BRIE,
+        .fifo_size    = 64,
+    },
+};
+
 static void scif_uart_interrupt(int irq, void *data, struct cpu_user_regs *regs)
 {
     struct serial_port *port = data;
@@ -49,7 +98,7 @@ static void scif_uart_interrupt(int irq, void *data, struct cpu_user_regs *regs)
     uint16_t status, ctrl;
 
     ctrl = scif_readw(uart, SCIF_SCSCR);
-    status = scif_readw(uart, SCIF_SCFSR) & ~SCFSR_TEND;
+    status = scif_readw(uart, uart->params->status_reg) & ~SCFSR_TEND;
     /* Ignore next flag if TX Interrupt is disabled */
     if ( !(ctrl & SCSCR_TIE) )
         status &= ~SCFSR_TDFE;
@@ -65,13 +114,19 @@ 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 & uart->params->error_mask )
+            scif_writew(uart, uart->params->status_reg,
+                        ~uart->params->error_mask);
+        if ( uart->params->overrun_reg != uart->params->status_reg )
+        {
+            if ( scif_readw(uart, uart->params->overrun_reg) &
+                 uart->params->overrun_mask )
+                scif_writew(uart, uart->params->overrun_reg,
+                            ~uart->params->overrun_mask);
+        }
 
         ctrl = scif_readw(uart, SCIF_SCSCR);
-        status = scif_readw(uart, SCIF_SCFSR) & ~SCFSR_TEND;
+        status = scif_readw(uart, uart->params->status_reg) & ~SCFSR_TEND;
         /* Ignore next flag if TX Interrupt is disabled */
         if ( !(ctrl & SCSCR_TIE) )
             status &= ~SCFSR_TDFE;
@@ -86,7 +141,7 @@ static void __init scif_uart_init_preirq(struct serial_port *port)
      * 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, uart->params->status_reg) & SCFSR_TEND) );
 
     /* Disable TX/RX parts and all interrupts */
     scif_writew(uart, SCIF_SCSCR, 0);
@@ -95,10 +150,13 @@ 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, uart->params->status_reg);
+    scif_writew(uart, uart->params->status_reg, 0);
+    if ( uart->params->overrun_reg != uart->params->status_reg )
+    {
+        scif_readw(uart, uart->params->overrun_reg);
+        scif_writew(uart, uart->params->overrun_reg, 0);
+    }
 
     /* Setup trigger level for TX/RX FIFOs */
     scif_writew(uart, SCIF_SCFCR, SCFCR_RTRG11 | SCFCR_TTRG11);
@@ -122,14 +180,19 @@ 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, uart->params->status_reg) & uart->params->error_mask )
+        scif_writew(uart, uart->params->status_reg, ~uart->params->error_mask);
+    if ( uart->params->overrun_reg != uart->params->status_reg )
+    {
+        if ( scif_readw(uart, uart->params->overrun_reg) &
+             uart->params->overrun_mask )
+            scif_writew(uart, uart->params->overrun_reg,
+                        ~uart->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);
+                uart->params->irq_flags);
 }
 
 static void scif_uart_suspend(struct serial_port *port)
@@ -148,24 +211,25 @@ static int scif_uart_tx_ready(struct serial_port *port)
     uint16_t cnt;
 
     /* Check for empty space in TX FIFO */
-    if ( !(scif_readw(uart, SCIF_SCFSR) & SCFSR_TDFE) )
+    if ( !(scif_readw(uart, 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 <= uart->params->fifo_size );
 
-    return (SCIF_FIFO_MAX_SIZE - cnt);
+    return (uart->params->fifo_size - cnt);
 }
 
 static void scif_uart_putc(struct serial_port *port, char c)
 {
     struct scif_uart *uart = port->uart;
 
-    scif_writeb(uart, SCIF_SCFTDR, c);
+    scif_writeb(uart, 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, uart->params->status_reg,
+                scif_readw(uart, uart->params->status_reg) &
+                ~(SCFSR_TEND | SCFSR_TDFE));
 }
 
 static int scif_uart_getc(struct serial_port *port, char *pc)
@@ -173,15 +237,16 @@ static int scif_uart_getc(struct serial_port *port, char *pc)
     struct scif_uart *uart = port->uart;
 
     /* Check for available data bytes in RX FIFO */
-    if ( !(scif_readw(uart, SCIF_SCFSR) & (SCFSR_RDF | SCFSR_DR)) )
+    if ( !(scif_readw(uart, uart->params->status_reg) &
+          (SCFSR_RDF | SCFSR_DR)) )
         return 0;
 
-    *pc = scif_readb(uart, SCIF_SCFRDR);
+    *pc = scif_readb(uart, uart->params->rx_fifo_reg);
 
     /* dummy read */
-    scif_readw(uart, SCIF_SCFSR);
+    scif_readw(uart, uart->params->status_reg);
     /* Clear required RX flags */
-    scif_writew(uart, SCIF_SCFSR, ~(SCFSR_RDF | SCFSR_DR));
+    scif_writew(uart, uart->params->status_reg, ~(SCFSR_RDF | SCFSR_DR));
 
     return 1;
 }
@@ -265,10 +330,15 @@ static int __init scif_uart_init(struct dt_device_node *dev,
         return -ENOMEM;
     }
 
+    if ( dt_device_is_compatible(dev, "renesas,scifa") )
+        uart->params = &port_params[SCIFA_PORT];
+    else
+        uart->params = &port_params[SCIF_PORT];
+
     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 */
@@ -282,6 +352,7 @@ static int __init scif_uart_init(struct dt_device_node *dev,
 static const struct dt_device_match scif_uart_dt_match[] __initconst =
 {
     DT_MATCH_COMPATIBLE("renesas,scif"),
+    DT_MATCH_COMPATIBLE("renesas,scifa"),
     { /* sentinel */ },
 };
 
diff --git a/xen/include/asm-arm/scif-uart.h b/xen/include/asm-arm/scif-uart.h
index 8137850..bce3404 100644
--- a/xen/include/asm-arm/scif-uart.h
+++ b/xen/include/asm-arm/scif-uart.h
@@ -2,7 +2,7 @@
  * xen/include/asm-arm/scif-uart.h
  *
  * Common constant definition between early printk and the UART driver
- * for the SCIF compatible UART.
+ * for the SCIF(A) compatible UART.
  *
  * Oleksandr Tyshchenko <oleksandr.tyshchenko@globallogic.com>
  * Copyright (C) 2014, Globallogic.
@@ -21,9 +21,7 @@
 #ifndef __ASM_ARM_SCIF_UART_H
 #define __ASM_ARM_SCIF_UART_H
 
-#define SCIF_FIFO_MAX_SIZE    16
-
-/* Register offsets */
+/* Register offsets (SCIF) */
 #define SCIF_SCSMR     (0x00)    /* Serial mode register           */
 #define SCIF_SCBRR     (0x04)    /* Bit rate register              */
 #define SCIF_SCSCR     (0x08)    /* Serial control 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 */
@@ -83,6 +79,42 @@
 #define SCFCR_TTRG10    (SCFCR_TTRG1)
 #define SCFCR_TTRG11    (SCFCR_TTRG1 | SCFCR_TTRG0)
 
+/* Register offsets (SCIFA) */
+#define SCIFA_SCASMR     (0x00)    /* Serial mode register           */
+#define SCIFA_SCABRR     (0x04)    /* Bit rate register              */
+#define SCIFA_SCASCR     (0x08)    /* Serial control register        */
+#define SCIFA_SCATDSR    (0x0C)    /* Transmit data stop register    */
+#define SCIFA_SCAFER     (0x10)    /* FIFO error count register      */
+#define SCIFA_SCASSR     (0x14)    /* Serial status register         */
+#define SCIFA_SCAFCR     (0x18)    /* FIFO control register          */
+#define SCIFA_SCAFDR     (0x1C)    /* FIFO data count register       */
+#define SCIFA_SCAFTDR    (0x20)    /* Transmit FIFO data register    */
+#define SCIFA_SCAFRDR    (0x24)    /* Receive FIFO data register     */
+#define SCIFA_SCAPCR     (0x30)    /* Serial port control register   */
+#define SCIFA_SCAPDR     (0x34)    /* Serial port data register      */
+
+/* Serial Control Register (SCASCR) */
+#define SCASCR_ERIE     (1 << 10)    /* Receive Error Interrupt Enable */
+#define SCASCR_BRIE     (1 << 9)     /* Break Interrupt Enable */
+#define SCASCR_DRIE     (1 << 8)     /* Receive Data Ready Interrupt Enable */
+#define SCASCR_TIE      (1 << 7)     /* Transmit Interrupt Enable */
+#define SCASCR_RIE      (1 << 6)     /* Receive Interrupt Enable */
+#define SCASCR_TE       (1 << 5)     /* Transmit Enable */
+#define SCASCR_RE       (1 << 4)     /* Receive Enable */
+#define SCASCR_CKE0     (1 << 0)     /* Clock Enable 0 */
+
+/* Serial Status Register (SCASSR) */
+#define SCASSR_ORER    (1 << 9)    /* Overrun Error */
+#define SCASSR_TSF     (1 << 8)    /* Transmit Data Stop */
+#define SCASSR_ER      (1 << 7)    /* Receive Error */
+#define SCASSR_TEND    (1 << 6)    /* Transmission End */
+#define SCASSR_TDFE    (1 << 5)    /* Transmit FIFO Data Empty */
+#define SCASSR_BRK     (1 << 4)    /* Break Detect */
+#define SCASSR_FER     (1 << 3)    /* Framing Error */
+#define SCASSR_PER     (1 << 2)    /* Parity Error */
+#define SCASSR_RDF     (1 << 1)    /* Receive FIFO Data Full */
+#define SCASSR_DR      (1 << 0)    /* Receive Data Ready */
+
 #endif /* __ASM_ARM_SCIF_UART_H */
 
 /*
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2018-08-06 18:36 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-06 18:35 [PATCH v1 0/4] Renesas Stout board support (R-Car Gen2) Oleksandr Tyshchenko
2018-08-06 18:35 ` [PATCH v1 1/4] xen/arm: drivers: scif: Remove unused #define-s Oleksandr Tyshchenko
2018-08-07 13:28   ` Julien Grall
2018-08-06 18:35 ` Oleksandr Tyshchenko [this message]
2018-08-07 13:43   ` [PATCH v1 2/4] xen/arm: drivers: scif: Add support for SCIFA compatible UARTs Julien Grall
2018-08-07 15:01     ` Oleksandr Tyshchenko
2018-08-07 15:20       ` Julien Grall
2018-08-06 18:35 ` [PATCH v1 3/4] xen/arm: Add SCIFA UART support for early printk Oleksandr Tyshchenko
2018-08-07 13:48   ` Julien Grall
2018-08-07 14:28     ` Oleksandr Tyshchenko
2018-08-07 15:22       ` Julien Grall
2018-08-07 17:18         ` Oleksandr Tyshchenko
2018-08-06 18:35 ` [PATCH v1 4/4] xen/arm: Reuse R-Car Gen2 platform code for Stout board Oleksandr Tyshchenko
2018-08-07 15:18   ` Julien Grall
2018-08-07 17:12     ` Oleksandr Tyshchenko
2018-08-07 17:21       ` Julien Grall
2018-08-07 19:13         ` Oleksandr Tyshchenko
2018-08-09 16:10           ` Julien Grall
2018-08-09 16:18             ` Oleksandr Tyshchenko
2018-08-09 16:19               ` Oleksandr Tyshchenko
2018-08-09 16:20               ` Julien Grall
2018-08-09 18:18                 ` Oleksandr Tyshchenko
2018-08-10  9:44                   ` Julien Grall
2018-08-10 11:47                     ` Oleksandr Tyshchenko
2018-08-10 12:50                       ` Julien Grall
2018-08-13 12:41                         ` Oleksandr Tyshchenko
2018-08-22 15:48 ` [PATCH v1 0/4] Renesas Stout board support (R-Car Gen2) Julien Grall
2018-08-22 15:53   ` Oleksandr Tyshchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1533580552-938-3-git-send-email-olekstysh@gmail.com \
    --to=olekstysh@gmail.com \
    --cc=Artem_Mygaiev@epam.com \
    --cc=julien.grall@arm.com \
    --cc=oleksandr_tyshchenko@epam.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).