Revert "wifi: fix wifi close issue"
[GitHub/LineageOS/G12/android_hardware_amlogic_kernel-modules_dhd-driver.git] / bcmdhd.1.579.77.41.1.cn / dhd_gpio.c
CommitLineData
010c3a89
RC
1
2#include <osl.h>
3#include <dhd_linux.h>
4#include <linux/gpio.h>
5
6#ifdef CUSTOMER_HW_PLATFORM
7#include <plat/sdhci.h>
8#define sdmmc_channel sdmmc_device_mmc0
9#endif /* CUSTOMER_HW_PLATFORM */
10
11#if defined(BUS_POWER_RESTORE) && defined(BCMSDIO)
12#include <linux/mmc/core.h>
13#include <linux/mmc/card.h>
14#include <linux/mmc/host.h>
15#include <linux/mmc/sdio_func.h>
16#endif /* defined(BUS_POWER_RESTORE) && defined(BCMSDIO) */
17
91a2c117
RC
18#ifdef CONFIG_DHD_USE_STATIC_BUF
19extern void *bcmdhd_mem_prealloc(int section, unsigned long size);
20#endif /* CONFIG_DHD_USE_STATIC_BUF */
ccd15baf
RC
21
22static int gpio_wl_reg_on = -1; // WL_REG_ON is input pin of WLAN module
23#ifdef CUSTOMER_OOB
24static int gpio_wl_host_wake = -1; // WL_HOST_WAKE is output pin of WLAN module
25#endif
26
010c3a89
RC
27#ifdef CUSTOMER_HW_AMLOGIC
28#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
29#include <linux/amlogic/aml_gpio_consumer.h>
30extern int wifi_irq_trigger_level(void);
31extern u8 *wifi_get_mac(void);
32#endif
33extern void sdio_reinit(void);
34extern void extern_wifi_set_enable(int is_on);
35#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
36extern int wifi_irq_num(void);
37#endif
38#endif
39
010c3a89
RC
40static int
41dhd_wlan_set_power(int on
42#ifdef BUS_POWER_RESTORE
43, wifi_adapter_info_t *adapter
44#endif /* BUS_POWER_RESTORE */
45)
46{
47 int err = 0;
48
49 if (on) {
50 printf("======== PULL WL_REG_ON(%d) HIGH! ========\n", gpio_wl_reg_on);
51 if (gpio_wl_reg_on >= 0) {
52 err = gpio_direction_output(gpio_wl_reg_on, 1);
53 if (err) {
54 printf("%s: WL_REG_ON didn't output high\n", __FUNCTION__);
55 return -EIO;
56 }
57 }
58#ifdef CUSTOMER_HW_AMLOGIC
59 extern_wifi_set_enable(0);
60 mdelay(200);
61 extern_wifi_set_enable(1);
62 mdelay(200);
63// sdio_reinit();
64#endif
65#if defined(BUS_POWER_RESTORE)
66#if defined(BCMSDIO)
67 if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) {
68 printf("======== mmc_power_restore_host! ========\n");
69 mmc_power_restore_host(adapter->sdio_func->card->host);
70 }
71#elif defined(BCMPCIE)
72 OSL_SLEEP(50); /* delay needed to be able to restore PCIe configuration registers */
73 if (adapter->pci_dev) {
74 printf("======== pci_set_power_state PCI_D0! ========\n");
75 pci_set_power_state(adapter->pci_dev, PCI_D0);
76 if (adapter->pci_saved_state)
77 pci_load_and_free_saved_state(adapter->pci_dev, &adapter->pci_saved_state);
78 pci_restore_state(adapter->pci_dev);
79 err = pci_enable_device(adapter->pci_dev);
80 if (err < 0)
81 printf("%s: PCI enable device failed", __FUNCTION__);
82 pci_set_master(adapter->pci_dev);
83 }
84#endif /* BCMPCIE */
85#endif /* BUS_POWER_RESTORE */
86 /* Lets customer power to get stable */
87 mdelay(100);
88 } else {
89#if defined(BUS_POWER_RESTORE)
90#if defined(BCMSDIO)
91 if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) {
92 printf("======== mmc_power_save_host! ========\n");
93 mmc_power_save_host(adapter->sdio_func->card->host);
94 }
95#elif defined(BCMPCIE)
96 if (adapter->pci_dev) {
97 printf("======== pci_set_power_state PCI_D3hot! ========\n");
98 pci_save_state(adapter->pci_dev);
99 adapter->pci_saved_state = pci_store_saved_state(adapter->pci_dev);
100 if (pci_is_enabled(adapter->pci_dev))
101 pci_disable_device(adapter->pci_dev);
102 pci_set_power_state(adapter->pci_dev, PCI_D3hot);
103 }
104#endif /* BCMPCIE */
105#endif /* BUS_POWER_RESTORE */
106 printf("======== PULL WL_REG_ON(%d) LOW! ========\n", gpio_wl_reg_on);
107 if (gpio_wl_reg_on >= 0) {
108 err = gpio_direction_output(gpio_wl_reg_on, 0);
109 if (err) {
110 printf("%s: WL_REG_ON didn't output low\n", __FUNCTION__);
111 return -EIO;
112 }
113 }
114#ifdef CUSTOMER_HW_AMLOGIC
838773a6
LY
115 extern_wifi_set_enable(0);
116 mdelay(200);
010c3a89
RC
117#endif
118 }
119
120 return err;
121}
122
123static int dhd_wlan_set_reset(int onoff)
124{
125 return 0;
126}
127
128static int dhd_wlan_set_carddetect(int present)
129{
130 int err = 0;
131
132#if !defined(BUS_POWER_RESTORE)
133 if (present) {
134#if defined(BCMSDIO)
135 printf("======== Card detection to detect SDIO card! ========\n");
136#ifdef CUSTOMER_HW_PLATFORM
137 err = sdhci_force_presence_change(&sdmmc_channel, 1);
138#endif /* CUSTOMER_HW_PLATFORM */
139#ifdef CUSTOMER_HW_AMLOGIC
140 sdio_reinit();
141#endif
142#elif defined(BCMPCIE)
143 printf("======== Card detection to detect PCIE card! ========\n");
144#endif
145 } else {
146#if defined(BCMSDIO)
147 printf("======== Card detection to remove SDIO card! ========\n");
148#ifdef CUSTOMER_HW_PLATFORM
149 err = sdhci_force_presence_change(&sdmmc_channel, 0);
150#endif /* CUSTOMER_HW_PLATFORM */
151#ifdef CUSTOMER_HW_AMLOGIC
152 extern_wifi_set_enable(0);
153 mdelay(200);
154#endif
155#elif defined(BCMPCIE)
156 printf("======== Card detection to remove PCIE card! ========\n");
157#endif
158 }
159#endif /* BUS_POWER_RESTORE */
160
161 return err;
162}
163
164static int dhd_wlan_get_mac_addr(unsigned char *buf)
165{
166 int err = 0;
167
168 printf("======== %s ========\n", __FUNCTION__);
169#ifdef EXAMPLE_GET_MAC
170 /* EXAMPLE code */
171 {
172 struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
173 bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
174 }
175#endif /* EXAMPLE_GET_MAC */
176#ifdef EXAMPLE_GET_MAC_VER2
177 /* EXAMPLE code */
178 {
010c3a89
RC
179 char macpad[56]= {
180 0x00,0xaa,0x9c,0x84,0xc7,0xbc,0x9b,0xf6,
181 0x02,0x33,0xa9,0x4d,0x5c,0xb4,0x0a,0x5d,
182 0xa8,0xef,0xb0,0xcf,0x8e,0xbf,0x24,0x8a,
183 0x87,0x0f,0x6f,0x0d,0xeb,0x83,0x6a,0x70,
184 0x4a,0xeb,0xf6,0xe6,0x3c,0xe7,0x5f,0xfc,
185 0x0e,0xa7,0xb3,0x0f,0x00,0xe4,0x4a,0xaf,
186 0x87,0x08,0x16,0x6d,0x3a,0xe3,0xc7,0x80};
010c3a89
RC
187 bcopy(macpad, buf+6, sizeof(macpad));
188 }
189#endif /* EXAMPLE_GET_MAC_VER2 */
190
191 return err;
192}
010c3a89 193
010c3a89
RC
194static struct cntry_locales_custom brcm_wlan_translate_custom_table[] = {
195 /* Table should be filled out based on custom platform regulatory requirement */
91a2c117 196#ifdef EXAMPLE_TABLE
010c3a89
RC
197 {"", "XT", 49}, /* Universal if Country code is unknown or empty */
198 {"US", "US", 0},
91a2c117 199#endif /* EXMAPLE_TABLE */
010c3a89
RC
200};
201
202#ifdef CUSTOM_FORCE_NODFS_FLAG
203struct cntry_locales_custom brcm_wlan_translate_nodfs_table[] = {
91a2c117 204#ifdef EXAMPLE_TABLE
010c3a89
RC
205 {"", "XT", 50}, /* Universal if Country code is unknown or empty */
206 {"US", "US", 0},
91a2c117 207#endif /* EXMAPLE_TABLE */
010c3a89
RC
208};
209#endif
210
211static void *dhd_wlan_get_country_code(char *ccode
212#ifdef CUSTOM_FORCE_NODFS_FLAG
213 , u32 flags
214#endif
215)
216{
217 struct cntry_locales_custom *locales;
218 int size;
219 int i;
220
221 if (!ccode)
222 return NULL;
223
224#ifdef CUSTOM_FORCE_NODFS_FLAG
225 if (flags & WLAN_PLAT_NODFS_FLAG) {
226 locales = brcm_wlan_translate_nodfs_table;
227 size = ARRAY_SIZE(brcm_wlan_translate_nodfs_table);
228 } else {
229#endif
230 locales = brcm_wlan_translate_custom_table;
231 size = ARRAY_SIZE(brcm_wlan_translate_custom_table);
232#ifdef CUSTOM_FORCE_NODFS_FLAG
233 }
234#endif
235
236 for (i = 0; i < size; i++)
237 if (strcmp(ccode, locales[i].iso_abbrev) == 0)
238 return &locales[i];
239 return NULL;
240}
241
242struct resource dhd_wlan_resources[] = {
243 [0] = {
244 .name = "bcmdhd_wlan_irq",
245 .start = 0, /* Dummy */
246 .end = 0, /* Dummy */
247 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE
248 | IORESOURCE_IRQ_HIGHLEVEL, /* Dummy */
249 },
250};
251
252struct wifi_platform_data dhd_wlan_control = {
253 .set_power = dhd_wlan_set_power,
254 .set_reset = dhd_wlan_set_reset,
255 .set_carddetect = dhd_wlan_set_carddetect,
256 .get_mac_addr = dhd_wlan_get_mac_addr,
257#ifdef CONFIG_DHD_USE_STATIC_BUF
91a2c117 258 .mem_prealloc = bcmdhd_mem_prealloc,
010c3a89
RC
259#endif /* CONFIG_DHD_USE_STATIC_BUF */
260 .get_country_code = dhd_wlan_get_country_code,
261};
262
263int dhd_wlan_init_gpio(void)
264{
265 int err = 0;
266#ifdef CUSTOMER_OOB
267 int host_oob_irq = -1;
268 uint host_oob_irq_flags = 0;
269#endif
270
271 /* Please check your schematic and fill right GPIO number which connected to
272 * WL_REG_ON and WL_HOST_WAKE.
273 */
274 gpio_wl_reg_on = -1;
275#ifdef CUSTOMER_OOB
276 gpio_wl_host_wake = -1;
277#endif
278
010c3a89
RC
279 if (gpio_wl_reg_on >= 0) {
280 err = gpio_request(gpio_wl_reg_on, "WL_REG_ON");
281 if (err < 0) {
dfb0f3ae 282 printf("%s: gpio_request(%d) for WL_REG_ON failed\n",
010c3a89
RC
283 __FUNCTION__, gpio_wl_reg_on);
284 gpio_wl_reg_on = -1;
285 }
286 }
287
288#ifdef CUSTOMER_OOB
010c3a89
RC
289 if (gpio_wl_host_wake >= 0) {
290 err = gpio_request(gpio_wl_host_wake, "bcmdhd");
291 if (err < 0) {
dfb0f3ae
RC
292 printf("%s: gpio_request(%d) for WL_HOST_WAKE failed\n",
293 __FUNCTION__, gpio_wl_host_wake);
010c3a89
RC
294 return -1;
295 }
296 err = gpio_direction_input(gpio_wl_host_wake);
297 if (err < 0) {
dfb0f3ae
RC
298 printf("%s: gpio_direction_input(%d) for WL_HOST_WAKE failed\n",
299 __FUNCTION__, gpio_wl_host_wake);
010c3a89
RC
300 gpio_free(gpio_wl_host_wake);
301 return -1;
302 }
303 host_oob_irq = gpio_to_irq(gpio_wl_host_wake);
304 if (host_oob_irq < 0) {
dfb0f3ae
RC
305 printf("%s: gpio_to_irq(%d) for WL_HOST_WAKE failed\n",
306 __FUNCTION__, gpio_wl_host_wake);
010c3a89
RC
307 gpio_free(gpio_wl_host_wake);
308 return -1;
309 }
310 }
311#ifdef CUSTOMER_HW_AMLOGIC
312#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
313 host_oob_irq = INT_GPIO_4;
314#else
315 host_oob_irq = wifi_irq_num();
316#endif
317#endif
010c3a89
RC
318
319#ifdef HW_OOB
320#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
321 if (wifi_irq_trigger_level() == GPIO_IRQ_LOW)
322 host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_SHAREABLE;
323 else
324 host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE;
325#else
326#ifdef HW_OOB_LOW_LEVEL
327 host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_SHAREABLE;
328#else
329 host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE;
330#endif
331#endif
332#else
333 host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_SHAREABLE;
334#endif
335
336 dhd_wlan_resources[0].start = dhd_wlan_resources[0].end = host_oob_irq;
337 dhd_wlan_resources[0].flags = host_oob_irq_flags;
838773a6
LY
338 printf("%s: WL_REG_ON=%d, WL_HOST_WAKE=%d\n", __FUNCTION__, gpio_wl_reg_on, gpio_wl_host_wake);
339 printf("%s: oob_irq=%d, oob_irq_flags=0x%x\n", __FUNCTION__, host_oob_irq, host_oob_irq_flags);
010c3a89
RC
340#endif /* CUSTOMER_OOB */
341
342 return 0;
343}
344
345static void dhd_wlan_deinit_gpio(void)
346{
347 if (gpio_wl_reg_on >= 0) {
348 printf("%s: gpio_free(WL_REG_ON %d)\n", __FUNCTION__, gpio_wl_reg_on);
349 gpio_free(gpio_wl_reg_on);
350 gpio_wl_reg_on = -1;
351 }
352#ifdef CUSTOMER_OOB
353 if (gpio_wl_host_wake >= 0) {
354 printf("%s: gpio_free(WL_HOST_WAKE %d)\n", __FUNCTION__, gpio_wl_host_wake);
355 gpio_free(gpio_wl_host_wake);
356 gpio_wl_host_wake = -1;
357 }
358#endif /* CUSTOMER_OOB */
359}
360
361int dhd_wlan_init_plat_data(void)
362{
363 int err = 0;
364
365 printf("======== %s ========\n", __FUNCTION__);
366 err = dhd_wlan_init_gpio();
367 return err;
368}
369
370void dhd_wlan_deinit_plat_data(wifi_adapter_info_t *adapter)
371{
372 printf("======== %s ========\n", __FUNCTION__);
373 dhd_wlan_deinit_gpio();
374}
375