4 * @Abstract: USB implementation of HIF
8 * Copyright (c) 2008 Atheros Communications Inc.
17 //#include <hif_api.h>
18 #include <Magpie_api.h>
19 #include <vdesc_api.h>
20 #include <adf_os_mem.h>
21 #include <adf_os_io.h>
23 #include <dma_engine_api.h>
27 HIF_USB_CONTEXT g_hifUSBCtx;
30 static void send_buffer_via_fifo(VBUF *buf);
31 static int _HIFusb_get_reserved_headroom(hif_handle_t handle);
32 static struct zsDmaQueue* get_queue_from_pipe(int pipe);
34 int _HIFusb_get_max_msg_len(hif_handle_t handle, int pipe);
38 static VBUF* usbfifo_get_command_buf()
42 buf = g_hifUSBCtx.cmdQueue;
43 g_hifUSBCtx.cmdQueue = buf->next_buf;
48 static void usbfifo_recv_command(VBUF *buf)
50 #if ENABLE_SW_SWAP_DATA_MODE
52 struct zsDmaDesc* usbDesc;
55 #if ZM_FM_LOOPBACK == 1
56 send_buffer_via_fifo(buf);
59 #if ENABLE_SW_SWAP_DATA_MODE
60 currVdesc = (VDESC *)buf->desc_list;
61 usbDesc = (struct zsDmaDesc *)currVdesc->hw_desc_buf;
62 usbDesc->dataSize = currVdesc->data_size;
63 usbDesc->dataAddr = (volatile u32_t)(currVdesc->buf_addr + currVdesc->data_offset);
65 DMA_Engine_swap_data(usbDesc);
67 g_hifUSBCtx.hifCb.recv_buf(NULL, buf, g_hifUSBCtx.hifCb.context);
71 static VBUF* usbfifo_get_event_buf()
75 buf = g_hifUSBCtx.eventBufQ.head;
76 if ( g_hifUSBCtx.eventBufQ.head == g_hifUSBCtx.eventBufQ.tail ) {
77 g_hifUSBCtx.eventBufQ.head = NULL;
78 g_hifUSBCtx.eventBufQ.tail = NULL;
80 g_hifUSBCtx.eventBufQ.head = buf->next_buf;
87 static void usbfifo_send_event_done(VBUF *buf)
89 #if ZM_FM_LOOPBACK == 1
91 _HIFusb_return_recv_buf(NULL, HIF_USB_PIPE_COMMAND, buf);
93 g_hifUSBCtx.hifCb.send_buf_done(buf, g_hifUSBCtx.hifCb.context);
97 #define MAGPIE_ENABLE_USBFIFO
99 hif_handle_t _HIFusb_init(HIF_CONFIG *pConfig)
101 USB_FIFO_CONFIG usbfifo;
103 #ifdef MAGPIE_ENABLE_USBFIFO
104 usbfifo.get_command_buf = usbfifo_get_command_buf;
105 usbfifo.recv_command = usbfifo_recv_command;
106 usbfifo.get_event_buf = usbfifo_get_event_buf;
107 usbfifo.send_event_done = usbfifo_send_event_done;
108 USBFIFO_init(&usbfifo);
111 // Initialize the terminator descriptor for dnQ & upQ
112 DMA_Engine_init_rx_queue(&g_hifUSBCtx.dnQ);
113 DMA_Engine_init_tx_queue(&g_hifUSBCtx.upQ);
115 #if SYSTEM_MODULE_HP_EP5
116 DMA_Engine_init_rx_queue(&g_hifUSBCtx.hpdnQ);
119 #if SYSTEM_MODULE_HP_EP6
120 DMA_Engine_init_rx_queue(&g_hifUSBCtx.mpdnQ);
123 g_hifUSBCtx.eventBufQ.head = NULL;
124 g_hifUSBCtx.eventBufQ.tail = NULL;
125 g_hifUSBCtx.cmdQueue = NULL;
130 void _HIFusb_shutdown(hif_handle_t handle)
132 // nothing to do in FW
135 void _HIFusb_register_callback(hif_handle_t handle, HIF_CALLBACK *pConfig)
137 //HIF_INPROC_CONTEXT *hifInprocCtx = (HIF_INPROC_CONTEXT *)handle;
139 g_hifUSBCtx.hifCb.send_buf_done = pConfig->send_buf_done;
140 g_hifUSBCtx.hifCb.recv_buf = pConfig->recv_buf;
141 g_hifUSBCtx.hifCb.context = pConfig->context;
146 //#define MAGPIE_REG_USB_
147 void _HIFusb_start(hif_handle_t handle)
150 ZM_PTA_DN_DMA_ADDRH_REG = (u32_t)g_hifUSBCtx.dnQ.head >> 16;
151 ZM_PTA_DN_DMA_ADDRL_REG = (u32_t)g_hifUSBCtx.dnQ.head & 0xffff;
153 ZM_PTA_UP_DMA_ADDRH_REG = (u32_t)g_hifUSBCtx.upQ.head >> 16;
154 ZM_PTA_UP_DMA_ADDRL_REG = (u32_t)g_hifUSBCtx.upQ.head & 0xffff;
156 A_PRINTF("\n\r\t=>[dnQ] 0x%08x \n[", (u32_t)g_hifUSBCtx.dnQ.head);
157 A_PRINTF("\t=>[upQ] 0x%08x \n[", (u32_t)g_hifUSBCtx.upQ.head);
159 MAGPIE_REG_USB_RX0_DESC_START = (u32_t)g_hifUSBCtx.dnQ.head;
160 MAGPIE_REG_USB_TX0_DESC_START = (u32_t)g_hifUSBCtx.upQ.head;
161 #if SYSTEM_MODULE_HP_EP5
162 A_PRINTF("\t=>[hp dnQ] 0x%08x \n[", (u32_t)g_hifUSBCtx.hpdnQ.head);
163 MAGPIE_REG_USB_RX1_DESC_START = (u32_t)g_hifUSBCtx.hpdnQ.head;
166 #if SYSTEM_MODULE_HP_EP6
167 A_PRINTF("\t=>[mp dnQ] 0x%08x \n[", (u32_t)g_hifUSBCtx.mpdnQ.head);
168 MAGPIE_REG_USB_RX2_DESC_START = (u32_t)g_hifUSBCtx.mpdnQ.head;
171 MAGPIE_REG_USB_INTERRUPT_MASK = 0xffffffff; // enable all interrupt, refer to 7-34, Ryan
172 MAGPIE_REG_USB_RX0_DMA_START = 1;
174 #if SYSTEM_MODULE_HP_EP5
175 MAGPIE_REG_USB_RX1_DMA_START = 1;
178 #if SYSTEM_MODULE_HP_EP6
179 MAGPIE_REG_USB_RX2_DMA_START = 1;
184 static int _HIFusb_get_reserved_headroom(hif_handle_t handle)
189 static void config_command_pipe(VDESC *desc_list)
195 while ( theDesc != NULL ) {
196 buf = VBUF_alloc_vbuf();
198 buf->desc_list = theDesc;
199 theDesc = theDesc->next_desc;
200 buf->desc_list->next_desc = NULL;
202 if ( g_hifUSBCtx.cmdQueue == NULL ) {
203 g_hifUSBCtx.cmdQueue = buf;
205 buf->next_buf = g_hifUSBCtx.cmdQueue;
206 g_hifUSBCtx.cmdQueue = buf;
211 static void enable_rx(int pipe)
213 if ( pipe == HIF_USB_PIPE_TX ) {
215 ZM_PTA_DN_DMA_TRIGGER_REG = 1;
217 MAGPIE_REG_USB_RX0_DMA_START = 1;
220 #if SYSTEM_MODULE_HP_EP5
221 else if ( pipe == HIF_USB_PIPE_HP_TX ) {
222 MAGPIE_REG_USB_RX1_DMA_START = 1;
225 #if SYSTEM_MODULE_HP_EP6
226 else if ( pipe == HIF_USB_PIPE_MP_TX ) {
227 MAGPIE_REG_USB_RX2_DMA_START = 1;
232 static struct zsDmaQueue* get_queue_from_pipe(int pipe)
234 struct zsDmaQueue* q = NULL;
236 if ( pipe == HIF_USB_PIPE_TX ) {
237 q = &g_hifUSBCtx.dnQ;
239 #if SYSTEM_MODULE_HP_EP5
240 else if ( pipe == HIF_USB_PIPE_HP_TX )
242 q = &g_hifUSBCtx.hpdnQ;
245 #if SYSTEM_MODULE_HP_EP6
246 else if ( pipe == HIF_USB_PIPE_MP_TX )
248 q = &g_hifUSBCtx.mpdnQ;
258 //#define MAX_TX_BUF_SIZE ZM_BLOCK_SIZE
259 //#define MAX_TX_BUF_SIZE 1600
261 //void _HIFusb_config_pipe(hif_handle_t handle, int pipe, VDESC *desc_list)
262 void _HIFusb_config_pipe(hif_handle_t handle, int pipe, int creditCount)
267 struct zsDmaQueue *q;
269 if ( pipe != HIF_USB_PIPE_COMMAND ) {
273 // USB command pipe doesn't use FIFO
274 for(i=0; i < creditCount; i++)
276 desc = VDESC_alloc_vdesc();
278 adf_os_assert(desc != NULL);
280 desc->buf_addr = (A_UINT8 *)adf_os_mem_alloc(HIF_get_max_msg_len(handle, pipe));
281 desc->buf_size = HIF_get_max_msg_len(handle, pipe);
282 desc->next_desc = NULL;
283 desc->data_offset = 0;
293 desc->next_desc = head;
298 config_command_pipe(head);
302 q = get_queue_from_pipe(pipe);
303 DMA_Engine_config_rx_queue(q, creditCount, HIF_get_max_msg_len(handle, pipe));
308 static void send_buffer_via_fifo(VBUF *buf)
310 #if ENABLE_SW_SWAP_DATA_MODE
312 struct zsDmaDesc* usbDesc;
314 //A_PRINTF("send_buffer_via_fifo buf len %d\n", buf->buf_length);
315 currVdesc = (VDESC *)buf->desc_list;
316 usbDesc = (struct zsDmaDesc *)currVdesc->hw_desc_buf;
317 usbDesc->dataSize = currVdesc->data_size;
318 usbDesc->dataAddr = (volatile u32_t)(currVdesc->buf_addr + currVdesc->data_offset);
320 DMA_Engine_swap_data(usbDesc);
323 if ( g_hifUSBCtx.eventBufQ.head == NULL ) {
324 g_hifUSBCtx.eventBufQ.head = buf;
325 g_hifUSBCtx.eventBufQ.tail = buf;
327 g_hifUSBCtx.eventBufQ.tail->next_buf = buf;
328 g_hifUSBCtx.eventBufQ.tail = buf;
331 USBFIFO_enable_event_isr();
334 int _HIFusb_send_buffer(hif_handle_t handle, int pipe, VBUF *buf)
336 if ( pipe == HIF_USB_PIPE_INTERRUPT ) {
337 send_buffer_via_fifo(buf);
339 DMA_Engine_xmit_buf(&g_hifUSBCtx.upQ, buf);
341 ZM_PTA_UP_DMA_TRIGGER_REG = 1;
343 MAGPIE_REG_USB_TX0_DMA_START = 1;
351 void _HIFusb_return_recv_buf(hif_handle_t handle, int pipe, VBUF *buf)
353 struct zsDmaQueue *q;
355 if ( pipe == HIF_USB_PIPE_COMMAND ) {
356 if ( g_hifUSBCtx.cmdQueue == NULL ) {
357 g_hifUSBCtx.cmdQueue = buf;
359 buf->next_buf = g_hifUSBCtx.cmdQueue;
360 g_hifUSBCtx.cmdQueue = buf;
363 q = get_queue_from_pipe(pipe);
364 DMA_Engine_return_recv_buf(q, buf);
369 void _HIFusb_set_recv_bufsz(hif_handle_t handle, int pipe, int bufsz)
375 void _HIFusb_pause_recv(hif_handle_t handle, int pipe)
380 void _HIFusb_resume_recv(hif_handle_t handle, int pipe)
385 int _HIFusb_is_pipe_supported(hif_handle_t handle, int pipe)
387 if ( pipe < HIF_USB_PIPE_TX || pipe > HIF_USB_PIPE_MP_TX ) {
394 int _HIFusb_get_max_msg_len(hif_handle_t handle, int pipe)
397 case HIF_USB_PIPE_INTERRUPT:
398 case HIF_USB_PIPE_COMMAND:
406 static void handle_tx_complete_isr()
410 //A_PRINTF("USB Tx complete\n\r");
411 #if ZM_FM_LOOPBACK == 1
413 struct zsDmaDesc* desc;
415 desc = DMA_Engine_get_packet(&g_hifUSBCtx.upQ);
416 vdesc = VDESC_HW_TO_VDESC(desc);
418 if ( vdesc->control == HIF_USB_PIPE_TX ) {
419 DMA_Engine_reclaim_packet(&g_hifUSBCtx.dnQ, desc);
421 #if SYSTEM_MODULE_HP_EP5
422 else if ( vdesc->control == HIF_USB_PIPE_HP_TX ) {
423 DMA_Engine_reclaim_packet(&g_hifUSBCtx.hpdnQ, desc);
426 #if SYSTEM_MODULE_HP_EP6
427 else if ( vdesc->control == HIF_USB_PIPE_MP_TX ) {
428 DMA_Engine_reclaim_packet(&g_hifUSBCtx.mpdnQ, desc);
433 ZM_PTA_DN_DMA_TRIGGER_REG = 1;
435 MAGPIE_REG_USB_RX0_DMA_START = 1;
439 buf = DMA_Engine_reap_xmited_buf(&g_hifUSBCtx.upQ);
440 g_hifUSBCtx.hifCb.send_buf_done(buf, g_hifUSBCtx.hifCb.context);
441 #endif /* ZM_FM_LOOPBACK == 1 */
444 static void handle_rx_complete_isr()
448 #if ZM_FM_LOOPBACK == 1
450 struct zsDmaDesc* desc;
452 //A_PRINTF("USB Rx complete\n\r");
453 desc = DMA_Engine_get_packet(&g_hifUSBCtx.dnQ);
454 vdesc = VDESC_HW_TO_VDESC(desc);
455 vdesc->control = HIF_USB_PIPE_TX;
457 DMA_Engine_put_packet(&g_hifUSBCtx.upQ, desc);
460 ZM_PTA_UP_DMA_TRIGGER_REG = 1;
462 MAGPIE_REG_USB_TX0_DMA_START = 1;
466 buf = DMA_Engine_reap_recv_buf(&g_hifUSBCtx.dnQ);
467 g_hifUSBCtx.hifCb.recv_buf(NULL, buf, g_hifUSBCtx.hifCb.context);
471 #if SYSTEM_MODULE_HP_EP5
472 static void handle_hp_rx_complete_isr()
476 #if ZM_FM_LOOPBACK == 1
478 struct zsDmaDesc* desc;
480 desc = DMA_Engine_get_packet(&g_hifUSBCtx.hpdnQ);
481 vdesc = VDESC_HW_TO_VDESC(desc);
482 vdesc->control = HIF_USB_PIPE_HP_TX;
484 DMA_Engine_put_packet(&g_hifUSBCtx.upQ, desc);
485 MAGPIE_REG_USB_TX0_DMA_START = 1;
488 buf = DMA_Engine_reap_recv_buf(&g_hifUSBCtx.hpdnQ);
489 g_hifUSBCtx.hifCb.recv_buf(NULL, buf, g_hifUSBCtx.hifCb.context);
494 #if SYSTEM_MODULE_HP_EP6
495 static void handle_mp_rx_complete_isr()
499 #if ZM_FM_LOOPBACK == 1
501 struct zsDmaDesc* desc;
503 desc = DMA_Engine_get_packet(&g_hifUSBCtx.mpdnQ);
504 vdesc = VDESC_HW_TO_VDESC(desc);
505 vdesc->control = HIF_USB_PIPE_MP_TX;
507 DMA_Engine_put_packet(&g_hifUSBCtx.upQ, desc);
508 MAGPIE_REG_USB_TX0_DMA_START = 1;
511 buf = DMA_Engine_reap_recv_buf(&g_hifUSBCtx.mpdnQ);
512 g_hifUSBCtx.hifCb.recv_buf(NULL, buf, g_hifUSBCtx.hifCb.context);
517 void _HIFusb_isr_handler(hif_handle_t h)
519 //struct zsDmaDesc* desc;
523 intr = ZM_PTA_INT_FLAG_REG;
525 intr = MAGPIE_REG_USB_INTERRUPT;
529 if ((intr & (ZM_PTA_DOWN_INT_BIT|ZM_PTA_UP_INT_BIT))!=0)
531 if ((intr & (MAGPIE_REG_USB_INTERRUPT_TX0_COMPL|MAGPIE_REG_USB_INTERRUPT_RX0_COMPL|
532 MAGPIE_REG_USB_INTERRUPT_RX1_COMPL|MAGPIE_REG_USB_INTERRUPT_RX2_COMPL)) != 0)
535 #if SYSTEM_MODULE_HP_EP5
538 if ( DMA_Engine_has_compl_packets(&g_hifUSBCtx.hpdnQ) )
540 handle_hp_rx_complete_isr();
548 #endif // endif SYSTEM_MODULE_HP_EP5
550 #if SYSTEM_MODULE_HP_EP6
553 if ( DMA_Engine_has_compl_packets(&g_hifUSBCtx.mpdnQ) )
555 handle_mp_rx_complete_isr();
563 #endif // endif SYSTEM_MODULE_HP_EP5
569 /* zgUpQ own bits changed */
570 if ( DMA_Engine_has_compl_packets((struct zsDmaQueue *)&g_hifUSBCtx.upQ) )
572 handle_tx_complete_isr();
576 /* zgDnQ own bits changed */
577 if ( DMA_Engine_has_compl_packets(&g_hifUSBCtx.dnQ) )
579 handle_rx_complete_isr();
592 void _HIFusb_get_default_pipe(hif_handle_t handle, A_UINT8 *pipe_uplink, A_UINT8 *pipe_downlink)
594 *pipe_uplink = HIF_USB_PIPE_COMMAND; // Host -> Target
595 *pipe_downlink = HIF_USB_PIPE_INTERRUPT; // Target -> Host
598 /* the exported entry point into this module. All apis are accessed through
599 * function pointers */
600 void hif_usb_module_install(struct hif_api *apis)
603 apis->_init = _HIFusb_init;
604 apis->_start = _HIFusb_start;
605 apis->_config_pipe = _HIFusb_config_pipe;
606 apis->_isr_handler = _HIFusb_isr_handler;
607 apis->_send_buffer = _HIFusb_send_buffer;
608 apis->_return_recv_buf = _HIFusb_return_recv_buf;
609 apis->_is_pipe_supported = _HIFusb_is_pipe_supported;
610 apis->_get_max_msg_len = _HIFusb_get_max_msg_len;
611 apis->_register_callback = _HIFusb_register_callback;
612 apis->_shutdown = _HIFusb_shutdown;
613 apis->_get_reserved_headroom = _HIFusb_get_reserved_headroom;
614 apis->_get_default_pipe = _HIFusb_get_default_pipe;
616 /* save ptr to the ptr to the context for external code to inspect/modify internal module state */
617 //apis->pReserved = &g_pMboxHWContext;
620 void HIFusb_DescTraceDump(void )
622 #if SYSTEM_MODULE_HP_EP5
623 A_PRINTF("\n\r[hp dnQ] 0x%08x, ", (u32_t)g_hifUSBCtx.hpdnQ.head);
624 A_PRINTF("DMA TRACE 0x%08x\n\r [", HAL_WORD_REG_READ(MAGPIE_REG_USB_RX1_CUR_TRACE_ADDR));
626 DMA_Engine_desc_dump(&g_hifUSBCtx.hpdnQ);
629 #if SYSTEM_MODULE_HP_EP6
630 A_PRINTF("\n\r[mp dnQ] 0x%08x, ", (u32_t)g_hifUSBCtx.mpdnQ.head);
631 A_PRINTF("DMA TRACE 0x%08x\n\r [", HAL_WORD_REG_READ(MAGPIE_REG_USB_RX2_CUR_TRACE_ADDR));
633 DMA_Engine_desc_dump(&g_hifUSBCtx.mpdnQ);
636 A_PRINTF("\n\r[dnQ] 0x%08x, ", (u32_t)g_hifUSBCtx.dnQ.head);
637 A_PRINTF("DMA TRACE 0x%08x\n\r [", HAL_WORD_REG_READ(MAGPIE_REG_USB_RX0_CUR_TRACE_ADDR));
638 DMA_Engine_desc_dump(&g_hifUSBCtx.dnQ);
640 A_PRINTF("\n\n\r[upQ] 0x%08x, ", (u32_t)g_hifUSBCtx.upQ.head);
641 A_PRINTF("DMA TRACE 0x%08x\n\r [", HAL_WORD_REG_READ(MAGPIE_REG_USB_TX0_CUR_TRACE_ADDR));
642 DMA_Engine_desc_dump((struct zsDmaQueue *)&g_hifUSBCtx.upQ);