]> git.sur5r.net Git - u-boot/blob - drivers/net/phy/micrel.c
net: phy: micrel: add support for KSZ8021RNL & KSZ8031RNL
[u-boot] / drivers / net / phy / micrel.c
1 /*
2  * Micrel PHY drivers
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  *
6  * Copyright 2010-2011 Freescale Semiconductor, Inc.
7  * author Andy Fleming
8  * (C) 2012 NetModule AG, David Andrey, added KSZ9031
9  */
10 #include <config.h>
11 #include <common.h>
12 #include <micrel.h>
13 #include <phy.h>
14
15 static struct phy_driver KSZ804_driver = {
16         .name = "Micrel KSZ804",
17         .uid = 0x221510,
18         .mask = 0xfffff0,
19         .features = PHY_BASIC_FEATURES,
20         .config = &genphy_config,
21         .startup = &genphy_startup,
22         .shutdown = &genphy_shutdown,
23 };
24
25 static struct phy_driver KSZ8031_driver = {
26         .name = "Micrel KSZ8021/KSZ8031",
27         .uid = 0x221550,
28         .mask = 0xfffff0,
29         .features = PHY_BASIC_FEATURES,
30         .config = &genphy_config,
31         .startup = &genphy_startup,
32         .shutdown = &genphy_shutdown,
33 };
34
35 static struct phy_driver KSZ8081_driver = {
36         .name = "Micrel KSZ8081",
37         .uid = 0x221560,
38         .mask = 0xfffff0,
39         .features = PHY_BASIC_FEATURES,
40         .config = &genphy_config,
41         .startup = &genphy_startup,
42         .shutdown = &genphy_shutdown,
43 };
44
45 /**
46  * KSZ8895
47  */
48
49 static unsigned short smireg_to_phy(unsigned short reg)
50 {
51         return ((reg & 0xc0) >> 3) + 0x06 + ((reg & 0x20) >> 5);
52 }
53
54 static unsigned short smireg_to_reg(unsigned short reg)
55 {
56         return reg & 0x1F;
57 }
58
59 static void ksz8895_write_smireg(struct phy_device *phydev, int smireg, int val)
60 {
61         phydev->bus->write(phydev->bus, smireg_to_phy(smireg), MDIO_DEVAD_NONE,
62                                                 smireg_to_reg(smireg), val);
63 }
64
65 #if 0
66 static int ksz8895_read_smireg(struct phy_device *phydev, int smireg)
67 {
68         return phydev->bus->read(phydev->bus, smireg_to_phy(smireg),
69                                         MDIO_DEVAD_NONE, smireg_to_reg(smireg));
70 }
71 #endif
72
73 int ksz8895_config(struct phy_device *phydev)
74 {
75         /* we are connected directly to the switch without
76          * dedicated PHY. SCONF1 == 001 */
77         phydev->link = 1;
78         phydev->duplex = DUPLEX_FULL;
79         phydev->speed = SPEED_100;
80
81         /* Force the switch to start */
82         ksz8895_write_smireg(phydev, 1, 1);
83
84         return 0;
85 }
86
87 static int ksz8895_startup(struct phy_device *phydev)
88 {
89         return 0;
90 }
91
92 static struct phy_driver ksz8895_driver = {
93         .name = "Micrel KSZ8895/KSZ8864",
94         .uid  = 0x221450,
95         .mask = 0xffffe1,
96         .features = PHY_BASIC_FEATURES,
97         .config   = &ksz8895_config,
98         .startup  = &ksz8895_startup,
99         .shutdown = &genphy_shutdown,
100 };
101
102 #ifndef CONFIG_PHY_MICREL_KSZ9021
103 /*
104  * I can't believe Micrel used the exact same part number
105  * for the KSZ9021. Shame Micrel, Shame!
106  */
107 static struct phy_driver KS8721_driver = {
108         .name = "Micrel KS8721BL",
109         .uid = 0x221610,
110         .mask = 0xfffff0,
111         .features = PHY_BASIC_FEATURES,
112         .config = &genphy_config,
113         .startup = &genphy_startup,
114         .shutdown = &genphy_shutdown,
115 };
116 #endif
117
118
119 /*
120  * KSZ9021 - KSZ9031 common
121  */
122
123 #define MII_KSZ90xx_PHY_CTL             0x1f
124 #define MIIM_KSZ90xx_PHYCTL_1000        (1 << 6)
125 #define MIIM_KSZ90xx_PHYCTL_100         (1 << 5)
126 #define MIIM_KSZ90xx_PHYCTL_10          (1 << 4)
127 #define MIIM_KSZ90xx_PHYCTL_DUPLEX      (1 << 3)
128
129 static int ksz90xx_startup(struct phy_device *phydev)
130 {
131         unsigned phy_ctl;
132         genphy_update_link(phydev);
133         phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
134
135         if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
136                 phydev->duplex = DUPLEX_FULL;
137         else
138                 phydev->duplex = DUPLEX_HALF;
139
140         if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
141                 phydev->speed = SPEED_1000;
142         else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
143                 phydev->speed = SPEED_100;
144         else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
145                 phydev->speed = SPEED_10;
146         return 0;
147 }
148
149 #ifdef CONFIG_PHY_MICREL_KSZ9021
150 /*
151  * KSZ9021
152  */
153
154 /* PHY Registers */
155 #define MII_KSZ9021_EXTENDED_CTRL       0x0b
156 #define MII_KSZ9021_EXTENDED_DATAW      0x0c
157 #define MII_KSZ9021_EXTENDED_DATAR      0x0d
158
159 #define CTRL1000_PREFER_MASTER          (1 << 10)
160 #define CTRL1000_CONFIG_MASTER          (1 << 11)
161 #define CTRL1000_MANUAL_CONFIG          (1 << 12)
162
163 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
164 {
165         /* extended registers */
166         phy_write(phydev, MDIO_DEVAD_NONE,
167                 MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
168         return phy_write(phydev, MDIO_DEVAD_NONE,
169                 MII_KSZ9021_EXTENDED_DATAW, val);
170 }
171
172 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
173 {
174         /* extended registers */
175         phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
176         return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
177 }
178
179
180 static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
181                               int regnum)
182 {
183         return ksz9021_phy_extended_read(phydev, regnum);
184 }
185
186 static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
187                                int devaddr, int regnum, u16 val)
188 {
189         return ksz9021_phy_extended_write(phydev, regnum, val);
190 }
191
192 /* Micrel ksz9021 */
193 static int ksz9021_config(struct phy_device *phydev)
194 {
195         unsigned ctrl1000 = 0;
196         const unsigned master = CTRL1000_PREFER_MASTER |
197                         CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
198         unsigned features = phydev->drv->features;
199
200         if (getenv("disable_giga"))
201                 features &= ~(SUPPORTED_1000baseT_Half |
202                                 SUPPORTED_1000baseT_Full);
203         /* force master mode for 1000BaseT due to chip errata */
204         if (features & SUPPORTED_1000baseT_Half)
205                 ctrl1000 |= ADVERTISE_1000HALF | master;
206         if (features & SUPPORTED_1000baseT_Full)
207                 ctrl1000 |= ADVERTISE_1000FULL | master;
208         phydev->advertising = phydev->supported = features;
209         phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
210         genphy_config_aneg(phydev);
211         genphy_restart_aneg(phydev);
212         return 0;
213 }
214
215 static struct phy_driver ksz9021_driver = {
216         .name = "Micrel ksz9021",
217         .uid  = 0x221610,
218         .mask = 0xfffff0,
219         .features = PHY_GBIT_FEATURES,
220         .config = &ksz9021_config,
221         .startup = &ksz90xx_startup,
222         .shutdown = &genphy_shutdown,
223         .writeext = &ksz9021_phy_extwrite,
224         .readext = &ksz9021_phy_extread,
225 };
226 #endif
227
228 /**
229  * KSZ9031
230  */
231 /* PHY Registers */
232 #define MII_KSZ9031_MMD_ACCES_CTRL      0x0d
233 #define MII_KSZ9031_MMD_REG_DATA        0x0e
234
235 /* Accessors to extended registers*/
236 int ksz9031_phy_extended_write(struct phy_device *phydev,
237                                int devaddr, int regnum, u16 mode, u16 val)
238 {
239         /*select register addr for mmd*/
240         phy_write(phydev, MDIO_DEVAD_NONE,
241                   MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
242         /*select register for mmd*/
243         phy_write(phydev, MDIO_DEVAD_NONE,
244                   MII_KSZ9031_MMD_REG_DATA, regnum);
245         /*setup mode*/
246         phy_write(phydev, MDIO_DEVAD_NONE,
247                   MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
248         /*write the value*/
249         return  phy_write(phydev, MDIO_DEVAD_NONE,
250                 MII_KSZ9031_MMD_REG_DATA, val);
251 }
252
253 int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
254                               int regnum, u16 mode)
255 {
256         phy_write(phydev, MDIO_DEVAD_NONE,
257                   MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
258         phy_write(phydev, MDIO_DEVAD_NONE,
259                   MII_KSZ9031_MMD_REG_DATA, regnum);
260         phy_write(phydev, MDIO_DEVAD_NONE,
261                   MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
262         return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
263 }
264
265 static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
266                                int regnum)
267 {
268         return ksz9031_phy_extended_read(phydev, devaddr, regnum,
269                                          MII_KSZ9031_MOD_DATA_NO_POST_INC);
270 };
271
272 static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
273                                 int devaddr, int regnum, u16 val)
274 {
275         return ksz9031_phy_extended_write(phydev, devaddr, regnum,
276                                          MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
277 };
278
279
280 static struct phy_driver ksz9031_driver = {
281         .name = "Micrel ksz9031",
282         .uid  = 0x221620,
283         .mask = 0xfffff0,
284         .features = PHY_GBIT_FEATURES,
285         .config   = &genphy_config,
286         .startup  = &ksz90xx_startup,
287         .shutdown = &genphy_shutdown,
288         .writeext = &ksz9031_phy_extwrite,
289         .readext = &ksz9031_phy_extread,
290 };
291
292 int phy_micrel_init(void)
293 {
294         phy_register(&KSZ804_driver);
295         phy_register(&KSZ8031_driver);
296         phy_register(&KSZ8081_driver);
297 #ifdef CONFIG_PHY_MICREL_KSZ9021
298         phy_register(&ksz9021_driver);
299 #else
300         phy_register(&KS8721_driver);
301 #endif
302         phy_register(&ksz9031_driver);
303         phy_register(&ksz8895_driver);
304         return 0;
305 }