⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpc52xx_uart.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
				/*				 * Overrun is special, since it's				 * reported immediately, and doesn't				 * affect the current character				 */				if (tty->flip.count < (TTY_FLIPBUF_SIZE-1)) {					tty->flip.flag_buf_ptr++;					tty->flip.char_buf_ptr++;					tty->flip.count++;				}				*tty->flip.flag_buf_ptr = TTY_OVERRUN;			}			/* Clear error condition */			out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT);		}		tty->flip.char_buf_ptr++;		tty->flip.flag_buf_ptr++;		tty->flip.count++;	}	tty_flip_buffer_push(tty);		return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY;}static inline intmpc52xx_uart_int_tx_chars(struct uart_port *port){	struct circ_buf *xmit = &port->info->xmit;	/* Process out of band chars */	if (port->x_char) {		out_8(&PSC(port)->mpc52xx_psc_buffer_8, port->x_char);		port->icount.tx++;		port->x_char = 0;		return 1;	}	/* Nothing to do ? */	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {		mpc52xx_uart_stop_tx(port,0);		return 0;	}	/* Send chars */	while (in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXRDY) {		out_8(&PSC(port)->mpc52xx_psc_buffer_8, xmit->buf[xmit->tail]);		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);		port->icount.tx++;		if (uart_circ_empty(xmit))			break;	}	/* Wake up */	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)		uart_write_wakeup(port);	/* Maybe we're done after all */	if (uart_circ_empty(xmit)) {		mpc52xx_uart_stop_tx(port,0);		return 0;	}	return 1;}static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id, struct pt_regs *regs){	struct uart_port *port = (struct uart_port *) dev_id;	unsigned long pass = ISR_PASS_LIMIT;	unsigned int keepgoing;	unsigned short status;		if ( irq != port->irq ) {		printk( KERN_WARNING		        "mpc52xx_uart_int : " \		        "Received wrong int %d. Waiting for %d\n",		       irq, port->irq);		return IRQ_NONE;	}		spin_lock(&port->lock);		/* While we have stuff to do, we continue */	do {		/* If we don't find anything to do, we stop */		keepgoing = 0; 				/* Read status */		status = in_be16(&PSC(port)->mpc52xx_psc_isr);		status &= port->read_status_mask;					/* Do we need to receive chars ? */		/* For this RX interrupts must be on and some chars waiting */		if ( status & MPC52xx_PSC_IMR_RXRDY )			keepgoing |= mpc52xx_uart_int_rx_chars(port, regs);		/* Do we need to send chars ? */		/* For this, TX must be ready and TX interrupt enabled */		if ( status & MPC52xx_PSC_IMR_TXRDY )			keepgoing |= mpc52xx_uart_int_tx_chars(port);				/* Limit number of iteration */		if ( !(--pass) )			keepgoing = 0;	} while (keepgoing);		spin_unlock(&port->lock);		return IRQ_HANDLED;}/* ======================================================================== *//* Console ( if applicable )                                                *//* ======================================================================== */#ifdef CONFIG_SERIAL_MPC52xx_CONSOLEstatic void __initmpc52xx_console_get_options(struct uart_port *port,                            int *baud, int *parity, int *bits, int *flow){	struct mpc52xx_psc *psc = PSC(port);	unsigned char mr1;	/* Read the mode registers */	out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1);	mr1 = in_8(&psc->mode);		/* CT{U,L}R are write-only ! */	*baud = __res.bi_baudrate ?		__res.bi_baudrate : CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;	/* Parse them */	switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {		case MPC52xx_PSC_MODE_5_BITS:	*bits = 5; break;		case MPC52xx_PSC_MODE_6_BITS:	*bits = 6; break;		case MPC52xx_PSC_MODE_7_BITS:	*bits = 7; break;		case MPC52xx_PSC_MODE_8_BITS:		default:			*bits = 8;	}		if (mr1 & MPC52xx_PSC_MODE_PARNONE)		*parity = 'n';	else		*parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e';}static void  mpc52xx_console_write(struct console *co, const char *s, unsigned int count){	struct uart_port *port = &mpc52xx_uart_ports[co->index];	struct mpc52xx_psc *psc = PSC(port);	unsigned int i, j;		/* Disable interrupts */	out_be16(&psc->mpc52xx_psc_imr, 0);	/* Wait the TX buffer to be empty */	j = 5000000;	/* Maximum wait */		while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && 	       --j)		udelay(1);	/* Write all the chars */	for ( i=0 ; i<count ; i++ ) {			/* Send the char */		out_8(&psc->mpc52xx_psc_buffer_8, *s);		/* Line return handling */		if ( *s++ == '\n' )			out_8(&psc->mpc52xx_psc_buffer_8, '\r');				/* Wait the TX buffer to be empty */		j = 20000;	/* Maximum wait */			while (!(in_be16(&psc->mpc52xx_psc_status) & 		         MPC52xx_PSC_SR_TXEMP) && --j)			udelay(1);	}	/* Restore interrupt state */	out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);}static int __initmpc52xx_console_setup(struct console *co, char *options){	struct uart_port *port = &mpc52xx_uart_ports[co->index];	int baud = 9600;	int bits = 8;	int parity = 'n';	int flow = 'n';	if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM)		return -EINVAL;		/* Basic port init. Needed since we use some uart_??? func before	 * real init for early access */	port->lock	= SPIN_LOCK_UNLOCKED;	port->uartclk	= __res.bi_ipbfreq / 2; /* Look at CTLR doc */	port->ops	= &mpc52xx_uart_ops;	port->mapbase	= MPC52xx_PSCx(co->index);		/* We ioremap ourself */	port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));	if (port->membase == NULL) {		release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));		return -EBUSY;	}	/* Setup the port parameters accoding to options */	if (options)		uart_parse_options(options, &baud, &parity, &bits, &flow);	else		mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow);	return uart_set_options(port, co, baud, parity, bits, flow);}extern struct uart_driver mpc52xx_uart_driver;static struct console mpc52xx_console = {	.name	= "ttyS",	.write	= mpc52xx_console_write,	.device	= uart_console_device,	.setup	= mpc52xx_console_setup,	.flags	= CON_PRINTBUFFER,	.index	= -1,	/* Specified on the cmdline (e.g. console=ttyS0 ) */	.data	= &mpc52xx_uart_driver,};	static int __init mpc52xx_console_init(void){	register_console(&mpc52xx_console);	return 0;}console_initcall(mpc52xx_console_init);#define MPC52xx_PSC_CONSOLE &mpc52xx_console#else#define MPC52xx_PSC_CONSOLE NULL#endif/* ======================================================================== *//* UART Driver                                                              *//* ======================================================================== */static struct uart_driver mpc52xx_uart_driver = {	.owner		= THIS_MODULE,	.driver_name	= "mpc52xx_psc_uart",	.dev_name	= "ttyS",	.devfs_name	= "ttyS",	.major		= TTY_MAJOR,	.minor		= 64,	.nr		= MPC52xx_PSC_MAXNUM,	.cons		= MPC52xx_PSC_CONSOLE,};/* ======================================================================== *//* OCP Driver                                                               *//* ======================================================================== */static int __devinitmpc52xx_uart_probe(struct ocp_device *ocp){	struct uart_port *port = NULL;	int idx, ret;	/* Get the corresponding port struct */	idx = ocp->def->index;	if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)		return -EINVAL;		port = &mpc52xx_uart_ports[idx];	/* Init the port structure */	port->lock	= SPIN_LOCK_UNLOCKED;	port->mapbase	= ocp->def->paddr;	port->irq	= ocp->def->irq;	port->uartclk	= __res.bi_ipbfreq / 2; /* Look at CTLR doc */	port->fifosize	= 255; /* Should be 512 ! But it can't be */	                       /* stored in a unsigned char       */	port->iotype	= UPIO_MEM;	port->flags	= UPF_BOOT_AUTOCONF |			  ( uart_console(port) ? 0 : UPF_IOREMAP );	port->line	= idx;	port->ops	= &mpc52xx_uart_ops;	port->read_status_mask = 0;		/* Requests the mem & irqs */	/* Unlike other serial drivers, we reserve the resources here, so we	 * can detect early if multiple drivers uses the same PSC. Special	 * care must be taken with the console PSC	 */	ret = request_irq(		port->irq, mpc52xx_uart_int,		SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);	if (ret)		goto error;	ret = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),	                         "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;	if (ret)		goto free_irq;	/* Add the port to the uart sub-system */	ret = uart_add_one_port(&mpc52xx_uart_driver, port);	if (ret)		goto release_mem;	ocp_set_drvdata(ocp, (void*)port);	return 0;free_irq:	free_irq(port->irq, mpc52xx_uart_int);release_mem:	release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));error:	if (uart_console(port))		printk(	"mpc52xx_uart.c: Error during resource alloction for "			"the console port !!! Check that the console PSC is "			"not used by another OCP driver !!!\n" );	return ret;}static voidmpc52xx_uart_remove(struct ocp_device *ocp){	struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);	ocp_set_drvdata(ocp, NULL);	if (port) {		uart_remove_one_port(&mpc52xx_uart_driver, port);		release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));		free_irq(port->irq, mpc52xx_uart_int);	}}#ifdef CONFIG_PMstatic intmpc52xx_uart_suspend(struct ocp_device *ocp, u32 state){	struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);	uart_suspend_port(&mpc52xx_uart_driver, port);	return 0;}static intmpc52xx_uart_resume(struct ocp_device *ocp){	struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);	uart_resume_port(&mpc52xx_uart_driver, port);	return 0;}#endifstatic struct ocp_device_id mpc52xx_uart_ids[] __devinitdata = {	{ .vendor = OCP_VENDOR_FREESCALE, .function = OCP_FUNC_PSC_UART },	{ .vendor = OCP_VENDOR_INVALID /* Terminating entry */ }};MODULE_DEVICE_TABLE(ocp, mpc52xx_uart_ids);static struct ocp_driver mpc52xx_uart_ocp_driver = {	.name		= "mpc52xx_psc_uart",	.id_table	= mpc52xx_uart_ids,	.probe		= mpc52xx_uart_probe,	.remove		= mpc52xx_uart_remove,#ifdef CONFIG_PM	.suspend	= mpc52xx_uart_suspend,	.resume		= mpc52xx_uart_resume,#endif};/* ======================================================================== *//* Module                                                                   *//* ======================================================================== */static int __initmpc52xx_uart_init(void){	int ret;	printk(KERN_INFO "Serial: MPC52xx PSC driver\n");	ret = uart_register_driver(&mpc52xx_uart_driver);	if (ret)		return ret;	ret = ocp_register_driver(&mpc52xx_uart_ocp_driver);	return ret;}static void __exitmpc52xx_uart_exit(void){	ocp_unregister_driver(&mpc52xx_uart_ocp_driver);	uart_unregister_driver(&mpc52xx_uart_driver);}module_init(mpc52xx_uart_init);module_exit(mpc52xx_uart_exit);MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");MODULE_DESCRIPTION("Freescale MPC52xx PSC UART");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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