f4228e71a90da2c3dd32ae97ab831ba69a0c69c3
[firefly-linux-kernel-4.4.55.git] / drivers / misc / bp / chips / mu509.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 #else\r
46 #define DBG(x...)\r
47 #endif\r
48 \r
49 \r
50 /****************operate according to bp chip:start************/\r
51 static int bp_active(struct bp_private_data *bp, int enable)\r
52 {       \r
53         int result = 0;\r
54         if(enable)\r
55         {\r
56                 gpio_direction_output(bp->ops->bp_reset, GPIO_HIGH);\r
57                 msleep(100);\r
58                 gpio_direction_output(bp->ops->bp_reset, GPIO_LOW);\r
59                 gpio_direction_output(bp->ops->bp_en, GPIO_LOW);\r
60                 msleep(1000);\r
61                 gpio_direction_output(bp->ops->bp_en, GPIO_HIGH);\r
62                 msleep(700);\r
63                 gpio_direction_output(bp->ops->bp_en, GPIO_LOW);\r
64                 gpio_direction_output(bp->ops->ap_wakeup_bp, GPIO_LOW);\r
65         }\r
66         else\r
67         {\r
68                 gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
69                 gpio_set_value(bp->ops->bp_en, GPIO_HIGH);\r
70                 msleep(2500);\r
71                 gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
72         }\r
73         \r
74         return result;\r
75 }\r
76 \r
77 static int ap_wake_bp(struct bp_private_data *bp, int wake)\r
78 {\r
79         int result = 0;\r
80         \r
81         gpio_direction_output(bp->ops->ap_wakeup_bp, wake);  \r
82         \r
83         return result;\r
84 \r
85 }\r
86 \r
87 static void  ap_wake_bp_work(struct work_struct *work)\r
88 {\r
89         struct delayed_work *wakeup_work = container_of(work, struct delayed_work, work);\r
90         struct bp_private_data *bp = container_of(wakeup_work, struct bp_private_data, wakeup_work);\r
91 \r
92         if(bp->suspend_status)\r
93         {\r
94                 if(bp->ops->ap_wake_bp)\r
95                 bp->ops->ap_wake_bp(bp, 0);\r
96         }\r
97         else    \r
98         {\r
99                 if(bp->ops->ap_wake_bp)\r
100                 bp->ops->ap_wake_bp(bp, 1);\r
101         }\r
102 }\r
103 \r
104 \r
105 static int bp_init(struct bp_private_data *bp)\r
106 {\r
107         int result = 0;\r
108         gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);\r
109         msleep(1000);\r
110         if(bp->ops->active)\r
111                 bp->ops->active(bp, 1);\r
112 \r
113         INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);\r
114         return result;\r
115 }\r
116 \r
117 static int bp_reset(struct bp_private_data *bp)\r
118 {\r
119         gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);\r
120         msleep(100);\r
121         gpio_direction_output(bp->ops->bp_power, GPIO_LOW);\r
122 \r
123         return 0;\r
124 }\r
125 \r
126 static int bp_wake_ap(struct bp_private_data *bp)\r
127 {\r
128         int result = 0;\r
129         \r
130         if(bp->suspend_status)\r
131         {\r
132                 bp->suspend_status = 0;\r
133                 wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);\r
134         }\r
135         \r
136         return result;\r
137 }\r
138 \r
139 \r
140 static int bp_shutdown(struct bp_private_data *bp)\r
141 {\r
142         int result = 0;\r
143         \r
144         if(bp->ops->active)\r
145                 bp->ops->active(bp, 0);\r
146         \r
147         cancel_delayed_work_sync(&bp->wakeup_work);     \r
148                 \r
149         return result;\r
150 }\r
151 \r
152 \r
153 static int read_status(struct bp_private_data *bp)\r
154 {\r
155         int result = 0;\r
156         \r
157         return result;\r
158 }\r
159 \r
160 \r
161 static int write_status(struct bp_private_data *bp)\r
162 {\r
163         int result = 0;\r
164 \r
165         if (bp->status == BP_ON)\r
166         {\r
167                 gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);\r
168                 gpio_direction_output(bp->ops->bp_uart_en,GPIO_LOW);\r
169         }\r
170         else if(bp->status == BP_OFF)\r
171         {\r
172                 gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);\r
173                 gpio_direction_output(bp->ops->bp_uart_en,GPIO_HIGH);\r
174         }\r
175         else\r
176         {\r
177                 printk("%s, invalid parameter \n", __FUNCTION__);\r
178         }\r
179         \r
180         return result;\r
181 }\r
182 \r
183 static int bp_suspend(struct bp_private_data *bp)\r
184 {       \r
185         int result = 0;\r
186         \r
187         if(!bp->suspend_status)\r
188         {\r
189                 bp->suspend_status = 1; \r
190         }\r
191         \r
192         return result;\r
193 }\r
194 \r
195 \r
196 \r
197 \r
198 static int bp_resume(struct bp_private_data *bp)\r
199 {\r
200         if(bp->suspend_status)\r
201         {\r
202                 bp->suspend_status = 0; \r
203                 gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);        \r
204         }\r
205         \r
206         return 0;\r
207 }\r
208 \r
209 \r
210 struct bp_operate bp_mu509_ops = {\r
211         .name                   = "mu509",\r
212         .bp_id                  = BP_ID_MU509,\r
213         .bp_bus                 = BP_BUS_TYPE_USB_UART,         \r
214         .bp_pid                 = 0,    \r
215         .bp_vid                 = 0,    \r
216         .bp_power               = RK30_PIN6_PB2,        // 3g_power\r
217         .bp_en                  = RK30_PIN2_PB6,        // 3g_en\r
218         .bp_reset               = RK30_PIN2_PC1,\r
219         .ap_ready               = BP_UNKNOW_DATA,       //\r
220         .bp_ready               = BP_UNKNOW_DATA,\r
221         .ap_wakeup_bp           = RK30_PIN2_PB7,\r
222         .bp_wakeup_ap           = RK30_PIN6_PA1,        //\r
223         .bp_uart_en             = BP_UNKNOW_DATA,       //EINT9\r
224         .bp_usb_en              = BP_UNKNOW_DATA,       //W_disable\r
225         .trig                   = IRQF_TRIGGER_FALLING,\r
226 \r
227         .active                 = bp_active,\r
228         .init                   = bp_init,\r
229         .reset                  = bp_reset,\r
230         .ap_wake_bp             = ap_wake_bp,\r
231         .bp_wake_ap             = bp_wake_ap,\r
232         .shutdown               = bp_shutdown,\r
233         .read_status            = read_status,\r
234         .write_status           = write_status,\r
235         .suspend                = bp_suspend,\r
236         .resume                 = bp_resume,\r
237         .misc_name              = "mu509",\r
238         .private_miscdev        = NULL,\r
239 };\r
240 \r
241 /****************operate according to bp chip:end************/\r
242 \r
243 //function name should not be changed\r
244 static struct bp_operate *bp_get_ops(void)\r
245 {\r
246         return &bp_mu509_ops;\r
247 }\r
248 \r
249 static int __init bp_mu509_init(void)\r
250 {\r
251         struct bp_operate *ops = bp_get_ops();\r
252         int result = 0;\r
253         result = bp_register_slave(NULL, NULL, bp_get_ops);\r
254         if(result)\r
255         {       \r
256                 return result;\r
257         }\r
258         \r
259         if(ops->private_miscdev)\r
260         {\r
261                 result = misc_register(ops->private_miscdev);\r
262                 if (result < 0) {\r
263                         printk("%s:misc_register err\n",__func__);\r
264                         return result;\r
265                 }\r
266         }\r
267         \r
268         DBG("%s\n",__func__);\r
269         return result;\r
270 }\r
271 \r
272 static void __exit bp_mu509_exit(void)\r
273 {\r
274         //struct bp_operate *ops = bp_get_ops();\r
275         bp_unregister_slave(NULL, NULL, bp_get_ops);\r
276 }\r
277 \r
278 \r
279 subsys_initcall(bp_mu509_init);\r
280 module_exit(bp_mu509_exit);\r
281 \r