v850e_uart.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 550 行 · 第 1/2 页

C
550
字号
	struct uart_port *port = data;	v850e_uart_tx (port);	return IRQ_HANDLED;}static irqreturn_t v850e_uart_rx_irq(int irq, void *data, struct pt_regs *regs){	struct uart_port *port = data;	unsigned ch_stat = TTY_NORMAL;	unsigned ch = v850e_uart_getc (port->line);	unsigned err = v850e_uart_err (port->line);	if (err) {		if (err & V850E_UART_ERR_OVERRUN) {			ch_stat = TTY_OVERRUN;			port->icount.overrun++;		} else if (err & V850E_UART_ERR_FRAME) {			ch_stat = TTY_FRAME;			port->icount.frame++;		} else if (err & V850E_UART_ERR_PARITY) {			ch_stat = TTY_PARITY;			port->icount.parity++;		}	}	port->icount.rx++;	tty_insert_flip_char (port->info->tty, ch, ch_stat);	tty_schedule_flip (port->info->tty);	return IRQ_HANDLED;}/* Control functions for the serial framework.  */static void v850e_uart_nop (struct uart_port *port) { }static int v850e_uart_success (struct uart_port *port) { return 0; }static unsigned v850e_uart_tx_empty (struct uart_port *port){	return TIOCSER_TEMT;	/* Can't detect.  */}static void v850e_uart_set_mctrl (struct uart_port *port, unsigned mctrl){#ifdef V850E_UART_SET_RTS	V850E_UART_SET_RTS (port->line, (mctrl & TIOCM_RTS));#endif}static unsigned v850e_uart_get_mctrl (struct uart_port *port){	/* We don't support DCD or DSR, so consider them permanently active. */	int mctrl = TIOCM_CAR | TIOCM_DSR;	/* We may support CTS.  */#ifdef V850E_UART_CTS	mctrl |= V850E_UART_CTS(port->line) ? TIOCM_CTS : 0;#else	mctrl |= TIOCM_CTS;#endif	return mctrl;}static void v850e_uart_start_tx (struct uart_port *port, unsigned tty_start){	v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));	v850e_uart_tx (port);	v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line));}static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop){	v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));}static void v850e_uart_start_rx (struct uart_port *port){	v850e_intc_enable_irq (V850E_UART_RX_IRQ (port->line));}static void v850e_uart_stop_rx (struct uart_port *port){	v850e_intc_disable_irq (V850E_UART_RX_IRQ (port->line));}static void v850e_uart_break_ctl (struct uart_port *port, int break_ctl){	/* Umm, do this later.  */}static int v850e_uart_startup (struct uart_port *port){	int err;	/* Alloc RX irq.  */	err = request_irq (V850E_UART_RX_IRQ (port->line), v850e_uart_rx_irq,			   SA_INTERRUPT, "v850e_uart", port);	if (err)		return err;	/* Alloc TX irq.  */	err = request_irq (V850E_UART_TX_IRQ (port->line), v850e_uart_tx_irq,			   SA_INTERRUPT, "v850e_uart", port);	if (err) {		free_irq (V850E_UART_RX_IRQ (port->line), port);		return err;	}	v850e_uart_start_rx (port);	return 0;}static void v850e_uart_shutdown (struct uart_port *port){	/* Disable port interrupts.  */	free_irq (V850E_UART_TX_IRQ (port->line), port);	free_irq (V850E_UART_RX_IRQ (port->line), port);	/* Turn off xmit/recv enable bits.  */	V850E_UART_CONFIG (port->line)		&= ~(V850E_UART_CONFIG_TX_ENABLE		     | V850E_UART_CONFIG_RX_ENABLE);	/* Then reset the channel.  */	V850E_UART_CONFIG (port->line) = 0;}static voidv850e_uart_set_termios (struct uart_port *port, struct termios *termios,		        struct termios *old){	unsigned cflags = termios->c_cflag;	/* Restrict flags to legal values.  */	if ((cflags & CSIZE) != CS7 && (cflags & CSIZE) != CS8)		/* The new value of CSIZE is invalid, use the old value.  */		cflags = (cflags & ~CSIZE)			| (old ? (old->c_cflag & CSIZE) : CS8);	termios->c_cflag = cflags;	v850e_uart_configure (port->line, cflags,			      uart_get_baud_rate (port, termios, old,						  v850e_uart_min_baud(),						  v850e_uart_max_baud()));}static const char *v850e_uart_type (struct uart_port *port){	return port->type == PORT_V850E_UART ? "v850e_uart" : 0;}static void v850e_uart_config_port (struct uart_port *port, int flags){	if (flags & UART_CONFIG_TYPE)		port->type = PORT_V850E_UART;}static intv850e_uart_verify_port (struct uart_port *port, struct serial_struct *ser){	if (ser->type != PORT_UNKNOWN && ser->type != PORT_V850E_UART)		return -EINVAL;	if (ser->irq != V850E_UART_TX_IRQ (port->line))		return -EINVAL;	return 0;}static struct uart_ops v850e_uart_ops = {	.tx_empty	= v850e_uart_tx_empty,	.get_mctrl	= v850e_uart_get_mctrl,	.set_mctrl	= v850e_uart_set_mctrl,	.start_tx	= v850e_uart_start_tx,	.stop_tx	= v850e_uart_stop_tx,	.stop_rx	= v850e_uart_stop_rx,	.enable_ms	= v850e_uart_nop,	.break_ctl	= v850e_uart_break_ctl,	.startup	= v850e_uart_startup,	.shutdown	= v850e_uart_shutdown,	.set_termios	= v850e_uart_set_termios,	.type		= v850e_uart_type,	.release_port	= v850e_uart_nop,	.request_port	= v850e_uart_success,	.config_port	= v850e_uart_config_port,	.verify_port	= v850e_uart_verify_port,};/* Initialization and cleanup.  */static struct uart_driver v850e_uart_driver = {	.owner			= THIS_MODULE,	.driver_name		= "v850e_uart",	.devfs_name		= "tts/",	.dev_name		= "ttyS",	.major			= TTY_MAJOR,	.minor			= V850E_UART_MINOR_BASE,	.nr			= V850E_UART_NUM_CHANNELS,	.cons			= V850E_UART_CONSOLE,};static struct uart_port v850e_uart_ports[V850E_UART_NUM_CHANNELS];static int __init v850e_uart_init (void){	int rval;	printk (KERN_INFO "%s on-chip UART\n", V850E_UART_CHIP_NAME);	rval = uart_register_driver (&v850e_uart_driver);	if (rval == 0) {		unsigned chan;		for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++) {			struct uart_port *port = &v850e_uart_ports[chan];						memset (port, 0, sizeof *port);			port->ops = &v850e_uart_ops;			port->line = chan;			port->iotype = SERIAL_IO_MEM;			port->flags = UPF_BOOT_AUTOCONF;			/* We actually use multiple IRQs, but the serial			   framework seems to mainly use this for			   informational purposes anyway.  Here we use the TX			   irq.  */			port->irq = V850E_UART_TX_IRQ (chan);			/* The serial framework doesn't really use these			   membase/mapbase fields for anything useful, but			   it requires that they be something non-zero to			   consider the port `valid', and also uses them			   for informational purposes.  */			port->membase = (void *)V850E_UART_BASE_ADDR (chan);			port->mapbase = V850E_UART_BASE_ADDR (chan);			/* The framework insists on knowing the uart's master			   clock freq, though it doesn't seem to do anything			   useful for us with it.  We must make it at least			   higher than (the maximum baud rate * 16), otherwise			   the framework will puke during its internal			   calculations, and force the baud rate to be 9600.			   To be accurate though, just repeat the calculation			   we use when actually setting the speed.  */			port->uartclk = v850e_uart_max_clock() * 16;			uart_add_one_port (&v850e_uart_driver, port);		}	}	return rval;}static void __exit v850e_uart_exit (void){	unsigned chan;	for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++)		uart_remove_one_port (&v850e_uart_driver,				      &v850e_uart_ports[chan]);	uart_unregister_driver (&v850e_uart_driver);}module_init (v850e_uart_init);module_exit (v850e_uart_exit);MODULE_AUTHOR ("Miles Bader");MODULE_DESCRIPTION ("NEC " V850E_UART_CHIP_NAME " on-chip UART");MODULE_LICENSE ("GPL");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?