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

📄 cpm_uart_core.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	.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		= UPIO_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		= UPIO_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		= UPIO_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		= UPIO_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		= UPIO_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		= UPIO_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,	},};int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con){	struct resource *r;	struct fs_uart_platform_info *pdata = pdev->dev.platform_data;	int idx = pdata->fs_no;	/* It is UART_SMCx or UART_SCCx index */	struct uart_cpm_port *pinfo;	int line;	u32 mem, pram;	line = cpm_uart_id2nr(idx);	if(line < 0) {		printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);		return -1;	}	pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];	pinfo->brg = pdata->brg;	if (!is_con) {		pinfo->port.line = line;		pinfo->port.flags = UPF_BOOT_AUTOCONF;	}	if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")))		return -EINVAL;	mem = r->start;	if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram")))		return -EINVAL;	pram = r->start;	if(idx > fsid_smc2_uart) {		pinfo->sccp = (scc_t *)mem;		pinfo->sccup = (scc_uart_t *)pram;	} else {		pinfo->smcp = (smc_t *)mem;		pinfo->smcup = (smc_uart_t *)pram;	}	pinfo->tx_nrfifos = pdata->tx_num_fifo;	pinfo->tx_fifosize = pdata->tx_buf_size;	pinfo->rx_nrfifos = pdata->rx_num_fifo;	pinfo->rx_fifosize = pdata->rx_buf_size;	pinfo->port.uartclk = pdata->uart_clk;	pinfo->port.mapbase = (unsigned long)mem;	pinfo->port.irq = platform_get_irq(pdev, 0);	return 0;}#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, pinfo);		*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, pinfo);			*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;}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;	struct fs_uart_platform_info *pdata;	struct platform_device* pdev = early_uart_get_pdev(co->index);	if (!pdev) {		pr_info("cpm_uart: console: compat mode\n");		/* compatibility - will be cleaned up */		cpm_uart_init_portdesc();	}	port =	    (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];	pinfo = (struct uart_cpm_port *)port;	if (!pdev) {		if (pinfo->set_lineif)			pinfo->set_lineif(pinfo);	} else {		pdata = pdev->dev.platform_data;		if (pdata)			if (pdata->init_ioports)    	                	pdata->init_ioports();		cpm_uart_drv_get_platform_data(pdev, 1);	}	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;	}	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){	register_console(&cpm_scc_uart_console);	return 0;}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 cpm_uart_drv_probe(struct device *dev){	struct platform_device  *pdev = to_platform_device(dev);	struct fs_uart_platform_info *pdata;	int ret = -ENODEV;	if(!pdev) {		printk(KERN_ERR"CPM UART: platform data missing!\n");		return ret;	}	pdata = pdev->dev.platform_data;	pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));	if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))		return ret;	if (pdata->init_ioports)                pdata->init_ioports();	ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);        return ret;}static int cpm_uart_drv_remove(struct device *dev){	struct platform_device  *pdev = to_platform_device(dev);	struct fs_uart_platform_info *pdata = pdev->dev.platform_data;	pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n",			cpm_uart_id2nr(pdata->fs_no));        uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);        return 0;}static struct device_driver cpm_smc_uart_driver = {        .name   = "fsl-cpm-smc:uart",        .bus    = &platform_bus_type,        .probe  = cpm_uart_drv_probe,        .remove = cpm_uart_drv_remove,};static struct device_driver cpm_scc_uart_driver = {        .name   = "fsl-cpm-scc:uart",        .bus    = &platform_bus_type,        .probe  = cpm_uart_drv_probe,        .remove = cpm_uart_drv_remove,};/*   This is supposed to match uart devices on platform bus,   */static int match_is_uart (struct device* dev, void* data){	struct platform_device* pdev = container_of(dev, struct platform_device, dev);	int ret = 0;	/* this was setfunc as uart */	if(strstr(pdev->name,":uart")) {		ret = 1;	}	return ret;}static int cpm_uart_init(void) {	int ret;	int i;	struct device *dev;	printk(KERN_INFO "Serial: CPM driver $Revision: 0.02 $\n");	/* lookup the bus for uart devices */	dev = bus_find_device(&platform_bus_type, NULL, 0, match_is_uart);	/* There are devices on the bus - all should be OK  */	if (dev) {		cpm_uart_count();		cpm_reg.nr = cpm_uart_nr;		if (!(ret = uart_register_driver(&cpm_reg))) {			if ((ret = driver_register(&cpm_smc_uart_driver))) {				uart_unregister_driver(&cpm_reg);				return ret;			}			if ((ret = driver_register(&cpm_scc_uart_driver))) {				driver_unregister(&cpm_scc_uart_driver);				uart_unregister_driver(&cpm_reg);			}		}	} else {	/* No capable platform devices found - falling back to legacy mode */		pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n");		pr_info(		"cpm_uart: the driver will guess configuration, but this mode is no longer supported.\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){	driver_unregister(&cpm_scc_uart_driver);	driver_unregister(&cpm_smc_uart_driver);	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 + -