(6/6) bcm57xx: package
[openwrt/svn-archive/archive.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 }