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