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