Revise MDIO driver code so that device instances can be attached
authorvisa <visa@openbsd.org>
Tue, 2 May 2017 13:26:49 +0000 (13:26 +0000)
committervisa <visa@openbsd.org>
Tue, 2 May 2017 13:26:49 +0000 (13:26 +0000)
using fdt. This lets the system utilize multiple MDIO controllers.

This patch enables all RJ45 Ethernet ports on EdgeRouter Pro.
The SFP module slots do not work yet.

OK kettenis@, jmatthew@

sys/arch/octeon/conf/GENERIC
sys/arch/octeon/conf/RAMDISK
sys/arch/octeon/conf/files.octeon
sys/arch/octeon/dev/cn30xxgmx.c
sys/arch/octeon/dev/cn30xxgmxvar.h
sys/arch/octeon/dev/cn30xxsmi.c
sys/arch/octeon/dev/cn30xxsmireg.h
sys/arch/octeon/dev/cn30xxsmivar.h
sys/arch/octeon/dev/if_cnmac.c

index cd80098..bf93324 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: GENERIC,v 1.30 2016/12/21 13:59:57 visa Exp $
+#      $OpenBSD: GENERIC,v 1.31 2017/05/02 13:26:49 visa Exp $
 #
 # For further information on compiling OpenBSD kernels, see the config(8)
 # man page.
@@ -51,6 +51,7 @@ pci*          at pcibus?
 ppb*           at pci?         # PCI-PCI bridges
 pci*           at ppb?
 
+cn30xxsmi*     at fdt?         # MDIO controller
 octmmc*                at fdt?         # MMC host controller
 sdmmc*         at octmmc?      # SD/MMC bus
 
index 8ec5666..4aed224 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: RAMDISK,v 1.28 2016/12/21 13:59:57 visa Exp $
+#      $OpenBSD: RAMDISK,v 1.29 2017/05/02 13:26:49 visa Exp $
 
 machine                octeon mips64
 maxusers       4
@@ -51,6 +51,7 @@ pci*          at pcibus?
 ppb*           at pci?
 pci*           at ppb?
 
+cn30xxsmi*     at fdt?         # MDIO controller
 octmmc*                at fdt?         # MMC host controller
 sdmmc*         at octmmc?      # SD/MMC bus
 
index d940fc4..813cab1 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.octeon,v 1.34 2017/04/24 13:54:28 visa Exp $
+#      $OpenBSD: files.octeon,v 1.35 2017/05/02 13:26:49 visa Exp $
 
 # Standard stanzas config(8) can't run without
 maxpartitions 16
@@ -68,7 +68,6 @@ file  arch/octeon/dev/cn30xxpip.c                     iobus
 file   arch/octeon/dev/cn30xxipd.c                     iobus
 file   arch/octeon/dev/cn30xxpko.c                     iobus
 file   arch/octeon/dev/cn30xxasx.c                     iobus
-file   arch/octeon/dev/cn30xxsmi.c                     iobus
 
 define fdt {[early = 0]}
 
@@ -103,6 +102,10 @@ device     octrng
 attach octrng at iobus
 file   arch/octeon/dev/octrng.c                        octrng
 
+device cn30xxsmi {}
+attach cn30xxsmi at fdt
+file   arch/octeon/dev/cn30xxsmi.c                     cn30xxsmi
+
 device cn30xxgmx {}
 attach cn30xxgmx at iobus
 file   arch/octeon/dev/cn30xxgmx.c                     cn30xxgmx
index 2d8d65f..af8dd1e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cn30xxgmx.c,v 1.33 2017/04/08 10:53:48 visa Exp $     */
+/*     $OpenBSD: cn30xxgmx.c,v 1.34 2017/05/02 13:26:49 visa Exp $     */
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
 #include <machine/octeonvar.h>
 
 #include <octeon/dev/iobusvar.h>
+#include <octeon/dev/cn30xxasxvar.h>
 #include <octeon/dev/cn30xxciureg.h>
 #include <octeon/dev/cn30xxgmxreg.h>
-#include <octeon/dev/cn30xxipdvar.h>
-#include <octeon/dev/cn30xxasxvar.h>
 #include <octeon/dev/cn30xxgmxvar.h>
+#include <octeon/dev/cn30xxipdvar.h>
+#include <octeon/dev/cn30xxpipvar.h>
+#include <octeon/dev/cn30xxsmivar.h>
 
 #define        dprintf(...)
 #define        OCTEON_ETH_KASSERT      KASSERT
@@ -176,63 +178,33 @@ cn30xxgmx_match(struct device *parent, void *match, void *aux)
 }
 
 int
-cn30xxgmx_port_phy_addr(int port)
+cn30xxgmx_get_phy_phandle(int port)
 {
-       static const int octeon_eth_phy_table[] = {
-               /* portwell cam-0100 */
-               0x02, 0x03, 0x22
-       };
        char name[64];
-       int phynode = 0;
-       int portnode = -1;
-       uint32_t phy = 0;
+       int node;
+       int phandle = 0;
 
        snprintf(name, sizeof(name),
            "/soc/pip@11800a0000000/interface@%x/ethernet@%x",
            port / 16, port % 16);
-       portnode = OF_finddevice(name);
-       if (portnode != -1) {
-               phy = OF_getpropint(portnode, "phy-handle", 0);
-               if (phy != 0)
-                       phynode = OF_getnodebyphandle(phy);
-               if (phynode != 0)
-                       return OF_getpropint(phynode, "reg", 0);
-       }
-
-       switch (octeon_boot_info->board_type) {
-       case BOARD_TYPE_UBIQUITI_E100:  /* port 0: 7, port 1: 6 */
-               if (port > 2)
-                       return -1;
-               return 7 - port;
-
-       case BOARD_TYPE_UBIQUITI_E200:
-               if (port >= 0 && port < 4)
-                       /* XXX RJ45/SFP combos use the second MDIO. */
-                       return port + 4;  /* GMX0: eth[4-7] */
-               else if (port >= 16 && port < 20)
-                       return port - 16; /* GMX1: eth[0-3] */
-               return -1;
-
-       case BOARD_TYPE_CN3010_EVB_HS5:
-               if (port >= nitems(octeon_eth_phy_table))
-                       return -1;
-               return octeon_eth_phy_table[port];
-
-       default:
-               return -1;
-       }
+       node = OF_finddevice(name);
+       if (node != - 1)
+               phandle = OF_getpropint(node, "phy-handle", 0);
+       return phandle;
 }
 
 void
 cn30xxgmx_attach(struct device *parent, struct device *self, void *aux)
 {
-       struct cn30xxgmx_softc *sc = (void *)self;
-       struct iobus_attach_args *aa = aux;
        struct cn30xxgmx_attach_args gmx_aa;
+       struct iobus_attach_args *aa = aux;
+       struct cn30xxgmx_port_softc *port_sc;
+       struct cn30xxgmx_softc *sc = (void *)self;
+       struct cn30xxsmi_softc *smi;
        int i;
        int phy_addr;
+       int port;
        int status;
-       struct cn30xxgmx_port_softc *port_sc;
 
        printf("\n");
 
@@ -254,14 +226,14 @@ cn30xxgmx_attach(struct device *parent, struct device *self, void *aux)
        }
 
        for (i = 0; i < sc->sc_nports; i++) {
-               phy_addr = cn30xxgmx_port_phy_addr(
-                   GMX_PORT_NUM(sc->sc_unitno, i));
-               if (phy_addr == -1)
+               port = GMX_PORT_NUM(sc->sc_unitno, i);
+               if (cn30xxsmi_get_phy(cn30xxgmx_get_phy_phandle(port), port,
+                   &smi, &phy_addr))
                        continue;
 
                port_sc = &sc->sc_ports[i];
                port_sc->sc_port_gmx = sc;
-               port_sc->sc_port_no = GMX_PORT_NUM(sc->sc_unitno, i);
+               port_sc->sc_port_no = port;
                port_sc->sc_port_type = sc->sc_port_types[i];
                port_sc->sc_port_ops = cn30xxgmx_port_ops[port_sc->sc_port_type];
                status = bus_space_map(sc->sc_regt,
@@ -302,6 +274,7 @@ cn30xxgmx_attach(struct device *parent, struct device *self, void *aux)
                gmx_aa.ga_gmx = sc;
                gmx_aa.ga_gmx_port = port_sc;
                gmx_aa.ga_phy_addr = phy_addr;
+               gmx_aa.ga_smi = smi;
 
                config_found(self, &gmx_aa, cn30xxgmx_print);
 
index 09f6423..14f0fc0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cn30xxgmxvar.h,v 1.6 2016/06/09 15:29:22 visa Exp $   */
+/*     $OpenBSD: cn30xxgmxvar.h,v 1.7 2017/05/02 13:26:49 visa Exp $   */
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -90,6 +90,7 @@ struct cn30xxgmx_attach_args {
        const char              *ga_name;
        int                     ga_portno;
        int                     ga_port_type;
+       struct cn30xxsmi_softc  *ga_smi;
        int                     ga_phy_addr;
 
        struct cn30xxgmx_softc *ga_gmx;
index a224411..9b128cc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cn30xxsmi.c,v 1.3 2014/08/11 18:08:17 miod Exp $      */
+/*     $OpenBSD: cn30xxsmi.c,v 1.4 2017/05/02 13:26:49 visa Exp $      */
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
+#include <sys/stdint.h>
 
+#include <dev/ofw/fdt.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/fdt.h>
 #include <machine/octeonvar.h>
 
-#include <octeon/dev/cn30xxfpavar.h>
-#include <octeon/dev/cn30xxpipreg.h>
 #include <octeon/dev/cn30xxsmireg.h>
 #include <octeon/dev/cn30xxsmivar.h>
 
+int    cn30xxsmi_match(struct device *, void *, void *);
+void   cn30xxsmi_attach(struct device *, struct device *, void *);
+
 void   cn30xxsmi_enable(struct cn30xxsmi_softc *);
 
-/* XXX */
+const struct cfattach cn30xxsmi_ca = {
+       sizeof(struct cn30xxsmi_softc), cn30xxsmi_match, cn30xxsmi_attach
+};
+
+struct cfdriver cn30xxsmi_cd = {
+       NULL, "cn30xxsmi", DV_DULL
+};
+
+static SLIST_HEAD(, cn30xxsmi_softc) smi_list =
+    SLIST_HEAD_INITIALIZER(smi_list);
+
+#define        _SMI_RD8(sc, off) \
+       bus_space_read_8((sc)->sc_regt, (sc)->sc_regh, (off))
+#define        _SMI_WR8(sc, off, v) \
+       bus_space_write_8((sc)->sc_regt, (sc)->sc_regh, (off), (v))
+
+int
+cn30xxsmi_match(struct device *parent, void *match, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+
+       return OF_is_compatible(faa->fa_node, "cavium,octeon-3860-mdio");
+}
+
 void
-cn30xxsmi_init(struct cn30xxsmi_attach_args *aa,
-    struct cn30xxsmi_softc **rsc)
+cn30xxsmi_attach(struct device *parent, struct device *self, void *aux)
 {
-       struct cn30xxsmi_softc *sc;
-       int status;
+       struct fdt_attach_args *faa = aux;
+       struct cn30xxsmi_softc *sc = (struct cn30xxsmi_softc *)self;
 
-       sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
-       if (sc == NULL)
-               panic("can't allocate memory: %s", __func__);
+       if (faa->fa_nreg != 1)
+               return;
 
-       sc->sc_port = aa->aa_port;
-       sc->sc_regt = aa->aa_regt;
+       sc->sc_node = faa->fa_node;
+       sc->sc_regt = faa->fa_iot;
 
-       status = bus_space_map(sc->sc_regt, SMI_BASE, SMI_SIZE, 0,
-           &sc->sc_regh);
-       if (status != 0)
-               panic("can't map %s space", "smi register");
+       if (bus_space_map(sc->sc_regt, faa->fa_reg[0].addr, faa->fa_reg[0].size,
+           0, &sc->sc_regh)) {
+               printf(": could not map registers\n");
+               return;
+       }
 
-       cn30xxsmi_enable(sc);
+       SLIST_INSERT_HEAD(&smi_list, sc, sc_link);
 
-       *rsc = sc;
-}
+       printf("\n");
 
-#define        _SMI_RD8(sc, off) \
-       bus_space_read_8((sc)->sc_regt, (sc)->sc_regh, (off))
-#define        _SMI_WR8(sc, off, v) \
-       bus_space_write_8((sc)->sc_regt, (sc)->sc_regh, (off), (v))
+       _SMI_WR8(sc, SMI_CLK_OFFSET, 0x1464);
+       _SMI_WR8(sc, SMI_EN_OFFSET, SMI_EN_EN);
+}
 
 int
 cn30xxsmi_read(struct cn30xxsmi_softc *sc, int phy_addr, int reg)
@@ -123,15 +147,56 @@ cn30xxsmi_write(struct cn30xxsmi_softc *sc, int phy_addr, int reg, int value)
        }
 }
 
-void
-cn30xxsmi_enable(struct cn30xxsmi_softc *sc)
+int
+cn30xxsmi_get_phy(int phandle, int port, struct cn30xxsmi_softc **psmi,
+    int *preg)
 {
-       _SMI_WR8(sc, SMI_EN_OFFSET, SMI_EN_EN);
-}
+       /* PHY addresses for Portwell CAM-0100 */
+       static const int cam0100_phys[] = {
+               0x02, 0x03, 0x22
+       };
+
+       struct cn30xxsmi_softc *smi;
+       int parent, phynode;
+       int reg;
+
+       if (phandle != 0) {
+               phynode = OF_getnodebyphandle(phandle);
+               if (phynode == 0)
+                       return ENOENT;
+               reg = OF_getpropint(phynode, "reg", UINT32_MAX);
+               if (reg == UINT32_MAX)
+                       return ENOENT;
+
+               parent = OF_parent(phynode);
+               SLIST_FOREACH(smi, &smi_list, sc_link) {
+                       if (smi->sc_node == parent)
+                               goto found;
+               }
+               return ENOENT;
+       } else {
+               smi = SLIST_FIRST(&smi_list);
+               if (smi == NULL)
+                       return ENOENT;
+
+               switch (octeon_boot_info->board_type) {
+               case BOARD_TYPE_UBIQUITI_E100:
+                       if (port > 2)
+                               return ENOENT;
+                       reg = 7 - port;
+                       break;
+               case BOARD_TYPE_CN3010_EVB_HS5:
+                       if (port >= nitems(cam0100_phys))
+                               return ENOENT;
+                       reg = cam0100_phys[port];
+                       break;
+               default:
+                       return ENOENT;
+               }
+       }
 
-void
-cn30xxsmi_set_clock(struct cn30xxsmi_softc *sc, uint64_t clock)
-{
-       _SMI_WR8(sc, SMI_CLK_OFFSET, clock);
+found:
+       *psmi = smi;
+       *preg = reg;
+       return 0;
 }
-
index a7b488d..ed863ce 100644 (file)
@@ -3,7 +3,7 @@
  * DONT EDIT THIS FILE
  */
 
-/*     $OpenBSD: cn30xxsmireg.h,v 1.1 2011/06/16 11:22:30 syuu Exp $   */
+/*     $OpenBSD: cn30xxsmireg.h,v 1.2 2017/05/02 13:26:49 visa Exp $   */
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
 #ifndef _CN30XXSMIREG_H_
 #define _CN30XXSMIREG_H_
 
-#define        SMI_CMD                                 0x0001180000001800ULL
-#define        SMI_WR_DAT                              0x0001180000001808ULL
-#define        SMI_RD_DAT                              0x0001180000001810ULL
-#define        SMI_CLK                                 0x0001180000001818ULL
-#define        SMI_EN                                  0x0001180000001820ULL
-
 #define        SMI_CMD_OFFSET                          0x00ULL
 #define        SMI_WR_DAT_OFFSET                       0x08ULL
 #define        SMI_RD_DAT_OFFSET                       0x10ULL
 #define        SMI_CLK_OFFSET                          0x18ULL
 #define        SMI_EN_OFFSET                           0x20ULL
 
-#define SMI_BASE                               0x0001180000001800ULL
-#define SMI_SIZE                               0x028ULL
-
 /* SMI CMD */
 #define SMI_CMD_63_17                  0xfffffffffffe0000ULL
 #define SMI_CMD_PHY_OP                 0x0000000000010000ULL
index d89ecac..54c61ab 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cn30xxsmivar.h,v 1.2 2011/06/24 02:13:23 yasuoka Exp $        */
+/*     $OpenBSD: cn30xxsmivar.h,v 1.3 2017/05/02 13:26:49 visa Exp $   */
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
 #ifndef _CN30XXSMIVAR_H_
 #define _CN30XXSMIVAR_H_
 
-/* XXX */
 struct cn30xxsmi_softc {
-       int                     sc_port;
+       struct device           sc_dev;
+       int                     sc_node;
+
        bus_space_tag_t         sc_regt;
        bus_space_handle_t      sc_regh;
-};
 
-/* XXX */
-struct cn30xxsmi_attach_args {
-       int                     aa_port;
-       bus_space_tag_t         aa_regt;
+       SLIST_ENTRY(cn30xxsmi_softc) sc_link;
 };
 
-void                   cn30xxsmi_init(struct cn30xxsmi_attach_args *,
-                           struct cn30xxsmi_softc **);
-int                    cn30xxsmi_read(struct cn30xxsmi_softc *, int, int);
-void                   cn30xxsmi_write(struct cn30xxsmi_softc *, int, int, int);
-void                   cn30xxsmi_set_clock(struct cn30xxsmi_softc *, uint64_t);
+int    cn30xxsmi_read(struct cn30xxsmi_softc *, int, int);
+void   cn30xxsmi_write(struct cn30xxsmi_softc *, int, int, int);
+
+int    cn30xxsmi_get_phy(int, int, struct cn30xxsmi_softc **, int *);
 
 #endif
index 040af8c..79ba10c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_cnmac.c,v 1.63 2017/04/02 15:25:05 visa Exp $      */
+/*     $OpenBSD: if_cnmac.c,v 1.64 2017/05/02 13:26:49 visa Exp $      */
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -254,6 +254,7 @@ octeon_eth_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_port_type = ga->ga_port_type;
        sc->sc_gmx = ga->ga_gmx;
        sc->sc_gmx_port = ga->ga_gmx_port;
+       sc->sc_smi = ga->ga_smi;
        sc->sc_phy_addr = ga->ga_phy_addr;
 
        sc->sc_init_flag = 0;
@@ -287,7 +288,6 @@ octeon_eth_attach(struct device *parent, struct device *self, void *aux)
        octeon_eth_pip_init(sc);
        octeon_eth_ipd_init(sc);
        octeon_eth_pko_init(sc);
-       octeon_eth_smi_init(sc);
 
        sc->sc_gmx_port->sc_ipd = sc->sc_ipd;
        sc->sc_gmx_port->sc_port_mii = &sc->sc_mii;
@@ -372,17 +372,6 @@ octeon_eth_pko_init(struct octeon_eth_softc *sc)
        cn30xxpko_init(&pko_aa, &sc->sc_pko);
 }
 
-void
-octeon_eth_smi_init(struct octeon_eth_softc *sc)
-{
-       struct cn30xxsmi_attach_args smi_aa;
-
-       smi_aa.aa_port = sc->sc_port;
-       smi_aa.aa_regt = sc->sc_regt;
-       cn30xxsmi_init(&smi_aa, &sc->sc_smi);
-       cn30xxsmi_set_clock(sc->sc_smi, 0x1464ULL); /* XXX */
-}
-
 /* ---- XXX */
 
 void