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