6e32ce0c5d065c727d57a0894650428ebf22ac99
[kernel/linux-2.6.36.git] / drivers / misc / modem / xmm6260.c
1 /*
2  * XMM6260 control driver
3  *
4  * Copyright (C) 2010 Samsung Electronics Co.Ltd
5  * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6  *
7  * This program is free software; you can redistribute  it and/or modify it
8  * under  the terms of  the GNU General  Public License as published by the
9  * Free Software Foundation;  either version 2 of the  License, or (at your
10  * option) any later version.
11  */
12
13 #define DEBUG
14
15 #define MODEM_PARTITION         "/dev/mmcblk0p2"
16 #define MODEM_MOUNT_PATH        "/boot"
17 #define MODEM_FS_TYPE           "ext4"
18 #define MODEM_FS_TYPE_TMP       "vfat"
19 #define CSA_PARTITION           "/dev/mmcblk0p1"
20 #define CSA_MOUNT_PATH          "/csa"
21 #define CSA_FS_TYPE             "ext4"
22
23 #define MODEM_BIN_PATH  "/boot/modem.bin"
24 #define MODEM_FLM_EXE_PATH  "/usr/bin/xmm6260-boot"
25 #define CP_DUMP_EXE_PATH        "/usr/bin/xmm6260-dump"
26
27 #include <linux/syscalls.h>
28 #include <asm/uaccess.h>
29 #include <linux/file.h>
30 #include <linux/init.h>
31 #include <linux/module.h>
32 #include <linux/platform_device.h>
33 #include <linux/delay.h>
34 #include <linux/err.h>
35 #include <linux/gpio.h>
36 #include <linux/interrupt.h>
37 #include <linux/regulator/consumer.h>
38 #include <linux/slab.h>
39 #include <linux/modem/xmm6260.h>
40
41 int (*req_xmm6260_bus_suspend)(void);
42 EXPORT_SYMBOL_GPL(req_xmm6260_bus_suspend);
43
44 int (*req_xmm6260_bus_resume)(void);
45 EXPORT_SYMBOL_GPL(req_xmm6260_bus_resume);
46
47 extern void xmm_set_boot_flag(int val);
48 extern int xmm_get_boot_flag(void);
49
50 static const char *xmm_state_str[] = {
51         "L0 Active",
52         "L2 Resuming",
53         "L2 Suspending",
54         "L3 Suspending",
55 };
56
57 enum xmm_gpio_irq_type {
58         XMM_GPIO_PHONE_ACTIVE,
59         XMM_GPIO_HOST_WAKEUP,
60         XMM_GPIO_SUSPEND_REQUEST_HSIC,
61         XMM_GPIO_DUMP_INT,
62         XMM_GPIO_MAX,
63 };
64
65 struct xmm6260_data {
66         struct device           *dev;
67         struct xmm6260_gpios    *gpios;
68         struct regulator        *vhsic;
69         struct workqueue_struct *boot_wq;
70         struct delayed_work     status_dwork;
71         struct delayed_work boot_dwork;
72         enum xmm6260_state      state;
73
74         bool            vhsic_enabled;
75         int                     crash_flag;
76         int                     boot_done;
77         int                     irq[XMM_GPIO_MAX];
78 };
79
80 static struct xmm6260_data *xmm6260_data = NULL;
81
82 static void xmm6260_set_state(enum xmm6260_state state)
83 {
84         struct xmm6260_data *data = xmm6260_data;
85         if (data->state == state)
86                 return;
87
88         data->state = state;
89         dev_dbg(data->dev, "state: %s\n", xmm_state_str[state]);
90 }
91
92 enum xmm6260_state xmm6260_get_state(void)
93 {
94         struct xmm6260_data *data = xmm6260_data;
95         return data->state;
96 }
97 EXPORT_SYMBOL(xmm6260_get_state);
98
99 void xmm6260_vhsic_on(void)
100 {
101         struct xmm6260_data *data = xmm6260_data;
102         struct device *dev = data->dev;
103         int err;
104
105         dev_dbg(data->dev, "vhsic on\n");
106
107         if (!data->vhsic) {
108                 data->vhsic = regulator_get(NULL, "vhsic");
109                 if (IS_ERR(data->vhsic)) {
110                         err = PTR_ERR(data->vhsic);
111                         dev_err(dev, "No VHSIC_1.2V regualtor: %d\n", err);
112                         data->vhsic = NULL;
113                 }
114         }
115
116         if (data->vhsic && !data->vhsic_enabled) {
117                 regulator_enable(data->vhsic);
118                 data->vhsic_enabled = true;
119         }
120 }
121 EXPORT_SYMBOL(xmm6260_vhsic_on);
122
123 void xmm6260_vhsic_off(void)
124 {
125         struct xmm6260_data *data = xmm6260_data;
126         dev_dbg(data->dev, "vhsic off\n");
127
128         if (data->vhsic && data->vhsic_enabled) {
129                 regulator_disable(data->vhsic);
130                 data->vhsic_enabled = false;
131         }
132 }
133 EXPORT_SYMBOL(xmm6260_vhsic_off);
134
135 void xmm6260_set_pda_active(int val)
136 {
137         struct xmm6260_data *data = xmm6260_data;
138
139         gpio_set_value(data->gpios->pda_active, val ? 1 : 0);
140         dev_info(data->dev, "PDA_ACTIVE: %s\n", val ? "raised" : "dropped");
141 }
142 EXPORT_SYMBOL(xmm6260_set_pda_active);
143
144 int xmm6260_get_host_wakeup(void)
145 {
146         struct xmm6260_data *data = xmm6260_data;
147         if(!data)
148                 return -EFAULT;
149         return gpio_get_value(data->gpios->ipc_host_wakeup);
150 }
151 EXPORT_SYMBOL(xmm6260_get_host_wakeup);
152
153 int xmm6260_get_slave_wakeup(void)
154 {
155         struct xmm6260_data *data = xmm6260_data;
156         if(!data)
157                 return -EFAULT;
158         return gpio_get_value(data->gpios->ipc_slave_wakeup);
159 }
160 EXPORT_SYMBOL(xmm6260_get_slave_wakeup);
161
162 static void xmm6260_on(struct xmm6260_data *data)
163 {
164         struct device *dev = data->dev;
165         struct xmm6260_gpios *gpios = data->gpios;
166
167         dev_dbg(dev, "%s [%s]\n", __func__, current->comm);
168
169         xmm6260_vhsic_on();
170
171         xmm6260_set_pda_active(0);
172         msleep(100);
173
174         gpio_set_value(gpios->cp_pmu_rst, 1);
175         udelay(160);
176         gpio_set_value(gpios->reset_req_n, 1);
177         msleep(100);
178
179         gpio_set_value(gpios->cp_on, 1);
180         xmm6260_set_pda_active(1);
181 }
182
183 static void xmm6260_off(struct xmm6260_data *data)
184 {
185         struct device *dev = data->dev;
186         struct xmm6260_gpios *gpios = data->gpios;
187
188         dev_dbg(dev, "%s [%s]\n", __func__, current->comm);
189
190         data->boot_done = 0;
191         gpio_set_value(gpios->cp_on, 0);
192         gpio_set_value(gpios->cp_pmu_rst, 0);
193
194         xmm6260_vhsic_off();
195 }
196
197 static void xmm6260_reset(struct xmm6260_data *data)
198 {
199         struct device *dev = data->dev;
200         struct xmm6260_gpios *gpios = data->gpios;
201
202         dev_dbg(dev, "%s [%s]\n", __func__, current->comm);
203
204         gpio_set_value(gpios->cp_pmu_rst, 0);
205         gpio_set_value(gpios->reset_req_n, 0);
206
207         msleep(100);
208
209         gpio_set_value(gpios->cp_pmu_rst, 1);
210         udelay(160);
211         gpio_set_value(gpios->reset_req_n, 1);
212 }
213
214 static void xmm6260_upload(struct xmm6260_data *data)
215 {
216         struct device *dev = data->dev;
217
218         dev_err(dev, "%s [%s]\n", __func__, current->comm);
219
220         /* TODO: need to upload method */
221 }
222
223 static ssize_t show_control(struct device *dev,
224                 struct device_attribute *attr, char *buf)
225 {
226         int count = 0;
227
228         count += sprintf(buf + count, "on off reset\n");
229
230         return count;
231 }
232
233 static ssize_t store_control(struct device *dev,
234                 struct device_attribute *attr, const char *buf, size_t count)
235 {
236         struct xmm6260_data *data = dev_get_drvdata(dev);
237
238         if (!strncmp(buf, "on", 2)) {
239                 xmm6260_on(data);
240                 return count;
241         }
242
243         if (!strncmp(buf, "off", 3)) {
244                 xmm6260_off(data);
245                 return count;
246         }
247
248         if (!strncmp(buf, "reset", 5)) {
249                 xmm6260_reset(data);
250                 return count;
251         }
252
253         if (!strncmp(buf, "upload", 6)) {
254                 xmm6260_upload(data);
255                 return count;
256         }
257
258         return count;
259 }
260
261 static ssize_t show_wakeup(struct device *dev,
262                 struct device_attribute *attr, char *buf)
263 {
264         struct xmm6260_data *data = dev_get_drvdata(dev);
265         struct xmm6260_gpios *gpios = data->gpios;
266         int count = 0;
267
268         count += sprintf(buf + count, "%d\n",
269                         gpio_get_value(gpios->ipc_host_wakeup));
270
271         return count;
272 }
273
274 static ssize_t show_status(struct device *dev,
275                 struct device_attribute *attr, char *buf)
276 {
277         struct xmm6260_data *data = dev_get_drvdata(dev);
278         struct xmm6260_gpios *gpios = data->gpios;
279         int count = 0;
280
281         count = sprintf(buf, "%d\n",
282                         gpio_get_value(gpios->phone_active));
283                         
284         return count;
285 }
286
287 static DEVICE_ATTR(control, S_IRUGO | S_IWUGO, show_control, store_control);
288 static DEVICE_ATTR(wakeup, S_IRUGO, show_wakeup, NULL);
289 static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
290
291 static struct attribute *xmm6260_attrs[] = {
292         &dev_attr_control.attr,
293         &dev_attr_wakeup.attr,
294         &dev_attr_status.attr,
295         NULL
296 };
297
298 static const struct attribute_group xmm6260_attr_group = {
299         .attrs = xmm6260_attrs,
300 };
301
302 int xmm6260_get_cp_on(void)
303 {
304         struct xmm6260_data *data = xmm6260_data;
305         if(!data)
306                 return -EFAULT;
307         return gpio_get_value(data->gpios->cp_on);
308 }
309 EXPORT_SYMBOL(xmm6260_get_cp_on);
310
311 int xmm6260_get_phone_active(void)
312 {
313         struct xmm6260_data *data = xmm6260_data;
314         if(!data)
315                 return -EFAULT;
316         return gpio_get_value(data->gpios->phone_active);
317 }
318 EXPORT_SYMBOL(xmm6260_get_phone_active);
319
320 static irqreturn_t phone_active_handler(int irq, void *dev_id)
321 {
322         struct xmm6260_data *data = dev_id;
323
324         if (!work_pending(&data->status_dwork.work))
325                 schedule_delayed_work(&data->status_dwork, msecs_to_jiffies(100));
326
327         return IRQ_HANDLED;
328 }
329
330 static irqreturn_t ipc_host_wakeup_handler(int irq, void *dev_id)
331 {
332         struct xmm6260_data *data = dev_id;
333         struct xmm6260_gpios *gpios = data->gpios;
334         struct device *dev = data->dev;
335         int host_wakeup;
336         int active_state_hsic;
337         int ret;
338
339         pm_wakeup_event(NULL, 0);
340
341         host_wakeup = gpio_get_value(gpios->ipc_host_wakeup);
342         dev_dbg(dev, "\tCP %s HOST_WAKEUP\n", 
343                         host_wakeup ? "raised" : "dropped");
344
345         ret = xmm6260_get_phone_active();
346         if (!ret) {
347                 dev_err(dev, "\tCP is not active\n");
348                 goto exit;
349         }
350
351         active_state_hsic = gpio_get_value(gpios->active_state_hsic);
352         if (!active_state_hsic) {
353                 dev_dbg(dev, "\tACTIVE_STATE_HSIC is low, wakeup from L3\n");
354                 xmm6260_set_state(STATE_L2_RESUME);
355                 goto exit;
356         }
357
358         if (data->state == STATE_L3_SUSPEND) {
359                 dev_dbg(dev, "\tIgnore HOST_WAKEUP while go to L3\n");
360                 goto exit;
361         }
362
363 #ifdef USE_CP_INITIATED_L0_L2
364         int counter = 0;
365
366         /* Wait for a suspend request/done routine. */
367         while (counter < 100 && data->state == STATE_L2_SUSPEND) {
368                 /* Wait for suspend request to be done */
369                 counter++;
370                 msleep(1);
371         }
372
373         if (data->state == STATE_L2_SUSPEND) {
374                 dev_err(dev, "\tResume Request: Timeout waiting suspend "
375                              "request to be done. (100ms)\n");
376                 goto exit;
377         }
378 #endif
379
380         if (!host_wakeup) {
381                 /* system is not in L3 so we can proceed waking work */
382                 xmm6260_set_state(STATE_L2_RESUME);
383
384                 if (!req_xmm6260_bus_resume)
385                         goto exit;
386
387                 ret = req_xmm6260_bus_resume();
388                 if (ret < 0)
389                         dev_err(dev, "\tFATAL : req bus resume failed: %d\n",
390                                         ret);
391         } else {
392                 xmm6260_set_state(STATE_L0_ACTIVE);
393                 gpio_set_value(gpios->ipc_slave_wakeup, 0);
394                 dev_dbg(dev, "\tAP dropped SLAVE_WAKEUP\n");
395         }
396
397 exit:
398         dev_dbg(dev, "\tCP %s HOST_WAKEUP handled\n", 
399                         host_wakeup ? "raised" : "dropped");
400
401         return IRQ_HANDLED;
402 }
403
404 static irqreturn_t suspend_request_hsic_handler(int irq, void *dev_id)
405 {
406         struct xmm6260_data *data = dev_id;
407         struct xmm6260_gpios *gpios = data->gpios;
408         struct device *dev = data->dev;
409         int suspend_request;
410         int err;
411
412
413         suspend_request = gpio_get_value(gpios->suspend_request_hsic);
414         dev_dbg(dev, "\tCP %s SUSPEND_REQUEST_HSIC\n", 
415                         suspend_request ? "raised" : "dropped");
416
417         err = xmm6260_get_phone_active();
418         if (!err) {
419                 dev_err(dev, "\tCP is not active\n");
420                 goto exit;
421         }
422
423 #ifdef USE_CP_INITIATED_L0_L2
424         if (data->state == STATE_L3_SUSPEND) {
425                 dev_err(dev, "\tSuspend request when the device is in L3\n");
426                 xmm6260_set_state(STATE_L0_ACTIVE);
427                 goto exit;
428         }
429
430         /* Completed suspending or Canceled a suspend request */
431         if (suspend_request == 0) {
432                 if (data->state == STATE_L2_SUSPEND) {
433                         /* Completed request */
434                         xmm6260_set_state(STATE_L0_ACTIVE);
435                         dev_dbg(dev, "\tSuspend Request: Done\n");
436                 } else
437                         /* Canceled request */
438                         dev_dbg(dev, "\tSuspend Request: Canceled\n");
439                 goto exit;
440         }
441
442         /*
443          * Do not check this before suspend_request. It may cancel suspend
444          * request and start resuming.
445          */
446         if (data->state == STATE_L2_RESUME) {
447                 dev_err(dev, "\tAbnormal suspend request (%s:%d). "
448                              "Called suspend during resume.\n",
449                              __func__, __LINE__);
450                 goto exit;
451         }
452
453         if (data->state == STATE_L2_SUSPEND)
454                 dev_err(dev, "\tduplicated suspend request\n");
455
456         xmm6260_set_state(STATE_L2_SUSPEND);
457
458         if (req_xmm6260_bus_suspend) {
459                 err = req_xmm6260_bus_suspend();
460                 if (err) {
461                         dev_err(dev, "\trequest suspend failed: %d\n",
462                                                 err);
463                 } else
464                         dev_dbg(dev, "\tSuspend Request: Submitted\n");
465         }
466 #else
467         dev_dbg(dev, "\tCP initiated L0->L2 is not supported\n");
468 #endif
469
470 exit:
471         dev_dbg(dev, "\tCP %s SUSPEND_REQUEST_HSIC handled\n", 
472                         suspend_request ? "raised" : "dropped");
473
474         return IRQ_HANDLED;
475 }
476
477 /*
478  * CP Crash: PHONE_ACTIVE(L) + CP_DUMP_INT(H) (0xC9)
479  * CP Reset: PHONE_ACTIVE(L) + CP_DUMP_INT(L) (0xC7)
480  */
481 void modem_status_dwork(struct work_struct *work)
482 {
483         struct xmm6260_data *data = container_of(work, struct xmm6260_data,
484                         status_dwork.work);
485         struct device *dev = data->dev;
486         struct xmm6260_gpios *gpios = data->gpios;
487
488         char * img_path = MODEM_BIN_PATH;
489         char * bin_path = CP_DUMP_EXE_PATH;
490         char *argv[] = { bin_path, img_path, NULL };
491         static char *envp[] = { "HOME=/usr/home/root",
492                                 "TERM=linux",
493                                 "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
494                                 NULL };
495         char *envs[2] = { NULL, NULL };
496         int ret;
497         int cp_dump_int = gpio_get_value(gpios->cp_dump_int);
498         int val = xmm6260_get_phone_active();
499
500         envs[0] = cp_dump_int ? "MAILBOX=cp_exit" : "MAILBOX=cp_reset";
501
502         if (val && gpio_get_value(gpios->cp_on)) {
503                 dev_dbg(dev, "\tPHONE_ACTIVE: %d CP_DUMP_INT: %d\n",
504                         val, cp_dump_int);
505                 data->crash_flag = 0;
506                 data->boot_done = 1;
507
508                 if (xmm_get_boot_flag() == 1) {
509                         kobject_uevent(&dev->kobj, KOBJ_ONLINE);
510                         dev_err(dev, "\tPHONE_ACTIVE: %d CP_DUMP_INT: %d and send uevent\n",
511                                 val, cp_dump_int);
512                 }
513         } else if (data->boot_done) {
514                 dev_dbg(dev, "\tPHONE_ACTIVE: %d CP_DUMP_INT: %d after boot_done\n",
515                         val, cp_dump_int);
516                 if (xmm6260_get_phone_active())
517                         return;
518                 if (data->crash_flag > 3) {
519                         data->boot_done = 0;
520
521                         if ((cp_dump_int == 1) && (xmm_get_boot_flag() == 1)) {
522                                 kobject_uevent_env(&dev->kobj, KOBJ_OFFLINE, envs);
523                                 dev_err(dev, "\tPHONE_ACTIVE: %d CP_DUMP_INT: %d and send uevent\n",
524                                         val, cp_dump_int);
525
526                                 ret = call_usermodehelper(bin_path, argv, envp,
527                                                 UMH_WAIT_EXEC);
528                                 if (ret < 0) {
529                                         dev_err(dev, "executing %s failed (%d)\n", 
530                                                         bin_path, ret);
531                                 }
532                         }
533                 }
534                 else {
535                         data->crash_flag++;
536                         schedule_delayed_work(&data->status_dwork,
537                                         msecs_to_jiffies(50));
538                 }
539         }
540 }
541
542 static irqreturn_t cp_dump_handler(int irq, void *dev_id)
543 {
544         struct xmm6260_data *data = dev_id;
545         struct xmm6260_gpios *gpios = data->gpios;
546         struct device *dev = data->dev;
547
548         int val = gpio_get_value(gpios->cp_dump_int);
549
550         dev_err(dev, "\tCP_DUMP_INT: %d\n", val);
551
552         return IRQ_HANDLED;
553 }
554
555 static int modem_mount_fs(char * dev_name, char * dir_name, char * type, ulong flags)
556 {
557         int ret;
558         mm_segment_t fs = get_fs();
559
560         set_fs(get_ds());
561         ret = sys_mount(dev_name, dir_name, type, flags, 0);
562         set_fs(fs);
563
564         return ret;
565 }
566
567 static int modem_umount_fs(char * name, ulong flags)
568 {
569         int ret;
570         mm_segment_t fs = get_fs();
571
572         set_fs(get_ds());
573         ret = sys_umount(name, flags);
574         set_fs(fs);
575
576         return ret;
577 }
578
579 static int mount_fs(void)
580 {
581         int ret;
582
583         ret = modem_mount_fs(MODEM_PARTITION, MODEM_MOUNT_PATH, MODEM_FS_TYPE, MS_VERBOSE);
584         if (ret && (ret != -EBUSY)) {
585                 printk("FATAL: %s mount failed! ret = %d\n", MODEM_PARTITION, ret);
586                 ret = modem_mount_fs(MODEM_PARTITION, MODEM_MOUNT_PATH, MODEM_FS_TYPE_TMP, MS_VERBOSE);
587                 if (ret && (ret != -EBUSY)) {
588                         printk("FATAL: %s (vfat) mount failed! ret = %d\n", MODEM_PARTITION, ret);
589                         return ret;
590                 }
591         }
592
593         ret = modem_mount_fs(CSA_PARTITION, CSA_MOUNT_PATH, CSA_FS_TYPE, MS_VERBOSE);
594         if (ret && (ret != -EBUSY)) {
595                 printk("FATAL: %s mount failed! ret = %d\n", CSA_PARTITION, ret);
596                 modem_umount_fs(MODEM_MOUNT_PATH, 0);
597                 return ret;
598         }
599
600         return ret;
601 }
602
603 static int xmm6260_flm(struct device *dev)
604 {
605         int ret;
606
607         static char *img_path = MODEM_BIN_PATH;
608         static char *bin_path = MODEM_FLM_EXE_PATH;
609         char *argv[] = { bin_path, img_path, NULL };
610         static char *envp[] = { "HOME=/usr/home/root",
611                                 "TERM=linux",
612                                 "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
613                                 NULL };
614
615         ret = mount_fs();
616         if (ret < 0) {
617                 dev_err(dev, "failed to mount file system\n");
618         }
619
620         usermodehelper_enable();
621
622         ret = call_usermodehelper(bin_path, argv, envp, UMH_WAIT_EXEC);
623         if (ret < 0) {
624                 dev_err(dev, "executing %s failed (%d)\n", bin_path, ret);
625         }
626
627         return ret;
628 }
629
630 void xmm6260_boot(struct work_struct *work)
631 {
632         int ret;
633         struct xmm6260_data *data = container_of(work, struct xmm6260_data,
634                         boot_dwork.work);
635         struct device *dev = data->dev;
636         dev_dbg(dev, "%s\n", __func__);
637
638         /* TODO: check fail */
639         ret = xmm6260_flm(dev);
640         if (ret < 0)
641                 dev_err(dev, "failed to xmm6260_flm\n");
642
643         dev_dbg(dev, "%s end\n", __func__);
644 }
645
646 int req_xmm6260_slave_wakeup(void)
647 {
648         struct device *dev;
649         struct xmm6260_gpios *gpios;
650         struct xmm6260_data *data;
651         int val;
652         int ret;
653
654         if (!xmm6260_data)
655                 return -EFAULT;
656
657         data = xmm6260_data;
658         dev = data->dev;
659         gpios = data->gpios;
660
661         if (unlikely(!xmm6260_get_cp_on() ||
662                                 !xmm6260_get_phone_active())) {
663                 dev_dbg(dev, "CP is not active\n");
664                 return -ENODEV;
665         }
666
667         val = gpio_get_value(gpios->ipc_host_wakeup);
668         if (!val) {
669                 dev_dbg(dev, "HOST_WAKEUP already low\n");
670                 if (!req_xmm6260_bus_resume)
671                         return -EFAULT;
672                 ret = req_xmm6260_bus_resume();
673                 if (ret < 0)
674                         dev_err(dev, "\tFATAL : req bus resume failed: %d\n",
675                                         ret);
676                 return 0;
677         } 
678
679         val = gpio_get_value(gpios->ipc_slave_wakeup);
680         if (val) {
681                 dev_dbg(dev, "SLAVE_WAKEUP already high\n");
682                 /* retry */
683                 gpio_set_value(gpios->ipc_slave_wakeup, 0);
684                 msleep(10);
685                 gpio_set_value(gpios->ipc_slave_wakeup, 1);
686         } else {
687                 gpio_set_value(gpios->ipc_slave_wakeup, 1);
688                 dev_dbg(dev, "SLAVE_WAKEUP set high\n");
689         }
690
691         return 0;
692 }
693 EXPORT_SYMBOL(req_xmm6260_slave_wakeup);
694
695 static int __devinit xmm6260_probe(struct platform_device *pdev)
696 {
697         struct device *dev = &pdev->dev;
698         struct xmm6260_platform_data *pdata = pdev->dev.platform_data;
699         struct xmm6260_data *data;
700         struct xmm6260_gpios *gpios;
701         int irq;
702         int err;
703         int i;
704
705         dev_dbg(dev, "Probe..\n");
706
707         if (!pdata || !pdata->gpios) {
708                 dev_err(dev, "Wrong platform data\n");
709                 return -EINVAL;
710         }
711
712         data = kzalloc(sizeof(struct xmm6260_data), GFP_KERNEL);
713         if (!data) {
714                 dev_err(dev, "Failed to allocate memory\n");
715                 return -ENOMEM;
716         }
717
718         data->dev = dev;
719         data->gpios = gpios = pdata->gpios;
720         data->boot_wq = create_workqueue("boot_wq");
721         if (!data->boot_wq) {
722                 dev_err(dev, "Failed to allocate workqueue\n");
723                 goto fail;
724         }
725         INIT_DELAYED_WORK(&data->status_dwork, modem_status_dwork);
726
727         err = sysfs_create_group(&dev->kobj, &xmm6260_attr_group);
728         if (err) {
729                 dev_err(dev, "Failed to create sysfs files\n");
730                 goto fail;
731         }
732
733         device_init_wakeup(&pdev->dev, pdata->wakeup);
734         platform_set_drvdata(pdev, data);
735
736         xmm6260_data = data;
737
738         irq = gpio_to_irq(gpios->phone_active);
739         err = request_threaded_irq(irq, NULL, phone_active_handler,
740                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
741                         "PHONE_ACTIVE", data);
742         if (err) {
743                 dev_err(dev, "Failed to allocate an interrupt(%d)\n", irq);
744                 goto fail;
745         }
746         data->irq[XMM_GPIO_PHONE_ACTIVE] = irq;
747
748         irq = gpio_to_irq(gpios->ipc_host_wakeup);
749         err = request_threaded_irq(irq, NULL, ipc_host_wakeup_handler,
750                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
751                         "HOST_WAKEUP", data);
752         if (err) {
753                 dev_err(dev, "Failed to allocate an interrupt(%d)\n", irq);
754                 goto fail;
755         }
756         data->irq[XMM_GPIO_HOST_WAKEUP] = irq;
757
758         irq = gpio_to_irq(gpios->suspend_request_hsic);
759         err = request_threaded_irq(irq, NULL, suspend_request_hsic_handler,
760                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
761                         "SUSPEND_REQUEST_HSIC", data);
762         if (err) {
763                 dev_err(dev, "Failed to allocate an interrupt(%d)\n", irq);
764                 goto fail;
765         }
766         data->irq[XMM_GPIO_SUSPEND_REQUEST_HSIC] = irq;
767
768         irq = gpio_to_irq(gpios->cp_dump_int);
769         err = request_irq(irq, cp_dump_handler,
770                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "CP_DUMP_INT", data);
771         if (err) {
772                 dev_err(dev, "Failed to allocate an interrupt(%d)\n", irq);
773                 goto fail;
774         }
775         data->irq[XMM_GPIO_DUMP_INT] = irq;
776
777         dev_dbg(dev, "Probe end\n");
778
779         return 0;
780
781 fail:
782         for (i = 0; i < ARRAY_SIZE(data->irq); i++) {
783                 if (data->irq[i])
784                         free_irq(data->irq[i], data);
785         }
786
787         xmm6260_data = NULL;
788         kfree(data);
789
790         return err;
791 }
792
793 static int __devexit xmm6260_remove(struct platform_device *pdev)
794 {
795         struct xmm6260_data *data = platform_get_drvdata(pdev);
796         struct device *dev = data->dev;
797         int i;
798
799         flush_work(&data->status_dwork.work);
800         platform_set_drvdata(pdev, NULL);
801         sysfs_remove_group(&dev->kobj, &xmm6260_attr_group);
802
803         for (i = 0; i < ARRAY_SIZE(data->irq); i++) {
804                 if (data->irq[i])
805                         free_irq(data->irq[i], data);
806         }
807
808         xmm6260_data = NULL;
809         kfree(data);
810
811         return 0;
812 }
813
814 #ifdef CONFIG_PM
815 static int xmm6260_suspend(struct device *dev)
816 {
817         struct platform_device *pdev = to_platform_device(dev);
818         struct xmm6260_data *data = platform_get_drvdata(pdev);
819         int ret = 0;
820
821         dev_dbg(dev, "%s\n", __func__);
822
823         /* check if CP already issued HOST_WAKEUP or AP issued SLAVE_WAKEUP */ 
824         if (xmm6260_get_slave_wakeup() > 0) {
825                 ret = -EBUSY;
826                 goto exit;
827         }
828
829         if (data->state == STATE_L2_RESUME) {
830                 ret = -EBUSY;
831                 goto exit;
832 #ifdef USE_CP_INITIATED_L0_L2
833         } else if (data->state == STATE_L2_SUSPEND) {
834                 ret = -EAGAIN;
835                 goto exit;
836 #endif
837         } else if (data->state == STATE_L3_SUSPEND) {
838                 ret = -EINVAL;
839                 goto exit;
840         }
841
842         if (device_may_wakeup(dev) && xmm6260_get_cp_on())
843                 enable_irq_wake(data->irq[XMM_GPIO_HOST_WAKEUP]);
844
845         xmm6260_set_state(STATE_L3_SUSPEND);
846
847 exit:
848         dev_dbg(dev, "%s end\n", __func__);
849
850         return ret;
851 }
852
853 static int xmm6260_resume(struct device *dev)
854 {
855         struct platform_device *pdev = to_platform_device(dev);
856         struct xmm6260_data *data = platform_get_drvdata(pdev);
857
858         dev_dbg(dev, "%s\n", __func__);
859
860         if (data->state == STATE_L3_SUSPEND)
861                 xmm6260_set_state(STATE_L2_RESUME);
862
863         if (device_may_wakeup(dev) && xmm6260_get_cp_on())
864                 disable_irq_wake(data->irq[XMM_GPIO_HOST_WAKEUP]);
865
866         xmm_set_boot_flag(0);
867
868         dev_dbg(dev, "%s end\n", __func__);
869
870         return 0;
871 }
872
873 static int xmm6260_restore(struct device *dev)
874 {
875         struct platform_device *pdev = to_platform_device(dev);
876         struct xmm6260_data *data = platform_get_drvdata(pdev);
877
878         data->boot_done = 0;
879         dev_dbg(dev, "%s and boot_done: %d\n", __func__, data->boot_done);
880
881         INIT_DELAYED_WORK(&data->boot_dwork, xmm6260_boot);
882         queue_delayed_work(data->boot_wq, &data->boot_dwork, 0UL);
883
884         return 0;
885 }
886
887 static const struct dev_pm_ops xmm6260_pm_ops = {
888         .suspend        = xmm6260_suspend,
889         .resume         = xmm6260_resume,
890         .restore        = xmm6260_restore,
891 };
892
893 #define XMM6260_PM_OPS  (&xmm6260_pm_ops)
894 #else
895 #define XMM6260_PM_OPS  NULL
896 #endif
897
898 /* 
899  * SLP uses standardized device name of modemctl 
900  * and this is same to Android.
901  */
902 static struct platform_device_id modem_ids[] = {
903         { .name         = "modemctl",},
904         { }
905 };
906
907 static struct platform_driver xmm6260_driver = {
908         .probe          = xmm6260_probe,
909         .remove         = __devexit_p(xmm6260_remove),
910         .id_table       = modem_ids,
911         .driver         = {
912                 .name   = "xmm6260",
913                 .owner  = THIS_MODULE,
914                 .pm     = XMM6260_PM_OPS,
915         },
916 };
917
918 static int __init xmm6260_init(void)
919 {
920         return platform_driver_register(&xmm6260_driver);
921 }
922
923 static void __exit xmm6260_exit(void)
924 {
925         platform_driver_unregister(&xmm6260_driver);
926 }
927
928 module_init(xmm6260_init);
929 module_exit(xmm6260_exit);
930
931 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
932 MODULE_DESCRIPTION("XMM6260 control driver");
933 MODULE_LICENSE("GPL");
934 MODULE_ALIAS("platform:xmm6260");