blob: 5e22399af158b1c22ba9389e332cd290ecc29da9 [file] [log] [blame]
Matt Porter3bbeb792013-03-20 05:38:13 +00001/*
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
37static 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
51static 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
89static int et1011c_startup(struct phy_device *phydev)
90{
91 genphy_update_link(phydev);
92 et1011c_parse_status(phydev);
93 return 0;
94}
95
96static 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
105int phy_et1011c_init(void)
106{
107 phy_register(&et1011c_driver);
108
109 return 0;
110}