dhd: import wifi and bluetooth firmware
[GitHub/LineageOS/G12/android_hardware_amlogic_kernel-modules_dhd-driver.git] / bcmdhd.101.10.240.x / dhd_custom_msm.c
1 /*
2 * Platform Dependent file for Qualcomm MSM/APQ
3 *
4 * Copyright (C) 2020, Broadcom.
5 *
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:
11 *
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.
19 *
20 *
21 * <<Broadcom-WL-IPTag/Open:>>
22 *
23 * $Id$
24 *
25 */
26
27 #include <linux/kernel.h>
28 #include <linux/init.h>
29 #include <linux/platform_device.h>
30 #include <linux/delay.h>
31 #include <linux/err.h>
32 #include <linux/gpio.h>
33 #include <linux/skbuff.h>
34 #include <linux/wlan_plat.h>
35 #include <linux/mmc/host.h>
36 #include <linux/msm_pcie.h>
37 #include <linux/fcntl.h>
38 #include <linux/fs.h>
39 #include <linux/of_gpio.h>
40 #if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) || \
41 defined(CONFIG_ARCH_SDM845) || defined(CONFIG_ARCH_SM8150) || defined(CONFIG_ARCH_KONA)
42 #include <linux/msm_pcie.h>
43 #endif /* CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998 ||
44 CONFIG_ARCH_SDM845 || CONFIG_ARCH_SM8150 || CONFIG_ARCH_KONA
45 */
46
47 #ifdef CONFIG_BROADCOM_WIFI_RESERVED_MEM
48 extern int dhd_init_wlan_mem(void);
49 extern void *dhd_wlan_mem_prealloc(int section, unsigned long size);
50 #endif /* CONFIG_BROADCOM_WIFI_RESERVED_MEM */
51
52 #define WIFI_TURNON_DELAY 200
53 static int wlan_reg_on = -1;
54 #define DHD_DT_COMPAT_ENTRY "android,bcmdhd_wlan"
55 #define WIFI_WL_REG_ON_PROPNAME "wlan-en-gpio"
56
57 #if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) || \
58 defined(CONFIG_ARCH_SDM845) || defined(CONFIG_ARCH_SM8150) || defined(CONFIG_ARCH_KONA)
59 #define MSM_PCIE_CH_NUM 0
60 #else
61 #define MSM_PCIE_CH_NUM 1
62 #endif /* CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998
63 || CONFIG_ARCH_SDM845 || CONFIG_ARCH_SM8150 || CONFIG_ARCH_KONA
64 */
65
66 #ifdef CONFIG_BCMDHD_OOB_HOST_WAKE
67 static int wlan_host_wake_up = -1;
68 static int wlan_host_wake_irq = 0;
69 #define WIFI_WLAN_HOST_WAKE_PROPNAME "wlan-host-wake-gpio"
70 #endif /* CONFIG_BCMDHD_OOB_HOST_WAKE */
71
72 int __init
73 dhd_wifi_init_gpio(void)
74 {
75 char *wlan_node = DHD_DT_COMPAT_ENTRY;
76 struct device_node *root_node = NULL;
77
78 root_node = of_find_compatible_node(NULL, NULL, wlan_node);
79 if (!root_node) {
80 WARN(1, "failed to get device node of BRCM WLAN\n");
81 return -ENODEV;
82 }
83
84 /* ========== WLAN_PWR_EN ============ */
85 wlan_reg_on = of_get_named_gpio(root_node, WIFI_WL_REG_ON_PROPNAME, 0);
86 printk(KERN_INFO "%s: gpio_wlan_power : %d\n", __FUNCTION__, wlan_reg_on);
87
88 if (gpio_request_one(wlan_reg_on, GPIOF_OUT_INIT_LOW, "WL_REG_ON")) {
89 printk(KERN_ERR "%s: Faiiled to request gpio %d for WL_REG_ON\n",
90 __FUNCTION__, wlan_reg_on);
91 } else {
92 printk(KERN_ERR "%s: gpio_request WL_REG_ON done - WLAN_EN: GPIO %d\n",
93 __FUNCTION__, wlan_reg_on);
94 }
95
96 if (gpio_direction_output(wlan_reg_on, 1)) {
97 printk(KERN_ERR "%s: WL_REG_ON failed to pull up\n", __FUNCTION__);
98 } else {
99 printk(KERN_ERR "%s: WL_REG_ON is pulled up\n", __FUNCTION__);
100 }
101
102 if (gpio_get_value(wlan_reg_on)) {
103 printk(KERN_INFO "%s: Initial WL_REG_ON: [%d]\n",
104 __FUNCTION__, gpio_get_value(wlan_reg_on));
105 }
106
107 /* Wait for WIFI_TURNON_DELAY due to power stability */
108 msleep(WIFI_TURNON_DELAY);
109
110 #ifdef CONFIG_BCMDHD_OOB_HOST_WAKE
111 /* ========== WLAN_HOST_WAKE ============ */
112 wlan_host_wake_up = of_get_named_gpio(root_node, WIFI_WLAN_HOST_WAKE_PROPNAME, 0);
113 printk(KERN_INFO "%s: gpio_wlan_host_wake : %d\n", __FUNCTION__, wlan_host_wake_up);
114
115 if (gpio_request_one(wlan_host_wake_up, GPIOF_IN, "WLAN_HOST_WAKE")) {
116 printk(KERN_ERR "%s: Faiiled to request gpio %d for WLAN_HOST_WAKE\n",
117 __FUNCTION__, wlan_host_wake_up);
118 return -ENODEV;
119 } else {
120 printk(KERN_ERR "%s: gpio_request WLAN_HOST_WAKE done"
121 " - WLAN_HOST_WAKE: GPIO %d\n",
122 __FUNCTION__, wlan_host_wake_up);
123 }
124
125 gpio_direction_input(wlan_host_wake_up);
126 wlan_host_wake_irq = gpio_to_irq(wlan_host_wake_up);
127 #endif /* CONFIG_BCMDHD_OOB_HOST_WAKE */
128
129 #if defined(CONFIG_BCM4359) || defined(CONFIG_BCM4361) || defined(CONFIG_BCM4375) || \
130 defined(CONFIG_BCM4389)
131 printk(KERN_INFO "%s: Call msm_pcie_enumerate\n", __FUNCTION__);
132 msm_pcie_enumerate(MSM_PCIE_CH_NUM);
133 #endif /* CONFIG_BCM4359 || CONFIG_BCM4361 || CONFIG_BCM4375 || CONFIG_BCM4389 */
134
135 return 0;
136 }
137
138 int
139 dhd_wlan_power(int onoff)
140 {
141 printk(KERN_INFO"%s Enter: power %s\n", __func__, onoff ? "on" : "off");
142
143 if (onoff) {
144 if (gpio_direction_output(wlan_reg_on, 1)) {
145 printk(KERN_ERR "%s: WL_REG_ON is failed to pull up\n", __FUNCTION__);
146 return -EIO;
147 }
148 if (gpio_get_value(wlan_reg_on)) {
149 printk(KERN_INFO"WL_REG_ON on-step-2 : [%d]\n",
150 gpio_get_value(wlan_reg_on));
151 } else {
152 printk("[%s] gpio value is 0. We need reinit.\n", __func__);
153 if (gpio_direction_output(wlan_reg_on, 1)) {
154 printk(KERN_ERR "%s: WL_REG_ON is "
155 "failed to pull up\n", __func__);
156 }
157 }
158 } else {
159 if (gpio_direction_output(wlan_reg_on, 0)) {
160 printk(KERN_ERR "%s: WL_REG_ON is failed to pull up\n", __FUNCTION__);
161 return -EIO;
162 }
163 if (gpio_get_value(wlan_reg_on)) {
164 printk(KERN_INFO"WL_REG_ON on-step-2 : [%d]\n",
165 gpio_get_value(wlan_reg_on));
166 }
167 }
168 return 0;
169 }
170 EXPORT_SYMBOL(dhd_wlan_power);
171
172 static int
173 dhd_wlan_reset(int onoff)
174 {
175 return 0;
176 }
177
178 static int
179 dhd_wlan_set_carddetect(int val)
180 {
181 #ifdef CONFIG_BCMDHD_PCIE
182 printk(KERN_INFO "%s: Call msm_pcie_enumerate\n", __FUNCTION__);
183 msm_pcie_enumerate(MSM_PCIE_CH_NUM);
184 #endif /* CONFIG_BCMDHD_PCIE */
185 return 0;
186 }
187
188 #if defined(CONFIG_BCMDHD_OOB_HOST_WAKE) && defined(CONFIG_BCMDHD_GET_OOB_STATE)
189 int
190 dhd_get_wlan_oob_gpio(void)
191 {
192 return gpio_is_valid(wlan_host_wake_up) ?
193 gpio_get_value(wlan_host_wake_up) : -1;
194 }
195 EXPORT_SYMBOL(dhd_get_wlan_oob_gpio);
196 #endif /* CONFIG_BCMDHD_OOB_HOST_WAKE && CONFIG_BCMDHD_GET_OOB_STATE */
197
198 struct resource dhd_wlan_resources = {
199 .name = "bcmdhd_wlan_irq",
200 .start = 0, /* Dummy */
201 .end = 0, /* Dummy */
202 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE |
203 #ifdef CONFIG_BCMDHD_PCIE
204 IORESOURCE_IRQ_HIGHEDGE,
205 #else
206 IORESOURCE_IRQ_HIGHLEVEL,
207 #endif /* CONFIG_BCMDHD_PCIE */
208 };
209 EXPORT_SYMBOL(dhd_wlan_resources);
210
211 struct wifi_platform_data dhd_wlan_control = {
212 .set_power = dhd_wlan_power,
213 .set_reset = dhd_wlan_reset,
214 .set_carddetect = dhd_wlan_set_carddetect,
215 #ifdef CONFIG_BROADCOM_WIFI_RESERVED_MEM
216 .mem_prealloc = dhd_wlan_mem_prealloc,
217 #endif /* CONFIG_BROADCOM_WIFI_RESERVED_MEM */
218 };
219 EXPORT_SYMBOL(dhd_wlan_control);
220
221 int __init
222 dhd_wlan_init(void)
223 {
224 int ret;
225
226 printk(KERN_INFO"%s: START.......\n", __FUNCTION__);
227 ret = dhd_wifi_init_gpio();
228 if (ret < 0) {
229 printk(KERN_ERR "%s: failed to initiate GPIO, ret=%d\n",
230 __FUNCTION__, ret);
231 goto fail;
232 }
233
234 #ifdef CONFIG_BCMDHD_OOB_HOST_WAKE
235 dhd_wlan_resources.start = wlan_host_wake_irq;
236 dhd_wlan_resources.end = wlan_host_wake_irq;
237 #endif /* CONFIG_BCMDHD_OOB_HOST_WAKE */
238
239 #ifdef CONFIG_BROADCOM_WIFI_RESERVED_MEM
240 ret = dhd_init_wlan_mem();
241 if (ret < 0) {
242 printk(KERN_ERR "%s: failed to alloc reserved memory,"
243 " ret=%d\n", __FUNCTION__, ret);
244 }
245 #endif /* CONFIG_BROADCOM_WIFI_RESERVED_MEM */
246
247 fail:
248 printk(KERN_INFO"%s: FINISH.......\n", __FUNCTION__);
249 return ret;
250 }
251 #if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) || \
252 defined(CONFIG_ARCH_SDM845) || defined(CONFIG_ARCH_SM8150) || defined(CONFIG_ARCH_KONA)
253 #if defined(CONFIG_DEFERRED_INITCALLS)
254 deferred_module_init(dhd_wlan_init);
255 #else
256 late_initcall(dhd_wlan_init);
257 #endif /* CONFIG_DEFERRED_INITCALLS */
258 #else
259 device_initcall(dhd_wlan_init);
260 #endif /* CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998
261 * CONFIG_ARCH_SDM845 || CONFIG_ARCH_SM8150 || CONFIG_ARCH_KONA
262 */