From 6eb17e0df74c036eba7548915b37f009403fe09e Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:09 +0800 Subject: [PATCH 01/13] ACPI: bus: add stub acpi_dev_found() to linux/acpi.h acpi_dev_found() will be used to detect if a given ACPI device is in the system. It will be compiled in non-ACPI case, but the function is in acpi_bus.h and acpi_bus.h can only be used in ACPI case, so this patch add the stub function to linux/acpi.h to make compiled successfully in non-ACPI cases. Cc: Rafael J. Wysocki Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- include/linux/acpi.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 288fac5294f5e..3025d1930f6eb 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -543,6 +543,11 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *); struct fwnode_handle; +static inline bool acpi_dev_found(const char *hid) +{ + return false; +} + static inline bool is_acpi_node(struct fwnode_handle *fwnode) { return false; From 4ae399241adba66ad72e5973a1004f37ffbe67cd Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:10 +0800 Subject: [PATCH 02/13] ACPI: bus: add stub acpi_evaluate_dsm() to linux/acpi.h acpi_evaluate_dsm() will be used to handle the _DSM method in ACPI case. It will be compiled in non-ACPI case, but the function is in acpi_bus.h and acpi_bus.h can only be used in ACPI case, so this patch add the stub function to linux/acpi.h to make compiled successfully in non-ACPI cases. Cc: Rafael J. Wysocki Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- include/linux/acpi.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 3025d1930f6eb..4d4bb49556825 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -659,6 +659,14 @@ static inline bool acpi_driver_match_device(struct device *dev, return false; } +static inline union acpi_object *acpi_evaluate_dsm(acpi_handle handle, + const u8 *uuid, + int rev, int func, + union acpi_object *argv4) +{ + return NULL; +} + static inline int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) { From 16a9f36150aa3cc516e8df0d1a979b5ca0c907ba Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:11 +0800 Subject: [PATCH 03/13] net: hisilicon: cleanup to prepare for other cases Hns-mdio only supports DT case now. do some cleanup to prepare for introducing other cases later, no functional change. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns_mdio.c | 48 +++++++++-------------- 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index 765ddb3dcd1a0..297edc47bb2b6 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -354,6 +354,9 @@ static int hns_mdio_reset(struct mii_bus *bus) struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; int ret; + if (!dev_of_node(bus->parent)) + return -ENOTSUPP; + if (!mdio_dev->subctrl_vbase) { dev_err(&bus->dev, "mdio sys ctl reg has not maped\n"); return -ENODEV; @@ -396,24 +399,6 @@ static int hns_mdio_reset(struct mii_bus *bus) return ret; } -/** - * hns_mdio_bus_name - get mdio bus name - * @name: mdio bus name - * @np: mdio device node pointer - */ -static void hns_mdio_bus_name(char *name, struct device_node *np) -{ - const u32 *addr; - u64 taddr = OF_BAD_ADDR; - - addr = of_get_address(np, 0, NULL, NULL); - if (addr) - taddr = of_translate_address(np, addr); - - snprintf(name, MII_BUS_ID_SIZE, "%s@%llx", np->name, - (unsigned long long)taddr); -} - /** * hns_mdio_probe - probe mdio device * @pdev: mdio platform device @@ -422,17 +407,16 @@ static void hns_mdio_bus_name(char *name, struct device_node *np) */ static int hns_mdio_probe(struct platform_device *pdev) { - struct device_node *np; struct hns_mdio_device *mdio_dev; struct mii_bus *new_bus; struct resource *res; - int ret; + int ret = -ENODEV; if (!pdev) { dev_err(NULL, "pdev is NULL!\r\n"); return -ENODEV; } - np = pdev->dev.of_node; + mdio_dev = devm_kzalloc(&pdev->dev, sizeof(*mdio_dev), GFP_KERNEL); if (!mdio_dev) return -ENOMEM; @@ -448,7 +432,7 @@ static int hns_mdio_probe(struct platform_device *pdev) new_bus->write = hns_mdio_write; new_bus->reset = hns_mdio_reset; new_bus->priv = mdio_dev; - hns_mdio_bus_name(new_bus->id, np); + new_bus->parent = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mdio_dev->vbase = devm_ioremap_resource(&pdev->dev, res); @@ -457,16 +441,20 @@ static int hns_mdio_probe(struct platform_device *pdev) return ret; } - mdio_dev->subctrl_vbase = - syscon_node_to_regmap(of_parse_phandle(np, "subctrl-vbase", 0)); - if (IS_ERR(mdio_dev->subctrl_vbase)) { - dev_warn(&pdev->dev, "no syscon hisilicon,peri-c-subctrl\n"); - mdio_dev->subctrl_vbase = NULL; - } - new_bus->parent = &pdev->dev; platform_set_drvdata(pdev, new_bus); + snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%s", "Mii", + dev_name(&pdev->dev)); + if (dev_of_node(&pdev->dev)) { + mdio_dev->subctrl_vbase = syscon_node_to_regmap( + of_parse_phandle(pdev->dev.of_node, + "subctrl-vbase", 0)); + if (IS_ERR(mdio_dev->subctrl_vbase)) { + dev_warn(&pdev->dev, "no syscon hisilicon,peri-c-subctrl\n"); + mdio_dev->subctrl_vbase = NULL; + } + ret = of_mdiobus_register(new_bus, pdev->dev.of_node); + } - ret = of_mdiobus_register(new_bus, np); if (ret) { dev_err(&pdev->dev, "Cannot register as MDIO bus!\n"); platform_set_drvdata(pdev, NULL); From 8a99ff5ab4f4f209358b177b376660066c9c4400 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:12 +0800 Subject: [PATCH 04/13] net: hisilicon: add support of acpi for hns-mdio hns-mdio needs to register itself to mii-bus. The info of the device can be read by both DT and ACPI. HNS tries to call Linux PHY driver to help access PHY-devices, the HNS hardware topology is as below. The MDIO controller may control several PHY-devices, and each PHY-device connects to a MAC device. The MDIO will be registered to mdiobus, then PHY-devices will register when each mac find PHY device. cpu | | ------------------------------------------- | | | | | | | dsaf | MDIO | MDIO | --------------------------- | | | | | | | | | | | | | | MAC MAC MAC MAC | | | | | | | ---- |-------- |-------- | | -------- || || || || PHY PHY PHY PHY And the driver can handle reset sequence by _RST method in DSDT in ACPI case. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns_mdio.c | 106 ++++++++++++++-------- 1 file changed, 69 insertions(+), 37 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index 297edc47bb2b6..761a32fcecebd 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -7,6 +7,7 @@ * (at your option) any later version. */ +#include #include #include #include @@ -354,48 +355,60 @@ static int hns_mdio_reset(struct mii_bus *bus) struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; int ret; - if (!dev_of_node(bus->parent)) - return -ENOTSUPP; + if (dev_of_node(bus->parent)) { + if (!mdio_dev->subctrl_vbase) { + dev_err(&bus->dev, "mdio sys ctl reg has not maped\n"); + return -ENODEV; + } - if (!mdio_dev->subctrl_vbase) { - dev_err(&bus->dev, "mdio sys ctl reg has not maped\n"); - return -ENODEV; - } + /* 1. reset req, and read reset st check */ + ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_RESET_REQ, 0x1, + MDIO_SC_RESET_ST, 0x1, + MDIO_CHECK_SET_ST); + if (ret) { + dev_err(&bus->dev, "MDIO reset fail\n"); + return ret; + } - /*1. reset req, and read reset st check*/ - ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_RESET_REQ, 0x1, - MDIO_SC_RESET_ST, 0x1, - MDIO_CHECK_SET_ST); - if (ret) { - dev_err(&bus->dev, "MDIO reset fail\n"); - return ret; - } + /* 2. dis clk, and read clk st check */ + ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_CLK_DIS, + 0x1, MDIO_SC_CLK_ST, 0x1, + MDIO_CHECK_CLR_ST); + if (ret) { + dev_err(&bus->dev, "MDIO dis clk fail\n"); + return ret; + } - /*2. dis clk, and read clk st check*/ - ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_CLK_DIS, - 0x1, MDIO_SC_CLK_ST, 0x1, - MDIO_CHECK_CLR_ST); - if (ret) { - dev_err(&bus->dev, "MDIO dis clk fail\n"); - return ret; - } + /* 3. reset dreq, and read reset st check */ + ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_RESET_DREQ, 0x1, + MDIO_SC_RESET_ST, 0x1, + MDIO_CHECK_CLR_ST); + if (ret) { + dev_err(&bus->dev, "MDIO dis clk fail\n"); + return ret; + } - /*3. reset dreq, and read reset st check*/ - ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_RESET_DREQ, 0x1, - MDIO_SC_RESET_ST, 0x1, - MDIO_CHECK_CLR_ST); - if (ret) { - dev_err(&bus->dev, "MDIO dis clk fail\n"); - return ret; + /* 4. en clk, and read clk st check */ + ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_CLK_EN, + 0x1, MDIO_SC_CLK_ST, 0x1, + MDIO_CHECK_SET_ST); + if (ret) + dev_err(&bus->dev, "MDIO en clk fail\n"); + } else if (is_acpi_node(bus->parent->fwnode)) { + acpi_status s; + + s = acpi_evaluate_object(ACPI_HANDLE(bus->parent), + "_RST", NULL, NULL); + if (ACPI_FAILURE(s)) { + dev_err(&bus->dev, "Reset failed, return:%#x\n", s); + ret = -EBUSY; + } else { + ret = 0; + } + } else { + dev_err(&bus->dev, "Can not get cfg data from DT or ACPI\n"); + ret = -ENXIO; } - - /*4. en clk, and read clk st check*/ - ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_CLK_EN, - 0x1, MDIO_SC_CLK_ST, 0x1, - MDIO_CHECK_SET_ST); - if (ret) - dev_err(&bus->dev, "MDIO en clk fail\n"); - return ret; } @@ -453,6 +466,18 @@ static int hns_mdio_probe(struct platform_device *pdev) mdio_dev->subctrl_vbase = NULL; } ret = of_mdiobus_register(new_bus, pdev->dev.of_node); + } else if (is_acpi_node(pdev->dev.fwnode)) { + /* Clear all the IRQ properties */ + memset(new_bus->irq, PHY_POLL, 4 * PHY_MAX_ADDR); + + /* Mask out all PHYs from auto probing. */ + new_bus->phy_mask = ~0; + + /* Register the MDIO bus */ + ret = mdiobus_register(new_bus); + } else { + dev_err(&pdev->dev, "Can not get cfg data from DT or ACPI\n"); + ret = -ENXIO; } if (ret) { @@ -487,12 +512,19 @@ static const struct of_device_id hns_mdio_match[] = { {} }; +static const struct acpi_device_id hns_mdio_acpi_match[] = { + { "HISI0141", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, hns_mdio_acpi_match); + static struct platform_driver hns_mdio_driver = { .probe = hns_mdio_probe, .remove = hns_mdio_remove, .driver = { .name = MDIO_DRV_NAME, .of_match_table = hns_mdio_match, + .acpi_match_table = ACPI_PTR(hns_mdio_acpi_match), }, }; From 6162928c76dcba2504c88eff19cbc190995401d7 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:13 +0800 Subject: [PATCH 05/13] net: hns: use device_* APIs instead of of_* APIs OF series functions can be used only for DT case. Use unified device property function instead to support both DT and ACPI. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 9 +++++---- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 11 +++-------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 1c2ddb25e7768..9afc5e665985a 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -50,7 +50,7 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) else dsaf_dev->dsaf_ver = AE_VERSION_2; - ret = of_property_read_string(np, "mode", &mode_str); + ret = device_property_read_string(dsaf_dev->dev, "mode", &mode_str); if (ret) { dev_err(dsaf_dev->dev, "get dsaf mode fail, ret=%d!\n", ret); return ret; @@ -142,7 +142,7 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) } } - ret = of_property_read_u32(np, "desc-num", &desc_num); + ret = device_property_read_u32(dsaf_dev->dev, "desc-num", &desc_num); if (ret < 0 || desc_num < HNS_DSAF_MIN_DESC_CNT || desc_num > HNS_DSAF_MAX_DESC_CNT) { dev_err(dsaf_dev->dev, "get desc-num(%d) fail, ret=%d!\n", @@ -151,14 +151,15 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) } dsaf_dev->desc_num = desc_num; - ret = of_property_read_u32(np, "reset-field-offset", &reset_offset); + ret = device_property_read_u32(dsaf_dev->dev, "reset-field-offset", + &reset_offset); if (ret < 0) { dev_dbg(dsaf_dev->dev, "get reset-field-offset fail, ret=%d!\r\n", ret); } dsaf_dev->reset_offset = reset_offset; - ret = of_property_read_u32(np, "buf-size", &buf_size); + ret = device_property_read_u32(dsaf_dev->dev, "buf-size", &buf_size); if (ret < 0) { dev_err(dsaf_dev->dev, "get buf-size fail, ret=%d!\r\n", ret); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index e621636e69b9e..8851420567505 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1067,13 +1067,8 @@ void hns_nic_update_stats(struct net_device *netdev) static void hns_init_mac_addr(struct net_device *ndev) { struct hns_nic_priv *priv = netdev_priv(ndev); - struct device_node *node = priv->dev->of_node; - const void *mac_addr_temp; - mac_addr_temp = of_get_mac_address(node); - if (mac_addr_temp && is_valid_ether_addr(mac_addr_temp)) { - memcpy(ndev->dev_addr, mac_addr_temp, ndev->addr_len); - } else { + if (!device_get_mac_address(priv->dev, ndev->dev_addr, ETH_ALEN)) { eth_hw_addr_random(ndev); dev_warn(priv->dev, "No valid mac, use random mac %pM", ndev->dev_addr); @@ -1898,10 +1893,10 @@ static int hns_nic_dev_probe(struct platform_device *pdev) goto out_read_prop_fail; } /* try to find port-idx-in-ae first */ - ret = of_property_read_u32(node, "port-idx-in-ae", &port_id); + ret = device_property_read_u32(dev, "port-idx-in-ae", &port_id); if (ret) { /* only for old code compatible */ - ret = of_property_read_u32(node, "port-id", &port_id); + ret = device_property_read_u32(dev, "port-id", &port_id); if (ret) goto out_read_prop_fail; /* for old dts, we need to caculate the port offset */ From 72fdddcefe603b9b7de3f1d6177dd413eceacb93 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:14 +0800 Subject: [PATCH 06/13] net: hns: use platform_get_irq instead of irq_of_parse_and_map As irq_of_parse_and_map is only used by DT case, it is excepted to use a uniform interface. So it is used platform_get_irq() instead. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index 4ef6d23d998e3..3ce24097fcf44 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -458,7 +458,6 @@ void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common) u32 i; u32 ring_num = rcb_common->ring_num; int base_irq_idx = hns_rcb_get_base_irq_idx(rcb_common); - struct device_node *np = rcb_common->dsaf_dev->dev->of_node; struct platform_device *pdev = to_platform_device(rcb_common->dsaf_dev->dev); bool is_ver1 = AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver); @@ -473,10 +472,10 @@ void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common) ring_pair_cb->port_id_in_comm = hns_rcb_get_port_in_comm(rcb_common, i); ring_pair_cb->virq[HNS_RCB_IRQ_IDX_TX] = - is_ver1 ? irq_of_parse_and_map(np, base_irq_idx + i * 2) : + is_ver1 ? platform_get_irq(pdev, base_irq_idx + i * 2) : platform_get_irq(pdev, base_irq_idx + i * 3 + 1); ring_pair_cb->virq[HNS_RCB_IRQ_IDX_RX] = - is_ver1 ? irq_of_parse_and_map(np, base_irq_idx + i * 2 + 1) : + is_ver1 ? platform_get_irq(pdev, base_irq_idx + i * 2 + 1) : platform_get_irq(pdev, base_irq_idx + i * 3); ring_pair_cb->q.phy_base = RCB_COMM_BASE_TO_RING_BASE(rcb_common->phy_base, i); From 7b2acae6fb28f0b3d32c0620f8045c4a1bf5bb92 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:15 +0800 Subject: [PATCH 07/13] net: hns: enet specify a reference to dsaf by fwnode_handle As device_node is only used by DT case, it is expected to find uniform ways. So fwnode_handle is the suitable method. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.c | 12 ++++++------ drivers/net/ethernet/hisilicon/hns/hnae.h | 2 +- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 14 ++++++++------ drivers/net/ethernet/hisilicon/hns/hns_enet.h | 2 +- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c index 3bfe36f9405b6..d630acdb07495 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.c +++ b/drivers/net/ethernet/hisilicon/hns/hnae.c @@ -96,16 +96,16 @@ static int __ae_match(struct device *dev, const void *data) { struct hnae_ae_dev *hdev = cls_to_ae_dev(dev); - return hdev->dev->of_node == data; + return (data == &hdev->dev->of_node->fwnode); } -static struct hnae_ae_dev *find_ae(const struct device_node *ae_node) +static struct hnae_ae_dev *find_ae(const struct fwnode_handle *fwnode) { struct device *dev; - WARN_ON(!ae_node); + WARN_ON(!fwnode); - dev = class_find_device(hnae_class, NULL, ae_node, __ae_match); + dev = class_find_device(hnae_class, NULL, fwnode, __ae_match); return dev ? cls_to_ae_dev(dev) : NULL; } @@ -312,7 +312,7 @@ EXPORT_SYMBOL(hnae_reinit_handle); * return handle ptr or ERR_PTR */ struct hnae_handle *hnae_get_handle(struct device *owner_dev, - const struct device_node *ae_node, + const struct fwnode_handle *fwnode, u32 port_id, struct hnae_buf_ops *bops) { @@ -321,7 +321,7 @@ struct hnae_handle *hnae_get_handle(struct device *owner_dev, int i, j; int ret; - dev = find_ae(ae_node); + dev = find_ae(fwnode); if (!dev) return ERR_PTR(-ENODEV); diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index e8d36aaea2232..f5f814083809b 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -528,7 +528,7 @@ struct hnae_handle { #define ring_to_dev(ring) ((ring)->q->dev->dev) struct hnae_handle *hnae_get_handle(struct device *owner_dev, - const struct device_node *ae_node, + const struct fwnode_handle *fwnode, u32 port_id, struct hnae_buf_ops *bops); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 8851420567505..93f6ccbb64337 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1807,7 +1807,7 @@ static int hns_nic_try_get_ae(struct net_device *ndev) int ret; h = hnae_get_handle(&priv->netdev->dev, - priv->ae_node, priv->port_id, NULL); + priv->fwnode, priv->port_id, NULL); if (IS_ERR_OR_NULL(h)) { ret = -ENODEV; dev_dbg(priv->dev, "has not handle, register notifier!\n"); @@ -1867,7 +1867,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct net_device *ndev; struct hns_nic_priv *priv; - struct device_node *node = dev->of_node; + struct device_node *ae_node; u32 port_id; int ret; @@ -1881,17 +1881,19 @@ static int hns_nic_dev_probe(struct platform_device *pdev) priv->dev = dev; priv->netdev = ndev; - if (of_device_is_compatible(node, "hisilicon,hns-nic-v1")) + if (of_device_is_compatible(dev->of_node, "hisilicon,hns-nic-v1")) priv->enet_ver = AE_VERSION_1; else priv->enet_ver = AE_VERSION_2; - priv->ae_node = (void *)of_parse_phandle(node, "ae-handle", 0); - if (IS_ERR_OR_NULL(priv->ae_node)) { - ret = PTR_ERR(priv->ae_node); + ae_node = of_parse_phandle(dev->of_node, "ae-handle", 0); + if (IS_ERR_OR_NULL(ae_node)) { + ret = PTR_ERR(ae_node); dev_err(dev, "not find ae-handle\n"); goto out_read_prop_fail; } + priv->fwnode = &ae_node->fwnode; + /* try to find port-idx-in-ae first */ ret = device_property_read_u32(dev, "port-idx-in-ae", &port_id); if (ret) { diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.h b/drivers/net/ethernet/hisilicon/hns/hns_enet.h index 337efa582bace..44bb3015eed33 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.h @@ -54,7 +54,7 @@ struct hns_nic_ops { }; struct hns_nic_priv { - const struct device_node *ae_node; + const struct fwnode_handle *fwnode; u32 enet_ver; u32 port_id; int phy_mode; From 652d39b0d50a6e99495442431c8dadeb8c05c986 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:16 +0800 Subject: [PATCH 08/13] net: hns: add uniform interface for phy connection As device_node is only used by DT case, HNS needs to treat the other cases including ACPI. It needs to use uniform ways to handle both of DT and ACPI. This patch chooses phy_device, and of_phy_connect and of_phy_attach are only used by DT case. It needs to use uniform interface to handle that sequence by both DT and ACPI. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.c | 8 ++++- drivers/net/ethernet/hisilicon/hns/hnae.h | 3 +- .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 2 +- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 34 +++++++++++++------ .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 2 +- .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 2 +- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 21 +++++++----- .../net/ethernet/hisilicon/hns/hns_ethtool.c | 2 +- 8 files changed, 49 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c index d630acdb07495..5d3047cc83807 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.c +++ b/drivers/net/ethernet/hisilicon/hns/hnae.c @@ -96,7 +96,13 @@ static int __ae_match(struct device *dev, const void *data) { struct hnae_ae_dev *hdev = cls_to_ae_dev(dev); - return (data == &hdev->dev->of_node->fwnode); + if (dev_of_node(hdev->dev)) + return (data == &hdev->dev->of_node->fwnode); + else if (is_acpi_node(hdev->dev->fwnode)) + return (data == hdev->dev->fwnode); + + dev_err(dev, "__ae_match cannot read cfg data from OF or acpi\n"); + return 0; } static struct hnae_ae_dev *find_ae(const struct fwnode_handle *fwnode) diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index f5f814083809b..529cb1341270b 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -27,6 +27,7 @@ * "cb" means control block */ +#include #include #include #include @@ -512,7 +513,7 @@ struct hnae_ae_dev { struct hnae_handle { struct device *owner_dev; /* the device which make use of this handle */ struct hnae_ae_dev *dev; /* the device who provides this handle */ - struct device_node *phy_node; + struct phy_device *phy_dev; phy_interface_t phy_if; u32 if_support; int q_num; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 7a757e88c89a7..8e009f4f0ee73 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -131,7 +131,7 @@ struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, vf_cb->mac_cb = dsaf_dev->mac_cb[port_id]; ae_handle->phy_if = vf_cb->mac_cb->phy_if; - ae_handle->phy_node = vf_cb->mac_cb->phy_node; + ae_handle->phy_dev = vf_cb->mac_cb->phy_dev; ae_handle->if_support = vf_cb->mac_cb->if_support; ae_handle->port_type = vf_cb->mac_cb->mac_type; ae_handle->dport_id = port_id; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 611581fccf2a4..527b49d3749e8 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -15,7 +15,8 @@ #include #include #include -#include +#include +#include #include #include "hns_dsaf_main.h" @@ -645,7 +646,7 @@ static int hns_mac_init_ex(struct hns_mac_cb *mac_cb) */ 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,21 +673,34 @@ 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); + mac_cb->mac_id, np->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) + 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) { + 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); + mac_cb->mac_id, np->name); + } + syscon = syscon_node_to_regmap( of_parse_phandle(to_of_node(mac_cb->fw_port), "serdes-syscon", 0)); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index 97ce9a750aaf4..89b49d7fa20fb 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -338,7 +338,7 @@ struct hns_mac_cb { phy_interface_t phy_if; enum hnae_loop loop_mode; - struct device_node *phy_node; + struct phy_device *phy_dev; struct mac_hw_stats hw_stats; }; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index a837bb9e3839f..a843a866455db 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -332,7 +332,7 @@ int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en) int sfp_prsnt; int ret = hns_mac_get_sfp_prsnt(mac_cb, &sfp_prsnt); - if (!mac_cb->phy_node) { + if (!mac_cb->phy_dev) { if (ret) pr_info("please confirm sfp is present or not\n"); else diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 93f6ccbb64337..3ec3c27983798 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -996,19 +996,22 @@ static void hns_nic_adjust_link(struct net_device *ndev) int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h) { struct hns_nic_priv *priv = netdev_priv(ndev); - struct phy_device *phy_dev = NULL; + struct phy_device *phy_dev = h->phy_dev; + int ret; - if (!h->phy_node) + if (!h->phy_dev) return 0; - if (h->phy_if != PHY_INTERFACE_MODE_XGMII) - phy_dev = of_phy_connect(ndev, h->phy_node, - hns_nic_adjust_link, 0, h->phy_if); - else - phy_dev = of_phy_attach(ndev, h->phy_node, 0, h->phy_if); + if (h->phy_if != PHY_INTERFACE_MODE_XGMII) { + phy_dev->dev_flags = 0; - if (unlikely(!phy_dev) || IS_ERR(phy_dev)) - return !phy_dev ? -ENODEV : PTR_ERR(phy_dev); + ret = phy_connect_direct(ndev, phy_dev, hns_nic_adjust_link, + h->phy_if); + } else { + ret = phy_attach_direct(ndev, phy_dev, 0, h->phy_if); + } + if (unlikely(ret)) + return -ENODEV; phy_dev->supported &= h->if_support; phy_dev->advertising = phy_dev->supported; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 67a648c7d3a9e..a809f52f6c16c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -596,7 +596,7 @@ static void hns_nic_self_test(struct net_device *ndev, st_param[1][0] = MAC_INTERNALLOOP_SERDES; st_param[1][1] = 1; /*serdes must exist*/ st_param[2][0] = MAC_INTERNALLOOP_PHY; /* only supporte phy node*/ - st_param[2][1] = ((!!(priv->ae_handle->phy_node)) && + st_param[2][1] = ((!!(priv->ae_handle->phy_dev)) && (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)); if (eth_test->flags == ETH_TEST_FL_OFFLINE) { From a24274aa5c2328a6ef4296d1ca8e81648cd0ddda Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:17 +0800 Subject: [PATCH 09/13] net: hns: add dsaf misc operation method The misc operation for different hw platform may be different, if using current implementation, it will add a new branch on each function for every new hw platform, so we add a method for this operation. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 4 +- .../ethernet/hisilicon/hns/hns_dsaf_gmac.c | 6 +- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 14 ++-- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 2 - .../ethernet/hisilicon/hns/hns_dsaf_main.c | 11 ++- .../ethernet/hisilicon/hns/hns_dsaf_main.h | 33 +++++--- .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 79 +++++++++++++------ .../ethernet/hisilicon/hns/hns_dsaf_misc.h | 7 +- .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 15 ++-- .../ethernet/hisilicon/hns/hns_dsaf_xgmac.c | 10 +-- 10 files changed, 111 insertions(+), 70 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 8e009f4f0ee73..d37b778b4a1b7 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -637,13 +637,15 @@ static int hns_ae_config_loopback(struct hnae_handle *handle, int ret; struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; switch (loop) { case MAC_INTERNALLOOP_PHY: ret = 0; break; case MAC_INTERNALLOOP_SERDES: - ret = hns_mac_config_sds_loopback(vf_cb->mac_cb, en); + ret = dsaf_dev->misc_op->cfg_serdes_loopback(vf_cb->mac_cb, + !!en); break; case MAC_INTERNALLOOP_MAC: ret = hns_mac_config_mac_loopback(vf_cb->mac_cb, loop, en); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c index 44abb08de155c..1235c7f2564bd 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c @@ -110,7 +110,7 @@ static void hns_gmac_free(void *mac_drv) u32 mac_id = drv->mac_id; - hns_dsaf_ge_srst_by_port(dsaf_dev, mac_id, 0); + dsaf_dev->misc_op->ge_srst(dsaf_dev, mac_id, 0); } static void hns_gmac_set_tx_auto_pause_frames(void *mac_drv, u16 newval) @@ -317,9 +317,9 @@ static void hns_gmac_init(void *mac_drv) port = drv->mac_id; - hns_dsaf_ge_srst_by_port(dsaf_dev, port, 0); + dsaf_dev->misc_op->ge_srst(dsaf_dev, port, 0); mdelay(10); - hns_dsaf_ge_srst_by_port(dsaf_dev, port, 1); + dsaf_dev->misc_op->ge_srst(dsaf_dev, port, 1); mdelay(10); hns_gmac_disable(mac_drv, MAC_COMM_MODE_RX_AND_TX); hns_gmac_tx_loop_pkt_dis(mac_drv); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 527b49d3749e8..2ebf14ad71988 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -95,7 +95,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; @@ -512,7 +512,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); } /** @@ -804,7 +804,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) { @@ -819,7 +819,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; @@ -906,7 +906,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; } } @@ -989,7 +989,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); } @@ -999,5 +999,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); } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index 89b49d7fa20fb..05a6e8f7a4198 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -448,8 +448,6 @@ int hns_mac_set_pauseparam(struct hns_mac_cb *mac_cb, u32 rx_en, u32 tx_en); int hns_mac_set_mtu(struct hns_mac_cb *mac_cb, u32 new_mtu); int hns_mac_get_port_info(struct hns_mac_cb *mac_cb, u8 *auto_neg, u16 *speed, u8 *duplex); -phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb); -int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en); int hns_mac_config_mac_loopback(struct hns_mac_cb *mac_cb, enum hnae_loop loop, int en); void hns_mac_update_stats(struct hns_mac_cb *mac_cb); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 9afc5e665985a..28bde08385a1c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -24,6 +24,7 @@ #include "hns_dsaf_main.h" #include "hns_dsaf_ppe.h" #include "hns_dsaf_rcb.h" +#include "hns_dsaf_misc.h" const char *g_dsaf_mode_match[DSAF_MODE_MAX] = { [DSAF_MODE_DISABLE_2PORT_64VM] = "2port-64vf", @@ -174,6 +175,10 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) goto unmap_base_addr; } + dsaf_dev->misc_op = hns_misc_op_get(dsaf_dev); + if (!dsaf_dev->misc_op) + return -ENOMEM; + if (!dma_set_mask_and_coherent(dsaf_dev->dev, DMA_BIT_MASK(64ULL))) dev_dbg(dsaf_dev->dev, "set mask to 64bit\n"); else @@ -1296,9 +1301,9 @@ static int hns_dsaf_init_hw(struct dsaf_device *dsaf_dev) dev_dbg(dsaf_dev->dev, "hns_dsaf_init_hw begin %s !\n", dsaf_dev->ae_dev.name); - hns_dsaf_rst(dsaf_dev, 0); + dsaf_dev->misc_op->dsaf_reset(dsaf_dev, 0); mdelay(10); - hns_dsaf_rst(dsaf_dev, 1); + dsaf_dev->misc_op->dsaf_reset(dsaf_dev, 1); hns_dsaf_comm_init(dsaf_dev); @@ -1326,7 +1331,7 @@ static int hns_dsaf_init_hw(struct dsaf_device *dsaf_dev) static void hns_dsaf_remove_hw(struct dsaf_device *dsaf_dev) { /*reset*/ - hns_dsaf_rst(dsaf_dev, 0); + dsaf_dev->misc_op->dsaf_reset(dsaf_dev, 0); } /** diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index f0502ba0a6776..2e55b3cc45153 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -268,6 +268,27 @@ struct dsaf_int_stat { }; +struct dsaf_misc_op { + void (*cpld_set_led)(struct hns_mac_cb *mac_cb, int link_status, + u16 speed, int data); + void (*cpld_reset_led)(struct hns_mac_cb *mac_cb); + int (*cpld_set_led_id)(struct hns_mac_cb *mac_cb, + enum hnae_led_state status); + /* reset seris function, it will be reset if the dereseet is 0 */ + void (*dsaf_reset)(struct dsaf_device *dsaf_dev, bool dereset); + void (*xge_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset); + void (*xge_core_srst)(struct dsaf_device *dsaf_dev, u32 port, + bool dereset); + void (*ge_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset); + void (*ppe_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset); + void (*ppe_comm_srst)(struct dsaf_device *dsaf_dev, bool dereset); + + phy_interface_t (*get_phy_if)(struct hns_mac_cb *mac_cb); + int (*get_sfp_prsnt)(struct hns_mac_cb *mac_cb, int *sfp_prsnt); + + int (*cfg_serdes_loopback)(struct hns_mac_cb *mac_cb, bool en); +}; + /* Dsaf device struct define ,and mac -> dsaf */ struct dsaf_device { struct device *dev; @@ -292,6 +313,7 @@ struct dsaf_device { struct ppe_common_cb *ppe_common[DSAF_COMM_DEV_NUM]; struct rcb_common_cb *rcb_common[DSAF_COMM_DEV_NUM]; struct hns_mac_cb *mac_cb[DSAF_MAX_PORT_NUM]; + struct dsaf_misc_op *misc_op; struct dsaf_hw_stats hw_stats[DSAF_NODE_NUM]; struct dsaf_int_stat int_stat; @@ -388,22 +410,11 @@ int hns_dsaf_get_mac_entry_by_index( u16 entry_index, struct dsaf_drv_mac_multi_dest_entry *mac_entry); -void hns_dsaf_rst(struct dsaf_device *dsaf_dev, u32 val); - -void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val); - -void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val); - void hns_dsaf_fix_mac_mode(struct hns_mac_cb *mac_cb); int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev); void hns_dsaf_ae_uninit(struct dsaf_device *dsaf_dev); -void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val); -void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val); -void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, - u32 port, u32 val); - void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 inode_num); int hns_dsaf_get_sset_count(int stringset); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index a843a866455db..e1c3e0d18ff02 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -32,8 +32,8 @@ static u32 dsaf_read_sub(struct dsaf_device *dsaf_dev, u32 reg) return ret; } -void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, - u16 speed, int data) +static void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, + u16 speed, int data) { int speed_reg = 0; u8 value; @@ -71,7 +71,7 @@ void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, } } -void cpld_led_reset(struct hns_mac_cb *mac_cb) +static void cpld_led_reset(struct hns_mac_cb *mac_cb) { if (!mac_cb || !mac_cb->cpld_ctrl) return; @@ -81,8 +81,8 @@ void cpld_led_reset(struct hns_mac_cb *mac_cb) mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE; } -int cpld_set_led_id(struct hns_mac_cb *mac_cb, - enum hnae_led_state status) +static int cpld_set_led_id(struct hns_mac_cb *mac_cb, + enum hnae_led_state status) { switch (status) { case HNAE_LED_ACTIVE: @@ -109,12 +109,12 @@ int cpld_set_led_id(struct hns_mac_cb *mac_cb, #define RESET_REQ_OR_DREQ 1 -void hns_dsaf_rst(struct dsaf_device *dsaf_dev, u32 val) +static void hns_dsaf_rst(struct dsaf_device *dsaf_dev, bool dereset) { u32 xbar_reg_addr; u32 nt_reg_addr; - if (!val) { + if (!dereset) { xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_REQ_REG; nt_reg_addr = DSAF_SUB_SC_NT_RESET_REQ_REG; } else { @@ -126,7 +126,8 @@ void hns_dsaf_rst(struct dsaf_device *dsaf_dev, u32 val) dsaf_write_sub(dsaf_dev, nt_reg_addr, RESET_REQ_OR_DREQ); } -void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) +static void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, + bool dereset) { u32 reg_val = 0; u32 reg_addr; @@ -137,7 +138,7 @@ void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) reg_val |= RESET_REQ_OR_DREQ; reg_val |= 0x2082082 << dsaf_dev->mac_cb[port]->port_rst_off; - if (val == 0) + if (!dereset) reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; else reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; @@ -145,8 +146,8 @@ void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) dsaf_write_sub(dsaf_dev, reg_addr, reg_val); } -void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, - u32 port, u32 val) +static void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, + u32 port, bool dereset) { u32 reg_val = 0; u32 reg_addr; @@ -157,7 +158,7 @@ void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, reg_val |= XGMAC_TRX_CORE_SRST_M << dsaf_dev->mac_cb[port]->port_rst_off; - if (val == 0) + if (!dereset) reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; else reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; @@ -165,7 +166,8 @@ void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, dsaf_write_sub(dsaf_dev, reg_addr, reg_val); } -void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) +static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, + bool dereset) { u32 reg_val_1; u32 reg_val_2; @@ -183,7 +185,7 @@ void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) else reg_val_2 = 0x2082082 << port_rst_off; - if (val == 0) { + if (!dereset) { dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_REQ1_REG, reg_val_1); @@ -200,7 +202,7 @@ void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) reg_val_1 = 0x15540 << dsaf_dev->reset_offset; reg_val_2 = 0x100 << dsaf_dev->reset_offset; - if (val == 0) { + if (!dereset) { dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_REQ1_REG, reg_val_1); @@ -216,14 +218,15 @@ void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) } } -void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) +static void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, + bool dereset) { u32 reg_val = 0; u32 reg_addr; reg_val |= RESET_REQ_OR_DREQ << dsaf_dev->mac_cb[port]->port_rst_off; - if (val == 0) + if (!dereset) reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; else reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; @@ -231,15 +234,14 @@ void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) dsaf_write_sub(dsaf_dev, reg_addr, reg_val); } -void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) +static void hns_ppe_com_srst(struct dsaf_device *dsaf_dev, bool dereset) { - struct dsaf_device *dsaf_dev = ppe_common->dsaf_dev; u32 reg_val; u32 reg_addr; if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { reg_val = RESET_REQ_OR_DREQ; - if (val == 0) + if (!dereset) reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_REQ_REG; else reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_DREQ_REG; @@ -247,7 +249,7 @@ void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) } else { reg_val = 0x100 << dsaf_dev->reset_offset; - if (val == 0) + if (!dereset) reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; else reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; @@ -261,7 +263,7 @@ void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) * @mac_cb: mac control block * retuen phy interface */ -phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) +static phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) { u32 mode; u32 reg; @@ -309,7 +311,7 @@ int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt) * @mac_cb: mac control block * retuen 0 == success */ -int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en) +static int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, bool en) { /* port 0-3 hilink4 base is serdes_vaddr + 0x00280000 * port 4-7 hilink3 base is serdes_vaddr + 0x00200000 @@ -343,11 +345,38 @@ int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en) if (mac_cb->serdes_ctrl) { u32 origin = dsaf_read_syscon(mac_cb->serdes_ctrl, reg_offset); - dsaf_set_field(origin, 1ull << 10, 10, !!en); + dsaf_set_field(origin, 1ull << 10, 10, en); dsaf_write_syscon(mac_cb->serdes_ctrl, reg_offset, origin); } else { - dsaf_set_reg_field(base_addr, reg_offset, 1ull << 10, 10, !!en); + dsaf_set_reg_field(base_addr, reg_offset, 1ull << 10, 10, en); } return 0; } + +struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev) +{ + struct dsaf_misc_op *misc_op; + + misc_op = devm_kzalloc(dsaf_dev->dev, sizeof(*misc_op), GFP_KERNEL); + if (!misc_op) + return NULL; + + misc_op->cpld_set_led = hns_cpld_set_led; + misc_op->cpld_reset_led = cpld_led_reset; + misc_op->cpld_set_led_id = cpld_set_led_id; + + misc_op->dsaf_reset = hns_dsaf_rst; + misc_op->xge_srst = hns_dsaf_xge_srst_by_port; + misc_op->xge_core_srst = hns_dsaf_xge_core_srst_by_port; + misc_op->ge_srst = hns_dsaf_ge_srst_by_port; + misc_op->ppe_srst = hns_ppe_srst_by_port; + misc_op->ppe_comm_srst = hns_ppe_com_srst; + + misc_op->get_phy_if = hns_mac_get_phy_if; + misc_op->get_sfp_prsnt = hns_mac_get_sfp_prsnt; + + misc_op->cfg_serdes_loopback = hns_mac_config_sds_loopback; + + return (void *)misc_op; +} diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h index 419f07aa97341..f06bb03d47a6e 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h @@ -33,11 +33,6 @@ #define DSAF_LED_DATA_B 4 #define DSAF_LED_ANCHOR_B 5 -void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, - u16 speed, int data); -void cpld_led_reset(struct hns_mac_cb *mac_cb); -int cpld_set_led_id(struct hns_mac_cb *mac_cb, - enum hnae_led_state status); -int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt); +struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev); #endif diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c index 8cd151a5245ea..ff8b6a468b248 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c @@ -112,7 +112,6 @@ void hns_ppe_common_free_cfg(struct dsaf_device *dsaf_dev, u32 comm_index) static void __iomem *hns_ppe_get_iobase(struct ppe_common_cb *ppe_common, int ppe_idx) { - return ppe_common->dsaf_dev->ppe_base + ppe_idx * PPE_REG_OFFSET; } @@ -200,11 +199,12 @@ static void hns_ppe_set_port_mode(struct hns_ppe_cb *ppe_cb, static int hns_ppe_common_init_hw(struct ppe_common_cb *ppe_common) { enum ppe_qid_mode qid_mode; - enum dsaf_mode dsaf_mode = ppe_common->dsaf_dev->dsaf_mode; + struct dsaf_device *dsaf_dev = ppe_common->dsaf_dev; + enum dsaf_mode dsaf_mode = dsaf_dev->dsaf_mode; - hns_ppe_com_srst(ppe_common, 0); + dsaf_dev->misc_op->ppe_comm_srst(dsaf_dev, 0); mdelay(100); - hns_ppe_com_srst(ppe_common, 1); + dsaf_dev->misc_op->ppe_comm_srst(dsaf_dev, 1); mdelay(100); if (ppe_common->ppe_mode == PPE_COMMON_MODE_SERVICE) { @@ -288,9 +288,9 @@ static void hns_ppe_init_hw(struct hns_ppe_cb *ppe_cb) /* get default RSS key */ netdev_rss_key_fill(ppe_cb->rss_key, HNS_PPEV2_RSS_KEY_SIZE); - hns_ppe_srst_by_port(dsaf_dev, port, 0); + dsaf_dev->misc_op->ppe_srst(dsaf_dev, port, 0); mdelay(10); - hns_ppe_srst_by_port(dsaf_dev, port, 1); + dsaf_dev->misc_op->ppe_srst(dsaf_dev, port, 1); /* clr and msk except irq*/ hns_ppe_exc_irq_en(ppe_cb, 0); @@ -328,10 +328,11 @@ static void hns_ppe_init_hw(struct hns_ppe_cb *ppe_cb) static void hns_ppe_uninit_hw(struct hns_ppe_cb *ppe_cb) { u32 port; + struct dsaf_device *dsaf_dev = ppe_cb->ppe_common_cb->dsaf_dev; if (ppe_cb->ppe_common_cb) { port = ppe_cb->index; - hns_ppe_srst_by_port(ppe_cb->ppe_common_cb->dsaf_dev, port, 0); + dsaf_dev->misc_op->ppe_srst(dsaf_dev, port, 0); } } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c index fd90f3737963b..8f4f0e8da984d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c @@ -119,7 +119,7 @@ static void hns_xgmac_enable(void *mac_drv, enum mac_commom_mode mode) = (struct dsaf_device *)dev_get_drvdata(drv->dev); u32 port = drv->mac_id; - hns_dsaf_xge_core_srst_by_port(dsaf_dev, port, 1); + dsaf_dev->misc_op->xge_core_srst(dsaf_dev, port, 1); mdelay(10); /*enable XGE rX/tX */ @@ -157,7 +157,7 @@ static void hns_xgmac_disable(void *mac_drv, enum mac_commom_mode mode) } mdelay(10); - hns_dsaf_xge_core_srst_by_port(dsaf_dev, port, 0); + dsaf_dev->misc_op->xge_core_srst(dsaf_dev, port, 0); } /** @@ -198,9 +198,9 @@ static void hns_xgmac_init(void *mac_drv) = (struct dsaf_device *)dev_get_drvdata(drv->dev); u32 port = drv->mac_id; - hns_dsaf_xge_srst_by_port(dsaf_dev, port, 0); + dsaf_dev->misc_op->xge_srst(dsaf_dev, port, 0); mdelay(100); - hns_dsaf_xge_srst_by_port(dsaf_dev, port, 1); + dsaf_dev->misc_op->xge_srst(dsaf_dev, port, 1); mdelay(100); hns_xgmac_exc_irq_en(drv, 0); @@ -425,7 +425,7 @@ static void hns_xgmac_free(void *mac_drv) u32 mac_id = drv->mac_id; - hns_dsaf_xge_srst_by_port(dsaf_dev, mac_id, 0); + dsaf_dev->misc_op->xge_srst(dsaf_dev, mac_id, 0); } /** From 8413b3be4d77dae0d0203cc8b6f2b928dda66e7e Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:18 +0800 Subject: [PATCH 10/13] net: hns: dsaf adds support of acpi Dsaf needs to get configuration parameter by ACPI, so this patch add support of ACPI. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 80 ++++++++--------- .../ethernet/hisilicon/hns/hns_dsaf_main.c | 85 +++++++++++++------ .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 32 +++---- 3 files changed, 114 insertions(+), 83 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 2ebf14ad71988..3ef0c9b185111 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -689,9 +689,7 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) return 0; } - if (!is_of_node(mac_cb->fw_port)) - return -EINVAL; - + 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); @@ -701,47 +699,49 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) mac_cb->mac_id, np->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; - - 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); - } + 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; - 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 = 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 = 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); - if (IS_ERR_OR_NULL(syscon)) { - dev_dbg(mac_cb->dev, "no cpld-syscon found!\n"); + 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]; + } } } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 28bde08385a1c..ac03c4a53e08f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -7,6 +7,7 @@ * (at your option) any later version. */ +#include #include #include #include @@ -33,6 +34,13 @@ const char *g_dsaf_mode_match[DSAF_MODE_MAX] = { [DSAF_MODE_DISABLE_SP] = "single-port", }; +static const struct acpi_device_id hns_dsaf_acpi_match[] = { + { "HISI00B1", 0 }, + { "HISI00B2", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, hns_dsaf_acpi_match); + int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) { int ret, i; @@ -46,10 +54,22 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) struct device_node *np = dsaf_dev->dev->of_node; struct platform_device *pdev = to_platform_device(dsaf_dev->dev); - if (of_device_is_compatible(np, "hisilicon,hns-dsaf-v1")) - dsaf_dev->dsaf_ver = AE_VERSION_1; - else - dsaf_dev->dsaf_ver = AE_VERSION_2; + if (dev_of_node(dsaf_dev->dev)) { + if (of_device_is_compatible(np, "hisilicon,hns-dsaf-v1")) + dsaf_dev->dsaf_ver = AE_VERSION_1; + else + dsaf_dev->dsaf_ver = AE_VERSION_2; + } else if (is_acpi_node(dsaf_dev->dev->fwnode)) { + if (acpi_dev_found(hns_dsaf_acpi_match[0].id)) + dsaf_dev->dsaf_ver = AE_VERSION_1; + else if (acpi_dev_found(hns_dsaf_acpi_match[1].id)) + dsaf_dev->dsaf_ver = AE_VERSION_2; + else + return -ENXIO; + } else { + dev_err(dsaf_dev->dev, "cannot get cfg data from of or acpi\n"); + return -ENXIO; + } ret = device_property_read_string(dsaf_dev->dev, "mode", &mode_str); if (ret) { @@ -81,32 +101,40 @@ int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) else dsaf_dev->dsaf_tc_mode = HRD_DSAF_4TC_MODE; - syscon = syscon_node_to_regmap( - of_parse_phandle(np, "subctrl-syscon", 0)); - if (IS_ERR_OR_NULL(syscon)) { - res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx++); - if (!res) { - dev_err(dsaf_dev->dev, "subctrl info is needed!\n"); - return -ENOMEM; - } - dsaf_dev->sc_base = devm_ioremap_resource(&pdev->dev, res); - if (!dsaf_dev->sc_base) { - dev_err(dsaf_dev->dev, "subctrl can not map!\n"); - return -ENOMEM; - } + if (dev_of_node(dsaf_dev->dev)) { + syscon = syscon_node_to_regmap( + of_parse_phandle(np, "subctrl-syscon", 0)); + if (IS_ERR_OR_NULL(syscon)) { + res = platform_get_resource(pdev, IORESOURCE_MEM, + res_idx++); + if (!res) { + dev_err(dsaf_dev->dev, "subctrl info is needed!\n"); + return -ENOMEM; + } - res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx++); - if (!res) { - dev_err(dsaf_dev->dev, "serdes-ctrl info is needed!\n"); - return -ENOMEM; - } - dsaf_dev->sds_base = devm_ioremap_resource(&pdev->dev, res); - if (!dsaf_dev->sds_base) { - dev_err(dsaf_dev->dev, "serdes-ctrl can not map!\n"); - return -ENOMEM; + dsaf_dev->sc_base = devm_ioremap_resource(&pdev->dev, + res); + if (!dsaf_dev->sc_base) { + dev_err(dsaf_dev->dev, "subctrl can not map!\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, + res_idx++); + if (!res) { + dev_err(dsaf_dev->dev, "serdes-ctrl info is needed!\n"); + return -ENOMEM; + } + + dsaf_dev->sds_base = devm_ioremap_resource(&pdev->dev, + res); + if (!dsaf_dev->sds_base) { + dev_err(dsaf_dev->dev, "serdes-ctrl can not map!\n"); + return -ENOMEM; + } + } else { + dsaf_dev->sub_ctrl = syscon; } - } else { - dsaf_dev->sub_ctrl = syscon; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ppe-base"); @@ -2686,6 +2714,7 @@ static struct platform_driver g_dsaf_driver = { .driver = { .name = DSAF_DRV_NAME, .of_match_table = g_dsaf_match, + .acpi_match_table = hns_dsaf_acpi_match, }, }; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index e1c3e0d18ff02..f21177bdfb66d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -362,21 +362,23 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev) if (!misc_op) return NULL; - misc_op->cpld_set_led = hns_cpld_set_led; - misc_op->cpld_reset_led = cpld_led_reset; - misc_op->cpld_set_led_id = cpld_set_led_id; - - misc_op->dsaf_reset = hns_dsaf_rst; - misc_op->xge_srst = hns_dsaf_xge_srst_by_port; - misc_op->xge_core_srst = hns_dsaf_xge_core_srst_by_port; - misc_op->ge_srst = hns_dsaf_ge_srst_by_port; - misc_op->ppe_srst = hns_ppe_srst_by_port; - misc_op->ppe_comm_srst = hns_ppe_com_srst; - - misc_op->get_phy_if = hns_mac_get_phy_if; - misc_op->get_sfp_prsnt = hns_mac_get_sfp_prsnt; - - misc_op->cfg_serdes_loopback = hns_mac_config_sds_loopback; + if (dev_of_node(dsaf_dev->dev)) { + misc_op->cpld_set_led = hns_cpld_set_led; + misc_op->cpld_reset_led = cpld_led_reset; + misc_op->cpld_set_led_id = cpld_set_led_id; + + misc_op->dsaf_reset = hns_dsaf_rst; + misc_op->xge_srst = hns_dsaf_xge_srst_by_port; + misc_op->xge_core_srst = hns_dsaf_xge_core_srst_by_port; + misc_op->ge_srst = hns_dsaf_ge_srst_by_port; + misc_op->ppe_srst = hns_ppe_srst_by_port; + misc_op->ppe_comm_srst = hns_ppe_com_srst; + + misc_op->get_phy_if = hns_mac_get_phy_if; + misc_op->get_sfp_prsnt = hns_mac_get_sfp_prsnt; + + misc_op->cfg_serdes_loopback = hns_mac_config_sds_loopback; + } return (void *)misc_op; } From 1d1afa2ebf8234cbeafd719cf964d7d4f4d6ac96 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:19 +0800 Subject: [PATCH 11/13] net: hns: register phy device in each mac initial sequence In ACPI case, there is no interface to register phy device to mdio-bus. Phy device has to be registered itself to mdio-bus, and then enet can get the phy device's info so that it can config the phy-device to help to trasmit and receive data. HNS hardware topology is as below. The MDIO controller may control several PHY-devices, and each PHY-device connects to a MAC device. PHY-devices will register when each mac find PHY device in initial sequence. cpu | | ------------------------------------------- | | | | | | | dsaf | MDIO | MDIO | --------------------------- | | | | | | | | | | | | | | MAC MAC MAC MAC | | | | | | | ---- |-------- |-------- | | -------- || || || || PHY PHY PHY PHY Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 133 +++++++++++++++++- 1 file changed, 126 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 3ef0c9b185111..c526558e63673 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -7,6 +7,7 @@ * (at your option) any later version. */ +#include #include #include #include @@ -638,6 +639,115 @@ static int hns_mac_init_ex(struct hns_mac_cb *mac_cb) 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 @@ -690,13 +800,17 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) } 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) { - 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); + /* 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); } syscon = syscon_node_to_regmap( @@ -743,6 +857,11 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) 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; From f00ef863da2b59313c466d2c826d2e8c28157d36 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:20 +0800 Subject: [PATCH 12/13] net: hns: implement the miscellaneous operation by asl The miscellaneous operation is implemented in BIOS, the kernel can call _DSM method help to call the implementation in ACPI case. Here is a patch to do that. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index f21177bdfb66d..96cb628a7c5f6 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -12,6 +12,27 @@ #include "hns_dsaf_ppe.h" #include "hns_dsaf_reg.h" +enum _dsm_op_index { + HNS_OP_RESET_FUNC = 0x1, + HNS_OP_SERDES_LP_FUNC = 0x2, + HNS_OP_LED_SET_FUNC = 0x3, + HNS_OP_GET_PORT_TYPE_FUNC = 0x4, + HNS_OP_GET_SFP_STAT_FUNC = 0x5, +}; + +enum _dsm_rst_type { + HNS_DSAF_RESET_FUNC = 0x1, + HNS_PPE_RESET_FUNC = 0x2, + HNS_XGE_CORE_RESET_FUNC = 0x3, + HNS_XGE_RESET_FUNC = 0x4, + HNS_GE_RESET_FUNC = 0x5, +}; + +const u8 hns_dsaf_acpi_dsm_uuid[] = { + 0x1A, 0xAA, 0x85, 0x1A, 0x93, 0xE2, 0x5E, 0x41, + 0x8E, 0x28, 0x8D, 0x69, 0x0A, 0x0F, 0x82, 0x0A +}; + static void dsaf_write_sub(struct dsaf_device *dsaf_dev, u32 reg, u32 val) { if (dsaf_dev->sub_ctrl) @@ -109,6 +130,34 @@ static int cpld_set_led_id(struct hns_mac_cb *mac_cb, #define RESET_REQ_OR_DREQ 1 +static void hns_dsaf_acpi_srst_by_port(struct dsaf_device *dsaf_dev, u8 op_type, + u32 port_type, u32 port, u32 val) +{ + union acpi_object *obj; + union acpi_object obj_args[3], argv4; + + obj_args[0].integer.type = ACPI_TYPE_INTEGER; + obj_args[0].integer.value = port_type; + obj_args[1].integer.type = ACPI_TYPE_INTEGER; + obj_args[1].integer.value = port; + obj_args[2].integer.type = ACPI_TYPE_INTEGER; + obj_args[2].integer.value = val; + + argv4.type = ACPI_TYPE_PACKAGE; + argv4.package.count = 3; + argv4.package.elements = obj_args; + + obj = acpi_evaluate_dsm(ACPI_HANDLE(dsaf_dev->dev), + hns_dsaf_acpi_dsm_uuid, 0, op_type, &argv4); + if (!obj) { + dev_warn(dsaf_dev->dev, "reset port_type%d port%d fail!", + port_type, port); + return; + } + + ACPI_FREE(obj); +} + static void hns_dsaf_rst(struct dsaf_device *dsaf_dev, bool dereset) { u32 xbar_reg_addr; @@ -126,6 +175,13 @@ static void hns_dsaf_rst(struct dsaf_device *dsaf_dev, bool dereset) dsaf_write_sub(dsaf_dev, nt_reg_addr, RESET_REQ_OR_DREQ); } +static void hns_dsaf_rst_acpi(struct dsaf_device *dsaf_dev, bool dereset) +{ + hns_dsaf_acpi_srst_by_port(dsaf_dev, HNS_OP_RESET_FUNC, + HNS_DSAF_RESET_FUNC, + 0, dereset); +} + static void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, bool dereset) { @@ -146,6 +202,13 @@ static void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, dsaf_write_sub(dsaf_dev, reg_addr, reg_val); } +static void hns_dsaf_xge_srst_by_port_acpi(struct dsaf_device *dsaf_dev, + u32 port, bool dereset) +{ + hns_dsaf_acpi_srst_by_port(dsaf_dev, HNS_OP_RESET_FUNC, + HNS_XGE_RESET_FUNC, port, dereset); +} + static void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, bool dereset) { @@ -166,6 +229,14 @@ static void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, dsaf_write_sub(dsaf_dev, reg_addr, reg_val); } +static void +hns_dsaf_xge_core_srst_by_port_acpi(struct dsaf_device *dsaf_dev, + u32 port, bool dereset) +{ + hns_dsaf_acpi_srst_by_port(dsaf_dev, HNS_OP_RESET_FUNC, + HNS_XGE_CORE_RESET_FUNC, port, dereset); +} + static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, bool dereset) { @@ -218,6 +289,13 @@ static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, } } +static void hns_dsaf_ge_srst_by_port_acpi(struct dsaf_device *dsaf_dev, + u32 port, bool dereset) +{ + hns_dsaf_acpi_srst_by_port(dsaf_dev, HNS_OP_RESET_FUNC, + HNS_GE_RESET_FUNC, port, dereset); +} + static void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, bool dereset) { @@ -234,11 +312,21 @@ static void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, dsaf_write_sub(dsaf_dev, reg_addr, reg_val); } +static void +hns_ppe_srst_by_port_acpi(struct dsaf_device *dsaf_dev, u32 port, bool dereset) +{ + hns_dsaf_acpi_srst_by_port(dsaf_dev, HNS_OP_RESET_FUNC, + HNS_PPE_RESET_FUNC, port, dereset); +} + static void hns_ppe_com_srst(struct dsaf_device *dsaf_dev, bool dereset) { u32 reg_val; u32 reg_addr; + if (!(dev_of_node(dsaf_dev->dev))) + return; + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { reg_val = RESET_REQ_OR_DREQ; if (!dereset) @@ -295,6 +383,36 @@ static phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) return phy_if; } +static phy_interface_t hns_mac_get_phy_if_acpi(struct hns_mac_cb *mac_cb) +{ + phy_interface_t phy_if = PHY_INTERFACE_MODE_NA; + union acpi_object *obj; + union acpi_object obj_args, argv4; + + obj_args.integer.type = ACPI_TYPE_INTEGER; + obj_args.integer.value = mac_cb->mac_id; + + argv4.type = ACPI_TYPE_PACKAGE, + argv4.package.count = 1, + argv4.package.elements = &obj_args, + + obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dev), + hns_dsaf_acpi_dsm_uuid, 0, + HNS_OP_GET_PORT_TYPE_FUNC, &argv4); + + if (!obj || obj->type != ACPI_TYPE_INTEGER) + return phy_if; + + phy_if = obj->integer.value ? + PHY_INTERFACE_MODE_XGMII : PHY_INTERFACE_MODE_SGMII; + + dev_dbg(mac_cb->dev, "mac_id=%d, phy_if=%d\n", mac_cb->mac_id, phy_if); + + ACPI_FREE(obj); + + return phy_if; +} + int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt) { if (!mac_cb->cpld_ctrl) @@ -354,6 +472,36 @@ static int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, bool en) return 0; } +static int +hns_mac_config_sds_loopback_acpi(struct hns_mac_cb *mac_cb, bool en) +{ + union acpi_object *obj; + union acpi_object obj_args[3], argv4; + + obj_args[0].integer.type = ACPI_TYPE_INTEGER; + obj_args[0].integer.value = mac_cb->mac_id; + obj_args[1].integer.type = ACPI_TYPE_INTEGER; + obj_args[1].integer.value = !!en; + + argv4.type = ACPI_TYPE_PACKAGE; + argv4.package.count = 2; + argv4.package.elements = obj_args; + + obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dsaf_dev->dev), + hns_dsaf_acpi_dsm_uuid, 0, + HNS_OP_SERDES_LP_FUNC, &argv4); + if (!obj) { + dev_warn(mac_cb->dsaf_dev->dev, "set port%d serdes lp fail!", + mac_cb->mac_id); + + return -ENOTSUPP; + } + + ACPI_FREE(obj); + + return 0; +} + struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev) { struct dsaf_misc_op *misc_op; @@ -378,6 +526,25 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev) misc_op->get_sfp_prsnt = hns_mac_get_sfp_prsnt; misc_op->cfg_serdes_loopback = hns_mac_config_sds_loopback; + } else if (is_acpi_node(dsaf_dev->dev->fwnode)) { + misc_op->cpld_set_led = hns_cpld_set_led; + misc_op->cpld_reset_led = cpld_led_reset; + misc_op->cpld_set_led_id = cpld_set_led_id; + + misc_op->dsaf_reset = hns_dsaf_rst_acpi; + misc_op->xge_srst = hns_dsaf_xge_srst_by_port_acpi; + misc_op->xge_core_srst = hns_dsaf_xge_core_srst_by_port_acpi; + misc_op->ge_srst = hns_dsaf_ge_srst_by_port_acpi; + misc_op->ppe_srst = hns_ppe_srst_by_port_acpi; + misc_op->ppe_comm_srst = hns_ppe_com_srst; + + misc_op->get_phy_if = hns_mac_get_phy_if_acpi; + misc_op->get_sfp_prsnt = hns_mac_get_sfp_prsnt; + + misc_op->cfg_serdes_loopback = hns_mac_config_sds_loopback_acpi; + } else { + devm_kfree(dsaf_dev->dev, (void *)misc_op); + misc_op = NULL; } return (void *)misc_op; From 63434888aaf1b2e73780f3ada9dcf09bf0f206e1 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Fri, 3 Jun 2016 10:55:21 +0800 Subject: [PATCH 13/13] net: hns: net: hns: enet adds support of acpi Enet needs to get configration parameter by acpi. This patch adds support of ACPI for enet. The configuration parameter will be configed in BIOS. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 56 +++++++++++++++---- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 3ec3c27983798..ad742a6f58795 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -132,6 +132,13 @@ static void fill_v2_desc(struct hnae_ring *ring, void *priv, ring_ptr_move_fw(ring, next_to_use); } +static const struct acpi_device_id hns_enet_acpi_match[] = { + { "HISI00C1", 0 }, + { "HISI00C2", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, hns_enet_acpi_match); + static void fill_desc(struct hnae_ring *ring, void *priv, int size, dma_addr_t dma, int frag_end, int buf_num, enum hns_desc_type type, int mtu) @@ -1870,7 +1877,6 @@ static int hns_nic_dev_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct net_device *ndev; struct hns_nic_priv *priv; - struct device_node *ae_node; u32 port_id; int ret; @@ -1884,20 +1890,45 @@ static int hns_nic_dev_probe(struct platform_device *pdev) priv->dev = dev; priv->netdev = ndev; - if (of_device_is_compatible(dev->of_node, "hisilicon,hns-nic-v1")) - priv->enet_ver = AE_VERSION_1; - else - priv->enet_ver = AE_VERSION_2; + if (dev_of_node(dev)) { + struct device_node *ae_node; - ae_node = of_parse_phandle(dev->of_node, "ae-handle", 0); - if (IS_ERR_OR_NULL(ae_node)) { - ret = PTR_ERR(ae_node); - dev_err(dev, "not find ae-handle\n"); - goto out_read_prop_fail; + if (of_device_is_compatible(dev->of_node, + "hisilicon,hns-nic-v1")) + priv->enet_ver = AE_VERSION_1; + else + priv->enet_ver = AE_VERSION_2; + + ae_node = of_parse_phandle(dev->of_node, "ae-handle", 0); + if (IS_ERR_OR_NULL(ae_node)) { + ret = PTR_ERR(ae_node); + dev_err(dev, "not find ae-handle\n"); + goto out_read_prop_fail; + } + priv->fwnode = &ae_node->fwnode; + } else if (is_acpi_node(dev->fwnode)) { + struct acpi_reference_args args; + + if (acpi_dev_found(hns_enet_acpi_match[0].id)) + priv->enet_ver = AE_VERSION_1; + else if (acpi_dev_found(hns_enet_acpi_match[1].id)) + priv->enet_ver = AE_VERSION_2; + else + return -ENXIO; + + /* try to find port-idx-in-ae first */ + ret = acpi_node_get_property_reference(dev->fwnode, + "ae-handle", 0, &args); + if (ret) { + dev_err(dev, "not find ae-handle\n"); + goto out_read_prop_fail; + } + priv->fwnode = acpi_fwnode_handle(args.adev); + } else { + dev_err(dev, "cannot read cfg data from OF or acpi\n"); + return -ENXIO; } - priv->fwnode = &ae_node->fwnode; - /* try to find port-idx-in-ae first */ ret = device_property_read_u32(dev, "port-idx-in-ae", &port_id); if (ret) { /* only for old code compatible */ @@ -2014,6 +2045,7 @@ static struct platform_driver hns_nic_dev_driver = { .driver = { .name = "hns-nic", .of_match_table = hns_enet_of_match, + .acpi_match_table = ACPI_PTR(hns_enet_acpi_match), }, .probe = hns_nic_dev_probe, .remove = hns_nic_dev_remove,