xref: /openbmc/u-boot/drivers/net/phy/et1011c.c (revision ea818dbb)
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