15f184715SAndy Fleming /* 25f184715SAndy Fleming * Generic PHY Management code 35f184715SAndy Fleming * 45f184715SAndy Fleming * This program is free software; you can redistribute it and/or 55f184715SAndy Fleming * modify it under the terms of the GNU General Public License as 65f184715SAndy Fleming * published by the Free Software Foundation; either version 2 of 75f184715SAndy Fleming * the License, or (at your option) any later version. 85f184715SAndy Fleming * 95f184715SAndy Fleming * This program is distributed in the hope that it will be useful, 105f184715SAndy Fleming * but WITHOUT ANY WARRANTY; without even the implied warranty of 115f184715SAndy Fleming * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 125f184715SAndy Fleming * GNU General Public License for more details. 135f184715SAndy Fleming * 145f184715SAndy Fleming * You should have received a copy of the GNU General Public License 155f184715SAndy Fleming * along with this program; if not, write to the Free Software 165f184715SAndy Fleming * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 175f184715SAndy Fleming * MA 02111-1307 USA 185f184715SAndy Fleming * 195f184715SAndy Fleming * 205f184715SAndy Fleming * Copyright 2011 Freescale Semiconductor, Inc. 215f184715SAndy Fleming * author Andy Fleming 225f184715SAndy Fleming * 235f184715SAndy Fleming * Based loosely off of Linux's PHY Lib 245f184715SAndy Fleming */ 255f184715SAndy Fleming 265f184715SAndy Fleming #include <config.h> 275f184715SAndy Fleming #include <common.h> 285f184715SAndy Fleming #include <miiphy.h> 295f184715SAndy Fleming #include <phy.h> 305f184715SAndy Fleming 315f184715SAndy Fleming int gen10g_shutdown(struct phy_device *phydev) 325f184715SAndy Fleming { 335f184715SAndy Fleming return 0; 345f184715SAndy Fleming } 355f184715SAndy Fleming 365f184715SAndy Fleming int gen10g_startup(struct phy_device *phydev) 375f184715SAndy Fleming { 385f184715SAndy Fleming int devad, reg; 39*ee8fa20fSAndy Fleming u32 mmd_mask = phydev->mmds & MDIO_DEVS_LINK; 405f184715SAndy Fleming 415f184715SAndy Fleming phydev->link = 1; 425f184715SAndy Fleming 435f184715SAndy Fleming /* For now just lie and say it's 10G all the time */ 445f184715SAndy Fleming phydev->speed = SPEED_10000; 455f184715SAndy Fleming phydev->duplex = DUPLEX_FULL; 465f184715SAndy Fleming 47*ee8fa20fSAndy Fleming /* 48*ee8fa20fSAndy Fleming * Go through all the link-reporting devices, and make sure 49*ee8fa20fSAndy Fleming * they're all up and happy 50*ee8fa20fSAndy Fleming */ 515f184715SAndy Fleming for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) { 52*ee8fa20fSAndy Fleming if (!(mmd_mask & 1)) 535f184715SAndy Fleming continue; 545f184715SAndy Fleming 555f184715SAndy Fleming /* Read twice because link state is latched and a 565f184715SAndy Fleming * read moves the current state into the register */ 575f184715SAndy Fleming phy_read(phydev, devad, MDIO_STAT1); 585f184715SAndy Fleming reg = phy_read(phydev, devad, MDIO_STAT1); 595f184715SAndy Fleming if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS)) 605f184715SAndy Fleming phydev->link = 0; 615f184715SAndy Fleming } 625f184715SAndy Fleming 635f184715SAndy Fleming return 0; 645f184715SAndy Fleming } 655f184715SAndy Fleming 665f184715SAndy Fleming int gen10g_discover_mmds(struct phy_device *phydev) 675f184715SAndy Fleming { 685f184715SAndy Fleming int mmd, stat2, devs1, devs2; 695f184715SAndy Fleming 705f184715SAndy Fleming /* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY 715f184715SAndy Fleming * XS or DTE XS; give up if none is present. */ 725f184715SAndy Fleming for (mmd = 1; mmd <= 5; mmd++) { 735f184715SAndy Fleming /* Is this MMD present? */ 745f184715SAndy Fleming stat2 = phy_read(phydev, mmd, MDIO_STAT2); 755f184715SAndy Fleming if (stat2 < 0 || 765f184715SAndy Fleming (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) 775f184715SAndy Fleming continue; 785f184715SAndy Fleming 795f184715SAndy Fleming /* It should tell us about all the other MMDs */ 805f184715SAndy Fleming devs1 = phy_read(phydev, mmd, MDIO_DEVS1); 815f184715SAndy Fleming devs2 = phy_read(phydev, mmd, MDIO_DEVS2); 825f184715SAndy Fleming if (devs1 < 0 || devs2 < 0) 835f184715SAndy Fleming continue; 845f184715SAndy Fleming 855f184715SAndy Fleming phydev->mmds = devs1 | (devs2 << 16); 865f184715SAndy Fleming return 0; 875f184715SAndy Fleming } 885f184715SAndy Fleming 895f184715SAndy Fleming return 0; 905f184715SAndy Fleming } 915f184715SAndy Fleming 925f184715SAndy Fleming int gen10g_config(struct phy_device *phydev) 935f184715SAndy Fleming { 945f184715SAndy Fleming /* For now, assume 10000baseT. Fill in later */ 955f184715SAndy Fleming phydev->supported = phydev->advertising = SUPPORTED_10000baseT_Full; 965f184715SAndy Fleming 975f184715SAndy Fleming return gen10g_discover_mmds(phydev); 985f184715SAndy Fleming } 995f184715SAndy Fleming 1005f184715SAndy Fleming struct phy_driver gen10g_driver = { 1015f184715SAndy Fleming .uid = 0xffffffff, 1025f184715SAndy Fleming .mask = 0xffffffff, 1035f184715SAndy Fleming .name = "Generic 10G PHY", 1045f184715SAndy Fleming .features = 0, 1055f184715SAndy Fleming .config = gen10g_config, 1065f184715SAndy Fleming .startup = gen10g_startup, 1075f184715SAndy Fleming .shutdown = gen10g_shutdown, 1085f184715SAndy Fleming }; 109