mirror of https://gitee.com/openkylin/linux.git
Merge branch 'xilinx-gmiitorgmii-converter'
Kedareswara rao Appana says: ==================== net: phy: Add xilinx gmiitorgmii converter support The Gigabit Media Independent Interface (GMII) to Reduced Gigabit Media Independent Interface (RGMII) core provides the RGMII between RGMII-compliant Ethernet physical media devices (PHY) and the Gigabit Ethernet controller. This core can be used in all three modes of operation(10/100/1000 Mb/s). The Management Data Input/Output (MDIO) interface is used to configure the Speed of operation. This core can switch dynamically between the three Different speed modes by configuring the conveter register through mdio write. The conveter sits b/w the MAC and external phy like below MACB <==> GMII2RGMII <==> RGMII_PHY MDIO <========> GMII2RGMII MCAB <=======> <========> RGMII Using MAC MDIO bus we can access both the converter and the external PHY. We need to program the line speed of the converter during run time based On the external phy negotiated speed. This patch series does the below ---> Add mask for Control register 10Mbps speed. ---> Add support for xilinx gmiitorgmii converter. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4330ea798f
|
@ -0,0 +1,35 @@
|
|||
XILINX GMIITORGMII Converter Driver Device Tree Bindings
|
||||
--------------------------------------------------------
|
||||
|
||||
The Gigabit Media Independent Interface (GMII) to Reduced Gigabit Media
|
||||
Independent Interface (RGMII) core provides the RGMII between RGMII-compliant
|
||||
Ethernet physical media devices (PHY) and the Gigabit Ethernet controller.
|
||||
This core can be used in all three modes of operation(10/100/1000 Mb/s).
|
||||
The Management Data Input/Output (MDIO) interface is used to configure the
|
||||
Speed of operation. This core can switch dynamically between the three
|
||||
Different speed modes by configuring the conveter register through mdio write.
|
||||
|
||||
This converter sits between the ethernet MAC and the external phy.
|
||||
MAC <==> GMII2RGMII <==> RGMII_PHY
|
||||
|
||||
For more details about mdio please refer phy.txt file in the same directory.
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "xlnx,gmii-to-rgmii-1.0"
|
||||
- reg : The ID number for the phy, usually a small integer
|
||||
- phy-handle : Should point to the external phy device.
|
||||
See ethernet.txt file in the same directory.
|
||||
|
||||
Example:
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy: ethernet-phy@0 {
|
||||
......
|
||||
};
|
||||
gmiitorgmii: gmiitorgmii@8 {
|
||||
compatible = "xlnx,gmii-to-rgmii-1.0";
|
||||
reg = <8>;
|
||||
phy-handle = <&phy>;
|
||||
};
|
||||
};
|
|
@ -312,6 +312,13 @@ config MICROSEMI_PHY
|
|||
---help---
|
||||
Currently supports the VSC8531 and VSC8541 PHYs
|
||||
|
||||
config XILINX_GMII2RGMII
|
||||
tristate "Xilinx GMII2RGMII converter driver"
|
||||
---help---
|
||||
This driver support xilinx GMII to RGMII IP core it provides
|
||||
the Reduced Gigabit Media Independent Interface(RGMII) between
|
||||
Ethernet physical media devices and the Gigabit Ethernet controller.
|
||||
|
||||
endif # PHYLIB
|
||||
|
||||
config MICREL_KS8995MA
|
||||
|
|
|
@ -50,3 +50,4 @@ obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o
|
|||
obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o
|
||||
obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o
|
||||
obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o
|
||||
obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/* Xilinx GMII2RGMII Converter driver
|
||||
*
|
||||
* Copyright (C) 2016 Xilinx, Inc.
|
||||
*
|
||||
* Author: Kedareswara rao Appana <appanad@xilinx.com>
|
||||
*
|
||||
* Description:
|
||||
* This driver is developed for Xilinx GMII2RGMII Converter
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/mdio.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/of_mdio.h>
|
||||
|
||||
#define XILINX_GMII2RGMII_REG 0x10
|
||||
#define XILINX_GMII2RGMII_SPEED_MASK (BMCR_SPEED1000 | BMCR_SPEED100)
|
||||
|
||||
struct gmii2rgmii {
|
||||
struct phy_device *phy_dev;
|
||||
struct phy_driver *phy_drv;
|
||||
struct phy_driver conv_phy_drv;
|
||||
int addr;
|
||||
};
|
||||
|
||||
static int xgmiitorgmii_read_status(struct phy_device *phydev)
|
||||
{
|
||||
struct gmii2rgmii *priv = phydev->priv;
|
||||
u16 val = 0;
|
||||
|
||||
priv->phy_drv->read_status(phydev);
|
||||
|
||||
val = mdiobus_read(phydev->mdio.bus, priv->addr, XILINX_GMII2RGMII_REG);
|
||||
val &= XILINX_GMII2RGMII_SPEED_MASK;
|
||||
|
||||
if (phydev->speed == SPEED_1000)
|
||||
val |= BMCR_SPEED1000;
|
||||
else if (phydev->speed == SPEED_100)
|
||||
val |= BMCR_SPEED100;
|
||||
else
|
||||
val |= BMCR_SPEED10;
|
||||
|
||||
mdiobus_write(phydev->mdio.bus, priv->addr, XILINX_GMII2RGMII_REG, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xgmiitorgmii_probe(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct device *dev = &mdiodev->dev;
|
||||
struct device_node *np = dev->of_node, *phy_node;
|
||||
struct gmii2rgmii *priv;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
phy_node = of_parse_phandle(np, "phy-handle", 0);
|
||||
if (IS_ERR(phy_node)) {
|
||||
dev_err(dev, "Couldn't parse phy-handle\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv->phy_dev = of_phy_find_device(phy_node);
|
||||
if (!priv->phy_dev) {
|
||||
dev_info(dev, "Couldn't find phydev\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
priv->addr = mdiodev->addr;
|
||||
priv->phy_drv = priv->phy_dev->drv;
|
||||
memcpy(&priv->conv_phy_drv, priv->phy_dev->drv,
|
||||
sizeof(struct phy_driver));
|
||||
priv->conv_phy_drv.read_status = xgmiitorgmii_read_status;
|
||||
priv->phy_dev->priv = priv;
|
||||
priv->phy_dev->drv = &priv->conv_phy_drv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id xgmiitorgmii_of_match[] = {
|
||||
{ .compatible = "xlnx,gmii-to-rgmii-1.0" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, xgmiitorgmii_of_match);
|
||||
|
||||
static struct mdio_driver xgmiitorgmii_driver = {
|
||||
.probe = xgmiitorgmii_probe,
|
||||
.mdiodrv.driver = {
|
||||
.name = "xgmiitorgmii",
|
||||
.of_match_table = xgmiitorgmii_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
mdio_module_driver(xgmiitorgmii_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Xilinx GMII2RGMII converter driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -48,6 +48,7 @@
|
|||
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
|
||||
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
|
||||
#define BMCR_RESET 0x8000 /* Reset to default state */
|
||||
#define BMCR_SPEED10 0x0000 /* Select 10Mbps */
|
||||
|
||||
/* Basic mode status register. */
|
||||
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
|
||||
|
|
Loading…
Reference in New Issue