Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rb532_button.c
Go to the documentation of this file.
1 /*
2  * Support for the S1 button on Routerboard 532
3  *
4  * Copyright (C) 2009 Phil Sutter <[email protected]>
5  */
6 
7 #include <linux/input-polldev.h>
8 #include <linux/module.h>
10 
11 #include <asm/mach-rc32434/gpio.h>
12 #include <asm/mach-rc32434/rb.h>
13 
14 #define DRV_NAME "rb532-button"
15 
16 #define RB532_BTN_RATE 100 /* msec */
17 #define RB532_BTN_KSYM BTN_0
18 
19 /* The S1 button state is provided by GPIO pin 1. But as this
20  * pin is also used for uart input as alternate function, the
21  * operational modes must be switched first:
22  * 1) disable uart using set_latch_u5()
23  * 2) turn off alternate function implicitly through
24  * gpio_direction_input()
25  * 3) read the GPIO's current value
26  * 4) undo step 2 by enabling alternate function (in this
27  * mode the GPIO direction is fixed, so no change needed)
28  * 5) turn on uart again
29  * The GPIO value occurs to be inverted, so pin high means
30  * button is not pressed.
31  */
32 static bool rb532_button_pressed(void)
33 {
34  int val;
35 
38 
40 
43 
44  return !val;
45 }
46 
47 static void rb532_button_poll(struct input_polled_dev *poll_dev)
48 {
49  input_report_key(poll_dev->input, RB532_BTN_KSYM,
50  rb532_button_pressed());
51  input_sync(poll_dev->input);
52 }
53 
54 static int __devinit rb532_button_probe(struct platform_device *pdev)
55 {
56  struct input_polled_dev *poll_dev;
57  int error;
58 
59  poll_dev = input_allocate_polled_device();
60  if (!poll_dev)
61  return -ENOMEM;
62 
63  poll_dev->poll = rb532_button_poll;
64  poll_dev->poll_interval = RB532_BTN_RATE;
65 
66  poll_dev->input->name = "rb532 button";
67  poll_dev->input->phys = "rb532/button0";
68  poll_dev->input->id.bustype = BUS_HOST;
69  poll_dev->input->dev.parent = &pdev->dev;
70 
71  dev_set_drvdata(&pdev->dev, poll_dev);
72 
73  input_set_capability(poll_dev->input, EV_KEY, RB532_BTN_KSYM);
74 
75  error = input_register_polled_device(poll_dev);
76  if (error) {
77  input_free_polled_device(poll_dev);
78  return error;
79  }
80 
81  return 0;
82 }
83 
84 static int __devexit rb532_button_remove(struct platform_device *pdev)
85 {
86  struct input_polled_dev *poll_dev = dev_get_drvdata(&pdev->dev);
87 
89  input_free_polled_device(poll_dev);
90  dev_set_drvdata(&pdev->dev, NULL);
91 
92  return 0;
93 }
94 
95 static struct platform_driver rb532_button_driver = {
96  .probe = rb532_button_probe,
97  .remove = __devexit_p(rb532_button_remove),
98  .driver = {
99  .name = DRV_NAME,
100  .owner = THIS_MODULE,
101  },
102 };
103 module_platform_driver(rb532_button_driver);
104 
105 MODULE_AUTHOR("Phil Sutter <[email protected]>");
106 MODULE_LICENSE("GPL");
107 MODULE_DESCRIPTION("Support for S1 button on Routerboard 532");
108 MODULE_ALIAS("platform:" DRV_NAME);