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-intel-plat.c (4495B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Intel DWMAC platform driver
      3 *
      4 * Copyright(C) 2020 Intel Corporation
      5 */
      6
      7#include <linux/ethtool.h>
      8#include <linux/module.h>
      9#include <linux/of.h>
     10#include <linux/of_device.h>
     11#include <linux/platform_device.h>
     12#include <linux/stmmac.h>
     13
     14#include "dwmac4.h"
     15#include "stmmac.h"
     16#include "stmmac_platform.h"
     17
     18struct intel_dwmac {
     19	struct device *dev;
     20	struct clk *tx_clk;
     21	const struct intel_dwmac_data *data;
     22};
     23
     24struct intel_dwmac_data {
     25	void (*fix_mac_speed)(void *priv, unsigned int speed);
     26	unsigned long ptp_ref_clk_rate;
     27	unsigned long tx_clk_rate;
     28	bool tx_clk_en;
     29};
     30
     31static void kmb_eth_fix_mac_speed(void *priv, unsigned int speed)
     32{
     33	struct intel_dwmac *dwmac = priv;
     34	unsigned long rate;
     35	int ret;
     36
     37	rate = clk_get_rate(dwmac->tx_clk);
     38
     39	switch (speed) {
     40	case SPEED_1000:
     41		rate = 125000000;
     42		break;
     43
     44	case SPEED_100:
     45		rate = 25000000;
     46		break;
     47
     48	case SPEED_10:
     49		rate = 2500000;
     50		break;
     51
     52	default:
     53		dev_err(dwmac->dev, "Invalid speed\n");
     54		break;
     55	}
     56
     57	ret = clk_set_rate(dwmac->tx_clk, rate);
     58	if (ret)
     59		dev_err(dwmac->dev, "Failed to configure tx clock rate\n");
     60}
     61
     62static const struct intel_dwmac_data kmb_data = {
     63	.fix_mac_speed = kmb_eth_fix_mac_speed,
     64	.ptp_ref_clk_rate = 200000000,
     65	.tx_clk_rate = 125000000,
     66	.tx_clk_en = true,
     67};
     68
     69static const struct of_device_id intel_eth_plat_match[] = {
     70	{ .compatible = "intel,keembay-dwmac", .data = &kmb_data },
     71	{ }
     72};
     73MODULE_DEVICE_TABLE(of, intel_eth_plat_match);
     74
     75static int intel_eth_plat_probe(struct platform_device *pdev)
     76{
     77	struct plat_stmmacenet_data *plat_dat;
     78	struct stmmac_resources stmmac_res;
     79	const struct of_device_id *match;
     80	struct intel_dwmac *dwmac;
     81	unsigned long rate;
     82	int ret;
     83
     84	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
     85	if (ret)
     86		return ret;
     87
     88	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
     89	if (IS_ERR(plat_dat)) {
     90		dev_err(&pdev->dev, "dt configuration failed\n");
     91		return PTR_ERR(plat_dat);
     92	}
     93
     94	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
     95	if (!dwmac) {
     96		ret = -ENOMEM;
     97		goto err_remove_config_dt;
     98	}
     99
    100	dwmac->dev = &pdev->dev;
    101	dwmac->tx_clk = NULL;
    102
    103	match = of_match_device(intel_eth_plat_match, &pdev->dev);
    104	if (match && match->data) {
    105		dwmac->data = (const struct intel_dwmac_data *)match->data;
    106
    107		if (dwmac->data->fix_mac_speed)
    108			plat_dat->fix_mac_speed = dwmac->data->fix_mac_speed;
    109
    110		/* Enable TX clock */
    111		if (dwmac->data->tx_clk_en) {
    112			dwmac->tx_clk = devm_clk_get(&pdev->dev, "tx_clk");
    113			if (IS_ERR(dwmac->tx_clk)) {
    114				ret = PTR_ERR(dwmac->tx_clk);
    115				goto err_remove_config_dt;
    116			}
    117
    118			clk_prepare_enable(dwmac->tx_clk);
    119
    120			/* Check and configure TX clock rate */
    121			rate = clk_get_rate(dwmac->tx_clk);
    122			if (dwmac->data->tx_clk_rate &&
    123			    rate != dwmac->data->tx_clk_rate) {
    124				rate = dwmac->data->tx_clk_rate;
    125				ret = clk_set_rate(dwmac->tx_clk, rate);
    126				if (ret) {
    127					dev_err(&pdev->dev,
    128						"Failed to set tx_clk\n");
    129					goto err_remove_config_dt;
    130				}
    131			}
    132		}
    133
    134		/* Check and configure PTP ref clock rate */
    135		rate = clk_get_rate(plat_dat->clk_ptp_ref);
    136		if (dwmac->data->ptp_ref_clk_rate &&
    137		    rate != dwmac->data->ptp_ref_clk_rate) {
    138			rate = dwmac->data->ptp_ref_clk_rate;
    139			ret = clk_set_rate(plat_dat->clk_ptp_ref, rate);
    140			if (ret) {
    141				dev_err(&pdev->dev,
    142					"Failed to set clk_ptp_ref\n");
    143				goto err_remove_config_dt;
    144			}
    145		}
    146	}
    147
    148	plat_dat->bsp_priv = dwmac;
    149	plat_dat->eee_usecs_rate = plat_dat->clk_ptp_rate;
    150
    151	if (plat_dat->eee_usecs_rate > 0) {
    152		u32 tx_lpi_usec;
    153
    154		tx_lpi_usec = (plat_dat->eee_usecs_rate / 1000000) - 1;
    155		writel(tx_lpi_usec, stmmac_res.addr + GMAC_1US_TIC_COUNTER);
    156	}
    157
    158	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
    159	if (ret) {
    160		clk_disable_unprepare(dwmac->tx_clk);
    161		goto err_remove_config_dt;
    162	}
    163
    164	return 0;
    165
    166err_remove_config_dt:
    167	stmmac_remove_config_dt(pdev, plat_dat);
    168
    169	return ret;
    170}
    171
    172static int intel_eth_plat_remove(struct platform_device *pdev)
    173{
    174	struct intel_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
    175	int ret;
    176
    177	ret = stmmac_pltfr_remove(pdev);
    178	clk_disable_unprepare(dwmac->tx_clk);
    179
    180	return ret;
    181}
    182
    183static struct platform_driver intel_eth_plat_driver = {
    184	.probe  = intel_eth_plat_probe,
    185	.remove = intel_eth_plat_remove,
    186	.driver = {
    187		.name		= "intel-eth-plat",
    188		.pm		= &stmmac_pltfr_pm_ops,
    189		.of_match_table = intel_eth_plat_match,
    190	},
    191};
    192module_platform_driver(intel_eth_plat_driver);
    193
    194MODULE_LICENSE("GPL v2");
    195MODULE_DESCRIPTION("Intel DWMAC platform driver");