Skip to content

Commit 5b281fe

Browse files
oleremkuba-moo
authored andcommitted
net: phy: dp83td510: introduce LED framework support
Add LED brightness, mode, HW control and polarity functions to enable external LED control in the TI DP83TD510 PHY. Signed-off-by: Oleksij Rempel <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 39f5426 commit 5b281fe

File tree

1 file changed

+187
-0
lines changed

1 file changed

+187
-0
lines changed

drivers/net/phy/dp83td510.c

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,191 @@ struct dp83td510_priv {
204204
#define DP83TD510E_UNKN_030E 0x30e
205205
#define DP83TD510E_030E_VAL 0x2520
206206

207+
#define DP83TD510E_LEDS_CFG_1 0x460
208+
#define DP83TD510E_LED_FN(idx, val) (((val) & 0xf) << ((idx) * 4))
209+
#define DP83TD510E_LED_FN_MASK(idx) (0xf << ((idx) * 4))
210+
/* link OK */
211+
#define DP83TD510E_LED_MODE_LINK_OK 0x0
212+
/* TX/RX activity */
213+
#define DP83TD510E_LED_MODE_TX_RX_ACTIVITY 0x1
214+
/* TX activity */
215+
#define DP83TD510E_LED_MODE_TX_ACTIVITY 0x2
216+
/* RX activity */
217+
#define DP83TD510E_LED_MODE_RX_ACTIVITY 0x3
218+
/* LR */
219+
#define DP83TD510E_LED_MODE_LR 0x4
220+
/* SR */
221+
#define DP83TD510E_LED_MODE_SR 0x5
222+
/* LED SPEED: High for 10Base-T */
223+
#define DP83TD510E_LED_MODE_LED_SPEED 0x6
224+
/* Duplex mode */
225+
#define DP83TD510E_LED_MODE_DUPLEX 0x7
226+
/* link + blink on activity with stretch option */
227+
#define DP83TD510E_LED_MODE_LINK_BLINK 0x8
228+
/* blink on activity with stretch option */
229+
#define DP83TD510E_LED_MODE_BLINK_ACTIVITY 0x9
230+
/* blink on tx activity with stretch option */
231+
#define DP83TD510E_LED_MODE_BLINK_TX 0xa
232+
/* blink on rx activity with stretch option */
233+
#define DP83TD510E_LED_MODE_BLINK_RX 0xb
234+
/* link_lost */
235+
#define DP83TD510E_LED_MODE_LINK_LOST 0xc
236+
/* PRBS error: toggles on error */
237+
#define DP83TD510E_LED_MODE_PRBS_ERROR 0xd
238+
/* XMII TX/RX Error with stretch option */
239+
#define DP83TD510E_LED_MODE_XMII_ERR 0xe
240+
241+
#define DP83TD510E_LED_COUNT 4
242+
243+
#define DP83TD510E_LEDS_CFG_2 0x469
244+
#define DP83TD510E_LED_POLARITY(idx) BIT((idx) * 4 + 2)
245+
#define DP83TD510E_LED_DRV_VAL(idx) BIT((idx) * 4 + 1)
246+
#define DP83TD510E_LED_DRV_EN(idx) BIT((idx) * 4)
247+
207248
#define DP83TD510E_ALCD_STAT 0xa9f
208249
#define DP83TD510E_ALCD_COMPLETE BIT(15)
209250
#define DP83TD510E_ALCD_CABLE_LENGTH GENMASK(10, 0)
210251

252+
static int dp83td510_led_brightness_set(struct phy_device *phydev, u8 index,
253+
enum led_brightness brightness)
254+
{
255+
u32 val;
256+
257+
if (index >= DP83TD510E_LED_COUNT)
258+
return -EINVAL;
259+
260+
val = DP83TD510E_LED_DRV_EN(index);
261+
262+
if (brightness)
263+
val |= DP83TD510E_LED_DRV_VAL(index);
264+
265+
return phy_modify_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_LEDS_CFG_2,
266+
DP83TD510E_LED_DRV_VAL(index) |
267+
DP83TD510E_LED_DRV_EN(index), val);
268+
}
269+
270+
static int dp83td510_led_mode(u8 index, unsigned long rules)
271+
{
272+
if (index >= DP83TD510E_LED_COUNT)
273+
return -EINVAL;
274+
275+
switch (rules) {
276+
case BIT(TRIGGER_NETDEV_LINK):
277+
return DP83TD510E_LED_MODE_LINK_OK;
278+
case BIT(TRIGGER_NETDEV_LINK_10):
279+
return DP83TD510E_LED_MODE_LED_SPEED;
280+
case BIT(TRIGGER_NETDEV_FULL_DUPLEX):
281+
return DP83TD510E_LED_MODE_DUPLEX;
282+
case BIT(TRIGGER_NETDEV_TX):
283+
return DP83TD510E_LED_MODE_TX_ACTIVITY;
284+
case BIT(TRIGGER_NETDEV_RX):
285+
return DP83TD510E_LED_MODE_RX_ACTIVITY;
286+
case BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX):
287+
return DP83TD510E_LED_MODE_TX_RX_ACTIVITY;
288+
case BIT(TRIGGER_NETDEV_LINK) | BIT(TRIGGER_NETDEV_TX) |
289+
BIT(TRIGGER_NETDEV_RX):
290+
return DP83TD510E_LED_MODE_LINK_BLINK;
291+
default:
292+
return -EOPNOTSUPP;
293+
}
294+
}
295+
296+
static int dp83td510_led_hw_is_supported(struct phy_device *phydev, u8 index,
297+
unsigned long rules)
298+
{
299+
int ret;
300+
301+
ret = dp83td510_led_mode(index, rules);
302+
if (ret < 0)
303+
return ret;
304+
305+
return 0;
306+
}
307+
308+
static int dp83td510_led_hw_control_set(struct phy_device *phydev, u8 index,
309+
unsigned long rules)
310+
{
311+
int mode, ret;
312+
313+
mode = dp83td510_led_mode(index, rules);
314+
if (mode < 0)
315+
return mode;
316+
317+
ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_LEDS_CFG_1,
318+
DP83TD510E_LED_FN_MASK(index),
319+
DP83TD510E_LED_FN(index, mode));
320+
if (ret)
321+
return ret;
322+
323+
return phy_modify_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_LEDS_CFG_2,
324+
DP83TD510E_LED_DRV_EN(index), 0);
325+
}
326+
327+
static int dp83td510_led_hw_control_get(struct phy_device *phydev,
328+
u8 index, unsigned long *rules)
329+
{
330+
int val;
331+
332+
val = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_LEDS_CFG_1);
333+
if (val < 0)
334+
return val;
335+
336+
val &= DP83TD510E_LED_FN_MASK(index);
337+
val >>= index * 4;
338+
339+
switch (val) {
340+
case DP83TD510E_LED_MODE_LINK_OK:
341+
*rules = BIT(TRIGGER_NETDEV_LINK);
342+
break;
343+
/* LED mode: LED SPEED (10BaseT1L indicator) */
344+
case DP83TD510E_LED_MODE_LED_SPEED:
345+
*rules = BIT(TRIGGER_NETDEV_LINK_10);
346+
break;
347+
case DP83TD510E_LED_MODE_DUPLEX:
348+
*rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX);
349+
break;
350+
case DP83TD510E_LED_MODE_TX_ACTIVITY:
351+
*rules = BIT(TRIGGER_NETDEV_TX);
352+
break;
353+
case DP83TD510E_LED_MODE_RX_ACTIVITY:
354+
*rules = BIT(TRIGGER_NETDEV_RX);
355+
break;
356+
case DP83TD510E_LED_MODE_TX_RX_ACTIVITY:
357+
*rules = BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX);
358+
break;
359+
case DP83TD510E_LED_MODE_LINK_BLINK:
360+
*rules = BIT(TRIGGER_NETDEV_LINK) |
361+
BIT(TRIGGER_NETDEV_TX) |
362+
BIT(TRIGGER_NETDEV_RX);
363+
break;
364+
default:
365+
*rules = 0;
366+
break;
367+
}
368+
369+
return 0;
370+
}
371+
372+
static int dp83td510_led_polarity_set(struct phy_device *phydev, int index,
373+
unsigned long modes)
374+
{
375+
u16 polarity = DP83TD510E_LED_POLARITY(index);
376+
u32 mode;
377+
378+
for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
379+
switch (mode) {
380+
case PHY_LED_ACTIVE_LOW:
381+
polarity = 0;
382+
break;
383+
default:
384+
return -EINVAL;
385+
}
386+
}
387+
388+
return phy_modify_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_LEDS_CFG_2,
389+
DP83TD510E_LED_POLARITY(index), polarity);
390+
}
391+
211392
/**
212393
* dp83td510_update_stats - Update the PHY statistics for the DP83TD510 PHY.
213394
* @phydev: Pointer to the phy_device structure.
@@ -712,6 +893,12 @@ static struct phy_driver dp83td510_driver[] = {
712893
.get_phy_stats = dp83td510_get_phy_stats,
713894
.update_stats = dp83td510_update_stats,
714895

896+
.led_brightness_set = dp83td510_led_brightness_set,
897+
.led_hw_is_supported = dp83td510_led_hw_is_supported,
898+
.led_hw_control_set = dp83td510_led_hw_control_set,
899+
.led_hw_control_get = dp83td510_led_hw_control_get,
900+
.led_polarity_set = dp83td510_led_polarity_set,
901+
715902
.suspend = genphy_suspend,
716903
.resume = genphy_resume,
717904
} };

0 commit comments

Comments
 (0)