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