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

📄 mpc52xx_uart.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (err && (port->flags & UPF_IOREMAP)) {		iounmap(port->membase);		port->membase = NULL;	}	return err;}static voidmpc52xx_uart_config_port(struct uart_port *port, int flags){	if ( (flags & UART_CONFIG_TYPE) &&	     (mpc52xx_uart_request_port(port) == 0) )	     	port->type = PORT_MPC52xx;}static intmpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser){	if ( ser->type != PORT_UNKNOWN && ser->type != PORT_MPC52xx )		return -EINVAL;	if ( (ser->irq != port->irq) ||	     (ser->io_type != SERIAL_IO_MEM) ||	     (ser->baud_base != port->uartclk)  ||	     (ser->iomem_base != (void*)port->mapbase) ||	     (ser->hub6 != 0 ) )		return -EINVAL;	return 0;}static struct uart_ops mpc52xx_uart_ops = {	.tx_empty	= mpc52xx_uart_tx_empty,	.set_mctrl	= mpc52xx_uart_set_mctrl,	.get_mctrl	= mpc52xx_uart_get_mctrl,	.stop_tx	= mpc52xx_uart_stop_tx,	.start_tx	= mpc52xx_uart_start_tx,	.send_xchar	= mpc52xx_uart_send_xchar,	.stop_rx	= mpc52xx_uart_stop_rx,	.enable_ms	= mpc52xx_uart_enable_ms,	.break_ctl	= mpc52xx_uart_break_ctl,	.startup	= mpc52xx_uart_startup,	.shutdown	= mpc52xx_uart_shutdown,	.set_termios	= mpc52xx_uart_set_termios,/*	.pm		= mpc52xx_uart_pm,		Not supported yet *//*	.set_wake	= mpc52xx_uart_set_wake,	Not supported yet */	.type		= mpc52xx_uart_type,	.release_port	= mpc52xx_uart_release_port,	.request_port	= mpc52xx_uart_request_port,	.config_port	= mpc52xx_uart_config_port,	.verify_port	= mpc52xx_uart_verify_port};/* ======================================================================== *//* Interrupt handling                                                       *//* ======================================================================== */static inline intmpc52xx_uart_int_rx_chars(struct uart_port *port){	struct tty_struct *tty = port->info->tty;	unsigned char ch, flag;	unsigned short status;	/* While we can read, do so ! */	while ( (status = in_be16(&PSC(port)->mpc52xx_psc_status)) &	        MPC52xx_PSC_SR_RXRDY) {		/* Get the char */		ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8);		/* Handle sysreq char */#ifdef SUPPORT_SYSRQ		if (uart_handle_sysrq_char(port, ch)) {			port->sysrq = 0;			continue;		}#endif		/* Store it */		flag = TTY_NORMAL;		port->icount.rx++;		if ( status & (MPC52xx_PSC_SR_PE |		               MPC52xx_PSC_SR_FE |		               MPC52xx_PSC_SR_RB) ) {			if (status & MPC52xx_PSC_SR_RB) {				flag = TTY_BREAK;				uart_handle_break(port);			} else if (status & MPC52xx_PSC_SR_PE)				flag = TTY_PARITY;			else if (status & MPC52xx_PSC_SR_FE)				flag = TTY_FRAME;			/* Clear error condition */			out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT);		}		tty_insert_flip_char(tty, ch, flag);		if (status & MPC52xx_PSC_SR_OE) {			/*			 * Overrun is special, since it's			 * reported immediately, and doesn't			 * affect the current character			 */			tty_insert_flip_char(tty, 0, TTY_OVERRUN);		}	}	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);		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);		return 0;	}	return 1;}static irqreturn_tmpc52xx_uart_int(int irq, void *dev_id){	struct uart_port *port = dev_id;	unsigned long pass = ISR_PASS_LIMIT;	unsigned int keepgoing;	unsigned short status;	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);		/* 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 __iomem *psc = PSC(port);	unsigned char mr1;	pr_debug("mpc52xx_console_get_options(port=%p)\n", port);	/* 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 = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;#if !defined(CONFIG_PPC_MERGE)	if (__res.bi_baudrate)		*baud = __res.bi_baudrate;#endif	/* 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 voidmpc52xx_console_write(struct console *co, const char *s, unsigned int count){	struct uart_port *port = &mpc52xx_uart_ports[co->index];	struct mpc52xx_psc __iomem *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++, s++) {		/* Line return handling */		if (*s == '\n')			out_8(&psc->mpc52xx_psc_buffer_8, '\r');		/* Send the char */		out_8(&psc->mpc52xx_psc_buffer_8, *s);		/* 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);}#if !defined(CONFIG_PPC_MERGE)static int __initmpc52xx_console_setup(struct console *co, char *options){	struct uart_port *port = &mpc52xx_uart_ports[co->index];	int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;	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 */	spin_lock_init(&port->lock);	port->uartclk	= __res.bi_ipbfreq / 2; /* Look at CTLR doc */	port->ops	= &mpc52xx_uart_ops;	port->mapbase	= MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1));	/* We ioremap ourself */	port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);	if (port->membase == NULL)		return -EINVAL;	/* 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);}#elsestatic int __initmpc52xx_console_setup(struct console *co, char *options){	struct uart_port *port = &mpc52xx_uart_ports[co->index];	struct device_node *np = mpc52xx_uart_nodes[co->index];	unsigned int ipb_freq;	struct resource res;	int ret;	int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;	int bits = 8;	int parity = 'n';	int flow = 'n';	pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n",		 co, co->index, options);	if ((co->index < 0) || (co->index > MPC52xx_PSC_MAXNUM)) {		pr_debug("PSC%x out of range\n", co->index);		return -EINVAL;	}	if (!np) {		pr_debug("PSC%x not found in device tree\n", co->index);		return -EINVAL;	}	pr_debug("Console on ttyPSC%x is %s\n",	         co->index, mpc52xx_uart_nodes[co->index]->full_name);	/* Fetch register locations */	if ((ret = of_address_to_resource(np, 0, &res)) != 0) {		pr_debug("Could not get resources for PSC%x\n", co->index);		return ret;	}	/* Search for bus-frequency property in this node or a parent */	if ((ipb_freq = mpc52xx_find_ipb_freq(np)) == 0) {		pr_debug("Could not find IPB bus frequency!\n");		return -EINVAL;	}	/* Basic port init. Needed since we use some uart_??? func before	 * real init for early access */	spin_lock_init(&port->lock);	port->uartclk	= ipb_freq / 2;	port->ops	= &mpc52xx_uart_ops;	port->mapbase = res.start;	port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc));	port->irq = irq_of_parse_and_map(np, 0);	if (port->membase == NULL)		return -EINVAL;	pr_debug("mpc52xx-psc uart at %p, mapped to %p, irq=%x, freq=%i\n",	         (void*)port->mapbase, port->membase, port->irq, port->uartclk);	/* 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);	pr_debug("Setting console parameters: %i %i%c1 flow=%c\n",	         baud, bits, parity, flow);	return uart_set_options(port, co, baud, parity, bits, flow);}#endif /* defined(CONFIG_PPC_MERGE) */static struct uart_driver mpc52xx_uart_driver;

⌨️ 快捷键说明

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