blob: ad12f6d61fb27b0b132a307afc0f1606275f4893 [file] [log] [blame]
Shaohui Xie0e548d72014-12-30 18:32:04 +08001/*
2 * Aquantia PHY drivers
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 *
6 * Copyright 2014 Freescale Semiconductor, Inc.
7 */
8#include <config.h>
9#include <common.h>
10#include <phy.h>
11
12#ifndef CONFIG_PHYLIB_10G
13#error The Aquantia PHY needs 10G support
14#endif
15
16#define AQUNTIA_10G_CTL 0x20
17#define AQUNTIA_VENDOR_P1 0xc400
18
19#define AQUNTIA_SPEED_LSB_MASK 0x2000
20#define AQUNTIA_SPEED_MSB_MASK 0x40
21
22int aquantia_config(struct phy_device *phydev)
23{
24 u32 val = phy_read(phydev, MDIO_MMD_PMAPMD, MII_BMCR);
25
26 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
27 /* 1000BASE-T mode */
28 phydev->advertising = SUPPORTED_1000baseT_Full;
29 phydev->supported = phydev->advertising;
30
31 val = (val & ~AQUNTIA_SPEED_LSB_MASK) | AQUNTIA_SPEED_MSB_MASK;
32 phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, val);
33 } else if (phydev->interface == PHY_INTERFACE_MODE_XGMII) {
34 /* 10GBASE-T mode */
35 phydev->advertising = SUPPORTED_10000baseT_Full;
36 phydev->supported = phydev->advertising;
37
38 if (!(val & AQUNTIA_SPEED_LSB_MASK) ||
39 !(val & AQUNTIA_SPEED_MSB_MASK))
40 phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR,
41 AQUNTIA_SPEED_LSB_MASK |
42 AQUNTIA_SPEED_MSB_MASK);
43 } else if (phydev->interface == PHY_INTERFACE_MODE_SGMII_2500) {
44 /* 2.5GBASE-T mode */
45 phydev->advertising = SUPPORTED_1000baseT_Full;
46 phydev->supported = phydev->advertising;
47
48 phy_write(phydev, MDIO_MMD_AN, AQUNTIA_10G_CTL, 1);
49 phy_write(phydev, MDIO_MMD_AN, AQUNTIA_VENDOR_P1, 0x9440);
50 } else if (phydev->interface == PHY_INTERFACE_MODE_MII) {
51 /* 100BASE-TX mode */
52 phydev->advertising = SUPPORTED_100baseT_Full;
53 phydev->supported = phydev->advertising;
54
55 val = (val & ~AQUNTIA_SPEED_MSB_MASK) | AQUNTIA_SPEED_LSB_MASK;
56 phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, val);
57 }
58 return 0;
59}
60
61int aquantia_startup(struct phy_device *phydev)
62{
63 u32 reg, speed;
64 int i = 0;
65
66 phydev->duplex = DUPLEX_FULL;
67
68 /* if the AN is still in progress, wait till timeout. */
69 phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
70 reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
71 if (!(reg & MDIO_AN_STAT1_COMPLETE)) {
72 printf("%s Waiting for PHY auto negotiation to complete",
73 phydev->dev->name);
74 do {
75 udelay(1000);
76 reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
77 if ((i++ % 500) == 0)
78 printf(".");
79 } while (!(reg & MDIO_AN_STAT1_COMPLETE) &&
80 i < (4 * PHY_ANEG_TIMEOUT));
81
82 if (i > PHY_ANEG_TIMEOUT)
83 printf(" TIMEOUT !\n");
84 }
85
86 /* Read twice because link state is latched and a
87 * read moves the current state into the register */
88 phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
89 reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
90 if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
91 phydev->link = 0;
92 else
93 phydev->link = 1;
94
95 speed = phy_read(phydev, MDIO_MMD_PMAPMD, MII_BMCR);
96 if (speed & AQUNTIA_SPEED_MSB_MASK) {
97 if (speed & AQUNTIA_SPEED_LSB_MASK)
98 phydev->speed = SPEED_10000;
99 else
100 phydev->speed = SPEED_1000;
101 } else {
102 if (speed & AQUNTIA_SPEED_LSB_MASK)
103 phydev->speed = SPEED_100;
104 else
105 phydev->speed = SPEED_10;
106 }
107
108 return 0;
109}
110
111struct phy_driver aq1202_driver = {
112 .name = "Aquantia AQ1202",
113 .uid = 0x3a1b445,
114 .mask = 0xfffffff0,
115 .features = PHY_10G_FEATURES,
116 .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS|
117 MDIO_MMD_PHYXS | MDIO_MMD_AN |
118 MDIO_MMD_VEND1),
119 .config = &aquantia_config,
120 .startup = &aquantia_startup,
121 .shutdown = &gen10g_shutdown,
122};
123
124struct phy_driver aq2104_driver = {
125 .name = "Aquantia AQ2104",
126 .uid = 0x3a1b460,
127 .mask = 0xfffffff0,
128 .features = PHY_10G_FEATURES,
129 .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS|
130 MDIO_MMD_PHYXS | MDIO_MMD_AN |
131 MDIO_MMD_VEND1),
132 .config = &aquantia_config,
133 .startup = &aquantia_startup,
134 .shutdown = &gen10g_shutdown,
135};
136
137struct phy_driver aqr105_driver = {
138 .name = "Aquantia AQR105",
139 .uid = 0x3a1b4a2,
140 .mask = 0xfffffff0,
141 .features = PHY_10G_FEATURES,
142 .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS|
143 MDIO_MMD_PHYXS | MDIO_MMD_AN |
144 MDIO_MMD_VEND1),
145 .config = &aquantia_config,
146 .startup = &aquantia_startup,
147 .shutdown = &gen10g_shutdown,
148};
Shaohui Xief6a0e732015-11-10 19:16:33 +0800149
Mingkai Hu602e9b52016-07-01 19:03:23 +0800150struct phy_driver aqr106_driver = {
151 .name = "Aquantia AQR106",
152 .uid = 0x3a1b4d0,
153 .mask = 0xfffffff0,
154 .features = PHY_10G_FEATURES,
155 .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS|
156 MDIO_MMD_PHYXS | MDIO_MMD_AN |
157 MDIO_MMD_VEND1),
158 .config = &aquantia_config,
159 .startup = &aquantia_startup,
160 .shutdown = &gen10g_shutdown,
161};
162
163struct phy_driver aqr107_driver = {
164 .name = "Aquantia AQR107",
165 .uid = 0x3a1b4e0,
166 .mask = 0xfffffff0,
167 .features = PHY_10G_FEATURES,
168 .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS|
169 MDIO_MMD_PHYXS | MDIO_MMD_AN |
170 MDIO_MMD_VEND1),
171 .config = &aquantia_config,
172 .startup = &aquantia_startup,
173 .shutdown = &gen10g_shutdown,
174};
175
Shaohui Xief6a0e732015-11-10 19:16:33 +0800176struct phy_driver aqr405_driver = {
177 .name = "Aquantia AQR405",
178 .uid = 0x3a1b4b2,
179 .mask = 0xfffffff0,
180 .features = PHY_10G_FEATURES,
181 .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS|
182 MDIO_MMD_PHYXS | MDIO_MMD_AN |
183 MDIO_MMD_VEND1),
184 .config = &aquantia_config,
185 .startup = &aquantia_startup,
186 .shutdown = &gen10g_shutdown,
187};
188
Shaohui Xie0e548d72014-12-30 18:32:04 +0800189int phy_aquantia_init(void)
190{
191 phy_register(&aq1202_driver);
192 phy_register(&aq2104_driver);
193 phy_register(&aqr105_driver);
Mingkai Hu602e9b52016-07-01 19:03:23 +0800194 phy_register(&aqr106_driver);
195 phy_register(&aqr107_driver);
Shaohui Xief6a0e732015-11-10 19:16:33 +0800196 phy_register(&aqr405_driver);
Shaohui Xie0e548d72014-12-30 18:32:04 +0800197
198 return 0;
199}