change u5501 modem usbport to 244
[firefly-linux-kernel-4.4.55.git] / drivers / misc / bp / chips / u5501.c
1 /* drivers/misc/bp/chips/u5501.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_power, GPIO_HIGH);\r
57 //              msleep(500);\r
58                 gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);\r
59                 msleep(100);\r
60                 gpio_set_value(bp->ops->bp_reset, GPIO_LOW);\r
61                 gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
62                 msleep(1000);\r
63                 gpio_set_value(bp->ops->bp_en, GPIO_HIGH);\r
64                 msleep(700);\r
65                 gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
66                 gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);\r
67         }\r
68         else\r
69         {\r
70 //              gpio_direction_output(bp->ops->bp_power, GPIO_LOW);\r
71                 gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
72                 gpio_set_value(bp->ops->bp_en, GPIO_HIGH);\r
73                 msleep(2500);\r
74                 gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
75         }\r
76         \r
77         return result;\r
78 }\r
79 \r
80 static int ap_wake_bp(struct bp_private_data *bp, int wake)\r
81 {\r
82         int result = 0;\r
83         \r
84         gpio_set_value(bp->ops->ap_wakeup_bp, wake);  \r
85         \r
86         return result;\r
87 \r
88 }\r
89 \r
90 static void  ap_wake_bp_work(struct work_struct *work)\r
91 {\r
92         struct delayed_work *wakeup_work = container_of(work, struct delayed_work, work);\r
93         struct bp_private_data *bp = container_of(wakeup_work, struct bp_private_data, wakeup_work);\r
94 \r
95         if(bp->suspend_status)\r
96         {\r
97                 if(bp->ops->ap_wake_bp)\r
98                 bp->ops->ap_wake_bp(bp, 0);\r
99                 bp->suspend_status = 0;\r
100         }\r
101         else    \r
102         {\r
103                 if(bp->ops->ap_wake_bp)\r
104                 bp->ops->ap_wake_bp(bp, 1);\r
105         }\r
106 }\r
107 \r
108 \r
109 static int bp_init(struct bp_private_data *bp)\r
110 {\r
111         int result = 0;\r
112         gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);\r
113         gpio_set_value(bp->ops->bp_power, GPIO_HIGH);\r
114         msleep(500);\r
115         //if(bp->ops->active)\r
116         //      bp->ops->active(bp, 1);\r
117         gpio_direction_input(bp->ops->bp_wakeup_ap);\r
118         gpio_pull_updown(bp->ops->bp_wakeup_ap, 1);     \r
119         gpio_direction_output(bp->ops->bp_reset, GPIO_LOW);\r
120         gpio_direction_output(bp->ops->bp_en, GPIO_LOW);\r
121         gpio_direction_output(bp->ops->ap_wakeup_bp, GPIO_LOW);\r
122         INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);\r
123         return result;\r
124 }\r
125 \r
126 static int bp_reset(struct bp_private_data *bp)\r
127 {\r
128 //      gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);\r
129 //      msleep(500);\r
130         gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);\r
131         msleep(100);\r
132         gpio_set_value(bp->ops->bp_reset, GPIO_LOW);\r
133         gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
134         msleep(1000);\r
135         gpio_set_value(bp->ops->bp_en, GPIO_HIGH);\r
136         msleep(700);\r
137         gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
138         gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);\r
139 \r
140         return 0;\r
141 }\r
142 \r
143 static int bp_wake_ap(struct bp_private_data *bp)\r
144 {\r
145         int result = 0;\r
146         \r
147         bp->suspend_status = 0;\r
148         wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);\r
149         \r
150         return result;\r
151 }\r
152 \r
153 \r
154 static int bp_shutdown(struct bp_private_data *bp)\r
155 {\r
156         int result = 0;\r
157         \r
158         if(bp->ops->active)\r
159                 bp->ops->active(bp, 0);\r
160         gpio_set_value(bp->ops->bp_power, GPIO_LOW);\r
161         cancel_delayed_work_sync(&bp->wakeup_work);     \r
162 \r
163         return result;\r
164 }\r
165 \r
166 \r
167 \r
168 static int bp_suspend(struct bp_private_data *bp)\r
169 {       \r
170         int result = 0;\r
171         printk("<-----u5501 bp_suspend-------->\n");\r
172         #if defined(CONFIG_ARCH_RK29)\r
173                 rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);\r
174         #elif defined(CONFIG_SOC_RK3066)\r
175                 rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_GPIO1A7);\r
176         #endif\r
177         \r
178         if(!bp->suspend_status)\r
179         {\r
180                 bp->suspend_status = 1; \r
181                 gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);       \r
182         }\r
183         #if defined(CONFIG_ARCH_RK2928)\r
184         rk29_mux_api_set(GPIO1B1_SPI_TXD_UART1_SOUT_NAME, GPIO1B_GPIO1B1);\r
185         gpio_set_value(RK2928_PIN1_PB1, GPIO_LOW);\r
186         #elif defined(CONFIG_SOC_RK3066)\r
187         rk30_mux_api_set(GPIO1A5_UART1SOUT_SPI0CLK_NAME, GPIO1A_GPIO1A5);\r
188         gpio_set_value(RK30_PIN1_PA5, GPIO_LOW);\r
189         #endif\r
190         return result;\r
191 }\r
192 \r
193 \r
194 \r
195 \r
196 static int bp_resume(struct bp_private_data *bp)\r
197 {       \r
198         #if defined(CONFIG_ARCH_RK29)\r
199                 rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);\r
200         #elif defined(CONFIG_SOC_RK3066)\r
201                 rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_UART1_RTS_N);\r
202         #endif\r
203         \r
204         #if defined(CONFIG_ARCH_RK2928)\r
205         rk29_mux_api_set(GPIO1B1_SPI_TXD_UART1_SOUT_NAME, GPIO1B_UART1_SOUT);\r
206         #elif defined(CONFIG_SOC_RK3066)\r
207         rk30_mux_api_set(GPIO1A5_UART1SOUT_SPI0CLK_NAME, GPIO1A_UART1_SOUT);\r
208         #endif\r
209         //bp->suspend_status = 0;       \r
210         //gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);      \r
211         schedule_delayed_work(&bp->wakeup_work, 4*HZ);\r
212         \r
213         \r
214         return 0;\r
215 }\r
216 \r
217 \r
218 struct bp_operate bp_u5501_ops = {\r
219 #if defined(CONFIG_ARCH_RK2928)\r
220         .name                   = "u5501",\r
221         .bp_id                  = BP_ID_U5501,\r
222         .bp_bus                 = BP_BUS_TYPE_USB_UART,         \r
223         .bp_pid                 = 0,    \r
224         .bp_vid                 = 0,    \r
225         .bp_power               = RK2928_PIN3_PC2,      // 3g_power\r
226         .bp_en                  = BP_UNKNOW_DATA,       // 3g_en\r
227         .bp_reset                       = RK2928_PIN1_PA3,\r
228         .ap_ready               = BP_UNKNOW_DATA,       //\r
229         .bp_ready               = BP_UNKNOW_DATA,\r
230         .ap_wakeup_bp           = RK2928_PIN3_PC4,\r
231         .bp_wakeup_ap           = RK2928_PIN3_PC3,      //\r
232         .bp_uart_en             = BP_UNKNOW_DATA,       //EINT9\r
233         .bp_usb_en              = BP_UNKNOW_DATA,       //W_disable\r
234         .trig                   = IRQF_TRIGGER_FALLING,\r
235 \r
236         .active                 = bp_active,\r
237         .init                   = bp_init,\r
238         .reset                  = bp_reset,\r
239         .ap_wake_bp             = ap_wake_bp,\r
240         .bp_wake_ap             = bp_wake_ap,\r
241         .shutdown               = bp_shutdown,\r
242         .read_status            = NULL,\r
243         .write_status           = NULL,\r
244         .suspend                = bp_suspend,\r
245         .resume                 = bp_resume,\r
246         .misc_name              = NULL,\r
247         .private_miscdev        = NULL,\r
248 #elif defined(CONFIG_ARCH_RK30)\r
249         .name                   = "u5501",\r
250         .bp_id                  = BP_ID_U5501,\r
251         .bp_bus                 = BP_BUS_TYPE_USB_UART,         \r
252         .bp_pid                 = 0,    \r
253         .bp_vid                 = 0,    \r
254         .bp_power               = BP_UNKNOW_DATA,//RK2928_PIN3_PC2,     // 3g_power\r
255         .bp_en                  = BP_UNKNOW_DATA,       // 3g_en\r
256         .bp_reset                       = BP_UNKNOW_DATA,//RK2928_PIN1_PA3,\r
257         .ap_ready               = BP_UNKNOW_DATA,       //\r
258         .bp_ready               = BP_UNKNOW_DATA,\r
259         .ap_wakeup_bp           = BP_UNKNOW_DATA,//RK2928_PIN3_PC4,\r
260         .bp_wakeup_ap           = BP_UNKNOW_DATA,//RK2928_PIN3_PC3,     //\r
261         .bp_uart_en             = BP_UNKNOW_DATA,       //EINT9\r
262         .bp_usb_en              = BP_UNKNOW_DATA,       //W_disable\r
263         .trig                   = IRQF_TRIGGER_FALLING,\r
264 \r
265         .active                 = bp_active,\r
266         .init                   = bp_init,\r
267         .reset                  = bp_reset,\r
268         .ap_wake_bp             = ap_wake_bp,\r
269         .bp_wake_ap             = bp_wake_ap,\r
270         .shutdown               = bp_shutdown,\r
271         .read_status            = NULL,\r
272         .write_status           = NULL,\r
273         .suspend                = bp_suspend,\r
274         .resume                 = bp_resume,\r
275         .misc_name              = NULL,\r
276         .private_miscdev        = NULL,\r
277 #else\r
278         .name                   = "u5501",\r
279         .bp_id                  = BP_ID_U5501,\r
280         .bp_bus                 = BP_BUS_TYPE_USB_UART,         \r
281         .bp_pid                 = 0,    \r
282         .bp_vid                 = 0,    \r
283         .bp_power               = BP_UNKNOW_DATA,//RK2928_PIN3_PC2,     // 3g_power\r
284         .bp_en                  = BP_UNKNOW_DATA,       // 3g_en\r
285         .bp_reset                       = BP_UNKNOW_DATA,//RK2928_PIN1_PA3,\r
286         .ap_ready               = BP_UNKNOW_DATA,       //\r
287         .bp_ready               = BP_UNKNOW_DATA,\r
288         .ap_wakeup_bp           = BP_UNKNOW_DATA,//RK2928_PIN3_PC4,\r
289         .bp_wakeup_ap           = BP_UNKNOW_DATA,//RK2928_PIN3_PC3,     //\r
290         .bp_uart_en             = BP_UNKNOW_DATA,       //EINT9\r
291         .bp_usb_en              = BP_UNKNOW_DATA,       //W_disable\r
292         .trig                   = IRQF_TRIGGER_FALLING,\r
293 \r
294         .active                 = bp_active,\r
295         .init                   = bp_init,\r
296         .reset                  = bp_reset,\r
297         .ap_wake_bp             = ap_wake_bp,\r
298         .bp_wake_ap             = bp_wake_ap,\r
299         .shutdown               = bp_shutdown,\r
300         .read_status            = NULL,\r
301         .write_status           = NULL,\r
302         .suspend                = bp_suspend,\r
303         .resume                 = bp_resume,\r
304         .misc_name              = NULL,\r
305         .private_miscdev        = NULL,\r
306 #endif\r
307 };\r
308 \r
309 /****************operate according to bp chip:end************/\r
310 \r
311 //function name should not be changed\r
312 static struct bp_operate *bp_get_ops(void)\r
313 {\r
314         return &bp_u5501_ops;\r
315 }\r
316 \r
317 static int __init bp_u5501_init(void)\r
318 {\r
319         struct bp_operate *ops = bp_get_ops();\r
320         int result = 0;\r
321         result = bp_register_slave(NULL, NULL, bp_get_ops);\r
322         if(result)\r
323         {       \r
324                 return result;\r
325         }\r
326         \r
327         if(ops->private_miscdev)\r
328         {\r
329                 result = misc_register(ops->private_miscdev);\r
330                 if (result < 0) {\r
331                         printk("%s:misc_register err\n",__func__);\r
332                         return result;\r
333                 }\r
334         }\r
335         \r
336         DBG("%s\n",__func__);\r
337         return result;\r
338 }\r
339 \r
340 static void __exit bp_u5501_exit(void)\r
341 {\r
342         //struct bp_operate *ops = bp_get_ops();\r
343         bp_unregister_slave(NULL, NULL, bp_get_ops);\r
344 }\r
345 \r
346 \r
347 subsys_initcall(bp_u5501_init);\r
348 module_exit(bp_u5501_exit);\r
349 \r