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

📄 cpm_uart_core.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			.ops		= &cpm_uart_pops,			.iotype		= UPIO_MEM,			.lock		= __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SCC2].port.lock),		},		.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(cpm_uart_ports[UART_SCC3].port.lock),		},		.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(cpm_uart_ports[UART_SCC4].port.lock),		},		.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;	/* It is UART_SMCx or UART_SCCx index */	struct uart_cpm_port *pinfo;	int line;	u32 mem, pram;        idx = pdata->fs_no = fs_uart_get_id(pdata);	line = cpm_uart_id2nr(idx);	if(line < 0) {		printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);		return -EINVAL;	}	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 = (u32)ioremap(r->start, r->end - r->start + 1);	if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram")))		return -EINVAL;	pram = (u32)ioremap(r->start, r->end - r->start + 1);	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;}#endif#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){#ifdef CONFIG_PPC_CPM_NEW_BINDING	struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];#else	struct uart_cpm_port *pinfo =	    &cpm_uart_ports[cpm_uart_port_map[co->index]];#endif	unsigned int i;	cbd_t __iomem *bdp, *bdbase;	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 ((in_be16(&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(in_be32(&bdp->cbd_bufaddr), pinfo);		*cp = *s;		out_be16(&bdp->cbd_datlen, 1);		setbits16(&bdp->cbd_sc, BD_SC_READY);		if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)			bdp = bdbase;		else			bdp++;		/* if a LF, also do CR... */		if (*s == 10) {			while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)				;			cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);			*cp = 13;			out_be16(&bdp->cbd_datlen, 1);			setbits16(&bdp->cbd_sc, BD_SC_READY);			if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)				bdp = bdbase;			else				bdp++;		}	}	/*	 * Finally, Wait for transmitter & holding register to empty	 *  and restore the IER	 */	while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)		;	pinfo->tx_cur = bdp;}static int __init cpm_uart_console_setup(struct console *co, char *options){	int baud = 38400;	int bits = 8;	int parity = 'n';	int flow = 'n';	int ret;	struct uart_cpm_port *pinfo;	struct uart_port *port;#ifdef CONFIG_PPC_CPM_NEW_BINDING	struct device_node *np = NULL;	int i = 0;	if (co->index >= UART_NR) {		printk(KERN_ERR "cpm_uart: console index %d too high\n",		       co->index);		return -ENODEV;	}	do {		np = of_find_node_by_type(np, "serial");		if (!np)			return -ENODEV;		if (!of_device_is_compatible(np, "fsl,cpm1-smc-uart") &&		    !of_device_is_compatible(np, "fsl,cpm1-scc-uart") &&		    !of_device_is_compatible(np, "fsl,cpm2-smc-uart") &&		    !of_device_is_compatible(np, "fsl,cpm2-scc-uart"))			i--;	} while (i++ != co->index);	pinfo = &cpm_uart_ports[co->index];	pinfo->flags |= FLAG_CONSOLE;	port = &pinfo->port;	ret = cpm_uart_init_port(np, pinfo);	of_node_put(np);	if (ret)		return ret;#else	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(pdata);		cpm_uart_drv_get_platform_data(pdev, 1);	}	pinfo->flags |= FLAG_CONSOLE;#endif	if (options) {		uart_parse_options(options, &baud, &parity, &bits, &flow);	} else {		if ((baud = uart_baudrate()) == -1)			baud = 9600;	}#ifdef CONFIG_PPC_EARLY_DEBUG_CPM	udbg_putc = NULL;#endif	cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);	if (IS_SMC(pinfo)) {		clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);		clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);	} else {		clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);		clrbits32(&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);	cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX);	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,};static 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,	.nr		= UART_NR,};#ifdef CONFIG_PPC_CPM_NEW_BINDINGstatic int probe_index;static int __devinit cpm_uart_probe(struct of_device *ofdev,                                    const struct of_device_id *match){	int index = probe_index++;	struct uart_cpm_port *pinfo = &cpm_uart_ports[index];	int ret;	pinfo->port.line = index;	if (index >= UART_NR)		return -ENODEV;	dev_set_drvdata(&ofdev->dev, pinfo);	ret = cpm_uart_init_port(ofdev->node, pinfo);	if (ret)		return ret;	return uart_add_one_port(&cpm_reg, &pinfo->port);}static int __devexit cpm_uart_remove(struct of_device *ofdev){	struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev);	return uart_remove_one_port(&cpm_reg, &pinfo->port);}static struct of_device_id cpm_uart_match[] = {	{		.compatible = "fsl,cpm1-smc-uart",	},	{		.compatible = "fsl,cpm1-scc-uart",	},	{		.compatible = "fsl,cpm2-smc-uart",	},	{		.compatible = "fsl,cpm2-scc-uart",	},	{}};static struct of_platform_driver cpm_uart_driver = {	.name = "cpm_uart",	.match_table = cpm_uart_match,	.probe = cpm_uart_probe,	.remove = cpm_uart_remove, };static int __init cpm_uart_init(void){	int ret = uart_register_driver(&cpm_reg);	if (ret)		return ret;	ret = of_register_platform_driver(&cpm_uart_driver);	if (ret)		uart_unregister_driver(&cpm_reg);	return ret;}static void __exit cpm_uart_exit(void){	of_unregister_platform_driver(&cpm_uart_driver);	uart_unregister_driver(&cpm_reg);}#elsestatic 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;	if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))		return ret;	pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));	if (pdata->init_ioports)                pdata->init_ioports(pdata);	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");		/* Don't run this again, if the console driver did it already */		if (cpm_uart_nr == 0)			cpm_uart_init_portdesc();		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;			if (cpm_uart_ports[con].set_lineif)				cpm_uart_ports[con].set_lineif(&cpm_uart_ports[con]);			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);}#endifmodule_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 + -