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