uart00.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 786 行 · 第 1/2 页

C
786
字号
	/* Set baud rate */	UART_PUT_DIV_LO(port, (quot & 0xff));	UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));	UART_PUT_MC(port, uart_mc);	UART_PUT_IES(port, old_ies);	spin_unlock_irqrestore(&port->lock, flags);}static int uart00_startup(struct uart_port *port){	int result;	/*	 * Allocate the IRQ	 */	result = request_irq(port->irq, uart00_int, 0, "uart00", port);	if (result) {		printk(KERN_ERR "Request of irq %d failed\n", port->irq);		return result;	}	/*	 * Finally, enable interrupts. Use the TII interrupt to minimise 	 * the number of interrupts generated. If higher performance is 	 * needed, consider using the TI interrupt with a suitable FIFO	 * threshold	 */	UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK);	return 0;}static void uart00_shutdown(struct uart_port *port){	/*	 * disable all interrupts, disable the port	 */	UART_PUT_IEC(port, 0xff);	/* disable break condition and fifos */	UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);        /*	 * Free the interrupt	 */	free_irq(port->irq, port);}static const char *uart00_type(struct uart_port *port){	return port->type == PORT_UART00 ? "Altera UART00" : NULL;}/* * Release the memory region(s) being used by 'port' */static void uart00_release_port(struct uart_port *port){	release_mem_region(port->mapbase, UART_PORT_SIZE);#ifdef CONFIG_ARCH_CAMELOT	if (port->membase != (void*)IO_ADDRESS(EXC_UART00_BASE)) {		iounmap(port->membase);	}#endif}/* * Request the memory region(s) being used by 'port' */static int uart00_request_port(struct uart_port *port){	return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_uart00")			!= NULL ? 0 : -EBUSY;}/* * Configure/autoconfigure the port. */static void uart00_config_port(struct uart_port *port, int flags){	/*	 * Map the io memory if this is a soft uart	 */	if (!port->membase)		port->membase = ioremap_nocache(port->mapbase,SZ_4K);	if (!port->membase)		printk(KERN_ERR "serial00: cannot map io memory\n");	else		port->type = PORT_UART00;}/* * verify the new serial_struct (for TIOCSSERIAL). */static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser){	int ret = 0;	if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)		ret = -EINVAL;	if (ser->irq < 0 || ser->irq >= NR_IRQS)		ret = -EINVAL;	if (ser->baud_base < 9600)		ret = -EINVAL;	return ret;}static struct uart_ops uart00_pops = {	.tx_empty	= uart00_tx_empty,	.set_mctrl	= uart00_set_mctrl_null,	.get_mctrl	= uart00_get_mctrl,	.stop_tx	= uart00_stop_tx,	.start_tx	= uart00_start_tx,	.stop_rx	= uart00_stop_rx,	.enable_ms	= uart00_enable_ms,	.break_ctl	= uart00_break_ctl,	.startup	= uart00_startup,	.shutdown	= uart00_shutdown,	.set_termios	= uart00_set_termios,	.type		= uart00_type,	.release_port	= uart00_release_port,	.request_port	= uart00_request_port,	.config_port	= uart00_config_port,	.verify_port	= uart00_verify_port,};#ifdef CONFIG_ARCH_CAMELOTstatic struct uart_port epxa10db_port = {	.membase	= (void*)IO_ADDRESS(EXC_UART00_BASE),	.mapbase	= EXC_UART00_BASE,	.iotype		= SERIAL_IO_MEM,	.irq		= IRQ_UART,	.uartclk	= EXC_AHB2_CLK_FREQUENCY,	.fifosize	= 16,	.ops		= &uart00_pops,	.flags		= ASYNC_BOOT_AUTOCONF,};#endif#ifdef CONFIG_SERIAL_UART00_CONSOLEstatic void uart00_console_write(struct console *co, const char *s, unsigned count){#ifdef CONFIG_ARCH_CAMELOT	struct uart_port *port = &epxa10db_port;	unsigned int status, old_ies;	int i;	/*	 *	First save the CR then disable the interrupts	 */	old_ies = UART_GET_IES(port);	UART_PUT_IEC(port,0xff);	/*	 *	Now, do each character	 */	for (i = 0; i < count; i++) {		do {			status = UART_GET_TSR(port);		} while (!UART_TX_READY(status));		UART_PUT_CHAR(port, s[i]);		if (s[i] == '\n') {			do {				status = UART_GET_TSR(port);			} while (!UART_TX_READY(status));			UART_PUT_CHAR(port, '\r');		}	}	/*	 *	Finally, wait for transmitter to become empty	 *	and restore the IES	 */	do {		status = UART_GET_TSR(port);	} while (status & UART_TSR_TX_LEVEL_MSK);	UART_PUT_IES(port, old_ies);#endif}static void __inituart00_console_get_options(struct uart_port *port, int *baud,			   int *parity, int *bits){	unsigned int uart_mc, quot;	uart_mc = UART_GET_MC(port);	*parity = 'n';	if (uart_mc & UART_MC_PE_MSK) {		if (uart_mc & UART_MC_EP_MSK)			*parity = 'e';		else			*parity = 'o';	}	switch (uart_mc & UART_MC_CLS_MSK) {	case UART_MC_CLS_CHARLEN_5:		*bits = 5;		break;	case UART_MC_CLS_CHARLEN_6:		*bits = 6;		break;	case UART_MC_CLS_CHARLEN_7:		*bits = 7;		break;	case UART_MC_CLS_CHARLEN_8:		*bits = 8;		break;	}	quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);	*baud = port->uartclk / (16 *quot );}static int __init uart00_console_setup(struct console *co, char *options){	struct uart_port *port;	int baud = 115200;	int bits = 8;	int parity = 'n';	int flow = 'n';#ifdef CONFIG_ARCH_CAMELOT	port = &epxa10db_port;             ;#else	return -ENODEV;#endif	if (options)		uart_parse_options(options, &baud, &parity, &bits, &flow);	else		uart00_console_get_options(port, &baud, &parity, &bits);	return uart_set_options(port, co, baud, parity, bits, flow);}extern struct uart_driver uart00_reg;static struct console uart00_console = {	.name		= SERIAL_UART00_NAME,	.write		= uart00_console_write,	.device		= uart_console_device,	.setup		= uart00_console_setup,	.flags		= CON_PRINTBUFFER,	.index		= 0,	.data		= &uart00_reg,};static int __init uart00_console_init(void){	register_console(&uart00_console);	return 0;}console_initcall(uart00_console_init);#define UART00_CONSOLE	&uart00_console#else#define UART00_CONSOLE	NULL#endifstatic struct uart_driver uart00_reg = {	.owner			= NULL,	.driver_name		= SERIAL_UART00_NAME,	.dev_name		= SERIAL_UART00_NAME,	.major			= SERIAL_UART00_MAJOR,	.minor			= SERIAL_UART00_MINOR,	.nr			= UART_NR,	.cons			= UART00_CONSOLE,};struct dev_port_entry{	unsigned int base_addr;	struct uart_port *port;};#ifdef CONFIG_PLD_HOTSWAPstatic struct dev_port_entry dev_port_map[UART_NR];/* * Keep a mapping of dev_info addresses -> port lines to use when * removing ports dev==NULL indicates unused entry */struct uart00_ps_data{	unsigned int clk;	unsigned int fifosize;};int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data){	struct uart00_ps_data* dev_ps=dev_ps_data;	struct uart_port * port;	int i,result;	i=0;	while(dev_port_map[i].port)		i++;	if(i==UART_NR){		printk(KERN_WARNING "uart00: Maximum number of ports reached\n");		return 0;	}	port=kmalloc(sizeof(struct uart_port),GFP_KERNEL);	if(!port)		return -ENOMEM;	printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize);	port->membase=0;	port->mapbase=dev_info->base_addr;	port->iotype=SERIAL_IO_MEM;	port->irq=dev_info->irq;	port->uartclk=dev_ps->clk;	port->fifosize=dev_ps->fifosize;	port->ops=&uart00_pops;	port->line=i;	port->flags=ASYNC_BOOT_AUTOCONF;	result=uart_add_one_port(&uart00_reg, port);	if(result){		printk("uart_add_one_port returned %d\n",result);		return result;	}	dev_port_map[i].base_addr=dev_info->base_addr;	dev_port_map[i].port=port;	printk("uart00: added device at %x as ttyUA%d\n",dev_port_map[i].base_addr,i);	return 0;}int uart00_remove_devices(void){	int i,result;	result=0;	for(i=1;i<UART_NR;i++){		if(dev_port_map[i].base_addr){			result=uart_remove_one_port(&uart00_reg, dev_port_map[i].port);			if(result)				return result;			/* port removed sucessfully, so now tidy up */			kfree(dev_port_map[i].port);			dev_port_map[i].base_addr=0;			dev_port_map[i].port=NULL;		}	}	return 0;}struct pld_hotswap_ops uart00_pldhs_ops={	.name		= "uart00",	.add_device	= uart00_add_device,	.remove_devices	= uart00_remove_devices,};#endifstatic int __init uart00_init(void){	int result;	printk(KERN_INFO "Serial: UART00 driver $Revision: 1.35 $\n");	printk(KERN_WARNING "serial_uart00:Using temporary major/minor pairs"		" - these WILL change in the future\n");	result = uart_register_driver(&uart00_reg);	if (result)		return result;#ifdef CONFIG_ARCH_CAMELOT	result = uart_add_one_port(&uart00_reg,&epxa10db_port);#endif	if (result)		uart_unregister_driver(&uart00_reg);#ifdef  CONFIG_PLD_HOTSWAP	pldhs_register_driver(&uart00_pldhs_ops);#endif	return result;}__initcall(uart00_init);

⌨️ 快捷键说明

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