1 // SPDX-License-Identifier: GPL-2.0
2 /* LED driver for Aquantia PHY
4 * Author: Daniel Golle <daniel@makrotopia.org>
11 int aqr_phy_led_brightness_set(struct phy_device
*phydev
,
12 u8 index
, enum led_brightness value
)
14 if (index
>= AQR_MAX_LEDS
)
17 return phy_modify_mmd(phydev
, MDIO_MMD_VEND1
, AQR_LED_PROV(index
),
18 VEND1_GLOBAL_LED_PROV_LINK_MASK
|
19 VEND1_GLOBAL_LED_PROV_FORCE_ON
|
20 VEND1_GLOBAL_LED_PROV_RX_ACT
|
21 VEND1_GLOBAL_LED_PROV_TX_ACT
,
22 value
? VEND1_GLOBAL_LED_PROV_FORCE_ON
: 0);
25 static const unsigned long supported_triggers
= (BIT(TRIGGER_NETDEV_LINK
) |
26 BIT(TRIGGER_NETDEV_LINK_100
) |
27 BIT(TRIGGER_NETDEV_LINK_1000
) |
28 BIT(TRIGGER_NETDEV_LINK_2500
) |
29 BIT(TRIGGER_NETDEV_LINK_5000
) |
30 BIT(TRIGGER_NETDEV_LINK_10000
) |
31 BIT(TRIGGER_NETDEV_RX
) |
32 BIT(TRIGGER_NETDEV_TX
));
34 int aqr_phy_led_hw_is_supported(struct phy_device
*phydev
, u8 index
,
37 if (index
>= AQR_MAX_LEDS
)
40 /* All combinations of the supported triggers are allowed */
41 if (rules
& ~supported_triggers
)
47 int aqr_phy_led_hw_control_get(struct phy_device
*phydev
, u8 index
,
52 if (index
>= AQR_MAX_LEDS
)
55 val
= phy_read_mmd(phydev
, MDIO_MMD_VEND1
, AQR_LED_PROV(index
));
60 if (val
& VEND1_GLOBAL_LED_PROV_LINK100
)
61 *rules
|= BIT(TRIGGER_NETDEV_LINK_100
);
63 if (val
& VEND1_GLOBAL_LED_PROV_LINK1000
)
64 *rules
|= BIT(TRIGGER_NETDEV_LINK_1000
);
66 if (val
& VEND1_GLOBAL_LED_PROV_LINK2500
)
67 *rules
|= BIT(TRIGGER_NETDEV_LINK_2500
);
69 if (val
& VEND1_GLOBAL_LED_PROV_LINK5000
)
70 *rules
|= BIT(TRIGGER_NETDEV_LINK_5000
);
72 if (val
& VEND1_GLOBAL_LED_PROV_LINK10000
)
73 *rules
|= BIT(TRIGGER_NETDEV_LINK_10000
);
75 if (val
& VEND1_GLOBAL_LED_PROV_RX_ACT
)
76 *rules
|= BIT(TRIGGER_NETDEV_RX
);
78 if (val
& VEND1_GLOBAL_LED_PROV_TX_ACT
)
79 *rules
|= BIT(TRIGGER_NETDEV_TX
);
84 int aqr_phy_led_hw_control_set(struct phy_device
*phydev
, u8 index
,
89 if (index
>= AQR_MAX_LEDS
)
92 if (rules
& (BIT(TRIGGER_NETDEV_LINK_100
) | BIT(TRIGGER_NETDEV_LINK
)))
93 val
|= VEND1_GLOBAL_LED_PROV_LINK100
;
95 if (rules
& (BIT(TRIGGER_NETDEV_LINK_1000
) | BIT(TRIGGER_NETDEV_LINK
)))
96 val
|= VEND1_GLOBAL_LED_PROV_LINK1000
;
98 if (rules
& (BIT(TRIGGER_NETDEV_LINK_2500
) | BIT(TRIGGER_NETDEV_LINK
)))
99 val
|= VEND1_GLOBAL_LED_PROV_LINK2500
;
101 if (rules
& (BIT(TRIGGER_NETDEV_LINK_5000
) | BIT(TRIGGER_NETDEV_LINK
)))
102 val
|= VEND1_GLOBAL_LED_PROV_LINK5000
;
104 if (rules
& (BIT(TRIGGER_NETDEV_LINK_10000
) | BIT(TRIGGER_NETDEV_LINK
)))
105 val
|= VEND1_GLOBAL_LED_PROV_LINK10000
;
107 if (rules
& BIT(TRIGGER_NETDEV_RX
))
108 val
|= VEND1_GLOBAL_LED_PROV_RX_ACT
;
110 if (rules
& BIT(TRIGGER_NETDEV_TX
))
111 val
|= VEND1_GLOBAL_LED_PROV_TX_ACT
;
113 return phy_modify_mmd(phydev
, MDIO_MMD_VEND1
, AQR_LED_PROV(index
),
114 VEND1_GLOBAL_LED_PROV_LINK_MASK
|
115 VEND1_GLOBAL_LED_PROV_FORCE_ON
|
116 VEND1_GLOBAL_LED_PROV_RX_ACT
|
117 VEND1_GLOBAL_LED_PROV_TX_ACT
, val
);
120 int aqr_phy_led_active_low_set(struct phy_device
*phydev
, int index
, bool enable
)
122 return phy_modify_mmd(phydev
, MDIO_MMD_VEND1
, AQR_LED_DRIVE(index
),
123 VEND1_GLOBAL_LED_DRIVE_VDD
,
124 enable
? 0 : VEND1_GLOBAL_LED_DRIVE_VDD
);
127 int aqr_phy_led_polarity_set(struct phy_device
*phydev
, int index
, unsigned long modes
)
129 bool force_active_low
= false, force_active_high
= false;
130 struct aqr107_priv
*priv
= phydev
->priv
;
133 if (index
>= AQR_MAX_LEDS
)
136 for_each_set_bit(mode
, &modes
, __PHY_LED_MODES_NUM
) {
138 case PHY_LED_ACTIVE_LOW
:
139 force_active_low
= true;
141 case PHY_LED_ACTIVE_HIGH
:
142 force_active_high
= true;
149 /* Save LED driver vdd state to restore on SW reset */
150 if (force_active_low
)
151 priv
->leds_active_low
|= BIT(index
);
153 if (force_active_high
)
154 priv
->leds_active_high
|= BIT(index
);
156 if (force_active_high
|| force_active_low
)
157 return aqr_phy_led_active_low_set(phydev
, index
, force_active_low
);