diff options
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac')
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/Kconfig | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c | 67 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 62 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 18 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 |
9 files changed, 157 insertions, 15 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 2d09c116cbc8..b02d4a3ffa37 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -26,6 +26,16 @@ config STMMAC_PLATFORM If unsure, say N. +config DWMAC_MESON + bool "Amlogic Meson dwmac support" + depends on STMMAC_PLATFORM && ARCH_MESON + help + Support for Ethernet controller on Amlogic Meson SoCs. + + This selects the Amlogic Meson SoC glue layer support for + the stmmac device driver. This driver is used for Meson6 and + Meson8 SoCs. + config DWMAC_SOCFPGA bool "SOCFPGA dwmac support" depends on STMMAC_PLATFORM && MFD_SYSCON && (ARCH_SOCFPGA || COMPILE_TEST) diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 18695ebef7e4..0533d0ba783d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o +stmmac-$(CONFIG_DWMAC_MESON) += dwmac-meson.o stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o stmmac-$(CONFIG_DWMAC_SOCFPGA) += dwmac-socfpga.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c new file mode 100644 index 000000000000..d225a603e604 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c @@ -0,0 +1,67 @@ +/* + * Amlogic Meson DWMAC glue layer + * + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/device.h> +#include <linux/ethtool.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> +#include <linux/stmmac.h> + +#define ETHMAC_SPEED_100 BIT(1) + +struct meson_dwmac { + struct device *dev; + void __iomem *reg; +}; + +static void meson6_dwmac_fix_mac_speed(void *priv, unsigned int speed) +{ + struct meson_dwmac *dwmac = priv; + unsigned int val; + + val = readl(dwmac->reg); + + switch (speed) { + case SPEED_10: + val &= ~ETHMAC_SPEED_100; + break; + case SPEED_100: + val |= ETHMAC_SPEED_100; + break; + } + + writel(val, dwmac->reg); +} + +static void *meson6_dwmac_setup(struct platform_device *pdev) +{ + struct meson_dwmac *dwmac; + struct resource *res; + + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); + if (!dwmac) + return ERR_PTR(-ENOMEM); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + dwmac->reg = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dwmac->reg)) + return dwmac->reg; + + return dwmac; +} + +const struct stmmac_of_data meson6_dwmac_data = { + .setup = meson6_dwmac_setup, + .fix_mac_speed = meson6_dwmac_fix_mac_speed, +}; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index ec632e666c56..3aad413e74b4 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,20 @@ 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 = devm_ioremap_resource(dev, &res_splitter); + if (IS_ERR(dwmac->splitter_base)) { + dev_info(dev, "Failed to mapping emac splitter\n"); + return PTR_ERR(dwmac->splitter_base); + } + } + dwmac->reg_offset = reg_offset; dwmac->reg_shift = reg_shift; dwmac->sys_mgr_base_addr = sys_mgr_base_addr; @@ -91,6 +144,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 +156,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 +257,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, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 58097c0e2ad5..44528896355d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -137,6 +137,9 @@ void stmmac_disable_eee_mode(struct stmmac_priv *priv); bool stmmac_eee_init(struct stmmac_priv *priv); #ifdef CONFIG_STMMAC_PLATFORM +#ifdef CONFIG_DWMAC_MESON +extern const struct stmmac_of_data meson6_dwmac_data; +#endif #ifdef CONFIG_DWMAC_SUNXI extern const struct stmmac_of_data sun7i_gmac_data; #endif diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index cf4f38db1c0a..3a08a1f78c73 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -261,11 +261,11 @@ static int stmmac_ethtool_getsettings(struct net_device *dev, ethtool_cmd_speed_set(cmd, priv->xstats.pcs_speed); /* Get and convert ADV/LP_ADV from the HW AN registers */ - if (priv->hw->mac->get_adv) - priv->hw->mac->get_adv(priv->hw, &adv); - else + if (!priv->hw->mac->get_adv) return -EOPNOTSUPP; /* should never happen indeed */ + priv->hw->mac->get_adv(priv->hw, &adv); + /* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */ if (adv.pause & STMMAC_PCS_PAUSE) @@ -340,19 +340,17 @@ static int stmmac_ethtool_setsettings(struct net_device *dev, if (cmd->autoneg != AUTONEG_ENABLE) return -EINVAL; - if (cmd->autoneg == AUTONEG_ENABLE) { - mask &= (ADVERTISED_1000baseT_Half | + mask &= (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full); - spin_lock(&priv->lock); - if (priv->hw->mac->ctrl_ane) - priv->hw->mac->ctrl_ane(priv->hw, 1); - spin_unlock(&priv->lock); - } + spin_lock(&priv->lock); + if (priv->hw->mac->ctrl_ane) + priv->hw->mac->ctrl_ane(priv->hw, 1); + spin_unlock(&priv->lock); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index b0c1521e08a3..6f77a46c7e2c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -834,7 +834,7 @@ static int stmmac_init_phy(struct net_device *dev) /* Stop Advertising 1000BASE Capability if interface is not GMII */ if ((interface == PHY_INTERFACE_MODE_MII) || (interface == PHY_INTERFACE_MODE_RMII) || - (max_speed < 1000 && max_speed > 0)) + (max_speed < 1000 && max_speed > 0)) phydev->advertising &= ~(SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full); @@ -2765,8 +2765,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, priv->device = device; priv->dev = ndev; - ether_setup(ndev); - stmmac_set_ethtool_ops(ndev); priv->pause = pause; priv->plat = plat_dat; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index a5b1e1b776fe..b735fa22ac95 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -253,7 +253,7 @@ int stmmac_mdio_register(struct net_device *ndev) } /* - * If we're going to bind the MAC to this PHY bus, + * If we're going to bind the MAC to this PHY bus, * and no PHY number was provided to the MAC, * use the one probed here. */ @@ -282,7 +282,7 @@ int stmmac_mdio_register(struct net_device *ndev) } if (!found) { - pr_warning("%s: No PHY found\n", ndev->name); + pr_warn("%s: No PHY found\n", ndev->name); mdiobus_unregister(new_bus); mdiobus_free(new_bus); return -ENODEV; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index bb524a932be4..652171706258 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -30,6 +30,9 @@ #include "stmmac.h" static const struct of_device_id stmmac_dt_ids[] = { +#ifdef CONFIG_DWMAC_MESON + { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data}, +#endif #ifdef CONFIG_DWMAC_SUNXI { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, #endif |