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

📄 at91_serial.c

📁 嵌入式 linux 扩展串口 驱动 测试程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* parity */	if (cflag & PARENB) {		if (cflag & CMSPAR) {			/* Mark or Space parity */			if (cflag & PARODD)				mode |= AT91C_US_PAR_MARK;			else				mode |= AT91C_US_PAR_SPACE;		}		else if (cflag & PARODD)			mode |= AT91C_US_PAR_ODD;		else			mode |= AT91C_US_PAR_EVEN;	}	else		mode |= AT91C_US_PAR_NONE;	port->read_status_mask |= AT91C_US_OVRE;	if (iflag & INPCK)		port->read_status_mask |= AT91C_US_FRAME | AT91C_US_PARE;	if (iflag & (BRKINT | PARMRK))		port->read_status_mask |= AT91C_US_RXBRK;	/*	 * Characters to ignore	 */	port->ignore_status_mask = 0;	if (iflag & IGNPAR)		port->ignore_status_mask |= (AT91C_US_FRAME | AT91C_US_PARE);	if (iflag & IGNBRK) {		port->ignore_status_mask |= AT91C_US_RXBRK;		/*		 * If we're ignoring parity and break indicators,		 * ignore overruns too (for real raw support).		 */		if (iflag & IGNPAR)			port->ignore_status_mask |= AT91C_US_OVRE;	}	// TODO: Ignore all characters if CREAD is set.	/* first, disable interrupts and drain transmitter */	local_irq_save(flags);	imr = UART_GET_IMR(port);	/* get interrupt mask */	UART_PUT_IDR(port, -1);		/* disable all interrupts */	local_irq_restore(flags);	while (!(UART_GET_CSR(port) & AT91C_US_TXEMPTY)) { barrier(); }	/* disable receiver and transmitter */	UART_PUT_CR(port, AT91C_US_TXDIS | AT91C_US_RXDIS);	/* set the parity, stop bits and data size */	UART_PUT_MR(port, mode);	/* set the baud rate */	UART_PUT_BRGR(port, quot);	UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN);	/* restore interrupts */	UART_PUT_IER(port, imr);	/* CTS flow-control and modem-status interrupts */	if (UART_ENABLE_MS(port, cflag))		at91_pops.enable_ms(port);}/* * Return string describing the specified port */static const char *at91_type(struct uart_port *port){  return port->type == PORT_AT91RM9200 ? "AT91_SERIAL" : NULL;}/* * Release the memory region(s) being used by 'port'. */static void at91_release_port(struct uart_port *port){  release_mem_region(port->mapbase,    port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K);}/* * Request the memory region(s) being used by 'port'. */static int at91_request_port(struct uart_port *port){  return request_mem_region(port->mapbase,    port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K,    "at91_serial") != NULL ? 0 : -EBUSY;}/* * Configure/autoconfigure the port. */static void at91_config_port(struct uart_port *port, int flags){  if (flags & UART_CONFIG_TYPE) {    port->type = PORT_AT91RM9200;    at91_request_port(port);  }}/* * Verify the new serial_struct (for TIOCSSERIAL). */static int at91_verify_port(struct uart_port *port, struct serial_struct *ser){  int ret = 0;  if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200)    ret = -EINVAL;  if (port->irq != ser->irq)    ret = -EINVAL;  if (ser->io_type != SERIAL_IO_MEM)    ret = -EINVAL;  if (port->uartclk / 16 != ser->baud_base)    ret = -EINVAL;  if ((void *)port->mapbase != ser->iomem_base)    ret = -EINVAL;  if (port->iobase != ser->port)    ret = -EINVAL;  if (ser->hub6 != 0)    ret = -EINVAL;  return ret;}//added by wujh@hyesco.comstatic int at91_port_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg){	  unsigned long flags;	  unsigned int mode,imr;	  int ret = -ENOIOCTLCMD;          unsigned int control = 0;	  	 switch (cmd) 	{		 case UART_RS485_CONFIG:		 if(port->line)                 {                  /* Get current mode register */                 mode = UART_GET_MR(port) & ~(AT91C_US_USMODE); 	                 mode |= AT91C_US_USMODE_RS485 ;	       	        	        local_irq_save(flags);	        imr = UART_GET_IMR(port);	/* get interrupt mask */	        UART_PUT_IDR(port, -1);		/* disable all interrupts */	        local_irq_restore(flags);        	while (!(UART_GET_CSR(port) & AT91C_US_TXEMPTY)) { barrier(); }	        /* disable receiver and transmitter */	        UART_PUT_CR(port, AT91C_US_TXDIS | AT91C_US_RXDIS);	        /* set the rs485 mode */	        UART_PUT_MR(port, mode); 	        UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN);                /* restore interrupts */                UART_PUT_IER(port, imr);                 printk("\n\r config mode succeed! \r\n");                }        		break;		                case UART_RS485_READ:                     if (port->mapbase == AT91C_VA_BASE_US0) {                        AT91_SYS->PIOA_CODR = AT91C_PA21_RTS0;                     }                     else if (port->mapbase == AT91C_VA_BASE_US3) {                        AT91_SYS->PIOB_CODR = AT91C_PB0_RTS3;                     }                            break;                case UART_RS485_WRITE:                     if (port->mapbase == AT91C_VA_BASE_US0) {                        AT91_SYS->PIOA_SODR = AT91C_PA21_RTS0;                     }                     else if (port->mapbase == AT91C_VA_BASE_US3) {                        AT91_SYS->PIOB_SODR = AT91C_PB0_RTS3;                     }                break;	  default:	  break;	}	 	 return ret;}static struct uart_ops at91_pops = {  tx_empty: at91_tx_empty,  set_mctrl:  at91_set_mctrl,  get_mctrl:  at91_get_mctrl,  stop_tx:  at91_stop_tx,  start_tx: at91_start_tx,  stop_rx:  at91_stop_rx,  enable_ms:  at91_enable_ms,  break_ctl:  at91_break_ctl,  startup:  at91_startup,  shutdown: at91_shutdown,  change_speed: at91_change_speed,  type:   at91_type,  release_port: at91_release_port,  request_port: at91_request_port,  config_port:  at91_config_port,  verify_port:  at91_verify_port,  ioctl:        at91_port_ioctl,	//added by wujh@hyesco.com};static struct uart_port at91_ports[AT91C_NR_UART];void __init at91_init_ports(void){	static int first = 1;	int i;	if (!first)		return;	first = 0;	for (i = 0; i < AT91C_NR_UART; i++) {		at91_ports[i].iotype	= SERIAL_IO_MEM;		at91_ports[i].flags     = ASYNC_BOOT_AUTOCONF;		at91_ports[i].uartclk   = AT91C_MASTER_CLOCK;		at91_ports[i].ops	= &at91_pops;		at91_ports[i].fifosize  = 1;		at91_ports[i].line	= i; 	}}void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns){  if (fns->enable_ms)    at91_pops.enable_ms = fns->enable_ms;  if (fns->get_mctrl)    at91_pops.get_mctrl = fns->get_mctrl;  if (fns->set_mctrl)    at91_pops.set_mctrl = fns->set_mctrl;  at91_open          = fns->open;  at91_close         = fns->close;  at91_pops.pm       = fns->pm;  at91_pops.set_wake = fns->set_wake;}/* * Setup ports. */void __init at91_register_uart(int idx, int port){	if ((idx < 0) || (idx >= AT91C_NR_UART)) {		printk(KERN_ERR __FUNCTION__ ": bad index number %d\n", idx);		return;	}	switch (port) {	case 0:		at91_ports[idx].membase = (void *) AT91C_VA_BASE_US0;		at91_ports[idx].mapbase = AT91C_VA_BASE_US0;		at91_ports[idx].irq     = AT91C_ID_US0;		AT91_CfgPIO_USART0();		break;	case 1:		at91_ports[idx].membase = (void *) AT91C_VA_BASE_US1;		at91_ports[idx].mapbase = AT91C_VA_BASE_US1;		at91_ports[idx].irq     = AT91C_ID_US1;		AT91_CfgPIO_USART1();		break;	case 2:		at91_ports[idx].membase = (void *) AT91C_VA_BASE_US2;		at91_ports[idx].mapbase = AT91C_VA_BASE_US2;		at91_ports[idx].irq     = AT91C_ID_US2;		AT91_CfgPIO_USART2();		break;	case 3:		at91_ports[idx].membase = (void *) AT91C_VA_BASE_US3;		at91_ports[idx].mapbase = AT91C_VA_BASE_US3;		at91_ports[idx].irq     = AT91C_ID_US3;		AT91_CfgPIO_USART3();		break;	case 4:		at91_ports[idx].membase = (void *) AT91C_VA_BASE_DBGU;		at91_ports[idx].mapbase = AT91C_VA_BASE_DBGU;		at91_ports[idx].irq     = AT91C_ID_SYS;		AT91_CfgPIO_DBGU();		break;	default:		printk(KERN_ERR __FUNCTION__ ": bad port number %d\n", port);	}}#ifdef CONFIG_SERIAL_AT91_CONSOLE/* * Interrupts are disabled on entering */static void at91_console_write(struct console *co, const char *s, u_int count){  struct uart_port *port = at91_ports + co->index;  unsigned int status, i, imr;	/*	 *	First, save IMR and then disable interrupts	 */	imr = UART_GET_IMR(port);	/* get interrupt mask */	UART_PUT_IDR(port, AT91C_US_RXRDY | AT91C_US_TXRDY);	/*	 *	Now, do each character	 */	for (i = 0; i < count; i++) {		do {			status = UART_GET_CSR(port);		} while (!(status & AT91C_US_TXRDY));		UART_PUT_CHAR(port, s[i]);		if (s[i] == '\n') {			do {				status = UART_GET_CSR(port);			} while (!(status & AT91C_US_TXRDY));			UART_PUT_CHAR(port, '\r');		}	}	/*	 *	Finally, wait for transmitter to become empty	 *	and restore IMR	 */	do {		status = UART_GET_CSR(port);	} while (!(status & AT91C_US_TXRDY));	UART_PUT_IER(port, imr);	/* set interrupts back the way they were */}static kdev_t at91_console_device(struct console *co){  return MKDEV(SERIAL_AT91_MAJOR, MINOR_START + co->index);}/* * If the port was already initialised (eg, by a boot loader), try to determine * the current setup. */static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits){	unsigned int mr, quot;// TODO: CR is a write-only register//	unsigned int cr;////	cr = UART_GET_CR(port) & (AT91C_US_RXEN | AT91C_US_TXEN);//	if (cr == (AT91C_US_RXEN | AT91C_US_TXEN)) {//		/* ok, the port was enabled */////    mr = UART_GET_MR(port) & AT91C_US_PAR;////    *parity = 'n';//    if (mr == AT91C_US_PAR_EVEN)//      *parity = 'e';//    else if (mr == AT91C_US_PAR_ODD)//      *parity = 'o';//  }  mr = UART_GET_MR(port) & AT91C_US_CHRL;  if (mr == AT91C_US_CHRL_8_BITS)    *bits = 8;  else    *bits = 7;  quot = UART_GET_BRGR(port);  *baud = port->uartclk / (16 * (quot));}static int __init at91_console_setup(struct console *co, char *options){	struct uart_port *port;	int baud = AT91C_CONSOLE_DEFAULT_BAUDRATE;	int bits = 8;	int parity = 'n';	int flow = 'n';	/*	 * Check whether an invalid uart number has been specified, and	 * if so, search for the first available port that does have	 * console support.	 */	port = uart_get_console(at91_ports, AT91C_NR_UART, co);	// TODO: The console port should be initialized, and clock enabled if	//  we're not relying on the bootloader to do it.	if (options)		uart_parse_options(options, &baud, &parity, &bits, &flow);	else		at91_console_get_options(port, &baud, &parity, &bits);  return uart_set_options(port, co, baud, parity, bits, flow);}static struct console at91_console = {  name:   "ttyS",  write:    at91_console_write,  device:   at91_console_device,  setup:    at91_console_setup,  flags:    CON_PRINTBUFFER,  index:    AT91C_CONSOLE,};#define AT91_CONSOLE_DEVICE &at91_consolevoid __init at91_console_init(void){	at91_init_ports();	register_console(&at91_console);}#else#define AT91_CONSOLE_DEVICE NULL#endifstruct uart_driver at91_reg = {  owner:      THIS_MODULE,  normal_major:   SERIAL_AT91_MAJOR,#ifdef CONFIG_DEVFS_FS  normal_name:    "ttyS%d",  callout_name:   "cua%d",#else  normal_name:    "ttyS",  callout_name:   "cua",#endif	normal_driver:		&normal,	callout_major:		CALLOUT_AT91_MAJOR,	callout_driver:		&callout,	table:			at91_table,	termios:		at91_termios,	termios_locked:		at91_termios_locked,	minor:			MINOR_START,//added by wujh@hyesco.com#ifdef SUPPORT_TL16C554	nr:			AT91C_NR_UART+4,#else	nr:			AT91C_NR_UART,#endif	cons:			AT91_CONSOLE_DEVICE,};static int __init at91_serial_init(void){	int ret, i;	at91_init_ports();	ret = uart_register_driver(&at91_reg);	if (ret)		return ret;	for (i = 0; i < AT91C_NR_UART; i++) {		if (at91_serialmap[i] >= 0)			uart_add_one_port(&at91_reg, &at91_ports[i]);	}	return 0;}static void __exit at91_serial_exit(void){	int i;	for (i = 0; i < AT91C_NR_UART; i++) { 		if (at91_serialmap[i] >= 0)			uart_remove_one_port(&at91_reg, &at91_ports[i]);  	}	uart_unregister_driver(&at91_reg);}//added by wujh@hyesco.comEXPORT_SYMBOL(at91_reg);module_init(at91_serial_init);module_exit(at91_serial_exit);MODULE_AUTHOR("Rick Bronson");MODULE_DESCRIPTION("AT91 generic serial port driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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