net: hns: delete redundancy ring enable operations
[deliverable/linux.git] / drivers / net / ethernet / hisilicon / hns / hns_dsaf_mac.c
index 611581fccf2a4eb1d569514d4c6613ebf54fee3e..c526558e63673be2e91916c53b990940508af759 100644 (file)
@@ -7,6 +7,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/acpi.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -15,7 +16,8 @@
 #include <linux/netdevice.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/phy_fixed.h>
+#include <linux/of_mdio.h>
+#include <linux/phy.h>
 #include <linux/platform_device.h>
 
 #include "hns_dsaf_main.h"
@@ -94,7 +96,7 @@ void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status)
        else
                *link_status = 0;
 
-       ret = hns_mac_get_sfp_prsnt(mac_cb, &sfp_prsnt);
+       ret = mac_cb->dsaf_dev->misc_op->get_sfp_prsnt(mac_cb, &sfp_prsnt);
        if (!ret)
                *link_status = *link_status && sfp_prsnt;
 
@@ -511,7 +513,7 @@ void hns_mac_stop(struct hns_mac_cb *mac_cb)
 
        mac_ctrl_drv->mac_en_flg = 0;
        mac_cb->link = 0;
-       cpld_led_reset(mac_cb);
+       mac_cb->dsaf_dev->misc_op->cpld_reset_led(mac_cb);
 }
 
 /**
@@ -637,6 +639,115 @@ free_mac_drv:
        return ret;
 }
 
+static int
+hns_mac_phy_parse_addr(struct device *dev, struct fwnode_handle *fwnode)
+{
+       u32 addr;
+       int ret;
+
+       ret = fwnode_property_read_u32(fwnode, "phy-addr", &addr);
+       if (ret) {
+               dev_err(dev, "has invalid PHY address ret:%d\n", ret);
+               return ret;
+       }
+
+       if (addr >= PHY_MAX_ADDR) {
+               dev_err(dev, "PHY address %i is too large\n", addr);
+               return -EINVAL;
+       }
+
+       return addr;
+}
+
+static int hns_mac_phydev_match(struct device *dev, void *fwnode)
+{
+       return dev->fwnode == fwnode;
+}
+
+static struct
+platform_device *hns_mac_find_platform_device(struct fwnode_handle *fwnode)
+{
+       struct device *dev;
+
+       dev = bus_find_device(&platform_bus_type, NULL,
+                             fwnode, hns_mac_phydev_match);
+       return dev ? to_platform_device(dev) : NULL;
+}
+
+static int
+hns_mac_register_phydev(struct mii_bus *mdio, struct hns_mac_cb *mac_cb,
+                       u32 addr)
+{
+       struct phy_device *phy;
+       const char *phy_type;
+       bool is_c45;
+       int rc;
+
+       rc = fwnode_property_read_string(mac_cb->fw_port,
+                                        "phy-mode", &phy_type);
+       if (rc < 0)
+               return rc;
+
+       if (!strcmp(phy_type, phy_modes(PHY_INTERFACE_MODE_XGMII)))
+               is_c45 = 1;
+       else if (!strcmp(phy_type, phy_modes(PHY_INTERFACE_MODE_SGMII)))
+               is_c45 = 0;
+       else
+               return -ENODATA;
+
+       phy = get_phy_device(mdio, addr, is_c45);
+       if (!phy || IS_ERR(phy))
+               return -EIO;
+
+       if (mdio->irq)
+               phy->irq = mdio->irq[addr];
+
+       /* All data is now stored in the phy struct;
+        * register it
+        */
+       rc = phy_device_register(phy);
+       if (rc) {
+               phy_device_free(phy);
+               return -ENODEV;
+       }
+
+       mac_cb->phy_dev = phy;
+
+       dev_dbg(&mdio->dev, "registered phy at address %i\n", addr);
+
+       return 0;
+}
+
+static void hns_mac_register_phy(struct hns_mac_cb *mac_cb)
+{
+       struct acpi_reference_args args;
+       struct platform_device *pdev;
+       struct mii_bus *mii_bus;
+       int rc;
+       int addr;
+
+       /* Loop over the child nodes and register a phy_device for each one */
+       if (!to_acpi_device_node(mac_cb->fw_port))
+               return;
+
+       rc = acpi_node_get_property_reference(
+                       mac_cb->fw_port, "mdio-node", 0, &args);
+       if (rc)
+               return;
+
+       addr = hns_mac_phy_parse_addr(mac_cb->dev, mac_cb->fw_port);
+       if (addr < 0)
+               return;
+
+       /* dev address in adev */
+       pdev = hns_mac_find_platform_device(acpi_fwnode_handle(args.adev));
+       mii_bus = platform_get_drvdata(pdev);
+       rc = hns_mac_register_phydev(mii_bus, mac_cb, addr);
+       if (!rc)
+               dev_dbg(mac_cb->dev, "mac%d register phy addr:%d\n",
+                       mac_cb->mac_id, addr);
+}
+
 /**
  *hns_mac_get_info  - get mac information from device node
  *@mac_cb: mac device
@@ -645,7 +756,7 @@ free_mac_drv:
  */
 static int  hns_mac_get_info(struct hns_mac_cb *mac_cb)
 {
-       struct device_node *np = mac_cb->dev->of_node;
+       struct device_node *np;
        struct regmap *syscon;
        struct of_phandle_args cpld_args;
        u32 ret;
@@ -672,63 +783,85 @@ static int  hns_mac_get_info(struct hns_mac_cb *mac_cb)
         * from dsaf node
         */
        if (!mac_cb->fw_port) {
-               mac_cb->phy_node = of_parse_phandle(np, "phy-handle",
-                                                   mac_cb->mac_id);
-               if (mac_cb->phy_node)
+               np = of_parse_phandle(mac_cb->dev->of_node, "phy-handle",
+                                     mac_cb->mac_id);
+               mac_cb->phy_dev = of_phy_find_device(np);
+               if (mac_cb->phy_dev) {
+                       /* refcount is held by of_phy_find_device()
+                        * if the phy_dev is found
+                        */
+                       put_device(&mac_cb->phy_dev->mdio.dev);
+
                        dev_dbg(mac_cb->dev, "mac%d phy_node: %s\n",
-                               mac_cb->mac_id, mac_cb->phy_node->name);
-               return 0;
-       }
-       if (!is_of_node(mac_cb->fw_port))
-               return -EINVAL;
-       /* parse property from port subnode in dsaf */
-       mac_cb->phy_node = of_parse_phandle(to_of_node(mac_cb->fw_port),
-                                           "phy-handle", 0);
-       if (mac_cb->phy_node)
-               dev_dbg(mac_cb->dev, "mac%d phy_node: %s\n",
-                       mac_cb->mac_id, mac_cb->phy_node->name);
-       syscon = syscon_node_to_regmap(
-                       of_parse_phandle(to_of_node(mac_cb->fw_port),
-                                        "serdes-syscon", 0));
-       if (IS_ERR_OR_NULL(syscon)) {
-               dev_err(mac_cb->dev, "serdes-syscon is needed!\n");
-               return -EINVAL;
-       }
-       mac_cb->serdes_ctrl = syscon;
+                               mac_cb->mac_id, np->name);
+               }
 
-       ret = fwnode_property_read_u32(mac_cb->fw_port,
-                                      "port-rst-offset",
-                                      &mac_cb->port_rst_off);
-       if (ret) {
-               dev_dbg(mac_cb->dev,
-                       "mac%d port-rst-offset not found, use default value.\n",
-                       mac_cb->mac_id);
+               return 0;
        }
 
-       ret = fwnode_property_read_u32(mac_cb->fw_port,
-                                      "port-mode-offset",
-                                      &mac_cb->port_mode_off);
-       if (ret) {
-               dev_dbg(mac_cb->dev,
-                       "mac%d port-mode-offset not found, use default value.\n",
-                       mac_cb->mac_id);
-       }
+       if (is_of_node(mac_cb->fw_port)) {
+               /* parse property from port subnode in dsaf */
+               np = of_parse_phandle(to_of_node(mac_cb->fw_port),
+                                     "phy-handle", 0);
+               mac_cb->phy_dev = of_phy_find_device(np);
+               if (mac_cb->phy_dev) {
+                       /* refcount is held by of_phy_find_device()
+                        * if the phy_dev is found
+                        */
+                       put_device(&mac_cb->phy_dev->mdio.dev);
+                       dev_dbg(mac_cb->dev, "mac%d phy_node: %s\n",
+                               mac_cb->mac_id, np->name);
+               }
 
-       ret = of_parse_phandle_with_fixed_args(to_of_node(mac_cb->fw_port),
-                                              "cpld-syscon", 1, 0, &cpld_args);
-       if (ret) {
-               dev_dbg(mac_cb->dev, "mac%d no cpld-syscon found.\n",
-                       mac_cb->mac_id);
-               mac_cb->cpld_ctrl = NULL;
-       } else {
-               syscon = syscon_node_to_regmap(cpld_args.np);
+               syscon = syscon_node_to_regmap(
+                               of_parse_phandle(to_of_node(mac_cb->fw_port),
+                                                "serdes-syscon", 0));
                if (IS_ERR_OR_NULL(syscon)) {
-                       dev_dbg(mac_cb->dev, "no cpld-syscon found!\n");
+                       dev_err(mac_cb->dev, "serdes-syscon is needed!\n");
+                       return -EINVAL;
+               }
+               mac_cb->serdes_ctrl = syscon;
+
+               ret = fwnode_property_read_u32(mac_cb->fw_port,
+                                              "port-rst-offset",
+                                              &mac_cb->port_rst_off);
+               if (ret) {
+                       dev_dbg(mac_cb->dev,
+                               "mac%d port-rst-offset not found, use default value.\n",
+                               mac_cb->mac_id);
+               }
+
+               ret = fwnode_property_read_u32(mac_cb->fw_port,
+                                              "port-mode-offset",
+                                              &mac_cb->port_mode_off);
+               if (ret) {
+                       dev_dbg(mac_cb->dev,
+                               "mac%d port-mode-offset not found, use default value.\n",
+                               mac_cb->mac_id);
+               }
+
+               ret = of_parse_phandle_with_fixed_args(
+                       to_of_node(mac_cb->fw_port), "cpld-syscon", 1, 0,
+                       &cpld_args);
+               if (ret) {
+                       dev_dbg(mac_cb->dev, "mac%d no cpld-syscon found.\n",
+                               mac_cb->mac_id);
                        mac_cb->cpld_ctrl = NULL;
                } else {
-                       mac_cb->cpld_ctrl = syscon;
-                       mac_cb->cpld_ctrl_reg = cpld_args.args[0];
+                       syscon = syscon_node_to_regmap(cpld_args.np);
+                       if (IS_ERR_OR_NULL(syscon)) {
+                               dev_dbg(mac_cb->dev, "no cpld-syscon found!\n");
+                               mac_cb->cpld_ctrl = NULL;
+                       } else {
+                               mac_cb->cpld_ctrl = syscon;
+                               mac_cb->cpld_ctrl_reg = cpld_args.args[0];
+                       }
                }
+       } else if (is_acpi_node(mac_cb->fw_port)) {
+               hns_mac_register_phy(mac_cb);
+       } else {
+               dev_err(mac_cb->dev, "mac%d cannot find phy node\n",
+                       mac_cb->mac_id);
        }
 
        return 0;
@@ -790,7 +923,7 @@ int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, struct hns_mac_cb *mac_cb)
        else
                mac_cb->mac_type = HNAE_PORT_DEBUG;
 
-       mac_cb->phy_if = hns_mac_get_phy_if(mac_cb);
+       mac_cb->phy_if = dsaf_dev->misc_op->get_phy_if(mac_cb);
 
        ret = hns_mac_get_mode(mac_cb->phy_if);
        if (ret < 0) {
@@ -805,7 +938,7 @@ int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, struct hns_mac_cb *mac_cb)
        if (ret)
                return ret;
 
-       cpld_led_reset(mac_cb);
+       mac_cb->dsaf_dev->misc_op->cpld_reset_led(mac_cb);
        mac_cb->vaddr = hns_mac_get_vaddr(dsaf_dev, mac_cb, mac_mode_idx);
 
        return 0;
@@ -892,7 +1025,7 @@ void hns_mac_uninit(struct dsaf_device *dsaf_dev)
        int max_port_num = hns_mac_get_max_port_num(dsaf_dev);
 
        for (i = 0; i < max_port_num; i++) {
-               cpld_led_reset(dsaf_dev->mac_cb[i]);
+               dsaf_dev->misc_op->cpld_reset_led(dsaf_dev->mac_cb[i]);
                dsaf_dev->mac_cb[i] = NULL;
        }
 }
@@ -975,7 +1108,7 @@ void hns_set_led_opt(struct hns_mac_cb *mac_cb)
                nic_data = 0;
        mac_cb->txpkt_for_led = mac_cb->hw_stats.tx_good_pkts;
        mac_cb->rxpkt_for_led = mac_cb->hw_stats.rx_good_pkts;
-       hns_cpld_set_led(mac_cb, (int)mac_cb->link,
+       mac_cb->dsaf_dev->misc_op->cpld_set_led(mac_cb, (int)mac_cb->link,
                         mac_cb->speed, nic_data);
 }
 
@@ -985,5 +1118,5 @@ int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb,
        if (!mac_cb || !mac_cb->cpld_ctrl)
                return 0;
 
-       return cpld_set_led_id(mac_cb, status);
+       return mac_cb->dsaf_dev->misc_op->cpld_set_led_id(mac_cb, status);
 }
This page took 0.043419 seconds and 5 git commands to generate.