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-dwc-qos-eth.c (12187B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Synopsys DWC Ethernet Quality-of-Service v4.10a linux driver
      4 *
      5 * Copyright (C) 2016 Joao Pinto <jpinto@synopsys.com>
      6 */
      7
      8#include <linux/clk.h>
      9#include <linux/clk-provider.h>
     10#include <linux/device.h>
     11#include <linux/gpio/consumer.h>
     12#include <linux/ethtool.h>
     13#include <linux/io.h>
     14#include <linux/iopoll.h>
     15#include <linux/ioport.h>
     16#include <linux/module.h>
     17#include <linux/of_device.h>
     18#include <linux/of_net.h>
     19#include <linux/mfd/syscon.h>
     20#include <linux/platform_device.h>
     21#include <linux/reset.h>
     22#include <linux/stmmac.h>
     23
     24#include "stmmac_platform.h"
     25#include "dwmac4.h"
     26
     27struct tegra_eqos {
     28	struct device *dev;
     29	void __iomem *regs;
     30
     31	struct reset_control *rst;
     32	struct clk *clk_master;
     33	struct clk *clk_slave;
     34	struct clk *clk_tx;
     35	struct clk *clk_rx;
     36
     37	struct gpio_desc *reset;
     38};
     39
     40static int dwc_eth_dwmac_config_dt(struct platform_device *pdev,
     41				   struct plat_stmmacenet_data *plat_dat)
     42{
     43	struct device *dev = &pdev->dev;
     44	u32 burst_map = 0;
     45	u32 bit_index = 0;
     46	u32 a_index = 0;
     47
     48	if (!plat_dat->axi) {
     49		plat_dat->axi = kzalloc(sizeof(struct stmmac_axi), GFP_KERNEL);
     50
     51		if (!plat_dat->axi)
     52			return -ENOMEM;
     53	}
     54
     55	plat_dat->axi->axi_lpi_en = device_property_read_bool(dev,
     56							      "snps,en-lpi");
     57	if (device_property_read_u32(dev, "snps,write-requests",
     58				     &plat_dat->axi->axi_wr_osr_lmt)) {
     59		/**
     60		 * Since the register has a reset value of 1, if property
     61		 * is missing, default to 1.
     62		 */
     63		plat_dat->axi->axi_wr_osr_lmt = 1;
     64	} else {
     65		/**
     66		 * If property exists, to keep the behavior from dwc_eth_qos,
     67		 * subtract one after parsing.
     68		 */
     69		plat_dat->axi->axi_wr_osr_lmt--;
     70	}
     71
     72	if (device_property_read_u32(dev, "snps,read-requests",
     73				     &plat_dat->axi->axi_rd_osr_lmt)) {
     74		/**
     75		 * Since the register has a reset value of 1, if property
     76		 * is missing, default to 1.
     77		 */
     78		plat_dat->axi->axi_rd_osr_lmt = 1;
     79	} else {
     80		/**
     81		 * If property exists, to keep the behavior from dwc_eth_qos,
     82		 * subtract one after parsing.
     83		 */
     84		plat_dat->axi->axi_rd_osr_lmt--;
     85	}
     86	device_property_read_u32(dev, "snps,burst-map", &burst_map);
     87
     88	/* converts burst-map bitmask to burst array */
     89	for (bit_index = 0; bit_index < 7; bit_index++) {
     90		if (burst_map & (1 << bit_index)) {
     91			switch (bit_index) {
     92			case 0:
     93			plat_dat->axi->axi_blen[a_index] = 4; break;
     94			case 1:
     95			plat_dat->axi->axi_blen[a_index] = 8; break;
     96			case 2:
     97			plat_dat->axi->axi_blen[a_index] = 16; break;
     98			case 3:
     99			plat_dat->axi->axi_blen[a_index] = 32; break;
    100			case 4:
    101			plat_dat->axi->axi_blen[a_index] = 64; break;
    102			case 5:
    103			plat_dat->axi->axi_blen[a_index] = 128; break;
    104			case 6:
    105			plat_dat->axi->axi_blen[a_index] = 256; break;
    106			default:
    107			break;
    108			}
    109			a_index++;
    110		}
    111	}
    112
    113	/* dwc-qos needs GMAC4, AAL, TSO and PMT */
    114	plat_dat->has_gmac4 = 1;
    115	plat_dat->dma_cfg->aal = 1;
    116	plat_dat->tso_en = 1;
    117	plat_dat->pmt = 1;
    118
    119	return 0;
    120}
    121
    122static int dwc_qos_probe(struct platform_device *pdev,
    123			 struct plat_stmmacenet_data *plat_dat,
    124			 struct stmmac_resources *stmmac_res)
    125{
    126	int err;
    127
    128	plat_dat->stmmac_clk = devm_clk_get(&pdev->dev, "apb_pclk");
    129	if (IS_ERR(plat_dat->stmmac_clk)) {
    130		dev_err(&pdev->dev, "apb_pclk clock not found.\n");
    131		return PTR_ERR(plat_dat->stmmac_clk);
    132	}
    133
    134	err = clk_prepare_enable(plat_dat->stmmac_clk);
    135	if (err < 0) {
    136		dev_err(&pdev->dev, "failed to enable apb_pclk clock: %d\n",
    137			err);
    138		return err;
    139	}
    140
    141	plat_dat->pclk = devm_clk_get(&pdev->dev, "phy_ref_clk");
    142	if (IS_ERR(plat_dat->pclk)) {
    143		dev_err(&pdev->dev, "phy_ref_clk clock not found.\n");
    144		err = PTR_ERR(plat_dat->pclk);
    145		goto disable;
    146	}
    147
    148	err = clk_prepare_enable(plat_dat->pclk);
    149	if (err < 0) {
    150		dev_err(&pdev->dev, "failed to enable phy_ref clock: %d\n",
    151			err);
    152		goto disable;
    153	}
    154
    155	return 0;
    156
    157disable:
    158	clk_disable_unprepare(plat_dat->stmmac_clk);
    159	return err;
    160}
    161
    162static int dwc_qos_remove(struct platform_device *pdev)
    163{
    164	struct net_device *ndev = platform_get_drvdata(pdev);
    165	struct stmmac_priv *priv = netdev_priv(ndev);
    166
    167	clk_disable_unprepare(priv->plat->pclk);
    168	clk_disable_unprepare(priv->plat->stmmac_clk);
    169
    170	return 0;
    171}
    172
    173#define SDMEMCOMPPADCTRL 0x8800
    174#define  SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31)
    175
    176#define AUTO_CAL_CONFIG 0x8804
    177#define  AUTO_CAL_CONFIG_START BIT(31)
    178#define  AUTO_CAL_CONFIG_ENABLE BIT(29)
    179
    180#define AUTO_CAL_STATUS 0x880c
    181#define  AUTO_CAL_STATUS_ACTIVE BIT(31)
    182
    183static void tegra_eqos_fix_speed(void *priv, unsigned int speed)
    184{
    185	struct tegra_eqos *eqos = priv;
    186	unsigned long rate = 125000000;
    187	bool needs_calibration = false;
    188	u32 value;
    189	int err;
    190
    191	switch (speed) {
    192	case SPEED_1000:
    193		needs_calibration = true;
    194		rate = 125000000;
    195		break;
    196
    197	case SPEED_100:
    198		needs_calibration = true;
    199		rate = 25000000;
    200		break;
    201
    202	case SPEED_10:
    203		rate = 2500000;
    204		break;
    205
    206	default:
    207		dev_err(eqos->dev, "invalid speed %u\n", speed);
    208		break;
    209	}
    210
    211	if (needs_calibration) {
    212		/* calibrate */
    213		value = readl(eqos->regs + SDMEMCOMPPADCTRL);
    214		value |= SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
    215		writel(value, eqos->regs + SDMEMCOMPPADCTRL);
    216
    217		udelay(1);
    218
    219		value = readl(eqos->regs + AUTO_CAL_CONFIG);
    220		value |= AUTO_CAL_CONFIG_START | AUTO_CAL_CONFIG_ENABLE;
    221		writel(value, eqos->regs + AUTO_CAL_CONFIG);
    222
    223		err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS,
    224						value,
    225						value & AUTO_CAL_STATUS_ACTIVE,
    226						1, 10);
    227		if (err < 0) {
    228			dev_err(eqos->dev, "calibration did not start\n");
    229			goto failed;
    230		}
    231
    232		err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS,
    233						value,
    234						(value & AUTO_CAL_STATUS_ACTIVE) == 0,
    235						20, 200);
    236		if (err < 0) {
    237			dev_err(eqos->dev, "calibration didn't finish\n");
    238			goto failed;
    239		}
    240
    241	failed:
    242		value = readl(eqos->regs + SDMEMCOMPPADCTRL);
    243		value &= ~SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
    244		writel(value, eqos->regs + SDMEMCOMPPADCTRL);
    245	} else {
    246		value = readl(eqos->regs + AUTO_CAL_CONFIG);
    247		value &= ~AUTO_CAL_CONFIG_ENABLE;
    248		writel(value, eqos->regs + AUTO_CAL_CONFIG);
    249	}
    250
    251	err = clk_set_rate(eqos->clk_tx, rate);
    252	if (err < 0)
    253		dev_err(eqos->dev, "failed to set TX rate: %d\n", err);
    254}
    255
    256static int tegra_eqos_init(struct platform_device *pdev, void *priv)
    257{
    258	struct tegra_eqos *eqos = priv;
    259	unsigned long rate;
    260	u32 value;
    261
    262	rate = clk_get_rate(eqos->clk_slave);
    263
    264	value = (rate / 1000000) - 1;
    265	writel(value, eqos->regs + GMAC_1US_TIC_COUNTER);
    266
    267	return 0;
    268}
    269
    270static int tegra_eqos_probe(struct platform_device *pdev,
    271			    struct plat_stmmacenet_data *data,
    272			    struct stmmac_resources *res)
    273{
    274	struct device *dev = &pdev->dev;
    275	struct tegra_eqos *eqos;
    276	int err;
    277
    278	eqos = devm_kzalloc(&pdev->dev, sizeof(*eqos), GFP_KERNEL);
    279	if (!eqos)
    280		return -ENOMEM;
    281
    282	eqos->dev = &pdev->dev;
    283	eqos->regs = res->addr;
    284
    285	if (!is_of_node(dev->fwnode))
    286		goto bypass_clk_reset_gpio;
    287
    288	eqos->clk_master = devm_clk_get(&pdev->dev, "master_bus");
    289	if (IS_ERR(eqos->clk_master)) {
    290		err = PTR_ERR(eqos->clk_master);
    291		goto error;
    292	}
    293
    294	err = clk_prepare_enable(eqos->clk_master);
    295	if (err < 0)
    296		goto error;
    297
    298	eqos->clk_slave = devm_clk_get(&pdev->dev, "slave_bus");
    299	if (IS_ERR(eqos->clk_slave)) {
    300		err = PTR_ERR(eqos->clk_slave);
    301		goto disable_master;
    302	}
    303
    304	data->stmmac_clk = eqos->clk_slave;
    305
    306	err = clk_prepare_enable(eqos->clk_slave);
    307	if (err < 0)
    308		goto disable_master;
    309
    310	eqos->clk_rx = devm_clk_get(&pdev->dev, "rx");
    311	if (IS_ERR(eqos->clk_rx)) {
    312		err = PTR_ERR(eqos->clk_rx);
    313		goto disable_slave;
    314	}
    315
    316	err = clk_prepare_enable(eqos->clk_rx);
    317	if (err < 0)
    318		goto disable_slave;
    319
    320	eqos->clk_tx = devm_clk_get(&pdev->dev, "tx");
    321	if (IS_ERR(eqos->clk_tx)) {
    322		err = PTR_ERR(eqos->clk_tx);
    323		goto disable_rx;
    324	}
    325
    326	err = clk_prepare_enable(eqos->clk_tx);
    327	if (err < 0)
    328		goto disable_rx;
    329
    330	eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH);
    331	if (IS_ERR(eqos->reset)) {
    332		err = PTR_ERR(eqos->reset);
    333		goto disable_tx;
    334	}
    335
    336	usleep_range(2000, 4000);
    337	gpiod_set_value(eqos->reset, 0);
    338
    339	/* MDIO bus was already reset just above */
    340	data->mdio_bus_data->needs_reset = false;
    341
    342	eqos->rst = devm_reset_control_get(&pdev->dev, "eqos");
    343	if (IS_ERR(eqos->rst)) {
    344		err = PTR_ERR(eqos->rst);
    345		goto reset_phy;
    346	}
    347
    348	err = reset_control_assert(eqos->rst);
    349	if (err < 0)
    350		goto reset_phy;
    351
    352	usleep_range(2000, 4000);
    353
    354	err = reset_control_deassert(eqos->rst);
    355	if (err < 0)
    356		goto reset_phy;
    357
    358	usleep_range(2000, 4000);
    359
    360bypass_clk_reset_gpio:
    361	data->fix_mac_speed = tegra_eqos_fix_speed;
    362	data->init = tegra_eqos_init;
    363	data->bsp_priv = eqos;
    364
    365	err = tegra_eqos_init(pdev, eqos);
    366	if (err < 0)
    367		goto reset;
    368
    369	return 0;
    370reset:
    371	reset_control_assert(eqos->rst);
    372reset_phy:
    373	gpiod_set_value(eqos->reset, 1);
    374disable_tx:
    375	clk_disable_unprepare(eqos->clk_tx);
    376disable_rx:
    377	clk_disable_unprepare(eqos->clk_rx);
    378disable_slave:
    379	clk_disable_unprepare(eqos->clk_slave);
    380disable_master:
    381	clk_disable_unprepare(eqos->clk_master);
    382error:
    383	return err;
    384}
    385
    386static int tegra_eqos_remove(struct platform_device *pdev)
    387{
    388	struct tegra_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev);
    389
    390	reset_control_assert(eqos->rst);
    391	gpiod_set_value(eqos->reset, 1);
    392	clk_disable_unprepare(eqos->clk_tx);
    393	clk_disable_unprepare(eqos->clk_rx);
    394	clk_disable_unprepare(eqos->clk_slave);
    395	clk_disable_unprepare(eqos->clk_master);
    396
    397	return 0;
    398}
    399
    400struct dwc_eth_dwmac_data {
    401	int (*probe)(struct platform_device *pdev,
    402		     struct plat_stmmacenet_data *data,
    403		     struct stmmac_resources *res);
    404	int (*remove)(struct platform_device *pdev);
    405};
    406
    407static const struct dwc_eth_dwmac_data dwc_qos_data = {
    408	.probe = dwc_qos_probe,
    409	.remove = dwc_qos_remove,
    410};
    411
    412static const struct dwc_eth_dwmac_data tegra_eqos_data = {
    413	.probe = tegra_eqos_probe,
    414	.remove = tegra_eqos_remove,
    415};
    416
    417static int dwc_eth_dwmac_probe(struct platform_device *pdev)
    418{
    419	const struct dwc_eth_dwmac_data *data;
    420	struct plat_stmmacenet_data *plat_dat;
    421	struct stmmac_resources stmmac_res;
    422	int ret;
    423
    424	data = device_get_match_data(&pdev->dev);
    425
    426	memset(&stmmac_res, 0, sizeof(struct stmmac_resources));
    427
    428	/**
    429	 * Since stmmac_platform supports name IRQ only, basic platform
    430	 * resource initialization is done in the glue logic.
    431	 */
    432	stmmac_res.irq = platform_get_irq(pdev, 0);
    433	if (stmmac_res.irq < 0)
    434		return stmmac_res.irq;
    435	stmmac_res.wol_irq = stmmac_res.irq;
    436
    437	stmmac_res.addr = devm_platform_ioremap_resource(pdev, 0);
    438	if (IS_ERR(stmmac_res.addr))
    439		return PTR_ERR(stmmac_res.addr);
    440
    441	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
    442	if (IS_ERR(plat_dat))
    443		return PTR_ERR(plat_dat);
    444
    445	ret = data->probe(pdev, plat_dat, &stmmac_res);
    446	if (ret < 0) {
    447		if (ret != -EPROBE_DEFER)
    448			dev_err(&pdev->dev, "failed to probe subdriver: %d\n",
    449				ret);
    450
    451		goto remove_config;
    452	}
    453
    454	ret = dwc_eth_dwmac_config_dt(pdev, plat_dat);
    455	if (ret)
    456		goto remove;
    457
    458	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
    459	if (ret)
    460		goto remove;
    461
    462	return ret;
    463
    464remove:
    465	data->remove(pdev);
    466remove_config:
    467	stmmac_remove_config_dt(pdev, plat_dat);
    468
    469	return ret;
    470}
    471
    472static int dwc_eth_dwmac_remove(struct platform_device *pdev)
    473{
    474	struct net_device *ndev = platform_get_drvdata(pdev);
    475	struct stmmac_priv *priv = netdev_priv(ndev);
    476	const struct dwc_eth_dwmac_data *data;
    477	int err;
    478
    479	data = device_get_match_data(&pdev->dev);
    480
    481	err = stmmac_dvr_remove(&pdev->dev);
    482	if (err < 0)
    483		dev_err(&pdev->dev, "failed to remove platform: %d\n", err);
    484
    485	err = data->remove(pdev);
    486	if (err < 0)
    487		dev_err(&pdev->dev, "failed to remove subdriver: %d\n", err);
    488
    489	stmmac_remove_config_dt(pdev, priv->plat);
    490
    491	return err;
    492}
    493
    494static const struct of_device_id dwc_eth_dwmac_match[] = {
    495	{ .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data },
    496	{ .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data },
    497	{ }
    498};
    499MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
    500
    501static struct platform_driver dwc_eth_dwmac_driver = {
    502	.probe  = dwc_eth_dwmac_probe,
    503	.remove = dwc_eth_dwmac_remove,
    504	.driver = {
    505		.name           = "dwc-eth-dwmac",
    506		.pm             = &stmmac_pltfr_pm_ops,
    507		.of_match_table = dwc_eth_dwmac_match,
    508	},
    509};
    510module_platform_driver(dwc_eth_dwmac_driver);
    511
    512MODULE_AUTHOR("Joao Pinto <jpinto@synopsys.com>");
    513MODULE_DESCRIPTION("Synopsys DWC Ethernet Quality-of-Service v4.10a driver");
    514MODULE_LICENSE("GPL v2");