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.
36 #include <Magpie_api.h>
37 #include <cmnos_api.h>
43 /**************************Constants******************************/
45 /*************************Data types*******************************/
47 MAG_REG_AHB_RESET = 0x00050010,
48 MAG_REG_AHB_ARB = 0x00050018
51 #define PCI_AHB_ARB_ENB (1 << 3)
52 #define PCI_AHB_RESET_DMA (1 << 13)
53 #define PCI_AHB_RESET_DMA_HST_RAW (1 << 14)
54 #define PCI_AHB_RESET_DMA_HST (1 << 15)
56 /*********************************softC************************/
57 typedef struct __pci_softc{
62 #define ret_pkt sw.send_buf_done
63 #define indicate_pkt sw.recv_buf
64 #define htc_ctx sw.context
65 /*********************************DEFINES**********************************/
66 #define hdl_to_softc(_hdl) (__pci_softc_t *)(_hdl)
68 #define PCI_ENG_NUM(_eng) HIF_PCI_PIPE_##_eng
70 #define PCI_INIT_PIPE { \
79 #define rx_pipe0 DMA_ENGINE_RX0
80 #define rx_pipe1 DMA_ENGINE_RX1
81 #define tx_pipe0 DMA_ENGINE_TX0
82 #define tx_pipe1 DMA_ENGINE_TX1
84 #define dbg_pci_loopback 0
86 #define PCI_DBG_MODE 0
88 void __pci_cfg_pipe(hif_handle_t hdl, int pipe, int num_desc);
89 int __pci_get_max_msg_len(hif_handle_t hdl, int pipe);
90 void __pci_return_recv(hif_handle_t hdl, int pipe, VBUF *buf);
91 void __pci_reset(void);
92 void __pci_enable(void);
95 /***********************************Globals********************************/
97 * @brief Engines are fixed
99 __pci_softc_t pci_sc = {0};
102 /**************************************APIs********************************/
105 __pci_reg_read(A_UINT32 addr)
107 return *((volatile A_UINT32 *)addr);
111 __pci_reg_write(A_UINT32 addr, A_UINT32 val)
113 *((volatile A_UINT32 *)addr) = val;
117 __pci_get_pipe(dma_engine_t eng)
121 return HIF_PCI_PIPE_RX0;
123 return HIF_PCI_PIPE_RX1;
125 return HIF_PCI_PIPE_RX2;
127 return HIF_PCI_PIPE_RX3;
129 return HIF_PCI_PIPE_TX0;
131 return HIF_PCI_PIPE_TX1;
138 __pci_get_tx_eng(hif_pci_pipe_tx_t pipe)
141 case HIF_PCI_PIPE_TX0:
142 return DMA_ENGINE_TX0;
144 case HIF_PCI_PIPE_TX1:
145 return DMA_ENGINE_TX1;
148 return DMA_ENGINE_MAX;
152 __pci_get_rx_eng(hif_pci_pipe_rx_t pipe)
155 case HIF_PCI_PIPE_RX0:
156 return DMA_ENGINE_RX0;
158 case HIF_PCI_PIPE_RX1:
159 return DMA_ENGINE_RX1;
161 case HIF_PCI_PIPE_RX2:
162 return DMA_ENGINE_RX2;
164 case HIF_PCI_PIPE_RX3:
165 return DMA_ENGINE_RX3;
168 return DMA_ENGINE_MAX;
179 * Grant access to the internal memory for PCI DMA
182 r_data = __pci_reg_read(MAG_REG_AHB_ARB);
183 r_data |= PCI_AHB_ARB_ENB;
184 __pci_reg_write(MAG_REG_AHB_ARB, r_data);
189 * XXX: Move this to RAM
194 volatile A_UINT32 r_data;
197 * Poll until the Host has reset
199 A_PRINTF("Waiting for host reset..");
201 r_data = __pci_reg_read(MAG_REG_AHB_RESET);
203 if ( r_data & PCI_AHB_RESET_DMA_HST_RAW)
206 A_PRINTF("received.\n");
209 * Pull the AHB out of reset
212 r_data = __pci_reg_read(MAG_REG_AHB_RESET);
213 r_data &= ~PCI_AHB_RESET_DMA;
214 __pci_reg_write(MAG_REG_AHB_RESET, r_data);
219 * Put the AHB into reset
222 r_data = __pci_reg_read(MAG_REG_AHB_RESET);
223 r_data |= PCI_AHB_RESET_DMA;
224 __pci_reg_write(MAG_REG_AHB_RESET, r_data);
229 * Pull the AHB out of reset
232 r_data = __pci_reg_read(MAG_REG_AHB_RESET);
233 r_data &= ~PCI_AHB_RESET_DMA;
234 __pci_reg_write(MAG_REG_AHB_RESET, r_data);
242 __pci_boot_init(void)
247 dma_lib_tx_init(DMA_ENGINE_TX0, DMA_IF_PCI);
248 dma_lib_rx_init(DMA_ENGINE_RX0, DMA_IF_PCI);
250 dma_lib_rx_config(DMA_ENGINE_RX0, PCI_MAX_BOOT_DESC,
251 PCI_MAX_DATA_PKT_LEN);
259 * @return hif_handle_t
262 __pci_init(HIF_CONFIG *pConfig)
268 * Initializing the other TX engines
270 dma_lib_tx_init(DMA_ENGINE_TX0, DMA_IF_PCI);
271 dma_lib_tx_init(DMA_ENGINE_TX1, DMA_IF_PCI);
274 * Initializing the other RX engines
276 dma_lib_rx_init(DMA_ENGINE_RX0, DMA_IF_PCI);
277 dma_lib_rx_init(DMA_ENGINE_RX1, DMA_IF_PCI);
278 dma_lib_rx_init(DMA_ENGINE_RX2, DMA_IF_PCI);
279 dma_lib_rx_init(DMA_ENGINE_RX3, DMA_IF_PCI);
284 * @brief Configure the receive pipe
291 __pci_cfg_pipe(hif_handle_t hdl, int pipe, int num_desc)
296 eng = __pci_get_rx_eng(pipe);
298 if (eng == DMA_ENGINE_MAX) {
299 A_PRINTF("Bad Engine number\n");
303 desc_len = __pci_get_max_msg_len(hdl, pipe);
305 dma_lib_rx_config(eng, num_desc, desc_len);
308 * @brief Start the interface
313 __pci_start(hif_handle_t hdl)
318 * @brief Register callback of thre HTC
324 __pci_reg_callback(hif_handle_t hdl, HIF_CALLBACK *sw)
326 __pci_softc_t *sc = &pci_sc;
328 sc->htc_ctx = sw->context;
329 sc->indicate_pkt = sw->recv_buf;
330 sc->ret_pkt = sw->send_buf_done;
334 * @brief reap the transmit queue for trasnmitted packets
340 __pci_reap_xmitted(__pci_softc_t *sc, dma_engine_t eng_no)
345 pipe = __pci_get_pipe(eng_no);
347 vbuf = dma_lib_reap_xmitted(eng_no);
350 sc->ret_pkt(vbuf, sc->htc_ctx);
352 A_PRINTF("Empty RX Reap\n");
358 * @brief reap the receive queue for vbuf's on the specified
365 __pci_reap_recv(__pci_softc_t *sc, dma_engine_t eng_no)
369 vbuf = dma_lib_reap_recv(eng_no);
372 sc->indicate_pkt(NULL, vbuf, sc->htc_ctx);
374 A_PRINTF("Empty TX Reap \n");
377 * @brief The interrupt handler
382 __pci_isr_handler(hif_handle_t hdl)
384 __pci_softc_t *sc = &pci_sc;
391 if( dma_lib_xmit_done(DMA_ENGINE_TX1) ) {
392 __pci_reap_xmitted(sc,DMA_ENGINE_TX1);
395 if( dma_lib_recv_pkt(DMA_ENGINE_RX3) ) {
396 __pci_reap_recv(sc, DMA_ENGINE_RX3);
406 if( dma_lib_xmit_done(DMA_ENGINE_TX1) ) {
407 __pci_reap_xmitted(sc,DMA_ENGINE_TX1);
410 if( dma_lib_recv_pkt(DMA_ENGINE_RX2) ) {
411 __pci_reap_recv(sc, DMA_ENGINE_RX2);
421 if( dma_lib_xmit_done(DMA_ENGINE_TX1) ) {
422 __pci_reap_xmitted(sc,DMA_ENGINE_TX1);
425 if( dma_lib_recv_pkt(DMA_ENGINE_RX1) ) {
426 __pci_reap_recv(sc, DMA_ENGINE_RX1);
436 if( dma_lib_xmit_done(DMA_ENGINE_TX0) ) {
437 __pci_reap_xmitted(sc,DMA_ENGINE_TX0);
441 if( dma_lib_recv_pkt(DMA_ENGINE_RX0) ) {
442 __pci_reap_recv(sc, DMA_ENGINE_RX0);
450 * @brief transmit the vbuf from the specified pipe
459 __pci_xmit_buf(hif_handle_t hdl, int pipe, VBUF *vbuf)
463 eng = __pci_get_tx_eng(pipe);
465 if (eng == DMA_ENGINE_MAX) {
466 A_PRINTF("Invalid Pipe number\n");
470 return dma_lib_hard_xmit(eng, vbuf);
473 * @brief Submit the receive vbuf into the receive queue
480 __pci_return_recv(hif_handle_t hdl, int pipe, VBUF *buf)
484 eng = __pci_get_rx_eng(pipe);
486 if (eng == DMA_ENGINE_MAX)
489 dma_lib_return_recv(eng, buf);
492 * @brief Is this pipe number supported
500 __pci_is_pipe_supported(hif_handle_t hdl, int pipe)
502 if (pipe >= 0 && pipe <= 4)
508 * @brief maximum message length this pipe can support
516 __pci_get_max_msg_len(hif_handle_t hdl, int pipe)
518 if( pipe == HIF_PCI_PIPE_TX0 || pipe == HIF_PCI_PIPE_RX0)
519 return PCI_MAX_CMD_PKT_LEN;
521 return PCI_MAX_DATA_PKT_LEN;
524 * @brief return the header room required by this HIF
531 __pci_get_reserved_headroom(hif_handle_t hdl)
536 * @brief Device shutdown, HIF reset required
541 __pci_shutdown(hif_handle_t hdl)
547 __pci_get_def_pipe(hif_handle_t handle, A_UINT8 *pipe_rx, A_UINT8 *pipe_tx)
549 *pipe_rx = HIF_PCI_PIPE_RX0;
550 *pipe_tx = HIF_PCI_PIPE_TX0;
553 * @brief This install the API's of the HIF
558 hif_pci_module_install(struct hif_api *apis)
561 apis->_init = __pci_init;
562 apis->_start = __pci_start;
563 apis->_config_pipe = __pci_cfg_pipe;
564 apis->_isr_handler = __pci_isr_handler;
565 apis->_send_buffer = __pci_xmit_buf;
566 apis->_return_recv_buf = __pci_return_recv;
567 apis->_is_pipe_supported = __pci_is_pipe_supported;
568 apis->_get_max_msg_len = __pci_get_max_msg_len;
569 apis->_register_callback = __pci_reg_callback;
570 apis->_shutdown = __pci_shutdown;
571 apis->_get_reserved_headroom = __pci_get_reserved_headroom;
572 apis->_get_default_pipe = __pci_get_def_pipe;
576 cmnos_pci_module_install(struct pci_api *apis)
578 apis->pci_boot_init = __pci_boot_init;