tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

(Ab?)use of MII



Hi,

so I've got NetBSD running on my Banana Pi BPi-R1.

With this board, the gigabit net interface on the processor chip is
connected via mii to a switch chip (BCM 53125). The 5 external ports
of this chip all have their own phys and are brought out for external
connection.

With an unmodified BPI kernel, the mii attach code finds all of those
phys via the mii bus of the processor's ethernet interface and then
enables only one of those.  In order to allow for a more appropriate
handling of the configuration, I added a flag to the mii_flags, to be
set by a phy driver to indicate that it wants to be the only phy to be
matched during the mii bus scan.  The driver for the broadcom chip sets
this flag, and on attachment sets things up so that the box emulates
the processor ethernet interface being connected to an unmanaged switch.

Would this be an acceptable modification to the mii code?

For now, I'm ignoring the capabilities of the 53125's onboard processor
which can implement some managed switch options as well.

Note that while it was quite easy to obtain a datasheet for the 53125,
for some reason that datasheet lacks the description of the register
which needs to be set for reverse mii operation in order to be able
to transfer packets from the processor to the 53125 and back.  So I
had to steal the relevant definition from the linux driver.

Attached are the diffs to the tree needed for this plus the driver
for the 53125.

BTW, does anyone know why cvs -N doesn't handle the new file as one
would expect?

Ciao,
Wolfgang
-- 
Wolfgang%Solfrank.net@localhost				Wolfgang Solfrank
? sys/dev/mii/bswphy.c
Index: sys/arch/evbarm/conf/BPI
===================================================================
RCS file: /cvsroot/src/sys/arch/evbarm/conf/BPI,v
retrieving revision 1.13
diff -u -r1.13 BPI
--- sys/arch/evbarm/conf/BPI	23 Nov 2014 20:02:37 -0000	1.13
+++ sys/arch/evbarm/conf/BPI	4 Apr 2015 11:46:54 -0000
@@ -312,6 +312,7 @@
 
 midi*		at midibus?
 
+bswphy* 	at mii? phy ?
 rlphy*		at mii? phy ?
 rgephy* 	at mii? phy ?
 ukphy*		at mii? phy ?
Index: sys/dev/mii/files.mii
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/files.mii,v
retrieving revision 1.50
diff -u -r1.50 files.mii
--- sys/dev/mii/files.mii	15 Nov 2014 19:18:18 -0000	1.50
+++ sys/dev/mii/files.mii	4 Apr 2015 11:47:01 -0000
@@ -33,6 +33,10 @@
 attach	brgphy at mii
 file	dev/mii/brgphy.c			brgphy
 
+device	bswphy: mii_phy
+attach	bswphy at mii
+file	dev/mii/bswphy.c			bswphy
+
 device	tlphy: mii_phy
 attach	tlphy at mii
 file	dev/mii/tlphy.c				tlphy
Index: sys/dev/mii/mii.c
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/mii.c,v
retrieving revision 1.50
diff -u -r1.50 mii.c
--- sys/dev/mii/mii.c	4 Dec 2009 22:37:35 -0000	1.50
+++ sys/dev/mii/mii.c	4 Apr 2015 11:47:01 -0000
@@ -145,6 +145,11 @@
 			LIST_INSERT_HEAD(&mii->mii_phys, child, mii_list);
 			child->mii_offset = offset;
 			mii->mii_instance++;
+			if (child->mii_flags & MIIF_SINGLE) {
+				if (LIST_NEXT(child, mii_list))
+					panic("mii_attach: multiple PHYs with MIIF_SINGLE");
+				break;
+			}
 		}
 		offset++;
 	}
Index: sys/dev/mii/miidevs
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/miidevs,v
retrieving revision 1.122
diff -u -r1.122 miidevs
--- sys/dev/mii/miidevs	9 Nov 2014 17:53:37 -0000	1.122
+++ sys/dev/mii/miidevs	4 Apr 2015 11:47:01 -0000
@@ -189,6 +189,7 @@
 model BROADCOM3 BCM5717C	0x0020 BCM5717C 1000BASE-T media interface
 model BROADCOM3 BCM5719C	0x0022 BCM5719C 1000BASE-T media interface
 model BROADCOM3 BCM57765	0x0024 BCM57765 1000BASE-T media interface
+model BROADCOM3 BCM53125	0x0032 BCM53125 1000BASE-T integrated PHY
 model BROADCOM3 BCM5720C	0x0036 BCM5720C 1000BASE-T media interface
 model xxBROADCOM_ALT1 BCM5906	0x0004 BCM5906 10/100baseTX media interface
  
Index: sys/dev/mii/miidevs.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/miidevs.h,v
retrieving revision 1.125
diff -u -r1.125 miidevs.h
--- sys/dev/mii/miidevs.h	9 Nov 2014 18:40:19 -0000	1.125
+++ sys/dev/mii/miidevs.h	4 Apr 2015 11:47:01 -0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: miidevs.h,v 1.125 2014/11/09 18:40:19 riz Exp $	*/
+/*	$NetBSD$	*/
 
 /*
  * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -257,6 +257,8 @@
 #define	MII_STR_BROADCOM3_BCM5719C	"BCM5719C 1000BASE-T media interface"
 #define	MII_MODEL_BROADCOM3_BCM57765	0x0024
 #define	MII_STR_BROADCOM3_BCM57765	"BCM57765 1000BASE-T media interface"
+#define	MII_MODEL_BROADCOM3_BCM53125	0x0032
+#define	MII_STR_BROADCOM3_BCM53125	"BCM53125 1000BASE-T integrated PHY"
 #define	MII_MODEL_BROADCOM3_BCM5720C	0x0036
 #define	MII_STR_BROADCOM3_BCM5720C	"BCM5720C 1000BASE-T media interface"
 #define	MII_MODEL_xxBROADCOM_ALT1_BCM5906	0x0004
Index: sys/dev/mii/miidevs_data.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/miidevs_data.h,v
retrieving revision 1.113
diff -u -r1.113 miidevs_data.h
--- sys/dev/mii/miidevs_data.h	9 Nov 2014 17:54:02 -0000	1.113
+++ sys/dev/mii/miidevs_data.h	4 Apr 2015 11:47:01 -0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: miidevs_data.h,v 1.113 2014/11/09 17:54:02 nonaka Exp $	*/
+/*	$NetBSD$	*/
 
 /*
  * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -98,6 +98,7 @@
  { MII_OUI_BROADCOM3, MII_MODEL_BROADCOM3_BCM5717C, MII_STR_BROADCOM3_BCM5717C },
  { MII_OUI_BROADCOM3, MII_MODEL_BROADCOM3_BCM5719C, MII_STR_BROADCOM3_BCM5719C },
  { MII_OUI_BROADCOM3, MII_MODEL_BROADCOM3_BCM57765, MII_STR_BROADCOM3_BCM57765 },
+ { MII_OUI_BROADCOM3, MII_MODEL_BROADCOM3_BCM53125, MII_STR_BROADCOM3_BCM53125 },
  { MII_OUI_BROADCOM3, MII_MODEL_BROADCOM3_BCM5720C, MII_STR_BROADCOM3_BCM5720C },
  { MII_OUI_xxBROADCOM_ALT1, MII_MODEL_xxBROADCOM_ALT1_BCM5906, MII_STR_xxBROADCOM_ALT1_BCM5906 },
  { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201, MII_STR_CICADA_CS8201 },
Index: sys/dev/mii/miivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/miivar.h,v
retrieving revision 1.62
diff -u -r1.62 miivar.h
--- sys/dev/mii/miivar.h	28 May 2014 09:49:55 -0000	1.62
+++ sys/dev/mii/miivar.h	4 Apr 2015 11:47:01 -0000
@@ -154,6 +154,7 @@
 #define	MIIF_DOPAUSE	0x0100		/* advertise PAUSE capability */
 #define	MIIF_IS_HPNA	0x0200		/* is a HomePNA device */
 #define	MIIF_FORCEANEG	0x0400		/* force auto-negotiation */
+#define	MIIF_SINGLE	0x8000		/* Known to be the only PHY here */
 
 #define	MIIF_INHERIT_MASK	(MIIF_NOISOLATE|MIIF_NOLOOP|MIIF_AUTOTSLEEP)
 
/*	$NetBSD	*/

/*-
 * Copyright (c) 2015 Wolfgang Solfrank.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*-
 * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center, and by Frank van der Linden.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1997 Manuel Bouyer.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Driver for BCM53125 switch PHY.
 * We pretend to be connected to an unmanaged switch via an
 * unchangeable 1000T-FDX interface.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD	$");

#include "opt_mii.h"

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/socket.h>
#include <sys/errno.h>

#include <net/if.h>
#include <net/if_media.h>

#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include <dev/mii/miidevs.h>

static int	bswphymatch(device_t, cfdata_t, void *);
static void	bswphyattach(device_t, device_t, void *);

CFATTACH_DECL3_NEW(bswphy, sizeof(struct mii_softc),
    bswphymatch, bswphyattach, mii_phy_detach, mii_phy_activate, NULL, NULL,
    DVF_DETACH_SHUTDOWN);

static int	bswphy_service(struct mii_softc *, struct mii_data *, int);
static void	bswphy_status(struct mii_softc *);
static void	bswphy_reset(struct mii_softc *);

static const struct mii_phy_funcs bswphy_funcs = {
	bswphy_service, bswphy_status, bswphy_reset,
};

/* Access any PHY on the 53125. */
#define BSWPHY_READ(p, phy, r) \
        ((uint64_t)(*(p)->mii_pdata->mii_readreg)(device_parent((p)->mii_dev), \
		(phy), (r)))
#define BSWPHY_WRITE(p, phy, r, v) \
        (*(p)->mii_pdata->mii_writereg)(device_parent((p)->mii_dev), \
		(phy), (r), (v))

#define	PSD_PHY		30		/* Pseudo-PHY within 53125 */
#define	PSD_PG		16		/* Page register */
#define		PSD_PAGE(pg)	\
	(((pg) << 8) | 1)
#define	PSD_ADDR	17		/* Register address */
#define		PSD_OP		3	/* Type of operation */
#define		PSD_READ(reg) \
	(((reg) << 8) | 2)
#define		PSD_WRITE(reg) \
	(((reg) << 8) | 1)
#define	PSD_0_15	24		/* Bits 0:15 */
#define	PSD_16_31	25		/* Bits 16:31 */
#define	PSD_32_47	26		/* Bits 32:47 */
#define	PSD_48_63	27		/* Bits 48:63 */

#define	PSD_CTL_PG	0		/* Control Registers */
/*
 * Note that the following register is not described in the
 * BCM53125 manual.  The definitions used here are extracted
 * from the Linux driver.
 */
#define		PSD_CTL_POVER	0x0e	/* Port override register */
#define			PSD_POVER_LINK	0x01
#define			PSD_POVER_USE	0x80
#define		PSD_CTL_RST	0x79	/* Software Reset Control Register */
#define			PSD_SW_RST	0x80
#define			PSD_EN_SW_RST	0x10

#define	PSD_MGMI_PG	2		/* Managament/Mirroring Registers */
#define		PSD_DEVID	0x30	/* Device ID Register */
#define			DEV_BCM53125	0x53125

static uint64_t	bswphy_pseudoread(struct mii_softc *, int, int);
static void	bswphy_pseudowrite(struct mii_softc *, int, int, uint64_t);

static const struct mii_phydesc bswphys[] = {
	{ MII_OUI_BROADCOM3,	MII_MODEL_BROADCOM3_BCM53125,
	  MII_STR_BROADCOM3_BCM53125 },
	{ 0,			0,
	  NULL }
};

static int
bswphymatch(device_t parent, cfdata_t match, void *aux)
{
	if (mii_phy_match(aux, bswphys) != NULL)
		/*
		 * Should we check the device id from the pseudo phy here?
		 */
		return 10;

	return 0;
}

static void
bswphyattach(device_t parent, device_t self, void *aux)
{
	struct mii_softc *sc = device_private(self);
	struct mii_attach_args *ma = aux;
	struct mii_data *mii = ma->mii_data;
	int oui = MII_OUI(ma->mii_id1, ma->mii_id2);
	int model = MII_MODEL(ma->mii_id2);
	int rev = MII_REV(ma->mii_id2);
	const char *descr;
	uint64_t devid, override;

	if ((descr = mii_get_descr(oui, model)) != NULL)
		aprint_normal(": %s (OUI 0x%06x, model 0x%04x), rev. %d\n",
		       descr, oui, model, rev);
	else
		aprint_normal(": OUI 0x%06x, model 0x%04x, rev. %d\n",
		       oui, model, rev);
	aprint_naive(": Media interface\n");

	sc->mii_dev = self;
	sc->mii_inst = mii->mii_instance;
	sc->mii_phy = ma->mii_phyno;	/* PSD_PHY? */
	sc->mii_funcs = &bswphy_funcs;
	sc->mii_pdata = mii;
	sc->mii_flags = (ma->mii_flags & ~MIIF_DOPAUSE)
		 | MIIF_NOISOLATE | MIIF_SINGLE;
	sc->mii_anegticks = MII_ANEGTICKS;

	/* Do a soft reset of the device to a known good state */
	bswphy_pseudowrite(sc, PSD_CTL_PG, PSD_CTL_RST,
		 PSD_SW_RST | PSD_EN_SW_RST);

	/* Check whether we are really a BCM54125 */
	devid = bswphy_pseudoread(sc, PSD_MGMI_PG, PSD_DEVID);
	if (devid != DEV_BCM53125)
		panic("bswphy: unknown device id %llx", devid);

	/*
	 * Enable reverse MII.
	 */
	override = bswphy_pseudoread(sc, PSD_CTL_PG, PSD_CTL_POVER)
		| PSD_POVER_LINK | PSD_POVER_USE;
	bswphy_pseudowrite(sc, PSD_CTL_PG, PSD_CTL_POVER, override);

	sc->mii_capabilities = BMSR_EXTSTAT | BMSR_MFPS
		| BMSR_ACOMP | BMSR_EXTCAP;
	sc->mii_extcapabilities = EXTSR_1000TFDX;
	aprint_normal_dev(self, "");
	mii_phy_add_media(sc);
	aprint_normal("\n");
}

static int
bswphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	switch (cmd) {
	case MII_POLLSTAT:
		break;
	case MII_MEDIACHG:
		break;
	case MII_TICK:
		sc->mii_ticks = 0;
		break;
	case MII_DOWN:
		mii_phy_down(sc);
		break;
	}

	mii_phy_status(sc);
	mii_phy_update(sc, cmd);

	return 0;
}

static void
bswphy_status(struct mii_softc *phy)
{
	struct mii_data *mii = phy->mii_pdata;

	/* For now, pretend to be connected vit 1000T Duplex */
	mii->mii_media_status = IFM_AVALID | IFM_ACTIVE;
	mii->mii_media_active = IFM_ETHER | IFM_1000_T | IFM_FDX;
}

static void
bswphy_reset(struct mii_softc *sc)
{
	/* Ignore */
}

static uint64_t
bswphy_pseudoread(struct mii_softc *phy, int page, int reg)
{
	uint64_t ret;

	BSWPHY_WRITE(phy, PSD_PHY, PSD_PG, PSD_PAGE(page));
	BSWPHY_WRITE(phy, PSD_PHY, PSD_ADDR, PSD_READ(reg));
	while (BSWPHY_READ(phy, PSD_PHY, PSD_ADDR) & PSD_OP);

	ret = BSWPHY_READ(phy, PSD_PHY, PSD_0_15) & 0xffff;
	ret |= (BSWPHY_READ(phy, PSD_PHY, PSD_16_31) & 0xffff) << 16;
	ret |= (BSWPHY_READ(phy, PSD_PHY, PSD_32_47) & 0xffff) << 32;
	ret |= (BSWPHY_READ(phy, PSD_PHY, PSD_48_63) & 0xffff) << 48;

	return ret;
}

static void
bswphy_pseudowrite(struct mii_softc *phy, int page, int reg, uint64_t val)
{
	BSWPHY_WRITE(phy, PSD_PHY, PSD_PG, PSD_PAGE(page));

	BSWPHY_WRITE(phy, PSD_PHY, PSD_0_15, val & 0xffff);
	BSWPHY_WRITE(phy, PSD_PHY, PSD_16_31, (val >> 16) & 0xffff);
	BSWPHY_WRITE(phy, PSD_PHY, PSD_32_47, (val >> 24) & 0xffff);
	BSWPHY_WRITE(phy, PSD_PHY, PSD_48_63, (val >> 32) & 0xffff);

	BSWPHY_WRITE(phy, PSD_PHY, PSD_ADDR, PSD_WRITE(reg));
	while (BSWPHY_READ(phy, PSD_PHY, PSD_ADDR) & PSD_OP);
}


Home | Main Index | Thread Index | Old Index