ffcd338f1005b42872319a86342865faf814e88c
[GitHub/LineageOS/G12/android_hardware_amlogic_kernel-modules_dhd-driver.git] / broadcm_40181 / dhd_custom_gpio.c
1 /*
2 * Customer code to add GPIO control during WLAN start/stop
3 * $Copyright Open Broadcom Corporation$
4 *
5 * $Id: dhd_custom_gpio.c 417465 2013-08-09 11:47:27Z $
6 */
7
8 #include <typedefs.h>
9 #include <linuxver.h>
10 #include <osl.h>
11 #include <bcmutils.h>
12
13 #include <dngl_stats.h>
14 #include <dhd.h>
15
16 #include <wlioctl.h>
17 #include <wl_iw.h>
18
19 #define WL_ERROR(x) printf x
20 #define WL_TRACE(x)
21
22 #ifdef CUSTOMER_HW_AMLOGIC
23 extern void sdio_reinit(void);
24 extern void extern_wifi_set_enable(int is_on);
25 #endif /* CUSTOMER_HW_AMLOGIC */
26
27 #ifdef CUSTOMER_HW
28 #if defined(CUSTOMER_OOB)
29 extern int bcm_wlan_get_oob_irq(void);
30 #endif
31 extern void bcm_wlan_power_off(int);
32 extern void bcm_wlan_power_on(int);
33 #endif /* CUSTOMER_HW */
34 #if defined(CUSTOMER_HW2)
35
36 #if defined(PLATFORM_MPS)
37 int __attribute__ ((weak)) wifi_get_fw_nv_path(char *fw, char *nv) { return 0;};
38 #endif
39
40 #ifdef CONFIG_WIFI_CONTROL_FUNC
41 int wifi_set_power(int on, unsigned long msec);
42 int wifi_get_irq_number(unsigned long *irq_flags_ptr);
43 int wifi_get_mac_addr(unsigned char *buf);
44 void *wifi_get_country_code(char *ccode);
45 #else
46 int wifi_set_power(int on, unsigned long msec) { return -1; }
47 int wifi_get_irq_number(unsigned long *irq_flags_ptr) { return -1; }
48 int wifi_get_mac_addr(unsigned char *buf) { return -1; }
49 void *wifi_get_country_code(char *ccode) { return NULL; }
50 #endif /* CONFIG_WIFI_CONTROL_FUNC */
51 #endif
52
53 #if defined(OOB_INTR_ONLY)
54
55 #if defined(BCMLXSDMMC)
56 extern int sdioh_mmc_irq(int irq);
57 #endif /* (BCMLXSDMMC) */
58
59 #if defined(CUSTOMER_HW3) || defined(PLATFORM_MPS)
60 #include <mach/gpio.h>
61 #endif
62
63 /* Customer specific Host GPIO defintion */
64 static int dhd_oob_gpio_num = -1;
65
66 module_param(dhd_oob_gpio_num, int, 0644);
67 MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number");
68
69 /* This function will return:
70 * 1) return : Host gpio interrupt number per customer platform
71 * 2) irq_flags_ptr : Type of Host interrupt as Level or Edge
72 *
73 * NOTE :
74 * Customer should check his platform definitions
75 * and his Host Interrupt spec
76 * to figure out the proper setting for his platform.
77 * Broadcom provides just reference settings as example.
78 *
79 */
80 int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
81 {
82 int host_oob_irq = CUSTOM_OOB_GPIO_NUM;
83
84 #if defined(CUSTOMER_HW2) && !defined(PLATFORM_MPS)
85 host_oob_irq = wifi_get_irq_number(irq_flags_ptr);
86
87 #elif defined(CUSTOMER_OOB)
88 host_oob_irq = bcm_wlan_get_oob_irq();
89
90 #else
91 #if defined(CUSTOM_OOB_GPIO_NUM)
92 if (dhd_oob_gpio_num < 0) {
93 dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
94 }
95 #endif /* CUSTOMER_OOB_GPIO_NUM */
96
97 if (dhd_oob_gpio_num < 0) {
98 WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n",
99 __FUNCTION__));
100 return (dhd_oob_gpio_num);
101 }
102
103 WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n",
104 __FUNCTION__, dhd_oob_gpio_num));
105
106 #if defined CUSTOMER_HW
107 host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num);
108 #elif defined CUSTOMER_HW3 || defined(PLATFORM_MPS)
109 gpio_request(dhd_oob_gpio_num, "oob irq");
110 host_oob_irq = gpio_to_irq(dhd_oob_gpio_num);
111 gpio_direction_input(dhd_oob_gpio_num);
112 #endif /* CUSTOMER_HW */
113 #endif
114
115 return (host_oob_irq);
116 }
117 #endif
118
119 /* Customer function to control hw specific wlan gpios */
120 void
121 dhd_customer_gpio_wlan_ctrl(int onoff)
122 {
123 switch (onoff) {
124 case WLAN_RESET_OFF:
125 WL_TRACE(("%s: call customer specific GPIO to insert WLAN RESET\n",
126 __FUNCTION__));
127 #ifdef CUSTOMER_HW
128 bcm_wlan_power_off(2);
129 #endif /* CUSTOMER_HW */
130 #if defined(CUSTOMER_HW2)
131 wifi_set_power(0, WIFI_TURNOFF_DELAY);
132 #endif
133 WL_ERROR(("=========== WLAN placed in RESET ========\n"));
134 break;
135
136 case WLAN_RESET_ON:
137 WL_TRACE(("%s: callc customer specific GPIO to remove WLAN RESET\n",
138 __FUNCTION__));
139 #ifdef CUSTOMER_HW
140 bcm_wlan_power_on(2);
141 OSL_DELAY(200);
142 #endif /* CUSTOMER_HW */
143 #if defined(CUSTOMER_HW2)
144 wifi_set_power(1, 200);
145 #endif
146 #ifdef CUSTOMER_HW_AMLOGIC
147 extern_wifi_set_enable(0);
148 mdelay(200);
149 extern_wifi_set_enable(1);
150 mdelay(200);
151 sdio_reinit();
152 #endif /* CUSTOMER_HW_AMLOGIC */
153 mdelay(100);
154 WL_ERROR(("=========== WLAN going back to live ========\n"));
155 break;
156
157 case WLAN_POWER_OFF:
158 WL_TRACE(("%s: call customer specific GPIO to turn off WL_REG_ON\n",
159 __FUNCTION__));
160 #ifdef CUSTOMER_HW
161 bcm_wlan_power_off(1);
162 #endif /* CUSTOMER_HW */
163
164 #ifdef CUSTOMER_HW_AMLOGIC
165 extern_wifi_set_enable(0);
166 #endif /* CUSTOMER_HW_AMLOGIC */
167 WL_ERROR(("=========== WLAN placed in POWER OFF ========\n"));
168 break;
169
170 case WLAN_POWER_ON:
171 WL_TRACE(("%s: call customer specific GPIO to turn on WL_REG_ON\n",
172 __FUNCTION__));
173 #ifdef CUSTOMER_HW
174 bcm_wlan_power_on(1);
175 #endif /* CUSTOMER_HW */
176
177 #ifdef CUSTOMER_HW_AMLOGIC
178 extern_wifi_set_enable(0);
179 mdelay(200);
180 extern_wifi_set_enable(1);
181 mdelay(200);
182 sdio_reinit();
183 #endif /* CUSTOMER_HW_AMLOGIC */
184 /* Lets customer power to get stable */
185 OSL_DELAY(200);
186 WL_ERROR(("=========== WLAN placed in POWER ON ========\n"));
187 break;
188 }
189 }
190
191 #ifdef GET_CUSTOM_MAC_ENABLE
192 /* Function to get custom MAC address */
193 int
194 dhd_custom_get_mac_address(unsigned char *buf)
195 {
196 int ret = 0;
197
198 WL_TRACE(("%s Enter\n", __FUNCTION__));
199 if (!buf)
200 return -EINVAL;
201
202 /* Customer access to MAC address stored outside of DHD driver */
203 #if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
204 ret = wifi_get_mac_addr(buf);
205 #endif
206
207 #ifdef EXAMPLE_GET_MAC
208 /* EXAMPLE code */
209 {
210 struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
211 bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
212 }
213 #endif /* EXAMPLE_GET_MAC */
214
215 return ret;
216 }
217 #endif /* GET_CUSTOM_MAC_ENABLE */
218
219 /* Customized Locale table : OPTIONAL feature */
220 const struct cntry_locales_custom translate_custom_table[] = {
221 /* Table should be filled out based on custom platform regulatory requirement */
222 #ifdef EXAMPLE_TABLE
223 {"", "XY", 4}, /* Universal if Country code is unknown or empty */
224 {"US", "US", 69}, /* input ISO "US" to : US regrev 69 */
225 {"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */
226 {"EU", "EU", 5}, /* European union countries to : EU regrev 05 */
227 {"AT", "EU", 5},
228 {"BE", "EU", 5},
229 {"BG", "EU", 5},
230 {"CY", "EU", 5},
231 {"CZ", "EU", 5},
232 {"DK", "EU", 5},
233 {"EE", "EU", 5},
234 {"FI", "EU", 5},
235 {"FR", "EU", 5},
236 {"DE", "EU", 5},
237 {"GR", "EU", 5},
238 {"HU", "EU", 5},
239 {"IE", "EU", 5},
240 {"IT", "EU", 5},
241 {"LV", "EU", 5},
242 {"LI", "EU", 5},
243 {"LT", "EU", 5},
244 {"LU", "EU", 5},
245 {"MT", "EU", 5},
246 {"NL", "EU", 5},
247 {"PL", "EU", 5},
248 {"PT", "EU", 5},
249 {"RO", "EU", 5},
250 {"SK", "EU", 5},
251 {"SI", "EU", 5},
252 {"ES", "EU", 5},
253 {"SE", "EU", 5},
254 {"GB", "EU", 5},
255 {"KR", "XY", 3},
256 {"AU", "XY", 3},
257 {"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */
258 {"TW", "XY", 3},
259 {"AR", "XY", 3},
260 {"MX", "XY", 3},
261 {"IL", "IL", 0},
262 {"CH", "CH", 0},
263 {"TR", "TR", 0},
264 {"NO", "NO", 0},
265 #endif /* EXMAPLE_TABLE */
266 };
267
268
269 /* Customized Locale convertor
270 * input : ISO 3166-1 country abbreviation
271 * output: customized cspec
272 */
273 void get_customized_country_code(char *country_iso_code, wl_country_t *cspec)
274 {
275 #if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
276
277 struct cntry_locales_custom *cloc_ptr;
278
279 if (!cspec)
280 return;
281
282 cloc_ptr = wifi_get_country_code(country_iso_code);
283 if (cloc_ptr) {
284 strlcpy(cspec->ccode, cloc_ptr->custom_locale, WLC_CNTRY_BUF_SZ);
285 cspec->rev = cloc_ptr->custom_locale_rev;
286 }
287 return;
288 #else
289 int size, i;
290
291 size = ARRAYSIZE(translate_custom_table);
292
293 if (cspec == 0)
294 return;
295
296 if (size == 0)
297 return;
298
299 for (i = 0; i < size; i++) {
300 if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) {
301 memcpy(cspec->ccode,
302 translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ);
303 cspec->rev = translate_custom_table[i].custom_locale_rev;
304 return;
305 }
306 }
307 #ifdef EXAMPLE_TABLE
308 /* if no country code matched return first universal code from translate_custom_table */
309 memcpy(cspec->ccode, translate_custom_table[0].custom_locale, WLC_CNTRY_BUF_SZ);
310 cspec->rev = translate_custom_table[0].custom_locale_rev;
311 #endif /* EXMAPLE_TABLE */
312 return;
313 #endif /* defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) */
314 }