--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/omap3530/beagle_drivers/wb/api/src/cyasmisc.c Wed Mar 03 13:10:32 2010 +0000
@@ -0,0 +1,3359 @@
+/* Cypress West Bridge API source file (cyasmisc.c)
+## ===========================
+##
+## Copyright Cypress Semiconductor Corporation, 2006-2009,
+## All Rights Reserved
+## UNPUBLISHED, LICENSED SOFTWARE.
+##
+## CONFIDENTIAL AND PROPRIETARY INFORMATION
+## WHICH IS THE PROPERTY OF CYPRESS.
+##
+## Use of this file is governed
+## by the license agreement included in the file
+##
+## <install>/license/license.txt
+##
+## where <install> is the Cypress software
+## installation root directory path.
+##
+## ===========================
+*/
+
+#include "cyashal.h"
+#include "cyasmisc.h"
+#include "cyasdma.h"
+#include "cyasintr.h"
+#include "cyaserr.h"
+#include "cyasregs.h"
+#include "cyaslowlevel.h"
+#include "cyasprotocol.h"
+
+/*
+* The device list, the only global in the API
+*/
+static CyAsDevice *gDeviceList = 0 ;
+
+/*
+ * The current debug level
+ */
+static uint8_t DebugLevel = 0 ;
+
+/*
+ * This function sets the debug level for the API
+ *
+ */
+void
+CyAsMiscSetLogLevel(uint8_t level)
+{
+ DebugLevel = level ;
+}
+
+#ifdef CY_AS_LOG_SUPPORT
+
+/*
+ * This function is a low level logger for the API.
+ */
+void
+CyAsLogDebugMessage(int level, const char *str)
+{
+ if (level <= DebugLevel)
+ CyAsHalPrintMessage("Log %d: %s\n", level, str) ;
+}
+
+#endif
+
+#define CyAsCheckDeviceReady(dev_p) \
+{ \
+ if (!(dev_p) ||((dev_p)->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) \
+ return CY_AS_ERROR_INVALID_HANDLE ; \
+ \
+ if (!CyAsDeviceIsConfigured(dev_p)) \
+ return CY_AS_ERROR_NOT_CONFIGURED ; \
+ \
+ if (!CyAsDeviceIsFirmwareLoaded(dev_p)) \
+ return CY_AS_ERROR_NO_FIRMWARE ; \
+}
+
+/* Find an West Bridge device based on a TAG */
+CyAsDevice *
+CyAsDeviceFindFromTag(CyAsHalDeviceTag tag)
+{
+ CyAsDevice *dev_p ;
+
+ for(dev_p = gDeviceList; dev_p != 0; dev_p = dev_p->next_p)
+ {
+ if (dev_p->tag == tag)
+ return dev_p ;
+ }
+
+ return 0 ;
+}
+
+/* Map a pre-V1.2 media type to the V1.2+ bus number */
+static void
+CyAsBusFromMediaType(CyAsMediaType type,
+ CyAsBusNumber_t* bus)
+{
+ if (type == CyAsMediaNand)
+ {
+ *bus = 0 ;
+ }
+ else
+ {
+ *bus = 1 ;
+ }
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseNoData(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ else
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+/*
+* Create a new West Bridge device
+*/
+CyAsReturnStatus_t
+CyAsMiscCreateDevice(CyAsDeviceHandle *handle_p, CyAsHalDeviceTag tag)
+{
+ CyAsDevice *dev_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscCreateDevice called") ;
+
+ dev_p = (CyAsDevice *)CyAsHalAlloc(sizeof(CyAsDevice)) ;
+ if (dev_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ CyAsHalMemSet(dev_p, 0, sizeof(CyAsDevice)) ;
+
+ /*
+ * Dynamically allocating this buffer to ensure that it is
+ * word aligned.
+ */
+ dev_p->usb_ep_data = (uint8_t *)CyAsHalAlloc(64 * sizeof(uint8_t)) ;
+ if (dev_p->usb_ep_data == 0)
+ {
+ CyAsHalFree(dev_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ dev_p->sig = CY_AS_DEVICE_HANDLE_SIGNATURE ;
+ dev_p->tag = tag ;
+ dev_p->usb_max_tx_size = 0x40 ;
+
+ dev_p->storage_write_endpoint = CY_AS_P2S_WRITE_ENDPOINT ;
+ dev_p->storage_read_endpoint = CY_AS_P2S_READ_ENDPOINT ;
+
+ dev_p->func_cbs_misc = CyAsCreateCBQueue(CYAS_FUNC_CB) ;
+ if(dev_p->func_cbs_misc == 0)
+ goto destroy ;
+
+ dev_p->func_cbs_res = CyAsCreateCBQueue(CYAS_FUNC_CB) ;
+ if(dev_p->func_cbs_res == 0)
+ goto destroy ;
+
+ dev_p->func_cbs_stor = CyAsCreateCBQueue(CYAS_FUNC_CB) ;
+ if(dev_p->func_cbs_stor == 0)
+ goto destroy ;
+
+ dev_p->func_cbs_usb = CyAsCreateCBQueue(CYAS_FUNC_CB) ;
+ if(dev_p->func_cbs_usb == 0)
+ goto destroy ;
+
+ dev_p->func_cbs_mtp = CyAsCreateCBQueue(CYAS_FUNC_CB) ;
+ if(dev_p->func_cbs_mtp == 0)
+ goto destroy ;
+
+ /*
+ * Allocate memory for the DMA module here. It is then marked idle, and
+ * will be activated when CyAsMiscConfigureDevice is called.
+ */
+ ret = CyAsDmaStart(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ CyAsDeviceSetDmaStopped(dev_p) ;
+
+ /*
+ * Allocate memory for the low level module here. This module is also
+ * activated only when CyAsMiscConfigureDevice is called.
+ */
+ ret = CyAsLLStart(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ CyAsDeviceSetLowLevelStopped(dev_p) ;
+
+ dev_p->next_p = gDeviceList ;
+ gDeviceList = dev_p ;
+
+ *handle_p = dev_p ;
+ CyAsHalInitDevRegisters(tag, CyFalse) ;
+ return CY_AS_ERROR_SUCCESS ;
+
+destroy:
+ /* Free any queues that were successfully allocated. */
+ if (dev_p->func_cbs_misc) CyAsDestroyCBQueue(dev_p->func_cbs_misc) ;
+ if (dev_p->func_cbs_res) CyAsDestroyCBQueue(dev_p->func_cbs_res) ;
+ if (dev_p->func_cbs_stor) CyAsDestroyCBQueue(dev_p->func_cbs_stor) ;
+ if (dev_p->func_cbs_usb) CyAsDestroyCBQueue(dev_p->func_cbs_usb) ;
+ if (dev_p->func_cbs_mtp) CyAsDestroyCBQueue(dev_p->func_cbs_mtp) ;
+
+ CyAsHalFree(dev_p->usb_ep_data) ;
+ CyAsHalFree(dev_p) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+ else
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+}
+
+/*
+* Destroy an existing West Bridge device
+*/
+CyAsReturnStatus_t
+CyAsMiscDestroyDevice(CyAsDeviceHandle handle)
+{
+ CyAsReturnStatus_t ret ;
+ CyAsDevice *dev_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscDestroyDevice called") ;
+
+ dev_p = (CyAsDevice *)handle ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ /*
+ * If the USB stack is still running, it must be stopped first
+ */
+ if (dev_p->usb_count > 0)
+ return CY_AS_ERROR_STILL_RUNNING ;
+
+ /*
+ * If the STORAGE stack is still running, it must be stopped first
+ */
+ if (dev_p->storage_count > 0)
+ return CY_AS_ERROR_STILL_RUNNING ;
+
+ if(CyAsDeviceIsIntrRunning(dev_p))
+ ret = CyAsIntrStop(dev_p) ;
+
+ ret = CyAsLLStop(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ CyAsIntrStart(dev_p, dev_p->use_int_drq) ;
+ return ret ;
+ }
+
+ ret = CyAsDmaStop(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ CyAsIntrStart(dev_p, dev_p->use_int_drq) ;
+ return ret ;
+ }
+
+ /* Reset the West Bridge device. */
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, CY_AS_MEM_RST_CTRL_REG_HARD) ;
+
+ /*
+ * Remove the device from the device list
+ */
+ if (gDeviceList == dev_p)
+ {
+ gDeviceList = dev_p->next_p ;
+ }
+ else
+ {
+ CyAsDevice *tmp_p = gDeviceList ;
+ while (tmp_p && tmp_p->next_p != dev_p)
+ tmp_p = tmp_p->next_p ;
+
+ CyAsHalAssert(tmp_p != 0) ;
+ tmp_p->next_p = dev_p->next_p ;
+ }
+
+ /*
+ * Reset the signature so this will not be detected
+ * as a valid handle
+ */
+ dev_p->sig = 0 ;
+
+ CyAsDestroyCBQueue(dev_p->func_cbs_misc) ;
+ CyAsDestroyCBQueue(dev_p->func_cbs_res) ;
+ CyAsDestroyCBQueue(dev_p->func_cbs_stor) ;
+ CyAsDestroyCBQueue(dev_p->func_cbs_usb) ;
+ CyAsDestroyCBQueue(dev_p->func_cbs_mtp) ;
+
+ /*
+ * Free the memory associated with the device
+ */
+ CyAsHalFree(dev_p->usb_ep_data) ;
+ CyAsHalFree(dev_p) ;
+
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+/*
+* Determine the endian mode for the processor we are running on, then
+* set the endian mode register
+*/
+static void
+CyAsSetupEndianMode(CyAsDevice *dev_p)
+{
+ /*
+ * BWG: In general, we always set West Bridge into the little endian mode. This
+ * causes the data on bit 0 internally to come out on data line 0 externally
+ * and it is generally what we want regardless of the endian mode of the
+ * processor. This capability in West Bridge should be labeled as a "SWAP" capability
+ * and can be used to swap the bytes of data in and out of West Bridge. This is
+ * useful if there is DMA hardware that requires this for some reason I cannot
+ * imagine at this time. Basically if the wires are connected correctly, we should
+ * never need to change the endian-ness of West Bridge.
+ */
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_ENDIAN, CY_AS_LITTLE_ENDIAN) ;
+}
+
+/*
+* Query the West Bridge device and determine if we are an standby mode
+*/
+CyAsReturnStatus_t
+CyAsMiscInStandby(CyAsDeviceHandle handle, CyBool *standby)
+{
+ CyAsDevice *dev_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscInStandby called") ;
+
+ dev_p = (CyAsDevice *)handle ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if (CyAsDeviceIsPinStandby(dev_p) || CyAsDeviceIsRegisterStandby(dev_p))
+ {
+ *standby = CyTrue ;
+ }
+ else
+ *standby = CyFalse ;
+
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+static void
+CyAsMiscFuncCallback(CyAsDevice *dev_p,
+ uint8_t context,
+ CyAsLLRequestResponse *rqt,
+ CyAsLLRequestResponse *resp,
+ CyAsReturnStatus_t ret) ;
+
+
+static void
+MyMiscCallback(CyAsDevice *dev_p, uint8_t context, CyAsLLRequestResponse *req_p, CyAsLLRequestResponse *resp_p,
+ CyAsReturnStatus_t ret)
+{
+ (void)resp_p ;
+ (void)context ;
+ (void)ret ;
+
+ switch (CyAsLLRequestResponse_GetCode(req_p))
+ {
+ case CY_RQT_INITIALIZATION_COMPLETE:
+ {
+ uint16_t v ;
+
+ CyAsLLSendStatusResponse(dev_p, CY_RQT_GENERAL_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
+ CyAsDeviceSetFirmwareLoaded(dev_p) ;
+
+ if (CyAsDeviceIsWaking(dev_p))
+ {
+ /*
+ * This is a callback from a CyAsMiscLeaveStandby() request. In this case we call the
+ * standby callback and clear the waking state.
+ */
+ if (dev_p->misc_event_cb)
+ dev_p->misc_event_cb((CyAsDeviceHandle)dev_p, CyAsEventMiscAwake, 0) ;
+ CyAsDeviceClearWaking(dev_p) ;
+ }
+ else
+ {
+ v = CyAsLLRequestResponse_GetWord(req_p, 3) ;
+
+ /*
+ * Store the media supported on each of the device buses.
+ */
+ dev_p->media_supported[0] = (uint8_t)(v & 0xFF) ;
+ dev_p->media_supported[1] = (uint8_t)((v >> 8) & 0xFF) ;
+
+ v = CyAsLLRequestResponse_GetWord(req_p, 4) ;
+ dev_p->is_mtp_firmware = (CyBool)((v >> 8) & 0xFF) ;
+
+ if (dev_p->misc_event_cb)
+ dev_p->misc_event_cb((CyAsDeviceHandle)dev_p, CyAsEventMiscInitialized, 0) ;
+ }
+
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_VM_SET) ;
+ if (v & CY_AS_MEM_P0_VM_SET_CFGMODE)
+ CyAsHalPrintMessage("Initialization Message Recieved, but config bit still set\n") ;
+
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG) ;
+ if ((v & CY_AS_MEM_RST_RSTCMPT) ==0)
+ CyAsHalPrintMessage("Initialization Message Recieved, but reset complete bit still not set\n") ;
+ }
+ break ;
+
+ case CY_RQT_OUT_OF_SUSPEND:
+ CyAsLLSendStatusResponse(dev_p, CY_RQT_GENERAL_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
+ CyAsDeviceClearSuspendMode(dev_p) ;
+
+ /*
+ * If the wakeup was caused by an async CyAsMiscLeaveSuspend call, we have to
+ * call the corresponding callback.
+ */
+ if (dev_p->func_cbs_misc->count > 0)
+ {
+ CyAsFuncCBNode *node = (CyAsFuncCBNode*)dev_p->func_cbs_misc->head_p ;
+ CyAsHalAssert(node) ;
+
+ if (CyAsFunctCBTypeGetType(node->dataType) == CY_FUNCT_CB_MISC_LEAVESUSPEND)
+ {
+ CyAsHalAssert(node->cb_p != 0) ;
+ node->cb_p((CyAsDeviceHandle)dev_p, CY_AS_ERROR_SUCCESS, node->client_data,
+ CY_FUNCT_CB_MISC_LEAVESUSPEND, 0) ;
+ CyAsRemoveCBNode(dev_p->func_cbs_misc) ;
+ }
+ }
+
+ if (dev_p->misc_event_cb)
+ dev_p->misc_event_cb((CyAsDeviceHandle)dev_p, CyAsEventMiscWakeup, 0) ;
+ break ;
+
+ case CY_RQT_DEBUG_MESSAGE:
+ if ((req_p->data[0] == 0) && (req_p->data[1] == 0) && (req_p->data[2] == 0))
+ {
+ if (dev_p->misc_event_cb)
+ dev_p->misc_event_cb((CyAsDeviceHandle)dev_p, CyAsEventMiscHeartBeat, 0) ;
+ }
+ else
+ {
+ CyAsHalPrintMessage("**** Debug Message: %02x %02x %02x %02x %02x %02x\n",
+ req_p->data[0] & 0xff, (req_p->data[0] >> 8) & 0xff,
+ req_p->data[1] & 0xff, (req_p->data[1] >> 8) & 0xff,
+ req_p->data[2] & 0xff, (req_p->data[2] >> 8) & 0xff) ;
+ }
+ break ;
+
+ case CY_RQT_WB_DEVICE_MISMATCH:
+ {
+ if (dev_p->misc_event_cb)
+ dev_p->misc_event_cb((CyAsDeviceHandle)dev_p, CyAsEventMiscDeviceMismatch, 0) ;
+ }
+ break ;
+
+ case CY_RQT_BOOTLOAD_NO_FIRMWARE:
+ {
+ /* TODO Handle case when firmware is not found during bootloading. */
+ CyAsHalPrintMessage("No firmware image found during bootload. Device not started\n") ;
+ }
+ break ;
+
+ default:
+ CyAsHalAssert (0) ;
+ }
+}
+
+static CyBool
+IsValidSiliconId(uint16_t v)
+{
+ CyBool idok = CyFalse ;
+
+ /*
+ * Remove the revision number from the ID value
+ */
+ v = v & CY_AS_MEM_CM_WB_CFG_ID_HDID_MASK ;
+
+ /*
+ * If this is West Bridge, then we are OK.
+ */
+ if (v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE ||
+ v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE ||
+ v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE)
+ idok = CyTrue ;
+
+ return idok ;
+}
+
+/*
+* Configure the West Bridge device hardware
+*/
+CyAsReturnStatus_t
+CyAsMiscConfigureDevice(CyAsDeviceHandle handle, CyAsDeviceConfig *config_p)
+{
+ CyAsReturnStatus_t ret ;
+ CyBool standby ;
+ CyAsDevice *dev_p ;
+ uint16_t v ;
+ uint16_t fw_present;
+ CyAsLogDebugMessage(6, "CyAsMiscConfigureDevice called") ;
+
+ dev_p = (CyAsDevice *)handle ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ /* Setup big endian vs little endian */
+ CyAsSetupEndianMode(dev_p) ;
+
+ /* Now, confirm that we can talk to the West Bridge device */
+ dev_p->silicon_id = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;
+ fw_present = CyAsHalReadRegister(dev_p->tag,CY_AS_MEM_RST_CTRL_REG ) ;
+ if (!(fw_present & CY_AS_MEM_RST_RSTCMPT))
+ {
+ if (!IsValidSiliconId(dev_p->silicon_id))
+ return CY_AS_ERROR_NO_ANTIOCH ;
+ }
+ /* Check for standby mode */
+ ret = CyAsMiscInStandby(handle, &standby) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+ if (ret)
+ return CY_AS_ERROR_IN_STANDBY ;
+
+ /* Setup P-port interface mode (CRAM / SRAM). */
+ if (CyAsDeviceIsAstoriaDev(dev_p))
+ {
+ if (config_p->srammode)
+ v = CY_AS_MEM_P0_VM_SET_VMTYPE_SRAM ;
+ else
+ v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM ;
+ }
+ else
+ v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM ;
+
+ /* Setup synchronous versus asynchronous mode */
+ if (config_p->sync)
+ v |= CY_AS_MEM_P0_VM_SET_IFMODE ;
+ if (config_p->dackmode == CyAsDeviceDackAck)
+ v |= CY_AS_MEM_P0_VM_SET_DACKEOB ;
+ if (config_p->drqpol)
+ v |= CY_AS_MEM_P0_VM_SET_DRQPOL ;
+ if (config_p->dackpol)
+ v |= CY_AS_MEM_P0_VM_SET_DACKPOL ;
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_VM_SET, v) ;
+
+ if (config_p->crystal)
+ CyAsDeviceSetCrystal(dev_p) ;
+ else
+ CyAsDeviceSetExternalClock(dev_p) ;
+
+ /* Register a callback to handle MISC requests from the firmware */
+ CyAsLLRegisterRequestCallback(dev_p, CY_RQT_GENERAL_RQT_CONTEXT, MyMiscCallback) ;
+
+ /* Now mark the DMA and low level modules as active. */
+ CyAsDeviceSetDmaRunning(dev_p) ;
+ CyAsDeviceSetLowLevelRunning(dev_p) ;
+
+ /* Now, initialize the interrupt module */
+ dev_p->use_int_drq = config_p->dmaintr ;
+
+ ret = CyAsIntrStart(dev_p, config_p->dmaintr) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ /* Mark the interface as initialized */
+ CyAsDeviceSetConfigured(dev_p) ;
+
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+static void
+MyDmaCallback(CyAsDevice * dev_p,
+ CyAsEndPointNumber_t ep,
+ void * mem_p,
+ uint32_t size,
+ CyAsReturnStatus_t ret
+ )
+{
+ CyAsDmaEndPoint *ep_p ;
+
+ (void)size ;
+
+ /* Get the endpoint pointer based on the endpoint number */
+ ep_p = CY_AS_NUM_EP(dev_p, ep) ;
+
+ /* Check the queue to see if is drained */
+ if (ep_p->queue_p == 0)
+ {
+ CyAsFuncCBNode* node = (CyAsFuncCBNode*)dev_p->func_cbs_misc->head_p ;
+
+ CyAsHalAssert(node) ;
+
+ if (ret == CY_AS_ERROR_SUCCESS)
+ {
+ /*
+ * Disable endpoint 2. The storage module will enable this EP if necessary.
+ */
+ CyAsDmaEnableEndPoint(dev_p, CY_AS_FIRMWARE_ENDPOINT, CyFalse, CyAsDirectionIn) ;
+
+ /*
+ * Clear the reset register. This releases the Antioch micro-controller from
+ * reset and begins running the code at address zero.
+ */
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, 0x00) ;
+ }
+
+ /* Call the user Callback */
+ node->cb_p((CyAsDeviceHandle)dev_p, ret, node->client_data, (CyAsFunctCBType)node->dataType, node->data) ;
+ CyAsRemoveCBNode(dev_p->func_cbs_misc) ;
+ }
+ else
+ {
+ /* This is the header data that was allocated in the download firmware function,
+ * and can be safely freed here. */
+ uint32_t state = CyAsHalDisableInterrupts() ;
+ CyAsHalCBFree(mem_p) ;
+ CyAsHalEnableInterrupts(state) ;
+ }
+}
+
+CyAsReturnStatus_t
+CyAsMiscDownloadFirmware(CyAsDeviceHandle handle,
+ const void *mem_p,
+ uint16_t size,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ uint8_t *header ;
+ CyAsReturnStatus_t ret ;
+ CyBool standby ;
+ CyAsDevice *dev_p ;
+ CyAsDmaCallback dmacb = 0 ;
+ uint32_t state ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscDownloadFirmware called") ;
+
+ /* Make sure we have a valid device */
+ dev_p = (CyAsDevice *)handle ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ /*
+ * If the device has not been initialized, we cannot download firmware
+ * to the device.
+ */
+ if (!CyAsDeviceIsConfigured(dev_p))
+ return CY_AS_ERROR_NOT_CONFIGURED ;
+
+ /*
+ * Make sure West Bridge is not in standby
+ */
+ ret = CyAsMiscInStandby(dev_p, &standby) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if (standby)
+ return CY_AS_ERROR_IN_STANDBY ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ /*
+ * Make sure we are in configuration mode
+ */
+ if ((CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_VM_SET) & CY_AS_MEM_P0_VM_SET_CFGMODE) == 0)
+ return CY_AS_ERROR_NOT_IN_CONFIG_MODE ;
+
+ /* Maximum firmware size is 24k */
+ if (size > CY_AS_MAXIMUM_FIRMWARE_SIZE)
+ return CY_AS_ERROR_INVALID_SIZE ;
+
+ /* Make sure the size is an even number of bytes as well */
+ if (size & 0x01)
+ return CY_AS_ERROR_ALIGNMENT_ERROR ;
+
+ /*
+ * Write the two word header that gives the base address and
+ * size of the firmware image to download
+ */
+ state = CyAsHalDisableInterrupts() ;
+ header = (uint8_t *)CyAsHalCBAlloc(4) ;
+ CyAsHalEnableInterrupts(state) ;
+ if (header == NULL)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ header[0] = 0x00 ;
+ header[1] = 0x00 ;
+ header[2] = (uint8_t)(size & 0xff) ;
+ header[3] = (uint8_t)((size >> 8) & 0xff) ;
+
+ /* Enable the firmware endpoint */
+ ret = CyAsDmaEnableEndPoint(dev_p, CY_AS_FIRMWARE_ENDPOINT, CyTrue, CyAsDirectionIn) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ /*
+ * Setup DMA for 64 byte packets. This is the requirement for downloading
+ * firmware to West Bridge.
+ */
+ CyAsDmaSetMaxDmaSize(dev_p, CY_AS_FIRMWARE_ENDPOINT, 64) ;
+
+ if(cb)
+ {
+ dmacb = MyDmaCallback ;
+ }
+
+ ret = CyAsDmaQueueRequest(dev_p, CY_AS_FIRMWARE_ENDPOINT, header, 4, CyFalse, CyFalse, dmacb) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ /*
+ * Write the firmware image to the West Bridge device
+ */
+ ret = CyAsDmaQueueRequest(dev_p, CY_AS_FIRMWARE_ENDPOINT, (void *)mem_p, size, CyFalse, CyFalse, dmacb) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if(cb)
+ {
+ CyAsFuncCBNode* cbnode = CyAsCreateFuncCBNodeData(cb, client, CY_FUNCT_CB_MISC_DOWNLOADFIRMWARE, 0) ;
+
+ if(cbnode == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ else
+ CyAsInsertCBNode(dev_p->func_cbs_misc, cbnode) ;
+
+ ret = CyAsDmaKickStart(dev_p, CY_AS_FIRMWARE_ENDPOINT) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+ }
+ else
+ {
+
+ ret = CyAsDmaDrainQueue(dev_p, CY_AS_FIRMWARE_ENDPOINT, CyTrue) ;
+
+ /* Free the header memory that was allocated earlier. */
+ CyAsHalCBFree(header) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ return ret ;
+ }
+ /*
+ * Disable endpoint 2. The storage module will enable this EP if necessary.
+ */
+ CyAsDmaEnableEndPoint(dev_p, CY_AS_FIRMWARE_ENDPOINT, CyFalse, CyAsDirectionIn) ;
+
+ /*
+ * Clear the reset register. This releases the West Bridge micro-controller from
+ * reset and begins running the code at address zero.
+ */
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, 0x00) ;
+ }
+
+ /*
+ * The firmware is not marked as loaded until the firmware initializes West Bridge and a request
+ * is sent from West Bridge to the P port processor indicating that West Bridge is ready.
+ */
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+
+static CyAsReturnStatus_t
+MyHandleResponseGetFirmwareVersion(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ CyAsGetFirmwareVersionData *data_p)
+{
+
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint16_t val ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_FIRMWARE_VERSION)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ data_p->major = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ data_p->minor = CyAsLLRequestResponse_GetWord(reply_p, 1) ;
+ data_p->build = CyAsLLRequestResponse_GetWord(reply_p, 2) ;
+ val = CyAsLLRequestResponse_GetWord(reply_p, 3) ;
+ data_p->mediaType = (uint8_t)(((val >> 8) & 0xFF) | (val & 0xFF)) ;
+ val = CyAsLLRequestResponse_GetWord(reply_p, 4) ;
+ data_p->isDebugMode = (CyBool)(val & 0xFF) ;
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscGetFirmwareVersion(CyAsDeviceHandle handle,
+ CyAsGetFirmwareVersionData* data,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyBool standby ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+
+ CyAsDevice *dev_p ;
+
+ (void)client ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscGetFirmwareVersion called") ;
+
+ /* Make sure we have a valid device */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ /*
+ * Make sure Antioch is not in standby
+ */
+ ret = CyAsMiscInStandby(dev_p, &standby) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+ if (standby)
+ return CY_AS_ERROR_IN_STANDBY ;
+
+ /* Make sure the Antioch is not in suspend mode. */
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_GET_FIRMWARE_VERSION, CY_RQT_GENERAL_RQT_CONTEXT, 0) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ /* Reserve space for the reply, the reply data will not exceed three words */
+ reply_p = CyAsLLCreateResponse(dev_p, 5) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* Request and response are freed in MyHandleResponseGetFirmwareVersion. */
+ ret = MyHandleResponseGetFirmwareVersion(dev_p, req_p, reply_p, data) ;
+ return ret ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_GETFIRMWAREVERSION,
+ data, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p,
+ reply_p, CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+static CyAsReturnStatus_t
+MyHandleResponseReadMCURegister(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ uint8_t *data_p)
+{
+
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_MCU_REGISTER_DATA)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ *data_p = (uint8_t)(CyAsLLRequestResponse_GetWord(reply_p, 0)) ;
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseGetGpioValue(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ uint8_t *data_p)
+{
+
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_GPIO_STATE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+ else
+ *data_p = (uint8_t)(CyAsLLRequestResponse_GetWord(reply_p, 0)) ;
+
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+
+CyAsReturnStatus_t CyAsMiscSetSDPowerPolarity(
+ CyAsDeviceHandle handle,
+ CyAsMiscSignalPolarity polarity,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if (!CyAsDeviceIsConfigured(dev_p))
+ return CY_AS_ERROR_NOT_CONFIGURED ;
+
+ if (!CyAsDeviceIsFirmwareLoaded(dev_p))
+ return CY_AS_ERROR_NO_FIRMWARE ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDPOLARITY , CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ {
+
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+ CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)polarity) ;
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ return (MyHandleResponseNoData(dev_p, req_p, reply_p)) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_SETSDPOLARITY,
+ 0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
+ req_p, reply_p, CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the FuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ return ret ;
+}
+
+
+
+
+
+CyAsReturnStatus_t
+CyAsMiscReadMCURegister(CyAsDeviceHandle handle,
+ uint16_t address,
+ uint8_t *value,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+
+ CyAsDevice *dev_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscReadMCURegister called") ;
+
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ /* Check whether the firmware supports this command. */
+ if (CyAsDeviceIsNandStorageSupported(dev_p))
+ return CY_AS_ERROR_NOT_SUPPORTED ;
+
+ /* Make sure the Antioch is not in suspend mode. */
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_READ_MCU_REGISTER, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)address) ;
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_MCU_REGISTER_DATA)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ *value = (uint8_t)(CyAsLLRequestResponse_GetWord(reply_p, 0)) ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_READMCUREGISTER,
+ value, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+ CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+
+CyAsReturnStatus_t
+CyAsMiscWriteMCURegister(CyAsDeviceHandle handle,
+ uint16_t address,
+ uint8_t mask,
+ uint8_t value,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsDevice *dev_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscWriteMCURegister called") ;
+
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ /* Check whether the firmware supports this command. */
+ if (CyAsDeviceIsNandStorageSupported(dev_p))
+ return CY_AS_ERROR_NOT_SUPPORTED ;
+
+ /* Make sure the Antioch is not in suspend mode. */
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_WRITE_MCU_REGISTER, CY_RQT_GENERAL_RQT_CONTEXT, 2) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)address) ;
+ CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((mask << 8) | value)) ;
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_WRITEMCUREGISTER,
+ 0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+ CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+MyHandleResponseReset(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ CyAsResetType type)
+{
+ uint16_t v ;
+
+ (void)req_p ;
+ (void)reply_p ;
+
+ /*
+ * If the device is in suspend mode, it needs to be woken up so that the write
+ * to the reset control register succeeds. We need not however wait for the
+ * wake up procedure to be complete.
+ */
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ {
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;
+ CyAsHalSleep (1) ;
+ }
+
+ if (type == CyAsResetHard)
+ {
+ CyAsMiscCancelExRequests(dev_p) ;
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, CY_AS_MEM_RST_CTRL_REG_HARD) ;
+ CyAsDeviceSetUnconfigured(dev_p) ;
+ CyAsDeviceSetFirmwareNotLoaded(dev_p) ;
+ CyAsDeviceSetDmaStopped(dev_p) ;
+ CyAsDeviceSetLowLevelStopped(dev_p) ;
+ CyAsDeviceSetIntrStopped(dev_p) ;
+ CyAsDeviceClearSuspendMode(dev_p) ;
+ CyAsUsbCleanup(dev_p) ;
+ CyAsStorageCleanup(dev_p) ;
+
+ /*
+ * Wait for a small amount of time to allow reset to be complete.
+ */
+ CyAsHalSleep(100) ;
+ }
+
+ CyAsDeviceClearResetPending(dev_p) ;
+
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscReset(CyAsDeviceHandle handle,
+ CyAsResetType type,
+ CyBool flush,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p ;
+ CyAsEndPointNumber_t i ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ (void)client ;
+ (void)cb ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscResetEX called") ;
+
+ /* Make sure the device is ready for the command. */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ /*
+ * Soft reset is not supported until we close on the issues in the
+ * firmware with what needs to happen.
+ */
+ if (type == CyAsResetSoft)
+ return CY_AS_ERROR_NOT_YET_SUPPORTED ;
+
+ CyAsDeviceSetResetPending(dev_p) ;
+
+ if (flush)
+ {
+
+ /* Unable to DrainQueues in polling mode */
+ if((dev_p->storage_cb || dev_p->storage_cb_ms) && CyAsHalIsPolling())
+ return CY_AS_ERROR_ASYNC_PENDING ;
+
+ /*
+ * Shutdown the endpoints so no more traffic can be queued
+ */
+ for(i = 0; i < 15; i++)
+ CyAsDmaEnableEndPoint(dev_p, i, CyFalse, CyAsDirectionDontChange) ;
+
+ /*
+ * If we are in normal mode, drain all traffic across all endpoints to be sure all traffic
+ * is flushed. If the device is suspended, data will not be coming in on any endpoint and
+ * all outstanding DMA operations can be canceled.
+ */
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ {
+ for(i = 0; i < 15; i++)
+ {
+ CyAsDmaCancel(dev_p, i, CY_AS_ERROR_CANCELED) ;
+ }
+ }
+ else
+ {
+ for(i = 0; i < 15; i++)
+ {
+ if ((i == CY_AS_P2S_WRITE_ENDPOINT) || (i == CY_AS_P2S_READ_ENDPOINT))
+ CyAsDmaDrainQueue(dev_p, i, CyFalse) ;
+ else
+ CyAsDmaDrainQueue(dev_p, i, CyTrue) ;
+ }
+ }
+ }
+ else
+ {
+ /* No flush was requested, so cancel any outstanding DMAs
+ * so the user callbacks are called as needed
+ */
+ if(CyAsDeviceIsStorageAsyncPending(dev_p))
+ {
+ for(i = 0; i < 15; i++)
+ CyAsDmaCancel(dev_p, i, CY_AS_ERROR_CANCELED) ;
+ }
+ }
+
+ ret = MyHandleResponseReset(dev_p, 0, 0, type) ;
+
+ if(cb)
+ /* Even though no mailbox communication was needed, issue the callback so the
+ * user does not need to special case their code. */
+ cb((CyAsDeviceHandle)dev_p, ret, client, CY_FUNCT_CB_MISC_RESET, 0) ;
+
+ /*
+ * Initialize any registers that may have been changed when the device was reset.
+ */
+ CyAsHalInitDevRegisters(dev_p->tag, CyFalse) ;
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+GetUnallocatedResource(CyAsDevice *dev_p, CyAsResourceType resource)
+{
+ uint8_t shift = 0 ;
+ uint16_t v ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_NOT_ACQUIRED ;
+
+ switch(resource)
+ {
+ case CyAsBusUSB:
+ shift = 4 ;
+ break ;
+ case CyAsBus_1:
+ shift = 0 ;
+ break ;
+ case CyAsBus_0:
+ shift = 2 ;
+ break ;
+ default:
+ CyAsHalAssert(CyFalse) ;
+ break ;
+ }
+
+ /* Get the semaphore value for this resource */
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE) ;
+ v = (v >> shift) & 0x03 ;
+
+ if (v == 0x03)
+ {
+ ret = CY_AS_ERROR_RESOURCE_ALREADY_OWNED ;
+ }
+ else if ((v & 0x01) == 0)
+ {
+ /* The resource is not owned by anyone, we can try to get it */
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_RSE_MASK, (0x03 << shift)) ;
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_RSE_MASK) ;
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE, (0x01 << shift)) ;
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_RSE_MASK) ;
+
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE) ;
+ v = (v >> shift) & 0x03 ;
+ if (v == 0x03)
+ ret = CY_AS_ERROR_SUCCESS ;
+ }
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseAcquireResource(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ CyAsResourceType *resource)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ if (ret == CY_AS_ERROR_SUCCESS)
+ {
+ ret = GetUnallocatedResource(dev_p, *resource) ;
+ if (ret != CY_AS_ERROR_NOT_ACQUIRED)
+ ret = CY_AS_ERROR_SUCCESS ;
+ }
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscAcquireResource(CyAsDeviceHandle handle,
+ CyAsResourceType *resource,
+ CyBool force,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsReturnStatus_t ret ;
+
+ CyAsDevice *dev_p ;
+
+ (void)client ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscAcquireResource called") ;
+
+ if (*resource != CyAsBusUSB && *resource != CyAsBus_0 && *resource != CyAsBus_1)
+ return CY_AS_ERROR_INVALID_RESOURCE ;
+
+
+ /* Make sure the device is ready to accept the command. */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+
+ ret = GetUnallocatedResource(dev_p, *resource) ;
+
+ /*
+ * Make sure that the callback is called if the resource is successfully
+ * acquired at this point.
+ */
+ if ((ret == CY_AS_ERROR_SUCCESS) && (cb != 0))
+ cb(handle, ret, client, CY_FUNCT_CB_MISC_ACQUIRERESOURCE, resource) ;
+
+ if (ret != CY_AS_ERROR_NOT_ACQUIRED)
+ return ret ;
+
+ if (!force)
+ return CY_AS_ERROR_NOT_ACQUIRED ;
+
+ /* Create the request to acquire the resource */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_ACQUIRE_RESOURCE, CY_RQT_RESOURCE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)(*resource)) ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_ACQUIRERESOURCE,
+ resource, dev_p->func_cbs_res, CY_AS_REQUEST_RESPONSE_EX, req_p,
+ reply_p, CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ if (ret == CY_AS_ERROR_SUCCESS)
+ {
+ ret = GetUnallocatedResource(dev_p, *resource) ;
+ if (ret != CY_AS_ERROR_NOT_ACQUIRED)
+ ret = CY_AS_ERROR_SUCCESS ;
+ }
+
+ return ret ;
+}
+CyAsReturnStatus_t
+CyAsMiscReleaseResource(CyAsDeviceHandle handle, CyAsResourceType resource)
+{
+ uint8_t shift = 0 ;
+ uint16_t v ;
+
+ CyAsDevice *dev_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscReleaseResource called") ;
+
+ /* Make sure the device is ready for the command. */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ if (resource != CyAsBusUSB && resource != CyAsBus_0 && resource != CyAsBus_1)
+ return CY_AS_ERROR_INVALID_RESOURCE ;
+
+ switch(resource)
+ {
+ case CyAsBusUSB:
+ shift = 4 ;
+ break ;
+ case CyAsBus_1:
+ shift = 0 ;
+ break ;
+ case CyAsBus_0:
+ shift = 2 ;
+ break ;
+ default:
+ CyAsHalAssert(CyFalse) ;
+ break ;
+ }
+
+ /* Get the semaphore value for this resource */
+ v = (CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE) >> shift) & 0x03 ;
+ if (v == 0 || v == 1 || v == 2)
+ return CY_AS_ERROR_RESOURCE_NOT_OWNED ;
+
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_RSE_MASK, (0x03 << shift)) ;
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE, (0x02 << shift)) ;
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_P0_RSE_MASK, 0) ;
+
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscSetTraceLevel(CyAsDeviceHandle handle,
+ uint8_t level,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint32_t unit,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsReturnStatus_t ret ;
+ CyAsDevice *dev_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscSetTraceLevel called") ;
+
+ /* Make sure the device is ready for the command. */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ if (bus < 0 || bus >= CY_AS_MAX_BUSES)
+ return CY_AS_ERROR_NO_SUCH_BUS ;
+
+ if (device >= CY_AS_MAX_STORAGE_DEVICES)
+ return CY_AS_ERROR_NO_SUCH_DEVICE ;
+
+ if (unit > 255)
+ return CY_AS_ERROR_NO_SUCH_UNIT ;
+
+ if (level >= CYAS_FW_TRACE_MAX_LEVEL)
+ return CY_AS_ERROR_INVALID_TRACE_LEVEL ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SET_TRACE_LEVEL, CY_RQT_GENERAL_RQT_CONTEXT, 2) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)level) ;
+ CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((bus << 12) | (device << 8) | (unit))) ;
+
+ /* Reserve space for the reply, the reply data will not exceed three words */
+ reply_p = CyAsLLCreateResponse(dev_p, 2) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_NOT_SUPPORTED ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_SETTRACELEVEL,
+ 0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+ CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscHeartBeatControl(CyAsDeviceHandle handle,
+ CyBool enable,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsReturnStatus_t ret ;
+ CyAsDevice *dev_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscHeartBeatControl called") ;
+
+ /* Make sure the device is ready for the command. */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_CONTROL_ANTIOCH_HEARTBEAT, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)enable) ;
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_HEARTBEATCONTROL,
+ 0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+ CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+MySetSDClockFreq (
+ CyAsDevice *dev_p,
+ uint8_t cardType,
+ uint8_t setting,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+
+ if (CyAsDeviceIsInCallback(dev_p) && (cb == 0))
+ return CY_AS_ERROR_INVALID_IN_CALLBACK ;
+
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SET_SD_CLOCK_FREQ, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)((cardType << 8) | setting)) ;
+
+ /* Reserve space for the reply, which will not exceed one word. */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if (cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_SETSDFREQ, 0,
+ dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscSetLowSpeedSDFreq(
+ CyAsDeviceHandle handle,
+ CyAsLowSpeedSDFreq setting,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscSetLowSpeedSDFreq called") ;
+
+ /* Make sure the device is ready for the command. */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ if ((setting != CY_AS_SD_DEFAULT_FREQ) && (setting != CY_AS_SD_RATED_FREQ))
+ return CY_AS_ERROR_INVALID_PARAMETER ;
+
+ return MySetSDClockFreq(dev_p, 0, (uint8_t)setting, cb, client) ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscSetHighSpeedSDFreq(
+ CyAsDeviceHandle handle,
+ CyAsHighSpeedSDFreq setting,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscSetHighSpeedSDFreq called") ;
+
+ /* Make sure the device is ready for the command. */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ if ((setting != CY_AS_HS_SD_FREQ_24) && (setting != CY_AS_HS_SD_FREQ_48))
+ return CY_AS_ERROR_INVALID_PARAMETER ;
+
+ return MySetSDClockFreq(dev_p, 1, (uint8_t)setting, cb, client) ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscGetGpioValue(CyAsDeviceHandle handle,
+ CyAsMiscGpio pin,
+ uint8_t *value,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsDevice *dev_p ;
+ uint16_t v ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscGetGpioValue called") ;
+
+ /* Make sure the device is ready for the command. */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ /* If the pin specified is UVALID, there is no need for firmware to be loaded. */
+ if (pin == CyAsMiscGpio_UValid)
+ {
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_PMU_UPDATE) ;
+ *value = (uint8_t)(v & CY_AS_MEM_PMU_UPDATE_UVALID) ;
+
+ if (cb != 0)
+ cb(dev_p, ret, client, CY_FUNCT_CB_MISC_GETGPIOVALUE, value) ;
+
+ return ret ;
+ }
+
+ /* Check whether the firmware supports this command. */
+ if (CyAsDeviceIsNandStorageSupported(dev_p))
+ return CY_AS_ERROR_NOT_SUPPORTED ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ /* Make sure the pin selected is valid */
+ if ((pin != CyAsMiscGpio_1) && (pin != CyAsMiscGpio_0))
+ return CY_AS_ERROR_INVALID_PARAMETER ;
+
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_GET_GPIO_STATE, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, ((uint8_t)pin << 8)) ;
+
+ /* Reserve space for the reply, which will not exceed one word. */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if (cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_GPIO_STATE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ *value = (uint8_t)CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_GETGPIOVALUE,
+ value, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+ CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+
+CyAsReturnStatus_t
+CyAsMiscSetGpioValue(CyAsDeviceHandle handle,
+ CyAsMiscGpio pin,
+ uint8_t value,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsDevice *dev_p ;
+ uint16_t v ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscSetGpioValue called") ;
+
+ /* Make sure the device is ready for the command. */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ /* If the pin specified is UVALID, there is no need for firmware to be loaded. */
+ if (pin == CyAsMiscGpio_UValid)
+ {
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_PMU_UPDATE) ;
+ if (value)
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_PMU_UPDATE, (v | CY_AS_MEM_PMU_UPDATE_UVALID)) ;
+ else
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_PMU_UPDATE, (v & ~CY_AS_MEM_PMU_UPDATE_UVALID)) ;
+
+ if (cb != 0)
+ cb(dev_p, ret, client, CY_FUNCT_CB_MISC_SETGPIOVALUE, 0) ;
+ return ret ;
+ }
+
+ /* Check whether the firmware supports this command. */
+ if (CyAsDeviceIsNandStorageSupported(dev_p))
+ return CY_AS_ERROR_NOT_SUPPORTED ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ /* Make sure the pin selected is valid */
+ if ((pin < CyAsMiscGpio_0) || (pin > CyAsMiscGpio_UValid))
+ return CY_AS_ERROR_INVALID_PARAMETER ;
+
+ /* Create and initialize the low level request to the firmware. */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SET_GPIO_STATE, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ v = (uint16_t)(((uint8_t)pin << 8) | (value > 0)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 0, v) ;
+
+ /* Reserve space for the reply, which will not exceed one word. */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if (cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_SETGPIOVALUE,
+ 0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+ CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+MyEnterStandby(CyAsDevice *dev_p, CyBool pin)
+{
+ CyAsMiscCancelExRequests(dev_p) ;
+
+ /* Save the current values in the critical P-port registers, where necessary. */
+ CyAsHalReadRegsBeforeStandby(dev_p->tag) ;
+
+ if (pin)
+ {
+ if (CyAsHalSetWakeupPin(dev_p->tag, CyFalse))
+ CyAsDeviceSetPinStandby(dev_p) ;
+ else
+ return CY_AS_ERROR_SETTING_WAKEUP_PIN ;
+ }
+ else
+ {
+ /*
+ * Put antioch in the standby mode
+ */
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_PWR_MAGT_STAT, 0x02) ;
+ CyAsDeviceSetRegisterStandby(dev_p) ;
+ }
+
+ /*
+ * When the Antioch comes out of standby, we have to wait until
+ * the firmware initialization completes before sending other
+ * requests down.
+ */
+ CyAsDeviceSetFirmwareNotLoaded(dev_p) ;
+
+ /*
+ * Keep West Bridge interrupt disabled until the device is being woken
+ * up from standby.
+ */
+ dev_p->stby_int_mask = CyAsHalDisableInterrupts ();
+
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseEnterStandby(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ CyBool pin)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ ret = MyEnterStandby(dev_p, pin) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscEnterStandby(CyAsDeviceHandle handle,
+ CyBool pin,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyBool standby ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscEnterStandby called") ;
+
+ /* Make sure we have a valid device */
+ dev_p = (CyAsDevice *)handle ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ /*
+ * If we already are in standby, do not do it again and let the
+ * user know via the error return.
+ */
+ ret = CyAsMiscInStandby(handle, &standby) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if (standby == CyTrue)
+ return CY_AS_ERROR_ALREADY_STANDBY ;
+
+ /*
+ * If the user wants to transition from suspend mode to standby mode,
+ * the device needs to be woken up so that it can complete all pending
+ * operations.
+ */
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ CyAsMiscLeaveSuspend(dev_p, 0, 0) ;
+
+ if (dev_p->usb_count)
+ {
+ /*
+ * We do not allow West Bridge to go into standby mode when the
+ * USB stack is initialized. You must stop the USB stack in
+ * order to enter standby mode.
+ */
+ return CY_AS_ERROR_USB_RUNNING ;
+ }
+
+ /*
+ * If the storage stack is not running, the device can directly be put into
+ * sleep mode. Otherwise, the firmware needs to be signaled to prepare for
+ * going into sleep mode.
+ */
+ if (dev_p->storage_count)
+ {
+ /*
+ * If there are async storage operations pending, make one attempt to
+ * complete them.
+ */
+ if (CyAsDeviceIsStorageAsyncPending(dev_p))
+ {
+ /* DrainQueue will not work in polling mode */
+ if(CyAsHalIsPolling())
+ return CY_AS_ERROR_ASYNC_PENDING ;
+
+ CyAsDmaDrainQueue(dev_p, CY_AS_P2S_READ_ENDPOINT, CyFalse) ;
+ CyAsDmaDrainQueue(dev_p, CY_AS_P2S_WRITE_ENDPOINT, CyFalse) ;
+
+ /*
+ * If more storage operations were queued at this stage, return
+ * an error.
+ */
+ if (CyAsDeviceIsStorageAsyncPending(dev_p))
+ return CY_AS_ERROR_ASYNC_PENDING ;
+ }
+
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_PREPARE_FOR_STANDBY, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(!cb)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed in the HandleResponse */
+ return MyHandleResponseEnterStandby(dev_p, req_p, reply_p, pin) ;
+
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_ENTERSTANDBY,
+ (void*)pin, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p,
+ reply_p, CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ }
+ else
+ {
+ ret = MyEnterStandby(dev_p, pin) ;
+ if(cb)
+ /* Even though no mailbox communication was needed, issue the callback so the
+ * user does not need to special case their code. */
+ cb((CyAsDeviceHandle)dev_p, ret, client, CY_FUNCT_CB_MISC_ENTERSTANDBY, 0) ;
+ }
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscEnterStandbyEXU(CyAsDeviceHandle handle,
+ CyBool pin,
+ CyBool uvalid_special,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p ;
+
+ dev_p = (CyAsDevice *)handle ;
+ if(uvalid_special)
+ {
+ CyAsHalWriteRegister(dev_p->tag, 0xc5, 0x4) ;
+ }
+
+ return CyAsMiscEnterStandby(handle, pin, cb, client) ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscLeaveStandby(CyAsDeviceHandle handle, CyAsResourceType resource)
+{
+ CyAsDevice *dev_p ;
+ uint16_t v ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint32_t count = 8 ;
+ uint8_t retry = 1 ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscLeaveStandby called") ;
+ (void)resource ;
+
+ /* Make sure we have a valid device */
+ dev_p = (CyAsDevice *)handle ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if (CyAsDeviceIsRegisterStandby(dev_p))
+ {
+ /*
+ * Set a flag to indicate that the West Bridge is waking up from standby.
+ */
+ CyAsDeviceSetWaking(dev_p) ;
+
+ /*
+ * The initial read will not succeed, but will just wake the West Bridge
+ * device from standby. Successive reads should succeed and in that way
+ * we know West Bridge is awake.
+ */
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;
+
+ do
+ {
+ /*
+ * We have initiated the operation to leave standby, now we need to wait at least
+ * N ms before trying to access the West Bridge device to insure the PLLs have locked and we
+ * can talk to the device.
+ */
+ if (CyAsDeviceIsCrystal(dev_p))
+ CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL) ;
+ else
+ CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ;
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;
+
+ /*
+ * If the P-SPI interface mode is in use, there may be a need to re-synchronise the
+ * serial clock used for Astoria access.
+ */
+ if (!IsValidSiliconId(v))
+ {
+ if (CyAsHalSyncDeviceClocks(dev_p->tag) != CyTrue)
+ {
+ CyAsHalEnableInterrupts (dev_p->stby_int_mask) ;
+ return CY_AS_ERROR_TIMEOUT ;
+ }
+ }
+ } while (!IsValidSiliconId(v) && count-- > 0) ;
+
+ /*
+ * If we tried to read the register and could not, return a timeout
+ */
+ if (count == 0)
+ {
+ CyAsHalEnableInterrupts (dev_p->stby_int_mask) ;
+ return CY_AS_ERROR_TIMEOUT ;
+ }
+
+ /*
+ * The standby flag is cleared here, after the action to exit standby has
+ * been taken. The wait for firmware initialization, is ensured by marking
+ * the firmware as not loaded until the init event is received.
+ */
+ CyAsDeviceClearRegisterStandby(dev_p) ;
+
+ /*
+ * Initialize any registers that may have been changed while the device was in standby mode.
+ */
+ CyAsHalInitDevRegisters(dev_p->tag, CyTrue) ;
+ }
+ else if (CyAsDeviceIsPinStandby(dev_p))
+ {
+ /*
+ * Set a flag to indicate that the West Bridge is waking up from standby.
+ */
+ CyAsDeviceSetWaking(dev_p) ;
+
+TryWakeupAgain:
+ /*
+ * Try to set the wakeup pin, if this fails in the HAL layer, return this
+ * failure to the user.
+ */
+ if (!CyAsHalSetWakeupPin(dev_p->tag, CyTrue))
+ {
+ CyAsHalEnableInterrupts (dev_p->stby_int_mask) ;
+ return CY_AS_ERROR_SETTING_WAKEUP_PIN ;
+ }
+
+ /*
+ * We have initiated the operation to leave standby, now we need to wait at least
+ * N ms before trying to access the West Bridge device to insure the PLLs have locked and we
+ * can talk to the device.
+ */
+ if (CyAsDeviceIsCrystal(dev_p))
+ CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL) ;
+ else
+ CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ;
+
+ /*
+ * Initialize any registers that may have been changed while the device was in standby mode.
+ */
+ CyAsHalInitDevRegisters(dev_p->tag, CyTrue) ;
+
+ /*
+ * The standby flag is cleared here, after the action to exit standby has
+ * been taken. The wait for firmware initialization, is ensured by marking
+ * the firmware as not loaded until the init event is received.
+ */
+ CyAsDeviceClearPinStandby(dev_p) ;
+ }
+ else
+ {
+ return CY_AS_ERROR_NOT_IN_STANDBY ;
+ }
+
+ /*
+ * The West Bridge interrupt can be enabled now.
+ */
+ CyAsHalEnableInterrupts (dev_p->stby_int_mask) ;
+
+ /*
+ * Release the West Bridge Micro-Controller from reset, so that firmware initialization
+ * can complete.
+ * The attempt to release Antioch reset is made upto 8 times.
+ */
+ v = 0x03 ;
+ count = 0x08 ;
+ while ((v & 0x03) && (count))
+ {
+ CyAsHalWriteRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, 0x00) ;
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_RST_CTRL_REG) ;
+ count-- ;
+ }
+
+ if (v & 0x03)
+ {
+ CyAsHalPrintMessage("Failed to clear Antioch reset\n") ;
+ return CY_AS_ERROR_TIMEOUT ;
+ }
+
+ /*
+ * If the wake-up pin is being used, wait here to make sure that the wake-up event
+ * is received within a reasonable delay. Otherwise, toggle the wake-up pin again
+ * in an attempt to start the firmware properly.
+ */
+ if (retry)
+ {
+ count = 10 ;
+ while (count)
+ {
+ /* If the wake-up event has been received, we can return. */
+ if (CyAsDeviceIsFirmwareLoaded (dev_p))
+ break ;
+ /* If we are in polling mode, the interrupt may not have been serviced as yet.
+ * Read the interrupt status register. If a pending mailbox interrupt is seen,
+ * we can assume that the wake-up event will be received soon. */
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_P0_INTR_REG) ;
+ if (v & CY_AS_MEM_P0_INTR_REG_MBINT)
+ break ;
+
+ CyAsHalSleep (10) ;
+ count-- ;
+ }
+
+ if (!count)
+ {
+ retry = 0 ;
+ dev_p->stby_int_mask = CyAsHalDisableInterrupts() ;
+ CyAsHalSetWakeupPin(dev_p->tag, CyFalse) ;
+ CyAsHalSleep (10) ;
+ goto TryWakeupAgain ;
+ }
+ }
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscRegisterCallback(
+ CyAsDeviceHandle handle, /* Handle to the West Bridge device */
+ CyAsMiscEventCallback callback /* The function to call */
+ )
+{
+ CyAsDevice *dev_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscRegisterCallback called") ;
+
+ /* Make sure we have a valid device */
+ dev_p = (CyAsDevice *)handle ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ dev_p->misc_event_cb = callback ;
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscStorageChanged(CyAsDeviceHandle handle,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyBool standby ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscStorageChanged called") ;
+
+ /* Make sure the device is ready for the command. */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ /*
+ * Make sure Antioch is not in standby
+ */
+ ret = CyAsMiscInStandby(dev_p, &standby) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if (standby)
+ return CY_AS_ERROR_IN_STANDBY ;
+
+ /*
+ * Make sure Westbridge is not in suspend mode.
+ */
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_STORAGE_MEDIA_CHANGED, CY_RQT_GENERAL_RQT_CONTEXT, 0) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_STORAGECHANGED,
+ 0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+ CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+
+CyAsReturnStatus_t
+CyAsMiscEnterSuspend(
+ CyAsDeviceHandle handle,
+ CyBool usb_wakeup_en,
+ CyBool gpio_wakeup_en,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyBool standby ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ uint16_t value ;
+ uint32_t int_state ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscEnterSuspend called") ;
+
+ /*
+ * Basic sanity checks to ensure that the device is initialised.
+ */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ /*
+ * Make sure West Bridge is not already in standby
+ */
+ CyAsMiscInStandby(dev_p, &standby) ;
+ if (standby)
+ return CY_AS_ERROR_IN_STANDBY ;
+
+ /*
+ * Make sure that the device is not already in suspend mode.
+ */
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ /*
+ * Make sure there is no active USB connection.
+ */
+ if ((CyAsDeviceIsUsbConnected(dev_p)) && (dev_p->usb_last_event != CyAsEventUsbSuspend))
+ return CY_AS_ERROR_USB_CONNECTED ;
+
+ /*
+ * Make sure that there are no async requests at this point in time.
+ */
+ int_state = CyAsHalDisableInterrupts() ;
+ if ((dev_p->func_cbs_misc->count) || (dev_p->func_cbs_res->count) ||
+ (dev_p->func_cbs_stor->count) || (dev_p->func_cbs_usb->count))
+ {
+ CyAsHalEnableInterrupts(int_state) ;
+ return CY_AS_ERROR_ASYNC_PENDING ;
+ }
+ CyAsHalEnableInterrupts(int_state) ;
+
+ /* Create the request to send to the Antioch device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_ENTER_SUSPEND_MODE, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ /* Wakeup control flags. */
+ value = 0x0001 ;
+ if (usb_wakeup_en)
+ value |= 0x04 ;
+ if (gpio_wakeup_en)
+ value |= 0x02 ;
+ CyAsLLRequestResponse_SetWord(req_p, 0, value) ;
+
+ if (cb != 0)
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_ENTERSUSPEND,
+ 0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+ CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ return CY_AS_ERROR_SUCCESS ;
+ }
+ else
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ else
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+
+destroy:
+ if (ret == CY_AS_ERROR_SUCCESS)
+ CyAsDeviceSetSuspendMode(dev_p) ;
+
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscLeaveSuspend(
+ CyAsDeviceHandle handle,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p ;
+ uint16_t v, count ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscLeaveSuspend called") ;
+
+ /* Make sure we have a valid device */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ /* Make sure we are in suspend mode. */
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ {
+ if (cb)
+ {
+ CyAsFuncCBNode *cbnode = CyAsCreateFuncCBNodeData(cb, client, CY_FUNCT_CB_MISC_LEAVESUSPEND, 0) ;
+ if (cbnode == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsInsertCBNode(dev_p->func_cbs_misc, cbnode) ;
+ }
+
+ /*
+ * Do a read from the ID register so that the CE assertion will wake West Bridge.
+ * The read is repeated until the read comes back with valid data.
+ */
+ count = 8 ;
+
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;
+
+ while (!IsValidSiliconId(v) && count-- > 0)
+ {
+ CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ;
+ v = CyAsHalReadRegister(dev_p->tag, CY_AS_MEM_CM_WB_CFG_ID) ;
+ }
+
+ /*
+ * If we tried to read the register and could not, return a timeout
+ */
+ if (count == 0)
+ return CY_AS_ERROR_TIMEOUT ;
+ }
+ else
+ return CY_AS_ERROR_NOT_IN_SUSPEND ;
+
+ if (cb == 0)
+ {
+ /*
+ * Wait until the in suspend mode flag is cleared.
+ */
+ count = 20 ;
+ while ((CyAsDeviceIsInSuspendMode(dev_p)) && (count--))
+ {
+ CyAsHalSleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ;
+ }
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ ret = CY_AS_ERROR_TIMEOUT ;
+ }
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscReserveLNABootArea(CyAsDeviceHandle handle,
+ uint8_t numzones,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyBool standby ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+
+ CyAsDevice *dev_p ;
+
+ (void)client ;
+
+ CyAsLogDebugMessage(6, "CyAsMiscSwitchPnandMode called") ;
+
+ /* Make sure we have a valid device */
+ dev_p = (CyAsDevice *)handle ;
+ CyAsCheckDeviceReady(dev_p) ;
+
+ /*
+ * Make sure Antioch is not in standby
+ */
+ ret = CyAsMiscInStandby(dev_p, &standby) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+ if (standby)
+ return CY_AS_ERROR_IN_STANDBY ;
+
+ /* Make sure the Antioch is not in suspend mode. */
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_RESERVE_LNA_BOOT_AREA, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ CyAsLLRequestResponse_SetWord(req_p, 0, (uint16_t)numzones) ;
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_MISC_RESERVELNABOOTAREA,
+ 0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, req_p,
+ reply_p, CyAsMiscFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsFuncCBNode*
+CyAsCreateFuncCBNodeData(CyAsFunctionCallback cb,
+ uint32_t client,
+ CyAsFunctCBType type,
+ void* data)
+{
+ uint32_t state = CyAsHalDisableInterrupts() ;
+ CyAsFuncCBNode* node = (CyAsFuncCBNode*)CyAsHalCBAlloc(sizeof(CyAsFuncCBNode)) ;
+ CyAsHalEnableInterrupts(state) ;
+ if(node != 0)
+ {
+ node->nodeType = CYAS_FUNC_CB ;
+ node->cb_p = cb ;
+ node->client_data = client ;
+ node->dataType = type ;
+ if(data != 0)
+ node->dataType |= CY_FUNCT_CB_DATA ;
+ else
+ node->dataType |= CY_FUNCT_CB_NODATA ;
+ node->data = data ;
+ node->next_p = 0 ;
+ }
+ return node ;
+}
+
+CyAsFuncCBNode*
+CyAsCreateFuncCBNode(CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ return CyAsCreateFuncCBNodeData(cb, client, CY_FUNCT_CB_NODATA, 0) ;
+}
+
+void
+CyAsDestroyFuncCBNode(CyAsFuncCBNode* node)
+{
+ uint32_t state ;
+
+ node->nodeType = CYAS_INVALID ;
+ state = CyAsHalDisableInterrupts() ;
+ CyAsHalCBFree(node) ;
+ CyAsHalEnableInterrupts(state) ;
+}
+
+CyAsUsbFuncCBNode*
+CyAsCreateUsbFuncCBNode(CyAsUsbFunctionCallback cb, uint32_t client)
+{
+ uint32_t state = CyAsHalDisableInterrupts() ;
+ CyAsUsbFuncCBNode * node = (CyAsUsbFuncCBNode *)CyAsHalCBAlloc(sizeof(CyAsUsbFuncCBNode)) ;
+ CyAsHalEnableInterrupts(state) ;
+ if(node != 0)
+ {
+ node->type = CYAS_USB_FUNC_CB ;
+ node->cb_p = cb ;
+ node->client_data = client ;
+ node->next_p = 0 ;
+ }
+ return node ;
+}
+
+void
+CyAsDestroyUsbFuncCBNode(CyAsUsbFuncCBNode* node)
+{
+ uint32_t state ;
+
+ node->type = CYAS_INVALID ;
+ state = CyAsHalDisableInterrupts() ;
+ CyAsHalCBFree(node) ;
+ CyAsHalEnableInterrupts(state) ;
+}
+
+CyAsUsbIoCBNode*
+CyAsCreateUsbIoCBNode(CyAsUsbIoCallback cb)
+{
+ uint32_t state = CyAsHalDisableInterrupts() ;
+ CyAsUsbIoCBNode * node = (CyAsUsbIoCBNode *)CyAsHalCBAlloc(sizeof(CyAsUsbIoCBNode)) ;
+ CyAsHalEnableInterrupts(state) ;
+ if(node != 0)
+ {
+ node->type = CYAS_USB_IO_CB ;
+ node->cb_p = cb ;
+ node->next_p = 0 ;
+ }
+ return node ;
+}
+
+void
+CyAsDestroyUsbIoCBNode(CyAsUsbIoCBNode* node)
+{
+ uint32_t state ;
+
+ node->type = CYAS_INVALID ;
+
+ state = CyAsHalDisableInterrupts() ;
+ CyAsHalCBFree(node) ;
+ CyAsHalEnableInterrupts(state) ;
+}
+
+CyAsStorageIoCBNode*
+CyAsCreateStorageIoCBNode(CyAsStorageCallback cb, CyAsMediaType media, uint32_t device_index,
+ uint32_t unit, uint32_t block_addr, CyAsOperType oper,
+ CyAsLLRequestResponse* req_p, CyAsLLRequestResponse* reply_p)
+{
+ uint32_t state = CyAsHalDisableInterrupts() ;
+ CyAsStorageIoCBNode * node = (CyAsStorageIoCBNode *)CyAsHalCBAlloc(sizeof(CyAsStorageIoCBNode)) ;
+ CyAsHalEnableInterrupts(state) ;
+ if(node != 0)
+ {
+ node->type = CYAS_STORAGE_IO_CB ;
+ node->cb_p = cb ;
+ node->media = media ;
+ node->device_index = device_index ;
+ node->unit = unit ;
+ node->block_addr = block_addr ;
+ node->oper = oper ;
+ node->req_p = req_p ;
+ node->reply_p = reply_p ;
+ node->next_p = 0 ;
+ }
+ return node ;
+}
+
+void
+CyAsDestroyStorageIoCBNode(CyAsStorageIoCBNode* node)
+{
+ uint32_t state ;
+ node->type = CYAS_INVALID ;
+ state = CyAsHalDisableInterrupts() ;
+ CyAsHalCBFree(node) ;
+ CyAsHalEnableInterrupts(state) ;
+}
+
+CyAsCBQueue *
+CyAsCreateCBQueue(CyAsCBNodeType type)
+{
+ uint32_t state = CyAsHalDisableInterrupts() ;
+ CyAsCBQueue * queue = (CyAsCBQueue *)CyAsHalCBAlloc(sizeof(CyAsCBQueue)) ;
+ CyAsHalEnableInterrupts(state) ;
+ if(queue)
+ {
+ queue->type = type ;
+ queue->head_p = 0 ;
+ queue->tail_p = 0 ;
+ queue->count = 0 ;
+ }
+
+ return queue ;
+}
+
+void
+CyAsDestroyCBQueue(CyAsCBQueue* queue)
+{
+ uint32_t state ;
+ queue->type = CYAS_INVALID ;
+ queue->head_p = 0 ;
+ queue->tail_p = 0 ;
+ queue->count = 0 ;
+ state = CyAsHalDisableInterrupts() ;
+ CyAsHalCBFree(queue) ;
+ CyAsHalEnableInterrupts(state) ;
+}
+
+/* Inserts a CyAsCBNode into the queue, the node type must match the queue type*/
+void
+CyAsInsertCBNode(CyAsCBQueue * queue_p, void* cbnode)
+{
+ uint32_t int_state ;
+
+ int_state = CyAsHalDisableInterrupts() ;
+
+ CyAsHalAssert(queue_p != 0) ;
+
+ switch (queue_p->type)
+ {
+ case CYAS_USB_FUNC_CB:
+ {
+ CyAsUsbFuncCBNode* node = (CyAsUsbFuncCBNode*)cbnode ;
+ CyAsUsbFuncCBNode* tail = (CyAsUsbFuncCBNode*)queue_p->tail_p ;
+
+ CyAsHalAssert(node->type == CYAS_USB_FUNC_CB) ;
+ CyAsHalAssert(tail == 0 || tail->type == CYAS_USB_FUNC_CB) ;
+ if(queue_p->head_p == 0)
+ queue_p->head_p = node ;
+ else
+ tail->next_p = node ;
+
+ queue_p->tail_p = node ;
+ }
+ break ;
+
+ case CYAS_USB_IO_CB:
+ {
+ CyAsUsbIoCBNode* node = (CyAsUsbIoCBNode*)cbnode ;
+ CyAsUsbIoCBNode* tail = (CyAsUsbIoCBNode*)queue_p->tail_p ;
+
+ CyAsHalAssert(node->type == CYAS_USB_IO_CB) ;
+ CyAsHalAssert(tail == 0 || tail->type == CYAS_USB_IO_CB) ;
+ if(queue_p->head_p == 0)
+ queue_p->head_p = node ;
+ else
+ tail->next_p = node ;
+
+ queue_p->tail_p = node ;
+ }
+ break ;
+
+ case CYAS_STORAGE_IO_CB:
+ {
+ CyAsStorageIoCBNode* node = (CyAsStorageIoCBNode*)cbnode ;
+ CyAsStorageIoCBNode* tail = (CyAsStorageIoCBNode*)queue_p->tail_p ;
+
+ CyAsHalAssert(node->type == CYAS_STORAGE_IO_CB) ;
+ CyAsHalAssert(tail == 0 || tail->type == CYAS_STORAGE_IO_CB) ;
+ if(queue_p->head_p == 0)
+ queue_p->head_p = node ;
+ else
+ tail->next_p = node ;
+
+ queue_p->tail_p = node ;
+ }
+ break ;
+
+ case CYAS_FUNC_CB:
+ {
+ CyAsFuncCBNode* node = (CyAsFuncCBNode*)cbnode ;
+ CyAsFuncCBNode* tail = (CyAsFuncCBNode*)queue_p->tail_p ;
+
+ CyAsHalAssert(node->nodeType == CYAS_FUNC_CB) ;
+ CyAsHalAssert(tail == 0 || tail->nodeType == CYAS_FUNC_CB) ;
+ if(queue_p->head_p == 0)
+ queue_p->head_p = node ;
+ else
+ tail->next_p = node ;
+
+ queue_p->tail_p = node ;
+ }
+ break ;
+
+ default:
+ CyAsHalAssert(CyFalse) ;
+ break ;
+ }
+
+ queue_p->count++ ;
+
+ CyAsHalEnableInterrupts(int_state) ;
+}
+
+/* Removes the tail node from the queue and frees it */
+void
+CyAsRemoveCBTailNode(CyAsCBQueue *queue_p)
+{
+ uint32_t int_state ;
+
+ int_state = CyAsHalDisableInterrupts () ;
+
+ if (queue_p->count > 0)
+ {
+ /*
+ * The worst case length of the queue should be under 10 elements, and the average
+ * case should be just 1 element. So, we just employ a linear search to find the node
+ * to be freed.
+ */
+ switch (queue_p->type)
+ {
+ case CYAS_FUNC_CB:
+ {
+ CyAsFuncCBNode* node = (CyAsFuncCBNode*)queue_p->head_p ;
+ CyAsFuncCBNode* tail = (CyAsFuncCBNode*)queue_p->tail_p ;
+ if (node != tail)
+ {
+ while (node->next_p != tail)
+ node = node->next_p ;
+ node->next_p = 0 ;
+ queue_p->tail_p = node ;
+ }
+ CyAsDestroyFuncCBNode (tail) ;
+ }
+ break ;
+
+ case CYAS_USB_FUNC_CB:
+ {
+ CyAsUsbFuncCBNode* node = (CyAsUsbFuncCBNode*)queue_p->head_p ;
+ CyAsUsbFuncCBNode* tail = (CyAsUsbFuncCBNode*)queue_p->tail_p ;
+ if (node != tail)
+ {
+ while (node->next_p != tail)
+ node = node->next_p ;
+ node->next_p = 0 ;
+ queue_p->tail_p = node ;
+ }
+
+ CyAsDestroyUsbFuncCBNode (tail) ;
+ }
+ break ;
+
+ case CYAS_USB_IO_CB:
+ {
+ CyAsUsbIoCBNode* node = (CyAsUsbIoCBNode*)queue_p->head_p ;
+ CyAsUsbIoCBNode* tail = (CyAsUsbIoCBNode*)queue_p->tail_p ;
+ if (node != tail)
+ {
+ while (node->next_p != tail)
+ node = node->next_p ;
+ node->next_p = 0 ;
+ queue_p->tail_p = node ;
+ }
+ CyAsDestroyUsbIoCBNode (tail) ;
+ }
+ break ;
+
+ case CYAS_STORAGE_IO_CB:
+ {
+ CyAsStorageIoCBNode* node = (CyAsStorageIoCBNode*)queue_p->head_p ;
+ CyAsStorageIoCBNode* tail = (CyAsStorageIoCBNode*)queue_p->tail_p ;
+ if (node != tail)
+ {
+ while (node->next_p != tail)
+ node = node->next_p ;
+ node->next_p = 0 ;
+ queue_p->tail_p = node ;
+ }
+ CyAsDestroyStorageIoCBNode (tail) ;
+ }
+ break ;
+
+ default:
+ CyAsHalAssert (CyFalse) ;
+ }
+
+ queue_p->count-- ;
+ if (queue_p->count == 0)
+ {
+ queue_p->head_p = 0 ;
+ queue_p->tail_p = 0 ;
+ }
+ }
+
+ CyAsHalEnableInterrupts (int_state) ;
+}
+
+/* Removes the first CyAsCBNode from the queue and frees it */
+void
+CyAsRemoveCBNode(CyAsCBQueue * queue_p)
+{
+ uint32_t int_state ;
+
+ int_state = CyAsHalDisableInterrupts() ;
+
+ CyAsHalAssert(queue_p->count >= 0) ;
+ if(queue_p->count > 0)
+ {
+ if(queue_p->type == CYAS_USB_FUNC_CB)
+ {
+ CyAsUsbFuncCBNode* node = (CyAsUsbFuncCBNode*)queue_p->head_p ;
+ queue_p->head_p = node->next_p ;
+ CyAsDestroyUsbFuncCBNode(node) ;
+ }
+ else if(queue_p->type == CYAS_USB_IO_CB)
+ {
+ CyAsUsbIoCBNode* node = (CyAsUsbIoCBNode*)queue_p->head_p ;
+ queue_p->head_p = node->next_p ;
+ CyAsDestroyUsbIoCBNode(node) ;
+ }
+ else if(queue_p->type == CYAS_STORAGE_IO_CB)
+ {
+ CyAsStorageIoCBNode* node = (CyAsStorageIoCBNode*)queue_p->head_p ;
+ queue_p->head_p = node->next_p ;
+ CyAsDestroyStorageIoCBNode(node) ;
+ }
+ else if(queue_p->type == CYAS_FUNC_CB)
+ {
+ CyAsFuncCBNode* node = (CyAsFuncCBNode*)queue_p->head_p ;
+ queue_p->head_p = node->next_p ;
+ CyAsDestroyFuncCBNode(node) ;
+ }
+ else
+ {
+ CyAsHalAssert(CyFalse) ;
+ }
+
+ queue_p->count-- ;
+ if(queue_p->count == 0)
+ {
+ queue_p->head_p = 0 ;
+ queue_p->tail_p = 0 ;
+ }
+ }
+
+ CyAsHalEnableInterrupts(int_state) ;
+}
+
+void MyPrintFuncCBNode(CyAsFuncCBNode* node)
+{
+ CyAsFunctCBType type = CyAsFunctCBTypeGetType(node->dataType) ;
+ CyAsHalPrintMessage("[cd:%2u dt:%2u cb:0x%08x d:0x%08x nt:%1i]",
+ node->client_data, type, (uint32_t)node->cb_p, (uint32_t)node->data, node->nodeType) ;
+}
+
+void MyPrintCBQueue(CyAsCBQueue* queue_p)
+{
+ uint32_t i = 0 ;
+
+ CyAsHalPrintMessage("| Count: %u Type: ", queue_p->count) ;
+
+ if(queue_p->type == CYAS_USB_FUNC_CB)
+ {
+ CyAsHalPrintMessage("USB_FUNC_CB\n") ;
+ }
+ else if(queue_p->type == CYAS_USB_IO_CB)
+ {
+ CyAsHalPrintMessage("USB_IO_CB\n") ;
+ }
+ else if(queue_p->type == CYAS_STORAGE_IO_CB)
+ {
+ CyAsHalPrintMessage("STORAGE_IO_CB\n") ;
+ }
+ else if(queue_p->type == CYAS_FUNC_CB)
+ {
+ CyAsFuncCBNode* node = (CyAsFuncCBNode*)queue_p->head_p ;
+ CyAsHalPrintMessage("FUNC_CB\n") ;
+ if(queue_p->count > 0)
+ {
+ CyAsHalPrintMessage("| Head->") ;
+
+ for(i = 0; i < queue_p->count; i++)
+ {
+ if(node)
+ {
+ CyAsHalPrintMessage("->") ;
+ MyPrintFuncCBNode(node) ;
+ node = node->next_p ;
+ }
+ else
+ CyAsHalPrintMessage("->[NULL]\n") ;
+ }
+
+ CyAsHalPrintMessage("\n| Tail->") ;
+ MyPrintFuncCBNode((CyAsFuncCBNode*)queue_p->tail_p) ;
+ CyAsHalPrintMessage("\n") ;
+ }
+ }
+ else
+ {
+ CyAsHalPrintMessage("INVALID\n") ;
+ }
+
+ CyAsHalPrintMessage("|----------\n") ;
+}
+
+
+/* Removes and frees all pending callbacks */
+void
+CyAsClearCBQueue(CyAsCBQueue * queue_p)
+{
+ uint32_t int_state = CyAsHalDisableInterrupts() ;
+
+ while(queue_p->count != 0)
+ CyAsRemoveCBNode(queue_p) ;
+
+ CyAsHalEnableInterrupts(int_state) ;
+}
+
+CyAsReturnStatus_t
+CyAsMiscSendRequest(CyAsDevice* dev_p,
+ CyAsFunctionCallback cb,
+ uint32_t client,
+ CyAsFunctCBType type,
+ void* data,
+ CyAsCBQueue* queue,
+ uint16_t req_type,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ CyAsResponseCallback rcb)
+{
+
+ CyAsFuncCBNode* cbnode = CyAsCreateFuncCBNodeData(cb, client, type, data) ;
+ CyAsReturnStatus_t ret ;
+
+ if(cbnode == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ else
+ CyAsInsertCBNode(queue, cbnode) ;
+
+ req_p->flags |= req_type ;
+
+ ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyFalse, rcb) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ CyAsRemoveCBTailNode(queue) ;
+ }
+
+ return ret ;
+}
+
+void
+CyAsMiscCancelExRequests(CyAsDevice *dev_p)
+{
+ int i ;
+ for(i = 0; i < CY_RQT_CONTEXT_COUNT; i++)
+ CyAsLLRemoveAllRequests(dev_p, dev_p->context[i]) ;
+}
+
+
+static void
+CyAsMiscFuncCallback(CyAsDevice *dev_p,
+ uint8_t context,
+ CyAsLLRequestResponse *rqt,
+ CyAsLLRequestResponse *resp,
+ CyAsReturnStatus_t stat)
+{
+ CyAsFuncCBNode* node = NULL ;
+ CyAsReturnStatus_t ret ;
+
+ CyBool exRequest = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX) == CY_AS_REQUEST_RESPONSE_EX ;
+ CyBool msRequest = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS) == CY_AS_REQUEST_RESPONSE_MS ;
+ uint8_t code ;
+ uint32_t type ;
+ uint8_t cntxt ;
+
+ CyAsHalAssert(exRequest || msRequest) ;
+ (void) exRequest;
+ (void) msRequest;
+ (void)context ;
+
+ cntxt = CyAsLLRequestResponse_GetContext(rqt) ;
+ code = CyAsLLRequestResponse_GetCode(rqt) ;
+
+ switch(cntxt)
+ {
+ case CY_RQT_GENERAL_RQT_CONTEXT:
+ CyAsHalAssert(dev_p->func_cbs_misc->count != 0) ;
+ CyAsHalAssert(dev_p->func_cbs_misc->type == CYAS_FUNC_CB) ;
+ node = (CyAsFuncCBNode*)dev_p->func_cbs_misc->head_p ;
+ type = CyAsFunctCBTypeGetType(node->dataType) ;
+
+ switch(code)
+ {
+ case CY_RQT_GET_FIRMWARE_VERSION:
+ CyAsHalAssert(node->data != 0) ;
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_GETFIRMWAREVERSION) ;
+ ret = MyHandleResponseGetFirmwareVersion(dev_p, rqt, resp, (CyAsGetFirmwareVersionData*)node->data) ;
+ break ;
+ case CY_RQT_READ_MCU_REGISTER:
+ CyAsHalAssert(node->data != 0) ;
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_READMCUREGISTER) ;
+ ret = MyHandleResponseReadMCURegister(dev_p, rqt, resp, (uint8_t*)node->data) ;
+ break ;
+ case CY_RQT_GET_GPIO_STATE:
+ CyAsHalAssert(node->data != 0) ;
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_GETGPIOVALUE) ;
+ ret = MyHandleResponseGetGpioValue(dev_p, rqt, resp, (uint8_t*)node->data) ;
+ break ;
+ case CY_RQT_SET_SD_CLOCK_FREQ:
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_SETSDFREQ) ;
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ break ;
+ case CY_RQT_CONTROL_ANTIOCH_HEARTBEAT:
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_HEARTBEATCONTROL) ;
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ break ;
+ case CY_RQT_WRITE_MCU_REGISTER:
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_WRITEMCUREGISTER) ;
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ break ;
+ case CY_RQT_STORAGE_MEDIA_CHANGED:
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_STORAGECHANGED) ;
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ break ;
+ case CY_RQT_SET_GPIO_STATE:
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_SETGPIOVALUE) ;
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ break ;
+ case CY_RQT_SET_TRACE_LEVEL:
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_SETTRACELEVEL) ;
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ if (ret == CY_AS_ERROR_INVALID_RESPONSE)
+ ret = CY_AS_ERROR_NOT_SUPPORTED ;
+ break ;
+ case CY_RQT_PREPARE_FOR_STANDBY:
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_ENTERSTANDBY) ;
+ ret = MyHandleResponseEnterStandby(dev_p, rqt, resp, (CyBool)node->data) ;
+ break ;
+ case CY_RQT_ENTER_SUSPEND_MODE:
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_ENTERSUSPEND) ;
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ if (ret == CY_AS_ERROR_SUCCESS)
+ {
+ CyAsDeviceSetSuspendMode(dev_p) ;
+ }
+ break ;
+ case CY_RQT_RESERVE_LNA_BOOT_AREA:
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_RESERVELNABOOTAREA) ;
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ break ;
+ case CY_RQT_SDPOLARITY:
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_SETSDPOLARITY) ;
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ break ;
+
+
+ default:
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ CyAsHalAssert(CyFalse) ;
+ break ;
+ }
+ break ;
+
+ case CY_RQT_RESOURCE_RQT_CONTEXT:
+ CyAsHalAssert(dev_p->func_cbs_res->count != 0) ;
+ CyAsHalAssert(dev_p->func_cbs_res->type == CYAS_FUNC_CB) ;
+ node = (CyAsFuncCBNode*)dev_p->func_cbs_res->head_p ;
+ type = CyAsFunctCBTypeGetType(node->dataType) ;
+
+ switch(code)
+ {
+ case CY_RQT_ACQUIRE_RESOURCE:
+ /* The node->data field is actually an enum value which could be
+ 0, thus no assert is done */
+ CyAsHalAssert(type == CY_FUNCT_CB_MISC_ACQUIRERESOURCE) ;
+ ret = MyHandleResponseAcquireResource(dev_p, rqt, resp, (CyAsResourceType*)node->data) ;
+ break ;
+ default:
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ CyAsHalAssert(CyFalse) ;
+ break ;
+ }
+ break ;
+
+ default:
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ CyAsHalAssert(CyFalse) ;
+ break ;
+ }
+
+ /*
+ * If the low level layer returns a direct error, use the corresponding error code.
+ * If not, use the error code based on the response from firmware.
+ */
+ if (stat == CY_AS_ERROR_SUCCESS)
+ stat = ret ;
+
+ /* Call the user Callback */
+ node->cb_p((CyAsDeviceHandle)dev_p, stat, node->client_data, (CyAsFunctCBType)node->dataType, node->data) ;
+ if(cntxt == CY_RQT_GENERAL_RQT_CONTEXT)
+ CyAsRemoveCBNode(dev_p->func_cbs_misc) ;
+ else
+ CyAsRemoveCBNode(dev_p->func_cbs_res) ;
+
+}
+
+
+/* This includes the implementation of the deprecated functions for backward
+ * compatibility
+ */
+#include "cyasmisc_dep_impl.h"
+
+/*[]*/
+