move sboot to the root directory
[open-ath9k-htc-firmware.git] / sboot / magpie_1_1 / sboot / hif / pci / hif_pci.c
diff --git a/sboot/magpie_1_1/sboot/hif/pci/hif_pci.c b/sboot/magpie_1_1/sboot/hif/pci/hif_pci.c
new file mode 100755 (executable)
index 0000000..d8ebac2
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  * Neither the name of Qualcomm Atheros nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <hif_api.h>
+#include <Magpie_api.h>
+#include <cmnos_api.h>
+
+#include <dma_lib.h>
+#include "hif_pci.h"
+
+
+/**************************Constants******************************/
+
+/*************************Data types*******************************/
+enum pci_regs{
+    MAG_REG_AHB_RESET   = 0x00050010,
+    MAG_REG_AHB_ARB     = 0x00050018
+};
+
+#define PCI_AHB_ARB_ENB             (1 << 3) 
+#define PCI_AHB_RESET_DMA           (1 << 13) 
+#define PCI_AHB_RESET_DMA_HST_RAW   (1 << 14)
+#define PCI_AHB_RESET_DMA_HST       (1 << 15)
+
+/*********************************softC************************/
+typedef struct __pci_softc{
+    HIF_CALLBACK       sw;
+}__pci_softc_t;
+
+
+#define ret_pkt         sw.send_buf_done
+#define indicate_pkt    sw.recv_buf
+#define htc_ctx         sw.context
+/*********************************DEFINES**********************************/
+#define  hdl_to_softc(_hdl)     (__pci_softc_t *)(_hdl)
+
+#define  PCI_ENG_NUM(_eng)     HIF_PCI_PIPE_##_eng
+
+#define PCI_INIT_PIPE   {   \
+    PCI_ENG_NUM(RX0),       \
+    PCI_ENG_NUM(RX1),       \
+    PCI_ENG_NUM(RX2),       \
+    PCI_ENG_NUM(RX3),       \
+    PCI_ENG_NUM(TX0),       \
+    PCI_ENG_NUM(TX1),       \
+}
+
+#define rx_pipe0                    DMA_ENGINE_RX0
+#define rx_pipe1                    DMA_ENGINE_RX1
+#define tx_pipe0                    DMA_ENGINE_TX0
+#define tx_pipe1                    DMA_ENGINE_TX1
+#define dbg_pci                     0
+#define dbg_pci_loopback            0
+
+#define PCI_DBG_MODE                0
+
+void    __pci_cfg_pipe(hif_handle_t hdl, int pipe, int num_desc);
+int     __pci_get_max_msg_len(hif_handle_t hdl, int pipe);
+void    __pci_return_recv(hif_handle_t hdl, int pipe, VBUF *buf);
+void    __pci_reset(void);
+void    __pci_enable(void);
+
+
+/***********************************Globals********************************/
+/**
+ * @brief Engines are fixed
+ */
+__pci_softc_t    pci_sc = {0};
+
+
+/**************************************APIs********************************/
+
+A_UINT32
+__pci_reg_read(A_UINT32 addr)
+{
+    return *((volatile A_UINT32 *)addr);
+}
+
+void
+__pci_reg_write(A_UINT32 addr, A_UINT32 val)
+{
+    *((volatile A_UINT32 *)addr) = val;
+}
+
+A_UINT8
+__pci_get_pipe(dma_engine_t   eng)
+{
+    switch (eng) {
+    case DMA_ENGINE_RX0:
+        return HIF_PCI_PIPE_RX0;
+    case DMA_ENGINE_RX1:
+        return HIF_PCI_PIPE_RX1;
+    case DMA_ENGINE_RX2:
+        return HIF_PCI_PIPE_RX2;
+    case DMA_ENGINE_RX3:
+        return HIF_PCI_PIPE_RX3;
+    case DMA_ENGINE_TX0:
+        return HIF_PCI_PIPE_TX0;
+    case DMA_ENGINE_TX1:
+        return HIF_PCI_PIPE_TX1;
+    default:
+        adf_os_assert(0);
+    }
+}
+
+dma_engine_t
+__pci_get_tx_eng(hif_pci_pipe_tx_t  pipe)
+{
+    switch (pipe) {
+    case HIF_PCI_PIPE_TX0:
+        return DMA_ENGINE_TX0;
+
+    case HIF_PCI_PIPE_TX1:
+        return DMA_ENGINE_TX1;
+
+    default:
+        return DMA_ENGINE_MAX;
+    }
+}
+dma_engine_t
+__pci_get_rx_eng(hif_pci_pipe_rx_t  pipe)
+{
+    switch (pipe) {
+    case HIF_PCI_PIPE_RX0:
+        return DMA_ENGINE_RX0;
+        
+    case HIF_PCI_PIPE_RX1:
+        return DMA_ENGINE_RX1;
+        
+    case HIF_PCI_PIPE_RX2:
+        return DMA_ENGINE_RX2;
+        
+    case HIF_PCI_PIPE_RX3:
+        return DMA_ENGINE_RX3;
+    
+    default:
+        return DMA_ENGINE_MAX;
+    }
+}
+
+
+
+void
+__pci_enable(void)
+{
+    A_UINT32      r_data;
+    /**
+     * Grant access to the internal memory for PCI DMA
+     */
+    
+    r_data  = __pci_reg_read(MAG_REG_AHB_ARB);
+    r_data |= PCI_AHB_ARB_ENB;
+    __pci_reg_write(MAG_REG_AHB_ARB, r_data);
+}
+
+/**
+ * @brief PCI reset 
+ * XXX: Move this to RAM
+ */ 
+void
+__pci_reset(void)
+{
+    volatile A_UINT32      r_data;
+    
+    /**
+     * Poll until the Host has reset
+     */ 
+    A_PRINTF("Waiting for host reset..");
+    for (;;) {
+        r_data =  __pci_reg_read(MAG_REG_AHB_RESET);
+
+        if ( r_data & PCI_AHB_RESET_DMA_HST_RAW)
+            break;
+    } 
+    A_PRINTF("received.\n");
+
+    /**
+     * Pull the AHB out of reset
+     */ 
+
+    r_data = __pci_reg_read(MAG_REG_AHB_RESET);
+    r_data &= ~PCI_AHB_RESET_DMA;
+    __pci_reg_write(MAG_REG_AHB_RESET, r_data);
+
+    A_DELAY_USECS(10);
+
+    /**
+     * Put the AHB into reset
+     */ 
+    
+    r_data = __pci_reg_read(MAG_REG_AHB_RESET);
+    r_data |= PCI_AHB_RESET_DMA;
+    __pci_reg_write(MAG_REG_AHB_RESET, r_data);
+
+    A_DELAY_USECS(10);
+    
+    /**
+     * Pull the AHB out of reset
+     */ 
+    
+    r_data = __pci_reg_read(MAG_REG_AHB_RESET);
+    r_data &= ~PCI_AHB_RESET_DMA;
+    __pci_reg_write(MAG_REG_AHB_RESET, r_data);
+
+    A_DELAY_USECS(10);
+}
+/**
+ * @brief Boot init
+ */
+void
+__pci_boot_init(void)
+{
+    __pci_reset();
+    __pci_enable();
+    
+    dma_lib_tx_init(DMA_ENGINE_TX0, DMA_IF_PCI);
+    dma_lib_rx_init(DMA_ENGINE_RX0, DMA_IF_PCI); 
+    
+    dma_lib_rx_config(DMA_ENGINE_RX0, PCI_MAX_BOOT_DESC, 
+                      PCI_MAX_DATA_PKT_LEN);
+
+}
+/**
+ * @brief
+ * 
+ * @param pConfig
+ * 
+ * @return hif_handle_t
+ */
+hif_handle_t 
+__pci_init(HIF_CONFIG *pConfig)
+{
+    __pci_reset();
+    __pci_enable();    
+    
+    /**
+     * Initializing the other TX engines
+     */
+    dma_lib_tx_init(DMA_ENGINE_TX0, DMA_IF_PCI);
+    dma_lib_tx_init(DMA_ENGINE_TX1, DMA_IF_PCI);
+    
+    /**
+     * Initializing the other RX engines
+     */
+    dma_lib_rx_init(DMA_ENGINE_RX0, DMA_IF_PCI);
+    dma_lib_rx_init(DMA_ENGINE_RX1, DMA_IF_PCI); 
+    dma_lib_rx_init(DMA_ENGINE_RX2, DMA_IF_PCI); 
+    dma_lib_rx_init(DMA_ENGINE_RX3, DMA_IF_PCI);
+
+    return &pci_sc;
+}
+/**
+ * @brief Configure the receive pipe
+ * 
+ * @param hdl
+ * @param pipe
+ * @param num_desc
+ */
+void
+__pci_cfg_pipe(hif_handle_t hdl, int pipe, int num_desc)
+{
+    dma_engine_t    eng;
+    A_UINT16        desc_len;
+
+    eng = __pci_get_rx_eng(pipe);
+    
+    if (eng == DMA_ENGINE_MAX) {
+        A_PRINTF("Bad Engine number\n");
+        return;
+    }
+    
+    desc_len = __pci_get_max_msg_len(hdl, pipe);
+    
+    dma_lib_rx_config(eng, num_desc, desc_len);
+}
+/**
+ * @brief Start the interface
+ * 
+ * @param hdl
+ */
+void
+__pci_start(hif_handle_t  hdl)
+{
+    return;
+}
+/**
+ * @brief Register callback of thre HTC
+ * 
+ * @param hdl
+ * @param sw
+ */
+void
+__pci_reg_callback(hif_handle_t hdl, HIF_CALLBACK *sw)
+{
+    __pci_softc_t   *sc = &pci_sc;
+    
+    sc->htc_ctx       = sw->context;
+    sc->indicate_pkt  = sw->recv_buf;
+    sc->ret_pkt       = sw->send_buf_done;
+}
+
+/**
+ * @brief reap the transmit queue for trasnmitted packets
+ * 
+ * @param sc
+ * @param eng_no
+ */
+void
+__pci_reap_xmitted(__pci_softc_t  *sc, dma_engine_t  eng_no)
+{
+    VBUF *vbuf = NULL;
+    A_UINT8     pipe;
+   
+    pipe = __pci_get_pipe(eng_no);
+    
+    vbuf = dma_lib_reap_xmitted(eng_no);
+
+    if ( vbuf )
+        sc->ret_pkt(vbuf, sc->htc_ctx);
+    else
+        A_PRINTF("Empty RX Reap\n");
+    
+
+}
+
+/**
+ * @brief reap the receive queue for vbuf's on the specified
+ *        engine number
+ * 
+ * @param sc
+ * @param eng_no
+ */
+void
+__pci_reap_recv(__pci_softc_t  *sc, dma_engine_t  eng_no)
+{
+    VBUF   *vbuf = NULL;
+
+    vbuf = dma_lib_reap_recv(eng_no);
+    
+    if(vbuf)
+        sc->indicate_pkt(NULL, vbuf, sc->htc_ctx);
+    else
+        A_PRINTF("Empty TX Reap \n");
+}
+/**
+ * @brief The interrupt handler
+ * 
+ * @param hdl
+ */
+void
+__pci_isr_handler(hif_handle_t hdl)
+{
+    __pci_softc_t  *sc = &pci_sc;
+    A_UINT16      more = 0;
+    
+    do {
+
+        more = 0;
+
+        if( dma_lib_xmit_done(DMA_ENGINE_TX1) ) {
+            __pci_reap_xmitted(sc,DMA_ENGINE_TX1);
+            more = 1;
+        }
+        if( dma_lib_recv_pkt(DMA_ENGINE_RX3) ) {
+            __pci_reap_recv(sc, DMA_ENGINE_RX3);
+            more = 1;
+        }
+
+    } while( more );
+
+    do {
+
+        more = 0;
+
+        if( dma_lib_xmit_done(DMA_ENGINE_TX1) ) {
+            __pci_reap_xmitted(sc,DMA_ENGINE_TX1);
+            more = 1;
+        }
+        if( dma_lib_recv_pkt(DMA_ENGINE_RX2) ) {
+            __pci_reap_recv(sc, DMA_ENGINE_RX2);
+            more = 1;
+        }
+
+    } while( more );
+
+    do {
+
+        more = 0;
+
+        if( dma_lib_xmit_done(DMA_ENGINE_TX1) ) {
+            __pci_reap_xmitted(sc,DMA_ENGINE_TX1);
+            more = 1;
+        }
+        if( dma_lib_recv_pkt(DMA_ENGINE_RX1) ) {
+            __pci_reap_recv(sc, DMA_ENGINE_RX1);
+            more = 1;
+        }
+
+    } while( more );
+    
+    do {
+        
+        more = 0;
+        
+        if( dma_lib_xmit_done(DMA_ENGINE_TX0) ) {
+            __pci_reap_xmitted(sc,DMA_ENGINE_TX0);
+            more = 1;
+        }
+        
+        if( dma_lib_recv_pkt(DMA_ENGINE_RX0) ) {
+            __pci_reap_recv(sc, DMA_ENGINE_RX0);
+            more = 1;
+        }
+        
+    } while( more );
+
+}
+/**
+ * @brief transmit the vbuf from the specified pipe
+ * 
+ * @param hdl
+ * @param pipe
+ * @param buf
+ * 
+ * @return int
+ */
+int
+__pci_xmit_buf(hif_handle_t hdl, int pipe, VBUF *vbuf)
+{
+    dma_engine_t   eng;
+   
+    eng = __pci_get_tx_eng(pipe);
+
+    if (eng == DMA_ENGINE_MAX) {
+        A_PRINTF("Invalid Pipe number\n");
+        return -1;
+    }
+
+    return dma_lib_hard_xmit(eng, vbuf);
+}
+/**
+ * @brief Submit the receive vbuf into the receive queue
+ * 
+ * @param handle
+ * @param pipe
+ * @param buf
+ */
+void
+__pci_return_recv(hif_handle_t hdl, int pipe, VBUF *buf)
+{
+    dma_engine_t   eng;
+
+    eng = __pci_get_rx_eng(pipe);
+
+    if (eng == DMA_ENGINE_MAX)
+        return;
+
+    dma_lib_return_recv(eng, buf);
+}
+/**
+ * @brief Is this pipe number supported
+ * 
+ * @param handle
+ * @param pipe
+ * 
+ * @return int
+ */
+int
+__pci_is_pipe_supported(hif_handle_t hdl, int pipe)
+{
+    if (pipe >= 0 && pipe <= 4)
+        return 1;
+    else
+        return 0;
+}
+/**
+ * @brief maximum message length this pipe can support
+ * 
+ * @param handle
+ * @param pipe
+ * 
+ * @return int
+ */
+int  
+__pci_get_max_msg_len(hif_handle_t hdl, int pipe)
+{
+    if( pipe == HIF_PCI_PIPE_TX0 || pipe == HIF_PCI_PIPE_RX0)
+        return PCI_MAX_CMD_PKT_LEN;
+    
+    return PCI_MAX_DATA_PKT_LEN;
+}
+/**
+ * @brief return the header room required by this HIF
+ * 
+ * @param hdl
+ * 
+ * @return int
+ */
+int
+__pci_get_reserved_headroom(hif_handle_t  hdl)
+{
+    return 0;
+}
+/**
+ * @brief Device shutdown, HIF reset required
+ * 
+ * @param hdl
+ */
+void
+__pci_shutdown(hif_handle_t hdl)
+{
+    return;
+}
+
+void
+__pci_get_def_pipe(hif_handle_t handle, A_UINT8 *pipe_rx, A_UINT8 *pipe_tx)
+{
+    *pipe_rx = HIF_PCI_PIPE_RX0;
+    *pipe_tx = HIF_PCI_PIPE_TX0;
+}
+/**
+ * @brief This install the API's of the HIF
+ * 
+ * @param apis
+ */
+void 
+hif_pci_module_install(struct hif_api *apis)
+{
+    /* hook in APIs */
+    apis->_init         = __pci_init;
+    apis->_start        = __pci_start;
+    apis->_config_pipe  = __pci_cfg_pipe;
+    apis->_isr_handler  = __pci_isr_handler;
+    apis->_send_buffer  = __pci_xmit_buf;
+    apis->_return_recv_buf       = __pci_return_recv;
+    apis->_is_pipe_supported     = __pci_is_pipe_supported;
+    apis->_get_max_msg_len       = __pci_get_max_msg_len;
+    apis->_register_callback     = __pci_reg_callback;
+    apis->_shutdown              = __pci_shutdown;
+    apis->_get_reserved_headroom = __pci_get_reserved_headroom;
+    apis->_get_default_pipe      = __pci_get_def_pipe;
+}
+
+void 
+cmnos_pci_module_install(struct pci_api *apis)
+{
+    apis->pci_boot_init     = __pci_boot_init;
+}