From c1f902841ce3c759a4dddbf02ccc8012e4c50162 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Wed, 10 Jan 2018 09:14:17 +0100 Subject: net: designware: move probe to generic driver The designware ethernet core is used on multiple different SoCs. The linux kernel has a generic driver and SoC-specific drivers. Do the same here. Signed-off-by: Steffen Trumtrar Signed-off-by: Sascha Hauer --- drivers/net/Kconfig | 12 +++++++- drivers/net/Makefile | 1 + drivers/net/designware.c | 60 ++++------------------------------------ drivers/net/designware.h | 33 ++++++++++++++++++++++ drivers/net/designware_generic.c | 59 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 55 deletions(-) create mode 100644 drivers/net/designware_generic.c (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9d69b6aeb0..36b257f43e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -64,13 +64,23 @@ config DRIVER_NET_DAVINCI_EMAC select PHYLIB config DRIVER_NET_DESIGNWARE - bool "Designware Universal MAC ethernet driver" + bool "Designware Universal MAC ethernet platform support" depends on HAS_DMA select PHYLIB help This option enables support for the Synopsys Designware Core Univesal MAC 10M/100M/1G ethernet IP. +if DRIVER_NET_DESIGNWARE + +config DRIVER_NET_DESIGNWARE_GENERIC + bool "Designware Universal MAC ethernet generic driver" + help + This option enables support for the Synopsys + Designware Core Univesal MAC 10M/100M/1G ethernet IP on SoCFPGA. + +endif + config DRIVER_NET_DM9K bool "Davicom dm9k[E|A|B] ethernet driver" depends on HAS_DM9000 diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 86c8ac32f9..eb07434ab4 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_DRIVER_NET_CS8900) += cs8900.o obj-$(CONFIG_DRIVER_NET_CPSW) += cpsw.o obj-$(CONFIG_DRIVER_NET_DAVINCI_EMAC) += davinci_emac.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE) += designware.o +obj-$(CONFIG_DRIVER_NET_DESIGNWARE_GENERIC) += designware_generic.o obj-$(CONFIG_DRIVER_NET_DM9K) += dm9k.o obj-$(CONFIG_DRIVER_NET_E1000) += e1000/regio.o e1000/main.o e1000/eeprom.o obj-$(CONFIG_DRIVER_NET_ENC28J60) += enc28j60.o diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 1d3a68384e..ec20da09b3 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -32,36 +32,6 @@ #include #include "designware.h" -struct dw_eth_dev { - struct eth_device netdev; - struct mii_bus miibus; - - void (*fix_mac_speed)(int speed); - u8 macaddr[6]; - u32 tx_currdescnum; - u32 rx_currdescnum; - - struct dmamacdescr *tx_mac_descrtable; - struct dmamacdescr *rx_mac_descrtable; - - u8 *txbuffs; - u8 *rxbuffs; - - struct eth_mac_regs *mac_regs_p; - struct eth_dma_regs *dma_regs_p; - int phy_addr; - phy_interface_t interface; - int enh_desc; -}; - -struct dw_eth_drvdata { - bool enh_desc; -}; - -static struct dw_eth_drvdata dwmac_370a_drvdata = { - .enh_desc = 1, -}; - /* Speed specific definitions */ #define SPEED_10M 1 #define SPEED_100M 2 @@ -447,7 +417,7 @@ static int dwc_probe_dt(struct device_d *dev, struct dw_eth_dev *priv) return 0; } -static int dwc_ether_probe(struct device_d *dev) +struct dw_eth_dev *dwc_drv_probe(struct device_d *dev) { struct resource *iores; struct dw_eth_dev *priv; @@ -462,7 +432,7 @@ static int dwc_ether_probe(struct device_d *dev) ret = dev_get_drvdata(dev, (const void **)&drvdata); if (ret) - return ret; + return ERR_PTR(ret); priv->enh_desc = drvdata->enh_desc; @@ -473,12 +443,12 @@ static int dwc_ether_probe(struct device_d *dev) } else { ret = dwc_probe_dt(dev, priv); if (ret) - return ret; + return ERR_PTR(ret); } iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) - return PTR_ERR(iores); + return ERR_CAST(iores); base = IOMEM(iores->start); priv->mac_regs_p = base; @@ -512,24 +482,6 @@ static int dwc_ether_probe(struct device_d *dev) mdiobus_register(miibus); eth_register(edev); - return 0; -} -static __maybe_unused struct of_device_id dwc_ether_compatible[] = { - { - .compatible = "snps,dwmac-3.70a", - .data = &dwmac_370a_drvdata, - }, { - .compatible = "snps,dwmac-3.72a", - .data = &dwmac_370a_drvdata, - }, { - /* sentinel */ - } -}; - -static struct driver_d dwc_ether_driver = { - .name = "designware_eth", - .probe = dwc_ether_probe, - .of_compatible = DRV_OF_COMPAT(dwc_ether_compatible), -}; -device_platform_driver(dwc_ether_driver); + return priv; +} diff --git a/drivers/net/designware.h b/drivers/net/designware.h index c36ba78779..c9dc27a594 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -20,6 +20,39 @@ #ifndef __DESIGNWARE_ETH_H #define __DESIGNWARE_ETH_H +struct eth_device; +struct mii_bus; + +struct dw_eth_dev { + struct eth_device netdev; + struct mii_bus miibus; + + void (*fix_mac_speed)(int speed); + u8 macaddr[6]; + u32 tx_currdescnum; + u32 rx_currdescnum; + + struct dmamacdescr *tx_mac_descrtable; + struct dmamacdescr *rx_mac_descrtable; + + u8 *txbuffs; + u8 *rxbuffs; + + struct eth_mac_regs *mac_regs_p; + struct eth_dma_regs *dma_regs_p; + int phy_addr; + phy_interface_t interface; + int enh_desc; + + struct reset_control *rst; +}; + +struct dw_eth_drvdata { + bool enh_desc; +}; + +struct dw_eth_dev *dwc_drv_probe(struct device_d *dev); + #define CONFIG_TX_DESCR_NUM 16 #define CONFIG_RX_DESCR_NUM 16 #define CONFIG_ETH_BUFSIZE 2048 diff --git a/drivers/net/designware_generic.c b/drivers/net/designware_generic.c new file mode 100644 index 0000000000..0e5b9c067b --- /dev/null +++ b/drivers/net/designware_generic.c @@ -0,0 +1,59 @@ +/* + * (C) Copyright 2010 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* + * Designware ethernet IP driver for u-boot + */ + +#include +#include "designware.h" + +static struct dw_eth_drvdata dwmac_370a_drvdata = { + .enh_desc = 1, +}; + +static int dwc_ether_probe(struct device_d *dev) +{ + struct dw_eth_dev *dwc; + + dwc = dwc_drv_probe(dev); + if (IS_ERR(dwc)) + return PTR_ERR(dwc); + + return 0; +} + +static __maybe_unused struct of_device_id dwc_ether_compatible[] = { + { + .compatible = "snps,dwmac-3.70a", + .data = &dwmac_370a_drvdata, + }, { + .compatible = "snps,dwmac-3.72a", + .data = &dwmac_370a_drvdata, + }, { + /* sentinel */ + } +}; + +static struct driver_d dwc_ether_driver = { + .name = "designware_eth", + .probe = dwc_ether_probe, + .of_compatible = DRV_OF_COMPAT(dwc_ether_compatible), +}; +device_platform_driver(dwc_ether_driver); -- cgit v1.2.3 From 3b6f631bfd2d5d80a4be338ee8947863e6f4e445 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Wed, 10 Jan 2018 09:14:18 +0100 Subject: net: add SoCFPGA-specific designware driver Add a driver for the SoCFPGA-specific version of the designware ethernet ip core. Signed-off-by: Steffen Trumtrar Signed-off-by: Sascha Hauer --- .../include/mach/cyclone5-system-manager.h | 3 + drivers/net/Kconfig | 7 + drivers/net/Makefile | 1 + drivers/net/designware_socfpga.c | 184 +++++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 drivers/net/designware_socfpga.c (limited to 'drivers') diff --git a/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h b/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h index 9efc37a4dc..24f52effd8 100644 --- a/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h +++ b/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h @@ -65,4 +65,7 @@ void socfpga_sysmgr_pinmux_init(unsigned long *sys_mgr_init_table, int num); #define SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB 2 #define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003 +#define SYSMGR_FPGAGRP_MODULE 0x00000028 +#define SYSMGR_FPGAGRP_MODULE_EMAC 0x00000004 + #endif /* _SYSTEM_MANAGER_H_ */ diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 36b257f43e..09676b3d60 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -79,6 +79,13 @@ config DRIVER_NET_DESIGNWARE_GENERIC This option enables support for the Synopsys Designware Core Univesal MAC 10M/100M/1G ethernet IP on SoCFPGA. +config DRIVER_NET_DESIGNWARE_SOCFPGA + bool "Designware Universal MAC ethernet driver for SoCFPGA platforms" + depends on ARCH_SOCFPGA + help + This option enables support for the Synopsys + Designware Core Univesal MAC 10M/100M/1G ethernet IP on SoCFPGA. + endif config DRIVER_NET_DM9K diff --git a/drivers/net/Makefile b/drivers/net/Makefile index eb07434ab4..304bbba02d 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_DRIVER_NET_CPSW) += cpsw.o obj-$(CONFIG_DRIVER_NET_DAVINCI_EMAC) += davinci_emac.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE) += designware.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE_GENERIC) += designware_generic.o +obj-$(CONFIG_DRIVER_NET_DESIGNWARE_SOCFPGA) += designware_socfpga.o obj-$(CONFIG_DRIVER_NET_DM9K) += dm9k.o obj-$(CONFIG_DRIVER_NET_E1000) += e1000/regio.o e1000/main.o e1000/eeprom.o obj-$(CONFIG_DRIVER_NET_ENC28J60) += enc28j60.o diff --git a/drivers/net/designware_socfpga.c b/drivers/net/designware_socfpga.c new file mode 100644 index 0000000000..154c38f9a1 --- /dev/null +++ b/drivers/net/designware_socfpga.c @@ -0,0 +1,184 @@ +/* + * (C) Copyright 2010 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* + * Designware ethernet IP driver for u-boot + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "designware.h" + +#define SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000010 + +struct socfpga_dwc_dev { + struct dw_eth_dev *priv; + u32 reg_offset; + u32 reg_shift; + void __iomem *sys_mgr_base; + bool f2h_ptp_ref_clk; +}; + +static int socfpga_dwc_set_phy_mode(struct socfpga_dwc_dev *dwc_dev) +{ + struct dw_eth_dev *eth_dev = dwc_dev->priv; + int phymode = eth_dev->interface; + u32 reg_offset = dwc_dev->reg_offset; + u32 reg_shift = dwc_dev->reg_shift; + u32 ctrl, val; + + 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: + case PHY_INTERFACE_MODE_GMII: + case PHY_INTERFACE_MODE_SGMII: + val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; + break; + default: + dev_err(ð_dev->netdev.dev, "bad phy mode %d\n", phymode); + return -EINVAL; + } + + /* Assert reset to the enet controller before changing the phy mode */ + if (eth_dev->rst) + reset_control_assert(eth_dev->rst); + + ctrl = readl(dwc_dev->sys_mgr_base + reg_offset); + ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); + ctrl |= val << reg_shift; + + if (dwc_dev->f2h_ptp_ref_clk || + phymode == PHY_INTERFACE_MODE_MII || + phymode == PHY_INTERFACE_MODE_GMII || + phymode == PHY_INTERFACE_MODE_SGMII) { + u32 module; + + ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2); + module = readl(dwc_dev->sys_mgr_base + SYSMGR_FPGAGRP_MODULE); + module |= (SYSMGR_FPGAGRP_MODULE_EMAC << (reg_shift / 2)); + + writel(module, dwc_dev->sys_mgr_base + SYSMGR_FPGAGRP_MODULE); + } else { + ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2)); + } + + writel(ctrl, dwc_dev->sys_mgr_base + reg_offset); + + /* Deassert reset for the phy configuration to be sampled by + * the enet controller, and operation to start in requested mode + */ + if (eth_dev->rst) + reset_control_deassert(eth_dev->rst); + + return 0; +} + +static int socfpga_dwc_probe_dt(struct device_d *dev, struct socfpga_dwc_dev *priv) +{ + u32 reg_offset, reg_shift; + int ret; + + if (!IS_ENABLED(CONFIG_OFTREE)) + return -ENODEV; + + ret = of_property_read_u32_index(dev->device_node, "altr,sysmgr-syscon", + 1, ®_offset); + if (ret) { + dev_err(dev, "Could not read reg_offset from sysmgr-syscon! Please update the devicetree.\n"); + + return -EINVAL; + } + + ret = of_property_read_u32_index(dev->device_node, "altr,sysmgr-syscon", + 2, ®_shift); + if (ret) { + dev_err(dev, "Could not read reg_shift from sysmgr-syscon! Please update the devicetree.\n"); + return -EINVAL; + } + + priv->f2h_ptp_ref_clk = of_property_read_bool(dev->device_node, "altr,f2h_ptp_ref_clk"); + + priv->reg_offset = reg_offset; + priv->reg_shift = reg_shift; + + return 0; +} + +static int socfpga_dwc_ether_probe(struct device_d *dev) +{ + struct socfpga_dwc_dev *dwc_dev; + struct dw_eth_dev *priv; + int ret; + + dwc_dev = xzalloc(sizeof(*dwc_dev)); + + priv = dwc_drv_probe(dev); + if (IS_ERR(priv)) + return PTR_ERR(priv); + + priv->rst = reset_control_get(dev, NULL); + if (IS_ERR(priv->rst)) + dev_warn(dev, "No reset lines.\n"); + + dwc_dev->priv = priv; + + dwc_dev->sys_mgr_base = syscon_base_lookup_by_phandle(dev->device_node, + "altr,sysmgr-syscon"); + if (IS_ERR(dwc_dev->sys_mgr_base)) { + dev_err(dev, "Could not get sysmgr-syscon node\n"); + return PTR_ERR(dwc_dev->sys_mgr_base); + } + + ret = socfpga_dwc_probe_dt(dev, dwc_dev); + if (ret) + return ret; + + socfpga_dwc_set_phy_mode(dwc_dev); + + return 0; +} + +static struct dw_eth_drvdata socfpga_stmmac_drvdata = { + .enh_desc = 1, +}; + +static __maybe_unused struct of_device_id socfpga_dwc_ether_compatible[] = { + { + .compatible = "altr,socfpga-stmmac", + .data = &socfpga_stmmac_drvdata, + }, { + /* sentinel */ + } +}; + +static struct driver_d socfpga_dwc_ether_driver = { + .name = "socfpga_designware_eth", + .probe = socfpga_dwc_ether_probe, + .of_compatible = DRV_OF_COMPAT(socfpga_dwc_ether_compatible), +}; +device_platform_driver(socfpga_dwc_ether_driver); -- cgit v1.2.3 From 0becc3085f4d948d8f2674b43e0e9e5f5425fcc7 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Wed, 10 Jan 2018 09:14:20 +0100 Subject: net: designware: add warning for drvdata Instead of silently using a wrong value, check if drvdata is defined before use. Print a warning if there is no drvdata found. Signed-off-by: Steffen Trumtrar Signed-off-by: Sascha Hauer --- drivers/net/designware.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/designware.c b/drivers/net/designware.c index ec20da09b3..862ee2f046 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -434,7 +434,11 @@ struct dw_eth_dev *dwc_drv_probe(struct device_d *dev) if (ret) return ERR_PTR(ret); - priv->enh_desc = drvdata->enh_desc; + if (drvdata && drvdata->enh_desc) + priv->enh_desc = drvdata->enh_desc; + else + dev_warn(dev, "No drvdata specified\n"); + if (pdata) { priv->phy_addr = pdata->phy_addr; -- cgit v1.2.3