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

📄 cpm_uart_core.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (IS_SMC(pinfo)) {			volatile smc_t *smcp = pinfo->smcp;			smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);			smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);		} else {			volatile scc_t *sccp = pinfo->sccp;			sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);			sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);		}		/* Shut them really down and reinit buffer descriptors */		if (IS_SMC(pinfo))			cpm_line_cr_cmd(line, CPM_CR_STOP_TX);		else			cpm_line_cr_cmd(line, CPM_CR_GRA_STOP_TX);		cpm_uart_initbd(pinfo);	}}static void cpm_uart_set_termios(struct uart_port *port,				 struct termios *termios, struct termios *old){	int baud;	unsigned long flags;	u16 cval, scval, prev_mode;	int bits, sbits;	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;	volatile smc_t *smcp = pinfo->smcp;	volatile scc_t *sccp = pinfo->sccp;	pr_debug("CPM uart[%d]:set_termios\n", port->line);	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);	/* Character length programmed into the mode register is the	 * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,	 * 1 or 2 stop bits, minus 1.	 * The value 'bits' counts this for us.	 */	cval = 0;	scval = 0;	/* byte size */	switch (termios->c_cflag & CSIZE) {	case CS5:		bits = 5;		break;	case CS6:		bits = 6;		break;	case CS7:		bits = 7;		break;	case CS8:		bits = 8;		break;		/* Never happens, but GCC is too dumb to figure it out */	default:		bits = 8;		break;	}	sbits = bits - 5;	if (termios->c_cflag & CSTOPB) {		cval |= SMCMR_SL;	/* Two stops */		scval |= SCU_PSMR_SL;		bits++;	}	if (termios->c_cflag & PARENB) {		cval |= SMCMR_PEN;		scval |= SCU_PSMR_PEN;		bits++;		if (!(termios->c_cflag & PARODD)) {			cval |= SMCMR_PM_EVEN;			scval |= (SCU_PSMR_REVP | SCU_PSMR_TEVP);		}	}	/*	 * Set up parity check flag	 */#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))	port->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);	if (termios->c_iflag & INPCK)		port->read_status_mask |= BD_SC_FR | BD_SC_PR;	if ((termios->c_iflag & BRKINT) || (termios->c_iflag & PARMRK))		port->read_status_mask |= BD_SC_BR;	/*	 * Characters to ignore	 */	port->ignore_status_mask = 0;	if (termios->c_iflag & IGNPAR)		port->ignore_status_mask |= BD_SC_PR | BD_SC_FR;	if (termios->c_iflag & IGNBRK) {		port->ignore_status_mask |= BD_SC_BR;		/*		 * If we're ignore parity and break indicators, ignore		 * overruns too.  (For real raw support).		 */		if (termios->c_iflag & IGNPAR)			port->ignore_status_mask |= BD_SC_OV;	}	/*	 * !!! ignore all characters if CREAD is not set	 */	if ((termios->c_cflag & CREAD) == 0)		port->read_status_mask &= ~BD_SC_EMPTY;	spin_lock_irqsave(&port->lock, flags);	/* Start bit has not been added (so don't, because we would just	 * subtract it later), and we need to add one for the number of	 * stops bits (there is always at least one).	 */	bits++;	if (IS_SMC(pinfo)) {		/* Set the mode register.  We want to keep a copy of the		 * enables, because we want to put them back if they were		 * present.		 */		prev_mode = smcp->smc_smcmr;		smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;		smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN));	} else {		sccp->scc_psmr = (sbits << 12) | scval;	}	cpm_set_brg(pinfo->brg - 1, baud);	spin_unlock_irqrestore(&port->lock, flags);}static const char *cpm_uart_type(struct uart_port *port){	pr_debug("CPM uart[%d]:uart_type\n", port->line);	return port->type == PORT_CPM ? "CPM UART" : NULL;}/* * verify the new serial_struct (for TIOCSSERIAL). */static int cpm_uart_verify_port(struct uart_port *port,				struct serial_struct *ser){	int ret = 0;	pr_debug("CPM uart[%d]:verify_port\n", port->line);	if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)		ret = -EINVAL;	if (ser->irq < 0 || ser->irq >= NR_IRQS)		ret = -EINVAL;	if (ser->baud_base < 9600)		ret = -EINVAL;	return ret;}/* * Transmit characters, refill buffer descriptor, if possible */static int cpm_uart_tx_pump(struct uart_port *port){	volatile cbd_t *bdp;	unsigned char *p;	int count;	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;	struct circ_buf *xmit = &port->info->xmit;	/* Handle xon/xoff */	if (port->x_char) {		/* Pick next descriptor and fill from buffer */		bdp = pinfo->tx_cur;		p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);		*p++ = port->x_char;		bdp->cbd_datlen = 1;		bdp->cbd_sc |= BD_SC_READY;		/* Get next BD. */		if (bdp->cbd_sc & BD_SC_WRAP)			bdp = pinfo->tx_bd_base;		else			bdp++;		pinfo->tx_cur = bdp;		port->icount.tx++;		port->x_char = 0;		return 1;	}	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {		cpm_uart_stop_tx(port);		return 0;	}	/* Pick next descriptor and fill from buffer */	bdp = pinfo->tx_cur;	while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {		count = 0;		p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);		while (count < pinfo->tx_fifosize) {			*p++ = xmit->buf[xmit->tail];			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);			port->icount.tx++;			count++;			if (xmit->head == xmit->tail)				break;		}		bdp->cbd_datlen = count;		bdp->cbd_sc |= BD_SC_READY;		__asm__("eieio");		/* Get next BD. */		if (bdp->cbd_sc & BD_SC_WRAP)			bdp = pinfo->tx_bd_base;		else			bdp++;	}	pinfo->tx_cur = bdp;	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)		uart_write_wakeup(port);	if (uart_circ_empty(xmit)) {		cpm_uart_stop_tx(port);		return 0;	}	return 1;}/* * init buffer descriptors */static void cpm_uart_initbd(struct uart_cpm_port *pinfo){	int i;	u8 *mem_addr;	volatile cbd_t *bdp;	pr_debug("CPM uart[%d]:initbd\n", pinfo->port.line);	/* Set the physical address of the host memory	 * buffers in the buffer descriptors, and the	 * virtual address for us to work with.	 */	mem_addr = pinfo->mem_addr;	bdp = pinfo->rx_cur = pinfo->rx_bd_base;	for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {		bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);		bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;		mem_addr += pinfo->rx_fifosize;	}	bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);	bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;	/* Set the physical address of the host memory	 * buffers in the buffer descriptors, and the	 * virtual address for us to work with.	 */	mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);	bdp = pinfo->tx_cur = pinfo->tx_bd_base;	for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {		bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);		bdp->cbd_sc = BD_SC_INTRPT;		mem_addr += pinfo->tx_fifosize;	}	bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);	bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;}static void cpm_uart_init_scc(struct uart_cpm_port *pinfo){	int line = pinfo - cpm_uart_ports;	volatile scc_t *scp;	volatile scc_uart_t *sup;	pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line);	scp = pinfo->sccp;	sup = pinfo->sccup;	/* Store address */	pinfo->sccup->scc_genscc.scc_rbase = (unsigned char *)pinfo->rx_bd_base - DPRAM_BASE;	pinfo->sccup->scc_genscc.scc_tbase = (unsigned char *)pinfo->tx_bd_base - DPRAM_BASE;	/* Set up the uart parameters in the	 * parameter ram.	 */	cpm_set_scc_fcr(sup);	sup->scc_genscc.scc_mrblr = pinfo->rx_fifosize;	sup->scc_maxidl = pinfo->rx_fifosize;	sup->scc_brkcr = 1;	sup->scc_parec = 0;	sup->scc_frmec = 0;	sup->scc_nosec = 0;	sup->scc_brkec = 0;	sup->scc_uaddr1 = 0;	sup->scc_uaddr2 = 0;	sup->scc_toseq = 0;	sup->scc_char1 = 0x8000;	sup->scc_char2 = 0x8000;	sup->scc_char3 = 0x8000;	sup->scc_char4 = 0x8000;	sup->scc_char5 = 0x8000;	sup->scc_char6 = 0x8000;	sup->scc_char7 = 0x8000;	sup->scc_char8 = 0x8000;	sup->scc_rccm = 0xc0ff;	/* Send the CPM an initialize command.	 */	cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);	/* Set UART mode, 8 bit, no parity, one stop.	 * Enable receive and transmit.	 */	scp->scc_gsmrh = 0;	scp->scc_gsmrl =	    (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);	/* Enable rx interrupts  and clear all pending events.  */	scp->scc_sccm = 0;	scp->scc_scce = 0xffff;	scp->scc_dsr = 0x7e7e;	scp->scc_psmr = 0x3000;	scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);}static void cpm_uart_init_smc(struct uart_cpm_port *pinfo){	int line = pinfo - cpm_uart_ports;	volatile smc_t *sp;	volatile smc_uart_t *up;	pr_debug("CPM uart[%d]:init_smc\n", pinfo->port.line);	sp = pinfo->smcp;	up = pinfo->smcup;	/* Store address */	pinfo->smcup->smc_rbase = (u_char *)pinfo->rx_bd_base - DPRAM_BASE;	pinfo->smcup->smc_tbase = (u_char *)pinfo->tx_bd_base - DPRAM_BASE;/* *  In case SMC1 is being relocated... */#if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH)	up->smc_rbptr = pinfo->smcup->smc_rbase;	up->smc_tbptr = pinfo->smcup->smc_tbase;	up->smc_rstate = 0;	up->smc_tstate = 0;	up->smc_brkcr = 1;              /* number of break chars */	up->smc_brkec = 0;#endif	/* Set up the uart parameters in the	 * parameter ram.	 */	cpm_set_smc_fcr(up);	/* Using idle charater time requires some additional tuning.  */	up->smc_mrblr = pinfo->rx_fifosize;	up->smc_maxidl = pinfo->rx_fifosize;	up->smc_brklen = 0;	up->smc_brkec = 0;	up->smc_brkcr = 1;	cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);	/* Set UART mode, 8 bit, no parity, one stop.	 * Enable receive and transmit.	 */	sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;	/* Enable only rx interrupts clear all pending events. */	sp->smc_smcm = 0;	sp->smc_smce = 0xff;	sp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);}/* * Initialize port. This is called from early_console stuff * so we have to be careful here ! */static int cpm_uart_request_port(struct uart_port *port){	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;	int ret;	pr_debug("CPM uart[%d]:request port\n", port->line);	if (pinfo->flags & FLAG_CONSOLE)		return 0;	if (IS_SMC(pinfo)) {		pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);		pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);	} else {		pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);		pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);	}	ret = cpm_uart_allocbuf(pinfo, 0);	if (ret)		return ret;	cpm_uart_initbd(pinfo);	if (IS_SMC(pinfo))		cpm_uart_init_smc(pinfo);	else		cpm_uart_init_scc(pinfo);	return 0;}static void cpm_uart_release_port(struct uart_port *port){	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;	if (!(pinfo->flags & FLAG_CONSOLE))		cpm_uart_freebuf(pinfo);}/* * Configure/autoconfigure the port. */static void cpm_uart_config_port(struct uart_port *port, int flags){	pr_debug("CPM uart[%d]:config_port\n", port->line);	if (flags & UART_CONFIG_TYPE) {		port->type = PORT_CPM;		cpm_uart_request_port(port);	}}static struct uart_ops cpm_uart_pops = {	.tx_empty	= cpm_uart_tx_empty,	.set_mctrl	= cpm_uart_set_mctrl,	.get_mctrl	= cpm_uart_get_mctrl,	.stop_tx	= cpm_uart_stop_tx,	.start_tx	= cpm_uart_start_tx,	.stop_rx	= cpm_uart_stop_rx,	.enable_ms	= cpm_uart_enable_ms,	.break_ctl	= cpm_uart_break_ctl,	.startup	= cpm_uart_startup,	.shutdown	= cpm_uart_shutdown,	.set_termios	= cpm_uart_set_termios,	.type		= cpm_uart_type,	.release_port	= cpm_uart_release_port,	.request_port	= cpm_uart_request_port,	.config_port	= cpm_uart_config_port,

⌨️ 快捷键说明

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