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

📄 at91_tl16c554.c

📁 嵌入式 linux 扩展串口 驱动 测试程序
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* * Perform initialization and enable port for reception */static int tl16c554_startup(struct uart_port *port){     int retval=0;	   	//   DPRINTK("\n\\rtl16c554_startup!\n\r");		   	   	  /*	   * If there is a specific "open" function (to register	   * control line interrupts)	   */	  if (tl16c554_open) 	  {		   retval = tl16c554_open(port);		   if (retval) 		   {			   return retval;		   }	  }	   port->read_status_mask = TL16C554_US_RXRDY | TL16C554_US_THRE | TL16C554_US_TEMT | TL16C554_US_OVRE			| TL16C554_US_PARE  | TL16C554_US_FRAME | TL16C554_US_BREAKI;		   /*	    * Finally, clear and enable interrupts	    */     //设置波特率     UART_PUT_IDR (port, -1);     UART_PUT_BRGR(port,QUTO_DEFAULT);     UART_PUT_LCR (port,LCR_CONFIG_DEFAULT);     UART_PUT_MCR (port,MCR_CONFIG_DEFAULT);	   UART_PUT_IER(port, TL16C554_RX_FULL);	   UART_PUT_FCR(port, TL16C554_EN);	   	   return 0;}/* * Disable the port */static void tl16c554_shutdown(struct uart_port *port){	  int status;	  	//  DPRINTK("\n\\rtl16c554_shutdown!\n\r");		  	  	  if (tl16c554_close)		tl16c554_close(port);	 /*	  * Clear all Err status and Disable all interrupts.	  */	  status = UART_GET_LSR(port);	  UART_PUT_IDR(port, -1);	 	 /* disable the tl16c554 */	  UART_PUT_FCR(port, TL16C554_DIS);}static struct uart_ops tl16c554_pops;		/* forward declaration *//* * Change the port parameters */static void tl16c554_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot){    unsigned long flags;    unsigned int mode,imr;	  //DPRINTK("\n\\rtl16c554_change_speed!\n\r");	          /* Get current mode register */          mode = UART_GET_LCR(port) & ~(AT91C_US_CHRL | AT91C_US_NBSTOP | AT91C_US_PAR);        	  /* byte size */	  switch (cflag & CSIZE) 	  {  	 case CS5:	       mode |= TL16C554_US_CHRL_5_BITS;		 break;		   case CS6:		     mode |= TL16C554_US_CHRL_6_BITS;		 break;		   case CS7:		     mode |= TL16C554_US_CHRL_7_BITS;		 break;		   default:	       mode |= TL16C554_US_CHRL_8_BITS;		 break;	  }	  /* stop bits */	  if (cflag & CSTOPB)		mode |= TL16C554_US_NBSTOP_2_BIT;	  /* parity */	  if (cflag & PARENB) 	  {		  if (cflag & PARODD)			   mode |= TL16C554_US_PAR_ODD;		  else if(cflag & PARENB)			   mode |= TL16C554_US_PAR_EVEN;	  }	  else		  mode |= TL16C554_US_PAR_NONE;	    port->read_status_mask |= TL16C554_US_OVRE;	  	  if (iflag & INPCK)		  port->read_status_mask |= TL16C554_US_FRAME | TL16C554_US_PARE;		  if (iflag & (BRKINT | PARMRK))		  port->read_status_mask |= TL16C554_US_BREAKI;	  /*	   * Characters to ignore	   */	  port->ignore_status_mask = 0;	  	  if (iflag & IGNPAR)		port->ignore_status_mask |= (TL16C554_US_FRAME | TL16C554_US_PARE);			  if (iflag & IGNBRK) {		port->ignore_status_mask |= TL16C554_US_BREAKI;		/*		 * If we're ignoring parity and break indicators,		 * ignore overruns too (for real raw support).		 */		  if (iflag & IGNPAR)			port->ignore_status_mask |= TL16C554_US_OVRE;	  }	  // TODO: Ignore all characters if CREAD is set.	  /* first, disable interrupts and drain transmitter */	  local_irq_save(flags);          imr = UART_GET_IER(port);     	/* get interrupt status */	  UART_PUT_IDR(port, -1);		/* disable all interrupts */	  local_irq_restore(flags);        	  //while (!(UART_GET_LSR(port) & TL16C554_US_TEMT)) 	  //{ barrier(); }	  /* disable the tl16c554 */	  UART_PUT_FCR(port, TL16C554_DIS);	  /* set the parity, stop bits and data size */	  UART_PUT_LCR(port, mode);	  /* set the baud rate */	  UART_PUT_BRGR(port, quot);	  	  /* restore interrupts */	  UART_PUT_IER(port, imr);	  	  UART_PUT_FCR(port, TL16C554_EN);	  /* CTS flow-control and modem-status interrupts */	  if (UART_ENABLE_MS(port, cflag))		tl16c554_pops.enable_ms(port);         // DPRINTK("\n\\rexit tl16c554_change_speed!\n\r");}/* * Return string describing the specified port */static const char *tl16c554_type(struct uart_port *port){    return port->type == PORT_AT91RM9200 ? "TL16C554_SERIAL" : NULL;}/* * Release the memory region(s) being used by 'port'. */static void tl16c554_release_port(struct uart_port *port){ }/* * Request the memory region(s) being used by 'port'. */static int tl16c554_request_port(struct uart_port *port){    return 0;}/* * Configure/autoconfigure the port. */static void tl16c554_config_port(struct uart_port *port, int flags){    if (flags & UART_CONFIG_TYPE) {     port->type = PORT_AT91RM9200;    }}/* * Verify the new serial_struct (for TIOCSSERIAL). */static int tl16c554_verify_port(struct uart_port *port, struct serial_struct *ser){    int ret = 0;    return ret;}static struct uart_ops tl16c554_pops = {    tx_empty:      tl16c554_tx_empty,    set_mctrl:     tl16c554_set_mctrl,    get_mctrl:     tl16c554_get_mctrl,    stop_tx:       tl16c554_stop_tx,    start_tx:      tl16c554_start_tx,    stop_rx:       tl16c554_stop_rx,    enable_ms:     tl16c554_enable_ms,    break_ctl:     tl16c554_break_ctl,    startup:       tl16c554_startup,    shutdown:      tl16c554_shutdown,    change_speed:  tl16c554_change_speed,    type:          tl16c554_type,    release_port:  tl16c554_release_port,    request_port:  tl16c554_request_port,    config_port:   tl16c554_config_port,    verify_port:   tl16c554_verify_port,};/* * Setup ports. */void __init tl16c554_register_uart(int idx, int port){	  	  DPRINTK("\n\\rtl16c554_register_uart!\n\r");			  	  if ((idx < 0) || (idx >= TL16C554_NR_UART)) {		  printk(KERN_ERR __FUNCTION__ ": bad index number %d\n", idx);		  return;	  }	  switch (port) 	  {	   case 5:		     tl16c554_ports[idx].membase = (void *) TL16C554_VA_BASE_ADDR5;		     tl16c554_ports[idx].mapbase = TL16C554_BASE_ADDR_USA5;		     tl16c554_ports[idx].irq     = TL16C554_PIO5;		 break;			   case 6:		     tl16c554_ports[idx].membase = (void *) TL16C554_VA_BASE_ADDR6;		     tl16c554_ports[idx].mapbase = TL16C554_BASE_ADDR_USB6;		     tl16c554_ports[idx].irq     = TL16C554_PIO6;		 break;			   case 7:		     tl16c554_ports[idx].membase = (void *) TL16C554_VA_BASE_ADDR7;		     tl16c554_ports[idx].mapbase = TL16C554_BASE_ADDR_USC7;		     tl16c554_ports[idx].irq     = TL16C554_PIO7;		 break;			   case 8:		     tl16c554_ports[idx].membase = (void *) TL16C554_VA_BASE_ADDR8;		     tl16c554_ports[idx].mapbase = TL16C554_BASE_ADDR_USD8;		     tl16c554_ports[idx].irq     = TL16C554_PIO8;		 break;			   default:		 printk(KERN_ERR __FUNCTION__ ": bad port number %d\n", port);	  }}void __init tl16c554_init_ports(void){	  static int first_in = 1;	  int i;	  	  DPRINTK("\n\\rtl16c554_init_ports!\n\r");		  	  if (!first_in)		return;	  first_in = 0;	  for (i = 0; i < TL16C554_NR_UART; i++) {		tl16c554_ports[i].iotype   = SERIAL_IO_MEM;		tl16c554_ports[i].flags    = ASYNC_BOOT_AUTOCONF;		tl16c554_ports[i].uartclk  = TL16C554_CLOCK;		tl16c554_ports[i].ops	     = &tl16c554_pops;		tl16c554_ports[i].fifosize = 1;		tl16c554_ports[i].line	   = i+5;				if (tl16c554_serialmap[i] >= 0)    tl16c554_register_uart(i, tl16c554_serialmap[i]); 	  }}extern struct uart_driver at91_reg ;static int __init at91_tl16c554_init(void){	  int  i,retval;	  	  DPRINTK("\n\\rat91_tl16c554_init!\n\r");		     AT91_SYS->PIOC_PDR  |= 0x2000;    AT91_SYS->PIOC_ASR  |= 0x2000;        AT91_SYS->EBI_SMC2_CSR[7] = 0x11003183; 	  //addr iomap	  if(!request_mem_region(TL16C554_BASE_ADDR_USA5,VA_SIZE,"tl16c554_serial_A"))	  { printk("tl16c554_serial: can't request mem for serial_a\n"); return -EBUSY; }	  TL16C554_VA_BASE_ADDR5 = (unsigned long)ioremap(TL16C554_BASE_ADDR_USA5,VA_SIZE);	  if(!request_mem_region(TL16C554_BASE_ADDR_USB6,VA_SIZE,"tl16c554_serial_B"))	  { printk("tl16c554_serial: can't request mem for serial_b\n"); return -EBUSY; } 	  TL16C554_VA_BASE_ADDR6 = (unsigned long)ioremap(TL16C554_BASE_ADDR_USB6,VA_SIZE);	  	  if(!request_mem_region(TL16C554_BASE_ADDR_USC7,VA_SIZE,"tl16c554_serial_A"))	  { printk("tl16c554_serial: can't request mem for serial_c\n"); return -EBUSY; }	  TL16C554_VA_BASE_ADDR7 = (unsigned long)ioremap(TL16C554_BASE_ADDR_USC7,VA_SIZE);	  	  	  if(!request_mem_region(TL16C554_BASE_ADDR_USD8,VA_SIZE,"tl16c554_serial_A"))	  { printk("tl16c554_serial: can't request mem for serial_d\n"); return -EBUSY; }	  TL16C554_VA_BASE_ADDR8 = (unsigned long)ioremap(TL16C554_BASE_ADDR_USD8,VA_SIZE);	  	          //GPIO config          //AT91_SYS->PIOA_PER  |= 0x1;                //AT91_SYS->PIOA_ODR  |= 0x1;           AT91_SYS->AIC_IDCR |= 0x1<< AT91C_ID_PIOA; //Disable interrupt          AT91_SYS->AIC_ICCR |= 0x1<< AT91C_ID_PIOA;	  AT91_SYS->PIOA_PER   |= (TL16C554_PIO5 | TL16C554_PIO6 | TL16C554_PIO7 | TL16C554_PIO8) ; //Enable peripheral control of the pin PIOA3	  AT91_SYS->PIOA_ODR   |= (TL16C554_PIO5 | TL16C554_PIO6 | TL16C554_PIO7 | TL16C554_PIO8); //Assign the I/O PIOA3 to the Peripheral B functiom	  AT91_SYS->PIOA_IFER  |= (TL16C554_PIO5 | TL16C554_PIO6 | TL16C554_PIO7 | TL16C554_PIO8);          AT91_SYS->PIOA_IER   |= (TL16C554_PIO5 | TL16C554_PIO6 | TL16C554_PIO7 | TL16C554_PIO8);	          AT91_SYS->PMC_PCER |= 0x1<< AT91C_ID_PIOA;// enable clock */    //init the tc16c554 uart	  tl16c554_init_ports();	  for (i = 0; i < TL16C554_NR_UART; i++) 	  {		  if (tl16c554_serialmap[i] >= 0)			uart_add_one_port(&at91_reg, &tl16c554_ports[i]);	  }    DPRINTK("\n\rtl16c554_serial request irq!\n\r");	  	  //request irq	  retval = request_irq(AT91C_ID_PIOA, tl16c554_interrupt, SA_INTERRUPT, "tl16c554_serial", NULL);	  if (retval) {		printk("tl16c554_serial: - Can't get irq\n");		return retval;	  }	            DPRINTK("\n\rtl16c554_serial request irq succeed!\n\r");          AT91_SYS->AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_PRIOR_LOWEST|AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE ;          //enable the irq          retval  = AT91_SYS->PIOA_ISR ;          	  AT91_SYS->AIC_IECR |= 0x1<< AT91C_ID_PIOA;	                DPRINTK("\n\rtl16c554_serial succeed!\n\r");  	return 0;}static void __exit at91_tl16c554_exit(void){	int i;         free_irq(AT91C_ID_PIOA,NULL);	for (i = 0; i < TL16C554_NR_UART; i++) { 		if (tl16c554_serialmap[i] >= 0)			uart_remove_one_port(&at91_reg, &tl16c554_ports[i]);  	}        iounmap((void*)TL16C554_VA_BASE_ADDR5);        iounmap((void*)TL16C554_VA_BASE_ADDR6);        iounmap((void*)TL16C554_VA_BASE_ADDR7);        iounmap((void*)TL16C554_VA_BASE_ADDR8);        release_mem_region(TL16C554_BASE_ADDR_USA5,VA_SIZE);        release_mem_region(TL16C554_BASE_ADDR_USB6,VA_SIZE);        release_mem_region(TL16C554_BASE_ADDR_USC7,VA_SIZE);        release_mem_region(TL16C554_BASE_ADDR_USD8,VA_SIZE);}module_init(at91_tl16c554_init);module_exit(at91_tl16c554_exit);EXPORT_NO_SYMBOLS;MODULE_AUTHOR("Wujh@hyesco.com");MODULE_DESCRIPTION("AT91 tl16c554 serial port driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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