]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
9082eeac AF |
2 | /* |
3 | * Micrel PHY drivers | |
4 | * | |
9082eeac AF |
5 | * Copyright 2010-2011 Freescale Semiconductor, Inc. |
6 | * author Andy Fleming | |
62d7dba7 | 7 | * (C) 2012 NetModule AG, David Andrey, added KSZ9031 |
d397f7c4 AG |
8 | * (C) Copyright 2017 Adaptrum, Inc. |
9 | * Written by Alexandru Gagniuc <alex.g@adaptrum.com> for Adaptrum, Inc. | |
9082eeac | 10 | */ |
d678a59d | 11 | #include <common.h> |
22854bda | 12 | #include <dm.h> |
7b51b576 | 13 | #include <env.h> |
22854bda | 14 | #include <errno.h> |
8682aba7 | 15 | #include <micrel.h> |
9082eeac AF |
16 | #include <phy.h> |
17 | ||
58ec63d6 | 18 | /* |
62d7dba7 DA |
19 | * KSZ9021 - KSZ9031 common |
20 | */ | |
21 | ||
22 | #define MII_KSZ90xx_PHY_CTL 0x1f | |
23 | #define MIIM_KSZ90xx_PHYCTL_1000 (1 << 6) | |
24 | #define MIIM_KSZ90xx_PHYCTL_100 (1 << 5) | |
25 | #define MIIM_KSZ90xx_PHYCTL_10 (1 << 4) | |
26 | #define MIIM_KSZ90xx_PHYCTL_DUPLEX (1 << 3) | |
27 | ||
d397f7c4 AG |
28 | /* KSZ9021 PHY Registers */ |
29 | #define MII_KSZ9021_EXTENDED_CTRL 0x0b | |
30 | #define MII_KSZ9021_EXTENDED_DATAW 0x0c | |
31 | #define MII_KSZ9021_EXTENDED_DATAR 0x0d | |
32 | ||
33 | #define CTRL1000_PREFER_MASTER (1 << 10) | |
34 | #define CTRL1000_CONFIG_MASTER (1 << 11) | |
35 | #define CTRL1000_MANUAL_CONFIG (1 << 12) | |
36 | ||
83f71ef5 JB |
37 | #define KSZ9021_PS_TO_REG 120 |
38 | ||
d397f7c4 AG |
39 | /* KSZ9031 PHY Registers */ |
40 | #define MII_KSZ9031_MMD_ACCES_CTRL 0x0d | |
41 | #define MII_KSZ9031_MMD_REG_DATA 0x0e | |
42 | ||
83f71ef5 JB |
43 | #define KSZ9031_PS_TO_REG 60 |
44 | ||
62d7dba7 DA |
45 | static int ksz90xx_startup(struct phy_device *phydev) |
46 | { | |
47 | unsigned phy_ctl; | |
b733c278 MS |
48 | int ret; |
49 | ||
50 | ret = genphy_update_link(phydev); | |
51 | if (ret) | |
52 | return ret; | |
53 | ||
62d7dba7 DA |
54 | phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL); |
55 | ||
56 | if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX) | |
57 | phydev->duplex = DUPLEX_FULL; | |
58 | else | |
59 | phydev->duplex = DUPLEX_HALF; | |
60 | ||
61 | if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000) | |
62 | phydev->speed = SPEED_1000; | |
63 | else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100) | |
64 | phydev->speed = SPEED_100; | |
65 | else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10) | |
66 | phydev->speed = SPEED_10; | |
67 | return 0; | |
68 | } | |
62d7dba7 | 69 | |
22854bda | 70 | /* Common OF config bits for KSZ9021 and KSZ9031 */ |
22854bda MV |
71 | struct ksz90x1_reg_field { |
72 | const char *name; | |
73 | const u8 size; /* Size of the bitfield, in bits */ | |
74 | const u8 off; /* Offset from bit 0 */ | |
75 | const u8 dflt; /* Default value */ | |
76 | }; | |
77 | ||
78 | struct ksz90x1_ofcfg { | |
79 | const u16 reg; | |
80 | const u16 devad; | |
81 | const struct ksz90x1_reg_field *grp; | |
82 | const u16 grpsz; | |
83 | }; | |
84 | ||
85 | static const struct ksz90x1_reg_field ksz90x1_rxd_grp[] = { | |
86 | { "rxd0-skew-ps", 4, 0, 0x7 }, { "rxd1-skew-ps", 4, 4, 0x7 }, | |
87 | { "rxd2-skew-ps", 4, 8, 0x7 }, { "rxd3-skew-ps", 4, 12, 0x7 } | |
88 | }; | |
89 | ||
90 | static const struct ksz90x1_reg_field ksz90x1_txd_grp[] = { | |
91 | { "txd0-skew-ps", 4, 0, 0x7 }, { "txd1-skew-ps", 4, 4, 0x7 }, | |
92 | { "txd2-skew-ps", 4, 8, 0x7 }, { "txd3-skew-ps", 4, 12, 0x7 }, | |
93 | }; | |
94 | ||
d397f7c4 AG |
95 | static const struct ksz90x1_reg_field ksz9021_clk_grp[] = { |
96 | { "txen-skew-ps", 4, 0, 0x7 }, { "txc-skew-ps", 4, 4, 0x7 }, | |
97 | { "rxdv-skew-ps", 4, 8, 0x7 }, { "rxc-skew-ps", 4, 12, 0x7 }, | |
98 | }; | |
99 | ||
100 | static const struct ksz90x1_reg_field ksz9031_ctl_grp[] = { | |
101 | { "txen-skew-ps", 4, 0, 0x7 }, { "rxdv-skew-ps", 4, 4, 0x7 } | |
102 | }; | |
103 | ||
104 | static const struct ksz90x1_reg_field ksz9031_clk_grp[] = { | |
105 | { "rxc-skew-ps", 5, 0, 0xf }, { "txc-skew-ps", 5, 5, 0xf } | |
106 | }; | |
107 | ||
22854bda | 108 | static int ksz90x1_of_config_group(struct phy_device *phydev, |
83f71ef5 JB |
109 | struct ksz90x1_ofcfg *ofcfg, |
110 | int ps_to_regval) | |
22854bda MV |
111 | { |
112 | struct udevice *dev = phydev->dev; | |
113 | struct phy_driver *drv = phydev->drv; | |
22854bda MV |
114 | int val[4]; |
115 | int i, changed = 0, offset, max; | |
116 | u16 regval = 0; | |
6314d1c8 | 117 | ofnode node; |
22854bda MV |
118 | |
119 | if (!drv || !drv->writeext) | |
120 | return -EOPNOTSUPP; | |
121 | ||
b5f09df2 MV |
122 | node = phydev->node; |
123 | ||
124 | if (!ofnode_valid(node)) { | |
125 | /* Look for a PHY node under the Ethernet node */ | |
126 | node = dev_read_subnode(dev, "ethernet-phy"); | |
127 | } | |
128 | ||
6314d1c8 JB |
129 | if (!ofnode_valid(node)) { |
130 | /* No node found, look in the Ethernet node */ | |
131 | node = dev_ofnode(dev); | |
132 | } | |
133 | ||
22854bda | 134 | for (i = 0; i < ofcfg->grpsz; i++) { |
6314d1c8 | 135 | val[i] = ofnode_read_u32_default(node, ofcfg->grp[i].name, ~0); |
22854bda MV |
136 | offset = ofcfg->grp[i].off; |
137 | if (val[i] == -1) { | |
138 | /* Default register value for KSZ9021 */ | |
139 | regval |= ofcfg->grp[i].dflt << offset; | |
140 | } else { | |
141 | changed = 1; /* Value was changed in OF */ | |
142 | /* Calculate the register value and fix corner cases */ | |
3b4cda34 AP |
143 | max = (1 << ofcfg->grp[i].size) - 1; |
144 | if (val[i] > ps_to_regval * max) { | |
22854bda MV |
145 | regval |= max << offset; |
146 | } else { | |
147 | regval |= (val[i] / ps_to_regval) << offset; | |
148 | } | |
149 | } | |
150 | } | |
151 | ||
152 | if (!changed) | |
153 | return 0; | |
154 | ||
155 | return drv->writeext(phydev, 0, ofcfg->devad, ofcfg->reg, regval); | |
156 | } | |
22854bda MV |
157 | |
158 | static int ksz9021_of_config(struct phy_device *phydev) | |
159 | { | |
160 | struct ksz90x1_ofcfg ofcfg[] = { | |
161 | { MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0, ksz90x1_rxd_grp, 4 }, | |
162 | { MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0, ksz90x1_txd_grp, 4 }, | |
163 | { MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0, ksz9021_clk_grp, 4 }, | |
164 | }; | |
165 | int i, ret = 0; | |
166 | ||
75c056d7 | 167 | for (i = 0; i < ARRAY_SIZE(ofcfg); i++) { |
83f71ef5 JB |
168 | ret = ksz90x1_of_config_group(phydev, &ofcfg[i], |
169 | KSZ9021_PS_TO_REG); | |
22854bda MV |
170 | if (ret) |
171 | return ret; | |
75c056d7 | 172 | } |
22854bda MV |
173 | |
174 | return 0; | |
175 | } | |
d397f7c4 AG |
176 | |
177 | static int ksz9031_of_config(struct phy_device *phydev) | |
178 | { | |
179 | struct ksz90x1_ofcfg ofcfg[] = { | |
180 | { MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, 2, ksz9031_ctl_grp, 2 }, | |
181 | { MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, 2, ksz90x1_rxd_grp, 4 }, | |
182 | { MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW, 2, ksz90x1_txd_grp, 4 }, | |
183 | { MII_KSZ9031_EXT_RGMII_CLOCK_SKEW, 2, ksz9031_clk_grp, 2 }, | |
184 | }; | |
185 | int i, ret = 0; | |
186 | ||
187 | for (i = 0; i < ARRAY_SIZE(ofcfg); i++) { | |
83f71ef5 JB |
188 | ret = ksz90x1_of_config_group(phydev, &ofcfg[i], |
189 | KSZ9031_PS_TO_REG); | |
d397f7c4 AG |
190 | if (ret) |
191 | return ret; | |
192 | } | |
193 | ||
194 | return 0; | |
195 | } | |
196 | ||
197 | static int ksz9031_center_flp_timing(struct phy_device *phydev) | |
198 | { | |
199 | struct phy_driver *drv = phydev->drv; | |
200 | int ret = 0; | |
201 | ||
202 | if (!drv || !drv->writeext) | |
203 | return -EOPNOTSUPP; | |
204 | ||
205 | ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_LO, 0x1A80); | |
206 | if (ret) | |
207 | return ret; | |
208 | ||
209 | ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_HI, 0x6); | |
210 | return ret; | |
211 | } | |
212 | ||
d397f7c4 AG |
213 | /* |
214 | * KSZ9021 | |
215 | */ | |
8682aba7 TK |
216 | int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val) |
217 | { | |
218 | /* extended registers */ | |
219 | phy_write(phydev, MDIO_DEVAD_NONE, | |
d397f7c4 | 220 | MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000); |
8682aba7 | 221 | return phy_write(phydev, MDIO_DEVAD_NONE, |
d397f7c4 | 222 | MII_KSZ9021_EXTENDED_DATAW, val); |
8682aba7 TK |
223 | } |
224 | ||
225 | int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum) | |
226 | { | |
227 | /* extended registers */ | |
228 | phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum); | |
229 | return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR); | |
230 | } | |
231 | ||
9ced16fe SB |
232 | |
233 | static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr, | |
d397f7c4 | 234 | int regnum) |
9ced16fe SB |
235 | { |
236 | return ksz9021_phy_extended_read(phydev, regnum); | |
237 | } | |
238 | ||
239 | static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr, | |
d397f7c4 | 240 | int devaddr, int regnum, u16 val) |
9ced16fe SB |
241 | { |
242 | return ksz9021_phy_extended_write(phydev, regnum, val); | |
243 | } | |
244 | ||
8682aba7 TK |
245 | static int ksz9021_config(struct phy_device *phydev) |
246 | { | |
247 | unsigned ctrl1000 = 0; | |
248 | const unsigned master = CTRL1000_PREFER_MASTER | | |
d397f7c4 | 249 | CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG; |
8682aba7 | 250 | unsigned features = phydev->drv->features; |
22854bda MV |
251 | int ret; |
252 | ||
253 | ret = ksz9021_of_config(phydev); | |
254 | if (ret) | |
255 | return ret; | |
8682aba7 | 256 | |
00caae6d | 257 | if (env_get("disable_giga")) |
8682aba7 | 258 | features &= ~(SUPPORTED_1000baseT_Half | |
d397f7c4 | 259 | SUPPORTED_1000baseT_Full); |
8682aba7 TK |
260 | /* force master mode for 1000BaseT due to chip errata */ |
261 | if (features & SUPPORTED_1000baseT_Half) | |
262 | ctrl1000 |= ADVERTISE_1000HALF | master; | |
263 | if (features & SUPPORTED_1000baseT_Full) | |
264 | ctrl1000 |= ADVERTISE_1000FULL | master; | |
d397f7c4 AG |
265 | phydev->advertising = features; |
266 | phydev->supported = features; | |
8682aba7 TK |
267 | phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000); |
268 | genphy_config_aneg(phydev); | |
269 | genphy_restart_aneg(phydev); | |
270 | return 0; | |
271 | } | |
272 | ||
6b5eea75 | 273 | U_BOOT_PHY_DRIVER(ksz9021) = { |
8682aba7 TK |
274 | .name = "Micrel ksz9021", |
275 | .uid = 0x221610, | |
77b508d3 | 276 | .mask = 0xfffffe, |
8682aba7 TK |
277 | .features = PHY_GBIT_FEATURES, |
278 | .config = &ksz9021_config, | |
62d7dba7 | 279 | .startup = &ksz90xx_startup, |
8682aba7 | 280 | .shutdown = &genphy_shutdown, |
9ced16fe SB |
281 | .writeext = &ksz9021_phy_extwrite, |
282 | .readext = &ksz9021_phy_extread, | |
8682aba7 TK |
283 | }; |
284 | ||
d397f7c4 | 285 | /* |
62d7dba7 DA |
286 | * KSZ9031 |
287 | */ | |
42a7cb50 SL |
288 | int ksz9031_phy_extended_write(struct phy_device *phydev, |
289 | int devaddr, int regnum, u16 mode, u16 val) | |
290 | { | |
291 | /*select register addr for mmd*/ | |
292 | phy_write(phydev, MDIO_DEVAD_NONE, | |
293 | MII_KSZ9031_MMD_ACCES_CTRL, devaddr); | |
294 | /*select register for mmd*/ | |
295 | phy_write(phydev, MDIO_DEVAD_NONE, | |
296 | MII_KSZ9031_MMD_REG_DATA, regnum); | |
297 | /*setup mode*/ | |
298 | phy_write(phydev, MDIO_DEVAD_NONE, | |
299 | MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr)); | |
300 | /*write the value*/ | |
301 | return phy_write(phydev, MDIO_DEVAD_NONE, | |
d397f7c4 | 302 | MII_KSZ9031_MMD_REG_DATA, val); |
42a7cb50 SL |
303 | } |
304 | ||
305 | int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr, | |
306 | int regnum, u16 mode) | |
307 | { | |
308 | phy_write(phydev, MDIO_DEVAD_NONE, | |
309 | MII_KSZ9031_MMD_ACCES_CTRL, devaddr); | |
310 | phy_write(phydev, MDIO_DEVAD_NONE, | |
311 | MII_KSZ9031_MMD_REG_DATA, regnum); | |
312 | phy_write(phydev, MDIO_DEVAD_NONE, | |
313 | MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode)); | |
314 | return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA); | |
315 | } | |
316 | ||
9ced16fe SB |
317 | static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr, |
318 | int regnum) | |
319 | { | |
320 | return ksz9031_phy_extended_read(phydev, devaddr, regnum, | |
321 | MII_KSZ9031_MOD_DATA_NO_POST_INC); | |
d397f7c4 | 322 | } |
9ced16fe SB |
323 | |
324 | static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr, | |
325 | int devaddr, int regnum, u16 val) | |
326 | { | |
327 | return ksz9031_phy_extended_write(phydev, devaddr, regnum, | |
d397f7c4 AG |
328 | MII_KSZ9031_MOD_DATA_POST_INC_RW, val); |
329 | } | |
9ced16fe | 330 | |
22854bda MV |
331 | static int ksz9031_config(struct phy_device *phydev) |
332 | { | |
333 | int ret; | |
ef1f61aa | 334 | |
22854bda | 335 | ret = ksz9031_of_config(phydev); |
f018545e AC |
336 | if (ret) |
337 | return ret; | |
338 | ret = ksz9031_center_flp_timing(phydev); | |
22854bda MV |
339 | if (ret) |
340 | return ret; | |
ef1f61aa SB |
341 | |
342 | /* add an option to disable the gigabit feature of this PHY */ | |
00caae6d | 343 | if (env_get("disable_giga")) { |
ef1f61aa SB |
344 | unsigned features; |
345 | unsigned bmcr; | |
346 | ||
347 | /* disable speed 1000 in features supported by the PHY */ | |
348 | features = phydev->drv->features; | |
349 | features &= ~(SUPPORTED_1000baseT_Half | | |
350 | SUPPORTED_1000baseT_Full); | |
351 | phydev->advertising = phydev->supported = features; | |
352 | ||
353 | /* disable speed 1000 in Basic Control Register */ | |
354 | bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); | |
355 | bmcr &= ~(1 << 6); | |
356 | phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, bmcr); | |
357 | ||
358 | /* disable speed 1000 in 1000Base-T Control Register */ | |
359 | phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, 0); | |
360 | ||
361 | /* start autoneg */ | |
362 | genphy_config_aneg(phydev); | |
363 | genphy_restart_aneg(phydev); | |
364 | ||
365 | return 0; | |
366 | } | |
367 | ||
22854bda MV |
368 | return genphy_config(phydev); |
369 | } | |
9ced16fe | 370 | |
6b5eea75 | 371 | U_BOOT_PHY_DRIVER(ksz9031) = { |
62d7dba7 | 372 | .name = "Micrel ksz9031", |
0861aa8f PS |
373 | .uid = PHY_ID_KSZ9031, |
374 | .mask = MII_KSZ9x31_SILICON_REV_MASK, | |
62d7dba7 | 375 | .features = PHY_GBIT_FEATURES, |
22854bda | 376 | .config = &ksz9031_config, |
62d7dba7 DA |
377 | .startup = &ksz90xx_startup, |
378 | .shutdown = &genphy_shutdown, | |
9ced16fe SB |
379 | .writeext = &ksz9031_phy_extwrite, |
380 | .readext = &ksz9031_phy_extread, | |
62d7dba7 DA |
381 | }; |
382 | ||
c51eef59 PS |
383 | /* |
384 | * KSZ9131 | |
385 | */ | |
c6df0e2f CB |
386 | |
387 | #define KSZ9131RN_MMD_COMMON_CTRL_REG 2 | |
388 | #define KSZ9131RN_RXC_DLL_CTRL 76 | |
389 | #define KSZ9131RN_TXC_DLL_CTRL 77 | |
390 | #define KSZ9131RN_DLL_CTRL_BYPASS BIT_MASK(12) | |
391 | #define KSZ9131RN_DLL_ENABLE_DELAY 0 | |
392 | #define KSZ9131RN_DLL_DISABLE_DELAY BIT(12) | |
393 | ||
394 | static int ksz9131_config_rgmii_delay(struct phy_device *phydev) | |
395 | { | |
396 | struct phy_driver *drv = phydev->drv; | |
397 | u16 rxcdll_val, txcdll_val, val; | |
398 | int ret; | |
399 | ||
400 | switch (phydev->interface) { | |
401 | case PHY_INTERFACE_MODE_RGMII: | |
402 | rxcdll_val = KSZ9131RN_DLL_DISABLE_DELAY; | |
403 | txcdll_val = KSZ9131RN_DLL_DISABLE_DELAY; | |
404 | break; | |
405 | case PHY_INTERFACE_MODE_RGMII_ID: | |
406 | rxcdll_val = KSZ9131RN_DLL_ENABLE_DELAY; | |
407 | txcdll_val = KSZ9131RN_DLL_ENABLE_DELAY; | |
408 | break; | |
409 | case PHY_INTERFACE_MODE_RGMII_RXID: | |
410 | rxcdll_val = KSZ9131RN_DLL_ENABLE_DELAY; | |
411 | txcdll_val = KSZ9131RN_DLL_DISABLE_DELAY; | |
412 | break; | |
413 | case PHY_INTERFACE_MODE_RGMII_TXID: | |
414 | rxcdll_val = KSZ9131RN_DLL_DISABLE_DELAY; | |
415 | txcdll_val = KSZ9131RN_DLL_ENABLE_DELAY; | |
416 | break; | |
417 | default: | |
418 | return 0; | |
419 | } | |
420 | ||
421 | val = drv->readext(phydev, 0, KSZ9131RN_MMD_COMMON_CTRL_REG, | |
422 | KSZ9131RN_RXC_DLL_CTRL); | |
423 | val &= ~KSZ9131RN_DLL_CTRL_BYPASS; | |
424 | val |= rxcdll_val; | |
425 | ret = drv->writeext(phydev, 0, KSZ9131RN_MMD_COMMON_CTRL_REG, | |
426 | KSZ9131RN_RXC_DLL_CTRL, val); | |
427 | if (ret) | |
428 | return ret; | |
429 | ||
430 | val = drv->readext(phydev, 0, KSZ9131RN_MMD_COMMON_CTRL_REG, | |
431 | KSZ9131RN_TXC_DLL_CTRL); | |
432 | ||
433 | val &= ~KSZ9131RN_DLL_CTRL_BYPASS; | |
434 | val |= txcdll_val; | |
435 | ret = drv->writeext(phydev, 0, KSZ9131RN_MMD_COMMON_CTRL_REG, | |
436 | KSZ9131RN_TXC_DLL_CTRL, val); | |
437 | ||
438 | return ret; | |
439 | } | |
440 | ||
c51eef59 PS |
441 | static int ksz9131_config(struct phy_device *phydev) |
442 | { | |
c6df0e2f CB |
443 | int ret; |
444 | ||
445 | if (phy_interface_is_rgmii(phydev)) { | |
446 | ret = ksz9131_config_rgmii_delay(phydev); | |
447 | if (ret) | |
448 | return ret; | |
449 | } | |
c51eef59 PS |
450 | |
451 | /* add an option to disable the gigabit feature of this PHY */ | |
452 | if (env_get("disable_giga")) { | |
453 | unsigned features; | |
454 | unsigned bmcr; | |
455 | ||
456 | /* disable speed 1000 in features supported by the PHY */ | |
457 | features = phydev->drv->features; | |
458 | features &= ~(SUPPORTED_1000baseT_Half | | |
459 | SUPPORTED_1000baseT_Full); | |
460 | phydev->advertising = phydev->supported = features; | |
461 | ||
462 | /* disable speed 1000 in Basic Control Register */ | |
463 | bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); | |
464 | bmcr &= ~(1 << 6); | |
465 | phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, bmcr); | |
466 | ||
467 | /* disable speed 1000 in 1000Base-T Control Register */ | |
468 | phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, 0); | |
469 | ||
470 | /* start autoneg */ | |
471 | genphy_config_aneg(phydev); | |
472 | genphy_restart_aneg(phydev); | |
473 | ||
474 | return 0; | |
475 | } | |
476 | ||
477 | return genphy_config(phydev); | |
478 | } | |
479 | ||
6b5eea75 | 480 | U_BOOT_PHY_DRIVER(ksz9131) = { |
36dfddc5 | 481 | .name = "Micrel ksz9131", |
c51eef59 PS |
482 | .uid = PHY_ID_KSZ9131, |
483 | .mask = MII_KSZ9x31_SILICON_REV_MASK, | |
484 | .features = PHY_GBIT_FEATURES, | |
485 | .config = &ksz9131_config, | |
486 | .startup = &ksz90xx_startup, | |
487 | .shutdown = &genphy_shutdown, | |
488 | .writeext = &ksz9031_phy_extwrite, | |
489 | .readext = &ksz9031_phy_extread, | |
490 | }; | |
491 | ||
492 | int ksz9xx1_phy_get_id(struct phy_device *phydev) | |
493 | { | |
494 | unsigned int phyid; | |
495 | ||
496 | get_phy_id(phydev->bus, phydev->addr, MDIO_DEVAD_NONE, &phyid); | |
497 | ||
498 | return phyid; | |
499 | } |