xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/ssv6xxx/platforms/t10-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 <asm/io.h>
29 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
30 #include <linux/printk.h>
31 #include <linux/err.h>
32 #else
33 #include <config/printk.h>
34 #endif
35 #if LINUX_VERSION_CODE > KERNEL_VERSION(3,2,0)
36 #include <linux/wlan_plat.h>
37 #else
38 struct wifi_platform_data {
39  int (*set_power)(int val);
40  int (*set_reset)(int val);
41  int (*set_carddetect)(int val);
42  void *(*mem_prealloc)(int section, unsigned long size);
43  int (*get_mac_addr)(unsigned char *buf);
44  void *(*get_country_code)(char *ccode);
45 };
46 #endif
47 #define GPIO_REG_WRITEL(val,reg) do{__raw_writel(val, CTL_PIN_BASE + (reg));}while(0)
48 static int g_wifidev_registered = 0;
49 static struct semaphore wifi_control_sem;
50 static struct wifi_platform_data *wifi_control_data = NULL;
51 static struct resource *wifi_irqres = NULL;
52 static int g_wifi_irq_rc=0;
53 #define SDIO_ID 2
54 #define IRQ_RES_NAME "ssv_wlan_irq"
55 #define WIFI_HOST_WAKE 0xFFFF
56 extern int ssv_6xxx_wlan_init(void);
57 extern int ssv_wlan_power_on(int flag);
58 extern int ssv_wlan_power_off(int flag);
wifi_pm_gpio_ctrl(char * name,int level)59 static int wifi_pm_gpio_ctrl(char* name, int level)
60 {
61     (void)name;
62     (void)level;
63     if (level)
64     {
65         ssv_wlan_power_on(1);
66     }
67     else
68     {
69         ssv_wlan_power_off(1);
70     }
71     return 0;
72 }
ssv_wifi_power(int on)73 static int ssv_wifi_power(int on)
74 {
75     printk("ssv pwr on=%d\n",on);
76  if(on)
77  {
78   wifi_pm_gpio_ctrl("wifi_ssv6200_power", 0);
79   mdelay(50);
80         wifi_pm_gpio_ctrl("wifi_ssv6200_power", 1);
81  }
82  else
83  {
84   wifi_pm_gpio_ctrl("wifi_ssv6200_power", 0);
85  }
86     return 0;
87 }
ssv_wifi_reset(int on)88 static int ssv_wifi_reset(int on)
89 {
90     return 0;
91 }
ssv_wifi_set_carddetect(int val)92 int ssv_wifi_set_carddetect(int val)
93 {
94     if (val)
95     {
96         ssv_wlan_power_on(1);
97     }
98     else
99     {
100         ssv_wlan_power_off(1);
101     }
102     return 0;
103 }
104 static struct wifi_platform_data ssv_wifi_control = {
105     .set_power = ssv_wifi_power,
106     .set_reset = ssv_wifi_reset,
107     .set_carddetect = ssv_wifi_set_carddetect,
108 };
109 static struct resource resources[] = {
110         {
111                 .start = WIFI_HOST_WAKE,
112                 .flags = IORESOURCE_IRQ,
113                 .name = IRQ_RES_NAME,
114         },
115 };
ssv_wifi_device_release(struct device * dev)116 void ssv_wifi_device_release(struct device *dev)
117 {
118     printk(KERN_INFO "ssv_wifi_device_release\n");
119 }
120 static struct platform_device ssv_wifi_device = {
121         .name = "ssv_wlan",
122         .id = 1,
123         .num_resources = ARRAY_SIZE(resources),
124         .resource = resources,
125         .dev = {
126                 .platform_data = &ssv_wifi_control,
127                 .release = ssv_wifi_device_release,
128          },
129 };
wifi_set_power(int on,unsigned long msec)130 int wifi_set_power(int on, unsigned long msec)
131 {
132  if (wifi_control_data && wifi_control_data->set_power) {
133   wifi_control_data->set_power(on);
134  }
135  if (msec)
136   msleep(msec);
137  return 0;
138 }
wifi_set_reset(int on,unsigned long msec)139 int wifi_set_reset(int on, unsigned long msec)
140 {
141  if (wifi_control_data && wifi_control_data->set_reset) {
142   wifi_control_data->set_reset(on);
143  }
144  if (msec)
145   msleep(msec);
146  return 0;
147 }
wifi_set_carddetect(int on)148 static int wifi_set_carddetect(int on)
149 {
150  if (wifi_control_data && wifi_control_data->set_carddetect) {
151     printk("[Debug-%s-%d]------\n",__func__,__LINE__);
152   wifi_control_data->set_carddetect(on);
153  }
154  return 0;
155 }
wifi_wakeup_irq_handler(int irq,void * dev)156 static irqreturn_t wifi_wakeup_irq_handler(int irq, void *dev){
157     printk("sdhci_wakeup_irq_handler\n");
158      disable_irq_nosync(irq);
159          return IRQ_HANDLED;
160 }
setup_wifi_wakeup_BB(struct platform_device * pdev,bool bEnable)161 void setup_wifi_wakeup_BB(struct platform_device *pdev, bool bEnable)
162 {
163     int rc=0,ret=0;
164     if (bEnable){
165       wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, IRQ_RES_NAME);
166        rc = (int)wifi_irqres->start;
167         g_wifi_irq_rc = rc;
168         ret = request_threaded_irq(rc,
169                                     NULL,
170                                     (void *)wifi_wakeup_irq_handler,
171 #if LINUX_VERSION_CODE > KERNEL_VERSION(3,0,0)
172                                     IRQ_TYPE_LEVEL_HIGH | IRQF_ONESHOT |IRQF_FORCE_RESUME,
173 #else
174                                     IRQ_TYPE_LEVEL_HIGH | IRQF_ONESHOT,
175 #endif
176                                     "wlan_wakeup_irq", NULL);
177         enable_irq_wake(g_wifi_irq_rc);
178     }else{
179         if(g_wifi_irq_rc){
180             free_irq(g_wifi_irq_rc,NULL);
181             g_wifi_irq_rc = 0;
182         }
183     }
184 }
wifi_probe(struct platform_device * pdev)185 static int wifi_probe(struct platform_device *pdev)
186 {
187  struct wifi_platform_data *wifi_ctrl =
188   (struct wifi_platform_data *)(pdev->dev.platform_data);
189  printk(KERN_ALERT "wifi_probe\n");
190     wifi_control_data = wifi_ctrl;
191     #ifndef CONFIG_SSV6XXX
192     printk("[Debug-%s-%d]------\n",__func__,__LINE__);
193     ssv_6xxx_wlan_init();
194     #endif
195     printk("[Debug-%s-%d]------\n",__func__,__LINE__);
196     wifi_set_carddetect(1);
197     up(&wifi_control_sem);
198     return 0;
199 }
wifi_remove(struct platform_device * pdev)200 static int wifi_remove(struct platform_device *pdev)
201 {
202  struct wifi_platform_data *wifi_ctrl =
203   (struct wifi_platform_data *)(pdev->dev.platform_data);
204  wifi_control_data = wifi_ctrl;
205  wifi_set_power(0, 0);
206  wifi_set_carddetect(0);
207  setup_wifi_wakeup_BB(pdev,false);
208  return 0;
209 }
wifi_suspend(struct platform_device * pdev,pm_message_t state)210 static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
211 {
212     setup_wifi_wakeup_BB(pdev,true);
213     return 0;
214 }
wifi_resume(struct platform_device * pdev)215 static int wifi_resume(struct platform_device *pdev)
216 {
217     setup_wifi_wakeup_BB(pdev,false);
218     return 0;
219 }
220 static struct platform_driver wifi_driver = {
221  .probe = wifi_probe,
222  .remove = wifi_remove,
223  .suspend = wifi_suspend,
224  .resume = wifi_resume,
225  .driver = {
226  .name = "ssv_wlan",
227  }
228 };
229 extern int ssvdevice_init(void);
230 extern void ssvdevice_exit(void);
231 #ifdef CONFIG_SSV_SUPPORT_AES_ASM
232 extern int aes_init(void);
233 extern void aes_fini(void);
234 extern int sha1_mod_init(void);
235 extern void sha1_mod_fini(void);
236 #endif
initWlan(void)237 int initWlan(void)
238 {
239     int ret=0;
240     sema_init(&wifi_control_sem, 0);
241 #ifdef CONFIG_SSV_SUPPORT_AES_ASM
242     sha1_mod_init();
243     aes_init();
244 #endif
245     platform_device_register(&ssv_wifi_device);
246     platform_driver_register(&wifi_driver);
247     g_wifidev_registered = 1;
248     if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
249         ret = -EINVAL;
250         printk(KERN_ALERT "%s: platform_driver_register timeout\n", __FUNCTION__);
251     }
252     ret = ssvdevice_init();
253     return ret;
254 }
exitWlan(void)255 void exitWlan(void)
256 {
257     if (g_wifidev_registered)
258     {
259         ssvdevice_exit();
260 #ifdef CONFIG_SSV_SUPPORT_AES_ASM
261         aes_fini();
262         sha1_mod_fini();
263 #endif
264         platform_driver_unregister(&wifi_driver);
265         platform_device_unregister(&ssv_wifi_device);
266         g_wifidev_registered = 0;
267     }
268     return;
269 }
generic_wifi_init_module(void)270 static int generic_wifi_init_module(void)
271 {
272  return initWlan();
273 }
generic_wifi_exit_module(void)274 static void generic_wifi_exit_module(void)
275 {
276  exitWlan();
277 }
278 EXPORT_SYMBOL(generic_wifi_init_module);
279 EXPORT_SYMBOL(generic_wifi_exit_module);
280 #ifdef CONFIG_SSV6XXX
281 late_initcall(generic_wifi_init_module);
282 #else
283 module_init(generic_wifi_init_module);
284 #endif
285 module_exit(generic_wifi_exit_module);
286 MODULE_LICENSE("Dual BSD/GPL");
287