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>
This commit is contained in:
commit
3026043dc4
|
@ -11,6 +11,8 @@ Required properties:
|
|||
designware version numbers documented in stmmac.txt
|
||||
- altr,sysmgr-syscon : Should be the phandle to the system manager node that
|
||||
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:
|
||||
altr,emac-splitter: Should be the phandle to the emac splitter soft IP node if
|
||||
|
|
|
@ -35,18 +35,18 @@ Optional properties:
|
|||
- reset-names: Should contain the reset signal name "stmmaceth", if a
|
||||
reset phandle is given
|
||||
- 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.
|
||||
- tx-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:
|
||||
|
||||
|
@ -65,4 +65,11 @@ Examples:
|
|||
tx-fifo-depth = <16384>;
|
||||
clocks = <&clock>;
|
||||
clock-names = "stmmaceth";
|
||||
mdio0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dwmac-mdio";
|
||||
phy1: ethernet-phy@0 {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -439,7 +439,7 @@ struct stmmac_ops {
|
|||
/* PTP and HW Timer helpers */
|
||||
struct stmmac_hwtimestamp {
|
||||
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 (*config_addend) (void __iomem *ioaddr, u32 addend);
|
||||
int (*adjust_systime) (void __iomem *ioaddr, u32 sec, u32 nsec,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
|
||||
#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
|
||||
#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_SPEED_MASK 0x3
|
||||
|
@ -47,6 +48,7 @@ struct socfpga_dwmac {
|
|||
struct regmap *sys_mgr_base_addr;
|
||||
struct reset_control *stmmac_rst;
|
||||
void __iomem *splitter_base;
|
||||
bool f2h_ptp_ref_clk;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (np_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 |= 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);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -33,22 +33,25 @@ static void stmmac_config_hw_tstamping(void __iomem *ioaddr, u32 data)
|
|||
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);
|
||||
unsigned long data;
|
||||
|
||||
/* Convert the ptp_clock to nano second
|
||||
* formula = (1/ptp_clock) * 1000000000
|
||||
* formula = (2/ptp_clock) * 1000000000
|
||||
* where, ptp_clock = 50MHz.
|
||||
*/
|
||||
data = (1000000000ULL / 50000000);
|
||||
data = (2000000000ULL / ptp_clock);
|
||||
|
||||
/* 0.465ns accuracy */
|
||||
if (!(value & PTP_TCR_TSCTRLSSR))
|
||||
data = (data * 1000) / 465;
|
||||
|
||||
writel(data, ioaddr + PTP_SSIR);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static int stmmac_init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "stmmac.h"
|
||||
#include <linux/reset.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include "dwmac1000.h"
|
||||
|
||||
#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;
|
||||
else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_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;
|
||||
}
|
||||
}
|
||||
|
@ -435,6 +436,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
|
|||
u32 ts_master_en = 0;
|
||||
u32 ts_event_en = 0;
|
||||
u32 value = 0;
|
||||
u32 sec_inc;
|
||||
|
||||
if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
|
||||
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 |
|
||||
ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
|
||||
ts_master_en | snap_type_sel);
|
||||
|
||||
priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
|
||||
|
||||
/* 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:
|
||||
* formula is :
|
||||
* 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->hw->ptp->config_addend(priv->ioaddr,
|
||||
priv->default_addend);
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <linux/of_mdio.h>
|
||||
#include <asm/io.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_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
|
||||
int addr, found;
|
||||
struct device_node *mdio_node = NULL;
|
||||
struct device_node *child_node = NULL;
|
||||
|
||||
if (!mdio_bus_data)
|
||||
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();
|
||||
if (new_bus == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -231,7 +250,8 @@ int stmmac_mdio_register(struct net_device *ndev)
|
|||
new_bus->irq = irqlist;
|
||||
new_bus->phy_mask = mdio_bus_data->phy_mask;
|
||||
new_bus->parent = priv->device;
|
||||
err = mdiobus_register(new_bus);
|
||||
|
||||
err = of_mdiobus_register(new_bus, mdio_node);
|
||||
if (err != 0) {
|
||||
pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
|
||||
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);
|
||||
mdiobus_unregister(new_bus);
|
||||
mdiobus_free(new_bus);
|
||||
|
|
|
@ -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)
|
||||
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;
|
||||
else
|
||||
plat->mdio_bus_data =
|
||||
|
|
Loading…
Reference in New Issue