cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hwif.c (7960B)


      1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
      2/*
      3 * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates.
      4 * stmmac HW Interface Handling
      5 */
      6
      7#include "common.h"
      8#include "stmmac.h"
      9#include "stmmac_ptp.h"
     10
     11static u32 stmmac_get_id(struct stmmac_priv *priv, u32 id_reg)
     12{
     13	u32 reg = readl(priv->ioaddr + id_reg);
     14
     15	if (!reg) {
     16		dev_info(priv->device, "Version ID not available\n");
     17		return 0x0;
     18	}
     19
     20	dev_info(priv->device, "User ID: 0x%x, Synopsys ID: 0x%x\n",
     21			(unsigned int)(reg & GENMASK(15, 8)) >> 8,
     22			(unsigned int)(reg & GENMASK(7, 0)));
     23	return reg & GENMASK(7, 0);
     24}
     25
     26static u32 stmmac_get_dev_id(struct stmmac_priv *priv, u32 id_reg)
     27{
     28	u32 reg = readl(priv->ioaddr + id_reg);
     29
     30	if (!reg) {
     31		dev_info(priv->device, "Version ID not available\n");
     32		return 0x0;
     33	}
     34
     35	return (reg & GENMASK(15, 8)) >> 8;
     36}
     37
     38static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv)
     39{
     40	struct mac_device_info *mac = priv->hw;
     41
     42	if (priv->chain_mode) {
     43		dev_info(priv->device, "Chain mode enabled\n");
     44		priv->mode = STMMAC_CHAIN_MODE;
     45		mac->mode = &chain_mode_ops;
     46	} else {
     47		dev_info(priv->device, "Ring mode enabled\n");
     48		priv->mode = STMMAC_RING_MODE;
     49		mac->mode = &ring_mode_ops;
     50	}
     51}
     52
     53static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
     54{
     55	struct mac_device_info *mac = priv->hw;
     56
     57	if (priv->plat->enh_desc) {
     58		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
     59
     60		/* GMAC older than 3.50 has no extended descriptors */
     61		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
     62			dev_info(priv->device, "Enabled extended descriptors\n");
     63			priv->extend_desc = 1;
     64		} else {
     65			dev_warn(priv->device, "Extended descriptors not supported\n");
     66		}
     67
     68		mac->desc = &enh_desc_ops;
     69	} else {
     70		dev_info(priv->device, "Normal descriptors\n");
     71		mac->desc = &ndesc_ops;
     72	}
     73
     74	stmmac_dwmac_mode_quirk(priv);
     75	return 0;
     76}
     77
     78static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
     79{
     80	stmmac_dwmac_mode_quirk(priv);
     81	return 0;
     82}
     83
     84static int stmmac_dwxlgmac_quirks(struct stmmac_priv *priv)
     85{
     86	priv->hw->xlgmac = true;
     87	return 0;
     88}
     89
     90static const struct stmmac_hwif_entry {
     91	bool gmac;
     92	bool gmac4;
     93	bool xgmac;
     94	u32 min_id;
     95	u32 dev_id;
     96	const struct stmmac_regs_off regs;
     97	const void *desc;
     98	const void *dma;
     99	const void *mac;
    100	const void *hwtimestamp;
    101	const void *mode;
    102	const void *tc;
    103	const void *mmc;
    104	int (*setup)(struct stmmac_priv *priv);
    105	int (*quirks)(struct stmmac_priv *priv);
    106} stmmac_hw[] = {
    107	/* NOTE: New HW versions shall go to the end of this table */
    108	{
    109		.gmac = false,
    110		.gmac4 = false,
    111		.xgmac = false,
    112		.min_id = 0,
    113		.regs = {
    114			.ptp_off = PTP_GMAC3_X_OFFSET,
    115			.mmc_off = MMC_GMAC3_X_OFFSET,
    116		},
    117		.desc = NULL,
    118		.dma = &dwmac100_dma_ops,
    119		.mac = &dwmac100_ops,
    120		.hwtimestamp = &stmmac_ptp,
    121		.mode = NULL,
    122		.tc = NULL,
    123		.mmc = &dwmac_mmc_ops,
    124		.setup = dwmac100_setup,
    125		.quirks = stmmac_dwmac1_quirks,
    126	}, {
    127		.gmac = true,
    128		.gmac4 = false,
    129		.xgmac = false,
    130		.min_id = 0,
    131		.regs = {
    132			.ptp_off = PTP_GMAC3_X_OFFSET,
    133			.mmc_off = MMC_GMAC3_X_OFFSET,
    134		},
    135		.desc = NULL,
    136		.dma = &dwmac1000_dma_ops,
    137		.mac = &dwmac1000_ops,
    138		.hwtimestamp = &stmmac_ptp,
    139		.mode = NULL,
    140		.tc = NULL,
    141		.mmc = &dwmac_mmc_ops,
    142		.setup = dwmac1000_setup,
    143		.quirks = stmmac_dwmac1_quirks,
    144	}, {
    145		.gmac = false,
    146		.gmac4 = true,
    147		.xgmac = false,
    148		.min_id = 0,
    149		.regs = {
    150			.ptp_off = PTP_GMAC4_OFFSET,
    151			.mmc_off = MMC_GMAC4_OFFSET,
    152		},
    153		.desc = &dwmac4_desc_ops,
    154		.dma = &dwmac4_dma_ops,
    155		.mac = &dwmac4_ops,
    156		.hwtimestamp = &stmmac_ptp,
    157		.mode = NULL,
    158		.tc = &dwmac510_tc_ops,
    159		.mmc = &dwmac_mmc_ops,
    160		.setup = dwmac4_setup,
    161		.quirks = stmmac_dwmac4_quirks,
    162	}, {
    163		.gmac = false,
    164		.gmac4 = true,
    165		.xgmac = false,
    166		.min_id = DWMAC_CORE_4_00,
    167		.regs = {
    168			.ptp_off = PTP_GMAC4_OFFSET,
    169			.mmc_off = MMC_GMAC4_OFFSET,
    170		},
    171		.desc = &dwmac4_desc_ops,
    172		.dma = &dwmac4_dma_ops,
    173		.mac = &dwmac410_ops,
    174		.hwtimestamp = &stmmac_ptp,
    175		.mode = &dwmac4_ring_mode_ops,
    176		.tc = &dwmac510_tc_ops,
    177		.mmc = &dwmac_mmc_ops,
    178		.setup = dwmac4_setup,
    179		.quirks = NULL,
    180	}, {
    181		.gmac = false,
    182		.gmac4 = true,
    183		.xgmac = false,
    184		.min_id = DWMAC_CORE_4_10,
    185		.regs = {
    186			.ptp_off = PTP_GMAC4_OFFSET,
    187			.mmc_off = MMC_GMAC4_OFFSET,
    188		},
    189		.desc = &dwmac4_desc_ops,
    190		.dma = &dwmac410_dma_ops,
    191		.mac = &dwmac410_ops,
    192		.hwtimestamp = &stmmac_ptp,
    193		.mode = &dwmac4_ring_mode_ops,
    194		.tc = &dwmac510_tc_ops,
    195		.mmc = &dwmac_mmc_ops,
    196		.setup = dwmac4_setup,
    197		.quirks = NULL,
    198	}, {
    199		.gmac = false,
    200		.gmac4 = true,
    201		.xgmac = false,
    202		.min_id = DWMAC_CORE_5_10,
    203		.regs = {
    204			.ptp_off = PTP_GMAC4_OFFSET,
    205			.mmc_off = MMC_GMAC4_OFFSET,
    206		},
    207		.desc = &dwmac4_desc_ops,
    208		.dma = &dwmac410_dma_ops,
    209		.mac = &dwmac510_ops,
    210		.hwtimestamp = &stmmac_ptp,
    211		.mode = &dwmac4_ring_mode_ops,
    212		.tc = &dwmac510_tc_ops,
    213		.mmc = &dwmac_mmc_ops,
    214		.setup = dwmac4_setup,
    215		.quirks = NULL,
    216	}, {
    217		.gmac = false,
    218		.gmac4 = false,
    219		.xgmac = true,
    220		.min_id = DWXGMAC_CORE_2_10,
    221		.dev_id = DWXGMAC_ID,
    222		.regs = {
    223			.ptp_off = PTP_XGMAC_OFFSET,
    224			.mmc_off = MMC_XGMAC_OFFSET,
    225		},
    226		.desc = &dwxgmac210_desc_ops,
    227		.dma = &dwxgmac210_dma_ops,
    228		.mac = &dwxgmac210_ops,
    229		.hwtimestamp = &stmmac_ptp,
    230		.mode = NULL,
    231		.tc = &dwmac510_tc_ops,
    232		.mmc = &dwxgmac_mmc_ops,
    233		.setup = dwxgmac2_setup,
    234		.quirks = NULL,
    235	}, {
    236		.gmac = false,
    237		.gmac4 = false,
    238		.xgmac = true,
    239		.min_id = DWXLGMAC_CORE_2_00,
    240		.dev_id = DWXLGMAC_ID,
    241		.regs = {
    242			.ptp_off = PTP_XGMAC_OFFSET,
    243			.mmc_off = MMC_XGMAC_OFFSET,
    244		},
    245		.desc = &dwxgmac210_desc_ops,
    246		.dma = &dwxgmac210_dma_ops,
    247		.mac = &dwxlgmac2_ops,
    248		.hwtimestamp = &stmmac_ptp,
    249		.mode = NULL,
    250		.tc = &dwmac510_tc_ops,
    251		.mmc = &dwxgmac_mmc_ops,
    252		.setup = dwxlgmac2_setup,
    253		.quirks = stmmac_dwxlgmac_quirks,
    254	},
    255};
    256
    257int stmmac_hwif_init(struct stmmac_priv *priv)
    258{
    259	bool needs_xgmac = priv->plat->has_xgmac;
    260	bool needs_gmac4 = priv->plat->has_gmac4;
    261	bool needs_gmac = priv->plat->has_gmac;
    262	const struct stmmac_hwif_entry *entry;
    263	struct mac_device_info *mac;
    264	bool needs_setup = true;
    265	u32 id, dev_id = 0;
    266	int i, ret;
    267
    268	if (needs_gmac) {
    269		id = stmmac_get_id(priv, GMAC_VERSION);
    270	} else if (needs_gmac4 || needs_xgmac) {
    271		id = stmmac_get_id(priv, GMAC4_VERSION);
    272		if (needs_xgmac)
    273			dev_id = stmmac_get_dev_id(priv, GMAC4_VERSION);
    274	} else {
    275		id = 0;
    276	}
    277
    278	/* Save ID for later use */
    279	priv->synopsys_id = id;
    280
    281	/* Lets assume some safe values first */
    282	priv->ptpaddr = priv->ioaddr +
    283		(needs_gmac4 ? PTP_GMAC4_OFFSET : PTP_GMAC3_X_OFFSET);
    284	priv->mmcaddr = priv->ioaddr +
    285		(needs_gmac4 ? MMC_GMAC4_OFFSET : MMC_GMAC3_X_OFFSET);
    286
    287	/* Check for HW specific setup first */
    288	if (priv->plat->setup) {
    289		mac = priv->plat->setup(priv);
    290		needs_setup = false;
    291	} else {
    292		mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
    293	}
    294
    295	if (!mac)
    296		return -ENOMEM;
    297
    298	/* Fallback to generic HW */
    299	for (i = ARRAY_SIZE(stmmac_hw) - 1; i >= 0; i--) {
    300		entry = &stmmac_hw[i];
    301
    302		if (needs_gmac ^ entry->gmac)
    303			continue;
    304		if (needs_gmac4 ^ entry->gmac4)
    305			continue;
    306		if (needs_xgmac ^ entry->xgmac)
    307			continue;
    308		/* Use synopsys_id var because some setups can override this */
    309		if (priv->synopsys_id < entry->min_id)
    310			continue;
    311		if (needs_xgmac && (dev_id ^ entry->dev_id))
    312			continue;
    313
    314		/* Only use generic HW helpers if needed */
    315		mac->desc = mac->desc ? : entry->desc;
    316		mac->dma = mac->dma ? : entry->dma;
    317		mac->mac = mac->mac ? : entry->mac;
    318		mac->ptp = mac->ptp ? : entry->hwtimestamp;
    319		mac->mode = mac->mode ? : entry->mode;
    320		mac->tc = mac->tc ? : entry->tc;
    321		mac->mmc = mac->mmc ? : entry->mmc;
    322
    323		priv->hw = mac;
    324		priv->ptpaddr = priv->ioaddr + entry->regs.ptp_off;
    325		priv->mmcaddr = priv->ioaddr + entry->regs.mmc_off;
    326
    327		/* Entry found */
    328		if (needs_setup) {
    329			ret = entry->setup(priv);
    330			if (ret)
    331				return ret;
    332		}
    333
    334		/* Save quirks, if needed for posterior use */
    335		priv->hwif_quirks = entry->quirks;
    336		return 0;
    337	}
    338
    339	dev_err(priv->device, "Failed to find HW IF (id=0x%x, gmac=%d/%d)\n",
    340			id, needs_gmac, needs_gmac4);
    341	return -EINVAL;
    342}