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

xilinx_gmii2rgmii.c (3415B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/* Xilinx GMII2RGMII Converter driver
      3 *
      4 * Copyright (C) 2016 Xilinx, Inc.
      5 * Copyright (C) 2016 Andrew Lunn <andrew@lunn.ch>
      6 *
      7 * Author: Andrew Lunn <andrew@lunn.ch>
      8 * Author: Kedareswara rao Appana <appanad@xilinx.com>
      9 *
     10 * Description:
     11 * This driver is developed for Xilinx GMII2RGMII Converter
     12 */
     13#include <linux/module.h>
     14#include <linux/kernel.h>
     15#include <linux/mii.h>
     16#include <linux/mdio.h>
     17#include <linux/phy.h>
     18#include <linux/of_mdio.h>
     19
     20#define XILINX_GMII2RGMII_REG		0x10
     21#define XILINX_GMII2RGMII_SPEED_MASK	(BMCR_SPEED1000 | BMCR_SPEED100)
     22
     23struct gmii2rgmii {
     24	struct phy_device *phy_dev;
     25	struct phy_driver *phy_drv;
     26	struct phy_driver conv_phy_drv;
     27	struct mdio_device *mdio;
     28};
     29
     30static void xgmiitorgmii_configure(struct gmii2rgmii *priv, int speed)
     31{
     32	struct mii_bus *bus = priv->mdio->bus;
     33	int addr = priv->mdio->addr;
     34	u16 val;
     35
     36	val = mdiobus_read(bus, addr, XILINX_GMII2RGMII_REG);
     37	val &= ~XILINX_GMII2RGMII_SPEED_MASK;
     38
     39	if (speed == SPEED_1000)
     40		val |= BMCR_SPEED1000;
     41	else if (speed == SPEED_100)
     42		val |= BMCR_SPEED100;
     43	else
     44		val |= BMCR_SPEED10;
     45
     46	mdiobus_write(bus, addr, XILINX_GMII2RGMII_REG, val);
     47}
     48
     49static int xgmiitorgmii_read_status(struct phy_device *phydev)
     50{
     51	struct gmii2rgmii *priv = mdiodev_get_drvdata(&phydev->mdio);
     52	int err;
     53
     54	if (priv->phy_drv->read_status)
     55		err = priv->phy_drv->read_status(phydev);
     56	else
     57		err = genphy_read_status(phydev);
     58	if (err < 0)
     59		return err;
     60
     61	xgmiitorgmii_configure(priv, phydev->speed);
     62
     63	return 0;
     64}
     65
     66static int xgmiitorgmii_set_loopback(struct phy_device *phydev, bool enable)
     67{
     68	struct gmii2rgmii *priv = mdiodev_get_drvdata(&phydev->mdio);
     69	int err;
     70
     71	if (priv->phy_drv->set_loopback)
     72		err = priv->phy_drv->set_loopback(phydev, enable);
     73	else
     74		err = genphy_loopback(phydev, enable);
     75	if (err < 0)
     76		return err;
     77
     78	xgmiitorgmii_configure(priv, phydev->speed);
     79
     80	return 0;
     81}
     82
     83static int xgmiitorgmii_probe(struct mdio_device *mdiodev)
     84{
     85	struct device *dev = &mdiodev->dev;
     86	struct device_node *np = dev->of_node, *phy_node;
     87	struct gmii2rgmii *priv;
     88
     89	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
     90	if (!priv)
     91		return -ENOMEM;
     92
     93	phy_node = of_parse_phandle(np, "phy-handle", 0);
     94	if (!phy_node) {
     95		dev_err(dev, "Couldn't parse phy-handle\n");
     96		return -ENODEV;
     97	}
     98
     99	priv->phy_dev = of_phy_find_device(phy_node);
    100	of_node_put(phy_node);
    101	if (!priv->phy_dev) {
    102		dev_info(dev, "Couldn't find phydev\n");
    103		return -EPROBE_DEFER;
    104	}
    105
    106	if (!priv->phy_dev->drv) {
    107		dev_info(dev, "Attached phy not ready\n");
    108		return -EPROBE_DEFER;
    109	}
    110
    111	priv->mdio = mdiodev;
    112	priv->phy_drv = priv->phy_dev->drv;
    113	memcpy(&priv->conv_phy_drv, priv->phy_dev->drv,
    114	       sizeof(struct phy_driver));
    115	priv->conv_phy_drv.read_status = xgmiitorgmii_read_status;
    116	priv->conv_phy_drv.set_loopback = xgmiitorgmii_set_loopback;
    117	mdiodev_set_drvdata(&priv->phy_dev->mdio, priv);
    118	priv->phy_dev->drv = &priv->conv_phy_drv;
    119
    120	return 0;
    121}
    122
    123static const struct of_device_id xgmiitorgmii_of_match[] = {
    124	{ .compatible = "xlnx,gmii-to-rgmii-1.0" },
    125	{},
    126};
    127MODULE_DEVICE_TABLE(of, xgmiitorgmii_of_match);
    128
    129static struct mdio_driver xgmiitorgmii_driver = {
    130	.probe	= xgmiitorgmii_probe,
    131	.mdiodrv.driver = {
    132		.name = "xgmiitorgmii",
    133		.of_match_table = xgmiitorgmii_of_match,
    134	},
    135};
    136
    137mdio_module_driver(xgmiitorgmii_driver);
    138
    139MODULE_DESCRIPTION("Xilinx GMII2RGMII converter driver");
    140MODULE_LICENSE("GPL");