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