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