19774934a34994329e0a8d855a31fbfb33f3cc38
[openwrt.git] / package / broadcom-57xx / src / hndgige.c
1 /*
2  * HND SiliconBackplane Gigabit Ethernet core software interface
3  *
4  * Copyright 2007, Broadcom Corporation
5  * All Rights Reserved.
6  * 
7  * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8  * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9  * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10  * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11  *
12  * $Id: hndgige.c,v 1.6 2007/06/01 05:59:06 michael Exp $
13  */
14
15 #include <typedefs.h>
16 #include <osl.h>
17 #include <pcicfg.h>
18 #include <sbconfig.h>
19 #include <sbutils.h>
20 #include "sbgige.h"
21 #include <hndpci.h>
22 #include "hndgige.h"
23
24 uint32
25 sb_base(uint32 admatch)
26 {
27         uint32 base;
28         uint type;
29
30         type = admatch & SBAM_TYPE_MASK;
31         ASSERT(type < 3);
32
33         base = 0;
34
35         if (type == 0) {
36                 base = admatch & SBAM_BASE0_MASK;
37         } else if (type == 1) {
38                 ASSERT(!(admatch & SBAM_ADNEG));        /* neg not supported */
39                 base = admatch & SBAM_BASE1_MASK;
40         } else if (type == 2) {
41                 ASSERT(!(admatch & SBAM_ADNEG));        /* neg not supported */
42                 base = admatch & SBAM_BASE2_MASK;
43         }
44
45         return (base);
46 }
47
48 /*
49  * Setup the gige core.
50  * Resetting the core will lose all settings.
51  */
52 void
53 sb_gige_init(sb_t *sbh, uint32 unit, bool *rgmii)
54 {
55         volatile pci_config_regs *pci;
56         sbgige_pcishim_t *ocp;
57         sbconfig_t *sb;
58         osl_t *osh;
59         uint32 statelow;
60         uint32 statehigh;
61         uint32 base;
62         uint32 idx;
63         void *regs;
64
65         /* Sanity checks */
66         ASSERT(sbh);
67         ASSERT(rgmii);
68
69         idx = sb_coreidx(sbh);
70
71         /* point to the gige core registers */
72         regs = sb_setcore(sbh, SB_GIGETH, unit);
73         ASSERT(regs);
74
75         osh = sb_osh(sbh);
76
77         pci = &((sbgige_t *)regs)->pcicfg;
78         ocp = &((sbgige_t *)regs)->pcishim;
79         sb = &((sbgige_t *)regs)->sbconfig;
80
81         /* Enable the core clock and memory access */
82         if (!sb_iscoreup(sbh))
83                 sb_core_reset(sbh, 0, 0);
84
85         /*
86          * Setup the 64K memory-mapped region base address through BAR0.
87          * Leave the other BAR values alone.
88          */
89         base = sb_base(R_REG(osh, &sb->sbadmatch1));
90         W_REG(osh, &pci->base[0], base);
91         W_REG(osh, &pci->base[1], 0);
92
93         /*
94          * Enable the PCI memory access anyway. Any PCI config commands
95          * issued before the core is enabled will go to the emulation
96          * only and will not go to the real PCI config registers.
97          */
98         OR_REG(osh, &pci->command, 2);
99
100         /*
101          * Enable the posted write flush scheme as follows:
102          *
103          * - Enable flush on any core register read
104          * - Enable timeout on the flush
105          * - Disable the interrupt mask when flushing
106          *
107          * This differs from the default setting only in that interrupts are
108          * not masked.  Since posted writes are not flushed on interrupt, the
109          * driver must explicitly request a flush in its interrupt handling
110          * by reading a core register.
111          */
112         W_REG(osh, &ocp->FlushStatusControl, 0x68);
113
114         /*
115          * Determine whether the GbE is in GMII or RGMII mode.  This is
116          * indicated in bit 16 of the SBTMStateHigh register, which is
117          * part of the core-specific flags field.
118          *
119          * For GMII, bypass the Rx/Tx DLLs, i.e. add no delay to RXC/GTXC
120          * within the core.  For RGMII, do not bypass the DLLs, resulting
121          * in added delay for RXC/GTXC.  The SBTMStateLow register contains
122          * the controls for doing this in the core-specific flags field:
123          *
124          *   bit 24 - Enable DLL controls
125          *   bit 20 - Bypass Rx DLL
126          *   bit 19 - Bypass Tx DLL
127          */
128         statelow = R_REG(osh, &sb->sbtmstatelow);       /* DLL controls */
129         statehigh = R_REG(osh, &sb->sbtmstatehigh);     /* GMII/RGMII mode */
130         if ((statehigh & (1 << 16)) != 0)       /* RGMII */
131         {
132                 statelow &= ~(1 << 20);         /* no Rx bypass (delay) */
133                 statelow &= ~(1 << 19);         /* no Tx bypass (delay) */
134                 *rgmii = TRUE;
135         }
136         else                                    /* GMII */
137         {
138                 statelow |= (1 << 20);          /* Rx bypass (no delay) */
139                 statelow |= (1 << 19);          /* Tx bypass (no delay) */
140                 *rgmii = FALSE;
141         }
142         statelow |= (1 << 24);                  /* enable DLL controls */
143         W_REG(osh, &sb->sbtmstatelow, statelow);
144
145         sb_setcoreidx(sbh, idx);
146 }