4069 lines
169 KiB
C
4069 lines
169 KiB
C
/*
|
|
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
|
* Copyright 2016 - 2019 NXP
|
|
* All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "usb_host_config.h"
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS > 0U))
|
|
#include "usb_host.h"
|
|
#include "usb_host_hci.h"
|
|
#include "fsl_device_registers.h"
|
|
#include "usb_host_ip3516hs.h"
|
|
#include "usb_host_devices.h"
|
|
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
|
|
#include "usb_phy.h"
|
|
#endif
|
|
#if (defined(USB_HOST_CONFIG_BATTERY_CHARGER) && (USB_HOST_CONFIG_BATTERY_CHARGER > 0U)) && \
|
|
((defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U)))
|
|
#include "usb_hsdcd.h"
|
|
#endif
|
|
#if ((USB_HOST_CONFIG_IP3516HS_MAX_ISO >= 256) || (USB_HOST_CONFIG_IP3516HS_MAX_INT >= 256) || \
|
|
(USB_HOST_CONFIG_IP3516HS_MAX_ATL >= 256))
|
|
#error "This driver doesn't support same type pipe exceed 255."
|
|
#endif
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
|
|
#define USB_HOST_IP3516HS_TEST_DESCRIPTOR_LENGTH (18U)
|
|
#define USB_HOST_IP3516HS_PORTSC_PTC_J_STATE (0x01U)
|
|
#define USB_HOST_IP3516HS_PORTSC_PTC_K_STATE (0x02U)
|
|
#define USB_HOST_IP3516HS_PORTSC_PTC_SE0_NAK (0x03U)
|
|
#define USB_HOST_IP3516HS_PORTSC_PTC_PACKET (0x04U)
|
|
#define USB_HOST_IP3516HS_PORTSC_PTC_FORCE_ENABLE (0x05U)
|
|
#endif
|
|
/* reset recovery time (ms) */
|
|
#define USB_HOST_IP3516HS_PORT_RESET_RECOVERY_DELAY (11U)
|
|
/*******************************************************************************
|
|
* Prototypes
|
|
******************************************************************************/
|
|
static usb_status_t USB_HostIp3516HsGetBuffer(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
uint32_t length,
|
|
uint32_t MaxPacketSize,
|
|
uint32_t *index,
|
|
uint32_t *bufferLength);
|
|
static usb_status_t USB_HostIp3516HsFreeBuffer(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
uint32_t index,
|
|
uint32_t bufferLength);
|
|
|
|
#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
|
|
/*!
|
|
* @brief suspend bus.
|
|
*
|
|
* @param usbHostState ip3516hs instance pointer.
|
|
*/
|
|
static void USB_HostIp3516HsSuspendBus(usb_host_ip3516hs_state_struct_t *usbHostState);
|
|
|
|
/*!
|
|
* @brief resume bus.
|
|
*
|
|
* @param usbHostState ip3516hs instance pointer.
|
|
*/
|
|
static void USB_HostIp3516HsResumeBus(usb_host_ip3516hs_state_struct_t *usbHostState);
|
|
|
|
extern usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance,
|
|
usb_host_transfer_t *transfer,
|
|
void *param);
|
|
|
|
static void USB_HostIp3516HsDelay(usb_host_ip3516hs_state_struct_t *usbHostState, uint32_t ms);
|
|
static void USB_HostIp3516HsTestModeInit(usb_device_handle deviceHandle);
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
USB_GLOBAL_DEDICATED_RAM USB_RAM_ADDRESS_ALIGNMENT(1024) static usb_host_ip3516hs_ptd_struct_t
|
|
s_UsbHostIp3516HsPtd[USB_HOST_CONFIG_IP3516HS];
|
|
static usb_host_ip3516hs_state_struct_t s_UsbHostIp3516HsState[USB_HOST_CONFIG_IP3516HS];
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U)) || \
|
|
(defined(USB_HOST_CONFIG_IP3516HS_MAX_INT) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
static uint8_t s_SlotMaxBandwidth[8] = {125, 125, 125, 125, 125, 125, 50, 0};
|
|
#endif
|
|
USB_GLOBAL_DEDICATED_RAM static uint8_t s_UsbHostIp3516HsBufferArray[80][64];
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
|
|
static usb_status_t USB_HostIp3516HsTestSetMode(usb_host_ip3516hs_state_struct_t *usbHostState, uint32_t testMode)
|
|
{
|
|
uint32_t Ip3516HsortSC;
|
|
|
|
Ip3516HsortSC = usbHostState->usbRegBase->PORTSC1;
|
|
Ip3516HsortSC &= ~((uint32_t)USBHSH_PORTSC1_PTC_MASK); /* clear test mode bits */
|
|
Ip3516HsortSC |= (testMode << USBHSH_PORTSC1_PTC_SHIFT); /* set test mode bits */
|
|
usbHostState->usbRegBase->PORTSC1 = Ip3516HsortSC;
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
static void USB_HostIp3516HsTestSuspendResume(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
uint8_t timeCount;
|
|
timeCount = 15U * 8U; /* 15s */
|
|
while (0U != (timeCount--))
|
|
{
|
|
USB_HostIp3516HsDelay(usbHostState, 1000U);
|
|
}
|
|
USB_HostIp3516HsSuspendBus(usbHostState);
|
|
timeCount = 15U * 8U; /* 15s */
|
|
while (0U != (timeCount--))
|
|
{
|
|
USB_HostIp3516HsDelay(usbHostState, 1000U);
|
|
}
|
|
|
|
USB_HostIp3516HsResumeBus(usbHostState);
|
|
}
|
|
|
|
static void USB_HostIp3516HsTestCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
|
|
{
|
|
(void)USB_HostFreeTransfer(param, transfer);
|
|
usb_host_ip3516hs_state_struct_t *usbHostState = (usb_host_ip3516hs_state_struct_t *)param;
|
|
if (1U == usbHostState->complianceTestStart)
|
|
{
|
|
uint8_t timeCount;
|
|
usbHostState->complianceTest = 0U;
|
|
usbHostState->complianceTestStart = 0U;
|
|
timeCount = 15U * 8U; /* 15s */
|
|
while (0U != (timeCount--))
|
|
{
|
|
USB_HostIp3516HsDelay(usbHostState, 1000U);
|
|
}
|
|
(void)usb_echo("test_single_step_get_dev_desc_data finished\r\n");
|
|
}
|
|
}
|
|
|
|
static void USB_HostIp3516HsTestSingleStepGetDeviceDesc(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_device_handle deviceHandle)
|
|
{
|
|
usb_host_process_descriptor_param_t getDescriptorParam;
|
|
usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
|
|
usb_host_transfer_t *transfer;
|
|
uint8_t timeCount;
|
|
|
|
/* disable periodic shedule */
|
|
usbHostState->usbRegBase->USBCMD &= ~(USB_HOST_IP3516HS_USBCMD_INT_EN_MASK | USB_HOST_IP3516HS_USBCMD_ISO_EN_MASK);
|
|
|
|
timeCount = 15U * 8U; /* 15s */
|
|
while (0U != (timeCount--))
|
|
{
|
|
USB_HostIp3516HsDelay(usbHostState, 1000U);
|
|
}
|
|
|
|
/* malloc one transfer */
|
|
if (USB_HostMallocTransfer(usbHostState->hostHandle, &transfer) != kStatus_USB_Success)
|
|
{
|
|
#ifdef HOST_ECHO
|
|
usb_echo("allocate transfer error\r\n");
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
getDescriptorParam.descriptorLength = sizeof(usb_descriptor_device_t);
|
|
getDescriptorParam.descriptorLength = 18;
|
|
getDescriptorParam.descriptorBuffer = (uint8_t *)&deviceInstance->deviceDescriptor;
|
|
getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_DEVICE;
|
|
getDescriptorParam.descriptorIndex = 0;
|
|
getDescriptorParam.languageId = 0;
|
|
transfer->callbackFn = USB_HostIp3516HsTestCallback;
|
|
transfer->callbackParam = usbHostState->hostHandle;
|
|
transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_DIR_IN;
|
|
transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
|
|
transfer->setupPacket->wIndex = 0;
|
|
transfer->setupPacket->wLength = 0;
|
|
transfer->setupPacket->wValue = 0;
|
|
(void)USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
|
|
}
|
|
|
|
static void USB_HostIp3516HsTestSingleStepGetDeviceDescData(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_device_handle deviceHandle)
|
|
{
|
|
static uint8_t buffer[USB_HOST_IP3516HS_TEST_DESCRIPTOR_LENGTH];
|
|
|
|
usb_host_process_descriptor_param_t getDescriptorParam;
|
|
usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
|
|
usb_host_transfer_t *transfer;
|
|
|
|
/* disable periodic shedule */
|
|
usbHostState->usbRegBase->USBCMD &= ~(USB_HOST_IP3516HS_USBCMD_INT_EN_MASK | USB_HOST_IP3516HS_USBCMD_ISO_EN_MASK);
|
|
|
|
/* malloc one transfer */
|
|
if (USB_HostMallocTransfer(usbHostState->hostHandle, &transfer) != kStatus_USB_Success)
|
|
{
|
|
#ifdef HOST_ECHO
|
|
usb_echo("allocate transfer error\r\n");
|
|
#endif
|
|
return;
|
|
}
|
|
usbHostState->complianceTestStart = 1;
|
|
getDescriptorParam.descriptorLength = sizeof(usb_descriptor_device_t);
|
|
getDescriptorParam.descriptorLength = 18;
|
|
getDescriptorParam.descriptorBuffer = (uint8_t *)buffer;
|
|
getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_DEVICE;
|
|
getDescriptorParam.descriptorIndex = 0;
|
|
getDescriptorParam.languageId = 0;
|
|
transfer->callbackFn = USB_HostIp3516HsTestCallback;
|
|
transfer->callbackParam = (void *)usbHostState;
|
|
transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_DIR_IN;
|
|
transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
|
|
transfer->setupPacket->wIndex = 0;
|
|
transfer->setupPacket->wLength = 0;
|
|
transfer->setupPacket->wValue = 0;
|
|
(void)USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
|
|
|
|
return;
|
|
}
|
|
|
|
static void USB_HostIp3516HsTestModeInit(usb_device_handle deviceHandle)
|
|
{
|
|
uint32_t productId;
|
|
usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
|
|
usb_host_ip3516hs_state_struct_t *usbHostState =
|
|
(usb_host_ip3516hs_state_struct_t *)(((usb_host_instance_t *)(deviceInstance->hostHandle))->controllerHandle);
|
|
|
|
(void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDevicePID, &productId);
|
|
|
|
(void)usb_echo("usb host Ip3516hs test mode init product id:0x%x\r\n", productId);
|
|
|
|
switch (productId)
|
|
{
|
|
case 0x0101U:
|
|
(void)USB_HostIp3516HsTestSetMode(usbHostState, USB_HOST_IP3516HS_PORTSC_PTC_SE0_NAK);
|
|
break;
|
|
case 0x0102U:
|
|
(void)USB_HostIp3516HsTestSetMode(usbHostState, USB_HOST_IP3516HS_PORTSC_PTC_J_STATE);
|
|
break;
|
|
case 0x0103U:
|
|
(void)USB_HostIp3516HsTestSetMode(usbHostState, USB_HOST_IP3516HS_PORTSC_PTC_K_STATE);
|
|
break;
|
|
case 0x0104U:
|
|
(void)USB_HostIp3516HsTestSetMode(usbHostState, USB_HOST_IP3516HS_PORTSC_PTC_PACKET);
|
|
break;
|
|
case 0x0105U:
|
|
(void)usb_echo("set test mode FORCE_ENALBE\r\n");
|
|
(void)USB_HostIp3516HsTestSetMode(usbHostState, USB_HOST_IP3516HS_PORTSC_PTC_FORCE_ENABLE);
|
|
break;
|
|
case 0x0106U:
|
|
USB_HostIp3516HsTestSuspendResume(usbHostState);
|
|
break;
|
|
case 0x0107U:
|
|
(void)usb_echo("start test SINGLE_STEP_GET_DEV_DESC\r\n");
|
|
USB_HostIp3516HsTestSingleStepGetDeviceDesc(usbHostState, deviceHandle);
|
|
break;
|
|
case 0x0108U:
|
|
(void)usb_echo("start test SINGLE_STEP_GET_DEV_DESC_DATA\r\n");
|
|
USB_HostIp3516HsTestSingleStepGetDeviceDescData(usbHostState, deviceHandle);
|
|
break;
|
|
default:
|
|
/*default*/
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void USB_HostIp3516HsSuspendBus(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
uint32_t portStatus;
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
USB_HostIp3516HsLock();
|
|
if (0U != (portStatus & USB_HOST_IP3516HS_PORTSC1_PED_MASK))
|
|
{
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_SUS_L1_MASK);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_SUSP_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
}
|
|
|
|
USB_HostIp3516HsUnlock();
|
|
}
|
|
|
|
static void USB_HostIp3516HsResumeBus(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
uint32_t portStatus;
|
|
|
|
USB_HostIp3516HsLock();
|
|
/* Resume port */
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
if (portStatus & USB_HOST_IP3516HS_PORTSC1_PED_MASK)
|
|
{
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_FPR_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
/**resume 21ms = 168/8*/
|
|
USB_HostIp3516HsDelay(usbHostState, 168U);
|
|
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_FPR_MASK);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_PP_MASK | USB_HOST_IP3516HS_PORTSC1_PED_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
}
|
|
USB_HostIp3516HsUnlock();
|
|
}
|
|
#endif
|
|
|
|
static void USB_HostOhciDisableIsr(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
OSA_SR_ALLOC();
|
|
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
if (0U == usbHostState->isrLevel)
|
|
{
|
|
NVIC_DisableIRQ((IRQn_Type)usbHostState->isrNumber);
|
|
}
|
|
usbHostState->isrLevel++;
|
|
OSA_EXIT_CRITICAL();
|
|
}
|
|
|
|
static void USB_HostOhciEnableIsr(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
OSA_SR_ALLOC();
|
|
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
usbHostState->isrLevel--;
|
|
if (0U == usbHostState->isrLevel)
|
|
{
|
|
NVIC_EnableIRQ((IRQn_Type)usbHostState->isrNumber);
|
|
}
|
|
OSA_EXIT_CRITICAL();
|
|
}
|
|
|
|
static void USB_HostIp3516HsDelay(usb_host_ip3516hs_state_struct_t *usbHostState, uint32_t ms)
|
|
{
|
|
/* note: the max delay time cannot exceed half of max value (0x4000) */
|
|
uint32_t sofStart;
|
|
uint32_t SofEnd;
|
|
uint32_t distance;
|
|
|
|
sofStart = (uint32_t)((usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
|
|
do
|
|
{
|
|
SofEnd = (uint32_t)((usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
distance = (uint32_t)(
|
|
(SofEnd - sofStart + (USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK >> USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT) + 1U) &
|
|
(USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK >> USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT));
|
|
} while ((distance) < (ms)); /* compute the distance between sofStart and SofEnd */
|
|
}
|
|
/*seperate bus control to standlone alone function for misra Rule17.2*/
|
|
static usb_status_t USB_HostIp3516HsControlBusReset(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
uint32_t portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
usb_status_t status = kStatus_USB_Success;
|
|
portStatus &= ~USB_HOST_IP3516HS_PORTSC1_WIC;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus | USB_HOST_IP3516HS_PORTSC1_PR_MASK;
|
|
|
|
USB_HostIp3516HsDelay(usbHostState, 200);
|
|
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_PR_MASK);
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
while (0U != (usbHostState->usbRegBase->PORTSC1 & USB_HOST_IP3516HS_PORTSC1_PR_MASK))
|
|
{
|
|
__NOP();
|
|
}
|
|
return status;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsControlBus(usb_host_ip3516hs_state_struct_t *usbHostState, uint8_t busControl)
|
|
{
|
|
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
|
|
uint32_t portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
#endif
|
|
usb_status_t status = kStatus_USB_Success;
|
|
usb_host_bus_control_t controlCode = (usb_host_bus_control_t)busControl;
|
|
switch (controlCode)
|
|
{
|
|
case kUSB_HostBusReset:
|
|
(void)USB_HostIp3516HsControlBusReset(usbHostState);
|
|
break;
|
|
|
|
case kUSB_HostBusRestart:
|
|
break;
|
|
|
|
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
|
|
case kUSB_HostBusSuspend:
|
|
if (0U != (usbHostState->usbRegBase->PORTSC1 & USB_HOST_IP3516HS_PORTSC1_CCS_MASK))
|
|
{
|
|
usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostState->hostHandle;
|
|
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_SUS_L1_MASK);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_SUSP_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
|
|
usbHostState->matchTick = hostPointer->hwTick;
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsStartSuspend;
|
|
|
|
while ((hostPointer->hwTick - usbHostState->matchTick) <= 5U)
|
|
{
|
|
}
|
|
portStatus = usbHostState->usbRegBase->USBCMD;
|
|
portStatus &= ~USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
usbHostState->usbRegBase->USBCMD = portStatus;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventSuspended); /* call host callback function */
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsSuspended;
|
|
}
|
|
else
|
|
{
|
|
status = kStatus_USB_Error;
|
|
}
|
|
break;
|
|
|
|
case kUSB_HostBusResume:
|
|
if (0U != (usbHostState->usbRegBase->PORTSC1 & USB_HOST_IP3516HS_PORTSC1_CCS_MASK))
|
|
{
|
|
usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostState->hostHandle;
|
|
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsStartResume;
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_FPR_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
usbHostState->matchTick = hostPointer->hwTick;
|
|
while ((hostPointer->hwTick - usbHostState->matchTick) <= 20U)
|
|
{
|
|
}
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_FPR_MASK);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_PP_MASK | USB_HOST_IP3516HS_PORTSC1_PED_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventResumed); /* call host callback function */
|
|
hostPointer->suspendedDevice = NULL;
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
}
|
|
else
|
|
{
|
|
usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostState->hostHandle;
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_FPR_MASK);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_PP_MASK | USB_HOST_IP3516HS_PORTSC1_PED_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
hostPointer->suspendedDevice = NULL;
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
|
|
status = kStatus_USB_Error;
|
|
}
|
|
break;
|
|
#if ((defined(USB_HOST_CONFIG_LPM_L1)) && (USB_HOST_CONFIG_LPM_L1 > 0U))
|
|
case kUSB_HostBusL1Sleep:
|
|
if (0U != (usbHostState->usbRegBase->PORTSC1 & USB_HOST_IP3516HS_PORTSC1_CCS_MASK))
|
|
{
|
|
usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostState->hostHandle;
|
|
|
|
portStatus = usbHostState->usbRegBase->USBCMD;
|
|
portStatus &= ~(USB_HOST_IP3516HS_USBCMD_HIRD_MASK | USB_HOST_IP3516HS_USBCMD_LPM_RWU_MASK);
|
|
portStatus |= (uint32_t)(
|
|
((uint32_t)usbHostState->hirdValue << USB_HOST_IP3516HS_USBCMD_HIRD_SHIFT) |
|
|
((uint32_t)usbHostState->L1remoteWakeupEnable << USB_HOST_IP3516HS_USBCMD_LPM_RWU_SHIFT));
|
|
usbHostState->usbRegBase->USBCMD = portStatus;
|
|
|
|
usb_host_device_instance_t *deviceInstance;
|
|
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsL1StartSleep;
|
|
|
|
deviceInstance = (usb_host_device_instance_t *)hostPointer->suspendedDevice;
|
|
usbHostState->usbRegBase->PORTSC1 |= (uint32_t)(
|
|
(uint32_t)USB_HOST_IP3516HS_PORTSC1_SUSP_MASK | (uint32_t)USB_HOST_IP3516HS_PORTSC1_SUS_L1_MASK |
|
|
(((uint32_t)deviceInstance->setAddress << USB_HOST_IP3516HS_PORTSC1_DEV_ADD_SHIFT) &
|
|
(uint32_t)USB_HOST_IP3516HS_PORTSC1_DEV_ADD_MASK));
|
|
#if (defined(FSL_FEATURE_USBHSH_VERSION) && (FSL_FEATURE_USBHSH_VERSION >= 300U))
|
|
#else
|
|
while (0U == (usbHostState->usbRegBase->PORTSC1 &
|
|
(uint32_t)((uint32_t)USB_HOST_IP3516HS_PORTSC1_SUSP_MASK |
|
|
(uint32_t)USB_HOST_IP3516HS_PORTSC1_SUS_STAT_MASK)))
|
|
{
|
|
__NOP();
|
|
}
|
|
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
|
|
if ((0U != (usbHostState->usbRegBase->PORTSC1 & USB_HOST_IP3516HS_PORTSC1_SUSP_MASK)) &&
|
|
(0x00U == ((portStatus & USB_HOST_IP3516HS_PORTSC1_SUS_STAT_MASK) >>
|
|
USB_HOST_IP3516HS_PORTSC1_SUS_STAT_SHIFT)))
|
|
{
|
|
usbHostState->matchTick = hostPointer->hwTick;
|
|
while ((hostPointer->hwTick - usbHostState->matchTick) <= 4U)
|
|
{
|
|
}
|
|
portStatus = usbHostState->usbRegBase->USBCMD;
|
|
portStatus &= ~USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
usbHostState->usbRegBase->USBCMD = portStatus;
|
|
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsL1Sleeped;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventL1Sleeped); /* call host callback function */
|
|
}
|
|
else if (0x02U == ((portStatus & USB_HOST_IP3516HS_PORTSC1_SUS_STAT_MASK) >>
|
|
USB_HOST_IP3516HS_PORTSC1_SUS_STAT_SHIFT))
|
|
{
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(
|
|
hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventL1SleepNotSupport); /* call host callback function */
|
|
}
|
|
else if (0x01U == ((portStatus & USB_HOST_IP3516HS_PORTSC1_SUS_STAT_MASK) >>
|
|
USB_HOST_IP3516HS_PORTSC1_SUS_STAT_SHIFT))
|
|
{
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventL1SleepNYET); /* call host callback function */
|
|
}
|
|
else if (0x03U == ((portStatus & USB_HOST_IP3516HS_PORTSC1_SUS_STAT_MASK) >>
|
|
USB_HOST_IP3516HS_PORTSC1_SUS_STAT_SHIFT))
|
|
{
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventL1SleepError); /* call host callback function */
|
|
}
|
|
else
|
|
{
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
status = kStatus_USB_Error;
|
|
}
|
|
break;
|
|
|
|
case kUSB_HostBusL1Resume:
|
|
if (0U != (usbHostState->usbRegBase->PORTSC1 & USB_HOST_IP3516HS_PORTSC1_CCS_MASK))
|
|
{
|
|
usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostState->hostHandle;
|
|
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsStartResume;
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_FPR_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
while (0U != ((portStatus)&USB_HOST_IP3516HS_PORTSC1_FPR_MASK))
|
|
{
|
|
portStatus = (usbHostState->usbRegBase->PORTSC1);
|
|
portStatus = portStatus & USB_HOST_IP3516HS_PORTSC1_FPR_MASK;
|
|
}
|
|
usbHostState->matchTick = hostPointer->hwTick;
|
|
while ((hostPointer->hwTick - usbHostState->matchTick) <= 5U)
|
|
{
|
|
}
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventL1Resumed); /* call host callback function */
|
|
hostPointer->suspendedDevice = NULL;
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
}
|
|
else
|
|
{
|
|
usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostState->hostHandle;
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_FPR_MASK);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_PP_MASK | USB_HOST_IP3516HS_PORTSC1_PED_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
hostPointer->suspendedDevice = NULL;
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
|
|
status = kStatus_USB_Error;
|
|
}
|
|
break;
|
|
#endif
|
|
#endif
|
|
case kUSB_HostBusEnableAttach:
|
|
if (0UL != (usbHostState->usbRegBase->HCSPARAMS &
|
|
USB_HOST_IP3516HS_HCSPARAMS_PPC_MASK)) /* Ports have power port switches */
|
|
{
|
|
/* only has one port */
|
|
uint32_t tmp = usbHostState->usbRegBase->PORTSC1;
|
|
tmp &= (~USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_PP_MASK);
|
|
usbHostState->usbRegBase->PORTSC1 = (tmp); /* turn on port power */
|
|
|
|
tmp = usbHostState->usbRegBase->PORTSC1;
|
|
tmp &= (~USB_HOST_IP3516HS_PORTSC1_WIC);
|
|
usbHostState->usbRegBase->PORTSC1 = (tmp | USB_HOST_IP3516HS_PORTSC1_PP_MASK); /* turn on port power */
|
|
}
|
|
(void)USB_HostIp3516HsControlBusReset(usbHostState);
|
|
usbHostState->portState[0].portStatus = (uint8_t)kUSB_DeviceIp3516HsPortDetached;
|
|
(void)OSA_EventSet(usbHostState->ip3516HsEvent, USB_HOST_IP3516HS_EVENT_PORT_CHANGE);
|
|
break;
|
|
case kUSB_HostBusDisableAttach:
|
|
break;
|
|
default:
|
|
status = kStatus_USB_Error;
|
|
break;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U)) || \
|
|
(defined(USB_HOST_CONFIG_IP3516HS_MAX_INT) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
static uint32_t USB_HostIp3516HsBusTime(uint8_t speed, uint8_t pipeType, uint8_t direction, uint32_t dataLength)
|
|
{
|
|
uint32_t result = (3167U + ((1000U * dataLength) * 7U * 8U / 6U)) / 1000U;
|
|
|
|
if (pipeType == USB_ENDPOINT_ISOCHRONOUS) /* iso */
|
|
{
|
|
if (speed == USB_SPEED_HIGH)
|
|
{
|
|
result = 2083U * (38U * 8U + result) + USB_HOST_IP3516HS_TIME_DELAY;
|
|
}
|
|
else if (speed == USB_SPEED_FULL)
|
|
{
|
|
if (direction == USB_IN)
|
|
{
|
|
result = 7268000U + 83540U * result + USB_HOST_IP3516HS_TIME_DELAY;
|
|
}
|
|
else
|
|
{
|
|
result = 6265000U + 83540U * result + USB_HOST_IP3516HS_TIME_DELAY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*no action*/
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (speed == USB_SPEED_HIGH)
|
|
{
|
|
result = 2083U * (55U * 8U + result) + USB_HOST_IP3516HS_TIME_DELAY;
|
|
}
|
|
else if (speed == USB_SPEED_FULL)
|
|
{
|
|
result = 9107000U + 83540U * result + USB_HOST_IP3516HS_TIME_DELAY;
|
|
}
|
|
else if (speed == USB_SPEED_LOW)
|
|
{
|
|
if (direction == USB_IN)
|
|
{
|
|
result = 64060000U + 2000U * USB_HOST_IP3516HS_HUB_LS_SETUP_TIME_DELAY + 676670U * result +
|
|
USB_HOST_IP3516HS_TIME_DELAY;
|
|
}
|
|
else
|
|
{
|
|
result = 64107000U + 2000U * USB_HOST_IP3516HS_HUB_LS_SETUP_TIME_DELAY + 667000U * result +
|
|
USB_HOST_IP3516HS_TIME_DELAY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*no action*/
|
|
}
|
|
}
|
|
|
|
result /= 1000000U;
|
|
if (result == 0U)
|
|
{
|
|
result = 1U;
|
|
}
|
|
else
|
|
{
|
|
/*no action*/
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
static usb_status_t USB_HostIp3516HsGetNewPipe(usb_host_ip3516hs_pipe_struct_t **pipeQueue,
|
|
usb_host_ip3516hs_pipe_struct_t **pipe)
|
|
{
|
|
usb_status_t error = kStatus_USB_Busy;
|
|
void *p;
|
|
OSA_SR_ALLOC();
|
|
|
|
/* get a pipe instance */
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
if (NULL != (*pipeQueue))
|
|
{
|
|
*pipe = *pipeQueue;
|
|
p = (void *)((*pipe)->pipeCommon.next);
|
|
*pipeQueue = (usb_host_ip3516hs_pipe_struct_t *)p;
|
|
error = kStatus_USB_Success;
|
|
}
|
|
/* Exit critical */
|
|
OSA_EXIT_CRITICAL();
|
|
return error;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsRemovePipe(usb_host_ip3516hs_pipe_struct_t **pipeQueue,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe)
|
|
{
|
|
usb_host_ip3516hs_pipe_struct_t *p = *pipeQueue;
|
|
usb_host_ip3516hs_pipe_struct_t *pre;
|
|
void *temp;
|
|
|
|
OSA_SR_ALLOC();
|
|
|
|
/* get a pipe instance */
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
pre = NULL;
|
|
while (NULL != p)
|
|
{
|
|
if (p != pipe)
|
|
{
|
|
pre = p;
|
|
temp = (void *)p->pipeCommon.next;
|
|
p = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
}
|
|
else
|
|
{
|
|
if (NULL != pre)
|
|
{
|
|
pre->pipeCommon.next = p->pipeCommon.next;
|
|
}
|
|
else
|
|
{
|
|
temp = (void *)p->pipeCommon.next;
|
|
*pipeQueue = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
OSA_EXIT_CRITICAL();
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsInsertPipe(usb_host_ip3516hs_pipe_struct_t **pipeQueue,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe)
|
|
{
|
|
usb_host_ip3516hs_pipe_struct_t *p = *pipeQueue;
|
|
void *temp;
|
|
|
|
OSA_SR_ALLOC();
|
|
|
|
pipe->pipeCommon.next = NULL;
|
|
/* get a pipe instance */
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
while (NULL != p)
|
|
{
|
|
if (p != pipe)
|
|
{
|
|
temp = (void *)p->pipeCommon.next;
|
|
p = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (NULL == p)
|
|
{
|
|
temp = (void *)(*pipeQueue);
|
|
pipe->pipeCommon.next = (usb_host_pipe_t *)temp;
|
|
*pipeQueue = pipe;
|
|
}
|
|
OSA_EXIT_CRITICAL();
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsPortChange(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
uint32_t portStatus;
|
|
uint8_t i = 0U;
|
|
|
|
for (i = 0U; i < usbHostState->portNumber; i++)
|
|
{
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
if (0U != (portStatus & USB_HOST_IP3516HS_PORTSC1_CSC_MASK))
|
|
{
|
|
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
|
|
if ((uint8_t)kBus_Ip3516HsIdle != usbHostState->busSuspendStatus)
|
|
{
|
|
usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostState->hostHandle;
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_FPR_MASK);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_PP_MASK | USB_HOST_IP3516HS_PORTSC1_PED_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
hostPointer->suspendedDevice = NULL;
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
}
|
|
#endif
|
|
uint32_t sofStart =
|
|
(uint32_t)((usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
uint32_t sof;
|
|
while (1U == 1U)
|
|
{
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
if (0U != (portStatus & USB_HOST_IP3516HS_PORTSC1_CSC_MASK))
|
|
{
|
|
portStatus &= ~USB_HOST_IP3516HS_PORTSC1_WIC;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus | USB_HOST_IP3516HS_PORTSC1_CSC_MASK;
|
|
}
|
|
sof = (uint32_t)((usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
if ((((sof + USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK + 1U) - sofStart) &
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) > 1U)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
|
|
if (0U != (portStatus & USB_HOST_IP3516HS_PORTSC1_CCS_MASK))
|
|
{
|
|
uint32_t index;
|
|
#if (defined(USB_HOST_CONFIG_BATTERY_CHARGER) && (USB_HOST_CONFIG_BATTERY_CHARGER > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
/* set the charger type as SDP to disable the DCD function because the usb host start to works. */
|
|
uint8_t chargerType = (uint8_t)kUSB_DcdSDP;
|
|
#endif
|
|
if (kUSB_DeviceIp3516HsPortDetached !=
|
|
(usb_host_ip3516hs_port_state_t)usbHostState->portState[i].portStatus)
|
|
{
|
|
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
|
|
if (((uint8_t)kBus_Ip3516HsSuspended == usbHostState->busSuspendStatus))
|
|
{
|
|
usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostState->hostHandle;
|
|
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsStartResume;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(
|
|
hostPointer->suspendedDevice, NULL,
|
|
(uint32_t)kUSB_HostEventDetectResume); /* call host callback function */
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_FPR_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
usbHostState->matchTick = hostPointer->hwTick;
|
|
while ((hostPointer->hwTick - usbHostState->matchTick) <= 20U)
|
|
{
|
|
}
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_FPR_MASK);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_PP_MASK | USB_HOST_IP3516HS_PORTSC1_PED_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventResumed); /* call host callback function */
|
|
hostPointer->suspendedDevice = NULL;
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
}
|
|
#if ((defined(USB_HOST_CONFIG_LPM_L1)) && (USB_HOST_CONFIG_LPM_L1 > 0U))
|
|
if (((uint8_t)kBus_Ip3516HsL1Sleeped == usbHostState->busSuspendStatus))
|
|
{
|
|
usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostState->hostHandle;
|
|
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsStartResume;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(
|
|
hostPointer->suspendedDevice, NULL,
|
|
(uint32_t)kUSB_HostEventDetectResume); /* call host callback function */
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
usbHostState->matchTick = hostPointer->hwTick;
|
|
|
|
while (0U != ((portStatus)&USB_HOST_IP3516HS_PORTSC1_FPR_MASK))
|
|
{
|
|
portStatus = (usbHostState->usbRegBase->PORTSC1);
|
|
portStatus = portStatus & USB_HOST_IP3516HS_PORTSC1_FPR_MASK;
|
|
if ((hostPointer->hwTick - usbHostState->matchTick) >= 1U)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
portStatus &= ~(USB_HOST_IP3516HS_PORTSC1_WIC | USB_HOST_IP3516HS_PORTSC1_FPR_MASK);
|
|
portStatus |= USB_HOST_IP3516HS_PORTSC1_PP_MASK | USB_HOST_IP3516HS_PORTSC1_PED_MASK;
|
|
usbHostState->usbRegBase->PORTSC1 = portStatus;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(
|
|
hostPointer->suspendedDevice, NULL,
|
|
(uint32_t)kUSB_HostEventL1Resumed); /* call host callback function */
|
|
hostPointer->suspendedDevice = NULL;
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
}
|
|
#if (defined(FSL_FEATURE_USBHSH_VERSION) && (FSL_FEATURE_USBHSH_VERSION >= 300U))
|
|
else if (((uint8_t)kBus_Ip3516HsL1StartSleep == usbHostState->busSuspendStatus))
|
|
{
|
|
usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostState->hostHandle;
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
|
|
if ((0U != (usbHostState->usbRegBase->PORTSC1 & USB_HOST_IP3516HS_PORTSC1_SUSP_MASK)) &&
|
|
(0x00U == ((portStatus & USB_HOST_IP3516HS_PORTSC1_SUS_STAT_MASK) >>
|
|
USB_HOST_IP3516HS_PORTSC1_SUS_STAT_SHIFT)))
|
|
{
|
|
portStatus = usbHostState->usbRegBase->USBCMD;
|
|
portStatus &= ~USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
usbHostState->usbRegBase->USBCMD = portStatus;
|
|
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsL1Sleeped;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventL1Sleeped); /* call host callback function */
|
|
}
|
|
else if (0x02U == ((portStatus & USB_HOST_IP3516HS_PORTSC1_SUS_STAT_MASK) >>
|
|
USB_HOST_IP3516HS_PORTSC1_SUS_STAT_SHIFT))
|
|
{
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(
|
|
hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventL1SleepNotSupport); /* call host callback function */
|
|
}
|
|
else if (0x01U == ((portStatus & USB_HOST_IP3516HS_PORTSC1_SUS_STAT_MASK) >>
|
|
USB_HOST_IP3516HS_PORTSC1_SUS_STAT_SHIFT))
|
|
{
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventL1SleepNYET); /* call host callback function */
|
|
}
|
|
else if (0x03U == ((portStatus & USB_HOST_IP3516HS_PORTSC1_SUS_STAT_MASK) >>
|
|
USB_HOST_IP3516HS_PORTSC1_SUS_STAT_SHIFT))
|
|
{
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
/* call host callback function, function is initialized in USB_HostInit */
|
|
(void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
|
|
kUSB_HostEventL1SleepError); /* call host callback function */
|
|
}
|
|
else
|
|
{
|
|
usbHostState->busSuspendStatus = (uint8_t)kBus_Ip3516HsIdle;
|
|
}
|
|
}
|
|
#else
|
|
|
|
#endif
|
|
else
|
|
{
|
|
/* no action */
|
|
}
|
|
#endif
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
for (index = 0U; index < USB_HOST_IP3516HS_PORT_CONNECT_DEBOUNCE_DELAY; index++)
|
|
{
|
|
USB_HostIp3516HsDelay(usbHostState, 8U);
|
|
if (0U == (usbHostState->usbRegBase->PORTSC1 & USB_HOST_IP3516HS_PORTSC1_CCS_MASK))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
portStatus = usbHostState->usbRegBase->PORTSC1;
|
|
|
|
/* CCS is cleared ?*/
|
|
if ((0U == (portStatus & USB_HOST_IP3516HS_PORTSC1_CCS_MASK)) ||
|
|
(index < USB_HOST_IP3516HS_PORT_CONNECT_DEBOUNCE_DELAY))
|
|
{
|
|
usbHostState->portState[i].portStatus = (uint8_t)kUSB_DeviceIp3516HsPortDetached;
|
|
continue;
|
|
}
|
|
|
|
#if (defined(USB_HOST_CONFIG_BATTERY_CHARGER) && (USB_HOST_CONFIG_BATTERY_CHARGER > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
USB_HSDCD_Control(usbHostState->dcdHandle, kUSB_HostHSDcdSetType, &(chargerType));
|
|
#endif
|
|
(void)USB_HostIp3516HsControlBus(usbHostState, (uint8_t)kUSB_HostBusReset);
|
|
USB_HostIp3516HsDelay(usbHostState, 81U);
|
|
usbHostState->portState[i].portSpeed =
|
|
(uint8_t)((usbHostState->usbRegBase->PORTSC1 & USB_HOST_IP3516HS_PORTSC1_PSPD_MASK) >>
|
|
USB_HOST_IP3516HS_PORTSC1_PSPD_SHIFT);
|
|
if (0x00U == usbHostState->portState[i].portSpeed)
|
|
{
|
|
usbHostState->portState[i].portSpeed = USB_SPEED_LOW;
|
|
}
|
|
else if (0x01U == usbHostState->portState[i].portSpeed)
|
|
{
|
|
usbHostState->portState[i].portSpeed = USB_SPEED_FULL;
|
|
}
|
|
else
|
|
{
|
|
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
|
|
/* enable phy disconnection */
|
|
USB_EhcihostPhyDisconnectDetectCmd((uint8_t)kUSB_ControllerIp3516Hs0 + usbHostState->controllerId, 1U);
|
|
#endif
|
|
}
|
|
/* do bus recovery delay */
|
|
USB_HostIp3516HsDelay(usbHostState, USB_HOST_IP3516HS_PORT_RESET_RECOVERY_DELAY * 8U);
|
|
usbHostState->portState[i].portStatus = (uint8_t)kUSB_DeviceIp3516HsPortPhyAttached;
|
|
(void)OSA_EventSet(usbHostState->ip3516HsEvent, USB_HOST_IP3516HS_EVENT_ATTACH);
|
|
}
|
|
else
|
|
{
|
|
if ((uint8_t)kUSB_DeviceIp3516HsPortDetached == usbHostState->portState[i].portStatus)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ((uint8_t)kUSB_DeviceIp3516HsPortAttached == usbHostState->portState[i].portStatus)
|
|
{
|
|
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
|
|
/* disable phy disconnection */
|
|
USB_EhcihostPhyDisconnectDetectCmd((uint8_t)kUSB_ControllerIp3516Hs0 + usbHostState->controllerId, 0U);
|
|
#endif
|
|
usbHostState->portState[i].portStatus = (uint8_t)kUSB_DeviceIp3516HsPortPhyDetached;
|
|
#if (defined(USB_HOST_CONFIG_BATTERY_CHARGER) && (USB_HOST_CONFIG_BATTERY_CHARGER > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
USB_HSDCD_Control(usbHostState->dcdHandle, kUSB_HostHSDcdSetType, &(usbHostState->chargerType));
|
|
#endif
|
|
(void)OSA_EventSet(usbHostState->ip3516HsEvent, USB_HOST_IP3516HS_EVENT_DETACH);
|
|
}
|
|
else
|
|
{
|
|
usbHostState->portState[i].portStatus = (uint8_t)kUSB_DeviceIp3516HsPortDetached;
|
|
}
|
|
}
|
|
}
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U)) || \
|
|
(defined(USB_HOST_CONFIG_IP3516HS_MAX_INT) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
static usb_status_t USB_HostIp3516HsFillSlotBusTime(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe,
|
|
uint32_t startUFrame,
|
|
uint8_t *slotTime,
|
|
uint8_t *ssSlot,
|
|
uint8_t *csSlot)
|
|
{
|
|
uint8_t slots = (uint8_t)((pipe->pipeCommon.maxPacketSize + 187U) / 188U);
|
|
uint8_t startSlot = (uint8_t)(startUFrame % 8UL);
|
|
|
|
for (uint8_t i = 0; i < 8U; i++)
|
|
{
|
|
slotTime[i] = 0U;
|
|
}
|
|
*ssSlot = 0U;
|
|
*csSlot = 0U;
|
|
|
|
if (USB_ENDPOINT_ISOCHRONOUS == pipe->pipeCommon.pipeType)
|
|
{
|
|
if (USB_OUT == pipe->pipeCommon.direction)
|
|
{
|
|
if ((startSlot + slots) > 7U)
|
|
{
|
|
return kStatus_USB_Error;
|
|
}
|
|
for (uint8_t i = 0; i < (slots); i++)
|
|
{
|
|
slotTime[startSlot + i] = 125U;
|
|
*ssSlot |= (uint8_t)(1UL << (startSlot + i));
|
|
}
|
|
slotTime[startSlot + slots - 1U] = (uint8_t)(((pipe->pipeCommon.maxPacketSize % 188U) * 125U) / 188U);
|
|
}
|
|
else
|
|
{
|
|
if ((startSlot + slots + 1U) > 8U)
|
|
{
|
|
return kStatus_USB_Error;
|
|
}
|
|
*ssSlot = 1U << startSlot;
|
|
for (uint8_t i = 0U; i < (slots); i++)
|
|
{
|
|
slotTime[startSlot + 1U + i] = 125U;
|
|
*csSlot |= (uint8_t)(1UL << (startSlot + 1U + i));
|
|
}
|
|
slotTime[startSlot + 1U + slots - 1U] = (uint8_t)(((pipe->pipeCommon.maxPacketSize % 188U) * 125U) / 188U);
|
|
}
|
|
}
|
|
else if (USB_ENDPOINT_INTERRUPT == pipe->pipeCommon.pipeType)
|
|
{
|
|
if ((startSlot + 3U + 2U) > 8U)
|
|
{
|
|
return kStatus_USB_Error;
|
|
}
|
|
*ssSlot = 1U << startSlot;
|
|
for (uint8_t i = 0U; i < 3U; i++)
|
|
{
|
|
*csSlot |= (uint8_t)(1UL << (startSlot + 2U + i));
|
|
}
|
|
if (USB_OUT == pipe->pipeCommon.direction)
|
|
{
|
|
slotTime[startSlot] = (uint8_t)pipe->busNoneHsTime;
|
|
}
|
|
else
|
|
{
|
|
for (uint8_t i = 0U; i < 3U; i++)
|
|
{
|
|
slotTime[startSlot + 2U + i] = (uint8_t)pipe->busNoneHsTime;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*no action*/
|
|
}
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsFindStartFrame(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe)
|
|
{
|
|
usb_host_ip3516hs_pipe_struct_t *p;
|
|
uint32_t startUFrame;
|
|
uint32_t frame;
|
|
uint32_t total = 0U;
|
|
void *temp;
|
|
uint8_t slotTime[8];
|
|
uint8_t speed = ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed;
|
|
|
|
pipe->startUFrame = 0U;
|
|
|
|
if (NULL == usbHostState->pipeListInUsing)
|
|
{
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
for (startUFrame = 0U; startUFrame < ((uint32_t)pipe->pipeCommon.interval); startUFrame++)
|
|
{
|
|
for (frame = startUFrame; frame < USB_HOST_IP3516HS_MAX_UFRAME; frame += pipe->pipeCommon.interval)
|
|
{
|
|
total = pipe->busHsTime;
|
|
/* using temp for misra 14.2, 10.4*/
|
|
temp = (void *)usbHostState->pipeListInUsing;
|
|
while (NULL != temp)
|
|
{
|
|
p = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
temp = (void *)p->pipeCommon.next;
|
|
if ((frame >= p->startUFrame) && ((p->pipeCommon.pipeType == USB_ENDPOINT_ISOCHRONOUS) ||
|
|
(p->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT)))
|
|
{
|
|
if (USB_SPEED_HIGH == speed)
|
|
{
|
|
if (0U == ((frame - p->startUFrame) % p->pipeCommon.interval))
|
|
{
|
|
total += p->busHsTime;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (USB_OUT == p->pipeCommon.direction)
|
|
{
|
|
if (0U == ((frame - p->startUFrame) % p->pipeCommon.interval))
|
|
{
|
|
total += p->busHsTime;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (uint32_t cs = 0U; cs < 8U; cs++)
|
|
{
|
|
if (0U != (p->csSlot & (1U << cs)))
|
|
{
|
|
if (0U == ((frame - (cs + (uint32_t)(((uint32_t)p->startUFrame) & 0xFFF8U))) %
|
|
(uint32_t)(p->pipeCommon.interval)))
|
|
{
|
|
total += p->busHsTime;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((float)total > USB_HOST_IP3516HS_PERIODIC_BANDWIDTH)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
if ((frame >= USB_HOST_IP3516HS_MAX_UFRAME) && (USB_SPEED_HIGH != speed))
|
|
{
|
|
uint32_t hsHubNumber;
|
|
usb_status_t error;
|
|
uint8_t totalSlotTime[8];
|
|
uint8_t deviceSlotTime[8];
|
|
|
|
hsHubNumber = 0U;
|
|
frame = startUFrame;
|
|
for (uint32_t i = 0; i < 8U; i++)
|
|
{
|
|
totalSlotTime[i] = 0U;
|
|
deviceSlotTime[i] = 0U;
|
|
slotTime[i] = 0U;
|
|
}
|
|
error = USB_HostIp3516HsFillSlotBusTime(usbHostState, pipe, startUFrame, slotTime, &pipe->ssSlot,
|
|
&pipe->csSlot);
|
|
if (kStatus_USB_Success != error)
|
|
{
|
|
break;
|
|
}
|
|
|
|
/* compute FS/LS bandwidth that blong to same high-speed hub, because FS/LS bandwidth is allocated from
|
|
* first parent high-speed hub */
|
|
(void)USB_HostHelperGetPeripheralInformation(pipe->pipeCommon.deviceHandle,
|
|
(uint32_t)kUSB_HostGetDeviceHSHubNumber, &hsHubNumber);
|
|
for (frame = startUFrame; frame < USB_HOST_IP3516HS_MAX_UFRAME; frame += pipe->pipeCommon.interval)
|
|
{
|
|
total = 0U;
|
|
temp = (void *)usbHostState->pipeListInUsing;
|
|
while (NULL != temp)
|
|
{
|
|
p = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
temp = (void *)p->pipeCommon.next;
|
|
if ((frame >= p->startUFrame) && ((p->pipeCommon.pipeType == USB_ENDPOINT_ISOCHRONOUS) ||
|
|
(p->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT)))
|
|
{
|
|
uint32_t deviceHsHubNumber = 0U;
|
|
(void)USB_HostHelperGetPeripheralInformation(p->pipeCommon.deviceHandle,
|
|
(uint32_t)kUSB_HostGetDeviceHSHubNumber,
|
|
&deviceHsHubNumber);
|
|
if ((deviceHsHubNumber == hsHubNumber) &&
|
|
(0U == (((frame & 0xFFFFFFF8U) - (p->startUFrame & 0xFFF8U)) % p->pipeCommon.interval)))
|
|
{
|
|
uint8_t ss;
|
|
uint8_t cs;
|
|
(void)USB_HostIp3516HsFillSlotBusTime(usbHostState, pipe, startUFrame, deviceSlotTime,
|
|
&ss, &cs);
|
|
for (uint32_t i = 0; i < 8U; i++)
|
|
{
|
|
totalSlotTime[i] += deviceSlotTime[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (uint32_t i = 0; i < 8U; i++)
|
|
{
|
|
if ((totalSlotTime[i] + slotTime[i]) > s_SlotMaxBandwidth[i])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} while (0U == 1U);
|
|
|
|
if (frame >= USB_HOST_IP3516HS_MAX_UFRAME)
|
|
{
|
|
pipe->startUFrame = (uint16_t)startUFrame;
|
|
return kStatus_USB_Success;
|
|
}
|
|
}
|
|
|
|
return kStatus_USB_BandwidthFail;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516BaudWidthCheck(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe)
|
|
{
|
|
usb_status_t error;
|
|
uint8_t speed = ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed;
|
|
OSA_SR_ALLOC();
|
|
|
|
pipe->busHsTime = (uint16_t)USB_HostIp3516HsBusTime(
|
|
USB_SPEED_HIGH, pipe->pipeCommon.pipeType, pipe->pipeCommon.direction,
|
|
((uint32_t)pipe->pipeCommon.maxPacketSize) * ((uint32_t)pipe->pipeCommon.numberPerUframe));
|
|
|
|
if (USB_SPEED_HIGH != speed)
|
|
{
|
|
uint32_t thinkTime = 0U;
|
|
pipe->busNoneHsTime = (uint16_t)USB_HostIp3516HsBusTime(
|
|
speed, pipe->pipeCommon.pipeType, pipe->pipeCommon.direction, pipe->pipeCommon.maxPacketSize);
|
|
(void)USB_HostHelperGetPeripheralInformation(pipe->pipeCommon.deviceHandle, (uint32_t)kUSB_HostGetHubThinkTime,
|
|
&thinkTime); /* Get the hub think time */
|
|
pipe->busNoneHsTime += (uint16_t)(thinkTime * 7U / (6U * 12U));
|
|
}
|
|
OSA_ENTER_CRITICAL();
|
|
error = USB_HostIp3516HsFindStartFrame(usbHostState, pipe);
|
|
OSA_EXIT_CRITICAL();
|
|
return error;
|
|
}
|
|
#endif
|
|
|
|
static usb_status_t USB_HostIp3516HsOpenControlBulkPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe)
|
|
{
|
|
usb_host_ip3516hs_atl_struct_t *atl;
|
|
OSA_SR_ALLOC();
|
|
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
for (uint8_t i = 0;
|
|
i < (sizeof(s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl) / sizeof(usb_host_ip3516hs_atl_struct_t));
|
|
i++)
|
|
{
|
|
if (0U == s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[i].control1Union.stateBitField.MaxPacketLength)
|
|
{
|
|
pipe->tdIndex = i;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[i].control1Union.stateBitField.MaxPacketLength =
|
|
pipe->pipeCommon.maxPacketSize;
|
|
break;
|
|
}
|
|
}
|
|
/* Exit critical */
|
|
OSA_EXIT_CRITICAL();
|
|
|
|
if (0xFFU == pipe->tdIndex)
|
|
{
|
|
return kStatus_USB_Busy;
|
|
}
|
|
atl = &s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex];
|
|
atl->control1Union.stateBitField.Mult = pipe->pipeCommon.numberPerUframe;
|
|
atl->control2Union.stateBitField.EP = pipe->pipeCommon.endpointAddress;
|
|
atl->control2Union.stateBitField.DeviceAddress =
|
|
((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->setAddress;
|
|
if (USB_SPEED_HIGH == usbHostState->portState[0].portSpeed)
|
|
{
|
|
atl->control2Union.stateBitField.S =
|
|
(USB_SPEED_HIGH == ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed) ? 0U : 1U;
|
|
}
|
|
else
|
|
{
|
|
atl->control2Union.stateBitField.S = 0U;
|
|
}
|
|
atl->control2Union.stateBitField.RL = 0xFU;
|
|
atl->stateUnion.stateBitField.NakCnt = 0xFU;
|
|
atl->control2Union.stateBitField.SE =
|
|
(USB_SPEED_LOW == ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed) ? 2U : 0U;
|
|
atl->control2Union.stateBitField.PortNumber =
|
|
#if (defined(USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB > 0U))
|
|
((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->hsHubPort;
|
|
#else
|
|
0U;
|
|
#endif
|
|
atl->control2Union.stateBitField.HubAddress =
|
|
#if (defined(USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB > 0U))
|
|
((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->hsHubNumber;
|
|
#else
|
|
0U;
|
|
#endif
|
|
atl->dataUnion.dataBitField.I = 1U;
|
|
atl->stateUnion.stateBitField.EpType = pipe->pipeCommon.pipeType;
|
|
atl->stateUnion.stateBitField.DT = 0U;
|
|
atl->stateUnion.stateBitField.P = 0U;
|
|
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
static usb_status_t USB_HostIp3516HsOpenIsoPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe)
|
|
{
|
|
usb_host_ip3516hs_ptl_struct_t *ptl;
|
|
usb_host_ip3516hs_sptl_struct_t *sptl;
|
|
uint32_t count = 0;
|
|
void *temp;
|
|
usb_status_t error;
|
|
OSA_SR_ALLOC();
|
|
|
|
error = USB_HostIp3516BaudWidthCheck(usbHostState, pipe);
|
|
|
|
if (kStatus_USB_Success != error)
|
|
{
|
|
return error;
|
|
}
|
|
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
for (uint32_t i = 0U; i < USB_HOST_CONFIG_IP3516HS_MAX_ISO; i++)
|
|
{
|
|
for (uint32_t j = i;
|
|
(j < (USB_HOST_IP3516HS_ISO_MULTIPLE_TRANSFER + i)) && (j < USB_HOST_CONFIG_IP3516HS_MAX_ISO); j++)
|
|
{
|
|
if (0U ==
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[j].control1Union.stateBitField.MaxPacketLength)
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
if (count >= USB_HOST_IP3516HS_ISO_MULTIPLE_TRANSFER)
|
|
{
|
|
pipe->tdIndex = (uint8_t)i;
|
|
for (uint32_t j = i;
|
|
(j < (USB_HOST_IP3516HS_ISO_MULTIPLE_TRANSFER + i)) && (j < USB_HOST_CONFIG_IP3516HS_MAX_ISO); j++)
|
|
{
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[j].control1Union.stateBitField.MaxPacketLength =
|
|
pipe->pipeCommon.maxPacketSize;
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
count = 0;
|
|
}
|
|
}
|
|
/* Exit critical */
|
|
OSA_EXIT_CRITICAL();
|
|
|
|
if (0xFFU == pipe->tdIndex)
|
|
{
|
|
return kStatus_USB_Busy;
|
|
}
|
|
|
|
for (uint32_t j = pipe->tdIndex; (j < ((uint32_t)USB_HOST_IP3516HS_ISO_MULTIPLE_TRANSFER + pipe->tdIndex)) &&
|
|
(j < USB_HOST_CONFIG_IP3516HS_MAX_ISO);
|
|
j++)
|
|
{
|
|
ptl = &s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[j];
|
|
temp = (void *)ptl;
|
|
sptl = (usb_host_ip3516hs_sptl_struct_t *)temp;
|
|
ptl->control1Union.stateBitField.Mult = pipe->pipeCommon.numberPerUframe;
|
|
ptl->control2Union.stateBitField.EP = pipe->pipeCommon.endpointAddress;
|
|
ptl->control2Union.stateBitField.DeviceAddress =
|
|
((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->setAddress;
|
|
if (USB_SPEED_HIGH == usbHostState->portState[0].portSpeed)
|
|
{
|
|
ptl->control2Union.stateBitField.S =
|
|
(USB_SPEED_HIGH == ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed) ? 0U : 1U;
|
|
}
|
|
else
|
|
{
|
|
ptl->control2Union.stateBitField.S = 0U;
|
|
}
|
|
ptl->control2Union.stateBitField.RL = 0U;
|
|
ptl->stateUnion.stateBitField.NakCnt = 0U;
|
|
ptl->control2Union.stateBitField.SE =
|
|
(USB_SPEED_LOW == ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed) ? 2U : 0U;
|
|
if (0U != ptl->control2Union.stateBitField.S)
|
|
{
|
|
sptl->control2Union.stateBitField.PortNumber =
|
|
#if (defined(USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB > 0U))
|
|
((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->hsHubPort;
|
|
#else
|
|
0U;
|
|
#endif
|
|
sptl->control2Union.stateBitField.HubAddress =
|
|
#if (defined(USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB > 0U))
|
|
((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->hsHubNumber;
|
|
#else
|
|
0U;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
sptl->control2Union.stateBitField.PortNumber = 0U;
|
|
sptl->control2Union.stateBitField.HubAddress = 0U;
|
|
}
|
|
ptl->dataUnion.dataBitField.NrBytesToTransfer = 0U;
|
|
ptl->dataUnion.dataBitField.I = 1U;
|
|
ptl->stateUnion.stateBitField.EpType = pipe->pipeCommon.pipeType;
|
|
ptl->stateUnion.stateBitField.DT = 0U;
|
|
ptl->stateUnion.stateBitField.P = 0U;
|
|
}
|
|
return kStatus_USB_Success;
|
|
}
|
|
#endif
|
|
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS_MAX_INT) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
static usb_status_t USB_HostIp3516HsOpenInterruptPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe)
|
|
{
|
|
usb_host_ip3516hs_ptl_struct_t *ptl;
|
|
usb_host_ip3516hs_sptl_struct_t *sptl;
|
|
usb_status_t error;
|
|
void *temp;
|
|
OSA_SR_ALLOC();
|
|
|
|
error = USB_HostIp3516BaudWidthCheck(usbHostState, pipe);
|
|
|
|
if (kStatus_USB_Success != error)
|
|
{
|
|
return error;
|
|
}
|
|
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
for (uint8_t i = 0; i < USB_HOST_CONFIG_IP3516HS_MAX_INT; i++)
|
|
{
|
|
if (0U ==
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[i].control1Union.stateBitField.MaxPacketLength)
|
|
{
|
|
pipe->tdIndex = i;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[i].control1Union.stateBitField.MaxPacketLength =
|
|
pipe->pipeCommon.maxPacketSize;
|
|
break;
|
|
}
|
|
}
|
|
/* Exit critical */
|
|
OSA_EXIT_CRITICAL();
|
|
|
|
if (0xFFU == pipe->tdIndex)
|
|
{
|
|
pipe->pipeCommon.open = 0U;
|
|
/* release the pipe */
|
|
(void)USB_HostIp3516HsInsertPipe(&usbHostState->pipeList, pipe);
|
|
return kStatus_USB_Busy;
|
|
}
|
|
ptl = &s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[pipe->tdIndex];
|
|
temp = (void *)ptl;
|
|
sptl = (usb_host_ip3516hs_sptl_struct_t *)temp;
|
|
ptl->control1Union.stateBitField.Mult = pipe->pipeCommon.numberPerUframe;
|
|
ptl->control2Union.stateBitField.EP = pipe->pipeCommon.endpointAddress;
|
|
ptl->control2Union.stateBitField.DeviceAddress =
|
|
((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->setAddress;
|
|
if (USB_SPEED_HIGH == usbHostState->portState[0].portSpeed)
|
|
{
|
|
ptl->control2Union.stateBitField.S =
|
|
(USB_SPEED_HIGH == ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed) ? 0U : 1U;
|
|
}
|
|
else
|
|
{
|
|
ptl->control2Union.stateBitField.S = 0U;
|
|
}
|
|
ptl->control2Union.stateBitField.RL = 0xFU;
|
|
ptl->stateUnion.stateBitField.NakCnt = 0xFU;
|
|
ptl->control2Union.stateBitField.SE =
|
|
(USB_SPEED_LOW == ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed) ? 2U : 0U;
|
|
if (0U != ptl->control2Union.stateBitField.S)
|
|
{
|
|
sptl->control2Union.stateBitField.PortNumber =
|
|
#if (defined(USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB > 0U))
|
|
((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->hsHubPort;
|
|
#else
|
|
0U;
|
|
#endif
|
|
sptl->control2Union.stateBitField.HubAddress =
|
|
#if (defined(USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB > 0U))
|
|
((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->hsHubNumber;
|
|
#else
|
|
0U;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
sptl->control2Union.stateBitField.PortNumber = 0U;
|
|
sptl->control2Union.stateBitField.HubAddress = 0U;
|
|
}
|
|
ptl->dataUnion.dataBitField.I = 1U;
|
|
ptl->stateUnion.stateBitField.EpType = pipe->pipeCommon.pipeType;
|
|
ptl->stateUnion.stateBitField.DT = 0U;
|
|
ptl->stateUnion.stateBitField.P = 0U;
|
|
|
|
return kStatus_USB_Success;
|
|
}
|
|
#endif
|
|
|
|
static usb_status_t USB_HostIp3516HsCancelPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe,
|
|
usb_host_transfer_t *tr)
|
|
{
|
|
usb_host_transfer_t *trCurrent;
|
|
usb_host_transfer_t *trPos;
|
|
usb_host_transfer_t *trPre;
|
|
uint32_t startUFrame;
|
|
uint32_t currentUFrame;
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
indexLength_t indexLength;
|
|
#endif
|
|
usb_status_t trStatus = kStatus_USB_Success;
|
|
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_BULK:
|
|
case USB_ENDPOINT_CONTROL:
|
|
usbHostState->usbRegBase->ATL_PTD_SKIP_MAP |= 1UL << pipe->tdIndex;
|
|
break;
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
usbHostState->usbRegBase->INT_PTD_SKIP_MAP |= 1UL << pipe->tdIndex;
|
|
break;
|
|
#endif
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
usbHostState->usbRegBase->ISO_PTD_SKIP_MAP |= ((1UL << USB_HOST_IP3516HS_ISO_MULTIPLE_TRANSFER) - 1U)
|
|
<< pipe->tdIndex;
|
|
break;
|
|
#endif
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
startUFrame = (uint32_t)((usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
currentUFrame = startUFrame;
|
|
|
|
while (currentUFrame == startUFrame)
|
|
{
|
|
currentUFrame = (uint32_t)((usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
}
|
|
|
|
USB_HostIp3516HsLock();
|
|
trCurrent = pipe->trList;
|
|
trPre = NULL;
|
|
while (NULL != trCurrent)
|
|
{
|
|
trPos = trCurrent->next;
|
|
if ((NULL == tr) || (tr == trCurrent))
|
|
{
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_BULK:
|
|
case USB_ENDPOINT_CONTROL:
|
|
trCurrent->transferSofar += s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer;
|
|
if (1U ==
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].stateUnion.stateBitField.H)
|
|
{
|
|
trStatus = kStatus_USB_TransferStall;
|
|
}
|
|
else if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.B) &&
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.X))
|
|
{
|
|
trStatus = kStatus_USB_TransferFailed;
|
|
}
|
|
else
|
|
{
|
|
if (((trCurrent->transferSofar != trCurrent->transferLength) ||
|
|
(pipe->pipeCommon.pipeType == USB_ENDPOINT_CONTROL)) &&
|
|
(kStatus_USB_Success == trStatus))
|
|
{
|
|
if (kStatus_USB_Success == (usb_status_t)trCurrent->union1.transferResult)
|
|
{
|
|
trStatus = kStatus_USB_TransferCancel;
|
|
}
|
|
else
|
|
{
|
|
trStatus = kStatus_USB_TransferFailed;
|
|
trCurrent->union1.transferResult = (int32_t)kStatus_USB_Success;
|
|
}
|
|
}
|
|
}
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].stateUnion.stateBitField.A = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].control1Union.stateBitField.V =
|
|
0U;
|
|
break;
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
trCurrent->transferSofar += s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer;
|
|
if (0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.H)
|
|
{
|
|
trStatus = kStatus_USB_TransferStall;
|
|
}
|
|
else if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.B) &&
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.X))
|
|
{
|
|
trStatus = kStatus_USB_TransferFailed;
|
|
}
|
|
else
|
|
{
|
|
if ((0U == trCurrent->transferSofar) && (kStatus_USB_Success == trStatus))
|
|
{
|
|
trStatus = kStatus_USB_TransferCancel;
|
|
}
|
|
}
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.A = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.control1Union.stateBitField.V = 0U;
|
|
break;
|
|
#endif
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
indexLength.indexLength = trCurrent->union2.frame;
|
|
trCurrent->union2.frame = 0;
|
|
if (0U != indexLength.indexLength)
|
|
{
|
|
trCurrent->transferSofar += s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer;
|
|
if (0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.stateUnion.stateBitField.H)
|
|
{
|
|
trStatus = kStatus_USB_TransferStall;
|
|
}
|
|
else if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.stateUnion.stateBitField.B) &&
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.stateUnion.stateBitField.X))
|
|
{
|
|
trStatus = kStatus_USB_TransferFailed;
|
|
}
|
|
else
|
|
{
|
|
if ((0U == trCurrent->transferSofar) && (kStatus_USB_Success == trStatus))
|
|
{
|
|
trStatus = kStatus_USB_TransferCancel;
|
|
}
|
|
}
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.stateUnion.stateBitField.A = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.control1Union.stateBitField.V = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.dataUnion.dataBitField.NrBytesToTransfer = 0U;
|
|
}
|
|
else
|
|
{
|
|
trStatus = kStatus_USB_TransferCancel;
|
|
}
|
|
pipe->bufferIndex = indexLength.state.bufferIndex;
|
|
pipe->bufferLength = indexLength.state.bufferLength;
|
|
break;
|
|
#endif
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
|
|
if (0UL != pipe->bufferLength)
|
|
{
|
|
(void)USB_HostIp3516HsFreeBuffer(usbHostState, pipe->bufferIndex, pipe->bufferLength);
|
|
pipe->bufferLength = 0U;
|
|
}
|
|
if (NULL != trPre)
|
|
{
|
|
trPre->next = trPos;
|
|
}
|
|
else
|
|
{
|
|
pipe->trList = trPos;
|
|
}
|
|
pipe->cutOffTime = USB_HOST_IP3516HS_TRANSFER_TIMEOUT_GAP;
|
|
pipe->isBusy = 0U;
|
|
/* callback function is different from the current condition */
|
|
trCurrent->callbackFn(trCurrent->callbackParam, trCurrent, trStatus); /* transfer callback */
|
|
}
|
|
else
|
|
{
|
|
trPre = trCurrent;
|
|
}
|
|
trCurrent = trPos;
|
|
}
|
|
USB_HostIp3516HsUnlock();
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_BULK:
|
|
case USB_ENDPOINT_CONTROL:
|
|
usbHostState->usbRegBase->ATL_PTD_SKIP_MAP &= ~(1UL << pipe->tdIndex);
|
|
break;
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
usbHostState->usbRegBase->INT_PTD_SKIP_MAP &= ~(1UL << pipe->tdIndex);
|
|
break;
|
|
#endif
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
usbHostState->usbRegBase->ISO_PTD_SKIP_MAP &=
|
|
~(((1UL << USB_HOST_IP3516HS_ISO_MULTIPLE_TRANSFER) - 1U) << pipe->tdIndex);
|
|
break;
|
|
#endif
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsCloseControlBulkPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe)
|
|
{
|
|
OSA_SR_ALLOC();
|
|
|
|
(void)USB_HostIp3516HsCancelPipe(usbHostState, pipe, NULL);
|
|
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].control1Union.stateBitField.V = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].control1Union.stateBitField.MaxPacketLength =
|
|
0U;
|
|
/* Exit critical */
|
|
OSA_EXIT_CRITICAL();
|
|
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
static usb_status_t USB_HostIp3516HsCloseIsoPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe)
|
|
{
|
|
OSA_SR_ALLOC();
|
|
|
|
(void)USB_HostIp3516HsCancelPipe(usbHostState, pipe, NULL);
|
|
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
|
|
for (uint32_t i = 0; i < USB_HOST_IP3516HS_ISO_MULTIPLE_TRANSFER; i++)
|
|
{
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[pipe->tdIndex + i].control1Union.stateBitField.V = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[pipe->tdIndex + i]
|
|
.control1Union.stateBitField.MaxPacketLength = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[pipe->tdIndex + i]
|
|
.dataUnion.dataBitField.NrBytesToTransfer = 0U;
|
|
}
|
|
/* Exit critical */
|
|
OSA_EXIT_CRITICAL();
|
|
|
|
return kStatus_USB_Success;
|
|
}
|
|
#endif
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
static usb_status_t USB_HostIp3516HsCloseInterruptPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe)
|
|
{
|
|
OSA_SR_ALLOC();
|
|
|
|
(void)USB_HostIp3516HsCancelPipe(usbHostState, pipe, NULL);
|
|
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[pipe->tdIndex].control1Union.stateBitField.V = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.control1Union.stateBitField.MaxPacketLength = 0U;
|
|
/* Exit critical */
|
|
OSA_EXIT_CRITICAL();
|
|
|
|
return kStatus_USB_Success;
|
|
}
|
|
#endif
|
|
|
|
static usb_status_t USB_HostIp3516HsGetBuffer(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
uint32_t length,
|
|
uint32_t MaxPacketSize,
|
|
uint32_t *index,
|
|
uint32_t *bufferLength)
|
|
{
|
|
uint32_t i;
|
|
uint32_t startIndex = 0xFFFFFFFFU;
|
|
uint32_t freeBufferSize = 0U;
|
|
OSA_SR_ALLOC();
|
|
|
|
OSA_ENTER_CRITICAL();
|
|
for (i = 0U; i < (sizeof(s_UsbHostIp3516HsBufferArray) / (sizeof(uint8_t) * 64U)); i++)
|
|
{
|
|
if (0U != (usbHostState->bufferArrayBitMap[i >> 5U] & (1UL << (i % 32U))))
|
|
{
|
|
freeBufferSize = 0U;
|
|
startIndex = 0xFFFFFFFFU;
|
|
}
|
|
else
|
|
{
|
|
freeBufferSize += 64U;
|
|
if (0xFFFFFFFFU == startIndex)
|
|
{
|
|
startIndex = i;
|
|
}
|
|
if (length <= freeBufferSize)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (0xFFFFFFFFU != startIndex)
|
|
{
|
|
*index = startIndex;
|
|
*bufferLength = freeBufferSize;
|
|
for (; startIndex <= i; startIndex++)
|
|
{
|
|
usbHostState->bufferArrayBitMap[startIndex >> 5U] |= (1UL << (startIndex % 32U));
|
|
}
|
|
OSA_EXIT_CRITICAL();
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
if (MaxPacketSize >= length)
|
|
{
|
|
OSA_EXIT_CRITICAL();
|
|
return kStatus_USB_Busy;
|
|
}
|
|
|
|
for (i = 0U; i < (sizeof(s_UsbHostIp3516HsBufferArray) / (sizeof(uint8_t) * 64U)); i++)
|
|
{
|
|
if (0U != (usbHostState->bufferArrayBitMap[i >> 5U] & (1UL << (i % 32U))))
|
|
{
|
|
freeBufferSize = 0U;
|
|
startIndex = 0xFFFFFFFFU;
|
|
}
|
|
else
|
|
{
|
|
freeBufferSize += 64U;
|
|
if (0xFFFFFFFFU == startIndex)
|
|
{
|
|
startIndex = i;
|
|
}
|
|
if (length <= MaxPacketSize)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (0xFFFFFFFFU != startIndex)
|
|
{
|
|
*index = startIndex;
|
|
*bufferLength = freeBufferSize;
|
|
for (; startIndex <= i; startIndex++)
|
|
{
|
|
usbHostState->bufferArrayBitMap[startIndex >> 5U] |= (1UL << (startIndex % 32U));
|
|
}
|
|
OSA_EXIT_CRITICAL();
|
|
return kStatus_USB_Success;
|
|
}
|
|
OSA_EXIT_CRITICAL();
|
|
return kStatus_USB_Busy;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsFreeBuffer(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
uint32_t index,
|
|
uint32_t bufferLength)
|
|
{
|
|
uint32_t i;
|
|
uint32_t indexCount = (bufferLength - 1U) / 64U + 1U;
|
|
if ((indexCount + index) > (sizeof(s_UsbHostIp3516HsBufferArray) / (sizeof(uint8_t) * 64U)))
|
|
{
|
|
indexCount = (sizeof(s_UsbHostIp3516HsBufferArray) / (sizeof(uint8_t) * 64U)) - index;
|
|
}
|
|
for (i = index; i < (index + indexCount); i++)
|
|
{
|
|
usbHostState->bufferArrayBitMap[i >> 5U] &= ~(1UL << (i % 32U));
|
|
}
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsWriteControlPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe,
|
|
usb_host_transfer_t *tr)
|
|
{
|
|
usb_host_ip3516hs_atl_struct_t *atl = &s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex];
|
|
uint8_t *bufferAddress;
|
|
uint32_t transferLength;
|
|
usb_status_t status = kStatus_USB_Success;
|
|
usb_host_ip3516hs_transfer_status_t transferStstus;
|
|
#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
|
|
uint8_t timeCount;
|
|
#endif
|
|
OSA_SR_ALLOC();
|
|
if (1U == pipe->isBusy)
|
|
{
|
|
return kStatus_USB_Success;
|
|
}
|
|
OSA_ENTER_CRITICAL();
|
|
pipe->isBusy = 1U;
|
|
OSA_EXIT_CRITICAL();
|
|
#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
|
|
if (1U == usbHostState->complianceTest)
|
|
{
|
|
timeCount = 15 * 8; /* 15s */
|
|
while (0U != (timeCount--))
|
|
{
|
|
USB_HostIp3516HsDelay(usbHostState, 1000U);
|
|
}
|
|
}
|
|
#endif
|
|
transferStstus = (usb_host_ip3516hs_transfer_status_t)tr->setupStatus;
|
|
switch (transferStstus)
|
|
{
|
|
case kStatus_UsbHostIp3516Hs_Idle:
|
|
if (0U != pipe->bufferLength)
|
|
{
|
|
bufferAddress = (uint8_t *)&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0];
|
|
}
|
|
else
|
|
{
|
|
transferLength = pipe->pipeCommon.maxPacketSize;
|
|
if (kStatus_USB_Success == USB_HostIp3516HsGetBuffer(usbHostState, transferLength,
|
|
pipe->pipeCommon.maxPacketSize, &pipe->bufferIndex,
|
|
&pipe->bufferLength))
|
|
{
|
|
bufferAddress = (uint8_t *)&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0];
|
|
}
|
|
else
|
|
{
|
|
OSA_ENTER_CRITICAL();
|
|
pipe->isBusy = 2U;
|
|
OSA_EXIT_CRITICAL();
|
|
return kStatus_USB_Success;
|
|
}
|
|
}
|
|
for (uint8_t i = 0; i < 8U; i++)
|
|
{
|
|
bufferAddress[i] = ((uint8_t *)tr->setupPacket)[i];
|
|
}
|
|
atl->control2Union.stateBitField.RL = 0U;
|
|
atl->stateUnion.stateBitField.P = 0U;
|
|
atl->stateUnion.stateBitField.NakCnt = 0U;
|
|
atl->stateUnion.stateBitField.Cerr = 0x3U;
|
|
atl->dataUnion.dataBitField.NrBytesToTransfer = 8U;
|
|
atl->stateUnion.stateBitField.NrBytesToTransfer = 0U;
|
|
atl->dataUnion.dataBitField.DataStartAddress = ((uint32_t)(bufferAddress)) & 0x0000FFFFU;
|
|
atl->dataUnion.dataBitField.I = 1U;
|
|
atl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_SETUP;
|
|
atl->stateUnion.stateBitField.DT = 0x00U;
|
|
atl->stateUnion.stateBitField.SC = 0x00U;
|
|
tr->setupStatus = (uint8_t)kStatus_UsbHostIp3516Hs_Setup;
|
|
atl->control1Union.stateBitField.V = 0x01U;
|
|
atl->stateUnion.stateBitField.A = 0x01U;
|
|
break;
|
|
case kStatus_UsbHostIp3516Hs_Data2:
|
|
case kStatus_UsbHostIp3516Hs_Setup:
|
|
transferLength = (tr->transferLength - tr->transferSofar);
|
|
if (transferLength > pipe->bufferLength)
|
|
{
|
|
transferLength = pipe->bufferLength;
|
|
}
|
|
bufferAddress = (uint8_t *)&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0];
|
|
if (USB_OUT == tr->direction)
|
|
{
|
|
for (uint32_t i = 0; i < transferLength; i++)
|
|
{
|
|
bufferAddress[i] = tr->transferBuffer[tr->transferSofar + i];
|
|
}
|
|
}
|
|
atl->control2Union.stateBitField.RL = 0U;
|
|
atl->stateUnion.stateBitField.NakCnt = 0U;
|
|
atl->stateUnion.stateBitField.Cerr = 0x3U;
|
|
atl->dataUnion.dataBitField.NrBytesToTransfer = transferLength;
|
|
atl->stateUnion.stateBitField.NrBytesToTransfer = 0U;
|
|
atl->dataUnion.dataBitField.DataStartAddress = ((uint32_t)(bufferAddress)) & 0x0000FFFFU;
|
|
atl->dataUnion.dataBitField.I = 1U;
|
|
atl->stateUnion.stateBitField.SC = 0x00U;
|
|
if (0U != transferLength)
|
|
{
|
|
if (USB_IN == tr->direction)
|
|
{
|
|
atl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_IN;
|
|
atl->stateUnion.stateBitField.P = 0x00U;
|
|
}
|
|
else
|
|
{
|
|
atl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_OUT;
|
|
}
|
|
if (transferLength < (tr->transferLength - tr->transferSofar))
|
|
{
|
|
tr->setupStatus = (uint8_t)kStatus_UsbHostIp3516Hs_Data2;
|
|
}
|
|
else
|
|
{
|
|
tr->setupStatus = (uint8_t)kStatus_UsbHostIp3516Hs_Data;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
atl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_IN;
|
|
tr->setupStatus = (uint8_t)kStatus_UsbHostIp3516Hs_State;
|
|
}
|
|
atl->control1Union.stateBitField.V = 0x01U;
|
|
atl->stateUnion.stateBitField.A = 0x01U;
|
|
break;
|
|
case kStatus_UsbHostIp3516Hs_Data:
|
|
tr->setupStatus = (uint8_t)kStatus_UsbHostIp3516Hs_State;
|
|
bufferAddress = (uint8_t *)&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0];
|
|
atl->control2Union.stateBitField.RL = 0U;
|
|
atl->stateUnion.stateBitField.NakCnt = 0U;
|
|
atl->stateUnion.stateBitField.Cerr = 0x3U;
|
|
atl->dataUnion.dataBitField.NrBytesToTransfer = 0;
|
|
atl->stateUnion.stateBitField.NrBytesToTransfer = 0U;
|
|
atl->dataUnion.dataBitField.DataStartAddress = ((uint32_t)(bufferAddress)) & 0x0000FFFFU;
|
|
atl->dataUnion.dataBitField.I = 1U;
|
|
atl->stateUnion.stateBitField.DT = 1U;
|
|
atl->stateUnion.stateBitField.P = 0x00U;
|
|
atl->stateUnion.stateBitField.SC = 0x00U;
|
|
if (USB_OUT == tr->direction)
|
|
{
|
|
atl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_IN;
|
|
}
|
|
else
|
|
{
|
|
atl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_OUT;
|
|
}
|
|
atl->control1Union.stateBitField.V = 0x01U;
|
|
atl->stateUnion.stateBitField.A = 0x01U;
|
|
|
|
break;
|
|
default:
|
|
status = kStatus_USB_Error;
|
|
tr->setupStatus = (uint8_t)kStatus_UsbHostIp3516Hs_Idle;
|
|
OSA_ENTER_CRITICAL();
|
|
pipe->isBusy = 0U;
|
|
OSA_EXIT_CRITICAL();
|
|
break;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsWriteBulkPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe,
|
|
usb_host_transfer_t *tr)
|
|
{
|
|
usb_host_ip3516hs_atl_struct_t *atl = &s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex];
|
|
uint32_t transferLength;
|
|
uint8_t *bufferAddress;
|
|
OSA_SR_ALLOC();
|
|
|
|
if (1U == pipe->isBusy)
|
|
{
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
OSA_ENTER_CRITICAL();
|
|
pipe->isBusy = 1U;
|
|
OSA_EXIT_CRITICAL();
|
|
|
|
transferLength = (tr->transferLength - tr->transferSofar);
|
|
if (0U != pipe->bufferLength)
|
|
{
|
|
bufferAddress = (uint8_t *)&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0];
|
|
}
|
|
else
|
|
{
|
|
if (transferLength > 4096U)
|
|
{
|
|
transferLength = 4096U;
|
|
}
|
|
if (kStatus_USB_Success == USB_HostIp3516HsGetBuffer(usbHostState, transferLength,
|
|
pipe->pipeCommon.maxPacketSize, &pipe->bufferIndex,
|
|
&pipe->bufferLength))
|
|
{
|
|
bufferAddress = (uint8_t *)&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0];
|
|
}
|
|
else
|
|
{
|
|
OSA_ENTER_CRITICAL();
|
|
pipe->isBusy = 2U;
|
|
OSA_EXIT_CRITICAL();
|
|
return kStatus_USB_Success;
|
|
}
|
|
}
|
|
if (transferLength > pipe->bufferLength)
|
|
{
|
|
transferLength = pipe->bufferLength;
|
|
}
|
|
/*transferLength should be positive*/
|
|
if ((USB_OUT == tr->direction) && (transferLength > 0U))
|
|
{
|
|
(void)memcpy((void *)bufferAddress, (void *)(&tr->transferBuffer[tr->transferSofar]), transferLength);
|
|
}
|
|
|
|
atl->control2Union.stateBitField.RL = 0U;
|
|
atl->stateUnion.stateBitField.NakCnt = 0U;
|
|
atl->stateUnion.stateBitField.Cerr = 0x3U;
|
|
atl->dataUnion.dataBitField.NrBytesToTransfer = transferLength;
|
|
atl->stateUnion.stateBitField.NrBytesToTransfer = 0U;
|
|
atl->dataUnion.dataBitField.DataStartAddress = ((uint32_t)(bufferAddress)) & 0x0000FFFFU;
|
|
atl->dataUnion.dataBitField.I = 1U;
|
|
atl->stateUnion.stateBitField.SC = 0x00U;
|
|
if (USB_IN == tr->direction)
|
|
{
|
|
atl->stateUnion.stateBitField.P = 0x00U;
|
|
atl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_IN;
|
|
}
|
|
else
|
|
{
|
|
atl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_OUT;
|
|
}
|
|
atl->control1Union.stateBitField.V = 0x01U;
|
|
atl->stateUnion.stateBitField.A = 0x01U;
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
static usb_status_t USB_HostIp3516HsWriteIsoPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe,
|
|
usb_host_transfer_t *tr)
|
|
{
|
|
usb_host_ip3516hs_ptl_struct_t *ptl;
|
|
usb_host_ip3516hs_sptl_struct_t *sptl;
|
|
usb_host_transfer_t *currentTr;
|
|
uint32_t transferLength;
|
|
uint32_t currentUFrame;
|
|
uint32_t insertUFrame;
|
|
uint32_t primedUFrame;
|
|
uint32_t tdIndex;
|
|
indexLength_t indexLength;
|
|
uint8_t *bufferAddress;
|
|
void *temp;
|
|
uint8_t speed = ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed;
|
|
OSA_SR_ALLOC();
|
|
|
|
OSA_ENTER_CRITICAL();
|
|
|
|
currentTr = tr;
|
|
while (NULL != currentTr)
|
|
{
|
|
transferLength = (currentTr->transferLength - currentTr->transferSofar);
|
|
indexLength.indexLength = currentTr->union2.frame;
|
|
if (0U == indexLength.indexLength)
|
|
{
|
|
uint32_t bufferIndex;
|
|
uint32_t bufferLength;
|
|
|
|
tdIndex = 0xFFU;
|
|
for (uint32_t i = 0U; i < (USB_HOST_IP3516HS_ISO_MULTIPLE_TRANSFER); i++)
|
|
{
|
|
ptl = &s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[pipe->tdIndex + i];
|
|
if (0U == ptl->dataUnion.dataBitField.NrBytesToTransfer)
|
|
{
|
|
tdIndex = pipe->tdIndex + i;
|
|
temp = (void *)ptl;
|
|
sptl = (usb_host_ip3516hs_sptl_struct_t *)temp;
|
|
break;
|
|
}
|
|
}
|
|
if (0xFFUL == tdIndex)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (kStatus_USB_Success == USB_HostIp3516HsGetBuffer(usbHostState, transferLength,
|
|
pipe->pipeCommon.maxPacketSize, &bufferIndex,
|
|
&bufferLength))
|
|
{
|
|
indexLength.state.bufferIndex = bufferIndex;
|
|
indexLength.state.bufferLength = bufferLength;
|
|
bufferAddress = (uint8_t *)&s_UsbHostIp3516HsBufferArray[indexLength.state.bufferIndex][0];
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
indexLength.state.tdIndex = tdIndex;
|
|
currentTr->union2.frame = indexLength.indexLength;
|
|
}
|
|
else
|
|
{
|
|
currentTr = currentTr->next;
|
|
continue;
|
|
}
|
|
|
|
if (transferLength > indexLength.state.bufferLength)
|
|
{
|
|
transferLength = indexLength.state.bufferLength;
|
|
}
|
|
|
|
if (USB_OUT == currentTr->direction)
|
|
{
|
|
for (uint32_t i = 0; i < transferLength; i++)
|
|
{
|
|
bufferAddress[i] = currentTr->transferBuffer[currentTr->transferSofar + i];
|
|
}
|
|
}
|
|
|
|
if (USB_SPEED_HIGH != speed)
|
|
{
|
|
if (transferLength > pipe->pipeCommon.maxPacketSize)
|
|
{
|
|
transferLength = pipe->pipeCommon.maxPacketSize;
|
|
}
|
|
}
|
|
ptl->control2Union.stateBitField.RL = 0U;
|
|
ptl->stateUnion.stateBitField.NakCnt = 0U;
|
|
ptl->stateUnion.stateBitField.Cerr = 0U;
|
|
ptl->dataUnion.dataBitField.NrBytesToTransfer = transferLength;
|
|
ptl->stateUnion.stateBitField.NrBytesToTransfer = 0U;
|
|
ptl->dataUnion.dataBitField.DataStartAddress = ((uint32_t)(bufferAddress)) & 0x0000FFFFU;
|
|
ptl->dataUnion.dataBitField.I = 1U;
|
|
ptl->stateUnion.stateBitField.SC = 0x00U;
|
|
|
|
ptl->stateUnion.stateBitField.H = 0U;
|
|
ptl->stateUnion.stateBitField.X = 0U;
|
|
ptl->stateUnion.stateBitField.B = 0U;
|
|
if (USB_IN == currentTr->direction)
|
|
{
|
|
ptl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_IN;
|
|
}
|
|
else
|
|
{
|
|
ptl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_OUT;
|
|
}
|
|
|
|
ptl->statusUnion.status = 0U;
|
|
ptl->isoInUnion1.isoIn = 0U;
|
|
ptl->isoInUnion2.isoIn = 0U;
|
|
ptl->isoInUnion3.isoIn = 0U;
|
|
|
|
currentUFrame = (uint32_t)((usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
currentUFrame = currentUFrame & 0xFFU;
|
|
|
|
primedUFrame = ((uint32_t)pipe->lastPrimedIndex + pipe->pipeCommon.interval) & 0xFFU;
|
|
|
|
if (primedUFrame < currentUFrame)
|
|
{
|
|
primedUFrame = primedUFrame + 0x100U;
|
|
}
|
|
if (primedUFrame >= (currentUFrame + USB_HOST_IP3516HS_PERIODIC_TRANSFER_GAP))
|
|
{
|
|
primedUFrame = primedUFrame & 0xFFU;
|
|
insertUFrame = primedUFrame;
|
|
}
|
|
else
|
|
{
|
|
insertUFrame =
|
|
pipe->startUFrame + ((currentUFrame - pipe->startUFrame + USB_HOST_IP3516HS_PERIODIC_TRANSFER_GAP +
|
|
pipe->pipeCommon.interval - 1U) &
|
|
(~(pipe->pipeCommon.interval - 1U)));
|
|
}
|
|
|
|
pipe->lastPrimedIndex = (uint16_t)insertUFrame;
|
|
|
|
if (USB_SPEED_HIGH == speed)
|
|
{
|
|
uint32_t primedLength = currentTr->transferSofar;
|
|
ptl->control1Union.stateBitField.uFrame = insertUFrame & 0xF8U;
|
|
ptl->statusUnion.statusBitField.uSA = 0U;
|
|
|
|
for (uint16_t i = (uint16_t)(insertUFrame & 0x07UL); (i < 8U); i += pipe->pipeCommon.interval)
|
|
{
|
|
primedLength += (uint32_t)pipe->pipeCommon.maxPacketSize * pipe->pipeCommon.numberPerUframe;
|
|
ptl->statusUnion.statusBitField.uSA |= 1UL << i;
|
|
if (primedLength >= currentTr->transferLength)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (0U != (ptl->control2Union.stateBitField.S))
|
|
{
|
|
#if (defined(FSL_FEATURE_USBHSH_VERSION) && (FSL_FEATURE_USBHSH_VERSION >= 300U))
|
|
if (USB_IN == currentTr->direction)
|
|
{
|
|
if (transferLength <= 192U)
|
|
{
|
|
sptl->control1Union.stateBitField.MaxPacketLength = transferLength;
|
|
}
|
|
else
|
|
{
|
|
sptl->control1Union.stateBitField.MaxPacketLength = 192U;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (transferLength <= 188U)
|
|
{
|
|
#if (defined(FSL_FEATURE_USBHSH_VERSION) && (FSL_FEATURE_USBHSH_VERSION >= 300U))
|
|
sptl->control1Union.stateBitField.MaxPacketLength = transferLength;
|
|
#else
|
|
sptl->control1Union.stateBitField.MaxPacketLength = transferLength + 1U;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
sptl->control1Union.stateBitField.MaxPacketLength = 188U;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sptl->control1Union.stateBitField.MaxPacketLength = pipe->pipeCommon.maxPacketSize;
|
|
}
|
|
sptl->control1Union.stateBitField.uFrame = insertUFrame & 0xF8U;
|
|
sptl->statusUnion.statusBitField.uSA = pipe->ssSlot;
|
|
sptl->isoInUnion1.bitField.uSCS = pipe->csSlot;
|
|
}
|
|
|
|
ptl->control1Union.stateBitField.V = 0x01U;
|
|
ptl->stateUnion.stateBitField.A = 0x01U;
|
|
|
|
currentTr = currentTr->next;
|
|
}
|
|
OSA_EXIT_CRITICAL();
|
|
return kStatus_USB_Success;
|
|
}
|
|
#endif
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
static usb_status_t USB_HostIp3516HsWriteInterruptPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
usb_host_ip3516hs_pipe_struct_t *pipe,
|
|
usb_host_transfer_t *tr)
|
|
{
|
|
usb_host_ip3516hs_ptl_struct_t *ptl = &s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[pipe->tdIndex];
|
|
usb_host_ip3516hs_sptl_struct_t *sptl;
|
|
uint32_t transferLength;
|
|
uint32_t currentUFrame;
|
|
uint32_t insertUFrame;
|
|
uint8_t *bufferAddress;
|
|
void *temp;
|
|
uint8_t speed = ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed;
|
|
temp = (void *)ptl;
|
|
sptl = (usb_host_ip3516hs_sptl_struct_t *)temp;
|
|
OSA_SR_ALLOC();
|
|
|
|
if (1U == pipe->isBusy)
|
|
{
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
OSA_ENTER_CRITICAL();
|
|
pipe->isBusy = 1U;
|
|
OSA_EXIT_CRITICAL();
|
|
|
|
transferLength = (tr->transferLength - tr->transferSofar);
|
|
if (transferLength > pipe->pipeCommon.maxPacketSize)
|
|
{
|
|
transferLength = pipe->pipeCommon.maxPacketSize;
|
|
}
|
|
if (kStatus_USB_Success == USB_HostIp3516HsGetBuffer(usbHostState, transferLength, pipe->pipeCommon.maxPacketSize,
|
|
&pipe->bufferIndex, &pipe->bufferLength))
|
|
{
|
|
bufferAddress = (uint8_t *)&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0];
|
|
}
|
|
else
|
|
{
|
|
OSA_ENTER_CRITICAL();
|
|
pipe->isBusy = 2U;
|
|
OSA_EXIT_CRITICAL();
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
if (USB_OUT == tr->direction)
|
|
{
|
|
for (uint32_t i = 0; i < transferLength; i++)
|
|
{
|
|
bufferAddress[i] = tr->transferBuffer[tr->transferSofar + i];
|
|
}
|
|
}
|
|
|
|
ptl->control2Union.stateBitField.RL = 0U;
|
|
ptl->stateUnion.stateBitField.NakCnt = 0x0FU;
|
|
ptl->stateUnion.stateBitField.Cerr = 0x3U;
|
|
ptl->dataUnion.dataBitField.NrBytesToTransfer = transferLength;
|
|
ptl->stateUnion.stateBitField.NrBytesToTransfer = 0U;
|
|
ptl->dataUnion.dataBitField.DataStartAddress = ((uint32_t)(bufferAddress)) & 0x0000FFFFU;
|
|
ptl->dataUnion.dataBitField.I = 1U;
|
|
ptl->stateUnion.stateBitField.P = 0x00U;
|
|
ptl->stateUnion.stateBitField.SC = 0x00U;
|
|
if (USB_IN == tr->direction)
|
|
{
|
|
ptl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_IN;
|
|
}
|
|
else
|
|
{
|
|
ptl->stateUnion.stateBitField.Token = USB_HOST_IP3516HS_PTD_TOKEN_OUT;
|
|
}
|
|
|
|
ptl->statusUnion.status = 0U;
|
|
ptl->isoInUnion1.isoIn = 0U;
|
|
ptl->isoInUnion2.isoIn = 0U;
|
|
ptl->isoInUnion3.isoIn = 0U;
|
|
|
|
currentUFrame = (uint32_t)((usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
currentUFrame = currentUFrame & 0xFFU;
|
|
|
|
insertUFrame = pipe->startUFrame + ((currentUFrame - pipe->startUFrame + USB_HOST_IP3516HS_PERIODIC_TRANSFER_GAP +
|
|
pipe->pipeCommon.interval - 1U) &
|
|
(~(pipe->pipeCommon.interval - 1U)));
|
|
|
|
ptl->control1Union.stateBitField.uFrame = (insertUFrame & 0xF8U);
|
|
switch (pipe->pipeCommon.interval)
|
|
{
|
|
case 1:
|
|
case 2:
|
|
case 4:
|
|
case 8:
|
|
break;
|
|
case 16:
|
|
ptl->control1Union.stateBitField.uFrame |= 1U;
|
|
break;
|
|
case 32:
|
|
ptl->control1Union.stateBitField.uFrame |= 2U;
|
|
break;
|
|
case 64:
|
|
ptl->control1Union.stateBitField.uFrame |= 3U;
|
|
break;
|
|
case 128:
|
|
ptl->control1Union.stateBitField.uFrame |= 4U;
|
|
break;
|
|
case 256:
|
|
ptl->control1Union.stateBitField.uFrame |= 5U;
|
|
break;
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
|
|
if (USB_SPEED_HIGH == speed)
|
|
{
|
|
for (uint32_t i = (insertUFrame & 0x07U); i < 8U; i += pipe->pipeCommon.interval)
|
|
{
|
|
ptl->statusUnion.statusBitField.uSA |= 1UL << i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sptl->statusUnion.statusBitField.uSA = pipe->ssSlot;
|
|
sptl->isoInUnion1.bitField.uSCS = pipe->csSlot;
|
|
}
|
|
|
|
ptl->control1Union.stateBitField.V = 0x01U;
|
|
ptl->stateUnion.stateBitField.A = 0x01U;
|
|
return kStatus_USB_Success;
|
|
}
|
|
#endif
|
|
|
|
static usb_host_ip3516hs_pipe_struct_t *USB_HostIp3516HsGetPipe(usb_host_ip3516hs_state_struct_t *usbHostState,
|
|
uint8_t pipeType,
|
|
uint8_t tdIndex)
|
|
{
|
|
usb_host_ip3516hs_pipe_struct_t *p = usbHostState->pipeListInUsing;
|
|
void *temp;
|
|
OSA_SR_ALLOC();
|
|
|
|
OSA_ENTER_CRITICAL();
|
|
while (p != NULL)
|
|
{
|
|
if ((p->pipeCommon.pipeType == pipeType) && (p->tdIndex == tdIndex))
|
|
{
|
|
OSA_EXIT_CRITICAL();
|
|
return p;
|
|
}
|
|
if ((p->pipeCommon.pipeType == pipeType) && (USB_ENDPOINT_ISOCHRONOUS == pipeType) && (p->tdIndex >= tdIndex) &&
|
|
(tdIndex < (p->tdIndex + USB_HOST_IP3516HS_ISO_MULTIPLE_TRANSFER)))
|
|
{
|
|
OSA_EXIT_CRITICAL();
|
|
return p;
|
|
}
|
|
temp = (void *)p->pipeCommon.next;
|
|
p = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
}
|
|
OSA_EXIT_CRITICAL();
|
|
return NULL;
|
|
}
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
static usb_status_t USB_HostIp3516HsCheckIsoTransferSofar(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
uint32_t tokenDoneBits = usbHostState->usbRegBase->ISO_PTD_DONE_MAP;
|
|
usb_host_ip3516hs_pipe_struct_t *p;
|
|
|
|
if (0U == tokenDoneBits)
|
|
{
|
|
return kStatus_USB_Success;
|
|
}
|
|
for (uint8_t i = 0; i < 32U; i++)
|
|
{
|
|
if (0U != (tokenDoneBits & (1UL << i)))
|
|
{
|
|
if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[i].stateUnion.stateBitField.A) &&
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[i].control1Union.stateBitField.V))
|
|
{
|
|
continue;
|
|
}
|
|
p = USB_HostIp3516HsGetPipe(usbHostState, USB_ENDPOINT_ISOCHRONOUS, i);
|
|
if (NULL != p)
|
|
{
|
|
p->isBusy = 0U;
|
|
#if 0
|
|
if (NULL != p->trList)
|
|
{
|
|
usb_host_transfer_t *trCurrent = p->trList;
|
|
if ((s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[p->tdIndex].stateUnion.stateBitField.B) ||
|
|
(s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[p->tdIndex].stateUnion.stateBitField.X))
|
|
{
|
|
trCurrent->union1.transferResult = kStatus_USB_TransferFailed;
|
|
}
|
|
else
|
|
{
|
|
trCurrent->union1.transferResult = kStatus_USB_Success;
|
|
}
|
|
if (USB_IN == trCurrent->direction)
|
|
{
|
|
memcpy(&trCurrent->transferBuffer[trCurrent->transferSofar], &s_UsbHostIp3516HsBufferArray[p->bufferIndex][0], s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[p->tdIndex].stateUnion.stateBitField.NrBytesToTransfer);
|
|
}
|
|
trCurrent->transferSofar += s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[p->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer;
|
|
if (p->trList)
|
|
{
|
|
p->currentTr = p->trList->next;
|
|
}
|
|
else
|
|
{
|
|
p->currentTr = NULL;
|
|
}
|
|
if (p->currentTr)
|
|
{
|
|
uint32_t trValue = (uint32_t)p->currentTr;
|
|
USB_HostIp3516HsWriteIsoPipe(usbHostState, p, (usb_host_transfer_t *)trValue);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
usbHostState->usbRegBase->ISO_PTD_DONE_MAP = tokenDoneBits;
|
|
return kStatus_USB_Success;
|
|
}
|
|
#endif
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
static usb_status_t USB_HostIp3516HsCheckIntTransferSofar(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
uint32_t tokenDoneBits = usbHostState->usbRegBase->INT_PTD_DONE_MAP;
|
|
usb_host_ip3516hs_pipe_struct_t *p;
|
|
|
|
if (0U == tokenDoneBits)
|
|
{
|
|
return kStatus_USB_Success;
|
|
}
|
|
for (uint8_t i = 0; i < 32U; i++)
|
|
{
|
|
if (0U != (tokenDoneBits & (1UL << i)))
|
|
{
|
|
if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[i].stateUnion.stateBitField.A) &&
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[i].control1Union.stateBitField.V))
|
|
{
|
|
continue;
|
|
}
|
|
p = USB_HostIp3516HsGetPipe(usbHostState, USB_ENDPOINT_INTERRUPT, i);
|
|
if (NULL != p)
|
|
{
|
|
p->isBusy = 0U;
|
|
}
|
|
}
|
|
}
|
|
usbHostState->usbRegBase->INT_PTD_DONE_MAP = tokenDoneBits;
|
|
return kStatus_USB_Success;
|
|
}
|
|
#endif
|
|
|
|
static usb_status_t USB_HostIp3516HsCheckAtlTransferSofar(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
uint32_t tokenDoneBits = usbHostState->usbRegBase->ATL_PTD_DONE_MAP;
|
|
usb_host_ip3516hs_pipe_struct_t *p;
|
|
|
|
if (0U == tokenDoneBits)
|
|
{
|
|
return kStatus_USB_Success;
|
|
}
|
|
for (uint8_t i = 0; i < 32U; i++)
|
|
{
|
|
if (0U != (tokenDoneBits & (1UL << i)))
|
|
{
|
|
p = USB_HostIp3516HsGetPipe(usbHostState, USB_ENDPOINT_CONTROL, i);
|
|
if (NULL != p)
|
|
{
|
|
p->isBusy = 0U;
|
|
}
|
|
p = USB_HostIp3516HsGetPipe(usbHostState, USB_ENDPOINT_BULK, i);
|
|
if ((NULL != p))
|
|
{
|
|
p->isBusy = 0U;
|
|
}
|
|
}
|
|
}
|
|
usbHostState->usbRegBase->ATL_PTD_DONE_MAP = tokenDoneBits;
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
static void USB_HostIp3516HsCheckGetBufferFailedPipe(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
usb_host_ip3516hs_pipe_struct_t *pipe = usbHostState->pipeListInUsing;
|
|
void *temp;
|
|
while (NULL != pipe)
|
|
{
|
|
if (2U == pipe->isBusy)
|
|
{
|
|
if (NULL != pipe->trList)
|
|
{
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_BULK:
|
|
(void)USB_HostIp3516HsWriteBulkPipe(usbHostState, pipe, pipe->trList);
|
|
break;
|
|
|
|
case USB_ENDPOINT_CONTROL:
|
|
(void)USB_HostIp3516HsWriteControlPipe(usbHostState, pipe, pipe->trList);
|
|
break;
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
(void)USB_HostIp3516HsWriteIsoPipe(usbHostState, pipe, pipe->trList);
|
|
break;
|
|
#endif
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
(void)USB_HostIp3516HsWriteInterruptPipe(usbHostState, pipe, pipe->trList);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
}
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsTokenDone(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
usb_host_ip3516hs_pipe_struct_t *pipe;
|
|
usb_host_transfer_t *trCurrent;
|
|
usb_host_ip3516hs_pipe_struct_t *p;
|
|
uint32_t startUFrame;
|
|
uint32_t currentUFrame;
|
|
usb_host_ip3516hs_transfer_status_t transferStatus;
|
|
void *temp;
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
indexLength_t indexLength;
|
|
#endif
|
|
usb_status_t trStatus;
|
|
uint8_t trDone;
|
|
|
|
/* Enter critical */
|
|
USB_HostIp3516HsLock();
|
|
USB_HostOhciDisableIsr(usbHostState);
|
|
pipe = usbHostState->pipeListInUsing;
|
|
while (NULL != pipe)
|
|
{
|
|
trStatus = kStatus_USB_Success;
|
|
trCurrent = pipe->trList;
|
|
if (NULL == trCurrent)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
trDone = 0;
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_CONTROL:
|
|
if (0U != pipe->isBusy)
|
|
{
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
continue;
|
|
}
|
|
transferStatus = (usb_host_ip3516hs_transfer_status_t)trCurrent->setupStatus;
|
|
switch (transferStatus)
|
|
{
|
|
case kStatus_UsbHostIp3516Hs_Idle:
|
|
break;
|
|
case kStatus_UsbHostIp3516Hs_Setup:
|
|
break;
|
|
case kStatus_UsbHostIp3516Hs_Data2:
|
|
if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer) &&
|
|
(0U == (s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer %
|
|
pipe->pipeCommon.maxPacketSize)))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
trCurrent->setupStatus = (uint8_t)kStatus_UsbHostIp3516Hs_Data;
|
|
}
|
|
if (USB_IN == trCurrent->direction)
|
|
{
|
|
(void)memcpy((void *)(&trCurrent->transferBuffer[trCurrent->transferSofar]),
|
|
(void *)(&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0]),
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer);
|
|
}
|
|
trCurrent->transferSofar += s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer;
|
|
break;
|
|
case kStatus_UsbHostIp3516Hs_Data:
|
|
if (USB_IN == trCurrent->direction)
|
|
{
|
|
(void)memcpy((void *)(&trCurrent->transferBuffer[trCurrent->transferSofar]),
|
|
(void *)(&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0]),
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer);
|
|
}
|
|
trCurrent->transferSofar += s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer;
|
|
break;
|
|
case kStatus_UsbHostIp3516Hs_State:
|
|
break;
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
|
|
if (!((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.A) &&
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.control1Union.stateBitField.V)))
|
|
{
|
|
trDone = 1U;
|
|
}
|
|
|
|
if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.B) ||
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.X))
|
|
{
|
|
trStatus = kStatus_USB_TransferFailed;
|
|
}
|
|
else if (0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.H)
|
|
{
|
|
trStatus = kStatus_USB_TransferStall;
|
|
}
|
|
else
|
|
{
|
|
if (0U != trDone)
|
|
{
|
|
#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
|
|
if (1U == usbHostState->complianceTestStart)
|
|
{
|
|
usbHostState->complianceTest++;
|
|
}
|
|
#endif
|
|
(void)USB_HostIp3516HsWriteControlPipe(usbHostState, pipe, pipe->trList);
|
|
}
|
|
}
|
|
|
|
if (0U != pipe->isBusy)
|
|
{
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
continue;
|
|
}
|
|
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].stateUnion.stateBitField.H = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].stateUnion.stateBitField.X = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].stateUnion.stateBitField.B = 0U;
|
|
break;
|
|
case USB_ENDPOINT_BULK:
|
|
if (0U != pipe->isBusy)
|
|
{
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
continue;
|
|
}
|
|
|
|
if (USB_IN == trCurrent->direction)
|
|
{
|
|
uint32_t length = s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer;
|
|
(void)memcpy((void *)(&trCurrent->transferBuffer[trCurrent->transferSofar]),
|
|
(void *)(&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0]), length);
|
|
}
|
|
trCurrent->transferSofar += s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer;
|
|
|
|
if (!((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.A) &&
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.control1Union.stateBitField.V)))
|
|
{
|
|
trDone = 1U;
|
|
}
|
|
|
|
if (0U !=
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].stateUnion.stateBitField.H)
|
|
{
|
|
trStatus = kStatus_USB_TransferStall;
|
|
}
|
|
else if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.B) ||
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.stateUnion.stateBitField.X))
|
|
{
|
|
trStatus = kStatus_USB_TransferFailed;
|
|
}
|
|
else
|
|
{
|
|
if (0U != trDone)
|
|
{
|
|
if ((0U == (pipe->trList->transferLength % pipe->pipeCommon.maxPacketSize)) &&
|
|
(pipe->trList->transferSofar < pipe->trList->transferLength))
|
|
{
|
|
(void)USB_HostIp3516HsWriteBulkPipe(usbHostState, pipe, pipe->trList);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0U != pipe->isBusy)
|
|
{
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
continue;
|
|
}
|
|
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].stateUnion.stateBitField.H = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].stateUnion.stateBitField.X = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[pipe->tdIndex].stateUnion.stateBitField.B = 0U;
|
|
|
|
break;
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
if (0U != pipe->isBusy)
|
|
{
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
continue;
|
|
}
|
|
|
|
if (!((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.A) &&
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.control1Union.stateBitField.V)))
|
|
{
|
|
trDone = 1U;
|
|
}
|
|
|
|
if (USB_IN == trCurrent->direction)
|
|
{
|
|
(void)memcpy((void *)(&trCurrent->transferBuffer[trCurrent->transferSofar]),
|
|
(void *)(&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0]),
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer);
|
|
}
|
|
trCurrent->transferSofar += s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer;
|
|
|
|
if (1U == s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.H)
|
|
{
|
|
trStatus = kStatus_USB_TransferStall;
|
|
}
|
|
else if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.B) ||
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.X))
|
|
{
|
|
trStatus = kStatus_USB_TransferFailed;
|
|
}
|
|
else
|
|
{
|
|
/*no action*/
|
|
}
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.H = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.X = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.stateUnion.stateBitField.B = 0U;
|
|
break;
|
|
#endif
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
#if 1
|
|
indexLength.indexLength = trCurrent->union2.frame;
|
|
trCurrent->union2.frame = 0u;
|
|
if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.stateUnion.stateBitField.A) &&
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.control1Union.stateBitField.V))
|
|
{
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
continue;
|
|
}
|
|
|
|
pipe->bufferIndex = indexLength.state.bufferIndex;
|
|
pipe->bufferLength = indexLength.state.bufferLength;
|
|
if (USB_IN == trCurrent->direction)
|
|
{
|
|
(void)memcpy((void *)(&trCurrent->transferBuffer[trCurrent->transferSofar]),
|
|
(void *)(&s_UsbHostIp3516HsBufferArray[pipe->bufferIndex][0]),
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer);
|
|
}
|
|
trCurrent->transferSofar += s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.stateUnion.stateBitField.NrBytesToTransfer;
|
|
|
|
if ((0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.stateUnion.stateBitField.B) ||
|
|
(0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.stateUnion.stateBitField.X))
|
|
{
|
|
trCurrent->union1.transferResult = (int32_t)kStatus_USB_TransferFailed;
|
|
}
|
|
else
|
|
{
|
|
trCurrent->union1.transferResult = (int32_t)kStatus_USB_Success;
|
|
}
|
|
|
|
if (NULL != pipe->trList)
|
|
{
|
|
pipe->currentTr = pipe->trList->next;
|
|
}
|
|
else
|
|
{
|
|
pipe->currentTr = NULL;
|
|
}
|
|
|
|
if (NULL != pipe->currentTr)
|
|
{
|
|
uint32_t trValue = (uint32_t)pipe->currentTr;
|
|
(void)USB_HostIp3516HsWriteIsoPipe(usbHostState, pipe, (usb_host_transfer_t *)trValue);
|
|
}
|
|
#else
|
|
if (pipe->trList == pipe->currentTr)
|
|
{
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
continue;
|
|
}
|
|
#endif
|
|
trDone = 1U;
|
|
|
|
trStatus = (usb_status_t)trCurrent->union1.transferResult;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[indexLength.state.tdIndex]
|
|
.dataUnion.dataBitField.NrBytesToTransfer = 0U;
|
|
|
|
break;
|
|
#endif
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
if (0U != trDone)
|
|
{
|
|
pipe->trList = trCurrent->next;
|
|
#if 0
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
if ((USB_ENDPOINT_ISOCHRONOUS != pipe->pipeCommon.pipeType) && (pipe->bufferLength))
|
|
#else
|
|
if ((pipe->bufferLength)
|
|
#endif
|
|
|
|
#else
|
|
if ((0U != pipe->bufferLength))
|
|
#endif
|
|
{
|
|
(void)USB_HostIp3516HsFreeBuffer(usbHostState, pipe->bufferIndex, pipe->bufferLength);
|
|
pipe->bufferLength = 0U;
|
|
}
|
|
pipe->cutOffTime = USB_HOST_IP3516HS_TRANSFER_TIMEOUT_GAP;
|
|
|
|
if ((kStatus_USB_Success == (trStatus)) && (USB_ENDPOINT_CONTROL == pipe->pipeCommon.pipeType) &&
|
|
(USB_REQUEST_STANDARD_CLEAR_FEATURE == trCurrent->setupPacket->bRequest) &&
|
|
(USB_REQUEST_TYPE_RECIPIENT_ENDPOINT == trCurrent->setupPacket->bmRequestType) &&
|
|
(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT ==
|
|
(USB_SHORT_FROM_LITTLE_ENDIAN(trCurrent->setupPacket->wValue) & 0x00FFU)))
|
|
{
|
|
p = usbHostState->pipeListInUsing;
|
|
while (p != NULL)
|
|
{
|
|
/* only compute bulk and interrupt pipe */
|
|
if ((p->pipeCommon.deviceHandle == pipe->pipeCommon.deviceHandle) &&
|
|
((p->pipeCommon.endpointAddress |
|
|
(p->pipeCommon.direction << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)) ==
|
|
((uint8_t)(USB_SHORT_FROM_LITTLE_ENDIAN(trCurrent->setupPacket->wIndex)))))
|
|
{
|
|
break;
|
|
}
|
|
temp = (void *)p->pipeCommon.next;
|
|
p = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
}
|
|
|
|
if ((NULL != p) && ((USB_ENDPOINT_BULK == p->pipeCommon.pipeType) ||
|
|
(USB_ENDPOINT_INTERRUPT == p->pipeCommon.pipeType)))
|
|
{
|
|
if (USB_ENDPOINT_BULK == p->pipeCommon.pipeType)
|
|
{
|
|
usbHostState->usbRegBase->ATL_PTD_SKIP_MAP |= 1UL << p->tdIndex;
|
|
}
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
else if (USB_ENDPOINT_INTERRUPT == p->pipeCommon.pipeType)
|
|
{
|
|
usbHostState->usbRegBase->INT_PTD_SKIP_MAP |= 1UL << p->tdIndex;
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
}
|
|
|
|
startUFrame = (uint32_t)(
|
|
(usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
currentUFrame = startUFrame;
|
|
|
|
while (currentUFrame == startUFrame)
|
|
{
|
|
currentUFrame = (uint32_t)(
|
|
(usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
}
|
|
|
|
if (USB_ENDPOINT_BULK == p->pipeCommon.pipeType)
|
|
{
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[p->tdIndex]
|
|
.stateUnion.stateBitField.DT = 0U;
|
|
usbHostState->usbRegBase->ATL_PTD_SKIP_MAP &= ~(1UL << p->tdIndex);
|
|
}
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
else if (USB_ENDPOINT_INTERRUPT == p->pipeCommon.pipeType)
|
|
{
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[p->tdIndex]
|
|
.stateUnion.stateBitField.DT = 0U;
|
|
usbHostState->usbRegBase->INT_PTD_SKIP_MAP &= ~(1UL << p->tdIndex);
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
}
|
|
}
|
|
}
|
|
/* callback function is different from the current condition */
|
|
trCurrent->callbackFn(trCurrent->callbackParam, trCurrent, trStatus); /* transfer callback */
|
|
USB_HostIp3516HsCheckGetBufferFailedPipe(usbHostState);
|
|
if (NULL != pipe->trList)
|
|
{
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_BULK:
|
|
(void)USB_HostIp3516HsWriteBulkPipe(usbHostState, pipe, pipe->trList);
|
|
break;
|
|
|
|
case USB_ENDPOINT_CONTROL:
|
|
(void)USB_HostIp3516HsWriteControlPipe(usbHostState, pipe, pipe->trList);
|
|
break;
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
(void)USB_HostIp3516HsWriteIsoPipe(usbHostState, pipe, pipe->trList);
|
|
break;
|
|
#endif
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
(void)USB_HostIp3516HsWriteInterruptPipe(usbHostState, pipe, pipe->trList);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
}
|
|
USB_HostOhciEnableIsr(usbHostState);
|
|
USB_HostIp3516HsUnlock();
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsSof(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
usb_host_ip3516hs_pipe_struct_t *pipe;
|
|
void *temp;
|
|
/* Enter critical */
|
|
USB_HostIp3516HsLock();
|
|
pipe = usbHostState->pipeListInUsing;
|
|
while (NULL != pipe)
|
|
{
|
|
if ((USB_ENDPOINT_CONTROL == pipe->pipeCommon.pipeType) || (USB_ENDPOINT_BULK == pipe->pipeCommon.pipeType))
|
|
{
|
|
if (NULL != pipe->trList)
|
|
{
|
|
pipe->cutOffTime--;
|
|
if (0U == pipe->cutOffTime)
|
|
{
|
|
pipe->trList->union1.transferResult = (int)kStatus_USB_TransferFailed;
|
|
(void)USB_HostIp3516HsCancelPipe(usbHostState, pipe, pipe->trList);
|
|
}
|
|
}
|
|
}
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
}
|
|
/* Exit critical */
|
|
USB_HostIp3516HsUnlock();
|
|
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsControllerReset(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
usbHostState->usbRegBase->USBCMD = USB_HOST_IP3516HS_USBCMD_HCRESET_MASK;
|
|
while (0U != (usbHostState->usbRegBase->USBCMD & USB_HOST_IP3516HS_USBCMD_HCRESET_MASK))
|
|
{
|
|
__NOP();
|
|
}
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
static usb_status_t USB_HostIp3516HsControllerInit(usb_host_ip3516hs_state_struct_t *usbHostState)
|
|
{
|
|
usb_host_ip3516hs_pipe_struct_t *pipe;
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS_MAX_GTD) && (USB_HOST_CONFIG_IP3516HS_MAX_GTD > 0U))
|
|
usb_host_ip3516hs_atl_struct_t *gtd;
|
|
#endif
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS_MAX_ITD) && (USB_HOST_CONFIG_IP3516HS_MAX_ITD > 0U))
|
|
usb_host_ip3516hs_isochronous_transfer_descritpor_struct_t *itd;
|
|
#endif
|
|
uint32_t i;
|
|
uint32_t interruptState;
|
|
void *temp;
|
|
OSA_SR_ALLOC();
|
|
|
|
/* Enter critical */
|
|
OSA_ENTER_CRITICAL();
|
|
|
|
for (i = 0U; i < (sizeof(usbHostState->bufferArrayBitMap) / (sizeof(uint32_t))); i++)
|
|
{
|
|
usbHostState->bufferArrayBitMap[i] = 0xFFFFFFFFU;
|
|
}
|
|
|
|
for (i = 0U; i < (sizeof(s_UsbHostIp3516HsBufferArray) / (sizeof(uint8_t) * 64U)); i++)
|
|
{
|
|
usbHostState->bufferArrayBitMap[i >> 5U] &= ~(1UL << (i % 32U));
|
|
}
|
|
|
|
for (i = 0U;
|
|
i < (sizeof(s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl) / sizeof(usb_host_ip3516hs_atl_struct_t));
|
|
i++)
|
|
{
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[i].control1Union.controlState = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[i].control2Union.controlState = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[i].dataUnion.data = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[i].stateUnion.state = 0U;
|
|
}
|
|
usbHostState->usbRegBase->ATL_PTD_BASE_ADDRESS =
|
|
(((uint32_t)(&s_UsbHostIp3516HsPtd[usbHostState->controllerId].atl[0])) &
|
|
USB_HOST_IP3516HS_ATL_PTD_ATL_BASE_MASK);
|
|
usbHostState->usbRegBase->LAST_PTD_IN_USE = (i - 1U) & USB_HOST_IP3516HS_LAST_PTD_IN_USE_ATL_LAST_MASK;
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_ATL_EN_MASK;
|
|
interruptState = USB_HOST_IP3516HS_USBINTR_ATL_IRQ_E_MASK;
|
|
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
for (i = 0U; i < USB_HOST_CONFIG_IP3516HS_MAX_ISO; i++)
|
|
{
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[i].control1Union.controlState = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[i].control2Union.controlState = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[i].dataUnion.data = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[i].stateUnion.state = 0U;
|
|
}
|
|
usbHostState->usbRegBase->ISO_PTD_BASE_ADDRESS =
|
|
(((uint32_t)(&s_UsbHostIp3516HsPtd[usbHostState->controllerId].iso[0])) &
|
|
USB_HOST_IP3516HS_ISO_PTD_ISO_BASE_MASK);
|
|
usbHostState->usbRegBase->LAST_PTD_IN_USE |=
|
|
((USB_HOST_CONFIG_IP3516HS_MAX_ISO - 1UL) << USB_HOST_IP3516HS_LAST_PTD_IN_USE_ISO_LAST_SHIFT) &
|
|
USB_HOST_IP3516HS_LAST_PTD_IN_USE_ISO_LAST_MASK;
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_ISO_EN_MASK;
|
|
interruptState |= USB_HOST_IP3516HS_USBINTR_ISO_IRQ_E_MASK;
|
|
#endif
|
|
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS_MAX_INT) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
for (i = 0U; i < USB_HOST_CONFIG_IP3516HS_MAX_INT; i++)
|
|
{
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[i].control1Union.controlState = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[i].control2Union.controlState = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[i].dataUnion.data = 0U;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[i].stateUnion.state = 0U;
|
|
}
|
|
usbHostState->usbRegBase->INT_PTD_BASE_ADDRESS =
|
|
(((uint32_t)(&s_UsbHostIp3516HsPtd[usbHostState->controllerId].interrupt[0])) &
|
|
USB_HOST_IP3516HS_INT_PTD_INT_BASE_MASK);
|
|
usbHostState->usbRegBase->LAST_PTD_IN_USE |=
|
|
(((uint32_t)USB_HOST_CONFIG_IP3516HS_MAX_INT - 1U) << USB_HOST_IP3516HS_LAST_PTD_IN_USE_INT_LAST_SHIFT) &
|
|
USB_HOST_IP3516HS_LAST_PTD_IN_USE_INT_LAST_MASK;
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_INT_EN_MASK;
|
|
interruptState |= USB_HOST_IP3516HS_USBINTR_INT_IRQ_E_MASK;
|
|
#endif
|
|
|
|
usbHostState->pipeListInUsing = NULL;
|
|
usbHostState->pipeList = &usbHostState->pipePool[0];
|
|
pipe = usbHostState->pipeList;
|
|
for (i = 1U; i < USB_HOST_CONFIG_IP3516HS_MAX_PIPE; i++)
|
|
{
|
|
temp = (void *)(&usbHostState->pipePool[i]);
|
|
pipe->pipeCommon.next = (usb_host_pipe_t *)temp;
|
|
temp = (void *)pipe->pipeCommon.next;
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)temp;
|
|
}
|
|
pipe->pipeCommon.next = NULL;
|
|
|
|
/* Exit critical */
|
|
OSA_EXIT_CRITICAL();
|
|
|
|
if (0U != (usbHostState->usbRegBase->HCSPARAMS &
|
|
USB_HOST_IP3516HS_HCSPARAMS_PPC_MASK)) /* Ports have power port switches */
|
|
{
|
|
/* only has one port */
|
|
uint32_t tmp = usbHostState->usbRegBase->PORTSC1;
|
|
tmp &= (~USB_HOST_IP3516HS_PORTSC1_WIC);
|
|
usbHostState->usbRegBase->PORTSC1 = (tmp | USB_HOST_IP3516HS_PORTSC1_PP_MASK); /* turn on port power */
|
|
}
|
|
usbHostState->usbRegBase->DATA_PAYLOAD_BASE_ADDRESS =
|
|
(uint32_t)(&s_UsbHostIp3516HsBufferArray[0][0]) & USB_HOST_IP3516HS_DAT_BASE_MASK;
|
|
|
|
usbHostState->usbRegBase->USBSTS = 0xFFFFFFFFU;
|
|
|
|
usbHostState->usbRegBase->USBINTR =
|
|
interruptState | USB_HOST_IP3516HS_USBINTR_PCDE_MASK | USB_HOST_IP3516HS_USBINTR_SOF_E_MASK;
|
|
|
|
/* On RT600, there is no attach information when LS device is connected, the designer said it is due to the default
|
|
* turnaround time is too small, the 0x654 is their suggested value. */
|
|
#if (defined(FSL_FEATURE_USBHSH_HAS_TURNAROUND_TIMEOUT) && (FSL_FEATURE_USBHSH_HAS_TURNAROUND_TIMEOUT > 0U))
|
|
usbHostState->usbRegBase->PACKET_TURNAROUND_TIMEOUT &= ~USBHSH_PACKET_TURNAROUND_TIME_HOST_TIMEOUT_LS_MASK;
|
|
usbHostState->usbRegBase->PACKET_TURNAROUND_TIMEOUT |= 0x00000654;
|
|
#endif
|
|
|
|
usbHostState->usbRegBase->USBCMD |= USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
/*!
|
|
* @brief create the USB host ip3516hs instance.
|
|
*
|
|
* This function initializes the USB host ip3516hs controller driver.
|
|
*
|
|
* @param controllerId The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
|
|
* @param hostHandle The host level handle.
|
|
* @param controllerHandle Return the controller instance handle.
|
|
*
|
|
* @retval kStatus_USB_Success The host is initialized successfully.
|
|
* @retval kStatus_USB_AllocFail allocate memory fail.
|
|
* @retval kStatus_USB_Error host mutex create fail, IP3516HS mutex or IP3516HS event create fail.
|
|
* Or, IP3516HS IP initialize fail.
|
|
*/
|
|
usb_status_t USB_HostIp3516HsCreate(uint8_t controllerId,
|
|
usb_host_handle hostHandle,
|
|
usb_host_controller_handle *controllerHandle)
|
|
{
|
|
usb_host_ip3516hs_state_struct_t *usbHostState;
|
|
uint32_t usb_base_addrs[] = USBHSH_BASE_ADDRS;
|
|
IRQn_Type usb_irq[] = USBHSH_IRQS;
|
|
usb_status_t status = kStatus_USB_Success;
|
|
#if (defined(USB_HOST_CONFIG_BATTERY_CHARGER) && (USB_HOST_CONFIG_BATTERY_CHARGER > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
uint32_t hsdcd_base[] = USBHSDCD_BASE_ADDRS;
|
|
USBHSDCD_Type *base;
|
|
#endif
|
|
|
|
if (((controllerId - (uint8_t)kUSB_ControllerIp3516Hs0) >= (uint8_t)USB_HOST_CONFIG_IP3516HS)
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS > 1U))
|
|
||
|
|
((controllerId - (uint8_t)kUSB_ControllerIp3516Hs0) >= (uint8_t)((sizeof(usb_base_addrs) / sizeof(uint32_t))))
|
|
#endif
|
|
)
|
|
{
|
|
return kStatus_USB_ControllerNotFound;
|
|
}
|
|
usbHostState = &s_UsbHostIp3516HsState[controllerId - (uint8_t)kUSB_ControllerIp3516Hs0];
|
|
/* Allocate the USB Host Pipe Descriptors */
|
|
usbHostState->hostHandle = hostHandle;
|
|
usbHostState->controllerId = controllerId - (uint8_t)kUSB_ControllerIp3516Hs0;
|
|
|
|
usbHostState->usbRegBase = (usb_host_ip3516hs_register_struct_t *)usb_base_addrs[usbHostState->controllerId];
|
|
usbHostState->isrNumber = (uint8_t)usb_irq[usbHostState->controllerId];
|
|
usbHostState->ip3516HsEvent = (osa_event_handle_t)&usbHostState->taskEventHandleBuffer[0];
|
|
if (KOSA_StatusSuccess != OSA_EventCreate(usbHostState->ip3516HsEvent, 1U))
|
|
{
|
|
#ifdef HOST_ECHO
|
|
usb_echo(" Event create failed in USB_HostIp3516HsCreate\n");
|
|
#endif
|
|
return kStatus_USB_AllocFail;
|
|
} /* Endif */
|
|
usbHostState->mutex = (osa_mutex_handle_t)(&usbHostState->mutexBuffer[0]);
|
|
if (KOSA_StatusSuccess != OSA_MutexCreate(usbHostState->mutex))
|
|
{
|
|
(void)USB_HostIp3516HsDestory(usbHostState);
|
|
#ifdef HOST_ECHO
|
|
usb_echo("USB_HostIp3516HsCreate: create host mutex fail\r\n");
|
|
#endif
|
|
return kStatus_USB_AllocFail;
|
|
}
|
|
|
|
usbHostState->portNumber =
|
|
(uint8_t)(usbHostState->usbRegBase->HCSPARAMS & USB_HOST_IP3516HS_HCSPARAMS_N_PORTS_MASK);
|
|
if (0U == usbHostState->portNumber)
|
|
{
|
|
#ifdef HOST_ECHO
|
|
usb_echo(" Port number is invalid in USB_HostIp3516HsCreate\n");
|
|
#endif
|
|
(void)USB_HostIp3516HsDestory(usbHostState);
|
|
return kStatus_USB_Error;
|
|
}
|
|
|
|
usbHostState->portState = (usb_host_ip3516hs_port_state_struct_t *)OSA_MemoryAllocate(
|
|
((uint32_t)sizeof(usb_host_ip3516hs_port_state_struct_t)) *
|
|
((uint32_t)usbHostState->portNumber)); /* malloc host ip3516hs port state */
|
|
if (NULL == usbHostState->portState)
|
|
{
|
|
#ifdef HOST_ECHO
|
|
usb_echo(" Mem alloc failed in USB_HostIp3516HsCreate\n");
|
|
#endif
|
|
(void)USB_HostIp3516HsDestory(usbHostState);
|
|
return kStatus_USB_Error;
|
|
}
|
|
|
|
(void)USB_HostIp3516HsControllerReset(usbHostState);
|
|
|
|
(void)USB_HostIp3516HsControllerInit(usbHostState);
|
|
|
|
#if (defined(USB_HOST_CONFIG_BATTERY_CHARGER) && (USB_HOST_CONFIG_BATTERY_CHARGER > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
base = (USBHSDCD_Type *)hsdcd_base[controllerId - kUSB_ControllerIp3516Hs0];
|
|
if (kStatus_hsdcd_Success != USB_HSDCD_Init(base, NULL, &usbHostState->dcdHandle))
|
|
{
|
|
(void)USB_HostIp3516HsDestory(usbHostState);
|
|
return kStatus_USB_Error;
|
|
}
|
|
usbHostState->chargerType = kUSB_DcdSDP;
|
|
#endif
|
|
|
|
*controllerHandle = (usb_host_handle)usbHostState;
|
|
return status;
|
|
}
|
|
|
|
/*!
|
|
* @brief destroy USB host ip3516hs instance.
|
|
*
|
|
* This function de-initialize the USB host ip3516hs controller driver.
|
|
*
|
|
* @param handle the controller handle.
|
|
*
|
|
* @retval kStatus_USB_Success The host is initialized successfully.
|
|
*/
|
|
usb_status_t USB_HostIp3516HsDestory(usb_host_controller_handle controllerHandle)
|
|
{
|
|
usb_host_ip3516hs_state_struct_t *usbHostState = (usb_host_ip3516hs_state_struct_t *)controllerHandle;
|
|
|
|
usbHostState->usbRegBase->USBINTR = 0U;
|
|
usbHostState->usbRegBase->USBSTS = 0xFFFFFFFFU;
|
|
|
|
usbHostState->usbRegBase->USBCMD &= ~USB_HOST_IP3516HS_USBCMD_RS_MASK;
|
|
|
|
if (NULL != usbHostState->portState)
|
|
{
|
|
(void)OSA_MemoryFree(usbHostState->portState);
|
|
usbHostState->portState = NULL;
|
|
}
|
|
|
|
if (NULL != usbHostState->mutex)
|
|
{
|
|
(void)OSA_MutexDestroy(usbHostState->mutex);
|
|
usbHostState->mutex = NULL;
|
|
}
|
|
|
|
if (NULL != usbHostState->ip3516HsEvent)
|
|
{
|
|
(void)OSA_EventDestroy(usbHostState->ip3516HsEvent);
|
|
usbHostState->ip3516HsEvent = NULL;
|
|
}
|
|
|
|
#if (defined(USB_HOST_CONFIG_BATTERY_CHARGER) && (USB_HOST_CONFIG_BATTERY_CHARGER > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
USB_HSDCD_Deinit(usbHostState->dcdHandle);
|
|
#endif
|
|
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
usb_status_t USB_HostIp3516HsOpenPipe(usb_host_controller_handle controllerHandle,
|
|
usb_host_pipe_handle *pipeHandle,
|
|
usb_host_pipe_init_t *pipeInit)
|
|
{
|
|
usb_host_ip3516hs_pipe_struct_t *pipe = NULL;
|
|
usb_host_ip3516hs_state_struct_t *usbHostState = (usb_host_ip3516hs_state_struct_t *)controllerHandle;
|
|
usb_status_t status;
|
|
|
|
status = USB_HostIp3516HsGetNewPipe(&usbHostState->pipeList, &pipe);
|
|
if ((kStatus_USB_Success != status) || (NULL == pipe))
|
|
{
|
|
#ifdef HOST_ECHO
|
|
usb_echo("ip3516hs open pipe failed\r\n");
|
|
#endif
|
|
return kStatus_USB_Busy;
|
|
}
|
|
|
|
/* initialize pipe informations */
|
|
pipe->pipeCommon.deviceHandle = pipeInit->devInstance;
|
|
pipe->pipeCommon.endpointAddress = pipeInit->endpointAddress;
|
|
pipe->pipeCommon.direction = pipeInit->direction;
|
|
pipe->pipeCommon.interval = pipeInit->interval;
|
|
pipe->pipeCommon.maxPacketSize = pipeInit->maxPacketSize;
|
|
pipe->pipeCommon.pipeType = pipeInit->pipeType;
|
|
pipe->pipeCommon.numberPerUframe = (pipeInit->numberPerUframe + 1U) & 0x03U;
|
|
pipe->pipeCommon.nakCount = pipeInit->nakCount;
|
|
pipe->pipeCommon.nextdata01 = 0U;
|
|
pipe->pipeCommon.currentCount = 0U;
|
|
pipe->pipeCommon.open = 1U;
|
|
pipe->tdIndex = 0xFFU;
|
|
pipe->cutOffTime = USB_HOST_IP3516HS_TRANSFER_TIMEOUT_GAP;
|
|
pipe->startUFrame = 0U;
|
|
pipe->csSlot = 0U;
|
|
pipe->isBusy = 0U;
|
|
pipe->bufferLength = 0U;
|
|
pipe->currentTr = NULL;
|
|
pipe->lastPrimedIndex = 0U;
|
|
|
|
if (USB_ENDPOINT_ISOCHRONOUS == pipe->pipeCommon.pipeType)
|
|
{
|
|
#if 1U
|
|
if (0U == pipe->pipeCommon.interval)
|
|
{
|
|
pipe->pipeCommon.interval = 1U;
|
|
}
|
|
pipe->pipeCommon.interval =
|
|
(uint16_t)(1UL << (pipe->pipeCommon.interval - 1U)); /* iso interval is the power of 2 */
|
|
#else
|
|
pipe->pipeCommon.interval = 1U;
|
|
#endif
|
|
}
|
|
else if (USB_ENDPOINT_INTERRUPT == pipe->pipeCommon.pipeType)
|
|
{
|
|
if (USB_SPEED_HIGH != ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed)
|
|
{
|
|
uint32_t interval = 0U;
|
|
/* FS/LS interrupt interval should be the power of 2, it is used for ip3516hs bandwidth */
|
|
for (uint32_t p = 0U; p < 16U; p++)
|
|
{
|
|
if (0U != (pipe->pipeCommon.interval & ((uint16_t)(1UL << p))))
|
|
{
|
|
if (p > interval)
|
|
{
|
|
interval = p;
|
|
}
|
|
}
|
|
}
|
|
pipe->pipeCommon.interval = (uint16_t)(1UL << interval);
|
|
}
|
|
else
|
|
{
|
|
pipe->pipeCommon.interval = ((uint16_t)(
|
|
1UL << ((uint32_t)pipe->pipeCommon.interval - 1UL))); /* HS interrupt interval is the power of 2 */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pipe->pipeCommon.interval = 0U;
|
|
}
|
|
|
|
if (USB_SPEED_HIGH != ((usb_host_device_instance_t *)pipe->pipeCommon.deviceHandle)->speed)
|
|
{
|
|
pipe->pipeCommon.interval = pipe->pipeCommon.interval << 3;
|
|
}
|
|
|
|
if (((uint16_t)USB_HOST_IP3516HS_MAX_FRAME) < pipe->pipeCommon.interval)
|
|
{
|
|
pipe->pipeCommon.interval = (uint16_t)USB_HOST_IP3516HS_MAX_FRAME;
|
|
}
|
|
/* open pipe */
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_CONTROL:
|
|
case USB_ENDPOINT_BULK:
|
|
status = USB_HostIp3516HsOpenControlBulkPipe(usbHostState, pipe);
|
|
break;
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
status = USB_HostIp3516HsOpenIsoPipe(usbHostState, pipe);
|
|
break;
|
|
#endif
|
|
|
|
#if (defined(USB_HOST_CONFIG_IP3516HS_MAX_INT) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
status = USB_HostIp3516HsOpenInterruptPipe(usbHostState, pipe);
|
|
break;
|
|
#endif
|
|
default:
|
|
status = kStatus_USB_Error;
|
|
break;
|
|
}
|
|
|
|
if (status != kStatus_USB_Success)
|
|
{
|
|
pipe->pipeCommon.open = 0U;
|
|
/* release the pipe */
|
|
(void)USB_HostIp3516HsInsertPipe(&usbHostState->pipeList, pipe);
|
|
return status;
|
|
}
|
|
|
|
(void)USB_HostIp3516HsInsertPipe(&usbHostState->pipeListInUsing, pipe);
|
|
|
|
*pipeHandle = pipe;
|
|
return status;
|
|
}
|
|
|
|
usb_status_t USB_HostIp3516HsClosePipe(usb_host_controller_handle controllerHandle, usb_host_pipe_handle pipeHandle)
|
|
{
|
|
usb_host_ip3516hs_state_struct_t *usbHostState = (usb_host_ip3516hs_state_struct_t *)controllerHandle;
|
|
usb_host_ip3516hs_pipe_struct_t *pipe = (usb_host_ip3516hs_pipe_struct_t *)pipeHandle;
|
|
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_BULK:
|
|
case USB_ENDPOINT_CONTROL:
|
|
(void)USB_HostIp3516HsCloseControlBulkPipe(usbHostState, pipe);
|
|
break;
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
(void)USB_HostIp3516HsCloseIsoPipe(usbHostState, pipe);
|
|
break;
|
|
#endif
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
(void)USB_HostIp3516HsCloseInterruptPipe(usbHostState, pipe);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
(void)USB_HostIp3516HsRemovePipe(&usbHostState->pipeListInUsing, pipe);
|
|
pipe->pipeCommon.open = 0U;
|
|
(void)USB_HostIp3516HsInsertPipe(&usbHostState->pipeList, pipe);
|
|
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
usb_status_t USB_HostIp3516HsWritePipe(usb_host_controller_handle controllerHandle,
|
|
usb_host_pipe_handle pipeHandle,
|
|
usb_host_transfer_t *transfer)
|
|
{
|
|
usb_host_ip3516hs_state_struct_t *usbHostState = (usb_host_ip3516hs_state_struct_t *)controllerHandle;
|
|
usb_host_ip3516hs_pipe_struct_t *pipe = (usb_host_ip3516hs_pipe_struct_t *)pipeHandle;
|
|
usb_host_transfer_t *trPre;
|
|
usb_status_t status = kStatus_USB_Success;
|
|
uint8_t trListEmpty = 0U;
|
|
OSA_SR_ALLOC();
|
|
|
|
transfer->setupStatus = (uint8_t)kStatus_UsbHostIp3516Hs_Idle;
|
|
transfer->next = NULL;
|
|
transfer->transferSofar = 0U;
|
|
transfer->union1.transferResult = (int32_t)kStatus_USB_Success;
|
|
|
|
OSA_ENTER_CRITICAL();
|
|
if (NULL == pipe->trList)
|
|
{
|
|
pipe->trList = transfer;
|
|
pipe->currentTr = transfer;
|
|
trListEmpty = 1U;
|
|
}
|
|
else
|
|
{
|
|
trPre = pipe->trList;
|
|
while (NULL != trPre->next)
|
|
{
|
|
trPre = trPre->next;
|
|
}
|
|
trPre->next = transfer;
|
|
}
|
|
OSA_EXIT_CRITICAL();
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
if ((0U != trListEmpty) || (USB_ENDPOINT_ISOCHRONOUS == pipe->pipeCommon.pipeType))
|
|
#else
|
|
if ((0U != trListEmpty))
|
|
#endif
|
|
{
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_BULK:
|
|
status = USB_HostIp3516HsWriteBulkPipe(usbHostState, pipe, transfer);
|
|
break;
|
|
|
|
case USB_ENDPOINT_CONTROL:
|
|
status = USB_HostIp3516HsWriteControlPipe(usbHostState, pipe, transfer);
|
|
break;
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
status = USB_HostIp3516HsWriteIsoPipe(usbHostState, pipe, pipe->trList);
|
|
break;
|
|
#endif
|
|
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
status = USB_HostIp3516HsWriteInterruptPipe(usbHostState, pipe, transfer);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
usb_status_t USB_HostIp3516HsReadPipe(usb_host_controller_handle controllerHandle,
|
|
usb_host_pipe_handle pipeHandle,
|
|
usb_host_transfer_t *transfer)
|
|
{
|
|
return USB_HostIp3516HsWritePipe(controllerHandle, pipeHandle, transfer);
|
|
}
|
|
|
|
usb_status_t USB_HostIp3516HsIoctl(usb_host_controller_handle controllerHandle, uint32_t ioctlEvent, void *ioctlParam)
|
|
{
|
|
usb_host_ip3516hs_state_struct_t *usbHostState = (usb_host_ip3516hs_state_struct_t *)controllerHandle;
|
|
usb_host_cancel_param_t *param;
|
|
usb_host_ip3516hs_pipe_struct_t *pipe;
|
|
uint32_t deviceAddress;
|
|
usb_host_controller_control_t ioctl;
|
|
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
|
|
#if ((defined(USB_HOST_CONFIG_LPM_L1)) && (USB_HOST_CONFIG_LPM_L1 > 0U))
|
|
uint8_t *lpmParam;
|
|
#endif
|
|
#endif
|
|
deviceAddress = 0U;
|
|
usb_status_t status = kStatus_USB_Success;
|
|
|
|
if (controllerHandle == NULL)
|
|
{
|
|
return kStatus_USB_InvalidHandle;
|
|
}
|
|
ioctl = (usb_host_controller_control_t)ioctlEvent;
|
|
switch (ioctl)
|
|
{
|
|
case kUSB_HostCancelTransfer:
|
|
/* cancel pipe or one transfer */
|
|
param = (usb_host_cancel_param_t *)ioctlParam;
|
|
status = USB_HostIp3516HsCancelPipe(usbHostState, (usb_host_ip3516hs_pipe_struct_t *)param->pipeHandle,
|
|
param->transfer);
|
|
break;
|
|
#if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
|
|
#if ((defined(USB_HOST_CONFIG_LPM_L1)) && (USB_HOST_CONFIG_LPM_L1 > 0U))
|
|
case kUSB_HostL1Config:
|
|
lpmParam = (uint8_t *)ioctlParam;
|
|
usbHostState->hirdValue = (*lpmParam) & 0xFU;
|
|
usbHostState->L1remoteWakeupEnable = (((*lpmParam) & 0x80U) >> 7);
|
|
break;
|
|
#endif
|
|
#endif
|
|
case kUSB_HostBusControl:
|
|
/* bus control */
|
|
status = USB_HostIp3516HsControlBus(usbHostState, *((uint8_t *)ioctlParam));
|
|
break;
|
|
|
|
case kUSB_HostGetFrameNumber:
|
|
/* get frame number */
|
|
*((uint32_t *)ioctlParam) =
|
|
(uint32_t)((usbHostState->usbRegBase->FLADJ_FRINDEX & USB_HOST_IP3516HS_FLADJ_FRINDEX_MASK) >>
|
|
USB_HOST_IP3516HS_FLADJ_FRINDEX_SHIFT);
|
|
break;
|
|
|
|
case kUSB_HostUpdateControlEndpointAddress:
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)ioctlParam;
|
|
/* update address */
|
|
(void)USB_HostHelperGetPeripheralInformation(pipe->pipeCommon.deviceHandle,
|
|
(uint32_t)kUSB_HostGetDeviceAddress, &deviceAddress);
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_BULK:
|
|
case USB_ENDPOINT_CONTROL:
|
|
usbHostState->usbRegBase->ATL_PTD_SKIP_MAP |= 1UL << pipe->tdIndex;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.control2Union.stateBitField.DeviceAddress = deviceAddress;
|
|
usbHostState->usbRegBase->ATL_PTD_SKIP_MAP &= ~(1UL << pipe->tdIndex);
|
|
break;
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
usbHostState->usbRegBase->INT_PTD_SKIP_MAP |= 1UL << pipe->tdIndex;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.control2Union.stateBitField.DeviceAddress = deviceAddress;
|
|
usbHostState->usbRegBase->INT_PTD_SKIP_MAP &= ~(1UL << pipe->tdIndex);
|
|
break;
|
|
#endif
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
usbHostState->usbRegBase->ISO_PTD_SKIP_MAP |= 1UL << pipe->tdIndex;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[pipe->tdIndex]
|
|
.control2Union.stateBitField.DeviceAddress = deviceAddress;
|
|
usbHostState->usbRegBase->ISO_PTD_SKIP_MAP &= ~(1UL << pipe->tdIndex);
|
|
break;
|
|
#endif
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
(void)USB_HostIp3516HsDelay(usbHostState, 16U);
|
|
break;
|
|
|
|
case kUSB_HostUpdateControlPacketSize:
|
|
pipe = (usb_host_ip3516hs_pipe_struct_t *)ioctlParam;
|
|
switch (pipe->pipeCommon.pipeType)
|
|
{
|
|
case USB_ENDPOINT_BULK:
|
|
case USB_ENDPOINT_CONTROL:
|
|
usbHostState->usbRegBase->ATL_PTD_SKIP_MAP |= 1UL << pipe->tdIndex;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.atl[pipe->tdIndex]
|
|
.control1Union.stateBitField.MaxPacketLength = pipe->pipeCommon.maxPacketSize;
|
|
usbHostState->usbRegBase->ATL_PTD_SKIP_MAP &= ~(1UL << pipe->tdIndex);
|
|
break;
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
case USB_ENDPOINT_INTERRUPT:
|
|
usbHostState->usbRegBase->INT_PTD_SKIP_MAP |= 1UL << pipe->tdIndex;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.interrupt[pipe->tdIndex]
|
|
.control1Union.stateBitField.MaxPacketLength = pipe->pipeCommon.maxPacketSize;
|
|
usbHostState->usbRegBase->INT_PTD_SKIP_MAP &= ~(1UL << pipe->tdIndex);
|
|
break;
|
|
#endif
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
case USB_ENDPOINT_ISOCHRONOUS:
|
|
usbHostState->usbRegBase->ISO_PTD_SKIP_MAP |= 1UL << pipe->tdIndex;
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[pipe->tdIndex]
|
|
.control1Union.stateBitField.MaxPacketLength = pipe->pipeCommon.maxPacketSize;
|
|
if (0U != s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[pipe->tdIndex]
|
|
.control2Union.stateBitField.S)
|
|
{
|
|
s_UsbHostIp3516HsPtd[usbHostState->controllerId]
|
|
.iso[pipe->tdIndex]
|
|
.control1Union.stateBitField.MaxPacketLength++;
|
|
}
|
|
usbHostState->usbRegBase->ISO_PTD_SKIP_MAP &= ~(1UL << pipe->tdIndex);
|
|
break;
|
|
#endif
|
|
default:
|
|
/*no action*/
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kUSB_HostPortAttachDisable:
|
|
break;
|
|
|
|
case kUSB_HostPortAttachEnable:
|
|
if ((*(uint8_t *)ioctlParam) < usbHostState->portNumber)
|
|
{
|
|
usbHostState->portState[*(uint8_t *)ioctlParam].portStatus = (uint8_t)kUSB_DeviceIp3516HsPortDetached;
|
|
}
|
|
break;
|
|
|
|
#if (defined(USB_HOST_CONFIG_BATTERY_CHARGER) && (USB_HOST_CONFIG_BATTERY_CHARGER > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
case kUSB_HostSetChargerType:
|
|
usbHostState->chargerType = *((uint8_t *)ioctlParam);
|
|
if ((usbHostState->portState[0].portStatus == kUSB_DeviceIp3516HsPortPhyDetached) ||
|
|
(usbHostState->portState[0].portStatus == kUSB_DeviceIp3516HsPortDetached))
|
|
{
|
|
USB_HSDCD_Control(usbHostState->dcdHandle, kUSB_HostHSDcdSetType, &(usbHostState->chargerType));
|
|
}
|
|
break;
|
|
#endif
|
|
#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
|
|
case kUSB_HostTestModeInit: /* test mode control */
|
|
USB_HostIp3516HsTestModeInit((usb_host_device_instance_t *)ioctlParam);
|
|
break;
|
|
#endif
|
|
default:
|
|
status = kStatus_USB_NotSupported;
|
|
break;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void USB_HostIp3516HsTaskFunction(void *hostHandle)
|
|
{
|
|
usb_host_ip3516hs_state_struct_t *usbHostState;
|
|
uint32_t bitSet;
|
|
|
|
if (NULL == hostHandle)
|
|
{
|
|
return;
|
|
}
|
|
usbHostState = (usb_host_ip3516hs_state_struct_t *)((usb_host_instance_t *)hostHandle)->controllerHandle;
|
|
|
|
/* wait all event */
|
|
if (KOSA_StatusSuccess == OSA_EventWait(usbHostState->ip3516HsEvent, 0xFFU, 0, USB_OSA_WAIT_TIMEOUT, &bitSet))
|
|
{
|
|
if (0U != (bitSet & USB_HOST_IP3516HS_EVENT_PORT_CHANGE))
|
|
{
|
|
(void)USB_HostIp3516HsPortChange(usbHostState);
|
|
}
|
|
if (0U != (bitSet & USB_HOST_IP3516HS_EVENT_ISO_TOKEN_DONE))
|
|
{
|
|
(void)USB_HostIp3516HsTokenDone(usbHostState);
|
|
}
|
|
if (0U != (bitSet & USB_HOST_IP3516HS_EVENT_INT_TOKEN_DONE))
|
|
{
|
|
(void)USB_HostIp3516HsTokenDone(usbHostState);
|
|
}
|
|
if (0U != (bitSet & USB_HOST_IP3516HS_EVENT_ATL_TOKEN_DONE))
|
|
{
|
|
(void)USB_HostIp3516HsTokenDone(usbHostState);
|
|
}
|
|
if (0U != (bitSet & USB_HOST_IP3516HS_EVENT_SOF))
|
|
{
|
|
(void)USB_HostIp3516HsSof(usbHostState);
|
|
}
|
|
if (0U != (bitSet & USB_HOST_IP3516HS_EVENT_ATTACH))
|
|
{
|
|
for (uint8_t i = 0; i < usbHostState->portNumber; i++)
|
|
{
|
|
if ((uint8_t)kUSB_DeviceIp3516HsPortPhyAttached == usbHostState->portState[i].portStatus)
|
|
{
|
|
void *deviceHandle;
|
|
if (kStatus_USB_Success == USB_HostAttachDevice(usbHostState->hostHandle,
|
|
usbHostState->portState[i].portSpeed, 0U, i, 1U,
|
|
&deviceHandle))
|
|
{
|
|
usbHostState->portState[i].portStatus = (uint8_t)kUSB_DeviceIp3516HsPortAttached;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (0U != (bitSet & USB_HOST_IP3516HS_EVENT_DETACH))
|
|
{
|
|
for (uint8_t i = 0; i < usbHostState->portNumber; i++)
|
|
{
|
|
if ((uint8_t)kUSB_DeviceIp3516HsPortPhyDetached == usbHostState->portState[i].portStatus)
|
|
{
|
|
(void)USB_HostDetachDevice(usbHostState->hostHandle, 0U, i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void USB_HostIp3516HsIsrFunction(void *hostHandle)
|
|
{
|
|
usb_host_ip3516hs_state_struct_t *usbHostState;
|
|
static uint32_t interruptStatus = 0U;
|
|
static uint32_t sofCount = 0U;
|
|
|
|
if (hostHandle == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
usbHostState = (usb_host_ip3516hs_state_struct_t *)((usb_host_instance_t *)hostHandle)->controllerHandle;
|
|
|
|
interruptStatus = usbHostState->usbRegBase->USBSTS;
|
|
interruptStatus &= usbHostState->usbRegBase->USBINTR;
|
|
|
|
if (0U != (interruptStatus & USB_HOST_IP3516HS_USBSTS_ISO_IRQ_MASK)) /* Write back done head */
|
|
{
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_ISO)) && (USB_HOST_CONFIG_IP3516HS_MAX_ISO > 0U))
|
|
(void)USB_HostIp3516HsCheckIsoTransferSofar(usbHostState);
|
|
(void)OSA_EventSet(usbHostState->ip3516HsEvent, USB_HOST_IP3516HS_EVENT_ISO_TOKEN_DONE);
|
|
#endif
|
|
}
|
|
|
|
if (0U != (interruptStatus & USB_HOST_IP3516HS_USBSTS_INT_IRQ_MASK)) /* Write back done head */
|
|
{
|
|
#if ((defined(USB_HOST_CONFIG_IP3516HS_MAX_INT)) && (USB_HOST_CONFIG_IP3516HS_MAX_INT > 0U))
|
|
(void)USB_HostIp3516HsCheckIntTransferSofar(usbHostState);
|
|
(void)OSA_EventSet(usbHostState->ip3516HsEvent, USB_HOST_IP3516HS_EVENT_INT_TOKEN_DONE);
|
|
#endif
|
|
}
|
|
|
|
if (0U != (interruptStatus & USB_HOST_IP3516HS_USBSTS_ATL_IRQ_MASK)) /* Write back done head */
|
|
{
|
|
(void)USB_HostIp3516HsCheckAtlTransferSofar(usbHostState);
|
|
(void)OSA_EventSet(usbHostState->ip3516HsEvent, USB_HOST_IP3516HS_EVENT_ATL_TOKEN_DONE);
|
|
}
|
|
|
|
if (0U != (interruptStatus & USB_HOST_IP3516HS_USBSTS_SOF_IRQ_MASK)) /* SOF interrupt */
|
|
{
|
|
if (USB_SPEED_HIGH == usbHostState->portState->portSpeed)
|
|
{
|
|
sofCount++;
|
|
}
|
|
else
|
|
{
|
|
sofCount += 8U;
|
|
}
|
|
if (sofCount >= USB_HOST_IP3516HS_TRANSFER_SCAN_INTERVAL)
|
|
{
|
|
sofCount = 0U;
|
|
(void)OSA_EventSet(usbHostState->ip3516HsEvent, USB_HOST_IP3516HS_EVENT_SOF);
|
|
}
|
|
}
|
|
|
|
if (0U != (interruptStatus & USB_HOST_IP3516HS_USBINTR_PCDE_MASK)) /* port change detect interrupt */
|
|
{
|
|
(void)OSA_EventSet(usbHostState->ip3516HsEvent, USB_HOST_IP3516HS_EVENT_PORT_CHANGE);
|
|
}
|
|
|
|
usbHostState->usbRegBase->USBSTS = interruptStatus; /* clear interrupt */
|
|
}
|
|
|
|
#endif
|