Setting up repository
[linux-libre-firmware.git] / ath9k_htc / sboot / magpie_1_1 / sboot / hif / pci / hif_pci.c
1 /*
2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3  * All rights reserved.
4  *
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:
8  *
9  *  * Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
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
15  *    distribution.
16  *
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.
20  *
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.
34  */
35 #include <hif_api.h>
36 #include <Magpie_api.h>
37 #include <cmnos_api.h>
38
39 #include <dma_lib.h>
40 #include "hif_pci.h"
41
42
43 /**************************Constants******************************/
44
45 /*************************Data types*******************************/
46 enum pci_regs{
47     MAG_REG_AHB_RESET   = 0x00050010,
48     MAG_REG_AHB_ARB     = 0x00050018
49 };
50
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)
55
56 /*********************************softC************************/
57 typedef struct __pci_softc{
58     HIF_CALLBACK       sw;
59 }__pci_softc_t;
60
61
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)
67
68 #define  PCI_ENG_NUM(_eng)     HIF_PCI_PIPE_##_eng
69
70 #define PCI_INIT_PIPE   {   \
71     PCI_ENG_NUM(RX0),       \
72     PCI_ENG_NUM(RX1),       \
73     PCI_ENG_NUM(RX2),       \
74     PCI_ENG_NUM(RX3),       \
75     PCI_ENG_NUM(TX0),       \
76     PCI_ENG_NUM(TX1),       \
77 }
78
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
83 #define dbg_pci                     0
84 #define dbg_pci_loopback            0
85
86 #define PCI_DBG_MODE                0
87
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);
93
94
95 /***********************************Globals********************************/
96 /**
97  * @brief Engines are fixed
98  */
99 __pci_softc_t    pci_sc = {0};
100
101
102 /**************************************APIs********************************/
103
104 A_UINT32
105 __pci_reg_read(A_UINT32 addr)
106 {
107     return *((volatile A_UINT32 *)addr);
108 }
109
110 void
111 __pci_reg_write(A_UINT32 addr, A_UINT32 val)
112 {
113     *((volatile A_UINT32 *)addr) = val;
114 }
115
116 A_UINT8
117 __pci_get_pipe(dma_engine_t   eng)
118 {
119     switch (eng) {
120     case DMA_ENGINE_RX0:
121         return HIF_PCI_PIPE_RX0;
122     case DMA_ENGINE_RX1:
123         return HIF_PCI_PIPE_RX1;
124     case DMA_ENGINE_RX2:
125         return HIF_PCI_PIPE_RX2;
126     case DMA_ENGINE_RX3:
127         return HIF_PCI_PIPE_RX3;
128     case DMA_ENGINE_TX0:
129         return HIF_PCI_PIPE_TX0;
130     case DMA_ENGINE_TX1:
131         return HIF_PCI_PIPE_TX1;
132     default:
133         adf_os_assert(0);
134     }
135 }
136
137 dma_engine_t
138 __pci_get_tx_eng(hif_pci_pipe_tx_t  pipe)
139 {
140     switch (pipe) {
141     case HIF_PCI_PIPE_TX0:
142         return DMA_ENGINE_TX0;
143
144     case HIF_PCI_PIPE_TX1:
145         return DMA_ENGINE_TX1;
146
147     default:
148         return DMA_ENGINE_MAX;
149     }
150 }
151 dma_engine_t
152 __pci_get_rx_eng(hif_pci_pipe_rx_t  pipe)
153 {
154     switch (pipe) {
155     case HIF_PCI_PIPE_RX0:
156         return DMA_ENGINE_RX0;
157         
158     case HIF_PCI_PIPE_RX1:
159         return DMA_ENGINE_RX1;
160         
161     case HIF_PCI_PIPE_RX2:
162         return DMA_ENGINE_RX2;
163         
164     case HIF_PCI_PIPE_RX3:
165         return DMA_ENGINE_RX3;
166     
167     default:
168         return DMA_ENGINE_MAX;
169     }
170 }
171
172
173
174 void
175 __pci_enable(void)
176 {
177     A_UINT32      r_data;
178     /**
179      * Grant access to the internal memory for PCI DMA
180      */
181     
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);
185 }
186
187 /**
188  * @brief PCI reset 
189  * XXX: Move this to RAM
190  */ 
191 void
192 __pci_reset(void)
193 {
194     volatile A_UINT32      r_data;
195     
196     /**
197      * Poll until the Host has reset
198      */ 
199     A_PRINTF("Waiting for host reset..");
200     for (;;) {
201         r_data =  __pci_reg_read(MAG_REG_AHB_RESET);
202
203         if ( r_data & PCI_AHB_RESET_DMA_HST_RAW)
204             break;
205     } 
206     A_PRINTF("received.\n");
207
208     /**
209      * Pull the AHB out of reset
210      */ 
211
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);
215
216     A_DELAY_USECS(10);
217
218     /**
219      * Put the AHB into reset
220      */ 
221     
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);
225
226     A_DELAY_USECS(10);
227     
228     /**
229      * Pull the AHB out of reset
230      */ 
231     
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);
235
236     A_DELAY_USECS(10);
237 }
238 /**
239  * @brief Boot init
240  */
241 void
242 __pci_boot_init(void)
243 {
244     __pci_reset();
245     __pci_enable();
246     
247     dma_lib_tx_init(DMA_ENGINE_TX0, DMA_IF_PCI);
248     dma_lib_rx_init(DMA_ENGINE_RX0, DMA_IF_PCI); 
249     
250     dma_lib_rx_config(DMA_ENGINE_RX0, PCI_MAX_BOOT_DESC, 
251                       PCI_MAX_DATA_PKT_LEN);
252
253 }
254 /**
255  * @brief
256  * 
257  * @param pConfig
258  * 
259  * @return hif_handle_t
260  */
261 hif_handle_t 
262 __pci_init(HIF_CONFIG *pConfig)
263 {
264     __pci_reset();
265     __pci_enable();    
266     
267     /**
268      * Initializing the other TX engines
269      */
270     dma_lib_tx_init(DMA_ENGINE_TX0, DMA_IF_PCI);
271     dma_lib_tx_init(DMA_ENGINE_TX1, DMA_IF_PCI);
272     
273     /**
274      * Initializing the other RX engines
275      */
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);
280
281     return &pci_sc;
282 }
283 /**
284  * @brief Configure the receive pipe
285  * 
286  * @param hdl
287  * @param pipe
288  * @param num_desc
289  */
290 void
291 __pci_cfg_pipe(hif_handle_t hdl, int pipe, int num_desc)
292 {
293     dma_engine_t    eng;
294     A_UINT16        desc_len;
295
296     eng = __pci_get_rx_eng(pipe);
297     
298     if (eng == DMA_ENGINE_MAX) {
299         A_PRINTF("Bad Engine number\n");
300         return;
301     }
302     
303     desc_len = __pci_get_max_msg_len(hdl, pipe);
304     
305     dma_lib_rx_config(eng, num_desc, desc_len);
306 }
307 /**
308  * @brief Start the interface
309  * 
310  * @param hdl
311  */
312 void
313 __pci_start(hif_handle_t  hdl)
314 {
315     return;
316 }
317 /**
318  * @brief Register callback of thre HTC
319  * 
320  * @param hdl
321  * @param sw
322  */
323 void
324 __pci_reg_callback(hif_handle_t hdl, HIF_CALLBACK *sw)
325 {
326     __pci_softc_t   *sc = &pci_sc;
327     
328     sc->htc_ctx       = sw->context;
329     sc->indicate_pkt  = sw->recv_buf;
330     sc->ret_pkt       = sw->send_buf_done;
331 }
332
333 /**
334  * @brief reap the transmit queue for trasnmitted packets
335  * 
336  * @param sc
337  * @param eng_no
338  */
339 void
340 __pci_reap_xmitted(__pci_softc_t  *sc, dma_engine_t  eng_no)
341 {
342     VBUF *vbuf = NULL;
343     A_UINT8     pipe;
344    
345     pipe = __pci_get_pipe(eng_no);
346     
347     vbuf = dma_lib_reap_xmitted(eng_no);
348
349     if ( vbuf )
350         sc->ret_pkt(vbuf, sc->htc_ctx);
351     else
352         A_PRINTF("Empty RX Reap\n");
353     
354
355 }
356
357 /**
358  * @brief reap the receive queue for vbuf's on the specified
359  *        engine number
360  * 
361  * @param sc
362  * @param eng_no
363  */
364 void
365 __pci_reap_recv(__pci_softc_t  *sc, dma_engine_t  eng_no)
366 {
367     VBUF   *vbuf = NULL;
368
369     vbuf = dma_lib_reap_recv(eng_no);
370     
371     if(vbuf)
372         sc->indicate_pkt(NULL, vbuf, sc->htc_ctx);
373     else
374         A_PRINTF("Empty TX Reap \n");
375 }
376 /**
377  * @brief The interrupt handler
378  * 
379  * @param hdl
380  */
381 void
382 __pci_isr_handler(hif_handle_t hdl)
383 {
384     __pci_softc_t  *sc = &pci_sc;
385     A_UINT16      more = 0;
386     
387     do {
388
389         more = 0;
390
391         if( dma_lib_xmit_done(DMA_ENGINE_TX1) ) {
392             __pci_reap_xmitted(sc,DMA_ENGINE_TX1);
393             more = 1;
394         }
395         if( dma_lib_recv_pkt(DMA_ENGINE_RX3) ) {
396             __pci_reap_recv(sc, DMA_ENGINE_RX3);
397             more = 1;
398         }
399
400     } while( more );
401
402     do {
403
404         more = 0;
405
406         if( dma_lib_xmit_done(DMA_ENGINE_TX1) ) {
407             __pci_reap_xmitted(sc,DMA_ENGINE_TX1);
408             more = 1;
409         }
410         if( dma_lib_recv_pkt(DMA_ENGINE_RX2) ) {
411             __pci_reap_recv(sc, DMA_ENGINE_RX2);
412             more = 1;
413         }
414
415     } while( more );
416
417     do {
418
419         more = 0;
420
421         if( dma_lib_xmit_done(DMA_ENGINE_TX1) ) {
422             __pci_reap_xmitted(sc,DMA_ENGINE_TX1);
423             more = 1;
424         }
425         if( dma_lib_recv_pkt(DMA_ENGINE_RX1) ) {
426             __pci_reap_recv(sc, DMA_ENGINE_RX1);
427             more = 1;
428         }
429
430     } while( more );
431     
432     do {
433         
434         more = 0;
435         
436         if( dma_lib_xmit_done(DMA_ENGINE_TX0) ) {
437             __pci_reap_xmitted(sc,DMA_ENGINE_TX0);
438             more = 1;
439         }
440         
441         if( dma_lib_recv_pkt(DMA_ENGINE_RX0) ) {
442             __pci_reap_recv(sc, DMA_ENGINE_RX0);
443             more = 1;
444         }
445         
446     } while( more );
447
448 }
449 /**
450  * @brief transmit the vbuf from the specified pipe
451  * 
452  * @param hdl
453  * @param pipe
454  * @param buf
455  * 
456  * @return int
457  */
458 int
459 __pci_xmit_buf(hif_handle_t hdl, int pipe, VBUF *vbuf)
460 {
461     dma_engine_t   eng;
462    
463     eng = __pci_get_tx_eng(pipe);
464
465     if (eng == DMA_ENGINE_MAX) {
466         A_PRINTF("Invalid Pipe number\n");
467         return -1;
468     }
469
470     return dma_lib_hard_xmit(eng, vbuf);
471 }
472 /**
473  * @brief Submit the receive vbuf into the receive queue
474  * 
475  * @param handle
476  * @param pipe
477  * @param buf
478  */
479 void
480 __pci_return_recv(hif_handle_t hdl, int pipe, VBUF *buf)
481 {
482     dma_engine_t   eng;
483
484     eng = __pci_get_rx_eng(pipe);
485
486     if (eng == DMA_ENGINE_MAX)
487         return;
488
489     dma_lib_return_recv(eng, buf);
490 }
491 /**
492  * @brief Is this pipe number supported
493  * 
494  * @param handle
495  * @param pipe
496  * 
497  * @return int
498  */
499 int
500 __pci_is_pipe_supported(hif_handle_t hdl, int pipe)
501 {
502     if (pipe >= 0 && pipe <= 4)
503         return 1;
504     else
505         return 0;
506 }
507 /**
508  * @brief maximum message length this pipe can support
509  * 
510  * @param handle
511  * @param pipe
512  * 
513  * @return int
514  */
515 int  
516 __pci_get_max_msg_len(hif_handle_t hdl, int pipe)
517 {
518     if( pipe == HIF_PCI_PIPE_TX0 || pipe == HIF_PCI_PIPE_RX0)
519         return PCI_MAX_CMD_PKT_LEN;
520     
521     return PCI_MAX_DATA_PKT_LEN;
522 }
523 /**
524  * @brief return the header room required by this HIF
525  * 
526  * @param hdl
527  * 
528  * @return int
529  */
530 int
531 __pci_get_reserved_headroom(hif_handle_t  hdl)
532 {
533     return 0;
534 }
535 /**
536  * @brief Device shutdown, HIF reset required
537  * 
538  * @param hdl
539  */
540 void
541 __pci_shutdown(hif_handle_t hdl)
542 {
543     return;
544 }
545
546 void
547 __pci_get_def_pipe(hif_handle_t handle, A_UINT8 *pipe_rx, A_UINT8 *pipe_tx)
548 {
549     *pipe_rx = HIF_PCI_PIPE_RX0;
550     *pipe_tx = HIF_PCI_PIPE_TX0;
551 }
552 /**
553  * @brief This install the API's of the HIF
554  * 
555  * @param apis
556  */
557 void 
558 hif_pci_module_install(struct hif_api *apis)
559 {
560     /* hook in 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;
573 }
574
575 void 
576 cmnos_pci_module_install(struct pci_api *apis)
577 {
578     apis->pci_boot_init     = __pci_boot_init;
579 }