add xilinx_phy driver
This commit is contained in:
parent
2d5c250396
commit
a2e92d1350
|
@ -338,6 +338,14 @@ config VITESSE_PHY
|
|||
help
|
||||
Currently supports the vsc8244
|
||||
|
||||
config XILINX_PHY
|
||||
tristate "Drivers for xilinx PHYs"
|
||||
help
|
||||
This module provides a driver for the Xilinx PCS/PMA Core.
|
||||
The supported PHY modes include SGMII and 1000BaseX.
|
||||
This can be used an Ethernet controller, for example Xilinx
|
||||
Axi Ethernet or Cadence GEM in Xilinx devices.
|
||||
|
||||
config XILINX_GMII2RGMII
|
||||
tristate "Xilinx GMII2RGMII converter driver"
|
||||
help
|
||||
|
|
|
@ -84,5 +84,6 @@ obj-$(CONFIG_SMSC_PHY) += smsc.o
|
|||
obj-$(CONFIG_STE10XP) += ste10Xp.o
|
||||
obj-$(CONFIG_TERANETICS_PHY) += teranetics.o
|
||||
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
|
||||
obj-$(CONFIG_XILINX_PHY) += xilinx_phy.o
|
||||
obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
|
||||
obj-$(CONFIG_CTC_PHY) += mars.o
|
||||
|
|
162
drivers/net/phy/xilinx_phy.c
Normal file
162
drivers/net/phy/xilinx_phy.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* Xilinx PCS/PMA Core phy driver
|
||||
*
|
||||
* Copyright (C) 2015 Xilinx, Inc.
|
||||
*
|
||||
* Description:
|
||||
* This driver is developed for PCS/PMA Core.
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/xilinx_phy.h>
|
||||
|
||||
#define MII_PHY_STATUS_SPD_MASK 0x0C00
|
||||
#define MII_PHY_STATUS_FULLDUPLEX 0x1000
|
||||
#define MII_PHY_STATUS_1000 0x0800
|
||||
#define MII_PHY_STATUS_100 0x0400
|
||||
#define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF
|
||||
|
||||
static int xilinxphy_read_status(struct phy_device *phydev)
|
||||
{
|
||||
int err;
|
||||
int status = 0;
|
||||
|
||||
/* Update the link, but return if there
|
||||
* was an error
|
||||
*/
|
||||
err = genphy_update_link(phydev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (phydev->autoneg == AUTONEG_ENABLE) {
|
||||
status = phy_read(phydev, MII_LPA);
|
||||
|
||||
if (status & MII_PHY_STATUS_FULLDUPLEX)
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
else
|
||||
phydev->duplex = DUPLEX_HALF;
|
||||
|
||||
switch (status & MII_PHY_STATUS_SPD_MASK) {
|
||||
case MII_PHY_STATUS_1000:
|
||||
phydev->speed = SPEED_1000;
|
||||
break;
|
||||
|
||||
case MII_PHY_STATUS_100:
|
||||
phydev->speed = SPEED_100;
|
||||
break;
|
||||
|
||||
default:
|
||||
phydev->speed = SPEED_10;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
int bmcr = phy_read(phydev, MII_BMCR);
|
||||
|
||||
if (bmcr < 0)
|
||||
return bmcr;
|
||||
|
||||
if (bmcr & BMCR_FULLDPLX)
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
else
|
||||
phydev->duplex = DUPLEX_HALF;
|
||||
|
||||
if (bmcr & BMCR_SPEED1000)
|
||||
phydev->speed = SPEED_1000;
|
||||
else if (bmcr & BMCR_SPEED100)
|
||||
phydev->speed = SPEED_100;
|
||||
else
|
||||
phydev->speed = SPEED_10;
|
||||
}
|
||||
|
||||
/* For 1000BASE-X Phy Mode the speed/duplex will always be
|
||||
* 1000Mbps/fullduplex
|
||||
*/
|
||||
if (phydev->dev_flags == XAE_PHY_TYPE_1000BASE_X) {
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
phydev->speed = SPEED_1000;
|
||||
}
|
||||
|
||||
/* For 2500BASE-X Phy Mode the speed/duplex will always be
|
||||
* 2500Mbps/fullduplex
|
||||
*/
|
||||
if (phydev->dev_flags == XAE_PHY_TYPE_2500) {
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
phydev->speed = SPEED_2500;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xilinxphy_of_init(struct phy_device *phydev)
|
||||
{
|
||||
struct device *dev = &phydev->mdio.dev;
|
||||
struct device_node *of_node = dev->of_node;
|
||||
u32 phytype;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_OF_MDIO))
|
||||
return 0;
|
||||
|
||||
if (!of_node)
|
||||
return -ENODEV;
|
||||
|
||||
if (!of_property_read_u32(of_node, "xlnx,phy-type", &phytype)) {
|
||||
if (phytype == XAE_PHY_TYPE_1000BASE_X)
|
||||
phydev->dev_flags |= XAE_PHY_TYPE_1000BASE_X;
|
||||
if (phytype == XAE_PHY_TYPE_2500)
|
||||
phydev->dev_flags |= XAE_PHY_TYPE_2500;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xilinxphy_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int temp;
|
||||
|
||||
xilinxphy_of_init(phydev);
|
||||
temp = phy_read(phydev, MII_BMCR);
|
||||
temp &= XPCSPMA_PHY_CTRL_ISOLATE_DISABLE;
|
||||
phy_write(phydev, MII_BMCR, temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_driver xilinx_drivers[] = {
|
||||
{
|
||||
.phy_id = XILINX_PHY_ID,
|
||||
.phy_id_mask = XILINX_PHY_ID_MASK,
|
||||
.name = "Xilinx PCS/PMA PHY",
|
||||
.flags = PHY_RST_AFTER_CLK_EN,
|
||||
.features = PHY_GBIT_FEATURES,
|
||||
.config_init = &xilinxphy_config_init,
|
||||
.config_aneg = &genphy_config_aneg,
|
||||
.read_status = &xilinxphy_read_status,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
},
|
||||
};
|
||||
|
||||
module_phy_driver(xilinx_drivers);
|
||||
|
||||
static struct mdio_device_id __maybe_unused xilinx_tbl[] = {
|
||||
{ XILINX_PHY_ID, XILINX_PHY_ID_MASK },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(mdio, xilinx_tbl);
|
||||
MODULE_DESCRIPTION("Xilinx PCS/PMA PHY driver");
|
||||
MODULE_LICENSE("GPL");
|
20
include/linux/xilinx_phy.h
Normal file
20
include/linux/xilinx_phy.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
#ifndef _XILINX_PHY_H
|
||||
#define _XILINX_PHY_H
|
||||
|
||||
/* Mask used for ID comparisons */
|
||||
#define XILINX_PHY_ID_MASK 0xfffffff0
|
||||
|
||||
/* Known PHY IDs */
|
||||
#define XILINX_PHY_ID 0x01740c00
|
||||
|
||||
/* struct phy_device dev_flags definitions */
|
||||
#define XAE_PHY_TYPE_MII 0
|
||||
#define XAE_PHY_TYPE_GMII 1
|
||||
#define XAE_PHY_TYPE_RGMII_1_3 2
|
||||
#define XAE_PHY_TYPE_RGMII_2_0 3
|
||||
#define XAE_PHY_TYPE_SGMII 4
|
||||
#define XAE_PHY_TYPE_1000BASE_X 5
|
||||
#define XAE_PHY_TYPE_2500 6
|
||||
|
||||
#endif /* _XILINX_PHY_H */
|
Loading…
Reference in New Issue
Block a user