diff mbox series

[U-Boot,1/3] net: designware: socfpga: Add Arria10 extras

Message ID 20180813185632.11459-1-marex@denx.de
State Accepted
Commit 215a06565a701c92e7f6918b7488d949d59c1d50
Delegated to: Marek Vasut
Headers show
Series [U-Boot,1/3] net: designware: socfpga: Add Arria10 extras | expand

Commit Message

Marek Vasut Aug. 13, 2018, 6:56 p.m. UTC
Add wrapper around the designware MAC driver to handle the SoCFPGA
specific configuration bits. On Arria10, this is configuration of
syscon phy_intf.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chin Liang See <chin.liang.see@intel.com>
Cc: Dinh Nguyen <dinguyen@kernel.org>
Cc: Ley Foon Tan <ley.foon.tan@intel.com>
Cc: Joe Hershberger <joe.hershberger@ni.com>
---
NOTE: This driver is not enabled on Gen5 or Stratix10 as the
      implementation for its specifics is missing thus far.
      The driver can be safely enabled though, as the behavior
      of the plain designware mac driver will be retained.
---
 drivers/net/Kconfig         |   8 +++
 drivers/net/Makefile        |   1 +
 drivers/net/dwmac_socfpga.c | 143 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 152 insertions(+)
 create mode 100644 drivers/net/dwmac_socfpga.c

Comments

Joe Hershberger Sept. 19, 2018, 8:04 p.m. UTC | #1
Hi Marek,

On Mon, Aug 13, 2018 at 1:56 PM, Marek Vasut <marex@denx.de> wrote:
> Add wrapper around the designware MAC driver to handle the SoCFPGA
> specific configuration bits. On Arria10, this is configuration of
> syscon phy_intf.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Chin Liang See <chin.liang.see@intel.com>
> Cc: Dinh Nguyen <dinguyen@kernel.org>
> Cc: Ley Foon Tan <ley.foon.tan@intel.com>
> Cc: Joe Hershberger <joe.hershberger@ni.com>

Looks good, but can you add something in doc/device-tree-bindings?

Acked-by: Joe Hershberger <joe.hershberger@ni.com>

> ---
> NOTE: This driver is not enabled on Gen5 or Stratix10 as the
>       implementation for its specifics is missing thus far.
>       The driver can be safely enabled though, as the behavior
>       of the plain designware mac driver will be retained.
> ---
diff mbox series

Patch

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f762b0898d..d86da7760e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -150,6 +150,14 @@  config ETH_DESIGNWARE
 	  100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to
 	  provide the PHY (physical media interface).
 
+config ETH_DESIGNWARE_SOCFPGA
+	bool "Altera SoCFPGA extras for Synopsys Designware Ethernet MAC"
+	depends on DM_ETH && ETH_DESIGNWARE
+	help
+	  The Altera SoCFPGA requires additional configuration of the
+	  Altera system manager to correctly interface with the PHY.
+	  This code handles those SoC specifics.
+
 config ETHOC
 	bool "OpenCores 10/100 Mbps Ethernet MAC"
 	help
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index c1ed44e21f..48a2878071 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -14,6 +14,7 @@  obj-$(CONFIG_CALXEDA_XGMAC) += calxedaxgmac.o
 obj-$(CONFIG_CS8900) += cs8900.o
 obj-$(CONFIG_TULIP) += dc2114x.o
 obj-$(CONFIG_ETH_DESIGNWARE) += designware.o
+obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o
 obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
 obj-$(CONFIG_DNET) += dnet.o
 obj-$(CONFIG_E1000) += e1000.o
diff --git a/drivers/net/dwmac_socfpga.c b/drivers/net/dwmac_socfpga.c
new file mode 100644
index 0000000000..08fc9677c4
--- /dev/null
+++ b/drivers/net/dwmac_socfpga.c
@@ -0,0 +1,143 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Marek Vasut <marex@denx.de>
+ *
+ * Altera SoCFPGA EMAC extras
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <clk.h>
+#include <phy.h>
+#include <regmap.h>
+#include <reset.h>
+#include <syscon.h>
+#include "designware.h"
+
+#include <asm/arch/system_manager.h>
+
+enum dwmac_type {
+	DWMAC_SOCFPGA_GEN5 = 0,
+	DWMAC_SOCFPGA_ARRIA10,
+	DWMAC_SOCFPGA_STRATIX10,
+};
+
+struct dwmac_socfpga_platdata {
+	struct dw_eth_pdata	dw_eth_pdata;
+	enum dwmac_type		type;
+	void			*phy_intf;
+};
+
+static int dwmac_socfpga_ofdata_to_platdata(struct udevice *dev)
+{
+	struct dwmac_socfpga_platdata *pdata = dev_get_platdata(dev);
+	struct regmap *regmap;
+	struct ofnode_phandle_args args;
+	void *range;
+	int ret;
+
+	ret = dev_read_phandle_with_args(dev, "altr,sysmgr-syscon", NULL,
+					 2, 0, &args);
+	if (ret) {
+		dev_err(dev, "Failed to get syscon: %d\n", ret);
+		return ret;
+	}
+
+	if (args.args_count != 2) {
+		dev_err(dev, "Invalid number of syscon args\n");
+		return -EINVAL;
+	}
+
+	regmap = syscon_node_to_regmap(args.node);
+	if (IS_ERR(regmap)) {
+		ret = PTR_ERR(regmap);
+		dev_err(dev, "Failed to get regmap: %d\n", ret);
+		return ret;
+	}
+
+	range = regmap_get_range(regmap, 0);
+	if (!range) {
+		dev_err(dev, "Failed to get regmap range\n");
+		return -ENOMEM;
+	}
+
+	pdata->phy_intf = range + args.args[0];
+
+	/*
+	 * Sadly, the Altera DT bindings don't have SoC-specific compatibles,
+	 * so we have to guesstimate which SoC we are running on from the
+	 * DWMAC version. Luckily, Altera at least updated the DWMAC with
+	 * each SoC.
+	 */
+	if (ofnode_device_is_compatible(dev->node, "snps,dwmac-3.70a"))
+		pdata->type = DWMAC_SOCFPGA_GEN5;
+
+	if (ofnode_device_is_compatible(dev->node, "snps,dwmac-3.72a"))
+		pdata->type = DWMAC_SOCFPGA_ARRIA10;
+
+	if (ofnode_device_is_compatible(dev->node, "snps,dwmac-3.74a"))
+		pdata->type = DWMAC_SOCFPGA_STRATIX10;
+
+	return designware_eth_ofdata_to_platdata(dev);
+}
+
+static int dwmac_socfpga_probe(struct udevice *dev)
+{
+	struct dwmac_socfpga_platdata *pdata = dev_get_platdata(dev);
+	struct eth_pdata *edata = &pdata->dw_eth_pdata.eth_pdata;
+	struct reset_ctl_bulk reset_bulk;
+	int ret;
+	u8 modereg;
+
+	if (pdata->type == DWMAC_SOCFPGA_ARRIA10) {
+		switch (edata->phy_interface) {
+		case PHY_INTERFACE_MODE_MII:
+		case PHY_INTERFACE_MODE_GMII:
+			modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
+			break;
+		case PHY_INTERFACE_MODE_RMII:
+			modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII;
+			break;
+		case PHY_INTERFACE_MODE_RGMII:
+			modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
+			break;
+		default:
+			dev_err(dev, "Unsupported PHY mode\n");
+			return -EINVAL;
+		}
+
+		ret = reset_get_bulk(dev, &reset_bulk);
+		if (ret) {
+			dev_err(dev, "Failed to get reset: %d\n", ret);
+			return ret;
+		}
+
+		reset_assert_bulk(&reset_bulk);
+
+		clrsetbits_le32(pdata->phy_intf,
+				SYSMGR_EMACGRP_CTRL_PHYSEL_MASK,
+				modereg);
+
+		reset_release_bulk(&reset_bulk);
+	}
+
+	return designware_eth_probe(dev);
+}
+
+static const struct udevice_id dwmac_socfpga_ids[] = {
+	{ .compatible = "altr,socfpga-stmmac" },
+	{ }
+};
+
+U_BOOT_DRIVER(dwmac_socfpga) = {
+	.name		= "dwmac_socfpga",
+	.id		= UCLASS_ETH,
+	.of_match	= dwmac_socfpga_ids,
+	.ofdata_to_platdata = dwmac_socfpga_ofdata_to_platdata,
+	.probe		= dwmac_socfpga_probe,
+	.ops		= &designware_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct dw_eth_dev),
+	.platdata_auto_alloc_size = sizeof(struct dwmac_socfpga_platdata),
+	.flags		= DM_FLAG_ALLOC_PRIV_DMA,
+};