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

📄 cpm_uart_core.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		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);		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);		bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;		mem_addr += pinfo->rx_fifosize;	}	bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);	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);		bdp->cbd_sc = BD_SC_INTRPT;		mem_addr += pinfo->tx_fifosize;	}	bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);	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;	/*	 * Setup any port IO, connect any baud rate generators,	 * etc.  This is expected to be handled by board	 * dependant code	 */	if (pinfo->set_lineif)		pinfo->set_lineif(pinfo);	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,	.verify_port	= cpm_uart_verify_port,};struct uart_cpm_port cpm_uart_ports[UART_NR] = {	[UART_SMC1] = {		.port = {			.irq		= SMC1_IRQ,			.ops		= &cpm_uart_pops,			.iotype		= SERIAL_IO_MEM,			.lock		= SPIN_LOCK_UNLOCKED,		},		.flags = FLAG_SMC,		.tx_nrfifos = TX_NUM_FIFO,		.tx_fifosize = TX_BUF_SIZE,		.rx_nrfifos = RX_NUM_FIFO,		.rx_fifosize = RX_BUF_SIZE,		.set_lineif = smc1_lineif,	},	[UART_SMC2] = {		.port = {			.irq		= SMC2_IRQ,			.ops		= &cpm_uart_pops,			.iotype		= SERIAL_IO_MEM,			.lock		= SPIN_LOCK_UNLOCKED,		},		.flags = FLAG_SMC,		.tx_nrfifos = TX_NUM_FIFO,		.tx_fifosize = TX_BUF_SIZE,		.rx_nrfifos = RX_NUM_FIFO,		.rx_fifosize = RX_BUF_SIZE,		.set_lineif = smc2_lineif,#ifdef CONFIG_SERIAL_CPM_ALT_SMC2		.is_portb = 1,#endif	},	[UART_SCC1] = {		.port = {			.irq		= SCC1_IRQ,			.ops		= &cpm_uart_pops,			.iotype		= SERIAL_IO_MEM,			.lock		= SPIN_LOCK_UNLOCKED,		},		.tx_nrfifos = TX_NUM_FIFO,		.tx_fifosize = TX_BUF_SIZE,		.rx_nrfifos = RX_NUM_FIFO,		.rx_fifosize = RX_BUF_SIZE,		.set_lineif = scc1_lineif,		.wait_closing = SCC_WAIT_CLOSING,	},	[UART_SCC2] = {		.port = {			.irq		= SCC2_IRQ,			.ops		= &cpm_uart_pops,			.iotype		= SERIAL_IO_MEM,			.lock		= SPIN_LOCK_UNLOCKED,		},		.tx_nrfifos = TX_NUM_FIFO,		.tx_fifosize = TX_BUF_SIZE,		.rx_nrfifos = RX_NUM_FIFO,		.rx_fifosize = RX_BUF_SIZE,		.set_lineif = scc2_lineif,		.wait_closing = SCC_WAIT_CLOSING,	},	[UART_SCC3] = {		.port = {			.irq		= SCC3_IRQ,			.ops		= &cpm_uart_pops,			.iotype		= SERIAL_IO_MEM,			.lock		= SPIN_LOCK_UNLOCKED,		},		.tx_nrfifos = TX_NUM_FIFO,		.tx_fifosize = TX_BUF_SIZE,		.rx_nrfifos = RX_NUM_FIFO,		.rx_fifosize = RX_BUF_SIZE,		.set_lineif = scc3_lineif,		.wait_closing = SCC_WAIT_CLOSING,	},	[UART_SCC4] = {		.port = {			.irq		= SCC4_IRQ,			.ops		= &cpm_uart_pops,			.iotype		= SERIAL_IO_MEM,			.lock		= SPIN_LOCK_UNLOCKED,		},		.tx_nrfifos = TX_NUM_FIFO,		.tx_fifosize = TX_BUF_SIZE,		.rx_nrfifos = RX_NUM_FIFO,		.rx_fifosize = RX_BUF_SIZE,		.set_lineif = scc4_lineif,		.wait_closing = SCC_WAIT_CLOSING,	},};#ifdef CONFIG_SERIAL_CPM_CONSOLE/* *	Print a string to the serial port trying not to disturb *	any possible real use of the port... * *	Note that this is called with interrupts already disabled */static void cpm_uart_console_write(struct console *co, const char *s,				   u_int count){	struct uart_cpm_port *pinfo =	    &cpm_uart_ports[cpm_uart_port_map[co->index]];	unsigned int i;	volatile cbd_t *bdp, *bdbase;	volatile unsigned char *cp;	/* Get the address of the host memory buffer.	 */	bdp = pinfo->tx_cur;	bdbase = pinfo->tx_bd_base;	/*	 * Now, do each character.  This is not as bad as it looks	 * since this is a holding FIFO and not a transmitting FIFO.	 * We could add the complexity of filling the entire transmit	 * buffer, but we would just wait longer between accesses......	 */	for (i = 0; i < count; i++, s++) {		/* Wait for transmitter fifo to empty.		 * Ready indicates output is ready, and xmt is doing		 * that, not that it is ready for us to send.		 */		while ((bdp->cbd_sc & BD_SC_READY) != 0)			;		/* Send the character out.		 * If the buffer address is in the CPM DPRAM, don't		 * convert it.		 */		cp = cpm2cpu_addr(bdp->cbd_bufaddr);		*cp = *s;		bdp->cbd_datlen = 1;		bdp->cbd_sc |= BD_SC_READY;		if (bdp->cbd_sc & BD_SC_WRAP)			bdp = bdbase;		else			bdp++;		/* if a LF, also do CR... */		if (*s == 10) {			while ((bdp->cbd_sc & BD_SC_READY) != 0)				;			cp = cpm2cpu_addr(bdp->cbd_bufaddr);			*cp = 13;			bdp->cbd_datlen = 1;			bdp->cbd_sc |= BD_SC_READY;			if (bdp->cbd_sc & BD_SC_WRAP)				bdp = bdbase;			else				bdp++;		}	}	/*	 * Finally, Wait for transmitter & holding register to empty	 *  and restore the IER	 */	while ((bdp->cbd_sc & BD_SC_READY) != 0)		;	pinfo->tx_cur = (volatile cbd_t *) bdp;}/* * Setup console. Be careful is called early ! */static int __init cpm_uart_console_setup(struct console *co, char *options){	struct uart_port *port;	struct uart_cpm_port *pinfo;	int baud = 38400;	int bits = 8;	int parity = 'n';	int flow = 'n';	int ret;	port =	    (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];	pinfo = (struct uart_cpm_port *)port;	pinfo->flags |= FLAG_CONSOLE;	if (options) {		uart_parse_options(options, &baud, &parity, &bits, &flow);	} else {		bd_t *bd = (bd_t *) __res;		if (bd->bi_baudrate)			baud = bd->bi_baudrate;		else			baud = 9600;	}	/*	 * Setup any port IO, connect any baud rate generators,	 * etc.  This is expected to be handled by board	 * dependant code	 */	if (pinfo->set_lineif)		pinfo->set_lineif(pinfo);	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, 1);	if (ret)		return ret;	cpm_uart_initbd(pinfo);	if (IS_SMC(pinfo))		cpm_uart_init_smc(pinfo);	else		cpm_uart_init_scc(pinfo);	uart_set_options(port, co, baud, parity, bits, flow);	return 0;}static struct uart_driver cpm_reg;static struct console cpm_scc_uart_console = {	.name		= "ttyCPM",	.write		= cpm_uart_console_write,	.device		= uart_console_device,	.setup		= cpm_uart_console_setup,	.flags		= CON_PRINTBUFFER,	.index		= -1,	.data		= &cpm_reg,};int __init cpm_uart_console_init(void){	int ret = cpm_uart_init_portdesc();	if (!ret)		register_console(&cpm_scc_uart_console);	return ret;}console_initcall(cpm_uart_console_init);#define CPM_UART_CONSOLE	&cpm_scc_uart_console#else#define CPM_UART_CONSOLE	NULL#endifstatic struct uart_driver cpm_reg = {	.owner		= THIS_MODULE,	.driver_name	= "ttyCPM",	.dev_name	= "ttyCPM",	.major		= SERIAL_CPM_MAJOR,	.minor		= SERIAL_CPM_MINOR,	.cons		= CPM_UART_CONSOLE,};static int __init cpm_uart_init(void){	int ret, i;	printk(KERN_INFO "Serial: CPM driver $Revision: 0.01 $\n");#ifndef CONFIG_SERIAL_CPM_CONSOLE	ret = cpm_uart_init_portdesc();	if (ret)		return ret;#endif	cpm_reg.nr = cpm_uart_nr;	ret = uart_register_driver(&cpm_reg);	if (ret)		return ret;	for (i = 0; i < cpm_uart_nr; i++) {		int con = cpm_uart_port_map[i];		cpm_uart_ports[con].port.line = i;		cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;		uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);	}	return ret;}static void __exit cpm_uart_exit(void){	int i;	for (i = 0; i < cpm_uart_nr; i++) {		int con = cpm_uart_port_map[i];		uart_remove_one_port(&cpm_reg, &cpm_uart_ports[con].port);	}	uart_unregister_driver(&cpm_reg);}module_init(cpm_uart_init);module_exit(cpm_uart_exit);MODULE_AUTHOR("Kumar Gala/Antoniou Pantelis");MODULE_DESCRIPTION("CPM SCC/SMC port driver $Revision: 0.01 $");MODULE_LICENSE("GPL");MODULE_ALIAS_CHARDEV(SERIAL_CPM_MAJOR, SERIAL_CPM_MINOR);

⌨️ 快捷键说明

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