?? uart00.c
字號:
if (break_state == -1) mcr |= UART_MCR_BR_MSK; else mcr &= ~UART_MCR_BR_MSK; UART_PUT_MCR(port, mcr);}static inline u_int uart_calculate_quot(struct uart_info *info, u_int baud){ u_int quot; /* Special case: B0 rate */ if (!baud) baud = 9600; quot = (info->port->uartclk / (16 * baud)-1) ; return quot;}static void uart00_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot){ u_int uart_mc=0, old_ies; unsigned long flags;#ifdef DEBUG printk("uart00_set_cflag(0x%x) called\n", cflag);#endif /* byte size and parity */ switch (cflag & CSIZE) { case CS5: uart_mc = UART_MC_CLS_CHARLEN_5; break; case CS6: uart_mc = UART_MC_CLS_CHARLEN_6; break; case CS7: uart_mc = UART_MC_CLS_CHARLEN_7; break; default: uart_mc = UART_MC_CLS_CHARLEN_8; break; // CS8 } if (cflag & CSTOPB) uart_mc|= UART_MC_ST_TWO; if (cflag & PARENB) { uart_mc |= UART_MC_PE_MSK; if (!(cflag & PARODD)) uart_mc |= UART_MC_EP_MSK; } port->read_status_mask = UART_RDS_OE_MSK; if (iflag & INPCK) port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK; if (iflag & (BRKINT | PARMRK)) port->read_status_mask |= UART_RDS_BI_MSK; /* * Characters to ignore */ port->ignore_status_mask = 0; if (iflag & IGNPAR) port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK; if (iflag & IGNBRK) { port->ignore_status_mask |= UART_RDS_BI_MSK; /* * If we're ignoring parity and break indicators, * ignore overruns to (for real raw support). */ if (iflag & IGNPAR) port->ignore_status_mask |= UART_RDS_OE_MSK; } /* first, disable everything */ save_flags(flags); cli(); old_ies = UART_GET_IES(port); if ((port->flags & ASYNC_HARDPPS_CD) || (cflag & CRTSCTS) || !(cflag & CLOCAL)) old_ies |= UART_IES_ME_MSK; /* Set baud rate */ UART_PUT_DIV_LO(port, (quot & 0xff)); UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8)); UART_PUT_MC(port, uart_mc); UART_PUT_IES(port, old_ies); restore_flags(flags);}static int uart00_startup(struct uart_port *port, struct uart_info *info){ int retval; /* * Use iobase to store a pointer to info. We need this to start a * transmission as the tranmittr interrupt is only generated on * the transition to the idle state */ port->iobase=(u_int)info; /* * Allocate the IRQ */ retval = request_irq(port->irq, uart00_int, 0, "uart00", info); if (retval) return retval; /* * Finally, enable interrupts. Use the TII interrupt to minimise * the number of interrupts generated. If higher performance is * needed, consider using the TI interrupt with a suitable FIFO * threshold */ UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK); return 0;}static void uart00_shutdown(struct uart_port *port, struct uart_info *info){ /* * disable all interrupts, disable the port */ UART_PUT_IEC(port, 0xff); /* disable break condition and fifos */ UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK); /* * Free the interrupt */ free_irq(port->irq, info);}static const char *uart00_type(struct uart_port *port){ return port->type == PORT_UART00 ? "UART00" : NULL;}/* * Release the memory region(s) being used by 'port' */static void uart00_release_port(struct uart_port *port){ release_mem_region(port->mapbase, UART_PORT_SIZE);#ifdef CONFIG_ARCH_CAMELOT if(port->membase!=(void*)IO_ADDRESS(EXC_UART00_BASE)){ iounmap(port->membase); }#endif}/* * Request the memory region(s) being used by 'port' */static int uart00_request_port(struct uart_port *port){ int result; result = request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_uart00") != NULL ? 0 : -EBUSY; if (result) return result; port->membase = ioremap(port->mapbase, SZ_4K); if (!port->membase) { printk(KERN_ERR "serial00: cannot map io memory\n"); release_mem_region(port->mapbase, UART_PORT_SIZE); } return port->membase ? 0 : -ENOMEM;}/* * Configure/autoconfigure the port. */static void uart00_config_port(struct uart_port *port, int flags){ if (flags & UART_CONFIG_TYPE) { if (uart00_request_port(port) == 0) port->type = PORT_UART00; }}/* * verify the new serial_struct (for TIOCSSERIAL). */static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser){ int ret = 0; if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00) 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 uart00_pops = { tx_empty: uart00_tx_empty, set_mctrl: uart00_set_mctrl_null, get_mctrl: uart00_get_mctrl, stop_tx: uart00_stop_tx, start_tx: uart00_start_tx, stop_rx: uart00_stop_rx, enable_ms: uart00_enable_ms, break_ctl: uart00_break_ctl, startup: uart00_startup, shutdown: uart00_shutdown, change_speed: uart00_change_speed, type: uart00_type, release_port: uart00_release_port, request_port: uart00_request_port, config_port: uart00_config_port, verify_port: uart00_verify_port,};#ifdef CONFIG_ARCH_CAMELOTstatic struct uart_port epxa10db_port = { membase: (void*)IO_ADDRESS(EXC_UART00_BASE), mapbase: EXC_UART00_BASE, iotype: SERIAL_IO_MEM, irq: IRQ_UART, uartclk: EXC_AHB2_CLK_FREQUENCY, fifosize: 16, ops: &uart00_pops, flags: ASYNC_BOOT_AUTOCONF,};#endif#ifdef CONFIG_SERIAL_UART00_CONSOLEstatic void uart00_console_write(struct console *co, const char *s, unsigned count){#ifdef CONFIG_ARCH_CAMELOT struct uart_port *port = &epxa10db_port; unsigned int status, old_ies; int i; /* * First save the CR then disable the interrupts */ old_ies = UART_GET_IES(port); UART_PUT_IEC(port,0xff); /* * Now, do each character */ for (i = 0; i < count; i++) { do { status = UART_GET_TSR(port); } while (!UART_TX_READY(status)); UART_PUT_CHAR(port, s[i]); if (s[i] == '\n') { do { status = UART_GET_TSR(port); } while (!UART_TX_READY(status)); UART_PUT_CHAR(port, '\r'); } } /* * Finally, wait for transmitter to become empty * and restore the IES */ do { status = UART_GET_TSR(port); } while (status & UART_TSR_TX_LEVEL_MSK); UART_PUT_IES(port, old_ies);#endif}static kdev_t uart00_console_device(struct console *co){ return MKDEV(SERIAL_UART00_MAJOR, SERIAL_UART00_MINOR + co->index);}static void /*__init*/ uart00_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits){ u_int uart_mc, quot; uart_mc= UART_GET_MC(port); *parity = 'n'; if (uart_mc & UART_MC_PE_MSK) { if (uart_mc & UART_MC_EP_MSK) *parity = 'e'; else *parity = 'o'; } switch (uart_mc & UART_MC_CLS_MSK){ case UART_MC_CLS_CHARLEN_5: *bits = 5; break; case UART_MC_CLS_CHARLEN_6: *bits = 6; break; case UART_MC_CLS_CHARLEN_7: *bits = 7; break; case UART_MC_CLS_CHARLEN_8: *bits = 8; break; } quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8); *baud = port->uartclk / (16 *quot );}static int __init uart00_console_setup(struct console *co, char *options){ struct uart_port *port; int baud = 38400; int bits = 8; int parity = 'n'; int flow= 'n';#ifdef CONFIG_ARCH_CAMELOT /* * Check whether an invalid uart number has been specified, and * if so, search for the first available port that does have * console support. */ port = &epxa10db_port; co->index = 0;#else return -ENODEV;#endif if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else uart00_console_get_options(port, &baud, &parity, &bits); return uart_set_options(port, co, baud, parity, bits, flow);}static struct console uart00_console = { name: SERIAL_UART00_NAME, write: uart00_console_write, device: uart00_console_device, setup: uart00_console_setup, flags: CON_PRINTBUFFER, index: 0,};void __init uart00_console_init(void){ register_console(&uart00_console);}#define UART00_CONSOLE &uart00_console#else#define UART00_CONSOLE NULL#endifstatic struct uart_driver uart00_reg = { owner: NULL, normal_major: SERIAL_UART00_MAJOR, normal_name: SERIAL_UART00_NAME, normal_driver: &normal, callout_major: CALLOUT_UART00_MAJOR, callout_name: CALLOUT_UART00_NAME, callout_driver: &callout, table: uart00_table, termios: uart00_termios, termios_locked: uart00_termios_locked, minor: SERIAL_UART00_MINOR, nr: UART_NR,#ifdef CONFIG_ARCH_CAMELOT port: &epxa10db_port,#endif state: NULL, cons: UART00_CONSOLE,};static int __init uart00_init(void){ printk(KERN_WARNING "serial_uart00:Using temporary major/minor pairs - these WILL change in the future\n"); return uart_register_driver(&uart00_reg);}__initcall(uart00_init);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -