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