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