rk3066 add phone pad modem support
[firefly-linux-kernel-4.4.55.git] / drivers / misc / bp / chips / c66a.c
1 /* drivers/misc/bp/chips/c66a.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("<-----c66a power on-------->\n");\r
57                 gpio_set_value(bp->ops->bp_power, GPIO_HIGH);\r
58         }\r
59         else\r
60         {\r
61                 printk("<-----c66a power on-------->\n");\r
62                 gpio_set_value(bp->ops->bp_power, GPIO_LOW);\r
63                 msleep(500);\r
64         }\r
65         \r
66         return result;\r
67 }\r
68 \r
69 static void  ap_wake_bp_work(struct work_struct *work)\r
70 {\r
71         return;\r
72 }\r
73 static int bp_wake_ap(struct bp_private_data *bp)\r
74 {\r
75         int result = 0;\r
76         \r
77         if(bp->suspend_status)\r
78         {\r
79                 printk("<-----c66a bp_wake_ap-------->\n");\r
80                 bp->suspend_status = 0;         \r
81                 wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);\r
82         }\r
83         \r
84         return result;\r
85 }\r
86 static int bp_init(struct bp_private_data *bp)\r
87 {\r
88         int result = 0; \r
89         gpio_direction_input(bp->ops->bp_wakeup_ap);\r
90         gpio_direction_output(bp->ops->bp_power,GPIO_LOW);\r
91         gpio_direction_output(bp->ops->ap_wakeup_bp,GPIO_HIGH);\r
92         INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);\r
93         return result;\r
94 }\r
95 \r
96 static int bp_reset(struct bp_private_data *bp)\r
97 {\r
98         printk("ioctrl c66a reset !!! \n");\r
99         gpio_set_value(bp->ops->bp_power, GPIO_LOW);\r
100         msleep(2000);\r
101         gpio_set_value(bp->ops->bp_power, GPIO_HIGH);   \r
102         return 0;\r
103 }\r
104 static int bp_shutdown(struct bp_private_data *bp)\r
105 {\r
106         int result = 0;\r
107         \r
108         if(bp->ops->active)\r
109                 bp->ops->active(bp, 0);\r
110         \r
111         cancel_delayed_work_sync(&bp->wakeup_work);     \r
112                 \r
113         return result;\r
114 }\r
115 static int bp_suspend(struct bp_private_data *bp)\r
116 {       \r
117         int result = 0;\r
118         bp->suspend_status = 1;\r
119         gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);                \r
120         \r
121         return result;\r
122 }\r
123 static int bp_resume(struct bp_private_data *bp)\r
124 {\r
125         \r
126         printk("<-----c66a bp_resume-------->\n");\r
127         bp->suspend_status = 0; \r
128         gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);       \r
129         \r
130         \r
131         return 0;\r
132 }\r
133 \r
134 \r
135 struct bp_operate bp_c66a_ops = {\r
136         .name                   = "c66a",\r
137         .bp_id                  = BP_ID_C66A,\r
138         .bp_bus                 = BP_BUS_TYPE_UART,             \r
139         .bp_pid                 = 0,    \r
140         .bp_vid                 = 0,    \r
141         .bp_power               = BP_UNKNOW_DATA,//RK2928_PIN3_PC2,     // 3g_power\r
142         .bp_en                  = BP_UNKNOW_DATA,       // 3g_en\r
143         .bp_reset                       = BP_UNKNOW_DATA,\r
144         .ap_ready               = BP_UNKNOW_DATA,       //\r
145         .bp_ready               = BP_UNKNOW_DATA,\r
146         .ap_wakeup_bp           = BP_UNKNOW_DATA,//RK2928_PIN3_PC4,\r
147         .bp_wakeup_ap           = BP_UNKNOW_DATA,//RK2928_PIN3_PC3,     //\r
148         .bp_uart_en             = BP_UNKNOW_DATA,       //EINT9\r
149         .bp_usb_en              = BP_UNKNOW_DATA,       //W_disable\r
150         .bp_assert              = BP_UNKNOW_DATA,//RK2928_PIN3_PC5,\r
151         .trig                           = IRQF_TRIGGER_RISING,\r
152 \r
153         .active                 = bp_active,\r
154         .init                           = bp_init,\r
155         .reset                  = bp_reset,\r
156         .ap_wake_bp             = NULL,\r
157         .bp_wake_ap             = bp_wake_ap,\r
158         .shutdown               = bp_shutdown,\r
159         .read_status            = NULL,\r
160         .write_status           = NULL,\r
161         .suspend                = bp_suspend,\r
162         .resume                 = bp_resume,\r
163         .misc_name              = NULL,\r
164         .private_miscdev        = NULL,\r
165 };\r
166 \r
167 /****************operate according to bp chip:end************/\r
168 \r
169 //function name should not be changed\r
170 static struct bp_operate *bp_get_ops(void)\r
171 {\r
172         return &bp_c66a_ops;\r
173 }\r
174 \r
175 static int __init bp_c66a_init(void)\r
176 {\r
177         struct bp_operate *ops = bp_get_ops();\r
178         int result = 0;\r
179         result = bp_register_slave(NULL, NULL, bp_get_ops);\r
180         if(result)\r
181         {       \r
182                 return result;\r
183         }\r
184         \r
185         if(ops->private_miscdev)\r
186         {\r
187                 result = misc_register(ops->private_miscdev);\r
188                 if (result < 0) {\r
189                         printk("%s:misc_register err\n",__func__);\r
190                         return result;\r
191                 }\r
192         }\r
193         \r
194         DBG("%s\n",__func__);\r
195         return result;\r
196 }\r
197 \r
198 static void __exit bp_c66a_exit(void)\r
199 {\r
200         //struct bp_operate *ops = bp_get_ops();\r
201         bp_unregister_slave(NULL, NULL, bp_get_ops);\r
202 }\r
203 \r
204 \r
205 subsys_initcall(bp_c66a_init);\r
206 module_exit(bp_c66a_exit);\r
207 \r