blob: a04bbf0f9739391df5a48d15687e3b22709e61f1 [file] [log] [blame]
/*****************************************************************************
* Copyright Statement:
* --------------------
* This software is protected by Copyright and the information contained
* herein is confidential. The software may not be copied and the information
* contained herein may not be used or disclosed except with the written
* permission of MediaTek Inc. (C) 2012
*
* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
*
* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
*
*****************************************************************************/
/*******************************************************************************
* Filename:
* ---------
* uart.c
*
* Project:
* --------
* TATAKA
*
* Description:
* ------------
* This Module defines the uart1 driver and the adaption layer
* between driver and TATAKA protocol.
* Author:
* -------
* -------
* -------
* -------
*
* ==========================================================================
* $Log$
*
* 07 02 2019 yao.xue
* [MOLY00418070] ISR Centralization : remove UART & WDT & Logseq IRQSensitivity/IRQ_Register_LISR
* ISR Centralization : remove UART & WDT & Logseq IRQSensitivity/IRQ_Register_LISR
*
* 04 11 2019 yao.xue
* [MOLY00397471] [VMOLY]Use API ust_us_duration take place ust_get_duration
* modify API ust_us_duration takeplace ust_get_duration in uart/slt code
*
* 02 15 2019 panu.peisa
* [MOLY00384803] [Gen97][SystemService][Change Request] KAL Refactoring Phase-in
*
* Added changes to swrd part.
*
* 10 29 2018 yao.xue
* [MOLY00360949] [SWRD] DRVTEST maintain
* Fix DRVTEST build pass in SWRD
*
* 03 13 2018 shenghui.shi
* [MOLY00309657] UMOLYE driver warning fix
* update UART driver
*
* 11 21 2017 shenghui.shi
* [MOLY00290848] [UMOLYA] Usage of INT_SW_SecVersion
* removed no used API INT_SW_SecVersion
*
* 11 21 2017 shenghui.shi
* [MOLY00290848] [UMOLYA] Usage of INT_SW_SecVersion
* remove INT_SW_SecVersion API from UART driver. This API is not used in 93/95
*
*
* 11 07 2017 shenghui.shi
* [MOLY00288093] update UART driver to remove no needed project option
* .
*
* 11 07 2017 shenghui.shi
* [MOLY00288093] update UART driver to remove no needed project option
* update uart driver to remove no needed files
*
* 11 03 2017 shenghui.shi
* [MOLY00287577] UMOLYA HISR coding change for UART part
* .
*
* 10 24 2017 yao.xue
* [MOLY00284920] [Cervino] UART driver porting for Cervino.
*
* 09 15 2017 da.li
* [MOLY00270315] [System Service][KIR] make ex robust before ex steplog work
* Replace INT_QueryExceptionStatus with #include <ex_public.h>.
*
* 09 08 2017 da.li
* [MOLY00274163] [Sylvia] Driver porting
* Build warning(error) fix.
*
* 09 07 2017 da.li
* [MOLY00274163] [Sylvia] Driver porting
* UART driver porting for Sylvia.
*
* 07 13 2017 shenghui.shi
* [MOLY00263518] Update UART driver test code
* fix build error
*
* 07 13 2017 shenghui.shi
* [MOLY00263518] Update UART driver test code
* update UART driver
*
* 06 12 2017 flamingo.wang
* [MOLY00244966] [ZION][IDC] add chip define of MT6739 in idc driver
* Add MT6739 define
*
* 06 12 2017 flamingo.wang
* [MOLY00254599] Normal mode UARTDriver���ܳ�Log
* norm uart mode print log fix
*
* 04 24 2017 shenghui.shi
* [MOLY00243727] update UART PDN feature
* update UART pdn feature,to void system could not entry DCM issue.
*
* 03 07 2017 shenghui.shi
* [MOLY00233604] UART print driver update for baudrate
* update UART driver for uart include.
*
* 02 07 2017 shenghui.shi
* [MOLY00228102] [Bianco Bring-up]UMOLYA uart driver update
* update UART dbgprint driver
*
* 09 22 2016 yuke.ren
* [MOLY00204183] Fix UART HDMA usage
* set RX SEL for RX channel
*
*
* 09 20 2016 yuke.ren
* [MOLY00204183] Fix UART HDMA usage
* .
*
* 07 15 2016 shenghui.shi
* [MOLY00171995] update uart driver for 93
* update UART cloclk to 26MHz (after GEN93 Bitfile 2016071380)
*
* 05 19 2016 shenghui.shi
* [MOLY00175766] NVRAM update for UMOLYA
* modify UART 26MHz macro to 20.8MHz to match real clock freq.
*
* 03 30 2016 shenghui.shi
* [MOLY00171995] update uart driver for 93
* update uart driver for 93.
*
* 01 27 2016 shenghui.shi
* [MOLY00081492] [UART] update uart driver
* use sst_get_exception_count() to replace INT_Exception_Enter.
*
* 01 22 2016 shenghui.shi
* [MOLY00162415] [Coverity inspect] driver coding issue fix
* [coverity inspect]driver coding issue fix
*
* 01 15 2016 shenghui.shi
* [MOLY00081492] [UART] update uart driver
* Merging
*
* update UART debug driver to use HMDA mode.
*
* 10 13 2015 shenghui.shi
* [MOLY00145129] fixed EWS build error which caused by UART IRQ naming exchange on ELBRUS
* .
*
* 10 13 2015 shenghui.shi
* [MOLY00145129] fixed EWS build error which caused by UART IRQ naming exchange on ELBRUS
* .
*
* 08 17 2015 shenghui.shi
* [MOLY00137551] [MOLY_LINUX_DOWNLOADBIN notify] ELBRUS_FPGA(BASIC) build error
* <saved by Perforce>
*
* 06 18 2015 da.li
* [MOLY00121478] [UMOLY][JADE]UART driver compile error fix
* Compile error fix on JADE(MT6755).
*
* 06 15 2015 da.li
* [MOLY00121478] [UMOLY][JADE]UART driver compile error fix
* UART driver compile error fix on MT6755(JADE).
*
* 05 11 2015 shenghui.shi
* [MOLY00081492] [UART] update uart driver
* pdn clear UART/GDMA clock before use UART driver
*
* 04 02 2015 tero.jarkko
* [MOLY00094214] [System Service][MOLY Kernel Internal Request]Modify driver HISR to individual HISR
*
* 03 25 2015 shenghui.shi
* [MOLY00104131] [UMOLY][Klocwork] Fix potential code defect in uart driver
* .
*
* 02 11 2015 shenghui.shi
* [MOLY00081492] [UART] update uart driver
* fix ews build error
*
* 02 11 2015 shenghui.shi
* [MOLY00081492] [UART] update uart driver
* 1. add sw escape feature to UMOLY
* 2. phase out VFIFO hw code in devdrv_common.c
*
* 12 18 2014 shenghui.shi
* [MOLY00081492] [UART] update uart driver
* .
*
* 11 17 2014 shenghui.shi
* [MOLY00084720] update UMOLY HDMA HISR
* move GDMA2 to DEVDRV share HISR
*
* 11 17 2014 shenghui.shi
* [MOLY00084720] update UMOLY HDMA HISR
* .
*
* 05 13 2014 shenghui.shi
* [MOLY00062001] TK6291 UART Fix EWS error
* .
*
* 05 13 2014 shenghui.shi
* [MOLY00065467] [TK6291] update UART driver for TK6291
* update UART clock to 26MHZ for TK6291
*
* 04 08 2014 shenghui.shi
* [MOLY00062001] TK6291 UART Fix EWS error
* .
*
* 04 08 2014 shenghui.shi
* [MOLY00062003] [MakeFile] [Modify Common Makefile] Disable __CUST_NEW__
* update a patch for no __FPGA__ macro
*
* 04 08 2014 shenghui.shi
* [MOLY00062001] TK6291 UART Fix EWS error
* update uart driver to fix ews error
*
* 01 10 2014 shenghui.shi
* [MOLY00043671] [klocwork_95][LTE] in uart.c, line 428
* .
*
* 01 10 2014 shenghui.shi
* [MOLY00043674] [klocwork_95][LTE] in uart.c, line 2247
* update uart driver to fix uninitial risk.
*
* 01 09 2014 shenghui.shi
* [MOLY00052974] MT6595 UART driver merge to Trunk
* MT6595 uart driver merge to MOLY TRUNK
*
* 12 10 2013 shenghui.shi
* [MOLY00049628] MT6595 UART merge to Trunk
* .
*
* 10 29 2013 shenghui.shi
* [MOLY00044172] uart all memory dump
* .
*
* 10 02 2013 vend_brandon-hy.lin
* [MOLY00040071] [MT6290] SRCLKEN cannot be toggled when LTE sleep feature is enable
* Fix SRCLEN_OUT0 cannot be toggle when LTE sleep feature is enable.
* Solution: enlarge transmission time of dummy fdma patch.
*
* 09 13 2013 shenghui.shi
* [MOLY00035078] [MT6290][PDN] Enable GDMA & HDMA related module PDN support
* move uart pdn_clr from dcl_tty.c to uart.c
*
* 09 03 2013 shenghui.shi
* [MOLY00036272] open UART SlEEP_EN feature
* open uart SLEEP_EN feature when MTK_SLEEP_EN enable.
*
* 08 29 2013 shenghui.shi
* [MOLY00035659] [MOLY] [MT6290][SLT] SLT Tool Communication API for driver test
* .
*
* 08 29 2013 shenghui.shi
* [MOLY00035768] fix uart build warnning
* .
*
* 08 26 2013 shenghui.shi
* [MOLY00035078] [MT6290][PDN] Enable GDMA & HDMA related module PDN support
* add uart PDN feature
*
* 08 14 2013 shenghui.shi
* [MOLY00033671] update exception uart driver for void use qbm_dest_q
* .
*
* 08 12 2013 shenghui.shi
* [MOLY00033396] update dummy_fdma() patch
* .
*
* 08 02 2013 shenghui.shi
* [MOLY00032203] update dummy_fdma for GDMA sleep ack issue
* update dummy_fdma() for GDMA sleep ack issue
* 08/02/2013 shenghui.shi
* [MOLY00032203]update dummy_fdma() for GDMA sleep ack issue
*
* 07 29 2013 shenghui.shi
* [MOLY00030921] [MT6290]Low Power Feature patch back from CBr
* merge UART dummy_fdma() patch from Branch to Trunk.
*
* 04 24 2013 shenghui.shi
* [MOLY00020330] MT6290 UART driver update
* uart driver update: modify the uart_hdma_isr().
*
* 04 03 2013 shenghui.shi
* [MOLY00012769] IOMUX driver
* update UART driver: add ASIC version for UART_CLOCK
*
* 02 04 2013 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* rename: 7208 -> 6290
*
* 01 29 2013 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* Integration change.
*
* 01 22 2013 ansel.liao
* [MOLY00006575] USIM driver modification
* *: remove an en-Q situation which won't occur
*
* 01 15 2013 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* *: recover U_GetUARTByte function, WCP3/SE7/SD9 Chuanbo need this function to verify MSDC driver (port from MT6280)
*
* 01 14 2013 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* Integration change.
*
* 01 04 2013 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* *: clear rx data timeout counter periodly to prevent XON/XOFF of sw flow control to destroy rx data timeout mechanism
*
* 01 02 2013 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* *: does not destroy rx queue when head of queue is null
*
* 12 26 2012 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* Integration change.
*
* 12 25 2012 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* *: free all TGPD/RGPD when TTY_CMD_EXCEPTION_CLEAR_CHANNEL is get
*
* 12 19 2012 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* Integration change.
*
* 12 06 2012 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* Integration change.
*
* 11 30 2012 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* add dbg_flush and corresponding drvtest
*
* 11 27 2012 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* update stress test
*
* 11 25 2012 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* update UART stress test
*
* 11 23 2012 ansel.liao
* [MOLY00006575] Add UART/HDMA Driver
* Add UART/HDMA driver
****************************************************************************/
#include "drv_features.h"
#include "kal_general_types.h"
#include "kal_public_api.h"
#ifdef KTEST_UART_TRACES
#include "kal_hrt_api.h"
#endif
#include "kal_public_defs.h"
#include "hisr_config.h"
#include "stack_msgs.h"
#include "stack_ltlcom.h" /* Task message communiction */
#include "drv_comm.h"
#include "reg_base.h"
#include "uart_hw.h"
#include "bmd.h"
#include "intrCtrl.h"
#include "drvpdn.h"
#include "stack_config.h" /*MOD_UART1_HISR,MOD_UART2_HISR*/
#include "uart_sw.h"
#include "uart_internal.h"
#include "dcl.h"
#include "uart_gpd.h"
#include "drv_msgid.h"
#include "devdrv_ls.h"
#include "pll.h"
#include "drv_gdma.h"
// for HDMA
#include "qmu_bm.h"
#include "qmu_bm_size.h"
#include "qmu_bm_util.h"
#include "init.h"
#include "cpu.h"
#include "cache_sw.h"
#include <ex_item.h>
#include <ex_public.h>
#if defined(__HMU_ENABLE__)
#include "hmu.h"
#include "hmu_conf_data.h"
#endif
#include "us_timer.h"
#if !defined(DRV_UART_OFF)
#define UART_CLOCK (26*1000000)
#ifndef MD_IRQID_MDGDMA2
#define MD_IRQID_MDGDMA2 PS_IRQID_MDGDMA2
#endif
// To enable or disable META Mode SW Escaping, defined this macro to enable it
#define META_MODE_SW_ESCAPING
#define UART_ESCAPE_CHAR 0x77
#define UART_ECPT_MAX_TIMEOUT 5000 //5s
kal_uint8 UART_handle;
tty_excp_hif_state uart_ecpt_tx_state[MAX_UART_PORT_NUM] =
{
HIF_STATE_NORMAL,
HIF_STATE_NORMAL,
};
UART_ecpt_timer_t uart_ecpt_timer[MAX_UART_PORT_NUM];
UARTStruct UARTPort[MAX_UART_PORT_NUM];
#ifdef DRV_DEBUG
kal_uint8 uart_initialize[MAX_UART_PORT_NUM];
#endif /*DRV_DEBUG*/
#define DEBUG_PORT uart_port1 // Use UART1 as debug port
#define DEBUG_BAUDRATE 115200
kal_int32 init_log_fail_count = 0;
kal_bool mutex_status = KAL_FALSE;
kal_mutexid mutexid = 0;
#if __LTE_ONLY__
#define MCU_BOOT_SPEED 40040000
#else
//MCU booting speed 26M/baudrate(bits/second) = 260M/baudrate(bytes/second) = MCU tick/bytes
#define MCU_BOOT_SPEED 260000000 //Currently all chips use 26M, 260M because of count [MCU ticks/byte]
#endif
kal_bool send_Txilm[MAX_UART_PORT_NUM] = {// change from kal_uint8 to kal_bool, avoid Warning 641: Converting enum 'kal_bool' to int"
KAL_FALSE,
KAL_FALSE,
};
kal_bool send_Rxilm[MAX_UART_PORT_NUM] = {// change from kal_uint8 to kal_bool, avoid Warning 641: Converting enum 'kal_bool' to int"
KAL_TRUE,
KAL_TRUE,
};
const VOID_FUNC UART_HISR[MAX_UART_PORT_NUM] =
{
UART1_HISR,
UART2_HISR,
};
const kal_uint32 UART_BaseAddr[MAX_UART_PORT_NUM] =
{
UART1_base,
UART2_base,
};
#ifdef __DMA_UART_VIRTUAL_FIFO__
kal_bool UART_VFIFO_support[MAX_UART_PORT_NUM] =
{
KAL_TRUE,
KAL_TRUE,
};
#else
kal_bool UART_VFIFO_support[MAX_UART_PORT_NUM] =
{
KAL_FALSE,
KAL_FALSE,
};
#endif/*__DMA_UART_VIRTUAL_FIFO__*/
//Add for new internal func
void UART2_TrxHandler(void);
kal_uint8 UART_GetIRQCode(UART_PORT port);
void uart_qbm_virt_to_phy(void** pp_gpd_head, void** pp_gpd_tail);
void uart_qbm_phy_to_virt(void**pp_gpd_head, void**pp_gpd_tail);
void UART_META_PutBytes(UART_PORT port, void * gpd_head, void * gpd_tail);
kal_uint16 U_ExBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length, kal_uint8 *status, module_type ownerid);
void UART_META_ExBytes(UART_PORT port, void * gpd_head, void * gpd_tail);
kal_uint8 uart_escape_state=0;
extern UartDriver_strcut* pUart_CMD_FUNC[];
#if defined(DRV_DEBUG_BUFFER_DMA_MODE) && !defined(KTEST_UART_TRACES)
kal_spinlockid print_buf_lock = 0;
#endif
//void dummy_fdma(kal_uint32 gdma_start);
void UART_Calback(void *parameter);
void U_ConfigEscape (UART_PORT port, kal_uint8 EscChar, kal_uint16 ESCGuardtime, module_type ownerid);
void UART_TrxHandler(void *parameter);
void UART_TxDMAHandler(void *parameter, kal_uint8 chk_done);
/*UART Customization */
extern const UART_customize_function_struct *UART_GetFunc(void);
const UART_customize_function_struct *UartCustomFunc;
const UART_rings_struct *UART_rings;
kal_bool WaitForUARTTx[MAX_UART_PORT_NUM] = {KAL_FALSE};
#define ASSERT_WAIT_LOOP 0xffffffff
#define VFIFO_SWITCH_WAIT_LOOP 100000
kal_uint16 DELAY_FOR_PUTBYTE = 300;
// for HDMA
void *uart_tgpd_head[3];
void *uart_rgpd_head[3];
void *uart_tgpd_tail[3];
void *uart_rgpd_tail[3];
void *uart_wait_tgpd_head[3];
void *uart_wait_tgpd_tail[3];
// for UART Exception mode
kal_uint8 uart_ecpt_bps_buf[UART_ECPT_QBM_BPS_BUF_SZ];
kal_bool uart_ecpt_init = KAL_FALSE;
uart_bps_gpd_t uart_bps_gpd;
#if defined(DRV_UART_MEMORY_TRACE)
UART_DRV_DBG_STRUCT UART_DRV_DBG_INFO_DATA;
/*uart_drv_dbg_trace(NAND_READ_START,drv_get_current_time(),0,0);*/
void uart_drv_dbg_trace(kal_uint16 index, kal_uint32 time, kal_uint32 data1, kal_uint32 data2)
{
kal_uint32 savedMask;
savedMask = SaveAndSetIRQMask();
{
UART_DRV_DBG_INFO_DATA.dbg_data[UART_DRV_DBG_INFO_DATA.dbg_data_idx&(MAX_UART_DRV_DBG_INFO_SIZE-1)].tag = index;
UART_DRV_DBG_INFO_DATA.dbg_data[UART_DRV_DBG_INFO_DATA.dbg_data_idx&(MAX_UART_DRV_DBG_INFO_SIZE-1)].time = time;
UART_DRV_DBG_INFO_DATA.dbg_data[UART_DRV_DBG_INFO_DATA.dbg_data_idx&(MAX_UART_DRV_DBG_INFO_SIZE-1)].data1 = data1;
UART_DRV_DBG_INFO_DATA.dbg_data[UART_DRV_DBG_INFO_DATA.dbg_data_idx&(MAX_UART_DRV_DBG_INFO_SIZE-1)].data2 = data2;
UART_DRV_DBG_INFO_DATA.dbg_data_idx++;
}
RestoreIRQMask(savedMask);
}
#endif //#if defined(DRV_UART_MEMORY_TRACE)
void uart_customize_init(void)
{
/* retreive the function table */
UartCustomFunc=UART_GetFunc();
/* use the entry in function table to retreive desired information */
UART_rings = UartCustomFunc->UART_Get_Data();
}
kal_bool UART_IsVfifoSetting(UART_PORT port, UART_TxRx_VFIFO_support vs)
{
#ifdef __DMA_UART_VIRTUAL_FIFO__
if(port >= MAX_UART_PORT_NUM)
return KAL_FALSE;
if(vs != NONE_VFIFO)
return UART_VFIFO_support[port];
else //NONE_VFIFO
return (kal_bool)!UART_VFIFO_support[port];
#else
if(vs == NONE_VFIFO)
return KAL_TRUE;
else //NONE_VFIFO
return KAL_FALSE;
#endif
}
/*check if chip can support auto escape*/
kal_bool uart_support_autoescape(void)
{
return KAL_TRUE;
}
void UART_sendilm(UART_PORT port, msg_type msgid) {}
//Add for U_ClrRxBuffer and U_ClrTxBuffer, reduce code size
void UART_Set_NormalFlowControl(UART_PORT port)
{
if (UARTPort[port].DCB.flowControl == fc_none)
DRV_UART_WriteReg(UART_IER(UART_BaseAddr[port]),IER_HW_NORMALINTS);
else if (UARTPort[port].DCB.flowControl == fc_hw)
DRV_UART_WriteReg(UART_IER(UART_BaseAddr[port]),IER_HW_NORMALINTS);
else if (UARTPort[port].DCB.flowControl == fc_sw)
DRV_UART_WriteReg(UART_IER(UART_BaseAddr[port]),IER_SW_NORMALINTS);
}
void U_ClrRxBuffer(UART_PORT port, module_type ownerid) /*clear sw buffer*/
{
kal_uint32 savedMask;
savedMask = SaveAndSetIRQMask();
BWrite_addr(UARTPort[port].Rx_Buffer) = 0;
BRead_addr(UARTPort[port].Rx_Buffer) = 0;
// UART_Set_NormalFlowControl(port);
send_Rxilm[port] = KAL_TRUE;
RestoreIRQMask(savedMask);
// HDMA procedure
uart_en_q_de_q_with_mutex(port, UART_RX, UART_DE_Q_ALL, NULL, NULL);
// end of HDMA procedure
}
void U_ClrTxBuffer(UART_PORT port, module_type ownerid) /*clear sw buffer*/
{
kal_uint32 savedMask;
savedMask = SaveAndSetIRQMask();
BWrite_addr(UARTPort[port].Tx_Buffer) = 0;
BRead_addr(UARTPort[port].Tx_Buffer) = 0;
// UART_Set_NormalFlowControl(port);
send_Txilm[port] = KAL_TRUE;
RestoreIRQMask(savedMask);
// HDMA procedure
uart_en_q_de_q_with_mutex(port, UART_TX, UART_DE_Q_ALL, NULL, NULL);
// end of HDMA procedure
}
void UART_EnableTX(UART_PORT port, kal_bool enable)
{
if (port < MAX_UART_PORT_NUM)
{
UARTPort[port].EnableTX= enable;
if(enable == KAL_TRUE){
EnableTxIntr(UART_BaseAddr[port]);
}else{
DisableTxIntr(UART_BaseAddr[port]);
}
}else{
ASSERT(0);
}
}
void UART_SleepOnTx_Enable(UART_PORT port, UART_SLEEP_ON_TX enable_flag) {}
kal_uint16 U_GetBytesAvail(UART_PORT port)
{
kal_uint16 real_count;
Buf_GetBytesAvail(&(UARTPort[port].Rx_Buffer),real_count);
return real_count;
}
kal_uint16 U_GetTxRoomLeft(UART_PORT port)
{
kal_uint16 real_count;
Buf_GetRoomLeft(&(UARTPort[port].Tx_Buffer),real_count);
return real_count;
}
#ifndef __ROMSA_SUPPORT__ /* Note: for ROM code */
#if defined(__MTK_INTERNAL__) && defined(__MTK_TARGET__)
kal_uint16 DEVDRV_LS_INTERNCODE
#else
kal_uint16
#endif
U_GetTxISRRoomLeft(UART_PORT port)
{
return 0;
}
#endif /* Note: for ROM code */
/*
* FUNCTION
* GetUARTByte
*
* DESCRIPTION
* This function is to read data from UART
*
* CALLS
* This function is to receive data through UART
*
* PARAMETERS
* None
*
* RETURNS
* the data from UART
*
* GLOBALS AFFECTED
* external_global
*/
kal_uint8 U_GetUARTByte(UART_PORT port)
{
kal_uint8 data;
kal_uint8 U_GetUARTByteWithTimeOut(UART_PORT port, kal_uint8* ch, kal_uint32 timeout_value);//liming add statement
while(!U_GetUARTByteWithTimeOut(port, &data, 0xffffffff)); // for descrease code size (U_GetUARTByte &U_GetUARTByteTimeout)
return data;
}
/*
* FUNCTION
* GetUARTByte
*
* DESCRIPTION
* This function is to read data from UART
*
* CALLS
* This function is to receive data through UART
*
* PARAMETERS
* None
*
* RETURNS
* the data from UART
*
* GLOBALS AFFECTED
* external_global
*/
kal_uint8 U_GetUARTByteWithTimeOut(UART_PORT port, kal_uint8* ch, kal_uint32 timeout_value)
{
kal_uint8 res_byte = 0;
kal_uint8 data;
while(timeout_value != 0)
{
kal_uint16 LSR;
LSR = DRV_UART_Reg(UART_LSR(UART_BaseAddr[port]));
if (LSR & UART_LSR_DR)
{
data = (kal_uint8)DRV_UART_Reg(UART_RBR(UART_BaseAddr[port]));
res_byte = 1;
//only META port use old flow control escape character,
if( (kal_query_boot_mode()== FACTORY_BOOT && UARTPort[port].DCB.flowControl==fc_sw && UARTPort[port].ownerid==MOD_DHL_READER)||
(uart_support_autoescape()==KAL_FALSE&&UARTPort[port].DCB.flowControl==fc_sw))
{
if(uart_escape_state==0)
{
if(data==0x77)
uart_escape_state=0x77;
else
{
*ch = data;
break;
}
}
else if (uart_escape_state==0x77)
{
uart_escape_state=0x0;
if (data == 0x01)
{
*ch = UARTPort[port].DCB.xonChar;
break;
}
else if (data == 0x02)
{
*ch = UARTPort[port].DCB.xoffChar;
break;
}
else if (data == 0x03)
{
*ch = 0x77;
break;
}
}
}
else
{
*ch = data;
break;
}
}
--timeout_value;
}
return res_byte;
}
/*
* FUNCTION
* PutUARTByte
*
* DESCRIPTION
* This function is to write data to UART
*
* CALLS
* This function is to transmit data through UART
*
* PARAMETERS
* None
*
* RETURNS
* the data from UART
*
* GLOBALS AFFECTED
* external_global
*/
void PutUARTRingBufferData(UART_PORT port) {}
void UART_PutUARTByte_limited(UART_PORT port, kal_uint8 data)
{
volatile kal_uint16 LSR;
kal_uint32 count = 0;
if(init_log_fail_count > 3)
{
DRV_UART_WriteReg(UART_THR(UART_BaseAddr[port]),(kal_uint16)data);
return;
}
while(1)
{
LSR = DRV_UART_Reg(UART_LSR(UART_BaseAddr[port]));
count++;
if ( LSR & UART_LSR_THRE )
{
DRV_UART_WriteReg(UART_THR(UART_BaseAddr[port]),(kal_uint16)data);
break;
}
else if(count > (MCU_BOOT_SPEED/DEBUG_BAUDRATE) )
{
DRV_UART_WriteReg(UART_THR(UART_BaseAddr[port]),(kal_uint16)data); //don't care the pending
init_log_fail_count++;
break;
}
}
}
void U_PutUARTByte(UART_PORT port, kal_uint8 data) {
kal_uint16 LSR;
while(1)
{
LSR = DRV_UART_Reg(UART_LSR(UART_BaseAddr[port]));
if ( LSR & UART_LSR_THRE )
{
DRV_UART_WriteReg(UART_THR(UART_BaseAddr[port]),(kal_uint16)data);
break;
}
}
}
void PutUARTData(UART_PORT port, kal_uint8 escape_char, kal_uint8 data)
{
if(port >= MAX_UART_PORT_NUM)
return;
//only META port use old flow control escape character,
if((kal_query_boot_mode() == FACTORY_BOOT && UARTPort[port].DCB.flowControl == fc_sw && UARTPort[port].ownerid == MOD_DHL_READER)
|| (uart_support_autoescape() == KAL_FALSE && UARTPort[port].DCB.flowControl == fc_sw))
{
if (data == UARTPort[port].DCB.xonChar)
{
pUart_CMD_FUNC[port]->PutUARTByte(port, escape_char);
pUart_CMD_FUNC[port]->PutUARTByte(port, 0x01);
}
else if (data == UARTPort[port].DCB.xoffChar)
{
pUart_CMD_FUNC[port]->PutUARTByte(port, escape_char);
pUart_CMD_FUNC[port]->PutUARTByte(port, 0x02);
}
else if (data == escape_char)
{
pUart_CMD_FUNC[port]->PutUARTByte(port, escape_char);
pUart_CMD_FUNC[port]->PutUARTByte(port, 0x03);
}
else
{
pUart_CMD_FUNC[port]->PutUARTByte(port, data);
}
}
else
{
pUart_CMD_FUNC[port]->PutUARTByte(port, data);
}
}
void PutUARTByteDelay(UART_PORT port, kal_uint8 data)
{
kal_uint16 LSR;
kal_uint16 i;
if(port >= MAX_UART_PORT_NUM)
return;
while(1)
{
LSR = DRV_UART_Reg(UART_LSR(UART_BaseAddr[port]));
if( LSR & UART_LSR_THRE )
{
for(i = 0; i < DELAY_FOR_PUTBYTE; i++); //add delay...
DRV_UART_WriteReg(UART_THR(UART_BaseAddr[port]),(kal_uint16)data);
break;
}
}
}
void PutUARTDataDelay(UART_PORT port, kal_uint8 escape_char, kal_uint8 data)
{
if(port >= MAX_UART_PORT_NUM)
return;
if( (kal_query_boot_mode()== FACTORY_BOOT && UARTPort[port].DCB.flowControl==fc_sw && UARTPort[port].ownerid==MOD_DHL_READER)||
(uart_support_autoescape()==KAL_FALSE))
{
if (data == UARTPort[port].DCB.xonChar)
{
PutUARTByteDelay(port, escape_char);
PutUARTByteDelay(port, 0x01);
}
else if (data == UARTPort[port].DCB.xoffChar)
{
PutUARTByteDelay(port, escape_char);
PutUARTByteDelay(port, 0x02);
}
else if (data == escape_char)
{
PutUARTByteDelay(port, escape_char);
PutUARTByteDelay(port, 0x03);
}
else
{
PutUARTByteDelay(port, data);
}
}
else
{
PutUARTByteDelay(port, data);
}
}
kal_uint16 U_ExBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length, kal_uint8 *status, module_type ownerid)
{
kal_uint16 real_count= Length, index;
kal_uint16 data_count = 0;
if((kal_query_boot_mode() == FACTORY_BOOT && UARTPort[port].DCB.flowControl == fc_sw && UARTPort[port].ownerid == MOD_DHL_READER)
|| (uart_support_autoescape() == KAL_FALSE && UARTPort[port].DCB.flowControl == fc_sw))
//if(0)
{
for(index = 0; (index < real_count) && (data_count < Length); index++)
{
// The following are for software flow control
if(uart_escape_state==0)
{
if(*(Buffaddr + index) == 0x77)
{
uart_escape_state=0x77;
} else
{
*(Buffaddr + data_count) = *(Buffaddr + index);
data_count++;
}
} else if(uart_escape_state == 0x77)
{
switch(*(Buffaddr + index))
{
case 0x01:
*(Buffaddr+data_count) = 0x11;//UARTPort[port].DCB.xonChar;
data_count++;
break;
case 0x02:
*(Buffaddr+data_count)= 0x13; //UARTPort[port].DCB.xoffChar;
data_count++;
break;
case 0x03:
*(Buffaddr + data_count) = 0x77;
data_count++;
break;
default:
break;
}
uart_escape_state=0x0;
}
}
}else{
for(index = 0; (index < real_count) && (data_count < Length); index++){
*(Buffaddr + data_count) = *(Buffaddr + index);
data_count++;
}
}
return data_count;
}
void UART_META_ExBytes(UART_PORT port, void * gpd_head, void * gpd_tail){
hdma_tbd_t *bd_ptr = NULL, *p_bd_cur =NULL;
hdma_tgpd_t *gpd_ptr = NULL;
kal_uint32 gpd_data_len=0, gpd_data_real_len = 0, bd_data_len=0, bd_data_real_len = 0;
kal_uint8 *gpd_data_ptr=NULL, *bd_data_ptr=NULL;
gpd_ptr = (hdma_tgpd_t*)gpd_head;
while(1){
if (QBM_DES_GET_BDP(gpd_ptr)) {
bd_ptr = QBM_DES_GET_DATAPTR(gpd_ptr);
p_bd_cur = bd_ptr;
while (1) {
bd_data_len = QBM_DES_GET_DATALEN(p_bd_cur);
if(bd_data_len>0){
bd_data_ptr = QBM_DES_GET_DATAPTR(p_bd_cur);
QBM_CACHE_INVALID(bd_data_ptr, bd_data_len);
bd_data_real_len = U_ExBytes(port,bd_data_ptr ,bd_data_len, NULL, UARTPort[port].ownerid);
if (bd_data_len != bd_data_real_len) {
QBM_CACHE_FLUSH(bd_data_ptr, bd_data_real_len);
QBM_DES_SET_DATALEN(p_bd_cur, bd_data_real_len);
QBM_CACHE_FLUSH(p_bd_cur, QBM_SIZE_TGPD);
}
}
if (QBM_DES_GET_EOL(p_bd_cur)) {
break;
}
p_bd_cur =(void *) QBM_DES_GET_NEXT(p_bd_cur);
}
} else{
gpd_data_len = QBM_DES_GET_DATALEN(gpd_ptr);
if(gpd_data_len>0){
gpd_data_ptr = QBM_DES_GET_DATAPTR(gpd_ptr);
QBM_CACHE_INVALID(gpd_data_ptr, gpd_data_len);
gpd_data_real_len = U_ExBytes(port,gpd_data_ptr ,gpd_data_len, NULL, UARTPort[port].ownerid);
if (gpd_data_len != gpd_data_real_len) {
QBM_CACHE_FLUSH(gpd_data_ptr, gpd_data_real_len);
QBM_DES_SET_DATALEN(gpd_ptr,gpd_data_real_len);
QBM_CACHE_FLUSH(gpd_ptr, QBM_SIZE_TGPD);
}
}
}
if(gpd_ptr == gpd_tail)
{
break;
} else
{
gpd_ptr = (void *) QBM_DES_GET_NEXT(gpd_ptr);
}
}
}
void UART_Boot_PutUARTBytes(UART_PORT port, kal_uint8 *data,kal_uint16 len)
{
volatile kal_uint16 LSR;
kal_uint16 index;
static kal_uint32 UART_Boot_Send_Count = 0;
UART_Boot_Send_Count+=len;
for(index=0;index<len;index++)
UART_PutUARTByte_limited(port,*(data+index));
index = 0;
while(1) //make sure tx already send out all data.
{
LSR = DRV_UART_Reg(UART_LSR(UART_BaseAddr[port]));
if( LSR & UART_LSR_THRE )
{
break;
}else if( (MCU_BOOT_SPEED/DEBUG_BAUDRATE) < index++)
{
init_log_fail_count++;
break;
}
}
}
void U_PutUARTBytes(UART_PORT port, kal_uint8 *data,kal_uint16 len) {
kal_uint16 index;
for(index=0;index<len;index++)
pUart_CMD_FUNC[port]->PutUARTByte(port,*(data+index));
}
void PutUARTDatas(UART_PORT port, kal_uint8 escape_char, kal_uint8 *data,kal_uint16 len)
{
kal_uint16 index;
if(port >= MAX_UART_PORT_NUM)
return;
if( (sst_get_exception_count() > 0) && (0 == UARTPort[port].Tx_DMA_Ch) && (1500000 == UARTPort[port].DCB.baud))
for(index=0;index<len;index++)
PutUARTDataDelay(port,escape_char,*(data+index));
else
for(index=0;index<len;index++)
PutUARTData(port,escape_char,*(data+index));
}
void U_SetBaudRate(UART_PORT port, UART_baudrate baudrate, module_type ownerid)
{
kal_uint16 byte = 0;
kal_uint32 freq_div = 1;
kal_uint32 sample_count = 0;
kal_uint32 UART_BASE;
UART_BASE = UART_BaseAddr[port];
UARTPort[port].DCB.baud = baudrate;
if(baudrate)
{
do {
sample_count = (UART_CLOCK + (freq_div * baudrate / 2)) / (freq_div * baudrate);
if(sample_count > 0xff) freq_div++;
} while(sample_count > 0xff);
}
// configure register
DRV_UART_WriteReg(UART_RATE_STEP(UART_BASE), 0x3);
byte = DRV_Reg32(UART_LCR(UART_BASE)); // DLAB start
DRV_WriteReg32(UART_LCR(UART_BASE), byte | UART_LCR_DLAB);
DRV_WriteReg32(UART_DLL(UART_BASE), freq_div & 0xFF);
DRV_WriteReg32(UART_DLH(UART_BASE), (freq_div >> 8) & 0xFF);
DRV_UART_WriteReg(UART_STEP_COUNT(UART_BASE), sample_count - 1);
DRV_UART_WriteReg(UART_SAMPLE_COUNT(UART_BASE), sample_count >> 1);
DRV_UART_WriteReg(UART_LCR(UART_BASE), byte); // DLAB end
}
void UART_Bootup_Init()
{
UARTPort[DEBUG_PORT].ownerid = (module_type)( (kal_uint16)MOD_UART1_HISR + (kal_uint8) DEBUG_PORT);
//Set SW flow control as equal to catcher default flow control
DRV_UART_WriteReg(UART_LCR(UART1_base),0xbf); /* Enchance setting */
DRV_UART_WriteReg(UART_EFR(UART1_base),UART_EFR_SWFlowCtrlX1);
//always open as new SW flow control, DHL under META will reset to disable
{
DRV_UART_WriteReg(UART_ESCAPE_DAT(UART1_base),0x77);
DRV_UART_WriteReg(UART_ESCAPE_EN(UART1_base),0x1);
}
DRV_UART_WriteReg(UART_XON1(UART1_base),0x11);
DRV_UART_WriteReg(UART_XOFF1(UART1_base),0x13);
DRV_UART_WriteReg(UART_XON2(UART1_base),0x11);
DRV_UART_WriteReg(UART_XOFF2(UART1_base),0x13);
DRV_UART_WriteReg(UART_LCR(UART1_base),0x3);
U_SetBaudRate(DEBUG_PORT, DEBUG_BAUDRATE, (module_type)( (kal_uint16)MOD_UART1_HISR + (kal_uint8) DEBUG_PORT));
}
/*This function is to cover 6218B/6219 hw bug.
UART should not send receiving data to its FIFO when doing auto baud*/
void U_SetAutoBaud_Div(UART_PORT port, module_type ownerid) {}
void U_SetDCBConfig(UART_PORT port, UARTDCBStruct *UART_Config, module_type ownerid)
{
kal_uint16 byte;
kal_uint16 IER;
kal_uint32 savedMask;
kal_uint32 UART_BASE;
UART_BASE = UART_BaseAddr[port];
savedMask = SaveAndSetIRQMask();
IER = DRV_UART_Reg(UART_IER(UART_BASE));
DRV_UART_WriteReg(UART_IER(UART_BASE),UART_IER_ALLOFF);
RestoreIRQMask(savedMask);
U_SetBaudRate(port, UART_Config->baud, ownerid);
/* Setup N81 */
byte = DRV_UART_Reg(UART_LCR(UART_BASE)); /* DLAB start */
byte &= ~UART_DATA_MASK;
switch(UART_Config->dataBits)
{
case len_5:
byte |= UART_WLS_5;
break;
case len_6:
byte |= UART_WLS_6;
break;
case len_7:
byte |= UART_WLS_7;
break;
case len_8:
byte |= UART_WLS_8;
break;
default:
break;
}
byte &= ~UART_STOP_MASK;
switch(UART_Config->stopBits)
{
case sb_1:
byte |= UART_1_STOP;
break;
case sb_2:
byte |= UART_2_STOP;
break;
case sb_1_5:
byte |= UART_1_5_STOP;
break;
default:
break;
}
byte &= ~UART_PARITY_MASK;
switch(UART_Config->parity)
{
case pa_none:
byte |= UART_NONE_PARITY;
break;
case pa_odd:
byte |= UART_ODD_PARITY;
break;
case pa_even:
byte |= UART_EVEN_PARITY;
break;
case pa_space:
byte |= UART_SPACE_PARITY;
break;
default:
break;
}
DRV_UART_WriteReg(UART_LCR(UART_BASE),byte); /* DLAB End */
/* flowControl */
byte = DRV_UART_Reg(UART_LCR(UART_BASE));
DRV_UART_WriteReg(UART_LCR(UART_BASE),0xbf); /* Enchance setting */
switch(UART_Config->flowControl)
{
case fc_none:
DRV_UART_WriteReg(UART_EFR(UART_BASE),UART_EFR_ALLOFF);
// Disable AutoEscape, we expect to use this functionality for S/W flow control
/*For AutoEscape*/
DRV_UART_WriteReg(UART_ESCAPE_EN(UART_BaseAddr[port]),0x0);
break;
case fc_hw:
DRV_UART_WriteReg(UART_EFR(UART_BASE),UART_EFR_AutoRTSCTS);
// Disable AutoEscape, we expect to use this functionality for S/W flow control
/*For AutoEscape*/
DRV_UART_WriteReg(UART_ESCAPE_EN(UART_BaseAddr[port]),0x0);
break;
case fc_sw:
DRV_UART_WriteReg(UART_EFR(UART_BASE), UART_EFR_SWFlowCtrlX1 |UART_EFR_Enchance);
//reset first
DRV_UART_WriteReg(UART_ESCAPE_EN(UART_BaseAddr[port]),0x0);
if(uart_support_autoescape()==KAL_TRUE)
{
/*For META, Dont use auto escape*/
#if defined(META_MODE_SW_ESCAPING)
if(kal_query_boot_mode() != FACTORY_BOOT || UARTPort[port].ownerid != MOD_DHL_READER)
#endif
{
/*For AutoEscape*/
DRV_UART_WriteReg(UART_ESCAPE_DAT(UART_BaseAddr[port]),0x77);
DRV_UART_WriteReg(UART_ESCAPE_EN(UART_BaseAddr[port]),0x1);
}
}
break;
default:
break;
}
/* XON and XOFF characters */
DRV_UART_WriteReg(UART_XON1(UART_BASE),UART_Config->xonChar);
DRV_UART_WriteReg(UART_XOFF1(UART_BASE),UART_Config->xoffChar);
DRV_UART_WriteReg(UART_XON2(UART_BASE),UART_Config->xonChar);
DRV_UART_WriteReg(UART_XOFF2(UART_BASE),UART_Config->xoffChar);
DRV_UART_WriteReg(UART_LCR(UART_BASE),byte); /* DLAB End */
kal_mem_cpy( &UARTPort[port].DCB, UART_Config, sizeof(UARTDCBStruct) );
savedMask = SaveAndSetIRQMask();
DRV_UART_WriteReg(UART_IER(UART_BASE),IER);
RestoreIRQMask(savedMask);
}
void U_ReadDCBConfig (UART_PORT port, UARTDCBStruct *DCB)
{
kal_mem_cpy( DCB, &UARTPort[port].DCB, sizeof(UARTDCBStruct) );
}
void UART_loopback(UART_PORT port)
{
kal_uint16 tmp;
kal_uint32 UART_BASE;
/* Enable Loop Back test!! */
if(port >= MAX_UART_PORT_NUM)
return;
UART_BASE = UART_BaseAddr[port];
tmp = DRV_UART_Reg(UART_MCR(UART_BASE));
tmp |= UART_MCR_LOOPB;
DRV_UART_WriteReg(UART_MCR(UART_BASE), tmp);
}
void UART_PDN_Disable(UART_PORT port)
{
switch(port)
{
case uart_port1:
PDN_CLR(PDN_UART0);
#if defined(__HIF_UART_SUPPORT__) ||(defined(DRV_DEBUG)&&(defined(DRV_DEBUG_DMA_MODE) || defined(DRV_DEBUG_BUFFER_DMA_MODE)))
HDMA_PDN_CLR(port+2);
HDMA_PDN_CLR(port+3);
#endif
break;
case uart_port2:
PDN_CLR(PDN_UART1);
break;
default:
ASSERT(0);
break;
}
}
void UART_PDN_Enable(UART_PORT port)
{
switch(port)
{
case uart_port1:
PDN_SET(PDN_UART0);
HDMA_PDN_SET(port+2);
HDMA_PDN_SET(port+3);
break;
case uart_port2:
PDN_SET(PDN_UART1);
break;
default:
ASSERT(0);
break;
}
}
void UART_HWInit(UART_PORT port)
{
UARTDCBStruct *DCBdefault;
UARTDCBStruct UART_DefaultConfig =
{
UART_BAUD_1500000, // baud
len_8, // dataBits
sb_1, // stopBits
pa_none, // parity
fc_none, // no flow control
0x11, // xonChar
0x13, // xoffChar
KAL_FALSE
};
kal_uint32 UART_BASE;
if(port >= MAX_UART_PORT_NUM)
return;
UART_BASE = UART_BaseAddr[port];
UART_PDN_Disable(port);
/* Setup N81,(UART_WLS_8 | UART_NONE_PARITY | UART_1_STOP) = 0x03 */
/* BaudRate and autoflowcontrol */
DCBdefault = (UARTDCBStruct *)&UART_DefaultConfig;
U_SetDCBConfig(port, DCBdefault, UARTPort[port].ownerid);
DRV_UART_Reg(UART_LSR(UART_BASE));
DRV_UART_Reg(UART_MSR(UART_BASE));
/* DTR , RTS is on, data will be coming,Output2 is high */
DRV_UART_SetBits(UART_MCR(UART_BASE), UART_MCR_Normal);
DRV_UART_WriteReg(UART_IER(UART_BASE), UART_IER_ALLOFF);
// Set handle value to 0xFF to indicate this handle is invalid
UARTPort[port].handle = 0xFF;
UARTPort[port].Rec_state = UART_RecNormal;
UARTPort[port].port_no = port;
UARTPort[port].sleep_on_tx = uart_sleep_on_tx_allow;
UARTPort[port].EnableTX= KAL_TRUE;
UARTPort[port].power_on= KAL_TRUE;
// HDMA related HW init
// init FIFO Control Regitser: UART_FCR_RFTL_12 | UART_FCR_TFTL_0 | UART_FCR_CLRT | UART_FCR_CLRR | UART_FCR_FIFOE
DRV_UART_WriteReg(UART_FCR(UART_BaseAddr[port]), 0x87);
#if defined(MTK_SLEEP_ENABLE)
DRV_UART_WriteReg(UART_SLEEP_EN(UART_BASE),KAL_TRUE);
#endif
switch(port)
{
case uart_port1:
// init TX HDMA
HDMA_MODE_CONFIG(UART1_HDMA_TX_CHANNEL, HDMA_CKSUM_EN_DEFAULT, HDMA_LIST_MODE, HDMA_CKSUM_12B);
HDMA_CONFIG(UART1_HDMA_TX_CHANNEL, HDMA_BURST_SIZE_DEFAULT, HDMA_DEV_BUS_WIDTH_DEFAULT, HDMA_MEM_BUS_WIDTH_DEFAULT);
HDMA_BUF0_XFER_SIZE_CONFIG(UART1_HDMA_TX_CHANNEL, 0);
// init RX HDMA
HDMA_CONFIG_RX_SEL(UART1_HDMA_RX_CHANNEL, 0x3);
HDMA_MODE_CONFIG(UART1_HDMA_RX_CHANNEL, HDMA_CKSUM_EN_DEFAULT, HDMA_LIST_MODE, HDMA_CKSUM_12B);
HDMA_CONFIG(UART1_HDMA_RX_CHANNEL, HDMA_BURST_SIZE_DEFAULT, HDMA_DEV_BUS_WIDTH_DEFAULT, HDMA_MEM_BUS_WIDTH_DEFAULT);
HDMA_BUF0_XFER_SIZE_CONFIG(UART1_HDMA_RX_CHANNEL, 0);
#ifdef DRV_DEBUG
DRV_WriteReg32(UART_DMA_EN(UART_BaseAddr[port]), 0x0);
#else
DRV_WriteReg32(UART_DMA_EN(UART_BaseAddr[port]), UART_TXRXDMA_ON|UART_TO_CNT_AUTORST);
DRV_WriteReg32(UART_DMA_ACK(UART_BaseAddr[port]),UART_DMA_ACK_DIS);
#endif
break;
case uart_port2:
break;
default:
ASSERT(0);
break;
}
// If needTxDoneCb is 1, the driver must call DclSerialPort_DrvTxDone(handle, source_id, tx_ior) after tx_ior data is sent.
// initial value is 0
UARTPort[port].need_tx_done_cb = KAL_FALSE;
}
kal_bool U_Open(UART_PORT port, module_type ownerid)
{
kal_uint32 UART_BASE;
kal_uint16 MSR;
kal_uint8 byte;
kal_uint8 irq_code = 0;
UART_BASE = UART_BaseAddr[port];
if(port == uart_port_null)
return KAL_FALSE;
UARTPort[port].initialized = KAL_TRUE;
UARTPort[port].ownerid = ownerid;
UARTPort[port].RingBuffers.rx_buffer = UART_rings->ring[port].rx_adrs;
UARTPort[port].RingBuffers.tx_buffer = UART_rings->ring[port].tx_adrs;
Buf_init(&(UARTPort[port].Rx_Buffer),(kal_uint8 *)(UARTPort[port].RingBuffers.rx_buffer),(kal_uint16)UART_rings->ring[port].rx_len);
Buf_init(&(UARTPort[port].Tx_Buffer),(kal_uint8 *)(UARTPort[port].RingBuffers.tx_buffer),(kal_uint16)UART_rings->ring[port].tx_len);
if( UART_IsVfifoSetting(port, TX_VFIFO) == KAL_FALSE )
{
UARTPort[port].RingBuffers.txISR_buffer = UART_rings->ring[port].txisr_adrs;
Buf_init(&(UARTPort[port].Tx_Buffer_ISR),(kal_uint8 *)(UARTPort[port].RingBuffers.txISR_buffer),(kal_uint16)UART_rings->ring[port].txisr_len);
}
MSR = DRV_UART_Reg(UART_MSR(UART_BASE));
if (MSR & UART_MSR_DSR)
UARTPort[port].DSR = io_high;
else
UARTPort[port].DSR = io_low;
/* Rx FIFO trigger = 62, Tx FIFO trigger is 16, and FIFO enable. */
DRV_UART_WriteReg(UART_FCR(UART_BASE),UART_FCR_Normal);
if( UART_IsVfifoSetting(port, TXRX_VFIFO))
{
ASSERT(0);/*wrong configuration*/
}
else
{
if (UARTPort[port].DCB.flowControl == fc_none)
{
DRV_UART_WriteReg(UART_IER(UART_BaseAddr[port]),IER_HW_NORMALINTS);
}
else if (UARTPort[port].DCB.flowControl == fc_hw)
{
// DRV_UART_WriteReg(UART_IER(UART_BaseAddr[port]),IER_HW_NORMALINTS);
DRV_UART_WriteReg32(UART_MCR(UART_BASE), (DRV_UART_Reg32(UART_MCR(UART_BASE)) | 0x02));
byte = DRV_UART_Reg(UART_LCR(UART_BASE));
DRV_UART_WriteReg(UART_LCR(UART_BASE), 0xbf);
DRV_UART_WriteReg(UART_EFR(UART_BASE), DRV_UART_Reg(UART_EFR(UART_BASE)) | UART_EFR_AutoRTSCTS);
DRV_UART_WriteReg(UART_LCR(UART_BASE), byte);
}
else if (UARTPort[port].DCB.flowControl == fc_sw)
{
// need to set EFR enhance before IRE
byte = DRV_UART_Reg(UART_LCR(UART_BASE));
DRV_UART_WriteReg(UART_LCR(UART_BASE),0xbf);
DRV_UART_WriteReg(UART_EFR(UART_BASE), DRV_UART_Reg(UART_EFR(UART_BASE)) | UART_EFR_Enchance);
DRV_UART_WriteReg(UART_LCR(UART_BASE),byte);
DRV_UART_WriteReg(UART_IER(UART_BaseAddr[port]),IER_SW_NORMALINTS);
DRV_UART_WriteReg(UART_ESCAPE_EN(UART_BaseAddr[port]),0x0); //reset to disable first
if(uart_support_autoescape()==KAL_TRUE)
{
/*For META, Dont use auto escape*/
#if defined(META_MODE_SW_ESCAPING)
if(kal_query_boot_mode() != FACTORY_BOOT || UARTPort[port].ownerid != MOD_DHL_READER)
#endif
{
/*For AutoEscape*/
byte = DRV_UART_Reg(UART_LCR(UART_BASE));
// DLAB start */
DRV_UART_WriteReg(UART_LCR(UART_BASE),0xbf); /* Enchance setting */
DRV_UART_WriteReg(UART_XON1(UART_BaseAddr[port]),0x11);
DRV_UART_WriteReg(UART_XON2(UART_BaseAddr[port]),0x11);
DRV_UART_WriteReg(UART_XOFF1(UART_BaseAddr[port]),0x13);
DRV_UART_WriteReg(UART_XOFF2(UART_BaseAddr[port]),0x13);
//autoescape
DRV_UART_WriteReg(UART_ESCAPE_DAT(UART_BaseAddr[port]),0x77);
DRV_UART_WriteReg(UART_ESCAPE_EN(UART_BaseAddr[port]),0x1);
DRV_UART_WriteReg(UART_LCR(UART_BASE),byte); /* Enchance setting */
}
}
}
}
/*For excetpion, we dont need to do the following */
#ifdef __MTK_TARGET__
if(INT_QueryExceptionStatus())
return KAL_TRUE;
#endif
switch(port)
{
case uart_port1:
irq_code = UART_GetIRQCode(uart_port1);
IRQMask(irq_code);
//IRQ_Register_LISR(irq_code, UART1_LISR, "UART1");
//IRQSensitivity(irq_code, LEVEL_SENSITIVE);
IRQClearInt(irq_code);
DRV_WriteReg32(UART_IER(UART_BASE), 0x4);
IRQUnmask(irq_code);
break;
case uart_port2:
irq_code = UART_GetIRQCode(uart_port2);
IRQMask(irq_code);
//IRQ_Register_LISR(irq_code, UART2_LISR, "UART2");
//IRQSensitivity(irq_code, LEVEL_SENSITIVE);
IRQClearInt(irq_code);
DRV_WriteReg32(UART_IER(UART_BASE), 0x4);
IRQUnmask(irq_code);
break;
default:
ASSERT(0);
break;
}
IRQMask(UART_HDMA_INTR_ID);
//IRQ_Register_LISR(UART_HDMA_INTR_ID, uart_hdma_lisr, "UART_HDMA");
//IRQSensitivity(UART_HDMA_INTR_ID, LEVEL_SENSITIVE);
HDMA_LENERR_INTR_UNMASK(2);
HDMA_BD_CSERR_INTR_UNMASK(2);
HDMA_GPD_CSERR_INTR_UNMASK(2);
HDMA_LENERR_INTR_UNMASK(3);
HDMA_BD_CSERR_INTR_UNMASK(3);
HDMA_GPD_CSERR_INTR_UNMASK(3);
HDMA_QE_INTR_UNMASK(3); // RX done
HDMA_INT_CLEAR_ALL();
IRQUnmask(UART_HDMA_INTR_ID);
return KAL_TRUE;
}
void U_Purge(UART_PORT port, UART_buffer dir, module_type ownerid)
{
kal_uint32 UART_BASE = UART_BaseAddr[port];
/* Rx FIFO trigger = 62, Tx FIFO trigger is 16, and FIFO enable. */
// for MT6290, Rx FIFO trigger = 12. Tx FIFO trigger is 0
if (dir == RX_BUF)
DRV_UART_WriteReg(UART_FCR(UART_BASE),(UART_FCR_Normal & ~UART_FCR_CLRT));
else
DRV_UART_WriteReg(UART_FCR(UART_BASE),(UART_FCR_Normal & ~UART_FCR_CLRR));
}
void U_Close(UART_PORT port, module_type ownerid)
{
kal_uint32 UART_BASE = UART_BaseAddr[port];
kal_uint8 irq_code;
UARTPort[port].initialized = KAL_FALSE;
UARTPort[port].ownerid = (module_type) ((kal_uint16) MOD_UART1_HISR + (kal_uint8) port);
switch(port)
{
case uart_port1:
irq_code = UART_GetIRQCode(uart_port1);
IRQMask(irq_code);
break;
case uart_port2:
irq_code = UART_GetIRQCode(uart_port2);
IRQMask(irq_code);
break;
default:
ASSERT(0);
break;
}
DRV_UART_WriteReg(UART_IER(UART_BASE), UART_IER_ALLOFF);
U_ConfigEscape(port, 0xff, 0, UARTPort[port].ownerid);
U_ClrRxBuffer(port, UARTPort[port].ownerid); // clear sw RX buffer
U_ClrTxBuffer(port, UARTPort[port].ownerid); // clear sw TX buffer
U_Purge(port, RX_BUF, UARTPort[port].ownerid); // clear hw RX FIFO
U_Purge(port, TX_BUF, UARTPort[port].ownerid); // clear hw TX FIFO
DRV_UART_WriteReg(UART_IER(UART_BASE),UART_IER_ALLOFF);
UART_PDN_Enable(port);
if(UARTPort[port].handle != 0xFF)
{
UARTPort[port].handle = 0xFF;
}
}
void U_SetOwner (UART_PORT port, module_type ownerid)
{
U_ClrTxBuffer(port, UARTPort[port].ownerid); // clear sw TX buffer
U_ClrRxBuffer(port, UARTPort[port].ownerid); // clear sw RX buffer
UARTPort[port].ownerid = ownerid;
UARTPort[port].need_tx_done_cb = KAL_FALSE;
}
module_type U_GetOwnerID(UART_PORT port)
{
return UARTPort[port].ownerid;
}
void U_ConfigEscape (UART_PORT port, kal_uint8 EscChar, kal_uint16 ESCGuardtime, module_type ownerid)
{
UARTPort[port].ESCDet.EscChar = EscChar;
UARTPort[port].ESCDet.GuardTime = ESCGuardtime;
// Escape character register is WO
DRV_UART_WriteReg(UART_ESCAPE_DAT(UART_BaseAddr[port]), EscChar); // added by ansel
DRV_UART_WriteReg(UART_GUARD(UART_BaseAddr[port]), ESCGuardtime); // added by ansel
if (UARTPort[port].ESCDet.GuardTime)
{
UARTPort[port].Rec_state = UART_RecNormal;
}
}
void U_SetFlowCtrl(UART_PORT port, kal_bool XON, module_type ownerid) {} /*NULL for all*/
kal_uint32 U_GetFlowCtrl(UART_PORT port, module_type ownerid)
{
kal_uint16 IER, LCR;
kal_uint32 savedMask;
kal_uint32 UART_BASE;
kal_uint32 EFR;
UART_BASE = UART_BaseAddr[port];
savedMask = SaveAndSetIRQMask();
IER = DRV_UART_Reg(UART_IER(UART_BASE));
DRV_UART_WriteReg(UART_IER(UART_BASE), UART_IER_ALLOFF);
RestoreIRQMask(savedMask);
LCR = DRV_UART_Reg(UART_LCR(UART_BASE));
DRV_UART_WriteReg(UART_LCR(UART_BASE), 0xBF);
EFR = DRV_UART_Reg(UART_EFR(UART_BASE));
DRV_UART_WriteReg(UART_LCR(UART_BASE), LCR);
savedMask = SaveAndSetIRQMask();
DRV_UART_WriteReg(UART_IER(UART_BASE), IER);
RestoreIRQMask(savedMask);
return EFR;
}
void U_CtrlDCD(UART_PORT port, IO_level SDCD, module_type ownerid) {} /*NULL for DCE*/
void U_CtrlRI (UART_PORT port, IO_level SRI, module_type ownerid) {} /*NULL for DCE*/
void U_CtrlDTR (UART_PORT port, IO_level SDTR, module_type ownerid) {}
void U_ReadHWStatus(UART_PORT port, IO_level *SDSR, IO_level *SCTS)
{
kal_uint16 MSR;
kal_uint32 UART_BASE;
UART_BASE = UART_BaseAddr[port];
MSR = DRV_UART_Reg(UART_MSR(UART_BASE));
*SDSR = (IO_level)(( MSR & UART_MSR_DSR) >> 5);
*SCTS = (IO_level)(( MSR & UART_MSR_CTS) >> 4);
}
void U_CtrlBreak(UART_PORT port, IO_level SBREAK, module_type ownerid)
{
kal_uint32 UART_BASE = UART_BaseAddr[port];
if(SBREAK == io_high)
{
if(HDMA_BUF0_IS_ACTIVE((port + 2)))
HDMA_BUF0_STOP((port + 2));
DRV_UART_SetBits(UART_LCR(UART_BASE), UART_LCR_BREAK);
} else
{
DRV_UART_ClearBits(UART_LCR(UART_BASE), UART_LCR_BREAK);
if(uart_wait_tgpd_head[port] != NULL || uart_tgpd_head[port] != NULL)
HDMA_BUF0_RESUME((port + 2));
}
}
kal_uint16 U_GetBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length, kal_uint8 *status, module_type ownerid)
{
kal_uint16 real_count, index;
kal_uint16 data_count = 0;
if(status != NULL)
*status = 0;
DisableRxIntr(UART_BaseAddr[port]);
if (status != NULL)
{
if (UARTPort[port].EscFound)
{
*status |= UART_STAT_EscDet;
UARTPort[port].EscFound = KAL_FALSE;
}
if(UARTPort[port].breakDet)
{
*status |= UART_STAT_Break;
UARTPort[port].breakDet = KAL_FALSE;
}
}
EnableRxIntr(UART_BaseAddr[port]);
do {
Buf_GetBytesAvail(&(UARTPort[port].Rx_Buffer),real_count);
if((kal_query_boot_mode() == FACTORY_BOOT && UARTPort[port].DCB.flowControl == fc_sw && UARTPort[port].ownerid == MOD_DHL_READER)
|| (uart_support_autoescape() == KAL_FALSE && UARTPort[port].DCB.flowControl == fc_sw))
{
for(index = 0; (index < real_count) && (data_count < Length); index++)
{
Buf_Pop(&(UARTPort[port].Rx_Buffer), *(Buffaddr + data_count));
// The following are for software flow control
if(uart_escape_state==0)
{
if(*(Buffaddr + data_count) == 0x77)
{
uart_escape_state=0x77;
} else
{
data_count++;
}
} else if(uart_escape_state == 0x77)
{
switch(*(Buffaddr + data_count))
{
case 0x01:
*(Buffaddr+data_count) = UARTPort[port].DCB.xonChar;
data_count++;
break;
case 0x02:
*(Buffaddr+data_count)=UARTPort[port].DCB.xoffChar;
data_count++;
break;
case 0x03:
*(Buffaddr + data_count) = 0x77;
data_count++;
break;
default:
break;
}
uart_escape_state=0x0;
}
}
} else // HW flow control
{
for(index = 0; (index < real_count) && (data_count < Length); index++)
{
Buf_Pop(&(UARTPort[port].Rx_Buffer),*(Buffaddr + data_count));
data_count++;
}
}
// satisfy uart owner request, so break
if (data_count == Length) break;
// disable interrupt
DisableRxIntr(UART_BaseAddr[port]);
Buf_GetBytesAvail(&(UARTPort[port].Rx_Buffer),real_count);
// there is no data in ringbuffer, so break
if(real_count == 0)
{
send_Rxilm[port] = KAL_TRUE;
// enable interrupt
EnableRxIntr(UART_BaseAddr[port]);
break;
}
/* enable interrupt*/
EnableRxIntr(UART_BaseAddr[port]);
} while(KAL_TRUE);
return data_count;
}
#ifdef DRV_DEBUG
void UART_DMA_PutBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length)
{
if(port>=uart_port3){
return;
}
clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)Buffaddr), CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)Buffaddr, (kal_uint32)Length));
HDMA_BUF0_PROG_ADDR_CONFIG(port+2, (kal_uint32)Buffaddr);
HDMA_BUF0_XFER_SIZE_CONFIG(port+2, (kal_uint32)Length);
Data_Sync_Barrier();
HDMA_BUF0_START(port+2);
}
kal_uint16 BMT_PutBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length)
{
kal_uint16 real_count, index;
#if defined(DRV_DEBUG_BUFFER_DMA_MODE)
kal_uint16 is_empty;
#endif
if(port >= MAX_UART_PORT_NUM)
return 0;
Buf_GetRoomLeft(&(UARTPort[port].Tx_Buffer), real_count);
if(real_count > Length)
{
real_count = Length;
}
/*
* The spin lock is used for the con-currency case of HDMA HISR
* and dbg_print. The write/read pointer of buffer is the basis
* whether to start the next DMA or NOT, so use the spin lock
* to protect the pointer updatding actions
*/
#if defined(DRV_DEBUG_BUFFER_DMA_MODE)
#ifndef KTEST_UART_TRACES
kal_take_spinlock(print_buf_lock, KAL_INFINITE_WAIT);
#else
kal_hrt_take_itc_lock(KAL_ITC_PRINT, KAL_INFINITE_WAIT);
#endif
/* To check if DMA should be start in this API */
Buf_IsEmpty(&(UARTPort[port].Tx_Buffer), is_empty);
#endif
for(index = 0; index < real_count; index++)
{
Buf_Push(&(UARTPort[port].Tx_Buffer), *(Buffaddr + index));
}
#if defined(DRV_DEBUG_BUFFER_DMA_MODE)
#ifndef KTEST_UART_TRACES
kal_give_spinlock(print_buf_lock);
#else
kal_hrt_give_itc_lock(KAL_ITC_PRINT);
#endif
#endif
switch(port)
{
case uart_port1:
#if defined(DRV_DEBUG_BUFFER_DMA_MODE)
if (is_empty == Buff_isEmpty)
UART_TxDMAHandler(&UARTPort[uart_port1], 0);
#else
EnableTxIntr(UART_BaseAddr[port]);
#endif
break;
case uart_port2:
EnableTxIntr(UART_BaseAddr[port]);
break;
default:
ASSERT(0);
break;
}
return real_count;
}
#endif /*DRV_DEBUG*/
/*************************************************************************
* FUNCTION
* UART_GetTxWorkingMode
*
* DESCRIPTION
*
* This function is to get the uart TX working mode.
*
* PARAMETERS
* port - the uart port
*
* RETURNS
* UART_ON_VFIFO: the uart port Tx working on VFIFO mode
* UART_ON_DMA: the uart port Tx working on normal DMA mode
* UART_ON_MCU: the uart port Tx working on sw mode
*
* Global AFFECTED
*
*************************************************************************/
UART_WORKING_MODE UART_GetTxWorkingMode(UART_PORT port)
{
if(UART_IsVfifoSetting(port, TX_VFIFO))
return UART_ON_VFIFO;
return UART_ON_MCU;
}
kal_uint16 U_PutBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length, module_type ownerid )
{
kal_uint16 real_count, index;
if(port >= MAX_UART_PORT_NUM)
return 0;
Buf_GetRoomLeft(&(UARTPort[port].Tx_Buffer), real_count);
if(real_count > Length)
{
real_count = Length;
}
for(index = 0; index < real_count; index++)
{
Buf_Push(&(UARTPort[port].Tx_Buffer), *(Buffaddr + index));
}
switch(port)
{
case uart_port1:
EnableTxIntr(UART_BaseAddr[port]);
break;
case uart_port2:
EnableTxIntr(UART_BaseAddr[port]);
break;
default:
ASSERT(0);
break;
}
return real_count;
}
#ifndef __ROMSA_SUPPORT__ /* Note: for ROM code */
#if defined(__MTK_INTERNAL__) && defined(__MTK_TARGET__)
kal_uint16 DEVDRV_LS_INTERNCODE
#else
kal_uint16
#endif
U_PutISRBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length, module_type ownerid)
{
return 0;
}
#endif /* Note: for ROM code */
#if defined(__MTK_INTERNAL__) && defined(__MTK_TARGET__)
kal_uint16 DEVDRV_LS_INTERNCODE
#else
kal_uint16
#endif
U_SendISRData(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length,kal_uint8 mode, kal_uint8 escape_char, module_type ownerid)
{
return 0;
}
kal_uint16 U_SendData(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length,kal_uint8 mode,kal_uint8 escape_char, module_type ownerid)
{
return 0;
}
//============================== ISR level ====================
/*============================ UART1 ========================*/
void UART_RLSHandler(void *parameter)
{
kal_uint16 LSR;
UARTStruct *UARTData = (UARTStruct *) parameter;
kal_uint32 UART_BASE;
if(UARTData->port_no >= MAX_UART_PORT_NUM)
return;
UART_BASE = UART_BaseAddr[UARTData->port_no];
LSR = DRV_UART_Reg(UART_LSR(UART_BASE));
/*
if(LSR & UART_LSR_OE) dbg_print("Overrun Error\n\r");
if(LSR & UART_LSR_PE) dbg_print("Parity Error\n\r");
if(LSR & UART_LSR_FE) dbg_print("Framing Error\n\r");
*/
if(LSR & UART_LSR_BI)
{
UARTData->breakDet = KAL_TRUE;
U_Purge(UARTData->port_no, RX_BUF, UARTPort[UARTData->port_no].ownerid);
}
if((LSR & UART_LSR_OE) || (LSR & UART_LSR_FIFOERR))
{
//for check BT overwrite UART FIFO, because BT do not use flow control, lost data will cause BT fail
// if((UARTPort[UARTData->port_no].ownerid == MOD_BT))
// {
// UART_DBG(__LINE__, UART_GetTimeStamp(), ust_get_current_time(), LSR);
// ASSERT(!(LSR & UART_LSR_OE)); // BT send too fast, VFIFO can not get bus, overwrite UART FIFO
// }
DisableRLSIntr(UART_BASE);
}
}
void UART_Calback(void *parameter) {}
void UART_SetRateFix(UART_PORT port) {}
int uart_pio_get_data_like_dma(UART_PORT port, kal_uint8 *ptr_dat, kal_uint32 allow_len)
{
int real_len = 0;
kal_uint32 base = UART_BaseAddr[port];
if ((DRV_Reg8(UART_LSR(base))&UART_LSR_DR) == 0) {
/* RX no data */
return 0;
}
for(;;) {
while ((real_len < allow_len) && (DRV_Reg8(UART_LSR(base))&UART_LSR_DR)) {
*ptr_dat++ = DRV_Reg8(UART_RBR(base));
real_len ++;
}
if (real_len == allow_len) {
/* Got Enough data */
break;
}
/* 32k timer, 30us */
kal_uint32 delayTime1;
delayTime1 = drv_get_current_time()+3; /* delay 60~90us*/
while(delayTime1 != drv_get_current_time()) {
if ((DRV_Reg8(UART_LSR(base))&UART_LSR_DR))
break;
}
if ((DRV_Reg8(UART_LSR(base))&UART_LSR_DR) == 0) {
/* RX Timeout */
break;
}
}
return real_len;
}
void UART_RecHandler(void *parameter) {
UARTStruct *UARTData=(UARTStruct *)parameter;
kal_uint32 UART_BASE;
kal_uint16 RoomLeft;
kal_uint16 LSR;
kal_uint8 cRXChar;
if(UARTData->port_no >= MAX_UART_PORT_NUM)
return;
UART_BASE = UART_BaseAddr[UARTData->port_no];
Buf_GetRoomLeft(&(UARTData->Rx_Buffer),RoomLeft);
while (RoomLeft)
{
LSR = DRV_UART_Reg(UART_LSR(UART_BASE));
if (LSR & UART_LSR_BI)
{
UARTData->breakDet = KAL_TRUE;
U_Purge(UARTData->port_no,RX_BUF,UARTPort[UARTData->port_no].ownerid);
LSR = DRV_UART_Reg(UART_LSR(UART_BASE));
}
if (LSR & UART_LSR_DR)
{
cRXChar = (kal_uint8)DRV_UART_Reg(UART_RBR(UART_BASE));
Buf_Push(&(UARTData->Rx_Buffer),cRXChar);
RoomLeft--;
}
else
{
break;
}
}
if (!RoomLeft) /*buffer is full*/
DisableRxIntr(UART_BASE);
}
#if defined(DRV_DEBUG_BUFFER_DMA_MODE)
/* This function might be called by HISR and dbg_print */
void UART_TxDMAHandler(void *parameter, kal_uint8 chk_done)
{
UARTStruct *UARTData = (UARTStruct *) parameter;
kal_uint16 real_count_TASK, done_count;
BUFFER_INFO *TxBuf = (BUFFER_INFO *)(&(UARTData->Tx_Buffer));
if(UARTData->port_no >= MAX_UART_PORT_NUM)
return;
/*
* The spin lock is used for the con-currency case of HDMA HISR
* and dbg_print. The write/read pointer of buffer is the basis
* whether to start the next DMA or NOT, so use the spin lock
* to protect the pointer updatding actions
*/
#ifndef KTEST_UART_TRACES
kal_take_spinlock(print_buf_lock, KAL_INFINITE_WAIT);
#else
kal_hrt_take_itc_lock(KAL_ITC_PRINT, KAL_INFINITE_WAIT);
#endif
if (chk_done) {
done_count = DRV_Reg32(GDMA_HCCR(UARTData->port_no+2)) & 0xFFFF;
if (done_count) {
BRead(TxBuf) += done_count;
if (BRead(TxBuf) >= BLength(TxBuf))
BRead(TxBuf) -= BLength(TxBuf);
}
}
Buf_GetBytesAvail_DMA(&(UARTData->Tx_Buffer), real_count_TASK);
#ifndef KTEST_UART_TRACES
kal_give_spinlock(print_buf_lock);
#else
kal_hrt_give_itc_lock(KAL_ITC_PRINT);
#endif
if (real_count_TASK) {
clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)BuffRead(TxBuf)),
CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)BuffRead(TxBuf), (kal_uint32)real_count_TASK));
HDMA_BUF0_PROG_ADDR_CONFIG(UARTData->port_no+2, (kal_uint32)BuffRead(TxBuf));
HDMA_BUF0_XFER_SIZE_CONFIG(UARTData->port_no+2, (kal_uint32)real_count_TASK);
HDMA_BUF0_START(UARTData->port_no+2);
return;
}
}
#endif
void UART_TrxHandler(void *parameter)
{
UARTStruct *UARTData = (UARTStruct *) parameter;
kal_uint32 UART_BASE;
kal_uint16 byteCount, index;
kal_uint16 real_count_TASK, real_count = 0;
kal_uint16 offset;
kal_uint8 TX_DATA;
if(UARTData->port_no >= MAX_UART_PORT_NUM)
return;
UART_BASE = UART_BaseAddr[UARTData->port_no];
byteCount = UART1_TxFIFO_DEPTH;
if(real_count != byteCount)
{
Buf_GetBytesAvail(&(UARTData->Tx_Buffer), real_count_TASK);
offset = byteCount - real_count;
real_count = real_count_TASK;
if(real_count_TASK > offset)
{
real_count = offset;
}
for(index = 0; index < real_count; index++)
{
Buf_Pop(&(UARTData->Tx_Buffer),TX_DATA);
DRV_UART_WriteReg(UART_THR(UART_BASE), (kal_uint16) TX_DATA);
}
}
Buf_GetBytesAvail(&(UARTData->Tx_Buffer), real_count_TASK);
if(real_count_TASK == 0)
DisableTxIntr(UART_BASE);
}
void UART_MsHandler(void *parameter) {}
//Bei add for get irq code
kal_uint8 UART_GetIRQCode(UART_PORT port)
{
kal_uint8 IRQ_code = 0;
switch(port)
{
case uart_port1:
IRQ_code = IRQ_UART_MD0_CODE;
break;
case uart_port2:
IRQ_code = IRQ_UART_MD1_CODE;
break;
default:
break;
}
return IRQ_code;
}
void UART1_LISR(kal_uint32 vector)
{
IRQMask(IRQ_UART_MD0_CODE);
kal_activate_hisr_index(UART_1_HISR);
}
void UART1_HISR(void)
{
kal_uint16 IIR;
IIR = DRV_UART_Reg(UART_IIR(UART_BaseAddr[uart_port1]));
if (IIR & UART_IIR_INT_INVALID)
{
IRQClearInt(IRQ_UART_MD0_CODE);
IRQUnmask(IRQ_UART_MD0_CODE);
return;
}
switch(IIR & UART_IIR_INT_MASK)
{
case UART_IIR_RLS:
UART_RLSHandler(&UARTPort[uart_port1]);
break;
case UART_IIR_CTI:
case UART_IIR_RDA:
#ifdef __SLT_TOOL_SUPPORT__
UART_RecHandler(&UARTPort[uart_port1]) ;
#endif
break;
case UART_IIR_THRE:
UART_TrxHandler(&UARTPort[uart_port1]);
break;
case UART_IIR_MS :
case UART_IIR_SWFlowCtrl:
case UART_IIR_HWFlowCtrl:
default:
break;
}
IRQClearInt(IRQ_UART_MD0_CODE);
IRQUnmask(IRQ_UART_MD0_CODE);
}
/*============================ UART2 ========================*/
void UART2_LISR(kal_uint32 vector)
{
IRQMask(IRQ_UART_MD1_CODE);
kal_activate_hisr_index(UART_2_HISR);
}
void UART2_HISR(void)
{
kal_uint16 IIR;
IIR = DRV_UART_Reg(UART_IIR(UART_BaseAddr[uart_port2]));
if (IIR & UART_IIR_INT_INVALID)
{
IRQClearInt(IRQ_UART_MD1_CODE);
IRQUnmask(IRQ_UART_MD1_CODE);
return;
}
switch(IIR & UART_IIR_INT_MASK)
{
case UART_IIR_RLS:
UART_RLSHandler(&UARTPort[uart_port2]);
break;
case UART_IIR_CTI:
case UART_IIR_RDA:
break;
case UART_IIR_THRE:
UART_TrxHandler(&UARTPort[uart_port2]);
break;
case UART_IIR_MS :
case UART_IIR_SWFlowCtrl:
case UART_IIR_HWFlowCtrl:
default:
break;
}
IRQClearInt(IRQ_UART_MD1_CODE);
IRQUnmask(IRQ_UART_MD1_CODE);
}
typedef struct _ut_hdma_intr_s{
kal_uint32 hdma_done_int;
kal_uint32 hdma_qe_int;
kal_uint32 hdma_len_err_int;
kal_uint32 hdma_bd_cserr_int;
kal_uint32 hdma_gpd_cserr_int;
}ut_hdma_intr_t;
volatile static ut_hdma_intr_t ut_hdma_intr_record[2];
void uart_hdma_lisr(kal_uint32 vector)
{
IRQMask(UART_HDMA_INTR_ID);
kal_activate_hisr_index(GDMA2_HISR);
}
void uart_hdma_hisr(void)
{
//kal_uint32 mask;
kal_uint32 val, chl;
kal_uint32 i;
//mask = SaveAndSetIRQMask();
val = DRV_Reg32(GDMA_GISAR_UART);
//Set the interrupt record table
for(i = 0; i < sizeof(ut_hdma_intr_record) / sizeof(ut_hdma_intr_t); i++ ){
chl = i + 2;
if(IS_HDMA_DONE_INTR(val, chl)){
ut_hdma_intr_record[i].hdma_done_int++;
#if defined(DRV_DEBUG_BUFFER_DMA_MODE)
if (chl == UART1_HDMA_TX_CHANNEL) {
UART_TxDMAHandler(&UARTPort[uart_port1], 1);
}
#endif
}
if(IS_HDMA_QE_INTR(val, chl)){
ut_hdma_intr_record[i].hdma_qe_int++;
#if defined(__HMU_ENABLE__)
if (chl == UART1_HDMA_RX_CHANNEL) {
// trigger UARTCORE task to polling RX
hmu_hifeg_set(HIF_DRV_EG_HIF_TICK_EVENT_UART);
}
#endif
}
if(IS_HDMA_GPD_CSERR_INTR(val, chl)){
ut_hdma_intr_record[i].hdma_gpd_cserr_int++;
ASSERT(0);
}
if(IS_HDMA_BD_CSERR_INTR(val, chl)){
ut_hdma_intr_record[i].hdma_bd_cserr_int++;
ASSERT(0);
}
if(IS_HDMA_LENERR_INTR(val, chl)){
ut_hdma_intr_record[i].hdma_len_err_int++;
ASSERT(0);
}
}
//Clear the interrupt status
HDMA_INT_CLEAR_ALL();
//RestoreIRQMask(mask);
IRQUnmask(UART_HDMA_INTR_ID);
}
#ifdef __USB_COM_PORT_ENABLE__
extern UARTStruct USB2UARTPort[MAX_USB_PORT_NUM];
#endif /*__USB_COM_PORT_ENABLE__*/
void UART_SetSleepEnable(UART_PORT port, kal_bool enable)
{
DRV_UART_WriteReg(UART_SLEEP_EN(UART_BaseAddr[port]), enable);
}
//This API only for test purpose, can only be called by MEUT DVT test.
//*********** do not call this API directly ************
//*********** do not call this API directly ************
//*********** do not call this API directly ************
void UART_set_FIFO_trigger(UART_PORT port, kal_uint16 tx_level, kal_uint16 rx_level)
{
if(port >= MAX_UART_PORT_NUM)
return;
DRV_UART_WriteReg(UART_FCR(UART_BaseAddr[port]), ((tx_level<<4) | (rx_level<<6) | 0x7));
}
void U_Register_TX_cb(UART_PORT port, module_type ownerid, UART_TX_FUNC func) {}
void U_Register_RX_cb(UART_PORT port, module_type ownerid, UART_RX_FUNC func) {}
void UART_TurnOnPower(UART_PORT port, kal_bool enable) {}
/* This is to check that all the data in UART TX ring buffer is empty. */
kal_bool UART_CheckTxBufferEmpty(UART_PORT port)
{
kal_uint8 result;
void *p_cur_gpd;
if(port >= MAX_UART_PORT_NUM)
return KAL_FALSE;
// HDMA
if(uart_wait_tgpd_head[port] != NULL || uart_wait_tgpd_tail[port] != NULL) return KAL_FALSE;
p_cur_gpd = uart_tgpd_head[port];
while(1)
{
if(p_cur_gpd == NULL) break;
if(p_cur_gpd == uart_tgpd_tail[port]) break;
if(QBM_DES_GET_HWO(p_cur_gpd + 0x40000000)) return KAL_FALSE;
p_cur_gpd = QBM_DES_GET_NEXT(p_cur_gpd);
}
Buf_IsEmpty(&(UARTPort[port].Tx_Buffer), result);
return ((Buff_isEmpty == result) ? KAL_TRUE : KAL_FALSE);
}
/* This is to check that all TX data have been sent out
including UART TX ring buffer and UART FIFO. */
kal_bool UART_CheckTxAllSentOut(UART_PORT port)
{
if(port >= MAX_UART_PORT_NUM)
return KAL_FALSE;
if (UART_CheckTxBufferEmpty(port) == KAL_FALSE)
return KAL_FALSE;
if (UART_LSR_TEMT & DRV_UART_Reg(UART_LSR(UART_BaseAddr[port])))
return KAL_TRUE;
else
return KAL_FALSE;
}
// this function has a problem
void UART_GetTxBufferSize(UART_PORT port, kal_uint32 *total_size, kal_uint32 *rest_size)
{
if(port >= MAX_UART_PORT_NUM)
return;
*total_size = UARTPort[port].Tx_Buffer.Length;
if(uart_tgpd_head[port] != NULL || uart_wait_tgpd_head[port] != NULL)
{
*rest_size = uart_cal_tgpd_buf_length((void *) GDMA_HDCPRN((port + 2)), (void *) uart_tgpd_tail[port]);
*rest_size += uart_cal_tgpd_buf_length((void *) uart_wait_tgpd_head[port], (void *) uart_wait_tgpd_tail[port]);
} else
Buf_GetBytesAvail(&(UARTPort[port].Tx_Buffer), *rest_size);
}
/*
* FUNCTION
* UART_VFIFO_TX_DMA_Enable
*
* DESCRIPTION
* for
*
* CALLS
* This function is called to enable or disable VFIFO DMA TX
* it is for logacc only , logacc will take UART TX , it might cause UART & VFIFO DMA sync problem
* so we must disable VFIFO DMA when logacc on
* enable and reset VFIFO DMA when logacc off
*
* PARAMETERS
* port: uart port
* enable: disable or enable VFIFO DMA TX
* RETURNS
* None
*
* GLOBALS AFFECTED
* external_global
*/
void UART_VFIFO_TX_DMA_Enable(UART_PORT port,kal_bool enable) {}
// Used under ASSERT condition
// This has effect only when the port does NOT support VFIFO and used as Catcher port
// After ASSERT, DHL will wait UART to send out all the data before ASSERT.
// But now, all the interrupts are disabled, DHL may wait forever when the UART port is configured with DMA
// To solve this problem, we provide this function for DHL to call
// in order to send out all the data in ring buffer before ASSERT
// DHL will open UART port again after previous data is sent out
void UART_AssertWaitPrevDataSentOut(UART_PORT port){
kal_uint16 LSR;
kal_uint16 TX_DATA;
if(port >= MAX_UART_PORT_NUM)
return;
// Manually send out data by MCU polling
while(!UART_CheckTxBufferEmpty(port))
{
LSR = DRV_UART_Reg(UART_LSR(UART_BaseAddr[port]));
if(LSR & UART_LSR_THRE)
{
Buf_Pop(&(UARTPort[port].Tx_Buffer), TX_DATA);
DRV_UART_WriteReg(UART_THR(UART_BaseAddr[port]), (kal_uint16) TX_DATA);
}
}
// Wait UART controller to sent out the data in FIFO
while(!UART_CheckTxAllSentOut(port));
}
kal_uint32 UART_Get_Maxbaudrate(UART_PORT port)
{
return 6000000;
}
kal_uint32 UART_PutBytesIor(UART_PORT port, void *putIor)
{
void *p_ior;
if(port >= MAX_UART_PORT_NUM)
return 0;
p_ior = putIor;
while(1)
{
// if there is no tgpd, atach a bypass tgpd
uart_en_q_de_q_with_mutex(port, UART_TX, UART_EN_Q, ((tty_io_request_t *) putIor)->first_gpd, ((tty_io_request_t *) putIor)->last_gpd);
if(((tty_io_request_t *) p_ior)->next_request == NULL)
{
break;
} else
{
p_ior = ((tty_io_request_t *) p_ior)->next_request;
}
}
return 0;
}
kal_uint32 UART_PutBytesIor_LIGHT(UART_PORT port, void *putIor)
{
void *p_ior;
if(port >= MAX_UART_PORT_NUM)
return 0;
p_ior = putIor;
while(1)
{
// if there is no tgpd, atach a bypass tgpd
uart_en_q_de_q_with_mutex(port, UART_TX, UART_EN_Q_LIGHT, ((tty_io_request_t *) putIor)->first_gpd, ((tty_io_request_t *) putIor)->last_gpd);
if(((tty_io_request_t *) p_ior)->next_request == NULL)
{
break;
} else
{
p_ior = ((tty_io_request_t *) p_ior)->next_request;
}
}
return 0;
}
kal_uint32 UART_GetBytesIor(UART_PORT port, void *ior)
{
void *p_ior;
if(port >= MAX_UART_PORT_NUM)
return 0;
p_ior = ior;
while(1)
{
uart_en_q_de_q_with_mutex(port, UART_RX, UART_EN_Q, ((tty_io_request_t *) p_ior)->first_gpd, ((tty_io_request_t *) p_ior)->last_gpd);
if(((tty_io_request_t *) p_ior)->next_request == NULL)
{
break;
} else
{
p_ior = ((tty_io_request_t *) p_ior)->next_request;
}
}
return 0;
}
void UART_DriverInit(UART_PORT port)
{
module_type ownerid;
static kal_bool b_uart_custom_init = KAL_FALSE;
kal_bool Is_OpenUart = KAL_TRUE;
ownerid = (MOD_UART1_HISR + port);
// Customization
if(b_uart_custom_init == KAL_FALSE)
{
uart_customize_init();
b_uart_custom_init = KAL_TRUE;
}
if(Is_OpenUart == KAL_TRUE)
{
UART_HWInit(port);
pUart_CMD_FUNC[port]= &UartDriver;
U_Open(port, ownerid);
}
// create mutex
if(mutex_status == KAL_FALSE && !INT_QueryExceptionStatus())
{
mutexid = kal_create_mutex("DRV_UART");
mutex_status = KAL_TRUE;
}
}
void UART_SetNeedTxDoneCb(UART_PORT port, kal_bool needTxDoneCb, module_type ownerid)
{
UARTPort[port].need_tx_done_cb = needTxDoneCb;
}
kal_uint32 uart_cal_tgpd_buf_length(void *head, void *tail)
{
void *gpd_cur, *bd_cur;
kal_uint32 sum = 0;
if(head == NULL || tail == NULL)
return 0;
gpd_cur = head;
while(1)
{
if(QBM_DES_GET_BPS(gpd_cur) == 0)
{
if(QBM_DES_GET_BDP(gpd_cur))
{
bd_cur = QBM_DES_GET_DATAPTR(gpd_cur);
while(1)
{
sum += QBM_DES_GET_DATALEN(bd_cur);
if(QBM_DES_GET_EOL(bd_cur)) {break;}
else {bd_cur = QBM_DES_GET_NEXT(bd_cur);}
}
} else
{
sum += QBM_DES_GET_DATALEN(gpd_cur);
}
}
if(gpd_cur == tail) {return sum;}
else {gpd_cur = QBM_DES_GET_NEXT(gpd_cur);}
}
}
void uart_en_q_de_q_with_mutex(UART_PORT port, kal_bool tx_or_rx, kal_uint8 en_q_or_de_q, void *p_ior_head, void *p_ior_tail)
{
void *p_gpd_head = NULL;
void *p_gpd_tail = NULL;
void *p_gpd_cur = NULL;
kal_uint32 queue_len = 0;
tty_io_request_t *ior = NULL;
if(!kal_if_hisr()){
// lock mutex
kal_take_mutex(mutexid);
}
DCL_HANDLE handle = DclSerialPort_Open(port, 0);
if(tx_or_rx == (kal_bool) UART_TX)
{
if(en_q_or_de_q == UART_EN_Q)
{
uart_cal_chksum_and_flush_gpd_list(p_ior_head, p_ior_tail);
if(uart_wait_tgpd_head[port] == NULL && uart_wait_tgpd_tail[port] == NULL)
{
uart_wait_tgpd_head[port] = p_ior_head;
uart_wait_tgpd_tail[port] = p_ior_tail;
} else
{
qbmt_common_en_q_rx(p_ior_head, p_ior_tail, (void **) &uart_wait_tgpd_head[port], (void **) &uart_wait_tgpd_tail[port]);
}
} else if(en_q_or_de_q == UART_EN_Q_LIGHT)
{
if(uart_wait_tgpd_head[port] == NULL && uart_wait_tgpd_tail[port] == NULL)
{
uart_wait_tgpd_head[port] = p_ior_head;
uart_wait_tgpd_tail[port] = p_ior_tail;
} else
{
qbmt_common_en_q_rx(p_ior_head, p_ior_tail, (void **) &uart_wait_tgpd_head[port], (void **) &uart_wait_tgpd_tail[port]);
}
} else
{
if(uart_tgpd_head[port] != NULL)
{
if(en_q_or_de_q == UART_DE_Q)
{
queue_len = qbmt_de_q((void **) &uart_tgpd_head[port], (void **) &uart_tgpd_tail[port], (void **) &p_gpd_head, (void **) &p_gpd_tail);
} else if(en_q_or_de_q == UART_DE_Q_ALL)
{
#if defined(META_MODE_SW_ESCAPING)
if(kal_query_boot_mode() != FACTORY_BOOT)
#endif
{
HDMA_BUF0_STOP((2 + port));
}
uart_clear_hwo_of_gpd_list(uart_tgpd_head[port], uart_tgpd_tail[port]);
queue_len = qbmt_de_q((void **) &uart_tgpd_head[port], (void **) &uart_tgpd_tail[port], (void **) &p_gpd_head, (void **) &p_gpd_tail);
QBM_FREE_ONE(uart_tgpd_head[port]);
if(uart_wait_tgpd_head[port] != NULL)
{
if(queue_len > 0)
{
qbmt_common_en_q_rx(uart_wait_tgpd_head[port], uart_wait_tgpd_tail[port], (void **) &p_gpd_head, (void **) &p_gpd_tail);
} else
{
p_gpd_head = uart_wait_tgpd_head[port];
p_gpd_tail = uart_wait_tgpd_tail[port];
queue_len = 1;
}
uart_clear_hwo_of_gpd_list(p_gpd_head, p_gpd_tail);
}
uart_tgpd_head[port] = NULL;
uart_tgpd_tail[port] = NULL;
uart_wait_tgpd_head[port] = NULL;
uart_wait_tgpd_tail[port] = NULL;
} else ASSERT(0);
if(queue_len > 0)
{
if(UARTPort[port].need_tx_done_cb)
{
ior = (tty_io_request_t *) QBM_DES_GET_SW_CTRL_FIELD(p_gpd_head);
ior->first_gpd = p_gpd_head;
ior->last_gpd = p_gpd_tail;
ior->next_request = NULL;
DclSerialPort_DrvTxDone(handle, kal_get_active_module_id(), ior);
} else
{
qbmt_dest_q((void *) p_gpd_head, (void *) p_gpd_tail);
}
}
}
}
} else
{
if(en_q_or_de_q == (kal_bool) UART_EN_Q)
{
if(uart_rgpd_head[port] == NULL && uart_rgpd_tail[port] == NULL)
{
uart_cal_chksum_and_flush_gpd_list(p_ior_head, p_ior_tail);
QBM_DES_CLR_HWO(p_ior_tail);
QBM_CACHE_FLUSH((void *) p_ior_tail, QBM_SIZE_GPD_BD_TST);
HDMA_BUF0_PROG_ADDR_CONFIG((3 + port), p_ior_head);
uart_rgpd_head[port] = p_ior_head;
uart_rgpd_tail[port] = p_ior_tail;
HDMA_BUF0_START((3 + port));
}else{
qbmt_common_en_q_rx(p_ior_head, p_ior_tail, (void **) &uart_rgpd_head[port], (void **) &uart_rgpd_tail[port]);
uart_cal_chksum_and_flush_gpd_list(uart_rgpd_head[port], uart_rgpd_tail[port]);
QBM_DES_CLR_HWO(uart_rgpd_tail[port]);
QBM_CACHE_FLUSH((void *) uart_rgpd_tail[port], QBM_SIZE_GPD_BD_TST);
HDMA_BUF0_RESUME((3 + port));
}
} else
{
if(uart_rgpd_head[port] == NULL)
{
if(!kal_if_hisr()){
kal_give_mutex(mutexid);
}
return;
} else
{
if(en_q_or_de_q == UART_DE_Q)
{
queue_len = qbmt_de_q((void **) &uart_rgpd_head[port], (void **) &uart_rgpd_tail[port], (void **) &p_gpd_head, (void **) &p_gpd_tail);
} else if(en_q_or_de_q == UART_DE_Q_ALL)
{
// stop q
HDMA_BUF0_STOP((port + 3));
// de-Q all GPDs
p_gpd_head = uart_rgpd_head[port];
p_gpd_tail = uart_rgpd_tail[port];
uart_rgpd_head[port] = NULL;
uart_rgpd_tail[port] = NULL;
queue_len = 1; // not real queue length
}
if(p_gpd_head != NULL && p_gpd_tail != NULL && queue_len > 0)
{
#if defined(META_MODE_SW_ESCAPING) && !defined(UART_SIM_QMU)
if(kal_query_boot_mode() == FACTORY_BOOT){
UART_META_ExBytes(port, p_gpd_head, p_gpd_tail);
}
#endif
ior = (tty_io_request_t *) QBM_DES_GET_SW_CTRL_FIELD(p_gpd_head);
ior->first_gpd = p_gpd_head;
ior->last_gpd = p_gpd_tail;
ior->next_request = NULL;
DclSerialPort_DrvRx(handle, kal_get_active_module_id(), ior); // need to modify
}
}
}
}
if(uart_wait_tgpd_head[port] != NULL && uart_wait_tgpd_tail[port] != NULL && !(DRV_Reg32(UART_LCR(UART_BaseAddr[port])) & UART_LCR_BREAK))
{
if(uart_tgpd_head[port] == NULL && uart_tgpd_tail[port] == NULL)
{
uart_tgpd_head[port] = uart_wait_tgpd_head[port];
uart_tgpd_tail[port] = uart_wait_tgpd_tail[port];
// connect a BPS GPD to the tail
qbmt_alloc_q(QBM_TYPE_TGPD_BPS, 1, (void **) &p_gpd_cur, (void **) &p_gpd_cur);
ASSERT(p_gpd_cur!= NULL);
qbmt_common_en_q_rx(p_gpd_cur, p_gpd_cur, (void **) &uart_tgpd_head[port], (void **) &uart_tgpd_tail[port]);
#if defined(META_MODE_SW_ESCAPING)
if(kal_query_boot_mode() == FACTORY_BOOT){
UART_META_PutBytes(port,uart_tgpd_head[port], uart_tgpd_tail[port]);
}else
#endif
{
HDMA_BUF0_PROG_ADDR_CONFIG((2 + port), uart_tgpd_head[port]);
HDMA_BUF0_START((2 + port));
}
uart_wait_tgpd_head[port] = NULL;
uart_wait_tgpd_tail[port] = NULL;
} else if(QBM_DES_GET_BPS(uart_tgpd_head[port]) && QBM_DES_GET_BPS(uart_tgpd_tail[port]))
{
QBM_FREE_ONE(uart_tgpd_head[port]);
uart_tgpd_head[port] = uart_wait_tgpd_head[port];
uart_tgpd_tail[port] = uart_wait_tgpd_tail[port];
// connect a BPS GPD to the tail
qbmt_alloc_q(QBM_TYPE_TGPD_BPS, 1, (void **) &p_gpd_cur, (void **) &p_gpd_cur);
ASSERT(p_gpd_cur!= NULL);
qbmt_common_en_q_rx(p_gpd_cur, p_gpd_cur, (void **) &uart_tgpd_head[port], (void **) &uart_tgpd_tail[port]);
#if defined(META_MODE_SW_ESCAPING)
if(kal_query_boot_mode() == FACTORY_BOOT){
UART_META_PutBytes(port,uart_wait_tgpd_head[port], uart_wait_tgpd_tail[port]);
}else
#endif
{
HDMA_BUF0_PROG_ADDR_CONFIG((2 + port), uart_wait_tgpd_head[port]);
HDMA_BUF0_START((2 + port));
}
uart_wait_tgpd_head[port] = NULL;
uart_wait_tgpd_tail[port] = NULL;
}
}
if(!kal_if_hisr()){
// unlock mutex
kal_give_mutex(mutexid);
}
return;
}
void uart_qbm_virt_to_phy(void** pp_gpd_head, void** pp_gpd_tail)
{
void *gpd_ptr = NULL, *gpd_ptr_tmp = NULL;
void *bd_ptr = NULL, *bd_ptr_tmp = NULL;;
void *pgd_data_ptr = NULL, *bd_data_ptr = NULL;
*pp_gpd_head = (void*)virt_to_phys(*pp_gpd_head);
gpd_ptr = *pp_gpd_head;
while(1)
{
if(QBM_DES_GET_BDP(gpd_ptr))
{
bd_ptr = QBM_DES_GET_DATAPTR(gpd_ptr);
bd_ptr = (void*)virt_to_phys(bd_ptr);
QBM_DES_SET_DATAPTR(gpd_ptr,bd_ptr);
qbm_cal_set_checksum_by_len((const kal_uint8 *)gpd_ptr, 12);
while(1)
{
bd_data_ptr = QBM_DES_GET_DATAPTR(bd_ptr);
bd_data_ptr = (void*)virt_to_phys(bd_data_ptr);
QBM_DES_SET_DATAPTR(bd_ptr,bd_data_ptr);
if(QBM_DES_GET_EOL(bd_ptr))
{
break;
} else
{
bd_ptr_tmp = (void*)QBM_DES_GET_NEXT(bd_ptr);
bd_ptr_tmp = (void*)virt_to_phys(bd_ptr_tmp);
QBM_DES_SET_NEXT(bd_ptr,bd_ptr_tmp);
qbm_cal_set_checksum_by_len((const kal_uint8 *)bd_ptr, 12);
bd_ptr = QBM_DES_GET_NEXT(bd_ptr);
}
}
} else
{
pgd_data_ptr = QBM_DES_GET_DATAPTR(gpd_ptr);
pgd_data_ptr = (void*)virt_to_phys(pgd_data_ptr);
QBM_DES_SET_DATAPTR(gpd_ptr,pgd_data_ptr);
}
if(gpd_ptr == *pp_gpd_tail)
{
break;
} else
{
gpd_ptr_tmp = (void*)QBM_DES_GET_NEXT(gpd_ptr);
gpd_ptr_tmp = (void*)virt_to_phys(gpd_ptr_tmp);
QBM_DES_SET_NEXT(gpd_ptr,gpd_ptr_tmp);
qbm_cal_set_checksum_by_len((const kal_uint8 *) gpd_ptr, 12);
gpd_ptr = QBM_DES_GET_NEXT(gpd_ptr);
}
}
}
void uart_qbm_phy_to_virt(void**pp_gpd_head, void**pp_gpd_tail)
{
void *gpd_ptr = NULL, *gpd_ptr_tmp = NULL;
void *bd_ptr = NULL, *bd_ptr_tmp = NULL;;
void *pgd_data_ptr = NULL, *bd_data_ptr = NULL;
*pp_gpd_head = (void*)phys_to_virt(*pp_gpd_head);
QBM_CACHE_INVALID(*pp_gpd_head, QBM_SIZE_TGPD);
gpd_ptr = *pp_gpd_head;
*pp_gpd_tail = (void*)phys_to_virt(*pp_gpd_tail);
QBM_CACHE_INVALID(*pp_gpd_tail, QBM_SIZE_TGPD);
while(1)
{
if(QBM_DES_GET_BDP(gpd_ptr))
{
bd_ptr = QBM_DES_GET_DATAPTR(gpd_ptr);
bd_ptr = (void*)phys_to_virt(bd_ptr);
QBM_CACHE_INVALID(bd_ptr, QBM_SIZE_TBD);
QBM_DES_SET_DATAPTR(gpd_ptr,bd_ptr);
while(1)
{
bd_data_ptr = QBM_DES_GET_DATAPTR(bd_ptr);
bd_data_ptr = (void*)phys_to_virt(bd_data_ptr);
QBM_CACHE_INVALID(bd_data_ptr, QBM_SIZE_CACHE_ALIGN(QBM_DES_GET_DATALEN(bd_data_ptr)));
QBM_DES_SET_DATAPTR(bd_ptr,bd_data_ptr);
if(QBM_DES_GET_EOL(bd_ptr))
{
break;
} else
{
bd_ptr_tmp = (void*)QBM_DES_GET_NEXT(bd_ptr);
bd_ptr_tmp = (void*)phys_to_virt(bd_ptr_tmp);
QBM_CACHE_INVALID(bd_ptr_tmp, QBM_SIZE_TBD);
QBM_DES_SET_NEXT(bd_ptr,bd_ptr_tmp);
bd_ptr = QBM_DES_GET_NEXT(bd_ptr);
}
}
} else
{
pgd_data_ptr = QBM_DES_GET_DATAPTR(gpd_ptr);
pgd_data_ptr = (void*)phys_to_virt(pgd_data_ptr);
QBM_CACHE_INVALID(pgd_data_ptr, QBM_SIZE_CACHE_ALIGN(QBM_DES_GET_DATALEN(pgd_data_ptr)));
QBM_DES_SET_DATAPTR(gpd_ptr,pgd_data_ptr);
}
if(gpd_ptr == *pp_gpd_tail)
{
break;
} else
{
gpd_ptr_tmp = (void*)QBM_DES_GET_NEXT(gpd_ptr);
gpd_ptr_tmp = (void*)phys_to_virt(gpd_ptr_tmp);
QBM_CACHE_INVALID(gpd_ptr_tmp, QBM_SIZE_TGPD);
QBM_DES_SET_NEXT(gpd_ptr,gpd_ptr_tmp);
gpd_ptr = QBM_DES_GET_NEXT(gpd_ptr);
}
}
}
void UART_META_PutBytes(UART_PORT port, void * gpd_head, void * gpd_tail){
hdma_tbd_t *bd_ptr = NULL, *p_bd_cur =NULL;
hdma_tgpd_t *gpd_ptr = NULL;
kal_uint8 gpd_ext_len=0, bd_ext_len=0;
kal_uint32 gpd_data_len=0, bd_data_len=0;
kal_uint8 *gpd_ext_ptr=NULL, *gpd_data_ptr=NULL, *bd_ext_ptr=NULL, *bd_data_ptr=NULL;
gpd_ptr = (hdma_tgpd_t*)gpd_head;
while(1){
if(QBM_DES_GET_HWO(gpd_ptr)==0){
break;
}
if(QBM_DES_GET_BPS(gpd_ptr)){
QBM_DES_CLR_HWO(gpd_ptr);
QBM_CACHE_FLUSH(gpd_ptr, QBM_SIZE_TGPD);
goto next;
}
if (QBM_DES_GET_EXTLEN(gpd_ptr)) {
gpd_ext_len = QBM_DES_GET_EXTLEN(gpd_ptr);
gpd_ext_ptr = QBM_DES_GET_EXT(gpd_ptr);
PutUARTDatas(port, UART_ESCAPE_CHAR, gpd_ext_ptr,gpd_ext_len);
//U_SendData(port, gpd_ext_ptr, gpd_ext_len, FACTORY_BOOT, UART_ESCAPE_CHAR, UARTPort[port].ownerid);
}
if (QBM_DES_GET_BDP(gpd_ptr)) {
bd_ptr = QBM_DES_GET_DATAPTR(gpd_ptr);
p_bd_cur = bd_ptr;
while (1) {
if (QBM_DES_GET_EXTLEN(p_bd_cur)) {
bd_ext_len = QBM_DES_GET_EXTLEN(p_bd_cur);
bd_ext_ptr = QBM_DES_GET_EXT(p_bd_cur);
PutUARTDatas(port, UART_ESCAPE_CHAR, bd_ext_ptr,bd_ext_len);
//U_SendData(port, bd_ext_ptr, bd_ext_len, FACTORY_BOOT, UART_ESCAPE_CHAR, UARTPort[port].ownerid);
}
if (QBM_DES_GET_DATALEN(p_bd_cur)) {
bd_data_len = QBM_DES_GET_DATALEN(p_bd_cur);
bd_data_ptr = QBM_DES_GET_DATAPTR(p_bd_cur);
PutUARTDatas(port, UART_ESCAPE_CHAR, bd_data_ptr,bd_data_len);
//U_SendData(port, bd_data_ptr, bd_data_len, FACTORY_BOOT, UART_ESCAPE_CHAR, UARTPort[port].ownerid);
}
if (QBM_DES_GET_EOL(p_bd_cur)) {
break;
}
p_bd_cur = (void *)QBM_DES_GET_NEXT(p_bd_cur);
}
} else{
gpd_data_len = QBM_DES_GET_DATALEN(gpd_ptr);
gpd_data_ptr = QBM_DES_GET_DATAPTR(gpd_ptr);
PutUARTDatas(port, UART_ESCAPE_CHAR, gpd_data_ptr,gpd_data_len);
//U_SendData(port, gpd_data_ptr, gpd_data_len, FACTORY_BOOT, UART_ESCAPE_CHAR, UARTPort[port].ownerid);
}
QBM_DES_CLR_HWO(gpd_ptr);
QBM_CACHE_FLUSH(gpd_ptr, QBM_SIZE_TGPD);
if(gpd_ptr == gpd_tail)
{
break;
} else
{
next:
gpd_ptr = (void *) QBM_DES_GET_NEXT(gpd_ptr);
}
}
/* Cooperate with Non-Blocking CACHE API */
MM_Sync();
}
void uart_cal_chksum_and_flush_gpd_list(void * gpd_head, void * gpd_tail)
{
hdma_tbd_t *gpd_ptr = NULL, *bd_ptr = NULL;
void *pgd_data_ptr = NULL, *bd_data_ptr = NULL;
gpd_ptr = (hdma_tbd_t*)gpd_head;
while(1)
{
QBM_DES_SET_HWO(gpd_ptr);
#if !defined(__DRVTEST_SW_DOMAIN__)
qbm_cal_set_checksum_by_len((const kal_uint8 *) gpd_ptr, 12);
#endif
QBM_CACHE_FLUSH((void *) gpd_ptr, QBM_SIZE_TGPD);
if(QBM_DES_GET_BDP(gpd_ptr))
{
bd_ptr = QBM_DES_GET_DATAPTR(gpd_ptr);
while(1)
{
#if !defined(__DRVTEST_SW_DOMAIN__)
qbm_cal_set_checksum_by_len((const kal_uint8 *) bd_ptr, 12);
#endif
QBM_CACHE_FLUSH((void *) bd_ptr, QBM_SIZE_TBD);
bd_data_ptr = QBM_DES_GET_DATAPTR(bd_ptr);
QBM_CACHE_FLUSH((void *) bd_data_ptr, QBM_DES_GET_DATALEN(bd_ptr));
if(QBM_DES_GET_EOL(bd_ptr))
{
break;
} else
{
bd_ptr = (void *) QBM_DES_GET_NEXT(bd_ptr);
}
}
} else
{
pgd_data_ptr = QBM_DES_GET_DATAPTR(gpd_ptr);
QBM_CACHE_FLUSH((void *) pgd_data_ptr, QBM_DES_GET_DATALEN(gpd_ptr));
}
if(gpd_ptr == gpd_tail)
{
break;
} else
{
gpd_ptr = (void *) QBM_DES_GET_NEXT(gpd_ptr);
}
}
/* Cooperate with Non-Blocking CACHE API */
MM_Sync();
}
void uart_clear_hwo_of_gpd_list(void *gpd_head, void *gpd_tail)
{
hdma_tbd_t *gpd_ptr = NULL;//, *bd_ptr = NULL;
gpd_ptr = gpd_head;
while(1)
{
QBM_DES_CLR_HWO(gpd_ptr);
QBM_CACHE_FLUSH(gpd_ptr, QBM_SIZE_GPD_BD_TST);
if(gpd_ptr == gpd_tail)
{
break;
} else
{
gpd_ptr = (void *) QBM_DES_GET_NEXT(gpd_ptr);
}
}
/* Cooperate with Non-Blocking CACHE API */
MM_Sync();
}
typedef struct _uart_bps_gpd_pool {
void *gpd_head;
void *gpd_tail;
kal_uint32 free_num;
kal_uint32 alloc_ok_cnt;
kal_uint32 alloc_fail_cnt;
kal_uint32 free_ok_cnt;
void *buffer_start;
void *buffer_end;
kal_uint32 total_num;
} uart_bps_gpd_pool;
static void *uart_discard_tgpd_head = NULL;
static void *uart_discard_tgpd_tail = NULL;
static void *uart_discard_rgpd_head = NULL;
static void *uart_discard_rgpd_tail = NULL;
static kal_uint32 uart_excpt_tx_bytes[MAX_UART_PORT_NUM];
static kal_uint32 uart_excpt_rx_bytes[MAX_UART_PORT_NUM];
static uart_bps_gpd_pool uart_bps_gpd_pool_info;
extern void uart_cal_chksum_and_flush_gpd_list(void *gpd_head, void *gpd_tail);
kal_bool uart_except_init_qbm()
{
uart_bps_gpd_pool *gpd_pool = &uart_bps_gpd_pool_info;
bm_queue_config conf;
kal_uint32 ret;
qbm_init_q_config(&conf);
conf.buff_num = UART_ECPT_QBM_BPS_NUM;
conf.p_mem_pool_str = uart_ecpt_bps_buf;
conf.p_mem_pool_end = conf.p_mem_pool_str + UART_ECPT_QBM_BPS_BUF_SZ;
ret = qbm_init_queue_non_free(QBM_TYPE_TGPD_BPS, &conf,
&gpd_pool->gpd_head,
&gpd_pool->gpd_tail);
if(QBM_ERROR_OK != ret)
return KAL_FALSE;
gpd_pool->buffer_start = conf.p_mem_pool_str;
gpd_pool->buffer_end = conf.p_mem_pool_end;
gpd_pool->total_num = conf.buff_num;
gpd_pool->free_num = conf.buff_num;
return KAL_TRUE;
}
kal_bool uart_except_check_bps_gpd(void *p_gpd)
{
kal_uint8* uart_bps_buf;
uart_bps_buf = uart_ecpt_bps_buf;
if (((kal_uint8 *)p_gpd >= uart_bps_buf) && ((kal_uint8 *)p_gpd < uart_bps_buf + UART_ECPT_QBM_BPS_BUF_SZ)){
return KAL_TRUE;
}
return KAL_FALSE;
}
void uart_except_free_bps_gpd(void *p_gpd)
{
uart_bps_gpd_pool *gpd_pool = &uart_bps_gpd_pool_info;
ASSERT(uart_except_check_bps_gpd(p_gpd));
if (gpd_pool->gpd_head == NULL) {
gpd_pool->gpd_head = gpd_pool->gpd_tail = p_gpd;
} else {
QBM_DES_SET_NEXT(gpd_pool->gpd_tail, p_gpd);
gpd_pool->gpd_tail = p_gpd;
}
gpd_pool->free_num ++;
gpd_pool->free_ok_cnt ++;
}
void *uart_except_alloc_bps_gpd(kal_bool tx_or_rx)
{
void *p_ret_gpd;
uart_bps_gpd_pool *gpd_pool = &uart_bps_gpd_pool_info;
if (gpd_pool->gpd_head == NULL) {
gpd_pool->alloc_fail_cnt ++;
return NULL;
}
p_ret_gpd = gpd_pool->gpd_head;
if (gpd_pool->gpd_head == gpd_pool->gpd_tail) {
gpd_pool->gpd_head = gpd_pool->gpd_tail = NULL;
} else {
gpd_pool->gpd_head = QBM_DES_GET_NEXT(gpd_pool->gpd_head);
}
gpd_pool->free_num --;
gpd_pool->alloc_ok_cnt ++;
QBM_DES_SET_NEXT(p_ret_gpd, NULL);
//QBM_DES_SET_BPS(p_ret_gpd);
return p_ret_gpd;
}
kal_uint32 uart_except_free_bps_gpd_in_list(void **pp_head, void **pp_tail)
{
void *p_gpd_cur, *p_gpd_pre, *p_gpd_nex;
int free_num = 0;
p_gpd_cur = *pp_head;
p_gpd_pre = NULL;
if (*pp_head == NULL || *pp_tail == NULL)
return 0;
while (1) {
p_gpd_nex = QBM_DES_GET_NEXT(p_gpd_cur);
if (uart_except_check_bps_gpd(p_gpd_cur)) {
/* free this gpd from list */
if (p_gpd_pre == NULL)
*pp_head = p_gpd_nex;
else
QBM_DES_SET_NEXT(p_gpd_pre, p_gpd_nex);
uart_except_free_bps_gpd(p_gpd_cur);
free_num ++;
} else {
p_gpd_pre = p_gpd_cur;
}
if(p_gpd_cur == *pp_tail)
break;
p_gpd_cur = p_gpd_nex;
}
return free_num;
}
void uart_except_en_q_rx(
void *p_new_head,
void *p_new_tail,
void **pp_orig_head,
void **pp_orig_tail
)
{
void *p_orig_tail = NULL;
ASSERT(pp_orig_head!=NULL);
ASSERT(pp_orig_tail!=NULL);
if (*pp_orig_head != NULL) {
p_orig_tail = *pp_orig_tail;
/* set new tail's HWO=0 */
QBM_DES_CLR_HWO(p_new_tail);
QBM_CACHE_FLUSH(p_new_tail, QBM_SIZE_TGPD);
/* link new list to tail of orig list */
QBM_DES_SET_NEXT(p_orig_tail, p_new_head);
/* re-calc the orig tail's checksum */
#if !defined(__DRVTEST_SW_DOMAIN__)
qbm_cal_set_checksum_wth_hwo(p_orig_tail);
#endif
/* set the orig tail's HWO=1 */
QBM_DES_SET_HWO(p_orig_tail);
QBM_CACHE_FLUSH(p_orig_tail, QBM_SIZE_TGPD);
/* update the orig tail */
*pp_orig_tail = p_new_tail;
} else {
*pp_orig_head = p_new_head;
*pp_orig_tail = p_new_tail;
}
}
/* the last gpd will not be de-queued */
kal_uint32 uart_except_de_q(
void **pp_src_head,
void **pp_src_tail,
void **pp_new_head,
void **pp_new_tail
)
{
kal_uint32 deqno = 0;
void *p_this_gpd = NULL;
*pp_new_head = NULL;
*pp_new_tail = NULL;
if (pp_src_head != NULL && *pp_src_head != NULL && *pp_src_head != *pp_src_tail) {
p_this_gpd = *pp_src_head;
QBM_CACHE_INVALID(p_this_gpd, QBM_SIZE_TGPD);
if (!QBM_DES_GET_HWO(p_this_gpd)){
*pp_new_head = p_this_gpd;
while(!QBM_DES_GET_HWO(p_this_gpd) && p_this_gpd != *pp_src_tail) {
*pp_new_tail = p_this_gpd;
deqno ++;
p_this_gpd = QBM_DES_GET_NEXT(p_this_gpd);
QBM_CACHE_INVALID(p_this_gpd, QBM_SIZE_TGPD);
}
*pp_src_head = p_this_gpd;
}
}
return deqno;
}
kal_uint32 uart_except_de_q_with_timeout(
UART_PORT port,
void **pp_src_head,
void **pp_src_tail,
void **pp_new_head,
void **pp_new_tail
)
{
kal_uint32 deqno = 0;
void *p_this_gpd = NULL;
*pp_new_head = NULL;
*pp_new_tail = NULL;
if (pp_src_head != NULL && *pp_src_head != NULL && *pp_src_head != *pp_src_tail) {
p_this_gpd = *pp_src_head;
QBM_CACHE_INVALID(p_this_gpd, QBM_SIZE_TGPD);
if (!QBM_DES_GET_HWO(p_this_gpd)){
*pp_new_head = p_this_gpd;
while(!QBM_DES_GET_HWO(p_this_gpd) && p_this_gpd != *pp_src_tail) {
*pp_new_tail = p_this_gpd;
deqno ++;
p_this_gpd = QBM_DES_GET_NEXT(p_this_gpd);
QBM_CACHE_INVALID(p_this_gpd, QBM_SIZE_TGPD);
}
*pp_src_head = p_this_gpd;
uart_ecpt_timer_reset(port);
}else{
uart_ecpt_timer_start(port);
}
}
return deqno;
}
DCL_STATUS uart_except_check_dma_status(kal_uint32 hdma_channel)
{
kal_uint32 int_sts;
DCL_STATUS ret_sts = STATUS_OK;
int_sts = DRV_Reg32(GDMA_GISAR_UART);
if(IS_HDMA_LENERR_INTR(int_sts, hdma_channel)) {
DRV_WriteReg32(GDMA_GISAR_UART, (HDMA_INTR_CHL_MASK(hdma_channel) << 16));
ret_sts = STATUS_FAIL;
}
if(IS_HDMA_BD_CSERR_INTR(int_sts, hdma_channel)) {
DRV_WriteReg32(GDMA_GISAR_UART, (HDMA_INTR_CHL_MASK(hdma_channel) << 24));
ret_sts = STATUS_ERROR_CRCERROR;
}
if(IS_HDMA_GPD_CSERR_INTR(int_sts, hdma_channel)) {
DRV_WriteReg32(GDMA_GISAR_UART, (HDMA_INTR_CHL_MASK(hdma_channel) << 28));
ret_sts = STATUS_ERROR_CRCERROR;
}
return ret_sts;
}
DCL_STATUS
uart_en_q_de_q_for_ecpt(
UART_PORT port,
kal_bool tx_or_rx,
kal_uint8 en_q_or_de_q,
void **pp_gpd_head,
void **pp_gpd_tail,
kal_uint32 *p_num
)
{
void *p_gpd_head, *p_gpd_tail; /* work queue */
void *p_bps_gpd;
kal_uint32 deq_num;
DCL_STATUS ret = STATUS_OK;
kal_uint32 hdma_ch;
kal_uint32 xfer_bytes;
ASSERT(pp_gpd_head != NULL);
ASSERT(pp_gpd_tail != NULL);
/* get global variable to local variable */
if (tx_or_rx == (kal_bool)UART_TX) {
p_gpd_head = uart_tgpd_head[port];
p_gpd_tail = uart_tgpd_tail[port];
} else {
p_gpd_head = uart_rgpd_head[port];
p_gpd_tail = uart_rgpd_tail[port];
}
hdma_ch = (tx_or_rx == (kal_bool)UART_TX)?port+2:port+3;
if (en_q_or_de_q == UART_EN_Q) {
if (*pp_gpd_head == NULL || *pp_gpd_tail == NULL) {
goto end;
}
/* alloc a bypass gpd */
if (tx_or_rx == (kal_bool)UART_TX) {
p_bps_gpd = uart_except_alloc_bps_gpd(tx_or_rx);
if (p_bps_gpd == NULL) {
ret = STATUS_FAIL;
goto end;
}
/* append the bypass gpd to the gpd list */
QBM_DES_SET_NEXT(*pp_gpd_tail, p_bps_gpd);
*pp_gpd_tail = p_bps_gpd;
} else {
QBM_DES_CLR_HWO(*pp_gpd_tail);
}
/* re-calc checksum and flush cache */
uart_cal_chksum_and_flush_gpd_list(*pp_gpd_head, *pp_gpd_tail);
/* now, start en-q operation */
if (p_gpd_head == NULL) {
/* clear tail's HWO bit manually */
QBM_DES_CLR_HWO(*pp_gpd_tail);
QBM_CACHE_FLUSH(*pp_gpd_tail, QBM_SIZE_TGPD_BPS);
p_gpd_head = *pp_gpd_head;
p_gpd_tail = *pp_gpd_tail;
#if defined(META_MODE_SW_ESCAPING)
if((kal_query_boot_mode() == FACTORY_BOOT) && (tx_or_rx ==(kal_bool)UART_TX)){
UART_META_PutBytes(port, p_gpd_head, p_gpd_tail);
}else
#endif
{
/* newly configure and start DMA */
HDMA_BUF0_PROG_ADDR_CONFIG(hdma_ch, p_gpd_head);
HDMA_BUF0_START(hdma_ch);
}
} else {
/* Because META mode Tx should be done before new en_q, p_gpd_head must be NULL. so Tx would not be affected by new Start putbytes.
The following step just for backup, but should not be running. If it run, will may send more data or lose data*/
#if defined(META_MODE_SW_ESCAPING)
if((kal_query_boot_mode() == FACTORY_BOOT) && (tx_or_rx ==(kal_bool)UART_TX)){
UART_META_PutBytes(port, p_gpd_head, p_gpd_tail);
}else
#endif
{
/* tail's HWO bit will be cleared automatically */
/* en-q and resume DMA */
uart_except_en_q_rx(*pp_gpd_head, *pp_gpd_tail, (void **)&p_gpd_head, (void **)&p_gpd_tail);
HDMA_BUF0_RESUME(hdma_ch);
}
}
} else if (en_q_or_de_q == UART_DE_Q) {
if (p_gpd_head == NULL) {
*pp_gpd_head = NULL;
*pp_gpd_tail = NULL;
if (NULL != p_num)
*p_num = 0;
goto end;
}
if(tx_or_rx == (kal_bool)UART_TX){
deq_num = uart_except_de_q_with_timeout(port,(void **)&p_gpd_head, (void **) &p_gpd_tail, (void **)pp_gpd_head, (void **)pp_gpd_tail);
}else{
deq_num = uart_except_de_q((void **)&p_gpd_head, (void **) &p_gpd_tail, (void **)pp_gpd_head, (void **)pp_gpd_tail);
}
if (deq_num == 0) {
*pp_gpd_head = NULL;
*pp_gpd_tail = NULL;
if (NULL != p_num)
*p_num = deq_num;
goto end;
}
/* check if all is done */
if (p_gpd_head == p_gpd_tail && QBM_DES_GET_HWO(p_gpd_head)==0) {
if (uart_except_check_bps_gpd(p_gpd_head)) {
uart_except_free_bps_gpd(p_gpd_head);
QBM_DES_SET_NEXT(*pp_gpd_tail, NULL);
} else {
QBM_DES_SET_NEXT(*pp_gpd_tail, p_gpd_head);
*pp_gpd_tail = p_gpd_head;
}
p_gpd_head = p_gpd_tail = NULL;
}
/* check and free bypass GPD allocated by us in list */
deq_num -= uart_except_free_bps_gpd_in_list(pp_gpd_head, pp_gpd_tail);
if (NULL != p_num && deq_num > 0) {
*p_num = deq_num;
#if defined(META_MODE_SW_ESCAPING)
if(kal_query_boot_mode() == FACTORY_BOOT && tx_or_rx == (kal_bool)UART_RX){
UART_META_ExBytes(port, *pp_gpd_head, *pp_gpd_tail);
}
#endif
xfer_bytes = uart_cal_tgpd_buf_length(*pp_gpd_head, *pp_gpd_tail);
if (tx_or_rx == (kal_bool)UART_TX)
uart_excpt_tx_bytes[port] += xfer_bytes;
else
uart_excpt_rx_bytes[port] += xfer_bytes;
}
} else {
ASSERT(en_q_or_de_q != UART_EN_Q && en_q_or_de_q != UART_DE_Q);
}
/* updated global variable from local variable */
if (tx_or_rx == (kal_bool)UART_TX) {
uart_tgpd_head[port] = p_gpd_head;
uart_tgpd_tail[port] = p_gpd_tail;
} else {
uart_rgpd_head[port] = p_gpd_head;
uart_rgpd_tail[port] = p_gpd_tail;
}
end:
return ret;
}
DCL_STATUS uart_ecpt_tx_gpd(UART_PORT port, void *p_first_gpd, void *p_last_gpd)
{
ASSERT(port < MAX_UART_PORT_NUM);
return uart_en_q_de_q_for_ecpt(port, UART_TX, UART_EN_Q, &p_first_gpd, &p_last_gpd, NULL);
}
DCL_STATUS uart_ecpt_tx_done_info(UART_PORT port, void **pp_first_gpd, void **pp_last_gpd, kal_uint32 *gpd_num)
{
ASSERT(port < MAX_UART_PORT_NUM);
return uart_en_q_de_q_for_ecpt(port, UART_TX, UART_DE_Q, pp_first_gpd, pp_last_gpd, gpd_num);
}
DCL_STATUS uart_ecpt_assign_rx_gpd(UART_PORT port, void *p_first_gpd, void *p_last_gpd)
{
ASSERT(port < MAX_UART_PORT_NUM);
return uart_en_q_de_q_for_ecpt(port, UART_RX, UART_EN_Q, &p_first_gpd, &p_last_gpd, NULL);
}
DCL_STATUS uart_ecpt_get_rx_gpd(UART_PORT port, void **pp_first_gpd, void **pp_last_gpd, kal_uint32 *gpd_num)
{
ASSERT(port < MAX_UART_PORT_NUM);
return uart_en_q_de_q_for_ecpt(port, UART_RX, UART_DE_Q, pp_first_gpd, pp_last_gpd, gpd_num);
}
void uart_ecpt_clear_sw_queue(UART_PORT port)
{
static kal_bool first_time_clear = KAL_TRUE;
if (first_time_clear) {
first_time_clear = KAL_FALSE;
if (uart_wait_tgpd_head[port] != NULL) {
if (uart_discard_tgpd_head != NULL) {
QBM_DES_SET_NEXT(uart_discard_tgpd_tail, uart_wait_tgpd_head[port]);
uart_discard_tgpd_tail = uart_wait_tgpd_tail[port];
} else {
uart_discard_tgpd_head = uart_wait_tgpd_head[port];
uart_discard_tgpd_tail = uart_wait_tgpd_tail[port];
}
}
if (uart_tgpd_head[port] != NULL) {
if (uart_discard_tgpd_head != NULL) {
QBM_DES_SET_NEXT(uart_discard_tgpd_tail, uart_tgpd_head[port]);
uart_discard_tgpd_tail = uart_tgpd_tail[port];
} else {
uart_discard_tgpd_head = uart_tgpd_head[port];
uart_discard_tgpd_tail = uart_tgpd_tail[port];
}
}
if (uart_rgpd_head[port] != NULL) {
if (uart_discard_rgpd_head != NULL) {
QBM_DES_SET_NEXT(uart_discard_rgpd_tail, uart_rgpd_head[port]);
uart_discard_rgpd_tail = uart_rgpd_tail[port];
} else {
uart_discard_rgpd_head = uart_rgpd_head[port];
uart_discard_rgpd_tail = uart_rgpd_tail[port];
}
}
} else {
;
}
uart_wait_tgpd_head[port] = NULL;
uart_wait_tgpd_tail[port] = NULL;
uart_tgpd_head[port] = NULL;
uart_tgpd_tail[port] = NULL;
uart_rgpd_head[port] = NULL;
uart_rgpd_tail[port] = NULL;
}
DCL_STATUS uart_ecpt_clear_ch(UART_PORT port)
{
kal_uint32 val = 0;
ASSERT(port < MAX_UART_PORT_NUM);
#if defined(META_MODE_SW_ESCAPING)
if(kal_query_boot_mode() != FACTORY_BOOT)
#endif
{
/* Wait Tx HDMA Channel to be inactive */
while(HDMA_BUF0_IS_ACTIVE((port + 2)))
{
val = DRV_Reg32(GDMA_GISAR_UART);
if(IS_HDMA_LENERR_INTR(val, (2 + port))) break;
if(IS_HDMA_GPD_CSERR_INTR(val, (2 + port))) break;
if(IS_HDMA_BD_CSERR_INTR(val, (2 + port))) break;
}
/* Stop Tx HDMA Channel */
HDMA_BUF0_STOP((2 + port));
while (HDMA_BUF0_IS_ACTIVE((port + 2)));
}
/* Stop Rx HDMA Channel */
HDMA_BUF0_STOP((3 + port));
while (HDMA_BUF0_IS_ACTIVE((port + 3)));
/* Clear SW Queue */
uart_ecpt_clear_sw_queue(port);
return STATUS_OK;
}
void uart_ecpt_timer_reset(UART_PORT port){
ASSERT(port < MAX_UART_PORT_NUM);
uart_ecpt_timer[port].timer_during = 0;
uart_ecpt_timer[port].timer_old = 0;
uart_ecpt_timer[port].timer_now = 0;
uart_ecpt_timer[port].timer_start = 0;
}
void uart_ecpt_timer_start(UART_PORT port)
{
ASSERT(port < MAX_UART_PORT_NUM);
if(uart_ecpt_timer[port].timer_start == 0){
uart_ecpt_timer[port].timer_now = ust_get_current_time();
uart_ecpt_timer[port].timer_old = uart_ecpt_timer[port].timer_now;
uart_ecpt_timer[port].timer_during = 0;
uart_ecpt_timer[port].timer_start = 1;
}else{
uart_ecpt_timer[port].timer_now = ust_get_current_time();
}
}
kal_uint32 uart_ecpt_get_timer_during(UART_PORT port)
{
ASSERT(port < MAX_UART_PORT_NUM);
uart_ecpt_timer[port].timer_during =ust_us_duration(uart_ecpt_timer[port].timer_old,uart_ecpt_timer[port].timer_now)/1000 ;
return uart_ecpt_timer[port].timer_during;
}
DCL_STATUS uart_ecpt_init_hif(UART_PORT port)
{
ASSERT(port < MAX_UART_PORT_NUM);
/* need re-init hardware ??? */
/* initial exception mode qbm */
if (uart_except_init_qbm() != KAL_TRUE) {
return STATUS_FAIL;
}
return STATUS_OK;
}
DCL_STATUS uart_except_reset(UART_PORT port)
{
ASSERT(port < MAX_UART_PORT_NUM);
uart_ecpt_tx_state[port] = HIF_STATE_NORMAL;
uart_ecpt_timer_reset(port);
return STATUS_OK;
}
kal_uint32 uart_ecpt_get_tx_state(UART_PORT port){
ASSERT(port < MAX_UART_PORT_NUM);
kal_uint32 timer_dur = 0;
timer_dur = uart_ecpt_get_timer_during(port);
if(timer_dur>=UART_ECPT_MAX_TIMEOUT){
uart_ecpt_tx_state[port] = HIF_STATE_TXERROR;
uart_ecpt_timer_reset( port);
}else{
uart_ecpt_tx_state[port] = HIF_STATE_NORMAL;
}
return uart_ecpt_tx_state[port];
}
#else //#if !defined(DRV_UART_OFF)
UARTStruct UARTPort[MAX_UART_PORT_NUM];
kal_bool UART_VFIFO_support[MAX_UART_PORT_NUM] =
{
KAL_FALSE,
KAL_FALSE,
};
void UART_Boot_PutUARTBytes(UART_PORT port, kal_uint8 *data,kal_uint16 len){}
void U_Register(UART_PORT port, UartType_enum type, UartDriver_strcut* drv){}
kal_bool U_Open(UART_PORT port, module_type ownerid){}
void U_Close(UART_PORT port, module_type ownerid){}
kal_uint16 U_GetBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length, kal_uint8 *status, module_type ownerid){}
kal_uint16 U_PutBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length, module_type ownerid){}
kal_uint16 U_GetBytesAvail(UART_PORT port){}
kal_uint16 U_GetTxRoomLeft(UART_PORT port){}
kal_uint16 U_PutISRBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length, module_type ownerid){}
kal_uint16 U_GetTxISRRoomLeft(UART_PORT port){}
kal_uint16 U_SendISRData(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length,kal_uint8 mode, kal_uint8 escape_char, module_type ownerid){}
kal_uint16 U_SendData(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length,kal_uint8 mode,kal_uint8 escape_char, module_type ownerid ){}
void U_Purge(UART_PORT port, UART_buffer dir, module_type ownerid){}
void U_SetOwner (UART_PORT port, module_type ownerid){}
void U_SetFlowCtrl(UART_PORT port, kal_bool XON, module_type ownerid){}
void U_ConfigEscape (UART_PORT port, kal_uint8 EscChar, kal_uint16 ESCGuardtime, module_type ownerid){}
void U_SetDCBConfig(UART_PORT port, UARTDCBStruct *UART_Config, module_type ownerid){}
void U_CtrlDCD(UART_PORT port, IO_level SDCD, module_type ownerid){}
void U_CtrlBreak(UART_PORT port, IO_level SBREAK, module_type ownerid){}
void U_ClrRxBuffer(UART_PORT port, module_type ownerid){}
void U_ClrTxBuffer(UART_PORT port, module_type ownerid){}
void U_SetBaudRate(UART_PORT port, UART_baudrate baudrate, module_type ownerid){}
module_type U_GetOwnerID(UART_PORT port){}
void U_SetAutoBaud_Div(UART_PORT port, module_type ownerid){}
void U_Register_TX_cb(UART_PORT port, module_type ownerid, UART_TX_FUNC func){}
void U_Register_RX_cb(UART_PORT port, module_type ownerid, UART_RX_FUNC func){}
kal_uint8 U_GetUARTByte(UART_PORT port){}
kal_uint8 U_GetUARTByteWithTimeOut(UART_PORT port, kal_uint8* ch, kal_uint32 timeout_value){return 0;}
void U_PutUARTByte(UART_PORT port, kal_uint8 data){}
void U_PutUARTBytes(UART_PORT port, kal_uint8 *data, kal_uint16 len){}
void U_ReadDCBConfig(UART_PORT port, UARTDCBStruct *DCB){}
void U_CtrlRI (UART_PORT port, IO_level SRI, module_type ownerid){}
void U_CtrlDTR (UART_PORT port, IO_level SDTR, module_type ownerid){}
void U_ReadHWStatus(UART_PORT port, IO_level *SDSR, IO_level *SCTS){}
void UART_AssertWaitPrevDataSentOut(UART_PORT port){}
void UART_Calback(void *parameter){}
void UART_CheckAT_Callback(void *parameter){}
kal_bool UART_CheckTxAllSentOut(UART_PORT port){}
kal_bool UART_CheckTxBufferEmpty(UART_PORT port){}
void UART_CompensateAT(UART_PORT port){}
void uart_customize_init(void){}
void UART_dafault_rx_cb(UART_PORT port){}
void UART_dafault_tx_cb(UART_PORT port){}
void UART_DriverInit(UART_PORT port){}
void UART_EnableTX(UART_PORT port, kal_bool enable){}
void UART_GetTxBufferSize(UART_PORT port, kal_uint32 *total_size, kal_uint32 *rest_size){}
void UART_HWInit(UART_PORT port){}
kal_bool UART_IsVfifoSetting(UART_PORT port, UART_TxRx_VFIFO_support vs){}
void UART_RecHandler(void *parameter){}
void UART_MsHandler(void *parameter){}
void UART_RLSHandler(void *parameter){}
void UART_sendilm(UART_PORT port, msg_type msgid){}
void UART_set_FIFO_trigger(UART_PORT port, kal_uint16 tx_level, kal_uint16 rx_level){}
void UART_SetRateFix(UART_PORT port){}
void UART_SetSleepEnable(UART_PORT port, kal_bool enable){}
void UART_SleepOnTx_Enable(UART_PORT port, UART_SLEEP_ON_TX enable_flag){}
kal_bool uart_support_autoescape(void){}
void UART_SwitchPort(UART_PORT *APP_port, UART_PORT new_uart_port){}
void UART_TrxHandler(void *parameter){}
void UART_TxDMAHandler(void *parameter, kal_uint8 chk_done){}
void UART_TurnOnPower(UART_PORT port, kal_bool enable){}
void UART1_HISR(void){}
void UART2_HISR(void){}
void PutUARTDatas(UART_PORT port, kal_uint8 escape_char, kal_uint8 *data,kal_uint16 len){}
kal_uint16 BMT_PutBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length){}
void PutUARTRingBufferData(UART_PORT port){}
void UART_loopback(UART_PORT port){}
void UART_dsp_dafault_tx_cb(UART_PORT port){}
void UART_dsp_dafault_rx_cb(UART_PORT port){}
#endif //if !defined(DRV_UART_OFF)
// uart dispatch funtion table
UartDriver_strcut UartDriver=
{
U_Open,
U_Close,
U_GetBytes, // SIO_CMD_GET_BYTES is not supported
U_PutBytes, // SIO_CMD_PUT_BYTES is not supported
U_GetBytesAvail, // SIO_CMD_GET_RX_AVAIL is not supported
U_GetTxRoomLeft, // SIO_CMD_GET_TX_AVAIL is not supported
U_PutISRBytes, // SIO_CMD_PUT_ISR_BYTES is not supported
U_GetTxISRRoomLeft, // SIO_CMD_GET_ISR_TX_AVAIL is not supported
U_Purge,
U_SetOwner,
U_SetFlowCtrl,
U_ConfigEscape,
U_SetDCBConfig,
U_CtrlDCD, // SIO_CMD_CTRL_DCD is not supported
U_CtrlBreak,
U_ClrRxBuffer,
U_ClrTxBuffer,
U_SetBaudRate,
U_SendISRData, // SIO_CMD_SEND_ISR_DATA is not supported
U_SendData, // SIO_CMD_SEND_DATA is not supported
U_GetOwnerID,
U_SetAutoBaud_Div, // SIO_CMD_SET_AUTOBAUD_DIV is not supported
/*TY adds these to expand flexibility 2004/10/15*/
U_Register_TX_cb, // SIO_CMD_REG_TX_CB is not supported
U_Register_RX_cb, // SIO_CMD_REG_RX_CB is not supported
/*TY adds these to let virtual COM port can retrive exception log 2005/3/8*/
U_GetUARTByte, // SIO_CMD_GET_UART_BYTE is not supported
U_PutUARTByte, // SIO_CMD_PUT_UART_BYTE is not supported
U_PutUARTBytes, // SIO_CMD_PUT_UART_BYTES is not supported
/*for virtual com port to return DCB configuration*/
U_ReadDCBConfig,
U_CtrlRI, // SIO_CMD_CTRL_RI is not supported
U_CtrlDTR, // SIO_CMD_CTRL_DTR is not supported
U_ReadHWStatus,
U_GetUARTByteWithTimeOut
};
typedef struct hdma_tgpd_ss {
kal_uint8 hwo:1;
kal_uint8 bdp:1;
kal_uint8 bps:1;
kal_uint8 resv1:4;
kal_uint8 ioc:1;
kal_uint8 cksum;
kal_uint16 resv2;
kal_uint32 nextPtr;
kal_uint32 bufPtr;
kal_uint8 resv3;
} hdma_tgpd_tt;
typedef struct hdma_rgpd_ss {
kal_uint8 hwo:1;
kal_uint8 bdp:1;
kal_uint8 bps:1;
kal_uint8 resv1:4;
kal_uint8 ioc:1;
kal_uint8 cksum;
kal_uint16 allowBufLen;
kal_uint32 nextPtr;
kal_uint32 bufPtr;
kal_uint16 bufLen;
kal_uint16 resv2;
} hdma_rgpd_tt;
// dummy_fdma() just for mt6595 workaround patch. removed on LR12.
/*
void dummy_fdma(kal_uint32 gdma_start)
{
FDMA_PDN_CLR(3);
if(gdma_start == 0){
DRV_WriteReg32(0xff2c0080, 0x4); // stop (GDMA_FDCR0)
FDMA_PDN_SET(3);
}
else{
DRV_WriteReg32(0xff2c0080, 0x4); // stop (GDMA_FDCR0)
while(DRV_Reg32(0xff2c0014) & (1<<16)); // check done state (GDMA_FDCSR0)
DRV_WriteReg32(0xff2c0014, 0x02000000); // GDMA_FDCSR
DRV_WriteReg32(0xff2c0084, 0xbf830C20); // GDMA_FDSAR3
DRV_WriteReg32(0xff2c0088, 0xbf830C24); // GDMA_FDDAR3
DRV_WriteReg32(0xff2c0080, 0xffff43a1); // start (GDMA_FDCR3)
}
return;
}
}
*/
extern UARTStruct UARTPort[];
extern Seriport_HANDLER_T Uart_Drv_Handler;
enum {
INIT_NOTINIT,
INIT_REG_CB,
INIT_DRV_ATTACH,
INIT_DRV_INIT,
INIT_UPMOD_INIT,
INIT_SET_BAUDRATE,
INIT_DONE,
} uart_excpt_drv_init_stage = INIT_NOTINIT;
kal_bool uart_excpt_drv_init_done_g = KAL_FALSE;
kal_bool uart_st_in_except_mode_g = KAL_FALSE;
#if defined __UART_UT__
kal_int32 uart_hmu_pre_init(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
kal_int32 uart_hmu_init(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return 0;
}
kal_int32 uart_hmu_post_init(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
kal_int32 uart_hmu_pre_deinit(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
kal_int32 uart_hmu_deinit(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
kal_int32 uart_hmu_post_deinit(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
kal_int32 uart_hmu_except_init(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
#else
kal_int32 uart_hmu_pre_init(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
kal_int32 uart_hmu_init(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
kal_int32 uart_hmu_post_init(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
kal_int32 uart_hmu_pre_deinit(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
kal_int32 uart_hmu_deinit(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
kal_int32 uart_hmu_post_deinit(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
return KAL_TRUE;
}
UARTStruct* uart_core_get_instance(kal_uint32 uart_port)
{
return &UARTPort[uart_port];
}
DCL_STATUS uart_ttyhdr_reg_ttycore(UARTStruct*p_dev_inst, kal_uint32 port)
{
DCL_STATUS status;
DCL_HANDLE handle;
handle = DclSerialPort_Open(port, 0);
uart_excpt_drv_init_stage = INIT_REG_CB;
status = DclSerialPort_DrvRegisterCb(handle, &Uart_Drv_Handler);
if (KAL_TRUE == uart_st_in_except_mode_g && STATUS_ALREADY_OPENED == status) {
return STATUS_OK;
}
return status;
}
DCL_STATUS uart_ttyhdr_cmd_init(UART_PORT port)
{
DCL_STATUS status;
DCL_HANDLE handle;
DCL_CTRL_DATA_T data;
handle = DclSerialPort_Open(port, 0);
uart_excpt_drv_init_stage = INIT_DRV_ATTACH;
status = DclSerialPort_DrvAttach(handle);
if(status != STATUS_OK)
{
return STATUS_FAIL;
}
uart_excpt_drv_init_stage = INIT_DRV_INIT;
status = DclSerialPort_Control(handle, SIO_CMD_INIT, &data);
return status;
}
DCL_STATUS uart_ttyhdr_upmodule_init(UART_PORT port)
{
DCL_STATUS status;
DCL_HANDLE handle;
UART_CTRL_DCB_T data;
handle = DclSerialPort_Open(port, 0);
uart_excpt_drv_init_stage = INIT_UPMOD_INIT;
status = DclSerialPort_UpModuleInit(handle, MOD_DRV_DBG, TTY_FLAG_NEW_TX | TTY_FLAG_NEW_RX);
if (status != STATUS_OK && status != STATUS_ALREADY_OPENED) {
return status;
}
//DclSerialPort_UpModuleRegisterCb(handle, dbg_print_tty_rx_cb, NULL, dbg_print_tty_state_cb);
data.u4OwenrId = MOD_DRV_DBG;
data.rUARTConfig.u4Baud = UART_BAUD_1500000;
data.rUARTConfig.u1DataBits = len_8;
data.rUARTConfig.u1StopBits = sb_1;
data.rUARTConfig.u1Parity = pa_none;
data.rUARTConfig.u1FlowControl = fc_sw;
data.rUARTConfig.ucXonChar = 0x11;
data.rUARTConfig.ucXoffChar = 0x13;
data.rUARTConfig.fgDSRCheck = KAL_FALSE;
// Set baudrate
uart_excpt_drv_init_stage = INIT_SET_BAUDRATE;
status = DclSerialPort_Control(handle, SIO_CMD_SET_DCB_CONFIG, (DCL_CTRL_DATA_T*)&data);
return status;
}
kal_int32 uart_hmu_except_init(kal_uint32 dev_mapping, kal_uint32 ext_devinfo_len, kal_char *ext_devinfo)
{
DCL_STATUS ret;
UARTStruct* p_dev_inst;
kal_uint32 uart_port;
kal_uint32 init_ports[] = {uart_port1, uart_port2};
kal_uint32 ret_val = 0;
int i;
uart_st_in_except_mode_g = KAL_TRUE;
if (uart_excpt_drv_init_done_g == KAL_TRUE) {
return 0;
}
for (i = 0; i < sizeof(init_ports)/sizeof(init_ports[0]); i++) {
uart_port = init_ports[i];
p_dev_inst = uart_core_get_instance(uart_port);
if(p_dev_inst->initialized == KAL_TRUE){
continue;
}
ret = uart_ttyhdr_reg_ttycore(p_dev_inst, uart_port);
if (STATUS_OK != ret) {
ret_val = -1;
continue;
}
ret = uart_ttyhdr_cmd_init(uart_port);
if (STATUS_OK != ret) {
ret_val = -1;
continue;
}
}
uart_excpt_drv_init_stage = INIT_DONE;
uart_excpt_drv_init_done_g = KAL_TRUE;
return ret_val;
}
#endif