import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / kr076 / ssw / sim_switch.c
1
2 #include <ssw.h>
3
4 /*--------------Feature option---------------*/
5 #define __ENABLE_SSW_SYSFS 1
6
7
8 /*--------------SIM mode list----------------*/
9 #define SINGLE_TALK_MDSYS (0x1)
10 #define SINGLE_TALK_MDSYS_LITE (0x2)
11 #define DUAL_TALK (0x3)
12 #define DUAL_TALK_SWAP (0x4)
13
14 /*----------------Error Code-----------------*/
15 #define SSW_SUCCESS (0)
16 #define SSW_INVALID_PARA (-1)
17
18
19 /*--------------Global varible---------------*/
20 unsigned int sim_mode_curr = SINGLE_TALK_MDSYS;
21
22 unsigned int get_sim_switch_type(void)
23 {
24 printk("[ccci/ssw]SSW_GENERIC\n");
25 return SSW_INTERN;
26 }
27 EXPORT_SYMBOL(get_sim_switch_type);
28
29 struct mutex sim_switch_mutex;
30
31
32 static inline void sim_switch_writel(void *addr, unsigned offset, u32 data)
33 {
34 *((volatile unsigned int*)(addr + offset)) = data;
35 }
36
37 static inline u32 sim_switch_readl(const void *addr, unsigned offset)
38 {
39
40 u32 rc = 0;
41 rc = *((volatile unsigned int*)(addr + offset));
42 return rc;
43 }
44
45 static int set_sim_gpio(unsigned int mode);
46 static int get_current_ssw_mode(void);
47
48 /*---------------------------------------------------------------------------*/
49 /*define sysfs entry for configuring debug level and sysrq*/
50 ssize_t ssw_attr_show(struct kobject *kobj, struct attribute *attr, char *buffer);
51 ssize_t ssw_attr_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size);
52 ssize_t ssw_mode_show(struct kobject *kobj, char *page);
53 ssize_t ssw_mode_store(struct kobject *kobj, const char *page, size_t size);
54
55 struct sysfs_ops ssw_sysfs_ops = {
56 .show = ssw_attr_show,
57 .store = ssw_attr_store,
58 };
59
60 struct ssw_sys_entry {
61 struct attribute attr;
62 ssize_t (*show)(struct kobject *kobj, char *page);
63 ssize_t (*store)(struct kobject *kobj, const char *page, size_t size);
64 };
65
66 static struct ssw_sys_entry mode_entry = {
67 { .name = "mode", .mode = S_IRUGO | S_IWUSR }, // remove .owner = NULL,
68 ssw_mode_show,
69 ssw_mode_store,
70 };
71
72 struct attribute *ssw_attributes[] = {
73 &mode_entry.attr,
74 NULL,
75 };
76
77 struct kobj_type ssw_ktype = {
78 .sysfs_ops = &ssw_sysfs_ops,
79 .default_attrs = ssw_attributes,
80 };
81
82 static struct ssw_sysobj_t {
83 struct kobject kobj;
84 } ssw_sysobj;
85
86
87 int ssw_sysfs_init(void)
88 {
89 struct ssw_sysobj_t *obj = &ssw_sysobj;
90
91 memset(&obj->kobj, 0x00, sizeof(obj->kobj));
92
93 obj->kobj.parent = kernel_kobj;
94 if (kobject_init_and_add(&obj->kobj, &ssw_ktype, NULL, "mtk_ssw")) {
95 kobject_put(&obj->kobj);
96 return -ENOMEM;
97 }
98 kobject_uevent(&obj->kobj, KOBJ_ADD);
99
100 return 0;
101 }
102
103 ssize_t ssw_attr_show(struct kobject *kobj, struct attribute *attr, char *buffer)
104 {
105 struct ssw_sys_entry *entry = container_of(attr, struct ssw_sys_entry, attr);
106 return entry->show(kobj, buffer);
107 }
108
109 ssize_t ssw_attr_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size)
110 {
111 struct ssw_sys_entry *entry = container_of(attr, struct ssw_sys_entry, attr);
112 return entry->store(kobj, buffer, size);
113 }
114
115 ssize_t ssw_mode_show(struct kobject *kobj, char *buffer)
116 {
117 int remain = PAGE_SIZE;
118 int len;
119 char *ptr = buffer;
120
121 len = scnprintf(ptr, remain, "0x%x\n", get_current_ssw_mode());
122 ptr += len;
123 remain -= len;
124 SSW_DBG("ssw_mode_show\n");
125
126 return (PAGE_SIZE-remain);
127 }
128
129 ssize_t ssw_mode_store(struct kobject *kobj, const char *buffer, size_t size)
130 {
131 int mode;
132 int res = sscanf(buffer, "%x", &mode);
133
134 if (res != 1)
135 {
136 printk("%s: expect 1 numbers\n", __FUNCTION__);
137 }
138 else
139 {
140 SSW_DBG("ssw_mode_store %d\n", mode);
141 //Switch sim mode
142 if ((sim_mode_curr != mode) && (SSW_SUCCESS == set_sim_gpio(mode)))
143 {
144 sim_mode_curr = mode;
145 }
146 }
147 return size;
148 }
149 /*---------------------------------------------------------------------------*/
150
151
152
153 int get_current_ssw_mode(void)
154 {
155 return sim_mode_curr;
156 }
157
158
159 static int set_sim_gpio(unsigned int mode)
160 {
161 SSW_DBG("set_sim_gpio %d\n", mode);
162
163 switch(mode)
164 {
165 case SINGLE_TALK_MDSYS:
166 #if defined(GPIO_SIM1_SCLK) && defined(GPIO_SIM1_SIO) && defined(GPIO_SIM2_SCLK) && defined(GPIO_SIM2_SIO)
167 mt_set_gpio_mode(GPIO_SIM1_SCLK, 1); //SIM1_SCLK
168 mt_set_gpio_mode(GPIO_SIM1_SIO, 1); //SIM1_SIO
169 mt_set_gpio_mode(GPIO_SIM2_SCLK, 1); //SIM2_SCLK
170 mt_set_gpio_mode(GPIO_SIM2_SIO, 1); //SIM2_SIO
171 //mt_set_gpio_mode(GPIO_SIM1_SRST, 4); //SIM1_SRST, 6582 not use reset pin
172 //mt_set_gpio_mode(GPIO_SIM2_SRST, 4); //SIM2_SRST, 6582 not use reset pin
173 #endif
174 break;
175
176 default:
177 SSW_DBG("Mode(%d) not supported!!!", mode);
178 return SSW_INVALID_PARA;
179 }
180
181 #if 0
182 SSW_DBG("Current sim mode(%d), GPIO0_MODE(%d, %d), GPIO1_MODE(%d, %d), GPIO2_MODE(%d, %d), GPIO3_MODE(%d, %d), GPIO89_MODE(%d, %d), GPIO90_MODE(%d, %d)\n", \
183 mode, mt_get_gpio_mode(GPIO0), mt_get_gpio_dir(GPIO0), mt_get_gpio_mode(GPIO1), mt_get_gpio_dir(GPIO1), \
184 mt_get_gpio_mode(GPIO2), mt_get_gpio_dir(GPIO2), mt_get_gpio_mode(GPIO3), mt_get_gpio_dir(GPIO3), \
185 mt_get_gpio_mode(GPIO89), mt_get_gpio_dir(GPIO89), mt_get_gpio_mode(GPIO90), mt_get_gpio_dir(GPIO90));
186 #else
187 #if defined(GPIO_SIM1_SCLK) && defined(GPIO_SIM1_SIO) && defined(GPIO_SIM2_SCLK) && defined(GPIO_SIM2_SIO)
188 SSW_DBG("Current sim mode(%d), GPIO_SIM1_SCLK_MODE(%d, %d), GPIO_SIM1_SIO_MODE(%d, %d), GPIO_SIM2_SCLK_MODE(%d, %d), GPIO_SIM2_SIO_MODE(%d, %d)\n", \
189 mode, mt_get_gpio_mode(GPIO_SIM1_SCLK), mt_get_gpio_dir(GPIO_SIM1_SCLK), mt_get_gpio_mode(GPIO_SIM1_SIO), mt_get_gpio_dir(GPIO_SIM1_SIO), \
190 mt_get_gpio_mode(GPIO_SIM2_SCLK), mt_get_gpio_dir(GPIO_SIM2_SCLK), mt_get_gpio_mode(GPIO_SIM2_SIO), mt_get_gpio_dir(GPIO_SIM2_SIO));
191 #endif
192 #endif
193
194 return SSW_SUCCESS;
195 }
196
197
198 int switch_sim_mode(int id, char *buf, unsigned int len)
199 {
200 unsigned int mode = *((unsigned int *)buf);
201
202 SSW_DBG("sim switch: %d(%d)\n", mode, sim_mode_curr);
203
204 mutex_lock(&sim_switch_mutex);
205
206 if ((sim_mode_curr != mode) && (SSW_SUCCESS == set_sim_gpio(mode)))
207 {
208 sim_mode_curr = mode;
209 }
210
211 mutex_unlock(&sim_switch_mutex);
212
213 SSW_DBG("sim switch(%d) OK\n", sim_mode_curr);
214
215 return 0;
216
217 }
218 EXPORT_SYMBOL(switch_sim_mode);
219
220 //To decide sim mode according to compile option
221 static int get_sim_mode_init(void)
222 {
223 unsigned int sim_mode = 0;
224 unsigned int md1_enable, md2_enable = 0;
225
226 md1_enable = get_modem_is_enabled(MD_SYS1);
227 md2_enable = get_modem_is_enabled(MD_SYS2);
228
229 if (md1_enable){
230 sim_mode = SINGLE_TALK_MDSYS;
231 if (md2_enable)
232 sim_mode = DUAL_TALK;
233 }
234 else if (md2_enable)
235 sim_mode = SINGLE_TALK_MDSYS_LITE;
236
237 return sim_mode;
238 }
239
240 //sim switch hardware initial
241 static int sim_switch_init(void)
242 {
243 SSW_DBG("sim_switch_init\n");
244
245 //better to set pull_en and pull_sel first, then mode
246 //if GPIO in sim mode, no need to set direction, because hw has done this when setting mode
247 /*
248 mt_set_gpio_dir(GPIO_SIM1_SCLK, GPIO_DIR_OUT); //GPIO0->SIM2_CLK, out
249 mt_set_gpio_dir(GPIO_SIM1_SIO, GPIO_DIR_IN); //GPIO1->SIM2_SIO, in
250 mt_set_gpio_dir(GPIO_SIM2_SCLK, GPIO_DIR_OUT); //GPIO2->SIM1_CLK, out
251 mt_set_gpio_dir(GPIO_SIM2_SIO, GPIO_DIR_IN); //GPIO3->SIM1_SIO, in
252 */
253 //mt_set_gpio_dir(GPIO89, GPIO_DIR_OUT); //GPIO89->SIM1_SRST, out, 6572 not use reset pin
254 //mt_set_gpio_dir(GPIO90, GPIO_DIR_OUT); //GPIO90->SIM2_SRST, out, 6572 not use reset pin
255
256 sim_mode_curr = get_sim_mode_init();
257 if (SSW_SUCCESS != set_sim_gpio(sim_mode_curr))
258 {
259 SSW_DBG("sim_switch_init fail \n");
260 return SSW_INVALID_PARA;
261 }
262
263 return 0;
264 }
265
266
267 static int sim_switch_probe(struct platform_device *dev)
268 {
269 SSW_DBG("Enter sim_switch_probe\n");
270
271 //sim_switch_init();
272
273 mutex_init(&sim_switch_mutex);
274
275 //register_ccci_kern_func(ID_SSW_SWITCH_MODE, switch_sim_mode);
276
277 return 0;
278 }
279
280 static int sim_switch_remove(struct platform_device *dev)
281 {
282 //SSW_DBG("sim_switch_remove \n");
283 return 0;
284 }
285
286 static void sim_switch_shutdown(struct platform_device *dev)
287 {
288 //SSW_DBG("sim_switch_shutdown \n");
289 }
290
291 static int sim_switch_suspend(struct platform_device *dev, pm_message_t state)
292 {
293 //SSW_DBG("sim_switch_suspend \n");
294 return 0;
295 }
296
297 static int sim_switch_resume(struct platform_device *dev)
298 {
299 //SSW_DBG("sim_switch_resume \n");
300 return 0;
301 }
302
303
304 static struct platform_driver sim_switch_driver =
305 {
306 .driver = {
307 .name = "sim-switch",
308 },
309 .probe = sim_switch_probe,
310 .remove = sim_switch_remove,
311 .shutdown = sim_switch_shutdown,
312 .suspend = sim_switch_suspend,
313 .resume = sim_switch_resume,
314 };
315
316
317 static int __init sim_switch_driver_init(void)
318 {
319 int ret = 0;
320
321 SSW_DBG("sim_switch_driver_init\n");
322 ret = platform_driver_register(&sim_switch_driver);
323 if (ret) {
324 SSW_DBG("ssw_driver register fail(%d)\n", ret);
325 return ret;
326 }
327 #if __ENABLE_SSW_SYSFS
328 ssw_sysfs_init();
329 #endif
330
331 sim_switch_init();
332
333 return ret;
334 }
335
336
337 static void __exit sim_switch_driver_exit(void)
338 {
339 return;
340 }
341
342
343 module_init(sim_switch_driver_init);
344 module_exit(sim_switch_driver_exit);
345
346
347 MODULE_DESCRIPTION("MTK SIM Switch Driver");
348 MODULE_AUTHOR("Anny <Anny.Hu@mediatek.com>");
349 MODULE_LICENSE("GPL");