sb: remove redundant unused debug driver
[efikamx:linux-kernel.git] / arch / arm / mach-mx5 / mx51_efikasb_lid.c
1 /*
2  * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
3  * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
4  */
5
6 #include <linux/init.h>
7 #include <linux/input.h>
8 #include <linux/irq.h>
9 #include <linux/interrupt.h>
10 #include <linux/suspend.h>
11 #include <linux/pci_ids.h>
12 #include <linux/platform_device.h>
13 #include <mach/gpio.h>
14 #include <asm/setup.h>
15
16 #include "mx51_efikasb.h"
17 #include "mx51_pins.h"
18 #include "iomux.h"
19
20 int lid_wake_enable = 0;
21 extern int mxc_get_lid_sw_status(void);
22
23 static struct input_dev *efikasb_lid_inputdev;
24
25 static struct platform_device efikasb_lid_dev = {
26         .name = "efikasb_lid",
27 };
28
29 static irqreturn_t lid_sw_int(int irq, void *dev_id)
30 {
31         int lid_close;
32
33         lid_close = mxc_get_lid_sw_status();
34         if(lid_close) {
35                 pr_info("Lid Switch Close\n");
36                 set_irq_type(irq, IRQF_TRIGGER_RISING);
37
38                 if(lid_wake_enable)
39                         enable_irq_wake(irq);
40
41                 input_report_switch(efikasb_lid_inputdev, SW_LID, lid_close);
42                 input_sync(efikasb_lid_inputdev);
43
44         } else {
45                 pr_info("Lid Switch Open\n");
46                 set_irq_type(irq, IRQF_TRIGGER_FALLING);
47
48                 input_report_switch(efikasb_lid_inputdev, SW_LID, lid_close);
49                 input_sync(efikasb_lid_inputdev);
50
51                 if(lid_wake_enable)
52                         disable_irq_wake(irq);
53         }
54
55         return IRQ_HANDLED;
56 }
57
58 static int mxc_init_lid_sw(void)
59 {
60         int irq, ret;
61
62         gpio_request(IOMUX_TO_GPIO(LID_SW_PIN), "lid_sw");
63         gpio_direction_input(IOMUX_TO_GPIO(LID_SW_PIN));
64         irq = IOMUX_TO_IRQ(LID_SW_PIN);
65
66         if(mxc_get_lid_sw_status()) {
67                 pr_info("Lid Switch Close\n");
68                 set_irq_type(irq, IRQF_TRIGGER_RISING);
69         } else {
70                 pr_info("Lid Switch Open\n");
71                 set_irq_type(irq, IRQF_TRIGGER_FALLING);
72         }
73
74         ret = request_irq(irq, lid_sw_int, 0, "lid-sw", 0);
75         if(ret) 
76                 pr_info("register lid switch interrupt failed\n");
77
78         return ret;
79 }
80
81 static ssize_t lid_status_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
82 {
83         return sprintf(buf, "%d\n", mxc_get_lid_sw_status());
84 }
85
86 static ssize_t lid_wake_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
87 {
88         return sprintf(buf, "%s\n", lid_wake_enable ? "on": "off");
89 }
90
91 static ssize_t lid_wake_store(struct kobject *kobj, struct kobj_attribute *attr,
92                               const char *buf, size_t count)
93 {
94         if(strncmp(buf, "on", 2) == 0)
95                 lid_wake_enable = 1;
96         else if (strncmp(buf, "off", 3) == 0)
97                 lid_wake_enable = 0;
98         else
99                 return -EINVAL;
100
101         return count;
102 }
103
104 static struct kobj_attribute lid_status_attribute =
105         __ATTR(lid, S_IFREG | S_IRUGO, lid_status_show, NULL);
106 static struct kobj_attribute lid_wake_attribute =
107         __ATTR(lid_wake, 0666, lid_wake_show, lid_wake_store);
108
109 static struct attribute *status_attrs[] = {
110         &lid_status_attribute.attr,
111         &lid_wake_attribute.attr,
112         NULL,
113 };
114
115 static struct attribute_group status_attr_group = {
116         .attrs = status_attrs,
117 };
118
119 static void __init lid_wake_setup(char **p)
120 {
121         if(memcmp(*p, "on", 2) == 0) {
122                 lid_wake_enable = 1;
123                 *p += 2;
124         } else if(memcmp(*p, "off", 3) == 0) {
125                 lid_wake_enable = 0;
126                 *p += 3;
127         }
128 }
129
130 __early_param("lid_wake=", lid_wake_setup);
131
132 static int __init mxc_init_efikasb_lid(void)
133 {
134         int ret ;
135         struct kobject *lid_kobj;
136
137         platform_device_register(&efikasb_lid_dev);
138
139         lid_kobj = kobject_create_and_add("status", &efikasb_lid_dev.dev.kobj);
140         if(!lid_kobj) {
141                 ret = -ENOMEM;
142                 goto err3;
143         }
144
145         ret = sysfs_create_group(lid_kobj, &status_attr_group);
146         if(ret) {
147                 goto err2;
148         }
149
150         efikasb_lid_inputdev = input_allocate_device();
151         if(!efikasb_lid_inputdev) {
152                 pr_err("Failed to allocate lid input device\n");
153                 ret = -ENOMEM;
154                 goto err2;
155         }
156
157         efikasb_lid_inputdev->name = "Efika MX Smartbook Lid Switch";
158         efikasb_lid_inputdev->phys = "efikasb/input1";
159         efikasb_lid_inputdev->uniq = "efikasb";
160         efikasb_lid_inputdev->id.bustype = BUS_HOST;
161         efikasb_lid_inputdev->id.vendor = PCI_VENDOR_ID_FREESCALE;
162
163         set_bit(EV_SW, efikasb_lid_inputdev->evbit);
164         set_bit(SW_LID, efikasb_lid_inputdev->swbit);
165
166         /* ron: 0:open 1:close */
167         if(mxc_get_lid_sw_status())
168                 set_bit(SW_LID, efikasb_lid_inputdev->sw);
169
170         ret = input_register_device(efikasb_lid_inputdev);
171         if(ret) {
172                 pr_err("Failed to register Efika MX Smartbook lid input device\n");
173                 ret = -ENODEV;
174                 goto err1;
175         }
176
177         mxc_init_lid_sw();
178
179         return ret;
180
181  err1:
182         input_free_device(efikasb_lid_inputdev);
183  err2:
184         kobject_put(lid_kobj);
185  err3:
186         platform_device_unregister(&efikasb_lid_dev);
187
188         return ret;
189 }
190
191 late_initcall(mxc_init_efikasb_lid);