📄 serial_clps711x.c
字号:
clps_writel(ubrlcr, UBRLCR(port));}static void clps711xuart_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot){ u_int ubrlcr; unsigned long flags;#if DEBUG printk("clps711xuart_change_speed(cflag=0x%x, iflag=0x%x, quot=%d) called\n", cflag, iflag, quot);#endif /* byte size and parity */ switch (cflag & CSIZE) { case CS5: ubrlcr = UBRLCR_WRDLEN5; break; case CS6: ubrlcr = UBRLCR_WRDLEN6; break; case CS7: ubrlcr = UBRLCR_WRDLEN7; break; default: ubrlcr = UBRLCR_WRDLEN8; break; // CS8 } if (cflag & CSTOPB) ubrlcr |= UBRLCR_XSTOP; if (cflag & PARENB) { ubrlcr |= UBRLCR_PRTEN; if (!(cflag & PARODD)) ubrlcr |= UBRLCR_EVENPRT; } if (port->fifosize > 1) ubrlcr |= UBRLCR_FIFOEN; port->read_status_mask = UARTDR_OVERR; if (iflag & INPCK) port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;// 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 |= UARTDR_FRMERR | UARTDR_PARERR; if (iflag & IGNBRK) {// port->ignore_status_mask |= AMBA_UARTRSR_BE; /* * If we're ignoring parity and break indicators, * ignore overruns to (for real raw support). */ if (iflag & IGNPAR) port->ignore_status_mask |= UARTDR_OVERR; } quot -= 1; /* first, disable everything */ save_flags(flags); cli(); clps_writel(ubrlcr | quot, UBRLCR(port)); restore_flags(flags);}static const char *clps711xuart_type(struct uart_port *port){ return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;}/* * Configure/autoconfigure the port. */static void clps711xuart_config_port(struct uart_port *port, int flags){ if (flags & UART_CONFIG_TYPE) port->type = PORT_CLPS711X;}static void clps711xuart_release_port(struct uart_port *port){}static int clps711xuart_request_port(struct uart_port *port){ return 0;}static struct uart_ops clps711x_pops = { tx_empty: clps711xuart_tx_empty, set_mctrl: clps711xuart_set_mctrl_null, get_mctrl: clps711xuart_get_mctrl, stop_tx: clps711xuart_stop_tx, start_tx: clps711xuart_start_tx, stop_rx: clps711xuart_stop_rx, enable_ms: clps711xuart_enable_ms, break_ctl: clps711xuart_break_ctl, startup: clps711xuart_startup, shutdown: clps711xuart_shutdown, change_speed: clps711xuart_change_speed, type: clps711xuart_type, config_port: clps711xuart_config_port, release_port: clps711xuart_release_port, request_port: clps711xuart_request_port,};static struct uart_port clps711x_ports[UART_NR] = { { iobase: SYSCON1, irq: IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */ uartclk: 3686400, fifosize: 16, ops: &clps711x_pops, flags: ASYNC_BOOT_AUTOCONF, }, { iobase: SYSCON2, irq: IRQ_UTXINT2, /* IRQ_URXINT2 */ uartclk: 3686400, fifosize: 16, ops: &clps711x_pops, flags: ASYNC_BOOT_AUTOCONF, }};#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE#ifdef used_and_not_const_char_pointer/* * This code is currently never used; console->read is never called. * Therefore, although we have an implementation, we don't use it. * FIXME: the "const char *s" should be fixed to "char *s" some day. * (when the definition in include/linux/console.h is also fixed) */static int clps711xuart_console_read(struct uart_port *port, char *s, u_int count){ u_int status; int c;#if DEBUG printk("clps711xuart_console_read() called\n");#endif c = 0; while (c < count) { status = clps_readl(SYSFLG(port)); if (status & SYSFLG_URXFE) { // nothing more to get, return return c; } else { *s++ = clps_readl(UARTDR(port)); c++; } } // return the count return c;}#endif/* * Print a string to the serial port trying not to disturb * any possible real use of the port... * * The console_lock must be held when we get here. * * Note that this is called with interrupts already disabled */static void clps711xuart_console_write(struct console *co, const char *s, u_int count){ struct uart_port *port = clps711x_ports + co->index; unsigned int status, syscon; int i; /* * Ensure that the port is enabled. */ syscon = clps_readl(SYSCON(port)); clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); /* * Now, do each character */ for (i = 0; i < count; i++) { do { status = clps_readl(SYSFLG(port)); } while (status & SYSFLG_UTXFF); clps_writel(s[i], UARTDR(port)); if (s[i] == '\n') { do { status = clps_readl(SYSFLG(port)); } while (status & SYSFLG_UTXFF); clps_writel('\r', UARTDR(port)); } } /* * Finally, wait for transmitter to become empty * and restore the uart state. */ do { status = clps_readl(SYSFLG(port)); } while (status & SYSFLG_UBUSY); clps_writel(syscon, SYSCON(port));}static kdev_t clps711xuart_console_device(struct console *co){ return MKDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR + co->index);}/* * Receive character from the serial port * what about interrupts? */static int clps711xuart_console_wait_key(struct console *co){ struct uart_port *port = clps711x_ports + co->index; u_int status, syscon, ch; /* * Ensure that the port is enabled. */ syscon = clps_readl(SYSCON(port)); clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); do { status = clps_readl(SYSFLG(port)); } while (status & SYSFLG_URXFE); ch = clps_readl(UARTDR(port)) & 0xff; clps_writel(syscon, SYSCON(port)); return ch;}static void __initclps711xuart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits){ if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) { u_int ubrlcr, quot; ubrlcr = clps_readl(UBRLCR(port)); *parity = 'n'; if (ubrlcr & UBRLCR_PRTEN) { if (ubrlcr & UBRLCR_EVENPRT) *parity = 'e'; else *parity = 'o'; } if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7) *bits = 7; else *bits = 8; quot = ubrlcr & UBRLCR_BAUD_MASK; *baud = port->uartclk / (16 * (quot + 1)); }}static int __init clps711xuart_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(clps711x_ports, UART_NR, co); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else clps711xuart_console_get_options(port, &baud, &parity, &bits); return uart_set_options(port, co, baud, parity, bits, flow);}static struct console clps711x_console = { name: SERIAL_CLPS711X_NAME, write: clps711xuart_console_write,#ifdef used_and_not_const_char_pointer read: clps711xuart_console_read,#endif device: clps711xuart_console_device, wait_key: clps711xuart_console_wait_key, setup: clps711xuart_console_setup, flags: CON_PRINTBUFFER, index: -1,};void __init clps711xuart_console_init(void){ register_console(&clps711x_console);}#define CLPS711X_CONSOLE &clps711x_console#else#define CLPS711X_CONSOLE NULL#endifstatic struct uart_driver clps711x_reg = {#ifdef CONFIG_DEVFS_FS normal_name: SERIAL_CLPS711X_NAME, callout_name: CALLOUT_CLPS711X_NAME,#else normal_name: SERIAL_CLPS711X_NAME, callout_name: CALLOUT_CLPS711X_NAME,#endif normal_major: SERIAL_CLPS711X_MAJOR, normal_driver: &normal, callout_major: CALLOUT_CLPS711X_MAJOR, callout_driver: &callout, table: clps711x_table, termios: clps711x_termios, termios_locked: clps711x_termios_locked, minor: SERIAL_CLPS711X_MINOR, nr: UART_NR, port: clps711x_ports, cons: CLPS711X_CONSOLE,};static int __init clps711xuart_init(void){ return uart_register_driver(&clps711x_reg);}static void __exit clps711xuart_exit(void){ uart_unregister_driver(&clps711x_reg);}module_init(clps711xuart_init);module_exit(clps711xuart_exit);EXPORT_NO_SYMBOLS;MODULE_AUTHOR("Deep Blue Solutions Ltd");MODULE_DESCRIPTION("CLPS-711x generic serial driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -