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

📄 s3c2410.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
	    serial_s3c2410_request_port(port) == 0)		port->type = PORT_S3C2410;}/* * verify the new serial_struct (for TIOCSSERIAL). */static intserial_s3c2410_verify_port(struct uart_port *port, struct serial_struct *ser){	int ret = 0;	if (ser->type != PORT_UNKNOWN && ser->type != PORT_S3C2410)		ret = -EINVAL;	return ret;}static struct uart_ops serial_s3c2410_ops = {	.tx_empty	= serial_s3c2410_tx_empty,	.get_mctrl	= serial_s3c2410_get_mctrl,	.set_mctrl	= serial_s3c2410_set_mctrl,	.stop_tx	= serial_s3c2410_stop_tx,	.start_tx	= serial_s3c2410_start_tx,	.stop_rx	= serial_s3c2410_stop_rx,	.enable_ms	= serial_s3c2410_enable_ms,	.break_ctl	= serial_s3c2410_break_ctl,	.startup	= serial_s3c2410_startup,	.shutdown	= serial_s3c2410_shutdown,	.set_termios	= serial_s3c2410_set_termios,	.type		= serial_s3c2410_type,	.release_port	= serial_s3c2410_release_port,	.request_port	= serial_s3c2410_request_port,	.config_port	= serial_s3c2410_config_port,	.verify_port	= serial_s3c2410_verify_port,};static struct uart_port serial_s3c2410_ports[NR_PORTS] = {	{		.membase	= 0,		.mapbase	= 0,		.iotype		= UPIO_MEM,		.irq		= IRQ_S3CUART_RX0,		.uartclk	= 0,		.fifosize	= 16,		.ops		= &serial_s3c2410_ops,		.flags		= UPF_BOOT_AUTOCONF,		.line		= 0,	},	{		.membase	= 0,		.mapbase	= 0,		.iotype		= UPIO_MEM,		.irq		= IRQ_S3CUART_RX1,		.uartclk	= 0,		.fifosize	= 16,		.ops		= &serial_s3c2410_ops,		.flags		= UPF_BOOT_AUTOCONF,		.line		= 1,	}#if NR_PORTS > 2	,	{		.membase	= 0,		.mapbase	= 0,		.iotype		= UPIO_MEM,		.irq		= IRQ_S3CUART_RX2,		.uartclk	= 0,		.fifosize	= 16,		.ops		= &serial_s3c2410_ops,		.flags		= UPF_BOOT_AUTOCONF,		.line		= 2,	}#endif};static intserial_s3c2410_resetport(struct uart_port *port,			 struct s3c2410_uartcfg *cfg){	/* ensure registers are setup */	dbg("serial_s3c2410_resetport: port=%p (%08x), cfg=%p\n",	    port, port->mapbase, cfg);	wr_regl(port, S3C2410_UCON,  cfg->ucon);	wr_regl(port, S3C2410_ULCON, cfg->ulcon);	/* reset both fifos */	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);	wr_regl(port, S3C2410_UFCON, cfg->ufcon);	return 0;}/* serial_s3c2410_init_ports * * initialise the serial ports from the machine provided initialisation * data.*/static int serial_s3c2410_init_ports(void){	struct uart_port *ptr = serial_s3c2410_ports;	struct s3c2410_uartcfg *cfg = s3c2410_uartcfgs;	static int inited = 0;	int i;	if (inited)		return 0;	inited = 1;	dbg("serial_s3c2410_init_ports: initialising ports...\n");	for (i = 0; i < NR_PORTS; i++, ptr++, cfg++) {		if (cfg->hwport > 3)			continue;		dbg("serial_s3c2410_init_ports: port %d (hw %d)...\n",		    i, cfg->hwport);		if (cfg->clock != NULL)			ptr->uartclk = *cfg->clock;		switch (cfg->hwport) {		case 0:			ptr->mapbase = S3C2410_PA_UART0;			ptr->membase = (char *)S3C2410_VA_UART0;			ptr->irq     = IRQ_S3CUART_RX0;			break;		case 1:			ptr->mapbase = S3C2410_PA_UART1;			ptr->membase = (char *)S3C2410_VA_UART1;			ptr->irq     = IRQ_S3CUART_RX1;			break;		case 2:			ptr->mapbase = S3C2410_PA_UART2;			ptr->membase = (char *)S3C2410_VA_UART2;			ptr->irq     = IRQ_S3CUART_RX2;			break;		}		if (ptr->mapbase == 0)			continue;		/* reset the fifos (and setup the uart */		serial_s3c2410_resetport(ptr, cfg);	}	return 0;}#ifdef CONFIG_SERIAL_S3C2410_CONSOLEstatic struct uart_port *cons_uart;static intserial_s3c2410_console_txrdy(struct uart_port *port, unsigned int ufcon){	unsigned long ufstat, utrstat;	if (ufcon & S3C2410_UFCON_FIFOMODE) {		/* fifo mode - check ammount of data in fifo registers... */		ufstat = rd_regl(port, S3C2410_UFSTAT);		return S3C2410_UFCON_TXC(ufstat) < 12;	}	/* in non-fifo mode, we go and use the tx buffer empty */	utrstat = rd_regl(port, S3C2410_UTRSTAT);	return (utrstat & S3C2410_UTRSTAT_TXFE) ? 1 : 0;}static voidserial_s3c2410_console_write(struct console *co, const char *s,			     unsigned int count){	int i;	unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);	for (i = 0; i < count; i++) {		while (!serial_s3c2410_console_txrdy(cons_uart, ufcon))			barrier();		wr_regb(cons_uart, S3C2410_UTXH, s[i]);		if (s[i] == '\n') {			while (!serial_s3c2410_console_txrdy(cons_uart, ufcon))				barrier();			wr_regb(cons_uart, S3C2410_UTXH, '\r');		}	}}static void __initserial_s3c2410_get_options(struct uart_port *port, int *baud,			   int *parity, int *bits){	unsigned int ulcon, ucon, ubrdiv;	ulcon  = rd_regl(port, S3C2410_ULCON);	ucon   = rd_regl(port, S3C2410_UCON);	ubrdiv = rd_regl(port, S3C2410_UBRDIV);	dbg("serial_s3c2410_get_options: port=%p\n"	    "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",	    port, ulcon, ucon, ubrdiv);	if ((ucon & 0xf) != 0) {		/* consider the serial port configured if the tx/rx mode set */		switch (ulcon & S3C2410_LCON_CSMASK) {		case S3C2410_LCON_CS5:			*bits = 5;			break;		case S3C2410_LCON_CS6:			*bits = 6;			break;		case S3C2410_LCON_CS7:			*bits = 7;			break;		default:		case S3C2410_LCON_CS8:			*bits = 8;			break;		}		switch (ulcon & S3C2410_LCON_PMASK) {		case S3C2410_LCON_PEVEN:			*parity = 'e';			break;		case S3C2410_LCON_PODD:			*parity = 'o';			break;		default:		case S3C2410_LCON_PNONE:			*parity = 'n';		}		/* now calculate the baud rate */		*baud = port->uartclk / ( 16 * (ubrdiv + 1));		dbg("calculated baud %d\n", *baud);	}}static int __initserial_s3c2410_console_setup(struct console *co, char *options){	struct uart_port *port;	int baud = 9600;	int bits = 8;	int parity = 'n';	int flow = 'n';	/* is this a valid port */	if (co->index == -1 || co->index >= NR_PORTS)		co->index = 0;	port = &serial_s3c2410_ports[co->index];	/* is the port configured? */	if (port->mapbase == 0x0) {		co->index = 0;		port = &serial_s3c2410_ports[co->index];	}	cons_uart = port;	dbg("serial_s3c2410_console_setup: port=%p (%d)\n", port, co->index);	/*	 * Check whether an invalid uart number has been specified, and	 * if so, search for the first available port that does have	 * console support.	 */	if (options)		uart_parse_options(options, &baud, &parity, &bits, &flow);	else		serial_s3c2410_get_options(port, &baud, &parity, &bits);	return uart_set_options(port, co, baud, parity, bits, flow);}static struct uart_driver s3c2410_uart_drv;static struct console serial_s3c2410_console ={	.name		= SERIAL_S3C2410_NAME,	.write		= serial_s3c2410_console_write,	.device		= uart_console_device,	.setup		= serial_s3c2410_console_setup,	.flags		= CON_PRINTBUFFER,	.index		= -1,	.data		= &s3c2410_uart_drv,};static int __init s3c2410_console_init(void){	dbg("s3c2410_console_init:\n");	serial_s3c2410_init_ports();	register_console(&serial_s3c2410_console);	return 0;}console_initcall(s3c2410_console_init);#define SERIAL_S3C2410_CONSOLE	&serial_s3c2410_console#else#define SERIAL_S3C2410_CONSOLE	NULL#endifstatic struct uart_driver s3c2410_uart_drv = {	.owner			= THIS_MODULE,	.driver_name		= SERIAL_S3C2410_NAME,	.dev_name		= SERIAL_S3C2410_NAME,	.major			= SERIAL_S3C2410_MAJOR,	.minor			= SERIAL_S3C2410_MINOR,	.nr			= 3,	.cons			= SERIAL_S3C2410_CONSOLE,};/* device driver */static int s3c2410_serial_probe(struct device *_dev);static int s3c2410_serial_remove(struct device *_dev);static struct device_driver s3c2410_serial_drv = {	.name		= "s3c2410-uart",	.bus		= &platform_bus_type,	.probe		= s3c2410_serial_probe,	.remove		= s3c2410_serial_remove,	.suspend	= NULL,	.resume		= NULL,};#define s3c2410_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev)static int s3c2410_serial_probe(struct device *_dev){	struct platform_device *dev = to_platform_device(_dev);	struct resource *res = dev->resource;	int i;	dbg("s3c2410_serial_probe: dev=%p, _dev=%p, res=%p\n", _dev, dev, res);	for (i = 0; i < dev->num_resources; i++, res++)		if (res->flags & IORESOURCE_MEM)			break;	if (i < dev->num_resources) {		struct uart_port *ptr = serial_s3c2410_ports;		for (i = 0; i < NR_PORTS; i++, ptr++) {			dbg("s3c2410_serial_probe: ptr=%p (%08x, %08x)\n",			    ptr, ptr->mapbase, ptr->membase);			if (ptr->mapbase != res->start)				continue;			dbg("s3c2410_serial_probe: got device %p: port=%p\n",			    _dev, ptr);			uart_add_one_port(&s3c2410_uart_drv, ptr);			dev_set_drvdata(_dev, ptr);			break;		}	}	return 0;}static int s3c2410_serial_remove(struct device *_dev){	struct uart_port *port = s3c2410_dev_to_port(_dev);	if (port)		uart_remove_one_port(&s3c2410_uart_drv, port);	return 0;}static int __init serial_s3c2410_init(void){	int ret;	printk(KERN_INFO "S3C2410X Serial, (c) 2003 Simtec Electronics\n");	ret = uart_register_driver(&s3c2410_uart_drv);	if (ret != 0)		return ret;	ret = driver_register(&s3c2410_serial_drv);	if (ret) {		uart_unregister_driver(&s3c2410_uart_drv);	}	return ret;}static void __exit serial_s3c2410_exit(void){	driver_unregister(&s3c2410_serial_drv);	uart_unregister_driver(&s3c2410_uart_drv);}module_init(serial_s3c2410_init);module_exit(serial_s3c2410_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");MODULE_DESCRIPTION("Samsung S3C2410X (S3C2410) Serial driver");

⌨️ 快捷键说明

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