1190558Simp/*-
2190558Simp * Copyright (c) 2009, M. Warner Losh
3190558Simp * All rights reserved.
4190558Simp *
5190558Simp * Redistribution and use in source and binary forms, with or without
6190558Simp * modification, are permitted provided that the following conditions
7190558Simp * are met:
8190558Simp * 1. Redistributions of source code must retain the above copyright
9190558Simp *    notice unmodified, this list of conditions, and the following
10190558Simp *    disclaimer.
11190558Simp * 2. Redistributions in binary form must reproduce the above copyright
12190558Simp *    notice, this list of conditions and the following disclaimer in the
13190558Simp *    documentation and/or other materials provided with the distribution.
14190558Simp *
15190558Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16190558Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17190558Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18190558Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19190558Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20190558Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21190558Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22190558Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23190558Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24190558Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25190558Simp * SUCH DAMAGE.
26190558Simp */
27190558Simp#include <sys/cdefs.h>
28190558Simp__FBSDID("$FreeBSD$");
29190558Simp
30190558Simp/*
31190558Simp * driver for internal phy in the AX88x9x chips.
32190558Simp */
33190558Simp
34190558Simp#include <sys/param.h>
35190558Simp#include <sys/systm.h>
36190558Simp#include <sys/kernel.h>
37190558Simp#include <sys/module.h>
38190558Simp#include <sys/socket.h>
39190558Simp#include <sys/bus.h>
40190558Simp
41190558Simp#include <net/if.h>
42190558Simp#include <net/if_media.h>
43190558Simp
44190558Simp#include <dev/mii/mii.h>
45190558Simp#include <dev/mii/miivar.h>
46190558Simp#include "miidevs.h"
47190558Simp
48190558Simp#include "miibus_if.h"
49190558Simp
50190558Simpstatic int 	axphy_probe(device_t dev);
51190558Simpstatic int 	axphy_attach(device_t dev);
52190558Simp
53190558Simpstatic device_method_t axphy_methods[] = {
54190558Simp	/* device interface */
55190558Simp	DEVMETHOD(device_probe,		axphy_probe),
56190558Simp	DEVMETHOD(device_attach,	axphy_attach),
57190558Simp	DEVMETHOD(device_detach,	mii_phy_detach),
58190558Simp	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
59227908Smarius	DEVMETHOD_END
60190558Simp};
61190558Simp
62190558Simpstatic devclass_t axphy_devclass;
63190558Simp
64190558Simpstatic driver_t axphy_driver = {
65190558Simp	"axphy",
66190558Simp	axphy_methods,
67190558Simp	sizeof(struct mii_softc)
68190558Simp};
69190558Simp
70190558SimpDRIVER_MODULE(axphy, miibus, axphy_driver, axphy_devclass, 0, 0);
71190558Simp
72190558Simpstatic int	axphy_service(struct mii_softc *, struct mii_data *, int);
73190558Simpstatic void	axphy_status(struct mii_softc *);
74190558Simp
75190558Simpstatic const struct mii_phydesc axphys[] = {
76221407Smarius	MII_PHY_DESC(xxASIX, AX88X9X),
77190558Simp	MII_PHY_END
78190558Simp};
79190558Simp
80221407Smariusstatic const struct mii_phy_funcs axphy_funcs = {
81221407Smarius	axphy_service,
82221407Smarius	axphy_status,
83221407Smarius	mii_phy_reset
84221407Smarius};
85221407Smarius
86190558Simpstatic int
87190558Simpaxphy_probe(device_t dev)
88190558Simp{
89190558Simp
90190558Simp	return (mii_phy_dev_probe(dev, axphys, BUS_PROBE_DEFAULT));
91190558Simp}
92190558Simp
93190558Simpstatic int
94190558Simpaxphy_attach(device_t dev)
95190558Simp{
96190558Simp	struct mii_softc *sc;
97190558Simp
98190558Simp	sc = device_get_softc(dev);
99190558Simp
100221407Smarius	mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE,
101221407Smarius	    &axphy_funcs, 1);
102190558Simp	mii_phy_setmedia(sc);
103190558Simp
104190558Simp	return (0);
105190558Simp}
106190558Simp
107190558Simpstatic int
108190558Simpaxphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
109190558Simp{
110190558Simp
111190558Simp	switch (cmd) {
112190558Simp	case MII_POLLSTAT:
113190558Simp		break;
114190558Simp
115190558Simp	case MII_MEDIACHG:
116190558Simp		mii_phy_setmedia(sc);
117190558Simp		break;
118190558Simp
119190558Simp	case MII_TICK:
120190558Simp		if (mii_phy_tick(sc) == EJUSTRETURN)
121190558Simp			return (0);
122190558Simp		break;
123190558Simp	}
124190558Simp
125190558Simp	/* Update the media status. */
126221407Smarius	PHY_STATUS(sc);
127190558Simp
128190558Simp	/* Callback if something changed. */
129190558Simp	mii_phy_update(sc, cmd);
130190558Simp	return (0);
131190558Simp}
132190558Simp
133190558Simpstatic void
134190558Simpaxphy_status(struct mii_softc *sc)
135190558Simp{
136190558Simp	struct mii_data *mii = sc->mii_pdata;
137190558Simp	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
138190558Simp	int bmsr, bmcr;
139190558Simp
140190558Simp	mii->mii_media_status = IFM_AVALID;
141190558Simp	mii->mii_media_active = IFM_ETHER;
142190558Simp
143190558Simp	bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
144190558Simp	if (bmsr & BMSR_LINK)
145190558Simp		mii->mii_media_status |= IFM_ACTIVE;
146190558Simp
147190558Simp	bmcr = PHY_READ(sc, MII_BMCR);
148190558Simp	if (bmcr & BMCR_ISO) {
149190558Simp		mii->mii_media_active |= IFM_NONE;
150190558Simp		mii->mii_media_status = 0;
151190558Simp		return;
152190558Simp	}
153190558Simp
154190558Simp	if (bmcr & BMCR_LOOP)
155190558Simp		mii->mii_media_active |= IFM_LOOP;
156190558Simp
157190558Simp	if (bmcr & BMCR_AUTOEN) {
158190558Simp		if ((bmsr & BMSR_ACOMP) == 0) {
159190558Simp			mii->mii_media_active |= IFM_NONE;
160190558Simp			return;
161190558Simp		}
162190558Simp
163190558Simp#if 0
164190558Simp		scr = PHY_READ(sc, MII_AXPHY_SCR);
165190558Simp		if (scr & SCR_S100)
166190558Simp			mii->mii_media_active |= IFM_100_TX;
167190558Simp		else
168190558Simp			mii->mii_media_active |= IFM_10_T;
169190558Simp		if (scr & SCR_FDX)
170221407Smarius			mii->mii_media_active |=
171221407Smarius			    IFM_FDX | mii_phy_flowstatus(sc);
172213384Smarius		else
173213384Smarius			mii->mii_media_active |= IFM_HDX;
174190558Simp#endif
175190558Simp	} else
176190558Simp		mii->mii_media_active = ife->ifm_media;
177190558Simp}
178