• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #include <osl.h>
3 #include <dhd_linux.h>
4 #include <linux/gpio.h>
5 
6 #if defined(BUS_POWER_RESTORE) && defined(BCMSDIO)
7 #include <linux/mmc/core.h>
8 #include <linux/mmc/card.h>
9 #include <linux/mmc/host.h>
10 #include <linux/mmc/sdio_func.h>
11 #endif /* defined(BUS_POWER_RESTORE) && defined(BCMSDIO) */
12 
13 #ifdef CONFIG_DHD_USE_STATIC_BUF
14 #ifdef DHD_STATIC_IN_DRIVER
15 extern int dhd_static_buf_init(void);
16 extern void dhd_static_buf_exit(void);
17 #endif /* DHD_STATIC_IN_DRIVER */
18 #ifdef BCMDHD_MDRIVER
19 extern void *dhd_wlan_mem_prealloc(uint bus_type, int index, int section,
20                                    unsigned long size);
21 #else
22 extern void *dhd_wlan_mem_prealloc(int section, unsigned long size);
23 #endif
24 #endif /* CONFIG_DHD_USE_STATIC_BUF */
25 
26 #ifdef BCMDHD_DTS
27 /* This is sample code in dts file.
28 bcmdhd {
29     compatible = "android,bcmdhd_wlan";
30     gpio_wl_reg_on = <&gpio GPIOH_4 GPIO_ACTIVE_HIGH>;
31     gpio_wl_host_wake = <&gpio GPIOZ_15 GPIO_ACTIVE_HIGH>;
32 };
33 */
34 #define DHD_DT_COMPAT_ENTRY "android,bcmdhd_wlan"
35 #define GPIO_WL_REG_ON_PROPNAME "gpio_wl_reg_on"
36 #define GPIO_WL_HOST_WAKE_PROPNAME "gpio_wl_host_wake"
37 #endif
38 
39 #ifdef CUSTOMER_HW_ALLWINNER
40 extern void sunxi_mmc_rescan_card(unsigned ids);
41 extern void sunxi_wlan_set_power(int on);
42 extern int sunxi_wlan_get_bus_index(void);
43 extern int sunxi_wlan_get_oob_irq(void);
44 extern int sunxi_wlan_get_oob_irq_flags(void);
45 
46 /* Customer specifia wifi mac addr file */
47 #define WIFIMAC_PATH "/mnt/factory/ULI/factory/mac.txt"
48 #endif
49 
dhd_wlan_set_power(int on,wifi_adapter_info_t * adapter)50 static int dhd_wlan_set_power(int on, wifi_adapter_info_t *adapter)
51 {
52     int gpio_wl_reg_on = adapter->gpio_wl_reg_on;
53     int err = 0;
54 
55     if (on) {
56         printf("======== PULL WL_REG_ON(%d) HIGH! ========\n", gpio_wl_reg_on);
57         if (gpio_wl_reg_on >= 0) {
58             err = gpio_direction_output(gpio_wl_reg_on, 1);
59             if (err) {
60                 printf("%s: WL_REG_ON didn't output high\n", __FUNCTION__);
61                 return -EIO;
62             }
63         }
64 #ifdef CUSTOMER_HW_ALLWINNER
65         sunxi_wlan_set_power(1);
66 #endif
67 #ifdef BUS_POWER_RESTORE
68 #ifdef BCMSDIO
69 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) &&                          \
70     LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
71         if (adapter->sdio_func && adapter->sdio_func->card &&
72             adapter->sdio_func->card->host) {
73             mdelay(0x64);
74             printf("======== mmc_power_restore_host! ========\n");
75             mmc_power_restore_host(adapter->sdio_func->card->host);
76         }
77 #endif
78 #elif defined(BCMPCIE)
79         if (adapter->pci_dev) {
80             mdelay(0x64);
81             printf("======== pci_set_power_state PCI_D0! ========\n");
82             pci_set_power_state(adapter->pci_dev, PCI_D0);
83             if (adapter->pci_saved_state) {
84                 pci_load_and_free_saved_state(adapter->pci_dev,
85                                               &adapter->pci_saved_state);
86             }
87             pci_restore_state(adapter->pci_dev);
88             err = pci_enable_device(adapter->pci_dev);
89             if (err < 0) {
90                 printf("%s: PCI enable device failed", __FUNCTION__);
91             }
92             pci_set_master(adapter->pci_dev);
93         }
94 #endif /* BCMPCIE */
95 #endif /* BUS_POWER_RESTORE */
96         /* Lets customer power to get stable */
97         mdelay(0x64);
98     } else {
99 #ifdef BUS_POWER_RESTORE
100 #ifdef BCMSDIO
101 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) &&                          \
102     LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
103         if (adapter->sdio_func && adapter->sdio_func->card &&
104             adapter->sdio_func->card->host) {
105             printf("======== mmc_power_save_host! ========\n");
106             mmc_power_save_host(adapter->sdio_func->card->host);
107         }
108 #endif
109 #elif defined(BCMPCIE)
110         if (adapter->pci_dev) {
111             printf("======== pci_set_power_state PCI_D3hot! ========\n");
112             pci_save_state(adapter->pci_dev);
113             adapter->pci_saved_state = pci_store_saved_state(adapter->pci_dev);
114             if (pci_is_enabled(adapter->pci_dev)) {
115                 pci_disable_device(adapter->pci_dev);
116             }
117             pci_set_power_state(adapter->pci_dev, PCI_D3hot);
118         }
119 #endif /* BCMPCIE */
120 #endif /* BUS_POWER_RESTORE */
121         printf("======== PULL WL_REG_ON(%d) LOW! ========\n", gpio_wl_reg_on);
122         if (gpio_wl_reg_on >= 0) {
123             err = gpio_direction_output(gpio_wl_reg_on, 0);
124             if (err) {
125                 printf("%s: WL_REG_ON didn't output low\n", __FUNCTION__);
126                 return -EIO;
127             }
128         }
129 #ifdef CUSTOMER_HW_ALLWINNER
130         sunxi_wlan_set_power(0);
131 #endif
132     }
133 
134     return err;
135 }
136 
dhd_wlan_set_reset(int onoff)137 static int dhd_wlan_set_reset(int onoff)
138 {
139     return 0;
140 }
141 
dhd_wlan_set_carddetect(int present)142 static int dhd_wlan_set_carddetect(int present)
143 {
144     int err = 0;
145 #ifdef CUSTOMER_HW_ALLWINNER
146     int wlan_bus_index = sunxi_wlan_get_bus_index();
147     if (wlan_bus_index < 0) {
148         return wlan_bus_index;
149     }
150 #endif
151 
152 #if !defined(BUS_POWER_RESTORE)
153     if (present) {
154 #if defined(BCMSDIO)
155         printf("======== Card detection to detect SDIO card! ========\n");
156 #ifdef CUSTOMER_HW_PLATFORM
157         err = sdhci_force_presence_change(&sdmmc_channel, 1);
158 #endif /* CUSTOMER_HW_PLATFORM */
159 #ifdef CUSTOMER_HW_ALLWINNER
160         sunxi_mmc_rescan_card(wlan_bus_index);
161 #endif
162 #elif defined(BCMPCIE)
163         printf("======== Card detection to detect PCIE card! ========\n");
164 #endif
165     } else {
166 #if defined(BCMSDIO)
167         printf("======== Card detection to remove SDIO card! ========\n");
168 #ifdef CUSTOMER_HW_PLATFORM
169         err = sdhci_force_presence_change(&sdmmc_channel, 0);
170 #endif /* CUSTOMER_HW_PLATFORM */
171 #ifdef CUSTOMER_HW_ALLWINNER
172         sunxi_mmc_rescan_card(wlan_bus_index);
173 #endif
174 #elif defined(BCMPCIE)
175         printf("======== Card detection to remove PCIE card! ========\n");
176 #endif
177     }
178 #endif /* BUS_POWER_RESTORE */
179 
180     return err;
181 }
182 
dhd_wlan_get_mac_addr(unsigned char * buf,int ifidx)183 static int dhd_wlan_get_mac_addr(unsigned char *buf, int ifidx)
184 {
185     int err = 0;
186 
187     if (ifidx == 1) {
188 #ifdef EXAMPLE_GET_MAC
189         struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
190         bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
191 #endif /* EXAMPLE_GET_MAC */
192     } else {
193 #ifdef EXAMPLE_GET_MAC
194         struct ether_addr ea_example = {{0x02, 0x11, 0x22, 0x33, 0x44, 0x55}};
195         bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
196 #endif /* EXAMPLE_GET_MAC */
197     }
198 
199 #ifdef EXAMPLE_GET_MAC_VER2
200     /* EXAMPLE code */
201     {
202         char macpad[56] = {0x00, 0xaa, 0x9c, 0x84, 0xc7, 0xbc, 0x9b, 0xf6,
203                            0x02, 0x33, 0xa9, 0x4d, 0x5c, 0xb4, 0x0a, 0x5d,
204                            0xa8, 0xef, 0xb0, 0xcf, 0x8e, 0xbf, 0x24, 0x8a,
205                            0x87, 0x0f, 0x6f, 0x0d, 0xeb, 0x83, 0x6a, 0x70,
206                            0x4a, 0xeb, 0xf6, 0xe6, 0x3c, 0xe7, 0x5f, 0xfc,
207                            0x0e, 0xa7, 0xb3, 0x0f, 0x00, 0xe4, 0x4a, 0xaf,
208                            0x87, 0x08, 0x16, 0x6d, 0x3a, 0xe3, 0xc7, 0x80};
209         bcopy(macpad, buf + 0x6, sizeof(macpad));
210     }
211 #endif /* EXAMPLE_GET_MAC_VER2 */
212 
213     printf("======== %s err=%d ========\n", __FUNCTION__, err);
214 
215     return err;
216 }
217 
218 static struct cntry_locales_custom brcm_wlan_translate_custom_table[] = {
219 /* Table should be filled out based on custom platform regulatory requirement */
220 #ifdef EXAMPLE_TABLE
221     {"", "XT", 49}, /* Universal if Country code is unknown or empty */
222     {"US", "US", 0},
223 #endif /* EXMAPLE_TABLE */
224 };
225 
226 #ifdef CUSTOM_FORCE_NODFS_FLAG
227 struct cntry_locales_custom brcm_wlan_translate_nodfs_table[] = {
228 #ifdef EXAMPLE_TABLE
229     {"", "XT", 50}, /* Universal if Country code is unknown or empty */
230     {"US", "US", 0},
231 #endif /* EXMAPLE_TABLE */
232 };
233 #endif
234 
dhd_wlan_get_country_code(char * ccode,u32 flags)235 static void *dhd_wlan_get_country_code(char *ccode
236 #ifdef CUSTOM_FORCE_NODFS_FLAG
237                                        ,
238                                        u32 flags
239 #endif
240 )
241 {
242     struct cntry_locales_custom *locales;
243     int size;
244     int i;
245 
246     if (!ccode) {
247         return NULL;
248     }
249 
250 #ifdef CUSTOM_FORCE_NODFS_FLAG
251     if (flags & WLAN_PLAT_NODFS_FLAG) {
252         locales = brcm_wlan_translate_nodfs_table;
253         size = ARRAY_SIZE(brcm_wlan_translate_nodfs_table);
254     } else {
255 #endif
256         locales = brcm_wlan_translate_custom_table;
257         size = ARRAY_SIZE(brcm_wlan_translate_custom_table);
258 #ifdef CUSTOM_FORCE_NODFS_FLAG
259     }
260 #endif
261 
262     for (i = 0; i < size; i++) {
263         if (strcmp(ccode, locales[i].iso_abbrev) == 0) {
264             return &locales[i];
265         }
266     }
267     return NULL;
268 }
269 
270 struct wifi_platform_data dhd_wlan_control = {
271     .set_power = dhd_wlan_set_power,
272     .set_reset = dhd_wlan_set_reset,
273     .set_carddetect = dhd_wlan_set_carddetect,
274     .get_mac_addr = dhd_wlan_get_mac_addr,
275 #ifdef CONFIG_DHD_USE_STATIC_BUF
276     .mem_prealloc = dhd_wlan_mem_prealloc,
277 #endif /* CONFIG_DHD_USE_STATIC_BUF */
278     .get_country_code = dhd_wlan_get_country_code,
279 };
280 
dhd_wlan_init_gpio(wifi_adapter_info_t * adapter)281 int dhd_wlan_init_gpio(wifi_adapter_info_t *adapter)
282 {
283 #ifdef BCMDHD_DTS
284     char wlan_node[32];
285     struct device_node *root_node = NULL;
286 #endif
287     int err = 0;
288     int gpio_wl_reg_on;
289 #ifdef CUSTOMER_OOB
290     int gpio_wl_host_wake;
291     int host_oob_irq = -1;
292     uint host_oob_irq_flags = 0;
293 #endif
294 
295     /* Please check your schematic and fill right GPIO number which connected to
296      * WL_REG_ON and WL_HOST_WAKE.
297      */
298 #ifdef BCMDHD_DTS
299     strcpy(wlan_node, DHD_DT_COMPAT_ENTRY);
300     printf("======== Get GPIO from DTS(%s) ========\n", wlan_node);
301     root_node = of_find_compatible_node(NULL, NULL, wlan_node);
302     if (root_node) {
303         gpio_wl_reg_on =
304             of_get_named_gpio(root_node, GPIO_WL_REG_ON_PROPNAME, 0);
305 #ifdef CUSTOMER_OOB
306         gpio_wl_host_wake =
307             of_get_named_gpio(root_node, GPIO_WL_HOST_WAKE_PROPNAME, 0);
308 #endif
309     } else
310 #endif
311     {
312         gpio_wl_reg_on = -1;
313 #ifdef CUSTOMER_OOB
314         gpio_wl_host_wake = -1;
315 #endif
316     }
317 
318     if (gpio_wl_reg_on >= 0) {
319         err = gpio_request(gpio_wl_reg_on, "WL_REG_ON");
320         if (err < 0) {
321             printf("%s: gpio_request(%d) for WL_REG_ON failed\n", __FUNCTION__,
322                    gpio_wl_reg_on);
323             gpio_wl_reg_on = -1;
324         }
325     }
326     adapter->gpio_wl_reg_on = gpio_wl_reg_on;
327 
328 #ifdef CUSTOMER_OOB
329     if (gpio_wl_host_wake >= 0) {
330         err = gpio_request(gpio_wl_host_wake, "bcmdhd");
331         if (err < 0) {
332             printf("%s: gpio_request(%d) for WL_HOST_WAKE failed\n",
333                    __FUNCTION__, gpio_wl_host_wake);
334             return -1;
335         }
336         adapter->gpio_wl_host_wake = gpio_wl_host_wake;
337         err = gpio_direction_input(gpio_wl_host_wake);
338         if (err < 0) {
339             printf("%s: gpio_direction_input(%d) for WL_HOST_WAKE failed\n",
340                    __FUNCTION__, gpio_wl_host_wake);
341             gpio_free(gpio_wl_host_wake);
342             return -1;
343         }
344         host_oob_irq = gpio_to_irq(gpio_wl_host_wake);
345         if (host_oob_irq < 0) {
346             printf("%s: gpio_to_irq(%d) for WL_HOST_WAKE failed\n",
347                    __FUNCTION__, gpio_wl_host_wake);
348             gpio_free(gpio_wl_host_wake);
349             return -1;
350         }
351     }
352 
353 #ifdef HW_OOB
354 #ifdef HW_OOB_LOW_LEVEL
355     host_oob_irq_flags =
356         IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_SHAREABLE;
357 #else
358     host_oob_irq_flags =
359         IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE;
360 #endif
361 #else
362     host_oob_irq_flags =
363         IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_SHAREABLE;
364 #endif
365 #ifdef CUSTOMER_HW_ALLWINNER
366 #ifdef HW_OOB
367     host_oob_irq_flags = sunxi_wlan_get_oob_irq_flags();
368 #endif
369 #endif
370     host_oob_irq_flags &= IRQF_TRIGGER_MASK;
371 
372     adapter->irq_num = host_oob_irq;
373     adapter->intr_flags = host_oob_irq_flags;
374     printf("%s: WL_HOST_WAKE=%d, oob_irq=%d, oob_irq_flags=0x%x\n",
375            __FUNCTION__, gpio_wl_host_wake, host_oob_irq, host_oob_irq_flags);
376 #endif /* CUSTOMER_OOB */
377     printf("%s: WL_REG_ON=%d\n", __FUNCTION__, gpio_wl_reg_on);
378 
379     return 0;
380 }
381 
dhd_wlan_deinit_gpio(wifi_adapter_info_t * adapter)382 static void dhd_wlan_deinit_gpio(wifi_adapter_info_t *adapter)
383 {
384     int gpio_wl_reg_on = adapter->gpio_wl_reg_on;
385 #ifdef CUSTOMER_OOB
386     int gpio_wl_host_wake = adapter->gpio_wl_host_wake;
387 #endif
388 
389     if (gpio_wl_reg_on >= 0) {
390         printf("%s: gpio_free(WL_REG_ON %d)\n", __FUNCTION__, gpio_wl_reg_on);
391         gpio_free(gpio_wl_reg_on);
392         gpio_wl_reg_on = -1;
393     }
394 #ifdef CUSTOMER_OOB
395     if (gpio_wl_host_wake >= 0) {
396         printf("%s: gpio_free(WL_HOST_WAKE %d)\n", __FUNCTION__,
397                gpio_wl_host_wake);
398         gpio_free(gpio_wl_host_wake);
399         gpio_wl_host_wake = -1;
400     }
401 #endif /* CUSTOMER_OOB */
402 }
403 
dhd_wlan_init_plat_data(wifi_adapter_info_t * adapter)404 int dhd_wlan_init_plat_data(wifi_adapter_info_t *adapter)
405 {
406     int err = 0;
407 
408     printf("======== %s ========\n", __FUNCTION__);
409     if (adapter->index == -1) {
410         adapter->index = 0;
411     }
412     err = dhd_wlan_init_gpio(adapter);
413 
414 #ifdef DHD_STATIC_IN_DRIVER
415     dhd_static_buf_init();
416 #endif
417     return err;
418 }
419 
dhd_wlan_deinit_plat_data(wifi_adapter_info_t * adapter)420 void dhd_wlan_deinit_plat_data(wifi_adapter_info_t *adapter)
421 {
422     printf("======== %s ========\n", __FUNCTION__);
423 #ifdef DHD_STATIC_IN_DRIVER
424     dhd_static_buf_exit();
425 #endif
426     dhd_wlan_deinit_gpio(adapter);
427 }
428