1 /*-
2 * Copyright (c) 2003-2012 Broadcom Corporation
3 * All Rights Reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 #include <sys/types.h>
32 #include <sys/systm.h>
33
34 #include <mips/nlm/hal/mips-extns.h>
35 #include <mips/nlm/hal/haldefs.h>
36 #include <mips/nlm/hal/iomap.h>
37 #include <mips/nlm/hal/sys.h>
38 #include <mips/nlm/hal/nae.h>
39 #include <mips/nlm/hal/mdio.h>
40
41 #include <mips/nlm/xlp.h>
42
43 /* Internal MDIO READ/WRITE Routines */
44 int
nlm_int_gmac_mdio_read(uint64_t nae_base,int bus,int block,int intf_type,int phyaddr,int regidx)45 nlm_int_gmac_mdio_read(uint64_t nae_base, int bus, int block,
46 int intf_type, int phyaddr, int regidx)
47 {
48 uint32_t mdio_ld_cmd;
49 uint32_t ctrlval;
50
51 ctrlval = INT_MDIO_CTRL_SMP |
52 (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) |
53 (regidx << INT_MDIO_CTRL_DEVTYPE_POS) |
54 (2 << INT_MDIO_CTRL_OP_POS) |
55 (1 << INT_MDIO_CTRL_ST_POS) |
56 (7 << INT_MDIO_CTRL_XDIV_POS) |
57 (2 << INT_MDIO_CTRL_TA_POS) |
58 (2 << INT_MDIO_CTRL_MIIM_POS) |
59 (1 << INT_MDIO_CTRL_MCDIV_POS);
60
61 mdio_ld_cmd = nlm_read_nae_reg(nae_base,
62 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)));
63 if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) {
64 nlm_write_nae_reg(nae_base,
65 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)),
66 (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD));
67 }
68
69 nlm_write_nae_reg(nae_base,
70 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
71 ctrlval);
72
73 /* Toggle Load Cmd Bit */
74 nlm_write_nae_reg(nae_base,
75 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
76 ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS));
77
78 /* poll master busy bit until it is not busy */
79 while(nlm_read_nae_reg(nae_base,
80 NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) &
81 INT_MDIO_STAT_MBSY) {
82 }
83
84 nlm_write_nae_reg(nae_base,
85 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
86 ctrlval);
87
88 /* Read the data back */
89 return nlm_read_nae_reg(nae_base,
90 NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4)));
91 }
92
93 /* Internal MDIO WRITE Routines */
94 int
nlm_int_gmac_mdio_write(uint64_t nae_base,int bus,int block,int intf_type,int phyaddr,int regidx,uint16_t val)95 nlm_int_gmac_mdio_write(uint64_t nae_base, int bus, int block,
96 int intf_type, int phyaddr, int regidx, uint16_t val)
97 {
98 uint32_t mdio_ld_cmd;
99 uint32_t ctrlval;
100
101 ctrlval = INT_MDIO_CTRL_SMP |
102 (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) |
103 (regidx << INT_MDIO_CTRL_DEVTYPE_POS) |
104 (1 << INT_MDIO_CTRL_OP_POS) |
105 (1 << INT_MDIO_CTRL_ST_POS) |
106 (7 << INT_MDIO_CTRL_XDIV_POS) |
107 (2 << INT_MDIO_CTRL_TA_POS) |
108 (1 << INT_MDIO_CTRL_MIIM_POS) |
109 (1 << INT_MDIO_CTRL_MCDIV_POS);
110
111 mdio_ld_cmd = nlm_read_nae_reg(nae_base,
112 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)));
113 if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) {
114 nlm_write_nae_reg(nae_base,
115 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)),
116 (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD));
117 }
118
119 /* load data into ctrl data reg */
120 nlm_write_nae_reg(nae_base,
121 NAE_REG(block, intf_type, (INT_MDIO_CTRL_DATA + bus * 4)),
122 val);
123
124 nlm_write_nae_reg(nae_base,
125 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
126 ctrlval);
127
128 nlm_write_nae_reg(nae_base,
129 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
130 ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS));
131
132 /* poll master busy bit until it is not busy */
133 while(nlm_read_nae_reg(nae_base,
134 NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) &
135 INT_MDIO_STAT_MBSY) {
136 }
137
138 nlm_write_nae_reg(nae_base,
139 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
140 ctrlval);
141
142 return (0);
143 }
144
145 int
nlm_int_gmac_mdio_reset(uint64_t nae_base,int bus,int block,int intf_type)146 nlm_int_gmac_mdio_reset(uint64_t nae_base, int bus, int block,
147 int intf_type)
148 {
149 uint32_t val;
150
151 val = (7 << INT_MDIO_CTRL_XDIV_POS) |
152 (1 << INT_MDIO_CTRL_MCDIV_POS) |
153 (INT_MDIO_CTRL_SMP);
154
155 nlm_write_nae_reg(nae_base,
156 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
157 val | INT_MDIO_CTRL_RST);
158
159 nlm_write_nae_reg(nae_base,
160 NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
161 val);
162
163 return (0);
164 }
165
166 /*
167 * nae_gmac_mdio_read - Read sgmii phy register
168 *
169 * Input parameters:
170 * bus - bus number, nae has two external gmac bus: 0 and 1
171 * phyaddr - PHY's address
172 * regidx - index of register to read
173 *
174 * Return value:
175 * value read (16 bits), or 0xffffffff if an error occurred.
176 */
177 int
nlm_gmac_mdio_read(uint64_t nae_base,int bus,int block,int intf_type,int phyaddr,int regidx)178 nlm_gmac_mdio_read(uint64_t nae_base, int bus, int block,
179 int intf_type, int phyaddr, int regidx)
180 {
181 uint32_t mdio_ld_cmd;
182 uint32_t ctrlval;
183
184 mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type,
185 (EXT_G0_MDIO_CTRL + bus * 4)));
186 if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) {
187 nlm_write_nae_reg(nae_base,
188 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
189 (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD));
190 while(nlm_read_nae_reg(nae_base,
191 NAE_REG(block, intf_type,
192 (EXT_G0_MDIO_RD_STAT + bus * 4))) &
193 EXT_G_MDIO_STAT_MBSY);
194 }
195
196 ctrlval = EXT_G_MDIO_CMD_SP |
197 (phyaddr << EXT_G_MDIO_PHYADDR_POS) |
198 (regidx << EXT_G_MDIO_REGADDR_POS);
199 if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax())
200 ctrlval |= EXT_G_MDIO_DIV;
201 else
202 ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64;
203
204 nlm_write_nae_reg(nae_base,
205 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
206 ctrlval);
207
208 nlm_write_nae_reg(nae_base,
209 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
210 ctrlval | (1<<18));
211 DELAY(1000);
212 /* poll master busy bit until it is not busy */
213 while(nlm_read_nae_reg(nae_base,
214 NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))) &
215 EXT_G_MDIO_STAT_MBSY);
216
217 nlm_write_nae_reg(nae_base,
218 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
219 ctrlval);
220
221 /* Read the data back */
222 return nlm_read_nae_reg(nae_base,
223 NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4)));
224 }
225
226 /*
227 * nae_gmac_mdio_write -Write sgmac mii PHY register.
228 *
229 * Input parameters:
230 * bus - bus number, nae has two external gmac bus: 0 and 1
231 * phyaddr - PHY to use
232 * regidx - register within the PHY
233 * val - data to write to register
234 *
235 * Return value:
236 * 0 - success
237 */
238 int
nlm_gmac_mdio_write(uint64_t nae_base,int bus,int block,int intf_type,int phyaddr,int regidx,uint16_t val)239 nlm_gmac_mdio_write(uint64_t nae_base, int bus, int block,
240 int intf_type, int phyaddr, int regidx, uint16_t val)
241 {
242 uint32_t mdio_ld_cmd;
243 uint32_t ctrlval;
244
245 mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type,
246 (EXT_G0_MDIO_CTRL + bus * 4)));
247 if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) {
248 nlm_write_nae_reg(nae_base,
249 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
250 (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD));
251 while(nlm_read_nae_reg(nae_base,
252 NAE_REG(block, intf_type,
253 (EXT_G0_MDIO_RD_STAT + bus * 4))) &
254 EXT_G_MDIO_STAT_MBSY);
255 }
256
257 /* load data into ctrl data reg */
258 nlm_write_nae_reg(nae_base,
259 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL_DATA+bus*4)),
260 val);
261
262 ctrlval = EXT_G_MDIO_CMD_SP |
263 (phyaddr << EXT_G_MDIO_PHYADDR_POS) |
264 (regidx << EXT_G_MDIO_REGADDR_POS);
265 if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax())
266 ctrlval |= EXT_G_MDIO_DIV;
267 else
268 ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64;
269
270 nlm_write_nae_reg(nae_base,
271 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
272 ctrlval);
273
274 nlm_write_nae_reg(nae_base,
275 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
276 ctrlval | EXT_G_MDIO_CMD_LCD);
277 DELAY(1000);
278
279 /* poll master busy bit until it is not busy */
280 while(nlm_read_nae_reg(nae_base,
281 NAE_REG(block, intf_type,
282 (EXT_G0_MDIO_RD_STAT + bus * 4))) & EXT_G_MDIO_STAT_MBSY);
283
284 nlm_write_nae_reg(nae_base,
285 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
286 ctrlval);
287
288 return (0);
289 }
290
291 /*
292 * nae_gmac_mdio_reset -Reset sgmii mdio module.
293 *
294 * Input parameters:
295 * bus - bus number, nae has two external gmac bus: 0 and 1
296 *
297 * Return value:
298 * 0 - success
299 */
300 int
nlm_gmac_mdio_reset(uint64_t nae_base,int bus,int block,int intf_type)301 nlm_gmac_mdio_reset(uint64_t nae_base, int bus, int block,
302 int intf_type)
303 {
304 uint32_t ctrlval;
305
306 ctrlval = nlm_read_nae_reg(nae_base,
307 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)));
308
309 if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax())
310 ctrlval |= EXT_G_MDIO_DIV;
311 else
312 ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64;
313
314 nlm_write_nae_reg(nae_base,
315 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)),
316 EXT_G_MDIO_MMRST | ctrlval);
317 nlm_write_nae_reg(nae_base,
318 NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)), ctrlval);
319 return (0);
320 }
321
322 /*
323 * nlm_mdio_reset_all : reset all internal and external MDIO
324 */
325 void
nlm_mdio_reset_all(uint64_t nae_base)326 nlm_mdio_reset_all(uint64_t nae_base)
327 {
328 /* reset internal MDIO */
329 nlm_int_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
330 /* reset external MDIO */
331 nlm_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
332 nlm_gmac_mdio_reset(nae_base, 1, BLOCK_7, LANE_CFG);
333 }
334