serial_lh7a40x.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 709 行 · 第 1/2 页
C
709 行
return retval; /* Initial modem control-line settings */ ((struct uart_port_lh7a40x*) port)->statusPrev = UR (port, UART_R_STATUS); /* There is presently no configuration option to enable IR. Thus, we always disable it. */ BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt); return 0;}static void lh7a40xuart_shutdown (struct uart_port* port){ free_irq (port->irq, port); BIT_CLR (port, UART_R_FCON, BRK | FEN); BIT_CLR (port, UART_R_CON, UARTEN);}static void lh7a40xuart_set_termios (struct uart_port* port, struct termios* termios, struct termios* old){ unsigned int con; unsigned int inten; unsigned int fcon; unsigned long flags; unsigned int baud; unsigned int quot; baud = uart_get_baud_rate (port, termios, old, 8, port->uartclk/16); quot = uart_get_divisor (port, baud); /* -1 performed elsewhere */ switch (termios->c_cflag & CSIZE) { case CS5: fcon = WLEN_5; break; case CS6: fcon = WLEN_6; break; case CS7: fcon = WLEN_7; break; case CS8: default: fcon = WLEN_8; break; } if (termios->c_cflag & CSTOPB) fcon |= STP2; if (termios->c_cflag & PARENB) { fcon |= PEN; if (!(termios->c_cflag & PARODD)) fcon |= EPS; } if (port->fifosize > 1) fcon |= FEN; spin_lock_irqsave (&port->lock, flags); uart_update_timeout (port, termios->c_cflag, baud); port->read_status_mask = RxOverrunError; if (termios->c_iflag & INPCK) port->read_status_mask |= RxFramingError | RxParityError; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= RxBreak; /* Figure mask for status we ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= RxFramingError | RxParityError; if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= RxBreak; /* Ignore overrun when ignorning parity */ /* *** FIXME: is this in the right place? */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= RxOverrunError; } /* Ignore all receive errors when receive disabled */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= RxError; con = UR (port, UART_R_CON); inten = (UR (port, UART_R_INTEN) & ~ModemInt); if (UART_ENABLE_MS (port, termios->c_cflag)) inten |= ModemInt; BIT_CLR (port, UART_R_CON, UARTEN); /* Disable UART */ UR (port, UART_R_INTEN) = 0; /* Disable interrupts */ UR (port, UART_R_BRCON) = quot - 1; /* Set baud rate divisor */ UR (port, UART_R_FCON) = fcon; /* Set FIFO and frame ctrl */ UR (port, UART_R_INTEN) = inten; /* Enable interrupts */ UR (port, UART_R_CON) = con; /* Restore UART mode */ spin_unlock_irqrestore(&port->lock, flags);}static const char* lh7a40xuart_type (struct uart_port* port){ return port->type == PORT_LH7A40X ? "LH7A40X" : NULL;}static void lh7a40xuart_release_port (struct uart_port* port){ release_mem_region (port->mapbase, UART_REG_SIZE);}static int lh7a40xuart_request_port (struct uart_port* port){ return request_mem_region (port->mapbase, UART_REG_SIZE, "serial_lh7a40x") != NULL ? 0 : -EBUSY;}static void lh7a40xuart_config_port (struct uart_port* port, int flags){ if (flags & UART_CONFIG_TYPE) { port->type = PORT_LH7A40X; lh7a40xuart_request_port (port); }}static int lh7a40xuart_verify_port (struct uart_port* port, struct serial_struct* ser){ int ret = 0; if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X) ret = -EINVAL; if (ser->irq < 0 || ser->irq >= NR_IRQS) ret = -EINVAL; if (ser->baud_base < 9600) /* *** FIXME: is this true? */ ret = -EINVAL; return ret;}static struct uart_ops lh7a40x_uart_ops = { .tx_empty = lh7a40xuart_tx_empty, .set_mctrl = lh7a40xuart_set_mctrl, .get_mctrl = lh7a40xuart_get_mctrl, .stop_tx = lh7a40xuart_stop_tx, .start_tx = lh7a40xuart_start_tx, .stop_rx = lh7a40xuart_stop_rx, .enable_ms = lh7a40xuart_enable_ms, .break_ctl = lh7a40xuart_break_ctl, .startup = lh7a40xuart_startup, .shutdown = lh7a40xuart_shutdown, .set_termios = lh7a40xuart_set_termios, .type = lh7a40xuart_type, .release_port = lh7a40xuart_release_port, .request_port = lh7a40xuart_request_port, .config_port = lh7a40xuart_config_port, .verify_port = lh7a40xuart_verify_port,};static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { { .port = { .membase = (void*) io_p2v (UART1_PHYS), .mapbase = UART1_PHYS, .iotype = SERIAL_IO_MEM, .irq = IRQ_UART1INTR, .uartclk = 14745600/2, .fifosize = 16, .ops = &lh7a40x_uart_ops, .flags = ASYNC_BOOT_AUTOCONF, .line = 0, }, }, { .port = { .membase = (void*) io_p2v (UART2_PHYS), .mapbase = UART2_PHYS, .iotype = SERIAL_IO_MEM, .irq = IRQ_UART2INTR, .uartclk = 14745600/2, .fifosize = 16, .ops = &lh7a40x_uart_ops, .flags = ASYNC_BOOT_AUTOCONF, .line = 1, }, }, { .port = { .membase = (void*) io_p2v (UART3_PHYS), .mapbase = UART3_PHYS, .iotype = SERIAL_IO_MEM, .irq = IRQ_UART3INTR, .uartclk = 14745600/2, .fifosize = 16, .ops = &lh7a40x_uart_ops, .flags = ASYNC_BOOT_AUTOCONF, .line = 2, }, },};#ifndef CONFIG_SERIAL_LH7A40X_CONSOLE# define LH7A40X_CONSOLE NULL#else# define LH7A40X_CONSOLE &lh7a40x_consolestatic void lh7a40xuart_console_write (struct console* co, const char* s, unsigned int count){ struct uart_port* port = &lh7a40x_ports[co->index].port; unsigned int con = UR (port, UART_R_CON); unsigned int inten = UR (port, UART_R_INTEN); UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */ BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */ for (; count-- > 0; ++s) { while (UR (port, UART_R_STATUS) & nTxRdy) ; UR (port, UART_R_DATA) = *s; if (*s == '\n') { while ((UR (port, UART_R_STATUS) & TxBusy)) ; UR (port, UART_R_DATA) = '\r'; } } /* Wait until all characters are sent */ while (UR (port, UART_R_STATUS) & TxBusy) ; /* Restore control and interrupt mask */ UR (port, UART_R_CON) = con; UR (port, UART_R_INTEN) = inten;}static void __init lh7a40xuart_console_get_options (struct uart_port* port, int* baud, int* parity, int* bits){ if (UR (port, UART_R_CON) & UARTEN) { unsigned int fcon = UR (port, UART_R_FCON); unsigned int quot = UR (port, UART_R_BRCON) + 1; switch (fcon & (PEN | EPS)) { default: *parity = 'n'; break; case PEN: *parity = 'o'; break; case PEN | EPS: *parity = 'e'; break; } switch (fcon & WLEN) { default: case WLEN_8: *bits = 8; break; case WLEN_7: *bits = 7; break; case WLEN_6: *bits = 6; break; case WLEN_5: *bits = 5; break; } *baud = port->uartclk/(16*quot); }}static int __init lh7a40xuart_console_setup (struct console* co, char* options){ struct uart_port* port; int baud = 38400; int bits = 8; int parity = 'n'; int flow = 'n'; if (co->index >= DEV_NR) /* Bounds check on device number */ co->index = 0; port = &lh7a40x_ports[co->index].port; if (options) uart_parse_options (options, &baud, &parity, &bits, &flow); else lh7a40xuart_console_get_options (port, &baud, &parity, &bits); return uart_set_options (port, co, baud, parity, bits, flow);}extern struct uart_driver lh7a40x_reg;static struct console lh7a40x_console = { .name = "ttyAM", .write = lh7a40xuart_console_write, .device = uart_console_device, .setup = lh7a40xuart_console_setup, .flags = CON_PRINTBUFFER, .index = -1, .data = &lh7a40x_reg,};static int __init lh7a40xuart_console_init(void){ register_console (&lh7a40x_console); return 0;}console_initcall (lh7a40xuart_console_init);#endifstatic struct uart_driver lh7a40x_reg = { .owner = THIS_MODULE, .driver_name = "ttyAM", .dev_name = "ttyAM", .major = DEV_MAJOR, .minor = DEV_MINOR, .nr = DEV_NR, .cons = LH7A40X_CONSOLE,};static int __init lh7a40xuart_init(void){ int ret; printk (KERN_INFO "serial: LH7A40X serial driver\n"); ret = uart_register_driver (&lh7a40x_reg); if (ret == 0) { int i; for (i = 0; i < DEV_NR; i++) uart_add_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port); } return ret;}static void __exit lh7a40xuart_exit(void){ int i; for (i = 0; i < DEV_NR; i++) uart_remove_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port); uart_unregister_driver (&lh7a40x_reg);}module_init (lh7a40xuart_init);module_exit (lh7a40xuart_exit);MODULE_AUTHOR ("Marc Singer");MODULE_DESCRIPTION ("Sharp LH7A40X serial port driver");MODULE_LICENSE ("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?