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

📄 bfin_5xx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		uart->tx_count = UART_XMIT_SIZE - xmit->tail;	blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail),					(unsigned long)(xmit->buf+xmit->tail+uart->tx_count));	set_dma_config(uart->tx_dma_channel,		set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP,			INTR_ON_BUF,			DIMENSION_LINEAR,			DATA_SIZE_8));	set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail));	set_dma_x_count(uart->tx_dma_channel, uart->tx_count);	set_dma_x_modify(uart->tx_dma_channel, 1);	enable_dma(uart->tx_dma_channel);#ifdef CONFIG_BF54x	UART_SET_IER(uart, ETBEI);#else	ier = UART_GET_IER(uart);	ier |= ETBEI;	UART_PUT_IER(uart, ier);#endif	spin_unlock_irqrestore(&uart->port.lock, flags);}static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart){	struct tty_struct *tty = uart->port.info->tty;	int i, flg, status;	status = UART_GET_LSR(uart);	uart->port.icount.rx += CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, UART_XMIT_SIZE);;	if (status & BI) {		uart->port.icount.brk++;		if (uart_handle_break(&uart->port))			goto dma_ignore_char;		status &= ~(PE | FE);	}	if (status & PE)		uart->port.icount.parity++;	if (status & OE)		uart->port.icount.overrun++;	if (status & FE)		uart->port.icount.frame++;	status &= uart->port.read_status_mask;	if (status & BI)		flg = TTY_BREAK;	else if (status & PE)		flg = TTY_PARITY;	else if (status & FE)		flg = TTY_FRAME;	else		flg = TTY_NORMAL;	for (i = uart->rx_dma_buf.head; i < uart->rx_dma_buf.tail; i++) {		if (uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i]))			goto dma_ignore_char;		uart_insert_char(&uart->port, status, OE, uart->rx_dma_buf.buf[i], flg);	} dma_ignore_char:	tty_flip_buffer_push(tty);}void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart){	int x_pos, pos;	int flags = 0;	bfin_serial_dma_tx_chars(uart);	spin_lock_irqsave(&uart->port.lock, flags);	x_pos = DMA_RX_XCOUNT - get_dma_curr_xcount(uart->rx_dma_channel);	if (x_pos == DMA_RX_XCOUNT)		x_pos = 0;	pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos;	if (pos>uart->rx_dma_buf.tail) {		uart->rx_dma_buf.tail = pos;		bfin_serial_dma_rx_chars(uart);		uart->rx_dma_buf.head = uart->rx_dma_buf.tail;	}	spin_unlock_irqrestore(&uart->port.lock, flags);	uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;	add_timer(&(uart->rx_dma_timer));}static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id){	struct bfin_serial_port *uart = dev_id;	struct circ_buf *xmit = &uart->port.info->xmit;	unsigned short ier;	spin_lock(&uart->port.lock);	if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {		clear_dma_irqstat(uart->tx_dma_channel);		disable_dma(uart->tx_dma_channel);#ifdef CONFIG_BF54x		UART_CLEAR_IER(uart, ETBEI);#else		ier = UART_GET_IER(uart);		ier &= ~ETBEI;		UART_PUT_IER(uart, ier);#endif		xmit->tail = (xmit->tail+uart->tx_count) &(UART_XMIT_SIZE -1);		uart->port.icount.tx+=uart->tx_count;		if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)			uart_write_wakeup(&uart->port);		if (uart_circ_empty(xmit))			bfin_serial_stop_tx(&uart->port);		uart->tx_done = 1;	}	spin_unlock(&uart->port.lock);	return IRQ_HANDLED;}static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id){	struct bfin_serial_port *uart = dev_id;	unsigned short irqstat;	uart->rx_dma_nrows++;	if (uart->rx_dma_nrows == DMA_RX_YCOUNT) {		uart->rx_dma_nrows = 0;		uart->rx_dma_buf.tail = DMA_RX_XCOUNT*DMA_RX_YCOUNT;		bfin_serial_dma_rx_chars(uart);		uart->rx_dma_buf.head = uart->rx_dma_buf.tail = 0;	}	spin_lock(&uart->port.lock);	irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);	clear_dma_irqstat(uart->rx_dma_channel);	spin_unlock(&uart->port.lock);	return IRQ_HANDLED;}#endif/* * Return TIOCSER_TEMT when transmitter is not busy. */static unsigned int bfin_serial_tx_empty(struct uart_port *port){	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;	unsigned short lsr;	lsr = UART_GET_LSR(uart);	if (lsr & TEMT)		return TIOCSER_TEMT;	else		return 0;}static unsigned int bfin_serial_get_mctrl(struct uart_port *port){#ifdef CONFIG_SERIAL_BFIN_CTSRTS	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;	if (uart->cts_pin < 0)		return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;	if (gpio_get_value(uart->cts_pin))		return TIOCM_DSR | TIOCM_CAR;	else#endif		return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;}static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl){#ifdef CONFIG_SERIAL_BFIN_CTSRTS	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;	if (uart->rts_pin < 0)		return;	if (mctrl & TIOCM_RTS)		gpio_set_value(uart->rts_pin, 0);	else		gpio_set_value(uart->rts_pin, 1);#endif}/* * Handle any change of modem status signal since we were last called. */static void bfin_serial_mctrl_check(struct bfin_serial_port *uart){#ifdef CONFIG_SERIAL_BFIN_CTSRTS	unsigned int status;# ifdef CONFIG_SERIAL_BFIN_DMA	struct uart_info *info = uart->port.info;	struct tty_struct *tty = info->tty;	status = bfin_serial_get_mctrl(&uart->port);	if (!(status & TIOCM_CTS)) {		tty->hw_stopped = 1;	} else {		tty->hw_stopped = 0;	}# else	status = bfin_serial_get_mctrl(&uart->port);	uart_handle_cts_change(&uart->port, status & TIOCM_CTS);	if (!(status & TIOCM_CTS))		schedule_work(&uart->cts_workqueue);# endif#endif}/* * Interrupts are always disabled. */static void bfin_serial_break_ctl(struct uart_port *port, int break_state){	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;	u16 lcr = UART_GET_LCR(uart);	if (break_state)		lcr |= SB;	else		lcr &= ~SB;	UART_PUT_LCR(uart, lcr);	SSYNC();}static int bfin_serial_startup(struct uart_port *port){	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;#ifdef CONFIG_SERIAL_BFIN_DMA	dma_addr_t dma_handle;	if (request_dma(uart->rx_dma_channel, "BFIN_UART_RX") < 0) {		printk(KERN_NOTICE "Unable to attach Blackfin UART RX DMA channel\n");		return -EBUSY;	}	if (request_dma(uart->tx_dma_channel, "BFIN_UART_TX") < 0) {		printk(KERN_NOTICE "Unable to attach Blackfin UART TX DMA channel\n");		free_dma(uart->rx_dma_channel);		return -EBUSY;	}	set_dma_callback(uart->rx_dma_channel, bfin_serial_dma_rx_int, uart);	set_dma_callback(uart->tx_dma_channel, bfin_serial_dma_tx_int, uart);	uart->rx_dma_buf.buf = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE, &dma_handle, GFP_DMA);	uart->rx_dma_buf.head = 0;	uart->rx_dma_buf.tail = 0;	uart->rx_dma_nrows = 0;	set_dma_config(uart->rx_dma_channel,		set_bfin_dma_config(DIR_WRITE, DMA_FLOW_AUTO,				INTR_ON_ROW, DIMENSION_2D,				DATA_SIZE_8));	set_dma_x_count(uart->rx_dma_channel, DMA_RX_XCOUNT);	set_dma_x_modify(uart->rx_dma_channel, 1);	set_dma_y_count(uart->rx_dma_channel, DMA_RX_YCOUNT);	set_dma_y_modify(uart->rx_dma_channel, 1);	set_dma_start_addr(uart->rx_dma_channel, (unsigned long)uart->rx_dma_buf.buf);	enable_dma(uart->rx_dma_channel);	uart->rx_dma_timer.data = (unsigned long)(uart);	uart->rx_dma_timer.function = (void *)bfin_serial_rx_dma_timeout;	uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;	add_timer(&(uart->rx_dma_timer));#else	if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED,	     "BFIN_UART_RX", uart)) {# ifdef	CONFIG_KGDB_UART		if (uart->port.line != CONFIG_KGDB_UART_PORT) {# endif		printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");		return -EBUSY;# ifdef	CONFIG_KGDB_UART		}# endif	}	if (request_irq	    (uart->port.irq+1, bfin_serial_tx_int, IRQF_DISABLED,	     "BFIN_UART_TX", uart)) {		printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n");		free_irq(uart->port.irq, uart);		return -EBUSY;	}#endif#ifdef CONFIG_BF54x	UART_SET_IER(uart, ERBFI);#else	UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);#endif	return 0;}static void bfin_serial_shutdown(struct uart_port *port){	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;#ifdef CONFIG_SERIAL_BFIN_DMA	disable_dma(uart->tx_dma_channel);	free_dma(uart->tx_dma_channel);	disable_dma(uart->rx_dma_channel);	free_dma(uart->rx_dma_channel);	del_timer(&(uart->rx_dma_timer));#else#ifdef	CONFIG_KGDB_UART	if (uart->port.line != CONFIG_KGDB_UART_PORT)#endif	free_irq(uart->port.irq, uart);	free_irq(uart->port.irq+1, uart);#endif}static voidbfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,		   struct ktermios *old){	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;	unsigned long flags;	unsigned int baud, quot;	unsigned short val, ier, lsr, lcr = 0;	switch (termios->c_cflag & CSIZE) {	case CS8:		lcr = WLS(8);		break;	case CS7:		lcr = WLS(7);		break;	case CS6:		lcr = WLS(6);		break;	case CS5:		lcr = WLS(5);		break;	default:		printk(KERN_ERR "%s: word lengh not supported\n",			__FUNCTION__);	}	if (termios->c_cflag & CSTOPB)		lcr |= STB;	if (termios->c_cflag & PARENB)		lcr |= PEN;	if (!(termios->c_cflag & PARODD))		lcr |= EPS;	if (termios->c_cflag & CMSPAR)		lcr |= STP;	port->read_status_mask = OE;	if (termios->c_iflag & INPCK)		port->read_status_mask |= (FE | PE);	if (termios->c_iflag & (BRKINT | PARMRK))		port->read_status_mask |= BI;	/*	 * Characters to ignore	 */	port->ignore_status_mask = 0;	if (termios->c_iflag & IGNPAR)		port->ignore_status_mask |= FE | PE;	if (termios->c_iflag & IGNBRK) {		port->ignore_status_mask |= BI;		/*		 * If we're ignoring parity and break indicators,		 * ignore overruns too (for real raw support).		 */		if (termios->c_iflag & IGNPAR)			port->ignore_status_mask |= OE;	}	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);	quot = uart_get_divisor(port, baud);	spin_lock_irqsave(&uart->port.lock, flags);	do {		lsr = UART_GET_LSR(uart);	} while (!(lsr & TEMT));	/* Disable UART */	ier = UART_GET_IER(uart);#ifdef CONFIG_BF54x	UART_CLEAR_IER(uart, 0xF);#else	UART_PUT_IER(uart, 0);#endif#ifndef CONFIG_BF54x	/* Set DLAB in LCR to Access DLL and DLH */	val = UART_GET_LCR(uart);	val |= DLAB;	UART_PUT_LCR(uart, val);	SSYNC();#endif	UART_PUT_DLL(uart, quot & 0xFF);	SSYNC();	UART_PUT_DLH(uart, (quot >> 8) & 0xFF);	SSYNC();#ifndef CONFIG_BF54x	/* Clear DLAB in LCR to Access THR RBR IER */	val = UART_GET_LCR(uart);	val &= ~DLAB;	UART_PUT_LCR(uart, val);	SSYNC();#endif	UART_PUT_LCR(uart, lcr);	/* Enable UART */#ifdef CONFIG_BF54x	UART_SET_IER(uart, ier);#else	UART_PUT_IER(uart, ier);#endif	val = UART_GET_GCTL(uart);	val |= UCEN;	UART_PUT_GCTL(uart, val);	spin_unlock_irqrestore(&uart->port.lock, flags);}static const char *bfin_serial_type(struct uart_port *port){	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;	return uart->port.type == PORT_BFIN ? "BFIN-UART" : NULL;}/* * Release the memory region(s) being used by 'port'. */static void bfin_serial_release_port(struct uart_port *port)

⌨️ 快捷键说明

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