19082eeacSAndy Fleming /* 29082eeacSAndy Fleming * National Semiconductor PHY drivers 39082eeacSAndy Fleming * 41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 59082eeacSAndy Fleming * 69082eeacSAndy Fleming * Copyright 2010-2011 Freescale Semiconductor, Inc. 79082eeacSAndy Fleming * author Andy Fleming 89082eeacSAndy Fleming */ 99082eeacSAndy Fleming #include <phy.h> 109082eeacSAndy Fleming 1196d0b9e1SHeiko Schocher /* NatSemi DP83630 */ 1296d0b9e1SHeiko Schocher 1396d0b9e1SHeiko Schocher #define DP83630_PHY_PAGESEL_REG 0x13 1496d0b9e1SHeiko Schocher #define DP83630_PHY_PTP_COC_REG 0x14 1596d0b9e1SHeiko Schocher #define DP83630_PHY_PTP_CLKOUT_EN (1<<15) 1696d0b9e1SHeiko Schocher #define DP83630_PHY_RBR_REG 0x17 1796d0b9e1SHeiko Schocher 1896d0b9e1SHeiko Schocher static int dp83630_config(struct phy_device *phydev) 1996d0b9e1SHeiko Schocher { 2096d0b9e1SHeiko Schocher int ptp_coc_reg; 2196d0b9e1SHeiko Schocher 2296d0b9e1SHeiko Schocher phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 2396d0b9e1SHeiko Schocher phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PAGESEL_REG, 0x6); 2496d0b9e1SHeiko Schocher ptp_coc_reg = phy_read(phydev, MDIO_DEVAD_NONE, 2596d0b9e1SHeiko Schocher DP83630_PHY_PTP_COC_REG); 2696d0b9e1SHeiko Schocher ptp_coc_reg &= ~DP83630_PHY_PTP_CLKOUT_EN; 2796d0b9e1SHeiko Schocher phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PTP_COC_REG, 2896d0b9e1SHeiko Schocher ptp_coc_reg); 2996d0b9e1SHeiko Schocher phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PAGESEL_REG, 0); 3096d0b9e1SHeiko Schocher 3196d0b9e1SHeiko Schocher genphy_config_aneg(phydev); 3296d0b9e1SHeiko Schocher 3396d0b9e1SHeiko Schocher return 0; 3496d0b9e1SHeiko Schocher } 3596d0b9e1SHeiko Schocher 3696d0b9e1SHeiko Schocher static struct phy_driver DP83630_driver = { 3796d0b9e1SHeiko Schocher .name = "NatSemi DP83630", 3896d0b9e1SHeiko Schocher .uid = 0x20005ce1, 3996d0b9e1SHeiko Schocher .mask = 0xfffffff0, 4096d0b9e1SHeiko Schocher .features = PHY_BASIC_FEATURES, 4196d0b9e1SHeiko Schocher .config = &dp83630_config, 4296d0b9e1SHeiko Schocher .startup = &genphy_startup, 4396d0b9e1SHeiko Schocher .shutdown = &genphy_shutdown, 4496d0b9e1SHeiko Schocher }; 4596d0b9e1SHeiko Schocher 4696d0b9e1SHeiko Schocher 479082eeacSAndy Fleming /* DP83865 Link and Auto-Neg Status Register */ 489082eeacSAndy Fleming #define MIIM_DP83865_LANR 0x11 499082eeacSAndy Fleming #define MIIM_DP83865_SPD_MASK 0x0018 509082eeacSAndy Fleming #define MIIM_DP83865_SPD_1000 0x0010 519082eeacSAndy Fleming #define MIIM_DP83865_SPD_100 0x0008 529082eeacSAndy Fleming #define MIIM_DP83865_DPX_FULL 0x0002 539082eeacSAndy Fleming 549082eeacSAndy Fleming 559082eeacSAndy Fleming /* NatSemi DP83865 */ 56*5ea667eaSVincent BENOIT static int dp838xx_config(struct phy_device *phydev) 579082eeacSAndy Fleming { 589082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 599082eeacSAndy Fleming genphy_config_aneg(phydev); 609082eeacSAndy Fleming 619082eeacSAndy Fleming return 0; 629082eeacSAndy Fleming } 639082eeacSAndy Fleming 649082eeacSAndy Fleming static int dp83865_parse_status(struct phy_device *phydev) 659082eeacSAndy Fleming { 669082eeacSAndy Fleming int mii_reg; 679082eeacSAndy Fleming 689082eeacSAndy Fleming mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_DP83865_LANR); 699082eeacSAndy Fleming 709082eeacSAndy Fleming switch (mii_reg & MIIM_DP83865_SPD_MASK) { 719082eeacSAndy Fleming 729082eeacSAndy Fleming case MIIM_DP83865_SPD_1000: 739082eeacSAndy Fleming phydev->speed = SPEED_1000; 749082eeacSAndy Fleming break; 759082eeacSAndy Fleming 769082eeacSAndy Fleming case MIIM_DP83865_SPD_100: 779082eeacSAndy Fleming phydev->speed = SPEED_100; 789082eeacSAndy Fleming break; 799082eeacSAndy Fleming 809082eeacSAndy Fleming default: 819082eeacSAndy Fleming phydev->speed = SPEED_10; 829082eeacSAndy Fleming break; 839082eeacSAndy Fleming 849082eeacSAndy Fleming } 859082eeacSAndy Fleming 869082eeacSAndy Fleming if (mii_reg & MIIM_DP83865_DPX_FULL) 879082eeacSAndy Fleming phydev->duplex = DUPLEX_FULL; 889082eeacSAndy Fleming else 899082eeacSAndy Fleming phydev->duplex = DUPLEX_HALF; 909082eeacSAndy Fleming 919082eeacSAndy Fleming return 0; 929082eeacSAndy Fleming } 939082eeacSAndy Fleming 949082eeacSAndy Fleming static int dp83865_startup(struct phy_device *phydev) 959082eeacSAndy Fleming { 969082eeacSAndy Fleming genphy_update_link(phydev); 979082eeacSAndy Fleming dp83865_parse_status(phydev); 989082eeacSAndy Fleming 999082eeacSAndy Fleming return 0; 1009082eeacSAndy Fleming } 1019082eeacSAndy Fleming 1029082eeacSAndy Fleming 1039082eeacSAndy Fleming static struct phy_driver DP83865_driver = { 1049082eeacSAndy Fleming .name = "NatSemi DP83865", 1059082eeacSAndy Fleming .uid = 0x20005c70, 1069082eeacSAndy Fleming .mask = 0xfffffff0, 1079082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 108*5ea667eaSVincent BENOIT .config = &dp838xx_config, 1099082eeacSAndy Fleming .startup = &dp83865_startup, 1109082eeacSAndy Fleming .shutdown = &genphy_shutdown, 1119082eeacSAndy Fleming }; 1129082eeacSAndy Fleming 113*5ea667eaSVincent BENOIT /* NatSemi DP83848 */ 114*5ea667eaSVincent BENOIT static int dp83848_parse_status(struct phy_device *phydev) 115*5ea667eaSVincent BENOIT { 116*5ea667eaSVincent BENOIT int mii_reg; 117*5ea667eaSVincent BENOIT 118*5ea667eaSVincent BENOIT mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); 119*5ea667eaSVincent BENOIT 120*5ea667eaSVincent BENOIT if(mii_reg & (BMSR_100FULL | BMSR_100HALF)) { 121*5ea667eaSVincent BENOIT phydev->speed = SPEED_100; 122*5ea667eaSVincent BENOIT } else { 123*5ea667eaSVincent BENOIT phydev->speed = SPEED_10; 124*5ea667eaSVincent BENOIT } 125*5ea667eaSVincent BENOIT 126*5ea667eaSVincent BENOIT if (mii_reg & (BMSR_10FULL | BMSR_100FULL)) { 127*5ea667eaSVincent BENOIT phydev->duplex = DUPLEX_FULL; 128*5ea667eaSVincent BENOIT } else { 129*5ea667eaSVincent BENOIT phydev->duplex = DUPLEX_HALF; 130*5ea667eaSVincent BENOIT } 131*5ea667eaSVincent BENOIT 132*5ea667eaSVincent BENOIT return 0; 133*5ea667eaSVincent BENOIT } 134*5ea667eaSVincent BENOIT 135*5ea667eaSVincent BENOIT static int dp83848_startup(struct phy_device *phydev) 136*5ea667eaSVincent BENOIT { 137*5ea667eaSVincent BENOIT genphy_update_link(phydev); 138*5ea667eaSVincent BENOIT dp83848_parse_status(phydev); 139*5ea667eaSVincent BENOIT 140*5ea667eaSVincent BENOIT return 0; 141*5ea667eaSVincent BENOIT } 142*5ea667eaSVincent BENOIT 143*5ea667eaSVincent BENOIT static struct phy_driver DP83848_driver = { 144*5ea667eaSVincent BENOIT .name = "NatSemi DP83848", 145*5ea667eaSVincent BENOIT .uid = 0x20005c90, 146*5ea667eaSVincent BENOIT .mask = 0x2000ff90, 147*5ea667eaSVincent BENOIT .features = PHY_BASIC_FEATURES, 148*5ea667eaSVincent BENOIT .config = &dp838xx_config, 149*5ea667eaSVincent BENOIT .startup = &dp83848_startup, 150*5ea667eaSVincent BENOIT .shutdown = &genphy_shutdown, 151*5ea667eaSVincent BENOIT }; 152*5ea667eaSVincent BENOIT 1539082eeacSAndy Fleming int phy_natsemi_init(void) 1549082eeacSAndy Fleming { 15596d0b9e1SHeiko Schocher phy_register(&DP83630_driver); 1569082eeacSAndy Fleming phy_register(&DP83865_driver); 157*5ea667eaSVincent BENOIT phy_register(&DP83848_driver); 1589082eeacSAndy Fleming 1599082eeacSAndy Fleming return 0; 1609082eeacSAndy Fleming } 161