2a8b6cb9479c716dd61ff8046dd38c27729fb77d
[platform/kernel/u-boot.git] / drivers / net / phy / micrel.c
1 /*
2  * Micrel PHY drivers
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17  * MA 02111-1307 USA
18  *
19  * Copyright 2010-2011 Freescale Semiconductor, Inc.
20  * author Andy Fleming
21  * (C) 2012 NetModule AG, David Andrey, added KSZ9031
22  *
23  */
24 #include <config.h>
25 #include <common.h>
26 #include <micrel.h>
27 #include <phy.h>
28
29 static struct phy_driver KSZ804_driver = {
30         .name = "Micrel KSZ804",
31         .uid = 0x221510,
32         .mask = 0xfffff0,
33         .features = PHY_BASIC_FEATURES,
34         .config = &genphy_config,
35         .startup = &genphy_startup,
36         .shutdown = &genphy_shutdown,
37 };
38
39 #ifndef CONFIG_PHY_MICREL_KSZ9021
40 /*
41  * I can't believe Micrel used the exact same part number
42  * for the KSZ9021
43  * Shame Micrel, Shame!!!!!
44  */
45 static struct phy_driver KS8721_driver = {
46         .name = "Micrel KS8721BL",
47         .uid = 0x221610,
48         .mask = 0xfffff0,
49         .features = PHY_BASIC_FEATURES,
50         .config = &genphy_config,
51         .startup = &genphy_startup,
52         .shutdown = &genphy_shutdown,
53 };
54 #endif
55
56
57 /**
58  * KSZ9021 - KSZ9031 common
59  */
60
61 #define MII_KSZ90xx_PHY_CTL             0x1f
62 #define MIIM_KSZ90xx_PHYCTL_1000        (1 << 6)
63 #define MIIM_KSZ90xx_PHYCTL_100         (1 << 5)
64 #define MIIM_KSZ90xx_PHYCTL_10          (1 << 4)
65 #define MIIM_KSZ90xx_PHYCTL_DUPLEX      (1 << 3)
66
67 static int ksz90xx_startup(struct phy_device *phydev)
68 {
69         unsigned phy_ctl;
70         genphy_update_link(phydev);
71         phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
72
73         if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
74                 phydev->duplex = DUPLEX_FULL;
75         else
76                 phydev->duplex = DUPLEX_HALF;
77
78         if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
79                 phydev->speed = SPEED_1000;
80         else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
81                 phydev->speed = SPEED_100;
82         else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
83                 phydev->speed = SPEED_10;
84         return 0;
85 }
86 #ifdef CONFIG_PHY_MICREL_KSZ9021
87
88 /*
89  * KSZ9021
90  */
91
92 /* PHY Registers */
93 #define MII_KSZ9021_EXTENDED_CTRL       0x0b
94 #define MII_KSZ9021_EXTENDED_DATAW      0x0c
95 #define MII_KSZ9021_EXTENDED_DATAR      0x0d
96
97 #define CTRL1000_PREFER_MASTER          (1 << 10)
98 #define CTRL1000_CONFIG_MASTER          (1 << 11)
99 #define CTRL1000_MANUAL_CONFIG          (1 << 12)
100
101 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
102 {
103         /* extended registers */
104         phy_write(phydev, MDIO_DEVAD_NONE,
105                 MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
106         return phy_write(phydev, MDIO_DEVAD_NONE,
107                 MII_KSZ9021_EXTENDED_DATAW, val);
108 }
109
110 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
111 {
112         /* extended registers */
113         phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
114         return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
115 }
116
117 /* Micrel ksz9021 */
118 static int ksz9021_config(struct phy_device *phydev)
119 {
120         unsigned ctrl1000 = 0;
121         const unsigned master = CTRL1000_PREFER_MASTER |
122                         CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
123         unsigned features = phydev->drv->features;
124
125         if (getenv("disable_giga"))
126                 features &= ~(SUPPORTED_1000baseT_Half |
127                                 SUPPORTED_1000baseT_Full);
128         /* force master mode for 1000BaseT due to chip errata */
129         if (features & SUPPORTED_1000baseT_Half)
130                 ctrl1000 |= ADVERTISE_1000HALF | master;
131         if (features & SUPPORTED_1000baseT_Full)
132                 ctrl1000 |= ADVERTISE_1000FULL | master;
133         phydev->advertising = phydev->supported = features;
134         phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
135         genphy_config_aneg(phydev);
136         genphy_restart_aneg(phydev);
137         return 0;
138 }
139
140 static struct phy_driver ksz9021_driver = {
141         .name = "Micrel ksz9021",
142         .uid  = 0x221610,
143         .mask = 0xfffff0,
144         .features = PHY_GBIT_FEATURES,
145         .config = &ksz9021_config,
146         .startup = &ksz90xx_startup,
147         .shutdown = &genphy_shutdown,
148 };
149 #endif
150
151 /*
152  * KSZ9031
153  */
154 static struct phy_driver ksz9031_driver = {
155         .name = "Micrel ksz9031",
156         .uid  = 0x221620,
157         .mask = 0xfffffe,
158         .features = PHY_GBIT_FEATURES,
159         .config   = &genphy_config,
160         .startup  = &ksz90xx_startup,
161         .shutdown = &genphy_shutdown,
162 };
163
164 int phy_micrel_init(void)
165 {
166         phy_register(&KSZ804_driver);
167 #ifdef CONFIG_PHY_MICREL_KSZ9021
168         phy_register(&ksz9021_driver);
169 #else
170         phy_register(&KS8721_driver);
171 #endif
172         phy_register(&ksz9031_driver);
173         return 0;
174 }