1 /*
2 * Copyright 2007-2013 Solarflare Communications Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26 #include "efsys.h"
27 #include "efx.h"
28 #include "efx_types.h"
29 #include "efx_regs.h"
30 #include "efx_impl.h"
31
32 #if EFSYS_OPT_FALCON
33
34 static __checkReturn int
35 falcon_mdio_wait(
36 __in efx_nic_t *enp)
37 {
38 efx_oword_t oword;
39 unsigned int count;
40 int rc;
41
42 count = 0;
43 do {
44 EFSYS_PROBE1(wait, unsigned int, count);
45
46 EFX_BAR_READO(enp, FR_AB_MD_STAT_REG, &oword);
47
48 if (EFX_OWORD_FIELD(oword, FRF_AB_MD_BSY) == 0)
49 goto done;
50
51 /* Spin for 100 us */
52 EFSYS_SPIN(100);
53
54 } while (++count < 100);
55
56 rc = ETIMEDOUT;
57 goto fail1;
58
59 done:
60 if (EFX_OWORD_FIELD(oword, FRF_AB_MD_LNFL) != 0) {
61 rc = EIO;
62 goto fail2;
63 }
64
65 if (EFX_OWORD_FIELD(oword, FRF_AB_MD_BSERR) != 0) {
66 rc = EIO;
67 goto fail3;
68 }
69
70 return (0);
71
72 fail3:
73 EFSYS_PROBE(fail3);
74 fail2:
75 EFSYS_PROBE(fail2);
76 fail1:
77 EFSYS_PROBE1(fail1, int, rc);
78
79 return (rc);
80 }
81
82 __checkReturn int
83 falcon_mdio_write(
84 __in efx_nic_t *enp,
85 __in uint8_t port,
86 __in uint8_t mmd,
87 __in uint16_t reg,
88 __in efx_word_t *ewp)
89 {
90 int state;
91 efx_oword_t oword;
92 uint32_t prtad;
93 uint32_t devad;
94 uint32_t addr;
95 uint16_t val;
96 int rc;
97
98 EFSYS_LOCK(enp->en_eslp, state);
99
100 /* Check MDIO is not currently being accessed */
101 if ((rc = falcon_mdio_wait(enp)) != 0)
102 goto fail1;
103
104 prtad = port;
105 devad = mmd;
106
107 /* Write address */
108 EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_PRT_ADR, prtad,
109 FRF_AB_MD_DEV_ADR, devad);
110 EFX_BAR_WRITEO(enp, FR_AB_MD_ID_REG, &oword);
111
112 addr = reg;
113
114 EFX_POPULATE_OWORD_1(oword, FRF_AB_MD_PHY_ADR, addr);
115 EFX_BAR_WRITEO(enp, FR_AB_MD_PHY_ADR_REG, &oword);
116
117 /* Write data */
118 val = EFX_WORD_FIELD(*ewp, EFX_WORD_0);
119
120 EFSYS_PROBE4(mdio_write, uint8_t, port, uint8_t, mmd,
121 uint16_t, reg, uint16_t, val);
122
123 EFX_POPULATE_OWORD_1(oword, FRF_AB_MD_TXD, (uint32_t)val);
124 EFX_BAR_WRITEO(enp, FR_AB_MD_TXD_REG, &oword);
125
126 /* Select clause 45 write cycle */
127 EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_WRC, 1, FRF_AB_MD_GC, 0);
128 EFX_BAR_WRITEO(enp, FR_AB_MD_CS_REG, &oword);
129
130 /* Wait for the cycle to complete */
131 if ((rc = falcon_mdio_wait(enp)) != 0)
132 goto fail2;
133
134 EFSYS_UNLOCK(enp->en_eslp, state);
135 return (0);
136
137 fail2:
138 EFSYS_PROBE(fail2);
139 fail1:
140 EFSYS_PROBE1(fail1, int, rc);
141
142 EFSYS_UNLOCK(enp->en_eslp, state);
143 return (rc);
144 }
145
146 __checkReturn int
147 falcon_mdio_read(
148 __in efx_nic_t *enp,
149 __in uint8_t port,
150 __in uint8_t mmd,
151 __in uint16_t reg,
152 __out efx_word_t *ewp)
153 {
154 int state;
155 efx_oword_t oword;
156 uint32_t prtad;
157 uint32_t devad;
158 uint32_t addr;
159 uint16_t val;
160 int rc;
161
162 EFSYS_LOCK(enp->en_eslp, state);
163
164 /* Check MDIO is not currently being accessed */
165 if ((rc = falcon_mdio_wait(enp)) != 0)
166 goto fail1;
167
168 prtad = port;
169 devad = mmd;
170
171 /* Write address */
172 EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_PRT_ADR, prtad,
173 FRF_AB_MD_DEV_ADR, devad);
174 EFX_BAR_WRITEO(enp, FR_AB_MD_ID_REG, &oword);
175
176 addr = reg;
177
178 EFX_POPULATE_OWORD_1(oword, FRF_AB_MD_PHY_ADR, addr);
179 EFX_BAR_WRITEO(enp, FR_AB_MD_PHY_ADR_REG, &oword);
180
181 /* Clear the data register */
182 EFX_SET_OWORD(oword);
183 EFX_BAR_WRITEO(enp, FR_AB_MD_RXD_REG, &oword);
184
185 /* Select clause 45 read cycle */
186 EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_RDC, 1, FRF_AB_MD_GC, 0);
187 EFX_BAR_WRITEO(enp, FR_AB_MD_CS_REG, &oword);
188
189 /* Wait for the cycle to complete */
190 if ((rc = falcon_mdio_wait(enp)) != 0)
191 goto fail2;
192
193 /* Read data */
194 EFX_BAR_READO(enp, FR_AB_MD_RXD_REG, &oword);
195 val = (uint16_t)EFX_OWORD_FIELD(oword, FRF_AB_MD_RXD);
196
197 EFSYS_PROBE4(mdio_read, uint8_t, port, uint8_t, mmd,
198 uint16_t, reg, uint16_t, val);
199
200 EFX_POPULATE_WORD_1(*ewp, EFX_WORD_0, val);
201
202 EFSYS_UNLOCK(enp->en_eslp, state);
203 return (0);
204
205 fail2:
206 EFSYS_PROBE(fail2);
207 fail1:
208 EFSYS_PROBE1(fail1, int, rc);
209
210 EFSYS_UNLOCK(enp->en_eslp, state);
211 return (rc);
212 }
213
214 #endif /* EFSYS_OPT_FALCON */