carl9170: Update to latest upstream
[linux-libre-firmware.git] / ath9k_htc / sboot / magpie_1_1 / sboot / hif / gmac / hif_gmac.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 <adf_os_stdtypes.h>
36 #include <adf_os_types.h>
37
38 //#include <HIF_api.h>
39 #include <cmnos_api.h>
40
41 #include <Magpie_api.h>
42
43 #include <adf_os_util.h>
44 #include <adf_os_mem.h>
45 #include <adf_os_time.h>
46 #include <dma_lib.h>
47 #include "hif_gmac.h"
48
49
50
51 /**************************Constants******************************/
52 enum __gmac_msg_type{
53     GMAC_HST_QUERY = 0x0001,
54     GMAC_HST_REPLY = 0x0002,
55     GMAC_TGT_QUERY = 0x0003,
56     GMAC_TGT_REPLY = 0x0004
57 };
58
59 enum __magpie_regs{
60     MAG_REG_GPIO_OE     = 0x00052000,/*GPIO Output Enable*/
61     MAG_REG_RST         = 0x00050010,/*Magpie reset reg*/
62     MAG_REG_RST_AHB     = 0x00050018,/*Magpie AHB_ARB reset reg*/
63     MAG_REG_MII0_CTRL   = 0x00054100,/*Magpie MII0 Control reg*/
64     MAG_REG_STAT_CTRL   = 0x00054104,/*Magpie Status reg*/
65     MAG_REG_MDIO        = 0x00054200,/*Mapie MDIO register*/
66     MAG_REG_MDIO_CMD    = 0x00 + MAG_REG_MDIO,/*CMD register (0)*/
67     MAG_REG_MDIO_OWN    = 0x02 + MAG_REG_MDIO,/*OWN register (1)*/
68     /**
69      * XXX: Endianess inside the word & between words
70      */
71     MAG_REG_MDIO_ADDR0  = 0x04 + MAG_REG_MDIO,/*ADDR0 register (2)*/
72     MAG_REG_MDIO_ADDR1  = 0x06 + MAG_REG_MDIO,/*ADDR1 register (3)*/
73     MAG_REG_MDIO_WRITE0 = 0x08 + MAG_REG_MDIO,/*Data WRITE0 register (4)*/
74     MAG_REG_MDIO_WRITE1 = 0x0a + MAG_REG_MDIO,/*Data WRITE1 register (5)*/
75     MAG_REG_MDIO_READ0  = 0x0c + MAG_REG_MDIO,/*Data READ0 register (6)*/
76     MAG_REG_MDIO_READ1  = 0x0e + MAG_REG_MDIO,/*Data READ1 register (7)*/
77 };
78
79 enum __gmac_regs{
80     GMAC_REG_BASE       = 0x00060000,
81     GMAC_REG_MAC_CFG1   = 0x00 + GMAC_REG_BASE,/*MAC config 1*/
82     GMAC_REG_MAC_CFG2   = 0x04 + GMAC_REG_BASE,/*MAC config 2*/
83     GMAC_REG_IPG_IFG    = 0x08 + GMAC_REG_BASE,/*Inter-packet-gap*/
84     GMAC_REG_HALF_DPLX  = 0x0c + GMAC_REG_BASE,/*Half duplex*/
85     GMAC_REG_MAX_FRAME  = 0x10 + GMAC_REG_BASE,/*Max frame length*/
86     GMAC_REG_MII_CFG    = 0x20 + GMAC_REG_BASE,/*MII mgmt config*/
87     GMAC_REG_MII_CMD    = 0x24 + GMAC_REG_BASE,/*MII mgmt command*/
88     GMAC_REG_MII_ADDR   = 0x28 + GMAC_REG_BASE,/*MII mgmt address*/
89     GMAC_REG_MII_CTRL   = 0x2c + GMAC_REG_BASE,/*MII mgmt control*/
90     GMAC_REG_MII_STAT   = 0x30 + GMAC_REG_BASE,/*MII mgmt status*/
91     GMAC_REG_MII_PSTAT  = 0x34 + GMAC_REG_BASE,/*MII mgmt Phy status/ind*/
92     GMAC_REG_IF_CTRL    = 0x38 + GMAC_REG_BASE,/*Interface control*/
93     GMAC_REG_IF_STAT    = 0x3c + GMAC_REG_BASE,/*Interface status*/
94     GMAC_REG_MAC_ADDR1  = 0x40 + GMAC_REG_BASE,/*MAC address 1*/
95     GMAC_REG_MAC_ADDR2  = 0x44 + GMAC_REG_BASE,/*MAC address 2*/
96     GMAC_REG_FIFO_CFG0  = 0x48 + GMAC_REG_BASE,/*FIFO config reg0*/
97     GMAC_REG_FIFO_CFG1  = 0x4c + GMAC_REG_BASE,/*FIFO config reg1*/
98     GMAC_REG_FIFO_CFG2  = 0x50 + GMAC_REG_BASE,/*FIFO config reg2*/
99     GMAC_REG_FIFO_CFG3  = 0x54 + GMAC_REG_BASE,/*FIFO config reg3*/
100     GMAC_REG_FIFO_CFG4  = 0x58 + GMAC_REG_BASE,/*FIFO config reg4*/
101     GMAC_REG_FIFO_CFG5  = 0x5c + GMAC_REG_BASE,/*FIFO config reg5*/
102     GMAC_REG_FIFO_RAM0  = 0x60 + GMAC_REG_BASE,/*FIFO RAM access reg0*/
103     GMAC_REG_FIFO_RAM1  = 0x64 + GMAC_REG_BASE,/*FIFO RAM access reg1*/
104     GMAC_REG_FIFO_RAM2  = 0x68 + GMAC_REG_BASE,/*FIFO RAM access reg2*/
105     GMAC_REG_FIFO_RAM3  = 0x6c + GMAC_REG_BASE,/*FIFO RAM access reg3*/
106     GMAC_REG_FIFO_RAM4  = 0x70 + GMAC_REG_BASE,/*FIFO RAM access reg4*/
107     GMAC_REG_FIFO_RAM5  = 0x74 + GMAC_REG_BASE,/*FIFO RAM access reg5*/
108     GMAC_REG_FIFO_RAM6  = 0x78 + GMAC_REG_BASE,/*FIFO RAM access reg6*/
109     GMAC_REG_FIFO_RAM7  = 0x7c + GMAC_REG_BASE,/*FIFO RAM access reg7*/
110 };
111
112 enum  __mag_reg_rst{
113     RST_GMAC   = (1 << 9),/*Reset the GMAC */
114     RST_MII    = (3 << 11),/*Reset the MII*/
115     RST_OTHERS = 0x5df,/*Reset everybody other than GMAC & MII*/
116 };
117
118 enum __mag_reg_rst_ahb{
119     RST_AHB_GMAC = 0x1
120 };
121 enum __mag_mii0_ctrl{
122     MII0_CTRL_MODE  = (1 << 0),/*MII mode*/
123     MII0_CTRL_100   = (1 << 4),/*MII control address 100 Mbps*/
124 };
125
126 enum __mag_mdio_cmd{
127     MDIO_CMD_DONE     = 0x01,/*Operation over*/
128     MDIO_CMD_WRITE    = 0x02,/*Write data*/
129     MDIO_CMD_READ     = 0x03 /*Read data*/
130 };
131 enum __mag_mdio_own{
132     MDIO_OWN_HST  = 0x00,/*Host can use CMD & Data Regs*/
133     MDIO_OWN_TGT  = 0x01 /*Tgt can use CMD & Data Regs*/
134 };
135
136 enum __gmac_reg_mac_cfg1{
137     MAC_CFG1_TX_EN   = (1 << 0),/*TX enable*/
138     MAC_CFG1_RX_EN   = (1 << 2),/*RX enable*/
139     MAC_CFG1_TX_FLOW = (1 << 4),/*TX Flow control enable*/
140     MAC_CFG1_RX_FLOW = (1 << 5),/*RX Flow control enable*/
141     MAC_CFG1_LOOP_EN = (1 << 8),/*Enable loopback*/
142 };
143 enum __gmac_reg_mac_cfg2{
144     MAC_CFG2_FULL_DUP = (1 << 0),/*Enable Full Duplex*/
145     MAC_CFG2_PAD_CRC  = (1 << 2),/*Enable MAC based CRC insertion*/
146     MAC_CFG2_CHK_LEN  = (1 << 4),/*Check Length field*/
147     MAC_CFG2_HUGE_FRM = (1 << 5),/*Allow sending huge frames*/
148     MAC_CFG2_MII      = (1 << 8),/*MAC is MII in mode*/
149     MAC_CFG2_GMII     = (1 << 9),/*MAC is in GMII mode*/
150     MAC_CFG2_PREAMBLE = (7 << 12),/*Default Preamble Length*/
151 };
152 enum __gmac_reg_mii_cfg{
153     MII_CFG_CLK_2MHZ  = 0x0006,/*Clock is 2Mhz*/ 
154 };
155 enum __gmac_reg_mii_addr{
156     MII_ADDR_RESET     = 0x000,/*Flush the MII address register*/
157     MII_ADDR_PHY_REG   = 0x011,/*Phy Status Reg*/
158 };
159 enum __gmac_reg_mii_ctrl{
160     MII_CTRL_FULL_DPLX = 0x0100,/*Full Duplex mode*/
161     MII_CTRL_SPEED_100 = 0x2000,/*Link Speed 100 Mbps*/
162     MII_CTRL_LOOPBACK  = 0x4000,/*Enable Loopback mode at PHY*/
163     MII_CTRL_RESET     = 0x8000,/*BMCR reset*/
164 };
165 enum __gma_reg_mii_cmd{
166     MII_CMD_WRITE  = 0x0,
167     MII_CMD_READ   = 0x1,/*Perform a Read cycle*/
168 };
169 enum __gmac_reg_fifo_cfg0{
170     FIFO_CFG0_EN   = 0x1f00,/*Enable all the Fifo module*/
171 };
172 enum __gmac_reg_fifo_cfg1{
173     FIFO_CFG1_SIZE_2K = (0x7ff << 16),/*Fifo size is 2K*/
174 };
175 enum __gmac_reg_fifo_cfg4{
176     FIFO_CFG4_RX_ALL = 0x3ffff,/*receive all frames*/
177 };
178 enum __gmac_reg_if_ctrl{
179     IF_CTRL_SPEED_100  = (1 << 16),/*Interface speed 100 Mbps for MII*/ 
180 };
181
182 /*************************GMAC Data types*******************************/
183 typedef enum __gmac_pkt_type{
184     GMAC_PKT_IS_BCAST,
185     GMAC_PKT_IS_UCAST
186 }__gmac_pkt_type_t;
187
188 struct __ethhdr{
189     unsigned char   dst[ETH_ALEN];/*destination eth addr */
190     unsigned char   src[ETH_ALEN]; /*source ether addr*/
191     A_UINT16      etype;/*ether type*/
192 }__attribute__((packed));
193 /**
194  * @brief this is will be in big endian format
195  */ 
196 struct __athhdr{
197 #ifdef LITTLE_ENDIAN
198     A_UINT8   proto:6,
199                 res:2;
200 #else                    
201     A_UINT8   res:2,
202                 proto:6;
203 #endif                
204     A_UINT8   res_lo;
205     A_UINT16  res_hi;
206 }__attribute__((packed));
207
208 typedef struct __gmac_hdr{
209     struct  __ethhdr   eth;
210     struct  __athhdr   ath;
211     A_UINT16         align_pad;/*pad it for 4 byte boundary*/
212 }__attribute__((packed))  __gmac_hdr_t;
213
214 /*********************************GMAC softC************************/
215
216 typedef struct __gmac_softc{
217     __gmac_hdr_t        hdr;
218     A_UINT16          gran;
219     HIF_CALLBACK        sw;
220 }__gmac_softc_t;
221
222
223 #define ret_pkt         sw.send_buf_done
224 #define indicate_pkt    sw.recv_buf
225 #define htc_ctx         sw.context
226 /*********************************DEFINES**********************************/
227 #define hif_gmac_sc(_hdl)   (__gmac_softc_t *)(_hdl)
228 #define gmac_hdr(_vbuf)     (__gmac_hdr_t *)(_vbuf)->desc_list->buf_addr
229 #define GMAC_HLEN           (sizeof(struct __gmac_hdr))
230
231 #define __gmac_mdelay(_msecs)   A_DELAY_USECS((_msecs) * 1000)
232
233 int     __gmac_xmit_buf(hif_handle_t hdl, int pipe, VBUF *vbuf);
234 void    __gmac_reap_recv(__gmac_softc_t  *sc, dma_engine_t  eng_no);
235
236 /***********************************Globals********************************/
237 /**
238  * @brief Engines are fixed
239  */
240 __gmac_softc_t    gmac_sc = {
241     .gran = GMAC_MAX_PKT_LEN
242 };
243 A_UINT8  gmac_addr[ETH_ALEN]  = {0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
244 A_UINT8  bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
245
246 /**************************************APIs********************************/
247
248 /**
249  * @brief This a replica of the ADF_NBUF_ALLOC
250  * 
251  * @param size
252  * @param reserve
253  * @param align
254  * 
255  * @return VBUF*
256  */
257 VBUF *
258 __gmac_vbuf_alloc(A_UINT32  size, A_UINT32  reserve, A_UINT32 align)
259 {
260     VBUF *buf = NULL;
261     VDESC *desc;
262     
263     buf = VBUF_alloc_vbuf();
264     if ( buf != NULL ) {
265         desc = VDESC_alloc_vdesc();
266         desc->buf_addr = (A_UINT8 *)A_ALLOCRAM(size);
267         desc->buf_size = size;
268         desc->next_desc = NULL;
269         desc->data_offset = reserve;
270         desc->data_size = 0;
271         desc->control = 0;    
272         
273         buf->desc_list = desc;
274         buf->buf_length = 0;    
275     }
276     
277     return buf;
278 }
279 /**
280  * @brief This is a replica of ADF_NBUF_PULL_HEAD
281  * 
282  * @param buf
283  * @param size
284  * 
285  * @return A_UINT8*
286  */
287 A_UINT8 *
288 __gmac_vbuf_pull_head(VBUF  *buf, A_UINT32 len)
289 {
290     A_UINT8 *ptr = NULL;
291     VDESC *desc = buf->desc_list;
292     
293     desc->data_offset += len;
294     desc->data_size -= len;
295     buf->buf_length -= len;
296     ptr = desc->buf_addr + desc->data_offset;
297     
298     return ptr;
299 }
300 /**
301  * @brief This is a replica of ADF_NBUF_PUSH_HEAD
302  * 
303  * @param buf
304  * @param size
305  * 
306  * @return A_UINT8*
307  */
308 A_UINT8 *
309 __gmac_vbuf_push_head(VBUF *buf, A_UINT32 len)
310 {
311     A_UINT8 *ptr = NULL; 
312     VDESC *desc = buf->desc_list;
313     
314     desc->data_offset -= len;
315     desc->data_size += len;
316     buf->buf_length += len;
317     ptr = desc->buf_addr + desc->data_offset;
318     return(ptr);
319 }
320 /**
321  * @brief This is a replica ADF_NBUF_LAST
322  * 
323  * @param buf
324  * 
325  * @return VDESC*
326  */
327 VDESC * 
328 __gmac_vbuf_last(VBUF *buf)
329 {
330     VDESC *desc = buf->desc_list;
331     
332     while(desc->next_desc != NULL)
333         desc = desc->next_desc;
334     
335     return desc;
336 }
337 /**
338  * @brief This is a replica of ADF_NBUF_PUT_TAIL
339  * 
340  * @param buf
341  * @param size
342  * 
343  * @return A_UINT8*
344  */
345 A_UINT8 *
346 __gmac_vbuf_put_tail(VBUF  *buf, A_UINT32 len)
347 {
348     A_UINT8 *tail = NULL;
349     VDESC *last_desc = __gmac_vbuf_last(buf);
350     
351     tail = ( last_desc->buf_addr + last_desc->data_offset + 
352              last_desc->data_size );
353
354     last_desc->data_size += len;
355     buf->buf_length += len;
356     
357     return tail;
358 }
359
360 /************************************GMAC**********************************/
361 A_UINT16
362 __gmac_reg_read16(A_UINT32 addr)
363 {
364     return *((volatile A_UINT16 *)addr);
365 }
366
367 void
368 __gmac_reg_write16(A_UINT32 addr, A_UINT16 val)
369 {
370     *((volatile A_UINT16 *)addr) = val;
371 }
372
373
374 A_UINT32
375 __gmac_reg_read32(A_UINT32 addr)
376 {
377     return *((volatile A_UINT32 *)addr);
378 }
379
380 void
381 __gmac_reg_write32(A_UINT32 addr, A_UINT32 val)
382 {
383     *((volatile A_UINT32 *)addr) = val;
384 }
385 /**
386  * @brief Read the MAC address from EEPROM
387  * XXX: read from real EEPROM
388  * 
389  * @param mac (pointer to fill the mac address)
390  */
391 void
392 __gmac_rom_read_mac(A_UINT8  mac_addr[])
393 {
394     A_MEMCPY(mac_addr, gmac_addr, ETH_ALEN);
395 }
396 /**
397  * @brief Write the MAC address into the Station address
398  *        register
399  * 
400  * @param mac
401  */
402 void
403 __gmac_reg_write_mac(A_UINT8  mac_addr[])
404 {
405     A_UINT32  mac_lo = 0, mac_hi = 0;
406
407     A_MEMCPY(&mac_lo, mac_addr, 4);
408     A_MEMCPY(&mac_hi, mac_addr + 4, 2);
409
410     A_PRINTF("mac address = %x:%x:%x:%x:%x:%x\n",
411                  mac_addr[0], mac_addr[1], mac_addr[2],
412                  mac_addr[3], mac_addr[4], mac_addr[5]);
413
414     __gmac_reg_write32(GMAC_REG_MAC_ADDR1, mac_lo);
415     __gmac_reg_write32(GMAC_REG_MAC_ADDR2, mac_hi);
416 }
417
418 /**
419  * @brief Wait for the MII operation to complete
420  */
421 void
422 __gmac_mii_op_wait(void)
423 {
424     A_UINT32 r_data;
425
426     r_data = __gmac_reg_read32(GMAC_REG_MII_PSTAT) & 0x1;
427     while(r_data)
428          r_data = (__gmac_reg_read32(GMAC_REG_MII_PSTAT) & 0x1);
429
430 }
431 void
432 __gmac_reset(void)
433 {
434     volatile A_UINT32 r_data;
435     volatile A_UINT32 w_data;
436
437     /**
438      * Reset the GMAC controller from Magpie Reset Register
439      */
440     r_data = __gmac_reg_read32(MAG_REG_RST);
441     r_data |= RST_GMAC;
442     __gmac_reg_write32(MAG_REG_RST, r_data);
443
444     __gmac_mdelay(1);
445   
446     /**
447      * Pull it out from the Reset State
448      */
449     r_data  = __gmac_reg_read32(MAG_REG_RST);
450     r_data &= ~RST_GMAC;
451     __gmac_reg_write32(MAG_REG_RST, r_data);
452
453     /**
454      * Reset the MII
455      */
456     r_data  = __gmac_reg_read32(MAG_REG_RST);
457     r_data |= (RST_MII | RST_GMAC);
458     __gmac_reg_write32(MAG_REG_RST, r_data);
459
460     __gmac_mdelay(1);
461     /**
462      * Pull the MII out of reset
463      */
464     r_data  = __gmac_reg_read32(MAG_REG_RST);
465     r_data &= ~( RST_MII | RST_GMAC);
466     __gmac_reg_write32(MAG_REG_RST, r_data);
467
468     __gmac_mdelay(1);
469
470     /**
471      * Reset other modules PCI, PCIE, USB & Eth PLL
472      * XXX:why???
473      */
474 //    __gmac_reg_write32(MAG_REG_RST, RST_OTHERS);
475
476     __gmac_mdelay(1);
477
478     /**
479      * Reset the AHB Arb. Unit
480      */
481     r_data  = __gmac_reg_read32(MAG_REG_RST_AHB);
482     r_data |= RST_AHB_GMAC;
483     __gmac_reg_write32(MAG_REG_RST_AHB, r_data);
484     
485     /**
486      * MII mode initialization
487      */
488     w_data = ( MAC_CFG2_FULL_DUP | MAC_CFG2_PAD_CRC | MAC_CFG2_CHK_LEN |
489                MAC_CFG2_HUGE_FRM | MAC_CFG2_MII | MAC_CFG2_PREAMBLE );
490
491     __gmac_reg_write32(GMAC_REG_MAC_CFG2, w_data);
492
493     /**
494      * Enable  FIFO modules
495      */
496     __gmac_reg_write32(GMAC_REG_FIFO_CFG0, FIFO_CFG0_EN);
497
498     /**
499      * Mode = MII & Speed = 100 Mbps
500      */
501     w_data = ( MII0_CTRL_100 | MII0_CTRL_MODE );
502     __gmac_reg_write32(MAG_REG_MII0_CTRL, w_data);
503
504     /**
505      * Set the interface speed to 100 Mbps
506      */
507     __gmac_reg_write32(GMAC_REG_IF_CTRL, IF_CTRL_SPEED_100);
508
509     /**
510      * Fifo size set to 2K bytes
511      */
512     r_data  = __gmac_reg_read32(GMAC_REG_FIFO_CFG1);
513     r_data |= FIFO_CFG1_SIZE_2K;
514     __gmac_reg_write32(GMAC_REG_FIFO_CFG1, r_data);
515
516     /**
517      * Enable the transceiver
518      */
519     w_data = MAC_CFG1_RX_EN | MAC_CFG1_TX_EN;
520     __gmac_reg_write32(GMAC_REG_MAC_CFG1, w_data);
521
522     /**
523      * Set the MII Clock to 2Mhz
524      */
525     __gmac_reg_write32(GMAC_REG_MII_CFG, MII_CFG_CLK_2MHZ);
526
527     /**
528      * Programming the phy registers
529      */
530     __gmac_reg_write32(GMAC_REG_MII_ADDR, MII_ADDR_RESET);
531
532     /**
533      * BMCR reset for the PHY
534      */
535     __gmac_reg_write32(GMAC_REG_MII_CTRL, MII_CTRL_RESET);
536
537     /**
538      * Wait until the MII Reg write has been flushed
539      */
540     __gmac_mii_op_wait();
541
542     /**
543      * PHY register 0x000 , BMCR
544      */
545     __gmac_reg_write32(GMAC_REG_MII_ADDR, MII_ADDR_RESET);
546
547     /**
548      * Write the value in the register
549      */
550     w_data = ( MII_CTRL_FULL_DPLX | MII_CTRL_SPEED_100 | MII_CTRL_RESET);
551     __gmac_reg_write32(GMAC_REG_MII_CTRL, w_data);
552     
553     __gmac_mii_op_wait();
554
555     /**
556      * Pull the BMCR out of the reset state
557      */
558     __gmac_reg_write32(GMAC_REG_MII_ADDR, MII_ADDR_RESET);
559
560     w_data = (MII_CTRL_FULL_DPLX | MII_CTRL_SPEED_100);
561     __gmac_reg_write32(GMAC_REG_MII_ADDR, w_data);
562
563     __gmac_mii_op_wait();
564
565     /**
566      * XXX: This should be for some debugging purpose, don't know
567      * why we should write into the GPIO Output Enable the value
568      * returned from PHY status register Read
569      */
570     __gmac_reg_write32(GMAC_REG_MII_CMD, MII_CMD_WRITE);
571     __gmac_reg_write32(GMAC_REG_MII_ADDR, MII_ADDR_PHY_REG);
572     __gmac_reg_write32(GMAC_REG_MII_CMD, MII_CMD_READ);
573
574     __gmac_mii_op_wait();
575
576     r_data = __gmac_reg_read32(GMAC_REG_MII_STAT);
577
578     __gmac_reg_write32(MAG_REG_GPIO_OE, r_data);
579
580     /**
581      * Enable Receive Fifo
582      */
583     r_data  = __gmac_reg_read32(GMAC_REG_FIFO_CFG4);
584     r_data |= FIFO_CFG4_RX_ALL;
585     __gmac_reg_write32(GMAC_REG_FIFO_CFG4, r_data);
586
587 }
588 /**
589  * @brief return if the pipe is supported
590  * 
591  * @param pipe
592  * 
593  * @return a_bool_t
594  */
595 static inline a_bool_t
596 __gmac_chk_pipe(hif_gmac_pipe_t pipe)
597 {
598     switch (pipe) {
599     case HIF_GMAC_PIPE_TX:
600     case HIF_GMAC_PIPE_RX:
601         return A_TRUE;
602     default:
603         return A_FALSE;
604     }
605 }
606
607 VBUF *
608 __gmac_pkt_alloc(A_UINT32  size)
609 {
610     VBUF * buf;
611     A_UINT16 fill_size;
612     A_UINT8  *data;
613
614     if(size < GMAC_HLEN)
615         return NULL;
616
617     buf = __gmac_vbuf_alloc(size, GMAC_HLEN, 0);
618     if(!buf)
619         return NULL;
620
621     fill_size = size - GMAC_HLEN;
622
623     data = __gmac_vbuf_put_tail(buf, fill_size);
624
625     A_MEMSET(data, 0xaa, fill_size);
626
627     return buf;
628 }
629 /**
630  * @brief Slap the header
631  * 
632  * @param buf
633  * @param hdr
634  */
635 void
636 __gmac_put_hdr(VBUF * buf, __gmac_hdr_t  *hdr)
637 {
638     A_UINT8  *data;
639
640     data = __gmac_vbuf_push_head(buf, GMAC_HLEN);
641
642     A_MEMCPY(data, hdr, GMAC_HLEN);
643 }
644 /**
645  * @brief
646  * 
647  * @param hdr
648  * @param src
649  */
650 void
651 __gmac_prep_ethhdr(__gmac_hdr_t  *hdr, A_UINT8  *dst)
652 {
653     A_MEMCPY(hdr->eth.dst, dst, ETH_ALEN);
654     hdr->eth.etype = ETH_P_ATH;
655 }
656
657
658 a_bool_t
659 __is_ath_header(__gmac_softc_t  *sc, VBUF  *vbuf)
660 {
661     __gmac_hdr_t  *hdr = gmac_hdr(vbuf);
662     
663     if(hdr->ath.proto != sc->hdr.ath.proto)
664         return A_FALSE;
665     
666     return A_TRUE;
667 }
668
669 a_status_t
670 __gmac_process_discv(__gmac_softc_t  *sc)
671 {
672     a_status_t  err = A_STATUS_OK;
673     VBUF  *vbuf;
674     __gmac_hdr_t  *buf_hdr ;
675     
676           
677     vbuf = dma_lib_reap_recv(DMA_ENGINE_RX0);
678     
679     if(!__is_ath_header(sc, vbuf))
680         goto fail;
681     
682     buf_hdr = gmac_hdr(vbuf);    
683     
684     A_MEMCPY(sc->hdr.eth.dst, buf_hdr->eth.src, ETH_ALEN);
685     
686     __gmac_vbuf_pull_head(vbuf, GMAC_HLEN);
687
688     /**
689      * Application should do the return_recv
690      */       
691     sc->indicate_pkt(NULL, vbuf, sc->htc_ctx);
692     
693     
694     return A_STATUS_OK;
695
696     /**
697      * This is not our packet
698      */
699 fail:
700     
701     dma_lib_return_recv(DMA_ENGINE_RX0, vbuf);
702             
703     return err;     
704 }
705 /**
706  * @brief The GMAC host discovery loop
707  */
708 void
709 __gmac_discover(void)
710 {
711     a_status_t    err = A_STATUS_FAILED;
712     VBUF *    buf;
713     __gmac_softc_t  *sc = &gmac_sc;
714
715
716     /**
717      * Get a packet
718      */
719     buf = __gmac_pkt_alloc(GMAC_DISCV_PKT_SZ);
720
721     /**
722      * Prepare the broadcast packet
723      */
724     __gmac_prep_ethhdr(&sc->hdr, bcast_addr);
725     __gmac_put_hdr(buf, &sc->hdr);
726
727     while(1){
728
729         if(buf)
730             dma_lib_hard_xmit(DMA_ENGINE_TX0, buf);
731
732         buf = NULL;
733         __gmac_mdelay(GMAC_DISCV_WAIT);
734         
735         if(dma_lib_xmit_done(DMA_ENGINE_TX0))
736             buf = dma_lib_reap_xmitted(DMA_ENGINE_TX0);
737         
738         
739         while(dma_lib_recv_pkt(DMA_ENGINE_RX0) && err)
740             err = __gmac_process_discv(sc);
741
742         if(!err)
743             break;
744     }
745
746     adf_os_assert(buf);
747 }
748
749 void
750 __gmac_mdio_check(void)
751 {
752     A_UINT16  own;
753
754     /*Read the Ownership register*/
755     do {
756         own = __gmac_reg_read16(MAG_REG_MDIO_OWN);
757     } while ( own == MDIO_OWN_TGT );
758
759 }
760
761 void
762 __gmac_mdio_load_exec(void)
763 {
764     volatile A_UINT16  cmd, more = 1 ;
765     volatile A_UINT16  *addr[2];
766     void ( *exec_fn)(void) = NULL;
767
768     do {
769         /**
770          * Read the Command register
771          */
772         cmd = __gmac_reg_read16(MAG_REG_MDIO_CMD);
773
774         switch (cmd) {
775
776         case MDIO_CMD_WRITE:
777
778            /**
779             * 1. Read the address from Address register
780             * 2. Write the data from Data register into the address
781             */
782             (A_UINT16 *)addr[0]  = __gmac_reg_read16(MAG_REG_MDIO_ADDR0);
783             *addr[0] = __gmac_reg_read16(MAG_REG_MDIO_WRITE0);
784             
785             (A_UINT16 *)addr[1]  = __gmac_reg_read16(MAG_REG_MDIO_ADDR1);
786             *addr[1] = __gmac_reg_read16(MAG_REG_MDIO_WRITE1);
787
788             if ( exec_fn ) 
789                 break;
790
791             exec_fn = (A_UINT32 *)addr;
792             break;
793
794         case MDIO_CMD_DONE:
795
796             more = 0;
797             break;
798
799         case MDIO_CMD_READ:
800             
801             /**
802              * 1. Read the address from Address register
803              * 2. Write the data into the Data register from the address
804              */
805             addr[0]  = (A_UINT16 *)__gmac_reg_read16(MAG_REG_MDIO_ADDR0);
806              __gmac_reg_write16(MAG_REG_MDIO_READ0, *addr[0]);
807
808             addr[1]  = (A_UINT16 *)__gmac_reg_read16(MAG_REG_MDIO_ADDR1);
809             __gmac_reg_write16(MAG_REG_MDIO_READ1, *addr[1]);
810
811             break;
812         default:
813
814             A_PRINTF("Command not implemmented\n");
815             adf_os_assert(0);
816             break;
817         }
818
819     } while ( more );
820
821     /**
822      * Change the Ownership
823      */
824     __gmac_reg_write16(MAG_REG_MDIO_OWN, MDIO_OWN_HST);
825     
826     if ( exec_fn )
827         exec_fn();
828
829 }
830
831 void
832 __gmac_mdio_init(void)
833 {
834
835 more_exec:
836
837         /**
838          * Check for Targets turn
839          */
840         __gmac_mdio_check();
841
842         /**
843          * Load & execute or Read data, if this returns then keep
844          * repeating
845          */
846         __gmac_mdio_load_exec();
847
848         /**
849          * If we are here then Host wants some more function execs or
850          * reads
851          */
852         goto more_exec;
853
854 }
855 void
856 __gmac_boot_init(void)
857 {
858     __gmac_softc_t   *sc = &gmac_sc;
859     
860     
861     __gmac_reset();
862
863     /**
864      * Magpie is Booting
865      */
866     sc->hdr.ath.proto = ATH_P_MAGBOOT;
867
868     dma_lib_tx_init(DMA_ENGINE_TX0, DMA_IF_GMAC);
869     dma_lib_rx_init(DMA_ENGINE_RX0, DMA_IF_GMAC);
870
871     dma_lib_rx_config(DMA_ENGINE_RX0, GMAC_MAX_DESC, GMAC_MAX_PKT_LEN);
872
873     /**
874      * Read the MAC address from the ROM & Write it into the
875      * Register
876      */ 
877     __gmac_rom_read_mac(sc->hdr.eth.src);
878     __gmac_reg_write_mac(sc->hdr.eth.src);
879
880     /**
881      * Discover the Host
882      */
883     __gmac_discover();
884 }   
885 /**
886  * @brief
887  * 
888  * @param pConfig
889  * 
890  * @return hif_handle_t
891  */
892 hif_handle_t 
893 __gmac_init(HIF_CONFIG *pConfig)
894 {
895     __gmac_softc_t  *sc = &gmac_sc;
896     
897     sc->hdr.ath.proto = ATH_P_MAGNORM;
898
899     dma_lib_tx_init(DMA_ENGINE_TX0, DMA_IF_GMAC);
900     dma_lib_rx_init(DMA_ENGINE_RX0, DMA_IF_GMAC);
901     
902     return &gmac_sc;
903 }
904 /**
905  * @brief Configure the receive pipe
906  * 
907  * @param hdl
908  * @param pipe
909  * @param num_desc
910  */
911 void
912 __gmac_cfg_pipe(hif_handle_t hdl, int pipe, int num_desc)
913 {
914     __gmac_softc_t  *sc = &gmac_sc;
915
916     if(pipe == HIF_GMAC_PIPE_RX)
917         dma_lib_rx_config(DMA_ENGINE_RX0, num_desc, sc->gran);
918 }
919 /**
920  * @brief Start the interface
921  * 
922  * @param hdl
923  */
924 void
925 __gmac_start(hif_handle_t  hdl)
926 {
927     return;
928 }
929 /**
930  * @brief Register callback of thre HTC
931  * 
932  * @param hdl
933  * @param sw
934  */
935 void
936 __gmac_reg_callback(hif_handle_t hdl, HIF_CALLBACK *sw)
937 {
938     __gmac_softc_t   *sc = &gmac_sc;
939
940     sc->htc_ctx       = sw->context;
941     sc->indicate_pkt  = sw->recv_buf;
942     sc->ret_pkt       = sw->send_buf_done;
943 }
944 /**
945  * @brief reap the transmit queue for trasnmitted packets
946  * 
947  * @param sc
948  * @param eng_no
949  */
950 void
951 __gmac_reap_xmitted(__gmac_softc_t  *sc, dma_engine_t  eng_no)
952 {
953     VBUF *vbuf = NULL;
954     /**
955      * Walk through the all your TX engines
956      */
957     do {
958        
959        vbuf = dma_lib_reap_xmitted(eng_no);
960        if(!vbuf)
961             break;
962        
963        __gmac_vbuf_pull_head(vbuf, GMAC_HLEN);
964        sc->ret_pkt(vbuf, sc->htc_ctx);
965
966     } while ( vbuf );
967 }
968 /**
969  * @brief reap the receive queue for vbuf's on the specified
970  *        engine number
971  * 
972  * @param sc
973  * @param eng_no
974  */
975 void
976 __gmac_reap_recv(__gmac_softc_t  *sc, dma_engine_t  eng_no)
977 {
978     VBUF   *vbuf = NULL;
979
980     do {
981         vbuf = dma_lib_reap_recv(eng_no);
982         
983         if(!vbuf)
984             break;
985         
986         if(!__is_ath_header(sc, vbuf)){
987             dma_lib_return_recv(eng_no, vbuf);
988             continue;
989         }
990             
991         __gmac_vbuf_pull_head(vbuf, GMAC_HLEN);
992
993         sc->indicate_pkt(NULL, vbuf, sc->htc_ctx); 
994
995     } while ( vbuf );
996 }
997 /**
998  * @brief The interrupt handler
999  * 
1000  * @param hdl
1001  */
1002 void
1003 __gmac_isr_handler(hif_handle_t hdl)
1004 {
1005     __gmac_softc_t  *sc = &gmac_sc;
1006
1007     if(dma_lib_xmit_done(DMA_ENGINE_TX0))
1008         __gmac_reap_xmitted(sc, DMA_ENGINE_TX0);
1009
1010     if(dma_lib_recv_pkt(DMA_ENGINE_RX0))
1011         __gmac_reap_recv(sc, DMA_ENGINE_RX0);
1012 }
1013 /**
1014  * @brief transmit the vbuf from the specified pipe
1015  * 
1016  * @param hdl
1017  * @param pipe
1018  * @param buf
1019  * 
1020  * @return int
1021  */
1022 int
1023 __gmac_xmit_buf(hif_handle_t hdl, int pipe, VBUF *vbuf)
1024 {
1025     __gmac_softc_t  *sc = &gmac_sc;
1026
1027     if (pipe != HIF_GMAC_PIPE_TX)
1028         return -1;
1029
1030 #if 0
1031     adf_os_assert( vbuf->desc_list->data_offset >= GMAC_HLEN)
1032 #endif
1033      
1034     __gmac_put_hdr(vbuf, &sc->hdr);
1035
1036     return dma_lib_hard_xmit(DMA_ENGINE_TX0, vbuf);
1037 }
1038 /**
1039  * @brief Submit the receive vbuf into the receive queue
1040  * 
1041  * @param handle
1042  * @param pipe
1043  * @param buf
1044  */
1045 void
1046 __gmac_return_recv(hif_handle_t hdl, int pipe, VBUF *vbuf)
1047 {
1048     if (pipe == HIF_GMAC_PIPE_RX) 
1049         dma_lib_return_recv(DMA_ENGINE_RX0, vbuf);
1050 }
1051 /**
1052  * @brief Is this pipe number supported
1053  * 
1054  * @param handle
1055  * @param pipe
1056  * 
1057  * @return int
1058  */
1059 int
1060 __gmac_is_pipe_supported(hif_handle_t hdl, int pipe)
1061 {
1062     return __gmac_chk_pipe(pipe);
1063 }
1064 /**
1065  * @brief maximum message length this pipe can support
1066  * 
1067  * @param handle
1068  * @param pipe
1069  * 
1070  * @return int
1071  */
1072 int  
1073 __gmac_get_max_msg_len(hif_handle_t hdl, int pipe)
1074 {
1075     if(__gmac_chk_pipe(pipe))
1076         return GMAC_MAX_PKT_LEN;
1077
1078     return 0;
1079 }
1080 /**
1081  * @brief return the header room required by this HIF
1082  * 
1083  * @param hdl
1084  * 
1085  * @return int
1086  */
1087 int
1088 __gmac_get_reserved_headroom(hif_handle_t  hdl)
1089 {
1090     return (GMAC_HLEN);
1091 }
1092 /**
1093  * @brief Device shutdown, HIF reset required
1094  * 
1095  * @param hdl
1096  */
1097 void
1098 __gmac_shutdown(hif_handle_t hdl)
1099 {
1100     return;
1101 }
1102 void 
1103 __gmac_get_def_pipe(hif_handle_t handle, A_UINT8 *pipe_uplink, 
1104                        A_UINT8 *pipe_downlink)
1105 {
1106     *pipe_uplink   = HIF_GMAC_PIPE_RX;
1107     *pipe_downlink = HIF_GMAC_PIPE_TX;
1108 }
1109
1110 /**
1111  * @brief This install the API's of the HIF
1112  * 
1113  * @param apis
1114  */
1115 void 
1116 hif_gmac_module_install(struct hif_api *apis)
1117 {
1118     /* hook in APIs */
1119     apis->_init = __gmac_init;
1120     apis->_start = __gmac_start;
1121     apis->_config_pipe = __gmac_cfg_pipe;
1122     apis->_isr_handler = __gmac_isr_handler;
1123     apis->_send_buffer = __gmac_xmit_buf;
1124     apis->_return_recv_buf = __gmac_return_recv;
1125     apis->_is_pipe_supported = __gmac_is_pipe_supported;
1126     apis->_get_max_msg_len = __gmac_get_max_msg_len;
1127     apis->_register_callback = __gmac_reg_callback;
1128     apis->_shutdown = __gmac_shutdown;/*XXX*/
1129     apis->_get_reserved_headroom = __gmac_get_reserved_headroom;
1130     apis->_get_default_pipe  = __gmac_get_def_pipe;
1131 }
1132
1133 void 
1134 cmnos_gmac_module_install(struct gmac_api *boot_apis)
1135 {
1136     boot_apis->gmac_boot_init  = __gmac_boot_init;
1137 }