summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.c166
2 files changed, 98 insertions, 71 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 553a8897b005..27083af54568 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -26,6 +26,9 @@
#include "hwif.h"
#include "mmc.h"
+#define DWMAC_SNPSVER GENMASK_U32(7, 0)
+#define DWMAC_USERVER GENMASK_U32(15, 8)
+
/* Synopsys Core versions */
#define DWMAC_CORE_3_40 0x34
#define DWMAC_CORE_3_50 0x35
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 41a7e1841227..8212441f9826 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -13,31 +13,42 @@
#include "dwmac4_descs.h"
#include "dwxgmac2.h"
-static u32 stmmac_get_id(struct stmmac_priv *priv, u32 id_reg)
+struct stmmac_version {
+ u8 snpsver;
+ u8 dev_id;
+};
+
+static void stmmac_get_version(struct stmmac_priv *priv,
+ struct stmmac_version *ver)
{
- u32 reg = readl(priv->ioaddr + id_reg);
+ enum dwmac_core_type core_type = priv->plat->core_type;
+ unsigned int version_offset;
+ u32 version;
- if (!reg) {
- dev_info(priv->device, "Version ID not available\n");
- return 0x0;
- }
+ ver->snpsver = 0;
+ ver->dev_id = 0;
- dev_info(priv->device, "User ID: 0x%x, Synopsys ID: 0x%x\n",
- (unsigned int)(reg & GENMASK(15, 8)) >> 8,
- (unsigned int)(reg & GENMASK(7, 0)));
- return reg & GENMASK(7, 0);
-}
+ if (core_type == DWMAC_CORE_MAC100)
+ return;
-static u32 stmmac_get_dev_id(struct stmmac_priv *priv, u32 id_reg)
-{
- u32 reg = readl(priv->ioaddr + id_reg);
+ if (core_type == DWMAC_CORE_GMAC)
+ version_offset = GMAC_VERSION;
+ else
+ version_offset = GMAC4_VERSION;
- if (!reg) {
+ version = readl(priv->ioaddr + version_offset);
+ if (version == 0) {
dev_info(priv->device, "Version ID not available\n");
- return 0x0;
+ return;
}
- return (reg & GENMASK(15, 8)) >> 8;
+ dev_info(priv->device, "User ID: 0x%x, Synopsys ID: 0x%x\n",
+ FIELD_GET(DWMAC_USERVER, version),
+ FIELD_GET(DWMAC_SNPSVER, version));
+
+ ver->snpsver = FIELD_GET(DWMAC_SNPSVER, version);
+ if (core_type == DWMAC_CORE_XGMAC)
+ ver->dev_id = FIELD_GET(DWMAC_USERVER, version);
}
static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv)
@@ -288,27 +299,43 @@ static const struct stmmac_hwif_entry {
},
};
+static const struct stmmac_hwif_entry *
+stmmac_hwif_find(enum dwmac_core_type core_type, u8 snpsver, u8 dev_id)
+{
+ const struct stmmac_hwif_entry *entry;
+ int i;
+
+ for (i = ARRAY_SIZE(stmmac_hw) - 1; i >= 0; i--) {
+ entry = &stmmac_hw[i];
+
+ if (core_type != entry->core_type)
+ continue;
+ /* Use synopsys_id var because some setups can override this */
+ if (snpsver < entry->min_id)
+ continue;
+ if (core_type == DWMAC_CORE_XGMAC &&
+ dev_id != entry->dev_id)
+ continue;
+
+ return entry;
+ }
+
+ return NULL;
+}
+
int stmmac_hwif_init(struct stmmac_priv *priv)
{
enum dwmac_core_type core_type = priv->plat->core_type;
const struct stmmac_hwif_entry *entry;
+ struct stmmac_version version;
struct mac_device_info *mac;
bool needs_setup = true;
- u32 id, dev_id = 0;
- int i, ret;
+ int ret;
- if (core_type == DWMAC_CORE_GMAC) {
- id = stmmac_get_id(priv, GMAC_VERSION);
- } else if (dwmac_is_xmac(core_type)) {
- id = stmmac_get_id(priv, GMAC4_VERSION);
- if (core_type == DWMAC_CORE_XGMAC)
- dev_id = stmmac_get_dev_id(priv, GMAC4_VERSION);
- } else {
- id = 0;
- }
+ stmmac_get_version(priv, &version);
/* Save ID for later use */
- priv->synopsys_id = id;
+ priv->synopsys_id = version.snpsver;
/* Lets assume some safe values first */
if (core_type == DWMAC_CORE_GMAC4) {
@@ -336,51 +363,48 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
spin_lock_init(&mac->irq_ctrl_lock);
/* Fallback to generic HW */
- for (i = ARRAY_SIZE(stmmac_hw) - 1; i >= 0; i--) {
- entry = &stmmac_hw[i];
- if (core_type != entry->core_type)
- continue;
- /* Use synopsys_id var because some setups can override this */
- if (priv->synopsys_id < entry->min_id)
- continue;
- if (core_type == DWMAC_CORE_XGMAC && (dev_id ^ entry->dev_id))
- continue;
+ /* Use synopsys_id var because some setups can override this */
+ entry = stmmac_hwif_find(core_type, priv->synopsys_id, version.dev_id);
+ if (!entry) {
+ dev_err(priv->device,
+ "Failed to find HW IF (id=0x%x, gmac=%d/%d)\n",
+ version.snpsver, core_type == DWMAC_CORE_GMAC,
+ core_type == DWMAC_CORE_GMAC4);
- /* Only use generic HW helpers if needed */
- mac->desc = mac->desc ? : entry->desc;
- mac->dma = mac->dma ? : entry->dma;
- mac->mac = mac->mac ? : entry->mac;
- mac->ptp = mac->ptp ? : entry->hwtimestamp;
- mac->mode = mac->mode ? : entry->mode;
- mac->tc = mac->tc ? : entry->tc;
- mac->mmc = mac->mmc ? : entry->mmc;
- mac->est = mac->est ? : entry->est;
- mac->vlan = mac->vlan ? : entry->vlan;
-
- priv->hw = mac;
- priv->fpe_cfg.reg = entry->regs.fpe_reg;
- priv->ptpaddr = priv->ioaddr + entry->regs.ptp_off;
- priv->mmcaddr = priv->ioaddr + entry->regs.mmc_off;
- memcpy(&priv->ptp_clock_ops, entry->ptp,
- sizeof(struct ptp_clock_info));
- if (entry->est)
- priv->estaddr = priv->ioaddr + entry->regs.est_off;
-
- /* Entry found */
- if (needs_setup) {
- ret = entry->setup(priv);
- if (ret)
- return ret;
- }
+ return -EINVAL;
+ }
- /* Save quirks, if needed for posterior use */
- priv->hwif_quirks = entry->quirks;
- return 0;
+ /* Only use generic HW helpers if needed */
+ mac->desc = mac->desc ? : entry->desc;
+ mac->dma = mac->dma ? : entry->dma;
+ mac->mac = mac->mac ? : entry->mac;
+ mac->ptp = mac->ptp ? : entry->hwtimestamp;
+ mac->mode = mac->mode ? : entry->mode;
+ mac->tc = mac->tc ? : entry->tc;
+ mac->mmc = mac->mmc ? : entry->mmc;
+ mac->est = mac->est ? : entry->est;
+ mac->vlan = mac->vlan ? : entry->vlan;
+
+ priv->hw = mac;
+ priv->fpe_cfg.reg = entry->regs.fpe_reg;
+ priv->ptpaddr = priv->ioaddr + entry->regs.ptp_off;
+ priv->mmcaddr = priv->ioaddr + entry->regs.mmc_off;
+ memcpy(&priv->ptp_clock_ops, entry->ptp,
+ sizeof(struct ptp_clock_info));
+
+ if (entry->est)
+ priv->estaddr = priv->ioaddr + entry->regs.est_off;
+
+ /* Entry found */
+ if (needs_setup) {
+ ret = entry->setup(priv);
+ if (ret)
+ return ret;
}
- dev_err(priv->device, "Failed to find HW IF (id=0x%x, gmac=%d/%d)\n",
- id, core_type == DWMAC_CORE_GMAC,
- core_type == DWMAC_CORE_GMAC4);
- return -EINVAL;
+ /* Save quirks, if needed for posterior use */
+ priv->hwif_quirks = entry->quirks;
+
+ return 0;
}