2 * Copyright (c) 2013 Qualcomm Atheros, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted (subject to the limitations in the
7 * disclaimer below) provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
17 * * Neither the name of Qualcomm Atheros nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
22 * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
23 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
33 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * @Abstract: USB implementation of HIF
47 //#include <hif_api.h>
48 #include <Magpie_api.h>
49 #include <vdesc_api.h>
50 #include <adf_os_mem.h>
51 #include <adf_os_io.h>
53 #include <dma_engine_api.h>
57 HIF_USB_CONTEXT g_hifUSBCtx;
60 static void send_buffer_via_fifo(VBUF *buf);
61 static int _HIFusb_get_reserved_headroom(hif_handle_t handle);
62 static struct zsDmaQueue* get_queue_from_pipe(int pipe);
64 int _HIFusb_get_max_msg_len(hif_handle_t handle, int pipe);
68 static VBUF* usbfifo_get_command_buf()
72 buf = g_hifUSBCtx.cmdQueue;
73 g_hifUSBCtx.cmdQueue = buf->next_buf;
78 static void usbfifo_recv_command(VBUF *buf)
80 #if ENABLE_SW_SWAP_DATA_MODE
82 struct zsDmaDesc* usbDesc;
85 #if ZM_FM_LOOPBACK == 1
86 send_buffer_via_fifo(buf);
89 #if ENABLE_SW_SWAP_DATA_MODE
90 currVdesc = (VDESC *)buf->desc_list;
91 usbDesc = (struct zsDmaDesc *)currVdesc->hw_desc_buf;
92 usbDesc->dataSize = currVdesc->data_size;
93 usbDesc->dataAddr = (volatile u32_t)(currVdesc->buf_addr + currVdesc->data_offset);
95 DMA_Engine_swap_data(usbDesc);
97 g_hifUSBCtx.hifCb.recv_buf(NULL, buf, g_hifUSBCtx.hifCb.context);
101 static VBUF* usbfifo_get_event_buf()
105 buf = g_hifUSBCtx.eventBufQ.head;
106 if ( g_hifUSBCtx.eventBufQ.head == g_hifUSBCtx.eventBufQ.tail ) {
107 g_hifUSBCtx.eventBufQ.head = NULL;
108 g_hifUSBCtx.eventBufQ.tail = NULL;
110 g_hifUSBCtx.eventBufQ.head = buf->next_buf;
113 buf->next_buf = NULL;
117 static void usbfifo_send_event_done(VBUF *buf)
119 #if ZM_FM_LOOPBACK == 1
121 _HIFusb_return_recv_buf(NULL, HIF_USB_PIPE_COMMAND, buf);
123 g_hifUSBCtx.hifCb.send_buf_done(buf, g_hifUSBCtx.hifCb.context);
127 #define MAGPIE_ENABLE_USBFIFO
129 hif_handle_t _HIFusb_init(HIF_CONFIG *pConfig)
131 USB_FIFO_CONFIG usbfifo;
133 #ifdef MAGPIE_ENABLE_USBFIFO
134 usbfifo.get_command_buf = usbfifo_get_command_buf;
135 usbfifo.recv_command = usbfifo_recv_command;
136 usbfifo.get_event_buf = usbfifo_get_event_buf;
137 usbfifo.send_event_done = usbfifo_send_event_done;
138 USBFIFO_init(&usbfifo);
141 // Initialize the terminator descriptor for dnQ & upQ
142 DMA_Engine_init_rx_queue(&g_hifUSBCtx.dnQ);
143 DMA_Engine_init_tx_queue(&g_hifUSBCtx.upQ);
145 #if SYSTEM_MODULE_HP_EP5
146 DMA_Engine_init_rx_queue(&g_hifUSBCtx.hpdnQ);
149 #if SYSTEM_MODULE_HP_EP6
150 DMA_Engine_init_rx_queue(&g_hifUSBCtx.mpdnQ);
153 g_hifUSBCtx.eventBufQ.head = NULL;
154 g_hifUSBCtx.eventBufQ.tail = NULL;
155 g_hifUSBCtx.cmdQueue = NULL;
160 void _HIFusb_shutdown(hif_handle_t handle)
162 // nothing to do in FW
165 void _HIFusb_register_callback(hif_handle_t handle, HIF_CALLBACK *pConfig)
167 //HIF_INPROC_CONTEXT *hifInprocCtx = (HIF_INPROC_CONTEXT *)handle;
169 g_hifUSBCtx.hifCb.send_buf_done = pConfig->send_buf_done;
170 g_hifUSBCtx.hifCb.recv_buf = pConfig->recv_buf;
171 g_hifUSBCtx.hifCb.context = pConfig->context;
176 //#define MAGPIE_REG_USB_
177 void _HIFusb_start(hif_handle_t handle)
180 ZM_PTA_DN_DMA_ADDRH_REG = (u32_t)g_hifUSBCtx.dnQ.head >> 16;
181 ZM_PTA_DN_DMA_ADDRL_REG = (u32_t)g_hifUSBCtx.dnQ.head & 0xffff;
183 ZM_PTA_UP_DMA_ADDRH_REG = (u32_t)g_hifUSBCtx.upQ.head >> 16;
184 ZM_PTA_UP_DMA_ADDRL_REG = (u32_t)g_hifUSBCtx.upQ.head & 0xffff;
186 A_PRINTF("\n\r\t=>[dnQ] 0x%08x \n[", (u32_t)g_hifUSBCtx.dnQ.head);
187 A_PRINTF("\t=>[upQ] 0x%08x \n[", (u32_t)g_hifUSBCtx.upQ.head);
189 MAGPIE_REG_USB_RX0_DESC_START = (u32_t)g_hifUSBCtx.dnQ.head;
190 MAGPIE_REG_USB_TX0_DESC_START = (u32_t)g_hifUSBCtx.upQ.head;
191 #if SYSTEM_MODULE_HP_EP5
192 A_PRINTF("\t=>[hp dnQ] 0x%08x \n[", (u32_t)g_hifUSBCtx.hpdnQ.head);
193 MAGPIE_REG_USB_RX1_DESC_START = (u32_t)g_hifUSBCtx.hpdnQ.head;
196 #if SYSTEM_MODULE_HP_EP6
197 A_PRINTF("\t=>[mp dnQ] 0x%08x \n[", (u32_t)g_hifUSBCtx.mpdnQ.head);
198 MAGPIE_REG_USB_RX2_DESC_START = (u32_t)g_hifUSBCtx.mpdnQ.head;
201 MAGPIE_REG_USB_INTERRUPT_MASK = 0xffffffff; // enable all interrupt, refer to 7-34, Ryan
202 MAGPIE_REG_USB_RX0_DMA_START = 1;
204 #if SYSTEM_MODULE_HP_EP5
205 MAGPIE_REG_USB_RX1_DMA_START = 1;
208 #if SYSTEM_MODULE_HP_EP6
209 MAGPIE_REG_USB_RX2_DMA_START = 1;
214 static int _HIFusb_get_reserved_headroom(hif_handle_t handle)
219 static void config_command_pipe(VDESC *desc_list)
225 while ( theDesc != NULL ) {
226 buf = VBUF_alloc_vbuf();
228 buf->desc_list = theDesc;
229 theDesc = theDesc->next_desc;
230 buf->desc_list->next_desc = NULL;
232 if ( g_hifUSBCtx.cmdQueue == NULL ) {
233 g_hifUSBCtx.cmdQueue = buf;
235 buf->next_buf = g_hifUSBCtx.cmdQueue;
236 g_hifUSBCtx.cmdQueue = buf;
241 static void enable_rx(int pipe)
243 if ( pipe == HIF_USB_PIPE_TX ) {
245 ZM_PTA_DN_DMA_TRIGGER_REG = 1;
247 MAGPIE_REG_USB_RX0_DMA_START = 1;
250 #if SYSTEM_MODULE_HP_EP5
251 else if ( pipe == HIF_USB_PIPE_HP_TX ) {
252 MAGPIE_REG_USB_RX1_DMA_START = 1;
255 #if SYSTEM_MODULE_HP_EP6
256 else if ( pipe == HIF_USB_PIPE_MP_TX ) {
257 MAGPIE_REG_USB_RX2_DMA_START = 1;
262 static struct zsDmaQueue* get_queue_from_pipe(int pipe)
264 struct zsDmaQueue* q = NULL;
266 if ( pipe == HIF_USB_PIPE_TX ) {
267 q = &g_hifUSBCtx.dnQ;
269 #if SYSTEM_MODULE_HP_EP5
270 else if ( pipe == HIF_USB_PIPE_HP_TX )
272 q = &g_hifUSBCtx.hpdnQ;
275 #if SYSTEM_MODULE_HP_EP6
276 else if ( pipe == HIF_USB_PIPE_MP_TX )
278 q = &g_hifUSBCtx.mpdnQ;
288 //#define MAX_TX_BUF_SIZE ZM_BLOCK_SIZE
289 //#define MAX_TX_BUF_SIZE 1600
291 //void _HIFusb_config_pipe(hif_handle_t handle, int pipe, VDESC *desc_list)
292 void _HIFusb_config_pipe(hif_handle_t handle, int pipe, int creditCount)
297 struct zsDmaQueue *q;
299 if ( pipe != HIF_USB_PIPE_COMMAND ) {
303 // USB command pipe doesn't use FIFO
304 for(i=0; i < creditCount; i++)
306 desc = VDESC_alloc_vdesc();
308 adf_os_assert(desc != NULL);
310 desc->buf_addr = (A_UINT8 *)adf_os_mem_alloc(HIF_get_max_msg_len(handle, pipe));
311 desc->buf_size = HIF_get_max_msg_len(handle, pipe);
312 desc->next_desc = NULL;
313 desc->data_offset = 0;
323 desc->next_desc = head;
328 config_command_pipe(head);
332 q = get_queue_from_pipe(pipe);
333 DMA_Engine_config_rx_queue(q, creditCount, HIF_get_max_msg_len(handle, pipe));
338 static void send_buffer_via_fifo(VBUF *buf)
340 #if ENABLE_SW_SWAP_DATA_MODE
342 struct zsDmaDesc* usbDesc;
344 //A_PRINTF("send_buffer_via_fifo buf len %d\n", buf->buf_length);
345 currVdesc = (VDESC *)buf->desc_list;
346 usbDesc = (struct zsDmaDesc *)currVdesc->hw_desc_buf;
347 usbDesc->dataSize = currVdesc->data_size;
348 usbDesc->dataAddr = (volatile u32_t)(currVdesc->buf_addr + currVdesc->data_offset);
350 DMA_Engine_swap_data(usbDesc);
353 if ( g_hifUSBCtx.eventBufQ.head == NULL ) {
354 g_hifUSBCtx.eventBufQ.head = buf;
355 g_hifUSBCtx.eventBufQ.tail = buf;
357 g_hifUSBCtx.eventBufQ.tail->next_buf = buf;
358 g_hifUSBCtx.eventBufQ.tail = buf;
361 USBFIFO_enable_event_isr();
364 int _HIFusb_send_buffer(hif_handle_t handle, int pipe, VBUF *buf)
366 if ( pipe == HIF_USB_PIPE_INTERRUPT ) {
367 send_buffer_via_fifo(buf);
369 DMA_Engine_xmit_buf(&g_hifUSBCtx.upQ, buf);
371 ZM_PTA_UP_DMA_TRIGGER_REG = 1;
373 MAGPIE_REG_USB_TX0_DMA_START = 1;
381 void _HIFusb_return_recv_buf(hif_handle_t handle, int pipe, VBUF *buf)
383 struct zsDmaQueue *q;
385 if ( pipe == HIF_USB_PIPE_COMMAND ) {
386 if ( g_hifUSBCtx.cmdQueue == NULL ) {
387 g_hifUSBCtx.cmdQueue = buf;
389 buf->next_buf = g_hifUSBCtx.cmdQueue;
390 g_hifUSBCtx.cmdQueue = buf;
393 q = get_queue_from_pipe(pipe);
394 DMA_Engine_return_recv_buf(q, buf);
399 void _HIFusb_set_recv_bufsz(hif_handle_t handle, int pipe, int bufsz)
405 void _HIFusb_pause_recv(hif_handle_t handle, int pipe)
410 void _HIFusb_resume_recv(hif_handle_t handle, int pipe)
415 int _HIFusb_is_pipe_supported(hif_handle_t handle, int pipe)
417 if ( pipe < HIF_USB_PIPE_TX || pipe > HIF_USB_PIPE_MP_TX ) {
424 int _HIFusb_get_max_msg_len(hif_handle_t handle, int pipe)
427 case HIF_USB_PIPE_INTERRUPT:
428 case HIF_USB_PIPE_COMMAND:
436 static void handle_tx_complete_isr()
440 //A_PRINTF("USB Tx complete\n\r");
441 #if ZM_FM_LOOPBACK == 1
443 struct zsDmaDesc* desc;
445 desc = DMA_Engine_get_packet(&g_hifUSBCtx.upQ);
446 vdesc = VDESC_HW_TO_VDESC(desc);
448 if ( vdesc->control == HIF_USB_PIPE_TX ) {
449 DMA_Engine_reclaim_packet(&g_hifUSBCtx.dnQ, desc);
451 #if SYSTEM_MODULE_HP_EP5
452 else if ( vdesc->control == HIF_USB_PIPE_HP_TX ) {
453 DMA_Engine_reclaim_packet(&g_hifUSBCtx.hpdnQ, desc);
456 #if SYSTEM_MODULE_HP_EP6
457 else if ( vdesc->control == HIF_USB_PIPE_MP_TX ) {
458 DMA_Engine_reclaim_packet(&g_hifUSBCtx.mpdnQ, desc);
463 ZM_PTA_DN_DMA_TRIGGER_REG = 1;
465 MAGPIE_REG_USB_RX0_DMA_START = 1;
469 buf = DMA_Engine_reap_xmited_buf(&g_hifUSBCtx.upQ);
470 g_hifUSBCtx.hifCb.send_buf_done(buf, g_hifUSBCtx.hifCb.context);
471 #endif /* ZM_FM_LOOPBACK == 1 */
474 static void handle_rx_complete_isr()
478 #if ZM_FM_LOOPBACK == 1
480 struct zsDmaDesc* desc;
482 //A_PRINTF("USB Rx complete\n\r");
483 desc = DMA_Engine_get_packet(&g_hifUSBCtx.dnQ);
484 vdesc = VDESC_HW_TO_VDESC(desc);
485 vdesc->control = HIF_USB_PIPE_TX;
487 DMA_Engine_put_packet(&g_hifUSBCtx.upQ, desc);
490 ZM_PTA_UP_DMA_TRIGGER_REG = 1;
492 MAGPIE_REG_USB_TX0_DMA_START = 1;
496 buf = DMA_Engine_reap_recv_buf(&g_hifUSBCtx.dnQ);
497 g_hifUSBCtx.hifCb.recv_buf(NULL, buf, g_hifUSBCtx.hifCb.context);
501 #if SYSTEM_MODULE_HP_EP5
502 static void handle_hp_rx_complete_isr()
506 #if ZM_FM_LOOPBACK == 1
508 struct zsDmaDesc* desc;
510 desc = DMA_Engine_get_packet(&g_hifUSBCtx.hpdnQ);
511 vdesc = VDESC_HW_TO_VDESC(desc);
512 vdesc->control = HIF_USB_PIPE_HP_TX;
514 DMA_Engine_put_packet(&g_hifUSBCtx.upQ, desc);
515 MAGPIE_REG_USB_TX0_DMA_START = 1;
518 buf = DMA_Engine_reap_recv_buf(&g_hifUSBCtx.hpdnQ);
519 g_hifUSBCtx.hifCb.recv_buf(NULL, buf, g_hifUSBCtx.hifCb.context);
524 #if SYSTEM_MODULE_HP_EP6
525 static void handle_mp_rx_complete_isr()
529 #if ZM_FM_LOOPBACK == 1
531 struct zsDmaDesc* desc;
533 desc = DMA_Engine_get_packet(&g_hifUSBCtx.mpdnQ);
534 vdesc = VDESC_HW_TO_VDESC(desc);
535 vdesc->control = HIF_USB_PIPE_MP_TX;
537 DMA_Engine_put_packet(&g_hifUSBCtx.upQ, desc);
538 MAGPIE_REG_USB_TX0_DMA_START = 1;
541 buf = DMA_Engine_reap_recv_buf(&g_hifUSBCtx.mpdnQ);
542 g_hifUSBCtx.hifCb.recv_buf(NULL, buf, g_hifUSBCtx.hifCb.context);
547 void _HIFusb_isr_handler(hif_handle_t h)
549 //struct zsDmaDesc* desc;
553 intr = ZM_PTA_INT_FLAG_REG;
555 intr = MAGPIE_REG_USB_INTERRUPT;
559 if ((intr & (ZM_PTA_DOWN_INT_BIT|ZM_PTA_UP_INT_BIT))!=0)
561 if ((intr & (MAGPIE_REG_USB_INTERRUPT_TX0_COMPL|MAGPIE_REG_USB_INTERRUPT_RX0_COMPL|
562 MAGPIE_REG_USB_INTERRUPT_RX1_COMPL|MAGPIE_REG_USB_INTERRUPT_RX2_COMPL)) != 0)
565 #if SYSTEM_MODULE_HP_EP5
568 if ( DMA_Engine_has_compl_packets(&g_hifUSBCtx.hpdnQ) )
570 handle_hp_rx_complete_isr();
578 #endif // endif SYSTEM_MODULE_HP_EP5
580 #if SYSTEM_MODULE_HP_EP6
583 if ( DMA_Engine_has_compl_packets(&g_hifUSBCtx.mpdnQ) )
585 handle_mp_rx_complete_isr();
593 #endif // endif SYSTEM_MODULE_HP_EP5
599 /* zgUpQ own bits changed */
600 if ( DMA_Engine_has_compl_packets((struct zsDmaQueue *)&g_hifUSBCtx.upQ) )
602 handle_tx_complete_isr();
606 /* zgDnQ own bits changed */
607 if ( DMA_Engine_has_compl_packets(&g_hifUSBCtx.dnQ) )
609 handle_rx_complete_isr();
622 void _HIFusb_get_default_pipe(hif_handle_t handle, A_UINT8 *pipe_uplink, A_UINT8 *pipe_downlink)
624 *pipe_uplink = HIF_USB_PIPE_COMMAND; // Host -> Target
625 *pipe_downlink = HIF_USB_PIPE_INTERRUPT; // Target -> Host
628 /* the exported entry point into this module. All apis are accessed through
629 * function pointers */
630 void hif_usb_module_install(struct hif_api *apis)
633 apis->_init = _HIFusb_init;
634 apis->_start = _HIFusb_start;
635 apis->_config_pipe = _HIFusb_config_pipe;
636 apis->_isr_handler = _HIFusb_isr_handler;
637 apis->_send_buffer = _HIFusb_send_buffer;
638 apis->_return_recv_buf = _HIFusb_return_recv_buf;
639 apis->_is_pipe_supported = _HIFusb_is_pipe_supported;
640 apis->_get_max_msg_len = _HIFusb_get_max_msg_len;
641 apis->_register_callback = _HIFusb_register_callback;
642 apis->_shutdown = _HIFusb_shutdown;
643 apis->_get_reserved_headroom = _HIFusb_get_reserved_headroom;
644 apis->_get_default_pipe = _HIFusb_get_default_pipe;
646 /* save ptr to the ptr to the context for external code to inspect/modify internal module state */
647 //apis->pReserved = &g_pMboxHWContext;
650 void HIFusb_DescTraceDump(void )
652 #if SYSTEM_MODULE_HP_EP5
653 A_PRINTF("\n\r[hp dnQ] 0x%08x, ", (u32_t)g_hifUSBCtx.hpdnQ.head);
654 A_PRINTF("DMA TRACE 0x%08x\n\r [", HAL_WORD_REG_READ(MAGPIE_REG_USB_RX1_CUR_TRACE_ADDR));
656 DMA_Engine_desc_dump(&g_hifUSBCtx.hpdnQ);
659 #if SYSTEM_MODULE_HP_EP6
660 A_PRINTF("\n\r[mp dnQ] 0x%08x, ", (u32_t)g_hifUSBCtx.mpdnQ.head);
661 A_PRINTF("DMA TRACE 0x%08x\n\r [", HAL_WORD_REG_READ(MAGPIE_REG_USB_RX2_CUR_TRACE_ADDR));
663 DMA_Engine_desc_dump(&g_hifUSBCtx.mpdnQ);
666 A_PRINTF("\n\r[dnQ] 0x%08x, ", (u32_t)g_hifUSBCtx.dnQ.head);
667 A_PRINTF("DMA TRACE 0x%08x\n\r [", HAL_WORD_REG_READ(MAGPIE_REG_USB_RX0_CUR_TRACE_ADDR));
668 DMA_Engine_desc_dump(&g_hifUSBCtx.dnQ);
670 A_PRINTF("\n\n\r[upQ] 0x%08x, ", (u32_t)g_hifUSBCtx.upQ.head);
671 A_PRINTF("DMA TRACE 0x%08x\n\r [", HAL_WORD_REG_READ(MAGPIE_REG_USB_TX0_CUR_TRACE_ADDR));
672 DMA_Engine_desc_dump((struct zsDmaQueue *)&g_hifUSBCtx.upQ);