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-anarion.c (3819B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Adaptrum Anarion DWMAC glue layer
      4 *
      5 * Copyright (C) 2017, Adaptrum, Inc.
      6 * (Written by Alexandru Gagniuc <alex.g at adaptrum.com> for Adaptrum, Inc.)
      7 */
      8
      9#include <linux/io.h>
     10#include <linux/of.h>
     11#include <linux/of_net.h>
     12#include <linux/stmmac.h>
     13
     14#include "stmmac.h"
     15#include "stmmac_platform.h"
     16
     17#define GMAC_RESET_CONTROL_REG		0
     18#define GMAC_SW_CONFIG_REG		4
     19#define  GMAC_CONFIG_INTF_SEL_MASK	(0x7 << 0)
     20#define  GMAC_CONFIG_INTF_RGMII		(0x1 << 0)
     21
     22struct anarion_gmac {
     23	uintptr_t ctl_block;
     24	uint32_t phy_intf_sel;
     25};
     26
     27static uint32_t gmac_read_reg(struct anarion_gmac *gmac, uint8_t reg)
     28{
     29	return readl((void *)(gmac->ctl_block + reg));
     30};
     31
     32static void gmac_write_reg(struct anarion_gmac *gmac, uint8_t reg, uint32_t val)
     33{
     34	writel(val, (void *)(gmac->ctl_block + reg));
     35}
     36
     37static int anarion_gmac_init(struct platform_device *pdev, void *priv)
     38{
     39	uint32_t sw_config;
     40	struct anarion_gmac *gmac = priv;
     41
     42	/* Reset logic, configure interface mode, then release reset. SIMPLE! */
     43	gmac_write_reg(gmac, GMAC_RESET_CONTROL_REG, 1);
     44
     45	sw_config = gmac_read_reg(gmac, GMAC_SW_CONFIG_REG);
     46	sw_config &= ~GMAC_CONFIG_INTF_SEL_MASK;
     47	sw_config |= (gmac->phy_intf_sel & GMAC_CONFIG_INTF_SEL_MASK);
     48	gmac_write_reg(gmac, GMAC_SW_CONFIG_REG, sw_config);
     49
     50	gmac_write_reg(gmac, GMAC_RESET_CONTROL_REG, 0);
     51
     52	return 0;
     53}
     54
     55static void anarion_gmac_exit(struct platform_device *pdev, void *priv)
     56{
     57	struct anarion_gmac *gmac = priv;
     58
     59	gmac_write_reg(gmac, GMAC_RESET_CONTROL_REG, 1);
     60}
     61
     62static struct anarion_gmac *anarion_config_dt(struct platform_device *pdev)
     63{
     64	struct anarion_gmac *gmac;
     65	phy_interface_t phy_mode;
     66	void __iomem *ctl_block;
     67	int err;
     68
     69	ctl_block = devm_platform_ioremap_resource(pdev, 1);
     70	if (IS_ERR(ctl_block)) {
     71		dev_err(&pdev->dev, "Cannot get reset region (%ld)!\n",
     72			PTR_ERR(ctl_block));
     73		return ctl_block;
     74	}
     75
     76	gmac = devm_kzalloc(&pdev->dev, sizeof(*gmac), GFP_KERNEL);
     77	if (!gmac)
     78		return ERR_PTR(-ENOMEM);
     79
     80	gmac->ctl_block = (uintptr_t)ctl_block;
     81
     82	err = of_get_phy_mode(pdev->dev.of_node, &phy_mode);
     83	if (err)
     84		return ERR_PTR(err);
     85
     86	switch (phy_mode) {
     87	case PHY_INTERFACE_MODE_RGMII:
     88		fallthrough;
     89	case PHY_INTERFACE_MODE_RGMII_ID:
     90	case PHY_INTERFACE_MODE_RGMII_RXID:
     91	case PHY_INTERFACE_MODE_RGMII_TXID:
     92		gmac->phy_intf_sel = GMAC_CONFIG_INTF_RGMII;
     93		break;
     94	default:
     95		dev_err(&pdev->dev, "Unsupported phy-mode (%d)\n",
     96			phy_mode);
     97		return ERR_PTR(-ENOTSUPP);
     98	}
     99
    100	return gmac;
    101}
    102
    103static int anarion_dwmac_probe(struct platform_device *pdev)
    104{
    105	int ret;
    106	struct anarion_gmac *gmac;
    107	struct plat_stmmacenet_data *plat_dat;
    108	struct stmmac_resources stmmac_res;
    109
    110	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
    111	if (ret)
    112		return ret;
    113
    114	gmac = anarion_config_dt(pdev);
    115	if (IS_ERR(gmac))
    116		return PTR_ERR(gmac);
    117
    118	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
    119	if (IS_ERR(plat_dat))
    120		return PTR_ERR(plat_dat);
    121
    122	plat_dat->init = anarion_gmac_init;
    123	plat_dat->exit = anarion_gmac_exit;
    124	anarion_gmac_init(pdev, gmac);
    125	plat_dat->bsp_priv = gmac;
    126
    127	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
    128	if (ret) {
    129		stmmac_remove_config_dt(pdev, plat_dat);
    130		return ret;
    131	}
    132
    133	return 0;
    134}
    135
    136static const struct of_device_id anarion_dwmac_match[] = {
    137	{ .compatible = "adaptrum,anarion-gmac" },
    138	{ }
    139};
    140MODULE_DEVICE_TABLE(of, anarion_dwmac_match);
    141
    142static struct platform_driver anarion_dwmac_driver = {
    143	.probe  = anarion_dwmac_probe,
    144	.remove = stmmac_pltfr_remove,
    145	.driver = {
    146		.name           = "anarion-dwmac",
    147		.pm		= &stmmac_pltfr_pm_ops,
    148		.of_match_table = anarion_dwmac_match,
    149	},
    150};
    151module_platform_driver(anarion_dwmac_driver);
    152
    153MODULE_DESCRIPTION("Adaptrum Anarion DWMAC specific glue layer");
    154MODULE_AUTHOR("Alexandru Gagniuc <mr.nuke.me@gmail.com>");
    155MODULE_LICENSE("GPL v2");