diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 8b243b485b77..4983994f5f12 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -2044,6 +2044,7 @@ "eth_txd2_rgmii", "eth_txd3_rgmii"; function = "eth"; + drive-strength = <3>; }; }; }; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c index ed929a5fead9..c7a23a1835df 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c @@ -30,6 +30,9 @@ #define ETHMAC_SPEED_10 BIT(1) #ifdef CONFIG_AMLOGIC_ETH_PRIVE +/*if not g12a use genphy driver*/ +/* if it's internal phy we will shutdown analog*/ +static unsigned int is_internal_phy; /* Ethernet register for G12A PHY */ #define ETH_PLL_CTL0 0x44 #define ETH_PLL_CTL1 0x48 @@ -277,6 +280,7 @@ static void __iomem *g12a_network_interface_setup(struct platform_device *pdev) void __iomem *REG_ETH_reg0_addr = NULL; void __iomem *ETH_PHY_config_addr = NULL; u32 internal_phy = 0; + is_internal_phy = 0; pr_debug("g12a_network_interface_setup\n"); /*map PRG_ETH_REG */ @@ -322,6 +326,7 @@ static void __iomem *g12a_network_interface_setup(struct platform_device *pdev) return REG_ETH_reg0_addr; } + is_internal_phy = internal_phy; /* Config G12A internal PHY */ if (internal_phy) { /*PLL*/ @@ -335,7 +340,8 @@ static void __iomem *g12a_network_interface_setup(struct platform_device *pdev) /*config extern phy*/ if (internal_phy == 0) { - /*TODO*/ + /*switch to extern phy*/ + writel(0x0, ETH_PHY_config_addr + ETH_PHY_CNTL2); pin_ctl = devm_pinctrl_get_select (&pdev->dev, "external_eth_pins"); return REG_ETH_reg0_addr; @@ -345,6 +351,71 @@ static void __iomem *g12a_network_interface_setup(struct platform_device *pdev) return REG_ETH_reg0_addr; } +void __iomem *phy_analog_config_addr; +static int dwmac_meson_disable_analog(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + void __iomem *phy_analog_config_addr = NULL; + + /*map ETH_PLL address*/ + phy_analog_config_addr = devm_ioremap_nocache + (&pdev->dev, + (resource_size_t)0xff64c000, 4); + pr_info("suspend addr %p\n", phy_analog_config_addr); + + writel(0x00000000, phy_analog_config_addr + 0x0); + writel(0x003e0000, phy_analog_config_addr + 0x4); + writel(0x12844008, phy_analog_config_addr + 0x8); + writel(0x0800a40c, phy_analog_config_addr + 0xc); + writel(0x00000000, phy_analog_config_addr + 0x10); + writel(0x031d161c, phy_analog_config_addr + 0x14); + writel(0x00001683, phy_analog_config_addr + 0x18); + writel(0x09c0040a, phy_analog_config_addr + 0x44); + return 0; +} + +static int dwmac_meson_recover_analog(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + void __iomem *phy_analog_config_addr = NULL; + + /*map ETH_PLL address*/ + phy_analog_config_addr = devm_ioremap_nocache + (&pdev->dev, + (resource_size_t)0xff64c000, 4); + pr_info("recover %p\n", phy_analog_config_addr); + + writel(0x19c0040a, phy_analog_config_addr + 0x44); + writel(0x0, phy_analog_config_addr + 0x4); + return 0; +} + +static int meson6_dwmac_suspend(struct device *dev) +{ + int ret; + + /*shudown internal phy analog*/ + pr_info("suspend inter = %d\n", is_internal_phy); + if (is_internal_phy) + dwmac_meson_disable_analog(dev); + ret = stmmac_pltfr_suspend(dev); + + return ret; +} + +static int meson6_dwmac_resume(struct device *dev) +{ + int ret; + + pr_info("resuem inter = %d\n", is_internal_phy); + if (is_internal_phy) + dwmac_meson_recover_analog(dev); + ret = stmmac_pltfr_resume(dev); + + return ret; +} +EXPORT_SYMBOL_GPL(meson6_dwmac_resume); + #endif static int meson6_dwmac_probe(struct platform_device *pdev) { @@ -436,6 +507,10 @@ static const struct of_device_id meson6_dwmac_match[] = { }; MODULE_DEVICE_TABLE(of, meson6_dwmac_match); +#ifdef CONFIG_AMLOGIC_ETH_PRIVE +SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, meson6_dwmac_suspend, + meson6_dwmac_resume); +#endif static struct platform_driver meson6_dwmac_driver = { .probe = meson6_dwmac_probe, .remove = stmmac_pltfr_remove, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c3d430f947fe..003869392c37 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1726,9 +1726,17 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) } #ifdef CONFIG_DEBUG_FS +#ifdef CONFIG_AMLOGIC_ETH_PRIVE + if (!priv->dbgfs_dir) { + ret = stmmac_init_fs(dev); + if (ret < 0) + pr_warn("%s: failed debugFS registration\n", __func__); + } +#else ret = stmmac_init_fs(dev); if (ret < 0) pr_warn("%s: failed debugFS registration\n", __func__); +#endif #endif /* Start the ball rolling... */ pr_debug("%s: DMA RX/TX processes started...\n", dev->name); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 93db6cfdc9db..87eba7bb77c5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -441,7 +441,11 @@ EXPORT_SYMBOL_GPL(stmmac_pltfr_remove); * call the main suspend function and then, if required, on some platform, it * can call an exit helper. */ +#ifdef CONFIG_AMLOGIC_ETH_PRIVE +int stmmac_pltfr_suspend(struct device *dev) +#else static int stmmac_pltfr_suspend(struct device *dev) +#endif { int ret; struct net_device *ndev = dev_get_drvdata(dev); @@ -464,7 +468,11 @@ static int stmmac_pltfr_suspend(struct device *dev) * the main resume function, on some platforms, it can call own init helper * if required. */ +#ifdef CONFIG_AMLOGIC_ETH_PRIVE +int stmmac_pltfr_resume(struct device *dev) +#else static int stmmac_pltfr_resume(struct device *dev) +#endif { struct net_device *ndev = dev_get_drvdata(dev); struct stmmac_priv *priv = netdev_priv(ndev); @@ -479,10 +487,12 @@ static int stmmac_pltfr_resume(struct device *dev) } #endif /* CONFIG_PM_SLEEP */ +#ifdef CONFIG_AMLOGIC_ETH_PRIVE +#else SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend, stmmac_pltfr_resume); EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops); - +#endif MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support"); MODULE_AUTHOR("Giuseppe Cavallaro "); MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h index b72eb0de57b7..a902bb6f01a1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h @@ -30,6 +30,10 @@ int stmmac_get_platform_resources(struct platform_device *pdev, struct stmmac_resources *stmmac_res); int stmmac_pltfr_remove(struct platform_device *pdev); +#ifdef CONFIG_AMLOGIC_ETH_PRIVE +int stmmac_pltfr_suspend(struct device *dev); +int stmmac_pltfr_resume(struct device *dev); +#endif extern const struct dev_pm_ops stmmac_pltfr_pm_ops; static inline void *get_stmmac_bsp_priv(struct device *dev)