drm/rockchip: Don't change hdmi reference clock rate
[drm/drm-misc.git] / drivers / net / phy / aquantia / aquantia_leds.c
blob00ad2313fed36eed549ffa55eb06e527f7c3de92
1 // SPDX-License-Identifier: GPL-2.0
2 /* LED driver for Aquantia PHY
4 * Author: Daniel Golle <daniel@makrotopia.org>
5 */
7 #include <linux/phy.h>
9 #include "aquantia.h"
11 int aqr_phy_led_brightness_set(struct phy_device *phydev,
12 u8 index, enum led_brightness value)
14 if (index >= AQR_MAX_LEDS)
15 return -EINVAL;
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,
35 unsigned long rules)
37 if (index >= AQR_MAX_LEDS)
38 return -EINVAL;
40 /* All combinations of the supported triggers are allowed */
41 if (rules & ~supported_triggers)
42 return -EOPNOTSUPP;
44 return 0;
47 int aqr_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
48 unsigned long *rules)
50 int val;
52 if (index >= AQR_MAX_LEDS)
53 return -EINVAL;
55 val = phy_read_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_PROV(index));
56 if (val < 0)
57 return val;
59 *rules = 0;
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);
81 return 0;
84 int aqr_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
85 unsigned long rules)
87 u16 val = 0;
89 if (index >= AQR_MAX_LEDS)
90 return -EINVAL;
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;
131 u32 mode;
133 if (index >= AQR_MAX_LEDS)
134 return -EINVAL;
136 for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
137 switch (mode) {
138 case PHY_LED_ACTIVE_LOW:
139 force_active_low = true;
140 break;
141 case PHY_LED_ACTIVE_HIGH:
142 force_active_high = true;
143 break;
144 default:
145 return -EINVAL;
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);
159 unreachable();