summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-03-08 11:48:20 -0800
committerDavid S. Miller <davem@davemloft.net>2019-03-08 11:48:20 -0800
commitffb3016bd6f2cc92b46b3232e88e3c27fdb86db1 (patch)
tree6cba91ed7105fe84411ddff358baa96b55bb0f24
parentf1a167050d0edc089d8155274611883c9db62743 (diff)
parent5473f1be53c90252d3323e69e90a29379e608aaa (diff)
downloadlinux-ffb3016bd6f2cc92b46b3232e88e3c27fdb86db1.tar.bz2
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: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/devicetree/bindings/net/stm32-dwmac.txt9
-rw-r--r--arch/arm/boot/dts/stm32h743-pinctrl.dtsi15
-rw-r--r--arch/arm/boot/dts/stm32h743.dtsi13
-rw-r--r--arch/arm/boot/dts/stm32h743i-disco.dts17
-rw-r--r--arch/arm/boot/dts/stm32h743i-eval.dts17
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c135
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c3
7 files changed, 183 insertions, 26 deletions
diff --git a/Documentation/devicetree/bindings/net/stm32-dwmac.txt b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
index 1341012722aa..a90eef11dc46 100644
--- a/Documentation/devicetree/bindings/net/stm32-dwmac.txt
+++ b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
@@ -14,8 +14,7 @@ Required properties:
- clock-names: Should be "stmmaceth" for the host clock.
Should be "mac-clk-tx" for the MAC TX clock.
Should be "mac-clk-rx" for the MAC RX clock.
- For MPU family need to add also "ethstp" for power mode clock and,
- "syscfg-clk" for SYSCFG clock.
+ For MPU family need to add also "ethstp" for power mode clock
- interrupt-names: Should contain a list of interrupt names corresponding to
the interrupts in the interrupts property, if available.
Should be "macirq" for the main MAC IRQ
@@ -24,9 +23,9 @@ Required properties:
encompases the glue register, and the offset of the control register.
Optional properties:
-- clock-names: For MPU family "mac-clk-ck" for PHY without quartz
-- st,int-phyclk (boolean) : valid only where PHY do not have quartz and need to be clock
- by RCC
+- clock-names: For MPU family "eth-ck" for PHY without quartz
+- st,eth-clk-sel (boolean) : set this property in RGMII PHY when you want to select RCC clock instead of ETH_CLK125.
+- 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:
diff --git a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
index 24be8e63dec8..980b2769caf9 100644
--- a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
@@ -173,6 +173,21 @@
};
};
+ 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 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF4)>; /* USART1_TX */
diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi
index cbdd69ca9e7a..e103b29969ca 100644
--- a/arch/arm/boot/dts/stm32h743.dtsi
+++ b/arch/arm/boot/dts/stm32h743.dtsi
@@ -511,6 +511,19 @@
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";
+ };
};
};
diff --git a/arch/arm/boot/dts/stm32h743i-disco.dts b/arch/arm/boot/dts/stm32h743i-disco.dts
index 45e088c55741..83ef63d515a8 100644
--- a/arch/arm/boot/dts/stm32h743i-disco.dts
+++ b/arch/arm/boot/dts/stm32h743i-disco.dts
@@ -66,6 +66,23 @@
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 {
pinctrl-0 = <&usart2_pins>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/stm32h743i-eval.dts b/arch/arm/boot/dts/stm32h743i-eval.dts
index 3f8e0c4a998d..383c5bb03720 100644
--- a/arch/arm/boot/dts/stm32h743i-eval.dts
+++ b/arch/arm/boot/dts/stm32h743i-eval.dts
@@ -104,6 +104,23 @@
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 {
pinctrl-0 = <&usart1_pins>;
pinctrl-names = "default";
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
index 7e2e79dedebf..062a600fa5a7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -25,9 +25,24 @@
#define SYSCFG_MCU_ETH_MASK BIT(23)
#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_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_RGMII BIT(21)
#define SYSCFG_PMCR_ETH_SEL_RMII BIT(23)
@@ -35,14 +50,54 @@
#define SYSCFG_MCU_ETH_SEL_MII 0
#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 clk *clk_tx;
struct clk *clk_rx;
struct clk *clk_eth_ck;
struct clk *clk_ethstp;
struct clk *syscfg_clk;
- bool int_phyclk; /* Clock from RCC to drive PHY */
- u32 mode_reg; /* MAC glue-logic mode register */
+ int eth_clk_sel_reg;
+ int eth_ref_clk_sel_reg;
+ int irq_pwr_wakeup;
+ u32 mode_reg; /* MAC glue-logic mode register */
struct regmap *regmap;
u32 speed;
const struct stm32_ops *ops;
@@ -102,7 +157,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
if (ret)
return ret;
- if (dwmac->int_phyclk) {
+ if (dwmac->clk_eth_ck) {
ret = clk_prepare_enable(dwmac->clk_eth_ck);
if (ret) {
clk_disable_unprepare(dwmac->syscfg_clk);
@@ -111,7 +166,7 @@ static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
}
} else {
clk_disable_unprepare(dwmac->syscfg_clk);
- if (dwmac->int_phyclk)
+ if (dwmac->clk_eth_ck)
clk_disable_unprepare(dwmac->clk_eth_ck);
}
return ret;
@@ -121,7 +176,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
{
struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
u32 reg = dwmac->mode_reg;
- int val;
+ int val, ret;
switch (plat_dat->interface) {
case PHY_INTERFACE_MODE_MII:
@@ -130,19 +185,22 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
break;
case PHY_INTERFACE_MODE_GMII:
val = SYSCFG_PMCR_ETH_SEL_GMII;
- if (dwmac->int_phyclk)
+ if (dwmac->eth_clk_sel_reg)
val |= SYSCFG_PMCR_ETH_CLK_SEL;
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n");
break;
case PHY_INTERFACE_MODE_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;
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n");
break;
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;
- if (dwmac->int_phyclk)
+ if (dwmac->eth_clk_sel_reg)
val |= SYSCFG_PMCR_ETH_CLK_SEL;
pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n");
break;
@@ -153,6 +211,11 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
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,
dwmac->ops->syscfg_eth_mask, val);
}
@@ -180,7 +243,7 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat)
}
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)
@@ -232,24 +295,29 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac,
static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
struct device_node *np = dev->of_node;
+ 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 */
- if (dwmac->int_phyclk) {
- /* Get ETH_CLK clocks */
- dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
- if (IS_ERR(dwmac->clk_eth_ck)) {
- dev_err(dev, "No ETH CK clock provided...\n");
- return PTR_ERR(dwmac->clk_eth_ck);
- }
+ /* Ethernet 50Mhz RMII clock selection */
+ dwmac->eth_ref_clk_sel_reg =
+ of_property_read_bool(np, "st,eth-ref-clk-sel");
+
+ /* Get ETH_CLK clocks */
+ dwmac->clk_eth_ck = devm_clk_get(dev, "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 */
dwmac->clk_ethstp = devm_clk_get(dev, "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);
}
@@ -260,7 +328,26 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
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)
@@ -326,9 +413,15 @@ static int stm32_dwmac_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
int ret = stmmac_dvr_remove(&pdev->dev);
+ struct stm32_dwmac *dwmac = 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;
}
@@ -342,7 +435,7 @@ static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
clk_disable_unprepare(dwmac->clk_tx);
clk_disable_unprepare(dwmac->syscfg_clk);
- if (dwmac->int_phyclk)
+ if (dwmac->clk_eth_ck)
clk_disable_unprepare(dwmac->clk_eth_ck);
return ret;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 2b800ce1d5bf..3031f2bf15d6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -408,6 +408,9 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
/* Default to phy auto-detection */
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
* and warn of its use. Remove this when phy node support is added.
*/