xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd_indep_power/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 #include <dhd_dbg.h>
6 #include <linux/rfkill-wlan.h>
7 
8 #ifdef CUSTOMER_HW_PLATFORM
9 #include <plat/sdhci.h>
10 #define	sdmmc_channel	sdmmc_device_mmc0
11 #endif /* CUSTOMER_HW_PLATFORM */
12 
13 #if defined(BUS_POWER_RESTORE) && defined(BCMSDIO)
14 #include <linux/mmc/core.h>
15 #include <linux/mmc/card.h>
16 #include <linux/mmc/host.h>
17 #include <linux/mmc/sdio_func.h>
18 #endif /* defined(BUS_POWER_RESTORE) && defined(BCMSDIO) */
19 
20 #ifdef CONFIG_DHD_USE_STATIC_BUF
21 extern void *dhd_wlan_mem_prealloc(int section, unsigned long size);
22 #endif /* CONFIG_DHD_USE_STATIC_BUF */
23 
24 static int gpio_wl_reg_on = -1; // WL_REG_ON is input pin of WLAN module
25 #ifdef CUSTOMER_OOB
26 static int gpio_wl_host_wake = -1; // WL_HOST_WAKE is output pin of WLAN module
27 #endif
28 
29 static int
dhd_wlan_set_power(int on,wifi_adapter_info_t * adapter)30 dhd_wlan_set_power(int on
31 #ifdef BUS_POWER_RESTORE
32 , wifi_adapter_info_t *adapter
33 #endif /* BUS_POWER_RESTORE */
34 )
35 {
36 	int err = 0;
37 
38 	if (on) {
39 		DHD_PRINT("======== PULL WL_REG_ON(%d) HIGH! ========\n", gpio_wl_reg_on);
40 		if (gpio_wl_reg_on >= 0) {
41 			err = gpio_direction_output(gpio_wl_reg_on, 1);
42 			if (err) {
43 				printf("%s: WL_REG_ON didn't output high\n", __FUNCTION__);
44 				return -EIO;
45 			}
46 		}
47 		rockchip_wifi_power(1);
48 #if defined(BUS_POWER_RESTORE)
49 #if defined(BCMSDIO) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0))
50 		if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) {
51 			mdelay(100);
52 			DHD_PRINT("======== mmc_power_restore_host! ========\n");
53 			mmc_power_restore_host(adapter->sdio_func->card->host);
54 		}
55 #elif defined(BCMPCIE)
56 		if (adapter->pci_dev) {
57 			mdelay(100);
58 			DHD_PRINT("======== pci_set_power_state PCI_D0! ========\n");
59 			pci_set_power_state(adapter->pci_dev, PCI_D0);
60 			if (adapter->pci_saved_state)
61 				pci_load_and_free_saved_state(adapter->pci_dev, &adapter->pci_saved_state);
62 			pci_restore_state(adapter->pci_dev);
63 			err = pci_enable_device(adapter->pci_dev);
64 			if (err < 0)
65 				printf("%s: PCI enable device failed", __FUNCTION__);
66 			pci_set_master(adapter->pci_dev);
67 		}
68 #endif /* BCMPCIE */
69 #endif /* BUS_POWER_RESTORE */
70 		/* Lets customer power to get stable */
71 //		mdelay(100);
72 	} else {
73 #if defined(BUS_POWER_RESTORE)
74 #if defined(BCMSDIO) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0))
75 		if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) {
76 			DHD_PRINT("======== mmc_power_save_host! ========\n");
77 			mmc_power_save_host(adapter->sdio_func->card->host);
78 		}
79 #elif defined(BCMPCIE)
80 		if (adapter->pci_dev) {
81 			DHD_PRINT("======== pci_set_power_state PCI_D3hot! ========\n");
82 			pci_save_state(adapter->pci_dev);
83 			adapter->pci_saved_state = pci_store_saved_state(adapter->pci_dev);
84 			if (pci_is_enabled(adapter->pci_dev))
85 				pci_disable_device(adapter->pci_dev);
86 			pci_set_power_state(adapter->pci_dev, PCI_D3hot);
87 		}
88 #endif /* BCMPCIE */
89 #endif /* BUS_POWER_RESTORE */
90 		DHD_PRINT("======== PULL WL_REG_ON(%d) LOW! ========\n", gpio_wl_reg_on);
91 		if (gpio_wl_reg_on >= 0) {
92 			err = gpio_direction_output(gpio_wl_reg_on, 0);
93 			if (err) {
94 				printf("%s: WL_REG_ON didn't output low\n", __FUNCTION__);
95 				return -EIO;
96 			}
97 		}
98 		rockchip_wifi_power(0);
99 	}
100 
101 	return err;
102 }
103 
dhd_wlan_set_reset(int onoff)104 static int dhd_wlan_set_reset(int onoff)
105 {
106 	return 0;
107 }
108 
dhd_wlan_set_carddetect(int present)109 static int dhd_wlan_set_carddetect(int present)
110 {
111 	int err = 0;
112 
113 #if !defined(BUS_POWER_RESTORE)
114 	if (present) {
115 #if defined(BCMSDIO)
116 		DHD_PRINT("======== Card detection to detect SDIO card! ========\n");
117 #ifdef CUSTOMER_HW_PLATFORM
118 		err = sdhci_force_presence_change(&sdmmc_channel, 1);
119 #endif /* CUSTOMER_HW_PLATFORM */
120 		rockchip_wifi_set_carddetect(1);
121 #elif defined(BCMPCIE)
122 		DHD_PRINT("======== Card detection to detect PCIE card! ========\n");
123 #endif
124 	} else {
125 #if defined(BCMSDIO)
126 		DHD_PRINT("======== Card detection to remove SDIO card! ========\n");
127 #ifdef CUSTOMER_HW_PLATFORM
128 		err = sdhci_force_presence_change(&sdmmc_channel, 0);
129 #endif /* CUSTOMER_HW_PLATFORM */
130 	rockchip_wifi_set_carddetect(0);
131 #elif defined(BCMPCIE)
132 		DHD_PRINT("======== Card detection to remove PCIE card! ========\n");
133 #endif
134 	}
135 #endif /* BUS_POWER_RESTORE */
136 
137 	return err;
138 }
139 
dhd_wlan_get_mac_addr(unsigned char * buf)140 static int dhd_wlan_get_mac_addr(unsigned char *buf)
141 {
142 	int err = 0;
143 
144 	DHD_PRINT("======== %s ========\n", __FUNCTION__);
145 #ifdef EXAMPLE_GET_MAC
146 	/* EXAMPLE code */
147 	{
148 		struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
149 		bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
150 	}
151 #endif /* EXAMPLE_GET_MAC */
152 	err = rockchip_wifi_mac_addr(buf);
153 #ifdef EXAMPLE_GET_MAC_VER2
154 	/* EXAMPLE code */
155 	{
156 		char macpad[56]= {
157 		0x00,0xaa,0x9c,0x84,0xc7,0xbc,0x9b,0xf6,
158 		0x02,0x33,0xa9,0x4d,0x5c,0xb4,0x0a,0x5d,
159 		0xa8,0xef,0xb0,0xcf,0x8e,0xbf,0x24,0x8a,
160 		0x87,0x0f,0x6f,0x0d,0xeb,0x83,0x6a,0x70,
161 		0x4a,0xeb,0xf6,0xe6,0x3c,0xe7,0x5f,0xfc,
162 		0x0e,0xa7,0xb3,0x0f,0x00,0xe4,0x4a,0xaf,
163 		0x87,0x08,0x16,0x6d,0x3a,0xe3,0xc7,0x80};
164 		bcopy(macpad, buf+6, sizeof(macpad));
165 	}
166 #endif /* EXAMPLE_GET_MAC_VER2 */
167 
168 	return err;
169 }
170 
171 static struct cntry_locales_custom brcm_wlan_translate_custom_table[] = {
172 	/* Table should be filled out based on custom platform regulatory requirement */
173 #ifdef EXAMPLE_TABLE
174 	{"",   "XT", 49},  /* Universal if Country code is unknown or empty */
175 	{"US", "US", 0},
176 #endif /* EXMAPLE_TABLE */
177 };
178 
179 #ifdef CUSTOM_FORCE_NODFS_FLAG
180 struct cntry_locales_custom brcm_wlan_translate_nodfs_table[] = {
181 #ifdef EXAMPLE_TABLE
182 	{"",   "XT", 50},  /* Universal if Country code is unknown or empty */
183 	{"US", "US", 0},
184 #endif /* EXMAPLE_TABLE */
185 };
186 #endif
187 
dhd_wlan_get_country_code(char * ccode,u32 flags)188 static void *dhd_wlan_get_country_code(char *ccode
189 #ifdef CUSTOM_FORCE_NODFS_FLAG
190 	, u32 flags
191 #endif
192 )
193 {
194 	struct cntry_locales_custom *locales;
195 	int size;
196 	int i;
197 
198 	if (!ccode)
199 		return NULL;
200 
201 #ifdef CUSTOM_FORCE_NODFS_FLAG
202 	if (flags & WLAN_PLAT_NODFS_FLAG) {
203 		locales = brcm_wlan_translate_nodfs_table;
204 		size = ARRAY_SIZE(brcm_wlan_translate_nodfs_table);
205 	} else {
206 #endif
207 		locales = brcm_wlan_translate_custom_table;
208 		size = ARRAY_SIZE(brcm_wlan_translate_custom_table);
209 #ifdef CUSTOM_FORCE_NODFS_FLAG
210 	}
211 #endif
212 
213 	for (i = 0; i < size; i++)
214 		if (strcmp(ccode, locales[i].iso_abbrev) == 0)
215 			return &locales[i];
216 	return NULL;
217 }
218 
219 struct resource dhd_wlan_resources[] = {
220 	[0] = {
221 		.name	= "bcmdhd_wlan_irq",
222 		.start	= 0, /* Dummy */
223 		.end	= 0, /* Dummy */
224 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE
225 			| IORESOURCE_IRQ_HIGHLEVEL, /* Dummy */
226 	},
227 };
228 
229 struct wifi_platform_data dhd_wlan_control = {
230 	.set_power	= dhd_wlan_set_power,
231 	.set_reset	= dhd_wlan_set_reset,
232 	.set_carddetect	= dhd_wlan_set_carddetect,
233 	.get_mac_addr	= dhd_wlan_get_mac_addr,
234 #ifdef CONFIG_DHD_USE_STATIC_BUF
235 	.mem_prealloc	= dhd_wlan_mem_prealloc,
236 #endif /* CONFIG_DHD_USE_STATIC_BUF */
237 	.get_country_code = dhd_wlan_get_country_code,
238 };
239 
dhd_wlan_init_gpio(void)240 int dhd_wlan_init_gpio(void)
241 {
242 	int err = 0;
243 #ifdef CUSTOMER_OOB
244 	int host_oob_irq = -1;
245 	uint host_oob_irq_flags = 0;
246 	int irq_flags = -1;
247 #endif
248 
249 	/* Please check your schematic and fill right GPIO number which connected to
250 	* WL_REG_ON and WL_HOST_WAKE.
251 	*/
252 	gpio_wl_reg_on = -1;
253 #ifdef CUSTOMER_OOB
254 	gpio_wl_host_wake = -1;
255 #endif
256 
257 	if (gpio_wl_reg_on >= 0) {
258 		err = gpio_request(gpio_wl_reg_on, "WL_REG_ON");
259 		if (err < 0) {
260 			printf("%s: gpio_request(%d) for WL_REG_ON failed\n",
261 				__FUNCTION__, gpio_wl_reg_on);
262 			gpio_wl_reg_on = -1;
263 		}
264 	}
265 
266 #ifdef CUSTOMER_OOB
267 	if (gpio_wl_host_wake >= 0) {
268 		err = gpio_request(gpio_wl_host_wake, "bcmdhd");
269 		if (err < 0) {
270 			printf("%s: gpio_request(%d) for WL_HOST_WAKE failed\n",
271 				__FUNCTION__, gpio_wl_host_wake);
272 			return -1;
273 		}
274 		err = gpio_direction_input(gpio_wl_host_wake);
275 		if (err < 0) {
276 			printf("%s: gpio_direction_input(%d) for WL_HOST_WAKE failed\n",
277 				__FUNCTION__, gpio_wl_host_wake);
278 			gpio_free(gpio_wl_host_wake);
279 			return -1;
280 		}
281 		host_oob_irq = gpio_to_irq(gpio_wl_host_wake);
282 		if (host_oob_irq < 0) {
283 			printf("%s: gpio_to_irq(%d) for WL_HOST_WAKE failed\n",
284 				__FUNCTION__, gpio_wl_host_wake);
285 			gpio_free(gpio_wl_host_wake);
286 			return -1;
287 		}
288 	}
289 	host_oob_irq = rockchip_wifi_get_oob_irq();
290 
291 #ifdef HW_OOB
292 	host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE;
293 	irq_flags = rockchip_wifi_get_oob_irq_flag();
294 	irq_flags = 1;
295 	if (irq_flags == 1)
296 		host_oob_irq_flags |= IORESOURCE_IRQ_HIGHLEVEL;
297 	else if (irq_flags == 0)
298 		host_oob_irq_flags |= IORESOURCE_IRQ_LOWLEVEL;
299 	else
300 		pr_warn("%s: unknown oob irqflags !\n", __func__);
301 #else
302 	host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_SHAREABLE;
303 #endif
304 
305 	dhd_wlan_resources[0].start = dhd_wlan_resources[0].end = host_oob_irq;
306 	dhd_wlan_resources[0].flags = host_oob_irq_flags;
307 	DHD_PRINT("%s: WL_HOST_WAKE=%d, oob_irq=%d, oob_irq_flags=0x%x\n", __FUNCTION__,
308 		gpio_wl_host_wake, host_oob_irq, host_oob_irq_flags);
309 #endif /* CUSTOMER_OOB */
310 	DHD_PRINT("%s: WL_REG_ON=%d\n", __FUNCTION__, gpio_wl_reg_on);
311 
312 	return 0;
313 }
314 
dhd_wlan_deinit_gpio(void)315 static void dhd_wlan_deinit_gpio(void)
316 {
317 	if (gpio_wl_reg_on >= 0) {
318 		DHD_PRINT("%s: gpio_free(WL_REG_ON %d)\n", __FUNCTION__, gpio_wl_reg_on);
319 		gpio_free(gpio_wl_reg_on);
320 		gpio_wl_reg_on = -1;
321 	}
322 #ifdef CUSTOMER_OOB
323 	if (gpio_wl_host_wake >= 0) {
324 		DHD_PRINT("%s: gpio_free(WL_HOST_WAKE %d)\n", __FUNCTION__, gpio_wl_host_wake);
325 		gpio_free(gpio_wl_host_wake);
326 		gpio_wl_host_wake = -1;
327 	}
328 #endif /* CUSTOMER_OOB */
329 }
330 
dhd_wlan_init_plat_data(void)331 int dhd_wlan_init_plat_data(void)
332 {
333 	int err = 0;
334 
335 	DHD_PRINT("======== %s ========\n", __FUNCTION__);
336 	err = dhd_wlan_init_gpio();
337 	return err;
338 }
339 
dhd_wlan_deinit_plat_data(wifi_adapter_info_t * adapter)340 void dhd_wlan_deinit_plat_data(wifi_adapter_info_t *adapter)
341 {
342 	DHD_PRINT("======== %s ========\n", __FUNCTION__);
343 	dhd_wlan_deinit_gpio();
344 }
345 
346