ethernet: add suspend and resume function with DS=3

PD#162078: suspend and resume code

Change-Id: I57d0582b4df5f4129b60c7e885022778b1f4c98c
Signed-off-by: Zhuo Wang <zhuo.wang@amlogic.com>
This commit is contained in:
Zhuo Wang
2018-03-13 16:29:10 +08:00
committed by Jianxin Pan
parent e511ce688a
commit e7f28d30cb
5 changed files with 100 additions and 2 deletions

View File

@@ -2044,6 +2044,7 @@
"eth_txd2_rgmii",
"eth_txd3_rgmii";
function = "eth";
drive-strength = <3>;
};
};
};

View File

@@ -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,

View File

@@ -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);

View File

@@ -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 <peppe.cavallaro@st.com>");
MODULE_LICENSE("GPL");

View File

@@ -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)