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