All of lore.kernel.org
 help / color / mirror / Atom feed
From: Russell King <rmk+lkml@arm.linux.org.uk>
To: Pantelis Antoniou <pantelis@embeddedalley.com>
Cc: linux-kernel@vger.kernel.org, cw@f00f.org,
	Pete Popov <ppopov@embeddedalley.com>,
	Matt Porter <mporter@embeddedalley.com>
Subject: Re: [PATCH] Au1x00 8250 uart support.
Date: Tue, 20 Sep 2005 17:37:49 +0100	[thread overview]
Message-ID: <20050920163748.GA6680@flint.arm.linux.org.uk> (raw)
In-Reply-To: <200509192340.10450.pantelis@embeddedalley.com>

On Mon, Sep 19, 2005 at 11:40:10PM +0300, Pantelis Antoniou wrote:
> diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
> --- a/drivers/serial/8250.c
> +++ b/drivers/serial/8250.c
> @@ -249,10 +249,42 @@ static const struct serial8250_config ua
>  		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
>  		.flags		= UART_CAP_FIFO | UART_CAP_UUE,
>  	},
> +	[PORT_AU1X00] = {
> +		.name		= "Au1x00",
> +		.fifo_size	= 16,
> +		.tx_loadsz	= 16,
> +		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
> +		.flags		= UART_CAP_FIFO | UART_CAP_NOMSR,
> +	},
> +};
> +
> +#ifdef CONFIG_SERIAL_8250_AU1X00
> +static const u8 au_io_in_map[] = {
> +	[UART_RX]  = 0,
> +	[UART_IER] = 2,
> +	[UART_IIR] = 3,
> +	[UART_LCR] = 5,
> +	[UART_MCR] = 6,
> +	[UART_LSR] = 7,
> +	[UART_MSR] = 8,
>  };
>  
> +static const u8 au_io_out_map[] = {
> +	[UART_TX]  = 1,
> +	[UART_IER] = 2,
> +	[UART_FCR] = 4,
> +	[UART_LCR] = 5,
> +	[UART_MCR] = 6,
> +};
> +#endif
> +
>  static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
>  {
> +#ifdef CONFIG_SERIAL_8250_AU1X00
> +	if (up->port.iotype == UPIO_AU)
> +		offset = au_io_in_map[offset];
> +#endif
> +
>  	offset <<= up->port.regshift;
>  
>  	switch (up->port.iotype) {
> @@ -266,6 +298,11 @@ static _INLINE_ unsigned int serial_in(s
>  	case UPIO_MEM32:
>  		return readl(up->port.membase + offset);
>  
> +#ifdef CONFIG_SERIAL_8250_AU1X00
> +	case UPIO_AU:
> +		return __raw_readl(up->port.membase + offset);
> +#endif
> +

At some point, we probably want to make this non-AU1x00 specific, but
it may as well wait until someone else has such quirkyness themselves.
It would be nice to pass the maps in somehow, but that's a fair re-jig
of the interfaces to other chunks of code elsewhere in the kernel tree.
Therefore, I think it's a change we should not make until there's a
reason to make it.

>  	default:
>  		return inb(up->port.iobase + offset);
>  	}
> @@ -274,6 +311,11 @@ static _INLINE_ unsigned int serial_in(s
>  static _INLINE_ void
>  serial_out(struct uart_8250_port *up, int offset, int value)
>  {
> +#ifdef CONFIG_SERIAL_8250_AU1X00
> +	if (up->port.iotype == UPIO_AU)
> +		offset = au_io_out_map[offset];
> +#endif
> +
>  	offset <<= up->port.regshift;
>  
>  	switch (up->port.iotype) {
> @@ -290,6 +332,12 @@ serial_out(struct uart_8250_port *up, in
>  		writel(value, up->port.membase + offset);
>  		break;
>  
> +#ifdef CONFIG_SERIAL_8250_AU1X00
> +	case UPIO_AU:
> +		__raw_writel(value, up->port.membase + offset);
> +		break;
> +#endif
> +
>  	default:
>  		outb(value, up->port.iobase + offset);
>  	}
> @@ -910,6 +958,15 @@ static void autoconfig(struct uart_8250_
>  		}
>  	}
>  #endif
> +
> +#ifdef CONFIG_SERIAL_8250_AU1X00
> +	/* if access method is AU, it is a AU */
> +	if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) {
> +		up->port.type = PORT_AU1X00;

I don't really see the need for a new port type - it's a quirky
16550A with a silly register layout.

> +		up->capabilities |= UART_CAP_NOMSR;	/* to stop whine */

Since this is for a hardware quirk, this should be UART_BUG_xxx not
UART_CAP_xxx - it's not a capability as such.

> +	}
> +#endif
> +
>  	serial_outp(up, UART_LCR, save_lcr);
>  
>  	if (up->capabilities != uart_config[up->port.type].flags) {
> @@ -1057,6 +1114,10 @@ static void serial8250_enable_ms(struct 
>  {
>  	struct uart_8250_port *up = (struct uart_8250_port *)port;
>  
> +	/* no MSR capabilities */
> +	if (up->capabilities & UART_CAP_NOMSR)

ditto.

> +		return;
> +
>  	up->ier |= UART_IER_MSI;
>  	serial_out(up, UART_IER, up->ier);
>  }
> @@ -1774,7 +1835,7 @@ serial8250_set_termios(struct uart_port 
>  	 * CTS flow control flag and modem status interrupts
>  	 */
>  	up->ier &= ~UART_IER_MSI;
> -	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
> +	if (!(up->capabilities & UART_CAP_NOMSR) && UART_ENABLE_MS(&up->port, termios->c_cflag))

ditto.

>  		up->ier |= UART_IER_MSI;
>  	if (up->capabilities & UART_CAP_UUE)
>  		up->ier |= UART_IER_UUE | UART_IER_RTOIE;
> diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
> --- a/drivers/serial/8250.h
> +++ b/drivers/serial/8250.h
> @@ -46,6 +46,7 @@ struct serial8250_config {
>  #define UART_CAP_SLEEP	(1 << 10)	/* UART has IER sleep */
>  #define UART_CAP_AFE	(1 << 11)	/* MCR-based hw flow control */
>  #define UART_CAP_UUE	(1 << 12)	/* UART needs IER bit 6 set (Xscale) */
> +#define UART_CAP_NOMSR	(1 << 13)	/* UART has no modem status bits (Au1x00) */

ditto.

>  
>  #define UART_BUG_QUOT	(1 << 0)	/* UART has buggy quot LSB */
>  #define UART_BUG_TXEN	(1 << 1)	/* UART has buggy TX IIR status */
> diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/serial/8250_au1x00.c
> @@ -0,0 +1,95 @@
> +/*
> + * Serial Device Initialisation for Au1x00
> + *
> + * (C) Copyright Embedded Alley Solutions, Inc 2005
> + * Author: Pantelis Antoniou <pantelis@embeddedalley.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/ioport.h>
> +#include <linux/module.h>
> +#include <linux/serial_core.h>
> +#include <linux/signal.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +
> +#include <linux/serial_8250.h>
> +
> +#include <asm/mach-au1x00/au1000.h>
> +
> +#include "8250.h"
> +
> +#define PORT(_base, _irq)				\
> +	{						\
> +		.iobase		= _base,		\
> +		.membase	= (void __iomem *)_base,\
> +		.mapbase	= _base,		\
> +		.irq		= _irq,			\
> +		.uartclk	= 0,	/* filled */	\
> +		.regshift	= 2,			\
> +		.iotype		= UPIO_AU,		\
> +		.flags		= UPF_SKIP_TEST | 	\
> +				  UPF_IOREMAP,		\
> +	}
> +
> +static struct plat_serial8250_port au1x00_data[] = {
> +#if defined(CONFIG_SOC_AU1000)
> +	PORT(UART0_ADDR, AU1000_UART0_INT),
> +	PORT(UART1_ADDR, AU1000_UART1_INT),
> +	PORT(UART2_ADDR, AU1000_UART2_INT),
> +	PORT(UART3_ADDR, AU1000_UART3_INT),
> +#elif defined(CONFIG_SOC_AU1500)
> +	PORT(UART0_ADDR, AU1500_UART0_INT),
> +	PORT(UART3_ADDR, AU1500_UART3_INT),
> +#elif defined(CONFIG_SOC_AU1100)
> +	PORT(UART0_ADDR, AU1100_UART0_INT),
> +	PORT(UART1_ADDR, AU1100_UART1_INT),
> +	PORT(UART2_ADDR, AU1100_UART2_INT),
> +	PORT(UART3_ADDR, AU1100_UART3_INT),
> +#elif defined(CONFIG_SOC_AU1550)
> +	PORT(UART0_ADDR, AU1550_UART0_INT),
> +	PORT(UART1_ADDR, AU1550_UART1_INT),
> +	PORT(UART2_ADDR, AU1550_UART2_INT),
> +	PORT(UART3_ADDR, AU1550_UART3_INT),
> +#elif defined(CONFIG_SOC_AU1200)
> +	PORT(UART0_ADDR, AU1200_UART0_INT),
> +	PORT(UART1_ADDR, AU1200_UART1_INT),
> +#endif
> +	{ },
> +};
> +
> +static struct platform_device au1x00_device = {
> +	.name			= "serial8250",
> +	.id			= PLAT8250_DEV_AU1X00,
> +	.dev			= {
> +		.platform_data	= au1x00_data,
> +	},
> +};
> +
> +static int __init au1x00_init(void)
> +{
> +	int i;
> +	unsigned int uartclk;
> +
> +	/* get uart clock */
> +	uartclk = get_au1x00_uart_baud_base() * 16;
> +
> +	/* fill up uartclk */
> +	for (i = 0; au1x00_data[i].flags ; i++)
> +		au1x00_data[i].uartclk = uartclk;
> +
> +	return platform_device_register(&au1x00_device);

This seems to be capable of being a modular, yet it's registering a
static platform device structure, which will cause an oops if this
module is force-unloaded.  Should it always be built in?

> +}
> +
> +module_init(au1x00_init);
> +
> +MODULE_AUTHOR("Pantelis Antoniou <pantelis@embeddedalley.com>");
> +MODULE_DESCRIPTION("8250 serial probe module for Au1x000 cards");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -207,6 +207,14 @@ config SERIAL_8250_ACORN
>  	  system, say Y to this option.  The driver can handle 1, 2, or 3 port
>  	  cards.  If unsure, say N.
>  
> +config SERIAL_8250_AU1X00
> +	tristate "AU1X00 serial port support"
> +	depends on SOC_AU1X00 && SERIAL_8250
> +	help
> +	  If you have an Au1x00 board and want to use the serial port, say Y
> +	  to this option.  The driver can handle 1 or 2 serial ports.
> +	  If unsure, say N.
> +
>  comment "Non-8250 serial port support"
>  
>  config SERIAL_AMBA_PL010
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -22,6 +22,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250
>  obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
>  obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
>  obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
> +obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o
>  obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
>  obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
>  obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
> diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
> --- a/drivers/serial/serial_core.c
> +++ b/drivers/serial/serial_core.c
> @@ -1960,6 +1960,7 @@ uart_report_port(struct uart_driver *drv
>  		break;
>  	case UPIO_MEM:
>  	case UPIO_MEM32:
> +	case UPIO_AU:
>  		snprintf(address, sizeof(address),
>  			 "MMIO 0x%lx", port->mapbase);
>  		break;
> diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
> --- a/include/linux/serial_8250.h
> +++ b/include/linux/serial_8250.h
> @@ -42,6 +42,7 @@ enum {
>  	PLAT8250_DEV_BOCA,
>  	PLAT8250_DEV_HUB6,
>  	PLAT8250_DEV_MCA,
> +	PLAT8250_DEV_AU1X00,
>  };
>  
>  /*
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -39,7 +39,8 @@
>  #define PORT_RSA	13
>  #define PORT_NS16550A	14
>  #define PORT_XSCALE	15
> -#define PORT_MAX_8250	15	/* max port ID */
> +#define PORT_AU1X00	16
> +#define PORT_MAX_8250	16	/* max port ID */
>  
>  /*
>   * ARM specific type numbers.  These are not currently guaranteed
> @@ -209,6 +210,7 @@ struct uart_port {
>  #define UPIO_HUB6		(1)
>  #define UPIO_MEM		(2)
>  #define UPIO_MEM32		(3)
> +#define UPIO_AU			(4)			/* Au1x00 type IO */
>  
>  	unsigned int		read_status_mask;	/* driver specific */
>  	unsigned int		ignore_status_mask;	/* driver specific */


-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core

  parent reply	other threads:[~2005-09-20 16:37 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-19 20:40 [PATCH] Au1x00 8250 uart support Pantelis Antoniou
2005-09-19 20:44 ` Christoph Hellwig
2005-09-19 20:53   ` Pantelis Antoniou
2005-09-19 20:58     ` Chris Wedgwood
2005-09-20 16:37 ` Russell King [this message]
2005-09-20 17:50   ` [PATCH] Au1x00 8250 uart support (Updated) Pantelis Antoniou
2005-09-21  7:11     ` Russell King
2005-09-21 16:14       ` [PATCH] Au1x00 8250 uart support (Updated - take #2) Pantelis Antoniou
2005-09-21 19:17         ` Russell King
2005-09-21 19:36           ` [PATCH] Au1x00 8250 uart support (Updated - take #3) Pantelis Antoniou
2005-09-22 19:11           ` [PATCH] Au1x00 8250 uart support (Updated - take #4) Pantelis Antoniou
2005-11-06  8:44             ` Russell King
2005-11-06  9:02               ` Pantelis Antoniou
2005-11-06  9:07                 ` Russell King

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=20050920163748.GA6680@flint.arm.linux.org.uk \
    --to=rmk+lkml@arm.linux.org.uk \
    --cc=cw@f00f.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mporter@embeddedalley.com \
    --cc=pantelis@embeddedalley.com \
    --cc=ppopov@embeddedalley.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.