592 lines
15 KiB
C
592 lines
15 KiB
C
/*
|
|
* Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "FreeRTOS.h"
|
|
#include "timers.h"
|
|
#include "common.h"
|
|
#include "uart.h"
|
|
#include "register.h"
|
|
#include "soc.h"
|
|
#include "interrupt.h"
|
|
#include "suspend.h"
|
|
#include "string.h"
|
|
#include <stdio.h>
|
|
#include "drv_errno.h"
|
|
#include "timer_source.h"
|
|
#ifdef CONFIG_SOC_A4
|
|
#include "uart-plat.h"
|
|
#endif
|
|
#ifdef CONFIG_BL30_LOG_SAVE
|
|
#include "ring_buffer.h"
|
|
#endif
|
|
|
|
//#define UART_PORT_CONS UART_B_WFIFO
|
|
|
|
#define UART_STP_BIT UART_MODE_MASK_STP_1BIT
|
|
#define UART_PRTY_BIT 0
|
|
#define UART_CHAR_LEN UART_MODE_MASK_CHAR_8BIT
|
|
#define UART_MODE_RESET_MASK \
|
|
(UART_MODE_MASK_RST_TX | UART_MODE_MASK_RST_RX | UART_MODE_MASK_CLR_ERR)
|
|
|
|
#define UART_WFIFO (0 << 2)
|
|
#define UART_RFIFO (1 << 2)
|
|
#define UART_CTRL (2 << 2)
|
|
#define UART_STATUS (3 << 2)
|
|
#define UART_MISC (4 << 2)
|
|
#define UART_REG5 (5 << 2)
|
|
|
|
#define UART_MODE_MASK_2WIRE (1<<15)
|
|
#define UART_MODE_MASK_STP_1BIT (0 << 16)
|
|
#define UART_MODE_MASK_CHAR_8BIT (0 << 20)
|
|
#define UART_MODE_MASK_TX_EN (1 << 12)
|
|
#define UART_MODE_MASK_RX_EN (1 << 13)
|
|
#define UART_MODE_MASK_RST_TX (1 << 22)
|
|
#define UART_MODE_MASK_RST_RX (1 << 23)
|
|
#define UART_MODE_MASK_CLR_ERR (1 << 24)
|
|
#define UART_CTRL_USE_XTAL_CLK (1 << 24)
|
|
#define UART_CTRL_USE_NEW_BAUD_RATE (1 << 23)
|
|
#define UART_CTRL_XTAL_CLK_24M (1 << 26)
|
|
#define UART_CTRL_XTAL_CLK_DIV2 (1<<27)
|
|
|
|
#define UART_MISC_CTS_FILTER (1<<27)
|
|
#define UART_MISC_RX_FILTER (1<<19)
|
|
|
|
#define UART_STAT_MASK_RFIFO_FULL (1 << 19)
|
|
#define UART_STAT_MASK_RX_FIFO_EMPTY (1 << 20)
|
|
#define UART_STAT_MASK_TFIFO_FULL (1 << 21)
|
|
#define UART_STAT_MASK_TFIFO_EMPTY (1 << 22)
|
|
|
|
#define P_UART(uart_base, reg) (uart_base + reg)
|
|
#define P_UART_WFIFO(uart_base) P_UART(uart_base, UART_WFIFO)
|
|
#define P_UART_RFIFO(uart_base) P_UART(uart_base, UART_RFIFO)
|
|
#define P_UART_CTRL(uart_base) P_UART(uart_base, UART_CTRL)
|
|
#define P_UART_STATUS(uart_base) P_UART(uart_base, UART_STATUS)
|
|
#define P_UART_MISC(uart_base) P_UART(uart_base, UART_MISC)
|
|
#define P_UART_REG5(uart_base) P_UART(uart_base, UART_REG5)
|
|
|
|
#define UART_TX_BUF_SIZE (512)
|
|
#define POLL_TX_FIFO_PRD (portTICK_PERIOD_MS)
|
|
#define POLL_TX_BUF_PRD (portTICK_PERIOD_MS * 10)
|
|
#define UART_TXBUF_TASK_PRI (3)
|
|
#define UART_TX_FIFO_FULL_WAIT (5000) //us
|
|
|
|
#define ERR_UART(errno) (DRV_ERRNO_UART_BASE | errno)
|
|
|
|
struct xUartTxBuf_t {
|
|
char *pcTxBuf;
|
|
uint32_t ulRdPtr;
|
|
uint32_t ulWrPtr;
|
|
uint32_t ulBufCnt;
|
|
uint32_t ulTimerPeriod;
|
|
TimerHandle_t xTimer;
|
|
uint8_t ucWarnMsgPrtEn;
|
|
uint8_t ucBufReady;
|
|
};
|
|
|
|
static const char cWarnMsg[] = "\r\nWarning: AOCPU log is lost due to TX FIFO full!";
|
|
static struct xUartTxBuf_t xUartTxBuf;
|
|
|
|
#ifdef ACS_DIS_PRINT_FLAG
|
|
static uint8_t bl30_print_en;
|
|
void enable_bl30_print(uint8_t enable)
|
|
{
|
|
/* Applied to output important logs */
|
|
bl30_print_en = enable;
|
|
}
|
|
|
|
#ifdef CONFIG_STICK_MEM
|
|
#include "stick_mem.h"
|
|
#include "mailbox-api.h"
|
|
/* Applied to enable or disable bl30 start logs before first
|
|
* suspend or shutdown when compile with '--noverbose'.
|
|
*/
|
|
static void *xMboxBL30PrintEn(void *msg)
|
|
{
|
|
stick_mem_write(STICK_BL30_PRINT_EN, *(uint32_t *)msg);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void vBL30PrintControlInit(void)
|
|
{
|
|
xInstallRemoteMessageCallbackFeedBack(REE2AO_CHANNEL,
|
|
MBX_CMD_SET_BL30_PRINT, xMboxBL30PrintEn, 0);
|
|
}
|
|
#endif
|
|
#endif /* ACS_DIS_PRINT_FLAG */
|
|
|
|
#ifdef CONFIG_BL30_LOG_SAVE
|
|
static void *xMboxBL30LogBufferRefresh(void *msg)
|
|
{
|
|
copy_ringbuffer_to_sram((unsigned char *)BL30MSG_LOCAL_BUF_BASE, BL30MSG_LOCAL_BUF_SIZE);
|
|
memset(msg, 0, MBOX_BUF_LEN);
|
|
*(uint32_t *)msg = MBOX_BL30_LOG_COPY_DONE;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void vBL30RealLogRefreshInit(void)
|
|
{
|
|
xInstallRemoteMessageCallbackFeedBack(REE2AO_CHANNEL,
|
|
MBX_CMD_REFRESH_BL30_LOG, xMboxBL30LogBufferRefresh, 1);
|
|
}
|
|
#endif
|
|
|
|
static int prvUartTxIsFull(void)
|
|
{
|
|
return REG32(P_UART_STATUS(UART_PORT_CONS)) & UART_STAT_MASK_TFIFO_FULL;
|
|
}
|
|
|
|
void vUartTxFlush(void)
|
|
{
|
|
while (!(REG32(P_UART_STATUS(UART_PORT_CONS)) & UART_STAT_MASK_TFIFO_EMPTY))
|
|
;
|
|
}
|
|
|
|
static int prvFillTxBuf(char c)
|
|
{
|
|
char *pcBuf;
|
|
|
|
taskENTER_CRITICAL();
|
|
if (xUartTxBuf.ulBufCnt >= UART_TX_BUF_SIZE) {
|
|
xUartTxBuf.ucWarnMsgPrtEn = 1;
|
|
taskEXIT_CRITICAL();
|
|
return 1;
|
|
}
|
|
|
|
pcBuf = xUartTxBuf.pcTxBuf;
|
|
pcBuf[xUartTxBuf.ulWrPtr] = c;
|
|
xUartTxBuf.ulWrPtr++;
|
|
xUartTxBuf.ulBufCnt++;
|
|
if (xUartTxBuf.ulWrPtr >= UART_TX_BUF_SIZE)
|
|
xUartTxBuf.ulWrPtr = 0;
|
|
taskEXIT_CRITICAL();
|
|
return 0;
|
|
}
|
|
|
|
static int prvFillTxBufStr(const char *s)
|
|
{
|
|
const char *pcChar = s;
|
|
int iCnt = 0;
|
|
|
|
while (*pcChar) {
|
|
if ('\n' == *pcChar) {
|
|
prvFillTxBuf('\r');
|
|
iCnt++;
|
|
}
|
|
prvFillTxBuf(*s);
|
|
iCnt++;
|
|
pcChar++;
|
|
}
|
|
|
|
return iCnt;
|
|
}
|
|
|
|
static uint8_t prvChkTxFifoBusy(void)
|
|
{
|
|
uint8_t ucIsTxBusy = 0;
|
|
uint32_t time_start;
|
|
uint32_t time_end;
|
|
uint32_t time_elapse;
|
|
|
|
/* Check if UART TX FIFO is busy */
|
|
time_start = timere_read_us();
|
|
while (prvUartTxIsFull()) {
|
|
time_end = timere_read_us();
|
|
time_elapse = time_end - time_start;
|
|
if (time_elapse > UART_TX_FIFO_FULL_WAIT) {
|
|
ucIsTxBusy = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ucIsTxBusy;
|
|
}
|
|
|
|
void vUartPutc(const char c)
|
|
{
|
|
#ifdef ACS_DIS_PRINT_FLAG
|
|
#ifdef CONFIG_STICK_MEM
|
|
unsigned int stick_mem_bl30_print_en;
|
|
|
|
stick_mem_read(STICK_BL30_PRINT_EN, &stick_mem_bl30_print_en);
|
|
#endif
|
|
|
|
if ((REG32(ACS_DIS_PRINT_REG) & ACS_DIS_PRINT_FLAG) && !bl30_print_en
|
|
#ifdef CONFIG_STICK_MEM
|
|
&& (stick_mem_bl30_print_en != STICK_MEM_EN_BL30_PRINT_FLAG)
|
|
#endif
|
|
)
|
|
return;
|
|
#endif /* ACS_DIS_PRINT_FLAG */
|
|
|
|
while (prvUartTxIsFull())
|
|
;
|
|
REG32(P_UART_WFIFO(UART_PORT_CONS)) = (char)c;
|
|
}
|
|
|
|
int vUartPuts(const char *s)
|
|
{
|
|
int n = 0;
|
|
#ifdef CONFIG_BL30_LOG_SAVE
|
|
write_ring_buffer((unsigned char *)s, strlen(s));
|
|
/* Dump by Linux system, no need for '\ r' */
|
|
write_ring_buffer((unsigned char *)"\n", 1);
|
|
#endif
|
|
while (*s) {
|
|
vUartPutc(*s++);
|
|
n++;
|
|
}
|
|
|
|
vUartPutc('\r');
|
|
n++;
|
|
vUartPutc('\n');
|
|
n++;
|
|
|
|
return n;
|
|
}
|
|
|
|
int iUartBufPuts(const char *s)
|
|
{
|
|
int iCnt = 0;
|
|
int iTxBufCnt = 0;
|
|
uint8_t ucIsTxBusy;
|
|
#ifdef CONFIG_BL30_LOG_SAVE
|
|
write_ring_buffer((unsigned char *)s, strlen(s));
|
|
#endif
|
|
while (*s) {
|
|
ucIsTxBusy = prvChkTxFifoBusy();
|
|
/* If Uart TX FIFO is busy, send string to TX Buffer */
|
|
if (ucIsTxBusy && xUartTxBuf.ucBufReady) {
|
|
iTxBufCnt = prvFillTxBufStr(s);
|
|
iCnt += iTxBufCnt;
|
|
break;
|
|
}
|
|
|
|
if (!ucIsTxBusy || !xUartTxBuf.ucBufReady) {
|
|
if ('\n' == *s) {
|
|
vUartPutc('\r');
|
|
iCnt++;
|
|
}
|
|
vUartPutc(*s);
|
|
iCnt++;
|
|
s++;
|
|
}
|
|
}
|
|
|
|
return iCnt;
|
|
}
|
|
|
|
void vUartEnTxBuf(void)
|
|
{
|
|
taskENTER_CRITICAL();
|
|
xUartTxBuf.ucBufReady = 1;
|
|
xTimerStart(xUartTxBuf.xTimer, 0);
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
void vUartDisTxBuf(void)
|
|
{
|
|
taskENTER_CRITICAL();
|
|
xUartTxBuf.ucBufReady = 0;
|
|
xTimerStop(xUartTxBuf.xTimer, 0);
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
void vUartTxStart(void)
|
|
{
|
|
/* Do not allow deep sleep while transmit in progress */
|
|
#ifdef CONFIG_LOW_POWER_IDLE
|
|
disable_sleep(SLEEP_MASK_UART);
|
|
#endif
|
|
|
|
//uart_flush_output();
|
|
}
|
|
|
|
void vUart_Debug(uint32_t RegBase)
|
|
{
|
|
int uart_reg[6] = {0};
|
|
|
|
uart_reg[2] = REG32(P_UART_CTRL(RegBase));
|
|
printf("reg2 contrl 0x%x = %x\n", P_UART_CTRL(RegBase), uart_reg[2]);
|
|
uart_reg[3] = REG32(P_UART_STATUS(RegBase));
|
|
printf("reg3 status 0x%x = %x\n", P_UART_STATUS(RegBase), uart_reg[3]);
|
|
uart_reg[4] = REG32(P_UART_MISC(RegBase));
|
|
printf("reg4 misc 0x%x = %x\n", P_UART_MISC(RegBase), uart_reg[4]);
|
|
uart_reg[5] = REG32(P_UART_REG5(RegBase));
|
|
printf("reg5 0x%x = %x\n", P_UART_REG5(RegBase), uart_reg[5]);
|
|
}
|
|
|
|
void vUartChangeBaudrate_suspend(unsigned long source, unsigned long baud)
|
|
{
|
|
unsigned long baud_para = 0;
|
|
|
|
while (!(REG32(P_UART_STATUS(UART_PORT_CONS)) & UART_STAT_MASK_RX_FIFO_EMPTY))
|
|
;
|
|
|
|
if (source == 24000000) {
|
|
baud_para = (source / 2 + baud / 2) / baud - 1;
|
|
REG32(P_UART_REG5(UART_PORT_CONS)) = baud_para | UART_CTRL_USE_NEW_BAUD_RATE |
|
|
UART_CTRL_USE_XTAL_CLK | UART_CTRL_XTAL_CLK_DIV2;
|
|
} else {
|
|
baud_para = ((source * 10 / (baud * 4) + 5) / 10) - 1;
|
|
/* recommend from VLSI */
|
|
REG32(P_UART_MISC(UART_PORT_CONS)) = REG32(P_UART_MISC(UART_PORT_CONS)) |
|
|
(UART_MISC_RX_FILTER | UART_MISC_CTS_FILTER);
|
|
|
|
REG32(P_UART_REG5(UART_PORT_CONS)) = baud_para | UART_CTRL_USE_NEW_BAUD_RATE;
|
|
|
|
}
|
|
}
|
|
|
|
void vUartChangeBaudrate_resume(unsigned long baud)
|
|
{
|
|
unsigned long baud_para = 0;
|
|
|
|
while (!(REG32(P_UART_STATUS(UART_PORT_CONS)) & UART_STAT_MASK_RX_FIFO_EMPTY))
|
|
;
|
|
|
|
REG32(P_UART_MISC(UART_PORT_CONS)) = REG32(P_UART_MISC(UART_PORT_CONS)) &
|
|
(~(UART_MISC_RX_FILTER | UART_MISC_CTS_FILTER));
|
|
|
|
baud_para = (12000000 + baud / 2) / baud - 1;
|
|
REG32(P_UART_REG5(UART_PORT_CONS)) = baud_para | UART_CTRL_USE_XTAL_CLK |
|
|
UART_CTRL_USE_NEW_BAUD_RATE | UART_CTRL_XTAL_CLK_DIV2;
|
|
|
|
}
|
|
|
|
void vUartTxStop(void)
|
|
{
|
|
}
|
|
|
|
long lUartTxReady(void)
|
|
{
|
|
return !(REG32(P_UART_STATUS(UART_PORT_CONS)) & UART_STAT_MASK_TFIFO_FULL);
|
|
}
|
|
|
|
static void prvUartTxBufHandle(TimerHandle_t xTimer)
|
|
{
|
|
char cTxChar;
|
|
uint32_t ulIsTxFifoEmpty;
|
|
|
|
(void)xTimer;
|
|
taskENTER_CRITICAL();
|
|
if (xUartTxBuf.ulBufCnt == 0) {
|
|
if (xUartTxBuf.ulTimerPeriod != POLL_TX_BUF_PRD) {
|
|
xUartTxBuf.ulTimerPeriod = POLL_TX_BUF_PRD;
|
|
xTimerChangePeriod(xUartTxBuf.xTimer, xUartTxBuf.ulTimerPeriod, 0);
|
|
}
|
|
ulIsTxFifoEmpty = (REG32(P_UART_STATUS(UART_PORT_CONS)) &
|
|
UART_STAT_MASK_TFIFO_EMPTY);
|
|
if (ulIsTxFifoEmpty && xUartTxBuf.ucWarnMsgPrtEn) {
|
|
xUartTxBuf.ucWarnMsgPrtEn = 0;
|
|
vUartPuts(cWarnMsg);
|
|
}
|
|
} else {
|
|
if (xUartTxBuf.ulTimerPeriod != POLL_TX_FIFO_PRD) {
|
|
xUartTxBuf.ulTimerPeriod = POLL_TX_FIFO_PRD;
|
|
xTimerChangePeriod(xUartTxBuf.xTimer, xUartTxBuf.ulTimerPeriod, 0);
|
|
}
|
|
while (xUartTxBuf.ulBufCnt) {
|
|
cTxChar = xUartTxBuf.pcTxBuf[xUartTxBuf.ulRdPtr];
|
|
vUartPutc(cTxChar);
|
|
xUartTxBuf.ulRdPtr++;
|
|
xUartTxBuf.ulBufCnt--;
|
|
if (xUartTxBuf.ulRdPtr >= UART_TX_BUF_SIZE)
|
|
xUartTxBuf.ulRdPtr = 0;
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
/*
|
|
* Set UART to 115200-8-N-1
|
|
*
|
|
* Using 24M XTAL as UART reference clock, *NOT* clk81
|
|
* So the clk81 can be dynamically changed and not
|
|
* diturb UART transfers.
|
|
*/
|
|
int iUartInit(void)
|
|
{
|
|
TimerHandle_t xUartTimer = NULL;
|
|
|
|
xUartTxBuf.pcTxBuf = pvPortMalloc(UART_TX_BUF_SIZE);
|
|
if (xUartTxBuf.pcTxBuf) {
|
|
memset(xUartTxBuf.pcTxBuf, 0, UART_TX_BUF_SIZE);
|
|
xUartTimer = xTimerCreate("UartTimer", pdMS_TO_TICKS(POLL_TX_BUF_PRD),
|
|
pdTRUE, NULL, prvUartTxBufHandle);
|
|
if (xUartTimer) {
|
|
xUartTxBuf.ulRdPtr = 0;
|
|
xUartTxBuf.ulWrPtr = 0;
|
|
xUartTxBuf.ulBufCnt = 0;
|
|
xUartTxBuf.ucWarnMsgPrtEn = 0;
|
|
xUartTxBuf.ucBufReady = 1;
|
|
xUartTxBuf.xTimer = xUartTimer;
|
|
xUartTxBuf.ulTimerPeriod = POLL_TX_BUF_PRD;
|
|
xTimerStart(xUartTxBuf.xTimer, 0);
|
|
} else {
|
|
vPortFree(xUartTxBuf.pcTxBuf);
|
|
return ERR_UART(DRV_ERROR_UNSUPPORTED);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_UART_WAKEUP
|
|
|
|
#define UART_TASK_PRI 3
|
|
static uint32_t UartWakeupRegBase = UART_PORT_WAKEUP_REG_BASE;
|
|
static uint32_t UartWakeupIrq = UART_PORT_WAKEUP_IRQ;
|
|
static uint32_t reg_uart[6];
|
|
static TaskHandle_t UartPollTask;
|
|
|
|
void vUartWakeupMatchHandler(void)
|
|
{
|
|
uint32_t buf[4] = {0};
|
|
int ch;
|
|
|
|
while (REG32(P_UART_STATUS(UartWakeupRegBase)) & 0xff) {
|
|
ch = REG32(P_UART_RFIFO(UartWakeupRegBase));
|
|
/* Todo: set the match string,then wake up sample is "w" */
|
|
/* printf("%s : ch=%x\n", __func__, ch); */
|
|
if ((ch & 0xff) == 'w') {
|
|
buf[0] = UART_RX_WAKEUP;
|
|
STR_Wakeup_src_Queue_Send_FromISR(buf);
|
|
DisableIrq(UartWakeupIrq);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void vUartPollTask(void *pvParameters)
|
|
{
|
|
uint32_t buf[4] = {0};
|
|
char ch;
|
|
|
|
while (1) {
|
|
while (REG32(P_UART_STATUS(UartWakeupRegBase)) & 0xff) {
|
|
ch = REG32(P_UART_RFIFO(UartWakeupRegBase));
|
|
/* Todo: set the match string,then wake up sample is "w" */
|
|
/* printf("%s : ch=%x\n", __func__, ch); */
|
|
if ((ch & 0xff) == 'w') {
|
|
buf[0] = UART_RX_WAKEUP;
|
|
STR_Wakeup_src_Queue_Send(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* The time can be adjusted as needed */
|
|
vTaskDelay(pdMS_TO_TICKS(200));
|
|
}
|
|
|
|
}
|
|
|
|
void vUartWakeupInit(uint16_t GpioRx, uint16_t GpioTx,
|
|
enum PinMuxType func, uint8_t reinit,
|
|
void (*vIRQHandler)(void), uint32_t baudrate, uint32_t source)
|
|
{
|
|
int ch;
|
|
uint32_t baud_para = 0;
|
|
|
|
/* Save uart port value suspend from AP core */
|
|
reg_uart[2] = REG32(P_UART_CTRL(UartWakeupRegBase));
|
|
reg_uart[3] = REG32(P_UART_STATUS(UartWakeupRegBase));
|
|
reg_uart[4] = REG32(P_UART_MISC(UartWakeupRegBase));
|
|
reg_uart[5] = REG32(P_UART_REG5(UartWakeupRegBase));
|
|
|
|
/* vUart_Debug(UartWakeupRegBase); */
|
|
|
|
/* The uart port of AP core debug, don't set pinmux.This pinmux is fixed */
|
|
if (UartWakeupRegBase != UART_PORT_CONS) {
|
|
/* Todo: set the fix pinmux */
|
|
xPinmuxSet(GpioRx, func);
|
|
xPinconfSet(GpioRx, PINF_CONFIG_BIAS_PULL_UP | PINF_CONFIG_DRV_STRENGTH_3);
|
|
|
|
xPinmuxSet(GpioTx, func);
|
|
xPinconfSet(GpioTx, PINF_CONFIG_BIAS_PULL_UP | PINF_CONFIG_DRV_STRENGTH_3);
|
|
}
|
|
|
|
/* todo: if uart is not use before,you should turn on this code */
|
|
if (reinit) {
|
|
REG32(P_UART_CTRL(UartWakeupRegBase)) = UART_STP_BIT |
|
|
UART_PRTY_BIT |
|
|
UART_CHAR_LEN |
|
|
UART_MODE_MASK_RST_TX |
|
|
UART_MODE_MASK_RST_RX |
|
|
UART_MODE_MASK_CLR_ERR |
|
|
UART_MODE_MASK_TX_EN |
|
|
UART_MODE_MASK_RX_EN |
|
|
UART_MODE_MASK_2WIRE;
|
|
|
|
if (source == 24000000) {
|
|
baud_para = (source / 2 + baudrate / 2) / baudrate - 1;
|
|
REG32(P_UART_REG5(UartWakeupRegBase)) = baud_para |
|
|
UART_CTRL_USE_NEW_BAUD_RATE |
|
|
UART_CTRL_USE_XTAL_CLK |
|
|
UART_CTRL_XTAL_CLK_DIV2;
|
|
} else if (source == 32000) {
|
|
baud_para = (source / 2 + baudrate / 2) / baudrate - 1;
|
|
REG32(P_UART_REG5(UartWakeupRegBase)) = baud_para |
|
|
UART_CTRL_USE_NEW_BAUD_RATE |
|
|
UART_CTRL_USE_XTAL_CLK |
|
|
UART_CTRL_XTAL_CLK_DIV2;
|
|
} else {
|
|
baud_para = ((source * 10 / (baudrate * 4) + 5) / 10) - 1;
|
|
/* recommend from VLSI */
|
|
REG32(P_UART_MISC(UartWakeupRegBase)) |= UART_MISC_RX_FILTER |
|
|
UART_MISC_CTS_FILTER;
|
|
|
|
REG32(P_UART_REG5(UartWakeupRegBase)) = baud_para |
|
|
UART_CTRL_USE_NEW_BAUD_RATE;
|
|
}
|
|
|
|
ch = REG32(P_UART_CTRL(UartWakeupRegBase));
|
|
ch &= ~(UART_MODE_MASK_RST_TX | UART_MODE_MASK_RST_RX | UART_MODE_MASK_CLR_ERR);
|
|
REG32(P_UART_CTRL(UartWakeupRegBase)) = ch;
|
|
}
|
|
|
|
if (vIRQHandler) {
|
|
ch = REG32(P_UART_CTRL(UartWakeupRegBase));
|
|
ch |= (1 << 27);
|
|
REG32(P_UART_CTRL(UartWakeupRegBase)) = ch;
|
|
|
|
ch = REG32(P_UART_MISC(UartWakeupRegBase));
|
|
ch &= 0xffffff00;
|
|
ch |= (1 << 0);
|
|
REG32(P_UART_MISC(UartWakeupRegBase)) = ch;
|
|
}
|
|
|
|
if (vIRQHandler) {
|
|
RegisterIrq(UartWakeupIrq, 2, vIRQHandler);
|
|
EnableIrq(UartWakeupIrq);
|
|
} else {
|
|
xTaskCreate(vUartPollTask, "UartPollTask", configMINIMAL_STACK_SIZE,
|
|
NULL, UART_TASK_PRI, &UartPollTask);
|
|
}
|
|
|
|
#ifdef CONFIG_SOC_A4
|
|
UART_AO_WakeUp_Setting();
|
|
#endif
|
|
/* vUart_Debug(UartWakeupRegBase); */
|
|
}
|
|
|
|
void vUartWakeupDeinit(void (*vIRQHandler)(void))
|
|
{
|
|
if (vIRQHandler) {
|
|
DisableIrq(UartWakeupIrq);
|
|
UnRegisterIrq(UartWakeupIrq);
|
|
} else {
|
|
vTaskDelete(UartPollTask);
|
|
}
|
|
|
|
/* restore uart value */
|
|
REG32(P_UART_CTRL(UartWakeupRegBase)) = reg_uart[2];
|
|
REG32(P_UART_STATUS(UartWakeupRegBase)) = reg_uart[3];
|
|
REG32(P_UART_MISC(UartWakeupRegBase)) = reg_uart[4];
|
|
REG32(P_UART_REG5(UartWakeupRegBase)) = reg_uart[5];
|
|
}
|
|
#endif
|