lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAMuHMdWUF=h-Q04xdLeKN9_jD+z=Uv+czbUbt1TU-_2TW2wWag@mail.gmail.com>
Date: Thu, 30 Jan 2025 09:38:57 +0100
From: Geert Uytterhoeven <geert@...ux-m68k.org>
To: Thierry Bultel <thierry.bultel.yh@...renesas.com>
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>, Jiri Slaby <jirislaby@...nel.org>, 
	linux-kernel@...r.kernel.org, linux-serial@...r.kernel.org, 
	Linux-Renesas <linux-renesas-soc@...r.kernel.org>
Subject: Re: [PATCH 09/14] serial: sh-sci: Introduced function pointers

CC linux-renesas-soc

On Wed, 29 Jan 2025 at 18:03, Thierry Bultel
<thierry.bultel.yh@...renesas.com> wrote:
> The aim here is to prepare support for new sci controllers like
> the T2H/RSCI whose registers are too much different for being
> handled in common code.
>
> This named serial controller also has 32 bits register,
> so some return types had to be changed.
>
> The needed generic functions are no longer static, with prototypes
> defined in sh-sci-common.h so that they can be used from specific
> implementation in a separate file, to keep this driver as little
> changed as possible.
>
> For doing so, a set of 'ops' is added to struct sci_port.
>
> Signed-off-by: Thierry Bultel <thierry.bultel.yh@...renesas.com>
> ---
>  drivers/tty/serial/sh-sci.c        | 339 +++++++++++++++--------------
>  drivers/tty/serial/sh-sci_common.h | 178 +++++++++++++++
>  2 files changed, 349 insertions(+), 168 deletions(-)
>  create mode 100644 drivers/tty/serial/sh-sci_common.h
>
> diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
> index 5ba25a6a5432..1b83a246c7ed 100644
> --- a/drivers/tty/serial/sh-sci.c
> +++ b/drivers/tty/serial/sh-sci.c
> @@ -56,19 +56,7 @@
>
>  #include "serial_mctrl_gpio.h"
>  #include "sh-sci.h"
> -
> -/* Offsets into the sci_port->irqs array */
> -enum {
> -       SCIx_ERI_IRQ,
> -       SCIx_RXI_IRQ,
> -       SCIx_TXI_IRQ,
> -       SCIx_BRI_IRQ,
> -       SCIx_DRI_IRQ,
> -       SCIx_TEI_IRQ,
> -       SCIx_NR_IRQS,
> -
> -       SCIx_MUX_IRQ = SCIx_NR_IRQS,    /* special case */
> -};
> +#include "sh-sci_common.h"
>
>  #define SCIx_IRQ_IS_MUXED(port)                        \
>         ((port)->irqs[SCIx_ERI_IRQ] ==  \
> @@ -76,101 +64,39 @@ enum {
>         ((port)->irqs[SCIx_ERI_IRQ] &&  \
>          ((port)->irqs[SCIx_RXI_IRQ] < 0))
>
> -enum SCI_CLKS {
> -       SCI_FCK,                /* Functional Clock */
> -       SCI_SCK,                /* Optional External Clock */
> -       SCI_BRG_INT,            /* Optional BRG Internal Clock Source */
> -       SCI_SCIF_CLK,           /* Optional BRG External Clock Source */
> -       SCI_NUM_CLKS
> -};
> -
> -/* Bit x set means sampling rate x + 1 is supported */
> -#define SCI_SR(x)              BIT((x) - 1)
>  #define SCI_SR_RANGE(x, y)     GENMASK((y) - 1, (x) - 1)
>
>  #define SCI_SR_SCIFAB          SCI_SR(5) | SCI_SR(7) | SCI_SR(11) | \
>                                 SCI_SR(13) | SCI_SR(16) | SCI_SR(17) | \
>                                 SCI_SR(19) | SCI_SR(27)
>
> -#define min_sr(_port)          ffs((_port)->sampling_rate_mask)
> -#define max_sr(_port)          fls((_port)->sampling_rate_mask)
> -
>  /* Iterate over all supported sampling rates, from high to low */
>  #define for_each_sr(_sr, _port)                                                \
>         for ((_sr) = max_sr(_port); (_sr) >= min_sr(_port); (_sr)--)    \
>                 if ((_port)->sampling_rate_mask & SCI_SR((_sr)))
>
> -struct plat_sci_reg {
> -       u8 offset, size;
> -};
> -
> -struct sci_port_params {
> -       const struct plat_sci_reg regs[SCIx_NR_REGS];
> -       unsigned int fifosize;
> -       unsigned int overrun_reg;
> -       unsigned int overrun_mask;
> -       unsigned int sampling_rate_mask;
> -       unsigned int error_mask;
> -       unsigned int error_clear;
> -};
> -
> -struct sci_port {
> -       struct uart_port        port;
> -
> -       /* Platform configuration */
> -       const struct sci_port_params *params;
> -       const struct plat_sci_port *cfg;
> -       unsigned int            sampling_rate_mask;
> -       resource_size_t         reg_size;
> -       struct mctrl_gpios      *gpios;
> -
> -       /* Clocks */
> -       struct clk              *clks[SCI_NUM_CLKS];
> -       unsigned long           clk_rates[SCI_NUM_CLKS];
> -
> -       int                     irqs[SCIx_NR_IRQS];
> -       char                    *irqstr[SCIx_NR_IRQS];
> -
> -       struct dma_chan                 *chan_tx;
> -       struct dma_chan                 *chan_rx;
> -
> -#ifdef CONFIG_SERIAL_SH_SCI_DMA
> -       struct dma_chan                 *chan_tx_saved;
> -       struct dma_chan                 *chan_rx_saved;
> -       dma_cookie_t                    cookie_tx;
> -       dma_cookie_t                    cookie_rx[2];
> -       dma_cookie_t                    active_rx;
> -       dma_addr_t                      tx_dma_addr;
> -       unsigned int                    tx_dma_len;
> -       struct scatterlist              sg_rx[2];
> -       void                            *rx_buf[2];
> -       size_t                          buf_len_rx;
> -       struct work_struct              work_tx;
> -       struct hrtimer                  rx_timer;
> -       unsigned int                    rx_timeout;     /* microseconds */
> -#endif
> -       unsigned int                    rx_frame;
> -       int                             rx_trigger;
> -       struct timer_list               rx_fifo_timer;
> -       int                             rx_fifo_timeout;
> -       u16                             hscif_tot;
> -
> -       bool has_rtscts;
> -       bool autorts;
> -       bool tx_occurred;
> -};
> -
>  #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
>
>  static struct sci_port sci_ports[SCI_NPORTS];
>  static unsigned long sci_ports_in_use;
>  static struct uart_driver sci_uart_driver;
>
> -static inline struct sci_port *
> -to_sci_port(struct uart_port *uart)
> -{
> -       return container_of(uart, struct sci_port, port);
> -}
> +static const struct sci_port_params_bits sci_sci_port_params_bits = {
> +       .rxtx_enable = SCSCR_RE | SCSCR_TE,
> +       .te_clear = SCSCR_TE | SCSCR_TEIE,
> +       .poll_sent_bits = SCI_FER | SCI_TEND
> +};
> +
> +static const struct sci_port_params_bits sci_scix_port_params_bits = {
> +       .rxtx_enable = SCSCR_RE | SCSCR_TE,
> +       .te_clear = SCSCR_TE | SCSCR_TEIE,
> +       .poll_sent_bits = SCIF_TDFE | SCIF_TEND
> +};
> +
> +static const struct sci_common_regs sci_common_regs = {
> +       .status = SCxSR,
> +       .control = SCSCR,
> +};
>
>  static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>         /*
> @@ -192,6 +118,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(32),
>                 .error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER,
>                 .error_clear = SCI_ERROR_CLEAR & ~SCI_ORER,
> +               .param_bits = sci_sci_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -214,6 +142,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(32),
>                 .error_mask = SCI_DEFAULT_ERROR_MASK | SCI_ORER,
>                 .error_clear = SCI_ERROR_CLEAR & ~SCI_ORER,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -238,6 +168,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR_SCIFAB,
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER,
>                 .error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -263,6 +195,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR_SCIFAB,
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER,
>                 .error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -288,6 +222,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(32),
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK,
>                 .error_clear = SCIF_ERROR_CLEAR,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -316,6 +252,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(32),
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK,
>                 .error_clear = SCIF_ERROR_CLEAR,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -347,6 +285,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(32),
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK,
>                 .error_clear = SCIF_ERROR_CLEAR,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -369,6 +309,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(32),
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK,
>                 .error_clear = SCIF_ERROR_CLEAR,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -393,6 +335,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(32),
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK,
>                 .error_clear = SCIF_ERROR_CLEAR,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -420,6 +364,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(32),
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK,
>                 .error_clear = SCIF_ERROR_CLEAR,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -449,6 +395,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR_RANGE(8, 32),
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK,
>                 .error_clear = SCIF_ERROR_CLEAR,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -473,6 +421,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(32),
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK,
>                 .error_clear = SCIF_ERROR_CLEAR,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -500,6 +450,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(32),
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK,
>                 .error_clear = SCIF_ERROR_CLEAR,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>
>         /*
> @@ -523,6 +475,8 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
>                 .sampling_rate_mask = SCI_SR(16),
>                 .error_mask = SCIF_DEFAULT_ERROR_MASK | SCIFA_ORER,
>                 .error_clear = SCIF_ERROR_CLEAR & ~SCIFA_ORER,
> +               .param_bits = sci_scix_port_params_bits,
> +               .common_regs = &sci_common_regs,
>         },
>  };
>
> @@ -560,7 +514,7 @@ static void sci_serial_out(struct uart_port *p, int offset, int value)
>                 WARN(1, "Invalid register access\n");
>  }
>
> -static void sci_port_enable(struct sci_port *sci_port)
> +void sci_port_enable(struct sci_port *sci_port)
>  {
>         unsigned int i;
>
> @@ -576,7 +530,7 @@ static void sci_port_enable(struct sci_port *sci_port)
>         sci_port->port.uartclk = sci_port->clk_rates[SCI_FCK];
>  }
>
> -static void sci_port_disable(struct sci_port *sci_port)
> +void sci_port_disable(struct sci_port *sci_port)
>  {
>         unsigned int i;
>
> @@ -713,15 +667,16 @@ static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask)
>      defined(CONFIG_SERIAL_SH_SCI_EARLYCON)
>
>  #ifdef CONFIG_CONSOLE_POLL
> -static int sci_poll_get_char(struct uart_port *port)
> +int sci_poll_get_char(struct uart_port *port)
>  {
>         unsigned short status;
> +       struct sci_port *s = to_sci_port(port);
>         int c;
>
>         do {
>                 status = sci_serial_in(port, SCxSR);
>                 if (status & SCxSR_ERRORS(port)) {
> -                       sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
> +                       s->ops->clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
>                         continue;
>                 }
>                 break;
> @@ -734,7 +689,7 @@ static int sci_poll_get_char(struct uart_port *port)
>
>         /* Dummy read */
>         sci_serial_in(port, SCxSR);
> -       sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
> +       s->ops->clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
>
>         return c;
>  }
> @@ -742,14 +697,16 @@ static int sci_poll_get_char(struct uart_port *port)
>
>  static void sci_poll_put_char(struct uart_port *port, unsigned char c)
>  {
> -       unsigned short status;
> +       struct sci_port *s = to_sci_port(port);
> +       const struct sci_common_regs *regs = s->params->common_regs;
> +       unsigned int status;
>
>         do {
> -               status = sci_serial_in(port, SCxSR);
> +               status = s->ops->read_reg(port, regs->status);
>         } while (!(status & SCxSR_TDxE(port)));
>
>         sci_serial_out(port, SCxTDR, c);
> -       sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
> +       s->ops->clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
>  }
>  #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE ||
>           CONFIG_SERIAL_SH_SCI_EARLYCON */
> @@ -892,7 +849,7 @@ static void sci_transmit_chars(struct uart_port *port)
>                 port->icount.tx++;
>         } while (--count > 0);
>
> -       sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port));
> +       s->ops->clear_SCxSR(port, SCxSR_TDxE_CLEAR(port));
>
>         if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
>                 uart_write_wakeup(port);
> @@ -911,6 +868,7 @@ static void sci_transmit_chars(struct uart_port *port)
>  static void sci_receive_chars(struct uart_port *port)
>  {
>         struct tty_port *tport = &port->state->port;
> +       struct sci_port *s = to_sci_port(port);
>         int i, count, copied = 0;
>         unsigned short status;
>         unsigned char flag;
> @@ -965,7 +923,7 @@ static void sci_receive_chars(struct uart_port *port)
>                 }
>
>                 sci_serial_in(port, SCxSR); /* dummy read */
> -               sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
> +               s->ops->clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
>
>                 copied += count;
>                 port->icount.rx += count;
> @@ -978,16 +936,17 @@ static void sci_receive_chars(struct uart_port *port)
>                 /* TTY buffers full; read from RX reg to prevent lockup */
>                 sci_serial_in(port, SCxRDR);
>                 sci_serial_in(port, SCxSR); /* dummy read */
> -               sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
> +               s->ops->clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
>         }
>  }
>
>  static int sci_handle_errors(struct uart_port *port)
>  {
>         int copied = 0;
> -       unsigned short status = sci_serial_in(port, SCxSR);
> -       struct tty_port *tport = &port->state->port;
>         struct sci_port *s = to_sci_port(port);
> +       const struct sci_common_regs *regs = s->params->common_regs;
> +       unsigned int status = s->ops->read_reg(port, regs->status);
> +       struct tty_port *tport = &port->state->port;
>
>         /* Handle overruns */
>         if (status & s->params->overrun_mask) {
> @@ -1146,7 +1105,7 @@ static void rx_fifo_timer_fn(struct timer_list *t)
>         struct uart_port *port = &s->port;
>
>         dev_dbg(port->dev, "Rx timed out\n");
> -       scif_set_rtrg(port, 1);
> +       s->ops->set_rtrg(port, 1);
>  }
>
>  static ssize_t rx_fifo_trigger_show(struct device *dev,
> @@ -1171,9 +1130,9 @@ static ssize_t rx_fifo_trigger_store(struct device *dev,
>         if (ret)
>                 return ret;
>
> -       sci->rx_trigger = scif_set_rtrg(port, r);
> +       sci->rx_trigger = sci->ops->set_rtrg(port, r);
>         if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
> -               scif_set_rtrg(port, 1);
> +               sci->ops->set_rtrg(port, 1);
>
>         return count;
>  }
> @@ -1216,7 +1175,7 @@ static ssize_t rx_fifo_timeout_store(struct device *dev,
>                 sci->hscif_tot = r << HSSCR_TOT_SHIFT;
>         } else {
>                 sci->rx_fifo_timeout = r;
> -               scif_set_rtrg(port, 1);
> +               sci->ops->set_rtrg(port, 1);
>                 if (r > 0)
>                         timer_setup(&sci->rx_fifo_timer, rx_fifo_timer_fn, 0);
>         }
> @@ -1341,7 +1300,7 @@ static void sci_dma_rx_reenable_irq(struct sci_port *s)
>             s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
>                 enable_irq(s->irqs[SCIx_RXI_IRQ]);
>                 if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE)
> -                       scif_set_rtrg(port, s->rx_trigger);
> +                       s->ops->set_rtrg(port, s->rx_trigger);
>                 else
>                         scr &= ~SCSCR_RDRQE;
>         }
> @@ -1623,7 +1582,7 @@ static struct dma_chan *sci_request_dma_chan(struct uart_port *port,
>         return chan;
>  }
>
> -static void sci_request_dma(struct uart_port *port)
> +void sci_request_dma(struct uart_port *port)
>  {
>         struct sci_port *s = to_sci_port(port);
>         struct tty_port *tport = &port->state->port;
> @@ -1711,7 +1670,7 @@ static void sci_request_dma(struct uart_port *port)
>         }
>  }
>
> -static void sci_free_dma(struct uart_port *port)
> +void sci_free_dma(struct uart_port *port)
>  {
>         struct sci_port *s = to_sci_port(port);
>
> @@ -1721,7 +1680,7 @@ static void sci_free_dma(struct uart_port *port)
>                 sci_dma_rx_release(s);
>  }
>
> -static void sci_flush_buffer(struct uart_port *port)
> +void sci_flush_buffer(struct uart_port *port)
>  {
>         struct sci_port *s = to_sci_port(port);
>
> @@ -1750,11 +1709,11 @@ static void sci_dma_check_tx_occurred(struct sci_port *s)
>                 s->tx_occurred = true;
>  }
>  #else /* !CONFIG_SERIAL_SH_SCI_DMA */
> -static inline void sci_request_dma(struct uart_port *port)
> +inline void sci_request_dma(struct uart_port *port)
>  {
>  }
>
> -static inline void sci_free_dma(struct uart_port *port)
> +inline void sci_free_dma(struct uart_port *port)
>  {
>  }
>
> @@ -1762,7 +1721,9 @@ static void sci_dma_check_tx_occurred(struct sci_port *s)
>  {
>  }
>
> -#define sci_flush_buffer       NULL
> +inline void sci_flush_buffer(struct uart_port *port)
> +{
> +}
>  #endif /* !CONFIG_SERIAL_SH_SCI_DMA */
>
>  static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
> @@ -1780,7 +1741,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
>                     s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
>                         disable_irq_nosync(s->irqs[SCIx_RXI_IRQ]);
>                         if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE) {
> -                               scif_set_rtrg(port, 1);
> +                               s->ops->set_rtrg(port, 1);
>                                 scr |= SCSCR_RIE;
>                         } else {
>                                 scr |= SCSCR_RDRQE;
> @@ -1806,8 +1767,8 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
>  #endif
>
>         if (s->rx_trigger > 1 && s->rx_fifo_timeout > 0) {
> -               if (!scif_rtrg_enabled(port))
> -                       scif_set_rtrg(port, s->rx_trigger);
> +               if (!s->ops->rtrg_enabled(port))
> +                       s->ops->set_rtrg(port, s->rx_trigger);
>
>                 mod_timer(&s->rx_fifo_timer, jiffies + DIV_ROUND_UP(
>                           s->rx_frame * HZ * s->rx_fifo_timeout, 1000000));
> @@ -1817,7 +1778,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
>          * of whether the I_IXOFF is set, otherwise, how is the interrupt
>          * to be disabled?
>          */
> -       sci_receive_chars(port);
> +       s->ops->receive_chars(port);
>
>         return IRQ_HANDLED;
>  }
> @@ -1826,9 +1787,10 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
>  {
>         struct uart_port *port = ptr;
>         unsigned long flags;
> +       struct sci_port *s = to_sci_port(port);
>
>         uart_port_lock_irqsave(port, &flags);
> -       sci_transmit_chars(port);
> +       s->ops->transmit_chars(port);
>         uart_port_unlock_irqrestore(port, flags);
>
>         return IRQ_HANDLED;
> @@ -1837,16 +1799,19 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
>  static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr)
>  {
>         struct uart_port *port = ptr;
> +       struct sci_port *s = to_sci_port(port);
> +       const struct sci_common_regs *regs = s->params->common_regs;
>         unsigned long flags;
> -       unsigned short ctrl;
> +       u32 ctrl;
>
>         if (port->type != PORT_SCI)
>                 return sci_tx_interrupt(irq, ptr);
>
>         uart_port_lock_irqsave(port, &flags);
> -       ctrl = sci_serial_in(port, SCSCR);
> -       ctrl &= ~(SCSCR_TE | SCSCR_TEIE);
> -       sci_serial_out(port, SCSCR, ctrl);
> +       ctrl = s->ops->read_reg(port, regs->control);
> +
> +       ctrl &= ~(s->params->param_bits.te_clear);
> +       s->ops->write_reg(port, regs->control, ctrl);
>         uart_port_unlock_irqrestore(port, flags);
>
>         return IRQ_HANDLED;
> @@ -1855,6 +1820,7 @@ static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr)
>  static irqreturn_t sci_br_interrupt(int irq, void *ptr)
>  {
>         struct uart_port *port = ptr;
> +       struct sci_port *s = to_sci_port(port);
>
>         /* Handle BREAKs */
>         sci_handle_breaks(port);
> @@ -1862,7 +1828,7 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
>         /* drop invalid character received before break was detected */
>         sci_serial_in(port, SCxRDR);
>
> -       sci_clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
> +       s->ops->clear_SCxSR(port, SCxSR_BREAK_CLEAR(port));
>
>         return IRQ_HANDLED;
>  }
> @@ -1890,15 +1856,15 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr)
>                 if (sci_handle_errors(port)) {
>                         /* discard character in rx buffer */
>                         sci_serial_in(port, SCxSR);
> -                       sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
> +                       s->ops->clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
>                 }
>         } else {
>                 sci_handle_fifo_overrun(port);
>                 if (!s->chan_rx)
> -                       sci_receive_chars(port);
> +                       s->ops->receive_chars(port);
>         }
>
> -       sci_clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
> +       s->ops->clear_SCxSR(port, SCxSR_ERROR_CLEAR(port));
>
>         /* Kick the transmission */
>         if (!s->chan_tx)
> @@ -2059,7 +2025,7 @@ static int sci_request_irq(struct sci_port *port)
>         return ret;
>  }
>
> -static void sci_free_irq(struct sci_port *port)
> +void sci_free_irq(struct sci_port *port)
>  {
>         int i, j;
>
> @@ -2232,7 +2198,7 @@ static unsigned int sci_get_mctrl(struct uart_port *port)
>         return mctrl;
>  }
>
> -static void sci_enable_ms(struct uart_port *port)
> +void sci_enable_ms(struct uart_port *port)
>  {
>         mctrl_gpio_enable_ms(to_sci_port(port)->gpios);
>  }
> @@ -2268,7 +2234,17 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
>         uart_port_unlock_irqrestore(port, flags);
>  }
>
> -static int sci_startup(struct uart_port *port)
> +static void sci_shutdown_complete(struct uart_port *port)
> +{
> +       struct sci_port *s = to_sci_port(port);
> +       u16 scr;
> +
> +       scr = sci_serial_in(port, SCSCR);
> +       sci_serial_out(port, SCSCR,
> +                      scr & (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot));
> +}
> +
> +int sci_startup(struct uart_port *port)
>  {
>         struct sci_port *s = to_sci_port(port);
>         int ret;
> @@ -2291,7 +2267,6 @@ static void sci_shutdown(struct uart_port *port)
>  {
>         struct sci_port *s = to_sci_port(port);
>         unsigned long flags;
> -       u16 scr;
>
>         dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
>
> @@ -2301,13 +2276,7 @@ static void sci_shutdown(struct uart_port *port)
>         uart_port_lock_irqsave(port, &flags);
>         sci_stop_rx(port);
>         sci_stop_tx(port);
> -       /*
> -        * Stop RX and TX, disable related interrupts, keep clock source
> -        * and HSCIF TOT bits
> -        */
> -       scr = sci_serial_in(port, SCSCR);
> -       sci_serial_out(port, SCSCR,
> -                      scr & (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot));
> +       s->ops->shutdown_complete(port);
>         uart_port_unlock_irqrestore(port, flags);
>
>  #ifdef CONFIG_SERIAL_SH_SCI_DMA
> @@ -2383,9 +2352,9 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps,
>  }
>
>  /* calculate sample rate, BRR, and clock select */
> -static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
> -                         unsigned int *brr, unsigned int *srr,
> -                         unsigned int *cks)
> +int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
> +                  unsigned int *brr, unsigned int *srr,
> +                  unsigned int *cks)
>  {
>         unsigned long freq = s->clk_rates[SCI_FCK];
>         unsigned int sr, br, prediv, scrate, c;
> @@ -2462,9 +2431,9 @@ static void sci_reset(struct uart_port *port)
>         if (reg->size)
>                 sci_serial_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
>
> -       sci_clear_SCxSR(port,
> -                       SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) &
> -                       SCxSR_BREAK_CLEAR(port));
> +       s->ops->clear_SCxSR(port,
> +                           SCxSR_RDxF_CLEAR(port) & SCxSR_ERROR_CLEAR(port) &
> +                           SCxSR_BREAK_CLEAR(port));
>         if (sci_getreg(port, SCLSR)->size) {
>                 status = sci_serial_in(port, SCLSR);
>                 status &= ~(SCLSR_TO | SCLSR_ORER);
> @@ -2473,14 +2442,14 @@ static void sci_reset(struct uart_port *port)
>
>         if (s->rx_trigger > 1) {
>                 if (s->rx_fifo_timeout) {
> -                       scif_set_rtrg(port, 1);
> +                       s->ops->set_rtrg(port, 1);
>                         timer_setup(&s->rx_fifo_timer, rx_fifo_timer_fn, 0);
>                 } else {
>                         if (port->type == PORT_SCIFA ||
>                             port->type == PORT_SCIFB)
> -                               scif_set_rtrg(port, 1);
> +                               s->ops->set_rtrg(port, 1);
>                         else
> -                               scif_set_rtrg(port, s->rx_trigger);
> +                               s->ops->set_rtrg(port, s->rx_trigger);
>                 }
>         }
>  }
> @@ -2740,7 +2709,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
>                 sci_enable_ms(port);
>  }
>
> -static void sci_pm(struct uart_port *port, unsigned int state,
> +void sci_pm(struct uart_port *port, unsigned int state,
>                    unsigned int oldstate)
>  {
>         struct sci_port *sci_port = to_sci_port(port);
> @@ -2803,7 +2772,7 @@ static int sci_remap_port(struct uart_port *port)
>         return 0;
>  }
>
> -static void sci_release_port(struct uart_port *port)
> +void sci_release_port(struct uart_port *port)
>  {
>         struct sci_port *sport = to_sci_port(port);
>
> @@ -2815,7 +2784,7 @@ static void sci_release_port(struct uart_port *port)
>         release_mem_region(port->mapbase, sport->reg_size);
>  }
>
> -static int sci_request_port(struct uart_port *port)
> +int sci_request_port(struct uart_port *port)
>  {
>         struct resource *res;
>         struct sci_port *sport = to_sci_port(port);
> @@ -2837,7 +2806,7 @@ static int sci_request_port(struct uart_port *port)
>         return 0;
>  }
>
> -static void sci_config_port(struct uart_port *port, int flags)
> +void sci_config_port(struct uart_port *port, int flags)
>  {
>         if (flags & UART_CONFIG_TYPE) {
>                 struct sci_port *sport = to_sci_port(port);
> @@ -2847,7 +2816,7 @@ static void sci_config_port(struct uart_port *port, int flags)
>         }
>  }
>
> -static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
> +int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
>  {
>         if (ser->baud_base < 2400)
>                 /* No paper tape reader for Mitch.. */
> @@ -2856,6 +2825,18 @@ static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
>         return 0;
>  }
>
> +static u32 sci_get_ctrl_temp(struct uart_port *port, unsigned int ctrl)
> +{
> +       struct sci_port *s = to_sci_port(port);
> +       unsigned int ctrl_temp;
> +
> +       ctrl_temp = s->params->param_bits.rxtx_enable;
> +       ctrl_temp |=
> +               (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) |
> +               (ctrl & (SCSCR_CKE1 | SCSCR_CKE0));
> +       return ctrl_temp;
> +}
> +
>  static const struct uart_ops sci_uart_ops = {
>         .tx_empty       = sci_tx_empty,
>         .set_mctrl      = sci_set_mctrl,
> @@ -2881,6 +2862,19 @@ static const struct uart_ops sci_uart_ops = {
>  #endif
>  };
>
> +static const struct sci_port_ops sci_port_ops = {
> +       .read_reg               = sci_serial_in,
> +       .write_reg              = sci_serial_out,
> +       .receive_chars          = sci_receive_chars,
> +       .transmit_chars         = sci_transmit_chars,
> +       .poll_put_char          = sci_poll_put_char,
> +       .clear_SCxSR            = sci_clear_SCxSR,
> +       .set_rtrg               = scif_set_rtrg,
> +       .rtrg_enabled           = scif_rtrg_enabled,
> +       .shutdown_complete      = sci_shutdown_complete,
> +       .get_ctrl_temp          = sci_get_ctrl_temp,
> +};
> +
>  static int sci_init_clocks(struct sci_port *sci_port, struct device *dev)
>  {
>         const char *clk_names[] = {
> @@ -2974,6 +2968,7 @@ static int sci_init_single(struct platform_device *dev,
>         int ret;
>
>         sci_port->cfg   = p;
> +       sci_port->ops   = &sci_port_ops;
>
>         port->ops       = &sci_uart_ops;
>         port->iotype    = UPIO_MEM;
> @@ -3095,7 +3090,7 @@ static void sci_cleanup_single(struct sci_port *port)
>      defined(CONFIG_SERIAL_SH_SCI_EARLYCON)
>  static void serial_console_putchar(struct uart_port *port, unsigned char ch)
>  {
> -       sci_poll_put_char(port, ch);
> +       to_sci_port(port)->ops->poll_put_char(port, ch);
>  }
>
>  /*
> @@ -3107,7 +3102,9 @@ static void serial_console_write(struct console *co, const char *s,
>  {
>         struct sci_port *sci_port = &sci_ports[co->index];
>         struct uart_port *port = &sci_port->port;
> -       unsigned short bits, ctrl, ctrl_temp;
> +       const struct sci_common_regs *regs = sci_port->params->common_regs;
> +       unsigned int bits;
> +       u32 ctrl, ctrl_temp;
>         unsigned long flags;
>         int locked = 1;
>
> @@ -3119,21 +3116,22 @@ static void serial_console_write(struct console *co, const char *s,
>                 uart_port_lock_irqsave(port, &flags);
>
>         /* first save SCSCR then disable interrupts, keep clock source */
> -       ctrl = sci_serial_in(port, SCSCR);
> -       ctrl_temp = SCSCR_RE | SCSCR_TE |
> -                   (sci_port->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0)) |
> -                   (ctrl & (SCSCR_CKE1 | SCSCR_CKE0));
> -       sci_serial_out(port, SCSCR, ctrl_temp | sci_port->hscif_tot);
> +       ctrl = sci_port->ops->read_reg(port, regs->control);
> +       ctrl_temp = sci_port->ops->get_ctrl_temp(port, ctrl);
> +
> +       sci_port->ops->write_reg(port, regs->control, ctrl_temp | sci_port->hscif_tot);
>
>         uart_console_write(port, s, count, serial_console_putchar);
>
>         /* wait until fifo is empty and last bit has been transmitted */
> -       bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
> -       while ((sci_serial_in(port, SCxSR) & bits) != bits)
> +
> +       bits = sci_ports->params->param_bits.poll_sent_bits;
> +
> +       while ((sci_port->ops->read_reg(port, regs->status) & bits) != bits)
>                 cpu_relax();
>
>         /* restore the SCSCR */
> -       sci_serial_out(port, SCSCR, ctrl);
> +       sci_port->ops->write_reg(port, regs->control, ctrl);
>
>         if (locked)
>                 uart_port_unlock_irqrestore(port, flags);
> @@ -3268,7 +3266,6 @@ static void sci_remove(struct platform_device *dev)
>                 device_remove_file(&dev->dev, &dev_attr_rx_fifo_timeout);
>  }
>
> -
>  #define SCI_OF_DATA(type, regtype)     (void *)((type) << 16 | (regtype))
>  #define SCI_OF_TYPE(data)              ((unsigned long)(data) >> 16)
>  #define SCI_OF_REGTYPE(data)           ((unsigned long)(data) & 0xffff)
> @@ -3564,9 +3561,11 @@ sh_early_platform_init_buffer("earlyprintk", &sci_driver,
>  #ifdef CONFIG_SERIAL_SH_SCI_EARLYCON
>  static struct plat_sci_port port_cfg __initdata;
>
> -static int __init early_console_setup(struct earlycon_device *device,
> +int __init early_console_setup(struct earlycon_device *device,
>                                       int type)
>  {
> +       const struct sci_common_regs *regs;
> +
>         if (!device->port.membase)
>                 return -ENODEV;
>
> @@ -3574,10 +3573,14 @@ static int __init early_console_setup(struct earlycon_device *device,
>         memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port));
>         port_cfg.type = type;
>         sci_ports[0].cfg = &port_cfg;
> +       sci_ports[0].ops = &sci_port_ops;
>         sci_ports[0].params = sci_probe_regmap(&port_cfg);
> -       port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR);
> -       sci_serial_out(&sci_ports[0].port, SCSCR,
> -                      SCSCR_RE | SCSCR_TE | port_cfg.scscr);
> +       regs = sci_ports[0].params->common_regs;
> +
> +       port_cfg.scscr = sci_ports[0].ops->read_reg(&sci_ports[0].port, regs->control);
> +       sci_ports[0].ops->write_reg(&sci_ports[0].port,
> +                                   regs->control,
> +                                   sci_ports[0].params->param_bits.rxtx_enable | port_cfg.scscr);
>
>         device->con->write = serial_console_write;
>         return 0;
> diff --git a/drivers/tty/serial/sh-sci_common.h b/drivers/tty/serial/sh-sci_common.h
> new file mode 100644
> index 000000000000..cbfacdc1a836
> --- /dev/null
> +++ b/drivers/tty/serial/sh-sci_common.h
> @@ -0,0 +1,178 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef __SH_SCI_COMMON_H__
> +#define __SH_SCI_COMMON_H__
> +
> +#define SCI_MAJOR      204
> +#define SCI_MINOR_START        8
> +
> +#include <linux/serial_core.h>
> +
> +enum SCI_CLKS {
> +       SCI_FCK,                /* Functional Clock */
> +       SCI_SCK,                /* Optional External Clock */
> +       SCI_BRG_INT,            /* Optional BRG Internal Clock Source */
> +       SCI_SCIF_CLK,           /* Optional BRG External Clock Source */
> +       SCI_NUM_CLKS
> +};
> +
> +/* Offsets into the sci_port->irqs array */
> +enum {
> +       SCIx_ERI_IRQ,
> +       SCIx_RXI_IRQ,
> +       SCIx_TXI_IRQ,
> +       SCIx_BRI_IRQ,
> +       SCIx_DRI_IRQ,
> +       SCIx_TEI_IRQ,
> +       SCIx_NR_IRQS,
> +
> +       SCIx_MUX_IRQ = SCIx_NR_IRQS,    /* special case */
> +};
> +
> +/* Bit x set means sampling rate x + 1 is supported */
> +#define SCI_SR(x)              BIT((x) - 1)
> +
> +extern void sci_release_port(struct uart_port *port);
> +extern int sci_request_port(struct uart_port *port);
> +extern void sci_config_port(struct uart_port *port, int flags);
> +extern int sci_verify_port(struct uart_port *port, struct serial_struct *ser);
> +extern void sci_pm(struct uart_port *port, unsigned int state,
> +                  unsigned int oldstate);
> +extern void sci_enable_ms(struct uart_port *port);
> +
> +#ifdef CONFIG_CONSOLE_POLL
> +extern int sci_poll_get_char(struct uart_port *port);
> +extern void sci_poll_put_char(struct uart_port *port, unsigned char c);
> +#endif /* CONFIG_CONSOLE_POLL */
> +
> +struct plat_sci_reg {
> +       u8 offset, size;
> +};
> +
> +/* The actual number of needed registers depends on the sci controller;
> + * using this value as a max covers both sci and rsci cases
> + */
> +#define SCI_NR_REGS 20
> +
> +struct sci_port_params_bits {
> +       unsigned int rxtx_enable;
> +       unsigned int te_clear;
> +       unsigned int poll_sent_bits;
> +};
> +
> +struct sci_common_regs {
> +       unsigned int status;
> +       unsigned int control;
> +};
> +
> +struct sci_port_params {
> +       const struct plat_sci_reg regs[SCI_NR_REGS];
> +       const struct sci_common_regs *common_regs;
> +       unsigned int fifosize;
> +       unsigned int overrun_reg;
> +       unsigned int overrun_mask;
> +       unsigned int sampling_rate_mask;
> +       unsigned int error_mask;
> +       unsigned int error_clear;
> +       struct sci_port_params_bits param_bits;
> +};
> +
> +struct sci_port_ops {
> +       u32 (*read_reg)(struct uart_port *port, int reg);
> +       void (*write_reg)(struct uart_port *port, int reg, int value);
> +       void (*clear_SCxSR)(struct uart_port *port, unsigned int mask);
> +
> +       void (*transmit_chars)(struct uart_port *port);
> +       void (*receive_chars)(struct uart_port *port);
> +
> +       void (*poll_put_char)(struct uart_port *port, unsigned char c);
> +
> +       int (*set_rtrg)(struct uart_port *port, int rx_trig);
> +       int (*rtrg_enabled)(struct uart_port *port);
> +
> +       void (*shutdown_complete)(struct uart_port *port);
> +
> +       unsigned int (*get_ctrl_temp)(struct uart_port *port, unsigned int ctrl);
> +};
> +
> +struct sci_of_data {
> +       const struct sci_port_params *params;
> +       const struct uart_ops *uart_ops;
> +       const struct sci_port_ops *ops;
> +       unsigned short regtype;
> +       unsigned short type;
> +};
> +
> +struct sci_port {
> +       struct uart_port        port;
> +
> +       /* Platform configuration */
> +       const struct sci_port_params *params;
> +       const struct plat_sci_port *cfg;
> +
> +       unsigned int            sampling_rate_mask;
> +       resource_size_t         reg_size;
> +       struct mctrl_gpios      *gpios;
> +
> +       /* Clocks */
> +       struct clk              *clks[SCI_NUM_CLKS];
> +       unsigned long           clk_rates[SCI_NUM_CLKS];
> +
> +       int                     irqs[SCIx_NR_IRQS];
> +       char                    *irqstr[SCIx_NR_IRQS];
> +
> +       struct dma_chan                 *chan_tx;
> +       struct dma_chan                 *chan_rx;
> +
> +#ifdef CONFIG_SERIAL_SH_SCI_DMA
> +       struct dma_chan                 *chan_tx_saved;
> +       struct dma_chan                 *chan_rx_saved;
> +       dma_cookie_t                    cookie_tx;
> +       dma_cookie_t                    cookie_rx[2];
> +       dma_cookie_t                    active_rx;
> +       dma_addr_t                      tx_dma_addr;
> +       unsigned int                    tx_dma_len;
> +       struct scatterlist              sg_rx[2];
> +       void                            *rx_buf[2];
> +       size_t                          buf_len_rx;
> +       struct work_struct              work_tx;
> +       struct hrtimer                  rx_timer;
> +       unsigned int                    rx_timeout;     /* microseconds */
> +#endif
> +       unsigned int                    rx_frame;
> +       int                             rx_trigger;
> +       struct timer_list               rx_fifo_timer;
> +       int                             rx_fifo_timeout;
> +       u16                             hscif_tot;
> +
> +       const struct sci_port_ops *ops;
> +
> +       bool has_rtscts;
> +       bool autorts;
> +       bool tx_occurred;
> +};
> +
> +#define to_sci_port(uart) container_of((uart), struct sci_port, port)
> +
> +extern int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
> +                         unsigned int *brr, unsigned int *srr,
> +                         unsigned int *cks);
> +
> +extern void sci_port_disable(struct sci_port *sci_port);
> +extern void sci_port_enable(struct sci_port *sci_port);
> +
> +extern int sci_startup(struct uart_port *port);
> +extern void sci_free_irq(struct sci_port *port);
> +
> +extern void sci_request_dma(struct uart_port *port);
> +extern void sci_free_dma(struct uart_port *port);
> +extern void sci_flush_buffer(struct uart_port *port);
> +
> +#define min_sr(_port)          ffs((_port)->sampling_rate_mask)
> +#define max_sr(_port)          fls((_port)->sampling_rate_mask)
> +
> +#ifdef CONFIG_SERIAL_SH_SCI_EARLYCON
> +extern int __init early_console_setup(struct earlycon_device *device, int);
> +#endif
> +
> +#endif /* __SH_SCI_COMMON_H__ */
> --
> 2.43.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ