X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;ds=sidebyside;f=target%2Flinux%2Fapm821xx%2Fpatches-4.9%2F702-powerpc_ibm_phy_add_dt_parser.patch;fp=target%2Flinux%2Fapm821xx%2Fpatches-4.9%2F702-powerpc_ibm_phy_add_dt_parser.patch;h=0000000000000000000000000000000000000000;hb=3c94691620b21ade34696ece133bdddd475c3582;hp=4e53fdfa2127550e79c7046d47730770133dc5b3;hpb=e97f92bbf90470329085ffe2a7610d5a413e75e2;p=openwrt%2Fopenwrt.git diff --git a/target/linux/apm821xx/patches-4.9/702-powerpc_ibm_phy_add_dt_parser.patch b/target/linux/apm821xx/patches-4.9/702-powerpc_ibm_phy_add_dt_parser.patch deleted file mode 100644 index 4e53fdfa21..0000000000 --- a/target/linux/apm821xx/patches-4.9/702-powerpc_ibm_phy_add_dt_parser.patch +++ /dev/null @@ -1,328 +0,0 @@ -From b1c54da602ae9215cfbde1c3ed3b6296b76f07fc Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <246bd6614529d28dc48b11981ab5dae7a7364fc2.1486337989.git.chunkeey@googlemail.com> -References: <246bd6614529d28dc48b11981ab5dae7a7364fc2.1486337989.git.chunkeey@googlemail.com> -From: Christian Lamparter -Date: Mon, 13 Jun 2016 15:42:21 +0200 -Subject: [RFC 2/2] net: emac: add support for device-tree based PHY discovery - and setup -To: netdev@vger.kernel.org, - devicetree@vger.kernel.org -Cc: David S. Miller , - Ivan Mikhaylov , - Mark Rutland , - Rob Herring - -This patch adds glue-code that allows the EMAC driver to interface -with the existing dt-supported PHYs in drivers/net/phy. - -Because currently, the emac driver maintains a small library of -supported phys for in a private phy.c file located in the drivers -directory. - -The support is limited to mostly single ethernet transceiver like the: -CIS8201, BCM5248, ET1011C, Marvell 88E1111 and 88E1112, AR8035. -However, routers like the Netgear WNDR4700 and Cisco Meraki MX60(W) -have a 5-port switch (QCA8327N) attached to the MDIO of the EMAC. -The switch chip has already a proper phy-driver (ar8216) that uses -the generic phy library. - -Signed-off-by: Christian Lamparter ---- ---- a/drivers/net/ethernet/ibm/emac/core.c -+++ b/drivers/net/ethernet/ibm/emac/core.c -@@ -42,6 +42,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -2422,6 +2423,229 @@ static int emac_read_uint_prop(struct de - return 0; - } - -+static void emac_adjust_link(struct net_device *ndev) -+{ -+ struct emac_instance *dev = netdev_priv(ndev); -+ struct phy_device *phy = dev->phy_dev; -+ -+ dev->phy.autoneg = phy->autoneg; -+ dev->phy.speed = phy->speed; -+ dev->phy.duplex = phy->duplex; -+ dev->phy.pause = phy->pause; -+ dev->phy.asym_pause = phy->asym_pause; -+ dev->phy.advertising = phy->advertising; -+} -+ -+static int emac_mii_bus_read(struct mii_bus *bus, int addr, int regnum) -+{ -+ return emac_mdio_read(bus->priv, addr, regnum); -+} -+ -+static int emac_mii_bus_write(struct mii_bus *bus, int addr, int regnum, u16 val) -+{ -+ emac_mdio_write(bus->priv, addr, regnum, val); -+ return 0; -+} -+ -+static int emac_mii_bus_reset(struct mii_bus *bus) -+{ -+ struct emac_instance *dev = netdev_priv(bus->priv); -+ int err; -+ -+ err = emac_reset(dev); -+ if (err) -+ return err; -+ /* Meraki MX60(W)'s uboot will disable the switch and -+ * a bus reset won't do anything. */ -+ emac_mii_reset_phy(&dev->phy); -+ return 0; -+} -+ -+static int emac_mdio_setup_aneg(struct mii_phy *phy, u32 advertise) -+{ -+ struct net_device *ndev = phy->dev; -+ struct emac_instance *dev = netdev_priv(ndev); -+ -+ dev->phy.autoneg = AUTONEG_ENABLE; -+ dev->phy.speed = SPEED_1000; -+ dev->phy.duplex = DUPLEX_FULL; -+ dev->phy.advertising = advertise; -+ phy->autoneg = AUTONEG_ENABLE; -+ phy->speed = dev->phy.speed; -+ phy->duplex = dev->phy.duplex; -+ phy->advertising = advertise; -+ return phy_start_aneg(dev->phy_dev); -+} -+ -+static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd) -+{ -+ struct net_device *ndev = phy->dev; -+ struct emac_instance *dev = netdev_priv(ndev); -+ -+ dev->phy.autoneg = AUTONEG_DISABLE; -+ dev->phy.speed = speed; -+ dev->phy.duplex = fd; -+ phy->autoneg = AUTONEG_DISABLE; -+ phy->speed = speed; -+ phy->duplex = fd; -+ return phy_start_aneg(dev->phy_dev); -+} -+ -+static int emac_mdio_poll_link(struct mii_phy *phy) -+{ -+ struct net_device *ndev = phy->dev; -+ struct emac_instance *dev = netdev_priv(ndev); -+ int res; -+ -+ res = phy_read_status(dev->phy_dev); -+ if (res) { -+ dev_err(&dev->ofdev->dev, "link update failed (%d).", res); -+ return ethtool_op_get_link(ndev); -+ } -+ -+ return dev->phy_dev->link; -+} -+ -+static int emac_mdio_read_link(struct mii_phy *phy) -+{ -+ struct net_device *ndev = phy->dev; -+ struct emac_instance *dev = netdev_priv(ndev); -+ int res; -+ -+ res = phy_read_status(dev->phy_dev); -+ if (res) -+ return res; -+ -+ dev->phy.speed = phy->speed; -+ dev->phy.duplex = phy->duplex; -+ dev->phy.pause = phy->pause; -+ dev->phy.asym_pause = phy->asym_pause; -+ return 0; -+} -+ -+static int emac_mdio_init_phy(struct mii_phy *phy) -+{ -+ struct net_device *ndev = phy->dev; -+ struct emac_instance *dev = netdev_priv(ndev); -+ -+ phy_start(dev->phy_dev); -+ dev->phy.autoneg = phy->autoneg; -+ dev->phy.speed = phy->speed; -+ dev->phy.duplex = phy->duplex; -+ dev->phy.advertising = phy->advertising; -+ dev->phy.pause = phy->pause; -+ dev->phy.asym_pause = phy->asym_pause; -+ -+ return phy_init_hw(dev->phy_dev); -+} -+ -+static const struct mii_phy_ops emac_dt_mdio_phy_ops = { -+ .init = emac_mdio_init_phy, -+ .setup_aneg = emac_mdio_setup_aneg, -+ .setup_forced = emac_mdio_setup_forced, -+ .poll_link = emac_mdio_poll_link, -+ .read_link = emac_mdio_read_link, -+}; -+ -+static int emac_dt_mdio_probe(struct emac_instance *dev) -+{ -+ struct device_node *mii_np; -+ int res; -+ -+ mii_np = of_get_child_by_name(dev->ofdev->dev.of_node, "mdio"); -+ if (!mii_np) { -+ dev_err(&dev->ofdev->dev, "no mdio definition found."); -+ return -ENODEV; -+ } -+ -+ if (!of_device_is_available(mii_np)) { -+ res = 1; -+ goto put_node; -+ } -+ -+ dev->mii_bus = devm_mdiobus_alloc(&dev->ofdev->dev); -+ if (!dev->mii_bus) { -+ res = -ENOMEM; -+ goto put_node; -+ } -+ -+ dev->mii_bus->priv = dev->ndev; -+ dev->mii_bus->parent = dev->ndev->dev.parent; -+ dev->mii_bus->name = "emac_mdio"; -+ dev->mii_bus->read = &emac_mii_bus_read; -+ dev->mii_bus->write = &emac_mii_bus_write; -+ dev->mii_bus->reset = &emac_mii_bus_reset; -+ snprintf(dev->mii_bus->id, MII_BUS_ID_SIZE, "%s", dev->ofdev->name); -+ res = of_mdiobus_register(dev->mii_bus, mii_np); -+ if (res) { -+ dev_err(&dev->ofdev->dev, "cannot register MDIO bus %s (%d)", -+ dev->mii_bus->name, res); -+ } -+ -+ put_node: -+ of_node_put(mii_np); -+ return res; -+} -+ -+static int emac_dt_phy_probe(struct emac_instance *dev, -+ struct device_node *phy_handle) -+{ -+ u32 phy_flags = 0; -+ int res; -+ -+ res = of_property_read_u32(phy_handle, "phy-flags", &phy_flags); -+ if (res < 0 && res != -EINVAL) -+ return res; -+ -+ dev->phy.def = devm_kzalloc(&dev->ofdev->dev, sizeof(*dev->phy.def), -+ GFP_KERNEL); -+ if (!dev->phy.def) -+ return -ENOMEM; -+ -+ dev->phy_dev = of_phy_connect(dev->ndev, phy_handle, -+ &emac_adjust_link, phy_flags, -+ PHY_INTERFACE_MODE_RGMII); -+ if (!dev->phy_dev) { -+ dev_err(&dev->ofdev->dev, "failed to connect to PHY.\n"); -+ return -ENODEV; -+ } -+ -+ dev->phy.def->phy_id = dev->phy_dev->drv->phy_id; -+ dev->phy.def->phy_id_mask = dev->phy_dev->drv->phy_id_mask; -+ dev->phy.def->name = dev->phy_dev->drv->name; -+ dev->phy.def->ops = &emac_dt_mdio_phy_ops; -+ dev->phy.features = dev->phy_dev->supported; -+ dev->phy.address = dev->phy_dev->mdio.addr; -+ dev->phy.mode = dev->phy_dev->interface; -+ return 0; -+} -+ -+static int emac_probe_dt_phy(struct emac_instance *dev) -+{ -+ struct device_node *np = dev->ofdev->dev.of_node; -+ struct device_node *phy_handle; -+ int res = 0; -+ -+ phy_handle = of_parse_phandle(np, "phy-handle", 0); -+ -+ if (phy_handle) { -+ res = emac_dt_mdio_probe(dev); -+ if (!res) { -+ res = emac_dt_phy_probe(dev, phy_handle); -+ if (!res) -+ res = 1; -+ else -+ mdiobus_unregister(dev->mii_bus); -+ } -+ } -+ -+ of_node_put(phy_handle); -+ /* if no phy device was specified in the device tree, then we fallback -+ * to the old emac_phy.c probe code for compatibility reasons. -+ */ -+ return res; -+} -+ - static int emac_init_phy(struct emac_instance *dev) - { - struct device_node *np = dev->ofdev->dev.of_node; -@@ -2492,6 +2716,22 @@ static int emac_init_phy(struct emac_ins - - emac_configure(dev); - -+ if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII)) { -+ int res = emac_probe_dt_phy(dev); -+ -+ if (res == 1) { -+ mutex_unlock(&emac_phy_map_lock); -+ goto init_phy; -+ } else if (res < 0) { -+ mutex_unlock(&emac_phy_map_lock); -+ dev_err(&dev->ofdev->dev, "failed to attach dt phy (%d).\n", -+ res); -+ return res; -+ } -+ -+ /* continue with old code */ -+ } -+ - if (dev->phy_address != 0xffffffff) - phy_map = ~(1 << dev->phy_address); - -@@ -2519,6 +2759,7 @@ static int emac_init_phy(struct emac_ins - return -ENXIO; - } - -+ init_phy: - /* Init PHY */ - if (dev->phy.def->ops->init) - dev->phy.def->ops->init(&dev->phy); -@@ -2988,6 +3229,12 @@ static int emac_remove(struct platform_d - if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII)) - zmii_detach(dev->zmii_dev, dev->zmii_port); - -+ if (dev->phy_dev) -+ phy_disconnect(dev->phy_dev); -+ -+ if (dev->mii_bus) -+ mdiobus_unregister(dev->mii_bus); -+ - busy_phy_map &= ~(1 << dev->phy.address); - DBG(dev, "busy_phy_map now %#x" NL, busy_phy_map); - ---- a/drivers/net/ethernet/ibm/emac/core.h -+++ b/drivers/net/ethernet/ibm/emac/core.h -@@ -199,6 +199,10 @@ struct emac_instance { - struct emac_instance *mdio_instance; - struct mutex mdio_lock; - -+ /* Device-tree based phy configuration */ -+ struct mii_bus *mii_bus; -+ struct phy_device *phy_dev; -+ - /* ZMII infos if any */ - u32 zmii_ph; - u32 zmii_port;