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