]>
Commit | Line | Data |
---|---|---|
ed6fad3e SDPP |
1 | /* |
2 | * Xilinx PCS/PMA Core phy driver | |
3 | * | |
4 | * Copyright (C) 2015 - 2016 Xilinx, Inc. | |
5 | * | |
6 | * SPDX-License-Identifier: GPL-2.0+ | |
7 | */ | |
8 | ||
9 | #include <config.h> | |
10 | #include <common.h> | |
11 | #include <phy.h> | |
12 | #include <dm.h> | |
13 | ||
14 | DECLARE_GLOBAL_DATA_PTR; | |
15 | ||
16 | #define MII_PHY_STATUS_SPD_MASK 0x0C00 | |
17 | #define MII_PHY_STATUS_FULLDUPLEX 0x1000 | |
18 | #define MII_PHY_STATUS_1000 0x0800 | |
19 | #define MII_PHY_STATUS_100 0x0400 | |
20 | #define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF | |
21 | ||
22 | /* Mask used for ID comparisons */ | |
23 | #define XILINX_PHY_ID_MASK 0xfffffff0 | |
24 | ||
25 | /* Known PHY IDs */ | |
26 | #define XILINX_PHY_ID 0x01740c00 | |
27 | ||
28 | /* struct phy_device dev_flags definitions */ | |
29 | #define XAE_PHY_TYPE_MII 0 | |
30 | #define XAE_PHY_TYPE_GMII 1 | |
31 | #define XAE_PHY_TYPE_RGMII_1_3 2 | |
32 | #define XAE_PHY_TYPE_RGMII_2_0 3 | |
33 | #define XAE_PHY_TYPE_SGMII 4 | |
34 | #define XAE_PHY_TYPE_1000BASE_X 5 | |
35 | ||
36 | static int xilinxphy_startup(struct phy_device *phydev) | |
37 | { | |
38 | int err; | |
39 | int status = 0; | |
40 | ||
41 | debug("%s\n", __func__); | |
42 | /* Update the link, but return if there | |
43 | * was an error | |
44 | */ | |
45 | err = genphy_update_link(phydev); | |
46 | if (err) | |
47 | return err; | |
48 | ||
49 | if (AUTONEG_ENABLE == phydev->autoneg) { | |
50 | status = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA); | |
51 | status = status & MII_PHY_STATUS_SPD_MASK; | |
52 | ||
53 | if (status & MII_PHY_STATUS_FULLDUPLEX) | |
54 | phydev->duplex = DUPLEX_FULL; | |
55 | else | |
56 | phydev->duplex = DUPLEX_HALF; | |
57 | ||
58 | switch (status) { | |
59 | case MII_PHY_STATUS_1000: | |
60 | phydev->speed = SPEED_1000; | |
61 | break; | |
62 | ||
63 | case MII_PHY_STATUS_100: | |
64 | phydev->speed = SPEED_100; | |
65 | break; | |
66 | ||
67 | default: | |
68 | phydev->speed = SPEED_10; | |
69 | break; | |
70 | } | |
71 | } else { | |
72 | int bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); | |
73 | ||
74 | if (bmcr < 0) | |
75 | return bmcr; | |
76 | ||
77 | if (bmcr & BMCR_FULLDPLX) | |
78 | phydev->duplex = DUPLEX_FULL; | |
79 | else | |
80 | phydev->duplex = DUPLEX_HALF; | |
81 | ||
82 | if (bmcr & BMCR_SPEED1000) | |
83 | phydev->speed = SPEED_1000; | |
84 | else if (bmcr & BMCR_SPEED100) | |
85 | phydev->speed = SPEED_100; | |
86 | else | |
87 | phydev->speed = SPEED_10; | |
88 | } | |
89 | ||
90 | /* | |
91 | * For 1000BASE-X Phy Mode the speed/duplex will always be | |
92 | * 1000Mbps/fullduplex | |
93 | */ | |
94 | if (phydev->flags == XAE_PHY_TYPE_1000BASE_X) { | |
95 | phydev->duplex = DUPLEX_FULL; | |
96 | phydev->speed = SPEED_1000; | |
97 | } | |
98 | ||
99 | return 0; | |
100 | } | |
101 | ||
102 | static int xilinxphy_of_init(struct phy_device *phydev) | |
103 | { | |
ed6fad3e SDPP |
104 | u32 phytype; |
105 | ||
106 | debug("%s\n", __func__); | |
e160f7d4 | 107 | phytype = fdtdec_get_int(gd->fdt_blob, dev_of_offset(phydev->dev), |
1e946297 | 108 | "phy-type", -1); |
ed6fad3e SDPP |
109 | if (phytype == XAE_PHY_TYPE_1000BASE_X) |
110 | phydev->flags |= XAE_PHY_TYPE_1000BASE_X; | |
111 | ||
112 | return 0; | |
113 | } | |
114 | ||
115 | static int xilinxphy_config(struct phy_device *phydev) | |
116 | { | |
117 | int temp; | |
118 | ||
119 | debug("%s\n", __func__); | |
120 | xilinxphy_of_init(phydev); | |
121 | temp = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); | |
122 | temp &= XPCSPMA_PHY_CTRL_ISOLATE_DISABLE; | |
123 | phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, temp); | |
124 | ||
125 | return 0; | |
126 | } | |
127 | ||
128 | static struct phy_driver xilinxphy_driver = { | |
129 | .uid = XILINX_PHY_ID, | |
130 | .mask = XILINX_PHY_ID_MASK, | |
131 | .name = "Xilinx PCS/PMA PHY", | |
132 | .features = PHY_GBIT_FEATURES, | |
133 | .config = &xilinxphy_config, | |
134 | .startup = &xilinxphy_startup, | |
135 | .shutdown = &genphy_shutdown, | |
136 | }; | |
137 | ||
138 | int phy_xilinx_init(void) | |
139 | { | |
140 | debug("%s\n", __func__); | |
141 | phy_register(&xilinxphy_driver); | |
142 | ||
143 | return 0; | |
144 | } |