]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/westbridge/astoria/api/src/cyasmisc.c
Fix common misspellings
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / westbridge / astoria / api / src / cyasmisc.c
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 */
34 static cy_as_device *g_device_list;
35
36 /*
37 * The current debug level
38 */
39 static uint8_t debug_level;
40
41 /*
42 * This function sets the debug level for the API
43 *
44 */
45 void
46 cy_as_misc_set_log_level(uint8_t level)
47 {
48 debug_level = level;
49 }
50
51 #ifdef CY_AS_LOG_SUPPORT
52
53 /*
54 * This function is a low level logger for the API.
55 */
56 void
57 cy_as_log_debug_message(int level, const char *str)
58 {
59 if (level <= debug_level)
60 cy_as_hal_print_message("log %d: %s\n", level, str);
61 }
62
63 #endif
64
65 #define cy_as_check_device_ready(dev_p) \
66 {\
67 if (!(dev_p) || ((dev_p)->sig != \
68 CY_AS_DEVICE_HANDLE_SIGNATURE)) \
69 return CY_AS_ERROR_INVALID_HANDLE; \
70 \
71 if (!cy_as_device_is_configured(dev_p)) \
72 return CY_AS_ERROR_NOT_CONFIGURED; \
73 \
74 if (!cy_as_device_is_firmware_loaded(dev_p))\
75 return CY_AS_ERROR_NO_FIRMWARE; \
76 }
77
78 /* Find an West Bridge device based on a TAG */
79 cy_as_device *
80 cy_as_device_find_from_tag(cy_as_hal_device_tag tag)
81 {
82 cy_as_device *dev_p;
83
84 for (dev_p = g_device_list; dev_p != 0; dev_p = dev_p->next_p) {
85 if (dev_p->tag == tag)
86 return dev_p;
87 }
88
89 return 0;
90 }
91
92 /* Map a pre-V1.2 media type to the V1.2+ bus number */
93 static void
94 cy_as_bus_from_media_type(cy_as_media_type type,
95 cy_as_bus_number_t *bus)
96 {
97 if (type == cy_as_media_nand)
98 *bus = 0;
99 else
100 *bus = 1;
101 }
102
103 static cy_as_return_status_t
104 my_handle_response_no_data(cy_as_device *dev_p,
105 cy_as_ll_request_response *req_p,
106 cy_as_ll_request_response *reply_p)
107 {
108 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
109
110 if (cy_as_ll_request_response__get_code(reply_p) !=
111 CY_RESP_SUCCESS_FAILURE)
112 ret = CY_AS_ERROR_INVALID_RESPONSE;
113 else
114 ret = cy_as_ll_request_response__get_word(reply_p, 0);
115
116 cy_as_ll_destroy_request(dev_p, req_p);
117 cy_as_ll_destroy_response(dev_p, reply_p);
118
119 return ret;
120 }
121
122 /*
123 * Create a new West Bridge device
124 */
125 cy_as_return_status_t
126 cy_as_misc_create_device(cy_as_device_handle *handle_p,
127 cy_as_hal_device_tag tag)
128 {
129 cy_as_device *dev_p;
130 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
131
132 cy_as_log_debug_message(6, "cy_as_misc_create_device called");
133
134 dev_p = (cy_as_device *)cy_as_hal_alloc(sizeof(cy_as_device));
135 if (dev_p == 0)
136 return CY_AS_ERROR_OUT_OF_MEMORY;
137 cy_as_hal_mem_set(dev_p, 0, sizeof(cy_as_device));
138
139 /*
140 * dynamically allocating this buffer to ensure that it is
141 * word aligned.
142 */
143 dev_p->usb_ep_data = (uint8_t *)cy_as_hal_alloc(64 * sizeof(uint8_t));
144 if (dev_p->usb_ep_data == 0) {
145 cy_as_hal_free(dev_p);
146 return CY_AS_ERROR_OUT_OF_MEMORY;
147 }
148
149 dev_p->sig = CY_AS_DEVICE_HANDLE_SIGNATURE;
150 dev_p->tag = tag;
151 dev_p->usb_max_tx_size = 0x40;
152
153 dev_p->storage_write_endpoint = CY_AS_P2S_WRITE_ENDPOINT;
154 dev_p->storage_read_endpoint = CY_AS_P2S_READ_ENDPOINT;
155
156 dev_p->func_cbs_misc = cy_as_create_c_b_queue(CYAS_FUNC_CB);
157 if (dev_p->func_cbs_misc == 0)
158 goto destroy;
159
160 dev_p->func_cbs_res = cy_as_create_c_b_queue(CYAS_FUNC_CB);
161 if (dev_p->func_cbs_res == 0)
162 goto destroy;
163
164 dev_p->func_cbs_stor = cy_as_create_c_b_queue(CYAS_FUNC_CB);
165 if (dev_p->func_cbs_stor == 0)
166 goto destroy;
167
168 dev_p->func_cbs_usb = cy_as_create_c_b_queue(CYAS_FUNC_CB);
169 if (dev_p->func_cbs_usb == 0)
170 goto destroy;
171
172 dev_p->func_cbs_mtp = cy_as_create_c_b_queue(CYAS_FUNC_CB);
173 if (dev_p->func_cbs_mtp == 0)
174 goto destroy;
175
176 /*
177 * allocate memory for the DMA module here. it is then marked idle, and
178 * will be activated when cy_as_misc_configure_device is called.
179 */
180 ret = cy_as_dma_start(dev_p);
181 if (ret != CY_AS_ERROR_SUCCESS)
182 goto destroy;
183
184 cy_as_device_set_dma_stopped(dev_p);
185
186 /*
187 * allocate memory for the low level module here. this module is also
188 * activated only when cy_as_misc_configure_device is called.
189 */
190 ret = cy_as_ll_start(dev_p);
191 if (ret != CY_AS_ERROR_SUCCESS)
192 goto destroy;
193
194 cy_as_device_set_low_level_stopped(dev_p);
195
196 dev_p->next_p = g_device_list;
197 g_device_list = dev_p;
198
199 *handle_p = dev_p;
200 cy_as_hal_init_dev_registers(tag, cy_false);
201 return CY_AS_ERROR_SUCCESS;
202
203 destroy:
204 /* Free any queues that were successfully allocated. */
205 if (dev_p->func_cbs_misc)
206 cy_as_destroy_c_b_queue(dev_p->func_cbs_misc);
207
208 if (dev_p->func_cbs_res)
209 cy_as_destroy_c_b_queue(dev_p->func_cbs_res);
210
211 if (dev_p->func_cbs_stor)
212 cy_as_destroy_c_b_queue(dev_p->func_cbs_stor);
213
214 if (dev_p->func_cbs_usb)
215 cy_as_destroy_c_b_queue(dev_p->func_cbs_usb);
216
217 if (dev_p->func_cbs_mtp)
218 cy_as_destroy_c_b_queue(dev_p->func_cbs_mtp);
219
220 cy_as_hal_free(dev_p->usb_ep_data);
221 cy_as_hal_free(dev_p);
222
223 if (ret != CY_AS_ERROR_SUCCESS)
224 return ret;
225 else
226 return CY_AS_ERROR_OUT_OF_MEMORY;
227 }
228
229 /*
230 * Destroy an existing West Bridge device
231 */
232 cy_as_return_status_t
233 cy_as_misc_destroy_device(cy_as_device_handle handle)
234 {
235 cy_as_return_status_t ret;
236 cy_as_device *dev_p;
237
238 cy_as_log_debug_message(6, "cy_as_misc_destroy_device called");
239
240 dev_p = (cy_as_device *)handle;
241 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
242 return CY_AS_ERROR_INVALID_HANDLE;
243
244 /*
245 * if the USB stack is still running,
246 * it must be stopped first
247 */
248 if (dev_p->usb_count > 0)
249 return CY_AS_ERROR_STILL_RUNNING;
250
251 /*
252 * if the STORAGE stack is still running,
253 * it must be stopped first
254 */
255 if (dev_p->storage_count > 0)
256 return CY_AS_ERROR_STILL_RUNNING;
257
258 if (cy_as_device_is_intr_running(dev_p))
259 ret = cy_as_intr_stop(dev_p);
260
261 ret = cy_as_ll_stop(dev_p);
262 if (ret != CY_AS_ERROR_SUCCESS) {
263 cy_as_intr_start(dev_p, dev_p->use_int_drq);
264 return ret;
265 }
266
267 ret = cy_as_dma_stop(dev_p);
268 if (ret != CY_AS_ERROR_SUCCESS) {
269 cy_as_intr_start(dev_p, dev_p->use_int_drq);
270 return ret;
271 }
272
273 /* Reset the West Bridge device. */
274 cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_RST_CTRL_REG,
275 CY_AS_MEM_RST_CTRL_REG_HARD);
276
277 /*
278 * remove the device from the device list
279 */
280 if (g_device_list == dev_p) {
281 g_device_list = dev_p->next_p;
282 } else {
283 cy_as_device *tmp_p = g_device_list;
284 while (tmp_p && tmp_p->next_p != dev_p)
285 tmp_p = tmp_p->next_p;
286
287 cy_as_hal_assert(tmp_p != 0);
288 tmp_p->next_p = dev_p->next_p;
289 }
290
291 /*
292 * reset the signature so this will not be detected
293 * as a valid handle
294 */
295 dev_p->sig = 0;
296
297 cy_as_destroy_c_b_queue(dev_p->func_cbs_misc);
298 cy_as_destroy_c_b_queue(dev_p->func_cbs_res);
299 cy_as_destroy_c_b_queue(dev_p->func_cbs_stor);
300 cy_as_destroy_c_b_queue(dev_p->func_cbs_usb);
301 cy_as_destroy_c_b_queue(dev_p->func_cbs_mtp);
302
303 /*
304 * free the memory associated with the device
305 */
306 cy_as_hal_free(dev_p->usb_ep_data);
307 cy_as_hal_free(dev_p);
308
309 return CY_AS_ERROR_SUCCESS;
310 }
311
312 /*
313 * Determine the endian mode for the processor we are
314 * running on, then set the endian mode register
315 */
316 static void
317 cy_as_setup_endian_mode(cy_as_device *dev_p)
318 {
319 /*
320 * In general, we always set west bridge intothe little
321 * endian mode. this causes the data on bit 0 internally
322 * to come out on data line 0 externally and it is generally
323 * what we want regardless of the endian mode of the
324 * processor. this capability in west bridge should be
325 * labeled as a "SWAP" capability and can be used to swap the
326 * bytes of data in and out of west bridge. this is
327 * useful if there is DMA hardware that requires this for some
328 * reason I cannot imagine at this time. basically if the
329 * wires are connected correctly, we should never need to
330 * change the endian-ness of west bridge.
331 */
332 cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_ENDIAN,
333 CY_AS_LITTLE_ENDIAN);
334 }
335
336 /*
337 * Query the West Bridge device and determine if we are an standby mode
338 */
339 cy_as_return_status_t
340 cy_as_misc_in_standby(cy_as_device_handle handle, cy_bool *standby)
341 {
342 cy_as_device *dev_p;
343
344 cy_as_log_debug_message(6, "cy_as_misc_in_standby called");
345
346 dev_p = (cy_as_device *)handle;
347 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
348 return CY_AS_ERROR_INVALID_HANDLE;
349
350 if (cy_as_device_is_pin_standby(dev_p) ||
351 cy_as_device_is_register_standby(dev_p)) {
352 *standby = cy_true;
353 } else
354 *standby = cy_false;
355
356 return CY_AS_ERROR_SUCCESS;
357 }
358
359 static void
360 cy_as_misc_func_callback(cy_as_device *dev_p,
361 uint8_t context,
362 cy_as_ll_request_response *rqt,
363 cy_as_ll_request_response *resp,
364 cy_as_return_status_t ret);
365
366
367 static void
368 my_misc_callback(cy_as_device *dev_p, uint8_t context,
369 cy_as_ll_request_response *req_p,
370 cy_as_ll_request_response *resp_p,
371 cy_as_return_status_t ret)
372 {
373 (void)resp_p;
374 (void)context;
375 (void)ret;
376
377 switch (cy_as_ll_request_response__get_code(req_p)) {
378 case CY_RQT_INITIALIZATION_COMPLETE:
379 {
380 uint16_t v;
381
382 cy_as_ll_send_status_response(dev_p,
383 CY_RQT_GENERAL_RQT_CONTEXT,
384 CY_AS_ERROR_SUCCESS, 0);
385 cy_as_device_set_firmware_loaded(dev_p);
386
387 if (cy_as_device_is_waking(dev_p)) {
388 /*
389 * this is a callback from a
390 * cy_as_misc_leave_standby()
391 * request. in this case we call
392 * the standby callback and clear
393 * the waking state.
394 */
395 if (dev_p->misc_event_cb)
396 dev_p->misc_event_cb(
397 (cy_as_device_handle)dev_p,
398 cy_as_event_misc_awake, 0);
399 cy_as_device_clear_waking(dev_p);
400 } else {
401 v = cy_as_ll_request_response__get_word
402 (req_p, 3);
403
404 /*
405 * store the media supported on
406 * each of the device buses.
407 */
408 dev_p->media_supported[0] =
409 (uint8_t)(v & 0xFF);
410 dev_p->media_supported[1] =
411 (uint8_t)((v >> 8) & 0xFF);
412
413 v = cy_as_ll_request_response__get_word
414 (req_p, 4);
415
416 dev_p->is_mtp_firmware =
417 (cy_bool)((v >> 8) & 0xFF);
418
419 if (dev_p->misc_event_cb)
420 dev_p->misc_event_cb(
421 (cy_as_device_handle)dev_p,
422 cy_as_event_misc_initialized, 0);
423 }
424
425 v = cy_as_hal_read_register(dev_p->tag,
426 CY_AS_MEM_P0_VM_SET);
427
428 if (v & CY_AS_MEM_P0_VM_SET_CFGMODE)
429 cy_as_hal_print_message(
430 "initialization message "
431 "received, but config bit "
432 "still set\n");
433
434 v = cy_as_hal_read_register(dev_p->tag,
435 CY_AS_MEM_RST_CTRL_REG);
436 if ((v & CY_AS_MEM_RST_RSTCMPT) == 0)
437 cy_as_hal_print_message(
438 "initialization message "
439 "received, but reset complete "
440 "bit still not set\n");
441 }
442 break;
443
444 case CY_RQT_OUT_OF_SUSPEND:
445 cy_as_ll_send_status_response(dev_p, CY_RQT_GENERAL_RQT_CONTEXT,
446 CY_AS_ERROR_SUCCESS, 0);
447 cy_as_device_clear_suspend_mode(dev_p);
448
449 /*
450 * if the wakeup was caused by an async cy_as_misc_leave_suspend
451 * call, we have to call the corresponding callback.
452 */
453 if (dev_p->func_cbs_misc->count > 0) {
454 cy_as_func_c_b_node *node = (cy_as_func_c_b_node *)
455 dev_p->func_cbs_misc->head_p;
456 cy_as_hal_assert(node);
457
458 if (cy_as_funct_c_b_type_get_type(node->data_type) ==
459 CY_FUNCT_CB_MISC_LEAVESUSPEND) {
460 cy_as_hal_assert(node->cb_p != 0);
461
462 node->cb_p((cy_as_device_handle)dev_p,
463 CY_AS_ERROR_SUCCESS, node->client_data,
464 CY_FUNCT_CB_MISC_LEAVESUSPEND, 0);
465 cy_as_remove_c_b_node(dev_p->func_cbs_misc);
466 }
467 }
468
469 if (dev_p->misc_event_cb)
470 dev_p->misc_event_cb((cy_as_device_handle)dev_p,
471 cy_as_event_misc_wakeup, 0);
472 break;
473
474 case CY_RQT_DEBUG_MESSAGE:
475 if ((req_p->data[0] == 0) && (req_p->data[1] == 0) &&
476 (req_p->data[2] == 0)) {
477 if (dev_p->misc_event_cb)
478 dev_p->misc_event_cb((cy_as_device_handle)dev_p,
479 cy_as_event_misc_heart_beat, 0);
480 } else {
481 cy_as_hal_print_message(
482 "**** debug message: %02x "
483 "%02x %02x %02x %02x %02x\n",
484 req_p->data[0] & 0xff,
485 (req_p->data[0] >> 8) & 0xff,
486 req_p->data[1] & 0xff,
487 (req_p->data[1] >> 8) & 0xff,
488 req_p->data[2] & 0xff,
489 (req_p->data[2] >> 8) & 0xff);
490 }
491 break;
492
493 case CY_RQT_WB_DEVICE_MISMATCH:
494 {
495 if (dev_p->misc_event_cb)
496 dev_p->misc_event_cb((cy_as_device_handle)dev_p,
497 cy_as_event_misc_device_mismatch, 0);
498 }
499 break;
500
501 case CY_RQT_BOOTLOAD_NO_FIRMWARE:
502 {
503 /* TODO Handle case when firmware is
504 * not found during bootloading. */
505 cy_as_hal_print_message("no firmware image found "
506 "during bootload. device not started\n");
507 }
508 break;
509
510 default:
511 cy_as_hal_assert(0);
512 }
513 }
514
515 static cy_bool
516 is_valid_silicon_id(uint16_t v)
517 {
518 cy_bool idok = cy_false;
519
520 /*
521 * remove the revision number from the ID value
522 */
523 v = v & CY_AS_MEM_CM_WB_CFG_ID_HDID_MASK;
524
525 /*
526 * if this is west bridge, then we are OK.
527 */
528 if (v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE ||
529 v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE ||
530 v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE)
531 idok = cy_true;
532
533 return idok;
534 }
535
536 /*
537 * Configure the West Bridge device hardware
538 */
539 cy_as_return_status_t
540 cy_as_misc_configure_device(cy_as_device_handle handle,
541 cy_as_device_config *config_p)
542 {
543 cy_as_return_status_t ret;
544 cy_bool standby;
545 cy_as_device *dev_p;
546 uint16_t v;
547 uint16_t fw_present;
548 cy_as_log_debug_message(6, "cy_as_misc_configure_device called");
549
550 dev_p = (cy_as_device *)handle;
551 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
552 return CY_AS_ERROR_INVALID_HANDLE;
553
554 /* Setup big endian vs little endian */
555 cy_as_setup_endian_mode(dev_p);
556
557 /* Now, confirm that we can talk to the West Bridge device */
558 dev_p->silicon_id = cy_as_hal_read_register(dev_p->tag,
559 CY_AS_MEM_CM_WB_CFG_ID);
560 fw_present = cy_as_hal_read_register(dev_p->tag,
561 CY_AS_MEM_RST_CTRL_REG);
562 if (!(fw_present & CY_AS_MEM_RST_RSTCMPT)) {
563 if (!is_valid_silicon_id(dev_p->silicon_id))
564 return CY_AS_ERROR_NO_ANTIOCH;
565 }
566 /* Check for standby mode */
567 ret = cy_as_misc_in_standby(handle, &standby);
568 if (ret != CY_AS_ERROR_SUCCESS)
569 return ret;
570 if (ret)
571 return CY_AS_ERROR_IN_STANDBY;
572
573 /* Setup P-port interface mode (CRAM / SRAM). */
574 if (cy_as_device_is_astoria_dev(dev_p)) {
575 if (config_p->srammode)
576 v = CY_AS_MEM_P0_VM_SET_VMTYPE_SRAM;
577 else
578 v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM;
579 } else
580 v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM;
581
582 /* Setup synchronous versus asynchronous mode */
583 if (config_p->sync)
584 v |= CY_AS_MEM_P0_VM_SET_IFMODE;
585 if (config_p->dackmode == cy_as_device_dack_ack)
586 v |= CY_AS_MEM_P0_VM_SET_DACKEOB;
587 if (config_p->drqpol)
588 v |= CY_AS_MEM_P0_VM_SET_DRQPOL;
589 if (config_p->dackpol)
590 v |= CY_AS_MEM_P0_VM_SET_DACKPOL;
591 cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_VM_SET, v);
592
593 if (config_p->crystal)
594 cy_as_device_set_crystal(dev_p);
595 else
596 cy_as_device_set_external_clock(dev_p);
597
598 /* Register a callback to handle MISC requests from the firmware */
599 cy_as_ll_register_request_callback(dev_p,
600 CY_RQT_GENERAL_RQT_CONTEXT, my_misc_callback);
601
602 /* Now mark the DMA and low level modules as active. */
603 cy_as_device_set_dma_running(dev_p);
604 cy_as_device_set_low_level_running(dev_p);
605
606 /* Now, initialize the interrupt module */
607 dev_p->use_int_drq = config_p->dmaintr;
608 ret = cy_as_intr_start(dev_p, config_p->dmaintr);
609 if (ret != CY_AS_ERROR_SUCCESS)
610 return ret;
611
612 /* Mark the interface as initialized */
613 cy_as_device_set_configured(dev_p);
614
615 return CY_AS_ERROR_SUCCESS;
616 }
617
618 static void
619 my_dma_callback(cy_as_device *dev_p,
620 cy_as_end_point_number_t ep,
621 void *mem_p,
622 uint32_t size,
623 cy_as_return_status_t ret
624 )
625 {
626 cy_as_dma_end_point *ep_p;
627
628 (void)size;
629
630 /* Get the endpoint pointer based on the endpoint number */
631 ep_p = CY_AS_NUM_EP(dev_p, ep);
632
633 /* Check the queue to see if is drained */
634 if (ep_p->queue_p == 0) {
635 cy_as_func_c_b_node *node =
636 (cy_as_func_c_b_node *)dev_p->func_cbs_misc->head_p;
637
638 cy_as_hal_assert(node);
639
640 if (ret == CY_AS_ERROR_SUCCESS) {
641 /*
642 * disable endpoint 2. the storage module
643 * will enable this EP if necessary.
644 */
645 cy_as_dma_enable_end_point(dev_p,
646 CY_AS_FIRMWARE_ENDPOINT,
647 cy_false, cy_as_direction_in);
648
649 /*
650 * clear the reset register. this releases the
651 * antioch micro-controller from reset and begins
652 * running the code at address zero.
653 */
654 cy_as_hal_write_register(dev_p->tag,
655 CY_AS_MEM_RST_CTRL_REG, 0x00);
656 }
657
658 /* Call the user Callback */
659 node->cb_p((cy_as_device_handle)dev_p, ret, node->client_data,
660 node->data_type, node->data);
661 cy_as_remove_c_b_node(dev_p->func_cbs_misc);
662 } else {
663 /* This is the header data that was allocated in the
664 * download firmware function, and can be safely freed
665 * here. */
666 uint32_t state = cy_as_hal_disable_interrupts();
667 cy_as_hal_c_b_free(mem_p);
668 cy_as_hal_enable_interrupts(state);
669 }
670 }
671
672 cy_as_return_status_t
673 cy_as_misc_download_firmware(cy_as_device_handle handle,
674 const void *mem_p,
675 uint16_t size,
676 cy_as_function_callback cb,
677 uint32_t client)
678 {
679 uint8_t *header;
680 cy_as_return_status_t ret;
681 cy_bool standby;
682 cy_as_device *dev_p;
683 cy_as_dma_callback dmacb = 0;
684 uint32_t state;
685
686 cy_as_log_debug_message(6, "cy_as_misc_download_firmware called");
687
688 /* Make sure we have a valid device */
689 dev_p = (cy_as_device *)handle;
690 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
691 return CY_AS_ERROR_INVALID_HANDLE;
692
693 /*
694 * if the device has not been initialized, we cannot download firmware
695 * to the device.
696 */
697 if (!cy_as_device_is_configured(dev_p))
698 return CY_AS_ERROR_NOT_CONFIGURED;
699
700 /*
701 * make sure west bridge is not in standby
702 */
703 ret = cy_as_misc_in_standby(dev_p, &standby);
704 if (ret != CY_AS_ERROR_SUCCESS)
705 return ret;
706
707 if (standby)
708 return CY_AS_ERROR_IN_STANDBY;
709
710 if (cy_as_device_is_in_suspend_mode(dev_p))
711 return CY_AS_ERROR_IN_SUSPEND;
712
713 /*
714 * make sure we are in configuration mode
715 */
716 if ((cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_VM_SET) &
717 CY_AS_MEM_P0_VM_SET_CFGMODE) == 0)
718 return CY_AS_ERROR_NOT_IN_CONFIG_MODE;
719
720 /* Maximum firmware size is 24k */
721 if (size > CY_AS_MAXIMUM_FIRMWARE_SIZE)
722 return CY_AS_ERROR_INVALID_SIZE;
723
724 /* Make sure the size is an even number of bytes as well */
725 if (size & 0x01)
726 return CY_AS_ERROR_ALIGNMENT_ERROR;
727
728 /*
729 * write the two word header that gives the base address and
730 * size of the firmware image to download
731 */
732 state = cy_as_hal_disable_interrupts();
733 header = (uint8_t *)cy_as_hal_c_b_alloc(4);
734 cy_as_hal_enable_interrupts(state);
735 if (header == NULL)
736 return CY_AS_ERROR_OUT_OF_MEMORY;
737
738 header[0] = 0x00;
739 header[1] = 0x00;
740 header[2] = (uint8_t)(size & 0xff);
741 header[3] = (uint8_t)((size >> 8) & 0xff);
742
743 /* Enable the firmware endpoint */
744 ret = cy_as_dma_enable_end_point(dev_p, CY_AS_FIRMWARE_ENDPOINT,
745 cy_true, cy_as_direction_in);
746 if (ret != CY_AS_ERROR_SUCCESS)
747 return ret;
748
749 /*
750 * setup DMA for 64 byte packets. this is the requirement for downloading
751 * firmware to west bridge.
752 */
753 cy_as_dma_set_max_dma_size(dev_p, CY_AS_FIRMWARE_ENDPOINT, 64);
754
755 if (cb)
756 dmacb = my_dma_callback;
757
758 ret = cy_as_dma_queue_request(dev_p, CY_AS_FIRMWARE_ENDPOINT, header,
759 4, cy_false, cy_false, dmacb);
760 if (ret != CY_AS_ERROR_SUCCESS)
761 return ret;
762
763 /*
764 * write the firmware image to the west bridge device
765 */
766 ret = cy_as_dma_queue_request(dev_p, CY_AS_FIRMWARE_ENDPOINT,
767 (void *)mem_p, size, cy_false, cy_false, dmacb);
768 if (ret != CY_AS_ERROR_SUCCESS)
769 return ret;
770
771 if (cb) {
772 cy_as_func_c_b_node *cbnode = cy_as_create_func_c_b_node_data(
773 cb, client, CY_FUNCT_CB_MISC_DOWNLOADFIRMWARE, 0);
774
775 if (cbnode == 0)
776 return CY_AS_ERROR_OUT_OF_MEMORY;
777 else
778 cy_as_insert_c_b_node(dev_p->func_cbs_misc, cbnode);
779
780 ret = cy_as_dma_kick_start(dev_p, CY_AS_FIRMWARE_ENDPOINT);
781 if (ret != CY_AS_ERROR_SUCCESS)
782 return ret;
783 } else {
784 ret = cy_as_dma_drain_queue(dev_p,
785 CY_AS_FIRMWARE_ENDPOINT, cy_true);
786
787 /* Free the header memory that was allocated earlier. */
788 cy_as_hal_c_b_free(header);
789
790 if (ret != CY_AS_ERROR_SUCCESS)
791 return ret;
792
793 /*
794 * disable EP 2. the storage module will
795 * enable this EP if necessary.
796 */
797 cy_as_dma_enable_end_point(dev_p, CY_AS_FIRMWARE_ENDPOINT,
798 cy_false, cy_as_direction_in);
799
800 /*
801 * clear the reset register. this releases the west bridge
802 * micro-controller from reset and begins running the code at
803 * address zero.
804 */
805 cy_as_hal_write_register(dev_p->tag,
806 CY_AS_MEM_RST_CTRL_REG, 0x00);
807 }
808
809 /*
810 * the firmware is not marked as loaded until the firmware
811 * initializes west bridge and a request is sent from west bridge
812 * to the P port processor indicating that west bridge is ready.
813 */
814 return CY_AS_ERROR_SUCCESS;
815 }
816
817
818 static cy_as_return_status_t
819 my_handle_response_get_firmware_version(cy_as_device *dev_p,
820 cy_as_ll_request_response *req_p,
821 cy_as_ll_request_response *reply_p,
822 cy_as_get_firmware_version_data *data_p)
823 {
824
825 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
826 uint16_t val;
827
828 if (cy_as_ll_request_response__get_code(reply_p)
829 != CY_RESP_FIRMWARE_VERSION) {
830 ret = CY_AS_ERROR_INVALID_RESPONSE;
831 goto destroy;
832 }
833
834 data_p->major = cy_as_ll_request_response__get_word(reply_p, 0);
835 data_p->minor = cy_as_ll_request_response__get_word(reply_p, 1);
836 data_p->build = cy_as_ll_request_response__get_word(reply_p, 2);
837 val = cy_as_ll_request_response__get_word(reply_p, 3);
838 data_p->media_type = (uint8_t)(((val >> 8) & 0xFF) | (val & 0xFF));
839 val = cy_as_ll_request_response__get_word(reply_p, 4);
840 data_p->is_debug_mode = (cy_bool)(val & 0xFF);
841
842 destroy:
843 cy_as_ll_destroy_request(dev_p, req_p);
844 cy_as_ll_destroy_response(dev_p, reply_p);
845
846 return ret;
847 }
848
849 cy_as_return_status_t
850 cy_as_misc_get_firmware_version(cy_as_device_handle handle,
851 cy_as_get_firmware_version_data *data,
852 cy_as_function_callback cb,
853 uint32_t client)
854 {
855 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
856 cy_bool standby;
857 cy_as_ll_request_response *req_p, *reply_p;
858
859 cy_as_device *dev_p;
860
861 (void)client;
862
863 cy_as_log_debug_message(6, "cy_as_misc_get_firmware_version called");
864
865 /* Make sure we have a valid device */
866 dev_p = (cy_as_device *)handle;
867 cy_as_check_device_ready(dev_p);
868
869 /*
870 * make sure antioch is not in standby
871 */
872 ret = cy_as_misc_in_standby(dev_p, &standby);
873 if (ret != CY_AS_ERROR_SUCCESS)
874 return ret;
875 if (standby)
876 return CY_AS_ERROR_IN_STANDBY;
877
878 /* Make sure the Antioch is not in suspend mode. */
879 if (cy_as_device_is_in_suspend_mode(dev_p))
880 return CY_AS_ERROR_IN_SUSPEND;
881
882 /* Create the request to send to the West Bridge device */
883 req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_FIRMWARE_VERSION,
884 CY_RQT_GENERAL_RQT_CONTEXT, 0);
885 if (req_p == 0)
886 return CY_AS_ERROR_OUT_OF_MEMORY;
887
888 /*
889 * Reserve space for the reply, the reply data
890 * will not exceed three words
891 */
892 reply_p = cy_as_ll_create_response(dev_p, 5);
893 if (reply_p == 0) {
894 cy_as_ll_destroy_request(dev_p, req_p);
895 return CY_AS_ERROR_OUT_OF_MEMORY;
896 }
897
898 if (cb == 0) {
899 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
900 if (ret != CY_AS_ERROR_SUCCESS)
901 goto destroy;
902
903 /* Request and response are freed in
904 * MyHandleResponseGetFirmwareVersion. */
905 ret = my_handle_response_get_firmware_version(dev_p,
906 req_p, reply_p, data);
907 return ret;
908 } else {
909
910 ret = cy_as_misc_send_request(dev_p, cb, client,
911 CY_FUNCT_CB_MISC_GETFIRMWAREVERSION, data,
912 dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
913 req_p, reply_p, cy_as_misc_func_callback);
914
915 if (ret != CY_AS_ERROR_SUCCESS)
916 goto destroy;
917
918 /* The request and response are freed
919 * as part of the MiscFuncCallback */
920 return ret;
921 }
922
923 destroy:
924 cy_as_ll_destroy_request(dev_p, req_p);
925 cy_as_ll_destroy_response(dev_p, reply_p);
926
927 return ret;
928 }
929 EXPORT_SYMBOL(cy_as_misc_get_firmware_version);
930
931 static cy_as_return_status_t
932 my_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
938 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
939
940 if (cy_as_ll_request_response__get_code(reply_p)
941 != CY_RESP_MCU_REGISTER_DATA) {
942 ret = CY_AS_ERROR_INVALID_RESPONSE;
943 goto destroy;
944 }
945
946 *data_p = (uint8_t)
947 (cy_as_ll_request_response__get_word(reply_p, 0));
948
949 destroy:
950 cy_as_ll_destroy_request(dev_p, req_p);
951 cy_as_ll_destroy_response(dev_p, reply_p);
952
953 return ret;
954 }
955
956 static cy_as_return_status_t
957 my_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
963 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
964
965 if (cy_as_ll_request_response__get_code(reply_p)
966 != CY_RESP_GPIO_STATE) {
967 ret = CY_AS_ERROR_INVALID_RESPONSE;
968 } else
969 *data_p = (uint8_t)
970 (cy_as_ll_request_response__get_word(reply_p, 0));
971
972 cy_as_ll_destroy_request(dev_p, req_p);
973 cy_as_ll_destroy_response(dev_p, reply_p);
974
975 return ret;
976 }
977
978
979 cy_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 {
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;
988
989 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
990 return CY_AS_ERROR_INVALID_HANDLE;
991
992 if (!cy_as_device_is_configured(dev_p))
993 return CY_AS_ERROR_NOT_CONFIGURED;
994
995 if (!cy_as_device_is_firmware_loaded(dev_p))
996 return CY_AS_ERROR_NO_FIRMWARE;
997
998 if (cy_as_device_is_in_suspend_mode(dev_p))
999 return CY_AS_ERROR_IN_SUSPEND;
1000
1001 req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDPOLARITY,
1002 CY_RQT_GENERAL_RQT_CONTEXT, 1);
1003 if (req_p == 0)
1004 return CY_AS_ERROR_OUT_OF_MEMORY;
1005
1006 cy_as_ll_request_response__set_word(req_p, 0,
1007 (uint16_t)polarity);
1008
1009 /*
1010 * Reserve space for the reply, the reply data will
1011 * not exceed one word
1012 */
1013 reply_p = cy_as_ll_create_response(dev_p, 1);
1014 if (reply_p == 0) {
1015 cy_as_ll_destroy_request(dev_p, req_p);
1016 return CY_AS_ERROR_OUT_OF_MEMORY;
1017 }
1018
1019 if (cb == 0) {
1020 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1021 if (ret != CY_AS_ERROR_SUCCESS)
1022 goto destroy;
1023
1024 return (my_handle_response_no_data(dev_p, req_p, reply_p));
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,
1029 cy_as_misc_func_callback);
1030
1031 if (ret != CY_AS_ERROR_SUCCESS)
1032 goto destroy;
1033
1034 /* The request and response are freed
1035 * as part of the FuncCallback */
1036 return ret;
1037 }
1038
1039 destroy:
1040 cy_as_ll_destroy_request(dev_p, req_p);
1041 cy_as_ll_destroy_response(dev_p, reply_p);
1042 return ret;
1043 }
1044
1045
1046 cy_as_return_status_t
1047 cy_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 {
1053 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1054 cy_as_ll_request_response *req_p, *reply_p;
1055
1056 cy_as_device *dev_p;
1057
1058 cy_as_log_debug_message(6, "cy_as_misc_read_m_c_u_register called");
1059
1060 dev_p = (cy_as_device *)handle;
1061 cy_as_check_device_ready(dev_p);
1062
1063 /* Check whether the firmware supports this command. */
1064 if (cy_as_device_is_nand_storage_supported(dev_p))
1065 return CY_AS_ERROR_NOT_SUPPORTED;
1066
1067 /* Make sure the Antioch is not in suspend mode. */
1068 if (cy_as_device_is_in_suspend_mode(dev_p))
1069 return CY_AS_ERROR_IN_SUSPEND;
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,
1073 CY_RQT_GENERAL_RQT_CONTEXT, 1);
1074 if (req_p == 0)
1075 return CY_AS_ERROR_OUT_OF_MEMORY;
1076
1077 cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)address);
1078
1079 /* Reserve space for the reply, the reply
1080 * data will not exceed one word */
1081 reply_p = cy_as_ll_create_response(dev_p, 1);
1082 if (reply_p == 0) {
1083 cy_as_ll_destroy_request(dev_p, req_p);
1084 return CY_AS_ERROR_OUT_OF_MEMORY;
1085 }
1086
1087 if (cb == 0) {
1088 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1089 if (ret != CY_AS_ERROR_SUCCESS)
1090 goto destroy;
1091
1092 if (cy_as_ll_request_response__get_code(reply_p) !=
1093 CY_RESP_MCU_REGISTER_DATA) {
1094 ret = CY_AS_ERROR_INVALID_RESPONSE;
1095 goto destroy;
1096 }
1097
1098 *value = (uint8_t)(cy_as_ll_request_response__get_word
1099 (reply_p, 0));
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,
1105 req_p, reply_p, cy_as_misc_func_callback);
1106
1107 if (ret != CY_AS_ERROR_SUCCESS)
1108 goto destroy;
1109
1110 /* The request and response are freed
1111 * as part of the MiscFuncCallback */
1112 return ret;
1113 }
1114 destroy:
1115 cy_as_ll_destroy_request(dev_p, req_p);
1116 cy_as_ll_destroy_response(dev_p, reply_p);
1117
1118 return ret;
1119 }
1120 EXPORT_SYMBOL(cy_as_misc_read_m_c_u_register);
1121
1122 cy_as_return_status_t
1123 cy_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 {
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;
1133
1134 cy_as_log_debug_message(6, "cy_as_misc_write_m_c_u_register called");
1135
1136 dev_p = (cy_as_device *)handle;
1137 cy_as_check_device_ready(dev_p);
1138
1139 /* Check whether the firmware supports this command. */
1140 if (cy_as_device_is_nand_storage_supported(dev_p))
1141 return CY_AS_ERROR_NOT_SUPPORTED;
1142
1143 /* Make sure the Antioch is not in suspend mode. */
1144 if (cy_as_device_is_in_suspend_mode(dev_p))
1145 return CY_AS_ERROR_IN_SUSPEND;
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,
1149 CY_RQT_GENERAL_RQT_CONTEXT, 2);
1150 if (req_p == 0)
1151 return CY_AS_ERROR_OUT_OF_MEMORY;
1152
1153 cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)address);
1154 cy_as_ll_request_response__set_word(req_p, 1,
1155 (uint16_t)((mask << 8) | value));
1156
1157 /*
1158 * Reserve space for the reply, the reply data
1159 * will not exceed one word
1160 */
1161 reply_p = cy_as_ll_create_response(dev_p, 1);
1162 if (reply_p == 0) {
1163 cy_as_ll_destroy_request(dev_p, req_p);
1164 return CY_AS_ERROR_OUT_OF_MEMORY;
1165 }
1166
1167 if (cb == 0) {
1168 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1169 if (ret != CY_AS_ERROR_SUCCESS)
1170 goto destroy;
1171
1172 if (cy_as_ll_request_response__get_code(reply_p) !=
1173 CY_RESP_SUCCESS_FAILURE) {
1174 ret = CY_AS_ERROR_INVALID_RESPONSE;
1175 goto destroy;
1176 }
1177
1178 ret = cy_as_ll_request_response__get_word(reply_p, 0);
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,
1183 req_p, reply_p, cy_as_misc_func_callback);
1184
1185 if (ret != CY_AS_ERROR_SUCCESS)
1186 goto destroy;
1187
1188 /*
1189 * The request and response are freed as part of the
1190 * MiscFuncCallback
1191 */
1192 return ret;
1193 }
1194
1195 destroy:
1196 cy_as_ll_destroy_request(dev_p, req_p);
1197 cy_as_ll_destroy_response(dev_p, reply_p);
1198
1199 return ret;
1200 }
1201
1202 cy_as_return_status_t
1203 my_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 {
1208 uint16_t v;
1209
1210 (void)req_p;
1211 (void)reply_p;
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,
1221 CY_AS_MEM_CM_WB_CFG_ID);
1222 cy_as_hal_sleep(1);
1223 }
1224
1225 if (type == cy_as_reset_hard) {
1226 cy_as_misc_cancel_ex_requests(dev_p);
1227 cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_RST_CTRL_REG,
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);
1237
1238 /*
1239 * wait for a small amount of time to
1240 * allow reset to be complete.
1241 */
1242 cy_as_hal_sleep(100);
1243 }
1244
1245 cy_as_device_clear_reset_pending(dev_p);
1246
1247 return CY_AS_ERROR_SUCCESS;
1248 }
1249
1250 cy_as_return_status_t
1251 cy_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 {
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;
1262
1263 cy_as_log_debug_message(6, "cy_as_misc_reset_e_x called");
1264
1265 /* Make sure the device is ready for the command. */
1266 dev_p = (cy_as_device *)handle;
1267 cy_as_check_device_ready(dev_p);
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)
1274 return CY_AS_ERROR_NOT_YET_SUPPORTED;
1275
1276 cy_as_device_set_reset_pending(dev_p);
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())
1282 return CY_AS_ERROR_ASYNC_PENDING;
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,
1289 cy_as_direction_dont_change);
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,
1301 CY_AS_ERROR_CANCELED);
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,
1307 cy_false);
1308 else
1309 cy_as_dma_drain_queue(dev_p, i,
1310 cy_true);
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,
1320 CY_AS_ERROR_CANCELED);
1321 }
1322 }
1323
1324 ret = my_handle_response_reset(dev_p, 0, 0, type);
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,
1331 CY_FUNCT_CB_MISC_RESET, 0);
1332
1333 /*
1334 * initialize any registers that may have been
1335 * changed when the device was reset.
1336 */
1337 cy_as_hal_init_dev_registers(dev_p->tag, cy_false);
1338
1339 return ret;
1340 }
1341 EXPORT_SYMBOL(cy_as_misc_reset);
1342
1343 static cy_as_return_status_t
1344 get_unallocated_resource(cy_as_device *dev_p, cy_as_resource_type resource)
1345 {
1346 uint8_t shift = 0;
1347 uint16_t v;
1348 cy_as_return_status_t ret = CY_AS_ERROR_NOT_ACQUIRED;
1349
1350 switch (resource) {
1351 case cy_as_bus_u_s_b:
1352 shift = 4;
1353 break;
1354 case cy_as_bus_1:
1355 shift = 0;
1356 break;
1357 case cy_as_bus_0:
1358 shift = 2;
1359 break;
1360 default:
1361 cy_as_hal_assert(cy_false);
1362 break;
1363 }
1364
1365 /* Get the semaphore value for this resource */
1366 v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE);
1367 v = (v >> shift) & 0x03;
1368
1369 if (v == 0x03) {
1370 ret = CY_AS_ERROR_RESOURCE_ALREADY_OWNED;
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,
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);
1376 cy_as_hal_write_register(dev_p->tag,
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);
1379
1380 v = cy_as_hal_read_register(dev_p->tag,
1381 CY_AS_MEM_P0_RSE_ALLOCATE);
1382 v = (v >> shift) & 0x03;
1383 if (v == 0x03)
1384 ret = CY_AS_ERROR_SUCCESS;
1385 }
1386
1387 return ret;
1388 }
1389
1390 static cy_as_return_status_t
1391 my_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 {
1396 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1397
1398 if (cy_as_ll_request_response__get_code(reply_p) !=
1399 CY_RESP_SUCCESS_FAILURE) {
1400 ret = CY_AS_ERROR_INVALID_RESPONSE;
1401 goto destroy;
1402 }
1403
1404 if (ret == CY_AS_ERROR_SUCCESS) {
1405 ret = get_unallocated_resource(dev_p, *resource);
1406 if (ret != CY_AS_ERROR_NOT_ACQUIRED)
1407 ret = CY_AS_ERROR_SUCCESS;
1408 }
1409
1410 destroy:
1411 cy_as_ll_destroy_request(dev_p, req_p);
1412 cy_as_ll_destroy_response(dev_p, reply_p);
1413
1414 return ret;
1415 }
1416
1417 cy_as_return_status_t
1418 cy_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 {
1424 cy_as_ll_request_response *req_p, *reply_p;
1425 cy_as_return_status_t ret;
1426
1427 cy_as_device *dev_p;
1428
1429 (void)client;
1430
1431 cy_as_log_debug_message(6, "cy_as_misc_acquire_resource called");
1432
1433 if (*resource != cy_as_bus_u_s_b && *resource !=
1434 cy_as_bus_0 && *resource != cy_as_bus_1)
1435 return CY_AS_ERROR_INVALID_RESOURCE;
1436
1437
1438 /* Make sure the device is ready to accept the command. */
1439 dev_p = (cy_as_device *)handle;
1440 cy_as_check_device_ready(dev_p);
1441
1442 if (cy_as_device_is_in_suspend_mode(dev_p))
1443 return CY_AS_ERROR_IN_SUSPEND;
1444
1445
1446 ret = get_unallocated_resource(dev_p, *resource);
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,
1454 CY_FUNCT_CB_MISC_ACQUIRERESOURCE, resource);
1455
1456 if (ret != CY_AS_ERROR_NOT_ACQUIRED)
1457 return ret;
1458
1459 if (!force)
1460 return CY_AS_ERROR_NOT_ACQUIRED;
1461
1462 /* Create the request to acquire the resource */
1463 req_p = cy_as_ll_create_request(dev_p, CY_RQT_ACQUIRE_RESOURCE,
1464 CY_RQT_RESOURCE_RQT_CONTEXT, 1);
1465 if (req_p == 0)
1466 return CY_AS_ERROR_OUT_OF_MEMORY;
1467
1468 cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)(*resource));
1469
1470 reply_p = cy_as_ll_create_response(dev_p, 1);
1471 if (reply_p == 0) {
1472 cy_as_ll_destroy_request(dev_p, req_p);
1473 return CY_AS_ERROR_OUT_OF_MEMORY;
1474 }
1475
1476 if (cb == 0) {
1477 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1478 if (ret != CY_AS_ERROR_SUCCESS)
1479 goto destroy;
1480
1481 if (cy_as_ll_request_response__get_code(reply_p) !=
1482 CY_RESP_SUCCESS_FAILURE) {
1483 ret = CY_AS_ERROR_INVALID_RESPONSE;
1484 goto destroy;
1485 }
1486
1487 ret = cy_as_ll_request_response__get_word(reply_p, 0);
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,
1492 req_p, reply_p, cy_as_misc_func_callback);
1493
1494 if (ret != CY_AS_ERROR_SUCCESS)
1495 goto destroy;
1496
1497 /* The request and response are freed
1498 * as part of the MiscFuncCallback */
1499 return ret;
1500 }
1501
1502 destroy:
1503 cy_as_ll_destroy_request(dev_p, req_p);
1504 cy_as_ll_destroy_response(dev_p, reply_p);
1505
1506 if (ret == CY_AS_ERROR_SUCCESS) {
1507 ret = get_unallocated_resource(dev_p, *resource);
1508 if (ret != CY_AS_ERROR_NOT_ACQUIRED)
1509 ret = CY_AS_ERROR_SUCCESS;
1510 }
1511
1512 return ret;
1513 }
1514 EXPORT_SYMBOL(cy_as_misc_acquire_resource);
1515
1516 cy_as_return_status_t
1517 cy_as_misc_release_resource(cy_as_device_handle handle,
1518 cy_as_resource_type resource)
1519 {
1520 uint8_t shift = 0;
1521 uint16_t v;
1522
1523 cy_as_device *dev_p;
1524
1525 cy_as_log_debug_message(6, "cy_as_misc_release_resource called");
1526
1527 /* Make sure the device is ready for the command. */
1528 dev_p = (cy_as_device *)handle;
1529 cy_as_check_device_ready(dev_p);
1530
1531 if (cy_as_device_is_in_suspend_mode(dev_p))
1532 return CY_AS_ERROR_IN_SUSPEND;
1533
1534 if (resource != cy_as_bus_u_s_b && resource !=
1535 cy_as_bus_0 && resource != cy_as_bus_1)
1536 return CY_AS_ERROR_INVALID_RESOURCE;
1537
1538 switch (resource) {
1539 case cy_as_bus_u_s_b:
1540 shift = 4;
1541 break;
1542 case cy_as_bus_1:
1543 shift = 0;
1544 break;
1545 case cy_as_bus_0:
1546 shift = 2;
1547 break;
1548 default:
1549 cy_as_hal_assert(cy_false);
1550 break;
1551 }
1552
1553 /* Get the semaphore value for this resource */
1554 v = (cy_as_hal_read_register(dev_p->tag,
1555 CY_AS_MEM_P0_RSE_ALLOCATE) >> shift) & 0x03;
1556 if (v == 0 || v == 1 || v == 2)
1557 return CY_AS_ERROR_RESOURCE_NOT_OWNED;
1558
1559 cy_as_hal_write_register(dev_p->tag,
1560 CY_AS_MEM_P0_RSE_MASK, (0x03 << shift));
1561 cy_as_hal_write_register(dev_p->tag,
1562 CY_AS_MEM_P0_RSE_ALLOCATE, (0x02 << shift));
1563 cy_as_hal_write_register(dev_p->tag,
1564 CY_AS_MEM_P0_RSE_MASK, 0);
1565
1566 return CY_AS_ERROR_SUCCESS;
1567 }
1568 EXPORT_SYMBOL(cy_as_misc_release_resource);
1569
1570 cy_as_return_status_t
1571 cy_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 {
1579 cy_as_ll_request_response *req_p, *reply_p;
1580 cy_as_return_status_t ret;
1581 cy_as_device *dev_p;
1582
1583 cy_as_log_debug_message(6, "cy_as_misc_set_trace_level called");
1584
1585 /* Make sure the device is ready for the command. */
1586 dev_p = (cy_as_device *)handle;
1587 cy_as_check_device_ready(dev_p);
1588
1589 if (cy_as_device_is_in_suspend_mode(dev_p))
1590 return CY_AS_ERROR_IN_SUSPEND;
1591
1592 if (bus < 0 || bus >= CY_AS_MAX_BUSES)
1593 return CY_AS_ERROR_NO_SUCH_BUS;
1594
1595 if (device >= CY_AS_MAX_STORAGE_DEVICES)
1596 return CY_AS_ERROR_NO_SUCH_DEVICE;
1597
1598 if (unit > 255)
1599 return CY_AS_ERROR_NO_SUCH_UNIT;
1600
1601 if (level >= CYAS_FW_TRACE_MAX_LEVEL)
1602 return CY_AS_ERROR_INVALID_TRACE_LEVEL;
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,
1606 CY_RQT_GENERAL_RQT_CONTEXT, 2);
1607 if (req_p == 0)
1608 return CY_AS_ERROR_OUT_OF_MEMORY;
1609
1610 cy_as_ll_request_response__set_word(req_p, 0,
1611 (uint16_t)level);
1612 cy_as_ll_request_response__set_word(req_p, 1,
1613 (uint16_t)((bus << 12) | (device << 8) | (unit)));
1614
1615 /*
1616 * Reserve space for the reply, the reply data will not
1617 * exceed three words
1618 */
1619 reply_p = cy_as_ll_create_response(dev_p, 2);
1620 if (reply_p == 0) {
1621 cy_as_ll_destroy_request(dev_p, req_p);
1622 return CY_AS_ERROR_OUT_OF_MEMORY;
1623 }
1624
1625 if (cb == 0) {
1626 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1627 if (ret != CY_AS_ERROR_SUCCESS)
1628 goto destroy;
1629
1630 if (cy_as_ll_request_response__get_code(reply_p) !=
1631 CY_RESP_SUCCESS_FAILURE) {
1632 ret = CY_AS_ERROR_NOT_SUPPORTED;
1633 goto destroy;
1634 }
1635
1636 ret = cy_as_ll_request_response__get_word(reply_p, 0);
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,
1642 cy_as_misc_func_callback);
1643
1644 if (ret != CY_AS_ERROR_SUCCESS)
1645 goto destroy;
1646
1647 /* The request and response are freed as part of the
1648 * MiscFuncCallback */
1649 return ret;
1650 }
1651
1652 destroy:
1653 cy_as_ll_destroy_request(dev_p, req_p);
1654 cy_as_ll_destroy_response(dev_p, reply_p);
1655
1656 return ret;
1657 }
1658
1659 cy_as_return_status_t
1660 cy_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 {
1665 cy_as_ll_request_response *req_p, *reply_p;
1666 cy_as_return_status_t ret;
1667 cy_as_device *dev_p;
1668
1669 cy_as_log_debug_message(6, "cy_as_misc_heart_beat_control called");
1670
1671 /* Make sure the device is ready for the command. */
1672 dev_p = (cy_as_device *)handle;
1673 cy_as_check_device_ready(dev_p);
1674
1675 if (cy_as_device_is_in_suspend_mode(dev_p))
1676 return CY_AS_ERROR_IN_SUSPEND;
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,
1680 CY_RQT_GENERAL_RQT_CONTEXT, 1);
1681 if (req_p == 0)
1682 return CY_AS_ERROR_OUT_OF_MEMORY;
1683
1684 cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)enable);
1685
1686 /* Reserve space for the reply, the reply
1687 * data will not exceed one word */
1688 reply_p = cy_as_ll_create_response(dev_p, 1);
1689 if (reply_p == 0) {
1690 cy_as_ll_destroy_request(dev_p, req_p);
1691 return CY_AS_ERROR_OUT_OF_MEMORY;
1692 }
1693
1694 if (cb == 0) {
1695 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1696 if (ret != CY_AS_ERROR_SUCCESS)
1697 goto destroy;
1698
1699 if (cy_as_ll_request_response__get_code(reply_p) !=
1700 CY_RESP_SUCCESS_FAILURE) {
1701 ret = CY_AS_ERROR_INVALID_RESPONSE;
1702 goto destroy;
1703 }
1704
1705 ret = cy_as_ll_request_response__get_word(reply_p, 0);
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,
1711 req_p, reply_p, cy_as_misc_func_callback);
1712
1713 if (ret != CY_AS_ERROR_SUCCESS)
1714 goto destroy;
1715
1716 /* The request and response are freed as part of the
1717 * MiscFuncCallback */
1718 return ret;
1719 }
1720
1721 destroy:
1722 cy_as_ll_destroy_request(dev_p, req_p);
1723 cy_as_ll_destroy_response(dev_p, reply_p);
1724
1725 return ret;
1726 }
1727 EXPORT_SYMBOL(cy_as_misc_heart_beat_control);
1728
1729 static cy_as_return_status_t
1730 my_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 {
1737 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1738 cy_as_ll_request_response *req_p, *reply_p;
1739
1740 if (cy_as_device_is_in_callback(dev_p) && (cb == 0))
1741 return CY_AS_ERROR_INVALID_IN_CALLBACK;
1742
1743 req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_SD_CLOCK_FREQ,
1744 CY_RQT_GENERAL_RQT_CONTEXT, 1);
1745 if (req_p == 0)
1746 return CY_AS_ERROR_OUT_OF_MEMORY;
1747
1748 cy_as_ll_request_response__set_word(req_p, 0,
1749 (uint16_t)((card_type << 8) | setting));
1750
1751 /* Reserve space for the reply, which will not exceed one word. */
1752 reply_p = cy_as_ll_create_response(dev_p, 1);
1753 if (reply_p == 0) {
1754 cy_as_ll_destroy_request(dev_p, req_p);
1755 return CY_AS_ERROR_OUT_OF_MEMORY;
1756 }
1757
1758 if (cb == 0) {
1759 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1760 if (ret != CY_AS_ERROR_SUCCESS)
1761 goto destroy;
1762
1763 if (cy_as_ll_request_response__get_code(reply_p) !=
1764 CY_RESP_SUCCESS_FAILURE) {
1765 ret = CY_AS_ERROR_INVALID_RESPONSE;
1766 goto destroy;
1767 }
1768
1769 ret = cy_as_ll_request_response__get_word(reply_p, 0);
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,
1774 cy_as_misc_func_callback);
1775
1776 if (ret != CY_AS_ERROR_SUCCESS)
1777 goto destroy;
1778
1779 /* The request and response are freed as part of the
1780 * MiscFuncCallback */
1781 return ret;
1782 }
1783
1784 destroy:
1785 cy_as_ll_destroy_request(dev_p, req_p);
1786 cy_as_ll_destroy_response(dev_p, reply_p);
1787
1788 return ret;
1789 }
1790
1791 cy_as_return_status_t
1792 cy_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 {
1798 cy_as_device *dev_p;
1799
1800 cy_as_log_debug_message(6, "cy_as_misc_set_low_speed_sd_freq called");
1801
1802 /* Make sure the device is ready for the command. */
1803 dev_p = (cy_as_device *)handle;
1804 cy_as_check_device_ready(dev_p);
1805
1806 if (cy_as_device_is_in_suspend_mode(dev_p))
1807 return CY_AS_ERROR_IN_SUSPEND;
1808
1809 if ((setting != CY_AS_SD_DEFAULT_FREQ) &&
1810 (setting != CY_AS_SD_RATED_FREQ))
1811 return CY_AS_ERROR_INVALID_PARAMETER;
1812
1813 return my_set_sd_clock_freq(dev_p, 0, (uint8_t)setting, cb, client);
1814 }
1815 EXPORT_SYMBOL(cy_as_misc_set_low_speed_sd_freq);
1816
1817 cy_as_return_status_t
1818 cy_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 {
1824 cy_as_device *dev_p;
1825
1826 cy_as_log_debug_message(6, "cy_as_misc_set_high_speed_sd_freq called");
1827
1828 /* Make sure the device is ready for the command. */
1829 dev_p = (cy_as_device *)handle;
1830 cy_as_check_device_ready(dev_p);
1831
1832 if (cy_as_device_is_in_suspend_mode(dev_p))
1833 return CY_AS_ERROR_IN_SUSPEND;
1834
1835 if ((setting != CY_AS_HS_SD_FREQ_24) &&
1836 (setting != CY_AS_HS_SD_FREQ_48))
1837 return CY_AS_ERROR_INVALID_PARAMETER;
1838
1839 return my_set_sd_clock_freq(dev_p, 1, (uint8_t)setting, cb, client);
1840 }
1841 EXPORT_SYMBOL(cy_as_misc_set_high_speed_sd_freq);
1842
1843 cy_as_return_status_t
1844 cy_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 {
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;
1854
1855 cy_as_log_debug_message(6, "cy_as_misc_get_gpio_value called");
1856
1857 /* Make sure the device is ready for the command. */
1858 dev_p = (cy_as_device *)handle;
1859 cy_as_check_device_ready(dev_p);
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) {
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);
1866
1867 if (cb != 0)
1868 cb(dev_p, ret, client,
1869 CY_FUNCT_CB_MISC_GETGPIOVALUE, value);
1870
1871 return ret;
1872 }
1873
1874 /* Check whether the firmware supports this command. */
1875 if (cy_as_device_is_nand_storage_supported(dev_p))
1876 return CY_AS_ERROR_NOT_SUPPORTED;
1877
1878 if (cy_as_device_is_in_suspend_mode(dev_p))
1879 return CY_AS_ERROR_IN_SUSPEND;
1880
1881 /* Make sure the pin selected is valid */
1882 if ((pin != cy_as_misc_gpio_1) && (pin != cy_as_misc_gpio_0))
1883 return CY_AS_ERROR_INVALID_PARAMETER;
1884
1885 req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_GPIO_STATE,
1886 CY_RQT_GENERAL_RQT_CONTEXT, 1);
1887 if (req_p == 0)
1888 return CY_AS_ERROR_OUT_OF_MEMORY;
1889
1890 cy_as_ll_request_response__set_word(req_p, 0, ((uint8_t)pin << 8));
1891
1892 /* Reserve space for the reply, which will not exceed one word. */
1893 reply_p = cy_as_ll_create_response(dev_p, 1);
1894 if (reply_p == 0) {
1895 cy_as_ll_destroy_request(dev_p, req_p);
1896 return CY_AS_ERROR_OUT_OF_MEMORY;
1897 }
1898
1899 if (cb == 0) {
1900 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1901 if (ret != CY_AS_ERROR_SUCCESS)
1902 goto destroy;
1903
1904 if (cy_as_ll_request_response__get_code(reply_p) !=
1905 CY_RESP_GPIO_STATE) {
1906 ret = CY_AS_ERROR_INVALID_RESPONSE;
1907 goto destroy;
1908 }
1909
1910 *value = (uint8_t)
1911 cy_as_ll_request_response__get_word(reply_p, 0);
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,
1917 req_p, reply_p, cy_as_misc_func_callback);
1918
1919 if (ret != CY_AS_ERROR_SUCCESS)
1920 goto destroy;
1921
1922 /* The request and response are freed as part of the
1923 * MiscFuncCallback */
1924 return ret;
1925 }
1926
1927 destroy:
1928 cy_as_ll_destroy_request(dev_p, req_p);
1929 cy_as_ll_destroy_response(dev_p, reply_p);
1930
1931 return ret;
1932 }
1933 EXPORT_SYMBOL(cy_as_misc_get_gpio_value);
1934
1935 cy_as_return_status_t
1936 cy_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 {
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;
1946
1947 cy_as_log_debug_message(6, "cy_as_misc_set_gpio_value called");
1948
1949 /* Make sure the device is ready for the command. */
1950 dev_p = (cy_as_device *)handle;
1951 cy_as_check_device_ready(dev_p);
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) {
1956 v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PMU_UPDATE);
1957 if (value)
1958 cy_as_hal_write_register(dev_p->tag,
1959 CY_AS_MEM_PMU_UPDATE,
1960 (v | CY_AS_MEM_PMU_UPDATE_UVALID));
1961 else
1962 cy_as_hal_write_register(dev_p->tag,
1963 CY_AS_MEM_PMU_UPDATE,
1964 (v & ~CY_AS_MEM_PMU_UPDATE_UVALID));
1965
1966 if (cb != 0)
1967 cb(dev_p, ret, client,
1968 CY_FUNCT_CB_MISC_SETGPIOVALUE, 0);
1969 return ret;
1970 }
1971
1972 /* Check whether the firmware supports this command. */
1973 if (cy_as_device_is_nand_storage_supported(dev_p))
1974 return CY_AS_ERROR_NOT_SUPPORTED;
1975
1976 if (cy_as_device_is_in_suspend_mode(dev_p))
1977 return CY_AS_ERROR_IN_SUSPEND;
1978
1979 /* Make sure the pin selected is valid */
1980 if ((pin < cy_as_misc_gpio_0) || (pin > cy_as_misc_gpio_U_valid))
1981 return CY_AS_ERROR_INVALID_PARAMETER;
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,
1985 CY_RQT_GENERAL_RQT_CONTEXT, 1);
1986 if (req_p == 0)
1987 return CY_AS_ERROR_OUT_OF_MEMORY;
1988
1989 v = (uint16_t)(((uint8_t)pin << 8) | (value > 0));
1990 cy_as_ll_request_response__set_word(req_p, 0, v);
1991
1992 /* Reserve space for the reply, which will not exceed one word. */
1993 reply_p = cy_as_ll_create_response(dev_p, 1);
1994 if (reply_p == 0) {
1995 cy_as_ll_destroy_request(dev_p, req_p);
1996 return CY_AS_ERROR_OUT_OF_MEMORY;
1997 }
1998
1999 if (cb == 0) {
2000 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2001 if (ret != CY_AS_ERROR_SUCCESS)
2002 goto destroy;
2003
2004 if (cy_as_ll_request_response__get_code(reply_p) !=
2005 CY_RESP_SUCCESS_FAILURE) {
2006 ret = CY_AS_ERROR_INVALID_RESPONSE;
2007 goto destroy;
2008 }
2009
2010 ret = cy_as_ll_request_response__get_word(reply_p, 0);
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,
2016 req_p, reply_p, cy_as_misc_func_callback);
2017
2018 if (ret != CY_AS_ERROR_SUCCESS)
2019 goto destroy;
2020
2021 /* The request and response are freed as part of the
2022 * MiscFuncCallback */
2023 return ret;
2024 }
2025
2026 destroy:
2027 cy_as_ll_destroy_request(dev_p, req_p);
2028 cy_as_ll_destroy_response(dev_p, reply_p);
2029
2030 return ret;
2031 }
2032 EXPORT_SYMBOL(cy_as_misc_set_gpio_value);
2033
2034 static cy_as_return_status_t
2035 my_enter_standby(cy_as_device *dev_p, cy_bool pin)
2036 {
2037 cy_as_misc_cancel_ex_requests(dev_p);
2038
2039 /* Save the current values in the critical P-port
2040 * registers, where necessary. */
2041 cy_as_hal_read_regs_before_standby(dev_p->tag);
2042
2043 if (pin) {
2044 if (cy_as_hal_set_wakeup_pin(dev_p->tag, cy_false))
2045 cy_as_device_set_pin_standby(dev_p);
2046 else
2047 return CY_AS_ERROR_SETTING_WAKEUP_PIN;
2048 } else {
2049 /*
2050 * put antioch in the standby mode
2051 */
2052 cy_as_hal_write_register(dev_p->tag,
2053 CY_AS_MEM_PWR_MAGT_STAT, 0x02);
2054 cy_as_device_set_register_standby(dev_p);
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 */
2062 cy_as_device_set_firmware_not_loaded(dev_p);
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
2070 return CY_AS_ERROR_SUCCESS;
2071 }
2072
2073 static cy_as_return_status_t
2074 my_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 {
2079 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2080
2081 if (cy_as_ll_request_response__get_code(reply_p) !=
2082 CY_RESP_SUCCESS_FAILURE) {
2083 ret = CY_AS_ERROR_INVALID_RESPONSE;
2084 goto destroy;
2085 }
2086
2087 ret = cy_as_ll_request_response__get_word(reply_p, 0);
2088
2089 destroy:
2090 cy_as_ll_destroy_request(dev_p, req_p);
2091 cy_as_ll_destroy_response(dev_p, reply_p);
2092
2093 if (ret != CY_AS_ERROR_SUCCESS)
2094 return ret;
2095
2096 ret = my_enter_standby(dev_p, pin);
2097
2098 return ret;
2099 }
2100
2101 cy_as_return_status_t
2102 cy_as_misc_enter_standby(cy_as_device_handle handle,
2103 cy_bool pin,
2104 cy_as_function_callback cb,
2105 uint32_t client)
2106 {
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;
2111
2112 cy_as_log_debug_message(6, "cy_as_misc_enter_standby called");
2113
2114 /* Make sure we have a valid device */
2115 dev_p = (cy_as_device *)handle;
2116 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2117 return CY_AS_ERROR_INVALID_HANDLE;
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 */
2123 ret = cy_as_misc_in_standby(handle, &standby);
2124 if (ret != CY_AS_ERROR_SUCCESS)
2125 return ret;
2126
2127 if (standby == cy_true)
2128 return CY_AS_ERROR_ALREADY_STANDBY;
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))
2136 cy_as_misc_leave_suspend(dev_p, 0, 0);
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 */
2144 return CY_AS_ERROR_USB_RUNNING;
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())
2160 return CY_AS_ERROR_ASYNC_PENDING;
2161
2162 cy_as_dma_drain_queue(dev_p,
2163 CY_AS_P2S_READ_ENDPOINT, cy_false);
2164 cy_as_dma_drain_queue(dev_p,
2165 CY_AS_P2S_WRITE_ENDPOINT, cy_false);
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))
2172 return CY_AS_ERROR_ASYNC_PENDING;
2173 }
2174
2175 req_p = cy_as_ll_create_request(dev_p,
2176 CY_RQT_PREPARE_FOR_STANDBY,
2177 CY_RQT_GENERAL_RQT_CONTEXT, 1);
2178 if (req_p == 0)
2179 return CY_AS_ERROR_OUT_OF_MEMORY;
2180
2181 reply_p = cy_as_ll_create_response(dev_p, 1);
2182 if (reply_p == 0) {
2183 cy_as_ll_destroy_request(dev_p, req_p);
2184 return CY_AS_ERROR_OUT_OF_MEMORY;
2185 }
2186
2187 if (!cb) {
2188 ret = cy_as_ll_send_request_wait_reply(dev_p,
2189 req_p, reply_p);
2190 if (ret != CY_AS_ERROR_SUCCESS)
2191 goto destroy;
2192
2193 /* The request and response are freed
2194 * in the HandleResponse */
2195 return my_handle_response_enter_standby(dev_p,
2196 req_p, reply_p, pin);
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,
2202 req_p, reply_p, cy_as_misc_func_callback);
2203
2204 if (ret != CY_AS_ERROR_SUCCESS)
2205 goto destroy;
2206
2207 /* The request and response are freed
2208 * as part of the MiscFuncCallback */
2209 return ret;
2210 }
2211 destroy:
2212 cy_as_ll_destroy_request(dev_p, req_p);
2213 cy_as_ll_destroy_response(dev_p, reply_p);
2214 } else {
2215 ret = my_enter_standby(dev_p, pin);
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,
2221 CY_FUNCT_CB_MISC_ENTERSTANDBY, 0);
2222 }
2223
2224 return ret;
2225 }
2226 EXPORT_SYMBOL(cy_as_misc_enter_standby);
2227
2228 cy_as_return_status_t
2229 cy_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 {
2235 cy_as_device *dev_p;
2236
2237 dev_p = (cy_as_device *)handle;
2238 if (uvalid_special)
2239 cy_as_hal_write_register(dev_p->tag, 0xc5, 0x4);
2240
2241 return cy_as_misc_enter_standby(handle, pin, cb, client);
2242 }
2243
2244 cy_as_return_status_t
2245 cy_as_misc_leave_standby(cy_as_device_handle handle,
2246 cy_as_resource_type resource)
2247 {
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;
2253
2254 cy_as_log_debug_message(6, "cy_as_misc_leave_standby called");
2255 (void)resource;
2256
2257 /* Make sure we have a valid device */
2258 dev_p = (cy_as_device *)handle;
2259 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2260 return CY_AS_ERROR_INVALID_HANDLE;
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 */
2267 cy_as_device_set_waking(dev_p);
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,
2275 CY_AS_MEM_CM_WB_CFG_ID);
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(
2286 CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL);
2287 else
2288 cy_as_hal_sleep(
2289 CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
2290 v = cy_as_hal_read_register(dev_p->tag,
2291 CY_AS_MEM_CM_WB_CFG_ID);
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(
2302 dev_p->stby_int_mask);
2303 return CY_AS_ERROR_TIMEOUT;
2304 }
2305 }
2306 } while (!is_valid_silicon_id(v) && count-- > 0);
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(
2314 dev_p->stby_int_mask);
2315 return CY_AS_ERROR_TIMEOUT;
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 */
2324 cy_as_device_clear_register_standby(dev_p);
2325
2326 /*
2327 * initialize any registers that may have been changed
2328 * while the device was in standby mode.
2329 */
2330 cy_as_hal_init_dev_registers(dev_p->tag, cy_true);
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 */
2336 cy_as_device_set_waking(dev_p);
2337
2338 try_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)) {
2344 cy_as_hal_enable_interrupts(dev_p->stby_int_mask);
2345 return CY_AS_ERROR_SETTING_WAKEUP_PIN;
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))
2355 cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL);
2356 else
2357 cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
2358
2359 /*
2360 * initialize any registers that may have been changed
2361 * while the device was in standby mode.
2362 */
2363 cy_as_hal_init_dev_registers(dev_p->tag, cy_true);
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 */
2371 cy_as_device_clear_pin_standby(dev_p);
2372 } else {
2373 return CY_AS_ERROR_NOT_IN_STANDBY;
2374 }
2375
2376 /*
2377 * the west bridge interrupt can be enabled now.
2378 */
2379 cy_as_hal_enable_interrupts(dev_p->stby_int_mask);
2380
2381 /*
2382 * release the west bridge micro-_controller from reset,
2383 * so that firmware initialization can complete. the attempt
2384 * to release antioch reset is made up to 8 times.
2385 */
2386 v = 0x03;
2387 count = 0x08;
2388 while ((v & 0x03) && (count)) {
2389 cy_as_hal_write_register(dev_p->tag,
2390 CY_AS_MEM_RST_CTRL_REG, 0x00);
2391 v = cy_as_hal_read_register(dev_p->tag,
2392 CY_AS_MEM_RST_CTRL_REG);
2393 count--;
2394 }
2395
2396 if (v & 0x03) {
2397 cy_as_hal_print_message("failed to clear antioch reset\n");
2398 return CY_AS_ERROR_TIMEOUT;
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) {
2408 count = 10;
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))
2413 break;
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,
2420 CY_AS_MEM_P0_INTR_REG);
2421 if (v & CY_AS_MEM_P0_INTR_REG_MBINT)
2422 break;
2423
2424 cy_as_hal_sleep(10);
2425 count--;
2426 }
2427
2428 if (!count) {
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;
2434 }
2435 }
2436
2437 return ret;
2438 }
2439 EXPORT_SYMBOL(cy_as_misc_leave_standby);
2440
2441 cy_as_return_status_t
2442 cy_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 {
2449 cy_as_device *dev_p;
2450
2451 cy_as_log_debug_message(6, "cy_as_misc_register_callback called");
2452
2453 /* Make sure we have a valid device */
2454 dev_p = (cy_as_device *)handle;
2455 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2456 return CY_AS_ERROR_INVALID_HANDLE;
2457
2458 dev_p->misc_event_cb = callback;
2459 return CY_AS_ERROR_SUCCESS;
2460 }
2461
2462 cy_as_return_status_t
2463 cy_as_misc_storage_changed(cy_as_device_handle handle,
2464 cy_as_function_callback cb,
2465 uint32_t client)
2466 {
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;
2471
2472 cy_as_log_debug_message(6, "cy_as_misc_storage_changed called");
2473
2474 /* Make sure the device is ready for the command. */
2475 dev_p = (cy_as_device *)handle;
2476 cy_as_check_device_ready(dev_p);
2477
2478 /*
2479 * make sure antioch is not in standby
2480 */
2481 ret = cy_as_misc_in_standby(dev_p, &standby);
2482 if (ret != CY_AS_ERROR_SUCCESS)
2483 return ret;
2484
2485 if (standby)
2486 return CY_AS_ERROR_IN_STANDBY;
2487
2488 /*
2489 * make sure westbridge is not in suspend mode.
2490 */
2491 if (cy_as_device_is_in_suspend_mode(dev_p))
2492 return CY_AS_ERROR_IN_SUSPEND;
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,
2496 CY_RQT_GENERAL_RQT_CONTEXT, 0);
2497 if (req_p == 0)
2498 return CY_AS_ERROR_OUT_OF_MEMORY;
2499
2500 /* Reserve space for the reply, the reply data will
2501 * not exceed one word */
2502 reply_p = cy_as_ll_create_response(dev_p, 1);
2503 if (reply_p == 0) {
2504 cy_as_ll_destroy_request(dev_p, req_p);
2505 return CY_AS_ERROR_OUT_OF_MEMORY;
2506 }
2507
2508 if (cb == 0) {
2509 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2510 if (ret != CY_AS_ERROR_SUCCESS)
2511 goto destroy;
2512
2513 if (cy_as_ll_request_response__get_code(reply_p) !=
2514 CY_RESP_SUCCESS_FAILURE) {
2515 ret = CY_AS_ERROR_INVALID_RESPONSE;
2516 goto destroy;
2517 }
2518
2519 ret = cy_as_ll_request_response__get_word(reply_p, 0);
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,
2525 req_p, reply_p, cy_as_misc_func_callback);
2526
2527 if (ret != CY_AS_ERROR_SUCCESS)
2528 goto destroy;
2529
2530 /* The request and response are freed as part of the
2531 * MiscFuncCallback */
2532 return ret;
2533 }
2534
2535 destroy:
2536 cy_as_ll_destroy_request(dev_p, req_p);
2537 cy_as_ll_destroy_response(dev_p, reply_p);
2538
2539 return ret;
2540 }
2541 EXPORT_SYMBOL(cy_as_misc_storage_changed);
2542
2543 cy_as_return_status_t
2544 cy_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 {
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;
2557
2558 cy_as_log_debug_message(6, "cy_as_misc_enter_suspend called");
2559
2560 /*
2561 * basic sanity checks to ensure that the device is initialised.
2562 */
2563 dev_p = (cy_as_device *)handle;
2564 cy_as_check_device_ready(dev_p);
2565
2566 /*
2567 * make sure west bridge is not already in standby
2568 */
2569 cy_as_misc_in_standby(dev_p, &standby);
2570 if (standby)
2571 return CY_AS_ERROR_IN_STANDBY;
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))
2577 return CY_AS_ERROR_IN_SUSPEND;
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))
2584 return CY_AS_ERROR_USB_CONNECTED;
2585
2586 /*
2587 * make sure that there are no async requests at this point in time.
2588 */
2589 int_state = cy_as_hal_disable_interrupts();
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)) {
2592 cy_as_hal_enable_interrupts(int_state);
2593 return CY_AS_ERROR_ASYNC_PENDING;
2594 }
2595 cy_as_hal_enable_interrupts(int_state);
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,
2599 CY_RQT_GENERAL_RQT_CONTEXT, 1);
2600 if (req_p == 0)
2601 return CY_AS_ERROR_OUT_OF_MEMORY;
2602
2603 /* Reserve space for the reply, the reply data will not
2604 * exceed one word */
2605 reply_p = cy_as_ll_create_response(dev_p, 1);
2606 if (reply_p == 0) {
2607 cy_as_ll_destroy_request(dev_p, req_p);
2608 return CY_AS_ERROR_OUT_OF_MEMORY;
2609 }
2610
2611 /* Wakeup control flags. */
2612 value = 0x0001;
2613 if (usb_wakeup_en)
2614 value |= 0x04;
2615 if (gpio_wakeup_en)
2616 value |= 0x02;
2617 cy_as_ll_request_response__set_word(req_p, 0, value);
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,
2625 cy_as_misc_func_callback);
2626
2627 if (ret != CY_AS_ERROR_SUCCESS)
2628 goto destroy;
2629
2630 return CY_AS_ERROR_SUCCESS;
2631 } else {
2632 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2633 if (cy_as_ll_request_response__get_code(reply_p) !=
2634 CY_RESP_SUCCESS_FAILURE)
2635 ret = CY_AS_ERROR_INVALID_RESPONSE;
2636 else
2637 ret = cy_as_ll_request_response__get_word(reply_p, 0);
2638 }
2639
2640 destroy:
2641 if (ret == CY_AS_ERROR_SUCCESS)
2642 cy_as_device_set_suspend_mode(dev_p);
2643
2644 cy_as_ll_destroy_request(dev_p, req_p);
2645 cy_as_ll_destroy_response(dev_p, reply_p);
2646
2647 return ret;
2648 }
2649 EXPORT_SYMBOL(cy_as_misc_enter_suspend);
2650
2651 cy_as_return_status_t
2652 cy_as_misc_leave_suspend(
2653 cy_as_device_handle handle,
2654 cy_as_function_callback cb,
2655 uint32_t client)
2656 {
2657 cy_as_device *dev_p;
2658 uint16_t v, count;
2659 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2660
2661 cy_as_log_debug_message(6, "cy_as_misc_leave_suspend called");
2662
2663 /* Make sure we have a valid device */
2664 dev_p = (cy_as_device *)handle;
2665 cy_as_check_device_ready(dev_p);
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,
2672 CY_FUNCT_CB_MISC_LEAVESUSPEND, 0);
2673 if (cbnode == 0)
2674 return CY_AS_ERROR_OUT_OF_MEMORY;
2675
2676 cy_as_insert_c_b_node(dev_p->func_cbs_misc, cbnode);
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 */
2684 count = 8;
2685
2686 v = cy_as_hal_read_register(dev_p->tag,
2687 CY_AS_MEM_CM_WB_CFG_ID);
2688
2689 while (!is_valid_silicon_id(v) && count-- > 0) {
2690 cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
2691 v = cy_as_hal_read_register(dev_p->tag,
2692 CY_AS_MEM_CM_WB_CFG_ID);
2693 }
2694
2695 /*
2696 * if we tried to read the register and could not,
2697 * return a timeout
2698 */
2699 if (count == 0)
2700 return CY_AS_ERROR_TIMEOUT;
2701 } else
2702 return CY_AS_ERROR_NOT_IN_SUSPEND;
2703
2704 if (cb == 0) {
2705 /*
2706 * wait until the in suspend mode flag is cleared.
2707 */
2708 count = 20;
2709 while ((cy_as_device_is_in_suspend_mode(dev_p))
2710 && (count--)) {
2711 cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
2712 }
2713
2714 if (cy_as_device_is_in_suspend_mode(dev_p))
2715 ret = CY_AS_ERROR_TIMEOUT;
2716 }
2717
2718 return ret;
2719 }
2720 EXPORT_SYMBOL(cy_as_misc_leave_suspend);
2721
2722 cy_as_return_status_t
2723 cy_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 {
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;
2731
2732 cy_as_device *dev_p;
2733
2734 (void)client;
2735
2736 cy_as_log_debug_message(6, "cy_as_misc_switch_pnand_mode called");
2737
2738 /* Make sure we have a valid device */
2739 dev_p = (cy_as_device *)handle;
2740 cy_as_check_device_ready(dev_p);
2741
2742 /*
2743 * make sure antioch is not in standby
2744 */
2745 ret = cy_as_misc_in_standby(dev_p, &standby);
2746 if (ret != CY_AS_ERROR_SUCCESS)
2747 return ret;
2748 if (standby)
2749 return CY_AS_ERROR_IN_STANDBY;
2750
2751 /* Make sure the Antioch is not in suspend mode. */
2752 if (cy_as_device_is_in_suspend_mode(dev_p))
2753 return CY_AS_ERROR_IN_SUSPEND;
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,
2758 CY_RQT_GENERAL_RQT_CONTEXT, 1);
2759 if (req_p == 0)
2760 return CY_AS_ERROR_OUT_OF_MEMORY;
2761 cy_as_ll_request_response__set_word(req_p,
2762 0, (uint16_t)numzones);
2763
2764 /* Reserve space for the reply, the reply data will not
2765 * exceed one word */
2766 reply_p = cy_as_ll_create_response(dev_p, 1);
2767 if (reply_p == 0) {
2768 cy_as_ll_destroy_request(dev_p, req_p);
2769 return CY_AS_ERROR_OUT_OF_MEMORY;
2770 }
2771
2772 if (cb == 0) {
2773 ret = cy_as_ll_send_request_wait_reply(dev_p,
2774 req_p, reply_p);
2775 if (ret != CY_AS_ERROR_SUCCESS)
2776 goto destroy;
2777
2778 if (cy_as_ll_request_response__get_code(reply_p) !=
2779 CY_RESP_SUCCESS_FAILURE) {
2780 ret = CY_AS_ERROR_INVALID_RESPONSE;
2781 goto destroy;
2782 }
2783
2784 ret = cy_as_ll_request_response__get_word(reply_p, 0);
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,
2790 req_p, reply_p, cy_as_misc_func_callback);
2791
2792 if (ret != CY_AS_ERROR_SUCCESS)
2793 goto destroy;
2794
2795 /* The request and response are freed as part of the
2796 * MiscFuncCallback */
2797 return ret;
2798 }
2799
2800 destroy:
2801 cy_as_ll_destroy_request(dev_p, req_p);
2802 cy_as_ll_destroy_response(dev_p, reply_p);
2803
2804 return ret;
2805 }
2806
2807 cy_as_func_c_b_node*
2808 cy_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 {
2813 uint32_t state = cy_as_hal_disable_interrupts();
2814 cy_as_func_c_b_node *node = cy_as_hal_c_b_alloc(
2815 sizeof(cy_as_func_c_b_node));
2816 cy_as_hal_enable_interrupts(state);
2817 if (node != 0) {
2818 node->node_type = CYAS_FUNC_CB;
2819 node->cb_p = cb;
2820 node->client_data = client;
2821 node->data_type = type;
2822 if (data != 0)
2823 node->data_type |= CY_FUNCT_CB_DATA;
2824 else
2825 node->data_type |= CY_FUNCT_CB_NODATA;
2826 node->data = data;
2827 node->next_p = 0;
2828 }
2829 return node;
2830 }
2831
2832 cy_as_func_c_b_node*
2833 cy_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,
2837 CY_FUNCT_CB_NODATA, 0);
2838 }
2839
2840 void
2841 cy_as_destroy_func_c_b_node(cy_as_func_c_b_node *node)
2842 {
2843 uint32_t state;
2844
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);
2849 }
2850
2851 cy_as_usb_func_c_b_node*
2852 cy_as_create_usb_func_c_b_node(
2853 cy_as_usb_function_callback cb, uint32_t client)
2854 {
2855 uint32_t state = cy_as_hal_disable_interrupts();
2856 cy_as_usb_func_c_b_node *node = cy_as_hal_c_b_alloc(
2857 sizeof(cy_as_usb_func_c_b_node));
2858 cy_as_hal_enable_interrupts(state);
2859 if (node != 0) {
2860 node->type = CYAS_USB_FUNC_CB;
2861 node->cb_p = cb;
2862 node->client_data = client;
2863 node->next_p = 0;
2864 }
2865 return node;
2866 }
2867
2868 void
2869 cy_as_destroy_usb_func_c_b_node(cy_as_usb_func_c_b_node *node)
2870 {
2871 uint32_t state;
2872
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);
2877 }
2878
2879 cy_as_usb_io_c_b_node*
2880 cy_as_create_usb_io_c_b_node(cy_as_usb_io_callback cb)
2881 {
2882 uint32_t state = cy_as_hal_disable_interrupts();
2883 cy_as_usb_io_c_b_node *node = cy_as_hal_c_b_alloc(
2884 sizeof(cy_as_usb_io_c_b_node));
2885 cy_as_hal_enable_interrupts(state);
2886 if (node != 0) {
2887 node->type = CYAS_USB_IO_CB;
2888 node->cb_p = cb;
2889 node->next_p = 0;
2890 }
2891 return node;
2892 }
2893
2894 void
2895 cy_as_destroy_usb_io_c_b_node(cy_as_usb_io_c_b_node *node)
2896 {
2897 uint32_t state;
2898
2899 node->type = CYAS_INVALID;
2900
2901 state = cy_as_hal_disable_interrupts();
2902 cy_as_hal_c_b_free(node);
2903 cy_as_hal_enable_interrupts(state);
2904 }
2905
2906 cy_as_storage_io_c_b_node*
2907 cy_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 {
2913 uint32_t state = cy_as_hal_disable_interrupts();
2914 cy_as_storage_io_c_b_node *node = cy_as_hal_c_b_alloc(
2915 sizeof(cy_as_storage_io_c_b_node));
2916 cy_as_hal_enable_interrupts(state);
2917 if (node != 0) {
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;
2928 }
2929 return node;
2930 }
2931
2932 void
2933 cy_as_destroy_storage_io_c_b_node(cy_as_storage_io_c_b_node *node)
2934 {
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);
2940 }
2941
2942 cy_as_c_b_queue *
2943 cy_as_create_c_b_queue(cy_as_c_b_node_type type)
2944 {
2945 uint32_t state = cy_as_hal_disable_interrupts();
2946 cy_as_c_b_queue *queue = cy_as_hal_c_b_alloc(
2947 sizeof(cy_as_c_b_queue));
2948 cy_as_hal_enable_interrupts(state);
2949 if (queue) {
2950 queue->type = type;
2951 queue->head_p = 0;
2952 queue->tail_p = 0;
2953 queue->count = 0;
2954 }
2955
2956 return queue;
2957 }
2958
2959 void
2960 cy_as_destroy_c_b_queue(cy_as_c_b_queue *queue)
2961 {
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);
2970 }
2971
2972 /* Inserts a CyAsCBNode into the queue, the
2973 * node type must match the queue type*/
2974 void
2975 cy_as_insert_c_b_node(cy_as_c_b_queue *queue_p, void*cbnode)
2976 {
2977 uint32_t int_state;
2978
2979 int_state = cy_as_hal_disable_interrupts();
2980
2981 cy_as_hal_assert(queue_p != 0);
2982
2983 switch (queue_p->type) {
2984 case CYAS_USB_FUNC_CB:
2985 {
2986 cy_as_usb_func_c_b_node *node =
2987 (cy_as_usb_func_c_b_node *)cbnode;
2988 cy_as_usb_func_c_b_node *tail =
2989 (cy_as_usb_func_c_b_node *)queue_p->tail_p;
2990
2991 cy_as_hal_assert(node->type == CYAS_USB_FUNC_CB);
2992 cy_as_hal_assert(tail == 0 ||
2993 tail->type == CYAS_USB_FUNC_CB);
2994 if (queue_p->head_p == 0)
2995 queue_p->head_p = node;
2996 else
2997 tail->next_p = node;
2998
2999 queue_p->tail_p = node;
3000 }
3001 break;
3002
3003 case CYAS_USB_IO_CB:
3004 {
3005 cy_as_usb_io_c_b_node *node =
3006 (cy_as_usb_io_c_b_node *)cbnode;
3007 cy_as_usb_io_c_b_node *tail =
3008 (cy_as_usb_io_c_b_node *)queue_p->tail_p;
3009
3010 cy_as_hal_assert(node->type == CYAS_USB_IO_CB);
3011 cy_as_hal_assert(tail == 0 ||
3012 tail->type == CYAS_USB_IO_CB);
3013 if (queue_p->head_p == 0)
3014 queue_p->head_p = node;
3015 else
3016 tail->next_p = node;
3017
3018 queue_p->tail_p = node;
3019 }
3020 break;
3021
3022 case CYAS_STORAGE_IO_CB:
3023 {
3024 cy_as_storage_io_c_b_node *node =
3025 (cy_as_storage_io_c_b_node *)cbnode;
3026 cy_as_storage_io_c_b_node *tail =
3027 (cy_as_storage_io_c_b_node *)queue_p->tail_p;
3028
3029 cy_as_hal_assert(node->type == CYAS_STORAGE_IO_CB);
3030 cy_as_hal_assert(tail == 0 ||
3031 tail->type == CYAS_STORAGE_IO_CB);
3032 if (queue_p->head_p == 0)
3033 queue_p->head_p = node;
3034 else
3035 tail->next_p = node;
3036
3037 queue_p->tail_p = node;
3038 }
3039 break;
3040
3041 case CYAS_FUNC_CB:
3042 {
3043 cy_as_func_c_b_node *node =
3044 (cy_as_func_c_b_node *)cbnode;
3045 cy_as_func_c_b_node *tail =
3046 (cy_as_func_c_b_node *)queue_p->tail_p;
3047
3048 cy_as_hal_assert(node->node_type == CYAS_FUNC_CB);
3049 cy_as_hal_assert(tail == 0 ||
3050 tail->node_type == CYAS_FUNC_CB);
3051 if (queue_p->head_p == 0)
3052 queue_p->head_p = node;
3053 else
3054 tail->next_p = node;
3055
3056 queue_p->tail_p = node;
3057 }
3058 break;
3059
3060 default:
3061 cy_as_hal_assert(cy_false);
3062 break;
3063 }
3064
3065 queue_p->count++;
3066
3067 cy_as_hal_enable_interrupts(int_state);
3068 }
3069
3070 /* Removes the tail node from the queue and frees it */
3071 void
3072 cy_as_remove_c_b_tail_node(cy_as_c_b_queue *queue_p)
3073 {
3074 uint32_t int_state;
3075
3076 int_state = cy_as_hal_disable_interrupts();
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 *)
3090 queue_p->head_p;
3091 cy_as_func_c_b_node *tail =
3092 (cy_as_func_c_b_node *)
3093 queue_p->tail_p;
3094 if (node != tail) {
3095 while (node->next_p != tail)
3096 node = node->next_p;
3097 node->next_p = 0;
3098 queue_p->tail_p = node;
3099 }
3100 cy_as_destroy_func_c_b_node(tail);
3101 }
3102 break;
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 *)
3108 queue_p->head_p;
3109 cy_as_usb_func_c_b_node *tail =
3110 (cy_as_usb_func_c_b_node *)
3111 queue_p->tail_p;
3112 if (node != tail) {
3113 while (node->next_p != tail)
3114 node = node->next_p;
3115 node->next_p = 0;
3116 queue_p->tail_p = node;
3117 }
3118
3119 cy_as_destroy_usb_func_c_b_node(tail);
3120 }
3121 break;
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 *)
3127 queue_p->head_p;
3128 cy_as_usb_io_c_b_node *tail =
3129 (cy_as_usb_io_c_b_node *)
3130 queue_p->tail_p;
3131 if (node != tail) {
3132 while (node->next_p != tail)
3133 node = node->next_p;
3134 node->next_p = 0;
3135 queue_p->tail_p = node;
3136 }
3137 cy_as_destroy_usb_io_c_b_node(tail);
3138 }
3139 break;
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 *)
3145 queue_p->head_p;
3146 cy_as_storage_io_c_b_node *tail =
3147 (cy_as_storage_io_c_b_node *)
3148 queue_p->tail_p;
3149 if (node != tail) {
3150 while (node->next_p != tail)
3151 node = node->next_p;
3152 node->next_p = 0;
3153 queue_p->tail_p = node;
3154 }
3155 cy_as_destroy_storage_io_c_b_node(tail);
3156 }
3157 break;
3158
3159 default:
3160 cy_as_hal_assert(cy_false);
3161 }
3162
3163 queue_p->count--;
3164 if (queue_p->count == 0) {
3165 queue_p->head_p = 0;
3166 queue_p->tail_p = 0;
3167 }
3168 }
3169
3170 cy_as_hal_enable_interrupts(int_state);
3171 }
3172
3173 /* Removes the first CyAsCBNode from the queue and frees it */
3174 void
3175 cy_as_remove_c_b_node(cy_as_c_b_queue *queue_p)
3176 {
3177 uint32_t int_state;
3178
3179 int_state = cy_as_hal_disable_interrupts();
3180
3181 cy_as_hal_assert(queue_p->count >= 0);
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 *)
3186 queue_p->head_p;
3187 queue_p->head_p = node->next_p;
3188 cy_as_destroy_usb_func_c_b_node(node);
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 *)
3192 queue_p->head_p;
3193 queue_p->head_p = node->next_p;
3194 cy_as_destroy_usb_io_c_b_node(node);
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 *)
3198 queue_p->head_p;
3199 queue_p->head_p = node->next_p;
3200 cy_as_destroy_storage_io_c_b_node(node);
3201 } else if (queue_p->type == CYAS_FUNC_CB) {
3202 cy_as_func_c_b_node *node =
3203 (cy_as_func_c_b_node *)
3204 queue_p->head_p;
3205 queue_p->head_p = node->next_p;
3206 cy_as_destroy_func_c_b_node(node);
3207 } else {
3208 cy_as_hal_assert(cy_false);
3209 }
3210
3211 queue_p->count--;
3212 if (queue_p->count == 0) {
3213 queue_p->head_p = 0;
3214 queue_p->tail_p = 0;
3215 }
3216 }
3217
3218 cy_as_hal_enable_interrupts(int_state);
3219 }
3220
3221 void my_print_func_c_b_node(cy_as_func_c_b_node *node)
3222 {
3223 cy_as_funct_c_b_type type =
3224 cy_as_funct_c_b_type_get_type(node->data_type);
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,
3228 node->node_type);
3229 }
3230
3231 void my_print_c_b_queue(cy_as_c_b_queue *queue_p)
3232 {
3233 uint32_t i = 0;
3234
3235 cy_as_hal_print_message("| count: %u type: ", queue_p->count);
3236
3237 if (queue_p->type == CYAS_USB_FUNC_CB) {
3238 cy_as_hal_print_message("USB_FUNC_CB\n");
3239 } else if (queue_p->type == CYAS_USB_IO_CB) {
3240 cy_as_hal_print_message("USB_IO_CB\n");
3241 } else if (queue_p->type == CYAS_STORAGE_IO_CB) {
3242 cy_as_hal_print_message("STORAGE_IO_CB\n");
3243 } else if (queue_p->type == CYAS_FUNC_CB) {
3244 cy_as_func_c_b_node *node = queue_p->head_p;
3245 cy_as_hal_print_message("FUNC_CB\n");
3246 if (queue_p->count > 0) {
3247 cy_as_hal_print_message("| head->");
3248
3249 for (i = 0; i < queue_p->count; i++) {
3250 if (node) {
3251 cy_as_hal_print_message("->");
3252 my_print_func_c_b_node(node);
3253 node = node->next_p;
3254 } else
3255 cy_as_hal_print_message("->[NULL]\n");
3256 }
3257
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");
3261 }
3262 } else {
3263 cy_as_hal_print_message("INVALID\n");
3264 }
3265
3266 cy_as_hal_print_message("|----------\n");
3267 }
3268
3269
3270 /* Removes and frees all pending callbacks */
3271 void
3272 cy_as_clear_c_b_queue(cy_as_c_b_queue *queue_p)
3273 {
3274 uint32_t int_state = cy_as_hal_disable_interrupts();
3275
3276 while (queue_p->count != 0)
3277 cy_as_remove_c_b_node(queue_p);
3278
3279 cy_as_hal_enable_interrupts(int_state);
3280 }
3281
3282 cy_as_return_status_t
3283 cy_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,
3296 client, type, data);
3297 cy_as_return_status_t ret;
3298
3299 if (cbnode == 0)
3300 return CY_AS_ERROR_OUT_OF_MEMORY;
3301 else
3302 cy_as_insert_c_b_node(queue, cbnode);
3303
3304 req_p->flags |= req_type;
3305
3306 ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_false, rcb);
3307 if (ret != CY_AS_ERROR_SUCCESS)
3308 cy_as_remove_c_b_tail_node(queue);
3309
3310 return ret;
3311 }
3312
3313 void
3314 cy_as_misc_cancel_ex_requests(cy_as_device *dev_p)
3315 {
3316 int i;
3317 for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++)
3318 cy_as_ll_remove_all_requests(dev_p, dev_p->context[i]);
3319 }
3320
3321
3322 static void
3323 cy_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 {
3329 cy_as_func_c_b_node *node = NULL;
3330 cy_as_return_status_t ret;
3331
3332 cy_bool ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX)
3333 == CY_AS_REQUEST_RESPONSE_EX;
3334 cy_bool ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS)
3335 == CY_AS_REQUEST_RESPONSE_MS;
3336 uint8_t code;
3337 uint32_t type;
3338 uint8_t cntxt;
3339
3340 cy_as_hal_assert(ex_request || ms_request);
3341 (void) ex_request;
3342 (void) ms_request;
3343 (void)context;
3344
3345 cntxt = cy_as_ll_request_response__get_context(rqt);
3346 code = cy_as_ll_request_response__get_code(rqt);
3347
3348 switch (cntxt) {
3349 case CY_RQT_GENERAL_RQT_CONTEXT:
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);
3354
3355 switch (code) {
3356 case CY_RQT_GET_FIRMWARE_VERSION:
3357 cy_as_hal_assert(node->data != 0);
3358 cy_as_hal_assert(type ==
3359 CY_FUNCT_CB_MISC_GETFIRMWAREVERSION);
3360 ret = my_handle_response_get_firmware_version(dev_p,
3361 rqt, resp,
3362 (cy_as_get_firmware_version_data *)node->data);
3363 break;
3364 case CY_RQT_READ_MCU_REGISTER:
3365 cy_as_hal_assert(node->data != 0);
3366 cy_as_hal_assert(type ==
3367 CY_FUNCT_CB_MISC_READMCUREGISTER);
3368 ret = my_handle_response_read_m_c_u_register(dev_p, rqt,
3369 resp, (uint8_t *)node->data);
3370 break;
3371 case CY_RQT_GET_GPIO_STATE:
3372 cy_as_hal_assert(node->data != 0);
3373 cy_as_hal_assert(type ==
3374 CY_FUNCT_CB_MISC_GETGPIOVALUE);
3375 ret = my_handle_response_get_gpio_value(dev_p, rqt,
3376 resp, (uint8_t *)node->data);
3377 break;
3378 case CY_RQT_SET_SD_CLOCK_FREQ:
3379 cy_as_hal_assert(type == CY_FUNCT_CB_MISC_SETSDFREQ);
3380 ret = my_handle_response_no_data(dev_p, rqt, resp);
3381 break;
3382 case CY_RQT_CONTROL_ANTIOCH_HEARTBEAT:
3383 cy_as_hal_assert(type ==
3384 CY_FUNCT_CB_MISC_HEARTBEATCONTROL);
3385 ret = my_handle_response_no_data(dev_p, rqt, resp);
3386 break;
3387 case CY_RQT_WRITE_MCU_REGISTER:
3388 cy_as_hal_assert(type ==
3389 CY_FUNCT_CB_MISC_WRITEMCUREGISTER);
3390 ret = my_handle_response_no_data(dev_p, rqt, resp);
3391 break;
3392 case CY_RQT_STORAGE_MEDIA_CHANGED:
3393 cy_as_hal_assert(type ==
3394 CY_FUNCT_CB_MISC_STORAGECHANGED);
3395 ret = my_handle_response_no_data(dev_p, rqt, resp);
3396 break;
3397 case CY_RQT_SET_GPIO_STATE:
3398 cy_as_hal_assert(type ==
3399 CY_FUNCT_CB_MISC_SETGPIOVALUE);
3400 ret = my_handle_response_no_data(dev_p, rqt, resp);
3401 break;
3402 case CY_RQT_SET_TRACE_LEVEL:
3403 cy_as_hal_assert(type ==
3404 CY_FUNCT_CB_MISC_SETTRACELEVEL);
3405 ret = my_handle_response_no_data(dev_p, rqt, resp);
3406 if (ret == CY_AS_ERROR_INVALID_RESPONSE)
3407 ret = CY_AS_ERROR_NOT_SUPPORTED;
3408 break;
3409 case CY_RQT_PREPARE_FOR_STANDBY:
3410 cy_as_hal_assert(type ==
3411 CY_FUNCT_CB_MISC_ENTERSTANDBY);
3412 ret = my_handle_response_enter_standby(dev_p, rqt, resp,
3413 (cy_bool)node->data);
3414 break;
3415 case CY_RQT_ENTER_SUSPEND_MODE:
3416 cy_as_hal_assert(type ==
3417 CY_FUNCT_CB_MISC_ENTERSUSPEND);
3418 ret = my_handle_response_no_data(dev_p, rqt, resp);
3419 if (ret == CY_AS_ERROR_SUCCESS)
3420 cy_as_device_set_suspend_mode(dev_p);
3421
3422 break;
3423 case CY_RQT_RESERVE_LNA_BOOT_AREA:
3424 cy_as_hal_assert(type ==
3425 CY_FUNCT_CB_MISC_RESERVELNABOOTAREA);
3426 ret = my_handle_response_no_data(dev_p, rqt, resp);
3427 break;
3428 case CY_RQT_SDPOLARITY:
3429 cy_as_hal_assert(type ==
3430 CY_FUNCT_CB_MISC_SETSDPOLARITY);
3431 ret = my_handle_response_no_data(dev_p, rqt, resp);
3432 break;
3433 default:
3434 ret = CY_AS_ERROR_INVALID_RESPONSE;
3435 cy_as_hal_assert(cy_false);
3436 break;
3437 }
3438 break;
3439
3440 case CY_RQT_RESOURCE_RQT_CONTEXT:
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);
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 ==
3451 CY_FUNCT_CB_MISC_ACQUIRERESOURCE);
3452 ret = my_handle_response_acquire_resource(dev_p, rqt,
3453 resp, (cy_as_resource_type *)node->data);
3454 break;
3455 default:
3456 ret = CY_AS_ERROR_INVALID_RESPONSE;
3457 cy_as_hal_assert(cy_false);
3458 break;
3459 }
3460 break;
3461
3462 default:
3463 ret = CY_AS_ERROR_INVALID_RESPONSE;
3464 cy_as_hal_assert(cy_false);
3465 break;
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)
3474 stat = ret;
3475
3476 /* Call the user Callback */
3477 node->cb_p((cy_as_device_handle)dev_p, stat, node->client_data,
3478 node->data_type, node->data);
3479 if (cntxt == CY_RQT_GENERAL_RQT_CONTEXT)
3480 cy_as_remove_c_b_node(dev_p->func_cbs_misc);
3481 else
3482 cy_as_remove_c_b_node(dev_p->func_cbs_res);
3483
3484 }
3485
3486
3487
3488 /*[]*/