]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
9082eeac AF |
2 | /* |
3 | * Atheros PHY drivers | |
4 | * | |
6027384a | 5 | * Copyright 2011, 2013 Freescale Semiconductor, Inc. |
9082eeac | 6 | * author Andy Fleming |
9082eeac | 7 | */ |
05b60ac5 | 8 | #include <common.h> |
9082eeac AF |
9 | #include <phy.h> |
10 | ||
ce412b79 M |
11 | #define AR803x_PHY_DEBUG_ADDR_REG 0x1d |
12 | #define AR803x_PHY_DEBUG_DATA_REG 0x1e | |
13 | ||
14 | #define AR803x_DEBUG_REG_5 0x5 | |
29602f9c | 15 | #define AR803x_RGMII_TX_CLK_DLY BIT(8) |
ce412b79 M |
16 | |
17 | #define AR803x_DEBUG_REG_0 0x0 | |
29602f9c VO |
18 | #define AR803x_RGMII_RX_CLK_DLY BIT(15) |
19 | ||
a234ae86 VO |
20 | /* CLK_25M register is at MMD 7, address 0x8016 */ |
21 | #define AR803x_CLK_25M_SEL_REG 0x8016 | |
22 | /* AR8035: Select frequency on CLK_25M pin through bits 4:3 */ | |
23 | #define AR8035_CLK_25M_FREQ_25M (0 | 0) | |
24 | #define AR8035_CLK_25M_FREQ_50M (0 | BIT(3)) | |
25 | #define AR8035_CLK_25M_FREQ_62M (BIT(4) | 0) | |
26 | #define AR8035_CLK_25M_FREQ_125M (BIT(4) | BIT(3)) | |
27 | #define AR8035_CLK_25M_MASK GENMASK(4, 3) | |
28 | ||
30e31931 MW |
29 | #define AR8021_PHY_ID 0x004dd040 |
30 | #define AR8031_PHY_ID 0x004dd074 | |
31 | #define AR8035_PHY_ID 0x004dd072 | |
32 | ||
f6ae47be | 33 | static int ar803x_debug_reg_read(struct phy_device *phydev, u16 reg) |
29602f9c | 34 | { |
f6ae47be MW |
35 | int ret; |
36 | ||
37 | ret = phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, | |
38 | reg); | |
39 | if (ret < 0) | |
40 | return ret; | |
41 | ||
42 | return phy_read(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG); | |
43 | } | |
44 | ||
45 | static int ar803x_debug_reg_mask(struct phy_device *phydev, u16 reg, | |
46 | u16 clear, u16 set) | |
47 | { | |
48 | int val; | |
49 | ||
50 | val = ar803x_debug_reg_read(phydev, reg); | |
51 | if (val < 0) | |
52 | return val; | |
53 | ||
54 | val &= 0xffff; | |
55 | val &= ~clear; | |
56 | val |= set; | |
57 | ||
58 | return phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, | |
59 | val); | |
60 | } | |
61 | ||
62 | static int ar803x_enable_rx_delay(struct phy_device *phydev, bool on) | |
63 | { | |
64 | u16 clear = 0, set = 0; | |
29602f9c | 65 | |
29602f9c | 66 | if (on) |
f6ae47be | 67 | set = AR803x_RGMII_RX_CLK_DLY; |
29602f9c | 68 | else |
f6ae47be MW |
69 | clear = AR803x_RGMII_RX_CLK_DLY; |
70 | ||
71 | return ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_0, clear, set); | |
29602f9c VO |
72 | } |
73 | ||
f6ae47be | 74 | static int ar803x_enable_tx_delay(struct phy_device *phydev, bool on) |
29602f9c | 75 | { |
f6ae47be | 76 | u16 clear = 0, set = 0; |
29602f9c | 77 | |
29602f9c | 78 | if (on) |
f6ae47be | 79 | set = AR803x_RGMII_TX_CLK_DLY; |
29602f9c | 80 | else |
f6ae47be MW |
81 | clear = AR803x_RGMII_TX_CLK_DLY; |
82 | ||
83 | return ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_5, clear, set); | |
29602f9c | 84 | } |
ce412b79 | 85 | |
9082eeac AF |
86 | static int ar8021_config(struct phy_device *phydev) |
87 | { | |
4d4e4cf7 VO |
88 | phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, |
89 | BMCR_ANENABLE | BMCR_ANRESTART); | |
90 | ||
91 | ar803x_enable_tx_delay(phydev, true); | |
9082eeac | 92 | |
e0d80964 | 93 | phydev->supported = phydev->drv->features; |
9082eeac AF |
94 | return 0; |
95 | } | |
96 | ||
ce412b79 M |
97 | static int ar8031_config(struct phy_device *phydev) |
98 | { | |
99 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || | |
29602f9c VO |
100 | phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) |
101 | ar803x_enable_tx_delay(phydev, true); | |
13114f38 VO |
102 | else |
103 | ar803x_enable_tx_delay(phydev, false); | |
ce412b79 M |
104 | |
105 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || | |
29602f9c VO |
106 | phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) |
107 | ar803x_enable_rx_delay(phydev, true); | |
13114f38 VO |
108 | else |
109 | ar803x_enable_rx_delay(phydev, false); | |
ce412b79 M |
110 | |
111 | phydev->supported = phydev->drv->features; | |
112 | ||
113 | genphy_config_aneg(phydev); | |
114 | genphy_restart_aneg(phydev); | |
115 | ||
116 | return 0; | |
117 | } | |
118 | ||
6027384a XX |
119 | static int ar8035_config(struct phy_device *phydev) |
120 | { | |
121 | int regval; | |
122 | ||
a234ae86 VO |
123 | /* Configure CLK_25M output clock at 125 MHz */ |
124 | regval = phy_read_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG); | |
125 | regval &= ~AR8035_CLK_25M_MASK; /* No surprises */ | |
126 | regval |= AR8035_CLK_25M_FREQ_125M; | |
127 | phy_write_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG, regval); | |
6027384a | 128 | |
2ec4d10b | 129 | if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || |
29602f9c VO |
130 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) |
131 | ar803x_enable_tx_delay(phydev, true); | |
13114f38 VO |
132 | else |
133 | ar803x_enable_tx_delay(phydev, false); | |
2ec4d10b AM |
134 | |
135 | if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || | |
29602f9c VO |
136 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) |
137 | ar803x_enable_rx_delay(phydev, true); | |
13114f38 VO |
138 | else |
139 | ar803x_enable_rx_delay(phydev, false); | |
2ec4d10b | 140 | |
02aa4c53 | 141 | phydev->supported = phydev->drv->features; |
6027384a | 142 | |
903d384d AW |
143 | genphy_config_aneg(phydev); |
144 | genphy_restart_aneg(phydev); | |
145 | ||
6027384a XX |
146 | return 0; |
147 | } | |
148 | ||
06370590 | 149 | static struct phy_driver AR8021_driver = { |
9082eeac | 150 | .name = "AR8021", |
30e31931 | 151 | .uid = AR8021_PHY_ID, |
f4d48f43 | 152 | .mask = 0xfffffff0, |
9082eeac AF |
153 | .features = PHY_GBIT_FEATURES, |
154 | .config = ar8021_config, | |
155 | .startup = genphy_startup, | |
156 | .shutdown = genphy_shutdown, | |
157 | }; | |
158 | ||
433a2c53 | 159 | static struct phy_driver AR8031_driver = { |
626ee1e3 | 160 | .name = "AR8031/AR8033", |
30e31931 | 161 | .uid = AR8031_PHY_ID, |
f66e3ded | 162 | .mask = 0xffffffef, |
433a2c53 | 163 | .features = PHY_GBIT_FEATURES, |
ce412b79 | 164 | .config = ar8031_config, |
433a2c53 HS |
165 | .startup = genphy_startup, |
166 | .shutdown = genphy_shutdown, | |
167 | }; | |
168 | ||
169 | static struct phy_driver AR8035_driver = { | |
6027384a | 170 | .name = "AR8035", |
30e31931 | 171 | .uid = AR8035_PHY_ID, |
f66e3ded | 172 | .mask = 0xffffffef, |
6027384a XX |
173 | .features = PHY_GBIT_FEATURES, |
174 | .config = ar8035_config, | |
175 | .startup = genphy_startup, | |
176 | .shutdown = genphy_shutdown, | |
177 | }; | |
178 | ||
9082eeac AF |
179 | int phy_atheros_init(void) |
180 | { | |
181 | phy_register(&AR8021_driver); | |
433a2c53 | 182 | phy_register(&AR8031_driver); |
6027384a | 183 | phy_register(&AR8035_driver); |
9082eeac AF |
184 | |
185 | return 0; | |
186 | } |