1235288Sadrian/*-
2235288Sadrian * Copyright (c) 2011-2012 Stefan Bethke.
3235288Sadrian * Copyright (c) 2012 Adrian Chadd.
4235288Sadrian * All rights reserved.
5235288Sadrian *
6235288Sadrian * Redistribution and use in source and binary forms, with or without
7235288Sadrian * modification, are permitted provided that the following conditions
8235288Sadrian * are met:
9235288Sadrian * 1. Redistributions of source code must retain the above copyright
10235288Sadrian *    notice, this list of conditions and the following disclaimer.
11235288Sadrian * 2. Redistributions in binary form must reproduce the above copyright
12235288Sadrian *    notice, this list of conditions and the following disclaimer in the
13235288Sadrian *    documentation and/or other materials provided with the distribution.
14235288Sadrian *
15235288Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16235288Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17235288Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18235288Sadrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19235288Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20235288Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21235288Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22235288Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23235288Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24235288Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25235288Sadrian * SUCH DAMAGE.
26235288Sadrian *
27235288Sadrian * $FreeBSD$
28235288Sadrian */
29235288Sadrian
30235288Sadrian#include <sys/param.h>
31235288Sadrian#include <sys/bus.h>
32235288Sadrian#include <sys/errno.h>
33235288Sadrian#include <sys/kernel.h>
34235288Sadrian#include <sys/module.h>
35235288Sadrian#include <sys/socket.h>
36235288Sadrian#include <sys/sockio.h>
37235288Sadrian#include <sys/sysctl.h>
38235288Sadrian#include <sys/systm.h>
39235288Sadrian
40235288Sadrian#include <net/if.h>
41235288Sadrian#include <net/if_arp.h>
42235288Sadrian#include <net/ethernet.h>
43235288Sadrian#include <net/if_dl.h>
44235288Sadrian#include <net/if_media.h>
45235288Sadrian#include <net/if_types.h>
46235288Sadrian
47235288Sadrian#include <machine/bus.h>
48235288Sadrian#include <dev/iicbus/iic.h>
49235288Sadrian#include <dev/iicbus/iiconf.h>
50235288Sadrian#include <dev/iicbus/iicbus.h>
51235288Sadrian#include <dev/mii/mii.h>
52235288Sadrian#include <dev/mii/miivar.h>
53235288Sadrian#include <dev/etherswitch/mdio.h>
54235288Sadrian
55235288Sadrian#include <dev/etherswitch/etherswitch.h>
56235288Sadrian
57235288Sadrian#include <dev/etherswitch/arswitch/arswitchreg.h>
58235288Sadrian#include <dev/etherswitch/arswitch/arswitchvar.h>
59235288Sadrian
60235288Sadrian#include <dev/etherswitch/arswitch/arswitch_reg.h>
61235288Sadrian#include <dev/etherswitch/arswitch/arswitch_phy.h>
62235288Sadrian
63235288Sadrian#include "mdio_if.h"
64235288Sadrian#include "miibus_if.h"
65235288Sadrian#include "etherswitch_if.h"
66235288Sadrian
67235288Sadrian#if	defined(DEBUG)
68235288Sadrianstatic SYSCTL_NODE(_debug, OID_AUTO, arswitch, CTLFLAG_RD, 0, "arswitch");
69235288Sadrian#endif
70235288Sadrian
71235288Sadrian/*
72235288Sadrian * access PHYs integrated into the switch chip through the switch's MDIO
73235288Sadrian * control register.
74235288Sadrian */
75235288Sadrianint
76235288Sadrianarswitch_readphy(device_t dev, int phy, int reg)
77235288Sadrian{
78241578Sray	struct arswitch_softc *sc;
79235288Sadrian	uint32_t data = 0, ctrl;
80235288Sadrian	int err, timeout;
81235288Sadrian
82241578Sray	sc = device_get_softc(dev);
83241578Sray	ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
84241578Sray
85235288Sadrian	if (phy < 0 || phy >= 32)
86235288Sadrian		return (ENXIO);
87235288Sadrian	if (reg < 0 || reg >= 32)
88235288Sadrian		return (ENXIO);
89241578Sray
90241578Sray	ARSWITCH_LOCK(sc);
91235288Sadrian	err = arswitch_writereg_msb(dev, AR8X16_REG_MDIO_CTRL,
92235288Sadrian	    AR8X16_MDIO_CTRL_BUSY | AR8X16_MDIO_CTRL_MASTER_EN |
93235288Sadrian	    AR8X16_MDIO_CTRL_CMD_READ |
94235288Sadrian	    (phy << AR8X16_MDIO_CTRL_PHY_ADDR_SHIFT) |
95235288Sadrian	    (reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT));
96235288Sadrian	DEVERR(dev, err, "arswitch_readphy()=%d: phy=%d.%02x\n", phy, reg);
97235288Sadrian	if (err != 0)
98241578Sray		goto fail;
99235288Sadrian	for (timeout = 100; timeout--; ) {
100235288Sadrian		ctrl = arswitch_readreg_msb(dev, AR8X16_REG_MDIO_CTRL);
101235288Sadrian		if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0)
102235288Sadrian			break;
103235288Sadrian	}
104235288Sadrian	if (timeout < 0)
105241578Sray		goto fail;
106235288Sadrian	data = arswitch_readreg_lsb(dev, AR8X16_REG_MDIO_CTRL) &
107235288Sadrian	    AR8X16_MDIO_CTRL_DATA_MASK;
108241578Sray	ARSWITCH_UNLOCK(sc);
109235288Sadrian	return (data);
110241578Sray
111241578Srayfail:
112241578Sray	ARSWITCH_UNLOCK(sc);
113241578Sray	return (-1);
114235288Sadrian}
115235288Sadrian
116235288Sadrianint
117235288Sadrianarswitch_writephy(device_t dev, int phy, int reg, int data)
118235288Sadrian{
119241578Sray	struct arswitch_softc *sc;
120235288Sadrian	uint32_t ctrl;
121235288Sadrian	int err, timeout;
122241578Sray
123241578Sray	sc = device_get_softc(dev);
124241578Sray	ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
125241578Sray
126235288Sadrian	if (reg < 0 || reg >= 32)
127235288Sadrian		return (ENXIO);
128241578Sray
129241578Sray	ARSWITCH_LOCK(sc);
130253570Sloos	err = arswitch_writereg(dev, AR8X16_REG_MDIO_CTRL,
131235288Sadrian	    AR8X16_MDIO_CTRL_BUSY |
132235288Sadrian	    AR8X16_MDIO_CTRL_MASTER_EN |
133235288Sadrian	    AR8X16_MDIO_CTRL_CMD_WRITE |
134235288Sadrian	    (phy << AR8X16_MDIO_CTRL_PHY_ADDR_SHIFT) |
135253570Sloos	    (reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT) |
136253570Sloos	    (data & AR8X16_MDIO_CTRL_DATA_MASK));
137235288Sadrian	if (err != 0)
138241578Sray		goto out;
139235288Sadrian	for (timeout = 100; timeout--; ) {
140235288Sadrian		ctrl = arswitch_readreg(dev, AR8X16_REG_MDIO_CTRL);
141235288Sadrian		if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0)
142235288Sadrian			break;
143235288Sadrian	}
144235288Sadrian	if (timeout < 0)
145235288Sadrian		err = EIO;
146241578Srayout:
147235288Sadrian	DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg);
148241578Sray	ARSWITCH_UNLOCK(sc);
149235288Sadrian	return (err);
150235288Sadrian}
151