From: Sylvain Munaut All Freescale MPC52xx related code now use new constants and the platform bus for it's driver. This patch makes this driver make use of that. Signed-off-by: Sylvain Munaut Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton --- 25-akpm/drivers/serial/mpc52xx_uart.c | 189 +++++++++++++++------------------- 1 files changed, 86 insertions(+), 103 deletions(-) diff -puN drivers/serial/mpc52xx_uart.c~serial-update-mpc52xx_uartc-to-use-platform-bus drivers/serial/mpc52xx_uart.c --- 25/drivers/serial/mpc52xx_uart.c~serial-update-mpc52xx_uartc-to-use-platform-bus 2005-03-28 16:18:51.000000000 -0800 +++ 25-akpm/drivers/serial/mpc52xx_uart.c 2005-03-28 16:18:51.000000000 -0800 @@ -18,7 +18,7 @@ * Some of the code has been inspired/copied from the 2.4 code written * by Dale Farnsworth . * - * Copyright (C) 2004 Sylvain Munaut + * Copyright (C) 2004-2005 Sylvain Munaut * Copyright (C) 2003 MontaVista, Software, Inc. * * This file is licensed under the terms of the GNU General Public License @@ -26,33 +26,26 @@ * kind, whether express or implied. */ -/* OCP Usage : +/* Platform device Usage : * - * This drivers uses the OCP model. To load the serial driver for one of the - * PSCs, just add this to the core_ocp table : + * Since PSCs can have multiple function, the correct driver for each one + * is selected by calling mpc52xx_match_psc_function(...). The function + * handled by this driver is "uart". * - * { - * .vendor = OCP_VENDOR_FREESCALE, - * .function = OCP_FUNC_PSC_UART, - * .index = 0, - * .paddr = MPC52xx_PSC1, - * .irq = MPC52xx_PSC1_IRQ, - * .pm = OCP_CPM_NA, - * }, - * - * This is for PSC1, replace the paddr and irq according to the PSC you want to - * use. The driver all necessary registers to place the PSC in uart mode without + * The driver init all necessary registers to place the PSC in uart mode without * DCD. However, the pin multiplexing aren't changed and should be set either * by the bootloader or in the platform init code. - * The index field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2, + * + * The idx field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2, * and so on). So the PSC1 is mapped to /dev/ttyS0, PSC2 to /dev/ttyS1 and so * on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly for * the console code : without this 1:1 mapping, at early boot time, when we are * parsing the kernel args console=ttyS?, we wouldn't know wich PSC it will be - * mapped to because OCP stuff is not yet initialized. + * mapped to. */ #include +#include #include #include #include @@ -61,7 +54,6 @@ #include #include -#include #include #include @@ -191,6 +183,13 @@ static int mpc52xx_uart_startup(struct uart_port *port) { struct mpc52xx_psc __iomem *psc = PSC(port); + int ret; + + /* Request IRQ */ + ret = request_irq(port->irq, mpc52xx_uart_int, + SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port); + if (ret) + return ret; /* Reset/activate the port, clear and enable interrupts */ out_8(&psc->command,MPC52xx_PSC_RST_RX); @@ -225,6 +224,9 @@ mpc52xx_uart_shutdown(struct uart_port * port->read_status_mask = 0; out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask); + + /* Release interrupt */ + free_irq(port->irq, port); } static void @@ -326,15 +328,21 @@ mpc52xx_uart_release_port(struct uart_po iounmap(port->membase); port->membase = NULL; } + + release_mem_region(port->mapbase, MPC52xx_PSC_SIZE); } static int mpc52xx_uart_request_port(struct uart_port *port) { if (port->flags & UPF_IOREMAP) /* Need to remap ? */ - port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc)); - - return port->membase != NULL ? 0 : -EBUSY; + port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE); + + if (!port->membase) + return -EINVAL; + + return request_mem_region(port->mapbase, MPC52xx_PSC_SIZE, + "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY; } static void @@ -354,7 +362,7 @@ mpc52xx_uart_verify_port(struct uart_por if ( (ser->irq != port->irq) || (ser->io_type != SERIAL_IO_MEM) || (ser->baud_base != port->uartclk) || - // FIXME Should check addresses/irq as well ? + (ser->iomem_base != (void*)port->mapbase) || (ser->hub6 != 0 ) ) return -EINVAL; @@ -630,7 +638,7 @@ mpc52xx_console_setup(struct console *co { struct uart_port *port = &mpc52xx_uart_ports[co->index]; - int baud = 9600; + int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; int bits = 8; int parity = 'n'; int flow = 'n'; @@ -643,14 +651,12 @@ mpc52xx_console_setup(struct console *co spin_lock_init(&port->lock); port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */ port->ops = &mpc52xx_uart_ops; - port->mapbase = MPC52xx_PSCx(co->index); + port->mapbase = MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1)); - /* We ioremap ourself */ - port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc)); - if (port->membase == NULL) { - release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc)); - return -EBUSY; - } + /* We ioremap ourself */ + port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE); + if (port->membase == NULL) + return -EINVAL; /* Setup the port parameters accoding to options */ if (options) @@ -707,26 +713,32 @@ static struct uart_driver mpc52xx_uart_d /* ======================================================================== */ -/* OCP Driver */ +/* Platform Driver */ /* ======================================================================== */ static int __devinit -mpc52xx_uart_probe(struct ocp_device *ocp) +mpc52xx_uart_probe(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); + struct resource *res = pdev->resource; + struct uart_port *port = NULL; - int idx, ret; + int i, idx, ret; - /* Get the corresponding port struct */ - idx = ocp->def->index; + /* Check validity & presence */ + idx = pdev->id; if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM) return -EINVAL; - - port = &mpc52xx_uart_ports[idx]; + + 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->mapbase = ocp->def->paddr; - port->irq = ocp->def->irq; port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */ port->fifosize = 255; /* Should be 512 ! But it can't be */ /* stored in a unsigned char */ @@ -735,95 +747,65 @@ mpc52xx_uart_probe(struct ocp_device *oc ( uart_console(port) ? 0 : UPF_IOREMAP ); port->line = idx; port->ops = &mpc52xx_uart_ops; - port->read_status_mask = 0; - - /* Requests the mem & irqs */ - /* Unlike other serial drivers, we reserve the resources here, so we - * can detect early if multiple drivers uses the same PSC. Special - * care must be taken with the console PSC - */ - ret = request_irq( - port->irq, mpc52xx_uart_int, - SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port); - if (ret) - goto error; - ret = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc), - "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY; - if (ret) - goto free_irq; + /* Search for IRQ and mapbase */ + for (i=0 ; inum_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) + return -EINVAL; /* Add the port to the uart sub-system */ ret = uart_add_one_port(&mpc52xx_uart_driver, port); - if (ret) - goto release_mem; - - ocp_set_drvdata(ocp, (void*)port); - - return 0; - - -free_irq: - free_irq(port->irq, mpc52xx_uart_int); - -release_mem: - release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc)); - -error: - if (uart_console(port)) - printk( "mpc52xx_uart.c: Error during resource alloction for " - "the console port !!! Check that the console PSC is " - "not used by another OCP driver !!!\n" ); + if (!ret) + dev_set_drvdata(dev, (void*)port); return ret; } -static void -mpc52xx_uart_remove(struct ocp_device *ocp) +static int +mpc52xx_uart_remove(struct device *dev) { - struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp); + struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev); - ocp_set_drvdata(ocp, NULL); + dev_set_drvdata(dev, NULL); - if (port) { + if (port) uart_remove_one_port(&mpc52xx_uart_driver, port); - release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc)); - free_irq(port->irq, mpc52xx_uart_int); - } + + return 0; } #ifdef CONFIG_PM static int -mpc52xx_uart_suspend(struct ocp_device *ocp, u32 state) +mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level) { - struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp); + struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev); - uart_suspend_port(&mpc52xx_uart_driver, port); + if (sport && level == SUSPEND_DISABLE) + uart_suspend_port(&mpc52xx_uart_driver, port); return 0; } static int -mpc52xx_uart_resume(struct ocp_device *ocp) +mpc52xx_uart_resume(struct device *dev, u32 level) { - struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp); + struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev); - uart_resume_port(&mpc52xx_uart_driver, port); + if (port && level == RESUME_ENABLE) + uart_resume_port(&mpc52xx_uart_driver, port); return 0; } #endif -static struct ocp_device_id mpc52xx_uart_ids[] __devinitdata = { - { .vendor = OCP_VENDOR_FREESCALE, .function = OCP_FUNC_PSC_UART }, - { .vendor = OCP_VENDOR_INVALID /* Terminating entry */ } -}; - -MODULE_DEVICE_TABLE(ocp, mpc52xx_uart_ids); - -static struct ocp_driver mpc52xx_uart_ocp_driver = { - .name = "mpc52xx_psc_uart", - .id_table = mpc52xx_uart_ids, +static struct device_driver mpc52xx_uart_platform_driver = { + .name = "mpc52xx-psc", + .bus = &platform_bus_type, .probe = mpc52xx_uart_probe, .remove = mpc52xx_uart_remove, #ifdef CONFIG_PM @@ -845,10 +827,11 @@ mpc52xx_uart_init(void) printk(KERN_INFO "Serial: MPC52xx PSC driver\n"); ret = uart_register_driver(&mpc52xx_uart_driver); - if (ret) - return ret; - - ret = ocp_register_driver(&mpc52xx_uart_ocp_driver); + if (ret == 0) { + ret = driver_register(&mpc52xx_uart_platform_driver); + if (ret) + uart_unregister_driver(&mpc52xx_uart_driver); + } return ret; } @@ -856,7 +839,7 @@ mpc52xx_uart_init(void) static void __exit mpc52xx_uart_exit(void) { - ocp_unregister_driver(&mpc52xx_uart_ocp_driver); + driver_unregister(&mpc52xx_uart_platform_driver); uart_unregister_driver(&mpc52xx_uart_driver); } _