Subject: Re: [RFC] powerpc: experimental of serial port driver

From: Benjamin Herrenschmidt <[email-masked]>
Date: Fri, 08 Dec 2006 15:43:38 +1100

On Thu, 2006-12-07 at 21:40 +0100, Arnd Bergmann wrote:
> This can be used for serial ports that are connected to an
> OF platform bus. This is independent of whether they also
> get detected as legacy_serial devices during early boot,
> because the serial core makes sure it handles multiple
> registrations fine.
> 
> It should be generic enough to work for more than just
> 8250 style devices, but those are the only ones I tested
> so far.
> 
> Signed-off-by: Arnd Bergmann <[email-masked]>

I'd rather call it 8250_of.c and have it be specific to 8250's.

Ben.

> Index: linux-2.6/drivers/serial/Makefile
> ===================================================================
> --- linux-2.6.orig/drivers/serial/Makefile
> +++ linux-2.6/drivers/serial/Makefile
> @@ -56,3 +56,4 @@ obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_se
>  obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
>  obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
>  obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
> +obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
> Index: linux-2.6/drivers/serial/of_serial.c
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/serial/of_serial.c
> @@ -0,0 +1,141 @@
> +/*
> + *  Serial Port driver for Open Firmware platform devices
> + *
> + *    Copyright (C) 2006 Arnd Bergmann <[email-masked]>, IBM Corp.
> + *
> + *  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/init.h>
> +#include <linux/module.h>
> +#include <linux/serial_core.h>
> +#include <linux/serial_8250.h>
> +
> +#include <asm/of_platform.h>
> +#include <asm/prom.h>
> +
> +/*
> + * Fill a struct uart_port for a given device node
> + */
> +static int __devinit of_platform_serial_setup(struct of_device *ofdev,
> +					int type, struct uart_port *port)
> +{
> +	struct resource resource;
> +	struct device_node *np = ofdev->node;
> +	const unsigned int *clk, *spd;
> +	int ret;
> +
> +	memset(port, 0, sizeof *port);
> +	spd = get_property(np, "current-speed", NULL);
> +	clk = get_property(np, "clock-frequency", NULL);
> +	if (!clk) {
> +		dev_warn(&ofdev->dev, "no clock-frequency property set\n");
> +		return -ENODEV;
> +	}
> +
> +	ret = of_address_to_resource(np, 0, &resource);
> +	if (ret) {
> +		dev_warn(&ofdev->dev, "invalid address\n");
> +		return ret;
> +	}
> +
> +	spin_lock_init(&port->lock);
> +	port->mapbase = resource.start;
> +	port->irq = irq_of_parse_and_map(np, 0);
> +	port->iotype = UPIO_MEM;
> +	port->type = type;
> +	port->uartclk = *clk;
> +	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP;
> +	port->dev = &ofdev->dev;
> +/*	if (spd) // FIXME: how to set?
> +		port->speed = spd;
> +*/
> +	return 0;
> +}
> +
> +/*
> + * Try to register a serial port
> + */
> +static int __devinit of_platform_serial_probe(struct of_device *ofdev,
> +						const struct of_device_id *id)
> +{
> +	struct uart_port port;
> +	int port_type;
> +	int ret;
> +
> +	port_type = (unsigned long)id->data;
> +	ret = of_platform_serial_setup(ofdev, port_type, &port);
> +	if (ret)
> +		goto out;
> +
> +	switch (port_type) {
> +	case PORT_UNKNOWN:
> +		dev_info(&ofdev->dev, "Unknown serial port found, "
> +			"attempting to use 8250 driver\n");
> +		/* fallthrough */
> +	case PORT_8250 ... PORT_MAX_8250:
> +		ret = serial8250_register_port(&port);
> +		break;
> +	default:
> +		/* need to add code for these */
> +		ret = -ENODEV;
> +		break;
> +	}
> +	if (ret < 0)
> +		goto out;
> +
> +	ofdev->dev.driver_data = (void *)(unsigned long)ret;
> +	return 0;
> +out:
> +	irq_dispose_mapping(port.irq);
> +	return ret;
> +}
> +
> +/*
> + * Release a line
> + */
> +static int of_platform_serial_remove(struct of_device *ofdev)
> +{
> +	int line = (unsigned long)ofdev->dev.driver_data;
> +	serial8250_unregister_port(line);
> +	return 0;
> +}
> +
> +/*
> + * A few common types, add more as needed.
> + */
> +static struct of_device_id __devinitdata of_platform_serial_table[] = {
> +	{ .type = "serial", .compatible = "ns8250",   .data = (void *)PORT_8250, },
> +	{ .type = "serial", .compatible = "ns16450",  .data = (void *)PORT_16450, },
> +	{ .type = "serial", .compatible = "ns16550",  .data = (void *)PORT_16550, },
> +	{ .type = "serial", .compatible = "ns16750",  .data = (void *)PORT_16750, },
> +	{ .type = "serial",			      .data = (void *)PORT_UNKNOWN, },
> +	{ /* end of list */ },
> +};
> +
> +static struct of_platform_driver __devinitdata of_platform_serial_driver = {
> +	.owner = THIS_MODULE,
> +	.name = "of_serial",
> +	.probe = of_platform_serial_probe,
> +	.remove = of_platform_serial_remove,
> +	.match_table = of_platform_serial_table,
> +};
> +
> +static int __init of_platform_serial_init(void)
> +{
> +	return of_register_platform_driver(&of_platform_serial_driver);
> +}
> +module_init(of_platform_serial_init);
> +
> +static void __exit of_platform_serial_exit(void)
> +{
> +	return of_unregister_platform_driver(&of_platform_serial_driver);
> +};
> +module_exit(of_platform_serial_exit);
> +
> +MODULE_AUTHOR("Arnd Bergmann <[email-masked]>");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("Serial Port driver for Open Firmware platform devices");
> Index: linux-2.6/drivers/serial/Kconfig
> ===================================================================
> --- linux-2.6.orig/drivers/serial/Kconfig
> +++ linux-2.6/drivers/serial/Kconfig
> @@ -965,4 +965,14 @@ config SERIAL_NETX_CONSOLE
>  	  If you have enabled the serial port on the Motorola IMX
>  	  CPU you can make it the console by answering Y to this option.
>  
> +config SERIAL_OF_PLATFORM
> +	tristate "Serial port on Open Firmware platform bus"
> +	depends on PPC_OF
> +	depends on SERIAL_8250
> +	help
> +	  If you have a PowerPC based system that has serial ports
> +	  on a platform specific bus, you should enable this option.
> +	  Currently, only 8250 compatible ports are supported, but
> +	  others can easily be added.
> +
>  endmenu
> _______________________________________________
> Linuxppc-dev mailing list
> [email-masked]
> https://ozlabs.org/mailman/listinfo/linuxppc-dev