📄 mpc52xx_uart.c
字号:
static struct console mpc52xx_console = { .name = "ttyPSC", .write = mpc52xx_console_write, .device = uart_console_device, .setup = mpc52xx_console_setup, .flags = CON_PRINTBUFFER, .index = -1, /* Specified on the cmdline (e.g. console=ttyPSC0 ) */ .data = &mpc52xx_uart_driver,};static int __initmpc52xx_console_init(void){#if defined(CONFIG_PPC_MERGE) mpc52xx_uart_of_enumerate();#endif register_console(&mpc52xx_console); return 0;}console_initcall(mpc52xx_console_init);#define MPC52xx_PSC_CONSOLE &mpc52xx_console#else#define MPC52xx_PSC_CONSOLE NULL#endif/* ======================================================================== *//* UART Driver *//* ======================================================================== */static struct uart_driver mpc52xx_uart_driver = { .owner = THIS_MODULE, .driver_name = "mpc52xx_psc_uart", .dev_name = "ttyPSC", .major = SERIAL_PSC_MAJOR, .minor = SERIAL_PSC_MINOR, .nr = MPC52xx_PSC_MAXNUM, .cons = MPC52xx_PSC_CONSOLE,};#if !defined(CONFIG_PPC_MERGE)/* ======================================================================== *//* Platform Driver *//* ======================================================================== */static int __devinitmpc52xx_uart_probe(struct platform_device *dev){ struct resource *res = dev->resource; struct uart_port *port = NULL; int i, idx, ret; /* Check validity & presence */ idx = dev->id; if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM) return -EINVAL; if (!mpc52xx_match_psc_function(idx,"uart")) return -ENODEV; /* Init the port structure */ port = &mpc52xx_uart_ports[idx]; 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 | ( uart_console(port) ? 0 : UPF_IOREMAP ); port->line = idx; port->ops = &mpc52xx_uart_ops; port->dev = &dev->dev; /* 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) 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); return ret;}static intmpc52xx_uart_remove(struct platform_device *dev){ struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev); platform_set_drvdata(dev, NULL); if (port) uart_remove_one_port(&mpc52xx_uart_driver, port); return 0;}#ifdef CONFIG_PMstatic intmpc52xx_uart_suspend(struct platform_device *dev, pm_message_t state){ struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev); if (port) uart_suspend_port(&mpc52xx_uart_driver, port); return 0;}static intmpc52xx_uart_resume(struct platform_device *dev){ struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev); if (port) uart_resume_port(&mpc52xx_uart_driver, port); return 0;}#endifstatic struct platform_driver mpc52xx_uart_platform_driver = { .probe = mpc52xx_uart_probe, .remove = mpc52xx_uart_remove,#ifdef CONFIG_PM .suspend = mpc52xx_uart_suspend, .resume = mpc52xx_uart_resume,#endif .driver = { .name = "mpc52xx-psc", },};#endif /* !defined(CONFIG_PPC_MERGE) */#if defined(CONFIG_PPC_MERGE)/* ======================================================================== *//* OF Platform Driver *//* ======================================================================== */static int __devinitmpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match){ int idx = -1; unsigned int ipb_freq; struct uart_port *port = NULL; struct resource res; int ret; dev_dbg(&op->dev, "mpc52xx_uart_probe(op=%p, match=%p)\n", op, match); /* Check validity & presence */ for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++) if (mpc52xx_uart_nodes[idx] == op->node) break; if (idx >= MPC52xx_PSC_MAXNUM) return -EINVAL; pr_debug("Found %s assigned to ttyPSC%x\n", mpc52xx_uart_nodes[idx]->full_name, idx); /* Search for bus-frequency property in this node or a parent */ if ((ipb_freq = mpc52xx_find_ipb_freq(op->node)) == 0) { dev_dbg(&op->dev, "Could not find IPB bus frequency!\n"); return -EINVAL; } /* Init the port structure */ port = &mpc52xx_uart_ports[idx]; spin_lock_init(&port->lock); port->uartclk = ipb_freq / 2; port->fifosize = 512; port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF | ( uart_console(port) ? 0 : UPF_IOREMAP ); port->line = idx; port->ops = &mpc52xx_uart_ops; port->dev = &op->dev; /* Search for IRQ and mapbase */ if ((ret = of_address_to_resource(op->node, 0, &res)) != 0) return ret; port->mapbase = res.start; port->irq = irq_of_parse_and_map(op->node, 0); dev_dbg(&op->dev, "mpc52xx-psc uart at %p, irq=%x, freq=%i\n", (void*)port->mapbase, port->irq, port->uartclk); if ((port->irq==NO_IRQ) || !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) dev_set_drvdata(&op->dev, (void*)port); return ret;}static intmpc52xx_uart_of_remove(struct of_device *op){ 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); irq_dispose_mapping(port->irq); } return 0;}#ifdef CONFIG_PMstatic intmpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state){ struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); if (port) uart_suspend_port(&mpc52xx_uart_driver, port); return 0;}static intmpc52xx_uart_of_resume(struct of_device *op){ struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); if (port) uart_resume_port(&mpc52xx_uart_driver, port); return 0;}#endifstatic voidmpc52xx_uart_of_assign(struct device_node *np, int idx){ int free_idx = -1; int i; /* Find the first free node */ for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) { if (mpc52xx_uart_nodes[i] == NULL) { free_idx = i; break; } } if ((idx < 0) || (idx >= MPC52xx_PSC_MAXNUM)) idx = free_idx; if (idx < 0) return; /* No free slot; abort */ /* If the slot is already occupied, then swap slots */ if (mpc52xx_uart_nodes[idx] && (free_idx != -1)) mpc52xx_uart_nodes[free_idx] = mpc52xx_uart_nodes[idx]; mpc52xx_uart_nodes[idx] = np;}static voidmpc52xx_uart_of_enumerate(void){ static int enum_done = 0; struct device_node *np; const unsigned int *devno; int i; if (enum_done) return; for_each_node_by_type(np, "serial") { if (!of_match_node(mpc52xx_uart_of_match, np)) continue; /* Is a particular device number requested? */ devno = of_get_property(np, "port-number", NULL); mpc52xx_uart_of_assign(of_node_get(np), devno ? *devno : -1); } enum_done = 1; for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) { if (mpc52xx_uart_nodes[i]) pr_debug("%s assigned to ttyPSC%x\n", mpc52xx_uart_nodes[i]->full_name, i); }}MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match);static struct of_platform_driver mpc52xx_uart_of_driver = { .owner = THIS_MODULE, .name = "mpc52xx-psc-uart", .match_table = mpc52xx_uart_of_match, .probe = mpc52xx_uart_of_probe, .remove = mpc52xx_uart_of_remove,#ifdef CONFIG_PM .suspend = mpc52xx_uart_of_suspend, .resume = mpc52xx_uart_of_resume,#endif .driver = { .name = "mpc52xx-psc-uart", },};#endif /* defined(CONFIG_PPC_MERGE) *//* ======================================================================== *//* Module *//* ======================================================================== */static int __initmpc52xx_uart_init(void){ int ret; printk(KERN_INFO "Serial: MPC52xx PSC UART driver\n"); if ((ret = uart_register_driver(&mpc52xx_uart_driver)) != 0) { printk(KERN_ERR "%s: uart_register_driver failed (%i)\n", __FILE__, ret); return ret; }#if defined(CONFIG_PPC_MERGE) mpc52xx_uart_of_enumerate(); ret = of_register_platform_driver(&mpc52xx_uart_of_driver); if (ret) { printk(KERN_ERR "%s: of_register_platform_driver failed (%i)\n", __FILE__, ret); uart_unregister_driver(&mpc52xx_uart_driver); return ret; }#else ret = platform_driver_register(&mpc52xx_uart_platform_driver); if (ret) { printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", __FILE__, ret); uart_unregister_driver(&mpc52xx_uart_driver); return ret; }#endif return 0;}static void __exitmpc52xx_uart_exit(void){#if defined(CONFIG_PPC_MERGE) of_unregister_platform_driver(&mpc52xx_uart_of_driver);#else platform_driver_unregister(&mpc52xx_uart_platform_driver);#endif uart_unregister_driver(&mpc52xx_uart_driver);}module_init(mpc52xx_uart_init);module_exit(mpc52xx_uart_exit);MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");MODULE_DESCRIPTION("Freescale MPC52xx PSC UART");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -