📄 uart00.c
字号:
} /* first, disable everything */ save_flags(flags); cli(); old_ies = UART_GET_IES(port); if ((port->flags & ASYNC_HARDPPS_CD) || (cflag & CRTSCTS) || !(cflag & CLOCAL)) old_ies |= UART_IES_ME_MSK; /* 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); restore_flags(flags);}static int uart00_startup(struct uart_port *port, struct uart_info *info){ int retval; /* * Use iobase to store a pointer to info. We need this to start a * transmission as the tranmittr interrupt is only generated on * the transition to the idle state */ port->iobase=(u_int)info; /* * Allocate the IRQ */ retval = request_irq(port->irq, uart00_int, 0, "uart00", info); if (retval) return retval; /* * 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, struct uart_info *info){ /* * 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, info);}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){ int result; result = request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_uart00") != NULL ? 0 : -EBUSY; if (result) return result; port->membase = ioremap(port->mapbase, SZ_4K); if (!port->membase) { printk(KERN_ERR "serial00: cannot map io memory\n"); release_mem_region(port->mapbase, UART_PORT_SIZE); } return port->membase ? 0 : -ENOMEM;}/* * Configure/autoconfigure the port. */static void uart00_config_port(struct uart_port *port, int flags){ if (flags & UART_CONFIG_TYPE) { if (uart00_request_port(port) == 0) 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, 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, change_speed: uart00_change_speed, type: uart00_type, release_port: uart00_release_port, request_port: uart00_request_port, config_port: uart00_config_port, verify_port: uart00_verify_port,};static struct uart_port uart00_ports[UART_NR] = {#ifdef CONFIG_ARCH_CAMELOT{ 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 = &uart00_ports[0]; 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 kdev_t uart00_console_device(struct console *co){ return MKDEV(SERIAL_UART00_MAJOR, SERIAL_UART00_MINOR + co->index);}static void /*__init*/ uart00_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits){ u_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 = 38400; int bits = 8; int parity = 'n'; int flow= 'n';#ifdef CONFIG_ARCH_CAMELOT /* * Check whether an invalid uart number has been specified, and * if so, search for the first available port that does have * console support. */ port = &uart00_ports[0]; co->index = 0;#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);}static struct console uart00_console = { name: SERIAL_UART00_NAME, write: uart00_console_write, device: uart00_console_device, setup: uart00_console_setup, flags: CON_PRINTBUFFER, index: 0,};void __init uart00_console_init(void){ register_console(&uart00_console);}#define UART00_CONSOLE &uart00_console#else#define UART00_CONSOLE NULL#endifstatic struct uart_driver uart00_reg = { owner: NULL, normal_major: SERIAL_UART00_MAJOR, normal_name: SERIAL_UART00_NAME, normal_driver: &normal, callout_major: CALLOUT_UART00_MAJOR, callout_name: CALLOUT_UART00_NAME, callout_driver: &callout, table: uart00_table, termios: uart00_termios, termios_locked: uart00_termios_locked, minor: SERIAL_UART00_MINOR, nr: UART_NR, port: uart00_ports, state: NULL, cons: UART00_CONSOLE,};struct dev_port_entry{ struct uart_port *port;};static struct dev_port_entry dev_port_map[UART_NR];#ifdef CONFIG_PLD_HOTSWAP/* * 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_register_port(&uart00_reg, port); if(result<0){ printk("uart_register_port returned %d\n",result); return result; } dev_port_map[i].port=port; printk("uart00: added device at %lx as ttyUA%d\n",dev_port_map[i].port->mapbase,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].port){ uart_unregister_port(&uart00_reg,i); /* port removed sucessfully, so now tidy up */ kfree(dev_port_map[i].port); dev_port_map[i].port=NULL; } } return 0;}#if CONFIG_PROC_FSint uart00_proc_read(char* buf,char** start,off_t offset,int count,int *eof,void *data){ int i,len=0; struct uart_port *port; int limit = count - 80; char ps_data[80]; if(*start) buf=*start; for(i=0;(i<UART_NR)&&(len<limit);i++){ if(dev_port_map[i].port){ port=dev_port_map[i].port; sprintf(ps_data,"clk, %dHz, fifo size, %dbytes", port->uartclk,port->fifosize); len+=PLDHS_READ_PROC_DATA(buf+len,"uart00",i, port->mapbase,port->irq,ps_data); } } *eof=1; return len;}#endifstruct pld_hotswap_ops uart00_pldhs_ops={ name: "uart00", add_device: uart00_add_device, remove_devices:uart00_remove_devices, proc_read:uart00_proc_read};#endifstatic int __init uart00_init(void){ int ret; int i; for(i=0;i<UART_NR;i++){ uart00_ports[i].ops=&uart00_pops; } printk(KERN_WARNING "uart00:Using temporary major/minor pairs - these WILL change in the future\n");#ifdef CONFIG_PLD_HOTSWAP pldhs_register_driver(&uart00_pldhs_ops);#endif unregister_console(&uart00_console); ret=uart_register_driver(&uart00_reg); register_console(&uart00_console);#ifdef CONFIG_ARCH_CAMELOT dev_port_map[0].port=uart00_ports;#endif return ret;}__initcall(uart00_init);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -