📄 omap24xx-uart.c
字号:
* return */int omap24xx_uart_interrupt(int uart_no, int enable){ FN_IN; if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) { D3(KERN_INFO "C Bad uart id %d \n", uart_no); return -ENXIO; } if (enable) enable_irq(uart_irq[uart_no]); else disable_irq(uart_irq[uart_no]); FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_interrupt);/** * brief omap24xx_uart_reset * resets the UART * param uart_no */int omap24xx_uart_reset(int uart_no){ unsigned long flags; u32 uart_base = UART_MODULE_BASE(uart_no); FN_IN; if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) { D3(KERN_INFO "C Bad uart id %d \n", uart_no); return -ENXIO; } spin_lock_irqsave(&(ui[uart_no].uart_lock), flags); /* UART reset sequence */ writeb(uart_base + REG_LCR, LCR_MODE3); writeb(uart_base + REG_EFR, BIT_EFR_ENHANCED_EN); writeb(uart_base + REG_LCR, LCR_MODE1); writeb(uart_base + REG_IER, DISABLE); writeb(uart_base + REG_MCR, DISABLE); writeb(uart_base + REG_MDR1, UART_DISABLE); spin_unlock_irqrestore(&(ui[uart_no].uart_lock), flags); FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_reset);/** * brief omap24xx_uart_request * Allocates requested UART. * param uart_no * param uart_cback */int omap24xx_uart_request(int uart_no, struct uart_callback *uart_cback){ int err; u32 uart_base; u8 sysc_val; FN_IN; if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) { D3(KERN_INFO "C Bad uart id %d \n", uart_no); return -EPERM; } spin_lock(&(ui[uart_no].uart_lock)); if (ui[uart_no].in_use) { printk(KERN_INFO "Err!!!!!!!!......Requested UART is not available\n"); spin_unlock(&(ui[uart_no].uart_lock)); FN_OUT(EACCES); return -EACCES; } uart_base = UART_MODULE_BASE(uart_no); /* Setting UART3 to NoIdle */ sysc_val = readb(uart_base + REG_SYSC); sysc_val |= (0x1 << 3); outb(sysc_val, uart_base + REG_SYSC); spin_unlock(&(ui[uart_no].uart_lock)); printk(KERN_INFO "Error...!!!CONFIG_HS_SERIAL_SUPPORT is not enabled " "during configuration\n"); return -EPERM; if ((uart_cb[uart_no].txrx_req_flag == TXRX) || (uart_cb[uart_no].txrx_req_flag == RX_ONLY)) { if (unlikely (uart_cback->rx_buf_size < 1 || uart_cback->rx_buf_size > MAX_BUF_SIZE)) { printk(KERN_INFO "Err!!!! .... Invalid RX buffer size\n"); FN_OUT(0); return -EACCES; } } if ((uart_cb[uart_no].txrx_req_flag == TXRX) || (uart_cb[uart_no].txrx_req_flag == TX_ONLY)) { if (unlikely (uart_cback->tx_buf_size < 1 || uart_cback->tx_buf_size > MAX_BUF_SIZE)) { printk(KERN_INFO "Err!!!! .... Invalid TX buffer size\n"); FN_OUT(0); return -EACCES; } } if ((uart_cback->mode != UART_DMA_MODE) && (uart_cback->mode != UART_NONDMA_MODE)) { printk ("Error :UART data transfer mode is not defined properly...!!!!\n"); return -EACCES; } if (uart_cback->mode == UART_NONDMA_MODE) { printk("NON DMA mode is supported only in Debug mode. " "Enable Debug mode in UART library\n"); return -EAGAIN; } /* Store the requested mode of tx/rx - DMA/Non DMA */ uart_cb[uart_no].mode = uart_cback->mode; uart_cb[uart_no].dev = uart_cback->dev; uart_cb[uart_no].int_callback = uart_cback->int_callback; uart_cb[uart_no].dev_name = uart_cback->dev_name; if (request_irq (uart_irq[uart_no], (void *)omap24xx_uart_isr, 0, uart_cb[uart_no].dev_name, uart_cb[uart_no].dev)) { printk("Error: IRQ allocation failed\n"); err = -EPERM; goto exit_path0; } spin_lock(&(ui[uart_no].uart_lock)); if (uart_cb[uart_no].mode == UART_DMA_MODE) { uart_cb[uart_no].mode = uart_cback->mode; uart_cb[uart_no].txrx_req_flag = uart_cback->txrx_req_flag; if ((uart_cb[uart_no].txrx_req_flag == TXRX) || (uart_cb[uart_no].txrx_req_flag == RX_ONLY)) { /* Request DMA Channels for requested UART */ err = omap_request_dma (uart_dma_rx[uart_no], "UART Rx DMA", (void *)uart_rx_dma_callback, uart_cb[uart_no].dev, &(ui[uart_no].rx_dma_channel)); if (err) { printk(KERN_ERR "Failed to get DMA Channels\n"); goto exit_path1; } uart_cb[uart_no].rx_buf_size = uart_cback->rx_buf_size; uart_cb[uart_no].uart_rx_dma_callback = uart_cback->uart_rx_dma_callback; ui[uart_no].rx_buf_dma_virt = dma_alloc_coherent(NULL, uart_cb[uart_no]. rx_buf_size, (dma_addr_t *)&(ui [uart_no].rx_buf_dma_phys), 0); if (!ui[uart_no].rx_buf_dma_virt) { printk(KERN_ERR "Failed to allocate DMA Rx Buffer...!!!!\n"); goto exit_path2; } } if ((uart_cb[uart_no].txrx_req_flag == TXRX) || (uart_cb[uart_no].txrx_req_flag == TX_ONLY)) { err = omap_request_dma (uart_dma_tx[uart_no], "UART Tx DMA", (void *)uart_tx_dma_callback, uart_cb[uart_no].dev, &(ui[uart_no].tx_dma_channel)); if (err) { printk(KERN_ERR "Failed to get DMA Channels\n"); goto exit_path3; } uart_cb[uart_no].tx_buf_size = uart_cback->tx_buf_size; uart_cb[uart_no].uart_tx_dma_callback = uart_cback->uart_tx_dma_callback; ui[uart_no].tx_buf_dma_virt = dma_alloc_coherent(NULL, uart_cb[uart_no]. tx_buf_size, (dma_addr_t *)&(ui [uart_no].tx_buf_dma_phys), 0); if (!ui[uart_no].tx_buf_dma_virt) { printk(KERN_ERR "Failed to allocate DMA Tx Buffer...!!!!\n"); goto exit_path4; } } } /* set timer to use for variable length receive. */ if (uart_cb[uart_no].mode == UART_DMA_MODE) { ui[uart_no].timeout = 10; init_timer(&ui[uart_no].timer); ui[uart_no].timer.function = omap24xx_timeout_isr; ui[uart_no].timer.expires = jiffies + msecs_to_jiffies(ui[uart_no].timeout); ui[uart_no].timer.data = uart_no; ui[uart_no].uart_no = uart_no; ui[uart_no].timer_active = 0; } ui[uart_no].tx_buf_state = FREE; ui[uart_no].rx_buf_state = FREE; ui[uart_no].in_use = 1; spin_unlock(&(ui[uart_no].uart_lock)); constr_handle = constraint_get("hsuart", &cnstr_id); constraint_set(constr_handle, CO_LATENCY_MPUOFF_COREON); FN_OUT(0); return 0; exit_path4: omap_free_dma(ui[uart_no].rx_dma_channel); if ((uart_cb[uart_no].txrx_req_flag == TXRX) || (uart_cb[uart_no].txrx_req_flag == TX_ONLY)) { uart_cb[uart_no].tx_buf_size = 0; uart_cb[uart_no].uart_tx_dma_callback = NULL; } exit_path3: if ((uart_cb[uart_no].txrx_req_flag == TXRX) || (uart_cb[uart_no].txrx_req_flag == RX_ONLY)) { dma_free_coherent(uart_cb[uart_no].dev, uart_cb[uart_no].rx_buf_size, ui[uart_no]. rx_buf_dma_virt, ui[uart_no].rx_buf_dma_phys); uart_cb[uart_no].rx_buf_size = 0; uart_cb[uart_no].uart_rx_dma_callback = NULL; } exit_path2: if (uart_cb[uart_no].txrx_req_flag == TXRX || (uart_cb[uart_no].txrx_req_flag == RX_ONLY)) omap_free_dma(ui[uart_no].rx_dma_channel); exit_path1: free_irq(uart_irq[uart_no], uart_cb[uart_no].dev); exit_path0: uart_cb[uart_no].dev = NULL; uart_cb[uart_no].int_callback = NULL; spin_unlock(&(ui[uart_no].uart_lock)); FN_OUT(0); return err;}EXPORT_SYMBOL(omap24xx_uart_request);/** * brief omap24xx_uart_release * release UART * param uart_no * * return */int omap24xx_uart_release(int uart_no){ u32 uart_base; u8 sysc_val; FN_IN; if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) { D3(KERN_INFO "C Bad uart id %d \n", uart_no); return -EPERM; } spin_lock(&(ui[uart_no].uart_lock)); if (!ui[uart_no].in_use) { printk(KERN_INFO "Requested UART is already in free state\n"); spin_unlock(&(ui[uart_no].uart_lock)); FN_OUT(EACCES); return -EACCES; } /* MOVE requested UART to free state. * Free DMA channels. * Free DMA buffers. */ /* Free IRQ, DMA channels and allocated memory. */ free_irq(uart_irq[uart_no], uart_cb[uart_no].dev); if (uart_cb[uart_no].mode == UART_DMA_MODE) { omap_free_dma(ui[uart_no].rx_dma_channel); omap_free_dma(ui[uart_no].tx_dma_channel); dma_free_coherent(uart_cb[uart_no].dev, uart_cb[uart_no].rx_buf_size, ui[uart_no]. rx_buf_dma_virt, ui[uart_no].rx_buf_dma_phys); dma_free_coherent(uart_cb[uart_no].dev, uart_cb[uart_no].tx_buf_size, ui[uart_no]. tx_buf_dma_virt, ui[uart_no].tx_buf_dma_phys); uart_cb[uart_no].uart_tx_dma_callback = NULL; uart_cb[uart_no].uart_rx_dma_callback = NULL; } uart_cb[uart_no].int_callback = NULL; uart_cb[uart_no].dev_name = NULL; uart_cb[uart_no].dev = NULL; ui[uart_no].in_use = 0; ui[uart_no].rx_dma_channel = 0; ui[uart_no].tx_dma_channel = 0; ui[uart_no].rx_buf_dma_phys = 0; ui[uart_no].tx_buf_dma_phys = 0; ui[uart_no].rx_buf_dma_virt = NULL; ui[uart_no].tx_buf_dma_virt = NULL; ui[uart_no].rx_buf_state = 0; ui[uart_no].tx_buf_state = 0; spin_unlock(&(ui[uart_no].uart_lock)); constraint_remove(constr_handle); constraint_put(constr_handle); uart_base = UART_MODULE_BASE(uart_no); /* Setting UART3 to ForceIdle */ sysc_val = readb(uart_base + REG_SYSC); sysc_val &= ~(0x3 << 3); outb(0x0, uart_base + REG_SYSC); FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_release);/** * omap24xx_uart_set_timeout * Set the GP Timer Divisor. * time_ms is in milisecond */int omap24xx_uart_set_timeout(int uart_no, u32 time_ms){ if ((!ui[uart_no].timer_active) && (time_ms != 0)) { ui[uart_no].timeout = time_ms; return 0; } else { ui[uart_no].timeout = time_ms; return -EPERM; }}EXPORT_SYMBOL(omap24xx_uart_set_timeout);/** * brief console_detect * Detect Console UART using command line parameter. * param str * * return */int console_detect(char *str){ extern char *saved_command_line; char *next, *start = NULL; int i; FN_IN; i = strlen(CONSOLE_NAME); next = saved_command_line; while ((next = strchr(next, 'c')) != NULL) { if (!strncmp(next, CONSOLE_NAME, i)) { start = next; break; } else { next++; } } if (!start) return -EPERM; i = 0; start = strchr(start, '=') + 1; while (*start != ',') { str[i++] = *start++; if (i > 6){ printk("Invalid Console Name\n"); return -EPERM; } } str[i] = '\0'; FN_OUT(0); return 0;}/** * brief omap24xx_init_uart * UART initialization * return */static int __init omap24xx_uart_init(void){ char str[7]; int i; FN_IN; spin_lock_init(&(ui[UART1].uart_lock)); spin_lock_init(&(ui[UART2].uart_lock)); spin_lock_init(&(ui[UART3].uart_lock)); /* Reserve the console uart */ if ( console_detect(str)){ printk("Invalid console paramter....UART Library Init Failed!!!!\n"); return -EPERM; } if (!strcmp(str, "ttyS0")) ui[UART1].in_use = 1; else if (!strcmp(str, "ttyS1")) ui[UART2].in_use = 1; else if (!strcmp(str, "ttyS2")) ui[UART3].in_use = 1; else printk(KERN_INFO "!!!!!!!!! Unable to recongnize Console UART........\n"); D3(" Console : %s\n", str); D3("\n ********** Initial UART States *************\n"); D3(" UART1 : %d\n", ui[UART1].in_use); D3(" UART2 : %d\n", ui[UART2].in_use); D3(" UART3 : %d\n", ui[UART3].in_use); /* initialize tx/rx channel */ for (i = UART1; i <= UART3; i++) { ui[i].rx_dma_channel = -1; ui[i].tx_dma_channel = -1; } FN_OUT(0); return 0;}/** * brief omap24xx_init_exit * exit function. * return */static void __exit omap24xx_uart_exit(void){ printk("UART Library Exit\n");}module_init(omap24xx_uart_init);module_exit(omap24xx_uart_exit);MODULE_AUTHOR("Texas Instruments");MODULE_DESCRIPTION("UART Library");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -