Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mc13783-pwrbutton.c
Go to the documentation of this file.
1 
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/input.h>
27 #include <linux/interrupt.h>
28 #include <linux/platform_device.h>
29 #include <linux/mfd/mc13783.h>
30 #include <linux/sched.h>
31 #include <linux/slab.h>
32 
33 struct mc13783_pwrb {
34  struct input_dev *pwr;
35  struct mc13xxx *mc13783;
36 #define MC13783_PWRB_B1_POL_INVERT (1 << 0)
37 #define MC13783_PWRB_B2_POL_INVERT (1 << 1)
38 #define MC13783_PWRB_B3_POL_INVERT (1 << 2)
39  int flags;
40  unsigned short keymap[3];
41 };
42 
43 #define MC13783_REG_INTERRUPT_SENSE_1 5
44 #define MC13783_IRQSENSE1_ONOFD1S (1 << 3)
45 #define MC13783_IRQSENSE1_ONOFD2S (1 << 4)
46 #define MC13783_IRQSENSE1_ONOFD3S (1 << 5)
47 
48 #define MC13783_REG_POWER_CONTROL_2 15
49 #define MC13783_POWER_CONTROL_2_ON1BDBNC 4
50 #define MC13783_POWER_CONTROL_2_ON2BDBNC 6
51 #define MC13783_POWER_CONTROL_2_ON3BDBNC 8
52 #define MC13783_POWER_CONTROL_2_ON1BRSTEN (1 << 1)
53 #define MC13783_POWER_CONTROL_2_ON2BRSTEN (1 << 2)
54 #define MC13783_POWER_CONTROL_2_ON3BRSTEN (1 << 3)
55 
56 static irqreturn_t button_irq(int irq, void *_priv)
57 {
58  struct mc13783_pwrb *priv = _priv;
59  int val;
60 
61  mc13xxx_irq_ack(priv->mc13783, irq);
63 
64  switch (irq) {
65  case MC13783_IRQ_ONOFD1:
66  val = val & MC13783_IRQSENSE1_ONOFD1S ? 1 : 0;
68  val ^= 1;
69  input_report_key(priv->pwr, priv->keymap[0], val);
70  break;
71 
72  case MC13783_IRQ_ONOFD2:
73  val = val & MC13783_IRQSENSE1_ONOFD2S ? 1 : 0;
75  val ^= 1;
76  input_report_key(priv->pwr, priv->keymap[1], val);
77  break;
78 
79  case MC13783_IRQ_ONOFD3:
80  val = val & MC13783_IRQSENSE1_ONOFD3S ? 1 : 0;
82  val ^= 1;
83  input_report_key(priv->pwr, priv->keymap[2], val);
84  break;
85  }
86 
87  input_sync(priv->pwr);
88 
89  return IRQ_HANDLED;
90 }
91 
92 static int __devinit mc13783_pwrbutton_probe(struct platform_device *pdev)
93 {
95  struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
96  struct input_dev *pwr;
97  struct mc13783_pwrb *priv;
98  int err = 0;
99  int reg = 0;
100 
101  pdata = dev_get_platdata(&pdev->dev);
102  if (!pdata) {
103  dev_err(&pdev->dev, "missing platform data\n");
104  return -ENODEV;
105  }
106 
107  pwr = input_allocate_device();
108  if (!pwr) {
109  dev_dbg(&pdev->dev, "Can't allocate power button\n");
110  return -ENOMEM;
111  }
112 
113  priv = kzalloc(sizeof(*priv), GFP_KERNEL);
114  if (!priv) {
115  err = -ENOMEM;
116  dev_dbg(&pdev->dev, "Can't allocate power button\n");
117  goto free_input_dev;
118  }
119 
120  reg |= (pdata->b1on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON1BDBNC;
121  reg |= (pdata->b2on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON2BDBNC;
122  reg |= (pdata->b3on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON3BDBNC;
123 
124  priv->pwr = pwr;
125  priv->mc13783 = mc13783;
126 
127  mc13xxx_lock(mc13783);
128 
129  if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) {
130  priv->keymap[0] = pdata->b1on_key;
131  if (pdata->b1on_key != KEY_RESERVED)
132  __set_bit(pdata->b1on_key, pwr->keybit);
133 
136 
137  if (pdata->b1on_flags & MC13783_BUTTON_RESET_EN)
139 
141  button_irq, "b1on", priv);
142  if (err) {
143  dev_dbg(&pdev->dev, "Can't request irq\n");
144  goto free_priv;
145  }
146  }
147 
148  if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) {
149  priv->keymap[1] = pdata->b2on_key;
150  if (pdata->b2on_key != KEY_RESERVED)
151  __set_bit(pdata->b2on_key, pwr->keybit);
152 
155 
156  if (pdata->b2on_flags & MC13783_BUTTON_RESET_EN)
158 
160  button_irq, "b2on", priv);
161  if (err) {
162  dev_dbg(&pdev->dev, "Can't request irq\n");
163  goto free_irq_b1;
164  }
165  }
166 
167  if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) {
168  priv->keymap[2] = pdata->b3on_key;
169  if (pdata->b3on_key != KEY_RESERVED)
170  __set_bit(pdata->b3on_key, pwr->keybit);
171 
174 
175  if (pdata->b3on_flags & MC13783_BUTTON_RESET_EN)
177 
179  button_irq, "b3on", priv);
180  if (err) {
181  dev_dbg(&pdev->dev, "Can't request irq: %d\n", err);
182  goto free_irq_b2;
183  }
184  }
185 
186  mc13xxx_reg_rmw(mc13783, MC13783_REG_POWER_CONTROL_2, 0x3FE, reg);
187 
188  mc13xxx_unlock(mc13783);
189 
190  pwr->name = "mc13783_pwrbutton";
191  pwr->phys = "mc13783_pwrbutton/input0";
192  pwr->dev.parent = &pdev->dev;
193 
194  pwr->keycode = priv->keymap;
195  pwr->keycodemax = ARRAY_SIZE(priv->keymap);
196  pwr->keycodesize = sizeof(priv->keymap[0]);
197  __set_bit(EV_KEY, pwr->evbit);
198 
199  err = input_register_device(pwr);
200  if (err) {
201  dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
202  goto free_irq;
203  }
204 
205  platform_set_drvdata(pdev, priv);
206 
207  return 0;
208 
209 free_irq:
210  mc13xxx_lock(mc13783);
211 
212  if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
213  mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD3, priv);
214 
215 free_irq_b2:
216  if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
217  mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD2, priv);
218 
219 free_irq_b1:
220  if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
221  mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD1, priv);
222 
223 free_priv:
224  mc13xxx_unlock(mc13783);
225  kfree(priv);
226 
227 free_input_dev:
228  input_free_device(pwr);
229 
230  return err;
231 }
232 
233 static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev)
234 {
235  struct mc13783_pwrb *priv = platform_get_drvdata(pdev);
236  const struct mc13xxx_buttons_platform_data *pdata;
237 
238  pdata = dev_get_platdata(&pdev->dev);
239 
240  mc13xxx_lock(priv->mc13783);
241 
242  if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
244  if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
246  if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
248 
249  mc13xxx_unlock(priv->mc13783);
250 
251  input_unregister_device(priv->pwr);
252  kfree(priv);
253  platform_set_drvdata(pdev, NULL);
254 
255  return 0;
256 }
257 
258 static struct platform_driver mc13783_pwrbutton_driver = {
259  .probe = mc13783_pwrbutton_probe,
260  .remove = __devexit_p(mc13783_pwrbutton_remove),
261  .driver = {
262  .name = "mc13783-pwrbutton",
263  .owner = THIS_MODULE,
264  },
265 };
266 
267 module_platform_driver(mc13783_pwrbutton_driver);
268 
269 MODULE_ALIAS("platform:mc13783-pwrbutton");
270 MODULE_DESCRIPTION("MC13783 Power Button");
271 MODULE_LICENSE("GPL v2");
272 MODULE_AUTHOR("Philippe Retornaz");