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

📄 mcf.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************//* *	mcf.c -- Freescale ColdFire UART driver * *	(C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *//****************************************************************************/#include <linux/kernel.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/module.h>#include <linux/console.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/serial.h>#include <linux/serial_core.h>#include <linux/io.h>#include <asm/coldfire.h>#include <asm/mcfsim.h>#include <asm/mcfuart.h>#include <asm/nettel.h>/****************************************************************************//* *	Some boards implement the DTR/DCD lines using GPIO lines, most *	don't. Dummy out the access macros for those that don't. Those *	that do should define these macros somewhere in there board *	specific inlude files. */#if !defined(mcf_getppdcd)#define	mcf_getppdcd(p)		(1)#endif#if !defined(mcf_getppdtr)#define	mcf_getppdtr(p)		(1)#endif#if !defined(mcf_setppdtr)#define	mcf_setppdtr(p, v)	do { } while (0)#endif/****************************************************************************//* *	Local per-uart structure. */struct mcf_uart {	struct uart_port	port;	unsigned int		sigs;		/* Local copy of line sigs */	unsigned char		imr;		/* Local IMR mirror */};/****************************************************************************/static unsigned int mcf_tx_empty(struct uart_port *port){	return (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXEMPTY) ?		TIOCSER_TEMT : 0;}/****************************************************************************/static unsigned int mcf_get_mctrl(struct uart_port *port){	struct mcf_uart *pp = (struct mcf_uart *) port;	unsigned long flags;	unsigned int sigs;	spin_lock_irqsave(&port->lock, flags);	sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ?		0 : TIOCM_CTS;	sigs |= (pp->sigs & TIOCM_RTS);	sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0);	sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0);	spin_unlock_irqrestore(&port->lock, flags);	return sigs;}/****************************************************************************/static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs){	struct mcf_uart *pp = (struct mcf_uart *) port;	unsigned long flags;	spin_lock_irqsave(&port->lock, flags);	pp->sigs = sigs;	mcf_setppdtr(port->line, (sigs & TIOCM_DTR));	if (sigs & TIOCM_RTS)		writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1);	else		writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0);	spin_unlock_irqrestore(&port->lock, flags);}/****************************************************************************/static void mcf_start_tx(struct uart_port *port){	struct mcf_uart *pp = (struct mcf_uart *) port;	unsigned long flags;	spin_lock_irqsave(&port->lock, flags);	pp->imr |= MCFUART_UIR_TXREADY;	writeb(pp->imr, port->membase + MCFUART_UIMR);	spin_unlock_irqrestore(&port->lock, flags);}/****************************************************************************/static void mcf_stop_tx(struct uart_port *port){	struct mcf_uart *pp = (struct mcf_uart *) port;	unsigned long flags;	spin_lock_irqsave(&port->lock, flags);	pp->imr &= ~MCFUART_UIR_TXREADY;	writeb(pp->imr, port->membase + MCFUART_UIMR);	spin_unlock_irqrestore(&port->lock, flags);}/****************************************************************************/static void mcf_stop_rx(struct uart_port *port){	struct mcf_uart *pp = (struct mcf_uart *) port;	unsigned long flags;	spin_lock_irqsave(&port->lock, flags);	pp->imr &= ~MCFUART_UIR_RXREADY;	writeb(pp->imr, port->membase + MCFUART_UIMR);	spin_unlock_irqrestore(&port->lock, flags);}/****************************************************************************/static void mcf_break_ctl(struct uart_port *port, int break_state){	unsigned long flags;	spin_lock_irqsave(&port->lock, flags);	if (break_state == -1)		writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR);	else		writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR);	spin_unlock_irqrestore(&port->lock, flags);}/****************************************************************************/static void mcf_enable_ms(struct uart_port *port){}/****************************************************************************/static int mcf_startup(struct uart_port *port){	struct mcf_uart *pp = (struct mcf_uart *) port;	unsigned long flags;	spin_lock_irqsave(&port->lock, flags);	/* Reset UART, get it into known state... */	writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);	writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);	/* Enable the UART transmitter and receiver */	writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,		port->membase + MCFUART_UCR);	/* Enable RX interrupts now */	pp->imr = MCFUART_UIR_RXREADY;	writeb(pp->imr, port->membase + MCFUART_UIMR);	spin_unlock_irqrestore(&port->lock, flags);	return 0;}/****************************************************************************/static void mcf_shutdown(struct uart_port *port){	struct mcf_uart *pp = (struct mcf_uart *) port;	unsigned long flags;	spin_lock_irqsave(&port->lock, flags);	/* Disable all interrupts now */	pp->imr = 0;	writeb(pp->imr, port->membase + MCFUART_UIMR);	/* Disable UART transmitter and receiver */	writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);	writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);	spin_unlock_irqrestore(&port->lock, flags);}/****************************************************************************/static void mcf_set_termios(struct uart_port *port, struct ktermios *termios,	struct ktermios *old){	unsigned long flags;	unsigned int baud, baudclk;	unsigned char mr1, mr2;	baud = uart_get_baud_rate(port, termios, old, 0, 230400);	baudclk = ((MCF_BUSCLK / baud) + 16) / 32;	mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;	mr2 = 0;	switch (termios->c_cflag & CSIZE) {	case CS5: mr1 |= MCFUART_MR1_CS5; break;	case CS6: mr1 |= MCFUART_MR1_CS6; break;	case CS7: mr1 |= MCFUART_MR1_CS7; break;	case CS8:	default:  mr1 |= MCFUART_MR1_CS8; break;	}	if (termios->c_cflag & PARENB) {		if (termios->c_cflag & CMSPAR) {			if (termios->c_cflag & PARODD)				mr1 |= MCFUART_MR1_PARITYMARK;			else				mr1 |= MCFUART_MR1_PARITYSPACE;		} else {			if (termios->c_cflag & PARODD)				mr1 |= MCFUART_MR1_PARITYODD;			else				mr1 |= MCFUART_MR1_PARITYEVEN;		}	} else {		mr1 |= MCFUART_MR1_PARITYNONE;	}	if (termios->c_cflag & CSTOPB)		mr2 |= MCFUART_MR2_STOP2;	else		mr2 |= MCFUART_MR2_STOP1;	if (termios->c_cflag & CRTSCTS) {		mr1 |= MCFUART_MR1_RXRTS;		mr2 |= MCFUART_MR2_TXCTS;	}	spin_lock_irqsave(&port->lock, flags);	writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);	writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);	writeb(MCFUART_UCR_CMDRESETMRPTR, port->membase + MCFUART_UCR);	writeb(mr1, port->membase + MCFUART_UMR);	writeb(mr2, port->membase + MCFUART_UMR);	writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1);	writeb((baudclk & 0xff), port->membase + MCFUART_UBG2);	writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER,		port->membase + MCFUART_UCSR);	writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,		port->membase + MCFUART_UCR);	spin_unlock_irqrestore(&port->lock, flags);}/****************************************************************************/static void mcf_rx_chars(struct mcf_uart *pp){	struct uart_port *port = (struct uart_port *) pp;	unsigned char status, ch, flag;	while ((status = readb(port->membase + MCFUART_USR)) & MCFUART_USR_RXREADY) {		ch = readb(port->membase + MCFUART_URB);		flag = TTY_NORMAL;		port->icount.rx++;		if (status & MCFUART_USR_RXERR) {			writeb(MCFUART_UCR_CMDRESETERR,				port->membase + MCFUART_UCR);			if (status & MCFUART_USR_RXBREAK) {				port->icount.brk++;				if (uart_handle_break(port))					continue;			} else if (status & MCFUART_USR_RXPARITY) {				port->icount.parity++;			} else if (status & MCFUART_USR_RXOVERRUN) {				port->icount.overrun++;			} else if (status & MCFUART_USR_RXFRAMING) {				port->icount.frame++;			}			status &= port->read_status_mask;			if (status & MCFUART_USR_RXBREAK)				flag = TTY_BREAK;			else if (status & MCFUART_USR_RXPARITY)				flag = TTY_PARITY;			else if (status & MCFUART_USR_RXFRAMING)				flag = TTY_FRAME;		}		if (uart_handle_sysrq_char(port, ch))			continue;		uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag);	}	tty_flip_buffer_push(port->info->tty);}/****************************************************************************/static void mcf_tx_chars(struct mcf_uart *pp){	struct uart_port *port = (struct uart_port *) pp;	struct circ_buf *xmit = &port->info->xmit;	if (port->x_char) {		/* Send special char - probably flow control */		writeb(port->x_char, port->membase + MCFUART_UTB);

⌨️ 快捷键说明

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