On Wed, Jun 27, 2018 at 04:42:22PM +0800, Kevin Lo wrote:
>
> Hi,
>
> The diff below sets SMSC_MII_BUSY bit, which is necessary for PHY to
> acknowledge a read/write request; from FreeBSD r333096.
> While here, mask off the PHY address and register.
>
> Tested on rpi3.
>
> # dmesg |grep smsc
> smsc0 at uhub1 port 1 configuration 1 interface 0 "Standard Microsystems
> SMSC9512/14" rev 2.00/2.00 addr 3
> smsc0: address b8:27:eb:b0:32:5d
> ukphy0 at smsc0 phy 1: Generic IEEE 802.3u media interface, rev. 3: OUI
> 0x0001f0, model 0x000c
>
Anyone? It also matches Linux commit 80928805babfd97b6f1721dd942a55dd2e7813ea.
>
> Index: sys/dev/usb/if_smsc.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/if_smsc.c,v
> retrieving revision 1.31
> diff -u -p -u -p -r1.31 if_smsc.c
> --- sys/dev/usb/if_smsc.c 29 Jul 2017 17:24:04 -0000 1.31
> +++ sys/dev/usb/if_smsc.c 27 Jun 2018 08:37:34 -0000
> @@ -283,7 +283,6 @@ int
> smsc_miibus_readreg(struct device *dev, int phy, int reg)
> {
> struct smsc_softc *sc = (struct smsc_softc *)dev;
> - uint32_t addr;
> uint32_t val = 0;
>
> smsc_lock_mii(sc);
> @@ -292,8 +291,8 @@ smsc_miibus_readreg(struct device *dev,
> goto done;
> }
>
> - addr = (phy << 11) | (reg << 6) | SMSC_MII_READ;
> - smsc_write_reg(sc, SMSC_MII_ADDR, addr);
> + smsc_write_reg(sc, SMSC_MII_ADDR, SMSC_MII_READ | SMSC_MII_BUSY |
> + SMSC_MII_PHY_ADDR(phy) | SMSC_MII_REG_ADDR(reg));
>
> if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0)
> smsc_warn_printf(sc, "MII read timeout\n");
> @@ -309,7 +308,6 @@ void
> smsc_miibus_writereg(struct device *dev, int phy, int reg, int val)
> {
> struct smsc_softc *sc = (struct smsc_softc *)dev;
> - uint32_t addr;
>
> if (sc->sc_phyno != phy)
> return;
> @@ -323,8 +321,9 @@ smsc_miibus_writereg(struct device *dev,
>
> smsc_write_reg(sc, SMSC_MII_DATA, val);
>
> - addr = (phy << 11) | (reg << 6) | SMSC_MII_WRITE;
> - smsc_write_reg(sc, SMSC_MII_ADDR, addr);
> + smsc_write_reg(sc, SMSC_MII_ADDR, SMSC_MII_WRITE | SMSC_MII_BUSY |
> + SMSC_MII_PHY_ADDR(phy) | SMSC_MII_REG_ADDR(reg));
> +
> smsc_unlock_mii(sc);
>
> if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0)
> Index: sys/dev/usb/if_smscreg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/if_smscreg.h,v
> retrieving revision 1.5
> diff -u -p -u -p -r1.5 if_smscreg.h
> --- sys/dev/usb/if_smscreg.h 18 Jun 2015 09:28:54 -0000 1.5
> +++ sys/dev/usb/if_smscreg.h 27 Jun 2018 08:37:35 -0000
> @@ -215,9 +215,17 @@
> #define SMSC_INTR_GPIOS 0x000007FFUL
>
> /* Phy MII interface register */
> +#define SMSC_MII_PHY_ADDR_MASK 0x0000F800
> +#define SMSC_MII_PHY_ADDR_SHIFT 11
> +#define SMSC_MII_REG_ADDR_MASK 0x000007C0
> +#define SMSC_MII_REG_ADDR_SHIFT 6
> #define SMSC_MII_WRITE (0x1UL << 1)
> #define SMSC_MII_READ (0x0UL << 1)
> #define SMSC_MII_BUSY (0x1UL << 0)
> +#define SMSC_MII_REG_ADDR(x) \
> + (((x) << SMSC_MII_REG_ADDR_SHIFT ) & SMSC_MII_REG_ADDR_MASK)
> +#define SMSC_MII_PHY_ADDR(x) \
> + (((x) << SMSC_MII_PHY_ADDR_SHIFT) & SMSC_MII_PHY_ADDR_MASK)
>
> /* H/W checksum register */
> #define SMSC_COE_CTRL_TX_EN (0x1UL << 16) /* Tx H/W csum enable */
>
>