From: visa Date: Tue, 2 May 2017 13:26:49 +0000 (+0000) Subject: Revise MDIO driver code so that device instances can be attached X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=ae667e95e2c8da10fc7cf5b4e4725ede3b148c31;p=openbsd Revise MDIO driver code so that device instances can be attached 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@ --- diff --git a/sys/arch/octeon/conf/GENERIC b/sys/arch/octeon/conf/GENERIC index cd80098b4ab..bf93324dcfd 100644 --- a/sys/arch/octeon/conf/GENERIC +++ b/sys/arch/octeon/conf/GENERIC @@ -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 diff --git a/sys/arch/octeon/conf/RAMDISK b/sys/arch/octeon/conf/RAMDISK index 8ec5666860b..4aed22448e0 100644 --- a/sys/arch/octeon/conf/RAMDISK +++ b/sys/arch/octeon/conf/RAMDISK @@ -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 diff --git a/sys/arch/octeon/conf/files.octeon b/sys/arch/octeon/conf/files.octeon index d940fc4e71d..813cab1e7b0 100644 --- a/sys/arch/octeon/conf/files.octeon +++ b/sys/arch/octeon/conf/files.octeon @@ -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 diff --git a/sys/arch/octeon/dev/cn30xxgmx.c b/sys/arch/octeon/dev/cn30xxgmx.c index 2d8d65fea27..af8dd1eb71a 100644 --- a/sys/arch/octeon/dev/cn30xxgmx.c +++ b/sys/arch/octeon/dev/cn30xxgmx.c @@ -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. @@ -40,11 +40,13 @@ #include #include +#include #include #include -#include -#include #include +#include +#include +#include #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); diff --git a/sys/arch/octeon/dev/cn30xxgmxvar.h b/sys/arch/octeon/dev/cn30xxgmxvar.h index 09f6423fb95..14f0fc02a72 100644 --- a/sys/arch/octeon/dev/cn30xxgmxvar.h +++ b/sys/arch/octeon/dev/cn30xxgmxvar.h @@ -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; diff --git a/sys/arch/octeon/dev/cn30xxsmi.c b/sys/arch/octeon/dev/cn30xxsmi.c index a2244113aca..9b128cc015a 100644 --- a/sys/arch/octeon/dev/cn30xxsmi.c +++ b/sys/arch/octeon/dev/cn30xxsmi.c @@ -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. @@ -28,47 +28,71 @@ #include #include -#include -#include +#include +#include +#include + +#include #include -#include -#include #include #include +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; } - diff --git a/sys/arch/octeon/dev/cn30xxsmireg.h b/sys/arch/octeon/dev/cn30xxsmireg.h index a7b488d9a22..ed863ce04ac 100644 --- a/sys/arch/octeon/dev/cn30xxsmireg.h +++ b/sys/arch/octeon/dev/cn30xxsmireg.h @@ -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. @@ -40,21 +40,12 @@ #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 diff --git a/sys/arch/octeon/dev/cn30xxsmivar.h b/sys/arch/octeon/dev/cn30xxsmivar.h index d89ecac0d15..54c61abf582 100644 --- a/sys/arch/octeon/dev/cn30xxsmivar.h +++ b/sys/arch/octeon/dev/cn30xxsmivar.h @@ -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. @@ -29,23 +29,19 @@ #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 diff --git a/sys/arch/octeon/dev/if_cnmac.c b/sys/arch/octeon/dev/if_cnmac.c index 040af8c7be2..79ba10c7600 100644 --- a/sys/arch/octeon/dev/if_cnmac.c +++ b/sys/arch/octeon/dev/if_cnmac.c @@ -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