📄 omap24xx-uart.c
字号:
printk(KERN_INFO "FIR Mode : Changing UART speed to %d....", speed); mdr1_data &= MODE_SELECT_MASK; mdr1_data |= UART_FIR_MODE; outb(mdr1_data, uart_base + REG_MDR1); printk("Done\n"); } else { printk(KERN_ERR "!!! Requested speed is not supported!!!!!!\n"); goto exit_path1; } } else if (uart_mode[uart_no] == UART_MODE) { if (speed <= UART_16X_SPEED) { printk(KERN_INFO "16X Mode : Changing UART speed to %d....\n", speed); divisor = BASE_CLK / (16 * speed); outb(divisor & 0xFF, uart_base + REG_DLL); outb(divisor >> 8, uart_base + REG_DLH); mdr1_data &= MODE_SELECT_MASK; mdr1_data |= UART_16X_MODE; outb(mdr1_data, uart_base + REG_MDR1); printk("Done\n"); } else if (speed <= UART_13X_SPEED) { printk(KERN_INFO "13X Mode : Changing UART speed to %d....\n", speed); divisor = BASE_CLK / (13 * speed); outb(divisor & 0xFF, uart_base + REG_DLL); outb(divisor >> 8, uart_base + REG_DLH); mdr1_data &= MODE_SELECT_MASK; mdr1_data |= UART_13X_MODE; outb(mdr1_data, uart_base + REG_MDR1); printk("Done\n"); } else { printk(KERN_ERR "!!! Requested speed is not supported!!!!!!\n"); goto exit_path1; } } else if (uart_mode[uart_no] == UART_AUTOBAUD_MODE) { printk(KERN_INFO " UART%d 16X Auto baud Mode\n", uart_no); mdr1_data &= MODE_SELECT_MASK; mdr1_data |= UART_16XAUTO_MODE; outb(mdr1_data, uart_base + REG_MDR1); } else if (uart_mode[uart_no] == CIR_MODE) { printk(KERN_INFO " UART%d CIR Mode\n", uart_no); mdr1_data &= MODE_SELECT_MASK; mdr1_data |= UART_CIR_MODE; outb(mdr1_data, uart_base + REG_MDR1); } else { printk(KERN_ERR "Invalid parameters for UART speed change!!!!!!!\n"); goto exit_path1; } /* restore LCR values */ outb(lcr_data, uart_base + REG_LCR); spin_unlock(&(ui[uart_no].uart_lock)); FN_OUT(0); return 0; exit_path1: /* Restore LCR and MDR1 regisgters to original value */ outb(mdr1_data, uart_base + REG_MDR1); outb(lcr_data, uart_base + REG_LCR); spin_unlock(&(ui[uart_no].uart_lock)); FN_OUT(EPERM); return -EPERM;}EXPORT_SYMBOL(omap24xx_uart_set_speed);/** * brief omap24xx_uart_config * configures the requested UART * param uart_no * param uartcfg * * return */int omap24xx_uart_config(int uart_no, struct uart_config *uartcfg){ u32 uart_base = UART_MODULE_BASE(uart_no); u8 reg_data = 0; struct clk *uarti = NULL, *uartf = NULL; FN_IN; if (in_interrupt()) BUG(); if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) { D3(KERN_INFO "C Bad uart id %d \n", uart_no); return -EPERM; } /* Start clock for requested UART */ if (get_uart_clocks(&uarti, &uartf, uart_no)) { printk(KERN_ERR "UART clock configuration error\n"); return -ENOENT; } clk_enable(uarti); clk_enable(uartf); spin_lock(&(ui[uart_no].uart_lock)); uart_mode[uart_no] = uartcfg->mode; /* Put UART3 in reset mode */ reg_data = UART_DISABLE; outb(reg_data, uart_base + REG_MDR1); /* Clear DLL and DLH */ reg_data = LCR_MODE2; outb(reg_data, uart_base + REG_LCR); reg_data = BIT_DLL_CLOCK_LSB; outb(reg_data, uart_base + REG_DLL); reg_data = BIT_DLH_CLOCK_MSB; outb(reg_data, uart_base + REG_DLH); reg_data = 0; outb(reg_data, uart_base + REG_SCR); reg_data = LCR_MODE3; outb(reg_data, uart_base + REG_LCR); reg_data = (uartcfg->efr); outb(reg_data, uart_base + REG_EFR); reg_data = LCR_MODE2; outb(reg_data, uart_base + REG_LCR); /* enable TCR and TLR Registers */ reg_data = ENABLE_TCR_TLR; outb(reg_data, uart_base + REG_MCR); reg_data = (uartcfg->tlr); outb(reg_data, uart_base + REG_TLR); reg_data = (uartcfg->lcr); outb(reg_data, uart_base + REG_LCR); reg_data = (uartcfg->fcr); outb(reg_data, uart_base + REG_FCR); /* disable access to TCR and TLR registers */ reg_data = DISABLE_TCR_TLR; outb(reg_data, uart_base + REG_MCR); reg_data = (uartcfg->scr) | (BIT_SCR_TX_TRIG_GRANU1_M | BIT_SCR_RX_TRIG_GRANU1_M); outb(reg_data, uart_base + REG_SCR); reg_data = (uartcfg->mdr1); outb(reg_data, uart_base + REG_MDR1); reg_data = (uartcfg->mdr2); outb(reg_data, uart_base + REG_MDR2); reg_data = (uartcfg->acreg); outb(reg_data, uart_base + REG_ACREG); reg_data = (uartcfg->ier); outb(reg_data, uart_base + REG_IER); if (uart_mode[uart_no] == IRDA_MODE) { reg_data = (uartcfg->rxfll); outb(reg_data, uart_base + REG_RXFLL); reg_data = (uartcfg->rxflh); outb(reg_data, uart_base + REG_RXFLH); } readb(uart_base + REG_RESUME); spin_unlock(&(ui[uart_no].uart_lock)); FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_config);/** * brief omap24xx_uart_stop * stops/resets requested UART. * param uart_no * * return */int omap24xx_uart_stop(int uart_no){ u32 uart_base = UART_MODULE_BASE(uart_no); u8 reg_data; struct clk *uarti = NULL, *uartf = NULL; FN_IN; if (in_interrupt()) BUG(); if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) { D3(KERN_INFO "C Bad uart id %d \n", uart_no); return -EPERM; } /* Stop clock for requested UART */ get_uart_clocks(&uarti, &uartf, uart_no); clk_disable(uarti); clk_disable(uartf); spin_lock(&(ui[uart_no].uart_lock)); /* Put UART3 in reset mode */ reg_data = BIT_MDR1_MODE_SELECT_M; outb(reg_data, uart_base + REG_MDR1); /* Clear DLL and DLH */ reg_data = LCR_MODE2; outb(reg_data, uart_base + REG_LCR); reg_data = BIT_DLL_CLOCK_LSB; outb(reg_data, uart_base + REG_DLL); reg_data = BIT_DLH_CLOCK_MSB; outb(reg_data, uart_base + REG_DLH); /* Disable requested UART interrupts */ reg_data = 0; outb(reg_data, uart_base + REG_IER); /* Stop DMA channels */ omap_stop_dma(ui[uart_no].rx_dma_channel); omap_stop_dma(ui[uart_no].tx_dma_channel); /* Move buffer states to free */ ui[uart_no].tx_buf_state = FREE; ui[uart_no].rx_buf_state = FREE; spin_unlock(&(ui[uart_no].uart_lock)); FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_stop);/** * brief omap24xx_uart_rx * Copies data from DMA buffer to user * driver buffer. * param uart_no * param data * param len * * return */int omap24xx_uart_rx(int uart_no, void *data, int *len){ unsigned long flags; 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_irqsave(&(ui[uart_no].uart_lock), flags); if (uart_cb[uart_no].mode == UART_DMA_MODE) { *len = omap_get_dma_dst_pos(ui[uart_no].rx_dma_channel); *len -= ui[uart_no].rx_buf_dma_phys; memcpy(data, ui[uart_no].rx_buf_dma_virt, *len); /* DMA data is copied to user driver buffer, * now it is safe to move rx_buf_state to free. */ ui[uart_no].rx_buf_state = FREE; } else { } spin_unlock_irqrestore(&(ui[uart_no].uart_lock), flags); FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_rx);/** * brief omap24xx_uart_tx * copies data from client driver buffer * to DMA buffer. * param uart_no * param data * param size * * return */int omap24xx_uart_tx(int uart_no, void *data, int size){ unsigned long flags; FN_IN; if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) { D3(KERN_INFO "C Bad uart id %d \n", uart_no); return -EPERM; } if (unlikely(size < 0 || size > uart_cb[uart_no].tx_buf_size)) { D3(KERN_INFO "Error...Invalid buffer size!!!!\n"); return -EPERM; } spin_lock_irqsave(&(ui[uart_no].uart_lock), flags); D3("omap24xx_uart_tx : %s\n", data); D3("omap24xx_uart_tx : %d\n", size); if (uart_cb[uart_no].mode == UART_DMA_MODE) { memcpy(ui[uart_no].tx_buf_dma_virt, data, size); } else { } spin_unlock_irqrestore(&(ui[uart_no].uart_lock), flags); FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_tx);/** * brief omap24xx_uart_start_tx * Starts transferring data from DMA tx channel * param uart_no * param size * * return */int omap24xx_uart_start_tx(int uart_no, int size){ u32 uart_base = UART_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 -EPERM; } if (ui[uart_no].tx_buf_state == USED) { D3("Error : UART DMA buffer is not free...!!!\n"); return -EAGAIN; } if (uart_cb[uart_no].mode == UART_DMA_MODE) { omap_set_dma_dest_params(ui[uart_no].tx_dma_channel, 0, // dest_port is only for OMAP1 OMAP_DMA_AMODE_CONSTANT, uart_base, 0, 0); omap_set_dma_src_params(ui[uart_no].tx_dma_channel, 0, // src_port is only for OMAP1 OMAP_DMA_AMODE_POST_INC, ui[uart_no].tx_buf_dma_phys, 0, 0); omap_set_dma_transfer_params(ui[uart_no].tx_dma_channel, OMAP_DMA_DATA_TYPE_S8, size, 1, OMAP_DMA_SYNC_ELEMENT, uart_dma_tx[uart_no], 0); omap_start_dma(ui[uart_no].tx_dma_channel); ui[uart_no].tx_buf_state = USED; } FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_start_tx);/** * brief omap24xx_uart_start_rx * Starts receiving data from DMA rx channel * param uart_no * param size * * return */int omap24xx_uart_start_rx(int uart_no, int size){ u32 uart_base = UART_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 -EPERM; } if (ui[uart_no].rx_buf_state == USED) { D3("Error : UART DMA buffer is not free...!!!\n"); return -EAGAIN; } if (uart_cb[uart_no].mode == UART_DMA_MODE) { omap_set_dma_src_params(ui[uart_no].rx_dma_channel, 0, // src_port is only for OMAP1 OMAP_DMA_AMODE_CONSTANT, uart_base, 0, 0); omap_set_dma_dest_params(ui[uart_no].rx_dma_channel, 0, // dest_port is only for OMAP1 OMAP_DMA_AMODE_POST_INC, ui[uart_no].rx_buf_dma_phys, 0, 0); omap_set_dma_transfer_params(ui[uart_no].rx_dma_channel, OMAP_DMA_DATA_TYPE_S8, size, 1, OMAP_DMA_SYNC_ELEMENT, uart_dma_rx[uart_no], 0); OMAP_DMA_CDAC_REG(ui[uart_no].rx_dma_channel) = ui[uart_no].rx_buf_dma_phys; if (ui[uart_no].timeout !=0) { /* Start dma */ omap_start_dma(ui[uart_no].rx_dma_channel); ui[uart_no].rx_buf_state = USED; /* Start timer */ ui[uart_no].timer_active = 1; add_timer(&ui[uart_no].timer); } else { /* Start dma */ omap_start_dma(ui[uart_no].rx_dma_channel); ui[uart_no].rx_buf_state = USED; } } FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_start_rx);/** * brief omap24xx_uart_stop_rx * * param uart_no * * return */int omap24xx_uart_stop_rx(int 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 -EPERM; } if (uart_cb[uart_no].mode == UART_DMA_MODE) { omap_stop_dma(ui[uart_no].rx_dma_channel); OMAP_DMA_CDAC_REG(ui[uart_no].rx_dma_channel) = ui[uart_no].rx_buf_dma_phys; del_timer(&ui[uart_no].timer); ui[uart_no].timer_active = 0; } FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_stop_rx);/** * brief omap24xx_uart_stop_tx * * param uart_no * * return */int omap24xx_uart_stop_tx(int 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 -EPERM; } if (uart_cb[uart_no].mode == UART_DMA_MODE) { omap_stop_dma(ui[uart_no].tx_dma_channel); } FN_OUT(0); return 0;}EXPORT_SYMBOL(omap24xx_uart_stop_tx);/** * brief omap24xx_uart_interrupt * used to enable/disable * UART interrupts. * param uart_no * param enable *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -