Files
TAIXIN/sdk/driver/uart/hguart_v2.c

1067 lines
28 KiB
C
Raw Normal View History

/**
* @file hguart_v2.c
* @author bxd
* @brief normal uart
* @version
* TXW80X; TXW81X
* @date 2023-08-02
*
* @copyright Copyright (c) 2023
*
*/
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "osal/irq.h"
#include "osal/string.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "hal/uart.h"
#include "dev/uart/hguart_v2.h"
#include "hguart_v2_hw.h"
#include "osal/sleep.h"
#define UART_FLAG_TDMA_BUSY (0x1)
/**********************************************************************************/
/* LOW LAYER FUNCTION */
/**********************************************************************************/
static int32 hguart_v2_switch_hal_uart_parity(enum uart_parity param)
{
switch (param) {
case (UART_PARITY_NONE):
return 0;
break;
case (UART_PARITY_ODD):
return 1;
break;
case (UART_PARITY_EVEN):
return 2;
break;
default:
return -1;
break;
}
}
static int32 hguart_v2_switch_hal_uart_stop_bit(enum uart_stop_bit param)
{
switch (param) {
case (UART_STOP_BIT_1):
return 0;
break;
case (UART_STOP_BIT_2):
return 1;
break;
default:
return -1;
break;
}
}
static int32 hguart_v2_switch_hal_uart_data_bit(enum uart_data_bit param)
{
switch (param) {
case (UART_DATA_BIT_8):
return 0;
break;
case (UART_DATA_BIT_9):
return 1;
break;
default:
return -1;
break;
}
}
static int32 hguart_v2_set_data_bit(struct hguart_v2_hw *p_uart, enum uart_data_bit data_bit)
{
int32 data_bit_to_reg = 0;
data_bit_to_reg = hguart_v2_switch_hal_uart_data_bit(data_bit);
if (((-1) == data_bit_to_reg)) {
return RET_ERR;
}
if (data_bit_to_reg) {
p_uart->CON |= LL_UART_CON_BIT9_EN;
} else {
p_uart->CON &= ~ LL_UART_CON_BIT9_EN;
}
return RET_OK;
}
static int32 hguart_v2_set_parity(struct hguart_v2_hw *p_uart, enum uart_parity parity)
{
int32 parity_to_reg = 0;
parity_to_reg = hguart_v2_switch_hal_uart_parity(parity);
if (((-1) == parity_to_reg)) {
return RET_ERR;
}
switch (parity_to_reg) {
case (0):
p_uart->CON &= ~(LL_UART_CON_PARITY_EN | LL_UART_CON_ODD_EN);
break;
case (1):
p_uart->CON |= LL_UART_CON_PARITY_EN | LL_UART_CON_ODD_EN;
break;
case (2):
p_uart->CON = (p_uart->CON & ~(LL_UART_CON_ODD_EN)) | LL_UART_CON_PARITY_EN;
break;
}
return RET_OK;
}
static int32 hguart_v2_set_stop_bit(struct hguart_v2_hw *p_uart, enum uart_stop_bit stop_bit)
{
int32 stop_bit_to_reg = 0;
stop_bit_to_reg = hguart_v2_switch_hal_uart_stop_bit(stop_bit);
if (((-1) == stop_bit_to_reg)) {
return RET_ERR;
}
if (stop_bit_to_reg) {
p_uart->CON |= LL_UART_CON_STOP_BIT(1);
} else {
p_uart->CON &= ~ LL_UART_CON_STOP_BIT(1);
}
return RET_OK;
}
static int32 hguart_v2_set_time_out(struct hguart_v2_hw *p_uart, uint32 time_bit, uint32 enable)
{
if (enable) {
p_uart->TOCON = (p_uart->TOCON & ~ LL_UART_TOCON_TO_BIT_LEN(0xFFFF)) | LL_UART_TOCON_TO_BIT_LEN(time_bit) | LL_UART_TOCON_TO_EN;
} else {
p_uart->TOCON = 0;
}
return RET_OK;
}
static int32 hguart_v2_set_dma(struct hguart_v2 *dev, uint32 enable)
{
if (enable) {
dev->use_dma = 1;
} else {
dev->use_dma = 0;
}
return RET_OK;
}
static int32 hguart_v2_set_baudrate(struct hguart_v2_hw *p_uart, uint32 baudrate)
{
p_uart->BAUD = (peripheral_clock_get(HG_APB0_PT_UART0) / baudrate - 1);
return RET_OK;
}
static int32 hguart_v2_set_mode(struct hguart_v2_hw *p_uart, uint32 mode)
{
switch (mode) {
case UART_MODE_DUPLEX:
p_uart->CON &= ~ LL_UART_CON_WORK_MODE(0x3);
p_uart->CON |= LL_UART_CON_WORK_MODE(0);
break;
case UART_MODE_SIMPLEX_TX:
p_uart->CON &= ~ LL_UART_CON_WORK_MODE(0x3);
p_uart->CON |= LL_UART_CON_WORK_MODE(1);
break;
case UART_MODE_SIMPLEX_RX:
p_uart->CON &= ~ LL_UART_CON_WORK_MODE(0x3);
p_uart->CON |= LL_UART_CON_WORK_MODE(2);
break;
default:
return -ENOTSUPP;
}
return RET_OK;
}
static void hguart_v2_dma_tx_config(struct hguart_v2_hw *p_uart, uint8 status)
{
uint32 _dmacon = p_uart->DMACON;
if (status) {
_dmacon |= LL_UART_DMACON_TX_DMA_EN;
} else {
_dmacon &= ~ BIT(0);
_dmacon |= BIT(8);
}
p_uart->DMACON = _dmacon;
}
static int32 hguart_v2_dma_rx_config(struct hguart_v2_hw *p_uart, uint8 status)
{
uint32 _dmacon = p_uart->DMACON;
if (status) {
_dmacon |= LL_UART_DMACON_RX_DMA_EN;
} else {
_dmacon &= ~ BIT(1);
_dmacon |= BIT(9);
}
p_uart->DMACON = _dmacon;
return 0;
}
// static int32 hguart_v2_rs485_config(struct hguart_v2_hw *p_uart, uint8 enable,
// uint8 re_sig_active_level, uint8 de_sig_active_level,
// uint32 de_deassertion_time, uint32 de_assertion_time,
// uint32 de2re_turnaround_time, uint32 re2de_turnaround_time)
// {
// struct hguart_v2 *dev = (struct hguart_v2 *)p_uart;
// struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
// if (enable) {
// hw->RS485_DET = LL_UART_RS485_DET_DE_AT(de_assertion_time) | LL_UART_RS485_DET_DE_DAT(de_deassertion_time);
// hw->RS485_TAT = LL_UART_RS485_TAT_DE2RE_T(de2re_turnaround_time) | LL_UART_RS485_TAT_RE2DE_T(re2de_turnaround_time);
// hw->RS485_CON = LL_UART_RS485_CON_DE_EN | LL_UART_RS485_CON_RE_EN | \
// LL_UART_RS485_CON_RS485_MODE(1) | \
// LL_UART_RS485_CON_RE_POL(re_sig_active_level)| \
// LL_UART_RS485_CON_DE_POL(de_sig_active_level)| \
// LL_UART_RS485_CON_RS485_EN;
// } else {
// hw->RS485_CON = 0;
// hw->RS485_DET = 0;
// hw->RS485_TAT = 0;
// }
// // hw->RS485_DET = LL_UART_RS485_DET_DE_AT(200) | LL_UART_RS485_DET_DE_DAT(100);
// // hw->RS485_TAT = LL_UART_RS485_TAT_DE2RE_T(400) | LL_UART_RS485_TAT_RE2DE_T(300);
// //
// // hw->RS485_CON = LL_UART_RS485_CON_DE_EN | LL_UART_RS485_CON_RE_EN | \
// // LL_UART_RS485_CON_RS485_MODE(1) |\
// // LL_UART_RS485_CON_RE_POL(1)|\
// // LL_UART_RS485_CON_DE_POL(0)|\
// // LL_UART_RS485_CON_RS485_EN;
// return RET_OK;
// }
static int32 hguart_v2_rs485det_set(struct hguart_v2_hw *p_uart, uint32 de_deassertion_time, uint32 de_assertion_time)
{
struct hguart_v2_hw *hw = p_uart;
hw->RS485_DET = LL_UART_RS485_DET_DE_AT(de_assertion_time) | LL_UART_RS485_DET_DE_DAT(de_deassertion_time);
return RET_OK;
}
static int32 hguart_v2_rs485tat_set(struct hguart_v2_hw *p_uart, uint32 de2re_turnaround_time, uint32 re2de_turnaround_time)
{
struct hguart_v2_hw *hw = p_uart;
hw->RS485_TAT = LL_UART_RS485_TAT_DE2RE_T(de2re_turnaround_time) | LL_UART_RS485_TAT_RE2DE_T(re2de_turnaround_time);
return RET_OK;
}
static int32 hguart_v2_rs485dre_pol_set(struct hguart_v2_hw *p_uart, uint8 re_sig_active_level, uint8 de_sig_active_level)
{
struct hguart_v2_hw *hw = p_uart;
hw->RS485_CON &= ~(LL_UART_RS485_CON_RE_POL(1)|LL_UART_RS485_CON_DE_POL(1));
hw->RS485_CON |= LL_UART_RS485_CON_RE_POL(re_sig_active_level)| \
LL_UART_RS485_CON_DE_POL(de_sig_active_level);
return RET_OK;
}
static int32 hguart_v2_rs485_en(struct hguart_v2_hw *p_uart, uint8 enable)
{
struct hguart_v2_hw *hw = p_uart;
if (enable) {
hw->RS485_DET = LL_UART_RS485_DET_DE_AT(200) | LL_UART_RS485_DET_DE_DAT(100);
hw->RS485_TAT = LL_UART_RS485_TAT_DE2RE_T(400) | LL_UART_RS485_TAT_RE2DE_T(300);
hw->RS485_CON = LL_UART_RS485_CON_DE_EN | LL_UART_RS485_CON_RE_EN | \
LL_UART_RS485_CON_RS485_MODE(1) | \
LL_UART_RS485_CON_RE_POL(1)| \
LL_UART_RS485_CON_DE_POL(0)| \
LL_UART_RS485_CON_RS485_EN;
} else {
hw->RS485_CON = 0;
hw->RS485_DET = 0;
hw->RS485_TAT = 0;
}
return RET_OK;
}
static int32 hguart_v2_hw_control_config(struct hguart_v2_hw *p_uart, uint8 enable)
{
struct hguart_v2 *dev = (struct hguart_v2 *)p_uart;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
if (enable) {
hw->CON |= LL_UART_CON_CTS_EN | LL_UART_CON_RTS_EN;
hw->RS485_CON = 0;
hw->RS485_DET = 0;
hw->RS485_TAT = 0;
} else {
hw->CON &= ~(LL_UART_CON_CTS_EN | LL_UART_CON_RTS_EN);
hw->RS485_CON = 0;
hw->RS485_DET = 0;
hw->RS485_TAT = 0;
}
return RET_OK;
}
/**********************************************************************************/
/* ATTCH FUNCTION */
/**********************************************************************************/
static int32 hguart_v2_open(struct uart_device *uart, uint32 baudrate)
{
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
if (dev->opened) {
if (!dev->dsleep) {
return -EBUSY;
}
}
if ((baudrate < 0) || ((peripheral_clock_get(HG_APB0_PT_UART0) / baudrate) > 0x0003ffff)) {
return RET_ERR;
}
/* pin config */
if (pin_func(dev->dev.dev.dev_id, 1) != RET_OK) {
return RET_ERR;
}
/*
* open UART clk
*/
if (UART0_BASE == (uint32)hw) {
sysctrl_uart0_clk_open();
} else if (UART1_BASE == (uint32)hw) {
sysctrl_uart1_clk_open();
}
/* clear reg */
hw->CON = 0;
hw->BAUD = 0;
hw->STA = 0xFFFFFFFF;
hw->DMACON = 0;
hw->DMASTA = 0xFFFFFFFF;
hw->RSTADR = 0;
hw->TSTADR = 0;
hw->RDMALEN = 0;
hw->TDMALEN = 0;
hw->TOCON = 0;
hw->RS485_CON = 0;
hw->RS485_DET = 0;
hw->RS485_TAT = 0;
/* reg config */
#ifndef FPGA_SUPPORT
hw->BAUD = (peripheral_clock_get(HG_APB0_PT_UART0) / baudrate) - 1;
#else
hw->BAUD = (96000000 / baudrate) - 1;
#endif
hw->CON = 0x1; /* Default config: 8bit + 1 stop_bit + no parity + duplex mode */
dev->opened = 1;
dev->dsleep = 0;
return RET_OK;
}
static int32 hguart_v2_close(struct uart_device *uart)
{
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
if (!dev->opened) {
return RET_OK;
}
/*
* close UART clk
*/
if (UART0_BASE == (uint32)hw) {
sysctrl_uart0_clk_close();
} else if (UART1_BASE == (uint32)hw) {
sysctrl_uart1_clk_close();
}
hw->CON &= ~0x1;
irq_disable(dev->irq_num);
pin_func(dev->dev.dev.dev_id, 0);
dev->opened = 0;
dev->dsleep = 0;
return RET_OK;
}
static int32 hguart_v2_rs485_de_set(struct hguart_v2_hw *p_uart)
{
if(PIN_UART0_DE != 255) {
ll_uart485_de_enable(p_uart);
return RET_OK;
}
return RET_ERR;
}
static int32 hguart_v2_rs485_de_reset(struct hguart_v2_hw *p_uart)
{
if(PIN_UART0_DE != 255) {
ll_uart485_de_disable(p_uart);
return RET_OK;
// p_uart->RS485_CON &= (~LL_UART_RS485_CON_DE_EN);
}
// os_printf("%s:%d\n", __FUNCTION__, __LINE__);
return RET_ERR;
}
static int32 hguart_v2_rs485_re_set(struct hguart_v2_hw *p_uart)
{
if(PIN_UART4_RE != 255) {
ll_uart485_re_enable(p_uart);
return RET_OK;
}
return RET_ERR;
}
static int32 hguart_v2_rs485_re_reset(struct hguart_v2_hw *p_uart)
{
if(PIN_UART4_RE != 255) {
ll_uart485_re_disable(p_uart);
return RET_OK;
}
return RET_ERR;
}
static int32 hguart_v2_putc(struct uart_device *uart, int8 value)
{
uint8 rs485_en_flag = 0;
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
if (dev->opened && (hw->CON & LL_UART_CON_UART_EN) && (!dev->dsleep)) {
if (hw->RS485_CON & LL_UART_RS485_CON_RS485_EN) {
hguart_v2_rs485_en(hw, 0);
rs485_en_flag = 1;
}
while (!(hw->STA & LL_UART_STA_TX_BUF_EMPTY));
hw->DATA = value;
if(rs485_en_flag) {
rs485_en_flag = 0;
hguart_v2_rs485_en(hw, 1);
}
return RET_OK;
} else {
return -EIO;
}
}
static uint8 hguart_v2_getc(struct uart_device *uart)
{
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
if (dev->opened && (hw->CON & LL_UART_CON_UART_EN) && (!dev->dsleep)) {
while (!(hw->STA & LL_UART_STA_RX_BUF_NOT_EMPTY));
}
return hw->DATA;
}
static int32 hguart_v2_puts(struct uart_device *uart, uint8 *buf, uint32 len)
{
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
int32 i = 0;
uint32_t irq_flag;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
if(hw->RS485_CON & LL_UART_RS485_CON_RS485_EN) {
hguart_v2_rs485_de_set(hw);
hguart_v2_rs485_re_set(hw);
}
if (((__PSRAM_ADDR_START <= (uint32)buf)) && (((uint32)buf) <= __PSRAM_ADDR_END)) {
for (i = 0; i < len; i++) {
hguart_v2_putc(uart, buf[i]);
}
} else {
if (dev->use_dma) {
irq_flag = disable_irq();
/* Clear the former configuration */
hguart_v2_dma_tx_config(hw, 0);
/* clear the tx dma done pending before tx kick */
hw->DMASTA = BIT(0);
hw->TSTADR = (uint32)buf;
hw->TDMALEN = len;
hguart_v2_dma_tx_config(hw, 1);
dev->flag |= UART_FLAG_TDMA_BUSY;
enable_irq(irq_flag);
//TDMA_IE_EN会造成两种情况
if ((hw->DMACON & LL_UART_DMACON_TX_DMA_IE_EN)
&& (!irq_flag)) {
while(dev->flag & UART_FLAG_TDMA_BUSY);
} else {
while (!(hw->DMASTA & LL_UART_DMASTA_TX_DMA_PEND)) {
//休眠唤醒后pending位被清零了 防卡死
if(!hw->TDMALEN) {
break;
}
}
}
} else {
for (i = 0; i < len; i++) {
hguart_v2_putc(uart, buf[i]);
}
}
}
if(hw->RS485_CON & LL_UART_RS485_CON_RS485_EN) {
hguart_v2_rs485_de_reset(hw);
hguart_v2_rs485_re_reset(hw);
}
irq_flag = disable_irq();
dev->flag &= ~UART_FLAG_TDMA_BUSY;
enable_irq(irq_flag);
return RET_OK;
}
static int32 hguart_v2_gets(struct uart_device *uart, uint8 *buf, uint32 len)
{
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
int32 i = 0;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
if (((__PSRAM_ADDR_START <= (uint32)buf)) && (((uint32)buf) <= __PSRAM_ADDR_END)) {
for (i = 0; i < len; i++) {
buf[i] = hguart_v2_getc(uart);
}
return i;
} else {
if (dev->use_dma) {
/* Clear the former configuration */
hguart_v2_dma_rx_config(hw, 0);
hw->STA = BIT(1);
hw->RSTADR = (uint32)buf;
hw->RDMALEN = len;
hguart_v2_dma_rx_config(hw, 1);
return RET_OK;
} else {
for (i = 0; i < len; i++) {
buf[i] = hguart_v2_getc(uart);
}
return i;
}
}
}
struct uart_testS {
struct uart_device *uart;
uint8_t *buf;
int len;
int id;
};
static int32 uart_test_irqhdl(uint32 irq_flag, uint32 irq_data, uint32 param1, uint32 param2)
{
struct uart_testS *tuart = (struct uart_testS *)irq_data;
int32 ret = 0;
switch (irq_flag) {
case UART_IRQ_FLAG_DMA_RX_DONE: // maybe overbuff?
case UART_IRQ_FLAG_TIME_OUT:
if (tuart->id == 1) {
if (memcmp(tuart->buf, "uart5 msg", 9) != 0) {
os_printf("uart1 recv lp err\r\n");
}
} else if (tuart->id == 5) {
if (memcmp(tuart->buf, "uart1 msg", 9) != 0) {
os_printf("uart5 recv lp err\r\n");
}
}
tuart->buf[param1] = 0;
os_printf("id = %d, recv: %s\r\n", tuart->id, tuart->buf);
uart_gets(tuart->uart, tuart->buf, tuart->len);
break;
default:
break;
}
return ret;
}
void uart_sleep_test()
{
uint8_t *uart1_buf = os_malloc(32);
uint8_t *uart5_buf = os_malloc(32);
struct uart_device *uart1 = (void *)dev_get(1+1);
struct uart_device *uart5 = (void *)dev_get(1+5);
uint8_t uart1_msg[] = "uart1 msg\r\n";
//uint8_t uart5_msg[] = "uart5 msg\r\n";
struct uart_testS uart1ts = {
.uart = uart1,
.buf = uart1_buf,
.len = 32,
.id = 1,
};
struct uart_testS uart5ts = {
.uart = uart5,
.buf = uart5_buf,
.len = 32,
.id = 5,
};
uart_open(uart1, 921600);
uart_open(uart5, 921600);
uart_ioctl(uart1, UART_IOCTL_CMD_USE_DMA, 1, 0);
uart_ioctl(uart5, UART_IOCTL_CMD_USE_DMA, 1, 0);
uart_ioctl(uart1, UART_IOCTL_CMD_SET_TIME_OUT, 40, 1);
uart_ioctl(uart5, UART_IOCTL_CMD_SET_TIME_OUT, 40, 1);
uart_request_irq(uart1, uart_test_irqhdl,
UART_IRQ_FLAG_DMA_RX_DONE | UART_IRQ_FLAG_TIME_OUT, (uint32)&uart1ts);
// uart_request_irq(uart1, uart_test_irqhdl,
// UART_IRQ_FLAG_DMA_RX_DONE, (uint32)&uart1ts);
uart_request_irq(uart5, uart_test_irqhdl,
UART_IRQ_FLAG_DMA_RX_DONE | UART_IRQ_FLAG_TIME_OUT, (uint32)&uart5ts);
uart_gets(uart1, uart1_buf, 32);
uart_gets(uart5, uart5_buf, 32);
while(1)
{
// uart_puts(uart5, uart5_msg, os_strlen((const char *)uart5_msg));
uart_puts(uart1, uart1_msg, os_strlen((const char *)uart1_msg));
os_sleep_ms(1000);
}
}
#ifdef CONFIG_SLEEP
int32 hguart_v2_suspend(struct dev_obj *obj)
{
struct hguart_v2 *dev = (struct hguart_v2 *)obj;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_OK;
}
uint32_t disable = disable_irq();
enable_irq(disable);
while(dev->flag & UART_FLAG_TDMA_BUSY);
hw->TDMALEN = 0;
/*
* save the reglist
*/
dev->bp_regs.con = hw->CON;
dev->bp_regs.baud = hw->BAUD;
dev->bp_regs.tstadr = hw->TSTADR|0x20000000;
dev->bp_regs.rstadr = hw->RSTADR|0x20000000;
dev->bp_regs.tdmalen = hw->TDMALEN;
dev->bp_regs.rdmalen = hw->RDMALEN;
dev->bp_regs.dmacon = hw->DMACON;
dev->bp_regs.rs485_con = hw->RS485_CON;
dev->bp_regs.rs485_det = hw->RS485_DET;
dev->bp_regs.rs485_tat = hw->RS485_TAT;
dev->bp_regs.tocon = hw->TOCON;
/*!
* Close the UART
*/
hw->DMACON = 0x300; //disable dma
hw->CON &= ~ BIT(0);
// pin_func(dev->dev.dev.dev_id, 0);
irq_disable(dev->irq_num);
/*
* clear pending
*/
hw->DMASTA = 0xFFFFFFFF;
hw->STA = 0xFFFFFFFF;
/*
* clear the data in the UART fifo
*/
do {
hw->DATA;
} while (hw->STA & LL_UART_STA_RX_CNT(0x7));
if (UART0_BASE == (uint32)hw) {
sysctrl_uart0_clk_close();
} else if (UART1_BASE == (uint32)hw) {
sysctrl_uart1_clk_close();
}
dev->dsleep = 1;
return RET_OK;
}
int32 hguart_v2_resume(struct dev_obj *obj)
{
struct hguart_v2 *dev = (struct hguart_v2 *)obj;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
if ((!dev->opened) || (!dev->dsleep)) {
return RET_OK;
}
/* pin config */
if (pin_func(dev->dev.dev.dev_id, 1) != RET_OK) {
return RET_ERR;
}
if (UART0_BASE == (uint32)hw) {
sysctrl_uart0_clk_open();
} else if (UART1_BASE == (uint32)hw) {
sysctrl_uart1_clk_open();
}
/*
* clear pending
*/
hw->DMASTA = 0xFFFFFFFF;
hw->STA = 0xFFFFFFFF;
/*
* recovery the reglist from sram
*/
hw->CON = dev->bp_regs.con;
hw->BAUD = dev->bp_regs.baud;
hw->TSTADR = dev->bp_regs.tstadr;
hw->RSTADR = dev->bp_regs.rstadr;
hw->TDMALEN = dev->bp_regs.tdmalen;
hw->RDMALEN = dev->bp_regs.rdmalen;
hw->DMACON = dev->bp_regs.dmacon;
hw->RS485_CON = dev->bp_regs.rs485_con;
hw->RS485_DET = dev->bp_regs.rs485_det;
hw->RS485_TAT = dev->bp_regs.rs485_tat;
hw->TOCON = dev->bp_regs.tocon;
/*!
* Open the UART
*/
hw->CON |= BIT(0);
if (dev->bp_regs.dmacon & LL_UART_DMACON_RX_DMA_EN)
hguart_v2_dma_rx_config(hw, 1);
irq_enable(dev->irq_num);
dev->dsleep = 0;
return RET_OK;
}
#else
int32 hguart_v2_suspend(struct dev_obj *obj)
{
return RET_ERR;
}
int32 hguart_v2_resume(struct dev_obj *obj)
{
return RET_ERR;
}
#endif
static int32 hguart_v2_ioctl(struct uart_device *uart, enum uart_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2)
{
int32 ret_val = RET_OK;
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
switch (ioctl_cmd) {
case (UART_IOCTL_CMD_SET_BAUDRATE):
ret_val = hguart_v2_set_baudrate(hw, param1);
break;
case (UART_IOCTL_CMD_SET_DATA_BIT):
ret_val = hguart_v2_set_data_bit(hw, param1);
break;
case (UART_IOCTL_CMD_SET_PARITY):
ret_val = hguart_v2_set_parity(hw, param1);
break;
case (UART_IOCTL_CMD_SET_STOP_BIT):
ret_val = hguart_v2_set_stop_bit(hw, param1);
break;
case (UART_IOCTL_CMD_SET_TIME_OUT):
ret_val = hguart_v2_set_time_out(hw, param1, param2);
break;
case (UART_IOCTL_CMD_USE_DMA):
ret_val = hguart_v2_set_dma(dev, param1);
break;
case (UART_IOCTL_CMD_SET_WORK_MODE):
ret_val = hguart_v2_set_mode(hw, param1);
break;
case (UART_IOCTL_CMD_SET_RS485_EN):
ret_val = hguart_v2_rs485_en(hw, param1);
break;
case (UART_IOCTL_CMD_SET_RS485_DET):
ret_val = hguart_v2_rs485det_set(hw, param1, param2);
break;
case (UART_IOCTL_CMD_SET_RS485_TAT):
ret_val = hguart_v2_rs485tat_set(hw, param1, param2);
break;
case (UART_IOCTL_CMD_SET_RS485DRE_POL):
ret_val = hguart_v2_rs485dre_pol_set(hw, param1, param2);
break;
default:
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
static void hguart_v2_irq_handler(void *data)
{
struct hguart_v2 *dev = (struct hguart_v2 *)data;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
static uint8 rec_data_len[2] = {0};
/*------Time out interrupt-----*/
if ((hw->TOCON & LL_UART_TOCON_TO_IE_EN) &&
(hw->STA & LL_UART_STA_TO_PEND)) {
hw->STA = LL_UART_STA_TO_PEND;
if (dev->irq_hdl) {
rec_data_len[1] = hw->RDMACNT >> 8;
rec_data_len[0] = hw->RDMACNT;
dev->irq_hdl(UART_IRQ_FLAG_TIME_OUT, dev->irq_data, hw->RDMACNT, 0);
if((PIN_UART0_DE != 255) && (PIN_UART0_RE != 255)) {
uart_puts((struct uart_device *)dev, rec_data_len, sizeof(rec_data_len));
}
}
}
/*------Frame erro interrupt-----*/
if ((hw->CON & LL_UART_CON_FERR_IE_EN) &&
(hw->STA & LL_UART_STA_FERR_PENDING)) {
hw->STA = LL_UART_STA_FERR_PENDING;
if (dev->irq_hdl) {
dev->irq_hdl(UART_IRQ_FLAG_FRAME_ERR, dev->irq_data, 0, 0);
}
}
/*------TX complete interrupt-----*/
if ((hw->CON & LL_UART_CON_TCIE_EN) &&
(hw->STA & LL_UART_STA_TC_PENDING)) {
hw->STA = LL_UART_STA_TC_PENDING;
if (dev->irq_hdl) {
dev->irq_hdl(UART_IRQ_FLAG_TX_BYTE, dev->irq_data, 0, 0);
}
}
/*------RX_DMA_INTERRUPT-----*/
if ((hw->DMACON & LL_UART_DMACON_RX_DMA_IE_EN) &&
(hw->DMASTA & LL_UART_DMASTA_RX_DMA_PEND)) {
hw->DMASTA = LL_UART_DMASTA_RX_DMA_PEND;
if (dev->irq_hdl) {
dev->irq_hdl(UART_IRQ_FLAG_DMA_RX_DONE, dev->irq_data, hw->RDMACNT, 0);
}
}
/*------TX_DMA_INTERRUPT-----*/
if ((hw->DMACON & LL_UART_DMACON_TX_DMA_IE_EN) &&
(hw->DMASTA & LL_UART_DMASTA_TX_DMA_PEND)) {
hw->DMASTA = LL_UART_DMASTA_TX_DMA_PEND;
dev->flag &= ~UART_FLAG_TDMA_BUSY;
if (dev->irq_hdl) {
dev->irq_hdl(UART_IRQ_FLAG_DMA_TX_DONE, dev->irq_data, hw->TDMACNT, 0);
}
}
/*------RX buf not empty interrupt-----*/
if ((hw->CON & LL_UART_CON_RXBUF_NEMPTY_IE_EN) &&
(hw->STA & LL_UART_STA_RX_BUF_NOT_EMPTY)) {
if (dev->irq_hdl) {
dev->irq_hdl(UART_IRQ_FLAG_RX_BYTE, dev->irq_data, hw->DATA, 0);
}
}
}
static int32 hguart_v2_request_irq(struct uart_device *uart, uart_irq_hdl irq_hdl, uint32 irq_flag, uint32 irq_data)
{
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
dev->irq_hdl = irq_hdl;
dev->irq_data = irq_data;
request_irq(dev->irq_num, hguart_v2_irq_handler, dev);
if (irq_flag & UART_IRQ_FLAG_TX_BYTE) {
hw->CON |= LL_UART_CON_TCIE_EN;
}
if (irq_flag & UART_IRQ_FLAG_TIME_OUT) {
hw->TOCON |= LL_UART_TOCON_TO_IE_EN;
}
if (irq_flag & UART_IRQ_FLAG_DMA_TX_DONE) {
hw->DMACON |= LL_UART_DMACON_TX_DMA_IE_EN;
}
if (irq_flag & UART_IRQ_FLAG_DMA_RX_DONE) {
hw->DMACON |= LL_UART_DMACON_RX_DMA_IE_EN;
}
if (irq_flag & UART_IRQ_FLAG_FRAME_ERR) {
hw->CON |= LL_UART_CON_FERR_IE_EN;
}
if (irq_flag & UART_IRQ_FLAG_RX_BYTE) {
hw->CON |= LL_UART_CON_RXBUF_NEMPTY_IE_EN;
}
irq_enable(dev->irq_num);
return RET_OK;
}
static int32 hguart_v2_release_irq(struct uart_device *uart, uint32 irq_flag)
{
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
if (irq_flag & UART_IRQ_FLAG_TX_BYTE) {
hw->CON &= ~ LL_UART_CON_TCIE_EN;
}
if (irq_flag & UART_IRQ_FLAG_TIME_OUT) {
hw->TOCON &= ~ LL_UART_TOCON_TO_IE_EN;
}
if (irq_flag & UART_IRQ_FLAG_DMA_TX_DONE) {
hw->DMACON &= ~ LL_UART_DMACON_TX_DMA_IE_EN;
}
if (irq_flag & UART_IRQ_FLAG_DMA_RX_DONE) {
hw->DMACON &= ~ LL_UART_DMACON_RX_DMA_IE_EN;
}
if (irq_flag & UART_IRQ_FLAG_FRAME_ERR) {
hw->CON &= ~ LL_UART_CON_FERR_IE_EN;
}
if (irq_flag & UART_IRQ_FLAG_RX_BYTE) {
hw->CON &= ~ LL_UART_CON_RXBUF_NEMPTY_IE_EN;
}
return RET_OK;
}
static const struct uart_hal_ops uart_v2_ops = {
.open = hguart_v2_open,
.close = hguart_v2_close,
.putc = hguart_v2_putc,
.getc = hguart_v2_getc,
.puts = hguart_v2_puts,
.gets = hguart_v2_gets,
.ioctl = hguart_v2_ioctl,
.request_irq = hguart_v2_request_irq,
.release_irq = hguart_v2_release_irq,
#ifdef CONFIG_SLEEP
.ops.suspend = NULL,//hguart_v2_suspend,
.ops.resume = NULL,//hguart_v2_resume,
#endif
};
int32 hguart_v2_attach(uint32 dev_id, struct hguart_v2 *uart)
{
uart->opened = 0;
uart->dsleep = 0;
uart->use_dma = 0;
uart->irq_hdl = NULL;
uart->irq_data = 0;
uart->flag = 0;
uart->dev.dev.ops = (const struct devobj_ops *)&uart_v2_ops;
#ifdef CONFIG_SLEEP
#endif
irq_disable(uart->irq_num);
dev_register(dev_id, (struct dev_obj *)uart);
return RET_OK;
}