1 /* 2 * ET1011C PHY driver 3 * 4 * Derived from Linux kernel driver by Chaithrika U S 5 * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/ 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 */ 18 #include <config.h> 19 #include <phy.h> 20 21 #define ET1011C_CONFIG_REG (0x16) 22 #define ET1011C_TX_FIFO_MASK (0x3 << 12) 23 #define ET1011C_TX_FIFO_DEPTH_8 (0x0 << 12) 24 #define ET1011C_TX_FIFO_DEPTH_16 (0x1 << 12) 25 #define ET1011C_INTERFACE_MASK (0x7 << 0) 26 #define ET1011C_GMII_INTERFACE (0x2 << 0) 27 #define ET1011C_SYS_CLK_EN (0x1 << 4) 28 #define ET1011C_TX_CLK_EN (0x1 << 5) 29 30 #define ET1011C_STATUS_REG (0x1A) 31 #define ET1011C_DUPLEX_STATUS (0x1 << 7) 32 #define ET1011C_SPEED_MASK (0x3 << 8) 33 #define ET1011C_SPEED_1000 (0x2 << 8) 34 #define ET1011C_SPEED_100 (0x1 << 8) 35 #define ET1011C_SPEED_10 (0x0 << 8) 36 37 static int et1011c_config(struct phy_device *phydev) 38 { 39 int ctl = 0; 40 ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 41 if (ctl < 0) 42 return ctl; 43 ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | 44 BMCR_ANENABLE); 45 /* First clear the PHY */ 46 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl | BMCR_RESET); 47 48 return genphy_config_aneg(phydev); 49 } 50 51 static int et1011c_parse_status(struct phy_device *phydev) 52 { 53 int mii_reg; 54 int speed; 55 56 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, ET1011C_STATUS_REG); 57 58 if (mii_reg & ET1011C_DUPLEX_STATUS) 59 phydev->duplex = DUPLEX_FULL; 60 else 61 phydev->duplex = DUPLEX_HALF; 62 63 speed = mii_reg & ET1011C_SPEED_MASK; 64 switch (speed) { 65 case ET1011C_SPEED_1000: 66 phydev->speed = SPEED_1000; 67 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, ET1011C_CONFIG_REG); 68 mii_reg &= ~ET1011C_TX_FIFO_MASK; 69 phy_write(phydev, MDIO_DEVAD_NONE, ET1011C_CONFIG_REG, 70 mii_reg | 71 ET1011C_GMII_INTERFACE | 72 ET1011C_SYS_CLK_EN | 73 #ifdef CONFIG_PHY_ET1011C_TX_CLK_FIX 74 ET1011C_TX_CLK_EN | 75 #endif 76 ET1011C_TX_FIFO_DEPTH_16); 77 break; 78 case ET1011C_SPEED_100: 79 phydev->speed = SPEED_100; 80 break; 81 case ET1011C_SPEED_10: 82 phydev->speed = SPEED_10; 83 break; 84 } 85 86 return 0; 87 } 88 89 static int et1011c_startup(struct phy_device *phydev) 90 { 91 genphy_update_link(phydev); 92 et1011c_parse_status(phydev); 93 return 0; 94 } 95 96 static struct phy_driver et1011c_driver = { 97 .name = "ET1011C", 98 .uid = 0x0282f014, 99 .mask = 0xfffffff0, 100 .features = PHY_GBIT_FEATURES, 101 .config = &et1011c_config, 102 .startup = &et1011c_startup, 103 }; 104 105 int phy_et1011c_init(void) 106 { 107 phy_register(&et1011c_driver); 108 109 return 0; 110 } 111