1f485c8a3SMatt Porter /* 2f485c8a3SMatt Porter * ET1011C PHY driver 3f485c8a3SMatt Porter * 4f485c8a3SMatt Porter * Derived from Linux kernel driver by Chaithrika U S 5f485c8a3SMatt Porter * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/ 6f485c8a3SMatt Porter * 71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 8f485c8a3SMatt Porter */ 9f485c8a3SMatt Porter #include <config.h> 10f485c8a3SMatt Porter #include <phy.h> 11f485c8a3SMatt Porter 12f485c8a3SMatt Porter #define ET1011C_CONFIG_REG (0x16) 13f485c8a3SMatt Porter #define ET1011C_TX_FIFO_MASK (0x3 << 12) 14f485c8a3SMatt Porter #define ET1011C_TX_FIFO_DEPTH_8 (0x0 << 12) 15f485c8a3SMatt Porter #define ET1011C_TX_FIFO_DEPTH_16 (0x1 << 12) 16f485c8a3SMatt Porter #define ET1011C_INTERFACE_MASK (0x7 << 0) 17f485c8a3SMatt Porter #define ET1011C_GMII_INTERFACE (0x2 << 0) 18f485c8a3SMatt Porter #define ET1011C_SYS_CLK_EN (0x1 << 4) 19f485c8a3SMatt Porter #define ET1011C_TX_CLK_EN (0x1 << 5) 20f485c8a3SMatt Porter 21f485c8a3SMatt Porter #define ET1011C_STATUS_REG (0x1A) 22f485c8a3SMatt Porter #define ET1011C_DUPLEX_STATUS (0x1 << 7) 23f485c8a3SMatt Porter #define ET1011C_SPEED_MASK (0x3 << 8) 24f485c8a3SMatt Porter #define ET1011C_SPEED_1000 (0x2 << 8) 25f485c8a3SMatt Porter #define ET1011C_SPEED_100 (0x1 << 8) 26f485c8a3SMatt Porter #define ET1011C_SPEED_10 (0x0 << 8) 27f485c8a3SMatt Porter 28f485c8a3SMatt Porter static int et1011c_config(struct phy_device *phydev) 29f485c8a3SMatt Porter { 30f485c8a3SMatt Porter int ctl = 0; 31f485c8a3SMatt Porter ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 32f485c8a3SMatt Porter if (ctl < 0) 33f485c8a3SMatt Porter return ctl; 34f485c8a3SMatt Porter ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | 35f485c8a3SMatt Porter BMCR_ANENABLE); 36f485c8a3SMatt Porter /* First clear the PHY */ 37f485c8a3SMatt Porter phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl | BMCR_RESET); 38f485c8a3SMatt Porter 39f485c8a3SMatt Porter return genphy_config_aneg(phydev); 40f485c8a3SMatt Porter } 41f485c8a3SMatt Porter 42f485c8a3SMatt Porter static int et1011c_parse_status(struct phy_device *phydev) 43f485c8a3SMatt Porter { 44f485c8a3SMatt Porter int mii_reg; 45f485c8a3SMatt Porter int speed; 46f485c8a3SMatt Porter 47f485c8a3SMatt Porter mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, ET1011C_STATUS_REG); 48f485c8a3SMatt Porter 49f485c8a3SMatt Porter if (mii_reg & ET1011C_DUPLEX_STATUS) 50f485c8a3SMatt Porter phydev->duplex = DUPLEX_FULL; 51f485c8a3SMatt Porter else 52f485c8a3SMatt Porter phydev->duplex = DUPLEX_HALF; 53f485c8a3SMatt Porter 54f485c8a3SMatt Porter speed = mii_reg & ET1011C_SPEED_MASK; 55f485c8a3SMatt Porter switch (speed) { 56f485c8a3SMatt Porter case ET1011C_SPEED_1000: 57f485c8a3SMatt Porter phydev->speed = SPEED_1000; 58f485c8a3SMatt Porter mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, ET1011C_CONFIG_REG); 59f485c8a3SMatt Porter mii_reg &= ~ET1011C_TX_FIFO_MASK; 60f485c8a3SMatt Porter phy_write(phydev, MDIO_DEVAD_NONE, ET1011C_CONFIG_REG, 61f485c8a3SMatt Porter mii_reg | 62f485c8a3SMatt Porter ET1011C_GMII_INTERFACE | 63f485c8a3SMatt Porter ET1011C_SYS_CLK_EN | 64f485c8a3SMatt Porter #ifdef CONFIG_PHY_ET1011C_TX_CLK_FIX 65f485c8a3SMatt Porter ET1011C_TX_CLK_EN | 66f485c8a3SMatt Porter #endif 67f485c8a3SMatt Porter ET1011C_TX_FIFO_DEPTH_16); 68f485c8a3SMatt Porter break; 69f485c8a3SMatt Porter case ET1011C_SPEED_100: 70f485c8a3SMatt Porter phydev->speed = SPEED_100; 71f485c8a3SMatt Porter break; 72f485c8a3SMatt Porter case ET1011C_SPEED_10: 73f485c8a3SMatt Porter phydev->speed = SPEED_10; 74f485c8a3SMatt Porter break; 75f485c8a3SMatt Porter } 76f485c8a3SMatt Porter 77f485c8a3SMatt Porter return 0; 78f485c8a3SMatt Porter } 79f485c8a3SMatt Porter 80f485c8a3SMatt Porter static int et1011c_startup(struct phy_device *phydev) 81f485c8a3SMatt Porter { 82*b733c278SMichal Simek int ret; 83*b733c278SMichal Simek 84*b733c278SMichal Simek ret = genphy_update_link(phydev); 85*b733c278SMichal Simek if (ret) 86*b733c278SMichal Simek return ret; 87*b733c278SMichal Simek 88*b733c278SMichal Simek return et1011c_parse_status(phydev); 89f485c8a3SMatt Porter } 90f485c8a3SMatt Porter 91f485c8a3SMatt Porter static struct phy_driver et1011c_driver = { 92f485c8a3SMatt Porter .name = "ET1011C", 93f485c8a3SMatt Porter .uid = 0x0282f014, 94f485c8a3SMatt Porter .mask = 0xfffffff0, 95f485c8a3SMatt Porter .features = PHY_GBIT_FEATURES, 96f485c8a3SMatt Porter .config = &et1011c_config, 97f485c8a3SMatt Porter .startup = &et1011c_startup, 98f485c8a3SMatt Porter }; 99f485c8a3SMatt Porter 100f485c8a3SMatt Porter int phy_et1011c_init(void) 101f485c8a3SMatt Porter { 102f485c8a3SMatt Porter phy_register(&et1011c_driver); 103f485c8a3SMatt Porter 104f485c8a3SMatt Porter return 0; 105f485c8a3SMatt Porter } 106