b135ba83668ce24fcca819a89a91359533555e1d
[firefly-linux-kernel-4.4.55.git] / drivers / misc / bp / chips / sew290.c
1 /* drivers/misc/bp/chips/mu509.c\r
2  *\r
3  * Copyright (C) 2012-2015 ROCKCHIP.\r
4  * Author: luowei <lw@rock-chips.com>\r
5  *\r
6  * This software is licensed under the terms of the GNU General Public\r
7  * License version 2, as published by the Free Software Foundation, and\r
8  * may be copied, distributed, and modified under those terms.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  */\r
16 #include <linux/module.h>\r
17 #include <linux/kernel.h>\r
18 #include <linux/i2c.h>\r
19 #include <linux/irq.h>\r
20 #include <linux/gpio.h>\r
21 #include <linux/input.h>\r
22 #include <linux/platform_device.h>\r
23 #include <linux/fs.h>\r
24 #include <linux/uaccess.h>\r
25 #include <linux/miscdevice.h>\r
26 #include <linux/circ_buf.h>\r
27 #include <linux/interrupt.h>\r
28 #include <linux/miscdevice.h>\r
29 #include <mach/iomux.h>\r
30 #include <mach/gpio.h>\r
31 #include <asm/gpio.h>\r
32 #include <linux/delay.h>\r
33 #include <linux/poll.h>\r
34 #include <linux/wait.h>\r
35 #include <linux/wakelock.h>\r
36 #include <linux/workqueue.h>\r
37 #include <linux/slab.h>\r
38 #include <linux/earlysuspend.h>\r
39 \r
40 #include <linux/bp-auto.h>\r
41          \r
42          \r
43 #if 0\r
44 #define DBG(x...)  printk(x)\r
45 \r
46 #else\r
47 #define DBG(x...)\r
48 #endif\r
49 \r
50 \r
51 /****************operate according to bp chip:start************/\r
52 static int bp_active(struct bp_private_data *bp, int enable)\r
53 {               \r
54         printk("<-----SEW290 bp_active-------->\n");\r
55         if(enable)\r
56         {\r
57                 gpio_set_value(bp->ops->bp_power, GPIO_LOW);\r
58                 msleep(1000);\r
59                 gpio_set_value(bp->ops->bp_power, GPIO_HIGH);\r
60                 msleep(2500);\r
61                 gpio_set_value(bp->ops->bp_power, GPIO_LOW);\r
62                 gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);\r
63         }\r
64         else\r
65         {\r
66                 gpio_set_value(bp->ops->bp_en, GPIO_HIGH);\r
67                 msleep(4000);\r
68                 gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
69 \r
70         }\r
71         \r
72         return 0;\r
73 }\r
74 \r
75 static int ap_wake_bp(struct bp_private_data *bp, int wake)\r
76 {\r
77         int result = 0;\r
78         \r
79         gpio_set_value(bp->ops->ap_wakeup_bp, wake);  \r
80         \r
81         return result;\r
82 \r
83 }\r
84 \r
85 static void  ap_wake_bp_work(struct work_struct *work)\r
86 {\r
87         struct delayed_work *wakeup_work = container_of(work, struct delayed_work, work);\r
88         struct bp_private_data *bp = container_of(wakeup_work, struct bp_private_data, wakeup_work);\r
89 \r
90         if(bp->suspend_status)\r
91         {\r
92                 if(bp->ops->ap_wake_bp)\r
93                 bp->ops->ap_wake_bp(bp, 0);\r
94         }\r
95         else    \r
96         {\r
97                 if(bp->ops->ap_wake_bp)\r
98                 bp->ops->ap_wake_bp(bp, 1);\r
99         }\r
100 }\r
101 \r
102 \r
103 static int bp_init(struct bp_private_data *bp)\r
104 {\r
105         printk("<-----SEW290 bp_init-------->\n");\r
106         gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);\r
107         gpio_set_value(bp->ops->bp_power, GPIO_HIGH);\r
108         msleep(500);\r
109         //if(bp->ops->active)\r
110         //      bp->ops->active(bp, 1);\r
111         gpio_direction_input(bp->ops->bp_wakeup_ap);\r
112         gpio_direction_output(bp->ops->bp_reset, GPIO_LOW);\r
113         gpio_direction_output(bp->ops->bp_en, GPIO_LOW);\r
114         gpio_direction_output(bp->ops->ap_wakeup_bp, GPIO_HIGH);\r
115         INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);\r
116         return 0;\r
117 }\r
118 \r
119 static int bp_reset(struct bp_private_data *bp)\r
120 {\r
121 //      gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);\r
122 //      msleep(500);\r
123         gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);\r
124         msleep(100);\r
125         gpio_set_value(bp->ops->bp_reset, GPIO_LOW);\r
126         gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
127         msleep(1000);\r
128         gpio_set_value(bp->ops->bp_en, GPIO_HIGH);\r
129         msleep(700);\r
130         gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
131         gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);\r
132 \r
133         return 0;\r
134 }\r
135 \r
136 static int bp_wake_ap(struct bp_private_data *bp)\r
137 {\r
138         printk("<-----SEW290 bp_wake_ap-------->\n");\r
139         \r
140         bp->suspend_status = 0;\r
141         wake_lock_timeout(&bp->bp_wakelock, 20* HZ);\r
142         \r
143         return 0;\r
144 }\r
145 \r
146 \r
147 static int bp_shutdown(struct bp_private_data *bp)\r
148 {\r
149         int result = 0;\r
150         \r
151         if(bp->ops->active)\r
152                 bp->ops->active(bp, 0);\r
153         gpio_set_value(bp->ops->bp_power, GPIO_LOW);\r
154         cancel_delayed_work_sync(&bp->wakeup_work);     \r
155 \r
156         return result;\r
157 }\r
158 \r
159 \r
160 \r
161 static int bp_suspend(struct bp_private_data *bp)\r
162 {       \r
163 \r
164         printk("<-----SEW290 bp_suspend-------->\n");\r
165         \r
166         bp->suspend_status = 1;\r
167         gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);                \r
168         \r
169         return 0;\r
170 }\r
171 \r
172 \r
173 \r
174 \r
175 static int bp_resume(struct bp_private_data *bp)\r
176 {       \r
177 \r
178         printk("<-----SEW290 bp_resume-------->\n");\r
179         bp->suspend_status = 0; \r
180         gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);       \r
181         \r
182         \r
183         return 0;\r
184 }\r
185 \r
186 \r
187 struct bp_operate bp_sew290_ops = {\r
188 #if defined(CONFIG_ARCH_RK2928)\r
189         .name                   = "sew290",\r
190         .bp_id                  = BP_ID_SEW290,\r
191         .bp_bus                 = BP_BUS_TYPE_USB_UART,         \r
192         .bp_pid                 = 0,    \r
193         .bp_vid                 = 0,    \r
194         .bp_power               = RK2928_PIN3_PC2,      // 3g_power\r
195         .bp_en                  = BP_UNKNOW_DATA,       // 3g_en\r
196         .bp_reset                       = RK2928_PIN1_PA3,\r
197         .ap_ready               = BP_UNKNOW_DATA,       //\r
198         .bp_ready               = BP_UNKNOW_DATA,\r
199         .ap_wakeup_bp           = RK2928_PIN3_PC4,\r
200         .bp_wakeup_ap           = RK2928_PIN3_PC3,      //\r
201         .bp_uart_en             = BP_UNKNOW_DATA,       //EINT9\r
202         .bp_usb_en              = BP_UNKNOW_DATA,       //W_disable\r
203         .trig                   = IRQF_TRIGGER_FALLING,\r
204 \r
205         .active                 = bp_active,\r
206         .init                   = bp_init,\r
207         .reset                  = bp_reset,\r
208         .ap_wake_bp             = ap_wake_bp,\r
209         .bp_wake_ap             = bp_wake_ap,\r
210         .shutdown               = bp_shutdown,\r
211         .read_status            = NULL,\r
212         .write_status           = NULL,\r
213         .suspend                = bp_suspend,\r
214         .resume                 = bp_resume,\r
215         .misc_name              = NULL,\r
216         .private_miscdev        = NULL,\r
217 #elif defined(CONFIG_ARCH_RK30)\r
218         .name                   = "sew290",\r
219         .bp_id                  = BP_ID_SEW290,\r
220         .bp_bus                 = BP_BUS_TYPE_USB_UART,         \r
221         .bp_pid                 = 0,    \r
222         .bp_vid                 = 0,    \r
223         .bp_power               = BP_UNKNOW_DATA,       // 3g_power\r
224         .bp_en                  = BP_UNKNOW_DATA,       // 3g_en\r
225         .bp_reset                       = BP_UNKNOW_DATA,\r
226         .ap_ready               = BP_UNKNOW_DATA,       //\r
227         .bp_ready               = BP_UNKNOW_DATA,\r
228         .ap_wakeup_bp           = RK30_PIN2_PC5,\r
229         .bp_wakeup_ap           = RK30_PIN2_PC4,        //\r
230         .bp_uart_en             = BP_UNKNOW_DATA,       //EINT9\r
231         .bp_usb_en              = BP_UNKNOW_DATA,       //W_disable\r
232         .trig                   = IRQF_TRIGGER_RISING,\r
233 \r
234         .active                 = bp_active,\r
235         .init                   = bp_init,\r
236         .reset                  = bp_reset,\r
237         .ap_wake_bp             = ap_wake_bp,\r
238         .bp_wake_ap             = bp_wake_ap,\r
239         .shutdown               = bp_shutdown,\r
240         .read_status            = NULL,\r
241         .write_status           = NULL,\r
242         .suspend                = bp_suspend,\r
243         .resume                 = bp_resume,\r
244         .misc_name              = NULL,\r
245         .private_miscdev        = NULL,\r
246 #else\r
247         .name                   = "sew290",\r
248         .bp_id                  = BP_ID_SEW290,\r
249         .bp_bus                 = BP_BUS_TYPE_USB_UART,         \r
250         .bp_pid                 = 0,    \r
251         .bp_vid                 = 0,    \r
252         .bp_power               = BP_UNKNOW_DATA,//RK2928_PIN3_PC2,     // 3g_power\r
253         .bp_en                  = BP_UNKNOW_DATA,       // 3g_en\r
254         .bp_reset                       = BP_UNKNOW_DATA,//RK2928_PIN1_PA3,\r
255         .ap_ready               = BP_UNKNOW_DATA,       //\r
256         .bp_ready               = BP_UNKNOW_DATA,\r
257         .ap_wakeup_bp           = BP_UNKNOW_DATA,//RK2928_PIN3_PC4,\r
258         .bp_wakeup_ap           = BP_UNKNOW_DATA,//RK2928_PIN3_PC3,     //\r
259         .bp_uart_en             = BP_UNKNOW_DATA,       //EINT9\r
260         .bp_usb_en              = BP_UNKNOW_DATA,       //W_disable\r
261         .trig                   = IRQF_TRIGGER_FALLING,\r
262 \r
263         .active                 = bp_active,\r
264         .init                   = bp_init,\r
265         .reset                  = bp_reset,\r
266         .ap_wake_bp             = ap_wake_bp,\r
267         .bp_wake_ap             = bp_wake_ap,\r
268         .shutdown               = bp_shutdown,\r
269         .read_status            = NULL,\r
270         .write_status           = NULL,\r
271         .suspend                = bp_suspend,\r
272         .resume                 = bp_resume,\r
273         .misc_name              = NULL,\r
274         .private_miscdev        = NULL,\r
275 #endif\r
276 };\r
277 \r
278 /****************operate according to bp chip:end************/\r
279 \r
280 //function name should not be changed\r
281 static struct bp_operate *bp_get_ops(void)\r
282 {\r
283         return &bp_sew290_ops;\r
284 }\r
285 \r
286 static int __init bp_sew290_init(void)\r
287 {\r
288         struct bp_operate *ops = bp_get_ops();\r
289         int result = 0;\r
290         result = bp_register_slave(NULL, NULL, bp_get_ops);\r
291         if(result)\r
292         {       \r
293                 return result;\r
294         }\r
295         \r
296         if(ops->private_miscdev)\r
297         {\r
298                 result = misc_register(ops->private_miscdev);\r
299                 if (result < 0) {\r
300                         printk("%s:misc_register err\n",__func__);\r
301                         return result;\r
302                 }\r
303         }\r
304         \r
305         DBG("%s\n",__func__);\r
306         return result;\r
307 }\r
308 \r
309 static void __exit bp_sew290_exit(void)\r
310 {\r
311         //struct bp_operate *ops = bp_get_ops();\r
312         bp_unregister_slave(NULL, NULL, bp_get_ops);\r
313 }\r
314 \r
315 \r
316 subsys_initcall(bp_sew290_init);\r
317 module_exit(bp_sew290_exit);\r
318 \r