1 /* Xilinx PCS/PMA Core phy driver
3 * Copyright (C) 2015 Xilinx, Inc.
6 * This driver is developed for PCS/PMA Core.
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/mii.h>
22 #include <linux/phy.h>
24 #include <linux/xilinx_phy.h>
26 #define MII_PHY_STATUS_SPD_MASK 0x0C00
27 #define MII_PHY_STATUS_FULLDUPLEX 0x1000
28 #define MII_PHY_STATUS_1000 0x0800
29 #define MII_PHY_STATUS_100 0x0400
30 #define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF
32 static int xilinxphy_read_status(struct phy_device *phydev)
37 /* Update the link, but return if there
40 err = genphy_update_link(phydev);
44 if (AUTONEG_ENABLE == phydev->autoneg) {
45 status = phy_read(phydev, MII_LPA);
46 status = status & MII_PHY_STATUS_SPD_MASK;
48 if (status & MII_PHY_STATUS_FULLDUPLEX)
49 phydev->duplex = DUPLEX_FULL;
51 phydev->duplex = DUPLEX_HALF;
54 case MII_PHY_STATUS_1000:
55 phydev->speed = SPEED_1000;
58 case MII_PHY_STATUS_100:
59 phydev->speed = SPEED_100;
63 phydev->speed = SPEED_10;
67 int bmcr = phy_read(phydev, MII_BMCR);
72 if (bmcr & BMCR_FULLDPLX)
73 phydev->duplex = DUPLEX_FULL;
75 phydev->duplex = DUPLEX_HALF;
77 if (bmcr & BMCR_SPEED1000)
78 phydev->speed = SPEED_1000;
79 else if (bmcr & BMCR_SPEED100)
80 phydev->speed = SPEED_100;
82 phydev->speed = SPEED_10;
85 /* For 1000BASE-X Phy Mode the speed/duplex will always be
88 if (phydev->dev_flags == XAE_PHY_TYPE_1000BASE_X) {
89 phydev->duplex = DUPLEX_FULL;
90 phydev->speed = SPEED_1000;
96 static int xilinxphy_config_init(struct phy_device *phydev)
100 temp = phy_read(phydev, MII_BMCR);
101 temp &= XPCSPMA_PHY_CTRL_ISOLATE_DISABLE;
102 phy_write(phydev, MII_BMCR, temp);
107 static struct phy_driver xilinx_drivers[] = {
109 .phy_id = XILINX_PHY_ID,
110 .phy_id_mask = XILINX_PHY_ID_MASK,
111 .name = "Xilinx PCS/PMA PHY",
112 .features = PHY_GBIT_FEATURES,
113 .config_init = &xilinxphy_config_init,
114 .config_aneg = &genphy_config_aneg,
115 .read_status = &xilinxphy_read_status,
116 .resume = &genphy_resume,
117 .suspend = &genphy_suspend,
118 .driver = { .owner = THIS_MODULE },
122 module_phy_driver(xilinx_drivers);
124 static struct mdio_device_id __maybe_unused xilinx_tbl[] = {
125 { XILINX_PHY_ID, XILINX_PHY_ID_MASK },
129 MODULE_DEVICE_TABLE(mdio, xilinx_tbl);
130 MODULE_DESCRIPTION("Xilinx PCS/PMA PHY driver");
131 MODULE_LICENSE("GPL");