فهرست منبع

Merge branch 'stmmac-mdio-compat'

Merge branch 'stmmac-mdio-compat'

Phil Reid says:

====================
stmmac: create of compatible mdio bus for stmacc driver

Provide ability to specify a fixed phy in the device tree and
retain the mdio bus if no phy is found. This is needed where
a dsa is connected via a fixed phy and uses the mdio bus for config.
Fixed ptp ref clock calculatins for the stmmac when ptp ref clock
is running at <= 50Mhz. Also add device tree setting to config
ptp clk source on socfpga platforms.

Changes from V5:
- Restore behaviour of unregister mdio bus when no phys found
  if there is no device tree node create the bus.
- Modify condition to allocate mdio_base_data conditional
  on fixed phy presece as well. Maintains existing behaviour
  in conditions where a fixed phy is not present.

Changes from V4:
- Restore #ifdef CONFIG_OF around setting of reset_gpio.
  Member doesn't exist when this isn't defined.

Changes from V3:
- Use if (IS_ENABLED(CONFIG_OF)) instead of #if.
  Reorder some code to reduce if statements.
- of_mdiobus_register already falls back to mdiobus_register
- Tested on system with CONFIG_OF

Changes from V2:
- Formatting, spaces & lines > 80 chars. Using checkpatch
- Drop PTP register debugfs patch.

Changes from V1:
- Fixed mismatch doc / code for ptp_ref_clk dt node.
- Remove unit address from doc example.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
David S. Miller 10 سال پیش
والد
کامیت
3026043dc4

+ 2 - 0
Documentation/devicetree/bindings/net/socfpga-dwmac.txt

@@ -11,6 +11,8 @@ Required properties:
 		  designware version numbers documented in stmmac.txt
 		  designware version numbers documented in stmmac.txt
  - altr,sysmgr-syscon : Should be the phandle to the system manager node that
  - altr,sysmgr-syscon : Should be the phandle to the system manager node that
    encompasses the glue register, the register offset, and the register shift.
    encompasses the glue register, the register offset, and the register shift.
+ - altr,f2h_ptp_ref_clk use f2h_ptp_ref_clk instead of default eosc1 clock
+   for ptp ref clk. This affects all emacs as the clock is common.
 
 
 Optional properties:
 Optional properties:
 altr,emac-splitter: Should be the phandle to the emac splitter soft IP node if
 altr,emac-splitter: Should be the phandle to the emac splitter soft IP node if

+ 16 - 9
Documentation/devicetree/bindings/net/stmmac.txt

@@ -35,18 +35,18 @@ Optional properties:
 - reset-names: Should contain the reset signal name "stmmaceth", if a
 - reset-names: Should contain the reset signal name "stmmaceth", if a
 	reset phandle is given
 	reset phandle is given
 - max-frame-size: See ethernet.txt file in the same directory
 - max-frame-size: See ethernet.txt file in the same directory
-- clocks: If present, the first clock should be the GMAC main clock and
-  the second clock should be peripheral's register interface clock. Further
-  clocks may be specified in derived bindings.
-- clock-names: One name for each entry in the clocks property, the
-  first one should be "stmmaceth" and the second one should be "pclk".
-- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is
-  available this clock is used for programming the Timestamp Addend Register.
-  If not passed then the system clock will be used and this is fine on some
-  platforms.
+- clocks: If present, the first clock should be the GMAC main clock
+  The optional second clock should be peripheral's register interface clock.
+  The third optional clock should be the ptp reference clock.
+  Further clocks may be specified in derived bindings.
+- clock-names: One name for each entry in the clocks property.
+  The first one should be "stmmaceth".
+  The optional second one should be "pclk".
+  The optional third one should be "clk_ptp_ref".
 - snps,burst_len: The AXI burst lenth value of the AXI BUS MODE register.
 - snps,burst_len: The AXI burst lenth value of the AXI BUS MODE register.
 - tx-fifo-depth: See ethernet.txt file in the same directory
 - tx-fifo-depth: See ethernet.txt file in the same directory
 - rx-fifo-depth: See ethernet.txt file in the same directory
 - rx-fifo-depth: See ethernet.txt file in the same directory
+- mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus.
 
 
 Examples:
 Examples:
 
 
@@ -65,4 +65,11 @@ Examples:
 		tx-fifo-depth = <16384>;
 		tx-fifo-depth = <16384>;
 		clocks = <&clock>;
 		clocks = <&clock>;
 		clock-names = "stmmaceth";
 		clock-names = "stmmaceth";
+		mdio0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "snps,dwmac-mdio";
+			phy1: ethernet-phy@0 {
+			};
+		};
 	};
 	};

+ 1 - 1
drivers/net/ethernet/stmicro/stmmac/common.h

@@ -439,7 +439,7 @@ struct stmmac_ops {
 /* PTP and HW Timer helpers */
 /* PTP and HW Timer helpers */
 struct stmmac_hwtimestamp {
 struct stmmac_hwtimestamp {
 	void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
 	void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
-	void (*config_sub_second_increment) (void __iomem *ioaddr);
+	u32 (*config_sub_second_increment) (void __iomem *ioaddr, u32 clk_rate);
 	int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
 	int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
 	int (*config_addend) (void __iomem *ioaddr, u32 addend);
 	int (*config_addend) (void __iomem *ioaddr, u32 addend);
 	int (*adjust_systime) (void __iomem *ioaddr, u32 sec, u32 nsec,
 	int (*adjust_systime) (void __iomem *ioaddr, u32 sec, u32 nsec,

+ 9 - 0
drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c

@@ -32,6 +32,7 @@
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
+#define SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000010
 
 
 #define EMAC_SPLITTER_CTRL_REG			0x0
 #define EMAC_SPLITTER_CTRL_REG			0x0
 #define EMAC_SPLITTER_CTRL_SPEED_MASK		0x3
 #define EMAC_SPLITTER_CTRL_SPEED_MASK		0x3
@@ -47,6 +48,7 @@ struct socfpga_dwmac {
 	struct regmap *sys_mgr_base_addr;
 	struct regmap *sys_mgr_base_addr;
 	struct reset_control *stmmac_rst;
 	struct reset_control *stmmac_rst;
 	void __iomem *splitter_base;
 	void __iomem *splitter_base;
+	bool f2h_ptp_ref_clk;
 };
 };
 
 
 static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
 static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
@@ -116,6 +118,8 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
+	dwmac->f2h_ptp_ref_clk = of_property_read_bool(np, "altr,f2h_ptp_ref_clk");
+
 	np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0);
 	np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0);
 	if (np_splitter) {
 	if (np_splitter) {
 		if (of_address_to_resource(np_splitter, 0, &res_splitter)) {
 		if (of_address_to_resource(np_splitter, 0, &res_splitter)) {
@@ -171,6 +175,11 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
 	ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
 	ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
 	ctrl |= val << reg_shift;
 	ctrl |= val << reg_shift;
 
 
+	if (dwmac->f2h_ptp_ref_clk)
+		ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2);
+	else
+		ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2));
+
 	regmap_write(sys_mgr_base_addr, reg_offset, ctrl);
 	regmap_write(sys_mgr_base_addr, reg_offset, ctrl);
 	return 0;
 	return 0;
 }
 }

+ 6 - 3
drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c

@@ -33,22 +33,25 @@ static void stmmac_config_hw_tstamping(void __iomem *ioaddr, u32 data)
 	writel(data, ioaddr + PTP_TCR);
 	writel(data, ioaddr + PTP_TCR);
 }
 }
 
 
-static void stmmac_config_sub_second_increment(void __iomem *ioaddr)
+static u32 stmmac_config_sub_second_increment(void __iomem *ioaddr,
+					      u32 ptp_clock)
 {
 {
 	u32 value = readl(ioaddr + PTP_TCR);
 	u32 value = readl(ioaddr + PTP_TCR);
 	unsigned long data;
 	unsigned long data;
 
 
 	/* Convert the ptp_clock to nano second
 	/* Convert the ptp_clock to nano second
-	 * formula = (1/ptp_clock) * 1000000000
+	 * formula = (2/ptp_clock) * 1000000000
 	 * where, ptp_clock = 50MHz.
 	 * where, ptp_clock = 50MHz.
 	 */
 	 */
-	data = (1000000000ULL / 50000000);
+	data = (2000000000ULL / ptp_clock);
 
 
 	/* 0.465ns accuracy */
 	/* 0.465ns accuracy */
 	if (!(value & PTP_TCR_TSCTRLSSR))
 	if (!(value & PTP_TCR_TSCTRLSSR))
 		data = (data * 1000) / 465;
 		data = (data * 1000) / 465;
 
 
 	writel(data, ioaddr + PTP_SSIR);
 	writel(data, ioaddr + PTP_SSIR);
+
+	return data;
 }
 }
 
 
 static int stmmac_init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)
 static int stmmac_init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)

+ 8 - 11
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

@@ -53,6 +53,7 @@
 #include "stmmac.h"
 #include "stmmac.h"
 #include <linux/reset.h>
 #include <linux/reset.h>
 #include <linux/of_mdio.h>
 #include <linux/of_mdio.h>
+#include "dwmac1000.h"
 
 
 #define STMMAC_ALIGN(x)	L1_CACHE_ALIGN(x)
 #define STMMAC_ALIGN(x)	L1_CACHE_ALIGN(x)
 
 
@@ -185,7 +186,7 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv)
 			priv->clk_csr = STMMAC_CSR_100_150M;
 			priv->clk_csr = STMMAC_CSR_100_150M;
 		else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
 		else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
 			priv->clk_csr = STMMAC_CSR_150_250M;
 			priv->clk_csr = STMMAC_CSR_150_250M;
-		else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M))
+		else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
 			priv->clk_csr = STMMAC_CSR_250_300M;
 			priv->clk_csr = STMMAC_CSR_250_300M;
 	}
 	}
 }
 }
@@ -435,6 +436,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
 	u32 ts_master_en = 0;
 	u32 ts_master_en = 0;
 	u32 ts_event_en = 0;
 	u32 ts_event_en = 0;
 	u32 value = 0;
 	u32 value = 0;
+	u32 sec_inc;
 
 
 	if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
 	if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
 		netdev_alert(priv->dev, "No support for HW time stamping\n");
 		netdev_alert(priv->dev, "No support for HW time stamping\n");
@@ -598,24 +600,19 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
 			 tstamp_all | ptp_v2 | ptp_over_ethernet |
 			 tstamp_all | ptp_v2 | ptp_over_ethernet |
 			 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
 			 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
 			 ts_master_en | snap_type_sel);
 			 ts_master_en | snap_type_sel);
-
 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
 
 
 		/* program Sub Second Increment reg */
 		/* program Sub Second Increment reg */
-		priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
+		sec_inc = priv->hw->ptp->config_sub_second_increment(
+			priv->ioaddr, priv->clk_ptp_rate);
+		temp = div_u64(1000000000ULL, sec_inc);
 
 
 		/* calculate default added value:
 		/* calculate default added value:
 		 * formula is :
 		 * formula is :
 		 * addend = (2^32)/freq_div_ratio;
 		 * addend = (2^32)/freq_div_ratio;
-		 * where, freq_div_ratio = clk_ptp_ref_i/50MHz
-		 * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
-		 * NOTE: clk_ptp_ref_i should be >= 50MHz to
-		 *       achieve 20ns accuracy.
-		 *
-		 * 2^x * y == (y << x), hence
-		 * 2^32 * 50000000 ==> (50000000 << 32)
+		 * where, freq_div_ratio = 1e9ns/sec_inc
 		 */
 		 */
-		temp = (u64) (50000000ULL << 32);
+		temp = (u64)(temp << 32);
 		priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
 		priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
 		priv->hw->ptp->config_addend(priv->ioaddr,
 		priv->hw->ptp->config_addend(priv->ioaddr,
 					     priv->default_addend);
 					     priv->default_addend);

+ 23 - 3
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c

@@ -29,7 +29,7 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_gpio.h>
-
+#include <linux/of_mdio.h>
 #include <asm/io.h>
 #include <asm/io.h>
 
 
 #include "stmmac.h"
 #include "stmmac.h"
@@ -200,10 +200,29 @@ int stmmac_mdio_register(struct net_device *ndev)
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
 	struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
 	int addr, found;
 	int addr, found;
+	struct device_node *mdio_node = NULL;
+	struct device_node *child_node = NULL;
 
 
 	if (!mdio_bus_data)
 	if (!mdio_bus_data)
 		return 0;
 		return 0;
 
 
+	if (IS_ENABLED(CONFIG_OF)) {
+		for_each_child_of_node(priv->device->of_node, child_node) {
+			if (of_device_is_compatible(child_node,
+						    "snps,dwmac-mdio")) {
+				mdio_node = child_node;
+				break;
+			}
+		}
+
+		if (mdio_node) {
+			netdev_dbg(ndev, "FOUND MDIO subnode\n");
+		} else {
+			netdev_err(ndev, "NO MDIO subnode\n");
+			return 0;
+		}
+	}
+
 	new_bus = mdiobus_alloc();
 	new_bus = mdiobus_alloc();
 	if (new_bus == NULL)
 	if (new_bus == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
@@ -231,7 +250,8 @@ int stmmac_mdio_register(struct net_device *ndev)
 	new_bus->irq = irqlist;
 	new_bus->irq = irqlist;
 	new_bus->phy_mask = mdio_bus_data->phy_mask;
 	new_bus->phy_mask = mdio_bus_data->phy_mask;
 	new_bus->parent = priv->device;
 	new_bus->parent = priv->device;
-	err = mdiobus_register(new_bus);
+
+	err = of_mdiobus_register(new_bus, mdio_node);
 	if (err != 0) {
 	if (err != 0) {
 		pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
 		pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
 		goto bus_register_fail;
 		goto bus_register_fail;
@@ -284,7 +304,7 @@ int stmmac_mdio_register(struct net_device *ndev)
 		}
 		}
 	}
 	}
 
 
-	if (!found) {
+	if (!found && !mdio_node) {
 		pr_warn("%s: No PHY found\n", ndev->name);
 		pr_warn("%s: No PHY found\n", ndev->name);
 		mdiobus_unregister(new_bus);
 		mdiobus_unregister(new_bus);
 		mdiobus_free(new_bus);
 		mdiobus_free(new_bus);

+ 1 - 1
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c

@@ -146,7 +146,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
 	if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
 	if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
 		dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
 		dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
 
 
-	if (plat->phy_node || plat->phy_bus_name)
+	if ((plat->phy_node && !of_phy_is_fixed_link(np)) || plat->phy_bus_name)
 		plat->mdio_bus_data = NULL;
 		plat->mdio_bus_data = NULL;
 	else
 	else
 		plat->mdio_bus_data =
 		plat->mdio_bus_data =