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