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