blob: a61471f4277739737f0a5a9a8798c7bf1a43febb [file] [log] [blame]
Michael Trimarchi80ba4362022-04-12 10:31:37 -03001// SPDX-License-Identifier: GPL-2.0
2/* NXP TJA1100 BroadRReach PHY driver
3 *
4 * Copyright (C) 2022 Michael Trimarchi <michael@amarulasolutions.com>
5 * Copyright (C) 2022 Ariel D'Alessandro <ariel.dalessandro@collabora.com>
6 * Copyright (C) 2018 Marek Vasut <marex@denx.de>
7 */
8
Michael Trimarchi80ba4362022-04-12 10:31:37 -03009#include <linux/bitops.h>
10#include <linux/delay.h>
11#include <linux/iopoll.h>
12#include <phy.h>
13
14#define PHY_ID_MASK 0xfffffff0
15#define PHY_ID_TJA1100 0x0180dc40
16#define PHY_ID_TJA1101 0x0180dd00
17
18#define MII_ECTRL 17
19#define MII_ECTRL_LINK_CONTROL BIT(15)
20#define MII_ECTRL_POWER_MODE_MASK GENMASK(14, 11)
21#define MII_ECTRL_POWER_MODE_NO_CHANGE (0x0 << 11)
22#define MII_ECTRL_POWER_MODE_NORMAL (0x3 << 11)
23#define MII_ECTRL_POWER_MODE_STANDBY (0xc << 11)
24#define MII_ECTRL_CABLE_TEST BIT(5)
25#define MII_ECTRL_CONFIG_EN BIT(2)
26#define MII_ECTRL_WAKE_REQUEST BIT(0)
27
28#define MII_CFG1 18
29#define MII_CFG1_MASTER_SLAVE BIT(15)
30#define MII_CFG1_AUTO_OP BIT(14)
31#define MII_CFG1_SLEEP_CONFIRM BIT(6)
32#define MII_CFG1_LED_MODE_MASK GENMASK(5, 4)
33#define MII_CFG1_LED_MODE_LINKUP 0
34#define MII_CFG1_LED_ENABLE BIT(3)
35
36#define MII_CFG2 19
37#define MII_CFG2_SLEEP_REQUEST_TO GENMASK(1, 0)
38#define MII_CFG2_SLEEP_REQUEST_TO_16MS 0x3
39
40#define MII_INTSRC 21
41#define MII_INTSRC_LINK_FAIL BIT(10)
42#define MII_INTSRC_LINK_UP BIT(9)
43#define MII_INTSRC_MASK (MII_INTSRC_LINK_FAIL | \
44 MII_INTSRC_LINK_UP)
45#define MII_INTSRC_UV_ERR BIT(3)
46#define MII_INTSRC_TEMP_ERR BIT(1)
47
48#define MII_INTEN 22
49#define MII_INTEN_LINK_FAIL BIT(10)
50#define MII_INTEN_LINK_UP BIT(9)
51#define MII_INTEN_UV_ERR BIT(3)
52#define MII_INTEN_TEMP_ERR BIT(1)
53
54#define MII_COMMSTAT 23
55#define MII_COMMSTAT_LINK_UP BIT(15)
56#define MII_COMMSTAT_SQI_STATE GENMASK(7, 5)
57#define MII_COMMSTAT_SQI_MAX 7
58
59#define MII_GENSTAT 24
60#define MII_GENSTAT_PLL_LOCKED BIT(14)
61
62#define MII_EXTSTAT 25
63#define MII_EXTSTAT_SHORT_DETECT BIT(8)
64#define MII_EXTSTAT_OPEN_DETECT BIT(7)
65#define MII_EXTSTAT_POLARITY_DETECT BIT(6)
66
67#define MII_COMMCFG 27
68#define MII_COMMCFG_AUTO_OP BIT(15)
69
70static inline int tja11xx_set_bits(struct phy_device *phydev, u32 regnum,
71 u16 val)
72{
73 return phy_set_bits_mmd(phydev, MDIO_DEVAD_NONE, regnum, val);
74}
75
76static inline int tja11xx_clear_bits(struct phy_device *phydev, u32 regnum,
77 u16 val)
78{
79 return phy_clear_bits_mmd(phydev, MDIO_DEVAD_NONE, regnum, val);
80}
81
82static inline int tja11xx_read(struct phy_device *phydev, int regnum)
83{
84 return phy_read(phydev, MDIO_DEVAD_NONE, regnum);
85}
86
87static inline int tja11xx_modify(struct phy_device *phydev, int regnum,
88 u16 mask, u16 set)
89{
90 return phy_modify(phydev, MDIO_DEVAD_NONE, regnum, mask, set);
91}
92
93static int tja11xx_check(struct phy_device *phydev, u8 reg, u16 mask, u16 set)
94{
95 int val;
96
97 return read_poll_timeout(tja11xx_read, val, (val & mask) == set, 150,
98 30000, phydev, reg);
99}
100
101static int tja11xx_modify_check(struct phy_device *phydev, u8 reg,
102 u16 mask, u16 set)
103{
104 int ret;
105
106 ret = tja11xx_modify(phydev, reg, mask, set);
107 if (ret)
108 return ret;
109
110 return tja11xx_check(phydev, reg, mask, set);
111}
112
113static int tja11xx_enable_reg_write(struct phy_device *phydev)
114{
115 return tja11xx_set_bits(phydev, MII_ECTRL, MII_ECTRL_CONFIG_EN);
116}
117
118static int tja11xx_enable_link_control(struct phy_device *phydev)
119{
120 return tja11xx_set_bits(phydev, MII_ECTRL, MII_ECTRL_LINK_CONTROL);
121}
122
123static int tja11xx_wakeup(struct phy_device *phydev)
124{
125 int ret;
126
127 ret = tja11xx_read(phydev, MII_ECTRL);
128 if (ret < 0)
129 return ret;
130
131 switch (ret & MII_ECTRL_POWER_MODE_MASK) {
132 case MII_ECTRL_POWER_MODE_NO_CHANGE:
133 break;
134 case MII_ECTRL_POWER_MODE_NORMAL:
135 ret = tja11xx_set_bits(phydev, MII_ECTRL,
136 MII_ECTRL_WAKE_REQUEST);
137 if (ret)
138 return ret;
139
140 ret = tja11xx_clear_bits(phydev, MII_ECTRL,
141 MII_ECTRL_WAKE_REQUEST);
142 if (ret)
143 return ret;
144 break;
145 case MII_ECTRL_POWER_MODE_STANDBY:
146 ret = tja11xx_modify_check(phydev, MII_ECTRL,
147 MII_ECTRL_POWER_MODE_MASK,
148 MII_ECTRL_POWER_MODE_STANDBY);
149 if (ret)
150 return ret;
151
152 ret = tja11xx_modify(phydev, MII_ECTRL,
153 MII_ECTRL_POWER_MODE_MASK,
154 MII_ECTRL_POWER_MODE_NORMAL);
155 if (ret)
156 return ret;
157
158 ret = tja11xx_modify_check(phydev, MII_GENSTAT,
159 MII_GENSTAT_PLL_LOCKED,
160 MII_GENSTAT_PLL_LOCKED);
161 if (ret)
162 return ret;
163
164 return tja11xx_enable_link_control(phydev);
165 default:
166 break;
167 }
168
169 return 0;
170}
171
172static int tja11xx_config_init(struct phy_device *phydev)
173{
174 int ret;
175
176 ret = tja11xx_enable_reg_write(phydev);
177 if (ret)
178 return ret;
179
180 phydev->autoneg = AUTONEG_DISABLE;
181 phydev->speed = SPEED_100;
182 phydev->duplex = DUPLEX_FULL;
183
184 switch (phydev->phy_id & PHY_ID_MASK) {
185 case PHY_ID_TJA1100:
186 ret = tja11xx_modify(phydev, MII_CFG1,
187 MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_MASK |
188 MII_CFG1_LED_ENABLE,
189 MII_CFG1_AUTO_OP |
190 MII_CFG1_LED_MODE_LINKUP |
191 MII_CFG1_LED_ENABLE);
192 if (ret)
193 return ret;
194 break;
195 case PHY_ID_TJA1101:
196 ret = tja11xx_set_bits(phydev, MII_COMMCFG,
197 MII_COMMCFG_AUTO_OP);
198 if (ret)
199 return ret;
200 break;
201 default:
202 return -EINVAL;
203 }
204
205 ret = tja11xx_clear_bits(phydev, MII_CFG1, MII_CFG1_SLEEP_CONFIRM);
206 if (ret)
207 return ret;
208
209 ret = tja11xx_modify(phydev, MII_CFG2, MII_CFG2_SLEEP_REQUEST_TO,
210 MII_CFG2_SLEEP_REQUEST_TO_16MS);
211 if (ret)
212 return ret;
213
214 ret = tja11xx_wakeup(phydev);
215 if (ret < 0)
216 return ret;
217
218 /* ACK interrupts by reading the status register */
219 ret = tja11xx_read(phydev, MII_INTSRC);
220 if (ret < 0)
221 return ret;
222
223 return 0;
224}
225
226static int tja11xx_startup(struct phy_device *phydev)
227{
228 int ret;
229
230 ret = genphy_update_link(phydev);
231 if (ret)
232 return ret;
233
234 ret = tja11xx_read(phydev, MII_CFG1);
235 if (ret < 0)
236 return ret;
237
238 if (phydev->link) {
239 ret = tja11xx_read(phydev, MII_COMMSTAT);
240 if (ret < 0)
241 return ret;
242
243 if (!(ret & MII_COMMSTAT_LINK_UP))
244 phydev->link = 0;
245 }
246
247 return 0;
248}
249
Marek Vasut6297e312023-03-19 18:03:00 +0100250U_BOOT_PHY_DRIVER(tja1100) = {
Michael Trimarchi80ba4362022-04-12 10:31:37 -0300251 .name = "NXP TJA1100",
252 .uid = PHY_ID_TJA1100,
253 .mask = PHY_ID_MASK,
254 .features = PHY_BASIC_FEATURES,
255 .config = &tja11xx_config_init,
256 .startup = &tja11xx_startup,
257 .shutdown = &genphy_shutdown,
258};
259
Marek Vasut6297e312023-03-19 18:03:00 +0100260U_BOOT_PHY_DRIVER(tja1101) = {
Michael Trimarchi80ba4362022-04-12 10:31:37 -0300261 .name = "NXP TJA1101",
262 .uid = PHY_ID_TJA1101,
263 .mask = PHY_ID_MASK,
264 .features = PHY_BASIC_FEATURES,
265 .config = &tja11xx_config_init,
266 .startup = &tja11xx_startup,
267 .shutdown = &genphy_shutdown,
268};