?? amba.c
字號:
static void ambauart_break_ctl(struct uart_port *port, int break_state){ unsigned int lcr_h; lcr_h = UART_GET_LCRH(port); if (break_state == -1) lcr_h |= AMBA_UARTLCR_H_BRK; else lcr_h &= ~AMBA_UARTLCR_H_BRK; UART_PUT_LCRH(port, lcr_h);}static int ambauart_startup(struct uart_port *port, struct uart_info *info){ int retval; /* * Allocate the IRQ */ retval = request_irq(port->irq, ambauart_int, 0, "amba", info); if (retval) return retval; /* * initialise the old status of the modem signals */ info->drv_old_status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY; /* * Finally, enable interrupts */ UART_PUT_CR(port, AMBA_UARTCR_UARTEN | AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE); return 0;}static void ambauart_shutdown(struct uart_port *port, struct uart_info *info){ /* * Free the interrupt */ free_irq(port->irq, info); /* * disable all interrupts, disable the port */ UART_PUT_CR(port, 0); /* disable break condition and fifos */ UART_PUT_LCRH(port, UART_GET_LCRH(port) & ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));}static void ambauart_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot){ u_int lcr_h, old_cr; unsigned long flags;#if DEBUG printk("ambauart_set_cflag(0x%x) called\n", cflag);#endif /* byte size and parity */ switch (cflag & CSIZE) { case CS5: lcr_h = AMBA_UARTLCR_H_WLEN_5; break; case CS6: lcr_h = AMBA_UARTLCR_H_WLEN_6; break; case CS7: lcr_h = AMBA_UARTLCR_H_WLEN_7; break; default: lcr_h = AMBA_UARTLCR_H_WLEN_8; break; // CS8 } if (cflag & CSTOPB) lcr_h |= AMBA_UARTLCR_H_STP2; if (cflag & PARENB) { lcr_h |= AMBA_UARTLCR_H_PEN; if (!(cflag & PARODD)) lcr_h |= AMBA_UARTLCR_H_EPS; } if (port->fifosize > 1) lcr_h |= AMBA_UARTLCR_H_FEN; port->read_status_mask = AMBA_UARTRSR_OE; if (iflag & INPCK) port->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE; if (iflag & (BRKINT | PARMRK)) port->read_status_mask |= AMBA_UARTRSR_BE; /* * Characters to ignore */ port->ignore_status_mask = 0; if (iflag & IGNPAR) port->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE; if (iflag & IGNBRK) { port->ignore_status_mask |= AMBA_UARTRSR_BE; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (iflag & IGNPAR) port->ignore_status_mask |= AMBA_UARTRSR_OE; } /* * Ignore all characters if CREAD is not set. */ if ((cflag & CREAD) == 0) port->ignore_status_mask |= UART_DUMMY_RSR_RX; /* first, disable everything */ save_flags(flags); cli(); old_cr = UART_GET_CR(port) & ~AMBA_UARTCR_MSIE; if ((port->flags & ASYNC_HARDPPS_CD) || (cflag & CRTSCTS) || !(cflag & CLOCAL)) old_cr |= AMBA_UARTCR_MSIE; UART_PUT_CR(port, 0); /* Set baud rate */ quot -= 1; UART_PUT_LCRM(port, ((quot & 0xf00) >> 8)); UART_PUT_LCRL(port, (quot & 0xff)); /* * ----------v----------v----------v----------v----- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L * ----------^----------^----------^----------^----- */ UART_PUT_LCRH(port, lcr_h); UART_PUT_CR(port, old_cr); restore_flags(flags);}static const char *ambauart_type(struct uart_port *port){ return port->type == PORT_AMBA ? "AMBA" : NULL;}/* * Release the memory region(s) being used by 'port' */static void ambauart_release_port(struct uart_port *port){ release_mem_region(port->mapbase, UART_PORT_SIZE);}/* * Request the memory region(s) being used by 'port' */static int ambauart_request_port(struct uart_port *port){ return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_amba") != NULL ? 0 : -EBUSY;}/* * Configure/autoconfigure the port. */static void ambauart_config_port(struct uart_port *port, int flags){ if (flags & UART_CONFIG_TYPE) { port->type = PORT_AMBA; ambauart_request_port(port); }}/* * verify the new serial_struct (for TIOCSSERIAL). */static int ambauart_verify_port(struct uart_port *port, struct serial_struct *ser){ int ret = 0; if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA) ret = -EINVAL; if (ser->irq < 0 || ser->irq >= NR_IRQS) ret = -EINVAL; if (ser->baud_base < 9600) ret = -EINVAL; return ret;}static struct uart_ops amba_pops = { tx_empty: ambauart_tx_empty, set_mctrl: ambauart_set_mctrl, get_mctrl: ambauart_get_mctrl, stop_tx: ambauart_stop_tx, start_tx: ambauart_start_tx, stop_rx: ambauart_stop_rx, enable_ms: ambauart_enable_ms, break_ctl: ambauart_break_ctl, startup: ambauart_startup, shutdown: ambauart_shutdown, change_speed: ambauart_change_speed, type: ambauart_type, release_port: ambauart_release_port, request_port: ambauart_request_port, config_port: ambauart_config_port, verify_port: ambauart_verify_port,};static struct uart_port amba_ports[UART_NR] = { { membase: (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), mapbase: INTEGRATOR_UART0_BASE, iotype: SERIAL_IO_MEM, irq: IRQ_UARTINT0, uartclk: 14745600, fifosize: 16, unused: { 4, 5 }, /*driver_priv: PORT_CTRLS(5, 4), */ ops: &amba_pops, flags: ASYNC_BOOT_AUTOCONF, }, { membase: (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), mapbase: INTEGRATOR_UART1_BASE, iotype: SERIAL_IO_MEM, irq: IRQ_UARTINT1, uartclk: 14745600, fifosize: 16, unused: { 6, 7 }, /*driver_priv: PORT_CTRLS(7, 6), */ ops: &amba_pops, flags: ASYNC_BOOT_AUTOCONF, }};#ifdef CONFIG_SERIAL_AMBA_CONSOLEstatic void ambauart_console_write(struct console *co, const char *s, u_int count){ struct uart_port *port = amba_ports + co->index; unsigned int status, old_cr; int i; /* * First save the CR then disable the interrupts */ old_cr = UART_GET_CR(port); UART_PUT_CR(port, AMBA_UARTCR_UARTEN); /* * Now, do each character */ for (i = 0; i < count; i++) { do { status = UART_GET_FR(port); } while (!UART_TX_READY(status)); UART_PUT_CHAR(port, s[i]); if (s[i] == '\n') { do { status = UART_GET_FR(port); } while (!UART_TX_READY(status)); UART_PUT_CHAR(port, '\r'); } } /* * Finally, wait for transmitter to become empty * and restore the TCR */ do { status = UART_GET_FR(port); } while (status & AMBA_UARTFR_BUSY); UART_PUT_CR(port, old_cr);}static kdev_t ambauart_console_device(struct console *co){ return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + co->index);}static void __initambauart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits){ if (UART_GET_CR(port) & AMBA_UARTCR_UARTEN) { u_int lcr_h, quot; lcr_h = UART_GET_LCRH(port); *parity = 'n'; if (lcr_h & AMBA_UARTLCR_H_PEN) { if (lcr_h & AMBA_UARTLCR_H_EPS) *parity = 'e'; else *parity = 'o'; } if ((lcr_h & 0x60) == AMBA_UARTLCR_H_WLEN_7) *bits = 7; else *bits = 8; quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8; *baud = port->uartclk / (16 * (quot + 1)); }}static int __init ambauart_console_setup(struct console *co, char *options){ struct uart_port *port; int baud = 38400; int bits = 8; int parity = 'n'; int flow = 'n'; /* * Check whether an invalid uart number has been specified, and * if so, search for the first available port that does have * console support. */ port = uart_get_console(amba_ports, UART_NR, co); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else ambauart_console_get_options(port, &baud, &parity, &bits); return uart_set_options(port, co, baud, parity, bits, flow);}static struct console amba_console = { name: "ttyAM", write: ambauart_console_write, device: ambauart_console_device, setup: ambauart_console_setup, flags: CON_PRINTBUFFER, index: -1,};void __init ambauart_console_init(void){ register_console(&amba_console);}#define AMBA_CONSOLE &amba_console#else#define AMBA_CONSOLE NULL#endifstatic struct uart_driver amba_reg = { owner: THIS_MODULE, normal_major: SERIAL_AMBA_MAJOR,#ifdef CONFIG_DEVFS_FS normal_name: "ttyAM%d", callout_name: "cuaam%d",#else normal_name: "ttyAM", callout_name: "cuaam",#endif normal_driver: &normal, callout_major: CALLOUT_AMBA_MAJOR, callout_driver: &callout, table: amba_table, termios: amba_termios, termios_locked: amba_termios_locked, minor: SERIAL_AMBA_MINOR, nr: UART_NR, port: amba_ports, cons: AMBA_CONSOLE,};static int __init ambauart_init(void){ return uart_register_driver(&amba_reg);}static void __exit ambauart_exit(void){ uart_unregister_driver(&amba_reg);}module_init(ambauart_init);module_exit(ambauart_exit);EXPORT_NO_SYMBOLS;MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");MODULE_DESCRIPTION("ARM AMBA serial port driver");MODULE_LICENSE("GPL");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -