Message ID | 1408516413-2928-1-git-send-email-lftan@altera.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
On Wed, Aug 20, 2014 at 2:33 PM, Ley Foon Tan <lftan@altera.com> wrote: > This patch adds fix_mac_speed() support for > Altera socfpga Ethernet controller. Emac splitter is a > soft IP core in FPGA system that converts GMII interface from > Synopsys mac to RGMII/SGMII interface. This splitter core is > an optional IP if user would like to use RGMII/SGMII > interface in their system. Software needs to update a register > in splitter core when there is speed change. > > Signed-off-by: Ley Foon Tan <lftan@altera.com> > --- > .../devicetree/bindings/net/socfpga-dwmac.txt | 4 ++ > .../net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 63 ++++++++++++++++++++++ > 2 files changed, 67 insertions(+) > > diff --git a/Documentation/devicetree/bindings/net/socfpga-dwmac.txt b/Documentation/devicetree/bindings/net/socfpga-dwmac.txt > index 2a60cd3..3a9d679 100644 > --- a/Documentation/devicetree/bindings/net/socfpga-dwmac.txt > +++ b/Documentation/devicetree/bindings/net/socfpga-dwmac.txt > @@ -12,6 +12,10 @@ Required properties: > - altr,sysmgr-syscon : Should be the phandle to the system manager node that > encompasses the glue register, the register offset, and the register shift. > > +Optional properties: > +altr,emac-splitter: Should be the phandle to the emac splitter soft IP node if > + DWMAC controller is connected emac splitter. > + > Example: > > gmac0: ethernet@ff700000 { > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c > index ec632e6..cd613d7 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c > @@ -17,6 +17,7 @@ > > #include <linux/mfd/syscon.h> > #include <linux/of.h> > +#include <linux/of_address.h> > #include <linux/of_net.h> > #include <linux/phy.h> > #include <linux/regmap.h> > @@ -30,6 +31,12 @@ > #define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2 > #define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003 > > +#define EMAC_SPLITTER_CTRL_REG 0x0 > +#define EMAC_SPLITTER_CTRL_SPEED_MASK 0x3 > +#define EMAC_SPLITTER_CTRL_SPEED_10 0x2 > +#define EMAC_SPLITTER_CTRL_SPEED_100 0x3 > +#define EMAC_SPLITTER_CTRL_SPEED_1000 0x0 > + > struct socfpga_dwmac { > int interface; > u32 reg_offset; > @@ -37,14 +44,46 @@ struct socfpga_dwmac { > struct device *dev; > struct regmap *sys_mgr_base_addr; > struct reset_control *stmmac_rst; > + void __iomem *splitter_base; > }; > > +static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) > +{ > + struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv; > + void __iomem *splitter_base = dwmac->splitter_base; > + u32 val; > + > + if (!splitter_base) > + return; > + > + val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG); > + val &= ~EMAC_SPLITTER_CTRL_SPEED_MASK; > + > + switch (speed) { > + case 1000: > + val |= EMAC_SPLITTER_CTRL_SPEED_1000; > + break; > + case 100: > + val |= EMAC_SPLITTER_CTRL_SPEED_100; > + break; > + case 10: > + val |= EMAC_SPLITTER_CTRL_SPEED_10; > + break; > + default: > + return; > + } > + > + writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); > +} > + > static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) > { > struct device_node *np = dev->of_node; > struct regmap *sys_mgr_base_addr; > u32 reg_offset, reg_shift; > int ret; > + struct device_node *np_splitter; > + struct resource res_splitter; > > dwmac->stmmac_rst = devm_reset_control_get(dev, > STMMAC_RESOURCE_NAME); > @@ -73,6 +112,21 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device * > return -EINVAL; > } > > + np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0); > + if (np_splitter) { > + if (of_address_to_resource(np_splitter, 0, &res_splitter)) { > + dev_info(dev, "Missing emac splitter address\n"); > + return -EINVAL; > + } > + > + dwmac->splitter_base = (void *)devm_ioremap_resource(dev, > + &res_splitter); > + if (!dwmac->splitter_base) { > + dev_info(dev, "Failed to mapping emac splitter\n"); > + return -EINVAL; > + } > + } > + > dwmac->reg_offset = reg_offset; > dwmac->reg_shift = reg_shift; > dwmac->sys_mgr_base_addr = sys_mgr_base_addr; > @@ -91,6 +145,7 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac) > > switch (phymode) { > case PHY_INTERFACE_MODE_RGMII: > + case PHY_INTERFACE_MODE_RGMII_ID: > val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; > break; > case PHY_INTERFACE_MODE_MII: > @@ -102,6 +157,13 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac) > return -EINVAL; > } > > + /* Overwrite val to GMII if splitter core is enabled. The phymode here > + * is the actual phy mode on phy hardware, but phy interface from > + * EMAC core is GMII. > + */ > + if (dwmac->splitter_base) > + val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; > + > regmap_read(sys_mgr_base_addr, reg_offset, &ctrl); > ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); > ctrl |= val << reg_shift; > @@ -196,4 +258,5 @@ const struct stmmac_of_data socfpga_gmac_data = { > .setup = socfpga_dwmac_probe, > .init = socfpga_dwmac_init, > .exit = socfpga_dwmac_exit, > + .fix_mac_speed = socfpga_dwmac_fix_mac_speed, > }; > -- > 1.8.2.1 > Adding David S. Miller to CC list. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Ley Foon Tan <lftan@altera.com> Date: Wed, 20 Aug 2014 14:33:33 +0800 > This patch adds fix_mac_speed() support for > Altera socfpga Ethernet controller. Emac splitter is a > soft IP core in FPGA system that converts GMII interface from > Synopsys mac to RGMII/SGMII interface. This splitter core is > an optional IP if user would like to use RGMII/SGMII > interface in their system. Software needs to update a register > in splitter core when there is speed change. > > Signed-off-by: Ley Foon Tan <lftan@altera.com> Applied. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/Documentation/devicetree/bindings/net/socfpga-dwmac.txt b/Documentation/devicetree/bindings/net/socfpga-dwmac.txt index 2a60cd3..3a9d679 100644 --- a/Documentation/devicetree/bindings/net/socfpga-dwmac.txt +++ b/Documentation/devicetree/bindings/net/socfpga-dwmac.txt @@ -12,6 +12,10 @@ Required properties: - altr,sysmgr-syscon : Should be the phandle to the system manager node that encompasses the glue register, the register offset, and the register shift. +Optional properties: +altr,emac-splitter: Should be the phandle to the emac splitter soft IP node if + DWMAC controller is connected emac splitter. + Example: gmac0: ethernet@ff700000 { diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index ec632e6..cd613d7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -17,6 +17,7 @@ #include <linux/mfd/syscon.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_net.h> #include <linux/phy.h> #include <linux/regmap.h> @@ -30,6 +31,12 @@ #define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2 #define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003 +#define EMAC_SPLITTER_CTRL_REG 0x0 +#define EMAC_SPLITTER_CTRL_SPEED_MASK 0x3 +#define EMAC_SPLITTER_CTRL_SPEED_10 0x2 +#define EMAC_SPLITTER_CTRL_SPEED_100 0x3 +#define EMAC_SPLITTER_CTRL_SPEED_1000 0x0 + struct socfpga_dwmac { int interface; u32 reg_offset; @@ -37,14 +44,46 @@ struct socfpga_dwmac { struct device *dev; struct regmap *sys_mgr_base_addr; struct reset_control *stmmac_rst; + void __iomem *splitter_base; }; +static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) +{ + struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv; + void __iomem *splitter_base = dwmac->splitter_base; + u32 val; + + if (!splitter_base) + return; + + val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG); + val &= ~EMAC_SPLITTER_CTRL_SPEED_MASK; + + switch (speed) { + case 1000: + val |= EMAC_SPLITTER_CTRL_SPEED_1000; + break; + case 100: + val |= EMAC_SPLITTER_CTRL_SPEED_100; + break; + case 10: + val |= EMAC_SPLITTER_CTRL_SPEED_10; + break; + default: + return; + } + + writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); +} + static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) { struct device_node *np = dev->of_node; struct regmap *sys_mgr_base_addr; u32 reg_offset, reg_shift; int ret; + struct device_node *np_splitter; + struct resource res_splitter; dwmac->stmmac_rst = devm_reset_control_get(dev, STMMAC_RESOURCE_NAME); @@ -73,6 +112,21 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device * return -EINVAL; } + np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0); + if (np_splitter) { + if (of_address_to_resource(np_splitter, 0, &res_splitter)) { + dev_info(dev, "Missing emac splitter address\n"); + return -EINVAL; + } + + dwmac->splitter_base = (void *)devm_ioremap_resource(dev, + &res_splitter); + if (!dwmac->splitter_base) { + dev_info(dev, "Failed to mapping emac splitter\n"); + return -EINVAL; + } + } + dwmac->reg_offset = reg_offset; dwmac->reg_shift = reg_shift; dwmac->sys_mgr_base_addr = sys_mgr_base_addr; @@ -91,6 +145,7 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac) switch (phymode) { case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; break; case PHY_INTERFACE_MODE_MII: @@ -102,6 +157,13 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac) return -EINVAL; } + /* Overwrite val to GMII if splitter core is enabled. The phymode here + * is the actual phy mode on phy hardware, but phy interface from + * EMAC core is GMII. + */ + if (dwmac->splitter_base) + val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; + regmap_read(sys_mgr_base_addr, reg_offset, &ctrl); ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); ctrl |= val << reg_shift; @@ -196,4 +258,5 @@ const struct stmmac_of_data socfpga_gmac_data = { .setup = socfpga_dwmac_probe, .init = socfpga_dwmac_init, .exit = socfpga_dwmac_exit, + .fix_mac_speed = socfpga_dwmac_fix_mac_speed, };
This patch adds fix_mac_speed() support for Altera socfpga Ethernet controller. Emac splitter is a soft IP core in FPGA system that converts GMII interface from Synopsys mac to RGMII/SGMII interface. This splitter core is an optional IP if user would like to use RGMII/SGMII interface in their system. Software needs to update a register in splitter core when there is speed change. Signed-off-by: Ley Foon Tan <lftan@altera.com> --- .../devicetree/bindings/net/socfpga-dwmac.txt | 4 ++ .../net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 63 ++++++++++++++++++++++ 2 files changed, 67 insertions(+)