Commit 22947335 authored by Christophe Roullier's avatar Christophe Roullier Committed by David S. Miller

net: ethernet: stmmac: update to support all PHY config for stm32mp157c.

Update glue codes to support all PHY config on stm32mp157c
 PHY_MODE	(MII,GMII, RMII, RGMII) and in normal, PHY wo crystal (25Mhz),
PHY wo crystal (50Mhz), No 125Mhz from PHY config.
Signed-off-by: default avatarChristophe Roullier <christophe.roullier@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 634565f8
...@@ -25,9 +25,24 @@ ...@@ -25,9 +25,24 @@
#define SYSCFG_MCU_ETH_MASK BIT(23) #define SYSCFG_MCU_ETH_MASK BIT(23)
#define SYSCFG_MP1_ETH_MASK GENMASK(23, 16) #define SYSCFG_MP1_ETH_MASK GENMASK(23, 16)
#define SYSCFG_PMCCLRR_OFFSET 0x40
#define SYSCFG_PMCR_ETH_CLK_SEL BIT(16) #define SYSCFG_PMCR_ETH_CLK_SEL BIT(16)
#define SYSCFG_PMCR_ETH_REF_CLK_SEL BIT(17) #define SYSCFG_PMCR_ETH_REF_CLK_SEL BIT(17)
/* Ethernet PHY interface selection in register SYSCFG Configuration
*------------------------------------------
* src |BIT(23)| BIT(22)| BIT(21)|BIT(20)|
*------------------------------------------
* MII | 0 | 0 | 0 | 1 |
*------------------------------------------
* GMII | 0 | 0 | 0 | 0 |
*------------------------------------------
* RGMII | 0 | 0 | 1 | n/a |
*------------------------------------------
* RMII | 1 | 0 | 0 | n/a |
*------------------------------------------
*/
#define SYSCFG_PMCR_ETH_SEL_MII BIT(20) #define SYSCFG_PMCR_ETH_SEL_MII BIT(20)
#define SYSCFG_PMCR_ETH_SEL_RGMII BIT(21) #define SYSCFG_PMCR_ETH_SEL_RGMII BIT(21)
#define SYSCFG_PMCR_ETH_SEL_RMII BIT(23) #define SYSCFG_PMCR_ETH_SEL_RMII BIT(23)
...@@ -35,15 +50,54 @@ ...@@ -35,15 +50,54 @@
#define SYSCFG_MCU_ETH_SEL_MII 0 #define SYSCFG_MCU_ETH_SEL_MII 0
#define SYSCFG_MCU_ETH_SEL_RMII 1 #define SYSCFG_MCU_ETH_SEL_RMII 1
/* STM32MP1 register definitions
*
* Below table summarizes the clock requirement and clock sources for
* supported phy interface modes.
* __________________________________________________________________________
*|PHY_MODE | Normal | PHY wo crystal| PHY wo crystal |No 125Mhz from PHY|
*| | | 25MHz | 50MHz | |
* ---------------------------------------------------------------------------
*| MII | - | eth-ck | n/a | n/a |
*| | | | | |
* ---------------------------------------------------------------------------
*| GMII | - | eth-ck | n/a | n/a |
*| | | | | |
* ---------------------------------------------------------------------------
*| RGMII | - | eth-ck | n/a | eth-ck (no pin) |
*| | | | | st,eth-clk-sel |
* ---------------------------------------------------------------------------
*| RMII | - | eth-ck | eth-ck | n/a |
*| | | | st,eth-ref-clk-sel | |
* ---------------------------------------------------------------------------
*
* BIT(17) : set this bit in RMII mode when you have PHY without crystal 50MHz
* BIT(16) : set this bit in GMII/RGMII PHY when you do not want use 125Mhz
* from PHY
*-----------------------------------------------------
* src | BIT(17) | BIT(16) |
*-----------------------------------------------------
* MII | n/a | n/a |
*-----------------------------------------------------
* GMII | n/a | st,eth-clk-sel |
*-----------------------------------------------------
* RGMII | n/a | st,eth-clk-sel |
*-----------------------------------------------------
* RMII | st,eth-ref-clk-sel | n/a |
*-----------------------------------------------------
*
*/
struct stm32_dwmac { struct stm32_dwmac {
struct clk *clk_tx; struct clk *clk_tx;
struct clk *clk_rx; struct clk *clk_rx;
struct clk *clk_eth_ck; struct clk *clk_eth_ck;
struct clk *clk_ethstp; struct clk *clk_ethstp;
struct clk *syscfg_clk; struct clk *syscfg_clk;
bool int_phyclk; /* Clock from RCC to drive PHY */ int eth_clk_sel_reg;
int eth_ref_clk_sel_reg;
int irq_pwr_wakeup; int irq_pwr_wakeup;
u32 mode_reg; /* MAC glue-logic mode register */ u32 mode_reg; /* MAC glue-logic mode register */
struct regmap *regmap; struct regmap *regmap;
u32 speed; u32 speed;
const struct stm32_ops *ops; const struct stm32_ops *ops;
...@@ -103,7 +157,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare) ...@@ -103,7 +157,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
if (ret) if (ret)
return ret; return ret;
if (dwmac->int_phyclk) { if (dwmac->clk_eth_ck) {
ret = clk_prepare_enable(dwmac->clk_eth_ck); ret = clk_prepare_enable(dwmac->clk_eth_ck);
if (ret) { if (ret) {
clk_disable_unprepare(dwmac->syscfg_clk); clk_disable_unprepare(dwmac->syscfg_clk);
...@@ -112,7 +166,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare) ...@@ -112,7 +166,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
} }
} else { } else {
clk_disable_unprepare(dwmac->syscfg_clk); clk_disable_unprepare(dwmac->syscfg_clk);
if (dwmac->int_phyclk) if (dwmac->clk_eth_ck)
clk_disable_unprepare(dwmac->clk_eth_ck); clk_disable_unprepare(dwmac->clk_eth_ck);
} }
return ret; return ret;
...@@ -122,7 +176,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) ...@@ -122,7 +176,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
{ {
struct stm32_dwmac *dwmac = plat_dat->bsp_priv; struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
u32 reg = dwmac->mode_reg; u32 reg = dwmac->mode_reg;
int val; int val, ret;
switch (plat_dat->interface) { switch (plat_dat->interface) {
case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_MII:
...@@ -131,19 +185,22 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) ...@@ -131,19 +185,22 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
break; break;
case PHY_INTERFACE_MODE_GMII: case PHY_INTERFACE_MODE_GMII:
val = SYSCFG_PMCR_ETH_SEL_GMII; val = SYSCFG_PMCR_ETH_SEL_GMII;
if (dwmac->int_phyclk) if (dwmac->eth_clk_sel_reg)
val |= SYSCFG_PMCR_ETH_CLK_SEL; val |= SYSCFG_PMCR_ETH_CLK_SEL;
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n"); pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n");
break; break;
case PHY_INTERFACE_MODE_RMII: case PHY_INTERFACE_MODE_RMII:
val = SYSCFG_PMCR_ETH_SEL_RMII; val = SYSCFG_PMCR_ETH_SEL_RMII;
if (dwmac->int_phyclk) if (dwmac->eth_ref_clk_sel_reg)
val |= SYSCFG_PMCR_ETH_REF_CLK_SEL; val |= SYSCFG_PMCR_ETH_REF_CLK_SEL;
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n"); pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n");
break; break;
case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
val = SYSCFG_PMCR_ETH_SEL_RGMII; val = SYSCFG_PMCR_ETH_SEL_RGMII;
if (dwmac->int_phyclk) if (dwmac->eth_clk_sel_reg)
val |= SYSCFG_PMCR_ETH_CLK_SEL; val |= SYSCFG_PMCR_ETH_CLK_SEL;
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n"); pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n");
break; break;
...@@ -154,6 +211,11 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) ...@@ -154,6 +211,11 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
return -EINVAL; return -EINVAL;
} }
/* Need to update PMCCLRR (clear register) */
ret = regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
dwmac->ops->syscfg_eth_mask);
/* Update PMCSETR (set register) */
return regmap_update_bits(dwmac->regmap, reg, return regmap_update_bits(dwmac->regmap, reg,
dwmac->ops->syscfg_eth_mask, val); dwmac->ops->syscfg_eth_mask, val);
} }
...@@ -181,7 +243,7 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) ...@@ -181,7 +243,7 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat)
} }
return regmap_update_bits(dwmac->regmap, reg, return regmap_update_bits(dwmac->regmap, reg,
dwmac->ops->syscfg_eth_mask, val); dwmac->ops->syscfg_eth_mask, val << 23);
} }
static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac) static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac)
...@@ -237,22 +299,25 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, ...@@ -237,22 +299,25 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
int err = 0; int err = 0;
dwmac->int_phyclk = of_property_read_bool(np, "st,int-phyclk"); /* Gigabit Ethernet 125MHz clock selection. */
dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel");
/* Check if internal clk from RCC selected */ /* Ethernet 50Mhz RMII clock selection */
if (dwmac->int_phyclk) { dwmac->eth_ref_clk_sel_reg =
/* Get ETH_CLK clocks */ of_property_read_bool(np, "st,eth-ref-clk-sel");
dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
if (IS_ERR(dwmac->clk_eth_ck)) { /* Get ETH_CLK clocks */
dev_err(dev, "No ETH CK clock provided...\n"); dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
return PTR_ERR(dwmac->clk_eth_ck); if (IS_ERR(dwmac->clk_eth_ck)) {
} dev_warn(dev, "No phy clock provided...\n");
dwmac->clk_eth_ck = NULL;
} }
/* Clock used for low power mode */ /* Clock used for low power mode */
dwmac->clk_ethstp = devm_clk_get(dev, "ethstp"); dwmac->clk_ethstp = devm_clk_get(dev, "ethstp");
if (IS_ERR(dwmac->clk_ethstp)) { if (IS_ERR(dwmac->clk_ethstp)) {
dev_err(dev, "No ETH peripheral clock provided for CStop mode ...\n"); dev_err(dev,
"No ETH peripheral clock provided for CStop mode ...\n");
return PTR_ERR(dwmac->clk_ethstp); return PTR_ERR(dwmac->clk_ethstp);
} }
...@@ -268,7 +333,7 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, ...@@ -268,7 +333,7 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
*/ */
dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev, dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev,
"stm32_pwr_wakeup"); "stm32_pwr_wakeup");
if (!dwmac->int_phyclk && dwmac->irq_pwr_wakeup >= 0) { if (!dwmac->clk_eth_ck && dwmac->irq_pwr_wakeup >= 0) {
err = device_init_wakeup(&pdev->dev, true); err = device_init_wakeup(&pdev->dev, true);
if (err) { if (err) {
dev_err(&pdev->dev, "Failed to init wake up irq\n"); dev_err(&pdev->dev, "Failed to init wake up irq\n");
...@@ -370,7 +435,7 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac) ...@@ -370,7 +435,7 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
clk_disable_unprepare(dwmac->clk_tx); clk_disable_unprepare(dwmac->clk_tx);
clk_disable_unprepare(dwmac->syscfg_clk); clk_disable_unprepare(dwmac->syscfg_clk);
if (dwmac->int_phyclk) if (dwmac->clk_eth_ck)
clk_disable_unprepare(dwmac->clk_eth_ck); clk_disable_unprepare(dwmac->clk_eth_ck);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment