Merge tag 'xilinx-for-v2020.01' of https://gitlab.denx.de/u-boot/custodians/u-boot...
[oweals/u-boot.git] / drivers / net / phy / et1011c.c
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 }