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 + -
显示快捷键?