/*
 * Copyright (c) 2013, Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __FSL_USB_HAL_H__
#define __FSL_USB_HAL_H__

#include "adapter.h"
#if (OS_ADAPTER_ACTIVE_OS == OS_ADAPTER_SDK)
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "fsl_usb_features.h"
#include "fsl_device_registers.h"
#define NEW_USB_HAL_ENABLE  1
#elif (OS_ADAPTER_ACTIVE_OS == OS_ADAPTER_BM)
    #if (defined(CPU_MK22F51212))
    #include "MK22F51212.h"
    #include "MK22F51212_usb.h"
    #define NEW_USB_HAL_ENABLE  1
    #elif (defined(CPU_MK70F12))
    #include "MK70F12.h"
    #define NEW_USB_HAL_ENABLE  0
    #endif
#elif (OS_ADAPTER_ACTIVE_OS == OS_ADAPTER_MQX)
#if (defined(CPU_MK22F51212))
#include "MK22F12.h"
#include "MK22F51212_usb.h"
#define NEW_USB_HAL_ENABLE	1
#elif (defined(CPU_MK70F12))
#include "MK70F12.h"
#define NEW_USB_HAL_ENABLE	0
#endif
#endif

#if NEW_USB_HAL_ENABLE
//! @addtogroup usb_hal
//! @{

//! @file

////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// API
////////////////////////////////////////////////////////////////////////////////
 
#if defined(__cplusplus)
extern "C" {
#endif

/*! 
 * @name Initialization
 * @{
 */

/*!
 * @brief Init the BDT page register from the BDT table
 *
 * @param instance   USB instance id
 * @param bdtAddress   the BDT address resides in memory
 */
static void usb_hal_khci_set_buffer_descriptor_table_addr(uint32_t instance, uint32_t bdtAddress)
{
    //assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_BDTPAGE1_WR((uint8_t)((uint32_t)bdtAddress >> 8));
	HW_USB_BDTPAGE2_WR((uint8_t)((uint32_t)bdtAddress >> 16));
	HW_USB_BDTPAGE3_WR((uint8_t)((uint32_t)bdtAddress >> 24));
}


/*!
 * @brief Enable the specific Interrupt
 *
 * @param instance  USB instance id
 * @param intrType  specific  interrupt type
 */
static inline void usb_hal_khci_enable_interrupts(uint32_t instance, uint32_t intrType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_INTEN_SET((uint8_t)intrType);
}


/*!
 * @brief Disable the specific Interrupt
 *
 * @param instance USB instance id
 * @param intrType  specific interrupt type 
 */
static inline void usb_hal_khci_disable_interrupts(uint32_t instance, uint32_t intrType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_INTEN_CLR((uint8_t)intrType);
}

/*!
 * @brief Get the interrupt status
 *
 * @param instance USB instance id
 * @return specific interrupt type 
 */
static inline uint8_t usb_hal_khci_get_interrupt_status(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (HW_USB_ISTAT_RD);
}

/*!
 * @brief Get the interrupt enable status
 *
 * @param instance USB instance id
 * @return current enabled interrupt types
 */
static inline uint8_t usb_hal_khci_get_interrupt_enable_status(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (HW_USB_INTEN_RD);
}

/*!
* @brief Clear the specific interrupt
*
* @param instance usb instance id
* @param intrType the interrupt type needs to be cleared
*/
static inline void usb_hal_khci_clr_interrupt(uint32_t instance, uint32_t intrType)
{

	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ISTAT_WR((uint8_t)intrType);
}

/*!
* @brief Clear all the interrupts
*
* @param instance usb instance id
*/
static inline void usb_hal_khci_clr_all_interrupts(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ISTAT_WR(0xff);
}

/*!
* @brief Judge if an interrupt type happen
*
* @param instance usb instance id
* @param intrType the interrupt type
* @return the current interrupt type is happen or not
*/
static inline uint8_t usb_hal_khci_is_interrupt_issued(uint32_t instance, uint32_t intrType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ( HW_USB_ISTAT_RD & HW_USB_INTEN_RD & (intrType));
}

/*!
* @brief Enable all the error interrupt
* @param instance usb instance id
*/
static inline void usb_hal_khci_enable_all_error_interrupts(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ERREN_WR(0xFF);
}

/*!
* @brief Disable all the error interrupts
* @param instance usb instance id
*/
static inline void usb_hal_khci_disable_all_error_interrupts(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ERREN_WR(0);
}

/*!
* @brief Enable the specific error interrupts
* @param instance usb instance id
* @param errIntrType the error interrupt type
*/
static inline void usb_hal_khci_enable_error_interrupts(uint32_t instance, uint32_t errIntrType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ERREN_SET((uint8_t)errIntrType);
}

/*!
* @brief Disable  the specific error interrupt
* @param instance usb instance id
* @param errIntrType the error interrupt type
*/
static inline void usb_hal_khci_disable_error_interrupts(uint32_t instance, uint32_t errorIntrType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ERREN_CLR((uint8_t)errorIntrType);
}

/*!
* @brief Get the error interrupt status
*
* @param instance usb instance id
* @return  the error interrupt status
*/
static inline uint8_t usb_hal_khci_get_error_interrupt_status(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (HW_USB_ERRSTAT_RD);
}

/*!
* @brief Get the error interrupt enable status
*
* @param instance usb instance id
* @return  the error interrupt enable status
*/
static inline uint8_t usb_hal_khci_get_error_interrupt_enable_status(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (HW_USB_ERREN_RD);
}

/*!
* @brief Clear all the error interrupt happened
*
* @param instance usb instance id
*/
static inline void usb_hal_khci_clr_all_error_interrupts(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ERRSTAT_WR(0xff);
}

/*!
* @brief Check if the specific error happened
*
* @param instance usb instance id
* @return the ERRSTAT register together with the error interrupt
*/
static inline uint8_t usb_hal_khci_is_error_happend(uint32_t instance, uint32_t errorType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ( HW_USB_ERRSTAT_RD & (uint8_t)errorType);
}

/*!
 * @brief Clear the TOKENBUSY flag.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_clr_token_busy(uint32_t instance)
{
    //assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CTL_CLR(USB_CTL_TXSUSPENDTOKENBUSY_MASK);	  
}

/*!
 * @brief Check if controller is busy on transferring.
 *
 * @param instance USB instance id.
 * @return the value of the TOKENBUSY bit from the control register
 */
static inline uint8_t usb_hal_khci_is_token_busy(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (uint8_t)(HW_USB_CTL_RD & USB_CTL_TXSUSPENDTOKENBUSY_MASK);
	
}

/*!
 * @brief reset all the BDT odd ping/pong fields.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_set_oddrst(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CTL_SET(USB_CTL_ODDRST_MASK);
}

/*!
 * @brief clear the ODDRST flag.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_clr_oddrst(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CTL_CLR(USB_CTL_ODDRST_MASK);
}
/*!
 * @brief Begin to issue RESET signal.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_start_bus_reset(uint32_t  instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CTL_SET(USB_CTL_RESET_MASK);
}

/*!
 * @brief Stop issuing RESET signal
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_stop_bus_reset(uint32_t  instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CTL_CLR(USB_CTL_RESET_MASK);
}

/*!
 * @brief Start to issue resume signal.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_start_resume(uint32_t instance)
{
    //assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CTL_SET(USB_CTL_RESUME_MASK);
}

/*!
 * @brief Stop issuing resume signal.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_stop_resume(uint32_t instance)
{
    //assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CTL_CLR(USB_CTL_RESUME_MASK);
}

/*!
 * @brief Set the USB controller to host mode
 *
 * @param instance USB instance id.
 *
 */
static inline void usb_hal_khci_set_host_mode(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CTL_WR(USB_CTL_HOSTMODEEN_MASK);
}

/*!
 * @brief Set the USB controller to device mode
 *
 * @param instance USB instance id.
 *
 */
static inline void usb_hal_khci_set_device_mode(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);	
    HW_USB_CTL_CLR(USB_CTL_HOSTMODEEN_MASK);
}

/*!
 * @brief Enable the USB module.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_enable_sof(uint32_t  instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CTL_SET(USB_CTL_USBENSOFEN_MASK);
}

/*!
 * @brief Disable the USB module.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_disable_sof(uint32_t  instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CTL_CLR(USB_CTL_USBENSOFEN_MASK);
}

/*!
 * @brief Clear the USB controller register
 *
 * @param instance USB instance id.
 *
 */
static inline void usb_hal_khci_clear_control_register(uint32_t instance)
{
    HW_USB_CTL_CLR(0xFF);
}

/*!
 * @brief Get the speed  of the USB module.
 *
 * @param instance USB instance id.
 * @return the current line status of the USB module
 */
static inline uint8_t usb_hal_khci_get_line_status(uint32_t  instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ((HW_USB_CTL_RD & USB_CTL_JSTATE_MASK) ? 0 : 1);
}

/*!
* @brief Get current  status
*
* @param instance usb instance id
* @return current status
*/
static inline uint8_t usb_hal_khci_get_transfer_status(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return HW_USB.STAT.U;
}

/*!
* @brief Get the endpoint number from STAT register
*
* @param instance usb instance id
* @return endpoint number
*/
static inline uint8_t usb_hal_khci_get_transfer_done_ep_number(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ((HW_USB.STAT.U & 0xf0) >> 4);
}

/*!
* @brief Return the transmit dir from STAT register
*
* @param instance usb instance id
* @return transmit direction
*/
static inline uint8_t usb_hal_khci_get_transfer_done_direction(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ((HW_USB.STAT.U & USB_STAT_TX_MASK) >>USB_STAT_TX_SHIFT);
}

/*!
* @brief Return the even or odd bank from STAT register
*
* @param instance usb instance id
* @return the even or odd bank
*/
static inline uint8_t usb_hal_khci_get_transfer_done_odd(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ((HW_USB.STAT.U & USB_STAT_ODD_MASK) >> USB_STAT_ODD_SHIFT);
}

/*!
* @brief Returned the computed BDT address
*
* @param instance usb instance id
* @return the computed BDT address
*/
static inline uint16_t usb_hal_khci_get_frame_number(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ( HW_USB.FRMNUMH.U << 8 | HW_USB.FRMNUML.U );
}

/*!
* @brief Set the device address 
*
* @param instance usb instance id
* @param addr the address used to set
*/
static inline void usb_hal_khci_set_device_addr(uint32_t instance, uint32_t addr)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	BW_USB_ADDR_ADDR(addr);
}

/*!
* @brief Set the transfer target 
*
* @param instance usb instance id
* @param address the address used to set
* @param speed the speed used to set
*/
static inline void usb_hal_khci_set_transfer_target(uint32_t instance, uint32_t address, uint32_t speed)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ADDR_WR((uint8_t)((speed == 0) ? (uint8_t)address : USB_ADDR_LSEN_MASK | (uint8_t)address));
}

/*!
* @brief Init the endpoint0
* 
* @param instance usb instance id
* @param isThoughHub endpoint0 is though hub or not
* @param isIsochPipe  current pipe is iso or not
*/
static inline void usb_hal_khci_endpoint0_init(uint32_t instance, uint32_t isThoughHub, uint32_t isIsochPipe)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB.ENDPOINT[0].ENDPTn.U = (isThoughHub == 1 ? USB_ENDPT_HOSTWOHUB_MASK : 0)| USB_ENDPT_RETRYDIS_MASK |
            USB_ENDPT_EPTXEN_MASK | USB_ENDPT_EPRXEN_MASK | (isIsochPipe == 1 ? 0 : USB_ENDPT_EPHSHK_MASK);	
}

/*!
* @brief Stop the endpoint
* 
* @param instance usb instance id
* @param epNumber endpoint number
*/
static inline void usb_hal_khci_endpoint_shut_down(uint32_t instance, uint32_t epNumber)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ENDPTn_WR(epNumber,0);
}

/*!
* @brief Set the flag to indicate if the endpoint is communicating with controller through the hub  
* 
* @param instance usb instance id
* @param epNumber endpoint number
*/
static inline void usb_hal_khci_endpoint_on_hub(uint32_t instance, uint32_t epNumber)
{
	
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ENDPTn_SET(epNumber,USB_ENDPT_HOSTWOHUB_MASK);
}

/*!
* @brief Set the endpoint in host mode which need handshake or not
* 
* @param instance usb instance id
* @param epNumber endpoint number
* @param isEphshkSet needs handshake or not
*/
static inline void usb_hal_khci_endpoint_enable_handshake(uint32_t instance, uint32_t epNumber, uint32_t isEphshkSet)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ENDPTn_SET(epNumber,((isEphshkSet == 1) ? USB_ENDPT_EPHSHK_MASK : 0));
}

/*!
* @brief Set the endpoint in host mode which in TX or RX
* 
* @param instance usb instance id
* @param epNumber endpoint number
* @param isEptxenSet in TX or RX
*/
static inline void usb_hal_khci_endpoint_set_direction(uint32_t instance, uint32_t epNumber, uint8_t isEptxenSet)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ENDPTn_SET(epNumber,((isEptxenSet == 1) ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK));
}

/*!
* @brief Clear the stall status of the endpoint
* 
* @param instance usb instance id
* @param epNumber endpoint number
*/
static inline void usb_hal_khci_endpoint_clr_stall(uint32_t instance, uint32_t epNumber)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ENDPTn_CLR(epNumber, USB_ENDPT_EPSTALL_MASK);
	
}

/*!
* @brief Enable the support for low speed
* @param instance usb instance id
*/
static inline void usb_hal_khci_enable_low_speed_support(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ADDR_SET(USB_ADDR_LSEN_MASK);
}


/*!
* @brief Disable the support for low speed
* @param instance usb instance id
*/
static inline void usb_hal_khci_disable_low_speed_support(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_ADDR_CLR(USB_ADDR_LSEN_MASK);
}


/*!
* @brief Enable the pull down
* 
* @param instance usb instance id
*/
static inline void usb_hal_khci_enable_pull_down(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CONTROL_SET(USB_USBCTRL_PDE_MASK);
}


/*!
* @brief Disable the pull down
* 
* @param instance usb instance id
*/
static inline void usb_hal_khci_disable_pull_down(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CONTROL_CLR(USB_USBCTRL_PDE_MASK);
}


/*!
* @brief Enable the pull up
* @param instance usb instance id
*/
static inline void usb_hal_khci_enable_pull_up(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_OTGCTL_WR(USB_OTGCTL_DPHIGH_MASK |  USB_OTGCTL_OTGEN_MASK |USB_OTGCTL_DMLOW_MASK |USB_OTGCTL_DPLOW_MASK);
}

/*!
* @brief Disable the pull up
* @param instance usb instance id
*/
static inline void usb_hal_khci_disable_pull_up(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_OTGCTL_CLR(USB_OTGCTL_DPHIGH_MASK |  USB_OTGCTL_OTGEN_MASK |USB_OTGCTL_DMLOW_MASK |USB_OTGCTL_DPLOW_MASK);
}

/*!
* @brief Set the controller to the suspend state
* @param instance usb instance id
*/
static inline void usb_hal_khci_set_suspend(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CONTROL_SET(USB_USBCTRL_SUSP_MASK);
}


/*!
* @brief Clear the suspend state of the controller
* @param instance usb instance id
*/
static inline void usb_hal_khci_clr_suspend(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_CONTROL_CLR(USB_USBCTRL_SUSP_MASK);
}

/*!
* @brief Set the sof threshold
* @param instance usb instance id
* @param value value used to set
*/
static inline void usb_hal_khci_set_sof_theshold(uint32_t instance, uint32_t value)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	HW_USB_SOFTHLD_WR((uint8_t)value);
}

static inline void usb_hal_khci_set_target_token(uint32_t instance, uint8_t token, uint8_t endpoint_number)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
    HW_USB_TOKEN_WR((uint8_t)(USB_TOKEN_TOKENENDPT(endpoint_number) | token));
}


#else
//#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "MK70F12.h"

//#include "fsl_usb_features.h"
//#include "device/fsl_device_registers.h"

//! @addtogroup usb_hal
//! @{

//! @file

////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// API
////////////////////////////////////////////////////////////////////////////////
 
#if defined(__cplusplus)
extern "C" {
#endif
#define HW_USB_INSTANCE_COUNT (1U)

static void usb_hal_ehci_set_controller_host_mode(uint32_t instance)
{
	USBHS_USBMODE = (USBHS_USBMODE & ~USBHS_USBMODE_CM_MASK) | USBHS_USBMODE_CM(0x3); 
}

static void usb_hal_ehci_set_controller_device_mode(uint32_t instance)
{
	USBHS_USBMODE = (USBHS_USBMODE & ~USBHS_USBMODE_CM_MASK) | USBHS_USBMODE_CM(0x2); 
}

static void usb_hal_ehci_set_big_endian(uint32_t instance)
{
	USBHS_USBMODE = (USBHS_USBMODE & ~USBHS_USBMODE_ES_MASK)|(1 << USBHS_USBMODE_ES_SHIFT);
}

static void usb_hal_ehci_set_little_endian(uint32_t instance)
{
	USBHS_USBMODE = (USBHS_USBMODE & ~USBHS_USBMODE_ES_MASK)|(0 << USBHS_USBMODE_ES_SHIFT);
}

static void usb_hal_ehci_disable_setup_lock(uint32_t instance)
{
	USBHS_USBMODE = (USBHS_USBMODE & ~USBHS_USBMODE_SLOM_MASK)|(1 << USBHS_USBMODE_SLOM_SHIFT);
}

static void usb_hal_ehci_enable_setup_lock(uint32_t instance)
{
	USBHS_USBMODE = (USBHS_USBMODE & ~USBHS_USBMODE_SLOM_MASK)|(0 << USBHS_USBMODE_SLOM_SHIFT);
}

static uint32_t usb_hal_ehci_get_dcc_params(uint32_t instance)
{
	return USBHS_DCCPARAMS;
}

static void usb_hal_ehci_clear_ep_setup_status(uint32_t instance, uint32_t epSetupStatus)
{	
	USBHS_EPSETUPSR |= (epSetupStatus << USBHS_EPSETUPSR_EPSETUPSTAT_SHIFT) & USBHS_EPSETUPSR_EPSETUPSTAT_MASK;
}

static uint32_t usb_hal_ehci_get_ep_setup_status(uint32_t instance)
{	
	return USBHS_EPSETUPSR;
}

static uint32_t usb_hal_ehci_get_ep_complete_status(uint32_t instance)
{
	return USBHS_EPCOMPLETE;
}

static void usb_hal_ehci_clear_ep_complete_status(uint32_t instance, uint32_t epCompleteStatus)
{
	USBHS_EPCOMPLETE = epCompleteStatus;
}

static void usb_hal_ehci_set_eplist_address(uint32_t instance, uint32_t epQHAddress)
{
	USBHS_EPLISTADDR = epQHAddress;
}

static uint32_t usb_hal_ehci_get_eplist_address(uint32_t instance)
{
	return USBHS_EPLISTADDR;
}


static void usb_hal_ehci_enable_interrupts(uint32_t instance, uint32_t intrType)
{
	USBHS_USBINTR = intrType;
}

static void usb_hal_ehci_disable_interrupts(uint32_t instance, uint32_t intrType)
{
	USBHS_USBINTR &= ~intrType;
}
static void usb_hal_ehci_enable_pull_up(uint32_t instance)
{
	USBHS_USBCMD = EHCI_CMD_RUN_STOP;
}

static void usb_hal_ehci_initiate_attach_event(uint32_t instance)
{
	USBHS_USBCMD |= EHCI_CMD_RUN_STOP;
}

static void usb_hal_ehci_initiate_detach_event(uint32_t instance)
{
	USBHS_USBCMD &= ~EHCI_CMD_RUN_STOP;
}

static void usb_hal_ehci_reset_controller(uint32_t instance)
{
	USBHS_USBCMD = EHCI_CMD_CTRL_RESET;
}

static void usb_hal_ehci_set_dTD_TripWire(uint32_t instance)
{
	USBHS_USBCMD |= EHCI_CMD_ATDTW_TRIPWIRE_SET;
}

static void usb_hal_ehci_clear_dTD_TripWire(uint32_t instance)
{
	USBHS_USBCMD &= ~EHCI_CMD_ATDTW_TRIPWIRE_SET;
}
static uint32_t usb_hal_ehci_is_TripWire_set(uint32_t instance)
{
	return (USBHS_USBCMD & EHCI_CMD_ATDTW_TRIPWIRE_SET);
}

static void usb_hal_ehci_set_endpoint_prime(uint32_t instance, uint32_t value)
{	
	USBHS_EPPRIME = value;
}

static uint32_t usb_hal_ehci_get_endpoint_prime(uint32_t instance)
{
	return USBHS_EPPRIME;
}
static uint32_t usb_hal_echi_get_endpoint_status(uint32_t instance)
{
	return USBHS_EPSR;
}

static void usb_hal_ehci_flush_endpoint_buffer(uint32_t instance, uint32_t epNumber)
{
	USBHS_EPFLUSH = epNumber;
}

static uint32_t usb_hal_ehci_is_endpoint_transfer_flushed(uint32_t instance, uint32_t epNumber)
{
	return (USBHS_EPFLUSH & epNumber);
}

static uint32_t usb_hal_ehci_get_frame_index(uint32_t instance)
{
	return USBHS_FRINDEX;
}

static uint32_t usb_hal_ehci_get_port_status(uint32_t instance)
{
	return USBHS_PORTSC1;
}

static void usb_hal_ehci_set_port_status(uint32_t instance, uint32_t status)
{
	USBHS_PORTSC1 = status;
}

static uint32_t usb_hal_ehci_get_usb_status(uint32_t instance)
{
	return USBHS_USBSTS;
}

static void usb_hal_ehci_set_device_address(uint32_t instance, uint32_t address)
{
	USBHS_DEVICEADDR = (uint32_t)(address << USBHS_ADDRESS_BIT_SHIFT);
}

static void usb_hal_ehci_clear_device_address(uint32_t instance)
{
	USBHS_DEVICEADDR &= ~0xFE000000;
}

static void usb_hal_ehci_enable_endpoint(uint32_t instance, uint32_t epNumber, uint32_t direction, uint32_t type)
{
	if (epNumber == 0)
		USBHS_EPCR0 |= ((direction ? (EHCI_EPCTRL_TX_ENABLE |
            EHCI_EPCTRL_TX_DATA_TOGGLE_RST) :
            (EHCI_EPCTRL_RX_ENABLE | EHCI_EPCTRL_RX_DATA_TOGGLE_RST)) |
            (type << (direction ?
            EHCI_EPCTRL_TX_EP_TYPE_SHIFT : EHCI_EPCTRL_RX_EP_TYPE_SHIFT)));
	else
		USBHS_EPCR_REG(USBHS_BASE_PTR,epNumber - 1) |= ((direction ? (EHCI_EPCTRL_TX_ENABLE |
            EHCI_EPCTRL_TX_DATA_TOGGLE_RST) :
            (EHCI_EPCTRL_RX_ENABLE | EHCI_EPCTRL_RX_DATA_TOGGLE_RST)) |
            (type << (direction ?
            EHCI_EPCTRL_TX_EP_TYPE_SHIFT : EHCI_EPCTRL_RX_EP_TYPE_SHIFT)));
}
static uint32_t usb_hal_ehci_get_endpoint_control(uint32_t instance, uint32_t epNumber)
{
	return (epNumber == 0 ? USBHS_EPCR0 : USBHS_EPCR_REG(USBHS_BASE_PTR,epNumber - 1));
}	


static void usb_hal_ehci_clear_endpoint_stall(uint32_t instance, uint32_t epNumber, uint32_t direction)
{
	if (epNumber == 0)
		USBHS_EPCR0 &= ~(direction ? EHCI_EPCTRL_TX_EP_STALL : EHCI_EPCTRL_RX_EP_STALL);
	else
		USBHS_EPCR_REG(USBHS_BASE_PTR,epNumber - 1) &= ~(direction ? EHCI_EPCTRL_TX_EP_STALL : EHCI_EPCTRL_RX_EP_STALL);
}

static void usb_hal_ehci_stall_both_directions(uint32_t instance, uint32_t epNumber)
{
	if (epNumber == 0)
		USBHS_EPCR0 |= (EHCI_EPCTRL_TX_EP_STALL | EHCI_EPCTRL_RX_EP_STALL);
	else
		USBHS_EPCR_REG(USBHS_BASE_PTR,epNumber - 1) |= (EHCI_EPCTRL_TX_EP_STALL | EHCI_EPCTRL_RX_EP_STALL);
}

static void usb_hal_ehci_stall_specific_direction(uint32_t instance, uint32_t epNumber, uint32_t direction)
{
	if (epNumber == 0)
		USBHS_EPCR0 |= (direction ? EHCI_EPCTRL_TX_EP_STALL : EHCI_EPCTRL_RX_EP_STALL);
	else
		USBHS_EPCR_REG(USBHS_BASE_PTR,epNumber - 1) |= (direction ? EHCI_EPCTRL_TX_EP_STALL : EHCI_EPCTRL_RX_EP_STALL);
		
}

static void usb_hal_ehci_clear_MAX_PKT_LENGTH(uint32_t instance,usb_ehc_dev_qh_struct_t * epQueueHeadAddr)
{
	epQueueHeadAddr->MAX_PKT_LENGTH = 0;
}

static void usb_hal_ehci_set_max_packet_length(uint32_t instance,usb_ehc_dev_qh_struct_t * epQueueHeadAddr, uint32_t maxPacketSize)
{
	epQueueHeadAddr->MAX_PKT_LENGTH = ((uint32_t)maxPacketSize << VUSB_EP_QUEUE_HEAD_MAX_PKT_LEN_POS) | VUSB_EP_QUEUE_HEAD_IOS;
}

static uint32_t usb_hal_ehci_is_ios_set(uint32_t instance, usb_ehc_dev_qh_struct_t * epQueueHeadAddr)
{
	return (epQueueHeadAddr->MAX_PKT_LENGTH & VUSB_EP_QUEUE_HEAD_IOS);
}



static void usb_hal_ehci_set_next_dtd_terminate(uint32_t instance,usb_ehc_dev_qh_struct_t * epQueueHeadAddr)
{
	epQueueHeadAddr->NEXT_DTD_PTR = VUSB_EP_QUEUE_HEAD_NEXT_TERMINATE;
}


static void usb_hal_ehci_set_qh_next_dtd(uint32_t instance,usb_ehc_dev_qh_struct_t * epQueueHeadAddr, uint32_t dtdAddr)
{
	epQueueHeadAddr->NEXT_DTD_PTR = dtdAddr;
}
static void usb_hal_ehci_set_next_dtd_invalid(uint32_t instance, usb_ehci_dev_dtd_struct_t * dtdAddr)
{
	dtdAddr->NEXT_TR_ELEM_PTR = USBHS_TD_NEXT_TERMINATE;
}

static void usb_hal_ehci_clear_SIZE_IOC_STS(uint32_t instance, usb_ehci_dev_dtd_struct_t * dtdAddr)
{
	dtdAddr->SIZE_IOC_STS = 0;
}

static void usb_hal_ehci_clear_IOC_reserved_fields(uint32_t instance, usb_ehci_dev_dtd_struct_t * dtdAddr)
{
	dtdAddr->SIZE_IOC_STS &= ~USBHS_TD_RESERVED_FIELDS;
}

static void usb_hal_ehci_clear_dtd(uint32_t instance, usb_ehci_dev_dtd_struct_t * dtdAddr)
{
	dtdAddr->NEXT_TR_ELEM_PTR = 0;
	dtdAddr->SIZE_IOC_STS = 0;
	dtdAddr->BUFF_PTR0 = 0;
	dtdAddr->BUFF_PTR1 = 0;
	dtdAddr->BUFF_PTR2 = 0;
	dtdAddr->BUFF_PTR3 = 0;
	dtdAddr->BUFF_PTR4 = 0;
}

static void usb_hal_ehci_set_dtd_buffer_address(uint32_t instance, usb_ehci_dev_dtd_struct_t * dtdAddr, uint32_t addr)
{
	dtdAddr->BUFF_PTR0 = addr;
	dtdAddr->BUFF_PTR1 = addr + 4096;
	dtdAddr->BUFF_PTR2 = addr + (4096*2);
	dtdAddr->BUFF_PTR3 = addr + (4096*3);
	dtdAddr->BUFF_PTR4 = addr + (4096*4);
}

static void usb_hal_ehci_set_dtd_size_ioc_status(uint32_t instance, usb_ehci_dev_dtd_struct_t * dtdAddr, uint32_t value)
{
	dtdAddr->SIZE_IOC_STS = value;
}

static uint32_t usb_hal_ehci_get_dtd_size_ioc_status(uint32_t instance, usb_ehci_dev_dtd_struct_t * dtdAddr)
{
	return dtdAddr->SIZE_IOC_STS;
}


static uint32_t usb_hal_ehci_get_next_dtd_address(uint32_t instance, usb_ehci_dev_dtd_struct_t * dtdAddr)
{
	return (dtdAddr->NEXT_TR_ELEM_PTR & USBHS_TD_ADDR_MASK);
}

static uint32_t usb_hal_ehci_get_dtd_error_status(uint32_t instance, usb_ehci_dev_dtd_struct_t * dtdAddr)
{
	return (dtdAddr->SIZE_IOC_STS & USBHS_TD_ERROR_MASK);
}

static void usb_hal_ehci_clear_qh_error_status(uint32_t instance, usb_ehc_dev_qh_struct_t * epQueueHeadAddr, uint32_t errors)
{
	epQueueHeadAddr->SIZE_IOC_INT_STS &= ~errors;
}

static uint32_t usb_hal_ehci_get_tr_packet_size(uint32_t instance,usb_ehci_dev_dtd_struct_t * dtdAddr)
{
	return ((dtdAddr->SIZE_IOC_STS & VUSB_EP_TR_PACKET_SIZE) >> 16);
}

static uint32_t usb_hal_ehci_get_xd_for_this_dtd(uint32_t instance, usb_ehci_dev_dtd_struct_t * dtdAddr)
{
	return (uint32_t)dtdAddr->xd_for_this_dtd;
}

static void usb_hal_ehci_clear_SIZE_IOC_INT_STS(uint32_t instance, usb_ehc_dev_qh_struct_t * epQueueHeadAddr)
{
	epQueueHeadAddr->SIZE_IOC_INT_STS = 0;
}
/*! 
 * @name Initialization
 * @{
 */

/*!
 * @brief Init the BDT page register from the BDT table
 *
 * @param instance USB instance id
 * @param bdtAddress   the BDT address resides in memory
 * 
 */
static void usb_hal_khci_set_buffer_descriptor_table_addr(uint32_t instance, uint32_t bdtAddress)
{
    //assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_BDTPAGE1 = (uint8_t)((uint32_t)bdtAddress >> 8);
	USB0_BDTPAGE2 = (uint8_t)((uint32_t)bdtAddress >> 16);
	USB0_BDTPAGE3 = (uint8_t)((uint32_t)bdtAddress >> 24);
}


/*!
 * @brief Enable the specific Interrupt
 *
 * @param instance  USB instance id
 * @param intrType  specific  interrupt type
 */
static inline void usb_hal_khci_enable_interrupts(uint32_t instance, uint32_t intrType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_INTEN |= (uint8_t)intrType;
}


/*!
 * @brief Disable the specific Interrupt
 *
 * @param instance USB instance id
 * @param intrType  specific interrupt type 
 */
static inline void usb_hal_khci_disable_interrupts(uint32_t instance, uint32_t intrType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_INTEN &= ~(uint8_t)intrType;
}

/*!
 * @brief Get the interrupt status
 *
 * @param instance USB instance id
 * @return specific interrupt type 
 */
static inline uint8_t usb_hal_khci_get_interrupt_status(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (USB0_ISTAT);
}

/*!
 * @brief Get the interrupt enable status
 *
 * @param instance USB instance id
 * @return current enabled interrupt types
 */
static inline uint8_t usb_hal_khci_get_interrupt_enable_status(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (USB0_INTEN);
}

/*!
* @brief Clear the specific interrupt
*
* @param instance usb instance id
* @param intrType the interrupt type needs to be cleared
*/
static inline void usb_hal_khci_clr_interrupt(uint32_t instance, uint32_t intrType)
{

	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ISTAT = (uint8_t)intrType;
}

/*!
* @brief Clear all the interrupts
*
* @param instance usb instance id
*/
static inline void usb_hal_khci_clr_all_interrupts(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ISTAT = 0xff;
}

/*!
* @brief Judge if an interrupt type happen
*
* @param instance usb instance id
* @param intrType the interrupt type
* @return the current interrupt type is happen or not
*/
static inline uint8_t usb_hal_khci_is_interrupt_issued(uint32_t instance, uint32_t intrType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (USB0_ISTAT & USB0_INTEN & (uint8_t)(intrType));
}

/*!
* @brief Enable all the error interrupt
* @param instance usb instance id
*/
static inline void usb_hal_khci_enable_all_error_interrupts(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ERREN = (uint8_t)0xFF;
}


/*!
* @brief Disable all the error interrupts
* @param instance usb instance id
*/
static inline void usb_hal_khci_disable_all_error_interrupts(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ERREN = (uint8_t)0;
}


/*!
* @brief Enable error interrupts
* @param instance usb instance id
* @param errIntrType the error interrupt type
*/
static inline void usb_hal_khci_enable_error_interrupts(uint32_t instance, uint32_t errIntrType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ERREN |= (uint8_t)errIntrType;
}

/*!
* @brief Disable  the specific error interrupt
* @param instance usb instance id
* @param errIntrType the error interrupt type
*/
static inline void usb_hal_khci_disable_error_interrupts(uint32_t instance, uint32_t errorIntrType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ERREN &= ~(uint8_t)errorIntrType;
}

/*!
* @brief Get the error interrupt status
*
* @param instance usb instance id
* @return  the error interrupt status
*/
static inline uint8_t usb_hal_khci_get_error_interrupt_status(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (USB0_ERRSTAT);
}

/*!
* @brief Get the error interrupt enable status
*
* @param instance usb instance id
* @return  the error interrupt enable status
*/
static inline uint8_t usb_hal_khci_get_error_interrupt_enable_status(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (USB0_ERREN);
}

/*!
* @brief Clear all the error interrupt happened
*
* @param instance usb instance id
*/
static inline void usb_hal_khci_clr_all_error_interrupts(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ERRSTAT = 0xff;
}

/*!
* @brief Check if the specific error happened
*
* @param instance usb instance id
* @return the ERRSTAT register together with the error interrupt
*/
static inline uint8_t usb_hal_khci_is_error_happend(uint32_t instance, uint32_t errorType)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ( USB0_ERRSTAT & (uint8_t)errorType);
}

/*!
 * @brief Clear the TOKENBUSY flag.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_clr_token_busy(uint32_t instance)
{
    //assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
    
}

/*!
 * @brief Check if controller is busy on transferring.
 *
 * @param instance USB instance id.
 * @return the value of the TOKENBUSY bit from the control register
 */
static inline uint8_t usb_hal_khci_is_token_busy(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return (uint8_t)(USB0_CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK);
}

/*!
 * @brief reset all the BDT odd ping/pong fields.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_set_oddrst(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CTL |= USB_CTL_ODDRST_MASK;
}

/*!
 * @brief Clear the ODDRST flag.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_clr_oddrst(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CTL &= ~USB_CTL_ODDRST_MASK;
}

/*!
 * @brief Begin to issue RESET signal.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_start_bus_reset(uint32_t  instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CTL |= USB_CTL_RESET_MASK;
}

/*!
 * @brief Stop issuing RESET signal
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_stop_bus_reset(uint32_t  instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CTL &= ~USB_CTL_RESET_MASK;
}

/*!
 * @brief Start to issue resume signal.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_start_resume(uint32_t instance)
{
    //assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CTL |= USB_CTL_RESUME_MASK;
}

/*!
 * @brief Stop issuing resume signal.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_stop_resume(uint32_t instance)
{
	//HW_USB_CTL_CLR(USB_CTL_RESUME_MASK);
	USB0_CTL &= ~USB_CTL_RESUME_MASK;
}


/*!
 * @brief Set the USB controller to host mode
 *
 * @param instance USB instance id.
 *
 */
static inline void usb_hal_khci_set_host_mode(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CTL = USB_CTL_HOSTMODEEN_MASK;
}

/*!
 * @brief Set the USB controller to device mode
 *
 * @param instance USB instance id.
 *
 */
static inline void usb_hal_khci_set_device_mode(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	
    USB0_CTL &= ~USB_CTL_HOSTMODEEN_MASK;
}


/*!
 * @brief Enable the USB module.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_enable_sof(uint32_t  instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CTL |= USB_CTL_USBENSOFEN_MASK;
}

/*!
 * @brief Disable the USB module.
 *
 * @param instance USB instance id.
 */
static inline void usb_hal_khci_disable_sof(uint32_t  instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CTL &= ~USB_CTL_USBENSOFEN_MASK;
}

/*!
 * @brief Clear the USB controller register
 *
 * @param instance USB instance id.
 *
 */
static inline void usb_hal_khci_clear_control_register(uint32_t instance)
{
    USB0_CTL = 0;
}

/*!
 * @brief Get the speed  of the USB module.
 *
 * @param instance USB instance id.
 * @return the current line status of the USB module
 */
static inline uint8_t usb_hal_khci_get_line_status(uint32_t  instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ((USB0_CTL & USB_CTL_JSTATE_MASK) ? 0 : 1);
}

/*!
* @brief Get current  status
*
* @param instance usb instance id
* @return current status
*/
static inline uint8_t usb_hal_khci_get_transfer_status(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return USB0_STAT;
}

/*!
* @brief Get the endpoint number from STAT register
*
* @param instance usb instance id
* @return endpoint number
*/
static inline uint8_t usb_hal_khci_get_transfer_done_ep_number(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ((USB0_STAT & 0xf0) >> 4);
}

/*!
* @brief Return the transmit dir from STAT register
*
* @param instance usb instance id
* @return transmit direction
*/
static inline uint8_t usb_hal_khci_get_transfer_done_direction(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ((USB0_STAT & USB_STAT_TX_MASK) >>USB_STAT_TX_SHIFT);
}

/*!
* @brief Return the even or odd bank from STAT register
*
* @param instance usb instance id
* @return the even or odd bank
*/
static inline uint8_t usb_hal_khci_get_transfer_done_odd(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ((USB0_STAT & USB_STAT_ODD_MASK) >> USB_STAT_ODD_SHIFT);
}


/*!
* @brief Returned the computed BDT address
*
* @param instance usb instance id
* @return the computed BDT address
*/
static inline uint16_t usb_hal_khci_get_frame_number(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	return ( USB0_FRMNUMH << 8 | USB0_FRMNUML);
}

/*!
* @brief Set the device address 
*
* @param instance usb instance id
* @param addr the address used to set
*/
static inline void usb_hal_khci_set_device_addr(uint32_t instance, uint32_t addr)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ADDR = (uint8_t)((USB0_ADDR & ~0x7F) | addr);
}


/*!
* @brief Set the transfer target 
*
* @param instance usb instance id
* @param addr the address used to set
*/
static inline void usb_hal_khci_set_transfer_target(uint32_t instance, uint32_t address, uint32_t speed)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ADDR = (uint8_t)((speed == 0) ? (uint8_t)address : USB_ADDR_LSEN_MASK | (uint8_t)address);
}

/*!
* @brief Init the endpoint0
* 
* @param instance usb instance id
* @param isThoughHub endpoint0 is though hub or not
* @param isIsochPipe  current pipe is iso or not
*/
static inline void usb_hal_khci_endpoint0_init(uint32_t instance, uint32_t isThoughHub, uint32_t isIsochPipe)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ENDPT0 = (isThoughHub == 1 ? USB_ENDPT_HOSTWOHUB_MASK : 0)| USB_ENDPT_RETRYDIS_MASK |
            USB_ENDPT_EPTXEN_MASK | USB_ENDPT_EPRXEN_MASK | (isIsochPipe == 1 ? 0 : USB_ENDPT_EPHSHK_MASK);
	
}

/*!
* @brief Stop the endpoint
* 
* @param instance usb instance id
* @param epNumber endpoint number
*/
static inline void usb_hal_khci_endpoint_shut_down(uint32_t instance, uint32_t epNumber)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB_ENDPT_REG(USB0_BASE_PTR, (uint8_t)epNumber) = 0;
}

/*!
* @brief Set the flag to indicate if the endpoint is communicating with controller through the hub  
* 
* @param instance usb instance id
* @param epNumber endpoint number
*/
static inline void usb_hal_khci_endpoint_on_hub(uint32_t instance, uint32_t epNumber)
{
	
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB_ENDPT_REG(USB0_BASE_PTR, (uint8_t)epNumber) |= USB_ENDPT_HOSTWOHUB_MASK;
}

/*!
* @brief Set the endpoint in host mode which need handshake or not
* 
* @param instance usb instance id
* @param epNumber endpoint number
* @param isEphshkSet needs handshake or not
*/
static inline void usb_hal_khci_endpoint_enable_handshake(uint32_t instance, uint32_t epNumber, uint32_t isEphshkSet)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB_ENDPT_REG(USB0_BASE_PTR, (uint8_t)epNumber) |= ((isEphshkSet == 1) ? USB_ENDPT_EPHSHK_MASK : 0);
	
}

/*!
* @brief Set the endpoint in host mode which in TX or RX
* 
* @param instance usb instance id
* @param epNumber endpoint number
* @param isEptxenSet in TX or RX
*/
static inline void usb_hal_khci_endpoint_set_direction(uint32_t instance, uint32_t epNumber, uint8_t isEptxenSet)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB_ENDPT_REG(USB0_BASE_PTR, (uint8_t)epNumber) |= ((isEptxenSet == 1) ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK);
}

/*!
* @brief Clear the stall status of the endpoint
* 
* @param instance usb instance id
* @param epNumber endpoint number
*/
static inline void usb_hal_khci_endpoint_clr_stall(uint32_t instance, uint32_t epNumber)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB_ENDPT_REG(USB0_BASE_PTR, (uint8_t)epNumber) &= ~USB_ENDPT_EPSTALL_MASK;

}

/*!
* @brief Enable the support for low speed
* @param instance usb instance id
*/
static inline void usb_hal_khci_enable_low_speed_support(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ADDR |= USB_ADDR_LSEN_MASK;
}


/*!
* @brief Disable the support for low speed
* @param instance usb instance id
*/
static inline void usb_hal_khci_disable_low_speed_support(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_ADDR &= ~USB_ADDR_LSEN_MASK;
}


/*!
* @brief Enable the pull down
* 
* @param instance usb instance id
*/
static inline void usb_hal_khci_enable_pull_down(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CONTROL |= USB_USBCTRL_PDE_MASK;
}


/*!
* @brief Disable the pull down
* 
* @param instance usb instance id
*/
static inline void usb_hal_khci_disable_pull_down(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CONTROL &= ~USB_USBCTRL_PDE_MASK;
}


/*!
* @brief Enable the pull up
* @param instance usb instance id
*/
static inline void usb_hal_khci_enable_pull_up(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_OTGCTL = USB_OTGCTL_DPHIGH_MASK |  USB_OTGCTL_OTGEN_MASK |USB_OTGCTL_DMLOW_MASK |USB_OTGCTL_DPLOW_MASK;
}

/*!
* @brief Disable the pull up
* @param instance usb instance id
*/
static inline void usb_hal_khci_disable_pull_up(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_OTGCTL &= ~(USB_OTGCTL_DPHIGH_MASK |  USB_OTGCTL_OTGEN_MASK |USB_OTGCTL_DMLOW_MASK |USB_OTGCTL_DPLOW_MASK);
}

/*!
* @brief Set the controller to the suspend state
* @param instance usb instance id
*/
static inline void usb_hal_khci_set_suspend(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CONTROL |= USB_USBCTRL_SUSP_MASK;
}


/*!
* @brief Clear the suspend state of the controller
* @param instance usb instance id
*/
static inline void usb_hal_khci_clr_suspend(uint32_t instance)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_CONTROL &= ~USB_USBCTRL_SUSP_MASK;
}

/*!
* @brief Set the sof threshold
* @param instance usb instance id
* @param value value used to set
*/
static inline void usb_hal_khci_set_sof_theshold(uint32_t instance, uint32_t value)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_SOFTHLD = (uint8_t)value;
}

static inline void usb_hal_khci_set_target_token(uint32_t instance, uint8_t token, uint8_t endpoint_number)
{
	//assert(instance < HW_USB_INSTANCE_COUNT);
	USB0_TOKEN = (uint8_t)(USB_TOKEN_TOKENENDPT(endpoint_number) | token);
}



#endif

#endif
