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