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