]>
Commit | Line | Data |
---|---|---|
5f184715 AF |
1 | /* |
2 | * Generic PHY Management code | |
3 | * | |
1a459660 | 4 | * SPDX-License-Identifier: GPL-2.0+ |
5f184715 AF |
5 | * |
6 | * Copyright 2011 Freescale Semiconductor, Inc. | |
7 | * author Andy Fleming | |
8 | * | |
9 | * Based loosely off of Linux's PHY Lib | |
10 | */ | |
11 | ||
12 | #include <config.h> | |
13 | #include <common.h> | |
14 | #include <miiphy.h> | |
15 | #include <phy.h> | |
16 | ||
17 | int gen10g_shutdown(struct phy_device *phydev) | |
18 | { | |
19 | return 0; | |
20 | } | |
21 | ||
22 | int gen10g_startup(struct phy_device *phydev) | |
23 | { | |
24 | int devad, reg; | |
ee8fa20f | 25 | u32 mmd_mask = phydev->mmds & MDIO_DEVS_LINK; |
5f184715 AF |
26 | |
27 | phydev->link = 1; | |
28 | ||
29 | /* For now just lie and say it's 10G all the time */ | |
30 | phydev->speed = SPEED_10000; | |
31 | phydev->duplex = DUPLEX_FULL; | |
32 | ||
ee8fa20f AF |
33 | /* |
34 | * Go through all the link-reporting devices, and make sure | |
35 | * they're all up and happy | |
36 | */ | |
5f184715 | 37 | for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) { |
ee8fa20f | 38 | if (!(mmd_mask & 1)) |
5f184715 AF |
39 | continue; |
40 | ||
41 | /* Read twice because link state is latched and a | |
42 | * read moves the current state into the register */ | |
43 | phy_read(phydev, devad, MDIO_STAT1); | |
44 | reg = phy_read(phydev, devad, MDIO_STAT1); | |
45 | if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS)) | |
46 | phydev->link = 0; | |
47 | } | |
48 | ||
49 | return 0; | |
50 | } | |
51 | ||
52 | int gen10g_discover_mmds(struct phy_device *phydev) | |
53 | { | |
54 | int mmd, stat2, devs1, devs2; | |
55 | ||
56 | /* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY | |
57 | * XS or DTE XS; give up if none is present. */ | |
58 | for (mmd = 1; mmd <= 5; mmd++) { | |
59 | /* Is this MMD present? */ | |
60 | stat2 = phy_read(phydev, mmd, MDIO_STAT2); | |
61 | if (stat2 < 0 || | |
62 | (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) | |
63 | continue; | |
64 | ||
65 | /* It should tell us about all the other MMDs */ | |
66 | devs1 = phy_read(phydev, mmd, MDIO_DEVS1); | |
67 | devs2 = phy_read(phydev, mmd, MDIO_DEVS2); | |
68 | if (devs1 < 0 || devs2 < 0) | |
69 | continue; | |
70 | ||
71 | phydev->mmds = devs1 | (devs2 << 16); | |
72 | return 0; | |
73 | } | |
74 | ||
75 | return 0; | |
76 | } | |
77 | ||
78 | int gen10g_config(struct phy_device *phydev) | |
79 | { | |
80 | /* For now, assume 10000baseT. Fill in later */ | |
81 | phydev->supported = phydev->advertising = SUPPORTED_10000baseT_Full; | |
82 | ||
83 | return gen10g_discover_mmds(phydev); | |
84 | } | |
85 | ||
86 | struct phy_driver gen10g_driver = { | |
87 | .uid = 0xffffffff, | |
88 | .mask = 0xffffffff, | |
89 | .name = "Generic 10G PHY", | |
90 | .features = 0, | |
91 | .config = gen10g_config, | |
92 | .startup = gen10g_startup, | |
93 | .shutdown = gen10g_shutdown, | |
94 | }; |