Commit ffb3016b authored by David S. Miller's avatar David S. Miller

Merge branch 'stmmac-add-some-fixes-for-stm32'

Christophe Roullier says:

====================
stmmac: add some fixes for stm32

For common stmmac:
	- Add support to set CSR Clock range selection in DT
For stm32mpu:
	- Glue codes to support magic packet
	- Glue codes to support all PHY config :
		PHY_MODE (MII,GMII, RMII, RGMII) and in normal,
		PHY wo crystal (25Mhz),
		PHY wo crystal (50Mhz), No 125Mhz from PHY config
For stm32mcu:
	- Add Ethernet support for stm32h7

Changes in V3:
	- Reverse for syscfg management because it is manage by these patches
	  https://lkml.org/lkml/2018/12/12/133
	  https://lkml.org/lkml/2018/12/12/134
	  https://lkml.org/lkml/2018/12/12/131
	  https://lkml.org/lkml/2018/12/12/132
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f1a16705 5473f1be
...@@ -14,8 +14,7 @@ Required properties: ...@@ -14,8 +14,7 @@ Required properties:
- clock-names: Should be "stmmaceth" for the host clock. - clock-names: Should be "stmmaceth" for the host clock.
Should be "mac-clk-tx" for the MAC TX clock. Should be "mac-clk-tx" for the MAC TX clock.
Should be "mac-clk-rx" for the MAC RX clock. Should be "mac-clk-rx" for the MAC RX clock.
For MPU family need to add also "ethstp" for power mode clock and, For MPU family need to add also "ethstp" for power mode clock
"syscfg-clk" for SYSCFG clock.
- interrupt-names: Should contain a list of interrupt names corresponding to - interrupt-names: Should contain a list of interrupt names corresponding to
the interrupts in the interrupts property, if available. the interrupts in the interrupts property, if available.
Should be "macirq" for the main MAC IRQ Should be "macirq" for the main MAC IRQ
...@@ -24,9 +23,9 @@ Required properties: ...@@ -24,9 +23,9 @@ Required properties:
encompases the glue register, and the offset of the control register. encompases the glue register, and the offset of the control register.
Optional properties: Optional properties:
- clock-names: For MPU family "mac-clk-ck" for PHY without quartz - clock-names: For MPU family "eth-ck" for PHY without quartz
- st,int-phyclk (boolean) : valid only where PHY do not have quartz and need to be clock - st,eth-clk-sel (boolean) : set this property in RGMII PHY when you want to select RCC clock instead of ETH_CLK125.
by RCC - st,eth-ref-clk-sel (boolean) : set this property in RMII mode when you have PHY without crystal 50MHz and want to select RCC clock instead of ETH_REF_CLK.
Example: Example:
......
...@@ -173,6 +173,21 @@ pins { ...@@ -173,6 +173,21 @@ pins {
}; };
}; };
ethernet_rmii: rmii@0 {
pins {
pinmux = <STM32_PINMUX('G', 11, AF11)>,
<STM32_PINMUX('G', 13, AF11)>,
<STM32_PINMUX('G', 12, AF11)>,
<STM32_PINMUX('C', 4, AF11)>,
<STM32_PINMUX('C', 5, AF11)>,
<STM32_PINMUX('A', 7, AF11)>,
<STM32_PINMUX('C', 1, AF11)>,
<STM32_PINMUX('A', 2, AF11)>,
<STM32_PINMUX('A', 1, AF11)>;
slew-rate = <2>;
};
};
usart1_pins: usart1@0 { usart1_pins: usart1@0 {
pins1 { pins1 {
pinmux = <STM32_PINMUX('B', 14, AF4)>; /* USART1_TX */ pinmux = <STM32_PINMUX('B', 14, AF4)>; /* USART1_TX */
......
...@@ -511,6 +511,19 @@ adc3: adc@0 { ...@@ -511,6 +511,19 @@ adc3: adc@0 {
status = "disabled"; status = "disabled";
}; };
}; };
mac: ethernet@40028000 {
compatible = "st,stm32-dwmac", "snps,dwmac-4.10a";
reg = <0x40028000 0x8000>;
reg-names = "stmmaceth";
interrupts = <61>;
interrupt-names = "macirq";
clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
clocks = <&rcc ETH1MAC_CK>, <&rcc ETH1TX_CK>, <&rcc ETH1RX_CK>;
st,syscon = <&syscfg 0x4>;
snps,pbl = <8>;
status = "disabled";
};
}; };
}; };
......
...@@ -66,6 +66,23 @@ &clk_hse { ...@@ -66,6 +66,23 @@ &clk_hse {
clock-frequency = <25000000>; clock-frequency = <25000000>;
}; };
&mac {
status = "disabled";
pinctrl-0 = <&ethernet_rmii>;
pinctrl-names = "default";
phy-mode = "rmii";
phy-handle = <&phy0>;
mdio0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
phy0: ethernet-phy@0 {
reg = <0>;
};
};
};
&usart2 { &usart2 {
pinctrl-0 = <&usart2_pins>; pinctrl-0 = <&usart2_pins>;
pinctrl-names = "default"; pinctrl-names = "default";
......
...@@ -104,6 +104,23 @@ &rtc { ...@@ -104,6 +104,23 @@ &rtc {
status = "okay"; status = "okay";
}; };
&mac {
status = "disabled";
pinctrl-0 = <&ethernet_rmii>;
pinctrl-names = "default";
phy-mode = "rmii";
phy-handle = <&phy0>;
mdio0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
phy0: ethernet-phy@0 {
reg = <0>;
};
};
};
&usart1 { &usart1 {
pinctrl-0 = <&usart1_pins>; pinctrl-0 = <&usart1_pins>;
pinctrl-names = "default"; pinctrl-names = "default";
......
...@@ -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,13 +50,53 @@ ...@@ -35,13 +50,53 @@
#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;
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;
...@@ -102,7 +157,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare) ...@@ -102,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);
...@@ -111,7 +166,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare) ...@@ -111,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;
...@@ -121,7 +176,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) ...@@ -121,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:
...@@ -130,19 +185,22 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) ...@@ -130,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;
...@@ -153,6 +211,11 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) ...@@ -153,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);
} }
...@@ -180,7 +243,7 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) ...@@ -180,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)
...@@ -232,24 +295,29 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac, ...@@ -232,24 +295,29 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac,
static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
struct device *dev) struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev);
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
int err = 0;
/* Gigabit Ethernet 125MHz clock selection. */
dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel");
dwmac->int_phyclk = of_property_read_bool(np, "st,int-phyclk"); /* Ethernet 50Mhz RMII clock selection */
dwmac->eth_ref_clk_sel_reg =
of_property_read_bool(np, "st,eth-ref-clk-sel");
/* Check if internal clk from RCC selected */
if (dwmac->int_phyclk) {
/* Get ETH_CLK clocks */ /* Get ETH_CLK clocks */
dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck"); dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
if (IS_ERR(dwmac->clk_eth_ck)) { if (IS_ERR(dwmac->clk_eth_ck)) {
dev_err(dev, "No ETH CK clock provided...\n"); dev_warn(dev, "No phy clock provided...\n");
return PTR_ERR(dwmac->clk_eth_ck); 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);
} }
...@@ -260,7 +328,26 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, ...@@ -260,7 +328,26 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
return PTR_ERR(dwmac->syscfg_clk); return PTR_ERR(dwmac->syscfg_clk);
} }
return 0; /* Get IRQ information early to have an ability to ask for deferred
* probe if needed before we went too far with resource allocation.
*/
dwmac->irq_pwr_wakeup = platform_get_irq_byname(pdev,
"stm32_pwr_wakeup");
if (!dwmac->clk_eth_ck && dwmac->irq_pwr_wakeup >= 0) {
err = device_init_wakeup(&pdev->dev, true);
if (err) {
dev_err(&pdev->dev, "Failed to init wake up irq\n");
return err;
}
err = dev_pm_set_dedicated_wake_irq(&pdev->dev,
dwmac->irq_pwr_wakeup);
if (err) {
dev_err(&pdev->dev, "Failed to set wake up irq\n");
device_init_wakeup(&pdev->dev, false);
}
device_set_wakeup_enable(&pdev->dev, false);
}
return err;
} }
static int stm32_dwmac_probe(struct platform_device *pdev) static int stm32_dwmac_probe(struct platform_device *pdev)
...@@ -326,9 +413,15 @@ static int stm32_dwmac_remove(struct platform_device *pdev) ...@@ -326,9 +413,15 @@ static int stm32_dwmac_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev); struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
int ret = stmmac_dvr_remove(&pdev->dev); int ret = stmmac_dvr_remove(&pdev->dev);
struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
stm32_dwmac_clk_disable(priv->plat->bsp_priv); stm32_dwmac_clk_disable(priv->plat->bsp_priv);
if (dwmac->irq_pwr_wakeup >= 0) {
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
}
return ret; return ret;
} }
...@@ -342,7 +435,7 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac) ...@@ -342,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;
......
...@@ -408,6 +408,9 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) ...@@ -408,6 +408,9 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
/* Default to phy auto-detection */ /* Default to phy auto-detection */
plat->phy_addr = -1; plat->phy_addr = -1;
/* Get clk_csr from device tree */
of_property_read_u32(np, "clk_csr", &plat->clk_csr);
/* "snps,phy-addr" is not a standard property. Mark it as deprecated /* "snps,phy-addr" is not a standard property. Mark it as deprecated
* and warn of its use. Remove this when phy node support is added. * and warn of its use. Remove this when phy node support is added.
*/ */
......
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