1*7a9a30c5Sthorpej /* $NetBSD: pnaphy.c,v 1.26 2020/03/15 23:04:50 thorpej Exp $ */
2158cb839Sthorpej
3158cb839Sthorpej /*
4158cb839Sthorpej * Copyright 2001 Wasabi Systems, Inc.
5158cb839Sthorpej * All rights reserved.
6158cb839Sthorpej *
7158cb839Sthorpej * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8158cb839Sthorpej *
9158cb839Sthorpej * Redistribution and use in source and binary forms, with or without
10158cb839Sthorpej * modification, are permitted provided that the following conditions
11158cb839Sthorpej * are met:
12158cb839Sthorpej * 1. Redistributions of source code must retain the above copyright
13158cb839Sthorpej * notice, this list of conditions and the following disclaimer.
14158cb839Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
15158cb839Sthorpej * notice, this list of conditions and the following disclaimer in the
16158cb839Sthorpej * documentation and/or other materials provided with the distribution.
17158cb839Sthorpej * 3. All advertising materials mentioning features or use of this software
18158cb839Sthorpej * must display the following acknowledgement:
19158cb839Sthorpej * This product includes software developed for the NetBSD Project by
20158cb839Sthorpej * Wasabi Systems, Inc.
21158cb839Sthorpej * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22158cb839Sthorpej * or promote products derived from this software without specific prior
23158cb839Sthorpej * written permission.
24158cb839Sthorpej *
25158cb839Sthorpej * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26158cb839Sthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27158cb839Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28158cb839Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29158cb839Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30158cb839Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31158cb839Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32158cb839Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33158cb839Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34158cb839Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35158cb839Sthorpej * POSSIBILITY OF SUCH DAMAGE.
36158cb839Sthorpej */
37158cb839Sthorpej
38158cb839Sthorpej /*
39158cb839Sthorpej * Driver for generic HomePNA 1.0 PHYs.
40158cb839Sthorpej *
41158cb839Sthorpej * HomePNA 1.0 PHYs are pretty simple -- they support exactly one
42158cb839Sthorpej * media type, and don't do autonegotiation.
43158cb839Sthorpej *
44158cb839Sthorpej * HomePNA PHYs often have vendor-specific registers for tuning
45158cb839Sthorpej * the network connection, but we don't deal with any of that
46158cb839Sthorpej * at all.
47158cb839Sthorpej */
48158cb839Sthorpej
498b7bb912Slukem #include <sys/cdefs.h>
50*7a9a30c5Sthorpej __KERNEL_RCSID(0, "$NetBSD: pnaphy.c,v 1.26 2020/03/15 23:04:50 thorpej Exp $");
518b7bb912Slukem
52158cb839Sthorpej #include <sys/param.h>
53158cb839Sthorpej #include <sys/systm.h>
54158cb839Sthorpej #include <sys/kernel.h>
55158cb839Sthorpej #include <sys/device.h>
56158cb839Sthorpej #include <sys/socket.h>
57158cb839Sthorpej #include <sys/errno.h>
58158cb839Sthorpej
59158cb839Sthorpej #include <net/if.h>
60158cb839Sthorpej #include <net/if_media.h>
61158cb839Sthorpej
62158cb839Sthorpej #include <dev/mii/mii.h>
63158cb839Sthorpej #include <dev/mii/miivar.h>
64158cb839Sthorpej #include <dev/mii/miidevs.h>
65158cb839Sthorpej
667db0e577Sxtraeme static int pnaphymatch(device_t, cfdata_t, void *);
677db0e577Sxtraeme static void pnaphyattach(device_t, device_t, void *);
68158cb839Sthorpej
697db0e577Sxtraeme CFATTACH_DECL_NEW(pnaphy, sizeof(struct mii_softc),
70c9b3657cSthorpej pnaphymatch, pnaphyattach, mii_phy_detach, mii_phy_activate);
71158cb839Sthorpej
721efb3da0Sthorpej static int pnaphy_service(struct mii_softc *, struct mii_data *, int);
731efb3da0Sthorpej static void pnaphy_status(struct mii_softc *);
74158cb839Sthorpej
751efb3da0Sthorpej static const struct mii_phy_funcs pnaphy_funcs = {
76158cb839Sthorpej pnaphy_service, pnaphy_status, mii_phy_reset,
77158cb839Sthorpej };
78158cb839Sthorpej
791efb3da0Sthorpej static const struct mii_phydesc pnaphys[] = {
807b43da1bSchristos MII_PHY_DESC(yyAMD, 79c901home),
817b43da1bSchristos MII_PHY_END,
82158cb839Sthorpej };
83158cb839Sthorpej
841efb3da0Sthorpej static int
pnaphymatch(device_t parent,cfdata_t match,void * aux)857db0e577Sxtraeme pnaphymatch(device_t parent, cfdata_t match, void *aux)
86158cb839Sthorpej {
87158cb839Sthorpej struct mii_attach_args *ma = aux;
88158cb839Sthorpej
89158cb839Sthorpej if (mii_phy_match(ma, pnaphys) != NULL) {
90158cb839Sthorpej /*
91158cb839Sthorpej * Match higher than ukphy, but lower than a specific
92158cb839Sthorpej * driver would match.
93158cb839Sthorpej */
948e65e831Smsaitoh return 2;
95158cb839Sthorpej }
96158cb839Sthorpej
978e65e831Smsaitoh return 0;
98158cb839Sthorpej }
99158cb839Sthorpej
1001efb3da0Sthorpej static void
pnaphyattach(device_t parent,device_t self,void * aux)1017db0e577Sxtraeme pnaphyattach(device_t parent, device_t self, void *aux)
102158cb839Sthorpej {
103838ee1e0Sthorpej struct mii_softc *sc = device_private(self);
104158cb839Sthorpej struct mii_attach_args *ma = aux;
105158cb839Sthorpej struct mii_data *mii = ma->mii_data;
106158cb839Sthorpej const struct mii_phydesc *mpd;
107158cb839Sthorpej
108158cb839Sthorpej mpd = mii_phy_match(ma, pnaphys);
109c31f87a5Sthorpej aprint_naive(": Media interface\n");
110c31f87a5Sthorpej aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
111158cb839Sthorpej
1127db0e577Sxtraeme sc->mii_dev = self;
113158cb839Sthorpej sc->mii_inst = mii->mii_instance;
114158cb839Sthorpej sc->mii_phy = ma->mii_phyno;
115158cb839Sthorpej sc->mii_funcs = &pnaphy_funcs;
116158cb839Sthorpej sc->mii_pdata = mii;
1178e65e831Smsaitoh sc->mii_flags = ma->mii_flags | MIIF_IS_HPNA; /* Force HomePNA */
118158cb839Sthorpej
119*7a9a30c5Sthorpej mii_lock(mii);
120*7a9a30c5Sthorpej
121158cb839Sthorpej PHY_RESET(sc);
122158cb839Sthorpej
123a5cdd4b4Smsaitoh PHY_READ(sc, MII_BMSR, &sc->mii_capabilities);
124a5cdd4b4Smsaitoh sc->mii_capabilities &= ma->mii_capmask;
125509697f3Smsaitoh
126*7a9a30c5Sthorpej mii_unlock(mii);
127*7a9a30c5Sthorpej
128158cb839Sthorpej mii_phy_add_media(sc);
129158cb839Sthorpej }
130158cb839Sthorpej
1311efb3da0Sthorpej static int
pnaphy_service(struct mii_softc * sc,struct mii_data * mii,int cmd)13289893e42Sthorpej pnaphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
133158cb839Sthorpej {
134158cb839Sthorpej struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
135a5cdd4b4Smsaitoh uint16_t reg;
136158cb839Sthorpej
137*7a9a30c5Sthorpej KASSERT(mii_locked(mii));
138*7a9a30c5Sthorpej
139158cb839Sthorpej switch (cmd) {
140158cb839Sthorpej case MII_POLLSTAT:
1418e65e831Smsaitoh /* If we're not polling our PHY instance, just return. */
142158cb839Sthorpej if (IFM_INST(ife->ifm_media) != sc->mii_inst)
1438e65e831Smsaitoh return 0;
144158cb839Sthorpej break;
145158cb839Sthorpej
146158cb839Sthorpej case MII_MEDIACHG:
147158cb839Sthorpej /*
148158cb839Sthorpej * If the media indicates a different PHY instance,
149158cb839Sthorpej * isolate ourselves.
150158cb839Sthorpej */
151158cb839Sthorpej if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
152a5cdd4b4Smsaitoh PHY_READ(sc, MII_BMCR, ®);
153158cb839Sthorpej PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
1548e65e831Smsaitoh return 0;
155158cb839Sthorpej }
156158cb839Sthorpej
1578e65e831Smsaitoh /* If the interface is not up, don't do anything. */
158158cb839Sthorpej if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
159158cb839Sthorpej break;
160158cb839Sthorpej
161158cb839Sthorpej mii_phy_setmedia(sc);
162158cb839Sthorpej break;
163158cb839Sthorpej
164158cb839Sthorpej case MII_TICK:
1658e65e831Smsaitoh /* If we're not currently selected, just return. */
166158cb839Sthorpej if (IFM_INST(ife->ifm_media) != sc->mii_inst)
1678e65e831Smsaitoh return 0;
168158cb839Sthorpej
169158cb839Sthorpej if (mii_phy_tick(sc) == EJUSTRETURN)
1708e65e831Smsaitoh return 0;
171158cb839Sthorpej break;
172158cb839Sthorpej
173158cb839Sthorpej case MII_DOWN:
174158cb839Sthorpej mii_phy_down(sc);
1758e65e831Smsaitoh return 0;
176158cb839Sthorpej }
177158cb839Sthorpej
178158cb839Sthorpej /* Update the media status. */
179158cb839Sthorpej mii_phy_status(sc);
180158cb839Sthorpej
181158cb839Sthorpej /* Callback if something changed. */
182158cb839Sthorpej mii_phy_update(sc, cmd);
1838e65e831Smsaitoh return 0;
184158cb839Sthorpej }
185158cb839Sthorpej
1861efb3da0Sthorpej static void
pnaphy_status(struct mii_softc * sc)18789893e42Sthorpej pnaphy_status(struct mii_softc *sc)
188158cb839Sthorpej {
189158cb839Sthorpej struct mii_data *mii = sc->mii_pdata;
190158cb839Sthorpej struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
191a5cdd4b4Smsaitoh uint16_t bmsr, bmcr;
192158cb839Sthorpej
193*7a9a30c5Sthorpej KASSERT(mii_locked(mii));
194*7a9a30c5Sthorpej
195158cb839Sthorpej mii->mii_media_status = IFM_AVALID;
196158cb839Sthorpej mii->mii_media_active = IFM_ETHER;
197158cb839Sthorpej
198a5cdd4b4Smsaitoh PHY_READ(sc, MII_BMSR, &bmsr);
199a5cdd4b4Smsaitoh PHY_READ(sc, MII_BMSR, &bmsr);
200158cb839Sthorpej
201158cb839Sthorpej if (bmsr & BMSR_LINK)
202158cb839Sthorpej mii->mii_media_status |= IFM_ACTIVE;
203158cb839Sthorpej
204a5cdd4b4Smsaitoh PHY_READ(sc, MII_BMCR, &bmcr);
205158cb839Sthorpej if (bmcr & BMCR_ISO) {
206158cb839Sthorpej mii->mii_media_active |= IFM_NONE;
207158cb839Sthorpej mii->mii_media_status = 0;
208158cb839Sthorpej return;
209158cb839Sthorpej }
210158cb839Sthorpej
211158cb839Sthorpej if (bmcr & BMCR_LOOP)
212158cb839Sthorpej mii->mii_media_active |= IFM_LOOP;
213158cb839Sthorpej
214158cb839Sthorpej /*
215158cb839Sthorpej * On HomePNA PHYs, the current media is always the selected
216158cb839Sthorpej * media.
217158cb839Sthorpej *
218158cb839Sthorpej * XXX May not be the case w/ HomePNA 2.
219158cb839Sthorpej */
220158cb839Sthorpej mii->mii_media_active = ife->ifm_media;
221158cb839Sthorpej }
222