1 /* Cypress West Bridge API source file (cyasmisc.c)
2 ## ===========================
3 ## Copyright (C) 2010 Cypress Semiconductor
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.
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.
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 ## ===========================
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"
32 * The device list, the only global in the API
34 static cy_as_device
*g_device_list
;
37 * The current debug level
39 static uint8_t debug_level
;
42 * This function sets the debug level for the API
46 cy_as_misc_set_log_level(uint8_t level
)
51 #ifdef CY_AS_LOG_SUPPORT
54 * This function is a low level logger for the API.
57 cy_as_log_debug_message(int level
, const char *str
)
59 if (level
<= debug_level
)
60 cy_as_hal_print_message("log %d: %s\n", level
, str
);
65 #define cy_as_check_device_ready(dev_p) \
67 if (!(dev_p) || ((dev_p)->sig != \
68 CY_AS_DEVICE_HANDLE_SIGNATURE)) \
69 return CY_AS_ERROR_INVALID_HANDLE; \
71 if (!cy_as_device_is_configured(dev_p)) \
72 return CY_AS_ERROR_NOT_CONFIGURED; \
74 if (!cy_as_device_is_firmware_loaded(dev_p))\
75 return CY_AS_ERROR_NO_FIRMWARE; \
78 /* Find an West Bridge device based on a TAG */
80 cy_as_device_find_from_tag(cy_as_hal_device_tag tag
)
84 for (dev_p
= g_device_list
; dev_p
!= 0; dev_p
= dev_p
->next_p
) {
85 if (dev_p
->tag
== tag
)
92 /* Map a pre-V1.2 media type to the V1.2+ bus number */
94 cy_as_bus_from_media_type(cy_as_media_type type
,
95 cy_as_bus_number_t
*bus
)
97 if (type
== cy_as_media_nand
)
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
)
108 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
110 if (cy_as_ll_request_response__get_code(reply_p
) !=
111 CY_RESP_SUCCESS_FAILURE
)
112 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
114 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
116 cy_as_ll_destroy_request(dev_p
, req_p
);
117 cy_as_ll_destroy_response(dev_p
, reply_p
);
123 * Create a new West Bridge device
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
)
130 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
132 cy_as_log_debug_message(6, "cy_as_misc_create_device called");
134 dev_p
= (cy_as_device
*)cy_as_hal_alloc(sizeof(cy_as_device
));
136 return CY_AS_ERROR_OUT_OF_MEMORY
;
137 cy_as_hal_mem_set(dev_p
, 0, sizeof(cy_as_device
));
140 * dynamically allocating this buffer to ensure that it is
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
;
149 dev_p
->sig
= CY_AS_DEVICE_HANDLE_SIGNATURE
;
151 dev_p
->usb_max_tx_size
= 0x40;
153 dev_p
->storage_write_endpoint
= CY_AS_P2S_WRITE_ENDPOINT
;
154 dev_p
->storage_read_endpoint
= CY_AS_P2S_READ_ENDPOINT
;
156 dev_p
->func_cbs_misc
= cy_as_create_c_b_queue(CYAS_FUNC_CB
);
157 if (dev_p
->func_cbs_misc
== 0)
160 dev_p
->func_cbs_res
= cy_as_create_c_b_queue(CYAS_FUNC_CB
);
161 if (dev_p
->func_cbs_res
== 0)
164 dev_p
->func_cbs_stor
= cy_as_create_c_b_queue(CYAS_FUNC_CB
);
165 if (dev_p
->func_cbs_stor
== 0)
168 dev_p
->func_cbs_usb
= cy_as_create_c_b_queue(CYAS_FUNC_CB
);
169 if (dev_p
->func_cbs_usb
== 0)
172 dev_p
->func_cbs_mtp
= cy_as_create_c_b_queue(CYAS_FUNC_CB
);
173 if (dev_p
->func_cbs_mtp
== 0)
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.
180 ret
= cy_as_dma_start(dev_p
);
181 if (ret
!= CY_AS_ERROR_SUCCESS
)
184 cy_as_device_set_dma_stopped(dev_p
);
187 * allocate memory for the low level module here. this module is also
188 * activated only when cy_as_misc_configure_device is called.
190 ret
= cy_as_ll_start(dev_p
);
191 if (ret
!= CY_AS_ERROR_SUCCESS
)
194 cy_as_device_set_low_level_stopped(dev_p
);
196 dev_p
->next_p
= g_device_list
;
197 g_device_list
= dev_p
;
200 cy_as_hal_init_dev_registers(tag
, cy_false
);
201 return CY_AS_ERROR_SUCCESS
;
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
);
208 if (dev_p
->func_cbs_res
)
209 cy_as_destroy_c_b_queue(dev_p
->func_cbs_res
);
211 if (dev_p
->func_cbs_stor
)
212 cy_as_destroy_c_b_queue(dev_p
->func_cbs_stor
);
214 if (dev_p
->func_cbs_usb
)
215 cy_as_destroy_c_b_queue(dev_p
->func_cbs_usb
);
217 if (dev_p
->func_cbs_mtp
)
218 cy_as_destroy_c_b_queue(dev_p
->func_cbs_mtp
);
220 cy_as_hal_free(dev_p
->usb_ep_data
);
221 cy_as_hal_free(dev_p
);
223 if (ret
!= CY_AS_ERROR_SUCCESS
)
226 return CY_AS_ERROR_OUT_OF_MEMORY
;
230 * Destroy an existing West Bridge device
232 cy_as_return_status_t
233 cy_as_misc_destroy_device(cy_as_device_handle handle
)
235 cy_as_return_status_t ret
;
238 cy_as_log_debug_message(6, "cy_as_misc_destroy_device called");
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
;
245 * if the USB stack is still running,
246 * it must be stopped first
248 if (dev_p
->usb_count
> 0)
249 return CY_AS_ERROR_STILL_RUNNING
;
252 * if the STORAGE stack is still running,
253 * it must be stopped first
255 if (dev_p
->storage_count
> 0)
256 return CY_AS_ERROR_STILL_RUNNING
;
258 if (cy_as_device_is_intr_running(dev_p
))
259 ret
= cy_as_intr_stop(dev_p
);
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
);
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
);
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
);
278 * remove the device from the device list
280 if (g_device_list
== dev_p
) {
281 g_device_list
= dev_p
->next_p
;
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
;
287 cy_as_hal_assert(tmp_p
!= 0);
288 tmp_p
->next_p
= dev_p
->next_p
;
292 * reset the signature so this will not be detected
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
);
304 * free the memory associated with the device
306 cy_as_hal_free(dev_p
->usb_ep_data
);
307 cy_as_hal_free(dev_p
);
309 return CY_AS_ERROR_SUCCESS
;
313 * Determine the endian mode for the processor we are
314 * running on, then set the endian mode register
317 cy_as_setup_endian_mode(cy_as_device
*dev_p
)
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.
332 cy_as_hal_write_register(dev_p
->tag
, CY_AS_MEM_P0_ENDIAN
,
333 CY_AS_LITTLE_ENDIAN
);
337 * Query the West Bridge device and determine if we are an standby mode
339 cy_as_return_status_t
340 cy_as_misc_in_standby(cy_as_device_handle handle
, cy_bool
*standby
)
344 cy_as_log_debug_message(6, "cy_as_misc_in_standby called");
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
;
350 if (cy_as_device_is_pin_standby(dev_p
) ||
351 cy_as_device_is_register_standby(dev_p
)) {
356 return CY_AS_ERROR_SUCCESS
;
360 cy_as_misc_func_callback(cy_as_device
*dev_p
,
362 cy_as_ll_request_response
*rqt
,
363 cy_as_ll_request_response
*resp
,
364 cy_as_return_status_t ret
);
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
)
377 switch (cy_as_ll_request_response__get_code(req_p
)) {
378 case CY_RQT_INITIALIZATION_COMPLETE
:
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
);
387 if (cy_as_device_is_waking(dev_p
)) {
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
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
);
401 v
= cy_as_ll_request_response__get_word
405 * store the media supported on
406 * each of the device buses.
408 dev_p
->media_supported
[0] =
410 dev_p
->media_supported
[1] =
411 (uint8_t)((v
>> 8) & 0xFF);
413 v
= cy_as_ll_request_response__get_word
416 dev_p
->is_mtp_firmware
=
417 (cy_bool
)((v
>> 8) & 0xFF);
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);
425 v
= cy_as_hal_read_register(dev_p
->tag
,
426 CY_AS_MEM_P0_VM_SET
);
428 if (v
& CY_AS_MEM_P0_VM_SET_CFGMODE
)
429 cy_as_hal_print_message(
430 "initialization message "
431 "received, but config bit "
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");
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
);
450 * if the wakeup was caused by an async cy_as_misc_leave_suspend
451 * call, we have to call the corresponding callback.
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
);
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);
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
);
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);
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);
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);
493 case CY_RQT_WB_DEVICE_MISMATCH
:
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);
501 case CY_RQT_BOOTLOAD_NO_FIRMWARE
:
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");
516 is_valid_silicon_id(uint16_t v
)
518 cy_bool idok
= cy_false
;
521 * remove the revision number from the ID value
523 v
= v
& CY_AS_MEM_CM_WB_CFG_ID_HDID_MASK
;
526 * if this is west bridge, then we are OK.
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
)
537 * Configure the West Bridge device hardware
539 cy_as_return_status_t
540 cy_as_misc_configure_device(cy_as_device_handle handle
,
541 cy_as_device_config
*config_p
)
543 cy_as_return_status_t ret
;
548 cy_as_log_debug_message(6, "cy_as_misc_configure_device called");
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
;
554 /* Setup big endian vs little endian */
555 cy_as_setup_endian_mode(dev_p
);
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
;
566 /* Check for standby mode */
567 ret
= cy_as_misc_in_standby(handle
, &standby
);
568 if (ret
!= CY_AS_ERROR_SUCCESS
)
571 return CY_AS_ERROR_IN_STANDBY
;
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
;
578 v
= CY_AS_MEM_P0_VM_SET_VMTYPE_RAM
;
580 v
= CY_AS_MEM_P0_VM_SET_VMTYPE_RAM
;
582 /* Setup synchronous versus asynchronous mode */
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
);
593 if (config_p
->crystal
)
594 cy_as_device_set_crystal(dev_p
);
596 cy_as_device_set_external_clock(dev_p
);
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
);
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
);
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
)
612 /* Mark the interface as initialized */
613 cy_as_device_set_configured(dev_p
);
615 return CY_AS_ERROR_SUCCESS
;
619 my_dma_callback(cy_as_device
*dev_p
,
620 cy_as_end_point_number_t ep
,
623 cy_as_return_status_t ret
626 cy_as_dma_end_point
*ep_p
;
630 /* Get the endpoint pointer based on the endpoint number */
631 ep_p
= CY_AS_NUM_EP(dev_p
, ep
);
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
;
638 cy_as_hal_assert(node
);
640 if (ret
== CY_AS_ERROR_SUCCESS
) {
642 * disable endpoint 2. the storage module
643 * will enable this EP if necessary.
645 cy_as_dma_enable_end_point(dev_p
,
646 CY_AS_FIRMWARE_ENDPOINT
,
647 cy_false
, cy_as_direction_in
);
650 * clear the reset register. this releases the
651 * antioch micro-controller from reset and begins
652 * running the code at address zero.
654 cy_as_hal_write_register(dev_p
->tag
,
655 CY_AS_MEM_RST_CTRL_REG
, 0x00);
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
);
663 /* This is the header data that was allocated in the
664 * download firmware function, and can be safely freed
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
);
672 cy_as_return_status_t
673 cy_as_misc_download_firmware(cy_as_device_handle handle
,
676 cy_as_function_callback cb
,
680 cy_as_return_status_t ret
;
683 cy_as_dma_callback dmacb
= 0;
686 cy_as_log_debug_message(6, "cy_as_misc_download_firmware called");
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
;
694 * if the device has not been initialized, we cannot download firmware
697 if (!cy_as_device_is_configured(dev_p
))
698 return CY_AS_ERROR_NOT_CONFIGURED
;
701 * make sure west bridge is not in standby
703 ret
= cy_as_misc_in_standby(dev_p
, &standby
);
704 if (ret
!= CY_AS_ERROR_SUCCESS
)
708 return CY_AS_ERROR_IN_STANDBY
;
710 if (cy_as_device_is_in_suspend_mode(dev_p
))
711 return CY_AS_ERROR_IN_SUSPEND
;
714 * make sure we are in configuration mode
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
;
720 /* Maximum firmware size is 24k */
721 if (size
> CY_AS_MAXIMUM_FIRMWARE_SIZE
)
722 return CY_AS_ERROR_INVALID_SIZE
;
724 /* Make sure the size is an even number of bytes as well */
726 return CY_AS_ERROR_ALIGNMENT_ERROR
;
729 * write the two word header that gives the base address and
730 * size of the firmware image to download
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
);
736 return CY_AS_ERROR_OUT_OF_MEMORY
;
740 header
[2] = (uint8_t)(size
& 0xff);
741 header
[3] = (uint8_t)((size
>> 8) & 0xff);
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
)
750 * setup DMA for 64 byte packets. this is the requirement for downloading
751 * firmware to west bridge.
753 cy_as_dma_set_max_dma_size(dev_p
, CY_AS_FIRMWARE_ENDPOINT
, 64);
756 dmacb
= my_dma_callback
;
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
)
764 * write the firmware image to the west bridge device
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
)
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);
776 return CY_AS_ERROR_OUT_OF_MEMORY
;
778 cy_as_insert_c_b_node(dev_p
->func_cbs_misc
, cbnode
);
780 ret
= cy_as_dma_kick_start(dev_p
, CY_AS_FIRMWARE_ENDPOINT
);
781 if (ret
!= CY_AS_ERROR_SUCCESS
)
784 ret
= cy_as_dma_drain_queue(dev_p
,
785 CY_AS_FIRMWARE_ENDPOINT
, cy_true
);
787 /* Free the header memory that was allocated earlier. */
788 cy_as_hal_c_b_free(header
);
790 if (ret
!= CY_AS_ERROR_SUCCESS
)
794 * disable EP 2. the storage module will
795 * enable this EP if necessary.
797 cy_as_dma_enable_end_point(dev_p
, CY_AS_FIRMWARE_ENDPOINT
,
798 cy_false
, cy_as_direction_in
);
801 * clear the reset register. this releases the west bridge
802 * micro-controller from reset and begins running the code at
805 cy_as_hal_write_register(dev_p
->tag
,
806 CY_AS_MEM_RST_CTRL_REG
, 0x00);
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.
814 return CY_AS_ERROR_SUCCESS
;
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
)
825 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
828 if (cy_as_ll_request_response__get_code(reply_p
)
829 != CY_RESP_FIRMWARE_VERSION
) {
830 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
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);
843 cy_as_ll_destroy_request(dev_p
, req_p
);
844 cy_as_ll_destroy_response(dev_p
, reply_p
);
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
,
855 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
857 cy_as_ll_request_response
*req_p
, *reply_p
;
863 cy_as_log_debug_message(6, "cy_as_misc_get_firmware_version called");
865 /* Make sure we have a valid device */
866 dev_p
= (cy_as_device
*)handle
;
867 cy_as_check_device_ready(dev_p
);
870 * make sure antioch is not in standby
872 ret
= cy_as_misc_in_standby(dev_p
, &standby
);
873 if (ret
!= CY_AS_ERROR_SUCCESS
)
876 return CY_AS_ERROR_IN_STANDBY
;
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
;
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);
886 return CY_AS_ERROR_OUT_OF_MEMORY
;
889 * Reserve space for the reply, the reply data
890 * will not exceed three words
892 reply_p
= cy_as_ll_create_response(dev_p
, 5);
894 cy_as_ll_destroy_request(dev_p
, req_p
);
895 return CY_AS_ERROR_OUT_OF_MEMORY
;
899 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
900 if (ret
!= CY_AS_ERROR_SUCCESS
)
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
);
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
);
915 if (ret
!= CY_AS_ERROR_SUCCESS
)
918 /* The request and response are freed
919 * as part of the MiscFuncCallback */
924 cy_as_ll_destroy_request(dev_p
, req_p
);
925 cy_as_ll_destroy_response(dev_p
, reply_p
);
929 EXPORT_SYMBOL(cy_as_misc_get_firmware_version
);
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
,
938 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
940 if (cy_as_ll_request_response__get_code(reply_p
)
941 != CY_RESP_MCU_REGISTER_DATA
) {
942 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
947 (cy_as_ll_request_response__get_word(reply_p
, 0));
950 cy_as_ll_destroy_request(dev_p
, req_p
);
951 cy_as_ll_destroy_response(dev_p
, reply_p
);
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
,
963 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
965 if (cy_as_ll_request_response__get_code(reply_p
)
966 != CY_RESP_GPIO_STATE
) {
967 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
970 (cy_as_ll_request_response__get_word(reply_p
, 0));
972 cy_as_ll_destroy_request(dev_p
, req_p
);
973 cy_as_ll_destroy_response(dev_p
, reply_p
);
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
,
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
;
989 if (!dev_p
|| (dev_p
->sig
!= CY_AS_DEVICE_HANDLE_SIGNATURE
))
990 return CY_AS_ERROR_INVALID_HANDLE
;
992 if (!cy_as_device_is_configured(dev_p
))
993 return CY_AS_ERROR_NOT_CONFIGURED
;
995 if (!cy_as_device_is_firmware_loaded(dev_p
))
996 return CY_AS_ERROR_NO_FIRMWARE
;
998 if (cy_as_device_is_in_suspend_mode(dev_p
))
999 return CY_AS_ERROR_IN_SUSPEND
;
1001 req_p
= cy_as_ll_create_request(dev_p
, CY_RQT_SDPOLARITY
,
1002 CY_RQT_GENERAL_RQT_CONTEXT
, 1);
1004 return CY_AS_ERROR_OUT_OF_MEMORY
;
1006 cy_as_ll_request_response__set_word(req_p
, 0,
1007 (uint16_t)polarity
);
1010 * Reserve space for the reply, the reply data will
1011 * not exceed one word
1013 reply_p
= cy_as_ll_create_response(dev_p
, 1);
1015 cy_as_ll_destroy_request(dev_p
, req_p
);
1016 return CY_AS_ERROR_OUT_OF_MEMORY
;
1020 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
1021 if (ret
!= CY_AS_ERROR_SUCCESS
)
1024 return (my_handle_response_no_data(dev_p
, req_p
, reply_p
));
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
);
1031 if (ret
!= CY_AS_ERROR_SUCCESS
)
1034 /* The request and response are freed
1035 * as part of the FuncCallback */
1040 cy_as_ll_destroy_request(dev_p
, req_p
);
1041 cy_as_ll_destroy_response(dev_p
, reply_p
);
1046 cy_as_return_status_t
1047 cy_as_misc_read_m_c_u_register(cy_as_device_handle handle
,
1050 cy_as_function_callback cb
,
1053 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
1054 cy_as_ll_request_response
*req_p
, *reply_p
;
1056 cy_as_device
*dev_p
;
1058 cy_as_log_debug_message(6, "cy_as_misc_read_m_c_u_register called");
1060 dev_p
= (cy_as_device
*)handle
;
1061 cy_as_check_device_ready(dev_p
);
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
;
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
;
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);
1075 return CY_AS_ERROR_OUT_OF_MEMORY
;
1077 cy_as_ll_request_response__set_word(req_p
, 0, (uint16_t)address
);
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);
1083 cy_as_ll_destroy_request(dev_p
, req_p
);
1084 return CY_AS_ERROR_OUT_OF_MEMORY
;
1088 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
1089 if (ret
!= CY_AS_ERROR_SUCCESS
)
1092 if (cy_as_ll_request_response__get_code(reply_p
) !=
1093 CY_RESP_MCU_REGISTER_DATA
) {
1094 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
1098 *value
= (uint8_t)(cy_as_ll_request_response__get_word
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
);
1107 if (ret
!= CY_AS_ERROR_SUCCESS
)
1110 /* The request and response are freed
1111 * as part of the MiscFuncCallback */
1115 cy_as_ll_destroy_request(dev_p
, req_p
);
1116 cy_as_ll_destroy_response(dev_p
, reply_p
);
1120 EXPORT_SYMBOL(cy_as_misc_read_m_c_u_register
);
1122 cy_as_return_status_t
1123 cy_as_misc_write_m_c_u_register(cy_as_device_handle handle
,
1127 cy_as_function_callback cb
,
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
;
1134 cy_as_log_debug_message(6, "cy_as_misc_write_m_c_u_register called");
1136 dev_p
= (cy_as_device
*)handle
;
1137 cy_as_check_device_ready(dev_p
);
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
;
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
;
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);
1151 return CY_AS_ERROR_OUT_OF_MEMORY
;
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
));
1158 * Reserve space for the reply, the reply data
1159 * will not exceed one word
1161 reply_p
= cy_as_ll_create_response(dev_p
, 1);
1163 cy_as_ll_destroy_request(dev_p
, req_p
);
1164 return CY_AS_ERROR_OUT_OF_MEMORY
;
1168 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
1169 if (ret
!= CY_AS_ERROR_SUCCESS
)
1172 if (cy_as_ll_request_response__get_code(reply_p
) !=
1173 CY_RESP_SUCCESS_FAILURE
) {
1174 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
1178 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
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
);
1185 if (ret
!= CY_AS_ERROR_SUCCESS
)
1189 * The request and response are freed as part of the
1196 cy_as_ll_destroy_request(dev_p
, req_p
);
1197 cy_as_ll_destroy_response(dev_p
, reply_p
);
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
)
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
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
);
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
);
1239 * wait for a small amount of time to
1240 * allow reset to be complete.
1242 cy_as_hal_sleep(100);
1245 cy_as_device_clear_reset_pending(dev_p
);
1247 return CY_AS_ERROR_SUCCESS
;
1250 cy_as_return_status_t
1251 cy_as_misc_reset(cy_as_device_handle handle
,
1252 cy_as_reset_type type
,
1254 cy_as_function_callback cb
,
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
;
1263 cy_as_log_debug_message(6, "cy_as_misc_reset_e_x called");
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
);
1270 * soft reset is not supported until we close on the issues
1271 * in the firmware with what needs to happen.
1273 if (type
== cy_as_reset_soft
)
1274 return CY_AS_ERROR_NOT_YET_SUPPORTED
;
1276 cy_as_device_set_reset_pending(dev_p
);
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
;
1285 * shutdown the endpoints so no more traffic can be queued
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
);
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
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
);
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
,
1309 cy_as_dma_drain_queue(dev_p
, i
,
1314 /* No flush was requested, so cancel any outstanding DMAs
1315 * so the user callbacks are called as needed
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
);
1324 ret
= my_handle_response_reset(dev_p
, 0, 0, type
);
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);
1334 * initialize any registers that may have been
1335 * changed when the device was reset.
1337 cy_as_hal_init_dev_registers(dev_p
->tag
, cy_false
);
1341 EXPORT_SYMBOL(cy_as_misc_reset
);
1343 static cy_as_return_status_t
1344 get_unallocated_resource(cy_as_device
*dev_p
, cy_as_resource_type resource
)
1348 cy_as_return_status_t ret
= CY_AS_ERROR_NOT_ACQUIRED
;
1351 case cy_as_bus_u_s_b
:
1361 cy_as_hal_assert(cy_false
);
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;
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
);
1380 v
= cy_as_hal_read_register(dev_p
->tag
,
1381 CY_AS_MEM_P0_RSE_ALLOCATE
);
1382 v
= (v
>> shift
) & 0x03;
1384 ret
= CY_AS_ERROR_SUCCESS
;
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
)
1396 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
1398 if (cy_as_ll_request_response__get_code(reply_p
) !=
1399 CY_RESP_SUCCESS_FAILURE
) {
1400 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
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
;
1411 cy_as_ll_destroy_request(dev_p
, req_p
);
1412 cy_as_ll_destroy_response(dev_p
, reply_p
);
1417 cy_as_return_status_t
1418 cy_as_misc_acquire_resource(cy_as_device_handle handle
,
1419 cy_as_resource_type
*resource
,
1421 cy_as_function_callback cb
,
1424 cy_as_ll_request_response
*req_p
, *reply_p
;
1425 cy_as_return_status_t ret
;
1427 cy_as_device
*dev_p
;
1431 cy_as_log_debug_message(6, "cy_as_misc_acquire_resource called");
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
;
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
);
1442 if (cy_as_device_is_in_suspend_mode(dev_p
))
1443 return CY_AS_ERROR_IN_SUSPEND
;
1446 ret
= get_unallocated_resource(dev_p
, *resource
);
1449 * make sure that the callback is called if the resource is
1450 * successfully acquired at this point.
1452 if ((ret
== CY_AS_ERROR_SUCCESS
) && (cb
!= 0))
1453 cb(handle
, ret
, client
,
1454 CY_FUNCT_CB_MISC_ACQUIRERESOURCE
, resource
);
1456 if (ret
!= CY_AS_ERROR_NOT_ACQUIRED
)
1460 return CY_AS_ERROR_NOT_ACQUIRED
;
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);
1466 return CY_AS_ERROR_OUT_OF_MEMORY
;
1468 cy_as_ll_request_response__set_word(req_p
, 0, (uint16_t)(*resource
));
1470 reply_p
= cy_as_ll_create_response(dev_p
, 1);
1472 cy_as_ll_destroy_request(dev_p
, req_p
);
1473 return CY_AS_ERROR_OUT_OF_MEMORY
;
1477 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
1478 if (ret
!= CY_AS_ERROR_SUCCESS
)
1481 if (cy_as_ll_request_response__get_code(reply_p
) !=
1482 CY_RESP_SUCCESS_FAILURE
) {
1483 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
1487 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
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
);
1494 if (ret
!= CY_AS_ERROR_SUCCESS
)
1497 /* The request and response are freed
1498 * as part of the MiscFuncCallback */
1503 cy_as_ll_destroy_request(dev_p
, req_p
);
1504 cy_as_ll_destroy_response(dev_p
, reply_p
);
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
;
1514 EXPORT_SYMBOL(cy_as_misc_acquire_resource
);
1516 cy_as_return_status_t
1517 cy_as_misc_release_resource(cy_as_device_handle handle
,
1518 cy_as_resource_type resource
)
1523 cy_as_device
*dev_p
;
1525 cy_as_log_debug_message(6, "cy_as_misc_release_resource called");
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
);
1531 if (cy_as_device_is_in_suspend_mode(dev_p
))
1532 return CY_AS_ERROR_IN_SUSPEND
;
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
;
1539 case cy_as_bus_u_s_b
:
1549 cy_as_hal_assert(cy_false
);
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
;
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);
1566 return CY_AS_ERROR_SUCCESS
;
1568 EXPORT_SYMBOL(cy_as_misc_release_resource
);
1570 cy_as_return_status_t
1571 cy_as_misc_set_trace_level(cy_as_device_handle handle
,
1573 cy_as_bus_number_t bus
,
1576 cy_as_function_callback cb
,
1579 cy_as_ll_request_response
*req_p
, *reply_p
;
1580 cy_as_return_status_t ret
;
1581 cy_as_device
*dev_p
;
1583 cy_as_log_debug_message(6, "cy_as_misc_set_trace_level called");
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
);
1589 if (cy_as_device_is_in_suspend_mode(dev_p
))
1590 return CY_AS_ERROR_IN_SUSPEND
;
1592 if (bus
< 0 || bus
>= CY_AS_MAX_BUSES
)
1593 return CY_AS_ERROR_NO_SUCH_BUS
;
1595 if (device
>= CY_AS_MAX_STORAGE_DEVICES
)
1596 return CY_AS_ERROR_NO_SUCH_DEVICE
;
1599 return CY_AS_ERROR_NO_SUCH_UNIT
;
1601 if (level
>= CYAS_FW_TRACE_MAX_LEVEL
)
1602 return CY_AS_ERROR_INVALID_TRACE_LEVEL
;
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);
1608 return CY_AS_ERROR_OUT_OF_MEMORY
;
1610 cy_as_ll_request_response__set_word(req_p
, 0,
1612 cy_as_ll_request_response__set_word(req_p
, 1,
1613 (uint16_t)((bus
<< 12) | (device
<< 8) | (unit
)));
1616 * Reserve space for the reply, the reply data will not
1617 * exceed three words
1619 reply_p
= cy_as_ll_create_response(dev_p
, 2);
1621 cy_as_ll_destroy_request(dev_p
, req_p
);
1622 return CY_AS_ERROR_OUT_OF_MEMORY
;
1626 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
1627 if (ret
!= CY_AS_ERROR_SUCCESS
)
1630 if (cy_as_ll_request_response__get_code(reply_p
) !=
1631 CY_RESP_SUCCESS_FAILURE
) {
1632 ret
= CY_AS_ERROR_NOT_SUPPORTED
;
1636 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
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
);
1644 if (ret
!= CY_AS_ERROR_SUCCESS
)
1647 /* The request and response are freed as part of the
1648 * MiscFuncCallback */
1653 cy_as_ll_destroy_request(dev_p
, req_p
);
1654 cy_as_ll_destroy_response(dev_p
, reply_p
);
1659 cy_as_return_status_t
1660 cy_as_misc_heart_beat_control(cy_as_device_handle handle
,
1662 cy_as_function_callback cb
,
1665 cy_as_ll_request_response
*req_p
, *reply_p
;
1666 cy_as_return_status_t ret
;
1667 cy_as_device
*dev_p
;
1669 cy_as_log_debug_message(6, "cy_as_misc_heart_beat_control called");
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
);
1675 if (cy_as_device_is_in_suspend_mode(dev_p
))
1676 return CY_AS_ERROR_IN_SUSPEND
;
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);
1682 return CY_AS_ERROR_OUT_OF_MEMORY
;
1684 cy_as_ll_request_response__set_word(req_p
, 0, (uint16_t)enable
);
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);
1690 cy_as_ll_destroy_request(dev_p
, req_p
);
1691 return CY_AS_ERROR_OUT_OF_MEMORY
;
1695 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
1696 if (ret
!= CY_AS_ERROR_SUCCESS
)
1699 if (cy_as_ll_request_response__get_code(reply_p
) !=
1700 CY_RESP_SUCCESS_FAILURE
) {
1701 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
1705 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
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
);
1713 if (ret
!= CY_AS_ERROR_SUCCESS
)
1716 /* The request and response are freed as part of the
1717 * MiscFuncCallback */
1722 cy_as_ll_destroy_request(dev_p
, req_p
);
1723 cy_as_ll_destroy_response(dev_p
, reply_p
);
1727 EXPORT_SYMBOL(cy_as_misc_heart_beat_control
);
1729 static cy_as_return_status_t
1730 my_set_sd_clock_freq(
1731 cy_as_device
*dev_p
,
1734 cy_as_function_callback cb
,
1737 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
1738 cy_as_ll_request_response
*req_p
, *reply_p
;
1740 if (cy_as_device_is_in_callback(dev_p
) && (cb
== 0))
1741 return CY_AS_ERROR_INVALID_IN_CALLBACK
;
1743 req_p
= cy_as_ll_create_request(dev_p
, CY_RQT_SET_SD_CLOCK_FREQ
,
1744 CY_RQT_GENERAL_RQT_CONTEXT
, 1);
1746 return CY_AS_ERROR_OUT_OF_MEMORY
;
1748 cy_as_ll_request_response__set_word(req_p
, 0,
1749 (uint16_t)((card_type
<< 8) | setting
));
1751 /* Reserve space for the reply, which will not exceed one word. */
1752 reply_p
= cy_as_ll_create_response(dev_p
, 1);
1754 cy_as_ll_destroy_request(dev_p
, req_p
);
1755 return CY_AS_ERROR_OUT_OF_MEMORY
;
1759 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
1760 if (ret
!= CY_AS_ERROR_SUCCESS
)
1763 if (cy_as_ll_request_response__get_code(reply_p
) !=
1764 CY_RESP_SUCCESS_FAILURE
) {
1765 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
1769 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
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
);
1776 if (ret
!= CY_AS_ERROR_SUCCESS
)
1779 /* The request and response are freed as part of the
1780 * MiscFuncCallback */
1785 cy_as_ll_destroy_request(dev_p
, req_p
);
1786 cy_as_ll_destroy_response(dev_p
, reply_p
);
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
,
1798 cy_as_device
*dev_p
;
1800 cy_as_log_debug_message(6, "cy_as_misc_set_low_speed_sd_freq called");
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
);
1806 if (cy_as_device_is_in_suspend_mode(dev_p
))
1807 return CY_AS_ERROR_IN_SUSPEND
;
1809 if ((setting
!= CY_AS_SD_DEFAULT_FREQ
) &&
1810 (setting
!= CY_AS_SD_RATED_FREQ
))
1811 return CY_AS_ERROR_INVALID_PARAMETER
;
1813 return my_set_sd_clock_freq(dev_p
, 0, (uint8_t)setting
, cb
, client
);
1815 EXPORT_SYMBOL(cy_as_misc_set_low_speed_sd_freq
);
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
,
1824 cy_as_device
*dev_p
;
1826 cy_as_log_debug_message(6, "cy_as_misc_set_high_speed_sd_freq called");
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
);
1832 if (cy_as_device_is_in_suspend_mode(dev_p
))
1833 return CY_AS_ERROR_IN_SUSPEND
;
1835 if ((setting
!= CY_AS_HS_SD_FREQ_24
) &&
1836 (setting
!= CY_AS_HS_SD_FREQ_48
))
1837 return CY_AS_ERROR_INVALID_PARAMETER
;
1839 return my_set_sd_clock_freq(dev_p
, 1, (uint8_t)setting
, cb
, client
);
1841 EXPORT_SYMBOL(cy_as_misc_set_high_speed_sd_freq
);
1843 cy_as_return_status_t
1844 cy_as_misc_get_gpio_value(cy_as_device_handle handle
,
1845 cy_as_misc_gpio pin
,
1847 cy_as_function_callback cb
,
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
;
1855 cy_as_log_debug_message(6, "cy_as_misc_get_gpio_value called");
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
);
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
);
1868 cb(dev_p
, ret
, client
,
1869 CY_FUNCT_CB_MISC_GETGPIOVALUE
, value
);
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
;
1878 if (cy_as_device_is_in_suspend_mode(dev_p
))
1879 return CY_AS_ERROR_IN_SUSPEND
;
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
;
1885 req_p
= cy_as_ll_create_request(dev_p
, CY_RQT_GET_GPIO_STATE
,
1886 CY_RQT_GENERAL_RQT_CONTEXT
, 1);
1888 return CY_AS_ERROR_OUT_OF_MEMORY
;
1890 cy_as_ll_request_response__set_word(req_p
, 0, ((uint8_t)pin
<< 8));
1892 /* Reserve space for the reply, which will not exceed one word. */
1893 reply_p
= cy_as_ll_create_response(dev_p
, 1);
1895 cy_as_ll_destroy_request(dev_p
, req_p
);
1896 return CY_AS_ERROR_OUT_OF_MEMORY
;
1900 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
1901 if (ret
!= CY_AS_ERROR_SUCCESS
)
1904 if (cy_as_ll_request_response__get_code(reply_p
) !=
1905 CY_RESP_GPIO_STATE
) {
1906 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
1911 cy_as_ll_request_response__get_word(reply_p
, 0);
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
);
1919 if (ret
!= CY_AS_ERROR_SUCCESS
)
1922 /* The request and response are freed as part of the
1923 * MiscFuncCallback */
1928 cy_as_ll_destroy_request(dev_p
, req_p
);
1929 cy_as_ll_destroy_response(dev_p
, reply_p
);
1933 EXPORT_SYMBOL(cy_as_misc_get_gpio_value
);
1935 cy_as_return_status_t
1936 cy_as_misc_set_gpio_value(cy_as_device_handle handle
,
1937 cy_as_misc_gpio pin
,
1939 cy_as_function_callback cb
,
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
;
1947 cy_as_log_debug_message(6, "cy_as_misc_set_gpio_value called");
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
);
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
);
1958 cy_as_hal_write_register(dev_p
->tag
,
1959 CY_AS_MEM_PMU_UPDATE
,
1960 (v
| CY_AS_MEM_PMU_UPDATE_UVALID
));
1962 cy_as_hal_write_register(dev_p
->tag
,
1963 CY_AS_MEM_PMU_UPDATE
,
1964 (v
& ~CY_AS_MEM_PMU_UPDATE_UVALID
));
1967 cb(dev_p
, ret
, client
,
1968 CY_FUNCT_CB_MISC_SETGPIOVALUE
, 0);
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
;
1976 if (cy_as_device_is_in_suspend_mode(dev_p
))
1977 return CY_AS_ERROR_IN_SUSPEND
;
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
;
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);
1987 return CY_AS_ERROR_OUT_OF_MEMORY
;
1989 v
= (uint16_t)(((uint8_t)pin
<< 8) | (value
> 0));
1990 cy_as_ll_request_response__set_word(req_p
, 0, v
);
1992 /* Reserve space for the reply, which will not exceed one word. */
1993 reply_p
= cy_as_ll_create_response(dev_p
, 1);
1995 cy_as_ll_destroy_request(dev_p
, req_p
);
1996 return CY_AS_ERROR_OUT_OF_MEMORY
;
2000 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
2001 if (ret
!= CY_AS_ERROR_SUCCESS
)
2004 if (cy_as_ll_request_response__get_code(reply_p
) !=
2005 CY_RESP_SUCCESS_FAILURE
) {
2006 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
2010 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
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
);
2018 if (ret
!= CY_AS_ERROR_SUCCESS
)
2021 /* The request and response are freed as part of the
2022 * MiscFuncCallback */
2027 cy_as_ll_destroy_request(dev_p
, req_p
);
2028 cy_as_ll_destroy_response(dev_p
, reply_p
);
2032 EXPORT_SYMBOL(cy_as_misc_set_gpio_value
);
2034 static cy_as_return_status_t
2035 my_enter_standby(cy_as_device
*dev_p
, cy_bool pin
)
2037 cy_as_misc_cancel_ex_requests(dev_p
);
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
);
2044 if (cy_as_hal_set_wakeup_pin(dev_p
->tag
, cy_false
))
2045 cy_as_device_set_pin_standby(dev_p
);
2047 return CY_AS_ERROR_SETTING_WAKEUP_PIN
;
2050 * put antioch in the standby mode
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
);
2058 * when the antioch comes out of standby, we have to wait until
2059 * the firmware initialization completes before sending other
2062 cy_as_device_set_firmware_not_loaded(dev_p
);
2065 * keep west bridge interrupt disabled until the device is being woken
2068 dev_p
->stby_int_mask
= cy_as_hal_disable_interrupts();
2070 return CY_AS_ERROR_SUCCESS
;
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
,
2079 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
2081 if (cy_as_ll_request_response__get_code(reply_p
) !=
2082 CY_RESP_SUCCESS_FAILURE
) {
2083 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
2087 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
2090 cy_as_ll_destroy_request(dev_p
, req_p
);
2091 cy_as_ll_destroy_response(dev_p
, reply_p
);
2093 if (ret
!= CY_AS_ERROR_SUCCESS
)
2096 ret
= my_enter_standby(dev_p
, pin
);
2101 cy_as_return_status_t
2102 cy_as_misc_enter_standby(cy_as_device_handle handle
,
2104 cy_as_function_callback cb
,
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
;
2112 cy_as_log_debug_message(6, "cy_as_misc_enter_standby called");
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
;
2120 * if we already are in standby, do not do it again and let the
2121 * user know via the error return.
2123 ret
= cy_as_misc_in_standby(handle
, &standby
);
2124 if (ret
!= CY_AS_ERROR_SUCCESS
)
2127 if (standby
== cy_true
)
2128 return CY_AS_ERROR_ALREADY_STANDBY
;
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
2135 if (cy_as_device_is_in_suspend_mode(dev_p
))
2136 cy_as_misc_leave_suspend(dev_p
, 0, 0);
2138 if (dev_p
->usb_count
) {
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.
2144 return CY_AS_ERROR_USB_RUNNING
;
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.
2152 if (dev_p
->storage_count
) {
2154 * if there are async storage operations pending,
2155 * make one attempt to complete them.
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
;
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
);
2168 * if more storage operations were queued
2169 * at this stage, return an error.
2171 if (cy_as_device_is_storage_async_pending(dev_p
))
2172 return CY_AS_ERROR_ASYNC_PENDING
;
2175 req_p
= cy_as_ll_create_request(dev_p
,
2176 CY_RQT_PREPARE_FOR_STANDBY
,
2177 CY_RQT_GENERAL_RQT_CONTEXT
, 1);
2179 return CY_AS_ERROR_OUT_OF_MEMORY
;
2181 reply_p
= cy_as_ll_create_response(dev_p
, 1);
2183 cy_as_ll_destroy_request(dev_p
, req_p
);
2184 return CY_AS_ERROR_OUT_OF_MEMORY
;
2188 ret
= cy_as_ll_send_request_wait_reply(dev_p
,
2190 if (ret
!= CY_AS_ERROR_SUCCESS
)
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
);
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
);
2204 if (ret
!= CY_AS_ERROR_SUCCESS
)
2207 /* The request and response are freed
2208 * as part of the MiscFuncCallback */
2212 cy_as_ll_destroy_request(dev_p
, req_p
);
2213 cy_as_ll_destroy_response(dev_p
, reply_p
);
2215 ret
= my_enter_standby(dev_p
, pin
);
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);
2226 EXPORT_SYMBOL(cy_as_misc_enter_standby
);
2228 cy_as_return_status_t
2229 cy_as_misc_enter_standby_e_x_u(cy_as_device_handle handle
,
2231 cy_bool uvalid_special
,
2232 cy_as_function_callback cb
,
2235 cy_as_device
*dev_p
;
2237 dev_p
= (cy_as_device
*)handle
;
2239 cy_as_hal_write_register(dev_p
->tag
, 0xc5, 0x4);
2241 return cy_as_misc_enter_standby(handle
, pin
, cb
, client
);
2244 cy_as_return_status_t
2245 cy_as_misc_leave_standby(cy_as_device_handle handle
,
2246 cy_as_resource_type resource
)
2248 cy_as_device
*dev_p
;
2250 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
2254 cy_as_log_debug_message(6, "cy_as_misc_leave_standby called");
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
;
2262 if (cy_as_device_is_register_standby(dev_p
)) {
2264 * set a flag to indicate that the west bridge is waking
2267 cy_as_device_set_waking(dev_p
);
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.
2274 v
= cy_as_hal_read_register(dev_p
->tag
,
2275 CY_AS_MEM_CM_WB_CFG_ID
);
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.
2284 if (cy_as_device_is_crystal(dev_p
))
2286 CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL
);
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
);
2294 * if the P-SPI interface mode is in use, there may be a
2295 * need to re-synchronise the serial clock used for
2298 if (!is_valid_silicon_id(v
)) {
2299 if (cy_as_hal_sync_device_clocks(dev_p
->tag
) !=
2301 cy_as_hal_enable_interrupts(
2302 dev_p
->stby_int_mask
);
2303 return CY_AS_ERROR_TIMEOUT
;
2306 } while (!is_valid_silicon_id(v
) && count
-- > 0);
2309 * if we tried to read the register and could not,
2313 cy_as_hal_enable_interrupts(
2314 dev_p
->stby_int_mask
);
2315 return CY_AS_ERROR_TIMEOUT
;
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.
2324 cy_as_device_clear_register_standby(dev_p
);
2327 * initialize any registers that may have been changed
2328 * while the device was in standby mode.
2330 cy_as_hal_init_dev_registers(dev_p
->tag
, cy_true
);
2331 } else if (cy_as_device_is_pin_standby(dev_p
)) {
2333 * set a flag to indicate that the west bridge is waking
2336 cy_as_device_set_waking(dev_p
);
2340 * try to set the wakeup pin, if this fails in the HAL
2341 * layer, return this failure to the user.
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
;
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.
2354 if (cy_as_device_is_crystal(dev_p
))
2355 cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL
);
2357 cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK
);
2360 * initialize any registers that may have been changed
2361 * while the device was in standby mode.
2363 cy_as_hal_init_dev_registers(dev_p
->tag
, cy_true
);
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.
2371 cy_as_device_clear_pin_standby(dev_p
);
2373 return CY_AS_ERROR_NOT_IN_STANDBY
;
2377 * the west bridge interrupt can be enabled now.
2379 cy_as_hal_enable_interrupts(dev_p
->stby_int_mask
);
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.
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
);
2397 cy_as_hal_print_message("failed to clear antioch reset\n");
2398 return CY_AS_ERROR_TIMEOUT
;
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.
2410 /* If the wake-up event has been received,
2412 if (cy_as_device_is_firmware_loaded(dev_p
))
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
)
2424 cy_as_hal_sleep(10);
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
;
2439 EXPORT_SYMBOL(cy_as_misc_leave_standby
);
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
2449 cy_as_device
*dev_p
;
2451 cy_as_log_debug_message(6, "cy_as_misc_register_callback called");
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
;
2458 dev_p
->misc_event_cb
= callback
;
2459 return CY_AS_ERROR_SUCCESS
;
2462 cy_as_return_status_t
2463 cy_as_misc_storage_changed(cy_as_device_handle handle
,
2464 cy_as_function_callback cb
,
2467 cy_as_device
*dev_p
;
2468 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
2470 cy_as_ll_request_response
*req_p
, *reply_p
;
2472 cy_as_log_debug_message(6, "cy_as_misc_storage_changed called");
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
);
2479 * make sure antioch is not in standby
2481 ret
= cy_as_misc_in_standby(dev_p
, &standby
);
2482 if (ret
!= CY_AS_ERROR_SUCCESS
)
2486 return CY_AS_ERROR_IN_STANDBY
;
2489 * make sure westbridge is not in suspend mode.
2491 if (cy_as_device_is_in_suspend_mode(dev_p
))
2492 return CY_AS_ERROR_IN_SUSPEND
;
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);
2498 return CY_AS_ERROR_OUT_OF_MEMORY
;
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);
2504 cy_as_ll_destroy_request(dev_p
, req_p
);
2505 return CY_AS_ERROR_OUT_OF_MEMORY
;
2509 ret
= cy_as_ll_send_request_wait_reply(dev_p
, req_p
, reply_p
);
2510 if (ret
!= CY_AS_ERROR_SUCCESS
)
2513 if (cy_as_ll_request_response__get_code(reply_p
) !=
2514 CY_RESP_SUCCESS_FAILURE
) {
2515 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
2519 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
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
);
2527 if (ret
!= CY_AS_ERROR_SUCCESS
)
2530 /* The request and response are freed as part of the
2531 * MiscFuncCallback */
2536 cy_as_ll_destroy_request(dev_p
, req_p
);
2537 cy_as_ll_destroy_response(dev_p
, reply_p
);
2541 EXPORT_SYMBOL(cy_as_misc_storage_changed
);
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
,
2551 cy_as_device
*dev_p
;
2552 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
2554 cy_as_ll_request_response
*req_p
, *reply_p
;
2558 cy_as_log_debug_message(6, "cy_as_misc_enter_suspend called");
2561 * basic sanity checks to ensure that the device is initialised.
2563 dev_p
= (cy_as_device
*)handle
;
2564 cy_as_check_device_ready(dev_p
);
2567 * make sure west bridge is not already in standby
2569 cy_as_misc_in_standby(dev_p
, &standby
);
2571 return CY_AS_ERROR_IN_STANDBY
;
2574 * make sure that the device is not already in suspend mode.
2576 if (cy_as_device_is_in_suspend_mode(dev_p
))
2577 return CY_AS_ERROR_IN_SUSPEND
;
2580 * make sure there is no active USB connection.
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
;
2587 * make sure that there are no async requests at this point in time.
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
;
2595 cy_as_hal_enable_interrupts(int_state
);
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);
2601 return CY_AS_ERROR_OUT_OF_MEMORY
;
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);
2607 cy_as_ll_destroy_request(dev_p
, req_p
);
2608 return CY_AS_ERROR_OUT_OF_MEMORY
;
2611 /* Wakeup control flags. */
2617 cy_as_ll_request_response__set_word(req_p
, 0, value
);
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
,
2625 cy_as_misc_func_callback
);
2627 if (ret
!= CY_AS_ERROR_SUCCESS
)
2630 return CY_AS_ERROR_SUCCESS
;
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
;
2637 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
2641 if (ret
== CY_AS_ERROR_SUCCESS
)
2642 cy_as_device_set_suspend_mode(dev_p
);
2644 cy_as_ll_destroy_request(dev_p
, req_p
);
2645 cy_as_ll_destroy_response(dev_p
, reply_p
);
2649 EXPORT_SYMBOL(cy_as_misc_enter_suspend
);
2651 cy_as_return_status_t
2652 cy_as_misc_leave_suspend(
2653 cy_as_device_handle handle
,
2654 cy_as_function_callback cb
,
2657 cy_as_device
*dev_p
;
2659 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
2661 cy_as_log_debug_message(6, "cy_as_misc_leave_suspend called");
2663 /* Make sure we have a valid device */
2664 dev_p
= (cy_as_device
*)handle
;
2665 cy_as_check_device_ready(dev_p
);
2667 /* Make sure we are in suspend mode. */
2668 if (cy_as_device_is_in_suspend_mode(dev_p
)) {
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);
2674 return CY_AS_ERROR_OUT_OF_MEMORY
;
2676 cy_as_insert_c_b_node(dev_p
->func_cbs_misc
, cbnode
);
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.
2686 v
= cy_as_hal_read_register(dev_p
->tag
,
2687 CY_AS_MEM_CM_WB_CFG_ID
);
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
);
2696 * if we tried to read the register and could not,
2700 return CY_AS_ERROR_TIMEOUT
;
2702 return CY_AS_ERROR_NOT_IN_SUSPEND
;
2706 * wait until the in suspend mode flag is cleared.
2709 while ((cy_as_device_is_in_suspend_mode(dev_p
))
2711 cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK
);
2714 if (cy_as_device_is_in_suspend_mode(dev_p
))
2715 ret
= CY_AS_ERROR_TIMEOUT
;
2720 EXPORT_SYMBOL(cy_as_misc_leave_suspend
);
2722 cy_as_return_status_t
2723 cy_as_misc_reserve_l_n_a_boot_area(cy_as_device_handle handle
,
2725 cy_as_function_callback cb
,
2728 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
2730 cy_as_ll_request_response
*req_p
, *reply_p
;
2732 cy_as_device
*dev_p
;
2736 cy_as_log_debug_message(6, "cy_as_misc_switch_pnand_mode called");
2738 /* Make sure we have a valid device */
2739 dev_p
= (cy_as_device
*)handle
;
2740 cy_as_check_device_ready(dev_p
);
2743 * make sure antioch is not in standby
2745 ret
= cy_as_misc_in_standby(dev_p
, &standby
);
2746 if (ret
!= CY_AS_ERROR_SUCCESS
)
2749 return CY_AS_ERROR_IN_STANDBY
;
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
;
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);
2760 return CY_AS_ERROR_OUT_OF_MEMORY
;
2761 cy_as_ll_request_response__set_word(req_p
,
2762 0, (uint16_t)numzones
);
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);
2768 cy_as_ll_destroy_request(dev_p
, req_p
);
2769 return CY_AS_ERROR_OUT_OF_MEMORY
;
2773 ret
= cy_as_ll_send_request_wait_reply(dev_p
,
2775 if (ret
!= CY_AS_ERROR_SUCCESS
)
2778 if (cy_as_ll_request_response__get_code(reply_p
) !=
2779 CY_RESP_SUCCESS_FAILURE
) {
2780 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
2784 ret
= cy_as_ll_request_response__get_word(reply_p
, 0);
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
);
2792 if (ret
!= CY_AS_ERROR_SUCCESS
)
2795 /* The request and response are freed as part of the
2796 * MiscFuncCallback */
2801 cy_as_ll_destroy_request(dev_p
, req_p
);
2802 cy_as_ll_destroy_response(dev_p
, reply_p
);
2807 cy_as_func_c_b_node
*
2808 cy_as_create_func_c_b_node_data(cy_as_function_callback cb
,
2810 cy_as_funct_c_b_type type
,
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
);
2818 node
->node_type
= CYAS_FUNC_CB
;
2820 node
->client_data
= client
;
2821 node
->data_type
= type
;
2823 node
->data_type
|= CY_FUNCT_CB_DATA
;
2825 node
->data_type
|= CY_FUNCT_CB_NODATA
;
2832 cy_as_func_c_b_node
*
2833 cy_as_create_func_c_b_node(cy_as_function_callback cb
,
2836 return cy_as_create_func_c_b_node_data(cb
, client
,
2837 CY_FUNCT_CB_NODATA
, 0);
2841 cy_as_destroy_func_c_b_node(cy_as_func_c_b_node
*node
)
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
);
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
)
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
);
2860 node
->type
= CYAS_USB_FUNC_CB
;
2862 node
->client_data
= client
;
2869 cy_as_destroy_usb_func_c_b_node(cy_as_usb_func_c_b_node
*node
)
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
);
2879 cy_as_usb_io_c_b_node
*
2880 cy_as_create_usb_io_c_b_node(cy_as_usb_io_callback cb
)
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
);
2887 node
->type
= CYAS_USB_IO_CB
;
2895 cy_as_destroy_usb_io_c_b_node(cy_as_usb_io_c_b_node
*node
)
2899 node
->type
= CYAS_INVALID
;
2901 state
= cy_as_hal_disable_interrupts();
2902 cy_as_hal_c_b_free(node
);
2903 cy_as_hal_enable_interrupts(state
);
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
)
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
);
2918 node
->type
= CYAS_STORAGE_IO_CB
;
2920 node
->media
= media
;
2921 node
->device_index
= device_index
;
2923 node
->block_addr
= block_addr
;
2925 node
->req_p
= req_p
;
2926 node
->reply_p
= reply_p
;
2933 cy_as_destroy_storage_io_c_b_node(cy_as_storage_io_c_b_node
*node
)
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
);
2943 cy_as_create_c_b_queue(cy_as_c_b_node_type type
)
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
);
2960 cy_as_destroy_c_b_queue(cy_as_c_b_queue
*queue
)
2963 queue
->type
= CYAS_INVALID
;
2967 state
= cy_as_hal_disable_interrupts();
2968 cy_as_hal_c_b_free(queue
);
2969 cy_as_hal_enable_interrupts(state
);
2972 /* Inserts a CyAsCBNode into the queue, the
2973 * node type must match the queue type*/
2975 cy_as_insert_c_b_node(cy_as_c_b_queue
*queue_p
, void*cbnode
)
2979 int_state
= cy_as_hal_disable_interrupts();
2981 cy_as_hal_assert(queue_p
!= 0);
2983 switch (queue_p
->type
) {
2984 case CYAS_USB_FUNC_CB
:
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
;
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
;
2997 tail
->next_p
= node
;
2999 queue_p
->tail_p
= node
;
3003 case CYAS_USB_IO_CB
:
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
;
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
;
3016 tail
->next_p
= node
;
3018 queue_p
->tail_p
= node
;
3022 case CYAS_STORAGE_IO_CB
:
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
;
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
;
3035 tail
->next_p
= node
;
3037 queue_p
->tail_p
= node
;
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
;
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
;
3054 tail
->next_p
= node
;
3056 queue_p
->tail_p
= node
;
3061 cy_as_hal_assert(cy_false
);
3067 cy_as_hal_enable_interrupts(int_state
);
3070 /* Removes the tail node from the queue and frees it */
3072 cy_as_remove_c_b_tail_node(cy_as_c_b_queue
*queue_p
)
3076 int_state
= cy_as_hal_disable_interrupts();
3078 if (queue_p
->count
> 0) {
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.
3085 switch (queue_p
->type
) {
3088 cy_as_func_c_b_node
*node
=
3089 (cy_as_func_c_b_node
*)
3091 cy_as_func_c_b_node
*tail
=
3092 (cy_as_func_c_b_node
*)
3095 while (node
->next_p
!= tail
)
3096 node
= node
->next_p
;
3098 queue_p
->tail_p
= node
;
3100 cy_as_destroy_func_c_b_node(tail
);
3104 case CYAS_USB_FUNC_CB
:
3106 cy_as_usb_func_c_b_node
*node
=
3107 (cy_as_usb_func_c_b_node
*)
3109 cy_as_usb_func_c_b_node
*tail
=
3110 (cy_as_usb_func_c_b_node
*)
3113 while (node
->next_p
!= tail
)
3114 node
= node
->next_p
;
3116 queue_p
->tail_p
= node
;
3119 cy_as_destroy_usb_func_c_b_node(tail
);
3123 case CYAS_USB_IO_CB
:
3125 cy_as_usb_io_c_b_node
*node
=
3126 (cy_as_usb_io_c_b_node
*)
3128 cy_as_usb_io_c_b_node
*tail
=
3129 (cy_as_usb_io_c_b_node
*)
3132 while (node
->next_p
!= tail
)
3133 node
= node
->next_p
;
3135 queue_p
->tail_p
= node
;
3137 cy_as_destroy_usb_io_c_b_node(tail
);
3141 case CYAS_STORAGE_IO_CB
:
3143 cy_as_storage_io_c_b_node
*node
=
3144 (cy_as_storage_io_c_b_node
*)
3146 cy_as_storage_io_c_b_node
*tail
=
3147 (cy_as_storage_io_c_b_node
*)
3150 while (node
->next_p
!= tail
)
3151 node
= node
->next_p
;
3153 queue_p
->tail_p
= node
;
3155 cy_as_destroy_storage_io_c_b_node(tail
);
3160 cy_as_hal_assert(cy_false
);
3164 if (queue_p
->count
== 0) {
3165 queue_p
->head_p
= 0;
3166 queue_p
->tail_p
= 0;
3170 cy_as_hal_enable_interrupts(int_state
);
3173 /* Removes the first CyAsCBNode from the queue and frees it */
3175 cy_as_remove_c_b_node(cy_as_c_b_queue
*queue_p
)
3179 int_state
= cy_as_hal_disable_interrupts();
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
*)
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
*)
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
*)
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
*)
3205 queue_p
->head_p
= node
->next_p
;
3206 cy_as_destroy_func_c_b_node(node
);
3208 cy_as_hal_assert(cy_false
);
3212 if (queue_p
->count
== 0) {
3213 queue_p
->head_p
= 0;
3214 queue_p
->tail_p
= 0;
3218 cy_as_hal_enable_interrupts(int_state
);
3221 void my_print_func_c_b_node(cy_as_func_c_b_node
*node
)
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
,
3231 void my_print_c_b_queue(cy_as_c_b_queue
*queue_p
)
3235 cy_as_hal_print_message("| count: %u type: ", queue_p
->count
);
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->");
3249 for (i
= 0; i
< queue_p
->count
; i
++) {
3251 cy_as_hal_print_message("->");
3252 my_print_func_c_b_node(node
);
3253 node
= node
->next_p
;
3255 cy_as_hal_print_message("->[NULL]\n");
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");
3263 cy_as_hal_print_message("INVALID\n");
3266 cy_as_hal_print_message("|----------\n");
3270 /* Removes and frees all pending callbacks */
3272 cy_as_clear_c_b_queue(cy_as_c_b_queue
*queue_p
)
3274 uint32_t int_state
= cy_as_hal_disable_interrupts();
3276 while (queue_p
->count
!= 0)
3277 cy_as_remove_c_b_node(queue_p
);
3279 cy_as_hal_enable_interrupts(int_state
);
3282 cy_as_return_status_t
3283 cy_as_misc_send_request(cy_as_device
*dev_p
,
3284 cy_as_function_callback cb
,
3286 cy_as_funct_c_b_type type
,
3288 cy_as_c_b_queue
*queue
,
3290 cy_as_ll_request_response
*req_p
,
3291 cy_as_ll_request_response
*reply_p
,
3292 cy_as_response_callback rcb
)
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
;
3300 return CY_AS_ERROR_OUT_OF_MEMORY
;
3302 cy_as_insert_c_b_node(queue
, cbnode
);
3304 req_p
->flags
|= req_type
;
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
);
3314 cy_as_misc_cancel_ex_requests(cy_as_device
*dev_p
)
3317 for (i
= 0; i
< CY_RQT_CONTEXT_COUNT
; i
++)
3318 cy_as_ll_remove_all_requests(dev_p
, dev_p
->context
[i
]);
3323 cy_as_misc_func_callback(cy_as_device
*dev_p
,
3325 cy_as_ll_request_response
*rqt
,
3326 cy_as_ll_request_response
*resp
,
3327 cy_as_return_status_t stat
)
3329 cy_as_func_c_b_node
*node
= NULL
;
3330 cy_as_return_status_t ret
;
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
;
3340 cy_as_hal_assert(ex_request
|| ms_request
);
3345 cntxt
= cy_as_ll_request_response__get_context(rqt
);
3346 code
= cy_as_ll_request_response__get_code(rqt
);
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
);
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
,
3362 (cy_as_get_firmware_version_data
*)node
->data
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
;
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
);
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
);
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
);
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
);
3434 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
3435 cy_as_hal_assert(cy_false
);
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
);
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
);
3456 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
3457 cy_as_hal_assert(cy_false
);
3463 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
3464 cy_as_hal_assert(cy_false
);
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.
3473 if (stat
== CY_AS_ERROR_SUCCESS
)
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
);
3482 cy_as_remove_c_b_node(dev_p
->func_cbs_res
);