/*******************************************************************************
 * (c) Copyright 2012-2014 Microsemi SoC Products Group. All rights reserved.
 *
 *   Microsemi Smartfusion2 MSS USB Driver Stack
 *      USB Core Interface Layer (USB-CIFL)
 *          USBH-CIF
 *
 *
 *  This file provides interfaces to perform register and register bit level
 *  read / write operations in USB Host mode.
 *
 *
 * SVN $Revision: 6145 $
 * SVN $Date: 2014-02-18 19:11:44 +0530 (Tue, 18 Feb 2014) $
 */

#ifndef __MSS_USB_HOST_REG_IO_H_
#define __MSS_USB_HOST_REG_IO_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "../../CMSIS/m2sxxx.h"
#include "mss_usb_core_regs.h"

/*******************************************************************************
* Host Mode Functions
*/



/*******************************************************************************
 * CSR0L register related APIs
 */
static __INLINE uint8_t
MSS_USB_HCIF_cep_is_rxstall_err
(
    void
)
{
    return (((USB->ENDPOINT[MSS_USB_CEP].TX_CSR & CSR0L_HOST_STALL_RCVD_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_cep_clr_rxstall_err
(
    void
)
{
    USB->ENDPOINT[MSS_USB_CEP].TX_CSR &= ~CSR0L_HOST_STALL_RCVD_MASK;
}

static __INLINE uint8_t
MSS_USB_HCIF_cep_is_retry_err
(
    void
)
{
    return (((USB->ENDPOINT[MSS_USB_CEP].TX_CSR & CSR0L_HOST_RETRY_ERR_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_cep_clr_retry_err
(
    void
)
{
    USB->ENDPOINT[MSS_USB_CEP].TX_CSR &= ~CSR0L_HOST_RETRY_ERR_MASK;
}

static __INLINE void
MSS_USB_HCIF_cep_clr_csr_reg
(
    void
)
{
    USB->ENDPOINT[MSS_USB_CEP].TX_CSR = 0x0000u;
}

static __INLINE uint8_t
MSS_USB_HCIF_cep_is_naktimeout_err
(
    void
)
{
    return (((USB->ENDPOINT[MSS_USB_CEP].TX_CSR & CSR0L_HOST_NAK_TIMEOUT_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_cep_clr_naktimeout_err
(
    void
)
{
    USB->ENDPOINT[MSS_USB_CEP].TX_CSR &= ~CSR0L_HOST_NAK_TIMEOUT_MASK;
}

/*******************************************************************************
 * CSR0H register related APIs
 */
static __INLINE void
MSS_USB_HCIF_cep_flush_fifo
(
    mss_usb_ep_num_t ep_num
)
{
    /*shoud be set when TxPktRdy/RxPktRdy is set*/
    if((USB->ENDPOINT[ep_num].TX_CSR) & (TxCSRL_HOST_EPN_TX_PKT_RDY_MASK |
                                          CSR0L_HOST_RX_PKT_RDY_MASK))
        USB->ENDPOINT[MSS_USB_CEP].TX_CSR |= CSR0H_HOST_FLUSH_FIFO_MASK;
}

static __INLINE uint8_t
MSS_USB_HCIF_cep_is_data_tog
(
    void
)
{
    return (((USB->ENDPOINT[MSS_USB_CEP].TX_CSR & CSR0H_HOST_DATA_TOG_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_cep_disable_ping
(
    void
)
{
    USB->ENDPOINT[MSS_USB_CEP].TX_CSR |= CSR0H_HOST_DISABLE_PING_MASK;
}

static __INLINE void
MSS_USB_HCIF_cep_enable_ping
(
    void
)
{
    USB->ENDPOINT[MSS_USB_CEP].TX_CSR &= ~CSR0H_HOST_DISABLE_PING_MASK;
}

/*******************************************************************************
 * NAKLIMIT0 register related APIs
 */
static __INLINE void
MSS_USB_HCIF_cep_set_naklimit
(
    uint8_t naklimit
)
{
    if((2u >= naklimit) && (naklimit <= 16u))
    {
        USB->ENDPOINT[MSS_USB_CEP].TX_INTERVAL = naklimit;
    }
}

/*******************************************************************************
* ENDOF - Host mode functions
*/

/*TXMAXP is common to host and device*/
/*******************************************************************************
 * TXCSRL register related APIs
 */

static __INLINE void MSS_USB_HCIF_tx_ep_set_txpktrdy(mss_usb_ep_num_t ep_num)
{
    USB->ENDPOINT[ep_num].TX_CSR |= TxCSRL_HOST_EPN_TX_PKT_RDY_MASK;
}

static __INLINE uint8_t
MSS_USB_HCIF_tx_ep_is_txpktrdy
(
    mss_usb_ep_num_t ep_num
)
{
    return (((USB->ENDPOINT[ep_num].TX_CSR & TxCSRL_HOST_EPN_TX_PKT_RDY_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE uint8_t
MSS_USB_HCIF_tx_ep_is_fifo_ne
(
    mss_usb_ep_num_t ep_num
)
{
    return (((USB->ENDPOINT[ep_num].TX_CSR & TxCSRL_HOST_EPN_TX_FIFO_NE_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE uint8_t
MSS_USB_HCIF_tx_ep_is_retry_err
(
    mss_usb_ep_num_t ep_num
)
{
    return (((USB->ENDPOINT[ep_num].TX_CSR & TxCSRL_HOST_EPN_RESPONSE_ERR_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_tx_ep_clr_retry_err
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR &= ~TxCSRL_HOST_EPN_RESPONSE_ERR_MASK;
}

static __INLINE void
MSS_USB_HCIF_tx_ep_flush_fifo_reg
(
    mss_usb_ep_num_t ep_num
)
{
    if(MSS_USB_HCIF_tx_ep_is_txpktrdy(ep_num))
    {
        USB->ENDPOINT[ep_num].TX_CSR |= TxCSRL_HOST_EPN_FLUSH_FIFO_MASK;
    }
}

static __INLINE uint8_t
MSS_USB_HCIF_tx_ep_is_rxstall_err
(
    mss_usb_ep_num_t ep_num
)
{
    return (((USB->ENDPOINT[ep_num].TX_CSR & TxCSRL_HOST_EPN_STALL_RCVD_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_tx_ep_clr_rxstall_err
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR &= ~TxCSRL_HOST_EPN_STALL_RCVD_MASK;
}

static __INLINE void
MSS_USB_HCIF_tx_ep_clr_data_tog
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR |= TxCSRL_HOST_EPN_CLR_DATA_TOG_MASK;
}


static __INLINE uint8_t
MSS_USB_HCIF_tx_ep_is_naktimeout_err
(
    mss_usb_ep_num_t ep_num
)
{
    return (((USB->ENDPOINT[ep_num].TX_CSR & TxCSRL_HOST_EPN_NAK_TIMEOUT_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_tx_ep_clr_naktimeout_err
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR &= ~TxCSRL_HOST_EPN_NAK_TIMEOUT_MASK ;
}

/*******************************************************************************
 * TXCSRH register related APIs
 */

static __INLINE uint8_t
MSS_USB_HCIF_tx_ep_is_data_tog
(
    mss_usb_ep_num_t ep_num
)
{
    return (((USB->ENDPOINT[ep_num].TX_CSR & TxCSRH_HOST_EPN_DATA_TOG_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_tx_ep_write_data_tog
(
    mss_usb_ep_num_t ep_num,
    uint32_t data_tog
)
{
    /*data_tog has to be 0 or 1*/
    USB->ENDPOINT[ep_num].TX_CSR = data_tog & 0x00000001;
}

static __INLINE void
MSS_USB_HCIF_tx_ep_set_data_tog_we
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR |= TxCSRH_HOST_EPN_DATA_TOG_WE_MASK;
}

static __INLINE void
MSS_USB_HCIF_tx_ep_clr_data_tog_we
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR &= ~TxCSRH_HOST_EPN_DATA_TOG_WE_MASK;
}

static __INLINE void
MSS_USB_HCIF_tx_ep_set_dma_mode1
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR |= TxCSRH_HOST_EPN_DMA_MODE_MASK;
}

static __INLINE void
MSS_USB_HCIF_tx_ep_set_dma_mode0
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR &= ~TxCSRH_HOST_EPN_DMA_MODE_MASK;
}

static __INLINE uint8_t
MSS_USB_HCIF_tx_ep_get_dma_mode
(
    mss_usb_ep_num_t ep_num
)
{
    return (((USB->ENDPOINT[ep_num].TX_CSR & TxCSRH_HOST_EPN_DMA_MODE_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_tx_ep_set_force_data_tog
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR |= TxCSRH_HOST_EPN_FRC_DATA_TOG_MASK;
}

static __INLINE void
MSS_USB_HCIF_tx_ep_clr_force_data_tog
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR &= ~TxCSRH_HOST_EPN_FRC_DATA_TOG_MASK;
}

static __INLINE void
MSS_USB_HCIF_tx_ep_enable_dma
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR |= TxCSRH_HOST_EPN_ENABLE_DMA_MASK;
}

static __INLINE void
MSS_USB_HCIF_tx_ep_disable_dma
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR &= ~TxCSRH_HOST_EPN_ENABLE_DMA_MASK;
}

static __INLINE uint8_t
MSS_USB_HCIF_tx_ep_is_dma_enabled
(
    mss_usb_ep_num_t ep_num
)
{
    return (((USB->ENDPOINT[ep_num].TX_CSR & TxCSRH_HOST_EPN_ENABLE_DMA_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_tx_ep_set_autoset
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR |= TxCSRH_HOST_EPN_ENABLE_AUTOSET_MASK;
}
static __INLINE void
MSS_USB_HCIF_tx_ep_clr_autoset
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].TX_CSR &= ~TxCSRH_HOST_EPN_ENABLE_AUTOSET_MASK;
}

static __INLINE uint8_t
MSS_USB_HCIF_tx_ep_is_autoset
(
    mss_usb_ep_num_t ep_num
)
{
    return (((USB->ENDPOINT[ep_num].TX_CSR & TxCSRH_HOST_EPN_ENABLE_AUTOSET_MASK) ?
                                    MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

/*******************************************************************************
 * RXCSRL register related APIs
 */
static __INLINE uint8_t
MSS_USB_HCIF_rx_ep_is_rxpktrdy
(
    mss_usb_ep_num_t ep_num
)
{
    return(((USB->ENDPOINT[ep_num].RX_CSR & RXCSRL_HOST_EPN_RX_PKT_RDY_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE uint8_t
MSS_USB_HCIF_rx_ep_is_fifo_full
(
    mss_usb_ep_num_t ep_num
)
{
    return(((USB->ENDPOINT[ep_num].RX_CSR & RXCSRL_HOST_EPN_RX_FIFO_FULL_MASK) ?
                                    MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE uint8_t
MSS_USB_HCIF_rx_ep_is_retry_err
(
    mss_usb_ep_num_t ep_num
)
{
    return(((USB->ENDPOINT[ep_num].RX_CSR & RXCSRL_HOST_EPN_RESPONSE_ERR_MASK) ?
                                    MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_rx_ep_clr_retry_err
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR &= ~RXCSRL_HOST_EPN_RESPONSE_ERR_MASK;
}

static __INLINE uint8_t
MSS_USB_HCIF_rx_ep_is_naktimeout_err
(
    mss_usb_ep_num_t ep_num
)
{
    return(((USB->ENDPOINT[ep_num].RX_CSR & RXCSRL_HOST_EPN_NAK_TIMEOUT_ERR_MASK) ?
                                    MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_rx_ep_clr_naktimeout_err
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR &= ~RXCSRL_HOST_EPN_NAK_TIMEOUT_ERR_MASK;
}

static __INLINE void
MSS_USB_HCIF_rx_ep_flush_fifo_reg
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR |= RXCSRL_HOST_EPN_FLUSH_FIFO_MASK;
}

static __INLINE uint8_t
MSS_USB_HCIF_rx_ep_is_rxstall_err
(
    mss_usb_ep_num_t ep_num
)
{
    return(((USB->ENDPOINT[ep_num].RX_CSR & RXCSRL_HOST_EPN_STALL_RCVD_MASK) ?
                                    MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_rx_ep_clr_rxstall_err
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR &= ~RXCSRL_HOST_EPN_STALL_RCVD_MASK;
}

static __INLINE void
MSS_USB_HCIF_rx_ep_clr_data_tog
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR |= RXCSRL_HOST_EPN_CLR_DATA_TOG_MASK;
}

/*******************************************************************************
 * RXCSRH register related APIs
 */
static __INLINE uint8_t
MSS_USB_HCIF_rx_ep_is_iso_incomp
(
    mss_usb_ep_num_t ep_num
)
{
    return(((USB->ENDPOINT[ep_num].RX_CSR & RXCSRH_HOST_EPN_RX_ISO_INCOMP) ?
                            MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE uint8_t
MSS_USB_HCIF_rx_ep_is_data_tog
(
    mss_usb_ep_num_t ep_num
)
{
    return(((USB->ENDPOINT[ep_num].RX_CSR & RXCSRH_HOST_EPN_DATA_TOG_MASK) ?
                            MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_rx_ep_write_data_tog
(
    mss_usb_ep_num_t ep_num,
    uint32_t data_tog
)
{
    USB->ENDPOINT[ep_num].RX_CSR = data_tog;
}

static __INLINE void
MSS_USB_HCIF_rx_ep_set_data_tog_we
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR |= RXCSRH_HOST_EPN_DATA_TOG_WE_MASK;
}

static __INLINE void
MSS_USB_HCIF_rx_ep_clr_data_tog_we
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR &= ~RXCSRH_HOST_EPN_DATA_TOG_WE_MASK;
}

static __INLINE mss_usb_dma_mode_t
MSS_USB_HCIF_rx_ep_get_dma_mode
(
    mss_usb_ep_num_t ep_num
)
{
    return(((USB->ENDPOINT[ep_num].RX_CSR & RXCSRH_HOST_EPN_DMA_MODE_MASK) ?
                                    MSS_USB_DMA_MODE1 : MSS_USB_DMA_MODE0));
}

static __INLINE void
MSS_USB_HCIF_rx_ep_set_dma_mode1
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR |= RXCSRH_HOST_EPN_DMA_MODE_MASK;
}

static __INLINE void
MSS_USB_HCIF_rx_ep_set_dma_mode0
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR &= ~RXCSRH_HOST_EPN_DMA_MODE_MASK;
}

static __INLINE void
MSS_USB_HCIF_rx_ep_enable_dma
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR |= RXCSRH_HOST_EPN_ENABLE_DMA_MASK;
}

static __INLINE void
MSS_USB_HCIF_rx_ep_disable_dma
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR &= ~RXCSRH_HOST_EPN_ENABLE_DMA_MASK;
}

static __INLINE uint8_t
MSS_USB_HCIF_rx_ep_is_dma_enabled
(
    mss_usb_ep_num_t ep_num
)
{
    return(((USB->ENDPOINT[ep_num].RX_CSR & RXCSRH_HOST_EPN_ENABLE_DMA_MASK) ?
                                MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

static __INLINE void
MSS_USB_HCIF_rx_ep_set_autoreq
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR |= RXCSRH_HOST_EPN_ENABLE_AUTOREQ_MASK;
}

static __INLINE void
MSS_USB_HCIF_rx_ep_set_autoclr
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR |= RXCSRH_HOST_EPN_ENABLE_AUTOCLR_MASK;
}

static __INLINE void
MSS_USB_HCIF_rx_ep_clr_autoclr
(
    mss_usb_ep_num_t ep_num
)
{
    USB->ENDPOINT[ep_num].RX_CSR &= ~RXCSRH_HOST_EPN_ENABLE_AUTOCLR_MASK;
}

static __INLINE uint8_t
MSS_USB_HCIF_rx_ep_is_autoclr
(
    mss_usb_ep_num_t ep_num
)
{
    return(((USB->ENDPOINT[ep_num].RX_CSR & RXCSRH_HOST_EPN_ENABLE_AUTOCLR_MASK) ?
                                    MSS_USB_BOOLEAN_TRUE : MSS_USB_BOOLEAN_FALSE));
}

/*******************************************************************************
 * TXTYPE register related APIs
 */
static __INLINE void
MSS_USB_HCIF_tx_ep_set_target_speed
(
    mss_usb_ep_num_t ep_num,
    mss_usb_device_speed_t speed
)
{
    USB->ENDPOINT[ep_num].TX_TYPE &= ~TXTYPE_HOST_TARGET_EP_SPEED_MASK;
    USB->ENDPOINT[ep_num].TX_TYPE |= (speed << TXTYPE_HOST_TARGET_EP_SPEED_SHIFT);
}

static __INLINE mss_usb_device_speed_t
MSS_USB_HCIF_tx_ep_get_target_speed
(
    mss_usb_ep_num_t ep_num
)
{
    return ((mss_usb_device_speed_t)((USB->ENDPOINT[ep_num].TX_TYPE & TXTYPE_HOST_TARGET_EP_SPEED_MASK)
                                                                    >> TXTYPE_HOST_TARGET_EP_SPEED_SHIFT));
}

static __INLINE void
MSS_USB_HCIF_tx_ep_set_target_protocol
(
    mss_usb_ep_num_t ep_num,
    mss_usb_xfr_type_t xfr_type
)
{
    USB->ENDPOINT[ep_num].TX_TYPE &= ~TXTYPE_HOST_TARGET_EP_PROTOCOL_MASK;
    USB->ENDPOINT[ep_num].TX_TYPE |= (xfr_type << TXTYPE_HOST_TARGET_EP_PROTOCOL_SHIFT);
}

static __INLINE mss_usb_xfr_type_t
MSS_USB_HCIF_tx_ep_get_target_protocol
(
    mss_usb_ep_num_t ep_num
)
{
    return ((mss_usb_xfr_type_t)((USB->ENDPOINT[ep_num].TX_TYPE & TXTYPE_HOST_TARGET_EP_PROTOCOL_MASK)
                                                                >> TXTYPE_HOST_TARGET_EP_PROTOCOL_SHIFT));
}

static __INLINE void
MSS_USB_HCIF_tx_ep_set_target_ep_no
(
    mss_usb_ep_num_t ep_num,
    uint8_t tdev_ep_num
)
{
    USB->ENDPOINT[ep_num].TX_TYPE &= ~TXTYPE_HOST_TARGET_EP_NUM_MASK;
    USB->ENDPOINT[ep_num].TX_TYPE |= (tdev_ep_num << TXTYPE_HOST_TARGET_EP_NUM_SHIFT);
}

static __INLINE uint8_t
MSS_USB_HCIF_tx_ep_get_target_ep_no
(
    mss_usb_ep_num_t ep_num
)
{
    return ((mss_usb_ep_num_t)((USB->ENDPOINT[ep_num].TX_TYPE & TXTYPE_HOST_TARGET_EP_NUM_MASK)
                                                                >> TXTYPE_HOST_TARGET_EP_NUM_SHIFT));
}

/*******************************************************************************
 * TXINTERVAL register related APIs
 */
static __INLINE void
MSS_USB_HCIF_tx_ep_set_target_interval
(
    mss_usb_ep_num_t ep_num,
    uint8_t interval
)
{
    /*
      meaning of the value dependes on Speed and transfer type.
      HCIF driver should take care of this.
    */
    if((2u >= interval) && (interval <= 16u))
    {
        USB->ENDPOINT[ep_num].TX_INTERVAL = interval;
    }
}

/*******************************************************************************
 * RXTYPE register related APIs
 */
static __INLINE void
MSS_USB_HCIF_rx_ep_set_target_speed
(
    mss_usb_ep_num_t ep_num,
    mss_usb_device_speed_t speed
)
{
    USB->ENDPOINT[ep_num].RX_TYPE &= ~RXTYPE_HOST_TARGET_EP_SPEED_MASK;
    USB->ENDPOINT[ep_num].RX_TYPE |= (speed << RXTYPE_HOST_TARGET_EP_SPEED_SHIFT);
}

static __INLINE mss_usb_device_speed_t
MSS_USB_HCIF_rx_ep_get_target_speed
(
    mss_usb_ep_num_t ep_num
)
{
    return ((mss_usb_device_speed_t)((USB->ENDPOINT[ep_num].RX_TYPE & RXTYPE_HOST_TARGET_EP_SPEED_MASK)
                                                                    >> RXTYPE_HOST_TARGET_EP_SPEED_SHIFT));
}

static __INLINE void
MSS_USB_HCIF_rx_ep_set_target_protocol
(
    mss_usb_ep_num_t ep_num,
    mss_usb_xfr_type_t xfr_type
)
{
    USB->ENDPOINT[ep_num].RX_TYPE &= ~RXTYPE_HOST_TARGET_EP_PROTOCOL_MASK;
    USB->ENDPOINT[ep_num].RX_TYPE |= (xfr_type << RXTYPE_HOST_TARGET_EP_PROTOCOL_SHIFT);
}

static __INLINE mss_usb_xfr_type_t
MSS_USB_HCIF_rx_ep_get_target_protocol
(
    mss_usb_ep_num_t ep_num
)
{
    return ((mss_usb_xfr_type_t)((USB->ENDPOINT[ep_num].RX_TYPE & RXTYPE_HOST_TARGET_EP_PROTOCOL_MASK)
                                                                >> RXTYPE_HOST_TARGET_EP_PROTOCOL_SHIFT));
}

static __INLINE void
MSS_USB_HCIF_rx_ep_set_target_ep_no
(
    mss_usb_ep_num_t ep_num,
    uint8_t tdev_ep_num
)
{
    USB->ENDPOINT[ep_num].RX_TYPE &= ~RXTYPE_HOST_TARGET_EP_NUM_MASK;
    USB->ENDPOINT[ep_num].RX_TYPE |= (tdev_ep_num << RXTYPE_HOST_TARGET_EP_NUM_SHIFT);
}

static __INLINE uint8_t
MSS_USB_HCIF_rx_ep_get_target_ep_no
(
    mss_usb_ep_num_t ep_num
)
{
    return ((mss_usb_ep_num_t)((USB->ENDPOINT[ep_num].RX_TYPE & RXTYPE_HOST_TARGET_EP_NUM_MASK)
                                                            >> RXTYPE_HOST_TARGET_EP_NUM_SHIFT));
}

/*******************************************************************************
 * RXINTERVAL register related APIs
 */
static __INLINE void
MSS_USB_HCIF_rx_ep_set_target_interval
(
    mss_usb_ep_num_t ep_num,
    uint8_t interval
)
{
    /*
     meaning of the value dependes on Speed and transfer type.
     HCIF driver should take care of this.
    */
    if((2u >= interval) && (interval <= 16u))
    {
        USB->ENDPOINT[ep_num].RX_INTERVAL = interval;
    }
}

/*******************************************************************************
 * REQPKTCOUNT register related APIs
 */
static __INLINE void
MSS_USB_HCIF_rx_ep_set_req_pkt_count
(
    mss_usb_ep_num_t ep_num,
    uint32_t count
)
{
    /*
    Used with AUTOREQ option.
    Multiple packets combined into a single bulk  packet within the FIFO count as one packet.
    */
    USB->RQ_PKT_CNT[ep_num] = count;
}

/*******************************************************************************
 * RXFUNCADDR register related APIs
 */
static __INLINE void
MSS_USB_HCIF_rx_ep_set_target_func_addr
(
    mss_usb_ep_num_t ep_num,
    uint32_t addr
)
{
    /*Device number of the target - initially zero, then determeined by enumeration process.*/
    USB->TAR[ep_num].RX_FUNC_ADDR = (addr & 0x7Fu);
}

/*******************************************************************************
 * TXHUBADDR register related APIs
 */
static __INLINE void
MSS_USB_HCIF_tx_ep_set_target_hub_addr
(
    mss_usb_ep_num_t ep_num,
    uint32_t addr,
    uint32_t mtt
)
{
    /*Device number of the target - initially zero, then determeined by enumeration process.*/
    USB->TAR[ep_num].TX_HUB_ADDR = ((uint8_t)(mtt << TARGET_DEVICE_HUB_MT_SHIFT) | (addr & 0x7Fu));
}

/*******************************************************************************
 * RXHUBADDR register related APIs
 */
static __INLINE void
MSS_USB_HCIF_rx_ep_set_target_hub_addr
(
    mss_usb_ep_num_t ep_num,
    uint32_t addr,
    uint32_t mtt
)
{
    /*Device number of the target - initially zero, then determeined by enumeration process.*/
    USB->TAR[ep_num].RX_HUB_ADDR = ((uint8_t)(mtt << TARGET_DEVICE_HUB_MT_SHIFT) | (addr & 0x7Fu));
}

/*******************************************************************************
 * TXHUBADDR register related APIs
 */
static __INLINE void
MSS_USB_HCIF_tx_ep_set_target_hub_port
(
    mss_usb_ep_num_t ep_num,
    uint32_t port_no
)
{
    /*for FS/LS devices only*/
    USB->TAR[ep_num].TX_HUB_PORT = (port_no & 0xFFu);
}

/*******************************************************************************
 * RXHUBADDR register related APIs
 */
static __INLINE void
MSS_USB_HCIF_rx_ep_set_target_hub_port
(
    mss_usb_ep_num_t ep_num,
    uint32_t port_no
)
{
    /*for FS/LS devices only*/
    USB->TAR[ep_num].RX_HUB_PORT = (port_no & 0xFFu);
}

/*Trailing zeros*/
static __INLINE uint32_t
MSS_USB_HCIF_ctz
(
    uint32_t number
)
{
    uint32_t c = 32u;
    number &= -(int32_t)(number);
    if (number) c--;
    if (number & 0x0000FFFF) c -= 16;
    if (number & 0x00FF00FF) c -= 8;
    if (number & 0x0F0F0F0F) c -= 4;
    if (number & 0x33333333) c -= 2;
    if (number & 0x55555555) c -= 1;

    return c;
}


#ifdef __cplusplus
}
#endif

#endif  /* __MSS_USB_HOST_REG_IO_H_ */
