]> Git Repo - linux.git/blob - drivers/net/phy/aquantia/aquantia_leds.c
x86/kaslr: Expose and use the end of the physical memory address space
[linux.git] / drivers / net / phy / aquantia / aquantia_leds.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* LED driver for Aquantia PHY
3  *
4  * Author: Daniel Golle <[email protected]>
5  */
6
7 #include <linux/phy.h>
8
9 #include "aquantia.h"
10
11 int aqr_phy_led_brightness_set(struct phy_device *phydev,
12                                u8 index, enum led_brightness value)
13 {
14         if (index >= AQR_MAX_LEDS)
15                 return -EINVAL;
16
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);
23 }
24
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));
33
34 int aqr_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
35                                 unsigned long rules)
36 {
37         if (index >= AQR_MAX_LEDS)
38                 return -EINVAL;
39
40         /* All combinations of the supported triggers are allowed */
41         if (rules & ~supported_triggers)
42                 return -EOPNOTSUPP;
43
44         return 0;
45 }
46
47 int aqr_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
48                                unsigned long *rules)
49 {
50         int val;
51
52         if (index >= AQR_MAX_LEDS)
53                 return -EINVAL;
54
55         val = phy_read_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_PROV(index));
56         if (val < 0)
57                 return val;
58
59         *rules = 0;
60         if (val & VEND1_GLOBAL_LED_PROV_LINK100)
61                 *rules |= BIT(TRIGGER_NETDEV_LINK_100);
62
63         if (val & VEND1_GLOBAL_LED_PROV_LINK1000)
64                 *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
65
66         if (val & VEND1_GLOBAL_LED_PROV_LINK2500)
67                 *rules |= BIT(TRIGGER_NETDEV_LINK_2500);
68
69         if (val & VEND1_GLOBAL_LED_PROV_LINK5000)
70                 *rules |= BIT(TRIGGER_NETDEV_LINK_5000);
71
72         if (val & VEND1_GLOBAL_LED_PROV_LINK10000)
73                 *rules |= BIT(TRIGGER_NETDEV_LINK_10000);
74
75         if (val & VEND1_GLOBAL_LED_PROV_RX_ACT)
76                 *rules |= BIT(TRIGGER_NETDEV_RX);
77
78         if (val & VEND1_GLOBAL_LED_PROV_TX_ACT)
79                 *rules |= BIT(TRIGGER_NETDEV_TX);
80
81         return 0;
82 }
83
84 int aqr_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
85                                unsigned long rules)
86 {
87         u16 val = 0;
88
89         if (index >= AQR_MAX_LEDS)
90                 return -EINVAL;
91
92         if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
93                 val |= VEND1_GLOBAL_LED_PROV_LINK100;
94
95         if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
96                 val |= VEND1_GLOBAL_LED_PROV_LINK1000;
97
98         if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK)))
99                 val |= VEND1_GLOBAL_LED_PROV_LINK2500;
100
101         if (rules & (BIT(TRIGGER_NETDEV_LINK_5000) | BIT(TRIGGER_NETDEV_LINK)))
102                 val |= VEND1_GLOBAL_LED_PROV_LINK5000;
103
104         if (rules & (BIT(TRIGGER_NETDEV_LINK_10000) | BIT(TRIGGER_NETDEV_LINK)))
105                 val |= VEND1_GLOBAL_LED_PROV_LINK10000;
106
107         if (rules & BIT(TRIGGER_NETDEV_RX))
108                 val |= VEND1_GLOBAL_LED_PROV_RX_ACT;
109
110         if (rules & BIT(TRIGGER_NETDEV_TX))
111                 val |= VEND1_GLOBAL_LED_PROV_TX_ACT;
112
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);
118 }
119
120 int aqr_phy_led_active_low_set(struct phy_device *phydev, int index, bool enable)
121 {
122         return phy_modify_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_DRIVE(index),
123                               VEND1_GLOBAL_LED_DRIVE_VDD, enable);
124 }
125
126 int aqr_phy_led_polarity_set(struct phy_device *phydev, int index, unsigned long modes)
127 {
128         struct aqr107_priv *priv = phydev->priv;
129         bool active_low = false;
130         u32 mode;
131
132         if (index >= AQR_MAX_LEDS)
133                 return -EINVAL;
134
135         for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
136                 switch (mode) {
137                 case PHY_LED_ACTIVE_LOW:
138                         active_low = true;
139                         break;
140                 default:
141                         return -EINVAL;
142                 }
143         }
144
145         /* Save LED driver vdd state to restore on SW reset */
146         if (active_low)
147                 priv->leds_active_low |= BIT(index);
148
149         return aqr_phy_led_active_low_set(phydev, index, active_low);
150 }
This page took 0.043786 seconds and 4 git commands to generate.