2 * Linux platform device for DHD WLAN adapter
4 * Copyright (C) 2020, Broadcom.
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
21 * <<Broadcom-WL-IPTag/Open:>>
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/platform_device.h>
31 #include <linux_osl.h>
33 #include <dngl_stats.h>
36 #include <dhd_linux.h>
37 #include <wl_android.h>
38 #if defined(CONFIG_WIFI_CONTROL_FUNC)
39 #include <linux/wlan_plat.h>
42 #include<linux/regulator/consumer.h>
43 #include<linux/of_gpio.h>
44 #endif /* CONFIG_DTS */
46 #if defined(CUSTOMER_HW)
47 extern int dhd_wlan_init_plat_data(void);
48 extern void dhd_wlan_deinit_plat_data(wifi_adapter_info_t
*adapter
);
49 #endif /* CUSTOMER_HW */
51 #define WIFI_PLAT_NAME "bcmdhd_wlan"
52 #define WIFI_PLAT_NAME2 "bcm4329_wlan"
53 #define WIFI_PLAT_EXT "bcmdhd_wifi_platform"
55 #ifdef DHD_WIFI_SHUTDOWN
56 extern void wifi_plat_dev_drv_shutdown(struct platform_device
*pdev
);
60 struct regulator
*wifi_regulator
= NULL
;
61 #endif /* CONFIG_DTS */
63 bool cfg_multichip
= FALSE
;
64 bcmdhd_wifi_platdata_t
*dhd_wifi_platdata
= NULL
;
65 static int wifi_plat_dev_probe_ret
= 0;
66 static bool is_power_on
= FALSE
;
67 /* XXX Some Qualcomm based CUSTOMER_HW4 platforms are using platform
68 * device structure even if the Kernel uses device tree structure.
69 * Therefore, the CONFIG_ARCH_MSM condition is temporarly remained
70 * to support in this case.
72 #if !defined(CONFIG_DTS)
73 #if defined(DHD_OF_SUPPORT)
74 static bool dts_enabled
= TRUE
;
75 extern struct resource dhd_wlan_resources
;
76 extern struct wifi_platform_data dhd_wlan_control
;
78 static bool dts_enabled
= FALSE
;
79 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
80 #pragma GCC diagnostic push
81 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
83 struct resource dhd_wlan_resources
= {0};
84 struct wifi_platform_data dhd_wlan_control
= {0};
85 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
86 #pragma GCC diagnostic pop
88 #endif /* CONFIG_OF && !defined(CONFIG_ARCH_MSM) */
89 #endif /* !defind(CONFIG_DTS) */
91 static int dhd_wifi_platform_load(void);
93 extern void* wl_cfg80211_get_dhdp(struct net_device
*dev
);
96 extern int dhd_wlan_init(void);
97 extern int dhd_wlan_deinit(void);
98 #endif /* BCMDHD_MODULAR */
100 #ifdef ENABLE_4335BT_WAR
101 extern int bcm_bt_lock(int cookie
);
102 extern void bcm_bt_unlock(int cookie
);
103 static int lock_cookie_wifi
= 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24; /* cookie is "WiFi" */
104 #endif /* ENABLE_4335BT_WAR */
106 #ifdef BCM4335_XTAL_WAR
107 extern bool check_bcm4335_rev(void);
108 #endif /* BCM4335_XTAL_WAR */
110 wifi_adapter_info_t
* dhd_wifi_platform_attach_adapter(uint32 bus_type
,
111 uint32 bus_num
, uint32 slot_num
, unsigned long status
)
115 if (dhd_wifi_platdata
== NULL
)
118 for (i
= 0; i
< dhd_wifi_platdata
->num_adapters
; i
++) {
119 wifi_adapter_info_t
*adapter
= &dhd_wifi_platdata
->adapters
[i
];
120 if ((adapter
->bus_type
== -1 || adapter
->bus_type
== bus_type
) &&
121 (adapter
->bus_num
== -1 || adapter
->bus_num
== bus_num
) &&
122 (adapter
->slot_num
== -1 || adapter
->slot_num
== slot_num
)
123 #if defined(ENABLE_INSMOD_NO_FW_LOAD)
124 && (wifi_chk_adapter_status(adapter
, status
))
127 DHD_ERROR(("attach adapter info '%s'\n", adapter
->name
));
134 wifi_adapter_info_t
* dhd_wifi_platform_get_adapter(uint32 bus_type
, uint32 bus_num
, uint32 slot_num
)
138 if (dhd_wifi_platdata
== NULL
)
141 for (i
= 0; i
< dhd_wifi_platdata
->num_adapters
; i
++) {
142 wifi_adapter_info_t
*adapter
= &dhd_wifi_platdata
->adapters
[i
];
143 if ((adapter
->bus_type
== -1 || adapter
->bus_type
== bus_type
) &&
144 (adapter
->bus_num
== -1 || adapter
->bus_num
== bus_num
) &&
145 (adapter
->slot_num
== -1 || adapter
->slot_num
== slot_num
)) {
146 DHD_TRACE(("found adapter info '%s'\n", adapter
->name
));
153 void* wifi_platform_prealloc(wifi_adapter_info_t
*adapter
, int section
, unsigned long size
)
155 void *alloc_ptr
= NULL
;
156 struct wifi_platform_data
*plat_data
;
158 if (!adapter
|| !adapter
->wifi_plat_data
)
160 plat_data
= adapter
->wifi_plat_data
;
161 if (plat_data
->mem_prealloc
) {
162 alloc_ptr
= plat_data
->mem_prealloc(section
, size
);
164 DHD_INFO(("success alloc section %d\n", section
));
166 bzero(alloc_ptr
, size
);
172 DHD_ERROR(("%s: failed to alloc static mem section %d\n", __FUNCTION__
, section
));
176 void* wifi_platform_get_prealloc_func_ptr(wifi_adapter_info_t
*adapter
)
178 struct wifi_platform_data
*plat_data
;
180 if (!adapter
|| !adapter
->wifi_plat_data
)
182 plat_data
= adapter
->wifi_plat_data
;
183 return plat_data
->mem_prealloc
;
186 int wifi_platform_get_irq_number(wifi_adapter_info_t
*adapter
, unsigned long *irq_flags_ptr
)
191 *irq_flags_ptr
= adapter
->intr_flags
;
192 return adapter
->irq_num
;
195 int wifi_platform_set_power(wifi_adapter_info_t
*adapter
, bool on
, unsigned long msec
)
199 struct wifi_platform_data
*plat_data
;
202 if (is_power_on
== on
) {
205 #endif /* BT_OVER_SDIO */
207 wifi_set_adapter_status(adapter
, WIFI_STATUS_POWER_ON
);
209 wifi_clr_adapter_status(adapter
, WIFI_STATUS_POWER_ON
);
213 printf("======== PULL WL_REG_ON HIGH! ========\n");
214 err
= regulator_enable(wifi_regulator
);
218 printf("======== PULL WL_REG_ON LOW! ========\n");
219 err
= regulator_disable(wifi_regulator
);
223 DHD_ERROR(("%s: regulator enable/disable failed", __FUNCTION__
));
227 if (!adapter
|| !adapter
->wifi_plat_data
) {
231 plat_data
= adapter
->wifi_plat_data
;
233 DHD_ERROR(("%s = %d, delay: %lu msec\n", __FUNCTION__
, on
, msec
));
234 if (plat_data
->set_power
) {
235 #ifdef ENABLE_4335BT_WAR
237 printk("WiFi: trying to acquire BT lock\n");
238 if (bcm_bt_lock(lock_cookie_wifi
) != 0)
239 printk("** WiFi: timeout in acquiring bt lock**\n");
240 printk("%s: btlock acquired\n", __FUNCTION__
);
243 /* For a exceptional case, release btlock */
244 bcm_bt_unlock(lock_cookie_wifi
);
246 #endif /* ENABLE_4335BT_WAR */
248 #ifdef BUS_POWER_RESTORE
249 err
= plat_data
->set_power(on
, adapter
);
251 err
= plat_data
->set_power(on
);
263 #endif /* CONFIG_DTS */
268 wifi_clr_adapter_status(adapter
, WIFI_STATUS_POWER_ON
);
270 wifi_set_adapter_status(adapter
, WIFI_STATUS_POWER_ON
);
275 int wifi_platform_bus_enumerate(wifi_adapter_info_t
*adapter
, bool device_present
)
278 struct wifi_platform_data
*plat_data
;
280 if (!adapter
|| !adapter
->wifi_plat_data
)
282 plat_data
= adapter
->wifi_plat_data
;
284 DHD_ERROR(("%s device present %d\n", __FUNCTION__
, device_present
));
285 if (plat_data
->set_carddetect
) {
286 err
= plat_data
->set_carddetect(device_present
);
292 int wifi_platform_get_mac_addr(wifi_adapter_info_t
*adapter
, unsigned char *buf
,
295 struct wifi_platform_data
*plat_data
;
297 DHD_ERROR(("%s\n", __FUNCTION__
));
298 if (!buf
|| !adapter
|| !adapter
->wifi_plat_data
)
300 plat_data
= adapter
->wifi_plat_data
;
301 if (plat_data
->get_mac_addr
) {
302 #ifdef CUSTOM_MULTI_MAC
303 return plat_data
->get_mac_addr(buf
, name
);
305 return plat_data
->get_mac_addr(buf
);
312 #ifdef CUSTOM_COUNTRY_CODE
313 wifi_platform_get_country_code(wifi_adapter_info_t
*adapter
, char *ccode
, u32 flags
)
315 wifi_platform_get_country_code(wifi_adapter_info_t
*adapter
, char *ccode
)
316 #endif /* CUSTOM_COUNTRY_CODE */
318 /* get_country_code was added after 2.6.39 */
319 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
320 struct wifi_platform_data
*plat_data
;
322 if (!ccode
|| !adapter
|| !adapter
->wifi_plat_data
)
324 plat_data
= adapter
->wifi_plat_data
;
326 DHD_TRACE(("%s\n", __FUNCTION__
));
327 if (plat_data
->get_country_code
) {
328 #ifdef CUSTOM_FORCE_NODFS_FLAG
329 return plat_data
->get_country_code(ccode
, flags
);
331 return plat_data
->get_country_code(ccode
);
332 #endif /* CUSTOM_COUNTRY_CODE */
334 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
340 static int wifi_plat_dev_drv_probe(struct platform_device
*pdev
)
342 struct resource
*resource
;
343 wifi_adapter_info_t
*adapter
;
344 #if defined(CONFIG_DTS) && defined(CUSTOMER_OOB)
346 #endif /* CONFIG_DTS */
348 /* Android style wifi platform data device ("bcmdhd_wlan" or "bcm4329_wlan")
349 * is kept for backward compatibility and supports only 1 adapter
351 ASSERT(dhd_wifi_platdata
!= NULL
);
352 ASSERT(dhd_wifi_platdata
->num_adapters
== 1);
353 adapter
= &dhd_wifi_platdata
->adapters
[0];
354 #if defined(CONFIG_WIFI_CONTROL_FUNC)
355 adapter
->wifi_plat_data
= (struct wifi_platform_data
*)(pdev
->dev
.platform_data
);
357 adapter
->wifi_plat_data
= (void *)&dhd_wlan_control
;
360 resource
= platform_get_resource_byname(pdev
, IORESOURCE_IRQ
, "bcmdhd_wlan_irq");
361 if (resource
== NULL
)
362 resource
= platform_get_resource_byname(pdev
, IORESOURCE_IRQ
, "bcm4329_wlan_irq");
364 adapter
->irq_num
= resource
->start
;
365 adapter
->intr_flags
= resource
->flags
& IRQF_TRIGGER_MASK
;
366 #ifdef DHD_ISR_NO_SUSPEND
367 adapter
->intr_flags
|= IRQF_NO_SUSPEND
;
372 wifi_regulator
= regulator_get(&pdev
->dev
, "wlreg_on");
373 if (wifi_regulator
== NULL
) {
374 DHD_ERROR(("%s regulator is null\n", __FUNCTION__
));
378 #if defined(CUSTOMER_OOB)
379 /* This is to get the irq for the OOB */
380 gpio
= of_get_gpio(pdev
->dev
.of_node
, 0);
383 DHD_ERROR(("%s gpio information is incorrect\n", __FUNCTION__
));
386 irq
= gpio_to_irq(gpio
);
388 DHD_ERROR(("%s irq information is incorrect\n", __FUNCTION__
));
391 adapter
->irq_num
= irq
;
393 /* need to change the flags according to our requirement */
394 adapter
->intr_flags
= IORESOURCE_IRQ
| IORESOURCE_IRQ_HIGHLEVEL
|
395 IORESOURCE_IRQ_SHAREABLE
;
397 #endif /* CONFIG_DTS */
399 wifi_plat_dev_probe_ret
= dhd_wifi_platform_load();
400 return wifi_plat_dev_probe_ret
;
403 static int wifi_plat_dev_drv_remove(struct platform_device
*pdev
)
405 wifi_adapter_info_t
*adapter
;
407 /* Android style wifi platform data device ("bcmdhd_wlan" or "bcm4329_wlan")
408 * is kept for backward compatibility and supports only 1 adapter
410 ASSERT(dhd_wifi_platdata
!= NULL
);
411 ASSERT(dhd_wifi_platdata
->num_adapters
== 1);
412 adapter
= &dhd_wifi_platdata
->adapters
[0];
415 wifi_platform_bus_enumerate(adapter
, FALSE
);
416 wifi_platform_set_power(adapter
, FALSE
, WIFI_TURNOFF_DELAY
);
418 wifi_platform_set_power(adapter
, FALSE
, WIFI_TURNOFF_DELAY
);
419 wifi_platform_bus_enumerate(adapter
, FALSE
);
424 regulator_put(wifi_regulator
);
425 #endif /* CONFIG_DTS */
429 static int wifi_plat_dev_drv_suspend(struct platform_device
*pdev
, pm_message_t state
)
431 DHD_TRACE(("##> %s\n", __FUNCTION__
));
432 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && \
434 bcmsdh_oob_intr_set(0);
435 #endif /* (OOB_INTR_ONLY) */
439 static int wifi_plat_dev_drv_resume(struct platform_device
*pdev
)
441 DHD_TRACE(("##> %s\n", __FUNCTION__
));
442 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && \
444 if (dhd_os_check_if_up(wl_cfg80211_get_dhdp()))
445 bcmsdh_oob_intr_set(1);
446 #endif /* (OOB_INTR_ONLY) */
451 static const struct of_device_id wifi_device_dt_match
[] = {
452 { .compatible
= "android,bcmdhd_wlan", },
455 #endif /* CONFIG_DTS */
457 static struct platform_driver wifi_platform_dev_driver
= {
458 .probe
= wifi_plat_dev_drv_probe
,
459 .remove
= wifi_plat_dev_drv_remove
,
460 .suspend
= wifi_plat_dev_drv_suspend
,
461 .resume
= wifi_plat_dev_drv_resume
,
462 #ifdef DHD_WIFI_SHUTDOWN
463 .shutdown
= wifi_plat_dev_drv_shutdown
,
464 #endif /* DHD_WIFI_SHUTDOWN */
466 .name
= WIFI_PLAT_NAME
,
468 .of_match_table
= wifi_device_dt_match
,
469 #endif /* CONFIG_DTS */
473 static struct platform_driver wifi_platform_dev_driver_legacy
= {
474 .probe
= wifi_plat_dev_drv_probe
,
475 .remove
= wifi_plat_dev_drv_remove
,
476 .suspend
= wifi_plat_dev_drv_suspend
,
477 .resume
= wifi_plat_dev_drv_resume
,
478 #ifdef DHD_WIFI_SHUTDOWN
479 .shutdown
= wifi_plat_dev_drv_shutdown
,
480 #endif /* DHD_WIFI_SHUTDOWN */
482 .name
= WIFI_PLAT_NAME2
,
486 static int wifi_platdev_match(struct device
*dev
, void *data
)
488 char *name
= (char*)data
;
489 const struct platform_device
*pdev
;
490 GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
491 pdev
= to_platform_device(dev
);
492 GCC_DIAGNOSTIC_POP();
494 if (strcmp(pdev
->name
, name
) == 0) {
495 DHD_ERROR(("found wifi platform device %s\n", name
));
503 static int wifi_ctrlfunc_register_drv(void)
505 wifi_adapter_info_t
*adapter
;
509 struct device
*dev1
, *dev2
;
510 dev1
= bus_find_device(&platform_bus_type
, NULL
, WIFI_PLAT_NAME
, wifi_platdev_match
);
511 dev2
= bus_find_device(&platform_bus_type
, NULL
, WIFI_PLAT_NAME2
, wifi_platdev_match
);
514 #ifdef BCMDHD_MODULAR
516 #endif /* BCMDHD_MODULAR */
518 #if !defined(CONFIG_DTS) && !defined(CUSTOMER_HW)
520 if (dev1
== NULL
&& dev2
== NULL
) {
521 DHD_ERROR(("no wifi platform data, skip\n"));
525 #endif /* !defined(CONFIG_DTS) */
527 /* multi-chip support not enabled, build one adapter information for
528 * DHD (either SDIO, USB or PCIe)
530 adapter
= kzalloc(sizeof(wifi_adapter_info_t
), GFP_KERNEL
);
531 if (adapter
== NULL
) {
532 DHD_ERROR(("%s:adapter alloc failed", __FUNCTION__
));
535 adapter
->name
= "DHD generic adapter";
536 adapter
->bus_type
= -1;
537 adapter
->bus_num
= -1;
538 adapter
->slot_num
= -1;
539 adapter
->irq_num
= -1;
541 wifi_plat_dev_probe_ret
= 0;
542 dhd_wifi_platdata
= kzalloc(sizeof(bcmdhd_wifi_platdata_t
), GFP_KERNEL
);
543 dhd_wifi_platdata
->num_adapters
= 1;
544 dhd_wifi_platdata
->adapters
= adapter
;
545 init_waitqueue_head(&adapter
->status_event
);
549 err
= platform_driver_register(&wifi_platform_dev_driver
);
551 DHD_ERROR(("%s: failed to register wifi ctrl func driver\n",
557 err
= platform_driver_register(&wifi_platform_dev_driver_legacy
);
559 DHD_ERROR(("%s: failed to register wifi ctrl func legacy driver\n",
566 #if !defined(CONFIG_DTS)
568 struct resource
*resource
;
569 adapter
->wifi_plat_data
= (void *)&dhd_wlan_control
;
570 resource
= &dhd_wlan_resources
;
572 wifi_plat_dev_probe_ret
= dhd_wlan_init_plat_data();
573 if (wifi_plat_dev_probe_ret
)
574 return wifi_plat_dev_probe_ret
;
576 adapter
->irq_num
= resource
->start
;
577 adapter
->intr_flags
= resource
->flags
& IRQF_TRIGGER_MASK
;
578 #ifdef DHD_ISR_NO_SUSPEND
579 adapter
->intr_flags
|= IRQF_NO_SUSPEND
;
581 wifi_plat_dev_probe_ret
= dhd_wifi_platform_load();
583 #endif /* !defined(CONFIG_DTS) */
585 #if defined(CONFIG_DTS) && !defined(CUSTOMER_HW)
586 wifi_plat_dev_probe_ret
= platform_driver_register(&wifi_platform_dev_driver
);
587 #endif /* CONFIG_DTS */
589 /* return probe function's return value if registeration succeeded */
590 return wifi_plat_dev_probe_ret
;
593 void wifi_ctrlfunc_unregister_drv(void)
596 wifi_adapter_info_t
*adapter
;
599 #if defined(CONFIG_DTS) && !defined(CUSTOMER_HW)
600 DHD_ERROR(("unregister wifi platform drivers\n"));
601 platform_driver_unregister(&wifi_platform_dev_driver
);
604 struct device
*dev1
, *dev2
;
605 dev1
= bus_find_device(&platform_bus_type
, NULL
, WIFI_PLAT_NAME
, wifi_platdev_match
);
606 dev2
= bus_find_device(&platform_bus_type
, NULL
, WIFI_PLAT_NAME2
, wifi_platdev_match
);
608 if (dev1
== NULL
&& dev2
== NULL
)
611 DHD_ERROR(("unregister wifi platform drivers\n"));
614 platform_driver_unregister(&wifi_platform_dev_driver
);
616 platform_driver_unregister(&wifi_platform_dev_driver_legacy
);
619 adapter
= &dhd_wifi_platdata
->adapters
[0];
621 wifi_platform_set_power(adapter
, FALSE
, WIFI_TURNOFF_DELAY
);
623 wifi_platform_bus_enumerate(adapter
, FALSE
);
625 #ifdef BCMDHD_MODULAR
627 #endif /* BCMDHD_MODULAR */
628 #endif /* !defined(CONFIG_DTS) */
630 #if defined(CUSTOMER_HW)
631 dhd_wlan_deinit_plat_data(adapter
);
634 kfree(dhd_wifi_platdata
->adapters
);
635 dhd_wifi_platdata
->adapters
= NULL
;
636 dhd_wifi_platdata
->num_adapters
= 0;
637 kfree(dhd_wifi_platdata
);
638 dhd_wifi_platdata
= NULL
;
642 static int bcmdhd_wifi_plat_dev_drv_probe(struct platform_device
*pdev
)
644 dhd_wifi_platdata
= (bcmdhd_wifi_platdata_t
*)(pdev
->dev
.platform_data
);
646 return dhd_wifi_platform_load();
649 static int bcmdhd_wifi_plat_dev_drv_remove(struct platform_device
*pdev
)
652 wifi_adapter_info_t
*adapter
;
653 ASSERT(dhd_wifi_platdata
!= NULL
);
655 /* power down all adapters */
656 for (i
= 0; i
< dhd_wifi_platdata
->num_adapters
; i
++) {
657 adapter
= &dhd_wifi_platdata
->adapters
[i
];
658 wifi_platform_set_power(adapter
, FALSE
, WIFI_TURNOFF_DELAY
);
659 wifi_platform_bus_enumerate(adapter
, FALSE
);
664 static struct platform_driver dhd_wifi_platform_dev_driver
= {
665 .probe
= bcmdhd_wifi_plat_dev_drv_probe
,
666 .remove
= bcmdhd_wifi_plat_dev_drv_remove
,
668 .name
= WIFI_PLAT_EXT
,
673 int dhd_wifi_platform_register_drv(void)
679 /* register Broadcom wifi platform data driver if multi-chip is enabled,
680 * otherwise use Android style wifi platform data (aka wifi control function)
683 * to support multi-chip DHD, Broadcom wifi platform data device must
684 * be added in kernel early boot (e.g. board config file).
687 dev
= bus_find_device(&platform_bus_type
, NULL
, WIFI_PLAT_EXT
, wifi_platdev_match
);
689 DHD_ERROR(("bcmdhd wifi platform data device not found!!\n"));
692 err
= platform_driver_register(&dhd_wifi_platform_dev_driver
);
696 err
= wifi_ctrlfunc_register_drv();
698 /* no wifi ctrl func either, load bus directly and ignore this error */
701 /* wifi ctrl function does not exist */
702 err
= dhd_wifi_platform_load();
704 /* unregister driver due to initialization failure */
705 wifi_ctrlfunc_unregister_drv();
714 static int dhd_wifi_platform_load_pcie(void)
718 wifi_adapter_info_t
*adapter
;
721 BCM_REFERENCE(adapter
);
723 if (dhd_wifi_platdata
== NULL
) {
724 /* XXX For x86 Bringup PC or BRIX */
725 err
= dhd_bus_register();
727 #ifdef DHD_SUPPORT_HDM
728 if (dhd_download_fw_on_driverload
|| hdm_trigger_init
) {
730 if (dhd_download_fw_on_driverload
) {
731 #endif /* DHD_SUPPORT_HDM */
732 /* power up all adapters */
733 for (i
= 0; i
< dhd_wifi_platdata
->num_adapters
; i
++) {
734 int retry
= POWERUP_MAX_RETRY
;
735 adapter
= &dhd_wifi_platdata
->adapters
[i
];
737 DHD_ERROR(("Power-up adapter '%s'\n", adapter
->name
));
738 DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",
739 adapter
->irq_num
, adapter
->intr_flags
, adapter
->fw_path
,
741 DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",
742 adapter
->bus_type
, adapter
->bus_num
, adapter
->slot_num
));
745 err
= wifi_platform_set_power(adapter
,
746 TRUE
, WIFI_TURNON_DELAY
);
748 DHD_ERROR(("failed to power up %s,"
750 adapter
->name
, retry
));
751 /* WL_REG_ON state unknown, Power off forcely */
752 wifi_platform_set_power(adapter
,
753 FALSE
, WIFI_TURNOFF_DELAY
);
756 err
= wifi_platform_bus_enumerate(adapter
, TRUE
);
758 DHD_ERROR(("failed to enumerate bus %s, "
760 adapter
->name
, retry
));
761 wifi_platform_set_power(adapter
, FALSE
,
770 DHD_ERROR(("failed to power up %s, max retry reached**\n",
777 err
= dhd_bus_register();
780 DHD_ERROR(("%s: pcie_register_driver failed\n", __FUNCTION__
));
781 if (dhd_download_fw_on_driverload
) {
782 /* power down all adapters */
783 for (i
= 0; i
< dhd_wifi_platdata
->num_adapters
; i
++) {
784 adapter
= &dhd_wifi_platdata
->adapters
[i
];
785 wifi_platform_bus_enumerate(adapter
, FALSE
);
786 wifi_platform_set_power(adapter
,
787 FALSE
, WIFI_TURNOFF_DELAY
);
796 static int dhd_wifi_platform_load_pcie(void)
802 void dhd_wifi_platform_unregister_drv(void)
806 platform_driver_unregister(&dhd_wifi_platform_dev_driver
);
809 wifi_ctrlfunc_unregister_drv();
812 extern int dhd_watchdog_prio
;
813 extern int dhd_dpc_prio
;
814 extern uint dhd_deferred_tx
;
815 #if defined(BCMLXSDMMC) || defined(BCMDBUS)
816 extern struct semaphore dhd_registration_sem
;
820 static int dhd_wifi_platform_load_sdio(void)
824 wifi_adapter_info_t
*adapter
;
827 BCM_REFERENCE(adapter
);
828 /* Sanity check on the module parameters
829 * - Both watchdog and DPC as tasklets are ok
830 * - If both watchdog and DPC are threads, TX must be deferred
832 if (!(dhd_watchdog_prio
< 0 && dhd_dpc_prio
< 0) &&
833 !(dhd_watchdog_prio
>= 0 && dhd_dpc_prio
>= 0 && dhd_deferred_tx
))
836 #if defined(BCMLXSDMMC) && !defined(DHD_PRELOAD)
837 sema_init(&dhd_registration_sem
, 0);
840 if (dhd_wifi_platdata
== NULL
) {
841 DHD_ERROR(("DHD wifi platform data is required for Android build\n"));
842 DHD_ERROR(("DHD registering bus directly\n"));
843 /* x86 bring-up PC needs no power-up operations */
844 err
= dhd_bus_register();
848 #if defined(BCMLXSDMMC) && !defined(DHD_PRELOAD)
849 /* power up all adapters */
850 for (i
= 0; i
< dhd_wifi_platdata
->num_adapters
; i
++) {
851 bool chip_up
= FALSE
;
852 int retry
= POWERUP_MAX_RETRY
;
853 struct semaphore dhd_chipup_sem
;
855 adapter
= &dhd_wifi_platdata
->adapters
[i
];
857 DHD_ERROR(("Power-up adapter '%s'\n", adapter
->name
));
858 DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",
859 adapter
->irq_num
, adapter
->intr_flags
, adapter
->fw_path
, adapter
->nv_path
));
860 DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",
861 adapter
->bus_type
, adapter
->bus_num
, adapter
->slot_num
));
864 #ifndef CUSTOMER_HW_AMLOGIC
865 sema_init(&dhd_chipup_sem
, 0);
866 err
= dhd_bus_reg_sdio_notify(&dhd_chipup_sem
);
868 DHD_ERROR(("%s dhd_bus_reg_sdio_notify fail(%d)\n\n",
873 err
= wifi_platform_set_power(adapter
, TRUE
, WIFI_TURNON_DELAY
);
875 DHD_ERROR(("%s: wifi pwr on error ! \n", __FUNCTION__
));
876 dhd_bus_unreg_sdio_notify();
877 /* WL_REG_ON state unknown, Power off forcely */
878 wifi_platform_set_power(adapter
, FALSE
, WIFI_TURNOFF_DELAY
);
881 wifi_platform_bus_enumerate(adapter
, TRUE
);
883 #ifdef CUSTOMER_HW_AMLOGIC
884 sema_init(&dhd_chipup_sem
, 0);
885 err
= dhd_bus_reg_sdio_notify(&dhd_chipup_sem
);
887 DHD_ERROR(("%s dhd_bus_reg_sdio_notify fail(%d)\n\n",
893 if (down_timeout(&dhd_chipup_sem
, msecs_to_jiffies(POWERUP_WAIT_MS
)) == 0) {
894 dhd_bus_unreg_sdio_notify();
899 DHD_ERROR(("failed to power up %s, %d retry left\n", adapter
->name
, retry
));
900 dhd_bus_unreg_sdio_notify();
901 wifi_platform_set_power(adapter
, FALSE
, WIFI_TURNOFF_DELAY
);
902 wifi_platform_bus_enumerate(adapter
, FALSE
);
906 DHD_ERROR(("failed to power up %s, max retry reached**\n", adapter
->name
));
912 err
= dhd_bus_register();
915 DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__
));
920 * Wait till MMC sdio_register_driver callback called and made driver attach.
921 * It's needed to make sync up exit from dhd insmod and
922 * Kernel MMC sdio device callback registration
924 err
= down_timeout(&dhd_registration_sem
, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT
));
926 DHD_ERROR(("%s: sdio_register_driver timeout or error \n", __FUNCTION__
));
927 dhd_bus_unregister();
934 /* power down all adapters */
935 for (i
= 0; i
< dhd_wifi_platdata
->num_adapters
; i
++) {
936 adapter
= &dhd_wifi_platdata
->adapters
[i
];
937 wifi_platform_set_power(adapter
, FALSE
, WIFI_TURNOFF_DELAY
);
938 wifi_platform_bus_enumerate(adapter
, FALSE
);
941 /* x86 bring-up PC needs no power-up operations */
942 err
= dhd_bus_register();
948 static int dhd_wifi_platform_load_sdio(void)
955 static int dhd_wifi_platform_load_usb(void)
958 #if !defined(DHD_PRELOAD)
959 wifi_adapter_info_t
*adapter
;
962 enum wifi_adapter_status wait_status
;
965 err
= dhd_bus_register();
967 DHD_ERROR(("%s: usb_register failed\n", __FUNCTION__
));
971 #if !defined(DHD_PRELOAD)
972 /* power up all adapters */
973 for (i
= 0; i
< dhd_wifi_platdata
->num_adapters
; i
++) {
974 adapter
= &dhd_wifi_platdata
->adapters
[i
];
975 DHD_ERROR(("Power-up adapter '%s'\n", adapter
->name
));
976 DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",
977 adapter
->irq_num
, adapter
->intr_flags
, adapter
->fw_path
, adapter
->nv_path
));
978 DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",
979 adapter
->bus_type
, adapter
->bus_num
, adapter
->slot_num
));
980 err
= wifi_platform_set_power(adapter
, TRUE
, WIFI_TURNON_DELAY
);
982 DHD_ERROR(("failed to wifi_platform_set_power on %s\n", adapter
->name
));
985 if (dhd_download_fw_on_driverload
)
986 wait_status
= WIFI_STATUS_ATTACH
;
988 wait_status
= WIFI_STATUS_DETTACH
;
989 timeout
= wait_event_interruptible_timeout(adapter
->status_event
,
990 wifi_get_adapter_status(adapter
, wait_status
),
991 msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT
));
994 DHD_ERROR(("%s: usb_register_driver timeout\n", __FUNCTION__
));
1003 #if !defined(DHD_PRELOAD)
1005 dhd_bus_unregister();
1006 /* power down all adapters */
1007 for (i
= 0; i
< dhd_wifi_platdata
->num_adapters
; i
++) {
1008 adapter
= &dhd_wifi_platdata
->adapters
[i
];
1009 wifi_platform_set_power(adapter
, FALSE
, WIFI_TURNOFF_DELAY
);
1016 static int dhd_wifi_platform_load_usb(void)
1020 #endif /* BCMDBUS */
1022 static int dhd_wifi_platform_load(void)
1025 printf("%s: Enter\n", __FUNCTION__
);
1029 if ((err
= dhd_wifi_platform_load_usb()))
1031 else if ((err
= dhd_wifi_platform_load_sdio()))
1034 err
= dhd_wifi_platform_load_pcie();
1039 #if !defined(MULTIPLE_SUPPLICANT)
1041 wl_android_post_init();