1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Driver for the Texas Instruments DP83867 PHY |
3 | * |
4 | * Copyright (C) 2015 Texas Instruments Inc. |
5 | */ |
6 | |
7 | #include <linux/ethtool.h> |
8 | #include <linux/kernel.h> |
9 | #include <linux/mii.h> |
10 | #include <linux/module.h> |
11 | #include <linux/of.h> |
12 | #include <linux/phy.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/netdevice.h> |
15 | #include <linux/etherdevice.h> |
16 | #include <linux/bitfield.h> |
17 | #include <linux/nvmem-consumer.h> |
18 | |
19 | #include <dt-bindings/net/ti-dp83867.h> |
20 | |
21 | #define DP83867_PHY_ID 0x2000a231 |
22 | #define DP83867_DEVADDR 0x1f |
23 | |
24 | #define MII_DP83867_PHYCTRL 0x10 |
25 | #define MII_DP83867_PHYSTS 0x11 |
26 | #define MII_DP83867_MICR 0x12 |
27 | #define MII_DP83867_ISR 0x13 |
28 | #define DP83867_CFG2 0x14 |
29 | #define DP83867_LEDCR1 0x18 |
30 | #define DP83867_LEDCR2 0x19 |
31 | #define DP83867_CFG3 0x1e |
32 | #define DP83867_CTRL 0x1f |
33 | |
34 | /* Extended Registers */ |
35 | #define DP83867_FLD_THR_CFG 0x002e |
36 | #define DP83867_CFG4 0x0031 |
37 | #define DP83867_CFG4_SGMII_ANEG_MASK (BIT(5) | BIT(6)) |
38 | #define DP83867_CFG4_SGMII_ANEG_TIMER_11MS (3 << 5) |
39 | #define DP83867_CFG4_SGMII_ANEG_TIMER_800US (2 << 5) |
40 | #define DP83867_CFG4_SGMII_ANEG_TIMER_2US (1 << 5) |
41 | #define DP83867_CFG4_SGMII_ANEG_TIMER_16MS (0 << 5) |
42 | |
43 | #define DP83867_RGMIICTL 0x0032 |
44 | #define DP83867_STRAP_STS1 0x006E |
45 | #define DP83867_STRAP_STS2 0x006f |
46 | #define DP83867_RGMIIDCTL 0x0086 |
47 | #define DP83867_DSP_FFE_CFG 0x012c |
48 | #define DP83867_RXFCFG 0x0134 |
49 | #define DP83867_RXFPMD1 0x0136 |
50 | #define DP83867_RXFPMD2 0x0137 |
51 | #define DP83867_RXFPMD3 0x0138 |
52 | #define DP83867_RXFSOP1 0x0139 |
53 | #define DP83867_RXFSOP2 0x013A |
54 | #define DP83867_RXFSOP3 0x013B |
55 | #define DP83867_IO_MUX_CFG 0x0170 |
56 | #define DP83867_SGMIICTL 0x00D3 |
57 | #define DP83867_10M_SGMII_CFG 0x016F |
58 | #define DP83867_10M_SGMII_RATE_ADAPT_MASK BIT(7) |
59 | |
60 | #define DP83867_SW_RESET BIT(15) |
61 | #define DP83867_SW_RESTART BIT(14) |
62 | |
63 | /* MICR Interrupt bits */ |
64 | #define MII_DP83867_MICR_AN_ERR_INT_EN BIT(15) |
65 | #define MII_DP83867_MICR_SPEED_CHNG_INT_EN BIT(14) |
66 | #define MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN BIT(13) |
67 | #define MII_DP83867_MICR_PAGE_RXD_INT_EN BIT(12) |
68 | #define MII_DP83867_MICR_AUTONEG_COMP_INT_EN BIT(11) |
69 | #define MII_DP83867_MICR_LINK_STS_CHNG_INT_EN BIT(10) |
70 | #define MII_DP83867_MICR_FALSE_CARRIER_INT_EN BIT(8) |
71 | #define MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN BIT(4) |
72 | #define MII_DP83867_MICR_WOL_INT_EN BIT(3) |
73 | #define MII_DP83867_MICR_XGMII_ERR_INT_EN BIT(2) |
74 | #define MII_DP83867_MICR_POL_CHNG_INT_EN BIT(1) |
75 | #define MII_DP83867_MICR_JABBER_INT_EN BIT(0) |
76 | |
77 | /* RGMIICTL bits */ |
78 | #define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1) |
79 | #define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0) |
80 | |
81 | /* SGMIICTL bits */ |
82 | #define DP83867_SGMII_TYPE BIT(14) |
83 | |
84 | /* RXFCFG bits*/ |
85 | #define DP83867_WOL_MAGIC_EN BIT(0) |
86 | #define DP83867_WOL_BCAST_EN BIT(2) |
87 | #define DP83867_WOL_UCAST_EN BIT(4) |
88 | #define DP83867_WOL_SEC_EN BIT(5) |
89 | #define DP83867_WOL_ENH_MAC BIT(7) |
90 | |
91 | /* STRAP_STS1 bits */ |
92 | #define DP83867_STRAP_STS1_RESERVED BIT(11) |
93 | |
94 | /* STRAP_STS2 bits */ |
95 | #define DP83867_STRAP_STS2_CLK_SKEW_TX_MASK GENMASK(6, 4) |
96 | #define DP83867_STRAP_STS2_CLK_SKEW_TX_SHIFT 4 |
97 | #define DP83867_STRAP_STS2_CLK_SKEW_RX_MASK GENMASK(2, 0) |
98 | #define DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT 0 |
99 | #define DP83867_STRAP_STS2_CLK_SKEW_NONE BIT(2) |
100 | #define DP83867_STRAP_STS2_STRAP_FLD BIT(10) |
101 | |
102 | /* PHY CTRL bits */ |
103 | #define DP83867_PHYCR_TX_FIFO_DEPTH_SHIFT 14 |
104 | #define DP83867_PHYCR_RX_FIFO_DEPTH_SHIFT 12 |
105 | #define DP83867_PHYCR_FIFO_DEPTH_MAX 0x03 |
106 | #define DP83867_PHYCR_TX_FIFO_DEPTH_MASK GENMASK(15, 14) |
107 | #define DP83867_PHYCR_RX_FIFO_DEPTH_MASK GENMASK(13, 12) |
108 | #define DP83867_PHYCR_RESERVED_MASK BIT(11) |
109 | #define DP83867_PHYCR_FORCE_LINK_GOOD BIT(10) |
110 | |
111 | /* RGMIIDCTL bits */ |
112 | #define DP83867_RGMII_TX_CLK_DELAY_MAX 0xf |
113 | #define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4 |
114 | #define DP83867_RGMII_TX_CLK_DELAY_INV (DP83867_RGMII_TX_CLK_DELAY_MAX + 1) |
115 | #define DP83867_RGMII_RX_CLK_DELAY_MAX 0xf |
116 | #define DP83867_RGMII_RX_CLK_DELAY_SHIFT 0 |
117 | #define DP83867_RGMII_RX_CLK_DELAY_INV (DP83867_RGMII_RX_CLK_DELAY_MAX + 1) |
118 | |
119 | /* IO_MUX_CFG bits */ |
120 | #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MASK 0x1f |
121 | #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 |
122 | #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f |
123 | #define DP83867_IO_MUX_CFG_CLK_O_DISABLE BIT(6) |
124 | #define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK (0x1f << 8) |
125 | #define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8 |
126 | |
127 | /* PHY STS bits */ |
128 | #define DP83867_PHYSTS_1000 BIT(15) |
129 | #define DP83867_PHYSTS_100 BIT(14) |
130 | #define DP83867_PHYSTS_DUPLEX BIT(13) |
131 | #define DP83867_PHYSTS_LINK BIT(10) |
132 | |
133 | /* CFG2 bits */ |
134 | #define DP83867_DOWNSHIFT_EN (BIT(8) | BIT(9)) |
135 | #define DP83867_DOWNSHIFT_ATTEMPT_MASK (BIT(10) | BIT(11)) |
136 | #define DP83867_DOWNSHIFT_1_COUNT_VAL 0 |
137 | #define DP83867_DOWNSHIFT_2_COUNT_VAL 1 |
138 | #define DP83867_DOWNSHIFT_4_COUNT_VAL 2 |
139 | #define DP83867_DOWNSHIFT_8_COUNT_VAL 3 |
140 | #define DP83867_DOWNSHIFT_1_COUNT 1 |
141 | #define DP83867_DOWNSHIFT_2_COUNT 2 |
142 | #define DP83867_DOWNSHIFT_4_COUNT 4 |
143 | #define DP83867_DOWNSHIFT_8_COUNT 8 |
144 | #define DP83867_SGMII_AUTONEG_EN BIT(7) |
145 | |
146 | /* CFG3 bits */ |
147 | #define DP83867_CFG3_INT_OE BIT(7) |
148 | #define DP83867_CFG3_ROBUST_AUTO_MDIX BIT(9) |
149 | |
150 | /* CFG4 bits */ |
151 | #define DP83867_CFG4_PORT_MIRROR_EN BIT(0) |
152 | |
153 | /* FLD_THR_CFG */ |
154 | #define DP83867_FLD_THR_CFG_ENERGY_LOST_THR_MASK 0x7 |
155 | |
156 | #define DP83867_LED_COUNT 4 |
157 | |
158 | /* LED_DRV bits */ |
159 | #define DP83867_LED_DRV_EN(x) BIT((x) * 4) |
160 | #define DP83867_LED_DRV_VAL(x) BIT((x) * 4 + 1) |
161 | |
162 | #define DP83867_LED_FN(idx, val) (((val) & 0xf) << ((idx) * 4)) |
163 | #define DP83867_LED_FN_MASK(idx) (0xf << ((idx) * 4)) |
164 | #define DP83867_LED_FN_RX_ERR 0xe /* Receive Error */ |
165 | #define DP83867_LED_FN_RX_TX_ERR 0xd /* Receive Error or Transmit Error */ |
166 | #define DP83867_LED_FN_LINK_RX_TX 0xb /* Link established, blink for rx or tx activity */ |
167 | #define DP83867_LED_FN_FULL_DUPLEX 0xa /* Full duplex */ |
168 | #define DP83867_LED_FN_LINK_100_1000_BT 0x9 /* 100/1000BT link established */ |
169 | #define DP83867_LED_FN_LINK_10_100_BT 0x8 /* 10/100BT link established */ |
170 | #define DP83867_LED_FN_LINK_10_BT 0x7 /* 10BT link established */ |
171 | #define DP83867_LED_FN_LINK_100_BTX 0x6 /* 100 BTX link established */ |
172 | #define DP83867_LED_FN_LINK_1000_BT 0x5 /* 1000 BT link established */ |
173 | #define DP83867_LED_FN_COLLISION 0x4 /* Collision detected */ |
174 | #define DP83867_LED_FN_RX 0x3 /* Receive activity */ |
175 | #define DP83867_LED_FN_TX 0x2 /* Transmit activity */ |
176 | #define DP83867_LED_FN_RX_TX 0x1 /* Receive or Transmit activity */ |
177 | #define DP83867_LED_FN_LINK 0x0 /* Link established */ |
178 | |
179 | enum { |
180 | DP83867_PORT_MIRROING_KEEP, |
181 | DP83867_PORT_MIRROING_EN, |
182 | DP83867_PORT_MIRROING_DIS, |
183 | }; |
184 | |
185 | struct dp83867_private { |
186 | u32 rx_id_delay; |
187 | u32 tx_id_delay; |
188 | u32 tx_fifo_depth; |
189 | u32 rx_fifo_depth; |
190 | int io_impedance; |
191 | int port_mirroring; |
192 | bool rxctrl_strap_quirk; |
193 | bool set_clk_output; |
194 | u32 clk_output_sel; |
195 | bool sgmii_ref_clk_en; |
196 | }; |
197 | |
198 | static int dp83867_ack_interrupt(struct phy_device *phydev) |
199 | { |
200 | int err = phy_read(phydev, MII_DP83867_ISR); |
201 | |
202 | if (err < 0) |
203 | return err; |
204 | |
205 | return 0; |
206 | } |
207 | |
208 | static int dp83867_set_wol(struct phy_device *phydev, |
209 | struct ethtool_wolinfo *wol) |
210 | { |
211 | struct net_device *ndev = phydev->attached_dev; |
212 | u16 val_rxcfg, val_micr; |
213 | const u8 *mac; |
214 | |
215 | val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG); |
216 | val_micr = phy_read(phydev, MII_DP83867_MICR); |
217 | |
218 | if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST | |
219 | WAKE_BCAST)) { |
220 | val_rxcfg |= DP83867_WOL_ENH_MAC; |
221 | val_micr |= MII_DP83867_MICR_WOL_INT_EN; |
222 | |
223 | if (wol->wolopts & WAKE_MAGIC) { |
224 | mac = (const u8 *)ndev->dev_addr; |
225 | |
226 | if (!is_valid_ether_addr(addr: mac)) |
227 | return -EINVAL; |
228 | |
229 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD1, |
230 | val: (mac[1] << 8 | mac[0])); |
231 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD2, |
232 | val: (mac[3] << 8 | mac[2])); |
233 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD3, |
234 | val: (mac[5] << 8 | mac[4])); |
235 | |
236 | val_rxcfg |= DP83867_WOL_MAGIC_EN; |
237 | } else { |
238 | val_rxcfg &= ~DP83867_WOL_MAGIC_EN; |
239 | } |
240 | |
241 | if (wol->wolopts & WAKE_MAGICSECURE) { |
242 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1, |
243 | val: (wol->sopass[1] << 8) | wol->sopass[0]); |
244 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP2, |
245 | val: (wol->sopass[3] << 8) | wol->sopass[2]); |
246 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP3, |
247 | val: (wol->sopass[5] << 8) | wol->sopass[4]); |
248 | |
249 | val_rxcfg |= DP83867_WOL_SEC_EN; |
250 | } else { |
251 | val_rxcfg &= ~DP83867_WOL_SEC_EN; |
252 | } |
253 | |
254 | if (wol->wolopts & WAKE_UCAST) |
255 | val_rxcfg |= DP83867_WOL_UCAST_EN; |
256 | else |
257 | val_rxcfg &= ~DP83867_WOL_UCAST_EN; |
258 | |
259 | if (wol->wolopts & WAKE_BCAST) |
260 | val_rxcfg |= DP83867_WOL_BCAST_EN; |
261 | else |
262 | val_rxcfg &= ~DP83867_WOL_BCAST_EN; |
263 | } else { |
264 | val_rxcfg &= ~DP83867_WOL_ENH_MAC; |
265 | val_micr &= ~MII_DP83867_MICR_WOL_INT_EN; |
266 | } |
267 | |
268 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG, val: val_rxcfg); |
269 | phy_write(phydev, MII_DP83867_MICR, val: val_micr); |
270 | |
271 | return 0; |
272 | } |
273 | |
274 | static void dp83867_get_wol(struct phy_device *phydev, |
275 | struct ethtool_wolinfo *wol) |
276 | { |
277 | u16 value, sopass_val; |
278 | |
279 | wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC | |
280 | WAKE_MAGICSECURE); |
281 | wol->wolopts = 0; |
282 | |
283 | value = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG); |
284 | |
285 | if (value & DP83867_WOL_UCAST_EN) |
286 | wol->wolopts |= WAKE_UCAST; |
287 | |
288 | if (value & DP83867_WOL_BCAST_EN) |
289 | wol->wolopts |= WAKE_BCAST; |
290 | |
291 | if (value & DP83867_WOL_MAGIC_EN) |
292 | wol->wolopts |= WAKE_MAGIC; |
293 | |
294 | if (value & DP83867_WOL_SEC_EN) { |
295 | sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR, |
296 | DP83867_RXFSOP1); |
297 | wol->sopass[0] = (sopass_val & 0xff); |
298 | wol->sopass[1] = (sopass_val >> 8); |
299 | |
300 | sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR, |
301 | DP83867_RXFSOP2); |
302 | wol->sopass[2] = (sopass_val & 0xff); |
303 | wol->sopass[3] = (sopass_val >> 8); |
304 | |
305 | sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR, |
306 | DP83867_RXFSOP3); |
307 | wol->sopass[4] = (sopass_val & 0xff); |
308 | wol->sopass[5] = (sopass_val >> 8); |
309 | |
310 | wol->wolopts |= WAKE_MAGICSECURE; |
311 | } |
312 | |
313 | if (!(value & DP83867_WOL_ENH_MAC)) |
314 | wol->wolopts = 0; |
315 | } |
316 | |
317 | static int dp83867_config_intr(struct phy_device *phydev) |
318 | { |
319 | int micr_status, err; |
320 | |
321 | if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { |
322 | err = dp83867_ack_interrupt(phydev); |
323 | if (err) |
324 | return err; |
325 | |
326 | micr_status = phy_read(phydev, MII_DP83867_MICR); |
327 | if (micr_status < 0) |
328 | return micr_status; |
329 | |
330 | micr_status |= |
331 | (MII_DP83867_MICR_AN_ERR_INT_EN | |
332 | MII_DP83867_MICR_SPEED_CHNG_INT_EN | |
333 | MII_DP83867_MICR_AUTONEG_COMP_INT_EN | |
334 | MII_DP83867_MICR_LINK_STS_CHNG_INT_EN | |
335 | MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN | |
336 | MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN); |
337 | |
338 | err = phy_write(phydev, MII_DP83867_MICR, val: micr_status); |
339 | } else { |
340 | micr_status = 0x0; |
341 | err = phy_write(phydev, MII_DP83867_MICR, val: micr_status); |
342 | if (err) |
343 | return err; |
344 | |
345 | err = dp83867_ack_interrupt(phydev); |
346 | } |
347 | |
348 | return err; |
349 | } |
350 | |
351 | static irqreturn_t dp83867_handle_interrupt(struct phy_device *phydev) |
352 | { |
353 | int irq_status, irq_enabled; |
354 | |
355 | irq_status = phy_read(phydev, MII_DP83867_ISR); |
356 | if (irq_status < 0) { |
357 | phy_error(phydev); |
358 | return IRQ_NONE; |
359 | } |
360 | |
361 | irq_enabled = phy_read(phydev, MII_DP83867_MICR); |
362 | if (irq_enabled < 0) { |
363 | phy_error(phydev); |
364 | return IRQ_NONE; |
365 | } |
366 | |
367 | if (!(irq_status & irq_enabled)) |
368 | return IRQ_NONE; |
369 | |
370 | phy_trigger_machine(phydev); |
371 | |
372 | return IRQ_HANDLED; |
373 | } |
374 | |
375 | static int dp83867_read_status(struct phy_device *phydev) |
376 | { |
377 | int status = phy_read(phydev, MII_DP83867_PHYSTS); |
378 | int ret; |
379 | |
380 | ret = genphy_read_status(phydev); |
381 | if (ret) |
382 | return ret; |
383 | |
384 | if (status < 0) |
385 | return status; |
386 | |
387 | if (status & DP83867_PHYSTS_DUPLEX) |
388 | phydev->duplex = DUPLEX_FULL; |
389 | else |
390 | phydev->duplex = DUPLEX_HALF; |
391 | |
392 | if (status & DP83867_PHYSTS_1000) |
393 | phydev->speed = SPEED_1000; |
394 | else if (status & DP83867_PHYSTS_100) |
395 | phydev->speed = SPEED_100; |
396 | else |
397 | phydev->speed = SPEED_10; |
398 | |
399 | return 0; |
400 | } |
401 | |
402 | static int dp83867_get_downshift(struct phy_device *phydev, u8 *data) |
403 | { |
404 | int val, cnt, enable, count; |
405 | |
406 | val = phy_read(phydev, DP83867_CFG2); |
407 | if (val < 0) |
408 | return val; |
409 | |
410 | enable = FIELD_GET(DP83867_DOWNSHIFT_EN, val); |
411 | cnt = FIELD_GET(DP83867_DOWNSHIFT_ATTEMPT_MASK, val); |
412 | |
413 | switch (cnt) { |
414 | case DP83867_DOWNSHIFT_1_COUNT_VAL: |
415 | count = DP83867_DOWNSHIFT_1_COUNT; |
416 | break; |
417 | case DP83867_DOWNSHIFT_2_COUNT_VAL: |
418 | count = DP83867_DOWNSHIFT_2_COUNT; |
419 | break; |
420 | case DP83867_DOWNSHIFT_4_COUNT_VAL: |
421 | count = DP83867_DOWNSHIFT_4_COUNT; |
422 | break; |
423 | case DP83867_DOWNSHIFT_8_COUNT_VAL: |
424 | count = DP83867_DOWNSHIFT_8_COUNT; |
425 | break; |
426 | default: |
427 | return -EINVAL; |
428 | } |
429 | |
430 | *data = enable ? count : DOWNSHIFT_DEV_DISABLE; |
431 | |
432 | return 0; |
433 | } |
434 | |
435 | static int dp83867_set_downshift(struct phy_device *phydev, u8 cnt) |
436 | { |
437 | int val, count; |
438 | |
439 | if (cnt > DP83867_DOWNSHIFT_8_COUNT) |
440 | return -E2BIG; |
441 | |
442 | if (!cnt) |
443 | return phy_clear_bits(phydev, DP83867_CFG2, |
444 | DP83867_DOWNSHIFT_EN); |
445 | |
446 | switch (cnt) { |
447 | case DP83867_DOWNSHIFT_1_COUNT: |
448 | count = DP83867_DOWNSHIFT_1_COUNT_VAL; |
449 | break; |
450 | case DP83867_DOWNSHIFT_2_COUNT: |
451 | count = DP83867_DOWNSHIFT_2_COUNT_VAL; |
452 | break; |
453 | case DP83867_DOWNSHIFT_4_COUNT: |
454 | count = DP83867_DOWNSHIFT_4_COUNT_VAL; |
455 | break; |
456 | case DP83867_DOWNSHIFT_8_COUNT: |
457 | count = DP83867_DOWNSHIFT_8_COUNT_VAL; |
458 | break; |
459 | default: |
460 | phydev_err(phydev, |
461 | "Downshift count must be 1, 2, 4 or 8\n" ); |
462 | return -EINVAL; |
463 | } |
464 | |
465 | val = DP83867_DOWNSHIFT_EN; |
466 | val |= FIELD_PREP(DP83867_DOWNSHIFT_ATTEMPT_MASK, count); |
467 | |
468 | return phy_modify(phydev, DP83867_CFG2, |
469 | DP83867_DOWNSHIFT_EN | DP83867_DOWNSHIFT_ATTEMPT_MASK, |
470 | set: val); |
471 | } |
472 | |
473 | static int dp83867_get_tunable(struct phy_device *phydev, |
474 | struct ethtool_tunable *tuna, void *data) |
475 | { |
476 | switch (tuna->id) { |
477 | case ETHTOOL_PHY_DOWNSHIFT: |
478 | return dp83867_get_downshift(phydev, data); |
479 | default: |
480 | return -EOPNOTSUPP; |
481 | } |
482 | } |
483 | |
484 | static int dp83867_set_tunable(struct phy_device *phydev, |
485 | struct ethtool_tunable *tuna, const void *data) |
486 | { |
487 | switch (tuna->id) { |
488 | case ETHTOOL_PHY_DOWNSHIFT: |
489 | return dp83867_set_downshift(phydev, cnt: *(const u8 *)data); |
490 | default: |
491 | return -EOPNOTSUPP; |
492 | } |
493 | } |
494 | |
495 | static int dp83867_config_port_mirroring(struct phy_device *phydev) |
496 | { |
497 | struct dp83867_private *dp83867 = phydev->priv; |
498 | |
499 | if (dp83867->port_mirroring == DP83867_PORT_MIRROING_EN) |
500 | phy_set_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, |
501 | DP83867_CFG4_PORT_MIRROR_EN); |
502 | else |
503 | phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, |
504 | DP83867_CFG4_PORT_MIRROR_EN); |
505 | return 0; |
506 | } |
507 | |
508 | static int dp83867_verify_rgmii_cfg(struct phy_device *phydev) |
509 | { |
510 | struct dp83867_private *dp83867 = phydev->priv; |
511 | |
512 | /* Existing behavior was to use default pin strapping delay in rgmii |
513 | * mode, but rgmii should have meant no delay. Warn existing users. |
514 | */ |
515 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { |
516 | const u16 val = phy_read_mmd(phydev, DP83867_DEVADDR, |
517 | DP83867_STRAP_STS2); |
518 | const u16 txskew = (val & DP83867_STRAP_STS2_CLK_SKEW_TX_MASK) >> |
519 | DP83867_STRAP_STS2_CLK_SKEW_TX_SHIFT; |
520 | const u16 rxskew = (val & DP83867_STRAP_STS2_CLK_SKEW_RX_MASK) >> |
521 | DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT; |
522 | |
523 | if (txskew != DP83867_STRAP_STS2_CLK_SKEW_NONE || |
524 | rxskew != DP83867_STRAP_STS2_CLK_SKEW_NONE) |
525 | phydev_warn(phydev, |
526 | "PHY has delays via pin strapping, but phy-mode = 'rgmii'\n" |
527 | "Should be 'rgmii-id' to use internal delays txskew:%x rxskew:%x\n" , |
528 | txskew, rxskew); |
529 | } |
530 | |
531 | /* RX delay *must* be specified if internal delay of RX is used. */ |
532 | if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || |
533 | phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) && |
534 | dp83867->rx_id_delay == DP83867_RGMII_RX_CLK_DELAY_INV) { |
535 | phydev_err(phydev, "ti,rx-internal-delay must be specified\n" ); |
536 | return -EINVAL; |
537 | } |
538 | |
539 | /* TX delay *must* be specified if internal delay of TX is used. */ |
540 | if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || |
541 | phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) && |
542 | dp83867->tx_id_delay == DP83867_RGMII_TX_CLK_DELAY_INV) { |
543 | phydev_err(phydev, "ti,tx-internal-delay must be specified\n" ); |
544 | return -EINVAL; |
545 | } |
546 | |
547 | return 0; |
548 | } |
549 | |
550 | #if IS_ENABLED(CONFIG_OF_MDIO) |
551 | static int dp83867_of_init_io_impedance(struct phy_device *phydev) |
552 | { |
553 | struct dp83867_private *dp83867 = phydev->priv; |
554 | struct device *dev = &phydev->mdio.dev; |
555 | struct device_node *of_node = dev->of_node; |
556 | struct nvmem_cell *cell; |
557 | u8 *buf, val; |
558 | int ret; |
559 | |
560 | cell = of_nvmem_cell_get(np: of_node, id: "io_impedance_ctrl" ); |
561 | if (IS_ERR(ptr: cell)) { |
562 | ret = PTR_ERR(ptr: cell); |
563 | if (ret != -ENOENT && ret != -EOPNOTSUPP) |
564 | return phydev_err_probe(phydev, ret, |
565 | "failed to get nvmem cell io_impedance_ctrl\n" ); |
566 | |
567 | /* If no nvmem cell, check for the boolean properties. */ |
568 | if (of_property_read_bool(np: of_node, propname: "ti,max-output-impedance" )) |
569 | dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX; |
570 | else if (of_property_read_bool(np: of_node, propname: "ti,min-output-impedance" )) |
571 | dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN; |
572 | else |
573 | dp83867->io_impedance = -1; /* leave at default */ |
574 | |
575 | return 0; |
576 | } |
577 | |
578 | buf = nvmem_cell_read(cell, NULL); |
579 | nvmem_cell_put(cell); |
580 | |
581 | if (IS_ERR(ptr: buf)) |
582 | return PTR_ERR(ptr: buf); |
583 | |
584 | val = *buf; |
585 | kfree(objp: buf); |
586 | |
587 | if ((val & DP83867_IO_MUX_CFG_IO_IMPEDANCE_MASK) != val) { |
588 | phydev_err(phydev, "nvmem cell 'io_impedance_ctrl' contents out of range\n" ); |
589 | return -ERANGE; |
590 | } |
591 | dp83867->io_impedance = val; |
592 | |
593 | return 0; |
594 | } |
595 | |
596 | static int dp83867_of_init(struct phy_device *phydev) |
597 | { |
598 | struct dp83867_private *dp83867 = phydev->priv; |
599 | struct device *dev = &phydev->mdio.dev; |
600 | struct device_node *of_node = dev->of_node; |
601 | int ret; |
602 | |
603 | if (!of_node) |
604 | return -ENODEV; |
605 | |
606 | /* Optional configuration */ |
607 | ret = of_property_read_u32(np: of_node, propname: "ti,clk-output-sel" , |
608 | out_value: &dp83867->clk_output_sel); |
609 | /* If not set, keep default */ |
610 | if (!ret) { |
611 | dp83867->set_clk_output = true; |
612 | /* Valid values are 0 to DP83867_CLK_O_SEL_REF_CLK or |
613 | * DP83867_CLK_O_SEL_OFF. |
614 | */ |
615 | if (dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK && |
616 | dp83867->clk_output_sel != DP83867_CLK_O_SEL_OFF) { |
617 | phydev_err(phydev, "ti,clk-output-sel value %u out of range\n" , |
618 | dp83867->clk_output_sel); |
619 | return -EINVAL; |
620 | } |
621 | } |
622 | |
623 | ret = dp83867_of_init_io_impedance(phydev); |
624 | if (ret) |
625 | return ret; |
626 | |
627 | dp83867->rxctrl_strap_quirk = of_property_read_bool(np: of_node, |
628 | propname: "ti,dp83867-rxctrl-strap-quirk" ); |
629 | |
630 | dp83867->sgmii_ref_clk_en = of_property_read_bool(np: of_node, |
631 | propname: "ti,sgmii-ref-clock-output-enable" ); |
632 | |
633 | dp83867->rx_id_delay = DP83867_RGMII_RX_CLK_DELAY_INV; |
634 | ret = of_property_read_u32(np: of_node, propname: "ti,rx-internal-delay" , |
635 | out_value: &dp83867->rx_id_delay); |
636 | if (!ret && dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) { |
637 | phydev_err(phydev, |
638 | "ti,rx-internal-delay value of %u out of range\n" , |
639 | dp83867->rx_id_delay); |
640 | return -EINVAL; |
641 | } |
642 | |
643 | dp83867->tx_id_delay = DP83867_RGMII_TX_CLK_DELAY_INV; |
644 | ret = of_property_read_u32(np: of_node, propname: "ti,tx-internal-delay" , |
645 | out_value: &dp83867->tx_id_delay); |
646 | if (!ret && dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) { |
647 | phydev_err(phydev, |
648 | "ti,tx-internal-delay value of %u out of range\n" , |
649 | dp83867->tx_id_delay); |
650 | return -EINVAL; |
651 | } |
652 | |
653 | if (of_property_read_bool(np: of_node, propname: "enet-phy-lane-swap" )) |
654 | dp83867->port_mirroring = DP83867_PORT_MIRROING_EN; |
655 | |
656 | if (of_property_read_bool(np: of_node, propname: "enet-phy-lane-no-swap" )) |
657 | dp83867->port_mirroring = DP83867_PORT_MIRROING_DIS; |
658 | |
659 | ret = of_property_read_u32(np: of_node, propname: "ti,fifo-depth" , |
660 | out_value: &dp83867->tx_fifo_depth); |
661 | if (ret) { |
662 | ret = of_property_read_u32(np: of_node, propname: "tx-fifo-depth" , |
663 | out_value: &dp83867->tx_fifo_depth); |
664 | if (ret) |
665 | dp83867->tx_fifo_depth = |
666 | DP83867_PHYCR_FIFO_DEPTH_4_B_NIB; |
667 | } |
668 | |
669 | if (dp83867->tx_fifo_depth > DP83867_PHYCR_FIFO_DEPTH_MAX) { |
670 | phydev_err(phydev, "tx-fifo-depth value %u out of range\n" , |
671 | dp83867->tx_fifo_depth); |
672 | return -EINVAL; |
673 | } |
674 | |
675 | ret = of_property_read_u32(np: of_node, propname: "rx-fifo-depth" , |
676 | out_value: &dp83867->rx_fifo_depth); |
677 | if (ret) |
678 | dp83867->rx_fifo_depth = DP83867_PHYCR_FIFO_DEPTH_4_B_NIB; |
679 | |
680 | if (dp83867->rx_fifo_depth > DP83867_PHYCR_FIFO_DEPTH_MAX) { |
681 | phydev_err(phydev, "rx-fifo-depth value %u out of range\n" , |
682 | dp83867->rx_fifo_depth); |
683 | return -EINVAL; |
684 | } |
685 | |
686 | return 0; |
687 | } |
688 | #else |
689 | static int dp83867_of_init(struct phy_device *phydev) |
690 | { |
691 | struct dp83867_private *dp83867 = phydev->priv; |
692 | u16 delay; |
693 | |
694 | /* For non-OF device, the RX and TX ID values are either strapped |
695 | * or take from default value. So, we init RX & TX ID values here |
696 | * so that the RGMIIDCTL is configured correctly later in |
697 | * dp83867_config_init(); |
698 | */ |
699 | delay = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIIDCTL); |
700 | dp83867->rx_id_delay = delay & DP83867_RGMII_RX_CLK_DELAY_MAX; |
701 | dp83867->tx_id_delay = (delay >> DP83867_RGMII_TX_CLK_DELAY_SHIFT) & |
702 | DP83867_RGMII_TX_CLK_DELAY_MAX; |
703 | |
704 | /* Per datasheet, IO impedance is default to 50-ohm, so we set the |
705 | * same here or else the default '0' means highest IO impedance |
706 | * which is wrong. |
707 | */ |
708 | dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN / 2; |
709 | |
710 | /* For non-OF device, the RX and TX FIFO depths are taken from |
711 | * default value. So, we init RX & TX FIFO depths here |
712 | * so that it is configured correctly later in dp83867_config_init(); |
713 | */ |
714 | dp83867->tx_fifo_depth = DP83867_PHYCR_FIFO_DEPTH_4_B_NIB; |
715 | dp83867->rx_fifo_depth = DP83867_PHYCR_FIFO_DEPTH_4_B_NIB; |
716 | |
717 | return 0; |
718 | } |
719 | #endif /* CONFIG_OF_MDIO */ |
720 | |
721 | static int dp83867_suspend(struct phy_device *phydev) |
722 | { |
723 | /* Disable PHY Interrupts */ |
724 | if (phy_interrupt_is_valid(phydev)) { |
725 | phydev->interrupts = PHY_INTERRUPT_DISABLED; |
726 | dp83867_config_intr(phydev); |
727 | } |
728 | |
729 | return genphy_suspend(phydev); |
730 | } |
731 | |
732 | static int dp83867_resume(struct phy_device *phydev) |
733 | { |
734 | /* Enable PHY Interrupts */ |
735 | if (phy_interrupt_is_valid(phydev)) { |
736 | phydev->interrupts = PHY_INTERRUPT_ENABLED; |
737 | dp83867_config_intr(phydev); |
738 | } |
739 | |
740 | genphy_resume(phydev); |
741 | |
742 | return 0; |
743 | } |
744 | |
745 | static int dp83867_probe(struct phy_device *phydev) |
746 | { |
747 | struct dp83867_private *dp83867; |
748 | |
749 | dp83867 = devm_kzalloc(dev: &phydev->mdio.dev, size: sizeof(*dp83867), |
750 | GFP_KERNEL); |
751 | if (!dp83867) |
752 | return -ENOMEM; |
753 | |
754 | phydev->priv = dp83867; |
755 | |
756 | return dp83867_of_init(phydev); |
757 | } |
758 | |
759 | static int dp83867_config_init(struct phy_device *phydev) |
760 | { |
761 | struct dp83867_private *dp83867 = phydev->priv; |
762 | int ret, val, bs; |
763 | u16 delay; |
764 | |
765 | /* Force speed optimization for the PHY even if it strapped */ |
766 | ret = phy_modify(phydev, DP83867_CFG2, DP83867_DOWNSHIFT_EN, |
767 | DP83867_DOWNSHIFT_EN); |
768 | if (ret) |
769 | return ret; |
770 | |
771 | ret = dp83867_verify_rgmii_cfg(phydev); |
772 | if (ret) |
773 | return ret; |
774 | |
775 | /* RX_DV/RX_CTRL strapped in mode 1 or mode 2 workaround */ |
776 | if (dp83867->rxctrl_strap_quirk) |
777 | phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, |
778 | BIT(7)); |
779 | |
780 | bs = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_STRAP_STS2); |
781 | if (bs & DP83867_STRAP_STS2_STRAP_FLD) { |
782 | /* When using strap to enable FLD, the ENERGY_LOST_FLD_THR will |
783 | * be set to 0x2. This may causes the PHY link to be unstable - |
784 | * the default value 0x1 need to be restored. |
785 | */ |
786 | ret = phy_modify_mmd(phydev, DP83867_DEVADDR, |
787 | DP83867_FLD_THR_CFG, |
788 | DP83867_FLD_THR_CFG_ENERGY_LOST_THR_MASK, |
789 | set: 0x1); |
790 | if (ret) |
791 | return ret; |
792 | } |
793 | |
794 | if (phy_interface_is_rgmii(phydev) || |
795 | phydev->interface == PHY_INTERFACE_MODE_SGMII) { |
796 | val = phy_read(phydev, MII_DP83867_PHYCTRL); |
797 | if (val < 0) |
798 | return val; |
799 | |
800 | val &= ~DP83867_PHYCR_TX_FIFO_DEPTH_MASK; |
801 | val |= (dp83867->tx_fifo_depth << |
802 | DP83867_PHYCR_TX_FIFO_DEPTH_SHIFT); |
803 | |
804 | if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { |
805 | val &= ~DP83867_PHYCR_RX_FIFO_DEPTH_MASK; |
806 | val |= (dp83867->rx_fifo_depth << |
807 | DP83867_PHYCR_RX_FIFO_DEPTH_SHIFT); |
808 | } |
809 | |
810 | ret = phy_write(phydev, MII_DP83867_PHYCTRL, val); |
811 | if (ret) |
812 | return ret; |
813 | } |
814 | |
815 | if (phy_interface_is_rgmii(phydev)) { |
816 | val = phy_read(phydev, MII_DP83867_PHYCTRL); |
817 | if (val < 0) |
818 | return val; |
819 | |
820 | /* The code below checks if "port mirroring" N/A MODE4 has been |
821 | * enabled during power on bootstrap. |
822 | * |
823 | * Such N/A mode enabled by mistake can put PHY IC in some |
824 | * internal testing mode and disable RGMII transmission. |
825 | * |
826 | * In this particular case one needs to check STRAP_STS1 |
827 | * register's bit 11 (marked as RESERVED). |
828 | */ |
829 | |
830 | bs = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_STRAP_STS1); |
831 | if (bs & DP83867_STRAP_STS1_RESERVED) |
832 | val &= ~DP83867_PHYCR_RESERVED_MASK; |
833 | |
834 | ret = phy_write(phydev, MII_DP83867_PHYCTRL, val); |
835 | if (ret) |
836 | return ret; |
837 | |
838 | /* If rgmii mode with no internal delay is selected, we do NOT use |
839 | * aligned mode as one might expect. Instead we use the PHY's default |
840 | * based on pin strapping. And the "mode 0" default is to *use* |
841 | * internal delay with a value of 7 (2.00 ns). |
842 | * |
843 | * Set up RGMII delays |
844 | */ |
845 | val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL); |
846 | |
847 | val &= ~(DP83867_RGMII_TX_CLK_DELAY_EN | DP83867_RGMII_RX_CLK_DELAY_EN); |
848 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) |
849 | val |= (DP83867_RGMII_TX_CLK_DELAY_EN | DP83867_RGMII_RX_CLK_DELAY_EN); |
850 | |
851 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) |
852 | val |= DP83867_RGMII_TX_CLK_DELAY_EN; |
853 | |
854 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) |
855 | val |= DP83867_RGMII_RX_CLK_DELAY_EN; |
856 | |
857 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL, val); |
858 | |
859 | delay = 0; |
860 | if (dp83867->rx_id_delay != DP83867_RGMII_RX_CLK_DELAY_INV) |
861 | delay |= dp83867->rx_id_delay; |
862 | if (dp83867->tx_id_delay != DP83867_RGMII_TX_CLK_DELAY_INV) |
863 | delay |= dp83867->tx_id_delay << |
864 | DP83867_RGMII_TX_CLK_DELAY_SHIFT; |
865 | |
866 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIIDCTL, |
867 | val: delay); |
868 | } |
869 | |
870 | /* If specified, set io impedance */ |
871 | if (dp83867->io_impedance >= 0) |
872 | phy_modify_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG, |
873 | DP83867_IO_MUX_CFG_IO_IMPEDANCE_MASK, |
874 | set: dp83867->io_impedance); |
875 | |
876 | if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { |
877 | /* For support SPEED_10 in SGMII mode |
878 | * DP83867_10M_SGMII_RATE_ADAPT bit |
879 | * has to be cleared by software. That |
880 | * does not affect SPEED_100 and |
881 | * SPEED_1000. |
882 | */ |
883 | ret = phy_modify_mmd(phydev, DP83867_DEVADDR, |
884 | DP83867_10M_SGMII_CFG, |
885 | DP83867_10M_SGMII_RATE_ADAPT_MASK, |
886 | set: 0); |
887 | if (ret) |
888 | return ret; |
889 | |
890 | /* After reset SGMII Autoneg timer is set to 2us (bits 6 and 5 |
891 | * are 01). That is not enough to finalize autoneg on some |
892 | * devices. Increase this timer duration to maximum 16ms. |
893 | */ |
894 | ret = phy_modify_mmd(phydev, DP83867_DEVADDR, |
895 | DP83867_CFG4, |
896 | DP83867_CFG4_SGMII_ANEG_MASK, |
897 | DP83867_CFG4_SGMII_ANEG_TIMER_16MS); |
898 | |
899 | if (ret) |
900 | return ret; |
901 | |
902 | val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_SGMIICTL); |
903 | /* SGMII type is set to 4-wire mode by default. |
904 | * If we place appropriate property in dts (see above) |
905 | * switch on 6-wire mode. |
906 | */ |
907 | if (dp83867->sgmii_ref_clk_en) |
908 | val |= DP83867_SGMII_TYPE; |
909 | else |
910 | val &= ~DP83867_SGMII_TYPE; |
911 | phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_SGMIICTL, val); |
912 | |
913 | /* This is a SW workaround for link instability if RX_CTRL is |
914 | * not strapped to mode 3 or 4 in HW. This is required for SGMII |
915 | * in addition to clearing bit 7, handled above. |
916 | */ |
917 | if (dp83867->rxctrl_strap_quirk) |
918 | phy_set_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, |
919 | BIT(8)); |
920 | } |
921 | |
922 | val = phy_read(phydev, DP83867_CFG3); |
923 | /* Enable Interrupt output INT_OE in CFG3 register */ |
924 | if (phy_interrupt_is_valid(phydev)) |
925 | val |= DP83867_CFG3_INT_OE; |
926 | |
927 | val |= DP83867_CFG3_ROBUST_AUTO_MDIX; |
928 | phy_write(phydev, DP83867_CFG3, val); |
929 | |
930 | if (dp83867->port_mirroring != DP83867_PORT_MIRROING_KEEP) |
931 | dp83867_config_port_mirroring(phydev); |
932 | |
933 | /* Clock output selection if muxing property is set */ |
934 | if (dp83867->set_clk_output) { |
935 | u16 mask = DP83867_IO_MUX_CFG_CLK_O_DISABLE; |
936 | |
937 | if (dp83867->clk_output_sel == DP83867_CLK_O_SEL_OFF) { |
938 | val = DP83867_IO_MUX_CFG_CLK_O_DISABLE; |
939 | } else { |
940 | mask |= DP83867_IO_MUX_CFG_CLK_O_SEL_MASK; |
941 | val = dp83867->clk_output_sel << |
942 | DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT; |
943 | } |
944 | |
945 | phy_modify_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG, |
946 | mask, set: val); |
947 | } |
948 | |
949 | return 0; |
950 | } |
951 | |
952 | static int dp83867_phy_reset(struct phy_device *phydev) |
953 | { |
954 | int err; |
955 | |
956 | err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESET); |
957 | if (err < 0) |
958 | return err; |
959 | |
960 | usleep_range(min: 10, max: 20); |
961 | |
962 | err = phy_modify(phydev, MII_DP83867_PHYCTRL, |
963 | DP83867_PHYCR_FORCE_LINK_GOOD, set: 0); |
964 | if (err < 0) |
965 | return err; |
966 | |
967 | /* Configure the DSP Feedforward Equalizer Configuration register to |
968 | * improve short cable (< 1 meter) performance. This will not affect |
969 | * long cable performance. |
970 | */ |
971 | err = phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_DSP_FFE_CFG, |
972 | val: 0x0e81); |
973 | if (err < 0) |
974 | return err; |
975 | |
976 | err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESTART); |
977 | if (err < 0) |
978 | return err; |
979 | |
980 | usleep_range(min: 10, max: 20); |
981 | |
982 | return 0; |
983 | } |
984 | |
985 | static void dp83867_link_change_notify(struct phy_device *phydev) |
986 | { |
987 | /* There is a limitation in DP83867 PHY device where SGMII AN is |
988 | * only triggered once after the device is booted up. Even after the |
989 | * PHY TPI is down and up again, SGMII AN is not triggered and |
990 | * hence no new in-band message from PHY to MAC side SGMII. |
991 | * This could cause an issue during power up, when PHY is up prior |
992 | * to MAC. At this condition, once MAC side SGMII is up, MAC side |
993 | * SGMII wouldn`t receive new in-band message from TI PHY with |
994 | * correct link status, speed and duplex info. |
995 | * Thus, implemented a SW solution here to retrigger SGMII Auto-Neg |
996 | * whenever there is a link change. |
997 | */ |
998 | if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { |
999 | int val = 0; |
1000 | |
1001 | val = phy_clear_bits(phydev, DP83867_CFG2, |
1002 | DP83867_SGMII_AUTONEG_EN); |
1003 | if (val < 0) |
1004 | return; |
1005 | |
1006 | phy_set_bits(phydev, DP83867_CFG2, |
1007 | DP83867_SGMII_AUTONEG_EN); |
1008 | } |
1009 | } |
1010 | |
1011 | static int dp83867_loopback(struct phy_device *phydev, bool enable) |
1012 | { |
1013 | return phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, |
1014 | set: enable ? BMCR_LOOPBACK : 0); |
1015 | } |
1016 | |
1017 | static int |
1018 | dp83867_led_brightness_set(struct phy_device *phydev, |
1019 | u8 index, enum led_brightness brightness) |
1020 | { |
1021 | u32 val; |
1022 | |
1023 | if (index >= DP83867_LED_COUNT) |
1024 | return -EINVAL; |
1025 | |
1026 | /* DRV_EN==1: output is DRV_VAL */ |
1027 | val = DP83867_LED_DRV_EN(index); |
1028 | |
1029 | if (brightness) |
1030 | val |= DP83867_LED_DRV_VAL(index); |
1031 | |
1032 | return phy_modify(phydev, DP83867_LEDCR2, |
1033 | DP83867_LED_DRV_VAL(index) | |
1034 | DP83867_LED_DRV_EN(index), |
1035 | set: val); |
1036 | } |
1037 | |
1038 | static int dp83867_led_mode(u8 index, unsigned long rules) |
1039 | { |
1040 | if (index >= DP83867_LED_COUNT) |
1041 | return -EINVAL; |
1042 | |
1043 | switch (rules) { |
1044 | case BIT(TRIGGER_NETDEV_LINK): |
1045 | return DP83867_LED_FN_LINK; |
1046 | case BIT(TRIGGER_NETDEV_LINK_10): |
1047 | return DP83867_LED_FN_LINK_10_BT; |
1048 | case BIT(TRIGGER_NETDEV_LINK_100): |
1049 | return DP83867_LED_FN_LINK_100_BTX; |
1050 | case BIT(TRIGGER_NETDEV_FULL_DUPLEX): |
1051 | return DP83867_LED_FN_FULL_DUPLEX; |
1052 | case BIT(TRIGGER_NETDEV_TX): |
1053 | return DP83867_LED_FN_TX; |
1054 | case BIT(TRIGGER_NETDEV_RX): |
1055 | return DP83867_LED_FN_RX; |
1056 | case BIT(TRIGGER_NETDEV_LINK_1000): |
1057 | return DP83867_LED_FN_LINK_1000_BT; |
1058 | case BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX): |
1059 | return DP83867_LED_FN_RX_TX; |
1060 | case BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000): |
1061 | return DP83867_LED_FN_LINK_100_1000_BT; |
1062 | case BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_100): |
1063 | return DP83867_LED_FN_LINK_10_100_BT; |
1064 | case BIT(TRIGGER_NETDEV_LINK) | BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX): |
1065 | return DP83867_LED_FN_LINK_RX_TX; |
1066 | default: |
1067 | return -EOPNOTSUPP; |
1068 | } |
1069 | } |
1070 | |
1071 | static int dp83867_led_hw_is_supported(struct phy_device *phydev, u8 index, |
1072 | unsigned long rules) |
1073 | { |
1074 | int ret; |
1075 | |
1076 | ret = dp83867_led_mode(index, rules); |
1077 | if (ret < 0) |
1078 | return ret; |
1079 | |
1080 | return 0; |
1081 | } |
1082 | |
1083 | static int dp83867_led_hw_control_set(struct phy_device *phydev, u8 index, |
1084 | unsigned long rules) |
1085 | { |
1086 | int mode, ret; |
1087 | |
1088 | mode = dp83867_led_mode(index, rules); |
1089 | if (mode < 0) |
1090 | return mode; |
1091 | |
1092 | ret = phy_modify(phydev, DP83867_LEDCR1, DP83867_LED_FN_MASK(index), |
1093 | DP83867_LED_FN(index, mode)); |
1094 | if (ret) |
1095 | return ret; |
1096 | |
1097 | return phy_modify(phydev, DP83867_LEDCR2, DP83867_LED_DRV_EN(index), set: 0); |
1098 | } |
1099 | |
1100 | static int dp83867_led_hw_control_get(struct phy_device *phydev, u8 index, |
1101 | unsigned long *rules) |
1102 | { |
1103 | int val; |
1104 | |
1105 | val = phy_read(phydev, DP83867_LEDCR1); |
1106 | if (val < 0) |
1107 | return val; |
1108 | |
1109 | val &= DP83867_LED_FN_MASK(index); |
1110 | val >>= index * 4; |
1111 | |
1112 | switch (val) { |
1113 | case DP83867_LED_FN_LINK: |
1114 | *rules = BIT(TRIGGER_NETDEV_LINK); |
1115 | break; |
1116 | case DP83867_LED_FN_LINK_10_BT: |
1117 | *rules = BIT(TRIGGER_NETDEV_LINK_10); |
1118 | break; |
1119 | case DP83867_LED_FN_LINK_100_BTX: |
1120 | *rules = BIT(TRIGGER_NETDEV_LINK_100); |
1121 | break; |
1122 | case DP83867_LED_FN_FULL_DUPLEX: |
1123 | *rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX); |
1124 | break; |
1125 | case DP83867_LED_FN_TX: |
1126 | *rules = BIT(TRIGGER_NETDEV_TX); |
1127 | break; |
1128 | case DP83867_LED_FN_RX: |
1129 | *rules = BIT(TRIGGER_NETDEV_RX); |
1130 | break; |
1131 | case DP83867_LED_FN_LINK_1000_BT: |
1132 | *rules = BIT(TRIGGER_NETDEV_LINK_1000); |
1133 | break; |
1134 | case DP83867_LED_FN_RX_TX: |
1135 | *rules = BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX); |
1136 | break; |
1137 | case DP83867_LED_FN_LINK_100_1000_BT: |
1138 | *rules = BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000); |
1139 | break; |
1140 | case DP83867_LED_FN_LINK_10_100_BT: |
1141 | *rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_100); |
1142 | break; |
1143 | case DP83867_LED_FN_LINK_RX_TX: |
1144 | *rules = BIT(TRIGGER_NETDEV_LINK) | BIT(TRIGGER_NETDEV_TX) | |
1145 | BIT(TRIGGER_NETDEV_RX); |
1146 | break; |
1147 | default: |
1148 | *rules = 0; |
1149 | break; |
1150 | } |
1151 | |
1152 | return 0; |
1153 | } |
1154 | |
1155 | static struct phy_driver dp83867_driver[] = { |
1156 | { |
1157 | .phy_id = DP83867_PHY_ID, |
1158 | .phy_id_mask = 0xfffffff0, |
1159 | .name = "TI DP83867" , |
1160 | /* PHY_GBIT_FEATURES */ |
1161 | |
1162 | .probe = dp83867_probe, |
1163 | .config_init = dp83867_config_init, |
1164 | .soft_reset = dp83867_phy_reset, |
1165 | |
1166 | .read_status = dp83867_read_status, |
1167 | .get_tunable = dp83867_get_tunable, |
1168 | .set_tunable = dp83867_set_tunable, |
1169 | |
1170 | .get_wol = dp83867_get_wol, |
1171 | .set_wol = dp83867_set_wol, |
1172 | |
1173 | /* IRQ related */ |
1174 | .config_intr = dp83867_config_intr, |
1175 | .handle_interrupt = dp83867_handle_interrupt, |
1176 | |
1177 | .suspend = dp83867_suspend, |
1178 | .resume = dp83867_resume, |
1179 | |
1180 | .link_change_notify = dp83867_link_change_notify, |
1181 | .set_loopback = dp83867_loopback, |
1182 | |
1183 | .led_brightness_set = dp83867_led_brightness_set, |
1184 | .led_hw_is_supported = dp83867_led_hw_is_supported, |
1185 | .led_hw_control_set = dp83867_led_hw_control_set, |
1186 | .led_hw_control_get = dp83867_led_hw_control_get, |
1187 | }, |
1188 | }; |
1189 | module_phy_driver(dp83867_driver); |
1190 | |
1191 | static struct mdio_device_id __maybe_unused dp83867_tbl[] = { |
1192 | { DP83867_PHY_ID, 0xfffffff0 }, |
1193 | { } |
1194 | }; |
1195 | |
1196 | MODULE_DEVICE_TABLE(mdio, dp83867_tbl); |
1197 | |
1198 | MODULE_DESCRIPTION("Texas Instruments DP83867 PHY driver" ); |
1199 | MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com" ); |
1200 | MODULE_LICENSE("GPL v2" ); |
1201 | |