]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/staging/westbridge/astoria/api/src/cyasmisc.c
Merge branch 'master' into tk71
[mv-sheeva.git] / drivers / staging / westbridge / astoria / api / src / cyasmisc.c
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasmisc.c b/drivers/staging/westbridge/astoria/api/src/cyasmisc.c
new file mode 100644 (file)
index 0000000..10a52a1
--- /dev/null
@@ -0,0 +1,3474 @@
+/* Cypress West Bridge API source file (cyasmisc.c)
+## ===========================
+## Copyright (C) 2010  Cypress Semiconductor
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License
+## as published by the Free Software Foundation; either version 2
+## of the License, or (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor
+## Boston, MA  02110-1301, USA.
+## ===========================
+*/
+
+#include "../../include/linux/westbridge/cyashal.h"
+#include "../../include/linux/westbridge/cyasmisc.h"
+#include "../../include/linux/westbridge/cyasdma.h"
+#include "../../include/linux/westbridge/cyasintr.h"
+#include "../../include/linux/westbridge/cyaserr.h"
+#include "../../include/linux/westbridge/cyasregs.h"
+#include "../../include/linux/westbridge/cyaslowlevel.h"
+#include "../../include/linux/westbridge/cyasprotocol.h"
+
+/*
+* The device list, the only global in the API
+*/
+static cy_as_device *g_device_list;
+
+/*
+ * The current debug level
+ */
+static uint8_t debug_level;
+
+/*
+ * This function sets the debug level for the API
+ *
+ */
+void
+cy_as_misc_set_log_level(uint8_t level)
+{
+       debug_level = level;
+}
+
+#ifdef CY_AS_LOG_SUPPORT
+
+/*
+ * This function is a low level logger for the API.
+ */
+void
+cy_as_log_debug_message(int level, const char *str)
+{
+       if (level <= debug_level)
+               cy_as_hal_print_message("log %d: %s\n", level, str);
+}
+
+#endif
+
+#define cy_as_check_device_ready(dev_p)                        \
+{\
+       if (!(dev_p) || ((dev_p)->sig !=                        \
+               CY_AS_DEVICE_HANDLE_SIGNATURE))                 \
+               return CY_AS_ERROR_INVALID_HANDLE;              \
+\
+       if (!cy_as_device_is_configured(dev_p))         \
+               return CY_AS_ERROR_NOT_CONFIGURED;              \
+\
+       if (!cy_as_device_is_firmware_loaded(dev_p))\
+               return CY_AS_ERROR_NO_FIRMWARE;         \
+}
+
+/* Find an West Bridge device based on a TAG */
+cy_as_device *
+cy_as_device_find_from_tag(cy_as_hal_device_tag tag)
+{
+       cy_as_device *dev_p;
+
+       for (dev_p = g_device_list; 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
+cy_as_bus_from_media_type(cy_as_media_type type,
+                                               cy_as_bus_number_t *bus)
+{
+       if (type == cy_as_media_nand)
+               *bus = 0;
+       else
+               *bus = 1;
+}
+
+static cy_as_return_status_t
+my_handle_response_no_data(cy_as_device *dev_p,
+                       cy_as_ll_request_response *req_p,
+                       cy_as_ll_request_response *reply_p)
+{
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+
+       if (cy_as_ll_request_response__get_code(reply_p) !=
+               CY_RESP_SUCCESS_FAILURE)
+               ret = CY_AS_ERROR_INVALID_RESPONSE;
+       else
+               ret = cy_as_ll_request_response__get_word(reply_p, 0);
+
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+/*
+* Create a new West Bridge device
+*/
+cy_as_return_status_t
+cy_as_misc_create_device(cy_as_device_handle *handle_p,
+       cy_as_hal_device_tag tag)
+{
+       cy_as_device *dev_p;
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+
+       cy_as_log_debug_message(6, "cy_as_misc_create_device called");
+
+       dev_p = (cy_as_device *)cy_as_hal_alloc(sizeof(cy_as_device));
+       if (dev_p == 0)
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       cy_as_hal_mem_set(dev_p, 0, sizeof(cy_as_device));
+
+       /*
+        * dynamically allocating this buffer to ensure that it is
+        * word aligned.
+        */
+       dev_p->usb_ep_data = (uint8_t *)cy_as_hal_alloc(64 * sizeof(uint8_t));
+       if (dev_p->usb_ep_data == 0) {
+               cy_as_hal_free(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 = cy_as_create_c_b_queue(CYAS_FUNC_CB);
+       if (dev_p->func_cbs_misc == 0)
+               goto destroy;
+
+       dev_p->func_cbs_res = cy_as_create_c_b_queue(CYAS_FUNC_CB);
+       if (dev_p->func_cbs_res == 0)
+               goto destroy;
+
+       dev_p->func_cbs_stor = cy_as_create_c_b_queue(CYAS_FUNC_CB);
+       if (dev_p->func_cbs_stor == 0)
+               goto destroy;
+
+       dev_p->func_cbs_usb = cy_as_create_c_b_queue(CYAS_FUNC_CB);
+       if (dev_p->func_cbs_usb == 0)
+               goto destroy;
+
+       dev_p->func_cbs_mtp = cy_as_create_c_b_queue(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 cy_as_misc_configure_device is called.
+        */
+       ret = cy_as_dma_start(dev_p);
+       if (ret != CY_AS_ERROR_SUCCESS)
+               goto destroy;
+
+       cy_as_device_set_dma_stopped(dev_p);
+
+       /*
+        * allocate memory for the low level module here. this module is also
+        * activated only when cy_as_misc_configure_device is called.
+        */
+       ret = cy_as_ll_start(dev_p);
+       if (ret != CY_AS_ERROR_SUCCESS)
+               goto destroy;
+
+       cy_as_device_set_low_level_stopped(dev_p);
+
+       dev_p->next_p = g_device_list;
+       g_device_list = dev_p;
+
+       *handle_p = dev_p;
+       cy_as_hal_init_dev_registers(tag, cy_false);
+       return CY_AS_ERROR_SUCCESS;
+
+destroy:
+       /* Free any queues that were successfully allocated. */
+       if (dev_p->func_cbs_misc)
+               cy_as_destroy_c_b_queue(dev_p->func_cbs_misc);
+
+       if (dev_p->func_cbs_res)
+               cy_as_destroy_c_b_queue(dev_p->func_cbs_res);
+
+       if (dev_p->func_cbs_stor)
+               cy_as_destroy_c_b_queue(dev_p->func_cbs_stor);
+
+       if (dev_p->func_cbs_usb)
+               cy_as_destroy_c_b_queue(dev_p->func_cbs_usb);
+
+       if (dev_p->func_cbs_mtp)
+               cy_as_destroy_c_b_queue(dev_p->func_cbs_mtp);
+
+       cy_as_hal_free(dev_p->usb_ep_data);
+       cy_as_hal_free(dev_p);
+
+       if (ret != CY_AS_ERROR_SUCCESS)
+               return ret;
+       else
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+}
+
+/*
+* Destroy an existing West Bridge device
+*/
+cy_as_return_status_t
+cy_as_misc_destroy_device(cy_as_device_handle handle)
+{
+       cy_as_return_status_t ret;
+       cy_as_device *dev_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_destroy_device called");
+
+       dev_p = (cy_as_device *)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 (cy_as_device_is_intr_running(dev_p))
+               ret = cy_as_intr_stop(dev_p);
+
+       ret = cy_as_ll_stop(dev_p);
+       if (ret != CY_AS_ERROR_SUCCESS) {
+               cy_as_intr_start(dev_p, dev_p->use_int_drq);
+               return ret;
+       }
+
+       ret = cy_as_dma_stop(dev_p);
+       if (ret != CY_AS_ERROR_SUCCESS) {
+               cy_as_intr_start(dev_p, dev_p->use_int_drq);
+               return ret;
+       }
+
+       /* Reset the West Bridge device. */
+       cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_RST_CTRL_REG,
+               CY_AS_MEM_RST_CTRL_REG_HARD);
+
+       /*
+       * remove the device from the device list
+       */
+       if (g_device_list == dev_p) {
+               g_device_list = dev_p->next_p;
+       } else {
+               cy_as_device *tmp_p = g_device_list;
+               while (tmp_p && tmp_p->next_p != dev_p)
+                       tmp_p = tmp_p->next_p;
+
+               cy_as_hal_assert(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;
+
+       cy_as_destroy_c_b_queue(dev_p->func_cbs_misc);
+       cy_as_destroy_c_b_queue(dev_p->func_cbs_res);
+       cy_as_destroy_c_b_queue(dev_p->func_cbs_stor);
+       cy_as_destroy_c_b_queue(dev_p->func_cbs_usb);
+       cy_as_destroy_c_b_queue(dev_p->func_cbs_mtp);
+
+       /*
+       * free the memory associated with the device
+       */
+       cy_as_hal_free(dev_p->usb_ep_data);
+       cy_as_hal_free(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
+cy_as_setup_endian_mode(cy_as_device *dev_p)
+{
+       /*
+       * In general, we always set west bridge intothe 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.
+       */
+       cy_as_hal_write_register(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
+*/
+cy_as_return_status_t
+cy_as_misc_in_standby(cy_as_device_handle handle, cy_bool *standby)
+{
+       cy_as_device *dev_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_in_standby called");
+
+       dev_p = (cy_as_device *)handle;
+       if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+               return CY_AS_ERROR_INVALID_HANDLE;
+
+       if (cy_as_device_is_pin_standby(dev_p) ||
+               cy_as_device_is_register_standby(dev_p)) {
+               *standby = cy_true;
+       } else
+               *standby = cy_false;
+
+       return CY_AS_ERROR_SUCCESS;
+}
+
+static void
+cy_as_misc_func_callback(cy_as_device *dev_p,
+                                               uint8_t context,
+                                               cy_as_ll_request_response *rqt,
+                                               cy_as_ll_request_response *resp,
+                                               cy_as_return_status_t ret);
+
+
+static void
+my_misc_callback(cy_as_device *dev_p, uint8_t context,
+               cy_as_ll_request_response *req_p,
+               cy_as_ll_request_response *resp_p,
+               cy_as_return_status_t ret)
+{
+       (void)resp_p;
+       (void)context;
+       (void)ret;
+
+       switch (cy_as_ll_request_response__get_code(req_p)) {
+       case CY_RQT_INITIALIZATION_COMPLETE:
+               {
+                       uint16_t v;
+
+                       cy_as_ll_send_status_response(dev_p,
+                               CY_RQT_GENERAL_RQT_CONTEXT,
+                               CY_AS_ERROR_SUCCESS, 0);
+                       cy_as_device_set_firmware_loaded(dev_p);
+
+                       if (cy_as_device_is_waking(dev_p)) {
+                               /*
+                                * this is a callback from a
+                                * cy_as_misc_leave_standby()
+                                * 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(
+                                        (cy_as_device_handle)dev_p,
+                                        cy_as_event_misc_awake, 0);
+                               cy_as_device_clear_waking(dev_p);
+                       } else {
+                               v = cy_as_ll_request_response__get_word
+                                       (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 = cy_as_ll_request_response__get_word
+                                       (req_p, 4);
+
+                               dev_p->is_mtp_firmware  =
+                                       (cy_bool)((v >> 8) & 0xFF);
+
+                               if (dev_p->misc_event_cb)
+                                       dev_p->misc_event_cb(
+                                        (cy_as_device_handle)dev_p,
+                                        cy_as_event_misc_initialized, 0);
+                       }
+
+                       v = cy_as_hal_read_register(dev_p->tag,
+                               CY_AS_MEM_P0_VM_SET);
+
+                               if (v & CY_AS_MEM_P0_VM_SET_CFGMODE)
+                                       cy_as_hal_print_message(
+                                       "initialization message "
+                                       "recieved, but config bit "
+                                       "still set\n");
+
+                               v = cy_as_hal_read_register(dev_p->tag,
+                                       CY_AS_MEM_RST_CTRL_REG);
+                               if ((v & CY_AS_MEM_RST_RSTCMPT) == 0)
+                                       cy_as_hal_print_message(
+                                       "initialization message "
+                                       "recieved, but reset complete "
+                                       "bit still not set\n");
+                       }
+                       break;
+
+       case CY_RQT_OUT_OF_SUSPEND:
+               cy_as_ll_send_status_response(dev_p, CY_RQT_GENERAL_RQT_CONTEXT,
+                       CY_AS_ERROR_SUCCESS, 0);
+                       cy_as_device_clear_suspend_mode(dev_p);
+
+               /*
+                * if the wakeup was caused by an async cy_as_misc_leave_suspend
+                * call, we have to call the corresponding callback.
+                */
+               if (dev_p->func_cbs_misc->count > 0) {
+                       cy_as_func_c_b_node *node = (cy_as_func_c_b_node *)
+                                       dev_p->func_cbs_misc->head_p;
+                       cy_as_hal_assert(node);
+
+                       if (cy_as_funct_c_b_type_get_type(node->data_type) ==
+                               CY_FUNCT_CB_MISC_LEAVESUSPEND) {
+                               cy_as_hal_assert(node->cb_p != 0);
+
+                               node->cb_p((cy_as_device_handle)dev_p,
+                                       CY_AS_ERROR_SUCCESS, node->client_data,
+                                       CY_FUNCT_CB_MISC_LEAVESUSPEND, 0);
+                               cy_as_remove_c_b_node(dev_p->func_cbs_misc);
+                       }
+               }
+
+               if (dev_p->misc_event_cb)
+                       dev_p->misc_event_cb((cy_as_device_handle)dev_p,
+                               cy_as_event_misc_wakeup, 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((cy_as_device_handle)dev_p,
+                                       cy_as_event_misc_heart_beat, 0);
+               } else {
+                       cy_as_hal_print_message(
+                               "**** 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((cy_as_device_handle)dev_p,
+                                       cy_as_event_misc_device_mismatch, 0);
+               }
+               break;
+
+       case CY_RQT_BOOTLOAD_NO_FIRMWARE:
+               {
+                       /* TODO Handle case when firmware is
+                        * not found during bootloading. */
+                       cy_as_hal_print_message("no firmware image found "
+                       "during bootload. device not started\n");
+               }
+               break;
+
+       default:
+               cy_as_hal_assert(0);
+       }
+}
+
+static cy_bool
+is_valid_silicon_id(uint16_t v)
+{
+       cy_bool idok = cy_false;
+
+       /*
+       * 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 = cy_true;
+
+       return idok;
+}
+
+/*
+* Configure the West Bridge device hardware
+*/
+cy_as_return_status_t
+cy_as_misc_configure_device(cy_as_device_handle handle,
+       cy_as_device_config *config_p)
+{
+       cy_as_return_status_t ret;
+       cy_bool standby;
+       cy_as_device *dev_p;
+       uint16_t v;
+       uint16_t fw_present;
+       cy_as_log_debug_message(6, "cy_as_misc_configure_device called");
+
+       dev_p = (cy_as_device *)handle;
+       if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+               return CY_AS_ERROR_INVALID_HANDLE;
+
+       /* Setup big endian vs little endian */
+       cy_as_setup_endian_mode(dev_p);
+
+       /* Now, confirm that we can talk to the West Bridge device */
+       dev_p->silicon_id = cy_as_hal_read_register(dev_p->tag,
+               CY_AS_MEM_CM_WB_CFG_ID);
+       fw_present = cy_as_hal_read_register(dev_p->tag,
+               CY_AS_MEM_RST_CTRL_REG);
+       if (!(fw_present & CY_AS_MEM_RST_RSTCMPT)) {
+               if (!is_valid_silicon_id(dev_p->silicon_id))
+                       return CY_AS_ERROR_NO_ANTIOCH;
+       }
+       /* Check for standby mode */
+       ret = cy_as_misc_in_standby(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 (cy_as_device_is_astoria_dev(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 == cy_as_device_dack_ack)
+               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;
+       cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_VM_SET, v);
+
+       if (config_p->crystal)
+               cy_as_device_set_crystal(dev_p);
+       else
+               cy_as_device_set_external_clock(dev_p);
+
+       /* Register a callback to handle MISC requests from the firmware */
+       cy_as_ll_register_request_callback(dev_p,
+               CY_RQT_GENERAL_RQT_CONTEXT, my_misc_callback);
+
+       /* Now mark the DMA and low level modules as active. */
+       cy_as_device_set_dma_running(dev_p);
+       cy_as_device_set_low_level_running(dev_p);
+
+       /* Now, initialize the interrupt module */
+       dev_p->use_int_drq = config_p->dmaintr;
+       ret = cy_as_intr_start(dev_p, config_p->dmaintr);
+       if (ret != CY_AS_ERROR_SUCCESS)
+               return ret;
+
+       /* Mark the interface as initialized */
+       cy_as_device_set_configured(dev_p);
+
+       return CY_AS_ERROR_SUCCESS;
+}
+
+static void
+my_dma_callback(cy_as_device *dev_p,
+                         cy_as_end_point_number_t ep,
+                         void *mem_p,
+                         uint32_t                        size,
+                         cy_as_return_status_t ret
+                        )
+{
+       cy_as_dma_end_point *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) {
+               cy_as_func_c_b_node *node =
+                       (cy_as_func_c_b_node *)dev_p->func_cbs_misc->head_p;
+
+               cy_as_hal_assert(node);
+
+               if (ret == CY_AS_ERROR_SUCCESS) {
+                       /*
+                        * disable endpoint 2.  the storage module
+                        * will enable this EP if necessary.
+                        */
+                       cy_as_dma_enable_end_point(dev_p,
+                               CY_AS_FIRMWARE_ENDPOINT,
+                               cy_false, cy_as_direction_in);
+
+                       /*
+                        * clear the reset register.  this releases the
+                        * antioch micro-controller from reset and begins
+                        * running the code at address zero.
+                        */
+                       cy_as_hal_write_register(dev_p->tag,
+                               CY_AS_MEM_RST_CTRL_REG, 0x00);
+               }
+
+               /* Call the user Callback */
+               node->cb_p((cy_as_device_handle)dev_p, ret, node->client_data,
+                       node->data_type, node->data);
+               cy_as_remove_c_b_node(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 = cy_as_hal_disable_interrupts();
+               cy_as_hal_c_b_free(mem_p);
+               cy_as_hal_enable_interrupts(state);
+       }
+}
+
+cy_as_return_status_t
+cy_as_misc_download_firmware(cy_as_device_handle handle,
+                                                  const void *mem_p,
+                                                  uint16_t size,
+                                                  cy_as_function_callback cb,
+                                                  uint32_t client)
+{
+       uint8_t *header;
+       cy_as_return_status_t ret;
+       cy_bool standby;
+       cy_as_device *dev_p;
+       cy_as_dma_callback dmacb = 0;
+       uint32_t state;
+
+       cy_as_log_debug_message(6, "cy_as_misc_download_firmware called");
+
+       /* Make sure we have a valid device */
+       dev_p = (cy_as_device *)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 (!cy_as_device_is_configured(dev_p))
+               return CY_AS_ERROR_NOT_CONFIGURED;
+
+       /*
+       * make sure west bridge is not in standby
+       */
+       ret = cy_as_misc_in_standby(dev_p, &standby);
+       if (ret != CY_AS_ERROR_SUCCESS)
+               return ret;
+
+       if (standby)
+               return CY_AS_ERROR_IN_STANDBY;
+
+       if (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       /*
+       * make sure we are in configuration mode
+       */
+       if ((cy_as_hal_read_register(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 = cy_as_hal_disable_interrupts();
+       header = (uint8_t *)cy_as_hal_c_b_alloc(4);
+       cy_as_hal_enable_interrupts(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 = cy_as_dma_enable_end_point(dev_p, CY_AS_FIRMWARE_ENDPOINT,
+               cy_true, cy_as_direction_in);
+       if (ret != CY_AS_ERROR_SUCCESS)
+               return ret;
+
+       /*
+       * setup DMA for 64 byte packets. this is the requirement for downloading
+       * firmware to west bridge.
+       */
+       cy_as_dma_set_max_dma_size(dev_p, CY_AS_FIRMWARE_ENDPOINT, 64);
+
+       if (cb)
+               dmacb = my_dma_callback;
+
+       ret = cy_as_dma_queue_request(dev_p, CY_AS_FIRMWARE_ENDPOINT, header,
+               4, cy_false, cy_false, dmacb);
+       if (ret != CY_AS_ERROR_SUCCESS)
+               return ret;
+
+       /*
+       * write the firmware image to the west bridge device
+       */
+       ret = cy_as_dma_queue_request(dev_p, CY_AS_FIRMWARE_ENDPOINT,
+               (void *)mem_p, size, cy_false, cy_false, dmacb);
+       if (ret != CY_AS_ERROR_SUCCESS)
+               return ret;
+
+       if (cb) {
+               cy_as_func_c_b_node *cbnode = cy_as_create_func_c_b_node_data(
+                       cb, client, CY_FUNCT_CB_MISC_DOWNLOADFIRMWARE, 0);
+
+               if (cbnode == 0)
+                       return CY_AS_ERROR_OUT_OF_MEMORY;
+               else
+                       cy_as_insert_c_b_node(dev_p->func_cbs_misc, cbnode);
+
+               ret = cy_as_dma_kick_start(dev_p, CY_AS_FIRMWARE_ENDPOINT);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       return ret;
+       } else {
+               ret = cy_as_dma_drain_queue(dev_p,
+                       CY_AS_FIRMWARE_ENDPOINT, cy_true);
+
+               /* Free the header memory that was allocated earlier. */
+               cy_as_hal_c_b_free(header);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       return ret;
+
+               /*
+               * disable EP 2. the storage module will
+               * enable this EP if necessary.
+               */
+               cy_as_dma_enable_end_point(dev_p, CY_AS_FIRMWARE_ENDPOINT,
+                       cy_false, cy_as_direction_in);
+
+               /*
+               * clear the reset register.  this releases the west bridge
+               * micro-controller from reset and begins running the code at
+               * address zero.
+               */
+               cy_as_hal_write_register(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 cy_as_return_status_t
+my_handle_response_get_firmware_version(cy_as_device *dev_p,
+                               cy_as_ll_request_response *req_p,
+                               cy_as_ll_request_response *reply_p,
+                               cy_as_get_firmware_version_data *data_p)
+{
+
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       uint16_t val;
+
+       if (cy_as_ll_request_response__get_code(reply_p)
+               != CY_RESP_FIRMWARE_VERSION) {
+               ret = CY_AS_ERROR_INVALID_RESPONSE;
+               goto destroy;
+       }
+
+       data_p->major = cy_as_ll_request_response__get_word(reply_p, 0);
+       data_p->minor = cy_as_ll_request_response__get_word(reply_p, 1);
+       data_p->build = cy_as_ll_request_response__get_word(reply_p, 2);
+       val     = cy_as_ll_request_response__get_word(reply_p, 3);
+       data_p->media_type   = (uint8_t)(((val >> 8) & 0xFF) | (val & 0xFF));
+       val     = cy_as_ll_request_response__get_word(reply_p, 4);
+       data_p->is_debug_mode = (cy_bool)(val & 0xFF);
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+cy_as_return_status_t
+cy_as_misc_get_firmware_version(cy_as_device_handle handle,
+                               cy_as_get_firmware_version_data *data,
+                               cy_as_function_callback cb,
+                               uint32_t client)
+{
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_bool standby;
+       cy_as_ll_request_response *req_p, *reply_p;
+
+       cy_as_device *dev_p;
+
+       (void)client;
+
+       cy_as_log_debug_message(6, "cy_as_misc_get_firmware_version called");
+
+       /* Make sure we have a valid device */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       /*
+       * make sure antioch is not in standby
+       */
+       ret = cy_as_misc_in_standby(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 (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       /* Create the request to send to the West Bridge device */
+       req_p = cy_as_ll_create_request(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 = cy_as_ll_create_response(dev_p, 5);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               /* Request and response are freed in
+                * MyHandleResponseGetFirmwareVersion. */
+               ret = my_handle_response_get_firmware_version(dev_p,
+                       req_p, reply_p, data);
+               return ret;
+       } else {
+
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_GETFIRMWAREVERSION, data,
+                       dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
+                       req_p, reply_p, cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+               /* The request and response are freed
+                * as part of the MiscFuncCallback */
+               return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+static cy_as_return_status_t
+my_handle_response_read_m_c_u_register(cy_as_device *dev_p,
+                               cy_as_ll_request_response *req_p,
+                               cy_as_ll_request_response *reply_p,
+                               uint8_t *data_p)
+{
+
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+
+       if (cy_as_ll_request_response__get_code(reply_p)
+               != CY_RESP_MCU_REGISTER_DATA) {
+               ret = CY_AS_ERROR_INVALID_RESPONSE;
+               goto destroy;
+       }
+
+       *data_p = (uint8_t)
+               (cy_as_ll_request_response__get_word(reply_p, 0));
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+static cy_as_return_status_t
+my_handle_response_get_gpio_value(cy_as_device *dev_p,
+               cy_as_ll_request_response *req_p,
+               cy_as_ll_request_response *reply_p,
+               uint8_t *data_p)
+{
+
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+
+       if (cy_as_ll_request_response__get_code(reply_p)
+               != CY_RESP_GPIO_STATE) {
+               ret = CY_AS_ERROR_INVALID_RESPONSE;
+       } else
+               *data_p = (uint8_t)
+                       (cy_as_ll_request_response__get_word(reply_p, 0));
+
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+
+cy_as_return_status_t cy_as_misc_set_sd_power_polarity(
+       cy_as_device_handle handle,
+       cy_as_misc_signal_polarity polarity,
+       cy_as_function_callback cb,
+       uint32_t client)
+{
+       cy_as_ll_request_response *req_p, *reply_p;
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_as_device *dev_p = (cy_as_device *)handle;
+
+       if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+               return CY_AS_ERROR_INVALID_HANDLE;
+
+       if (!cy_as_device_is_configured(dev_p))
+               return CY_AS_ERROR_NOT_CONFIGURED;
+
+       if (!cy_as_device_is_firmware_loaded(dev_p))
+               return CY_AS_ERROR_NO_FIRMWARE;
+
+       if (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDPOLARITY,
+               CY_RQT_GENERAL_RQT_CONTEXT, 1);
+       if (req_p == 0)
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+
+       cy_as_ll_request_response__set_word(req_p, 0,
+               (uint16_t)polarity);
+
+       /*
+        * Reserve space for the reply, the reply data will
+        * not exceed one word
+        */
+       reply_p = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               return (my_handle_response_no_data(dev_p, req_p, reply_p));
+       } else {
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_SETSDPOLARITY, 0, dev_p->func_cbs_misc,
+                       CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+                       cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               /* The request and response are freed
+                * as part of the FuncCallback */
+               return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+       return ret;
+}
+
+
+cy_as_return_status_t
+cy_as_misc_read_m_c_u_register(cy_as_device_handle handle,
+                                                 uint16_t address,
+                                                 uint8_t *value,
+                                                 cy_as_function_callback cb,
+                                                 uint32_t client)
+{
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_as_ll_request_response *req_p, *reply_p;
+
+       cy_as_device *dev_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_read_m_c_u_register called");
+
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       /* Check whether the firmware supports this command. */
+       if (cy_as_device_is_nand_storage_supported(dev_p))
+               return CY_AS_ERROR_NOT_SUPPORTED;
+
+       /* Make sure the Antioch is not in suspend mode. */
+       if (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       /* Create the request to send to the West Bridge device */
+       req_p = cy_as_ll_create_request(dev_p, CY_RQT_READ_MCU_REGISTER,
+               CY_RQT_GENERAL_RQT_CONTEXT, 1);
+       if (req_p == 0)
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+
+       cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)address);
+
+       /* Reserve space for the reply, the reply
+        * data will not exceed one word */
+       reply_p = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_MCU_REGISTER_DATA) {
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       goto destroy;
+               }
+
+               *value = (uint8_t)(cy_as_ll_request_response__get_word
+                       (reply_p, 0));
+       } else {
+
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_READMCUREGISTER, value,
+                       dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
+                       req_p, reply_p, cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+               /* The request and response are freed
+                * as part of the MiscFuncCallback */
+               return ret;
+       }
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+
+cy_as_return_status_t
+cy_as_misc_write_m_c_u_register(cy_as_device_handle handle,
+                                                  uint16_t address,
+                                                  uint8_t mask,
+                                                  uint8_t value,
+                                                  cy_as_function_callback cb,
+                                                  uint32_t client)
+{
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_as_ll_request_response *req_p, *reply_p;
+       cy_as_device *dev_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_write_m_c_u_register called");
+
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       /* Check whether the firmware supports this command. */
+       if (cy_as_device_is_nand_storage_supported(dev_p))
+               return CY_AS_ERROR_NOT_SUPPORTED;
+
+       /* Make sure the Antioch is not in suspend mode. */
+       if (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       /* Create the request to send to the West Bridge device */
+       req_p = cy_as_ll_create_request(dev_p, CY_RQT_WRITE_MCU_REGISTER,
+               CY_RQT_GENERAL_RQT_CONTEXT, 2);
+       if (req_p == 0)
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+
+       cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)address);
+       cy_as_ll_request_response__set_word(req_p, 1,
+               (uint16_t)((mask << 8) | value));
+
+       /*
+        * Reserve space for the reply, the reply data
+        * will not exceed one word
+        */
+       reply_p = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_SUCCESS_FAILURE) {
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       goto destroy;
+               }
+
+               ret = cy_as_ll_request_response__get_word(reply_p, 0);
+       } else {
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_WRITEMCUREGISTER, 0,
+                       dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
+                       req_p, reply_p, cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               /*
+                * The request and response are freed as part of the
+                * MiscFuncCallback
+                */
+               return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+cy_as_return_status_t
+my_handle_response_reset(cy_as_device *dev_p,
+                                         cy_as_ll_request_response *req_p,
+                                         cy_as_ll_request_response *reply_p,
+                                         cy_as_reset_type 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 (cy_as_device_is_in_suspend_mode(dev_p)) {
+               v = cy_as_hal_read_register(dev_p->tag,
+                       CY_AS_MEM_CM_WB_CFG_ID);
+               cy_as_hal_sleep(1);
+       }
+
+       if (type == cy_as_reset_hard) {
+               cy_as_misc_cancel_ex_requests(dev_p);
+               cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_RST_CTRL_REG,
+                       CY_AS_MEM_RST_CTRL_REG_HARD);
+               cy_as_device_set_unconfigured(dev_p);
+               cy_as_device_set_firmware_not_loaded(dev_p);
+               cy_as_device_set_dma_stopped(dev_p);
+               cy_as_device_set_low_level_stopped(dev_p);
+               cy_as_device_set_intr_stopped(dev_p);
+               cy_as_device_clear_suspend_mode(dev_p);
+               cy_as_usb_cleanup(dev_p);
+               cy_as_storage_cleanup(dev_p);
+
+               /*
+                * wait for a small amount of time to
+                * allow reset to be complete.
+                */
+               cy_as_hal_sleep(100);
+       }
+
+       cy_as_device_clear_reset_pending(dev_p);
+
+       return CY_AS_ERROR_SUCCESS;
+}
+
+cy_as_return_status_t
+cy_as_misc_reset(cy_as_device_handle handle,
+                               cy_as_reset_type type,
+                               cy_bool flush,
+                               cy_as_function_callback cb,
+                               uint32_t client)
+{
+       cy_as_device *dev_p;
+       cy_as_end_point_number_t i;
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       (void)client;
+       (void)cb;
+
+       cy_as_log_debug_message(6, "cy_as_misc_reset_e_x called");
+
+       /* Make sure the device is ready for the command. */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       /*
+        * soft reset is not supported until we close on the issues
+        * in the firmware with what needs to happen.
+        */
+       if (type == cy_as_reset_soft)
+               return CY_AS_ERROR_NOT_YET_SUPPORTED;
+
+       cy_as_device_set_reset_pending(dev_p);
+
+       if (flush) {
+               /* Unable to DrainQueues in polling mode */
+               if ((dev_p->storage_cb || dev_p->storage_cb_ms) &&
+                       cy_as_hal_is_polling())
+                       return CY_AS_ERROR_ASYNC_PENDING;
+
+               /*
+               * shutdown the endpoints so no more traffic can be queued
+               */
+               for (i = 0; i < 15; i++)
+                       cy_as_dma_enable_end_point(dev_p, i, cy_false,
+                               cy_as_direction_dont_change);
+
+               /*
+                * 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
+                * cancelled.
+                */
+               if (cy_as_device_is_in_suspend_mode(dev_p)) {
+                       for (i = 0; i < 15; i++)
+                               cy_as_dma_cancel(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))
+                                       cy_as_dma_drain_queue(dev_p, i,
+                                               cy_false);
+                               else
+                                       cy_as_dma_drain_queue(dev_p, i,
+                                               cy_true);
+                       }
+               }
+       } else {
+               /* No flush was requested, so cancel any outstanding DMAs
+                * so the user callbacks are called as needed
+                */
+               if (cy_as_device_is_storage_async_pending(dev_p)) {
+                       for (i = 0; i < 15; i++)
+                               cy_as_dma_cancel(dev_p, i,
+                                       CY_AS_ERROR_CANCELED);
+               }
+       }
+
+       ret = my_handle_response_reset(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((cy_as_device_handle)dev_p, ret, client,
+                       CY_FUNCT_CB_MISC_RESET, 0);
+
+       /*
+        * initialize any registers that may have been
+        * changed when the device was reset.
+        */
+       cy_as_hal_init_dev_registers(dev_p->tag, cy_false);
+
+       return ret;
+}
+
+static cy_as_return_status_t
+get_unallocated_resource(cy_as_device *dev_p, cy_as_resource_type resource)
+{
+       uint8_t shift = 0;
+       uint16_t v;
+       cy_as_return_status_t ret = CY_AS_ERROR_NOT_ACQUIRED;
+
+       switch (resource) {
+       case cy_as_bus_u_s_b:
+               shift = 4;
+               break;
+       case cy_as_bus_1:
+               shift = 0;
+               break;
+       case cy_as_bus_0:
+               shift = 2;
+               break;
+       default:
+               cy_as_hal_assert(cy_false);
+               break;
+       }
+
+       /* Get the semaphore value for this resource */
+       v = cy_as_hal_read_register(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 */
+               cy_as_hal_write_register(dev_p->tag,
+                       CY_AS_MEM_P0_RSE_MASK, (0x03 << shift));
+               v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_MASK);
+               cy_as_hal_write_register(dev_p->tag,
+                       CY_AS_MEM_P0_RSE_ALLOCATE, (0x01 << shift));
+               v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_MASK);
+
+               v = cy_as_hal_read_register(dev_p->tag,
+                       CY_AS_MEM_P0_RSE_ALLOCATE);
+               v = (v >> shift) & 0x03;
+               if (v == 0x03)
+                       ret = CY_AS_ERROR_SUCCESS;
+       }
+
+       return ret;
+}
+
+static cy_as_return_status_t
+my_handle_response_acquire_resource(cy_as_device *dev_p,
+                       cy_as_ll_request_response *req_p,
+                       cy_as_ll_request_response *reply_p,
+                       cy_as_resource_type *resource)
+{
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+
+       if (cy_as_ll_request_response__get_code(reply_p) !=
+               CY_RESP_SUCCESS_FAILURE) {
+               ret = CY_AS_ERROR_INVALID_RESPONSE;
+               goto destroy;
+       }
+
+       if (ret == CY_AS_ERROR_SUCCESS) {
+                       ret = get_unallocated_resource(dev_p, *resource);
+                       if (ret != CY_AS_ERROR_NOT_ACQUIRED)
+                               ret = CY_AS_ERROR_SUCCESS;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+cy_as_return_status_t
+cy_as_misc_acquire_resource(cy_as_device_handle handle,
+                       cy_as_resource_type *resource,
+                       cy_bool force,
+                       cy_as_function_callback cb,
+                       uint32_t client)
+{
+       cy_as_ll_request_response *req_p, *reply_p;
+       cy_as_return_status_t ret;
+
+       cy_as_device *dev_p;
+
+       (void)client;
+
+       cy_as_log_debug_message(6, "cy_as_misc_acquire_resource called");
+
+       if (*resource != cy_as_bus_u_s_b && *resource !=
+               cy_as_bus_0 && *resource != cy_as_bus_1)
+                       return CY_AS_ERROR_INVALID_RESOURCE;
+
+
+       /* Make sure the device is ready to accept the command. */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       if (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+
+       ret = get_unallocated_resource(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 = cy_as_ll_create_request(dev_p, CY_RQT_ACQUIRE_RESOURCE,
+               CY_RQT_RESOURCE_RQT_CONTEXT, 1);
+       if (req_p == 0)
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+
+       cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)(*resource));
+
+       reply_p = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_SUCCESS_FAILURE) {
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       goto destroy;
+               }
+
+               ret = cy_as_ll_request_response__get_word(reply_p, 0);
+       } else {
+                       ret = cy_as_misc_send_request(dev_p, cb, client,
+                               CY_FUNCT_CB_MISC_ACQUIRERESOURCE, resource,
+                               dev_p->func_cbs_res, CY_AS_REQUEST_RESPONSE_EX,
+                               req_p, reply_p, cy_as_misc_func_callback);
+
+                       if (ret != CY_AS_ERROR_SUCCESS)
+                                       goto destroy;
+
+                       /* The request and response are freed
+                        * as part of the MiscFuncCallback */
+                       return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       if (ret == CY_AS_ERROR_SUCCESS) {
+               ret = get_unallocated_resource(dev_p, *resource);
+               if (ret != CY_AS_ERROR_NOT_ACQUIRED)
+                       ret = CY_AS_ERROR_SUCCESS;
+       }
+
+       return ret;
+}
+cy_as_return_status_t
+cy_as_misc_release_resource(cy_as_device_handle handle,
+       cy_as_resource_type resource)
+{
+       uint8_t shift = 0;
+       uint16_t v;
+
+       cy_as_device *dev_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_release_resource called");
+
+       /* Make sure the device is ready for the command. */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       if (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       if (resource != cy_as_bus_u_s_b && resource !=
+               cy_as_bus_0 && resource != cy_as_bus_1)
+               return CY_AS_ERROR_INVALID_RESOURCE;
+
+       switch (resource) {
+       case cy_as_bus_u_s_b:
+               shift = 4;
+               break;
+       case cy_as_bus_1:
+               shift = 0;
+               break;
+       case cy_as_bus_0:
+               shift = 2;
+               break;
+       default:
+               cy_as_hal_assert(cy_false);
+               break;
+       }
+
+       /* Get the semaphore value for this resource */
+       v = (cy_as_hal_read_register(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;
+
+       cy_as_hal_write_register(dev_p->tag,
+               CY_AS_MEM_P0_RSE_MASK, (0x03 << shift));
+       cy_as_hal_write_register(dev_p->tag,
+               CY_AS_MEM_P0_RSE_ALLOCATE, (0x02 << shift));
+       cy_as_hal_write_register(dev_p->tag,
+               CY_AS_MEM_P0_RSE_MASK, 0);
+
+       return CY_AS_ERROR_SUCCESS;
+}
+
+cy_as_return_status_t
+cy_as_misc_set_trace_level(cy_as_device_handle handle,
+                                               uint8_t level,
+                                               cy_as_bus_number_t bus,
+                                               uint32_t device,
+                                               uint32_t unit,
+                                               cy_as_function_callback cb,
+                                               uint32_t client)
+{
+       cy_as_ll_request_response *req_p, *reply_p;
+       cy_as_return_status_t ret;
+       cy_as_device *dev_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_set_trace_level called");
+
+       /* Make sure the device is ready for the command. */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       if (cy_as_device_is_in_suspend_mode(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 = cy_as_ll_create_request(dev_p, CY_RQT_SET_TRACE_LEVEL,
+               CY_RQT_GENERAL_RQT_CONTEXT, 2);
+       if (req_p == 0)
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+
+       cy_as_ll_request_response__set_word(req_p, 0,
+               (uint16_t)level);
+       cy_as_ll_request_response__set_word(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 = cy_as_ll_create_response(dev_p, 2);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_SUCCESS_FAILURE) {
+                       ret = CY_AS_ERROR_NOT_SUPPORTED;
+                       goto destroy;
+               }
+
+               ret = cy_as_ll_request_response__get_word(reply_p, 0);
+       } else {
+
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_SETTRACELEVEL, 0, dev_p->func_cbs_misc,
+                       CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+                       cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+               /* The request and response are freed as part of the
+                * MiscFuncCallback */
+               return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+cy_as_return_status_t
+cy_as_misc_heart_beat_control(cy_as_device_handle handle,
+                                                  cy_bool enable,
+                                                  cy_as_function_callback cb,
+                                                  uint32_t client)
+{
+       cy_as_ll_request_response *req_p, *reply_p;
+       cy_as_return_status_t ret;
+       cy_as_device *dev_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_heart_beat_control called");
+
+       /* Make sure the device is ready for the command. */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       if (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       /* Create the request to send to the West Bridge device */
+       req_p = cy_as_ll_create_request(dev_p, CY_RQT_CONTROL_ANTIOCH_HEARTBEAT,
+               CY_RQT_GENERAL_RQT_CONTEXT, 1);
+       if (req_p == 0)
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+
+       cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)enable);
+
+       /* Reserve space for the reply, the reply
+        * data will not exceed one word */
+       reply_p = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_SUCCESS_FAILURE) {
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       goto destroy;
+               }
+
+               ret = cy_as_ll_request_response__get_word(reply_p, 0);
+       } else {
+
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_HEARTBEATCONTROL, 0,
+                       dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
+                       req_p, reply_p, cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+               /* The request and response are freed as part of the
+                * MiscFuncCallback */
+               return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+static cy_as_return_status_t
+my_set_sd_clock_freq(
+               cy_as_device              *dev_p,
+               uint8_t                   card_type,
+               uint8_t                   setting,
+               cy_as_function_callback cb,
+               uint32_t                         client)
+{
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_as_ll_request_response *req_p, *reply_p;
+
+       if (cy_as_device_is_in_callback(dev_p) && (cb == 0))
+               return CY_AS_ERROR_INVALID_IN_CALLBACK;
+
+       req_p = cy_as_ll_create_request(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;
+
+       cy_as_ll_request_response__set_word(req_p, 0,
+               (uint16_t)((card_type << 8) | setting));
+
+       /* Reserve space for the reply, which will not exceed one word. */
+       reply_p = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_SUCCESS_FAILURE) {
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       goto destroy;
+               }
+
+               ret = cy_as_ll_request_response__get_word(reply_p, 0);
+       } else {
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_SETSDFREQ, 0, dev_p->func_cbs_misc,
+                       CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
+                       cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+               /* The request and response are freed as part of the
+                * MiscFuncCallback */
+               return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+cy_as_return_status_t
+cy_as_misc_set_low_speed_sd_freq(
+               cy_as_device_handle      handle,
+               cy_as_low_speed_sd_freq   setting,
+               cy_as_function_callback cb,
+               uint32_t                         client)
+{
+       cy_as_device *dev_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_set_low_speed_sd_freq called");
+
+       /* Make sure the device is ready for the command. */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       if (cy_as_device_is_in_suspend_mode(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 my_set_sd_clock_freq(dev_p, 0, (uint8_t)setting, cb, client);
+}
+
+cy_as_return_status_t
+cy_as_misc_set_high_speed_sd_freq(
+               cy_as_device_handle      handle,
+               cy_as_high_speed_sd_freq  setting,
+               cy_as_function_callback cb,
+               uint32_t                         client)
+{
+       cy_as_device *dev_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_set_high_speed_sd_freq called");
+
+       /* Make sure the device is ready for the command. */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       if (cy_as_device_is_in_suspend_mode(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 my_set_sd_clock_freq(dev_p, 1, (uint8_t)setting, cb, client);
+}
+
+cy_as_return_status_t
+cy_as_misc_get_gpio_value(cy_as_device_handle handle,
+               cy_as_misc_gpio pin,
+               uint8_t *value,
+               cy_as_function_callback cb,
+               uint32_t client)
+{
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_as_ll_request_response *req_p, *reply_p;
+       cy_as_device *dev_p;
+       uint16_t v;
+
+       cy_as_log_debug_message(6, "cy_as_misc_get_gpio_value called");
+
+       /* Make sure the device is ready for the command. */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       /* If the pin specified is UVALID, there is no need
+        * for firmware to be loaded. */
+       if (pin == cy_as_misc_gpio_U_valid) {
+               v = cy_as_hal_read_register(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 (cy_as_device_is_nand_storage_supported(dev_p))
+               return CY_AS_ERROR_NOT_SUPPORTED;
+
+       if (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       /* Make sure the pin selected is valid */
+       if ((pin != cy_as_misc_gpio_1) && (pin != cy_as_misc_gpio_0))
+               return CY_AS_ERROR_INVALID_PARAMETER;
+
+       req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_GPIO_STATE,
+               CY_RQT_GENERAL_RQT_CONTEXT, 1);
+       if (req_p == 0)
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+
+       cy_as_ll_request_response__set_word(req_p, 0, ((uint8_t)pin << 8));
+
+       /* Reserve space for the reply, which will not exceed one word. */
+       reply_p = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_GPIO_STATE) {
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       goto destroy;
+               }
+
+               *value = (uint8_t)
+                       cy_as_ll_request_response__get_word(reply_p, 0);
+       } else {
+
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_GETGPIOVALUE, value,
+                       dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
+                       req_p, reply_p, cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+               /* The request and response are freed as part of the
+                * MiscFuncCallback */
+               return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+
+cy_as_return_status_t
+cy_as_misc_set_gpio_value(cy_as_device_handle handle,
+               cy_as_misc_gpio pin,
+               uint8_t value,
+               cy_as_function_callback cb,
+               uint32_t client)
+{
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_as_ll_request_response *req_p, *reply_p;
+       cy_as_device *dev_p;
+       uint16_t v;
+
+       cy_as_log_debug_message(6, "cy_as_misc_set_gpio_value called");
+
+       /* Make sure the device is ready for the command. */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       /* If the pin specified is UVALID, there is
+        * no need for firmware to be loaded. */
+       if (pin == cy_as_misc_gpio_U_valid) {
+               v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PMU_UPDATE);
+               if (value)
+                       cy_as_hal_write_register(dev_p->tag,
+                               CY_AS_MEM_PMU_UPDATE,
+                               (v | CY_AS_MEM_PMU_UPDATE_UVALID));
+               else
+                       cy_as_hal_write_register(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 (cy_as_device_is_nand_storage_supported(dev_p))
+               return CY_AS_ERROR_NOT_SUPPORTED;
+
+       if (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       /* Make sure the pin selected is valid */
+       if ((pin < cy_as_misc_gpio_0) || (pin > cy_as_misc_gpio_U_valid))
+               return CY_AS_ERROR_INVALID_PARAMETER;
+
+       /* Create and initialize the low level request to the firmware. */
+       req_p = cy_as_ll_create_request(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));
+       cy_as_ll_request_response__set_word(req_p, 0, v);
+
+       /* Reserve space for the reply, which will not exceed one word. */
+       reply_p = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_SUCCESS_FAILURE) {
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       goto destroy;
+               }
+
+               ret = cy_as_ll_request_response__get_word(reply_p, 0);
+       } else {
+
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_SETGPIOVALUE, 0,
+                       dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
+                       req_p, reply_p, cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+               /* The request and response are freed as part of the
+                * MiscFuncCallback */
+               return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+static cy_as_return_status_t
+my_enter_standby(cy_as_device *dev_p, cy_bool pin)
+{
+       cy_as_misc_cancel_ex_requests(dev_p);
+
+       /* Save the current values in the critical P-port
+        * registers, where necessary. */
+       cy_as_hal_read_regs_before_standby(dev_p->tag);
+
+       if (pin) {
+               if (cy_as_hal_set_wakeup_pin(dev_p->tag, cy_false))
+                       cy_as_device_set_pin_standby(dev_p);
+               else
+                       return CY_AS_ERROR_SETTING_WAKEUP_PIN;
+       } else {
+               /*
+                * put antioch in the standby mode
+                */
+               cy_as_hal_write_register(dev_p->tag,
+                       CY_AS_MEM_PWR_MAGT_STAT, 0x02);
+               cy_as_device_set_register_standby(dev_p);
+       }
+
+       /*
+        * when the antioch comes out of standby, we have to wait until
+        * the firmware initialization completes before sending other
+        * requests down.
+        */
+       cy_as_device_set_firmware_not_loaded(dev_p);
+
+       /*
+        * keep west bridge interrupt disabled until the device is being woken
+        * up from standby.
+        */
+       dev_p->stby_int_mask = cy_as_hal_disable_interrupts();
+
+       return CY_AS_ERROR_SUCCESS;
+}
+
+static cy_as_return_status_t
+my_handle_response_enter_standby(cy_as_device *dev_p,
+                       cy_as_ll_request_response *req_p,
+                       cy_as_ll_request_response *reply_p,
+                       cy_bool pin)
+{
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+
+       if (cy_as_ll_request_response__get_code(reply_p) !=
+               CY_RESP_SUCCESS_FAILURE) {
+               ret = CY_AS_ERROR_INVALID_RESPONSE;
+               goto destroy;
+       }
+
+       ret = cy_as_ll_request_response__get_word(reply_p, 0);
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       if (ret != CY_AS_ERROR_SUCCESS)
+               return ret;
+
+       ret = my_enter_standby(dev_p, pin);
+
+       return ret;
+}
+
+cy_as_return_status_t
+cy_as_misc_enter_standby(cy_as_device_handle handle,
+                                               cy_bool pin,
+                                               cy_as_function_callback cb,
+                                               uint32_t client)
+{
+       cy_as_device *dev_p;
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_as_ll_request_response *req_p, *reply_p;
+       cy_bool standby;
+
+       cy_as_log_debug_message(6, "cy_as_misc_enter_standby called");
+
+       /* Make sure we have a valid device */
+       dev_p = (cy_as_device *)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 = cy_as_misc_in_standby(handle, &standby);
+       if (ret != CY_AS_ERROR_SUCCESS)
+               return ret;
+
+       if (standby == cy_true)
+               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 (cy_as_device_is_in_suspend_mode(dev_p))
+               cy_as_misc_leave_suspend(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 (cy_as_device_is_storage_async_pending(dev_p)) {
+                       /* DrainQueue will not work in polling mode */
+                       if (cy_as_hal_is_polling())
+                               return CY_AS_ERROR_ASYNC_PENDING;
+
+                       cy_as_dma_drain_queue(dev_p,
+                               CY_AS_P2S_READ_ENDPOINT, cy_false);
+                       cy_as_dma_drain_queue(dev_p,
+                               CY_AS_P2S_WRITE_ENDPOINT, cy_false);
+
+                       /*
+                        * if more storage operations were queued
+                        * at this stage, return an error.
+                        */
+                       if (cy_as_device_is_storage_async_pending(dev_p))
+                               return CY_AS_ERROR_ASYNC_PENDING;
+               }
+
+               req_p = cy_as_ll_create_request(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 = cy_as_ll_create_response(dev_p, 1);
+               if (reply_p == 0) {
+                       cy_as_ll_destroy_request(dev_p, req_p);
+                       return CY_AS_ERROR_OUT_OF_MEMORY;
+               }
+
+               if (!cb) {
+                       ret = cy_as_ll_send_request_wait_reply(dev_p,
+                               req_p, reply_p);
+                       if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+                       /* The request and response are freed
+                        * in the HandleResponse */
+                       return my_handle_response_enter_standby(dev_p,
+                               req_p, reply_p, pin);
+
+               } else {
+                       ret = cy_as_misc_send_request(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, cy_as_misc_func_callback);
+
+                       if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+                       /* The request and response are freed
+                        * as part of the MiscFuncCallback */
+                       return ret;
+               }
+destroy:
+               cy_as_ll_destroy_request(dev_p, req_p);
+               cy_as_ll_destroy_response(dev_p, reply_p);
+       } else {
+               ret = my_enter_standby(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((cy_as_device_handle)dev_p, ret, client,
+                               CY_FUNCT_CB_MISC_ENTERSTANDBY, 0);
+       }
+
+       return ret;
+}
+
+cy_as_return_status_t
+cy_as_misc_enter_standby_e_x_u(cy_as_device_handle handle,
+                                               cy_bool pin,
+                                               cy_bool uvalid_special,
+                                               cy_as_function_callback cb,
+                                               uint32_t client)
+{
+       cy_as_device *dev_p;
+
+       dev_p = (cy_as_device *)handle;
+       if (uvalid_special)
+               cy_as_hal_write_register(dev_p->tag, 0xc5, 0x4);
+
+       return cy_as_misc_enter_standby(handle, pin, cb, client);
+}
+
+cy_as_return_status_t
+cy_as_misc_leave_standby(cy_as_device_handle handle,
+       cy_as_resource_type resource)
+{
+       cy_as_device *dev_p;
+       uint16_t v;
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       uint32_t count = 8;
+       uint8_t  retry = 1;
+
+       cy_as_log_debug_message(6, "cy_as_misc_leave_standby called");
+       (void)resource;
+
+       /* Make sure we have a valid device */
+       dev_p = (cy_as_device *)handle;
+       if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+               return CY_AS_ERROR_INVALID_HANDLE;
+
+       if (cy_as_device_is_register_standby(dev_p)) {
+               /*
+                * set a flag to indicate that the west bridge is waking
+                * up from standby.
+                */
+               cy_as_device_set_waking(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 = cy_as_hal_read_register(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 (cy_as_device_is_crystal(dev_p))
+                               cy_as_hal_sleep(
+                                       CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL);
+                       else
+                               cy_as_hal_sleep(
+                                       CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
+                       v = cy_as_hal_read_register(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 (!is_valid_silicon_id(v)) {
+                               if (cy_as_hal_sync_device_clocks(dev_p->tag) !=
+                                       cy_true) {
+                                       cy_as_hal_enable_interrupts(
+                                               dev_p->stby_int_mask);
+                                       return CY_AS_ERROR_TIMEOUT;
+                               }
+                       }
+               } while (!is_valid_silicon_id(v) && count-- > 0);
+
+               /*
+                * if we tried to read the register and could not,
+                * return a timeout
+                */
+               if (count == 0) {
+                       cy_as_hal_enable_interrupts(
+                               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.
+                */
+               cy_as_device_clear_register_standby(dev_p);
+
+               /*
+                * initialize any registers that may have been changed
+                * while the device was in standby mode.
+                */
+               cy_as_hal_init_dev_registers(dev_p->tag, cy_true);
+       } else if (cy_as_device_is_pin_standby(dev_p)) {
+               /*
+                * set a flag to indicate that the west bridge is waking
+                * up from standby.
+                */
+               cy_as_device_set_waking(dev_p);
+
+try_wakeup_again:
+               /*
+               * try to set the wakeup pin, if this fails in the HAL
+               * layer, return this failure to the user.
+               */
+               if (!cy_as_hal_set_wakeup_pin(dev_p->tag, cy_true)) {
+                       cy_as_hal_enable_interrupts(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 PL_ls have locked
+               * and we can talk to the device.
+               */
+               if (cy_as_device_is_crystal(dev_p))
+                       cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL);
+               else
+                       cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
+
+               /*
+                * initialize any registers that may have been changed
+                * while the device was in standby mode.
+                */
+               cy_as_hal_init_dev_registers(dev_p->tag, cy_true);
+
+               /*
+                * 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.
+                */
+               cy_as_device_clear_pin_standby(dev_p);
+       } else {
+               return CY_AS_ERROR_NOT_IN_STANDBY;
+       }
+
+       /*
+        * the west bridge interrupt can be enabled now.
+        */
+       cy_as_hal_enable_interrupts(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)) {
+               cy_as_hal_write_register(dev_p->tag,
+                       CY_AS_MEM_RST_CTRL_REG, 0x00);
+               v = cy_as_hal_read_register(dev_p->tag,
+                       CY_AS_MEM_RST_CTRL_REG);
+               count--;
+       }
+
+       if (v & 0x03) {
+               cy_as_hal_print_message("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 (cy_as_device_is_firmware_loaded(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 = cy_as_hal_read_register(dev_p->tag,
+                               CY_AS_MEM_P0_INTR_REG);
+                       if (v & CY_AS_MEM_P0_INTR_REG_MBINT)
+                               break;
+
+                       cy_as_hal_sleep(10);
+                       count--;
+               }
+
+               if (!count) {
+                       retry = 0;
+                       dev_p->stby_int_mask = cy_as_hal_disable_interrupts();
+                       cy_as_hal_set_wakeup_pin(dev_p->tag, cy_false);
+                       cy_as_hal_sleep(10);
+                       goto try_wakeup_again;
+               }
+       }
+
+       return ret;
+}
+
+cy_as_return_status_t
+cy_as_misc_register_callback(
+                       /* Handle to the West Bridge device */
+                       cy_as_device_handle handle,
+                       /* The function to call */
+                       cy_as_misc_event_callback  callback
+                       )
+{
+       cy_as_device *dev_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_register_callback called");
+
+       /* Make sure we have a valid device */
+       dev_p = (cy_as_device *)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;
+}
+
+cy_as_return_status_t
+cy_as_misc_storage_changed(cy_as_device_handle handle,
+                                                cy_as_function_callback   cb,
+                                                uint32_t client)
+{
+       cy_as_device *dev_p;
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_bool standby;
+       cy_as_ll_request_response *req_p, *reply_p;
+
+       cy_as_log_debug_message(6, "cy_as_misc_storage_changed called");
+
+       /* Make sure the device is ready for the command. */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       /*
+       * make sure antioch is not in standby
+       */
+       ret = cy_as_misc_in_standby(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 (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       /* Create the request to send to the West Bridge device */
+       req_p = cy_as_ll_create_request(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 = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(dev_p, req_p);
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_SUCCESS_FAILURE) {
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       goto destroy;
+               }
+
+               ret = cy_as_ll_request_response__get_word(reply_p, 0);
+       } else {
+
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_STORAGECHANGED, 0,
+                       dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
+                       req_p, reply_p, cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+               /* The request and response are freed as part of the
+                * MiscFuncCallback */
+               return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+
+cy_as_return_status_t
+cy_as_misc_enter_suspend(
+               cy_as_device_handle      handle,
+               cy_bool                    usb_wakeup_en,
+               cy_bool                    gpio_wakeup_en,
+               cy_as_function_callback cb,
+               uint32_t                         client)
+{
+       cy_as_device *dev_p;
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_bool standby;
+       cy_as_ll_request_response *req_p, *reply_p;
+       uint16_t value;
+       uint32_t int_state;
+
+       cy_as_log_debug_message(6, "cy_as_misc_enter_suspend called");
+
+       /*
+        * basic sanity checks to ensure that the device is initialised.
+        */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       /*
+        * make sure west bridge is not already in standby
+        */
+       cy_as_misc_in_standby(dev_p, &standby);
+       if (standby)
+               return CY_AS_ERROR_IN_STANDBY;
+
+       /*
+        * make sure that the device is not already in suspend mode.
+        */
+       if (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       /*
+        * make sure there is no active USB connection.
+        */
+       if ((cy_as_device_is_usb_connected(dev_p)) && (dev_p->usb_last_event
+               != cy_as_event_usb_suspend))
+               return CY_AS_ERROR_USB_CONNECTED;
+
+       /*
+        * make sure that there are no async requests at this point in time.
+        */
+       int_state = cy_as_hal_disable_interrupts();
+       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)) {
+               cy_as_hal_enable_interrupts(int_state);
+               return CY_AS_ERROR_ASYNC_PENDING;
+       }
+       cy_as_hal_enable_interrupts(int_state);
+
+       /* Create the request to send to the Antioch device */
+       req_p = cy_as_ll_create_request(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 = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+               cy_as_ll_destroy_request(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;
+       cy_as_ll_request_response__set_word(req_p, 0, value);
+
+       if (cb != 0) {
+
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_ENTERSUSPEND,
+                       0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
+                       req_p, reply_p,
+                       cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                               goto destroy;
+
+               return CY_AS_ERROR_SUCCESS;
+       } else {
+               ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_SUCCESS_FAILURE)
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+               else
+                       ret = cy_as_ll_request_response__get_word(reply_p, 0);
+       }
+
+destroy:
+       if (ret == CY_AS_ERROR_SUCCESS)
+               cy_as_device_set_suspend_mode(dev_p);
+
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+cy_as_return_status_t
+cy_as_misc_leave_suspend(
+               cy_as_device_handle      handle,
+               cy_as_function_callback cb,
+               uint32_t                         client)
+{
+       cy_as_device *dev_p;
+       uint16_t v, count;
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+
+       cy_as_log_debug_message(6, "cy_as_misc_leave_suspend called");
+
+       /* Make sure we have a valid device */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       /* Make sure we are in suspend mode. */
+       if (cy_as_device_is_in_suspend_mode(dev_p)) {
+               if (cb) {
+                       cy_as_func_c_b_node *cbnode =
+                               cy_as_create_func_c_b_node_data(cb, client,
+                               CY_FUNCT_CB_MISC_LEAVESUSPEND, 0);
+                       if (cbnode == 0)
+                               return CY_AS_ERROR_OUT_OF_MEMORY;
+
+                       cy_as_insert_c_b_node(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 = cy_as_hal_read_register(dev_p->tag,
+                               CY_AS_MEM_CM_WB_CFG_ID);
+
+               while (!is_valid_silicon_id(v) && count-- > 0) {
+                       cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
+                       v = cy_as_hal_read_register(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 ((cy_as_device_is_in_suspend_mode(dev_p))
+                       && (count--)) {
+                       cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
+               }
+
+               if (cy_as_device_is_in_suspend_mode(dev_p))
+                       ret = CY_AS_ERROR_TIMEOUT;
+       }
+
+       return ret;
+}
+
+cy_as_return_status_t
+cy_as_misc_reserve_l_n_a_boot_area(cy_as_device_handle handle,
+                                                  uint8_t numzones,
+                                                  cy_as_function_callback cb,
+                                                  uint32_t client)
+{
+       cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
+       cy_bool standby;
+       cy_as_ll_request_response *req_p, *reply_p;
+
+       cy_as_device *dev_p;
+
+       (void)client;
+
+       cy_as_log_debug_message(6, "cy_as_misc_switch_pnand_mode called");
+
+       /* Make sure we have a valid device */
+       dev_p = (cy_as_device *)handle;
+       cy_as_check_device_ready(dev_p);
+
+       /*
+       * make sure antioch is not in standby
+       */
+       ret = cy_as_misc_in_standby(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 (cy_as_device_is_in_suspend_mode(dev_p))
+               return CY_AS_ERROR_IN_SUSPEND;
+
+       /* Create the request to send to the West Bridge device */
+       req_p = cy_as_ll_create_request(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;
+               cy_as_ll_request_response__set_word(req_p,
+                       0, (uint16_t)numzones);
+
+       /* Reserve space for the reply, the reply data will not
+        * exceed one word */
+       reply_p = cy_as_ll_create_response(dev_p, 1);
+       if (reply_p == 0) {
+                       cy_as_ll_destroy_request(dev_p, req_p);
+                       return CY_AS_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (cb == 0) {
+               ret = cy_as_ll_send_request_wait_reply(dev_p,
+                               req_p, reply_p);
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               if (cy_as_ll_request_response__get_code(reply_p) !=
+                       CY_RESP_SUCCESS_FAILURE) {
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       goto destroy;
+               }
+
+               ret = cy_as_ll_request_response__get_word(reply_p, 0);
+       } else {
+
+               ret = cy_as_misc_send_request(dev_p, cb, client,
+                       CY_FUNCT_CB_MISC_RESERVELNABOOTAREA,
+                       0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
+                       req_p, reply_p, cy_as_misc_func_callback);
+
+               if (ret != CY_AS_ERROR_SUCCESS)
+                       goto destroy;
+
+               /* The request and response are freed as part of the
+                * MiscFuncCallback */
+               return ret;
+       }
+
+destroy:
+       cy_as_ll_destroy_request(dev_p, req_p);
+       cy_as_ll_destroy_response(dev_p, reply_p);
+
+       return ret;
+}
+
+cy_as_func_c_b_node*
+cy_as_create_func_c_b_node_data(cy_as_function_callback cb,
+                                        uint32_t client,
+                                        cy_as_funct_c_b_type type,
+                                        void *data)
+{
+       uint32_t state = cy_as_hal_disable_interrupts();
+       cy_as_func_c_b_node *node = cy_as_hal_c_b_alloc(
+                                       sizeof(cy_as_func_c_b_node));
+       cy_as_hal_enable_interrupts(state);
+       if (node != 0) {
+               node->node_type = CYAS_FUNC_CB;
+               node->cb_p = cb;
+               node->client_data = client;
+               node->data_type = type;
+               if (data != 0)
+                       node->data_type |= CY_FUNCT_CB_DATA;
+               else
+                       node->data_type |= CY_FUNCT_CB_NODATA;
+               node->data = data;
+               node->next_p = 0;
+       }
+       return node;
+}
+
+cy_as_func_c_b_node*
+cy_as_create_func_c_b_node(cy_as_function_callback cb,
+                                        uint32_t client)
+{
+       return cy_as_create_func_c_b_node_data(cb, client,
+               CY_FUNCT_CB_NODATA, 0);
+}
+
+void
+cy_as_destroy_func_c_b_node(cy_as_func_c_b_node *node)
+{
+       uint32_t state;
+
+       node->node_type = CYAS_INVALID;
+       state = cy_as_hal_disable_interrupts();
+       cy_as_hal_c_b_free(node);
+       cy_as_hal_enable_interrupts(state);
+}
+
+cy_as_usb_func_c_b_node*
+cy_as_create_usb_func_c_b_node(
+               cy_as_usb_function_callback cb, uint32_t client)
+{
+       uint32_t state = cy_as_hal_disable_interrupts();
+       cy_as_usb_func_c_b_node *node = cy_as_hal_c_b_alloc(
+               sizeof(cy_as_usb_func_c_b_node));
+       cy_as_hal_enable_interrupts(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
+cy_as_destroy_usb_func_c_b_node(cy_as_usb_func_c_b_node *node)
+{
+       uint32_t state;
+
+       node->type = CYAS_INVALID;
+       state = cy_as_hal_disable_interrupts();
+       cy_as_hal_c_b_free(node);
+       cy_as_hal_enable_interrupts(state);
+}
+
+cy_as_usb_io_c_b_node*
+cy_as_create_usb_io_c_b_node(cy_as_usb_io_callback cb)
+{
+       uint32_t state = cy_as_hal_disable_interrupts();
+       cy_as_usb_io_c_b_node *node = cy_as_hal_c_b_alloc(
+               sizeof(cy_as_usb_io_c_b_node));
+       cy_as_hal_enable_interrupts(state);
+       if (node != 0) {
+               node->type = CYAS_USB_IO_CB;
+               node->cb_p = cb;
+               node->next_p = 0;
+       }
+       return node;
+}
+
+void
+cy_as_destroy_usb_io_c_b_node(cy_as_usb_io_c_b_node *node)
+{
+       uint32_t state;
+
+       node->type = CYAS_INVALID;
+
+       state = cy_as_hal_disable_interrupts();
+       cy_as_hal_c_b_free(node);
+       cy_as_hal_enable_interrupts(state);
+}
+
+cy_as_storage_io_c_b_node*
+cy_as_create_storage_io_c_b_node(cy_as_storage_callback cb,
+       cy_as_media_type media, uint32_t device_index,
+       uint32_t unit, uint32_t block_addr, cy_as_oper_type oper,
+       cy_as_ll_request_response *req_p,
+       cy_as_ll_request_response *reply_p)
+{
+       uint32_t state = cy_as_hal_disable_interrupts();
+       cy_as_storage_io_c_b_node *node = cy_as_hal_c_b_alloc(
+               sizeof(cy_as_storage_io_c_b_node));
+       cy_as_hal_enable_interrupts(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
+cy_as_destroy_storage_io_c_b_node(cy_as_storage_io_c_b_node *node)
+{
+       uint32_t state;
+       node->type = CYAS_INVALID;
+       state = cy_as_hal_disable_interrupts();
+       cy_as_hal_c_b_free(node);
+       cy_as_hal_enable_interrupts(state);
+}
+
+cy_as_c_b_queue *
+cy_as_create_c_b_queue(cy_as_c_b_node_type type)
+{
+       uint32_t state = cy_as_hal_disable_interrupts();
+       cy_as_c_b_queue *queue = cy_as_hal_c_b_alloc(
+               sizeof(cy_as_c_b_queue));
+       cy_as_hal_enable_interrupts(state);
+       if (queue) {
+               queue->type = type;
+               queue->head_p = 0;
+               queue->tail_p = 0;
+               queue->count = 0;
+       }
+
+       return queue;
+}
+
+void
+cy_as_destroy_c_b_queue(cy_as_c_b_queue *queue)
+{
+       uint32_t state;
+       queue->type = CYAS_INVALID;
+       queue->head_p = 0;
+       queue->tail_p = 0;
+       queue->count = 0;
+       state = cy_as_hal_disable_interrupts();
+       cy_as_hal_c_b_free(queue);
+       cy_as_hal_enable_interrupts(state);
+}
+
+/* Inserts a CyAsCBNode into the queue, the
+ * node type must match the queue type*/
+void
+cy_as_insert_c_b_node(cy_as_c_b_queue *queue_p, void*cbnode)
+{
+       uint32_t int_state;
+
+       int_state = cy_as_hal_disable_interrupts();
+
+       cy_as_hal_assert(queue_p != 0);
+
+       switch (queue_p->type) {
+       case CYAS_USB_FUNC_CB:
+               {
+                       cy_as_usb_func_c_b_node *node =
+                               (cy_as_usb_func_c_b_node *)cbnode;
+                       cy_as_usb_func_c_b_node *tail =
+                               (cy_as_usb_func_c_b_node *)queue_p->tail_p;
+
+                       cy_as_hal_assert(node->type == CYAS_USB_FUNC_CB);
+                       cy_as_hal_assert(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:
+               {
+                       cy_as_usb_io_c_b_node *node =
+                               (cy_as_usb_io_c_b_node *)cbnode;
+                       cy_as_usb_io_c_b_node *tail =
+                               (cy_as_usb_io_c_b_node *)queue_p->tail_p;
+
+                       cy_as_hal_assert(node->type == CYAS_USB_IO_CB);
+                       cy_as_hal_assert(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:
+               {
+                       cy_as_storage_io_c_b_node *node =
+                               (cy_as_storage_io_c_b_node *)cbnode;
+                       cy_as_storage_io_c_b_node *tail =
+                               (cy_as_storage_io_c_b_node *)queue_p->tail_p;
+
+                       cy_as_hal_assert(node->type == CYAS_STORAGE_IO_CB);
+                       cy_as_hal_assert(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:
+               {
+                       cy_as_func_c_b_node *node =
+                               (cy_as_func_c_b_node *)cbnode;
+                       cy_as_func_c_b_node *tail =
+                               (cy_as_func_c_b_node *)queue_p->tail_p;
+
+                       cy_as_hal_assert(node->node_type == CYAS_FUNC_CB);
+                       cy_as_hal_assert(tail == 0 ||
+                               tail->node_type == 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:
+               cy_as_hal_assert(cy_false);
+               break;
+       }
+
+       queue_p->count++;
+
+       cy_as_hal_enable_interrupts(int_state);
+}
+
+/* Removes the tail node from the queue and frees it */
+void
+cy_as_remove_c_b_tail_node(cy_as_c_b_queue *queue_p)
+{
+       uint32_t int_state;
+
+       int_state = cy_as_hal_disable_interrupts();
+
+       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:
+                       {
+                               cy_as_func_c_b_node *node =
+                                       (cy_as_func_c_b_node *)
+                                       queue_p->head_p;
+                               cy_as_func_c_b_node *tail =
+                                       (cy_as_func_c_b_node *)
+                                       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;
+                               }
+                               cy_as_destroy_func_c_b_node(tail);
+                       }
+                       break;
+
+               case CYAS_USB_FUNC_CB:
+                       {
+                               cy_as_usb_func_c_b_node *node =
+                                       (cy_as_usb_func_c_b_node *)
+                                       queue_p->head_p;
+                               cy_as_usb_func_c_b_node *tail =
+                                       (cy_as_usb_func_c_b_node *)
+                                       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;
+                               }
+
+                               cy_as_destroy_usb_func_c_b_node(tail);
+                       }
+                       break;
+
+               case CYAS_USB_IO_CB:
+                       {
+                               cy_as_usb_io_c_b_node *node =
+                                       (cy_as_usb_io_c_b_node *)
+                                       queue_p->head_p;
+                               cy_as_usb_io_c_b_node *tail =
+                                       (cy_as_usb_io_c_b_node *)
+                                       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;
+                               }
+                               cy_as_destroy_usb_io_c_b_node(tail);
+                       }
+                       break;
+
+               case CYAS_STORAGE_IO_CB:
+                       {
+                               cy_as_storage_io_c_b_node *node =
+                                       (cy_as_storage_io_c_b_node *)
+                                       queue_p->head_p;
+                               cy_as_storage_io_c_b_node *tail =
+                                       (cy_as_storage_io_c_b_node *)
+                                       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;
+                               }
+                               cy_as_destroy_storage_io_c_b_node(tail);
+                       }
+                       break;
+
+               default:
+                       cy_as_hal_assert(cy_false);
+               }
+
+               queue_p->count--;
+               if (queue_p->count == 0) {
+                       queue_p->head_p = 0;
+                       queue_p->tail_p = 0;
+               }
+       }
+
+       cy_as_hal_enable_interrupts(int_state);
+}
+
+/* Removes the first CyAsCBNode from the queue and frees it */
+void
+cy_as_remove_c_b_node(cy_as_c_b_queue *queue_p)
+{
+       uint32_t int_state;
+
+       int_state = cy_as_hal_disable_interrupts();
+
+       cy_as_hal_assert(queue_p->count >= 0);
+       if (queue_p->count > 0) {
+               if (queue_p->type == CYAS_USB_FUNC_CB) {
+                       cy_as_usb_func_c_b_node *node =
+                               (cy_as_usb_func_c_b_node *)
+                               queue_p->head_p;
+                       queue_p->head_p = node->next_p;
+                       cy_as_destroy_usb_func_c_b_node(node);
+               } else if (queue_p->type == CYAS_USB_IO_CB) {
+                       cy_as_usb_io_c_b_node *node =
+                               (cy_as_usb_io_c_b_node *)
+                               queue_p->head_p;
+                       queue_p->head_p = node->next_p;
+                       cy_as_destroy_usb_io_c_b_node(node);
+               } else if (queue_p->type == CYAS_STORAGE_IO_CB) {
+                       cy_as_storage_io_c_b_node *node =
+                               (cy_as_storage_io_c_b_node *)
+                               queue_p->head_p;
+                       queue_p->head_p = node->next_p;
+                       cy_as_destroy_storage_io_c_b_node(node);
+               } else if (queue_p->type == CYAS_FUNC_CB) {
+                       cy_as_func_c_b_node *node =
+                               (cy_as_func_c_b_node *)
+                               queue_p->head_p;
+                       queue_p->head_p = node->next_p;
+                       cy_as_destroy_func_c_b_node(node);
+               } else {
+                       cy_as_hal_assert(cy_false);
+               }
+
+               queue_p->count--;
+               if (queue_p->count == 0) {
+                       queue_p->head_p = 0;
+                       queue_p->tail_p = 0;
+               }
+       }
+
+       cy_as_hal_enable_interrupts(int_state);
+}
+
+void my_print_func_c_b_node(cy_as_func_c_b_node *node)
+{
+       cy_as_funct_c_b_type type =
+               cy_as_funct_c_b_type_get_type(node->data_type);
+       cy_as_hal_print_message("[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->node_type);
+}
+
+void my_print_c_b_queue(cy_as_c_b_queue *queue_p)
+{
+       uint32_t i = 0;
+
+       cy_as_hal_print_message("| count: %u type: ", queue_p->count);
+
+       if (queue_p->type == CYAS_USB_FUNC_CB) {
+               cy_as_hal_print_message("USB_FUNC_CB\n");
+       } else if (queue_p->type == CYAS_USB_IO_CB) {
+               cy_as_hal_print_message("USB_IO_CB\n");
+       } else if (queue_p->type == CYAS_STORAGE_IO_CB) {
+               cy_as_hal_print_message("STORAGE_IO_CB\n");
+       } else if (queue_p->type == CYAS_FUNC_CB) {
+               cy_as_func_c_b_node *node = queue_p->head_p;
+               cy_as_hal_print_message("FUNC_CB\n");
+               if (queue_p->count > 0) {
+                       cy_as_hal_print_message("| head->");
+
+                       for (i = 0; i < queue_p->count; i++) {
+                               if (node) {
+                                       cy_as_hal_print_message("->");
+                                       my_print_func_c_b_node(node);
+                                       node = node->next_p;
+                               } else
+                                       cy_as_hal_print_message("->[NULL]\n");
+                       }
+
+                       cy_as_hal_print_message("\n| tail->");
+                       my_print_func_c_b_node(queue_p->tail_p);
+                       cy_as_hal_print_message("\n");
+               }
+       } else {
+               cy_as_hal_print_message("INVALID\n");
+       }
+
+       cy_as_hal_print_message("|----------\n");
+}
+
+
+/* Removes and frees all pending callbacks */
+void
+cy_as_clear_c_b_queue(cy_as_c_b_queue *queue_p)
+{
+       uint32_t int_state = cy_as_hal_disable_interrupts();
+
+       while (queue_p->count != 0)
+               cy_as_remove_c_b_node(queue_p);
+
+       cy_as_hal_enable_interrupts(int_state);
+}
+
+cy_as_return_status_t
+cy_as_misc_send_request(cy_as_device *dev_p,
+                                         cy_as_function_callback cb,
+                                         uint32_t client,
+                                         cy_as_funct_c_b_type type,
+                                         void *data,
+                                         cy_as_c_b_queue *queue,
+                                         uint16_t req_type,
+                                         cy_as_ll_request_response *req_p,
+                                         cy_as_ll_request_response *reply_p,
+                                         cy_as_response_callback rcb)
+{
+
+       cy_as_func_c_b_node *cbnode = cy_as_create_func_c_b_node_data(cb,
+               client, type, data);
+       cy_as_return_status_t ret;
+
+       if (cbnode == 0)
+               return CY_AS_ERROR_OUT_OF_MEMORY;
+       else
+               cy_as_insert_c_b_node(queue, cbnode);
+
+       req_p->flags |= req_type;
+
+       ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_false, rcb);
+       if (ret != CY_AS_ERROR_SUCCESS)
+               cy_as_remove_c_b_tail_node(queue);
+
+       return ret;
+}
+
+void
+cy_as_misc_cancel_ex_requests(cy_as_device *dev_p)
+{
+       int i;
+       for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++)
+               cy_as_ll_remove_all_requests(dev_p, dev_p->context[i]);
+}
+
+
+static void
+cy_as_misc_func_callback(cy_as_device *dev_p,
+                                               uint8_t context,
+                                               cy_as_ll_request_response *rqt,
+                                               cy_as_ll_request_response *resp,
+                                               cy_as_return_status_t stat)
+{
+       cy_as_func_c_b_node *node = NULL;
+       cy_as_return_status_t ret;
+
+       cy_bool ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX)
+                       == CY_AS_REQUEST_RESPONSE_EX;
+       cy_bool ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS)
+                       == CY_AS_REQUEST_RESPONSE_MS;
+       uint8_t code;
+       uint32_t type;
+       uint8_t cntxt;
+
+       cy_as_hal_assert(ex_request || ms_request);
+       (void) ex_request;
+       (void) ms_request;
+       (void)context;
+
+       cntxt = cy_as_ll_request_response__get_context(rqt);
+       code = cy_as_ll_request_response__get_code(rqt);
+
+       switch (cntxt) {
+       case CY_RQT_GENERAL_RQT_CONTEXT:
+               cy_as_hal_assert(dev_p->func_cbs_misc->count != 0);
+               cy_as_hal_assert(dev_p->func_cbs_misc->type == CYAS_FUNC_CB);
+               node = (cy_as_func_c_b_node *)dev_p->func_cbs_misc->head_p;
+               type = cy_as_funct_c_b_type_get_type(node->data_type);
+
+               switch (code) {
+               case CY_RQT_GET_FIRMWARE_VERSION:
+                       cy_as_hal_assert(node->data != 0);
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_GETFIRMWAREVERSION);
+                       ret = my_handle_response_get_firmware_version(dev_p,
+                               rqt, resp,
+                               (cy_as_get_firmware_version_data *)node->data);
+                       break;
+               case CY_RQT_READ_MCU_REGISTER:
+                       cy_as_hal_assert(node->data != 0);
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_READMCUREGISTER);
+                       ret = my_handle_response_read_m_c_u_register(dev_p, rqt,
+                               resp, (uint8_t *)node->data);
+                       break;
+               case CY_RQT_GET_GPIO_STATE:
+                       cy_as_hal_assert(node->data != 0);
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_GETGPIOVALUE);
+                       ret = my_handle_response_get_gpio_value(dev_p, rqt,
+                               resp, (uint8_t *)node->data);
+                       break;
+               case CY_RQT_SET_SD_CLOCK_FREQ:
+                       cy_as_hal_assert(type == CY_FUNCT_CB_MISC_SETSDFREQ);
+                       ret = my_handle_response_no_data(dev_p, rqt, resp);
+                       break;
+               case CY_RQT_CONTROL_ANTIOCH_HEARTBEAT:
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_HEARTBEATCONTROL);
+                       ret = my_handle_response_no_data(dev_p, rqt, resp);
+                       break;
+               case CY_RQT_WRITE_MCU_REGISTER:
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_WRITEMCUREGISTER);
+                       ret = my_handle_response_no_data(dev_p, rqt, resp);
+                       break;
+               case CY_RQT_STORAGE_MEDIA_CHANGED:
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_STORAGECHANGED);
+                       ret = my_handle_response_no_data(dev_p, rqt, resp);
+                       break;
+               case CY_RQT_SET_GPIO_STATE:
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_SETGPIOVALUE);
+                       ret = my_handle_response_no_data(dev_p, rqt, resp);
+                       break;
+               case CY_RQT_SET_TRACE_LEVEL:
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_SETTRACELEVEL);
+                       ret = my_handle_response_no_data(dev_p, rqt, resp);
+                       if (ret == CY_AS_ERROR_INVALID_RESPONSE)
+                               ret = CY_AS_ERROR_NOT_SUPPORTED;
+                       break;
+               case CY_RQT_PREPARE_FOR_STANDBY:
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_ENTERSTANDBY);
+                       ret = my_handle_response_enter_standby(dev_p, rqt, resp,
+                               (cy_bool)node->data);
+                       break;
+               case CY_RQT_ENTER_SUSPEND_MODE:
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_ENTERSUSPEND);
+                       ret = my_handle_response_no_data(dev_p, rqt, resp);
+                       if (ret == CY_AS_ERROR_SUCCESS)
+                               cy_as_device_set_suspend_mode(dev_p);
+
+                       break;
+               case CY_RQT_RESERVE_LNA_BOOT_AREA:
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_RESERVELNABOOTAREA);
+                       ret = my_handle_response_no_data(dev_p, rqt, resp);
+                       break;
+               case CY_RQT_SDPOLARITY:
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_SETSDPOLARITY);
+                       ret = my_handle_response_no_data(dev_p, rqt, resp);
+                       break;
+               default:
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       cy_as_hal_assert(cy_false);
+                       break;
+               }
+               break;
+
+       case CY_RQT_RESOURCE_RQT_CONTEXT:
+               cy_as_hal_assert(dev_p->func_cbs_res->count != 0);
+               cy_as_hal_assert(dev_p->func_cbs_res->type == CYAS_FUNC_CB);
+               node = (cy_as_func_c_b_node *)dev_p->func_cbs_res->head_p;
+               type = cy_as_funct_c_b_type_get_type(node->data_type);
+
+               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 */
+                       cy_as_hal_assert(type ==
+                               CY_FUNCT_CB_MISC_ACQUIRERESOURCE);
+                       ret = my_handle_response_acquire_resource(dev_p, rqt,
+                               resp, (cy_as_resource_type *)node->data);
+                       break;
+               default:
+                       ret = CY_AS_ERROR_INVALID_RESPONSE;
+                       cy_as_hal_assert(cy_false);
+                       break;
+               }
+               break;
+
+       default:
+               ret = CY_AS_ERROR_INVALID_RESPONSE;
+               cy_as_hal_assert(cy_false);
+               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((cy_as_device_handle)dev_p, stat, node->client_data,
+               node->data_type, node->data);
+       if (cntxt == CY_RQT_GENERAL_RQT_CONTEXT)
+               cy_as_remove_c_b_node(dev_p->func_cbs_misc);
+       else
+               cy_as_remove_c_b_node(dev_p->func_cbs_res);
+
+}
+
+
+
+/*[]*/