1233545Sjchandra/*-
2233545Sjchandra * Copyright (c) 2003-2012 Broadcom Corporation
3233545Sjchandra * All Rights Reserved
4233545Sjchandra *
5233545Sjchandra * Redistribution and use in source and binary forms, with or without
6233545Sjchandra * modification, are permitted provided that the following conditions
7233545Sjchandra * are met:
8233545Sjchandra *
9233545Sjchandra * 1. Redistributions of source code must retain the above copyright
10233545Sjchandra *    notice, this list of conditions and the following disclaimer.
11233545Sjchandra * 2. Redistributions in binary form must reproduce the above copyright
12233545Sjchandra *    notice, this list of conditions and the following disclaimer in
13233545Sjchandra *    the documentation and/or other materials provided with the
14233545Sjchandra *    distribution.
15233545Sjchandra *
16233545Sjchandra * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
17233545Sjchandra * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18233545Sjchandra * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19233545Sjchandra * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
20233545Sjchandra * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21233545Sjchandra * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22233545Sjchandra * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23233545Sjchandra * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24233545Sjchandra * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25233545Sjchandra * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26233545Sjchandra * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27233545Sjchandra */
28233545Sjchandra
29233545Sjchandra#include <sys/cdefs.h>
30233545Sjchandra__FBSDID("$FreeBSD$");
31233545Sjchandra#include <sys/types.h>
32233545Sjchandra#include <sys/systm.h>
33233545Sjchandra
34233545Sjchandra#include <mips/nlm/hal/mips-extns.h>
35233545Sjchandra#include <mips/nlm/hal/haldefs.h>
36233545Sjchandra#include <mips/nlm/hal/iomap.h>
37233545Sjchandra#include <mips/nlm/hal/sys.h>
38233545Sjchandra#include <mips/nlm/hal/nae.h>
39233545Sjchandra#include <mips/nlm/hal/mdio.h>
40233545Sjchandra
41238293Sjchandra#include <mips/nlm/xlp.h>
42238293Sjchandra
43233545Sjchandra/* Internal MDIO READ/WRITE Routines */
44233545Sjchandraint
45233545Sjchandranlm_int_gmac_mdio_read(uint64_t nae_base, int bus, int block,
46233545Sjchandra    int intf_type, int phyaddr, int regidx)
47233545Sjchandra{
48233545Sjchandra	uint32_t mdio_ld_cmd;
49233545Sjchandra	uint32_t ctrlval;
50233545Sjchandra
51233545Sjchandra	ctrlval = INT_MDIO_CTRL_SMP 		|
52233545Sjchandra	    (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) |
53233545Sjchandra	    (regidx << INT_MDIO_CTRL_DEVTYPE_POS) |
54233545Sjchandra	    (2 << INT_MDIO_CTRL_OP_POS)		|
55233545Sjchandra	    (1 << INT_MDIO_CTRL_ST_POS)		|
56233545Sjchandra	    (7 << INT_MDIO_CTRL_XDIV_POS) 	|
57233545Sjchandra	    (2 << INT_MDIO_CTRL_TA_POS)		|
58233545Sjchandra	    (2 << INT_MDIO_CTRL_MIIM_POS) 	|
59233545Sjchandra	    (1 << INT_MDIO_CTRL_MCDIV_POS);
60233545Sjchandra
61233545Sjchandra	mdio_ld_cmd = nlm_read_nae_reg(nae_base,
62233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)));
63233545Sjchandra	if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) {
64233545Sjchandra		nlm_write_nae_reg(nae_base,
65233545Sjchandra		    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)),
66233545Sjchandra		    (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD));
67233545Sjchandra	}
68233545Sjchandra
69233545Sjchandra	nlm_write_nae_reg(nae_base,
70233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
71233545Sjchandra	    ctrlval);
72233545Sjchandra
73233545Sjchandra	/* Toggle Load Cmd Bit */
74233545Sjchandra	nlm_write_nae_reg(nae_base,
75233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
76233545Sjchandra	    ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS));
77233545Sjchandra
78233545Sjchandra	/* poll master busy bit until it is not busy */
79233545Sjchandra	while(nlm_read_nae_reg(nae_base,
80233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) &
81233545Sjchandra	    INT_MDIO_STAT_MBSY) {
82233545Sjchandra	}
83233545Sjchandra
84233545Sjchandra	nlm_write_nae_reg(nae_base,
85233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
86233545Sjchandra	    ctrlval);
87233545Sjchandra
88233545Sjchandra	/* Read the data back */
89233545Sjchandra	return nlm_read_nae_reg(nae_base,
90233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4)));
91233545Sjchandra}
92233545Sjchandra
93233545Sjchandra/* Internal MDIO WRITE Routines */
94233545Sjchandraint
95233545Sjchandranlm_int_gmac_mdio_write(uint64_t nae_base, int bus, int block,
96233545Sjchandra    int intf_type, int phyaddr, int regidx, uint16_t val)
97233545Sjchandra{
98233545Sjchandra	uint32_t mdio_ld_cmd;
99233545Sjchandra	uint32_t ctrlval;
100233545Sjchandra
101233545Sjchandra	ctrlval = INT_MDIO_CTRL_SMP		|
102233545Sjchandra	    (phyaddr << INT_MDIO_CTRL_PHYADDR_POS) |
103233545Sjchandra	    (regidx << INT_MDIO_CTRL_DEVTYPE_POS) |
104233545Sjchandra	    (1 << INT_MDIO_CTRL_OP_POS)		|
105233545Sjchandra	    (1 << INT_MDIO_CTRL_ST_POS)		|
106233545Sjchandra	    (7 << INT_MDIO_CTRL_XDIV_POS)	|
107233545Sjchandra	    (2 << INT_MDIO_CTRL_TA_POS)		|
108233545Sjchandra	    (1 << INT_MDIO_CTRL_MIIM_POS)	|
109233545Sjchandra	    (1 << INT_MDIO_CTRL_MCDIV_POS);
110233545Sjchandra
111233545Sjchandra	mdio_ld_cmd = nlm_read_nae_reg(nae_base,
112233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)));
113233545Sjchandra	if (mdio_ld_cmd & INT_MDIO_CTRL_CMD_LOAD) {
114233545Sjchandra		nlm_write_nae_reg(nae_base,
115233545Sjchandra		    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus*4)),
116233545Sjchandra		    (mdio_ld_cmd & ~INT_MDIO_CTRL_CMD_LOAD));
117233545Sjchandra	}
118233545Sjchandra
119233545Sjchandra	/* load data into ctrl data reg */
120233545Sjchandra	nlm_write_nae_reg(nae_base,
121233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL_DATA + bus * 4)),
122233545Sjchandra	    val);
123233545Sjchandra
124233545Sjchandra	nlm_write_nae_reg(nae_base,
125233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
126233545Sjchandra	    ctrlval);
127233545Sjchandra
128233545Sjchandra	nlm_write_nae_reg(nae_base,
129233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
130233545Sjchandra	    ctrlval | (1 << INT_MDIO_CTRL_LOAD_POS));
131233545Sjchandra
132233545Sjchandra	/* poll master busy bit until it is not busy */
133233545Sjchandra	while(nlm_read_nae_reg(nae_base,
134233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_RD_STAT + bus * 4))) &
135233545Sjchandra	    INT_MDIO_STAT_MBSY) {
136233545Sjchandra	}
137233545Sjchandra
138233545Sjchandra	nlm_write_nae_reg(nae_base,
139233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
140233545Sjchandra	    ctrlval);
141233545Sjchandra
142233545Sjchandra	return (0);
143233545Sjchandra}
144233545Sjchandra
145233545Sjchandraint
146233545Sjchandranlm_int_gmac_mdio_reset(uint64_t nae_base, int bus, int block,
147233545Sjchandra    int intf_type)
148233545Sjchandra{
149233545Sjchandra	uint32_t val;
150233545Sjchandra
151233545Sjchandra	val = (7 << INT_MDIO_CTRL_XDIV_POS) |
152245881Sjchandra	    (1 << INT_MDIO_CTRL_MCDIV_POS) |
153245881Sjchandra	    (INT_MDIO_CTRL_SMP);
154233545Sjchandra
155233545Sjchandra	nlm_write_nae_reg(nae_base,
156233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
157233545Sjchandra	    val | INT_MDIO_CTRL_RST);
158233545Sjchandra
159233545Sjchandra	nlm_write_nae_reg(nae_base,
160233545Sjchandra	    NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
161233545Sjchandra	    val);
162233545Sjchandra
163233545Sjchandra        return (0);
164233545Sjchandra}
165233545Sjchandra
166233545Sjchandra/*
167233545Sjchandra *  nae_gmac_mdio_read - Read sgmii phy register
168233545Sjchandra *
169233545Sjchandra *  Input parameters:
170233545Sjchandra *         bus          - bus number, nae has two external gmac bus: 0 and 1
171233545Sjchandra *         phyaddr      - PHY's address
172233545Sjchandra *         regidx       - index of register to read
173233545Sjchandra *
174233545Sjchandra *  Return value:
175233545Sjchandra *         value read (16 bits), or 0xffffffff if an error occurred.
176233545Sjchandra */
177233545Sjchandraint
178233545Sjchandranlm_gmac_mdio_read(uint64_t nae_base, int bus, int block,
179233545Sjchandra    int intf_type, int phyaddr, int regidx)
180233545Sjchandra{
181233545Sjchandra	uint32_t mdio_ld_cmd;
182238293Sjchandra	uint32_t ctrlval;
183233545Sjchandra
184233545Sjchandra	mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type,
185233545Sjchandra	    (EXT_G0_MDIO_CTRL + bus * 4)));
186233545Sjchandra	if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) {
187233545Sjchandra		nlm_write_nae_reg(nae_base,
188233545Sjchandra		    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
189233545Sjchandra		    (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD));
190233545Sjchandra		while(nlm_read_nae_reg(nae_base,
191233545Sjchandra		    NAE_REG(block, intf_type,
192233545Sjchandra		    (EXT_G0_MDIO_RD_STAT + bus * 4))) &
193233545Sjchandra		    EXT_G_MDIO_STAT_MBSY);
194233545Sjchandra	}
195233545Sjchandra
196238293Sjchandra	ctrlval = EXT_G_MDIO_CMD_SP |
197238293Sjchandra	    (phyaddr << EXT_G_MDIO_PHYADDR_POS) |
198238293Sjchandra	    (regidx << EXT_G_MDIO_REGADDR_POS);
199238293Sjchandra	if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax())
200238293Sjchandra	    	ctrlval |= EXT_G_MDIO_DIV;
201238293Sjchandra	else
202238293Sjchandra		ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64;
203238293Sjchandra
204238293Sjchandra	nlm_write_nae_reg(nae_base,
205233545Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
206238293Sjchandra	    ctrlval);
207233545Sjchandra
208233545Sjchandra	nlm_write_nae_reg(nae_base,
209233545Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
210238293Sjchandra	    ctrlval | (1<<18));
211238293Sjchandra	DELAY(1000);
212233545Sjchandra	/* poll master busy bit until it is not busy */
213233545Sjchandra	while(nlm_read_nae_reg(nae_base,
214233545Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4))) &
215233545Sjchandra	    EXT_G_MDIO_STAT_MBSY);
216233545Sjchandra
217233545Sjchandra	nlm_write_nae_reg(nae_base,
218233545Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
219238293Sjchandra	    ctrlval);
220233545Sjchandra
221233545Sjchandra	/* Read the data back */
222233545Sjchandra	return nlm_read_nae_reg(nae_base,
223233545Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_RD_STAT + bus * 4)));
224233545Sjchandra}
225233545Sjchandra
226233545Sjchandra/*
227233545Sjchandra *  nae_gmac_mdio_write -Write sgmac mii PHY register.
228233545Sjchandra *
229233545Sjchandra *  Input parameters:
230233545Sjchandra *         bus          - bus number, nae has two external gmac bus: 0 and 1
231233545Sjchandra *         phyaddr      - PHY to use
232233545Sjchandra *         regidx       - register within the PHY
233233545Sjchandra *         val          - data to write to register
234233545Sjchandra *
235233545Sjchandra *  Return value:
236233545Sjchandra *         0 - success
237233545Sjchandra */
238233545Sjchandraint
239233545Sjchandranlm_gmac_mdio_write(uint64_t nae_base, int bus, int block,
240233545Sjchandra    int intf_type, int phyaddr, int regidx, uint16_t val)
241233545Sjchandra{
242233545Sjchandra	uint32_t mdio_ld_cmd;
243233545Sjchandra	uint32_t ctrlval;
244233545Sjchandra
245233545Sjchandra	mdio_ld_cmd = nlm_read_nae_reg(nae_base, NAE_REG(block, intf_type,
246233545Sjchandra	    (EXT_G0_MDIO_CTRL + bus * 4)));
247233545Sjchandra	if (mdio_ld_cmd & EXT_G_MDIO_CMD_LCD) {
248233545Sjchandra		nlm_write_nae_reg(nae_base,
249233545Sjchandra		    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
250233545Sjchandra		    (mdio_ld_cmd & ~EXT_G_MDIO_CMD_LCD));
251233545Sjchandra		while(nlm_read_nae_reg(nae_base,
252233545Sjchandra		    NAE_REG(block, intf_type,
253233545Sjchandra		    (EXT_G0_MDIO_RD_STAT + bus * 4))) &
254233545Sjchandra		    EXT_G_MDIO_STAT_MBSY);
255233545Sjchandra	}
256233545Sjchandra
257233545Sjchandra	/* load data into ctrl data reg */
258233545Sjchandra	nlm_write_nae_reg(nae_base,
259233545Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL_DATA+bus*4)),
260233545Sjchandra	    val);
261233545Sjchandra
262238293Sjchandra	ctrlval = EXT_G_MDIO_CMD_SP		|
263238293Sjchandra	    (phyaddr << EXT_G_MDIO_PHYADDR_POS)	|
264238293Sjchandra	    (regidx << EXT_G_MDIO_REGADDR_POS);
265238293Sjchandra	if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax())
266238293Sjchandra	    	ctrlval |= EXT_G_MDIO_DIV;
267238293Sjchandra	else
268238293Sjchandra		ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64;
269238293Sjchandra
270233545Sjchandra	nlm_write_nae_reg(nae_base,
271233545Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
272233545Sjchandra	    ctrlval);
273233545Sjchandra
274233545Sjchandra	nlm_write_nae_reg(nae_base,
275233545Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
276233545Sjchandra	    ctrlval | EXT_G_MDIO_CMD_LCD);
277238293Sjchandra	DELAY(1000);
278233545Sjchandra
279233545Sjchandra	/* poll master busy bit until it is not busy */
280233545Sjchandra	while(nlm_read_nae_reg(nae_base,
281233545Sjchandra	    NAE_REG(block, intf_type,
282233545Sjchandra	    (EXT_G0_MDIO_RD_STAT + bus * 4))) & EXT_G_MDIO_STAT_MBSY);
283233545Sjchandra
284233545Sjchandra	nlm_write_nae_reg(nae_base,
285233545Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)),
286233545Sjchandra	    ctrlval);
287233545Sjchandra
288233545Sjchandra	return (0);
289233545Sjchandra}
290233545Sjchandra
291233545Sjchandra/*
292233545Sjchandra *  nae_gmac_mdio_reset -Reset sgmii mdio module.
293233545Sjchandra *
294233545Sjchandra *  Input parameters:
295233545Sjchandra *         bus - bus number, nae has two external gmac bus: 0 and 1
296233545Sjchandra *
297233545Sjchandra *  Return value:
298233545Sjchandra *        0 - success
299233545Sjchandra */
300233545Sjchandraint
301233545Sjchandranlm_gmac_mdio_reset(uint64_t nae_base, int bus, int block,
302233545Sjchandra    int intf_type)
303233545Sjchandra{
304238293Sjchandra	uint32_t ctrlval;
305238293Sjchandra
306245881Sjchandra	ctrlval = nlm_read_nae_reg(nae_base,
307245881Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)));
308245881Sjchandra
309238293Sjchandra	if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax())
310245881Sjchandra		ctrlval |= EXT_G_MDIO_DIV;
311238293Sjchandra	else
312245881Sjchandra		ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64;
313238293Sjchandra
314233545Sjchandra	nlm_write_nae_reg(nae_base,
315238293Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)),
316238293Sjchandra	    EXT_G_MDIO_MMRST | ctrlval);
317233545Sjchandra	nlm_write_nae_reg(nae_base,
318238293Sjchandra	    NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)), ctrlval);
319233545Sjchandra	return (0);
320233545Sjchandra}
321245881Sjchandra
322245881Sjchandra/*
323245881Sjchandra * nlm_mdio_reset_all : reset all internal and external MDIO
324245881Sjchandra */
325245881Sjchandravoid
326245881Sjchandranlm_mdio_reset_all(uint64_t nae_base)
327245881Sjchandra{
328245881Sjchandra	/* reset internal MDIO */
329245881Sjchandra	nlm_int_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
330245881Sjchandra	/* reset external MDIO */
331245881Sjchandra	nlm_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
332245881Sjchandra	nlm_gmac_mdio_reset(nae_base, 1, BLOCK_7, LANE_CFG);
333245881Sjchandra}
334