xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/ssv6xxx/platforms/v66-generic-wlan.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (c) 2015 South Silicon Valley Microelectronics Inc.
3  * Copyright (c) 2015 iComm Corporation
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include <linux/irq.h>
18 #include <linux/version.h>
19 #include <linux/module.h>
20 #include <linux/vmalloc.h>
21 #include <linux/platform_device.h>
22 #include <linux/gpio.h>
23 #include <linux/pm_runtime.h>
24 #include <linux/mmc/host.h>
25 #include <linux/delay.h>
26 #include <linux/semaphore.h>
27 #include <linux/regulator/consumer.h>
28 #include <mach/hardware.h>
29 #include <asm/io.h>
30 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
31 #include <linux/printk.h>
32 #include <linux/err.h>
33 #else
34 #include <config/printk.h>
35 #endif
36 #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)
37 #include <linux/wlan_plat.h>
38 #else
39 struct wifi_platform_data
40 {
41  int (*set_power)(int val);
42  int (*set_reset)(int val);
43  int (*set_carddetect)(int val);
44  void *(*mem_prealloc)(int section, unsigned long size);
45  int (*get_mac_addr)(unsigned char *buf);
46  void *(*get_country_code)(char *ccode);
47 };
48 #endif
49 #define GPIO_REG_WRITEL(val,reg) \
50  do { \
51   __raw_writel(val, CTL_PIN_BASE + (reg)); \
52  } while (0)
53 static int g_wifidev_registered = 0;
54 static struct semaphore wifi_control_sem;
55 static struct wifi_platform_data *wifi_control_data = NULL;
56 static struct resource *wifi_irqres = NULL;
57 static int g_wifi_irq_rc = 0;
58 #define SDIO_ID 1
59 #define IRQ_RES_NAME "ssv_wlan_irq"
60 #define WIFI_HOST_WAKE 0xFFFF
61 extern void sunxi_mci_rescan_card(unsigned id, unsigned insert);
62 extern int wifi_pm_gpio_ctrl(char *name, int level);
ssv_wifi_power(int on)63 static int ssv_wifi_power(int on)
64 {
65  printk("ssv pwr on=%d\n", on);
66  if (on) {
67   wifi_pm_gpio_ctrl("wl_reg_on", 0);
68   mdelay(50);
69   wifi_pm_gpio_ctrl("wl_reg_on", 1);
70  } else {
71   wifi_pm_gpio_ctrl("wl_reg_on", 0);
72  }
73  return 0;
74 }
ssv_wifi_reset(int on)75 static int ssv_wifi_reset(int on)
76 {
77  return 0;
78 }
ssv_wifi_set_carddetect(int val)79 int ssv_wifi_set_carddetect(int val)
80 {
81  sunxi_mci_rescan_card(SDIO_ID, val);
82  return 0;
83 }
84 static struct wifi_platform_data ssv_wifi_control = {
85  .set_power = ssv_wifi_power,
86  .set_reset = ssv_wifi_reset,
87  .set_carddetect = ssv_wifi_set_carddetect,
88 };
89 static struct resource resources[] = { { .start = WIFI_HOST_WAKE,
90       .flags = IORESOURCE_IRQ,
91       .name = IRQ_RES_NAME, }, };
ssv_wifi_device_release(struct device * dev)92 void ssv_wifi_device_release(struct device *dev)
93 {
94  printk(KERN_INFO "ssv_wifi_device_release\n");
95 }
96 static struct platform_device ssv_wifi_device = {
97  .name = "ssv_wlan",
98  .id = 1,
99  .num_resources = ARRAY_SIZE(resources),
100  .resource = resources,
101  .dev = { .platform_data = &ssv_wifi_control,
102    .release = ssv_wifi_device_release, },
103 };
wifi_set_power(int on,unsigned long msec)104 int wifi_set_power(int on, unsigned long msec)
105 {
106  if (wifi_control_data && wifi_control_data->set_power) {
107   wifi_control_data->set_power(on);
108  }
109  if (msec)
110   msleep(msec);
111  return 0;
112 }
wifi_set_reset(int on,unsigned long msec)113 int wifi_set_reset(int on, unsigned long msec)
114 {
115  if (wifi_control_data && wifi_control_data->set_reset) {
116   wifi_control_data->set_reset(on);
117  }
118  if (msec)
119   msleep(msec);
120  return 0;
121 }
wifi_set_carddetect(int on)122 static int wifi_set_carddetect(int on)
123 {
124  if (wifi_control_data && wifi_control_data->set_carddetect) {
125   wifi_control_data->set_carddetect(on);
126  }
127  return 0;
128 }
wifi_wakeup_irq_handler(int irq,void * dev)129 static irqreturn_t wifi_wakeup_irq_handler(int irq, void *dev)
130 {
131  printk("sdhci_wakeup_irq_handler\n");
132  disable_irq_nosync(irq);
133  return IRQ_HANDLED;
134 }
setup_wifi_wakeup_BB(struct platform_device * pdev,bool bEnable)135 void setup_wifi_wakeup_BB(struct platform_device *pdev, bool bEnable)
136 {
137  int rc = 0, ret = 0;
138  if (bEnable) {
139   wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
140           IRQ_RES_NAME);
141   rc = (int)wifi_irqres->start;
142   g_wifi_irq_rc = rc;
143   ret = request_threaded_irq(
144       rc, NULL, (void *)wifi_wakeup_irq_handler,
145 #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 0, 0)
146       IRQ_TYPE_LEVEL_HIGH | IRQF_ONESHOT | IRQF_FORCE_RESUME,
147 #else
148       IRQ_TYPE_LEVEL_HIGH | IRQF_ONESHOT,
149 #endif
150       "wlan_wakeup_irq", NULL);
151   enable_irq_wake(g_wifi_irq_rc);
152  } else {
153   if (g_wifi_irq_rc) {
154    free_irq(g_wifi_irq_rc, NULL);
155    g_wifi_irq_rc = 0;
156   }
157  }
158 }
wifi_probe(struct platform_device * pdev)159 static int wifi_probe(struct platform_device *pdev)
160 {
161  struct wifi_platform_data *wifi_ctrl =
162      (struct wifi_platform_data *)(pdev->dev.platform_data);
163  printk(KERN_ALERT "wifi_probe\n");
164  wifi_control_data = wifi_ctrl;
165  wifi_set_power(0, 40);
166  wifi_set_power(1, 50);
167  wifi_set_carddetect(1);
168  up(&wifi_control_sem);
169  return 0;
170 }
wifi_remove(struct platform_device * pdev)171 static int wifi_remove(struct platform_device *pdev)
172 {
173  struct wifi_platform_data *wifi_ctrl =
174      (struct wifi_platform_data *)(pdev->dev.platform_data);
175  wifi_control_data = wifi_ctrl;
176  wifi_set_power(0, 0);
177  wifi_set_power(0, 0);
178  wifi_set_power(0, 0);
179  wifi_set_power(0, 0);
180  wifi_set_carddetect(0);
181  return 0;
182 }
wifi_suspend(struct platform_device * pdev,pm_message_t state)183 static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
184 {
185  return 0;
186 }
wifi_resume(struct platform_device * pdev)187 static int wifi_resume(struct platform_device *pdev)
188 {
189  return 0;
190 }
191 static struct platform_driver wifi_driver = { .probe = wifi_probe,
192            .remove = wifi_remove,
193            .suspend = wifi_suspend,
194            .resume = wifi_resume,
195            .driver = { .name =
196              "ssv_wlan", } };
197 extern int ssvdevice_init(void);
198 extern void ssvdevice_exit(void);
199 #ifdef CONFIG_SSV_SUPPORT_AES_ASM
200 extern int aes_init(void);
201 extern void aes_fini(void);
202 extern int sha1_mod_init(void);
203 extern void sha1_mod_fini(void);
204 #endif
initWlan(void)205 int initWlan(void)
206 {
207  int ret = 0;
208  sema_init(&wifi_control_sem, 0);
209 #ifdef CONFIG_SSV_SUPPORT_AES_ASM
210  sha1_mod_init();
211  aes_init();
212 #endif
213  platform_device_register(&ssv_wifi_device);
214  platform_driver_register(&wifi_driver);
215  g_wifidev_registered = 1;
216  if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
217   ret = -EINVAL;
218   printk(KERN_ALERT "%s: platform_driver_register timeout\n",
219          __FUNCTION__);
220  }
221  ret = ssvdevice_init();
222  return ret;
223 }
exitWlan(void)224 void exitWlan(void)
225 {
226  if (g_wifidev_registered) {
227   ssvdevice_exit();
228 #ifdef CONFIG_SSV_SUPPORT_AES_ASM
229   aes_fini();
230   sha1_mod_fini();
231 #endif
232   platform_driver_unregister(&wifi_driver);
233   platform_device_unregister(&ssv_wifi_device);
234   g_wifidev_registered = 0;
235  }
236  return;
237 }
generic_wifi_init_module(void)238 static int generic_wifi_init_module(void)
239 {
240  return initWlan();
241 }
generic_wifi_exit_module(void)242 static void generic_wifi_exit_module(void)
243 {
244  exitWlan();
245 }
246 EXPORT_SYMBOL(generic_wifi_init_module);
247 EXPORT_SYMBOL(generic_wifi_exit_module);
248 module_init(generic_wifi_init_module);
249 module_exit(generic_wifi_exit_module);
250 MODULE_LICENSE("Dual BSD/GPL");
251