Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752990AbbG3RqL (ORCPT ); Thu, 30 Jul 2015 13:46:11 -0400 Received: from down.free-electrons.com ([37.187.137.238]:46073 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750926AbbG3RqJ (ORCPT ); Thu, 30 Jul 2015 13:46:09 -0400 Date: Thu, 30 Jul 2015 19:46:05 +0200 From: Alexandre Belloni To: Cyrille Pitchen Cc: nicolas.ferre@atmel.com, gregkh@linuxfoundation.org, linux-serial@vger.kernel.org, egtvedt@samfundet.no, andriy.shevchenko@linux.intel.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: Re: [PATCH linux-next 1/1] tty/serial: at91: fix I/O accesses on RHR and THR for AVR32 Message-ID: <20150730174605.GE27985@piout.net> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5560 Lines: 155 On 30/07/2015 at 16:33:38 +0200, Cyrille Pitchen wrote : > This patch fixes I/O accesses on the Receiver Holding Register and on the > Transmitter Holding Register. Indeed AVR32 can only perform 32bit I/O > accesses on registers: using 8bit I/O accesses would read or write garbage > data. > > Fixes: commit b5199d468177 ("tty/serial: at91: add support to FIFOs") > Signed-off-by: Cyrille Pitchen Acked-by: Alexandre Belloni Also, tested on at91rm9200ek. > --- > Hi all, > > this patch fixes a bug on AVR32 introduced by the support of FIFOs for > AT91. Indeed when FIFOs are enabled they work in Multiple Data mode. > The Multiple Data mode allows to read up to 4 data from the Receiver > Holding Register (RHR) or write up to 4 data into the Transmitter Holding > Register (THR) in a single I/O access. Hence when only one data is to be > read from the RHR or written into the THR, the driver cannot use 32bit I/O > access anymore but must use 8bit I/O access instead. > > For ARM-base AT91 SoCs, 8bit I/O accesses can always be used even when > FIFOs are not available. However AV32 can only use 32bit I/O accesses. > > Since atmel_uart_readb(), resp. atmel_uart_writeb(), was created by the > FIFO support patch to access the RHR, resp. the THR, this patch replaces > it by atmel_uart_read_char(), resp. atmel_uart_write_char(). Hence the > actual width of the I/O access now depends only on the architecture. > > All registers but RHR and THR use 32bit I/O accesses. > > This patch was tested on a at91sam9260ek board. > > Best Regards, > > Cyrille > > ChangeLog: > > v1: initial version > > drivers/tty/serial/atmel_serial.c | 37 +++++++++++++++++++++++++++---------- > 1 file changed, 27 insertions(+), 10 deletions(-) > > diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c > index e91b3b2f0590..5ca5cf3e9359 100644 > --- a/drivers/tty/serial/atmel_serial.c > +++ b/drivers/tty/serial/atmel_serial.c > @@ -204,16 +204,33 @@ static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value) > __raw_writel(value, port->membase + reg); > } > > -static inline u8 atmel_uart_readb(struct uart_port *port, u32 reg) > +#ifdef CONFIG_AVR32 > + > +/* AVR32 cannot handle 8 or 16bit I/O accesses but only 32bit I/O accesses */ > +static inline u8 atmel_uart_read_char(struct uart_port *port) > +{ > + return __raw_readl(port->membase + ATMEL_US_RHR); > +} > + > +static inline void atmel_uart_write_char(struct uart_port *port, u8 value) > { > - return __raw_readb(port->membase + reg); > + __raw_writel(value, port->membase + ATMEL_US_THR); > } > > -static inline void atmel_uart_writeb(struct uart_port *port, u32 reg, u8 value) > +#else > + > +static inline u8 atmel_uart_read_char(struct uart_port *port) > { > - __raw_writeb(value, port->membase + reg); > + return __raw_readb(port->membase + ATMEL_US_RHR); > } > > +static inline void atmel_uart_write_char(struct uart_port *port, u8 value) > +{ > + __raw_writeb(value, port->membase + ATMEL_US_THR); > +} > + > +#endif > + > #ifdef CONFIG_SERIAL_ATMEL_PDC > static bool atmel_use_pdc_rx(struct uart_port *port) > { > @@ -658,7 +675,7 @@ static void atmel_rx_chars(struct uart_port *port) > > status = atmel_uart_readl(port, ATMEL_US_CSR); > while (status & ATMEL_US_RXRDY) { > - ch = atmel_uart_readb(port, ATMEL_US_RHR); > + ch = atmel_uart_read_char(port); > > /* > * note that the error handling code is > @@ -709,7 +726,7 @@ static void atmel_tx_chars(struct uart_port *port) > > if (port->x_char && > (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) { > - atmel_uart_writeb(port, ATMEL_US_THR, port->x_char); > + atmel_uart_write_char(port, port->x_char); > port->icount.tx++; > port->x_char = 0; > } > @@ -718,7 +735,7 @@ static void atmel_tx_chars(struct uart_port *port) > > while (atmel_uart_readl(port, ATMEL_US_CSR) & > atmel_port->tx_done_mask) { > - atmel_uart_writeb(port, ATMEL_US_THR, xmit->buf[xmit->tail]); > + atmel_uart_write_char(port, xmit->buf[xmit->tail]); > xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); > port->icount.tx++; > if (uart_circ_empty(xmit)) > @@ -2294,7 +2311,7 @@ static int atmel_poll_get_char(struct uart_port *port) > while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY)) > cpu_relax(); > > - return atmel_uart_readb(port, ATMEL_US_RHR); > + return atmel_uart_read_char(port); > } > > static void atmel_poll_put_char(struct uart_port *port, unsigned char ch) > @@ -2302,7 +2319,7 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch) > while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY)) > cpu_relax(); > > - atmel_uart_writeb(port, ATMEL_US_THR, ch); > + atmel_uart_write_char(port, ch); > } > #endif > > @@ -2409,7 +2426,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch) > { > while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY)) > cpu_relax(); > - atmel_uart_writeb(port, ATMEL_US_THR, ch); > + atmel_uart_write_char(port, ch); > } > > /* > -- > 1.8.2.2 > -- Alexandre Belloni, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/