From b33a3dc4add359db25d751b8bdb5ea1041748fc7 Mon Sep 17 00:00:00 2001 From: ian Date: Mon, 11 Sep 2017 01:59:24 +0000 Subject: MFC r319814, r319815, r319818: Add a set of constants describing the ways a MAC and PHY can be connected. While the initial need for this is to help support phy drivers which are configured with FDT data, there is nothing devicetree-specific about the concept or the names, so they are available for use even on non-FDT systems. Add some utility functions to help a PHY driver on an FDT-configured system retrieve its config data from the fdt data. Convert if_ffec from local code and constants for mac<->phy connection type to new common fdt helper code. --- sys/conf/files | 1 + sys/dev/ffec/if_ffec.c | 38 ++++------ sys/dev/mii/mii_fdt.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/mii/mii_fdt.h | 75 +++++++++++++++++++ sys/dev/mii/miivar.h | 36 +++++++++ 5 files changed, 325 insertions(+), 25 deletions(-) create mode 100644 sys/dev/mii/mii_fdt.c create mode 100644 sys/dev/mii/mii_fdt.h diff --git a/sys/conf/files b/sys/conf/files index 2338355..8a9ed9d 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2166,6 +2166,7 @@ dev/mii/micphy.c optional miibus fdt | micphy fdt dev/mii/mii.c optional miibus | mii dev/mii/mii_bitbang.c optional miibus | mii_bitbang dev/mii/mii_physubr.c optional miibus | mii +dev/mii/mii_fdt.c optional miibus fdt | mii fdt dev/mii/miibus_if.m optional miibus | mii dev/mii/mlphy.c optional miibus | mlphy dev/mii/nsgphy.c optional miibus | nsgphy diff --git a/sys/dev/ffec/if_ffec.c b/sys/dev/ffec/if_ffec.c index 345cb71..e18e3f1 100644 --- a/sys/dev/ffec/if_ffec.c +++ b/sys/dev/ffec/if_ffec.c @@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include "miibus_if.h" /* @@ -135,13 +136,6 @@ struct ffec_bufmap { bus_dmamap_t map; }; -enum { - PHY_CONN_UNKNOWN, - PHY_CONN_MII, - PHY_CONN_RMII, - PHY_CONN_RGMII -}; - struct ffec_softc { device_t dev; device_t miibus; @@ -153,7 +147,7 @@ struct ffec_softc { struct resource *mem_res; void * intr_cookie; struct callout ffec_callout; - uint8_t phy_conn_type; + mii_contype_t phy_conn_type; uint8_t fectype; boolean_t link_is_up; boolean_t is_attached; @@ -262,10 +256,10 @@ ffec_miigasket_setup(struct ffec_softc *sc) switch (sc->phy_conn_type) { - case PHY_CONN_MII: + case MII_CONTYPE_MII: ifmode = 0; break; - case PHY_CONN_RMII: + case MII_CONTYPE_RMII: ifmode = FEC_MIIGSK_CFGR_IF_MODE_RMII; break; default: @@ -377,14 +371,17 @@ ffec_miibus_statchg(device_t dev) rcr |= FEC_RCR_MII_MODE; /* Must always be on even for R[G]MII. */ switch (sc->phy_conn_type) { - case PHY_CONN_MII: - break; - case PHY_CONN_RMII: + case MII_CONTYPE_RMII: rcr |= FEC_RCR_RMII_MODE; break; - case PHY_CONN_RGMII: + case MII_CONTYPE_RGMII: + case MII_CONTYPE_RGMII_ID: + case MII_CONTYPE_RGMII_RXID: + case MII_CONTYPE_RGMII_TXID: rcr |= FEC_RCR_RGMII_EN; break; + default: + break; } switch (IFM_SUBTYPE(mii->mii_media_active)) { @@ -1440,7 +1437,6 @@ ffec_attach(device_t dev) phandle_t ofw_node; int error, phynum, rid; uint8_t eaddr[ETHER_ADDR_LEN]; - char phy_conn_name[32]; uint32_t idx, mscr; sc = device_get_softc(dev); @@ -1463,16 +1459,8 @@ ffec_attach(device_t dev) error = ENXIO; goto out; } - if (OF_searchprop(ofw_node, "phy-mode", - phy_conn_name, sizeof(phy_conn_name)) != -1) { - if (strcasecmp(phy_conn_name, "mii") == 0) - sc->phy_conn_type = PHY_CONN_MII; - else if (strcasecmp(phy_conn_name, "rmii") == 0) - sc->phy_conn_type = PHY_CONN_RMII; - else if (strcasecmp(phy_conn_name, "rgmii") == 0) - sc->phy_conn_type = PHY_CONN_RGMII; - } - if (sc->phy_conn_type == PHY_CONN_UNKNOWN) { + sc->phy_conn_type = mii_fdt_get_contype(ofw_node); + if (sc->phy_conn_type == MII_CONTYPE_UNKNOWN) { device_printf(sc->dev, "No valid 'phy-mode' " "property found in FDT data for device.\n"); error = ENOATTR; diff --git a/sys/dev/mii/mii_fdt.c b/sys/dev/mii/mii_fdt.c new file mode 100644 index 0000000..009a523 --- /dev/null +++ b/sys/dev/mii/mii_fdt.c @@ -0,0 +1,200 @@ +/*- + * Copyright (c) 2017 Ian Lepore + * All rights reserved. + * + * Development sponsored by Microsemi, Inc. + * + * 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 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 AUTHOR 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Utility functions for PHY drivers on systems configured using FDT data. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +/* + * Table to translate MII_CONTYPE_xxxx constants to/from devicetree strings. + * We explicitly associate the enum values with the strings in a table to avoid + * relying on this list being sorted in the same order as the enum in miivar.h, + * and to avoid problems if the enum gains new types that aren't in the FDT + * data. However, the "unknown" entry must be first because it is referenced + * using subscript 0 in mii_fdt_contype_to_name(). + */ +static struct contype_names { + mii_contype_t type; + const char *name; +} fdt_contype_names[] = { + {MII_CONTYPE_UNKNOWN, "unknown"}, + {MII_CONTYPE_MII, "mii"}, + {MII_CONTYPE_GMII, "gmii"}, + {MII_CONTYPE_SGMII, "sgmii"}, + {MII_CONTYPE_QSGMII, "qsgmii"}, + {MII_CONTYPE_TBI, "tbi"}, + {MII_CONTYPE_REVMII, "rev-mii"}, + {MII_CONTYPE_RMII, "rmii"}, + {MII_CONTYPE_RGMII, "rgmii"}, + {MII_CONTYPE_RGMII_ID, "rgmii-id"}, + {MII_CONTYPE_RGMII_RXID, "rgmii-rxid"}, + {MII_CONTYPE_RGMII_TXID, "rgmii-txid"}, + {MII_CONTYPE_RTBI, "rtbi"}, + {MII_CONTYPE_SMII, "smii"}, + {MII_CONTYPE_XGMII, "xgmii"}, + {MII_CONTYPE_TRGMII, "trgmii"}, + {MII_CONTYPE_2000BX, "2000base-x"}, + {MII_CONTYPE_2500BX, "2500base-x"}, + {MII_CONTYPE_RXAUI, "rxaui"}, +}; + +static phandle_t +mii_fdt_get_phynode(phandle_t macnode) +{ + static const char *props[] = { + "phy-handle", "phy", "phy-device" + }; + pcell_t xref; + u_int i; + + for (i = 0; i < nitems(props); ++i) { + if (OF_getencprop(macnode, props[i], &xref, sizeof(xref)) > 0) + return (OF_node_from_xref(xref)); + } + return (-1); +} + +mii_contype_t +mii_fdt_contype_from_name(const char *name) +{ + u_int i; + + for (i = 0; i < nitems(fdt_contype_names); ++i) { + if (strcmp(name, fdt_contype_names[i].name) == 0) + return (fdt_contype_names[i].type); + } + return (MII_CONTYPE_UNKNOWN); +} + +const char * +mii_fdt_contype_to_name(mii_contype_t contype) +{ + u_int i; + + for (i = 0; i < nitems(fdt_contype_names); ++i) { + if (contype == fdt_contype_names[i].type) + return (fdt_contype_names[i].name); + } + return (fdt_contype_names[0].name); +} + +mii_contype_t +mii_fdt_get_contype(phandle_t macnode) +{ + char val[32]; + + if (OF_getprop(macnode, "phy-mode", val, sizeof(val)) <= 0 && + OF_getprop(macnode, "phy-connection-type", val, sizeof(val)) <= 0) { + return (MII_CONTYPE_UNKNOWN); + } + return (mii_fdt_contype_from_name(val)); +} + +void +mii_fdt_free_config(struct mii_fdt_phy_config *cfg) +{ + + free(cfg, M_OFWPROP); +} + +mii_fdt_phy_config_t * +mii_fdt_get_config(device_t phydev) +{ + mii_fdt_phy_config_t *cfg; + device_t miibus, macdev; + pcell_t val; + + miibus = device_get_parent(phydev); + macdev = device_get_parent(miibus); + + cfg = malloc(sizeof(*cfg), M_OFWPROP, M_ZERO | M_WAITOK); + + /* + * If we can't find our parent MAC's node, there's nothing more we can + * fill in; cfg is already full of zero/default values, return it. + */ + if ((cfg->macnode = ofw_bus_get_node(macdev)) == -1) + return (cfg); + + cfg->con_type = mii_fdt_get_contype(cfg->macnode); + + /* + * If we can't find our own PHY node, there's nothing more we can fill + * in, just return what we've got. + */ + if ((cfg->phynode = mii_fdt_get_phynode(cfg->macnode)) == -1) + return (cfg); + + if (OF_getencprop(cfg->phynode, "max-speed", &val, sizeof(val)) > 0) + cfg->max_speed = val; + + if (ofw_bus_node_is_compatible(cfg->phynode, + "ethernet-phy-ieee802.3-c45")) + cfg->flags |= MIIF_FDT_COMPAT_CLAUSE45; + + if (OF_hasprop(cfg->phynode, "broken-turn-around")) + cfg->flags |= MIIF_FDT_BROKEN_TURNAROUND; + if (OF_hasprop(cfg->phynode, "enet-phy-lane-swap")) + cfg->flags |= MIIF_FDT_LANE_SWAP; + if (OF_hasprop(cfg->phynode, "enet-phy-lane-no-swap")) + cfg->flags |= MIIF_FDT_NO_LANE_SWAP; + if (OF_hasprop(cfg->phynode, "eee-broken-100tx")) + cfg->flags |= MIIF_FDT_EEE_BROKEN_100TX; + if (OF_hasprop(cfg->phynode, "eee-broken-1000t")) + cfg->flags |= MIIF_FDT_EEE_BROKEN_1000T; + if (OF_hasprop(cfg->phynode, "eee-broken-10gt")) + cfg->flags |= MIIF_FDT_EEE_BROKEN_10GT; + if (OF_hasprop(cfg->phynode, "eee-broken-1000kx")) + cfg->flags |= MIIF_FDT_EEE_BROKEN_1000KX; + if (OF_hasprop(cfg->phynode, "eee-broken-10gkx4")) + cfg->flags |= MIIF_FDT_EEE_BROKEN_10GKX4; + if (OF_hasprop(cfg->phynode, "eee-broken-10gkr")) + cfg->flags |= MIIF_FDT_EEE_BROKEN_10GKR; + + return (cfg); +} diff --git a/sys/dev/mii/mii_fdt.h b/sys/dev/mii/mii_fdt.h new file mode 100644 index 0000000..7b0b513 --- /dev/null +++ b/sys/dev/mii/mii_fdt.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2017 Ian Lepore + * All rights reserved. + * + * Development sponsored by Microsemi, Inc. + * + * 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. + * + * $FreeBSD$ + */ + +#ifndef _DEV_MII_FDT_H_ +#define _DEV_MII_FDT_H_ + +/* + * Common FDT config for a PHY, as documented in the devicetree bindings + * documents ethernet.txt and phy.txt. Boolean properties are represented as + * bits in the flags member. + */ +struct mii_fdt_phy_config { + phandle_t macnode; /* Node (not xref) of parent MAC */ + phandle_t phynode; /* Node (not xref) of PHY */ + mii_contype_t con_type; /* MAC<->PHY connection type */ + u_int max_speed; /* Mbits/sec, 0 = not specified */ + uint32_t flags; /* MIIF_FDT_xxx boolean properties */ +}; +typedef struct mii_fdt_phy_config mii_fdt_phy_config_t; + +/* PHY config flags. */ +#define MIIF_FDT_COMPAT_CLAUSE45 0x0001 +#define MIIF_FDT_BROKEN_TURNAROUND 0x0002 +#define MIIF_FDT_LANE_SWAP 0x0004 +#define MIIF_FDT_NO_LANE_SWAP 0x0008 +#define MIIF_FDT_EEE_BROKEN_100TX 0x0010 +#define MIIF_FDT_EEE_BROKEN_1000T 0x0020 +#define MIIF_FDT_EEE_BROKEN_10GT 0x0040 +#define MIIF_FDT_EEE_BROKEN_1000KX 0x0080 +#define MIIF_FDT_EEE_BROKEN_10GKX4 0x0100 +#define MIIF_FDT_EEE_BROKEN_10GKR 0x0200 + +/* + * Convert between mii_contype enums and devicetree property strings. + */ +const char *mii_fdt_contype_to_name(mii_contype_t contype); +mii_contype_t mii_fdt_contype_from_name(const char *name); + +/* Get the connection type from the given MAC node. */ +mii_contype_t mii_fdt_get_contype(phandle_t macnode); + +/* + * Get/free the config for the given PHY device. + */ +void mii_fdt_free_config(struct mii_fdt_phy_config *cfg); +mii_fdt_phy_config_t *mii_fdt_get_config(device_t phydev); + +#endif diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h index 498e720..ef81bdb 100644 --- a/sys/dev/mii/miivar.h +++ b/sys/dev/mii/miivar.h @@ -156,6 +156,42 @@ typedef struct mii_softc mii_softc_t; #define MII_PHY_ANY -1 /* + * Constants used to describe the type of attachment between MAC and PHY. + */ +enum mii_contype { + MII_CONTYPE_UNKNOWN, /* Must be have value 0. */ + + MII_CONTYPE_MII, + MII_CONTYPE_GMII, + MII_CONTYPE_SGMII, + MII_CONTYPE_QSGMII, + MII_CONTYPE_TBI, + MII_CONTYPE_REVMII, /* Reverse MII */ + MII_CONTYPE_RMII, + MII_CONTYPE_RGMII, /* Delays provided by MAC or PCB */ + MII_CONTYPE_RGMII_ID, /* Rx and tx delays provided by PHY */ + MII_CONTYPE_RGMII_RXID, /* Only rx delay provided by PHY */ + MII_CONTYPE_RGMII_TXID, /* Only tx delay provided by PHY */ + MII_CONTYPE_RTBI, + MII_CONTYPE_SMII, + MII_CONTYPE_XGMII, + MII_CONTYPE_TRGMII, + MII_CONTYPE_2000BX, + MII_CONTYPE_2500BX, + MII_CONTYPE_RXAUI, + + MII_CONTYPE_COUNT /* Add new types before this line. */ +}; +typedef enum mii_contype mii_contype_t; + +static inline bool +mii_contype_is_rgmii(mii_contype_t con) +{ + + return (con >= MII_CONTYPE_RGMII && con <= MII_CONTYPE_RGMII_TXID); +} + +/* * Used to attach a PHY to a parent. */ struct mii_attach_args { -- cgit v1.1