As part of the transition to arch/powerpc, this patch moves the mpc5200 PSC driver over to the OF platform bus infrastructure.
This patch is not acceptable for mainline as-is because it breaks arch/ppc support for the mpc52xx. More rework is needed to allow it to compile for either arch (or alternately, fork the driver) Signed-off-by: Grant Likely <[EMAIL PROTECTED]> --- drivers/serial/mpc52xx_uart.c | 146 +++++++++++++++++++++++++++++------------ 1 files changed, 105 insertions(+), 41 deletions(-) diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 29c9300..09bf8e0 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -42,7 +42,8 @@ * will be mapped to. */ -#include <linux/platform_device.h> +#define DEBUG + #include <linux/module.h> #include <linux/tty.h> #include <linux/serial.h> @@ -51,6 +52,7 @@ #include <linux/console.h> #include <asm/delay.h> #include <asm/io.h> +#include <asm/of_device.h> #include <asm/mpc52xx.h> #include <asm/mpc52xx_psc.h> @@ -371,7 +373,7 @@ mpc52xx_uart_verify_port(struct uart_por if ( (ser->irq != port->irq) || (ser->io_type != SERIAL_IO_MEM) || - (ser->baud_base != port->uartclk) || + (ser->baud_base != port->uartclk) || (ser->iomem_base != (void*)port->mapbase) || (ser->hub6 != 0 ) ) return -EINVAL; @@ -561,13 +563,13 @@ mpc52xx_console_get_options(struct uart_ struct mpc52xx_psc __iomem *psc = PSC(port); unsigned char mr1; + pr_debug("mpc52xx_console_get_options(port=%p)\n", port); /* Read the mode registers */ out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1); mr1 = in_8(&psc->mode); /* CT{U,L}R are write-only ! */ - *baud = __res.bi_baudrate ? - __res.bi_baudrate : CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; + *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; /* Parse them */ switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) { @@ -604,10 +606,10 @@ mpc52xx_console_write(struct console *co for (i = 0; i < count; i++, s++) { /* Line return handling */ if (*s == '\n') - out_8(&psc->mpc52xx_psc_buffer_8, '\r'); + out_8(&psc->buffer.buffer_8, '\r'); /* Send the char */ - out_8(&psc->mpc52xx_psc_buffer_8, *s); + out_8(&psc->buffer.buffer_8, *s); /* Wait the TX buffer to be empty */ j = 20000; /* Maximum wait */ @@ -624,33 +626,74 @@ static int __init mpc52xx_console_setup(struct console *co, char *options) { struct uart_port *port = &mpc52xx_uart_ports[co->index]; + struct device_node *np = NULL; + struct device_node *np_idx; + const void *pp = NULL; + struct resource res; + int index = 0; + int ret; int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; int bits = 8; int parity = 'n'; int flow = 'n'; - if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM) + pr_debug("mpc52xx_console_setup co=%p, options=%s, index=%i\n", + co, options, co->index); + + while ((np = of_find_compatible_node(np, "serial", "mpc52xx-psc"))) { + if (index == co->index) + break; + index++; + } + + if (!np) { + pr_debug("PSC%x not found in device tree\n", co->index); + return -EINVAL; + } + + /* Fetch register locations */ + if ((ret = of_address_to_resource(np, 0, &res)) != 0) { + pr_debug("Could not get resources for PSC%x\n", index); + return ret; + } + + /* Search for bus-frequency property in this node or a parent */ + np_idx = np; + while (np_idx) { + if ((pp = get_property(np_idx, "bus-frequency", NULL)) != NULL) + break; + np_idx = of_get_parent(np_idx); + } + if (!pp) { + pr_debug("Could not find bus-frequency property!\n"); return -EINVAL; + } /* Basic port init. Needed since we use some uart_??? func before * real init for early access */ spin_lock_init(&port->lock); - port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */ + port->uartclk = *(const u32*)pp / 2; port->ops = &mpc52xx_uart_ops; - port->mapbase = MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1)); + port->mapbase = res.start; + port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); + port->irq = irq_of_parse_and_map(np, 0); - /* We ioremap ourself */ - port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE); if (port->membase == NULL) return -EINVAL; + pr_debug("mpc52xx_psc at %lx mapped to %p; irq=%x freq=%i\n", + port->mapbase, port->membase, port->irq, port->uartclk); + /* Setup the port parameters accoding to options */ if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow); + pr_debug("Setting console parameters: %i %i%c1 flow=%c\n", + baud, bits, parity, flow); + return uart_set_options(port, co, baud, parity, bits, flow); } @@ -703,28 +746,26 @@ static struct uart_driver mpc52xx_uart_d /* ======================================================================== */ static int __devinit -mpc52xx_uart_probe(struct platform_device *dev) +mpc52xx_uart_probe(struct of_device *op, const struct of_device_id *match) { - struct resource *res = dev->resource; - + static int idx = 0; struct uart_port *port = NULL; - int i, idx, ret; + struct resource res; + int ret; + + printk("Got here!\n"); + dev_dbg(&op->dev, "mpc52xx_uart_probe(op=%p, match=%p)\n", op, match); /* Check validity & presence */ - idx = dev->id; - if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM) + if (idx >= MPC52xx_PSC_MAXNUM) return -EINVAL; - if (!mpc52xx_match_psc_function(idx,"uart")) - return -ENODEV; - /* Init the port structure */ port = &mpc52xx_uart_ports[idx]; memset(port, 0x00, sizeof(struct uart_port)); spin_lock_init(&port->lock); - port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */ port->fifosize = 512; port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF | @@ -733,29 +774,36 @@ mpc52xx_uart_probe(struct platform_devic port->ops = &mpc52xx_uart_ops; /* Search for IRQ and mapbase */ - for (i=0 ; i<dev->num_resources ; i++, res++) { - if (res->flags & IORESOURCE_MEM) - port->mapbase = res->start; - else if (res->flags & IORESOURCE_IRQ) - port->irq = res->start; - } - if (!port->irq || !port->mapbase) + if ((ret = of_address_to_resource(op->node, 0, &res)) != 0) + return ret; + + port->mapbase = res.start; + port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); + port->irq = irq_of_parse_and_map(op->node, 0); + + dev_dbg(&op->dev, "mpc52xx-psc UART at %lx. mapped to %p, irq %x\n", + port->mapbase, port->membase, port->irq); + + //if (!port->irq || !port->mapbase) { + if (!port->mapbase) { + printk(KERN_ERR "Could not allocate resources for PSC\n"); return -EINVAL; + } /* Add the port to the uart sub-system */ ret = uart_add_one_port(&mpc52xx_uart_driver, port); if (!ret) - platform_set_drvdata(dev, (void*)port); + dev_set_drvdata(&op->dev, (void*)port); + idx++; return ret; } static int -mpc52xx_uart_remove(struct platform_device *dev) +mpc52xx_uart_remove(struct of_device *op) { - struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev); - - platform_set_drvdata(dev, NULL); + struct uart_port *port = dev_get_drvdata(&op->dev); + dev_set_drvdata(&op->dev, NULL); if (port) uart_remove_one_port(&mpc52xx_uart_driver, port); @@ -787,7 +835,19 @@ mpc52xx_uart_resume(struct platform_devi } #endif -static struct platform_driver mpc52xx_uart_platform_driver = { +static struct of_device_id mpc52xx_uart_match[] = { + { + .name = "serial", + .compatible = "mpc52xx-psc", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, mpc52xx_uart_match); + +static struct of_platform_driver mpc52xx_uart_of_driver = { + .owner = THIS_MODULE, + .name = "mpc52xx-uart", + .match_table = mpc52xx_uart_match, .probe = mpc52xx_uart_probe, .remove = mpc52xx_uart_remove, #ifdef CONFIG_PM @@ -811,20 +871,24 @@ mpc52xx_uart_init(void) printk(KERN_INFO "Serial: MPC52xx PSC driver\n"); - ret = uart_register_driver(&mpc52xx_uart_driver); - if (ret == 0) { - ret = platform_driver_register(&mpc52xx_uart_platform_driver); - if (ret) - uart_unregister_driver(&mpc52xx_uart_driver); + if ((ret = uart_register_driver(&mpc52xx_uart_driver)) != 0) { + printk(KERN_ERR "Could not register mpc52xx uart driver\n"); + return ret; } - return ret; + if ((ret = of_register_driver(&mpc52xx_uart_of_driver)) != 0) { + printk(KERN_ERR "Could not register mpc52xx of driver\n"); + uart_unregister_driver(&mpc52xx_uart_driver); + return ret; + } + + return 0; } static void __exit mpc52xx_uart_exit(void) { - platform_driver_unregister(&mpc52xx_uart_platform_driver); + of_unregister_driver(&mpc52xx_uart_of_driver); uart_unregister_driver(&mpc52xx_uart_driver); } -- 1.4.3.rc2.g0503 _______________________________________________ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded