On Wed, Aug 20, 2014 at 2:33 PM, Ley Foon Tan <lf...@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 <lf...@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 linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/