xref: /freebsd/sys/dev/etherswitch/arswitch/arswitch_phy.c (revision a043e8c76bf48ad7b37394d5963a0ac6dc3bb9dd)
1*a043e8c7SAdrian Chadd /*-
2*a043e8c7SAdrian Chadd  * Copyright (c) 2011-2012 Stefan Bethke.
3*a043e8c7SAdrian Chadd  * Copyright (c) 2012 Adrian Chadd.
4*a043e8c7SAdrian Chadd  * All rights reserved.
5*a043e8c7SAdrian Chadd  *
6*a043e8c7SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
7*a043e8c7SAdrian Chadd  * modification, are permitted provided that the following conditions
8*a043e8c7SAdrian Chadd  * are met:
9*a043e8c7SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
10*a043e8c7SAdrian Chadd  *    notice, this list of conditions and the following disclaimer.
11*a043e8c7SAdrian Chadd  * 2. Redistributions in binary form must reproduce the above copyright
12*a043e8c7SAdrian Chadd  *    notice, this list of conditions and the following disclaimer in the
13*a043e8c7SAdrian Chadd  *    documentation and/or other materials provided with the distribution.
14*a043e8c7SAdrian Chadd  *
15*a043e8c7SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*a043e8c7SAdrian Chadd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*a043e8c7SAdrian Chadd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*a043e8c7SAdrian Chadd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*a043e8c7SAdrian Chadd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*a043e8c7SAdrian Chadd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*a043e8c7SAdrian Chadd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*a043e8c7SAdrian Chadd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*a043e8c7SAdrian Chadd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*a043e8c7SAdrian Chadd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*a043e8c7SAdrian Chadd  * SUCH DAMAGE.
26*a043e8c7SAdrian Chadd  *
27*a043e8c7SAdrian Chadd  * $FreeBSD$
28*a043e8c7SAdrian Chadd  */
29*a043e8c7SAdrian Chadd 
30*a043e8c7SAdrian Chadd #include <sys/param.h>
31*a043e8c7SAdrian Chadd #include <sys/bus.h>
32*a043e8c7SAdrian Chadd #include <sys/errno.h>
33*a043e8c7SAdrian Chadd #include <sys/kernel.h>
34*a043e8c7SAdrian Chadd #include <sys/module.h>
35*a043e8c7SAdrian Chadd #include <sys/socket.h>
36*a043e8c7SAdrian Chadd #include <sys/sockio.h>
37*a043e8c7SAdrian Chadd #include <sys/sysctl.h>
38*a043e8c7SAdrian Chadd #include <sys/systm.h>
39*a043e8c7SAdrian Chadd 
40*a043e8c7SAdrian Chadd #include <net/if.h>
41*a043e8c7SAdrian Chadd #include <net/if_arp.h>
42*a043e8c7SAdrian Chadd #include <net/ethernet.h>
43*a043e8c7SAdrian Chadd #include <net/if_dl.h>
44*a043e8c7SAdrian Chadd #include <net/if_media.h>
45*a043e8c7SAdrian Chadd #include <net/if_types.h>
46*a043e8c7SAdrian Chadd 
47*a043e8c7SAdrian Chadd #include <machine/bus.h>
48*a043e8c7SAdrian Chadd #include <dev/iicbus/iic.h>
49*a043e8c7SAdrian Chadd #include <dev/iicbus/iiconf.h>
50*a043e8c7SAdrian Chadd #include <dev/iicbus/iicbus.h>
51*a043e8c7SAdrian Chadd #include <dev/mii/mii.h>
52*a043e8c7SAdrian Chadd #include <dev/mii/miivar.h>
53*a043e8c7SAdrian Chadd #include <dev/etherswitch/mdio.h>
54*a043e8c7SAdrian Chadd 
55*a043e8c7SAdrian Chadd #include <dev/etherswitch/etherswitch.h>
56*a043e8c7SAdrian Chadd 
57*a043e8c7SAdrian Chadd #include <dev/etherswitch/arswitch/arswitchreg.h>
58*a043e8c7SAdrian Chadd #include <dev/etherswitch/arswitch/arswitchvar.h>
59*a043e8c7SAdrian Chadd 
60*a043e8c7SAdrian Chadd #include <dev/etherswitch/arswitch/arswitch_reg.h>
61*a043e8c7SAdrian Chadd #include <dev/etherswitch/arswitch/arswitch_phy.h>
62*a043e8c7SAdrian Chadd 
63*a043e8c7SAdrian Chadd #include "mdio_if.h"
64*a043e8c7SAdrian Chadd #include "miibus_if.h"
65*a043e8c7SAdrian Chadd #include "etherswitch_if.h"
66*a043e8c7SAdrian Chadd 
67*a043e8c7SAdrian Chadd #if	defined(DEBUG)
68*a043e8c7SAdrian Chadd static SYSCTL_NODE(_debug, OID_AUTO, arswitch, CTLFLAG_RD, 0, "arswitch");
69*a043e8c7SAdrian Chadd #endif
70*a043e8c7SAdrian Chadd 
71*a043e8c7SAdrian Chadd /*
72*a043e8c7SAdrian Chadd  * access PHYs integrated into the switch chip through the switch's MDIO
73*a043e8c7SAdrian Chadd  * control register.
74*a043e8c7SAdrian Chadd  */
75*a043e8c7SAdrian Chadd int
76*a043e8c7SAdrian Chadd arswitch_readphy(device_t dev, int phy, int reg)
77*a043e8c7SAdrian Chadd {
78*a043e8c7SAdrian Chadd 	uint32_t data = 0, ctrl;
79*a043e8c7SAdrian Chadd 	int err, timeout;
80*a043e8c7SAdrian Chadd 
81*a043e8c7SAdrian Chadd 	if (phy < 0 || phy >= 32)
82*a043e8c7SAdrian Chadd 		return (ENXIO);
83*a043e8c7SAdrian Chadd 	if (reg < 0 || reg >= 32)
84*a043e8c7SAdrian Chadd 		return (ENXIO);
85*a043e8c7SAdrian Chadd 	err = arswitch_writereg_msb(dev, AR8X16_REG_MDIO_CTRL,
86*a043e8c7SAdrian Chadd 	    AR8X16_MDIO_CTRL_BUSY | AR8X16_MDIO_CTRL_MASTER_EN |
87*a043e8c7SAdrian Chadd 	    AR8X16_MDIO_CTRL_CMD_READ |
88*a043e8c7SAdrian Chadd 	    (phy << AR8X16_MDIO_CTRL_PHY_ADDR_SHIFT) |
89*a043e8c7SAdrian Chadd 	    (reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT));
90*a043e8c7SAdrian Chadd 	DEVERR(dev, err, "arswitch_readphy()=%d: phy=%d.%02x\n", phy, reg);
91*a043e8c7SAdrian Chadd 	if (err != 0)
92*a043e8c7SAdrian Chadd 		return (-1);
93*a043e8c7SAdrian Chadd 	for (timeout = 100; timeout--; ) {
94*a043e8c7SAdrian Chadd 		ctrl = arswitch_readreg_msb(dev, AR8X16_REG_MDIO_CTRL);
95*a043e8c7SAdrian Chadd 		if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0)
96*a043e8c7SAdrian Chadd 			break;
97*a043e8c7SAdrian Chadd 	}
98*a043e8c7SAdrian Chadd 	if (timeout < 0)
99*a043e8c7SAdrian Chadd 		err = EIO;
100*a043e8c7SAdrian Chadd 	data = arswitch_readreg_lsb(dev, AR8X16_REG_MDIO_CTRL) &
101*a043e8c7SAdrian Chadd 	    AR8X16_MDIO_CTRL_DATA_MASK;
102*a043e8c7SAdrian Chadd 	return (data);
103*a043e8c7SAdrian Chadd }
104*a043e8c7SAdrian Chadd 
105*a043e8c7SAdrian Chadd int
106*a043e8c7SAdrian Chadd arswitch_writephy(device_t dev, int phy, int reg, int data)
107*a043e8c7SAdrian Chadd {
108*a043e8c7SAdrian Chadd 	uint32_t ctrl;
109*a043e8c7SAdrian Chadd 	int err, timeout;
110*a043e8c7SAdrian Chadd 
111*a043e8c7SAdrian Chadd 	if (reg < 0 || reg >= 32)
112*a043e8c7SAdrian Chadd 		return (ENXIO);
113*a043e8c7SAdrian Chadd 	err = arswitch_writereg_lsb(dev, AR8X16_REG_MDIO_CTRL,
114*a043e8c7SAdrian Chadd 	    (data & AR8X16_MDIO_CTRL_DATA_MASK));
115*a043e8c7SAdrian Chadd 	DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg);
116*a043e8c7SAdrian Chadd 	if (err != 0)
117*a043e8c7SAdrian Chadd 		return (err);
118*a043e8c7SAdrian Chadd 	err = arswitch_writereg_msb(dev, AR8X16_REG_MDIO_CTRL,
119*a043e8c7SAdrian Chadd 	    AR8X16_MDIO_CTRL_BUSY |
120*a043e8c7SAdrian Chadd 	    AR8X16_MDIO_CTRL_MASTER_EN |
121*a043e8c7SAdrian Chadd 	    AR8X16_MDIO_CTRL_CMD_WRITE |
122*a043e8c7SAdrian Chadd 	    (phy << AR8X16_MDIO_CTRL_PHY_ADDR_SHIFT) |
123*a043e8c7SAdrian Chadd 	    (reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT));
124*a043e8c7SAdrian Chadd 	DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg);
125*a043e8c7SAdrian Chadd 	if (err != 0)
126*a043e8c7SAdrian Chadd 		return (err);
127*a043e8c7SAdrian Chadd 	for (timeout = 100; timeout--; ) {
128*a043e8c7SAdrian Chadd 		ctrl = arswitch_readreg(dev, AR8X16_REG_MDIO_CTRL);
129*a043e8c7SAdrian Chadd 		if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0)
130*a043e8c7SAdrian Chadd 			break;
131*a043e8c7SAdrian Chadd 	}
132*a043e8c7SAdrian Chadd 	if (timeout < 0)
133*a043e8c7SAdrian Chadd 		err = EIO;
134*a043e8c7SAdrian Chadd 	DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg);
135*a043e8c7SAdrian Chadd 	return (err);
136*a043e8c7SAdrian Chadd }
137