1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <config.h>
24#include <common.h>
25#include <phy.h>
26
27#ifndef CONFIG_PHYLIB_10G
28#error The Teranetics PHY needs 10G support
29#endif
30
31int tn2020_config(struct phy_device *phydev)
32{
33 if (phydev->port == PORT_FIBRE) {
34 unsigned short restart_an = (MDIO_AN_CTRL1_RESTART |
35 MDIO_AN_CTRL1_ENABLE |
36 MDIO_AN_CTRL1_XNP);
37
38 phy_write(phydev, 30, 93, 2);
39 phy_write(phydev, MDIO_MMD_AN, MDIO_CTRL1, restart_an);
40 }
41
42 return 0;
43}
44
45int tn2020_startup(struct phy_device *phydev)
46{
47 unsigned int timeout = 5 * 1000;
48
49#define MDIO_PHYXS_LANE_READY (MDIO_PHYXS_LNSTAT_SYNC0 | \
50 MDIO_PHYXS_LNSTAT_SYNC1 | \
51 MDIO_PHYXS_LNSTAT_SYNC2 | \
52 MDIO_PHYXS_LNSTAT_SYNC3 | \
53 MDIO_PHYXS_LNSTAT_ALIGN)
54
55
56
57
58
59 while (--timeout) {
60 int reg = phy_read(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_LNSTAT);
61 if (reg < 0) {
62 printf("TN2020: Error reading from PHY at "
63 "address %u\n", phydev->addr);
64 break;
65 }
66 if ((reg & MDIO_PHYXS_LANE_READY) == MDIO_PHYXS_LANE_READY)
67 break;
68 udelay(1000);
69 }
70 if (!timeout) {
71
72
73
74
75 printf("TN2020: Timeout waiting for PHY at address %u to "
76 "align.\n", phydev->addr);
77 }
78
79 if (phydev->port != PORT_FIBRE)
80 return gen10g_startup(phydev);
81
82
83
84
85
86
87 phydev->link = 1;
88
89
90 phydev->speed = SPEED_10000;
91 phydev->duplex = DUPLEX_FULL;
92
93 return 0;
94}
95
96struct phy_driver tn2020_driver = {
97 .name = "Teranetics TN2020",
98 .uid = PHY_UID_TN2020,
99 .mask = 0xfffffff0,
100 .features = PHY_10G_FEATURES,
101 .mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
102 MDIO_DEVS_PHYXS | MDIO_DEVS_AN |
103 MDIO_DEVS_VEND1 | MDIO_DEVS_VEND2),
104 .config = &tn2020_config,
105 .startup = &tn2020_startup,
106 .shutdown = &gen10g_shutdown,
107};
108
109int phy_teranetics_init(void)
110{
111 phy_register(&tn2020_driver);
112
113 return 0;
114}
115