diff mbox series

[net-next] driver: cadence macb driver support acpi mode

Message ID 20220824121351.578-1-xiaowu.ding@jaguarmicro.com (mailing list archive)
State New, archived
Headers show
Series [net-next] driver: cadence macb driver support acpi mode | expand

Commit Message

xiaowu.ding Aug. 24, 2022, 12:13 p.m. UTC
Uefi report the device info with acpi mode.But the macb driver
just support dts mode , So we need to add acpi mode with this driver.

We add the macb_acpi_support interface to get the clock rating from
the acpi.Because in the acpi mode ,the clock is controlled by the uefi,
and the driver will not modify the clock anymore.So we need get the
clock rating from the acpi

And we add macb_mdiobus_register interface ,and distinction the dts mode
and the acpi mode.Within the function, we add macb_acpi_mdiobus_register
function to realize the acpi mdio device register function.

And we also add macb_phylink_connect interface,and to distinction the dts
and acpi mode with the phy connection function.We add the
macb_acpi_phylink_connect function to realize the acpi phylink function.

Signed-off-by: xiaowu.ding <xiaowu.ding@jaguarmicro.com>
---
 drivers/net/ethernet/cadence/macb.h      |  46 ++++
 drivers/net/ethernet/cadence/macb_main.c | 330 +++++++++++++++++++++--
 2 files changed, 357 insertions(+), 19 deletions(-)

Comments

Russell King (Oracle) Aug. 24, 2022, 1:10 p.m. UTC | #1
On Wed, Aug 24, 2022 at 08:13:51PM +0800, xiaowu.ding wrote:
> -static bool macb_phy_handle_exists(struct device_node *dn)
> +static bool macb_of_phy_handle_exists(struct device_node *dn)
>  {
>  	dn = of_parse_phandle(dn, "phy-handle", 0);
>  	of_node_put(dn);
>  	return dn != NULL;
>  }
>  
> -static int macb_phylink_connect(struct macb *bp)
> +static int macb_of_phylink_connect(struct macb *bp)
>  {
>  	struct device_node *dn = bp->pdev->dev.of_node;
>  	struct net_device *dev = bp->dev;
> @@ -765,7 +767,7 @@ static int macb_phylink_connect(struct macb *bp)
>  	if (dn)
>  		ret = phylink_of_phy_connect(bp->phylink, dn, 0);
>  
> -	if (!dn || (ret && !macb_phy_handle_exists(dn))) {
> +	if (!dn || (ret && !macb_of_phy_handle_exists(dn))) {
>  		phydev = phy_find_first(bp->mii_bus);
>  		if (!phydev) {
>  			netdev_err(dev, "no PHY found\n");
> @@ -786,6 +788,166 @@ static int macb_phylink_connect(struct macb *bp)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_ACPI
> +
> +static bool macb_acpi_phy_handle_exists(struct fwnode_handle *fwnd)
> +{
> +	struct fwnode_handle *phy_node;
> +	bool flag = false;
> +	/* Only phy-handle is used for ACPI */
> +	phy_node = fwnode_find_reference(fwnd, "phy-handle", 0);
> +	flag = !IS_ERR_OR_NULL(phy_node);
> +
> +	if (flag)
> +		fwnode_handle_put(phy_node);
> +
> +	return flag;
> +}
> +
> +static int macb_acpi_phylink_connect(struct macb *bp)
> +{
> +	struct fwnode_handle *fwnd = bp->pdev->dev.fwnode;
> +	struct net_device *dev = bp->dev;
> +	struct phy_device *phydev;
> +	int ret;
> +
> +	if (fwnd)
> +		ret = phylink_fwnode_phy_connect(bp->phylink, fwnd, 0);
> +
> +	if (!fwnd || (ret && !macb_acpi_phy_handle_exists(fwnd))) {
> +		phydev = phy_find_first(bp->mii_bus);
> +		if (!phydev) {
> +			netdev_err(dev, "no PHY found\n");
> +			return -ENXIO;
> +		}
> +
> +		/* attach the mac to the phy */
> +		ret = phylink_connect_phy(bp->phylink, phydev);
> +	}
> +
> +	if (ret) {
> +		netdev_err(dev, "Could not attach PHY (%d)\n", ret);
> +		return ret;
> +	}
> +
> +	phylink_start(bp->phylink);
> +
> +	return 0;
> +}

You shouldn't need this duplication. phylink_fwnode_phy_connect() can be
used to connect DT-based PHYs just fine, so you should be able to use it
for both cases without needing to resort to two copies. This is one of
the reasons the fwnode API exists.

The functionality of your macb_acpi_phy_handle_exists() and
macb_of_phy_handle_exists() should also be the same. Not that
fwnode_handle_put() is safe to call with NULL or err-pointer fwnodes.
Andrew Lunn Aug. 24, 2022, 3:17 p.m. UTC | #2
> +/* On ACPI platforms, clocks are controlled by firmware and/or
> + * ACPI, not by drivers.Need to store the clock value.
> + */
> +struct macb_acpi_config {
> +	u32 hclk_rate;          /* amba clock rate*/
> +	u32 pclk_rate;          /* amba apb clock rate*/
> +	u32 txclk_rate;         /* tx clock rate*/
> +	u32 rxclk_rate;         /* rx clock rate*/
> +	u32 tsuclk_rate;        /* tx clock rate*/
> +	bool acpi_enable;       /* is acpi or not */
> +};

> +static int macb_acpi_support(struct macb *bp)
> +{
> +	struct device *dev = &bp->pdev->dev;
> +	struct macb_acpi_config *config = &bp->acpicfg;
> +	int ret;
> +	u32 property;
> +
> +	/*acpi must be report the pclk*/
> +	property = 0;
> +	ret = device_property_read_u32(dev, MACB_SYSPCLOCK, &property);
> +	if (ret) {
> +		dev_err(dev, "unable to obtain %s property\n", MACB_SYSPCLOCK);
> +		return ret;
> +	}
> +
> +	config->pclk_rate = property;

It seems like you could make this simpler by just calling

clk_hw_register_fixed_rate(dev, "pclk", NULL, 0, property);

You then don't need to modify any other code with respect to clocks.
The clock does exist, so model it in the common clock framework.

    Andrew
Andrew Lunn Aug. 24, 2022, 3:25 p.m. UTC | #3
> +static int macb_acpi_phylink_connect(struct macb *bp)
> +{
> +	struct fwnode_handle *fwnd = bp->pdev->dev.fwnode;
> +	struct net_device *dev = bp->dev;
> +	struct phy_device *phydev;
> +	int ret;
> +
> +	if (fwnd)
> +		ret = phylink_fwnode_phy_connect(bp->phylink, fwnd, 0);
> +
> +	if (!fwnd || (ret && !macb_acpi_phy_handle_exists(fwnd))) {
> +		phydev = phy_find_first(bp->mii_bus);

Please don't use phy_find_first. That is somewhat historical. Since
this is a new binding, simply error out if
phylink_fwnode_phy_connect() fails.

> +static int macb_acpi_mdiobus_register(struct macb *bp)
> +{
> +	struct platform_device *pdev =	bp->pdev;
> +	struct fwnode_handle *fwnode = pdev->dev.fwnode;
> +	struct fwnode_handle *child;
> +	u32 addr;
> +	int ret;
> +
> +	if (!IS_ERR_OR_NULL(fwnode_find_reference(pdev->dev.fwnode, "fixed-link", 0)))
> +		return mdiobus_register(bp->mii_bus);
> +
> +	fwnode_for_each_child_node(fwnode, child) {
> +		ret = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), &addr);
> +		if (ret || addr >= PHY_MAX_ADDR)
> +			continue;
> +		ret = acpi_mdiobus_register(bp->mii_bus, fwnode);
> +		if (!ret)
> +			return ret;
> +		break;

Why loop looking for a node with a register value < 32?

Please make sure you are conformant with Documentation/firmware-guide/acpi/dsd/phy.rst

       Andrew
xiaowu.ding Sept. 5, 2022, 2:25 a.m. UTC | #4
Hi Andrew:
	Thank you very much for your advices.
 
	There will be some problems with the clk_hw_register_fixed_rate interface in the acpi mode.
	It seems that the kernel common clock framework can not support the acpi mode,just support the dt mode.
	Register the fixed clocks with the clk_hw_register_fixed_rate function ,and the clks hw should be used by some
	Drivers,but the driver can not get the clock hw with the devm_get_clk function,because this function can not support
	acpi mode, the driver cannot find the device correct parent clk hw node.
	
	So currently, we just get the clk rate from the acpi node with the device_property_read_u32 function.

Br Xiaowu

-----邮件原件-----
发件人: Andrew Lunn <andrew@lunn.ch> 
发送时间: 2022年8月24日 23:17
收件人: Xiaowu Ding <xiaowu.ding@jaguarmicro.com>
抄送: davem@davemloft.net; edumazet@google.com; kuba@kernel.org; pabeni@redhat.com; linux@armlinux.org.uk; nicolas.ferre@microchip.com; claudiu.beznea@microchip.com; palmer@dabbelt.com; paul.walmsley@sifive.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org; linux-riscv@lists.infradead.org
主题: Re: [PATCH net-next] driver: cadence macb driver support acpi mode

> +/* On ACPI platforms, clocks are controlled by firmware and/or
> + * ACPI, not by drivers.Need to store the clock value.
> + */
> +struct macb_acpi_config {
> +	u32 hclk_rate;          /* amba clock rate*/
> +	u32 pclk_rate;          /* amba apb clock rate*/
> +	u32 txclk_rate;         /* tx clock rate*/
> +	u32 rxclk_rate;         /* rx clock rate*/
> +	u32 tsuclk_rate;        /* tx clock rate*/
> +	bool acpi_enable;       /* is acpi or not */
> +};

> +static int macb_acpi_support(struct macb *bp) {
> +	struct device *dev = &bp->pdev->dev;
> +	struct macb_acpi_config *config = &bp->acpicfg;
> +	int ret;
> +	u32 property;
> +
> +	/*acpi must be report the pclk*/
> +	property = 0;
> +	ret = device_property_read_u32(dev, MACB_SYSPCLOCK, &property);
> +	if (ret) {
> +		dev_err(dev, "unable to obtain %s property\n", MACB_SYSPCLOCK);
> +		return ret;
> +	}
> +
> +	config->pclk_rate = property;

It seems like you could make this simpler by just calling

clk_hw_register_fixed_rate(dev, "pclk", NULL, 0, property);

You then don't need to modify any other code with respect to clocks.
The clock does exist, so model it in the common clock framework.

    Andrew
Andrew Lunn Sept. 5, 2022, 5:13 p.m. UTC | #5
On Mon, Sep 05, 2022 at 02:25:06AM +0000, Xiaowu Ding wrote:
> Hi Andrew:
> 	Thank you very much for your advices.
>  
> 	There will be some problems with the clk_hw_register_fixed_rate interface in the acpi mode.
> 	It seems that the kernel common clock framework can not support the acpi mode,just support the dt mode.

It has two modes:

https://elixir.bootlin.com/linux/v6.0-rc4/source/drivers/clk/clkdev.c#L100
struct clk *clk_get(struct device *dev, const char *con_id)
{
	const char *dev_id = dev ? dev_name(dev) : NULL;
	struct clk_hw *hw;

	if (dev && dev->of_node) {
		hw = of_clk_get_hw(dev->of_node, 0, con_id);
		if (!IS_ERR(hw) || PTR_ERR(hw) == -EPROBE_DEFER)
			return clk_hw_create_clk(dev, hw, dev_id, con_id);
	}

	return __clk_get_sys(dev, dev_id, con_id);
}

If dev has an of_node, it uses of_clk_get_hw().

If dev does not have an of node, it uses __clk_get_sys(), which looks
purely using the clock name.

The common clock framework is older than DT, and so does not force you
to use DT. Please look at making __clk_get_sys() work for you
scenario. You should just need to register the fixed clock using the
correct name. Look at some of the very old boards which have not been
converted to DT.

   Andrew
diff mbox series

Patch

diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 9c410f93a..a92299434 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -731,6 +731,33 @@ 
 #define MACB_LSO_UFO_ENABLE			0x01
 #define MACB_LSO_TSO_ENABLE			0x02
 
+/*Clk name define used for acpi mode*/
+#define MACB_SYSPCLOCK             "pclk"
+#define MACB_SYSHCLOCK             "hclk"
+#define MACB_TXCLOCK               "tx_clk"
+#define MACB_RXCLOCK               "rx_clk"
+#define MACB_TSCLOCK               "tsu_clk"
+
+/*Get the pclk clock rate used for acpi*/
+#define MACB_GET_GET_PCLOCKRATE(MACB)	\
+		((MACB)->acpicfg.pclk_rate)
+
+/*Get the hclk clock rate used for acpi*/
+#define MACB_GET_GET_HCLOCKRATE(MACB)	\
+		((MACB)->acpicfg.hclk_rate)
+
+/*Get the tsuclk clock rate used for acpi*/
+#define MACB_GET_GET_TSUCLOCKRATE(MACB)	\
+		((MACB)->acpicfg.tsuclk_rate)
+
+/*Get the tsuclk clock rate used for acpi*/
+#define MACB_GET_GET_TXCLOCKRATE(MACB)	\
+		((MACB)->acpicfg.txclk_rate)
+
+/*Get the tsuclk clock rate used for acpi*/
+#define MACB_GET_GET_RXCLOCKRATE(MACB)	\
+		((MACB)->acpicfg.rxclk_rate)
+
 /* Bit manipulation macros */
 #define MACB_BIT(name)					\
 	(1 << MACB_##name##_OFFSET)
@@ -1242,6 +1269,18 @@  struct ethtool_rx_fs_list {
 	unsigned int count;
 };
 
+/* On ACPI platforms, clocks are controlled by firmware and/or
+ * ACPI, not by drivers.Need to store the clock value.
+ */
+struct macb_acpi_config {
+	u32 hclk_rate;          /* amba clock rate*/
+	u32 pclk_rate;          /* amba apb clock rate*/
+	u32 txclk_rate;         /* tx clock rate*/
+	u32 rxclk_rate;         /* rx clock rate*/
+	u32 tsuclk_rate;        /* tx clock rate*/
+	bool acpi_enable;       /* is acpi or not */
+};
+
 struct macb {
 	void __iomem		*regs;
 	bool			native_io;
@@ -1324,6 +1363,7 @@  struct macb {
 
 	struct macb_pm_data pm_data;
 	const struct macb_usrio_config *usrio;
+	struct macb_acpi_config acpicfg;
 };
 
 #ifdef CONFIG_MACB_USE_HWSTAMP
@@ -1381,6 +1421,12 @@  static inline bool gem_has_ptp(struct macb *bp)
 	return !!(bp->caps & MACB_CAPS_GEM_HAS_PTP);
 }
 
+/* macb is support acpi or not */
+static inline bool macb_has_acpi(struct macb *bp)
+{
+	return bp->acpicfg.acpi_enable;
+}
+
 /**
  * struct macb_platform_data - platform data for MACB Ethernet used for PCI registration
  * @pclk:		platform clock
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 66c7d08d3..41116d4ee 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -38,6 +38,8 @@ 
 #include <linux/pm_runtime.h>
 #include <linux/ptp_classify.h>
 #include <linux/reset.h>
+#include <linux/acpi.h>
+#include <linux/acpi_mdio.h>
 #include "macb.h"
 
 /* This structure is only used for MACB on SiFive FU540 devices */
@@ -748,14 +750,14 @@  static const struct phylink_mac_ops macb_phylink_ops = {
 	.mac_link_up = macb_mac_link_up,
 };
 
-static bool macb_phy_handle_exists(struct device_node *dn)
+static bool macb_of_phy_handle_exists(struct device_node *dn)
 {
 	dn = of_parse_phandle(dn, "phy-handle", 0);
 	of_node_put(dn);
 	return dn != NULL;
 }
 
-static int macb_phylink_connect(struct macb *bp)
+static int macb_of_phylink_connect(struct macb *bp)
 {
 	struct device_node *dn = bp->pdev->dev.of_node;
 	struct net_device *dev = bp->dev;
@@ -765,7 +767,7 @@  static int macb_phylink_connect(struct macb *bp)
 	if (dn)
 		ret = phylink_of_phy_connect(bp->phylink, dn, 0);
 
-	if (!dn || (ret && !macb_phy_handle_exists(dn))) {
+	if (!dn || (ret && !macb_of_phy_handle_exists(dn))) {
 		phydev = phy_find_first(bp->mii_bus);
 		if (!phydev) {
 			netdev_err(dev, "no PHY found\n");
@@ -786,6 +788,166 @@  static int macb_phylink_connect(struct macb *bp)
 	return 0;
 }
 
+#ifdef CONFIG_ACPI
+
+static bool macb_acpi_phy_handle_exists(struct fwnode_handle *fwnd)
+{
+	struct fwnode_handle *phy_node;
+	bool flag = false;
+	/* Only phy-handle is used for ACPI */
+	phy_node = fwnode_find_reference(fwnd, "phy-handle", 0);
+	flag = !IS_ERR_OR_NULL(phy_node);
+
+	if (flag)
+		fwnode_handle_put(phy_node);
+
+	return flag;
+}
+
+static int macb_acpi_phylink_connect(struct macb *bp)
+{
+	struct fwnode_handle *fwnd = bp->pdev->dev.fwnode;
+	struct net_device *dev = bp->dev;
+	struct phy_device *phydev;
+	int ret;
+
+	if (fwnd)
+		ret = phylink_fwnode_phy_connect(bp->phylink, fwnd, 0);
+
+	if (!fwnd || (ret && !macb_acpi_phy_handle_exists(fwnd))) {
+		phydev = phy_find_first(bp->mii_bus);
+		if (!phydev) {
+			netdev_err(dev, "no PHY found\n");
+			return -ENXIO;
+		}
+
+		/* attach the mac to the phy */
+		ret = phylink_connect_phy(bp->phylink, phydev);
+	}
+
+	if (ret) {
+		netdev_err(dev, "Could not attach PHY (%d)\n", ret);
+		return ret;
+	}
+
+	phylink_start(bp->phylink);
+
+	return 0;
+}
+
+static int macb_acpi_support(struct macb *bp)
+{
+	struct device *dev = &bp->pdev->dev;
+	struct macb_acpi_config *config = &bp->acpicfg;
+	int ret;
+	u32 property;
+
+	/*acpi must be report the pclk*/
+	property = 0;
+	ret = device_property_read_u32(dev, MACB_SYSPCLOCK, &property);
+	if (ret) {
+		dev_err(dev, "unable to obtain %s property\n", MACB_SYSPCLOCK);
+		return ret;
+	}
+
+	config->pclk_rate = property;
+
+	/*acpi must be report the hclk*/
+	property = 0;
+	ret = device_property_read_u32(dev, MACB_SYSHCLOCK, &property);
+	if (ret) {
+		dev_err(dev, "unable to obtain %s property\n", MACB_SYSHCLOCK);
+		return ret;
+	}
+
+	config->hclk_rate = property;
+
+	/*acpi optional report txclk */
+	property = 0;
+	ret = device_property_read_u32(dev, MACB_TXCLOCK, &property);
+	if (ret) {
+		dev_info(dev, "unable to obtain %s property\n", MACB_TXCLOCK);
+		property = 0;
+	}
+
+	config->txclk_rate = property;
+
+	/*acpi optional report rxclk */
+	property = 0;
+	ret = device_property_read_u32(dev, MACB_RXCLOCK, &property);
+	if (ret) {
+		dev_info(dev, "unable to obtain %s property\n", MACB_RXCLOCK);
+		property = 0;
+	}
+
+	config->rxclk_rate = property;
+
+	/*acpi optional report tsuclk */
+	property = 0;
+	ret = device_property_read_u32(dev, MACB_TSCLOCK, &property);
+	if (ret) {
+		dev_info(dev, "unable to obtain %s property\n", MACB_TSCLOCK);
+		property = 0;
+	}
+
+	config->tsuclk_rate = property;
+
+	return 0;
+}
+
+static int macb_acpi_mdiobus_register(struct macb *bp)
+{
+	struct platform_device *pdev =	bp->pdev;
+	struct fwnode_handle *fwnode = pdev->dev.fwnode;
+	struct fwnode_handle *child;
+	u32 addr;
+	int ret;
+
+	if (!IS_ERR_OR_NULL(fwnode_find_reference(pdev->dev.fwnode, "fixed-link", 0)))
+		return mdiobus_register(bp->mii_bus);
+
+	fwnode_for_each_child_node(fwnode, child) {
+		ret = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), &addr);
+		if (ret || addr >= PHY_MAX_ADDR)
+			continue;
+		ret = acpi_mdiobus_register(bp->mii_bus, fwnode);
+		if (!ret)
+			return ret;
+		break;
+	}
+
+	return mdiobus_register(bp->mii_bus);
+}
+
+#else
+
+static int macb_acpi_phylink_connect(struct macb *bp)
+{
+	return -EINVAL;
+}
+
+static int macb_acpi_support(struct macb *bp)
+{
+	return -EINVAL;
+}
+
+static int macb_acpi_mdiobus_register(struct macb *bp)
+{
+	return -EINVAL;
+}
+
+#endif
+
+static int macb_phylink_connect(struct macb *bp)
+{
+	if (likely(!macb_has_acpi(bp))) {
+		/* macb of device tree mode register mdiobus */
+		return macb_of_phylink_connect(bp);
+	}
+		/* macb acpi mode register mdiobus */
+	return macb_acpi_phylink_connect(bp);
+}
+
 static void macb_get_pcs_fixed_state(struct phylink_config *config,
 				     struct phylink_link_state *state)
 {
@@ -851,7 +1013,7 @@  static int macb_mii_probe(struct net_device *dev)
 	return 0;
 }
 
-static int macb_mdiobus_register(struct macb *bp)
+static int macb_of_mdiobus_register(struct macb *bp)
 {
 	struct device_node *child, *np = bp->pdev->dev.of_node;
 
@@ -887,6 +1049,16 @@  static int macb_mdiobus_register(struct macb *bp)
 	return mdiobus_register(bp->mii_bus);
 }
 
+static int macb_mdiobus_register(struct macb *bp)
+{
+	if (likely(!macb_has_acpi(bp))) {
+		/* macb of device tree mode register mdio bus */
+		return macb_of_mdiobus_register(bp);
+	}
+	/* macb acpi mode register mdio bus */
+	return macb_acpi_mdiobus_register(bp);
+}
+
 static int macb_mii_init(struct macb *bp)
 {
 	int err = -ENXIO;
@@ -2578,7 +2750,12 @@  static void macb_reset_hw(struct macb *bp)
 static u32 gem_mdc_clk_div(struct macb *bp)
 {
 	u32 config;
-	unsigned long pclk_hz = clk_get_rate(bp->pclk);
+	unsigned long pclk_hz;
+
+	if (unlikely(macb_has_acpi(bp)))
+		pclk_hz = MACB_GET_GET_PCLOCKRATE(bp);
+	else
+		pclk_hz = clk_get_rate(bp->pclk);
 
 	if (pclk_hz <= 20000000)
 		config = GEM_BF(CLK, GEM_CLK_DIV8);
@@ -3263,6 +3440,8 @@  static unsigned int gem_get_tsu_rate(struct macb *bp)
 {
 	struct clk *tsu_clk;
 	unsigned int tsu_rate;
+	if (unlikely(macb_has_acpi(bp)))
+		return MACB_GET_GET_TSUCLOCKRATE(bp);
 
 	tsu_clk = devm_clk_get(&bp->pdev->dev, "tsu_clk");
 	if (!IS_ERR(tsu_clk))
@@ -3865,7 +4044,6 @@  static void macb_clks_disable(struct clk *pclk, struct clk *hclk, struct clk *tx
 		{ .clk = hclk, },
 		{ .clk = tx_clk },
 	};
-
 	clk_bulk_disable_unprepare(ARRAY_SIZE(clks), clks);
 }
 
@@ -4811,6 +4989,94 @@  static const struct of_device_id macb_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, macb_dt_ids);
 #endif /* CONFIG_OF */
 
+#ifdef CONFIG_ACPI
+
+static int jmnd_mac_clk_init(struct platform_device *pdev, struct clk **pclk,
+			     struct clk **hclk, struct clk **tx_clk,
+			     struct clk **rx_clk, struct clk **tsu_clk)
+{
+	/*On ACPI platforms, clocks are controlled by firmware and/or
+	 * ACPI, not configure by drivers.So here need to dummy here.
+	 */
+	*pclk = NULL;
+	*hclk = NULL;
+	*tx_clk = NULL;
+	*rx_clk = NULL;
+	*tsu_clk = NULL;
+	dev_info(&pdev->dev, "Jmnd Mac clock dummpy init.\n");
+	return 0;
+}
+
+static const struct macb_config jmnd_gem_rgmii_config = {
+	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_SG_DISABLED |
+			MACB_CAPS_JUMBO,
+	.dma_burst_length = 16,
+	.clk_init = jmnd_mac_clk_init,
+	.init = macb_init,
+	.jumbo_max_len = 10240,
+	.usrio = &macb_default_usrio
+};
+
+static const struct macb_config jmnd_gem_rmii_config = {
+	.caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_JUMBO,
+	.dma_burst_length = 16,
+	.clk_init = jmnd_mac_clk_init,
+	.init = macb_init,
+	.jumbo_max_len = 10240,
+	.usrio = &macb_default_usrio,
+};
+
+static const struct acpi_device_id macb_acpi_ids[] = {
+	{
+		.id = "JAMC00B0",
+		.driver_data = (kernel_ulong_t)&jmnd_gem_rgmii_config
+	},
+	{
+		.id = "JAMC00BA",
+		.driver_data = (kernel_ulong_t)&jmnd_gem_rmii_config
+	},
+	{
+	},
+};
+
+MODULE_DEVICE_TABLE(acpi, macb_acpi_ids);
+
+static void macb_acpi_gdata(struct platform_device *pdev, int (**init)(struct platform_device *),
+			    int (**clk_init)(struct platform_device *, struct clk **, struct clk **,
+					     struct clk **,  struct clk **, struct clk **),
+			    const struct macb_config **macb_config)
+{
+	const struct acpi_device_id *match;
+
+	match = acpi_match_device(macb_acpi_ids, &pdev->dev);
+	if (match && match->driver_data) {
+		*macb_config = (struct macb_config *)match->driver_data;
+		*clk_init = (*macb_config)->clk_init;
+		*init = (*macb_config)->init;
+	}
+}
+
+#else
+
+static void macb_acpi_gdata(struct platform_device *pdev, int (**init)(struct platform_device *),
+			    int (**clk_init)(struct platform_device *, struct clk **, struct clk **,
+					     struct clk **,  struct clk **, struct clk **),
+			    const struct macb_config **macb_config)
+{
+}
+
+#endif
+
+/* config acpi mode ,dts priority high*/
+static inline void macb_set_acpi_mode(struct macb *bp)
+{
+	struct device *dev = &bp->pdev->dev;
+
+	bp->acpicfg.acpi_enable = dev_of_node(dev) ? false :
+		(is_acpi_node(dev->fwnode) ? true : false);
+	wmb();/* drain writebuffer */
+}
+
 static const struct macb_config default_gem_config = {
 	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
 		MACB_CAPS_JUMBO |
@@ -4830,6 +5096,7 @@  static int macb_probe(struct platform_device *pdev)
 			struct clk **) = macb_config->clk_init;
 	int (*init)(struct platform_device *) = macb_config->init;
 	struct device_node *np = pdev->dev.of_node;
+	struct fwnode_handle *fwnodep = pdev->dev.fwnode;
 	struct clk *pclk, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL;
 	struct clk *tsu_clk = NULL;
 	unsigned int queue_mask, num_queues;
@@ -4845,7 +5112,7 @@  static int macb_probe(struct platform_device *pdev)
 	if (IS_ERR(mem))
 		return PTR_ERR(mem);
 
-	if (np) {
+	if (likely(np)) {
 		const struct of_device_id *match;
 
 		match = of_match_node(macb_dt_ids, np);
@@ -4855,10 +5122,15 @@  static int macb_probe(struct platform_device *pdev)
 			init = macb_config->init;
 		}
 	}
+	/*add gem support acpi*/
+	else if (is_acpi_node(fwnodep))
+		macb_acpi_gdata(pdev, &init, &clk_init, &macb_config);
 
-	err = clk_init(pdev, &pclk, &hclk, &tx_clk, &rx_clk, &tsu_clk);
-	if (err)
-		return err;
+	if (clk_init) {
+		err = clk_init(pdev, &pclk, &hclk, &tx_clk, &rx_clk, &tsu_clk);
+		if (err)
+			return err;
+	}
 
 	pm_runtime_set_autosuspend_delay(&pdev->dev, MACB_PM_TIMEOUT);
 	pm_runtime_use_autosuspend(&pdev->dev);
@@ -4902,9 +5174,16 @@  static int macb_probe(struct platform_device *pdev)
 	if (macb_config)
 		bp->jumbo_max_len = macb_config->jumbo_max_len;
 
+	/* macb set acpi mode is enabled */
+	macb_set_acpi_mode(bp);
+
+	if (macb_has_acpi(bp))
+		macb_acpi_support(bp);
+
 	bp->wol = 0;
-	if (of_get_property(np, "magic-packet", NULL))
+	if (device_property_present(&pdev->dev, "magic-packet"))
 		bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
+
 	device_set_wakeup_capable(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
 
 	bp->usrio = macb_config->usrio;
@@ -4951,15 +5230,13 @@  static int macb_probe(struct platform_device *pdev)
 	if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR)
 		bp->rx_intr_mask |= MACB_BIT(RXUBR);
 
-	err = of_get_ethdev_address(np, bp->dev);
-	if (err == -EPROBE_DEFER)
-		goto err_out_free_netdev;
-	else if (err)
+	if (device_get_ethdev_address(&pdev->dev, dev))
 		macb_get_hwaddr(bp);
 
-	err = of_get_phy_mode(np, &interface);
-	if (err)
-		/* not found in DT, MII by default */
+	/*add gem support acpi*/
+	interface = device_get_phy_mode(&pdev->dev);
+	if (interface < 0)
+		/* not found in DT and ACPI , MII by default */
 		bp->phy_interface = PHY_INTERFACE_MODE_MII;
 	else
 		bp->phy_interface = interface;
@@ -5213,6 +5490,12 @@  static int __maybe_unused macb_runtime_suspend(struct device *dev)
 	struct net_device *netdev = dev_get_drvdata(dev);
 	struct macb *bp = netdev_priv(netdev);
 
+	/*On ACPI platforms, clocks are controlled by firmware and/or
+	 * ACPI, not by drivers.
+	 */
+	if (unlikely(macb_has_acpi(bp)))
+		return 0;
+
 	if (!(device_may_wakeup(dev)))
 		macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk, bp->rx_clk, bp->tsu_clk);
 	else if (!(bp->caps & MACB_CAPS_NEED_TSUCLK))
@@ -5226,6 +5509,12 @@  static int __maybe_unused macb_runtime_resume(struct device *dev)
 	struct net_device *netdev = dev_get_drvdata(dev);
 	struct macb *bp = netdev_priv(netdev);
 
+	/*On ACPI platforms, clocks are controlled by firmware and/or
+	 * ACPI, not by drivers.
+	 */
+	if (unlikely(macb_has_acpi(bp)))
+		return 0;
+
 	if (!(device_may_wakeup(dev))) {
 		clk_prepare_enable(bp->pclk);
 		clk_prepare_enable(bp->hclk);
@@ -5250,7 +5539,10 @@  static struct platform_driver macb_driver = {
 	.driver		= {
 		.name		= "macb",
 		.of_match_table	= of_match_ptr(macb_dt_ids),
-		.pm	= &macb_pm_ops,
+#ifdef CONFIG_ACPI
+		.acpi_match_table = ACPI_PTR(macb_acpi_ids),
+#endif
+		.pm = &macb_pm_ops,
 	},
 };