Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b1c6a3a4 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'hns-acpi'



Kejian Yan says:

====================
net: hns: add support of ACPI

This series adds HNS support of acpi. The routine will call some ACPI
helper functions, like acpi_dev_found() and acpi_evaluate_dsm(), which
are not included in other cases. In order to make system compile
successfully in other cases except ACPI, it needs to add relative stub
functions to linux/acpi.h. And we use device property functions instead
of serial helper functions to suport both DT and ACPI cases. And then
add the supports of ACPI for HNS.

change log:
 v3->v4:
  mii-id gets from dev-name instead of address

 v2->v3:
 1. add Review-by: Andy Shevchenko
 2. fix the potential memory leak

 v1 -> v2:
 1. use acpi_dev_found() instead of acpi_match_device_ids() to check if
it is a acpi node.
 2. use is_of_node() instead of IS_ENABLED() to check if it is a DT node.
 3. split the patch("add support of acpi for hns-mdio") into two patches:
    3.1 Move to use fwnode_handle
    3.2 Add ACPI
 4. add the patch which subject is dsaf misc operation method
 5. fix the comments by Andy Shevchenko
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 169fbdc6 63434888
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -96,16 +96,22 @@ 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;
	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 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 +318,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 +327,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);

+3 −2
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
 * "cb" means control block
 */

#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/module.h>
@@ -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;
@@ -528,7 +529,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);

+4 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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);
+3 −3
Original line number Diff line number Diff line
@@ -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);
+190 −57
Original line number Diff line number Diff line
@@ -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 @@ 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
@@ -645,7 +756,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 +783,36 @@ 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",
		np = of_parse_phandle(mac_cb->dev->of_node, "phy-handle",
				      mac_cb->mac_id);
		if (mac_cb->phy_node)
		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;

	if (is_of_node(mac_cb->fw_port)) {
		/* parse property from port subnode in dsaf */
	mac_cb->phy_node = of_parse_phandle(to_of_node(mac_cb->fw_port),
		np = of_parse_phandle(to_of_node(mac_cb->fw_port),
				      "phy-handle", 0);
	if (mac_cb->phy_node)
		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);
		}

		syscon = syscon_node_to_regmap(
				of_parse_phandle(to_of_node(mac_cb->fw_port),
						 "serdes-syscon", 0));
@@ -714,8 +840,9 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb)
				mac_cb->mac_id);
		}

	ret = of_parse_phandle_with_fixed_args(to_of_node(mac_cb->fw_port),
					       "cpld-syscon", 1, 0, &cpld_args);
		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);
@@ -730,6 +857,12 @@ 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;
}
@@ -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);
}
Loading