diff options
author | ian <ian@FreeBSD.org> | 2017-09-11 01:59:24 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2017-09-11 01:59:24 +0000 |
commit | b33a3dc4add359db25d751b8bdb5ea1041748fc7 (patch) | |
tree | d9b610fe8d78e198abb8b77601ec98742c7ffc31 /sys/dev/mii | |
parent | a8c8c6f7c99020232ee481f9e5c9389c60f8e20a (diff) | |
download | FreeBSD-src-b33a3dc4add359db25d751b8bdb5ea1041748fc7.zip FreeBSD-src-b33a3dc4add359db25d751b8bdb5ea1041748fc7.tar.gz |
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.
Diffstat (limited to 'sys/dev/mii')
-rw-r--r-- | sys/dev/mii/mii_fdt.c | 200 | ||||
-rw-r--r-- | sys/dev/mii/mii_fdt.h | 75 | ||||
-rw-r--r-- | sys/dev/mii/miivar.h | 36 |
3 files changed, 311 insertions, 0 deletions
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 <ian@freebsd.org> + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * Utility functions for PHY drivers on systems configured using FDT data. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <sys/bus.h> +#include <sys/malloc.h> + +#include <net/if.h> +#include <net/if_media.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> +#include <dev/mii/mii_fdt.h> + +/* + * 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 <ian@freebsd.org> + * 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 { |