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