net: designware: socfpga: Add Arria10 extras

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>
This commit is contained in:
Marek Vasut 2018-08-13 19:32:14 +02:00
parent f9edeb32a9
commit 215a06565a
3 changed files with 152 additions and 0 deletions

View File

@ -150,6 +150,14 @@ config ETH_DESIGNWARE
100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to 100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to
provide the PHY (physical media interface). 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 config ETHOC
bool "OpenCores 10/100 Mbps Ethernet MAC" bool "OpenCores 10/100 Mbps Ethernet MAC"
help help

View File

@ -14,6 +14,7 @@ obj-$(CONFIG_CALXEDA_XGMAC) += calxedaxgmac.o
obj-$(CONFIG_CS8900) += cs8900.o obj-$(CONFIG_CS8900) += cs8900.o
obj-$(CONFIG_TULIP) += dc2114x.o obj-$(CONFIG_TULIP) += dc2114x.o
obj-$(CONFIG_ETH_DESIGNWARE) += designware.o obj-$(CONFIG_ETH_DESIGNWARE) += designware.o
obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o
obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_DNET) += dnet.o
obj-$(CONFIG_E1000) += e1000.o obj-$(CONFIG_E1000) += e1000.o

143
drivers/net/dwmac_socfpga.c Normal file
View File

@ -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,
};