]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/mips/nlm/dev/net/mdio.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / mips / nlm / dev / net / mdio.c
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
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
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
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
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
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
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
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 }