1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2010 Realtek Corporation.*/
3
4 #include "../wifi.h"
5 #include "../pci.h"
6 #include "reg.h"
7 #include "led.h"
8
rtl8821ae_sw_led_on(struct ieee80211_hw * hw,enum rtl_led_pin pin)9 void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
10 {
11 u8 ledcfg;
12 struct rtl_priv *rtlpriv = rtl_priv(hw);
13
14 rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
15 "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
16
17 switch (pin) {
18 case LED_PIN_GPIO0:
19 break;
20 case LED_PIN_LED0:
21 ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
22 ledcfg &= ~BIT(6);
23 rtl_write_byte(rtlpriv,
24 REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5));
25 break;
26 case LED_PIN_LED1:
27 ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
28 rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10);
29 break;
30 default:
31 rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
32 "switch case %#x not processed\n", pin);
33 break;
34 }
35 }
36
rtl8812ae_sw_led_on(struct ieee80211_hw * hw,enum rtl_led_pin pin)37 void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
38 {
39 u16 ledreg = REG_LEDCFG1;
40 u8 ledcfg = 0;
41 struct rtl_priv *rtlpriv = rtl_priv(hw);
42
43 switch (pin) {
44 case LED_PIN_LED0:
45 ledreg = REG_LEDCFG1;
46 break;
47
48 case LED_PIN_LED1:
49 ledreg = REG_LEDCFG2;
50 break;
51
52 case LED_PIN_GPIO0:
53 default:
54 break;
55 }
56
57 rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
58 "In SwLedOn, LedAddr:%X LEDPIN=%d\n",
59 ledreg, pin);
60
61 ledcfg = rtl_read_byte(rtlpriv, ledreg);
62 ledcfg |= BIT(5); /*Set 0x4c[21]*/
63 ledcfg &= ~(BIT(7) | BIT(6) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
64 /*Clear 0x4c[23:22] and 0x4c[19:16]*/
65 rtl_write_byte(rtlpriv, ledreg, ledcfg); /*SW control led0 on.*/
66 }
67
rtl8821ae_sw_led_off(struct ieee80211_hw * hw,enum rtl_led_pin pin)68 void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
69 {
70 struct rtl_priv *rtlpriv = rtl_priv(hw);
71 u8 ledcfg;
72
73 rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
74 "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
75
76 ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
77
78 switch (pin) {
79 case LED_PIN_GPIO0:
80 break;
81 case LED_PIN_LED0:
82 ledcfg &= 0xf0;
83 if (rtlpriv->ledctl.led_opendrain) {
84 ledcfg &= 0x90; /* Set to software control. */
85 rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3)));
86 ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
87 ledcfg &= 0xFE;
88 rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg);
89 } else {
90 ledcfg &= ~BIT(6);
91 rtl_write_byte(rtlpriv, REG_LEDCFG2,
92 (ledcfg | BIT(3) | BIT(5)));
93 }
94 break;
95 case LED_PIN_LED1:
96 ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
97 ledcfg &= 0x10; /* Set to software control. */
98 rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg|BIT(3));
99 break;
100 default:
101 rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
102 "switch case %#x not processed\n", pin);
103 break;
104 }
105 }
106
rtl8812ae_sw_led_off(struct ieee80211_hw * hw,enum rtl_led_pin pin)107 void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
108 {
109 u16 ledreg = REG_LEDCFG1;
110 struct rtl_priv *rtlpriv = rtl_priv(hw);
111
112 switch (pin) {
113 case LED_PIN_LED0:
114 ledreg = REG_LEDCFG1;
115 break;
116
117 case LED_PIN_LED1:
118 ledreg = REG_LEDCFG2;
119 break;
120
121 case LED_PIN_GPIO0:
122 default:
123 break;
124 }
125
126 rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
127 "In SwLedOff,LedAddr:%X LEDPIN=%d\n",
128 ledreg, pin);
129 /*Open-drain arrangement for controlling the LED*/
130 if (rtlpriv->ledctl.led_opendrain) {
131 u8 ledcfg = rtl_read_byte(rtlpriv, ledreg);
132
133 ledreg &= 0xd0; /* Set to software control.*/
134 rtl_write_byte(rtlpriv, ledreg, (ledcfg | BIT(3)));
135
136 /*Open-drain arrangement*/
137 ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
138 ledcfg &= 0xFE;/*Set GPIO[8] to input mode*/
139 rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg);
140 } else {
141 rtl_write_byte(rtlpriv, ledreg, 0x28);
142 }
143 }
144
_rtl8821ae_sw_led_control(struct ieee80211_hw * hw,enum led_ctl_mode ledaction)145 static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw,
146 enum led_ctl_mode ledaction)
147 {
148 struct rtl_priv *rtlpriv = rtl_priv(hw);
149 enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
150 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
151
152 switch (ledaction) {
153 case LED_CTL_POWER_ON:
154 case LED_CTL_LINK:
155 case LED_CTL_NO_LINK:
156 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
157 rtl8812ae_sw_led_on(hw, pin0);
158 else
159 rtl8821ae_sw_led_on(hw, pin0);
160 break;
161 case LED_CTL_POWER_OFF:
162 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
163 rtl8812ae_sw_led_off(hw, pin0);
164 else
165 rtl8821ae_sw_led_off(hw, pin0);
166 break;
167 default:
168 break;
169 }
170 }
171
rtl8821ae_led_control(struct ieee80211_hw * hw,enum led_ctl_mode ledaction)172 void rtl8821ae_led_control(struct ieee80211_hw *hw,
173 enum led_ctl_mode ledaction)
174 {
175 struct rtl_priv *rtlpriv = rtl_priv(hw);
176 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
177
178 if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
179 (ledaction == LED_CTL_TX ||
180 ledaction == LED_CTL_RX ||
181 ledaction == LED_CTL_SITE_SURVEY ||
182 ledaction == LED_CTL_LINK ||
183 ledaction == LED_CTL_NO_LINK ||
184 ledaction == LED_CTL_START_TO_LINK ||
185 ledaction == LED_CTL_POWER_ON)) {
186 return;
187 }
188 rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n",
189 ledaction);
190 _rtl8821ae_sw_led_control(hw, ledaction);
191 }
192