0001
0002
0003
0004
0005
0006
0007 #include <linux/input.h>
0008 #include <linux/io.h>
0009 #include <linux/ioport.h>
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/slab.h>
0013
0014 #define BUTTONS_POLL_INTERVAL 30
0015 #define BUTTONS_COUNT_THRESHOLD 3
0016 #define BUTTONS_STATUS_MASK 0xfe000000
0017
0018 static const unsigned short cobalt_map[] = {
0019 KEY_RESERVED,
0020 KEY_RESTART,
0021 KEY_LEFT,
0022 KEY_UP,
0023 KEY_DOWN,
0024 KEY_RIGHT,
0025 KEY_ENTER,
0026 KEY_SELECT
0027 };
0028
0029 struct buttons_dev {
0030 unsigned short keymap[ARRAY_SIZE(cobalt_map)];
0031 int count[ARRAY_SIZE(cobalt_map)];
0032 void __iomem *reg;
0033 };
0034
0035 static void handle_buttons(struct input_dev *input)
0036 {
0037 struct buttons_dev *bdev = input_get_drvdata(input);
0038 uint32_t status;
0039 int i;
0040
0041 status = ~readl(bdev->reg) >> 24;
0042
0043 for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) {
0044 if (status & (1U << i)) {
0045 if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) {
0046 input_event(input, EV_MSC, MSC_SCAN, i);
0047 input_report_key(input, bdev->keymap[i], 1);
0048 input_sync(input);
0049 }
0050 } else {
0051 if (bdev->count[i] >= BUTTONS_COUNT_THRESHOLD) {
0052 input_event(input, EV_MSC, MSC_SCAN, i);
0053 input_report_key(input, bdev->keymap[i], 0);
0054 input_sync(input);
0055 }
0056 bdev->count[i] = 0;
0057 }
0058 }
0059 }
0060
0061 static int cobalt_buttons_probe(struct platform_device *pdev)
0062 {
0063 struct buttons_dev *bdev;
0064 struct input_dev *input;
0065 struct resource *res;
0066 int error, i;
0067
0068 bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL);
0069 if (!bdev)
0070 return -ENOMEM;
0071
0072 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0073 if (!res)
0074 return -EBUSY;
0075
0076 bdev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res));
0077 if (!bdev->reg)
0078 return -ENOMEM;
0079
0080 memcpy(bdev->keymap, cobalt_map, sizeof(bdev->keymap));
0081
0082 input = devm_input_allocate_device(&pdev->dev);
0083 if (!input)
0084 return -ENOMEM;
0085
0086 input_set_drvdata(input, bdev);
0087
0088 input->name = "Cobalt buttons";
0089 input->phys = "cobalt/input0";
0090 input->id.bustype = BUS_HOST;
0091
0092 input->keycode = bdev->keymap;
0093 input->keycodemax = ARRAY_SIZE(bdev->keymap);
0094 input->keycodesize = sizeof(unsigned short);
0095
0096 input_set_capability(input, EV_MSC, MSC_SCAN);
0097 __set_bit(EV_KEY, input->evbit);
0098 for (i = 0; i < ARRAY_SIZE(cobalt_map); i++)
0099 __set_bit(bdev->keymap[i], input->keybit);
0100 __clear_bit(KEY_RESERVED, input->keybit);
0101
0102
0103 error = input_setup_polling(input, handle_buttons);
0104 if (error)
0105 return error;
0106
0107 input_set_poll_interval(input, BUTTONS_POLL_INTERVAL);
0108
0109 error = input_register_device(input);
0110 if (error)
0111 return error;
0112
0113 return 0;
0114 }
0115
0116 MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
0117 MODULE_DESCRIPTION("Cobalt button interface driver");
0118 MODULE_LICENSE("GPL");
0119
0120 MODULE_ALIAS("platform:Cobalt buttons");
0121
0122 static struct platform_driver cobalt_buttons_driver = {
0123 .probe = cobalt_buttons_probe,
0124 .driver = {
0125 .name = "Cobalt buttons",
0126 },
0127 };
0128 module_platform_driver(cobalt_buttons_driver);