linux/drivers/staging/westbridge/astoria/api/src/cyasmisc.c
<<
>>
Prefs
   1/* Cypress West Bridge API source file (cyasmisc.c)
   2## ===========================
   3## Copyright (C) 2010  Cypress Semiconductor
   4##
   5## This program is free software; you can redistribute it and/or
   6## modify it under the terms of the GNU General Public License
   7## as published by the Free Software Foundation; either version 2
   8## of the License, or (at your option) any later version.
   9##
  10## This program is distributed in the hope that it will be useful,
  11## but WITHOUT ANY WARRANTY; without even the implied warranty of
  12## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13## GNU General Public License for more details.
  14##
  15## You should have received a copy of the GNU General Public License
  16## along with this program; if not, write to the Free Software
  17## Foundation, Inc., 51 Franklin Street, Fifth Floor
  18## Boston, MA  02110-1301, USA.
  19## ===========================
  20*/
  21
  22#include "../../include/linux/westbridge/cyashal.h"
  23#include "../../include/linux/westbridge/cyasmisc.h"
  24#include "../../include/linux/westbridge/cyasdma.h"
  25#include "../../include/linux/westbridge/cyasintr.h"
  26#include "../../include/linux/westbridge/cyaserr.h"
  27#include "../../include/linux/westbridge/cyasregs.h"
  28#include "../../include/linux/westbridge/cyaslowlevel.h"
  29#include "../../include/linux/westbridge/cyasprotocol.h"
  30
  31/*
  32* The device list, the only global in the API
  33*/
  34static cy_as_device *g_device_list;
  35
  36/*
  37 * The current debug level
  38 */
  39static uint8_t debug_level;
  40
  41/*
  42 * This function sets the debug level for the API
  43 *
  44 */
  45void
  46cy_as_misc_set_log_level(uint8_t level)
  47{
  48        debug_level = level;
  49}
  50
  51#ifdef CY_AS_LOG_SUPPORT
  52
  53/*
  54 * This function is a low level logger for the API.
  55 */
  56void
  57cy_as_log_debug_message(int level, const char *str)
  58{
  59        if (level <= debug_level)
  60                cy_as_hal_print_message("log %d: %s\n", level, str);
  61}
  62
  63#endif
  64
  65#define cy_as_check_device_ready(dev_p)                 \
  66{\
  67        if (!(dev_p) || ((dev_p)->sig !=                        \
  68                CY_AS_DEVICE_HANDLE_SIGNATURE))                 \
  69                return CY_AS_ERROR_INVALID_HANDLE;              \
  70\
  71        if (!cy_as_device_is_configured(dev_p))         \
  72                return CY_AS_ERROR_NOT_CONFIGURED;              \
  73\
  74        if (!cy_as_device_is_firmware_loaded(dev_p))\
  75                return CY_AS_ERROR_NO_FIRMWARE;         \
  76}
  77
  78/* Find an West Bridge device based on a TAG */
  79cy_as_device *
  80cy_as_device_find_from_tag(cy_as_hal_device_tag tag)
  81{
  82        cy_as_device *dev_p;
  83
  84        for (dev_p = g_device_list; dev_p != 0; dev_p = dev_p->next_p) {
  85                if (dev_p->tag == tag)
  86                        return dev_p;
  87        }
  88
  89        return 0;
  90}
  91
  92/* Map a pre-V1.2 media type to the V1.2+ bus number */
  93static void
  94cy_as_bus_from_media_type(cy_as_media_type type,
  95                                                cy_as_bus_number_t *bus)
  96{
  97        if (type == cy_as_media_nand)
  98                *bus = 0;
  99        else
 100                *bus = 1;
 101}
 102
 103static cy_as_return_status_t
 104my_handle_response_no_data(cy_as_device *dev_p,
 105                        cy_as_ll_request_response *req_p,
 106                        cy_as_ll_request_response *reply_p)
 107{
 108        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 109
 110        if (cy_as_ll_request_response__get_code(reply_p) !=
 111                CY_RESP_SUCCESS_FAILURE)
 112                ret = CY_AS_ERROR_INVALID_RESPONSE;
 113        else
 114                ret = cy_as_ll_request_response__get_word(reply_p, 0);
 115
 116        cy_as_ll_destroy_request(dev_p, req_p);
 117        cy_as_ll_destroy_response(dev_p, reply_p);
 118
 119        return ret;
 120}
 121
 122/*
 123* Create a new West Bridge device
 124*/
 125cy_as_return_status_t
 126cy_as_misc_create_device(cy_as_device_handle *handle_p,
 127        cy_as_hal_device_tag tag)
 128{
 129        cy_as_device *dev_p;
 130        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 131
 132        cy_as_log_debug_message(6, "cy_as_misc_create_device called");
 133
 134        dev_p = (cy_as_device *)cy_as_hal_alloc(sizeof(cy_as_device));
 135        if (dev_p == 0)
 136                return CY_AS_ERROR_OUT_OF_MEMORY;
 137        cy_as_hal_mem_set(dev_p, 0, sizeof(cy_as_device));
 138
 139        /*
 140         * dynamically allocating this buffer to ensure that it is
 141         * word aligned.
 142         */
 143        dev_p->usb_ep_data = (uint8_t *)cy_as_hal_alloc(64 * sizeof(uint8_t));
 144        if (dev_p->usb_ep_data == 0) {
 145                cy_as_hal_free(dev_p);
 146                return CY_AS_ERROR_OUT_OF_MEMORY;
 147        }
 148
 149        dev_p->sig = CY_AS_DEVICE_HANDLE_SIGNATURE;
 150        dev_p->tag = tag;
 151        dev_p->usb_max_tx_size = 0x40;
 152
 153        dev_p->storage_write_endpoint = CY_AS_P2S_WRITE_ENDPOINT;
 154        dev_p->storage_read_endpoint = CY_AS_P2S_READ_ENDPOINT;
 155
 156        dev_p->func_cbs_misc = cy_as_create_c_b_queue(CYAS_FUNC_CB);
 157        if (dev_p->func_cbs_misc == 0)
 158                goto destroy;
 159
 160        dev_p->func_cbs_res = cy_as_create_c_b_queue(CYAS_FUNC_CB);
 161        if (dev_p->func_cbs_res == 0)
 162                goto destroy;
 163
 164        dev_p->func_cbs_stor = cy_as_create_c_b_queue(CYAS_FUNC_CB);
 165        if (dev_p->func_cbs_stor == 0)
 166                goto destroy;
 167
 168        dev_p->func_cbs_usb = cy_as_create_c_b_queue(CYAS_FUNC_CB);
 169        if (dev_p->func_cbs_usb == 0)
 170                goto destroy;
 171
 172        dev_p->func_cbs_mtp = cy_as_create_c_b_queue(CYAS_FUNC_CB);
 173        if (dev_p->func_cbs_mtp == 0)
 174                        goto destroy;
 175
 176        /*
 177         * allocate memory for the DMA module here. it is then marked idle, and
 178         * will be activated when cy_as_misc_configure_device is called.
 179         */
 180        ret = cy_as_dma_start(dev_p);
 181        if (ret != CY_AS_ERROR_SUCCESS)
 182                goto destroy;
 183
 184        cy_as_device_set_dma_stopped(dev_p);
 185
 186        /*
 187         * allocate memory for the low level module here. this module is also
 188         * activated only when cy_as_misc_configure_device is called.
 189         */
 190        ret = cy_as_ll_start(dev_p);
 191        if (ret != CY_AS_ERROR_SUCCESS)
 192                goto destroy;
 193
 194        cy_as_device_set_low_level_stopped(dev_p);
 195
 196        dev_p->next_p = g_device_list;
 197        g_device_list = dev_p;
 198
 199        *handle_p = dev_p;
 200        cy_as_hal_init_dev_registers(tag, cy_false);
 201        return CY_AS_ERROR_SUCCESS;
 202
 203destroy:
 204        /* Free any queues that were successfully allocated. */
 205        if (dev_p->func_cbs_misc)
 206                cy_as_destroy_c_b_queue(dev_p->func_cbs_misc);
 207
 208        if (dev_p->func_cbs_res)
 209                cy_as_destroy_c_b_queue(dev_p->func_cbs_res);
 210
 211        if (dev_p->func_cbs_stor)
 212                cy_as_destroy_c_b_queue(dev_p->func_cbs_stor);
 213
 214        if (dev_p->func_cbs_usb)
 215                cy_as_destroy_c_b_queue(dev_p->func_cbs_usb);
 216
 217        if (dev_p->func_cbs_mtp)
 218                cy_as_destroy_c_b_queue(dev_p->func_cbs_mtp);
 219
 220        cy_as_hal_free(dev_p->usb_ep_data);
 221        cy_as_hal_free(dev_p);
 222
 223        if (ret != CY_AS_ERROR_SUCCESS)
 224                return ret;
 225        else
 226                return CY_AS_ERROR_OUT_OF_MEMORY;
 227}
 228
 229/*
 230* Destroy an existing West Bridge device
 231*/
 232cy_as_return_status_t
 233cy_as_misc_destroy_device(cy_as_device_handle handle)
 234{
 235        cy_as_return_status_t ret;
 236        cy_as_device *dev_p;
 237
 238        cy_as_log_debug_message(6, "cy_as_misc_destroy_device called");
 239
 240        dev_p = (cy_as_device *)handle;
 241        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 242                return CY_AS_ERROR_INVALID_HANDLE;
 243
 244        /*
 245        * if the USB stack is still running,
 246        * it must be stopped first
 247        */
 248        if (dev_p->usb_count > 0)
 249                return CY_AS_ERROR_STILL_RUNNING;
 250
 251        /*
 252        * if the STORAGE stack is still running,
 253        * it must be stopped first
 254        */
 255        if (dev_p->storage_count > 0)
 256                return CY_AS_ERROR_STILL_RUNNING;
 257
 258        if (cy_as_device_is_intr_running(dev_p))
 259                ret = cy_as_intr_stop(dev_p);
 260
 261        ret = cy_as_ll_stop(dev_p);
 262        if (ret != CY_AS_ERROR_SUCCESS) {
 263                cy_as_intr_start(dev_p, dev_p->use_int_drq);
 264                return ret;
 265        }
 266
 267        ret = cy_as_dma_stop(dev_p);
 268        if (ret != CY_AS_ERROR_SUCCESS) {
 269                cy_as_intr_start(dev_p, dev_p->use_int_drq);
 270                return ret;
 271        }
 272
 273        /* Reset the West Bridge device. */
 274        cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_RST_CTRL_REG,
 275                CY_AS_MEM_RST_CTRL_REG_HARD);
 276
 277        /*
 278        * remove the device from the device list
 279        */
 280        if (g_device_list == dev_p) {
 281                g_device_list = dev_p->next_p;
 282        } else {
 283                cy_as_device *tmp_p = g_device_list;
 284                while (tmp_p && tmp_p->next_p != dev_p)
 285                        tmp_p = tmp_p->next_p;
 286
 287                cy_as_hal_assert(tmp_p != 0);
 288                tmp_p->next_p = dev_p->next_p;
 289        }
 290
 291        /*
 292        * reset the signature so this will not be detected
 293        * as a valid handle
 294        */
 295        dev_p->sig = 0;
 296
 297        cy_as_destroy_c_b_queue(dev_p->func_cbs_misc);
 298        cy_as_destroy_c_b_queue(dev_p->func_cbs_res);
 299        cy_as_destroy_c_b_queue(dev_p->func_cbs_stor);
 300        cy_as_destroy_c_b_queue(dev_p->func_cbs_usb);
 301        cy_as_destroy_c_b_queue(dev_p->func_cbs_mtp);
 302
 303        /*
 304        * free the memory associated with the device
 305        */
 306        cy_as_hal_free(dev_p->usb_ep_data);
 307        cy_as_hal_free(dev_p);
 308
 309        return CY_AS_ERROR_SUCCESS;
 310}
 311
 312/*
 313* Determine the endian mode for the processor we are
 314* running on, then set the endian mode register
 315*/
 316static void
 317cy_as_setup_endian_mode(cy_as_device *dev_p)
 318{
 319        /*
 320        * In general, we always set west bridge intothe little
 321        * endian mode. this causes the data on bit 0 internally
 322        * to come out on data line 0 externally and it is generally
 323        * what we want regardless of the endian mode of the
 324        * processor.  this capability in west bridge should be
 325        * labeled as a "SWAP" capability and can be used to swap the
 326        * bytes of data in and out of west bridge.  this is
 327        * useful if there is DMA hardware that requires this for some
 328        * reason I cannot imagine at this time.  basically if the
 329        * wires are connected correctly, we should never need to
 330        * change the endian-ness of west bridge.
 331        */
 332        cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_ENDIAN,
 333                CY_AS_LITTLE_ENDIAN);
 334}
 335
 336/*
 337* Query the West Bridge device and determine if we are an standby mode
 338*/
 339cy_as_return_status_t
 340cy_as_misc_in_standby(cy_as_device_handle handle, cy_bool *standby)
 341{
 342        cy_as_device *dev_p;
 343
 344        cy_as_log_debug_message(6, "cy_as_misc_in_standby called");
 345
 346        dev_p = (cy_as_device *)handle;
 347        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 348                return CY_AS_ERROR_INVALID_HANDLE;
 349
 350        if (cy_as_device_is_pin_standby(dev_p) ||
 351                cy_as_device_is_register_standby(dev_p)) {
 352                *standby = cy_true;
 353        } else
 354                *standby = cy_false;
 355
 356        return CY_AS_ERROR_SUCCESS;
 357}
 358
 359static void
 360cy_as_misc_func_callback(cy_as_device *dev_p,
 361                                                uint8_t context,
 362                                                cy_as_ll_request_response *rqt,
 363                                                cy_as_ll_request_response *resp,
 364                                                cy_as_return_status_t ret);
 365
 366
 367static void
 368my_misc_callback(cy_as_device *dev_p, uint8_t context,
 369                cy_as_ll_request_response *req_p,
 370                cy_as_ll_request_response *resp_p,
 371                cy_as_return_status_t ret)
 372{
 373        (void)resp_p;
 374        (void)context;
 375        (void)ret;
 376
 377        switch (cy_as_ll_request_response__get_code(req_p)) {
 378        case CY_RQT_INITIALIZATION_COMPLETE:
 379                {
 380                        uint16_t v;
 381
 382                        cy_as_ll_send_status_response(dev_p,
 383                                CY_RQT_GENERAL_RQT_CONTEXT,
 384                                CY_AS_ERROR_SUCCESS, 0);
 385                        cy_as_device_set_firmware_loaded(dev_p);
 386
 387                        if (cy_as_device_is_waking(dev_p)) {
 388                                /*
 389                                 * this is a callback from a
 390                                 * cy_as_misc_leave_standby()
 391                                 * request. in this case we call
 392                                 * the standby callback and clear
 393                                 * the waking state.
 394                                 */
 395                                if (dev_p->misc_event_cb)
 396                                        dev_p->misc_event_cb(
 397                                         (cy_as_device_handle)dev_p,
 398                                         cy_as_event_misc_awake, 0);
 399                                cy_as_device_clear_waking(dev_p);
 400                        } else {
 401                                v = cy_as_ll_request_response__get_word
 402                                        (req_p, 3);
 403
 404                                /*
 405                                 * store the media supported on
 406                                 * each of the device buses.
 407                                 */
 408                                dev_p->media_supported[0] =
 409                                        (uint8_t)(v & 0xFF);
 410                                dev_p->media_supported[1] =
 411                                        (uint8_t)((v >> 8) & 0xFF);
 412
 413                                v = cy_as_ll_request_response__get_word
 414                                        (req_p, 4);
 415
 416                                dev_p->is_mtp_firmware  =
 417                                        (cy_bool)((v >> 8) & 0xFF);
 418
 419                                if (dev_p->misc_event_cb)
 420                                        dev_p->misc_event_cb(
 421                                         (cy_as_device_handle)dev_p,
 422                                         cy_as_event_misc_initialized, 0);
 423                        }
 424
 425                        v = cy_as_hal_read_register(dev_p->tag,
 426                                CY_AS_MEM_P0_VM_SET);
 427
 428                                if (v & CY_AS_MEM_P0_VM_SET_CFGMODE)
 429                                        cy_as_hal_print_message(
 430                                        "initialization message "
 431                                        "recieved, but config bit "
 432                                        "still set\n");
 433
 434                                v = cy_as_hal_read_register(dev_p->tag,
 435                                        CY_AS_MEM_RST_CTRL_REG);
 436                                if ((v & CY_AS_MEM_RST_RSTCMPT) == 0)
 437                                        cy_as_hal_print_message(
 438                                        "initialization message "
 439                                        "recieved, but reset complete "
 440                                        "bit still not set\n");
 441                        }
 442                        break;
 443
 444        case CY_RQT_OUT_OF_SUSPEND:
 445                cy_as_ll_send_status_response(dev_p, CY_RQT_GENERAL_RQT_CONTEXT,
 446                        CY_AS_ERROR_SUCCESS, 0);
 447                        cy_as_device_clear_suspend_mode(dev_p);
 448
 449                /*
 450                 * if the wakeup was caused by an async cy_as_misc_leave_suspend
 451                 * call, we have to call the corresponding callback.
 452                 */
 453                if (dev_p->func_cbs_misc->count > 0) {
 454                        cy_as_func_c_b_node *node = (cy_as_func_c_b_node *)
 455                                        dev_p->func_cbs_misc->head_p;
 456                        cy_as_hal_assert(node);
 457
 458                        if (cy_as_funct_c_b_type_get_type(node->data_type) ==
 459                                CY_FUNCT_CB_MISC_LEAVESUSPEND) {
 460                                cy_as_hal_assert(node->cb_p != 0);
 461
 462                                node->cb_p((cy_as_device_handle)dev_p,
 463                                        CY_AS_ERROR_SUCCESS, node->client_data,
 464                                        CY_FUNCT_CB_MISC_LEAVESUSPEND, 0);
 465                                cy_as_remove_c_b_node(dev_p->func_cbs_misc);
 466                        }
 467                }
 468
 469                if (dev_p->misc_event_cb)
 470                        dev_p->misc_event_cb((cy_as_device_handle)dev_p,
 471                                cy_as_event_misc_wakeup, 0);
 472                        break;
 473
 474        case CY_RQT_DEBUG_MESSAGE:
 475                if ((req_p->data[0] == 0) && (req_p->data[1] == 0) &&
 476                        (req_p->data[2] == 0)) {
 477                        if (dev_p->misc_event_cb)
 478                                dev_p->misc_event_cb((cy_as_device_handle)dev_p,
 479                                        cy_as_event_misc_heart_beat, 0);
 480                } else {
 481                        cy_as_hal_print_message(
 482                                "**** debug message: %02x "
 483                                "%02x %02x %02x %02x %02x\n",
 484                                req_p->data[0] & 0xff,
 485                                (req_p->data[0] >> 8) & 0xff,
 486                                req_p->data[1] & 0xff,
 487                                (req_p->data[1] >> 8) & 0xff,
 488                                req_p->data[2] & 0xff,
 489                                (req_p->data[2] >> 8) & 0xff);
 490                }
 491                break;
 492
 493        case CY_RQT_WB_DEVICE_MISMATCH:
 494                {
 495                        if (dev_p->misc_event_cb)
 496                                dev_p->misc_event_cb((cy_as_device_handle)dev_p,
 497                                        cy_as_event_misc_device_mismatch, 0);
 498                }
 499                break;
 500
 501        case CY_RQT_BOOTLOAD_NO_FIRMWARE:
 502                {
 503                        /* TODO Handle case when firmware is
 504                         * not found during bootloading. */
 505                        cy_as_hal_print_message("no firmware image found "
 506                        "during bootload. device not started\n");
 507                }
 508                break;
 509
 510        default:
 511                cy_as_hal_assert(0);
 512        }
 513}
 514
 515static cy_bool
 516is_valid_silicon_id(uint16_t v)
 517{
 518        cy_bool idok = cy_false;
 519
 520        /*
 521        * remove the revision number from the ID value
 522        */
 523        v = v & CY_AS_MEM_CM_WB_CFG_ID_HDID_MASK;
 524
 525        /*
 526        * if this is west bridge, then we are OK.
 527        */
 528        if (v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE ||
 529                v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE ||
 530                v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE)
 531                idok = cy_true;
 532
 533        return idok;
 534}
 535
 536/*
 537* Configure the West Bridge device hardware
 538*/
 539cy_as_return_status_t
 540cy_as_misc_configure_device(cy_as_device_handle handle,
 541        cy_as_device_config *config_p)
 542{
 543        cy_as_return_status_t ret;
 544        cy_bool standby;
 545        cy_as_device *dev_p;
 546        uint16_t v;
 547        uint16_t fw_present;
 548        cy_as_log_debug_message(6, "cy_as_misc_configure_device called");
 549
 550        dev_p = (cy_as_device *)handle;
 551        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 552                return CY_AS_ERROR_INVALID_HANDLE;
 553
 554        /* Setup big endian vs little endian */
 555        cy_as_setup_endian_mode(dev_p);
 556
 557        /* Now, confirm that we can talk to the West Bridge device */
 558        dev_p->silicon_id = cy_as_hal_read_register(dev_p->tag,
 559                CY_AS_MEM_CM_WB_CFG_ID);
 560        fw_present = cy_as_hal_read_register(dev_p->tag,
 561                CY_AS_MEM_RST_CTRL_REG);
 562        if (!(fw_present & CY_AS_MEM_RST_RSTCMPT)) {
 563                if (!is_valid_silicon_id(dev_p->silicon_id))
 564                        return CY_AS_ERROR_NO_ANTIOCH;
 565        }
 566        /* Check for standby mode */
 567        ret = cy_as_misc_in_standby(handle, &standby);
 568        if (ret != CY_AS_ERROR_SUCCESS)
 569                return ret;
 570        if (ret)
 571                return CY_AS_ERROR_IN_STANDBY;
 572
 573        /* Setup P-port interface mode (CRAM / SRAM). */
 574        if (cy_as_device_is_astoria_dev(dev_p)) {
 575                if (config_p->srammode)
 576                        v = CY_AS_MEM_P0_VM_SET_VMTYPE_SRAM;
 577                else
 578                        v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM;
 579        } else
 580                v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM;
 581
 582        /* Setup synchronous versus asynchronous mode */
 583        if (config_p->sync)
 584                v |= CY_AS_MEM_P0_VM_SET_IFMODE;
 585        if (config_p->dackmode == cy_as_device_dack_ack)
 586                v |= CY_AS_MEM_P0_VM_SET_DACKEOB;
 587        if (config_p->drqpol)
 588                v |= CY_AS_MEM_P0_VM_SET_DRQPOL;
 589        if (config_p->dackpol)
 590                v |= CY_AS_MEM_P0_VM_SET_DACKPOL;
 591        cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_VM_SET, v);
 592
 593        if (config_p->crystal)
 594                cy_as_device_set_crystal(dev_p);
 595        else
 596                cy_as_device_set_external_clock(dev_p);
 597
 598        /* Register a callback to handle MISC requests from the firmware */
 599        cy_as_ll_register_request_callback(dev_p,
 600                CY_RQT_GENERAL_RQT_CONTEXT, my_misc_callback);
 601
 602        /* Now mark the DMA and low level modules as active. */
 603        cy_as_device_set_dma_running(dev_p);
 604        cy_as_device_set_low_level_running(dev_p);
 605
 606        /* Now, initialize the interrupt module */
 607        dev_p->use_int_drq = config_p->dmaintr;
 608        ret = cy_as_intr_start(dev_p, config_p->dmaintr);
 609        if (ret != CY_AS_ERROR_SUCCESS)
 610                return ret;
 611
 612        /* Mark the interface as initialized */
 613        cy_as_device_set_configured(dev_p);
 614
 615        return CY_AS_ERROR_SUCCESS;
 616}
 617
 618static void
 619my_dma_callback(cy_as_device *dev_p,
 620                          cy_as_end_point_number_t ep,
 621                          void *mem_p,
 622                          uint32_t                        size,
 623                          cy_as_return_status_t ret
 624                         )
 625{
 626        cy_as_dma_end_point *ep_p;
 627
 628        (void)size;
 629
 630        /* Get the endpoint pointer based on the endpoint number */
 631        ep_p = CY_AS_NUM_EP(dev_p, ep);
 632
 633        /* Check the queue to see if is drained */
 634        if (ep_p->queue_p == 0) {
 635                cy_as_func_c_b_node *node =
 636                        (cy_as_func_c_b_node *)dev_p->func_cbs_misc->head_p;
 637
 638                cy_as_hal_assert(node);
 639
 640                if (ret == CY_AS_ERROR_SUCCESS) {
 641                        /*
 642                         * disable endpoint 2.  the storage module
 643                         * will enable this EP if necessary.
 644                         */
 645                        cy_as_dma_enable_end_point(dev_p,
 646                                CY_AS_FIRMWARE_ENDPOINT,
 647                                cy_false, cy_as_direction_in);
 648
 649                        /*
 650                         * clear the reset register.  this releases the
 651                         * antioch micro-controller from reset and begins
 652                         * running the code at address zero.
 653                         */
 654                        cy_as_hal_write_register(dev_p->tag,
 655                                CY_AS_MEM_RST_CTRL_REG, 0x00);
 656                }
 657
 658                /* Call the user Callback */
 659                node->cb_p((cy_as_device_handle)dev_p, ret, node->client_data,
 660                        node->data_type, node->data);
 661                cy_as_remove_c_b_node(dev_p->func_cbs_misc);
 662        } else {
 663                /* This is the header data that was allocated in the
 664                 * download firmware function, and can be safely freed
 665                 * here. */
 666                uint32_t state = cy_as_hal_disable_interrupts();
 667                cy_as_hal_c_b_free(mem_p);
 668                cy_as_hal_enable_interrupts(state);
 669        }
 670}
 671
 672cy_as_return_status_t
 673cy_as_misc_download_firmware(cy_as_device_handle handle,
 674                                                   const void *mem_p,
 675                                                   uint16_t size,
 676                                                   cy_as_function_callback cb,
 677                                                   uint32_t client)
 678{
 679        uint8_t *header;
 680        cy_as_return_status_t ret;
 681        cy_bool standby;
 682        cy_as_device *dev_p;
 683        cy_as_dma_callback dmacb = 0;
 684        uint32_t state;
 685
 686        cy_as_log_debug_message(6, "cy_as_misc_download_firmware called");
 687
 688        /* Make sure we have a valid device */
 689        dev_p = (cy_as_device *)handle;
 690        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 691                return CY_AS_ERROR_INVALID_HANDLE;
 692
 693        /*
 694        * if the device has not been initialized, we cannot download firmware
 695        * to the device.
 696        */
 697        if (!cy_as_device_is_configured(dev_p))
 698                return CY_AS_ERROR_NOT_CONFIGURED;
 699
 700        /*
 701        * make sure west bridge is not in standby
 702        */
 703        ret = cy_as_misc_in_standby(dev_p, &standby);
 704        if (ret != CY_AS_ERROR_SUCCESS)
 705                return ret;
 706
 707        if (standby)
 708                return CY_AS_ERROR_IN_STANDBY;
 709
 710        if (cy_as_device_is_in_suspend_mode(dev_p))
 711                return CY_AS_ERROR_IN_SUSPEND;
 712
 713        /*
 714        * make sure we are in configuration mode
 715        */
 716        if ((cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_VM_SET) &
 717                CY_AS_MEM_P0_VM_SET_CFGMODE) == 0)
 718                return CY_AS_ERROR_NOT_IN_CONFIG_MODE;
 719
 720        /* Maximum firmware size is 24k */
 721        if (size > CY_AS_MAXIMUM_FIRMWARE_SIZE)
 722                return CY_AS_ERROR_INVALID_SIZE;
 723
 724        /* Make sure the size is an even number of bytes as well */
 725        if (size & 0x01)
 726                return CY_AS_ERROR_ALIGNMENT_ERROR;
 727
 728        /*
 729         * write the two word header that gives the base address and
 730         * size of the firmware image to download
 731         */
 732        state = cy_as_hal_disable_interrupts();
 733        header = (uint8_t *)cy_as_hal_c_b_alloc(4);
 734        cy_as_hal_enable_interrupts(state);
 735        if (header == NULL)
 736                return CY_AS_ERROR_OUT_OF_MEMORY;
 737
 738        header[0] = 0x00;
 739        header[1] = 0x00;
 740        header[2] = (uint8_t)(size & 0xff);
 741        header[3] = (uint8_t)((size >> 8) & 0xff);
 742
 743        /* Enable the firmware endpoint */
 744        ret = cy_as_dma_enable_end_point(dev_p, CY_AS_FIRMWARE_ENDPOINT,
 745                cy_true, cy_as_direction_in);
 746        if (ret != CY_AS_ERROR_SUCCESS)
 747                return ret;
 748
 749        /*
 750        * setup DMA for 64 byte packets. this is the requirement for downloading
 751        * firmware to west bridge.
 752        */
 753        cy_as_dma_set_max_dma_size(dev_p, CY_AS_FIRMWARE_ENDPOINT, 64);
 754
 755        if (cb)
 756                dmacb = my_dma_callback;
 757
 758        ret = cy_as_dma_queue_request(dev_p, CY_AS_FIRMWARE_ENDPOINT, header,
 759                4, cy_false, cy_false, dmacb);
 760        if (ret != CY_AS_ERROR_SUCCESS)
 761                return ret;
 762
 763        /*
 764        * write the firmware image to the west bridge device
 765        */
 766        ret = cy_as_dma_queue_request(dev_p, CY_AS_FIRMWARE_ENDPOINT,
 767                (void *)mem_p, size, cy_false, cy_false, dmacb);
 768        if (ret != CY_AS_ERROR_SUCCESS)
 769                return ret;
 770
 771        if (cb) {
 772                cy_as_func_c_b_node *cbnode = cy_as_create_func_c_b_node_data(
 773                        cb, client, CY_FUNCT_CB_MISC_DOWNLOADFIRMWARE, 0);
 774
 775                if (cbnode == 0)
 776                        return CY_AS_ERROR_OUT_OF_MEMORY;
 777                else
 778                        cy_as_insert_c_b_node(dev_p->func_cbs_misc, cbnode);
 779
 780                ret = cy_as_dma_kick_start(dev_p, CY_AS_FIRMWARE_ENDPOINT);
 781                if (ret != CY_AS_ERROR_SUCCESS)
 782                        return ret;
 783        } else {
 784                ret = cy_as_dma_drain_queue(dev_p,
 785                        CY_AS_FIRMWARE_ENDPOINT, cy_true);
 786
 787                /* Free the header memory that was allocated earlier. */
 788                cy_as_hal_c_b_free(header);
 789
 790                if (ret != CY_AS_ERROR_SUCCESS)
 791                        return ret;
 792
 793                /*
 794                * disable EP 2. the storage module will
 795                * enable this EP if necessary.
 796                */
 797                cy_as_dma_enable_end_point(dev_p, CY_AS_FIRMWARE_ENDPOINT,
 798                        cy_false, cy_as_direction_in);
 799
 800                /*
 801                * clear the reset register.  this releases the west bridge
 802                * micro-controller from reset and begins running the code at
 803                * address zero.
 804                */
 805                cy_as_hal_write_register(dev_p->tag,
 806                        CY_AS_MEM_RST_CTRL_REG, 0x00);
 807        }
 808
 809        /*
 810        * the firmware is not marked as loaded until the firmware
 811        * initializes west bridge and a request is sent from west bridge
 812        * to the P port processor indicating that west bridge is ready.
 813        */
 814        return CY_AS_ERROR_SUCCESS;
 815}
 816
 817
 818static cy_as_return_status_t
 819my_handle_response_get_firmware_version(cy_as_device *dev_p,
 820                                cy_as_ll_request_response *req_p,
 821                                cy_as_ll_request_response *reply_p,
 822                                cy_as_get_firmware_version_data *data_p)
 823{
 824
 825        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 826        uint16_t val;
 827
 828        if (cy_as_ll_request_response__get_code(reply_p)
 829                != CY_RESP_FIRMWARE_VERSION) {
 830                ret = CY_AS_ERROR_INVALID_RESPONSE;
 831                goto destroy;
 832        }
 833
 834        data_p->major = cy_as_ll_request_response__get_word(reply_p, 0);
 835        data_p->minor = cy_as_ll_request_response__get_word(reply_p, 1);
 836        data_p->build = cy_as_ll_request_response__get_word(reply_p, 2);
 837        val     = cy_as_ll_request_response__get_word(reply_p, 3);
 838        data_p->media_type   = (uint8_t)(((val >> 8) & 0xFF) | (val & 0xFF));
 839        val     = cy_as_ll_request_response__get_word(reply_p, 4);
 840        data_p->is_debug_mode = (cy_bool)(val & 0xFF);
 841
 842destroy:
 843        cy_as_ll_destroy_request(dev_p, req_p);
 844        cy_as_ll_destroy_response(dev_p, reply_p);
 845
 846        return ret;
 847}
 848
 849cy_as_return_status_t
 850cy_as_misc_get_firmware_version(cy_as_device_handle handle,
 851                                cy_as_get_firmware_version_data *data,
 852                                cy_as_function_callback cb,
 853                                uint32_t client)
 854{
 855        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 856        cy_bool standby;
 857        cy_as_ll_request_response *req_p, *reply_p;
 858
 859        cy_as_device *dev_p;
 860
 861        (void)client;
 862
 863        cy_as_log_debug_message(6, "cy_as_misc_get_firmware_version called");
 864
 865        /* Make sure we have a valid device */
 866        dev_p = (cy_as_device *)handle;
 867        cy_as_check_device_ready(dev_p);
 868
 869        /*
 870        * make sure antioch is not in standby
 871        */
 872        ret = cy_as_misc_in_standby(dev_p, &standby);
 873        if (ret != CY_AS_ERROR_SUCCESS)
 874                return ret;
 875        if (standby)
 876                return CY_AS_ERROR_IN_STANDBY;
 877
 878        /* Make sure the Antioch is not in suspend mode. */
 879        if (cy_as_device_is_in_suspend_mode(dev_p))
 880                return CY_AS_ERROR_IN_SUSPEND;
 881
 882        /* Create the request to send to the West Bridge device */
 883        req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_FIRMWARE_VERSION,
 884                CY_RQT_GENERAL_RQT_CONTEXT, 0);
 885        if (req_p == 0)
 886                return CY_AS_ERROR_OUT_OF_MEMORY;
 887
 888        /*
 889         * Reserve space for the reply, the reply data
 890         * will not exceed three words
 891         */
 892        reply_p = cy_as_ll_create_response(dev_p, 5);
 893        if (reply_p == 0) {
 894                cy_as_ll_destroy_request(dev_p, req_p);
 895                return CY_AS_ERROR_OUT_OF_MEMORY;
 896        }
 897
 898        if (cb == 0) {
 899                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
 900                if (ret != CY_AS_ERROR_SUCCESS)
 901                        goto destroy;
 902
 903                /* Request and response are freed in
 904                 * MyHandleResponseGetFirmwareVersion. */
 905                ret = my_handle_response_get_firmware_version(dev_p,
 906                        req_p, reply_p, data);
 907                return ret;
 908        } else {
 909
 910                ret = cy_as_misc_send_request(dev_p, cb, client,
 911                        CY_FUNCT_CB_MISC_GETFIRMWAREVERSION, data,
 912                        dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
 913                        req_p, reply_p, cy_as_misc_func_callback);
 914
 915                if (ret != CY_AS_ERROR_SUCCESS)
 916                                goto destroy;
 917
 918                /* The request and response are freed
 919                 * as part of the MiscFuncCallback */
 920                return ret;
 921        }
 922
 923destroy:
 924        cy_as_ll_destroy_request(dev_p, req_p);
 925        cy_as_ll_destroy_response(dev_p, reply_p);
 926
 927        return ret;
 928}
 929static cy_as_return_status_t
 930my_handle_response_read_m_c_u_register(cy_as_device *dev_p,
 931                                cy_as_ll_request_response *req_p,
 932                                cy_as_ll_request_response *reply_p,
 933                                uint8_t *data_p)
 934{
 935
 936        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 937
 938        if (cy_as_ll_request_response__get_code(reply_p)
 939                != CY_RESP_MCU_REGISTER_DATA) {
 940                ret = CY_AS_ERROR_INVALID_RESPONSE;
 941                goto destroy;
 942        }
 943
 944        *data_p = (uint8_t)
 945                (cy_as_ll_request_response__get_word(reply_p, 0));
 946
 947destroy:
 948        cy_as_ll_destroy_request(dev_p, req_p);
 949        cy_as_ll_destroy_response(dev_p, reply_p);
 950
 951        return ret;
 952}
 953
 954static cy_as_return_status_t
 955my_handle_response_get_gpio_value(cy_as_device *dev_p,
 956                cy_as_ll_request_response *req_p,
 957                cy_as_ll_request_response *reply_p,
 958                uint8_t *data_p)
 959{
 960
 961        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 962
 963        if (cy_as_ll_request_response__get_code(reply_p)
 964                != CY_RESP_GPIO_STATE) {
 965                ret = CY_AS_ERROR_INVALID_RESPONSE;
 966        } else
 967                *data_p = (uint8_t)
 968                        (cy_as_ll_request_response__get_word(reply_p, 0));
 969
 970        cy_as_ll_destroy_request(dev_p, req_p);
 971        cy_as_ll_destroy_response(dev_p, reply_p);
 972
 973        return ret;
 974}
 975
 976
 977cy_as_return_status_t cy_as_misc_set_sd_power_polarity(
 978        cy_as_device_handle handle,
 979        cy_as_misc_signal_polarity polarity,
 980        cy_as_function_callback cb,
 981        uint32_t client)
 982{
 983        cy_as_ll_request_response *req_p, *reply_p;
 984        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 985        cy_as_device *dev_p = (cy_as_device *)handle;
 986
 987        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 988                return CY_AS_ERROR_INVALID_HANDLE;
 989
 990        if (!cy_as_device_is_configured(dev_p))
 991                return CY_AS_ERROR_NOT_CONFIGURED;
 992
 993        if (!cy_as_device_is_firmware_loaded(dev_p))
 994                return CY_AS_ERROR_NO_FIRMWARE;
 995
 996        if (cy_as_device_is_in_suspend_mode(dev_p))
 997                return CY_AS_ERROR_IN_SUSPEND;
 998
 999        req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDPOLARITY,
1000                CY_RQT_GENERAL_RQT_CONTEXT, 1);
1001        if (req_p == 0)
1002                return CY_AS_ERROR_OUT_OF_MEMORY;
1003
1004        cy_as_ll_request_response__set_word(req_p, 0,
1005                (uint16_t)polarity);
1006
1007        /*
1008         * Reserve space for the reply, the reply data will
1009         * not exceed one word
1010         */
1011        reply_p = cy_as_ll_create_response(dev_p, 1);
1012        if (reply_p == 0) {
1013                cy_as_ll_destroy_request(dev_p, req_p);
1014                return CY_AS_ERROR_OUT_OF_MEMORY;
1015        }
1016
1017        if (cb == 0) {
1018                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1019                if (ret != CY_AS_ERROR_SUCCESS)
1020                        goto destroy;
1021
1022                return (my_handle_response_no_data(dev_p, req_p, reply_p));
1023        } else {
1024                ret = cy_as_misc_send_request(dev_p, cb, client,
1025                        CY_FUNCT_CB_MISC_SETSDPOLARITY, 0, dev_p->func_cbs_misc,
1026                        CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
1027                        cy_as_misc_func_callback);
1028
1029                if (ret != CY_AS_ERROR_SUCCESS)
1030                        goto destroy;
1031
1032                /* The request and response are freed
1033                 * as part of the FuncCallback */
1034                return ret;
1035        }
1036
1037destroy:
1038        cy_as_ll_destroy_request(dev_p, req_p);
1039        cy_as_ll_destroy_response(dev_p, reply_p);
1040        return ret;
1041}
1042
1043
1044cy_as_return_status_t
1045cy_as_misc_read_m_c_u_register(cy_as_device_handle handle,
1046                                                  uint16_t address,
1047                                                  uint8_t *value,
1048                                                  cy_as_function_callback cb,
1049                                                  uint32_t client)
1050{
1051        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1052        cy_as_ll_request_response *req_p, *reply_p;
1053
1054        cy_as_device *dev_p;
1055
1056        cy_as_log_debug_message(6, "cy_as_misc_read_m_c_u_register called");
1057
1058        dev_p = (cy_as_device *)handle;
1059        cy_as_check_device_ready(dev_p);
1060
1061        /* Check whether the firmware supports this command. */
1062        if (cy_as_device_is_nand_storage_supported(dev_p))
1063                return CY_AS_ERROR_NOT_SUPPORTED;
1064
1065        /* Make sure the Antioch is not in suspend mode. */
1066        if (cy_as_device_is_in_suspend_mode(dev_p))
1067                return CY_AS_ERROR_IN_SUSPEND;
1068
1069        /* Create the request to send to the West Bridge device */
1070        req_p = cy_as_ll_create_request(dev_p, CY_RQT_READ_MCU_REGISTER,
1071                CY_RQT_GENERAL_RQT_CONTEXT, 1);
1072        if (req_p == 0)
1073                return CY_AS_ERROR_OUT_OF_MEMORY;
1074
1075        cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)address);
1076
1077        /* Reserve space for the reply, the reply
1078         * data will not exceed one word */
1079        reply_p = cy_as_ll_create_response(dev_p, 1);
1080        if (reply_p == 0) {
1081                cy_as_ll_destroy_request(dev_p, req_p);
1082                return CY_AS_ERROR_OUT_OF_MEMORY;
1083        }
1084
1085        if (cb == 0) {
1086                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1087                if (ret != CY_AS_ERROR_SUCCESS)
1088                        goto destroy;
1089
1090                if (cy_as_ll_request_response__get_code(reply_p) !=
1091                        CY_RESP_MCU_REGISTER_DATA) {
1092                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1093                        goto destroy;
1094                }
1095
1096                *value = (uint8_t)(cy_as_ll_request_response__get_word
1097                        (reply_p, 0));
1098        } else {
1099
1100                ret = cy_as_misc_send_request(dev_p, cb, client,
1101                        CY_FUNCT_CB_MISC_READMCUREGISTER, value,
1102                        dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
1103                        req_p, reply_p, cy_as_misc_func_callback);
1104
1105                if (ret != CY_AS_ERROR_SUCCESS)
1106                                goto destroy;
1107
1108                /* The request and response are freed
1109                 * as part of the MiscFuncCallback */
1110                return ret;
1111        }
1112destroy:
1113        cy_as_ll_destroy_request(dev_p, req_p);
1114        cy_as_ll_destroy_response(dev_p, reply_p);
1115
1116        return ret;
1117}
1118
1119
1120cy_as_return_status_t
1121cy_as_misc_write_m_c_u_register(cy_as_device_handle handle,
1122                                                   uint16_t address,
1123                                                   uint8_t mask,
1124                                                   uint8_t value,
1125                                                   cy_as_function_callback cb,
1126                                                   uint32_t client)
1127{
1128        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1129        cy_as_ll_request_response *req_p, *reply_p;
1130        cy_as_device *dev_p;
1131
1132        cy_as_log_debug_message(6, "cy_as_misc_write_m_c_u_register called");
1133
1134        dev_p = (cy_as_device *)handle;
1135        cy_as_check_device_ready(dev_p);
1136
1137        /* Check whether the firmware supports this command. */
1138        if (cy_as_device_is_nand_storage_supported(dev_p))
1139                return CY_AS_ERROR_NOT_SUPPORTED;
1140
1141        /* Make sure the Antioch is not in suspend mode. */
1142        if (cy_as_device_is_in_suspend_mode(dev_p))
1143                return CY_AS_ERROR_IN_SUSPEND;
1144
1145        /* Create the request to send to the West Bridge device */
1146        req_p = cy_as_ll_create_request(dev_p, CY_RQT_WRITE_MCU_REGISTER,
1147                CY_RQT_GENERAL_RQT_CONTEXT, 2);
1148        if (req_p == 0)
1149                return CY_AS_ERROR_OUT_OF_MEMORY;
1150
1151        cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)address);
1152        cy_as_ll_request_response__set_word(req_p, 1,
1153                (uint16_t)((mask << 8) | value));
1154
1155        /*
1156         * Reserve space for the reply, the reply data
1157         * will not exceed one word
1158         */
1159        reply_p = cy_as_ll_create_response(dev_p, 1);
1160        if (reply_p == 0) {
1161                cy_as_ll_destroy_request(dev_p, req_p);
1162                return CY_AS_ERROR_OUT_OF_MEMORY;
1163        }
1164
1165        if (cb == 0) {
1166                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1167                if (ret != CY_AS_ERROR_SUCCESS)
1168                        goto destroy;
1169
1170                if (cy_as_ll_request_response__get_code(reply_p) !=
1171                        CY_RESP_SUCCESS_FAILURE) {
1172                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1173                        goto destroy;
1174                }
1175
1176                ret = cy_as_ll_request_response__get_word(reply_p, 0);
1177        } else {
1178                ret = cy_as_misc_send_request(dev_p, cb, client,
1179                        CY_FUNCT_CB_MISC_WRITEMCUREGISTER, 0,
1180                        dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
1181                        req_p, reply_p, cy_as_misc_func_callback);
1182
1183                if (ret != CY_AS_ERROR_SUCCESS)
1184                        goto destroy;
1185
1186                /*
1187                 * The request and response are freed as part of the
1188                 * MiscFuncCallback
1189                 */
1190                return ret;
1191        }
1192
1193destroy:
1194        cy_as_ll_destroy_request(dev_p, req_p);
1195        cy_as_ll_destroy_response(dev_p, reply_p);
1196
1197        return ret;
1198}
1199
1200cy_as_return_status_t
1201my_handle_response_reset(cy_as_device *dev_p,
1202                                          cy_as_ll_request_response *req_p,
1203                                          cy_as_ll_request_response *reply_p,
1204                                          cy_as_reset_type type)
1205{
1206        uint16_t   v;
1207
1208        (void)req_p;
1209        (void)reply_p;
1210
1211        /*
1212         * if the device is in suspend mode, it needs to be woken up
1213         * so that the write to the reset control register succeeds.
1214         * we need not however wait for the  wake up procedure to be
1215         * complete.
1216         */
1217        if (cy_as_device_is_in_suspend_mode(dev_p)) {
1218                v = cy_as_hal_read_register(dev_p->tag,
1219                        CY_AS_MEM_CM_WB_CFG_ID);
1220                cy_as_hal_sleep(1);
1221        }
1222
1223        if (type == cy_as_reset_hard) {
1224                cy_as_misc_cancel_ex_requests(dev_p);
1225                cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_RST_CTRL_REG,
1226                        CY_AS_MEM_RST_CTRL_REG_HARD);
1227                cy_as_device_set_unconfigured(dev_p);
1228                cy_as_device_set_firmware_not_loaded(dev_p);
1229                cy_as_device_set_dma_stopped(dev_p);
1230                cy_as_device_set_low_level_stopped(dev_p);
1231                cy_as_device_set_intr_stopped(dev_p);
1232                cy_as_device_clear_suspend_mode(dev_p);
1233                cy_as_usb_cleanup(dev_p);
1234                cy_as_storage_cleanup(dev_p);
1235
1236                /*
1237                 * wait for a small amount of time to
1238                 * allow reset to be complete.
1239                 */
1240                cy_as_hal_sleep(100);
1241        }
1242
1243        cy_as_device_clear_reset_pending(dev_p);
1244
1245        return CY_AS_ERROR_SUCCESS;
1246}
1247
1248cy_as_return_status_t
1249cy_as_misc_reset(cy_as_device_handle handle,
1250                                cy_as_reset_type type,
1251                                cy_bool flush,
1252                                cy_as_function_callback cb,
1253                                uint32_t client)
1254{
1255        cy_as_device *dev_p;
1256        cy_as_end_point_number_t i;
1257        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1258        (void)client;
1259        (void)cb;
1260
1261        cy_as_log_debug_message(6, "cy_as_misc_reset_e_x called");
1262
1263        /* Make sure the device is ready for the command. */
1264        dev_p = (cy_as_device *)handle;
1265        cy_as_check_device_ready(dev_p);
1266
1267        /*
1268         * soft reset is not supported until we close on the issues
1269         * in the firmware with what needs to happen.
1270         */
1271        if (type == cy_as_reset_soft)
1272                return CY_AS_ERROR_NOT_YET_SUPPORTED;
1273
1274        cy_as_device_set_reset_pending(dev_p);
1275
1276        if (flush) {
1277                /* Unable to DrainQueues in polling mode */
1278                if ((dev_p->storage_cb || dev_p->storage_cb_ms) &&
1279                        cy_as_hal_is_polling())
1280                        return CY_AS_ERROR_ASYNC_PENDING;
1281
1282                /*
1283                * shutdown the endpoints so no more traffic can be queued
1284                */
1285                for (i = 0; i < 15; i++)
1286                        cy_as_dma_enable_end_point(dev_p, i, cy_false,
1287                                cy_as_direction_dont_change);
1288
1289                /*
1290                 * if we are in normal mode, drain all traffic across all
1291                 * endpoints to be sure all traffic is flushed. if the
1292                 * device is suspended, data will not be coming in on any
1293                 * endpoint and all outstanding DMA operations can be
1294                 * cancelled.
1295                 */
1296                if (cy_as_device_is_in_suspend_mode(dev_p)) {
1297                        for (i = 0; i < 15; i++)
1298                                cy_as_dma_cancel(dev_p, i,
1299                                        CY_AS_ERROR_CANCELED);
1300                } else {
1301                        for (i = 0; i < 15; i++) {
1302                                if ((i == CY_AS_P2S_WRITE_ENDPOINT) ||
1303                                        (i == CY_AS_P2S_READ_ENDPOINT))
1304                                        cy_as_dma_drain_queue(dev_p, i,
1305                                                cy_false);
1306                                else
1307                                        cy_as_dma_drain_queue(dev_p, i,
1308                                                cy_true);
1309                        }
1310                }
1311        } else {
1312                /* No flush was requested, so cancel any outstanding DMAs
1313                 * so the user callbacks are called as needed
1314                 */
1315                if (cy_as_device_is_storage_async_pending(dev_p)) {
1316                        for (i = 0; i < 15; i++)
1317                                cy_as_dma_cancel(dev_p, i,
1318                                        CY_AS_ERROR_CANCELED);
1319                }
1320        }
1321
1322        ret = my_handle_response_reset(dev_p, 0, 0, type);
1323
1324        if (cb)
1325                /* Even though no mailbox communication was needed,
1326                 * issue the callback so the user does not need to
1327                 * special case their code. */
1328                cb((cy_as_device_handle)dev_p, ret, client,
1329                        CY_FUNCT_CB_MISC_RESET, 0);
1330
1331        /*
1332         * initialize any registers that may have been
1333         * changed when the device was reset.
1334         */
1335        cy_as_hal_init_dev_registers(dev_p->tag, cy_false);
1336
1337        return ret;
1338}
1339
1340static cy_as_return_status_t
1341get_unallocated_resource(cy_as_device *dev_p, cy_as_resource_type resource)
1342{
1343        uint8_t shift = 0;
1344        uint16_t v;
1345        cy_as_return_status_t ret = CY_AS_ERROR_NOT_ACQUIRED;
1346
1347        switch (resource) {
1348        case cy_as_bus_u_s_b:
1349                shift = 4;
1350                break;
1351        case cy_as_bus_1:
1352                shift = 0;
1353                break;
1354        case cy_as_bus_0:
1355                shift = 2;
1356                break;
1357        default:
1358                cy_as_hal_assert(cy_false);
1359                break;
1360        }
1361
1362        /* Get the semaphore value for this resource */
1363        v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE);
1364        v = (v >> shift) & 0x03;
1365
1366        if (v == 0x03) {
1367                ret = CY_AS_ERROR_RESOURCE_ALREADY_OWNED;
1368        } else if ((v & 0x01) == 0) {
1369                /* The resource is not owned by anyone, we can try to get it */
1370                cy_as_hal_write_register(dev_p->tag,
1371                        CY_AS_MEM_P0_RSE_MASK, (0x03 << shift));
1372                v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_MASK);
1373                cy_as_hal_write_register(dev_p->tag,
1374                        CY_AS_MEM_P0_RSE_ALLOCATE, (0x01 << shift));
1375                v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_MASK);
1376
1377                v = cy_as_hal_read_register(dev_p->tag,
1378                        CY_AS_MEM_P0_RSE_ALLOCATE);
1379                v = (v >> shift) & 0x03;
1380                if (v == 0x03)
1381                        ret = CY_AS_ERROR_SUCCESS;
1382        }
1383
1384        return ret;
1385}
1386
1387static cy_as_return_status_t
1388my_handle_response_acquire_resource(cy_as_device *dev_p,
1389                        cy_as_ll_request_response *req_p,
1390                        cy_as_ll_request_response *reply_p,
1391                        cy_as_resource_type *resource)
1392{
1393        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1394
1395        if (cy_as_ll_request_response__get_code(reply_p) !=
1396                CY_RESP_SUCCESS_FAILURE) {
1397                ret = CY_AS_ERROR_INVALID_RESPONSE;
1398                goto destroy;
1399        }
1400
1401        if (ret == CY_AS_ERROR_SUCCESS) {
1402                        ret = get_unallocated_resource(dev_p, *resource);
1403                        if (ret != CY_AS_ERROR_NOT_ACQUIRED)
1404                                ret = CY_AS_ERROR_SUCCESS;
1405        }
1406
1407destroy:
1408        cy_as_ll_destroy_request(dev_p, req_p);
1409        cy_as_ll_destroy_response(dev_p, reply_p);
1410
1411        return ret;
1412}
1413
1414cy_as_return_status_t
1415cy_as_misc_acquire_resource(cy_as_device_handle handle,
1416                        cy_as_resource_type *resource,
1417                        cy_bool force,
1418                        cy_as_function_callback cb,
1419                        uint32_t client)
1420{
1421        cy_as_ll_request_response *req_p, *reply_p;
1422        cy_as_return_status_t ret;
1423
1424        cy_as_device *dev_p;
1425
1426        (void)client;
1427
1428        cy_as_log_debug_message(6, "cy_as_misc_acquire_resource called");
1429
1430        if (*resource != cy_as_bus_u_s_b && *resource !=
1431                cy_as_bus_0 && *resource != cy_as_bus_1)
1432                        return CY_AS_ERROR_INVALID_RESOURCE;
1433
1434
1435        /* Make sure the device is ready to accept the command. */
1436        dev_p = (cy_as_device *)handle;
1437        cy_as_check_device_ready(dev_p);
1438
1439        if (cy_as_device_is_in_suspend_mode(dev_p))
1440                return CY_AS_ERROR_IN_SUSPEND;
1441
1442
1443        ret = get_unallocated_resource(dev_p, *resource);
1444
1445        /*
1446         * make sure that the callback is called if the resource is
1447         * successfully acquired at this point.
1448         */
1449        if ((ret == CY_AS_ERROR_SUCCESS) && (cb != 0))
1450                cb(handle, ret, client,
1451                        CY_FUNCT_CB_MISC_ACQUIRERESOURCE, resource);
1452
1453        if (ret != CY_AS_ERROR_NOT_ACQUIRED)
1454                return ret;
1455
1456        if (!force)
1457                return CY_AS_ERROR_NOT_ACQUIRED;
1458
1459        /* Create the request to acquire the resource */
1460        req_p = cy_as_ll_create_request(dev_p, CY_RQT_ACQUIRE_RESOURCE,
1461                CY_RQT_RESOURCE_RQT_CONTEXT, 1);
1462        if (req_p == 0)
1463                return CY_AS_ERROR_OUT_OF_MEMORY;
1464
1465        cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)(*resource));
1466
1467        reply_p = cy_as_ll_create_response(dev_p, 1);
1468        if (reply_p == 0) {
1469                cy_as_ll_destroy_request(dev_p, req_p);
1470                return CY_AS_ERROR_OUT_OF_MEMORY;
1471        }
1472
1473        if (cb == 0) {
1474                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1475                if (ret != CY_AS_ERROR_SUCCESS)
1476                        goto destroy;
1477
1478                if (cy_as_ll_request_response__get_code(reply_p) !=
1479                        CY_RESP_SUCCESS_FAILURE) {
1480                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1481                        goto destroy;
1482                }
1483
1484                ret = cy_as_ll_request_response__get_word(reply_p, 0);
1485        } else {
1486                        ret = cy_as_misc_send_request(dev_p, cb, client,
1487                                CY_FUNCT_CB_MISC_ACQUIRERESOURCE, resource,
1488                                dev_p->func_cbs_res, CY_AS_REQUEST_RESPONSE_EX,
1489                                req_p, reply_p, cy_as_misc_func_callback);
1490
1491                        if (ret != CY_AS_ERROR_SUCCESS)
1492                                        goto destroy;
1493
1494                        /* The request and response are freed
1495                         * as part of the MiscFuncCallback */
1496                        return ret;
1497        }
1498
1499destroy:
1500        cy_as_ll_destroy_request(dev_p, req_p);
1501        cy_as_ll_destroy_response(dev_p, reply_p);
1502
1503        if (ret == CY_AS_ERROR_SUCCESS) {
1504                ret = get_unallocated_resource(dev_p, *resource);
1505                if (ret != CY_AS_ERROR_NOT_ACQUIRED)
1506                        ret = CY_AS_ERROR_SUCCESS;
1507        }
1508
1509        return ret;
1510}
1511cy_as_return_status_t
1512cy_as_misc_release_resource(cy_as_device_handle handle,
1513        cy_as_resource_type resource)
1514{
1515        uint8_t shift = 0;
1516        uint16_t v;
1517
1518        cy_as_device *dev_p;
1519
1520        cy_as_log_debug_message(6, "cy_as_misc_release_resource called");
1521
1522        /* Make sure the device is ready for the command. */
1523        dev_p = (cy_as_device *)handle;
1524        cy_as_check_device_ready(dev_p);
1525
1526        if (cy_as_device_is_in_suspend_mode(dev_p))
1527                return CY_AS_ERROR_IN_SUSPEND;
1528
1529        if (resource != cy_as_bus_u_s_b && resource !=
1530                cy_as_bus_0 && resource != cy_as_bus_1)
1531                return CY_AS_ERROR_INVALID_RESOURCE;
1532
1533        switch (resource) {
1534        case cy_as_bus_u_s_b:
1535                shift = 4;
1536                break;
1537        case cy_as_bus_1:
1538                shift = 0;
1539                break;
1540        case cy_as_bus_0:
1541                shift = 2;
1542                break;
1543        default:
1544                cy_as_hal_assert(cy_false);
1545                break;
1546        }
1547
1548        /* Get the semaphore value for this resource */
1549        v = (cy_as_hal_read_register(dev_p->tag,
1550                CY_AS_MEM_P0_RSE_ALLOCATE) >> shift) & 0x03;
1551        if (v == 0 || v == 1 || v == 2)
1552                return CY_AS_ERROR_RESOURCE_NOT_OWNED;
1553
1554        cy_as_hal_write_register(dev_p->tag,
1555                CY_AS_MEM_P0_RSE_MASK, (0x03 << shift));
1556        cy_as_hal_write_register(dev_p->tag,
1557                CY_AS_MEM_P0_RSE_ALLOCATE, (0x02 << shift));
1558        cy_as_hal_write_register(dev_p->tag,
1559                CY_AS_MEM_P0_RSE_MASK, 0);
1560
1561        return CY_AS_ERROR_SUCCESS;
1562}
1563
1564cy_as_return_status_t
1565cy_as_misc_set_trace_level(cy_as_device_handle handle,
1566                                                uint8_t level,
1567                                                cy_as_bus_number_t bus,
1568                                                uint32_t device,
1569                                                uint32_t unit,
1570                                                cy_as_function_callback cb,
1571                                                uint32_t client)
1572{
1573        cy_as_ll_request_response *req_p, *reply_p;
1574        cy_as_return_status_t ret;
1575        cy_as_device *dev_p;
1576
1577        cy_as_log_debug_message(6, "cy_as_misc_set_trace_level called");
1578
1579        /* Make sure the device is ready for the command. */
1580        dev_p = (cy_as_device *)handle;
1581        cy_as_check_device_ready(dev_p);
1582
1583        if (cy_as_device_is_in_suspend_mode(dev_p))
1584                return CY_AS_ERROR_IN_SUSPEND;
1585
1586        if (bus < 0 || bus >= CY_AS_MAX_BUSES)
1587                return CY_AS_ERROR_NO_SUCH_BUS;
1588
1589        if (device >= CY_AS_MAX_STORAGE_DEVICES)
1590                return CY_AS_ERROR_NO_SUCH_DEVICE;
1591
1592        if (unit > 255)
1593                return CY_AS_ERROR_NO_SUCH_UNIT;
1594
1595        if (level >= CYAS_FW_TRACE_MAX_LEVEL)
1596                return CY_AS_ERROR_INVALID_TRACE_LEVEL;
1597
1598        /* Create the request to send to the West Bridge device */
1599        req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_TRACE_LEVEL,
1600                CY_RQT_GENERAL_RQT_CONTEXT, 2);
1601        if (req_p == 0)
1602                return CY_AS_ERROR_OUT_OF_MEMORY;
1603
1604        cy_as_ll_request_response__set_word(req_p, 0,
1605                (uint16_t)level);
1606        cy_as_ll_request_response__set_word(req_p, 1,
1607                (uint16_t)((bus << 12) | (device << 8) | (unit)));
1608
1609        /*
1610         * Reserve space for the reply, the reply data will not
1611         * exceed three words
1612         */
1613        reply_p = cy_as_ll_create_response(dev_p, 2);
1614        if (reply_p == 0) {
1615                cy_as_ll_destroy_request(dev_p, req_p);
1616                return CY_AS_ERROR_OUT_OF_MEMORY;
1617        }
1618
1619        if (cb == 0) {
1620                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1621                if (ret != CY_AS_ERROR_SUCCESS)
1622                        goto destroy;
1623
1624                if (cy_as_ll_request_response__get_code(reply_p) !=
1625                        CY_RESP_SUCCESS_FAILURE) {
1626                        ret = CY_AS_ERROR_NOT_SUPPORTED;
1627                        goto destroy;
1628                }
1629
1630                ret = cy_as_ll_request_response__get_word(reply_p, 0);
1631        } else {
1632
1633                ret = cy_as_misc_send_request(dev_p, cb, client,
1634                        CY_FUNCT_CB_MISC_SETTRACELEVEL, 0, dev_p->func_cbs_misc,
1635                        CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
1636                        cy_as_misc_func_callback);
1637
1638                if (ret != CY_AS_ERROR_SUCCESS)
1639                                goto destroy;
1640
1641                /* The request and response are freed as part of the
1642                 * MiscFuncCallback */
1643                return ret;
1644        }
1645
1646destroy:
1647        cy_as_ll_destroy_request(dev_p, req_p);
1648        cy_as_ll_destroy_response(dev_p, reply_p);
1649
1650        return ret;
1651}
1652
1653cy_as_return_status_t
1654cy_as_misc_heart_beat_control(cy_as_device_handle handle,
1655                                                   cy_bool enable,
1656                                                   cy_as_function_callback cb,
1657                                                   uint32_t client)
1658{
1659        cy_as_ll_request_response *req_p, *reply_p;
1660        cy_as_return_status_t ret;
1661        cy_as_device *dev_p;
1662
1663        cy_as_log_debug_message(6, "cy_as_misc_heart_beat_control called");
1664
1665        /* Make sure the device is ready for the command. */
1666        dev_p = (cy_as_device *)handle;
1667        cy_as_check_device_ready(dev_p);
1668
1669        if (cy_as_device_is_in_suspend_mode(dev_p))
1670                return CY_AS_ERROR_IN_SUSPEND;
1671
1672        /* Create the request to send to the West Bridge device */
1673        req_p = cy_as_ll_create_request(dev_p, CY_RQT_CONTROL_ANTIOCH_HEARTBEAT,
1674                CY_RQT_GENERAL_RQT_CONTEXT, 1);
1675        if (req_p == 0)
1676                return CY_AS_ERROR_OUT_OF_MEMORY;
1677
1678        cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)enable);
1679
1680        /* Reserve space for the reply, the reply
1681         * data will not exceed one word */
1682        reply_p = cy_as_ll_create_response(dev_p, 1);
1683        if (reply_p == 0) {
1684                cy_as_ll_destroy_request(dev_p, req_p);
1685                return CY_AS_ERROR_OUT_OF_MEMORY;
1686        }
1687
1688        if (cb == 0) {
1689                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1690                if (ret != CY_AS_ERROR_SUCCESS)
1691                        goto destroy;
1692
1693                if (cy_as_ll_request_response__get_code(reply_p) !=
1694                        CY_RESP_SUCCESS_FAILURE) {
1695                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1696                        goto destroy;
1697                }
1698
1699                ret = cy_as_ll_request_response__get_word(reply_p, 0);
1700        } else {
1701
1702                ret = cy_as_misc_send_request(dev_p, cb, client,
1703                        CY_FUNCT_CB_MISC_HEARTBEATCONTROL, 0,
1704                        dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
1705                        req_p, reply_p, cy_as_misc_func_callback);
1706
1707                if (ret != CY_AS_ERROR_SUCCESS)
1708                                goto destroy;
1709
1710                /* The request and response are freed as part of the
1711                 * MiscFuncCallback */
1712                return ret;
1713        }
1714
1715destroy:
1716        cy_as_ll_destroy_request(dev_p, req_p);
1717        cy_as_ll_destroy_response(dev_p, reply_p);
1718
1719        return ret;
1720}
1721
1722static cy_as_return_status_t
1723my_set_sd_clock_freq(
1724                cy_as_device              *dev_p,
1725                uint8_t                   card_type,
1726                uint8_t                   setting,
1727                cy_as_function_callback cb,
1728                uint32_t                         client)
1729{
1730        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1731        cy_as_ll_request_response *req_p, *reply_p;
1732
1733        if (cy_as_device_is_in_callback(dev_p) && (cb == 0))
1734                return CY_AS_ERROR_INVALID_IN_CALLBACK;
1735
1736        req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_SD_CLOCK_FREQ,
1737                CY_RQT_GENERAL_RQT_CONTEXT, 1);
1738        if (req_p == 0)
1739                return CY_AS_ERROR_OUT_OF_MEMORY;
1740
1741        cy_as_ll_request_response__set_word(req_p, 0,
1742                (uint16_t)((card_type << 8) | setting));
1743
1744        /* Reserve space for the reply, which will not exceed one word. */
1745        reply_p = cy_as_ll_create_response(dev_p, 1);
1746        if (reply_p == 0) {
1747                cy_as_ll_destroy_request(dev_p, req_p);
1748                return CY_AS_ERROR_OUT_OF_MEMORY;
1749        }
1750
1751        if (cb == 0) {
1752                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1753                if (ret != CY_AS_ERROR_SUCCESS)
1754                        goto destroy;
1755
1756                if (cy_as_ll_request_response__get_code(reply_p) !=
1757                        CY_RESP_SUCCESS_FAILURE) {
1758                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1759                        goto destroy;
1760                }
1761
1762                ret = cy_as_ll_request_response__get_word(reply_p, 0);
1763        } else {
1764                ret = cy_as_misc_send_request(dev_p, cb, client,
1765                        CY_FUNCT_CB_MISC_SETSDFREQ, 0, dev_p->func_cbs_misc,
1766                        CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
1767                        cy_as_misc_func_callback);
1768
1769                if (ret != CY_AS_ERROR_SUCCESS)
1770                                goto destroy;
1771
1772                /* The request and response are freed as part of the
1773                 * MiscFuncCallback */
1774                return ret;
1775        }
1776
1777destroy:
1778        cy_as_ll_destroy_request(dev_p, req_p);
1779        cy_as_ll_destroy_response(dev_p, reply_p);
1780
1781        return ret;
1782}
1783
1784cy_as_return_status_t
1785cy_as_misc_set_low_speed_sd_freq(
1786                cy_as_device_handle      handle,
1787                cy_as_low_speed_sd_freq   setting,
1788                cy_as_function_callback cb,
1789                uint32_t                         client)
1790{
1791        cy_as_device *dev_p;
1792
1793        cy_as_log_debug_message(6, "cy_as_misc_set_low_speed_sd_freq called");
1794
1795        /* Make sure the device is ready for the command. */
1796        dev_p = (cy_as_device *)handle;
1797        cy_as_check_device_ready(dev_p);
1798
1799        if (cy_as_device_is_in_suspend_mode(dev_p))
1800                return CY_AS_ERROR_IN_SUSPEND;
1801
1802        if ((setting != CY_AS_SD_DEFAULT_FREQ) &&
1803                (setting != CY_AS_SD_RATED_FREQ))
1804                return CY_AS_ERROR_INVALID_PARAMETER;
1805
1806        return my_set_sd_clock_freq(dev_p, 0, (uint8_t)setting, cb, client);
1807}
1808
1809cy_as_return_status_t
1810cy_as_misc_set_high_speed_sd_freq(
1811                cy_as_device_handle      handle,
1812                cy_as_high_speed_sd_freq  setting,
1813                cy_as_function_callback cb,
1814                uint32_t                         client)
1815{
1816        cy_as_device *dev_p;
1817
1818        cy_as_log_debug_message(6, "cy_as_misc_set_high_speed_sd_freq called");
1819
1820        /* Make sure the device is ready for the command. */
1821        dev_p = (cy_as_device *)handle;
1822        cy_as_check_device_ready(dev_p);
1823
1824        if (cy_as_device_is_in_suspend_mode(dev_p))
1825                return CY_AS_ERROR_IN_SUSPEND;
1826
1827        if ((setting != CY_AS_HS_SD_FREQ_24) &&
1828                (setting != CY_AS_HS_SD_FREQ_48))
1829                return CY_AS_ERROR_INVALID_PARAMETER;
1830
1831        return my_set_sd_clock_freq(dev_p, 1, (uint8_t)setting, cb, client);
1832}
1833
1834cy_as_return_status_t
1835cy_as_misc_get_gpio_value(cy_as_device_handle handle,
1836                cy_as_misc_gpio pin,
1837                uint8_t *value,
1838                cy_as_function_callback cb,
1839                uint32_t client)
1840{
1841        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1842        cy_as_ll_request_response *req_p, *reply_p;
1843        cy_as_device *dev_p;
1844        uint16_t v;
1845
1846        cy_as_log_debug_message(6, "cy_as_misc_get_gpio_value called");
1847
1848        /* Make sure the device is ready for the command. */
1849        dev_p = (cy_as_device *)handle;
1850        cy_as_check_device_ready(dev_p);
1851
1852        /* If the pin specified is UVALID, there is no need
1853         * for firmware to be loaded. */
1854        if (pin == cy_as_misc_gpio_U_valid) {
1855                v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PMU_UPDATE);
1856                *value = (uint8_t)(v & CY_AS_MEM_PMU_UPDATE_UVALID);
1857
1858                if (cb != 0)
1859                        cb(dev_p, ret, client,
1860                                CY_FUNCT_CB_MISC_GETGPIOVALUE, value);
1861
1862                return ret;
1863        }
1864
1865        /* Check whether the firmware supports this command. */
1866        if (cy_as_device_is_nand_storage_supported(dev_p))
1867                return CY_AS_ERROR_NOT_SUPPORTED;
1868
1869        if (cy_as_device_is_in_suspend_mode(dev_p))
1870                return CY_AS_ERROR_IN_SUSPEND;
1871
1872        /* Make sure the pin selected is valid */
1873        if ((pin != cy_as_misc_gpio_1) && (pin != cy_as_misc_gpio_0))
1874                return CY_AS_ERROR_INVALID_PARAMETER;
1875
1876        req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_GPIO_STATE,
1877                CY_RQT_GENERAL_RQT_CONTEXT, 1);
1878        if (req_p == 0)
1879                return CY_AS_ERROR_OUT_OF_MEMORY;
1880
1881        cy_as_ll_request_response__set_word(req_p, 0, ((uint8_t)pin << 8));
1882
1883        /* Reserve space for the reply, which will not exceed one word. */
1884        reply_p = cy_as_ll_create_response(dev_p, 1);
1885        if (reply_p == 0) {
1886                cy_as_ll_destroy_request(dev_p, req_p);
1887                return CY_AS_ERROR_OUT_OF_MEMORY;
1888        }
1889
1890        if (cb == 0) {
1891                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1892                if (ret != CY_AS_ERROR_SUCCESS)
1893                        goto destroy;
1894
1895                if (cy_as_ll_request_response__get_code(reply_p) !=
1896                        CY_RESP_GPIO_STATE) {
1897                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1898                        goto destroy;
1899                }
1900
1901                *value = (uint8_t)
1902                        cy_as_ll_request_response__get_word(reply_p, 0);
1903        } else {
1904
1905                ret = cy_as_misc_send_request(dev_p, cb, client,
1906                        CY_FUNCT_CB_MISC_GETGPIOVALUE, value,
1907                        dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
1908                        req_p, reply_p, cy_as_misc_func_callback);
1909
1910                if (ret != CY_AS_ERROR_SUCCESS)
1911                                goto destroy;
1912
1913                /* The request and response are freed as part of the
1914                 * MiscFuncCallback */
1915                return ret;
1916        }
1917
1918destroy:
1919        cy_as_ll_destroy_request(dev_p, req_p);
1920        cy_as_ll_destroy_response(dev_p, reply_p);
1921
1922        return ret;
1923}
1924
1925
1926cy_as_return_status_t
1927cy_as_misc_set_gpio_value(cy_as_device_handle handle,
1928                cy_as_misc_gpio pin,
1929                uint8_t value,
1930                cy_as_function_callback cb,
1931                uint32_t client)
1932{
1933        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1934        cy_as_ll_request_response *req_p, *reply_p;
1935        cy_as_device *dev_p;
1936        uint16_t v;
1937
1938        cy_as_log_debug_message(6, "cy_as_misc_set_gpio_value called");
1939
1940        /* Make sure the device is ready for the command. */
1941        dev_p = (cy_as_device *)handle;
1942        cy_as_check_device_ready(dev_p);
1943
1944        /* If the pin specified is UVALID, there is
1945         * no need for firmware to be loaded. */
1946        if (pin == cy_as_misc_gpio_U_valid) {
1947                v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PMU_UPDATE);
1948                if (value)
1949                        cy_as_hal_write_register(dev_p->tag,
1950                                CY_AS_MEM_PMU_UPDATE,
1951                                (v | CY_AS_MEM_PMU_UPDATE_UVALID));
1952                else
1953                        cy_as_hal_write_register(dev_p->tag,
1954                                CY_AS_MEM_PMU_UPDATE,
1955                                (v & ~CY_AS_MEM_PMU_UPDATE_UVALID));
1956
1957                if (cb != 0)
1958                        cb(dev_p, ret, client,
1959                                CY_FUNCT_CB_MISC_SETGPIOVALUE, 0);
1960                return ret;
1961        }
1962
1963        /* Check whether the firmware supports this command. */
1964        if (cy_as_device_is_nand_storage_supported(dev_p))
1965                return CY_AS_ERROR_NOT_SUPPORTED;
1966
1967        if (cy_as_device_is_in_suspend_mode(dev_p))
1968                return CY_AS_ERROR_IN_SUSPEND;
1969
1970        /* Make sure the pin selected is valid */
1971        if ((pin < cy_as_misc_gpio_0) || (pin > cy_as_misc_gpio_U_valid))
1972                return CY_AS_ERROR_INVALID_PARAMETER;
1973
1974        /* Create and initialize the low level request to the firmware. */
1975        req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_GPIO_STATE,
1976                CY_RQT_GENERAL_RQT_CONTEXT, 1);
1977        if (req_p == 0)
1978                return CY_AS_ERROR_OUT_OF_MEMORY;
1979
1980        v = (uint16_t)(((uint8_t)pin << 8) | (value > 0));
1981        cy_as_ll_request_response__set_word(req_p, 0, v);
1982
1983        /* Reserve space for the reply, which will not exceed one word. */
1984        reply_p = cy_as_ll_create_response(dev_p, 1);
1985        if (reply_p == 0) {
1986                cy_as_ll_destroy_request(dev_p, req_p);
1987                return CY_AS_ERROR_OUT_OF_MEMORY;
1988        }
1989
1990        if (cb == 0) {
1991                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1992                if (ret != CY_AS_ERROR_SUCCESS)
1993                        goto destroy;
1994
1995                if (cy_as_ll_request_response__get_code(reply_p) !=
1996                        CY_RESP_SUCCESS_FAILURE) {
1997                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1998                        goto destroy;
1999                }
2000
2001                ret = cy_as_ll_request_response__get_word(reply_p, 0);
2002        } else {
2003
2004                ret = cy_as_misc_send_request(dev_p, cb, client,
2005                        CY_FUNCT_CB_MISC_SETGPIOVALUE, 0,
2006                        dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
2007                        req_p, reply_p, cy_as_misc_func_callback);
2008
2009                if (ret != CY_AS_ERROR_SUCCESS)
2010                                goto destroy;
2011
2012                /* The request and response are freed as part of the
2013                 * MiscFuncCallback */
2014                return ret;
2015        }
2016
2017destroy:
2018        cy_as_ll_destroy_request(dev_p, req_p);
2019        cy_as_ll_destroy_response(dev_p, reply_p);
2020
2021        return ret;
2022}
2023
2024static cy_as_return_status_t
2025my_enter_standby(cy_as_device *dev_p, cy_bool pin)
2026{
2027        cy_as_misc_cancel_ex_requests(dev_p);
2028
2029        /* Save the current values in the critical P-port
2030         * registers, where necessary. */
2031        cy_as_hal_read_regs_before_standby(dev_p->tag);
2032
2033        if (pin) {
2034                if (cy_as_hal_set_wakeup_pin(dev_p->tag, cy_false))
2035                        cy_as_device_set_pin_standby(dev_p);
2036                else
2037                        return CY_AS_ERROR_SETTING_WAKEUP_PIN;
2038        } else {
2039                /*
2040                 * put antioch in the standby mode
2041                 */
2042                cy_as_hal_write_register(dev_p->tag,
2043                        CY_AS_MEM_PWR_MAGT_STAT, 0x02);
2044                cy_as_device_set_register_standby(dev_p);
2045        }
2046
2047        /*
2048         * when the antioch comes out of standby, we have to wait until
2049         * the firmware initialization completes before sending other
2050         * requests down.
2051         */
2052        cy_as_device_set_firmware_not_loaded(dev_p);
2053
2054        /*
2055         * keep west bridge interrupt disabled until the device is being woken
2056         * up from standby.
2057         */
2058        dev_p->stby_int_mask = cy_as_hal_disable_interrupts();
2059
2060        return CY_AS_ERROR_SUCCESS;
2061}
2062
2063static cy_as_return_status_t
2064my_handle_response_enter_standby(cy_as_device *dev_p,
2065                        cy_as_ll_request_response *req_p,
2066                        cy_as_ll_request_response *reply_p,
2067                        cy_bool pin)
2068{
2069        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2070
2071        if (cy_as_ll_request_response__get_code(reply_p) !=
2072                CY_RESP_SUCCESS_FAILURE) {
2073                ret = CY_AS_ERROR_INVALID_RESPONSE;
2074                goto destroy;
2075        }
2076
2077        ret = cy_as_ll_request_response__get_word(reply_p, 0);
2078
2079destroy:
2080        cy_as_ll_destroy_request(dev_p, req_p);
2081        cy_as_ll_destroy_response(dev_p, reply_p);
2082
2083        if (ret != CY_AS_ERROR_SUCCESS)
2084                return ret;
2085
2086        ret = my_enter_standby(dev_p, pin);
2087
2088        return ret;
2089}
2090
2091cy_as_return_status_t
2092cy_as_misc_enter_standby(cy_as_device_handle handle,
2093                                                cy_bool pin,
2094                                                cy_as_function_callback cb,
2095                                                uint32_t client)
2096{
2097        cy_as_device *dev_p;
2098        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2099        cy_as_ll_request_response *req_p, *reply_p;
2100        cy_bool standby;
2101
2102        cy_as_log_debug_message(6, "cy_as_misc_enter_standby called");
2103
2104        /* Make sure we have a valid device */
2105        dev_p = (cy_as_device *)handle;
2106        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2107                return CY_AS_ERROR_INVALID_HANDLE;
2108
2109        /*
2110         * if we already are in standby, do not do it again and let the
2111         * user know via the error return.
2112         */
2113        ret = cy_as_misc_in_standby(handle, &standby);
2114        if (ret != CY_AS_ERROR_SUCCESS)
2115                return ret;
2116
2117        if (standby == cy_true)
2118                return CY_AS_ERROR_ALREADY_STANDBY;
2119
2120        /*
2121         * if the user wants to transition from suspend mode to standby mode,
2122         * the device needs to be woken up so that it can complete all pending
2123         * operations.
2124         */
2125        if (cy_as_device_is_in_suspend_mode(dev_p))
2126                cy_as_misc_leave_suspend(dev_p, 0, 0);
2127
2128        if (dev_p->usb_count) {
2129                /*
2130                 * we do not allow west bridge to go into standby mode when the
2131                 * USB stack is initialized.  you must stop the USB stack in
2132                 * order to enter standby mode.
2133                 */
2134                return CY_AS_ERROR_USB_RUNNING;
2135        }
2136
2137        /*
2138         * if the storage stack is not running, the device can directly be
2139         * put into sleep mode. otherwise, the firmware needs to be signaled
2140         * to prepare for going into sleep mode.
2141         */
2142        if (dev_p->storage_count) {
2143                /*
2144                 * if there are async storage operations pending,
2145                 * make one attempt to complete them.
2146                 */
2147                if (cy_as_device_is_storage_async_pending(dev_p)) {
2148                        /* DrainQueue will not work in polling mode */
2149                        if (cy_as_hal_is_polling())
2150                                return CY_AS_ERROR_ASYNC_PENDING;
2151
2152                        cy_as_dma_drain_queue(dev_p,
2153                                CY_AS_P2S_READ_ENDPOINT, cy_false);
2154                        cy_as_dma_drain_queue(dev_p,
2155                                CY_AS_P2S_WRITE_ENDPOINT, cy_false);
2156
2157                        /*
2158                         * if more storage operations were queued
2159                         * at this stage, return an error.
2160                         */
2161                        if (cy_as_device_is_storage_async_pending(dev_p))
2162                                return CY_AS_ERROR_ASYNC_PENDING;
2163                }
2164
2165                req_p = cy_as_ll_create_request(dev_p,
2166                        CY_RQT_PREPARE_FOR_STANDBY,
2167                        CY_RQT_GENERAL_RQT_CONTEXT, 1);
2168                if (req_p == 0)
2169                        return CY_AS_ERROR_OUT_OF_MEMORY;
2170
2171                reply_p = cy_as_ll_create_response(dev_p, 1);
2172                if (reply_p == 0) {
2173                        cy_as_ll_destroy_request(dev_p, req_p);
2174                        return CY_AS_ERROR_OUT_OF_MEMORY;
2175                }
2176
2177                if (!cb) {
2178                        ret = cy_as_ll_send_request_wait_reply(dev_p,
2179                                req_p, reply_p);
2180                        if (ret != CY_AS_ERROR_SUCCESS)
2181                                goto destroy;
2182
2183                        /* The request and response are freed
2184                         * in the HandleResponse */
2185                        return my_handle_response_enter_standby(dev_p,
2186                                req_p, reply_p, pin);
2187
2188                } else {
2189                        ret = cy_as_misc_send_request(dev_p, cb, client,
2190                                CY_FUNCT_CB_MISC_ENTERSTANDBY,  (void *)pin,
2191                                dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
2192                                req_p, reply_p, cy_as_misc_func_callback);
2193
2194                        if (ret != CY_AS_ERROR_SUCCESS)
2195                                goto destroy;
2196
2197                        /* The request and response are freed
2198                         * as part of the MiscFuncCallback */
2199                        return ret;
2200                }
2201destroy:
2202                cy_as_ll_destroy_request(dev_p, req_p);
2203                cy_as_ll_destroy_response(dev_p, reply_p);
2204        } else {
2205                ret = my_enter_standby(dev_p, pin);
2206                if (cb)
2207                        /* Even though no mailbox communication was
2208                         * needed, issue the callback so the user
2209                         * does not need to special case their code. */
2210                        cb((cy_as_device_handle)dev_p, ret, client,
2211                                CY_FUNCT_CB_MISC_ENTERSTANDBY, 0);
2212        }
2213
2214        return ret;
2215}
2216
2217cy_as_return_status_t
2218cy_as_misc_enter_standby_e_x_u(cy_as_device_handle handle,
2219                                                cy_bool pin,
2220                                                cy_bool uvalid_special,
2221                                                cy_as_function_callback cb,
2222                                                uint32_t client)
2223{
2224        cy_as_device *dev_p;
2225
2226        dev_p = (cy_as_device *)handle;
2227        if (uvalid_special)
2228                cy_as_hal_write_register(dev_p->tag, 0xc5, 0x4);
2229
2230        return cy_as_misc_enter_standby(handle, pin, cb, client);
2231}
2232
2233cy_as_return_status_t
2234cy_as_misc_leave_standby(cy_as_device_handle handle,
2235        cy_as_resource_type resource)
2236{
2237        cy_as_device *dev_p;
2238        uint16_t v;
2239        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2240        uint32_t count = 8;
2241        uint8_t  retry = 1;
2242
2243        cy_as_log_debug_message(6, "cy_as_misc_leave_standby called");
2244        (void)resource;
2245
2246        /* Make sure we have a valid device */
2247        dev_p = (cy_as_device *)handle;
2248        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2249                return CY_AS_ERROR_INVALID_HANDLE;
2250
2251        if (cy_as_device_is_register_standby(dev_p)) {
2252                /*
2253                 * set a flag to indicate that the west bridge is waking
2254                 * up from standby.
2255                 */
2256                cy_as_device_set_waking(dev_p);
2257
2258                /*
2259                 * the initial read will not succeed, but will just wake
2260                 * the west bridge device from standby.  successive reads
2261                 * should succeed and in that way we know west bridge is awake.
2262                 */
2263                v = cy_as_hal_read_register(dev_p->tag,
2264                        CY_AS_MEM_CM_WB_CFG_ID);
2265
2266                do {
2267                        /*
2268                         * we have initiated the operation to leave standby, now
2269                         * we need to wait at least N ms before trying to access
2270                         * the west bridge device to insure the PLLs have locked
2271                         * and we can talk to the device.
2272                         */
2273                        if (cy_as_device_is_crystal(dev_p))
2274                                cy_as_hal_sleep(
2275                                        CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL);
2276                        else
2277                                cy_as_hal_sleep(
2278                                        CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
2279                        v = cy_as_hal_read_register(dev_p->tag,
2280                                CY_AS_MEM_CM_WB_CFG_ID);
2281
2282                        /*
2283                        * if the P-SPI interface mode is in use, there may be a
2284                        * need to re-synchronise the serial clock used for
2285                        * astoria access.
2286                        */
2287                        if (!is_valid_silicon_id(v)) {
2288                                if (cy_as_hal_sync_device_clocks(dev_p->tag) !=
2289                                        cy_true) {
2290                                        cy_as_hal_enable_interrupts(
2291                                                dev_p->stby_int_mask);
2292                                        return CY_AS_ERROR_TIMEOUT;
2293                                }
2294                        }
2295                } while (!is_valid_silicon_id(v) && count-- > 0);
2296
2297                /*
2298                 * if we tried to read the register and could not,
2299                 * return a timeout
2300                 */
2301                if (count == 0) {
2302                        cy_as_hal_enable_interrupts(
2303                                dev_p->stby_int_mask);
2304                        return CY_AS_ERROR_TIMEOUT;
2305                }
2306
2307                /*
2308                 * the standby flag is cleared here, after the action to
2309                 * exit standby has been taken. the wait for firmware
2310                 * initialization, is ensured by marking the firmware as
2311                 * not loaded until the init event is received.
2312                 */
2313                cy_as_device_clear_register_standby(dev_p);
2314
2315                /*
2316                 * initialize any registers that may have been changed
2317                 * while the device was in standby mode.
2318                 */
2319                cy_as_hal_init_dev_registers(dev_p->tag, cy_true);
2320        } else if (cy_as_device_is_pin_standby(dev_p)) {
2321                /*
2322                 * set a flag to indicate that the west bridge is waking
2323                 * up from standby.
2324                 */
2325                cy_as_device_set_waking(dev_p);
2326
2327try_wakeup_again:
2328                /*
2329                * try to set the wakeup pin, if this fails in the HAL
2330                * layer, return this failure to the user.
2331                */
2332                if (!cy_as_hal_set_wakeup_pin(dev_p->tag, cy_true)) {
2333                        cy_as_hal_enable_interrupts(dev_p->stby_int_mask);
2334                        return CY_AS_ERROR_SETTING_WAKEUP_PIN;
2335                }
2336
2337                /*
2338                * we have initiated the operation to leave standby, now
2339                * we need to wait at least N ms before trying to access
2340                * the west bridge device to insure the PL_ls have locked
2341                * and we can talk to the device.
2342                */
2343                if (cy_as_device_is_crystal(dev_p))
2344                        cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL);
2345                else
2346                        cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
2347
2348                /*
2349                 * initialize any registers that may have been changed
2350                 * while the device was in standby mode.
2351                 */
2352                cy_as_hal_init_dev_registers(dev_p->tag, cy_true);
2353
2354                /*
2355                 * the standby flag is cleared here, after the action to
2356                 * exit standby has been taken. the wait for firmware
2357                 * initialization, is ensured by marking the firmware as
2358                 * not loaded until the init event is received.
2359                 */
2360                cy_as_device_clear_pin_standby(dev_p);
2361        } else {
2362                return CY_AS_ERROR_NOT_IN_STANDBY;
2363        }
2364
2365        /*
2366         * the west bridge interrupt can be enabled now.
2367         */
2368        cy_as_hal_enable_interrupts(dev_p->stby_int_mask);
2369
2370        /*
2371         * release the west bridge micro-_controller from reset,
2372         * so that firmware initialization can complete. the attempt
2373         * to release antioch reset is made upto 8 times.
2374         */
2375        v = 0x03;
2376        count = 0x08;
2377        while ((v & 0x03) && (count)) {
2378                cy_as_hal_write_register(dev_p->tag,
2379                        CY_AS_MEM_RST_CTRL_REG, 0x00);
2380                v = cy_as_hal_read_register(dev_p->tag,
2381                        CY_AS_MEM_RST_CTRL_REG);
2382                count--;
2383        }
2384
2385        if (v & 0x03) {
2386                cy_as_hal_print_message("failed to clear antioch reset\n");
2387                return CY_AS_ERROR_TIMEOUT;
2388        }
2389
2390        /*
2391         * if the wake-up pin is being used, wait here to make
2392         * sure that the wake-up event is received within a
2393         * reasonable delay. otherwise, toggle the wake-up pin
2394         * again in an attempt to start the firmware properly.
2395         */
2396        if (retry) {
2397                count = 10;
2398                while (count) {
2399                        /* If the wake-up event has been received,
2400                         * we can return. */
2401                        if (cy_as_device_is_firmware_loaded(dev_p))
2402                                break;
2403                        /* If we are in polling mode, the interrupt may
2404                         * not have been serviced as yet. read the
2405                         * interrupt status register. if a pending mailbox
2406                         * interrupt is seen, we can assume that the
2407                         * wake-up event will be received soon. */
2408                        v = cy_as_hal_read_register(dev_p->tag,
2409                                CY_AS_MEM_P0_INTR_REG);
2410                        if (v & CY_AS_MEM_P0_INTR_REG_MBINT)
2411                                break;
2412
2413                        cy_as_hal_sleep(10);
2414                        count--;
2415                }
2416
2417                if (!count) {
2418                        retry = 0;
2419                        dev_p->stby_int_mask = cy_as_hal_disable_interrupts();
2420                        cy_as_hal_set_wakeup_pin(dev_p->tag, cy_false);
2421                        cy_as_hal_sleep(10);
2422                        goto try_wakeup_again;
2423                }
2424        }
2425
2426        return ret;
2427}
2428
2429cy_as_return_status_t
2430cy_as_misc_register_callback(
2431                        /* Handle to the West Bridge device */
2432                        cy_as_device_handle handle,
2433                        /* The function to call */
2434                        cy_as_misc_event_callback  callback
2435                        )
2436{
2437        cy_as_device *dev_p;
2438
2439        cy_as_log_debug_message(6, "cy_as_misc_register_callback called");
2440
2441        /* Make sure we have a valid device */
2442        dev_p = (cy_as_device *)handle;
2443        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2444                return CY_AS_ERROR_INVALID_HANDLE;
2445
2446        dev_p->misc_event_cb = callback;
2447        return CY_AS_ERROR_SUCCESS;
2448}
2449
2450cy_as_return_status_t
2451cy_as_misc_storage_changed(cy_as_device_handle handle,
2452                                                 cy_as_function_callback   cb,
2453                                                 uint32_t client)
2454{
2455        cy_as_device *dev_p;
2456        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2457        cy_bool standby;
2458        cy_as_ll_request_response *req_p, *reply_p;
2459
2460        cy_as_log_debug_message(6, "cy_as_misc_storage_changed called");
2461
2462        /* Make sure the device is ready for the command. */
2463        dev_p = (cy_as_device *)handle;
2464        cy_as_check_device_ready(dev_p);
2465
2466        /*
2467        * make sure antioch is not in standby
2468        */
2469        ret = cy_as_misc_in_standby(dev_p, &standby);
2470        if (ret != CY_AS_ERROR_SUCCESS)
2471                return ret;
2472
2473        if (standby)
2474                return CY_AS_ERROR_IN_STANDBY;
2475
2476        /*
2477         * make sure westbridge is not in suspend mode.
2478         */
2479        if (cy_as_device_is_in_suspend_mode(dev_p))
2480                return CY_AS_ERROR_IN_SUSPEND;
2481
2482        /* Create the request to send to the West Bridge device */
2483        req_p = cy_as_ll_create_request(dev_p, CY_RQT_STORAGE_MEDIA_CHANGED,
2484                CY_RQT_GENERAL_RQT_CONTEXT, 0);
2485        if (req_p == 0)
2486                return CY_AS_ERROR_OUT_OF_MEMORY;
2487
2488        /* Reserve space for the reply, the reply data will
2489         * not exceed one word */
2490        reply_p = cy_as_ll_create_response(dev_p, 1);
2491        if (reply_p == 0) {
2492                cy_as_ll_destroy_request(dev_p, req_p);
2493                return CY_AS_ERROR_OUT_OF_MEMORY;
2494        }
2495
2496        if (cb == 0) {
2497                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2498                if (ret != CY_AS_ERROR_SUCCESS)
2499                        goto destroy;
2500
2501                if (cy_as_ll_request_response__get_code(reply_p) !=
2502                        CY_RESP_SUCCESS_FAILURE) {
2503                        ret = CY_AS_ERROR_INVALID_RESPONSE;
2504                        goto destroy;
2505                }
2506
2507                ret = cy_as_ll_request_response__get_word(reply_p, 0);
2508        } else {
2509
2510                ret = cy_as_misc_send_request(dev_p, cb, client,
2511                        CY_FUNCT_CB_MISC_STORAGECHANGED, 0,
2512                        dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
2513                        req_p, reply_p, cy_as_misc_func_callback);
2514
2515                if (ret != CY_AS_ERROR_SUCCESS)
2516                                goto destroy;
2517
2518                /* The request and response are freed as part of the
2519                 * MiscFuncCallback */
2520                return ret;
2521        }
2522
2523destroy:
2524        cy_as_ll_destroy_request(dev_p, req_p);
2525        cy_as_ll_destroy_response(dev_p, reply_p);
2526
2527        return ret;
2528}
2529
2530
2531cy_as_return_status_t
2532cy_as_misc_enter_suspend(
2533                cy_as_device_handle      handle,
2534                cy_bool                    usb_wakeup_en,
2535                cy_bool                    gpio_wakeup_en,
2536                cy_as_function_callback cb,
2537                uint32_t                         client)
2538{
2539        cy_as_device *dev_p;
2540        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2541        cy_bool standby;
2542        cy_as_ll_request_response *req_p, *reply_p;
2543        uint16_t value;
2544        uint32_t int_state;
2545
2546        cy_as_log_debug_message(6, "cy_as_misc_enter_suspend called");
2547
2548        /*
2549         * basic sanity checks to ensure that the device is initialised.
2550         */
2551        dev_p = (cy_as_device *)handle;
2552        cy_as_check_device_ready(dev_p);
2553
2554        /*
2555         * make sure west bridge is not already in standby
2556         */
2557        cy_as_misc_in_standby(dev_p, &standby);
2558        if (standby)
2559                return CY_AS_ERROR_IN_STANDBY;
2560
2561        /*
2562         * make sure that the device is not already in suspend mode.
2563         */
2564        if (cy_as_device_is_in_suspend_mode(dev_p))
2565                return CY_AS_ERROR_IN_SUSPEND;
2566
2567        /*
2568         * make sure there is no active USB connection.
2569         */
2570        if ((cy_as_device_is_usb_connected(dev_p)) && (dev_p->usb_last_event
2571                != cy_as_event_usb_suspend))
2572                return CY_AS_ERROR_USB_CONNECTED;
2573
2574        /*
2575         * make sure that there are no async requests at this point in time.
2576         */
2577        int_state = cy_as_hal_disable_interrupts();
2578        if ((dev_p->func_cbs_misc->count) || (dev_p->func_cbs_res->count) ||
2579                (dev_p->func_cbs_stor->count) || (dev_p->func_cbs_usb->count)) {
2580                cy_as_hal_enable_interrupts(int_state);
2581                return CY_AS_ERROR_ASYNC_PENDING;
2582        }
2583        cy_as_hal_enable_interrupts(int_state);
2584
2585        /* Create the request to send to the Antioch device */
2586        req_p = cy_as_ll_create_request(dev_p, CY_RQT_ENTER_SUSPEND_MODE,
2587                CY_RQT_GENERAL_RQT_CONTEXT, 1);
2588        if (req_p == 0)
2589                return CY_AS_ERROR_OUT_OF_MEMORY;
2590
2591        /* Reserve space for the reply, the reply data will not
2592         * exceed one word */
2593        reply_p = cy_as_ll_create_response(dev_p, 1);
2594        if (reply_p == 0) {
2595                cy_as_ll_destroy_request(dev_p, req_p);
2596                return CY_AS_ERROR_OUT_OF_MEMORY;
2597        }
2598
2599        /* Wakeup control flags. */
2600        value = 0x0001;
2601        if (usb_wakeup_en)
2602                value |= 0x04;
2603        if (gpio_wakeup_en)
2604                value |= 0x02;
2605        cy_as_ll_request_response__set_word(req_p, 0, value);
2606
2607        if (cb != 0) {
2608
2609                ret = cy_as_misc_send_request(dev_p, cb, client,
2610                        CY_FUNCT_CB_MISC_ENTERSUSPEND,
2611                        0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
2612                        req_p, reply_p,
2613                        cy_as_misc_func_callback);
2614
2615                if (ret != CY_AS_ERROR_SUCCESS)
2616                                goto destroy;
2617
2618                return CY_AS_ERROR_SUCCESS;
2619        } else {
2620                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2621                if (cy_as_ll_request_response__get_code(reply_p) !=
2622                        CY_RESP_SUCCESS_FAILURE)
2623                        ret = CY_AS_ERROR_INVALID_RESPONSE;
2624                else
2625                        ret = cy_as_ll_request_response__get_word(reply_p, 0);
2626        }
2627
2628destroy:
2629        if (ret == CY_AS_ERROR_SUCCESS)
2630                cy_as_device_set_suspend_mode(dev_p);
2631
2632        cy_as_ll_destroy_request(dev_p, req_p);
2633        cy_as_ll_destroy_response(dev_p, reply_p);
2634
2635        return ret;
2636}
2637
2638cy_as_return_status_t
2639cy_as_misc_leave_suspend(
2640                cy_as_device_handle      handle,
2641                cy_as_function_callback cb,
2642                uint32_t                         client)
2643{
2644        cy_as_device *dev_p;
2645        uint16_t v, count;
2646        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2647
2648        cy_as_log_debug_message(6, "cy_as_misc_leave_suspend called");
2649
2650        /* Make sure we have a valid device */
2651        dev_p = (cy_as_device *)handle;
2652        cy_as_check_device_ready(dev_p);
2653
2654        /* Make sure we are in suspend mode. */
2655        if (cy_as_device_is_in_suspend_mode(dev_p)) {
2656                if (cb) {
2657                        cy_as_func_c_b_node *cbnode =
2658                                cy_as_create_func_c_b_node_data(cb, client,
2659                                CY_FUNCT_CB_MISC_LEAVESUSPEND, 0);
2660                        if (cbnode == 0)
2661                                return CY_AS_ERROR_OUT_OF_MEMORY;
2662
2663                        cy_as_insert_c_b_node(dev_p->func_cbs_misc, cbnode);
2664                }
2665
2666                /*
2667                 * do a read from the ID register so that the CE assertion
2668                 * will wake west bridge. the read is repeated until the
2669                 * read comes back with valid data.
2670                 */
2671                count = 8;
2672
2673                v = cy_as_hal_read_register(dev_p->tag,
2674                                CY_AS_MEM_CM_WB_CFG_ID);
2675
2676                while (!is_valid_silicon_id(v) && count-- > 0) {
2677                        cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
2678                        v = cy_as_hal_read_register(dev_p->tag,
2679                                        CY_AS_MEM_CM_WB_CFG_ID);
2680                }
2681
2682                /*
2683                 * if we tried to read the register and could not,
2684                 * return a timeout
2685                 */
2686                if (count == 0)
2687                        return CY_AS_ERROR_TIMEOUT;
2688        } else
2689                return CY_AS_ERROR_NOT_IN_SUSPEND;
2690
2691        if (cb == 0) {
2692                /*
2693                 * wait until the in suspend mode flag is cleared.
2694                 */
2695                count = 20;
2696                while ((cy_as_device_is_in_suspend_mode(dev_p))
2697                        && (count--)) {
2698                        cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
2699                }
2700
2701                if (cy_as_device_is_in_suspend_mode(dev_p))
2702                        ret = CY_AS_ERROR_TIMEOUT;
2703        }
2704
2705        return ret;
2706}
2707
2708cy_as_return_status_t
2709cy_as_misc_reserve_l_n_a_boot_area(cy_as_device_handle handle,
2710                                                   uint8_t numzones,
2711                                                   cy_as_function_callback cb,
2712                                                   uint32_t client)
2713{
2714        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2715        cy_bool standby;
2716        cy_as_ll_request_response *req_p, *reply_p;
2717
2718        cy_as_device *dev_p;
2719
2720        (void)client;
2721
2722        cy_as_log_debug_message(6, "cy_as_misc_switch_pnand_mode called");
2723
2724        /* Make sure we have a valid device */
2725        dev_p = (cy_as_device *)handle;
2726        cy_as_check_device_ready(dev_p);
2727
2728        /*
2729        * make sure antioch is not in standby
2730        */
2731        ret = cy_as_misc_in_standby(dev_p, &standby);
2732        if (ret != CY_AS_ERROR_SUCCESS)
2733                return ret;
2734        if (standby)
2735                return CY_AS_ERROR_IN_STANDBY;
2736
2737        /* Make sure the Antioch is not in suspend mode. */
2738        if (cy_as_device_is_in_suspend_mode(dev_p))
2739                return CY_AS_ERROR_IN_SUSPEND;
2740
2741        /* Create the request to send to the West Bridge device */
2742        req_p = cy_as_ll_create_request(dev_p,
2743                CY_RQT_RESERVE_LNA_BOOT_AREA,
2744                CY_RQT_GENERAL_RQT_CONTEXT, 1);
2745        if (req_p == 0)
2746                        return CY_AS_ERROR_OUT_OF_MEMORY;
2747                cy_as_ll_request_response__set_word(req_p,
2748                        0, (uint16_t)numzones);
2749
2750        /* Reserve space for the reply, the reply data will not
2751         * exceed one word */
2752        reply_p = cy_as_ll_create_response(dev_p, 1);
2753        if (reply_p == 0) {
2754                        cy_as_ll_destroy_request(dev_p, req_p);
2755                        return CY_AS_ERROR_OUT_OF_MEMORY;
2756        }
2757
2758        if (cb == 0) {
2759                ret = cy_as_ll_send_request_wait_reply(dev_p,
2760                                req_p, reply_p);
2761                if (ret != CY_AS_ERROR_SUCCESS)
2762                        goto destroy;
2763
2764                if (cy_as_ll_request_response__get_code(reply_p) !=
2765                        CY_RESP_SUCCESS_FAILURE) {
2766                        ret = CY_AS_ERROR_INVALID_RESPONSE;
2767                        goto destroy;
2768                }
2769
2770                ret = cy_as_ll_request_response__get_word(reply_p, 0);
2771        } else {
2772
2773                ret = cy_as_misc_send_request(dev_p, cb, client,
2774                        CY_FUNCT_CB_MISC_RESERVELNABOOTAREA,
2775                        0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
2776                        req_p, reply_p, cy_as_misc_func_callback);
2777
2778                if (ret != CY_AS_ERROR_SUCCESS)
2779                        goto destroy;
2780
2781                /* The request and response are freed as part of the
2782                 * MiscFuncCallback */
2783                return ret;
2784        }
2785
2786destroy:
2787        cy_as_ll_destroy_request(dev_p, req_p);
2788        cy_as_ll_destroy_response(dev_p, reply_p);
2789
2790        return ret;
2791}
2792
2793cy_as_func_c_b_node*
2794cy_as_create_func_c_b_node_data(cy_as_function_callback cb,
2795                                         uint32_t client,
2796                                         cy_as_funct_c_b_type type,
2797                                         void *data)
2798{
2799        uint32_t state = cy_as_hal_disable_interrupts();
2800        cy_as_func_c_b_node *node = cy_as_hal_c_b_alloc(
2801                                        sizeof(cy_as_func_c_b_node));
2802        cy_as_hal_enable_interrupts(state);
2803        if (node != 0) {
2804                node->node_type = CYAS_FUNC_CB;
2805                node->cb_p = cb;
2806                node->client_data = client;
2807                node->data_type = type;
2808                if (data != 0)
2809                        node->data_type |= CY_FUNCT_CB_DATA;
2810                else
2811                        node->data_type |= CY_FUNCT_CB_NODATA;
2812                node->data = data;
2813                node->next_p = 0;
2814        }
2815        return node;
2816}
2817
2818cy_as_func_c_b_node*
2819cy_as_create_func_c_b_node(cy_as_function_callback cb,
2820                                         uint32_t client)
2821{
2822        return cy_as_create_func_c_b_node_data(cb, client,
2823                CY_FUNCT_CB_NODATA, 0);
2824}
2825
2826void
2827cy_as_destroy_func_c_b_node(cy_as_func_c_b_node *node)
2828{
2829        uint32_t state;
2830
2831        node->node_type = CYAS_INVALID;
2832        state = cy_as_hal_disable_interrupts();
2833        cy_as_hal_c_b_free(node);
2834        cy_as_hal_enable_interrupts(state);
2835}
2836
2837cy_as_usb_func_c_b_node*
2838cy_as_create_usb_func_c_b_node(
2839                cy_as_usb_function_callback cb, uint32_t client)
2840{
2841        uint32_t state = cy_as_hal_disable_interrupts();
2842        cy_as_usb_func_c_b_node *node = cy_as_hal_c_b_alloc(
2843                sizeof(cy_as_usb_func_c_b_node));
2844        cy_as_hal_enable_interrupts(state);
2845        if (node != 0) {
2846                node->type = CYAS_USB_FUNC_CB;
2847                node->cb_p = cb;
2848                node->client_data = client;
2849                node->next_p = 0;
2850        }
2851        return node;
2852}
2853
2854void
2855cy_as_destroy_usb_func_c_b_node(cy_as_usb_func_c_b_node *node)
2856{
2857        uint32_t state;
2858
2859        node->type = CYAS_INVALID;
2860        state = cy_as_hal_disable_interrupts();
2861        cy_as_hal_c_b_free(node);
2862        cy_as_hal_enable_interrupts(state);
2863}
2864
2865cy_as_usb_io_c_b_node*
2866cy_as_create_usb_io_c_b_node(cy_as_usb_io_callback cb)
2867{
2868        uint32_t state = cy_as_hal_disable_interrupts();
2869        cy_as_usb_io_c_b_node *node = cy_as_hal_c_b_alloc(
2870                sizeof(cy_as_usb_io_c_b_node));
2871        cy_as_hal_enable_interrupts(state);
2872        if (node != 0) {
2873                node->type = CYAS_USB_IO_CB;
2874                node->cb_p = cb;
2875                node->next_p = 0;
2876        }
2877        return node;
2878}
2879
2880void
2881cy_as_destroy_usb_io_c_b_node(cy_as_usb_io_c_b_node *node)
2882{
2883        uint32_t state;
2884
2885        node->type = CYAS_INVALID;
2886
2887        state = cy_as_hal_disable_interrupts();
2888        cy_as_hal_c_b_free(node);
2889        cy_as_hal_enable_interrupts(state);
2890}
2891
2892cy_as_storage_io_c_b_node*
2893cy_as_create_storage_io_c_b_node(cy_as_storage_callback cb,
2894        cy_as_media_type media, uint32_t device_index,
2895        uint32_t unit, uint32_t block_addr, cy_as_oper_type oper,
2896        cy_as_ll_request_response *req_p,
2897        cy_as_ll_request_response *reply_p)
2898{
2899        uint32_t state = cy_as_hal_disable_interrupts();
2900        cy_as_storage_io_c_b_node *node = cy_as_hal_c_b_alloc(
2901                sizeof(cy_as_storage_io_c_b_node));
2902        cy_as_hal_enable_interrupts(state);
2903        if (node != 0) {
2904                node->type = CYAS_STORAGE_IO_CB;
2905                node->cb_p = cb;
2906                node->media = media;
2907                node->device_index = device_index;
2908                node->unit = unit;
2909                node->block_addr = block_addr;
2910                node->oper = oper;
2911                node->req_p = req_p;
2912                node->reply_p = reply_p;
2913                node->next_p = 0;
2914        }
2915        return node;
2916}
2917
2918void
2919cy_as_destroy_storage_io_c_b_node(cy_as_storage_io_c_b_node *node)
2920{
2921        uint32_t state;
2922        node->type = CYAS_INVALID;
2923        state = cy_as_hal_disable_interrupts();
2924        cy_as_hal_c_b_free(node);
2925        cy_as_hal_enable_interrupts(state);
2926}
2927
2928cy_as_c_b_queue *
2929cy_as_create_c_b_queue(cy_as_c_b_node_type type)
2930{
2931        uint32_t state = cy_as_hal_disable_interrupts();
2932        cy_as_c_b_queue *queue = cy_as_hal_c_b_alloc(
2933                sizeof(cy_as_c_b_queue));
2934        cy_as_hal_enable_interrupts(state);
2935        if (queue) {
2936                queue->type = type;
2937                queue->head_p = 0;
2938                queue->tail_p = 0;
2939                queue->count = 0;
2940        }
2941
2942        return queue;
2943}
2944
2945void
2946cy_as_destroy_c_b_queue(cy_as_c_b_queue *queue)
2947{
2948        uint32_t state;
2949        queue->type = CYAS_INVALID;
2950        queue->head_p = 0;
2951        queue->tail_p = 0;
2952        queue->count = 0;
2953        state = cy_as_hal_disable_interrupts();
2954        cy_as_hal_c_b_free(queue);
2955        cy_as_hal_enable_interrupts(state);
2956}
2957
2958/* Inserts a CyAsCBNode into the queue, the
2959 * node type must match the queue type*/
2960void
2961cy_as_insert_c_b_node(cy_as_c_b_queue *queue_p, void*cbnode)
2962{
2963        uint32_t int_state;
2964
2965        int_state = cy_as_hal_disable_interrupts();
2966
2967        cy_as_hal_assert(queue_p != 0);
2968
2969        switch (queue_p->type) {
2970        case CYAS_USB_FUNC_CB:
2971                {
2972                        cy_as_usb_func_c_b_node *node =
2973                                (cy_as_usb_func_c_b_node *)cbnode;
2974                        cy_as_usb_func_c_b_node *tail =
2975                                (cy_as_usb_func_c_b_node *)queue_p->tail_p;
2976
2977                        cy_as_hal_assert(node->type == CYAS_USB_FUNC_CB);
2978                        cy_as_hal_assert(tail == 0 ||
2979                                tail->type == CYAS_USB_FUNC_CB);
2980                        if (queue_p->head_p == 0)
2981                                queue_p->head_p = node;
2982                        else
2983                                tail->next_p = node;
2984
2985                        queue_p->tail_p = node;
2986                }
2987                break;
2988
2989        case CYAS_USB_IO_CB:
2990                {
2991                        cy_as_usb_io_c_b_node *node =
2992                                (cy_as_usb_io_c_b_node *)cbnode;
2993                        cy_as_usb_io_c_b_node *tail =
2994                                (cy_as_usb_io_c_b_node *)queue_p->tail_p;
2995
2996                        cy_as_hal_assert(node->type == CYAS_USB_IO_CB);
2997                        cy_as_hal_assert(tail == 0 ||
2998                                tail->type == CYAS_USB_IO_CB);
2999                        if (queue_p->head_p == 0)
3000                                queue_p->head_p = node;
3001                        else
3002                                tail->next_p = node;
3003
3004                        queue_p->tail_p = node;
3005                }
3006                break;
3007
3008        case CYAS_STORAGE_IO_CB:
3009                {
3010                        cy_as_storage_io_c_b_node *node =
3011                                (cy_as_storage_io_c_b_node *)cbnode;
3012                        cy_as_storage_io_c_b_node *tail =
3013                                (cy_as_storage_io_c_b_node *)queue_p->tail_p;
3014
3015                        cy_as_hal_assert(node->type == CYAS_STORAGE_IO_CB);
3016                        cy_as_hal_assert(tail == 0 ||
3017                                tail->type == CYAS_STORAGE_IO_CB);
3018                        if (queue_p->head_p == 0)
3019                                queue_p->head_p = node;
3020                        else
3021                                tail->next_p = node;
3022
3023                                queue_p->tail_p = node;
3024                }
3025                break;
3026
3027        case CYAS_FUNC_CB:
3028                {
3029                        cy_as_func_c_b_node *node =
3030                                (cy_as_func_c_b_node *)cbnode;
3031                        cy_as_func_c_b_node *tail =
3032                                (cy_as_func_c_b_node *)queue_p->tail_p;
3033
3034                        cy_as_hal_assert(node->node_type == CYAS_FUNC_CB);
3035                        cy_as_hal_assert(tail == 0 ||
3036                                tail->node_type == CYAS_FUNC_CB);
3037                        if (queue_p->head_p == 0)
3038                                queue_p->head_p = node;
3039                        else
3040                                tail->next_p = node;
3041
3042                                queue_p->tail_p = node;
3043                }
3044                break;
3045
3046        default:
3047                cy_as_hal_assert(cy_false);
3048                break;
3049        }
3050
3051        queue_p->count++;
3052
3053        cy_as_hal_enable_interrupts(int_state);
3054}
3055
3056/* Removes the tail node from the queue and frees it */
3057void
3058cy_as_remove_c_b_tail_node(cy_as_c_b_queue *queue_p)
3059{
3060        uint32_t int_state;
3061
3062        int_state = cy_as_hal_disable_interrupts();
3063
3064        if (queue_p->count > 0) {
3065                /*
3066                 * the worst case length of the queue should be
3067                 * under 10 elements, and the average case should
3068                 * be just 1 element. so, we just employ a linear
3069                 * search to find the node to be freed.
3070                 */
3071                switch (queue_p->type) {
3072                case CYAS_FUNC_CB:
3073                        {
3074                                cy_as_func_c_b_node *node =
3075                                        (cy_as_func_c_b_node *)
3076                                        queue_p->head_p;
3077                                cy_as_func_c_b_node *tail =
3078                                        (cy_as_func_c_b_node *)
3079                                        queue_p->tail_p;
3080                                if (node != tail) {
3081                                        while (node->next_p != tail)
3082                                                node = node->next_p;
3083                                        node->next_p = 0;
3084                                        queue_p->tail_p = node;
3085                                }
3086                                cy_as_destroy_func_c_b_node(tail);
3087                        }
3088                        break;
3089
3090                case CYAS_USB_FUNC_CB:
3091                        {
3092                                cy_as_usb_func_c_b_node *node =
3093                                        (cy_as_usb_func_c_b_node *)
3094                                        queue_p->head_p;
3095                                cy_as_usb_func_c_b_node *tail =
3096                                        (cy_as_usb_func_c_b_node *)
3097                                        queue_p->tail_p;
3098                                if (node != tail) {
3099                                        while (node->next_p != tail)
3100                                                        node = node->next_p;
3101                                                node->next_p = 0;
3102                                                queue_p->tail_p = node;
3103                                }
3104
3105                                cy_as_destroy_usb_func_c_b_node(tail);
3106                        }
3107                        break;
3108
3109                case CYAS_USB_IO_CB:
3110                        {
3111                                cy_as_usb_io_c_b_node *node =
3112                                        (cy_as_usb_io_c_b_node *)
3113                                        queue_p->head_p;
3114                                cy_as_usb_io_c_b_node *tail =
3115                                        (cy_as_usb_io_c_b_node *)
3116                                        queue_p->tail_p;
3117                                if (node != tail) {
3118                                        while (node->next_p != tail)
3119                                                node = node->next_p;
3120                                        node->next_p = 0;
3121                                        queue_p->tail_p = node;
3122                                }
3123                                cy_as_destroy_usb_io_c_b_node(tail);
3124                        }
3125                        break;
3126
3127                case CYAS_STORAGE_IO_CB:
3128                        {
3129                                cy_as_storage_io_c_b_node *node =
3130                                        (cy_as_storage_io_c_b_node *)
3131                                        queue_p->head_p;
3132                                cy_as_storage_io_c_b_node *tail =
3133                                        (cy_as_storage_io_c_b_node *)
3134                                        queue_p->tail_p;
3135                                if (node != tail) {
3136                                        while (node->next_p != tail)
3137                                                node = node->next_p;
3138                                        node->next_p = 0;
3139                                        queue_p->tail_p = node;
3140                                }
3141                                cy_as_destroy_storage_io_c_b_node(tail);
3142                        }
3143                        break;
3144
3145                default:
3146                        cy_as_hal_assert(cy_false);
3147                }
3148
3149                queue_p->count--;
3150                if (queue_p->count == 0) {
3151                        queue_p->head_p = 0;
3152                        queue_p->tail_p = 0;
3153                }
3154        }
3155
3156        cy_as_hal_enable_interrupts(int_state);
3157}
3158
3159/* Removes the first CyAsCBNode from the queue and frees it */
3160void
3161cy_as_remove_c_b_node(cy_as_c_b_queue *queue_p)
3162{
3163        uint32_t int_state;
3164
3165        int_state = cy_as_hal_disable_interrupts();
3166
3167        cy_as_hal_assert(queue_p->count >= 0);
3168        if (queue_p->count > 0) {
3169                if (queue_p->type == CYAS_USB_FUNC_CB) {
3170                        cy_as_usb_func_c_b_node *node =
3171                                (cy_as_usb_func_c_b_node *)
3172                                queue_p->head_p;
3173                        queue_p->head_p = node->next_p;
3174                        cy_as_destroy_usb_func_c_b_node(node);
3175                } else if (queue_p->type == CYAS_USB_IO_CB) {
3176                        cy_as_usb_io_c_b_node *node =
3177                                (cy_as_usb_io_c_b_node *)
3178                                queue_p->head_p;
3179                        queue_p->head_p = node->next_p;
3180                        cy_as_destroy_usb_io_c_b_node(node);
3181                } else if (queue_p->type == CYAS_STORAGE_IO_CB) {
3182                        cy_as_storage_io_c_b_node *node =
3183                                (cy_as_storage_io_c_b_node *)
3184                                queue_p->head_p;
3185                        queue_p->head_p = node->next_p;
3186                        cy_as_destroy_storage_io_c_b_node(node);
3187                } else if (queue_p->type == CYAS_FUNC_CB) {
3188                        cy_as_func_c_b_node *node =
3189                                (cy_as_func_c_b_node *)
3190                                queue_p->head_p;
3191                        queue_p->head_p = node->next_p;
3192                        cy_as_destroy_func_c_b_node(node);
3193                } else {
3194                        cy_as_hal_assert(cy_false);
3195                }
3196
3197                queue_p->count--;
3198                if (queue_p->count == 0) {
3199                        queue_p->head_p = 0;
3200                        queue_p->tail_p = 0;
3201                }
3202        }
3203
3204        cy_as_hal_enable_interrupts(int_state);
3205}
3206
3207void my_print_func_c_b_node(cy_as_func_c_b_node *node)
3208{
3209        cy_as_funct_c_b_type type =
3210                cy_as_funct_c_b_type_get_type(node->data_type);
3211        cy_as_hal_print_message("[cd:%2u dt:%2u cb:0x%08x "
3212                "d:0x%08x nt:%1i]", node->client_data, type,
3213                (uint32_t)node->cb_p, (uint32_t)node->data,
3214                node->node_type);
3215}
3216
3217void my_print_c_b_queue(cy_as_c_b_queue *queue_p)
3218{
3219        uint32_t i = 0;
3220
3221        cy_as_hal_print_message("| count: %u type: ", queue_p->count);
3222
3223        if (queue_p->type == CYAS_USB_FUNC_CB) {
3224                cy_as_hal_print_message("USB_FUNC_CB\n");
3225        } else if (queue_p->type == CYAS_USB_IO_CB) {
3226                cy_as_hal_print_message("USB_IO_CB\n");
3227        } else if (queue_p->type == CYAS_STORAGE_IO_CB) {
3228                cy_as_hal_print_message("STORAGE_IO_CB\n");
3229        } else if (queue_p->type == CYAS_FUNC_CB) {
3230                cy_as_func_c_b_node *node = queue_p->head_p;
3231                cy_as_hal_print_message("FUNC_CB\n");
3232                if (queue_p->count > 0) {
3233                        cy_as_hal_print_message("| head->");
3234
3235                        for (i = 0; i < queue_p->count; i++) {
3236                                if (node) {
3237                                        cy_as_hal_print_message("->");
3238                                        my_print_func_c_b_node(node);
3239                                        node = node->next_p;
3240                                } else
3241                                        cy_as_hal_print_message("->[NULL]\n");
3242                        }
3243
3244                        cy_as_hal_print_message("\n| tail->");
3245                        my_print_func_c_b_node(queue_p->tail_p);
3246                        cy_as_hal_print_message("\n");
3247                }
3248        } else {
3249                cy_as_hal_print_message("INVALID\n");
3250        }
3251
3252        cy_as_hal_print_message("|----------\n");
3253}
3254
3255
3256/* Removes and frees all pending callbacks */
3257void
3258cy_as_clear_c_b_queue(cy_as_c_b_queue *queue_p)
3259{
3260        uint32_t int_state = cy_as_hal_disable_interrupts();
3261
3262        while (queue_p->count != 0)
3263                cy_as_remove_c_b_node(queue_p);
3264
3265        cy_as_hal_enable_interrupts(int_state);
3266}
3267
3268cy_as_return_status_t
3269cy_as_misc_send_request(cy_as_device *dev_p,
3270                                          cy_as_function_callback cb,
3271                                          uint32_t client,
3272                                          cy_as_funct_c_b_type type,
3273                                          void *data,
3274                                          cy_as_c_b_queue *queue,
3275                                          uint16_t req_type,
3276                                          cy_as_ll_request_response *req_p,
3277                                          cy_as_ll_request_response *reply_p,
3278                                          cy_as_response_callback rcb)
3279{
3280
3281        cy_as_func_c_b_node *cbnode = cy_as_create_func_c_b_node_data(cb,
3282                client, type, data);
3283        cy_as_return_status_t ret;
3284
3285        if (cbnode == 0)
3286                return CY_AS_ERROR_OUT_OF_MEMORY;
3287        else
3288                cy_as_insert_c_b_node(queue, cbnode);
3289
3290        req_p->flags |= req_type;
3291
3292        ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_false, rcb);
3293        if (ret != CY_AS_ERROR_SUCCESS)
3294                cy_as_remove_c_b_tail_node(queue);
3295
3296        return ret;
3297}
3298
3299void
3300cy_as_misc_cancel_ex_requests(cy_as_device *dev_p)
3301{
3302        int i;
3303        for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++)
3304                cy_as_ll_remove_all_requests(dev_p, dev_p->context[i]);
3305}
3306
3307
3308static void
3309cy_as_misc_func_callback(cy_as_device *dev_p,
3310                                                uint8_t context,
3311                                                cy_as_ll_request_response *rqt,
3312                                                cy_as_ll_request_response *resp,
3313                                                cy_as_return_status_t stat)
3314{
3315        cy_as_func_c_b_node *node = NULL;
3316        cy_as_return_status_t ret;
3317
3318        cy_bool ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX)
3319                        == CY_AS_REQUEST_RESPONSE_EX;
3320        cy_bool ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS)
3321                        == CY_AS_REQUEST_RESPONSE_MS;
3322        uint8_t code;
3323        uint32_t type;
3324        uint8_t cntxt;
3325
3326        cy_as_hal_assert(ex_request || ms_request);
3327        (void) ex_request;
3328        (void) ms_request;
3329        (void)context;
3330
3331        cntxt = cy_as_ll_request_response__get_context(rqt);
3332        code = cy_as_ll_request_response__get_code(rqt);
3333
3334        switch (cntxt) {
3335        case CY_RQT_GENERAL_RQT_CONTEXT:
3336                cy_as_hal_assert(dev_p->func_cbs_misc->count != 0);
3337                cy_as_hal_assert(dev_p->func_cbs_misc->type == CYAS_FUNC_CB);
3338                node = (cy_as_func_c_b_node *)dev_p->func_cbs_misc->head_p;
3339                type = cy_as_funct_c_b_type_get_type(node->data_type);
3340
3341                switch (code) {
3342                case CY_RQT_GET_FIRMWARE_VERSION:
3343                        cy_as_hal_assert(node->data != 0);
3344                        cy_as_hal_assert(type ==
3345                                CY_FUNCT_CB_MISC_GETFIRMWAREVERSION);
3346                        ret = my_handle_response_get_firmware_version(dev_p,
3347                                rqt, resp,
3348                                (cy_as_get_firmware_version_data *)node->data);
3349                        break;
3350                case CY_RQT_READ_MCU_REGISTER:
3351                        cy_as_hal_assert(node->data != 0);
3352                        cy_as_hal_assert(type ==
3353                                CY_FUNCT_CB_MISC_READMCUREGISTER);
3354                        ret = my_handle_response_read_m_c_u_register(dev_p, rqt,
3355                                resp, (uint8_t *)node->data);
3356                        break;
3357                case CY_RQT_GET_GPIO_STATE:
3358                        cy_as_hal_assert(node->data != 0);
3359                        cy_as_hal_assert(type ==
3360                                CY_FUNCT_CB_MISC_GETGPIOVALUE);
3361                        ret = my_handle_response_get_gpio_value(dev_p, rqt,
3362                                resp, (uint8_t *)node->data);
3363                        break;
3364                case CY_RQT_SET_SD_CLOCK_FREQ:
3365                        cy_as_hal_assert(type == CY_FUNCT_CB_MISC_SETSDFREQ);
3366                        ret = my_handle_response_no_data(dev_p, rqt, resp);
3367                        break;
3368                case CY_RQT_CONTROL_ANTIOCH_HEARTBEAT:
3369                        cy_as_hal_assert(type ==
3370                                CY_FUNCT_CB_MISC_HEARTBEATCONTROL);
3371                        ret = my_handle_response_no_data(dev_p, rqt, resp);
3372                        break;
3373                case CY_RQT_WRITE_MCU_REGISTER:
3374                        cy_as_hal_assert(type ==
3375                                CY_FUNCT_CB_MISC_WRITEMCUREGISTER);
3376                        ret = my_handle_response_no_data(dev_p, rqt, resp);
3377                        break;
3378                case CY_RQT_STORAGE_MEDIA_CHANGED:
3379                        cy_as_hal_assert(type ==
3380                                CY_FUNCT_CB_MISC_STORAGECHANGED);
3381                        ret = my_handle_response_no_data(dev_p, rqt, resp);
3382                        break;
3383                case CY_RQT_SET_GPIO_STATE:
3384                        cy_as_hal_assert(type ==
3385                                CY_FUNCT_CB_MISC_SETGPIOVALUE);
3386                        ret = my_handle_response_no_data(dev_p, rqt, resp);
3387                        break;
3388                case CY_RQT_SET_TRACE_LEVEL:
3389                        cy_as_hal_assert(type ==
3390                                CY_FUNCT_CB_MISC_SETTRACELEVEL);
3391                        ret = my_handle_response_no_data(dev_p, rqt, resp);
3392                        if (ret == CY_AS_ERROR_INVALID_RESPONSE)
3393                                ret = CY_AS_ERROR_NOT_SUPPORTED;
3394                        break;
3395                case CY_RQT_PREPARE_FOR_STANDBY:
3396                        cy_as_hal_assert(type ==
3397                                CY_FUNCT_CB_MISC_ENTERSTANDBY);
3398                        ret = my_handle_response_enter_standby(dev_p, rqt, resp,
3399                                (cy_bool)node->data);
3400                        break;
3401                case CY_RQT_ENTER_SUSPEND_MODE:
3402                        cy_as_hal_assert(type ==
3403                                CY_FUNCT_CB_MISC_ENTERSUSPEND);
3404                        ret = my_handle_response_no_data(dev_p, rqt, resp);
3405                        if (ret == CY_AS_ERROR_SUCCESS)
3406                                cy_as_device_set_suspend_mode(dev_p);
3407
3408                        break;
3409                case CY_RQT_RESERVE_LNA_BOOT_AREA:
3410                        cy_as_hal_assert(type ==
3411                                CY_FUNCT_CB_MISC_RESERVELNABOOTAREA);
3412                        ret = my_handle_response_no_data(dev_p, rqt, resp);
3413                        break;
3414                case CY_RQT_SDPOLARITY:
3415                        cy_as_hal_assert(type ==
3416                                CY_FUNCT_CB_MISC_SETSDPOLARITY);
3417                        ret = my_handle_response_no_data(dev_p, rqt, resp);
3418                        break;
3419                default:
3420                        ret = CY_AS_ERROR_INVALID_RESPONSE;
3421                        cy_as_hal_assert(cy_false);
3422                        break;
3423                }
3424                break;
3425
3426        case CY_RQT_RESOURCE_RQT_CONTEXT:
3427                cy_as_hal_assert(dev_p->func_cbs_res->count != 0);
3428                cy_as_hal_assert(dev_p->func_cbs_res->type == CYAS_FUNC_CB);
3429                node = (cy_as_func_c_b_node *)dev_p->func_cbs_res->head_p;
3430                type = cy_as_funct_c_b_type_get_type(node->data_type);
3431
3432                switch (code) {
3433                case CY_RQT_ACQUIRE_RESOURCE:
3434                        /* The node->data field is actually an enum value
3435                         * which could be 0, thus no assert is done */
3436                        cy_as_hal_assert(type ==
3437                                CY_FUNCT_CB_MISC_ACQUIRERESOURCE);
3438                        ret = my_handle_response_acquire_resource(dev_p, rqt,
3439                                resp, (cy_as_resource_type *)node->data);
3440                        break;
3441                default:
3442                        ret = CY_AS_ERROR_INVALID_RESPONSE;
3443                        cy_as_hal_assert(cy_false);
3444                        break;
3445                }
3446                break;
3447
3448        default:
3449                ret = CY_AS_ERROR_INVALID_RESPONSE;
3450                cy_as_hal_assert(cy_false);
3451                break;
3452        }
3453
3454        /*
3455         * if the low level layer returns a direct error, use the
3456         * corresponding error code. if not, use the error code
3457         * based on the response from firmware.
3458         */
3459        if (stat == CY_AS_ERROR_SUCCESS)
3460                stat = ret;
3461
3462        /* Call the user Callback */
3463        node->cb_p((cy_as_device_handle)dev_p, stat, node->client_data,
3464                node->data_type, node->data);
3465        if (cntxt == CY_RQT_GENERAL_RQT_CONTEXT)
3466                cy_as_remove_c_b_node(dev_p->func_cbs_misc);
3467        else
3468                cy_as_remove_c_b_node(dev_p->func_cbs_res);
3469
3470}
3471
3472
3473
3474/*[]*/
3475