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

dwmac-socfpga.c (15315B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* Copyright Altera Corporation (C) 2014. All rights reserved.
      3 *
      4 * Adopted from dwmac-sti.c
      5 */
      6
      7#include <linux/mfd/altera-sysmgr.h>
      8#include <linux/of.h>
      9#include <linux/of_address.h>
     10#include <linux/of_net.h>
     11#include <linux/phy.h>
     12#include <linux/regmap.h>
     13#include <linux/reset.h>
     14#include <linux/stmmac.h>
     15
     16#include "stmmac.h"
     17#include "stmmac_platform.h"
     18
     19#include "altr_tse_pcs.h"
     20
     21#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
     22#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
     23#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
     24#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
     25#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
     26#define SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000010
     27#define SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000100
     28
     29#define SYSMGR_FPGAGRP_MODULE_REG  0x00000028
     30#define SYSMGR_FPGAGRP_MODULE_EMAC 0x00000004
     31#define SYSMGR_FPGAINTF_EMAC_REG	0x00000070
     32#define SYSMGR_FPGAINTF_EMAC_BIT	0x1
     33
     34#define EMAC_SPLITTER_CTRL_REG			0x0
     35#define EMAC_SPLITTER_CTRL_SPEED_MASK		0x3
     36#define EMAC_SPLITTER_CTRL_SPEED_10		0x2
     37#define EMAC_SPLITTER_CTRL_SPEED_100		0x3
     38#define EMAC_SPLITTER_CTRL_SPEED_1000		0x0
     39
     40struct socfpga_dwmac;
     41struct socfpga_dwmac_ops {
     42	int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv);
     43};
     44
     45struct socfpga_dwmac {
     46	u32	reg_offset;
     47	u32	reg_shift;
     48	struct	device *dev;
     49	struct regmap *sys_mgr_base_addr;
     50	struct reset_control *stmmac_rst;
     51	struct reset_control *stmmac_ocp_rst;
     52	void __iomem *splitter_base;
     53	bool f2h_ptp_ref_clk;
     54	struct tse_pcs pcs;
     55	const struct socfpga_dwmac_ops *ops;
     56};
     57
     58static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
     59{
     60	struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv;
     61	void __iomem *splitter_base = dwmac->splitter_base;
     62	void __iomem *sgmii_adapter_base = dwmac->pcs.sgmii_adapter_base;
     63	struct device *dev = dwmac->dev;
     64	struct net_device *ndev = dev_get_drvdata(dev);
     65	struct phy_device *phy_dev = ndev->phydev;
     66	u32 val;
     67
     68	if (sgmii_adapter_base)
     69		writew(SGMII_ADAPTER_DISABLE,
     70		       sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
     71
     72	if (splitter_base) {
     73		val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG);
     74		val &= ~EMAC_SPLITTER_CTRL_SPEED_MASK;
     75
     76		switch (speed) {
     77		case 1000:
     78			val |= EMAC_SPLITTER_CTRL_SPEED_1000;
     79			break;
     80		case 100:
     81			val |= EMAC_SPLITTER_CTRL_SPEED_100;
     82			break;
     83		case 10:
     84			val |= EMAC_SPLITTER_CTRL_SPEED_10;
     85			break;
     86		default:
     87			return;
     88		}
     89		writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG);
     90	}
     91
     92	if (phy_dev && sgmii_adapter_base) {
     93		writew(SGMII_ADAPTER_ENABLE,
     94		       sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
     95		tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed);
     96	}
     97}
     98
     99static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
    100{
    101	struct device_node *np = dev->of_node;
    102	struct regmap *sys_mgr_base_addr;
    103	u32 reg_offset, reg_shift;
    104	int ret, index;
    105	struct device_node *np_splitter = NULL;
    106	struct device_node *np_sgmii_adapter = NULL;
    107	struct resource res_splitter;
    108	struct resource res_tse_pcs;
    109	struct resource res_sgmii_adapter;
    110
    111	sys_mgr_base_addr =
    112		altr_sysmgr_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
    113	if (IS_ERR(sys_mgr_base_addr)) {
    114		dev_info(dev, "No sysmgr-syscon node found\n");
    115		return PTR_ERR(sys_mgr_base_addr);
    116	}
    117
    118	ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 1, &reg_offset);
    119	if (ret) {
    120		dev_info(dev, "Could not read reg_offset from sysmgr-syscon!\n");
    121		return -EINVAL;
    122	}
    123
    124	ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 2, &reg_shift);
    125	if (ret) {
    126		dev_info(dev, "Could not read reg_shift from sysmgr-syscon!\n");
    127		return -EINVAL;
    128	}
    129
    130	dwmac->f2h_ptp_ref_clk = of_property_read_bool(np, "altr,f2h_ptp_ref_clk");
    131
    132	np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0);
    133	if (np_splitter) {
    134		ret = of_address_to_resource(np_splitter, 0, &res_splitter);
    135		of_node_put(np_splitter);
    136		if (ret) {
    137			dev_info(dev, "Missing emac splitter address\n");
    138			return -EINVAL;
    139		}
    140
    141		dwmac->splitter_base = devm_ioremap_resource(dev, &res_splitter);
    142		if (IS_ERR(dwmac->splitter_base)) {
    143			dev_info(dev, "Failed to mapping emac splitter\n");
    144			return PTR_ERR(dwmac->splitter_base);
    145		}
    146	}
    147
    148	np_sgmii_adapter = of_parse_phandle(np,
    149					    "altr,gmii-to-sgmii-converter", 0);
    150	if (np_sgmii_adapter) {
    151		index = of_property_match_string(np_sgmii_adapter, "reg-names",
    152						 "hps_emac_interface_splitter_avalon_slave");
    153
    154		if (index >= 0) {
    155			if (of_address_to_resource(np_sgmii_adapter, index,
    156						   &res_splitter)) {
    157				dev_err(dev,
    158					"%s: ERROR: missing emac splitter address\n",
    159					__func__);
    160				ret = -EINVAL;
    161				goto err_node_put;
    162			}
    163
    164			dwmac->splitter_base =
    165			    devm_ioremap_resource(dev, &res_splitter);
    166
    167			if (IS_ERR(dwmac->splitter_base)) {
    168				ret = PTR_ERR(dwmac->splitter_base);
    169				goto err_node_put;
    170			}
    171		}
    172
    173		index = of_property_match_string(np_sgmii_adapter, "reg-names",
    174						 "gmii_to_sgmii_adapter_avalon_slave");
    175
    176		if (index >= 0) {
    177			if (of_address_to_resource(np_sgmii_adapter, index,
    178						   &res_sgmii_adapter)) {
    179				dev_err(dev,
    180					"%s: ERROR: failed mapping adapter\n",
    181					__func__);
    182				ret = -EINVAL;
    183				goto err_node_put;
    184			}
    185
    186			dwmac->pcs.sgmii_adapter_base =
    187			    devm_ioremap_resource(dev, &res_sgmii_adapter);
    188
    189			if (IS_ERR(dwmac->pcs.sgmii_adapter_base)) {
    190				ret = PTR_ERR(dwmac->pcs.sgmii_adapter_base);
    191				goto err_node_put;
    192			}
    193		}
    194
    195		index = of_property_match_string(np_sgmii_adapter, "reg-names",
    196						 "eth_tse_control_port");
    197
    198		if (index >= 0) {
    199			if (of_address_to_resource(np_sgmii_adapter, index,
    200						   &res_tse_pcs)) {
    201				dev_err(dev,
    202					"%s: ERROR: failed mapping tse control port\n",
    203					__func__);
    204				ret = -EINVAL;
    205				goto err_node_put;
    206			}
    207
    208			dwmac->pcs.tse_pcs_base =
    209			    devm_ioremap_resource(dev, &res_tse_pcs);
    210
    211			if (IS_ERR(dwmac->pcs.tse_pcs_base)) {
    212				ret = PTR_ERR(dwmac->pcs.tse_pcs_base);
    213				goto err_node_put;
    214			}
    215		}
    216	}
    217	dwmac->reg_offset = reg_offset;
    218	dwmac->reg_shift = reg_shift;
    219	dwmac->sys_mgr_base_addr = sys_mgr_base_addr;
    220	dwmac->dev = dev;
    221	of_node_put(np_sgmii_adapter);
    222
    223	return 0;
    224
    225err_node_put:
    226	of_node_put(np_sgmii_adapter);
    227	return ret;
    228}
    229
    230static int socfpga_get_plat_phymode(struct socfpga_dwmac *dwmac)
    231{
    232	struct net_device *ndev = dev_get_drvdata(dwmac->dev);
    233	struct stmmac_priv *priv = netdev_priv(ndev);
    234
    235	return priv->plat->interface;
    236}
    237
    238static int socfpga_set_phy_mode_common(int phymode, u32 *val)
    239{
    240	switch (phymode) {
    241	case PHY_INTERFACE_MODE_RGMII:
    242	case PHY_INTERFACE_MODE_RGMII_ID:
    243	case PHY_INTERFACE_MODE_RGMII_RXID:
    244	case PHY_INTERFACE_MODE_RGMII_TXID:
    245		*val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
    246		break;
    247	case PHY_INTERFACE_MODE_MII:
    248	case PHY_INTERFACE_MODE_GMII:
    249	case PHY_INTERFACE_MODE_SGMII:
    250		*val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
    251		break;
    252	case PHY_INTERFACE_MODE_RMII:
    253		*val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII;
    254		break;
    255	default:
    256		return -EINVAL;
    257	}
    258	return 0;
    259}
    260
    261static int socfpga_gen5_set_phy_mode(struct socfpga_dwmac *dwmac)
    262{
    263	struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr;
    264	int phymode = socfpga_get_plat_phymode(dwmac);
    265	u32 reg_offset = dwmac->reg_offset;
    266	u32 reg_shift = dwmac->reg_shift;
    267	u32 ctrl, val, module;
    268
    269	if (socfpga_set_phy_mode_common(phymode, &val)) {
    270		dev_err(dwmac->dev, "bad phy mode %d\n", phymode);
    271		return -EINVAL;
    272	}
    273
    274	/* Overwrite val to GMII if splitter core is enabled. The phymode here
    275	 * is the actual phy mode on phy hardware, but phy interface from
    276	 * EMAC core is GMII.
    277	 */
    278	if (dwmac->splitter_base)
    279		val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
    280
    281	/* Assert reset to the enet controller before changing the phy mode */
    282	reset_control_assert(dwmac->stmmac_ocp_rst);
    283	reset_control_assert(dwmac->stmmac_rst);
    284
    285	regmap_read(sys_mgr_base_addr, reg_offset, &ctrl);
    286	ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
    287	ctrl |= val << reg_shift;
    288
    289	if (dwmac->f2h_ptp_ref_clk ||
    290	    phymode == PHY_INTERFACE_MODE_MII ||
    291	    phymode == PHY_INTERFACE_MODE_GMII ||
    292	    phymode == PHY_INTERFACE_MODE_SGMII) {
    293		regmap_read(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG,
    294			    &module);
    295		module |= (SYSMGR_FPGAGRP_MODULE_EMAC << (reg_shift / 2));
    296		regmap_write(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG,
    297			     module);
    298	}
    299
    300	if (dwmac->f2h_ptp_ref_clk)
    301		ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2);
    302	else
    303		ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK <<
    304			  (reg_shift / 2));
    305
    306	regmap_write(sys_mgr_base_addr, reg_offset, ctrl);
    307
    308	/* Deassert reset for the phy configuration to be sampled by
    309	 * the enet controller, and operation to start in requested mode
    310	 */
    311	reset_control_deassert(dwmac->stmmac_ocp_rst);
    312	reset_control_deassert(dwmac->stmmac_rst);
    313	if (phymode == PHY_INTERFACE_MODE_SGMII) {
    314		if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) {
    315			dev_err(dwmac->dev, "Unable to initialize TSE PCS");
    316			return -EINVAL;
    317		}
    318	}
    319
    320	return 0;
    321}
    322
    323static int socfpga_gen10_set_phy_mode(struct socfpga_dwmac *dwmac)
    324{
    325	struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr;
    326	int phymode = socfpga_get_plat_phymode(dwmac);
    327	u32 reg_offset = dwmac->reg_offset;
    328	u32 reg_shift = dwmac->reg_shift;
    329	u32 ctrl, val, module;
    330
    331	if (socfpga_set_phy_mode_common(phymode, &val))
    332		return -EINVAL;
    333
    334	/* Overwrite val to GMII if splitter core is enabled. The phymode here
    335	 * is the actual phy mode on phy hardware, but phy interface from
    336	 * EMAC core is GMII.
    337	 */
    338	if (dwmac->splitter_base)
    339		val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
    340
    341	/* Assert reset to the enet controller before changing the phy mode */
    342	reset_control_assert(dwmac->stmmac_ocp_rst);
    343	reset_control_assert(dwmac->stmmac_rst);
    344
    345	regmap_read(sys_mgr_base_addr, reg_offset, &ctrl);
    346	ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK);
    347	ctrl |= val;
    348
    349	if (dwmac->f2h_ptp_ref_clk ||
    350	    phymode == PHY_INTERFACE_MODE_MII ||
    351	    phymode == PHY_INTERFACE_MODE_GMII ||
    352	    phymode == PHY_INTERFACE_MODE_SGMII) {
    353		ctrl |= SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK;
    354		regmap_read(sys_mgr_base_addr, SYSMGR_FPGAINTF_EMAC_REG,
    355			    &module);
    356		module |= (SYSMGR_FPGAINTF_EMAC_BIT << reg_shift);
    357		regmap_write(sys_mgr_base_addr, SYSMGR_FPGAINTF_EMAC_REG,
    358			     module);
    359	} else {
    360		ctrl &= ~SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK;
    361	}
    362
    363	regmap_write(sys_mgr_base_addr, reg_offset, ctrl);
    364
    365	/* Deassert reset for the phy configuration to be sampled by
    366	 * the enet controller, and operation to start in requested mode
    367	 */
    368	reset_control_deassert(dwmac->stmmac_ocp_rst);
    369	reset_control_deassert(dwmac->stmmac_rst);
    370	if (phymode == PHY_INTERFACE_MODE_SGMII) {
    371		if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) {
    372			dev_err(dwmac->dev, "Unable to initialize TSE PCS");
    373			return -EINVAL;
    374		}
    375	}
    376	return 0;
    377}
    378
    379static int socfpga_dwmac_probe(struct platform_device *pdev)
    380{
    381	struct plat_stmmacenet_data *plat_dat;
    382	struct stmmac_resources stmmac_res;
    383	struct device		*dev = &pdev->dev;
    384	int			ret;
    385	struct socfpga_dwmac	*dwmac;
    386	struct net_device	*ndev;
    387	struct stmmac_priv	*stpriv;
    388	const struct socfpga_dwmac_ops *ops;
    389
    390	ops = device_get_match_data(&pdev->dev);
    391	if (!ops) {
    392		dev_err(&pdev->dev, "no of match data provided\n");
    393		return -EINVAL;
    394	}
    395
    396	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
    397	if (ret)
    398		return ret;
    399
    400	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
    401	if (IS_ERR(plat_dat))
    402		return PTR_ERR(plat_dat);
    403
    404	dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
    405	if (!dwmac) {
    406		ret = -ENOMEM;
    407		goto err_remove_config_dt;
    408	}
    409
    410	dwmac->stmmac_ocp_rst = devm_reset_control_get_optional(dev, "stmmaceth-ocp");
    411	if (IS_ERR(dwmac->stmmac_ocp_rst)) {
    412		ret = PTR_ERR(dwmac->stmmac_ocp_rst);
    413		dev_err(dev, "error getting reset control of ocp %d\n", ret);
    414		goto err_remove_config_dt;
    415	}
    416
    417	reset_control_deassert(dwmac->stmmac_ocp_rst);
    418
    419	ret = socfpga_dwmac_parse_data(dwmac, dev);
    420	if (ret) {
    421		dev_err(dev, "Unable to parse OF data\n");
    422		goto err_remove_config_dt;
    423	}
    424
    425	dwmac->ops = ops;
    426	plat_dat->bsp_priv = dwmac;
    427	plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
    428
    429	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
    430	if (ret)
    431		goto err_remove_config_dt;
    432
    433	ndev = platform_get_drvdata(pdev);
    434	stpriv = netdev_priv(ndev);
    435
    436	/* The socfpga driver needs to control the stmmac reset to set the phy
    437	 * mode. Create a copy of the core reset handle so it can be used by
    438	 * the driver later.
    439	 */
    440	dwmac->stmmac_rst = stpriv->plat->stmmac_rst;
    441
    442	ret = ops->set_phy_mode(dwmac);
    443	if (ret)
    444		goto err_dvr_remove;
    445
    446	return 0;
    447
    448err_dvr_remove:
    449	stmmac_dvr_remove(&pdev->dev);
    450err_remove_config_dt:
    451	stmmac_remove_config_dt(pdev, plat_dat);
    452
    453	return ret;
    454}
    455
    456#ifdef CONFIG_PM_SLEEP
    457static int socfpga_dwmac_resume(struct device *dev)
    458{
    459	struct net_device *ndev = dev_get_drvdata(dev);
    460	struct stmmac_priv *priv = netdev_priv(ndev);
    461	struct socfpga_dwmac *dwmac_priv = get_stmmac_bsp_priv(dev);
    462
    463	dwmac_priv->ops->set_phy_mode(priv->plat->bsp_priv);
    464
    465	/* Before the enet controller is suspended, the phy is suspended.
    466	 * This causes the phy clock to be gated. The enet controller is
    467	 * resumed before the phy, so the clock is still gated "off" when
    468	 * the enet controller is resumed. This code makes sure the phy
    469	 * is "resumed" before reinitializing the enet controller since
    470	 * the enet controller depends on an active phy clock to complete
    471	 * a DMA reset. A DMA reset will "time out" if executed
    472	 * with no phy clock input on the Synopsys enet controller.
    473	 * Verified through Synopsys Case #8000711656.
    474	 *
    475	 * Note that the phy clock is also gated when the phy is isolated.
    476	 * Phy "suspend" and "isolate" controls are located in phy basic
    477	 * control register 0, and can be modified by the phy driver
    478	 * framework.
    479	 */
    480	if (ndev->phydev)
    481		phy_resume(ndev->phydev);
    482
    483	return stmmac_resume(dev);
    484}
    485#endif /* CONFIG_PM_SLEEP */
    486
    487static int __maybe_unused socfpga_dwmac_runtime_suspend(struct device *dev)
    488{
    489	struct net_device *ndev = dev_get_drvdata(dev);
    490	struct stmmac_priv *priv = netdev_priv(ndev);
    491
    492	stmmac_bus_clks_config(priv, false);
    493
    494	return 0;
    495}
    496
    497static int __maybe_unused socfpga_dwmac_runtime_resume(struct device *dev)
    498{
    499	struct net_device *ndev = dev_get_drvdata(dev);
    500	struct stmmac_priv *priv = netdev_priv(ndev);
    501
    502	return stmmac_bus_clks_config(priv, true);
    503}
    504
    505static const struct dev_pm_ops socfpga_dwmac_pm_ops = {
    506	SET_SYSTEM_SLEEP_PM_OPS(stmmac_suspend, socfpga_dwmac_resume)
    507	SET_RUNTIME_PM_OPS(socfpga_dwmac_runtime_suspend, socfpga_dwmac_runtime_resume, NULL)
    508};
    509
    510static const struct socfpga_dwmac_ops socfpga_gen5_ops = {
    511	.set_phy_mode = socfpga_gen5_set_phy_mode,
    512};
    513
    514static const struct socfpga_dwmac_ops socfpga_gen10_ops = {
    515	.set_phy_mode = socfpga_gen10_set_phy_mode,
    516};
    517
    518static const struct of_device_id socfpga_dwmac_match[] = {
    519	{ .compatible = "altr,socfpga-stmmac", .data = &socfpga_gen5_ops },
    520	{ .compatible = "altr,socfpga-stmmac-a10-s10", .data = &socfpga_gen10_ops },
    521	{ }
    522};
    523MODULE_DEVICE_TABLE(of, socfpga_dwmac_match);
    524
    525static struct platform_driver socfpga_dwmac_driver = {
    526	.probe  = socfpga_dwmac_probe,
    527	.remove = stmmac_pltfr_remove,
    528	.driver = {
    529		.name           = "socfpga-dwmac",
    530		.pm		= &socfpga_dwmac_pm_ops,
    531		.of_match_table = socfpga_dwmac_match,
    532	},
    533};
    534module_platform_driver(socfpga_dwmac_driver);
    535
    536MODULE_LICENSE("GPL v2");