📄 uartlite.c
字号:
struct uart_port *port = &ulite_ports[co->index]; unsigned long flags; unsigned int ier; int locked = 1; if (oops_in_progress) { locked = spin_trylock_irqsave(&port->lock, flags); } else spin_lock_irqsave(&port->lock, flags); /* save and disable interrupt */ ier = readb(port->membase + ULITE_STATUS) & ULITE_STATUS_IE; writeb(0, port->membase + ULITE_CONTROL); uart_console_write(port, s, count, ulite_console_putchar); ulite_console_wait_tx(port); /* restore interrupt state */ if (ier) writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL); if (locked) spin_unlock_irqrestore(&port->lock, flags);}#if defined(CONFIG_OF)static inline void __init ulite_console_of_find_device(int id){ struct device_node *np; struct resource res; const unsigned int *of_id; int rc; for_each_compatible_node(np, NULL, "xilinx,uartlite") { of_id = of_get_property(np, "port-number", NULL); if ((!of_id) || (*of_id != id)) continue; rc = of_address_to_resource(np, 0, &res); if (rc) continue; ulite_ports[id].mapbase = res.start; of_node_put(np); return; }}#else /* CONFIG_OF */static inline void __init ulite_console_of_find_device(int id) { /* do nothing */ }#endif /* CONFIG_OF */static int __init ulite_console_setup(struct console *co, char *options){ struct uart_port *port; int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n'; if (co->index < 0 || co->index >= ULITE_NR_UARTS) return -EINVAL; port = &ulite_ports[co->index]; /* Check if it is an OF device */ if (!port->mapbase) ulite_console_of_find_device(co->index); /* Do we have a device now? */ if (!port->mapbase) { pr_debug("console on ttyUL%i not present\n", co->index); return -ENODEV; } /* not initialized yet? */ if (!port->membase) { if (ulite_request_port(port)) return -ENODEV; } if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); return uart_set_options(port, co, baud, parity, bits, flow);}static struct uart_driver ulite_uart_driver;static struct console ulite_console = { .name = ULITE_NAME, .write = ulite_console_write, .device = uart_console_device, .setup = ulite_console_setup, .flags = CON_PRINTBUFFER, .index = -1, /* Specified on the cmdline (e.g. console=ttyUL0 ) */ .data = &ulite_uart_driver,};static int __init ulite_console_init(void){ register_console(&ulite_console); return 0;}console_initcall(ulite_console_init);#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */static struct uart_driver ulite_uart_driver = { .owner = THIS_MODULE, .driver_name = "uartlite", .dev_name = ULITE_NAME, .major = ULITE_MAJOR, .minor = ULITE_MINOR, .nr = ULITE_NR_UARTS,#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE .cons = &ulite_console,#endif};/* --------------------------------------------------------------------- * Port assignment functions (mapping devices to uart_port structures) *//** ulite_assign: register a uartlite device with the driver * * @dev: pointer to device structure * @id: requested id number. Pass -1 for automatic port assignment * @base: base address of uartlite registers * @irq: irq number for uartlite * * Returns: 0 on success, <0 otherwise */static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq){ struct uart_port *port; int rc; /* if id = -1; then scan for a free id and use that */ if (id < 0) { for (id = 0; id < ULITE_NR_UARTS; id++) if (ulite_ports[id].mapbase == 0) break; } if (id < 0 || id >= ULITE_NR_UARTS) { dev_err(dev, "%s%i too large\n", ULITE_NAME, id); return -EINVAL; } if ((ulite_ports[id].mapbase) && (ulite_ports[id].mapbase != base)) { dev_err(dev, "cannot assign to %s%i; it is already in use\n", ULITE_NAME, id); return -EBUSY; } port = &ulite_ports[id]; spin_lock_init(&port->lock); port->fifosize = 16; port->regshift = 2; port->iotype = UPIO_MEM; port->iobase = 1; /* mark port in use */ port->mapbase = base; port->membase = NULL; port->ops = &ulite_ops; port->irq = irq; port->flags = UPF_BOOT_AUTOCONF; port->dev = dev; port->type = PORT_UNKNOWN; port->line = id; dev_set_drvdata(dev, port); /* Register the port */ rc = uart_add_one_port(&ulite_uart_driver, port); if (rc) { dev_err(dev, "uart_add_one_port() failed; err=%i\n", rc); port->mapbase = 0; dev_set_drvdata(dev, NULL); return rc; } return 0;}/** ulite_release: register a uartlite device with the driver * * @dev: pointer to device structure */static int __devinit ulite_release(struct device *dev){ struct uart_port *port = dev_get_drvdata(dev); int rc = 0; if (port) { rc = uart_remove_one_port(&ulite_uart_driver, port); dev_set_drvdata(dev, NULL); port->mapbase = 0; } return rc;}/* --------------------------------------------------------------------- * Platform bus binding */static int __devinit ulite_probe(struct platform_device *pdev){ struct resource *res, *res2; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res2) return -ENODEV; return ulite_assign(&pdev->dev, pdev->id, res->start, res2->start);}static int ulite_remove(struct platform_device *pdev){ return ulite_release(&pdev->dev);}static struct platform_driver ulite_platform_driver = { .probe = ulite_probe, .remove = ulite_remove, .driver = { .owner = THIS_MODULE, .name = "uartlite", },};/* --------------------------------------------------------------------- * OF bus bindings */#if defined(CONFIG_OF)static int __devinitulite_of_probe(struct of_device *op, const struct of_device_id *match){ struct resource res; const unsigned int *id; int irq, rc; dev_dbg(&op->dev, "%s(%p, %p)\n", __FUNCTION__, op, match); rc = of_address_to_resource(op->node, 0, &res); if (rc) { dev_err(&op->dev, "invalid address\n"); return rc; } irq = irq_of_parse_and_map(op->node, 0); id = of_get_property(op->node, "port-number", NULL); return ulite_assign(&op->dev, id ? *id : -1, res.start+3, irq);}static int __devexit ulite_of_remove(struct of_device *op){ return ulite_release(&op->dev);}/* Match table for of_platform binding */static struct of_device_id __devinit ulite_of_match[] = { { .type = "serial", .compatible = "xilinx,uartlite", }, {},};MODULE_DEVICE_TABLE(of, ulite_of_match);static struct of_platform_driver ulite_of_driver = { .owner = THIS_MODULE, .name = "uartlite", .match_table = ulite_of_match, .probe = ulite_of_probe, .remove = __devexit_p(ulite_of_remove), .driver = { .name = "uartlite", },};/* Registration helpers to keep the number of #ifdefs to a minimum */static inline int __init ulite_of_register(void){ pr_debug("uartlite: calling of_register_platform_driver()\n"); return of_register_platform_driver(&ulite_of_driver);}static inline void __exit ulite_of_unregister(void){ of_unregister_platform_driver(&ulite_of_driver);}#else /* CONFIG_OF *//* CONFIG_OF not enabled; do nothing helpers */static inline int __init ulite_of_register(void) { return 0; }static inline void __exit ulite_of_unregister(void) { }#endif /* CONFIG_OF *//* --------------------------------------------------------------------- * Module setup/teardown */int __init ulite_init(void){ int ret; pr_debug("uartlite: calling uart_register_driver()\n"); ret = uart_register_driver(&ulite_uart_driver); if (ret) goto err_uart; ret = ulite_of_register(); if (ret) goto err_of; pr_debug("uartlite: calling platform_driver_register()\n"); ret = platform_driver_register(&ulite_platform_driver); if (ret) goto err_plat; return 0;err_plat: ulite_of_unregister();err_of: uart_unregister_driver(&ulite_uart_driver);err_uart: printk(KERN_ERR "registering uartlite driver failed: err=%i", ret); return ret;}void __exit ulite_exit(void){ platform_driver_unregister(&ulite_platform_driver); ulite_of_unregister(); uart_unregister_driver(&ulite_uart_driver);}module_init(ulite_init);module_exit(ulite_exit);MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");MODULE_DESCRIPTION("Xilinx uartlite serial driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -