Path: blob/master/drivers/input/misc/rb532_button.c
15109 views
/*1* Support for the S1 button on Routerboard 5322*3* Copyright (C) 2009 Phil Sutter <[email protected]>4*/56#include <linux/input-polldev.h>7#include <linux/module.h>8#include <linux/platform_device.h>910#include <asm/mach-rc32434/gpio.h>11#include <asm/mach-rc32434/rb.h>1213#define DRV_NAME "rb532-button"1415#define RB532_BTN_RATE 100 /* msec */16#define RB532_BTN_KSYM BTN_01718/* The S1 button state is provided by GPIO pin 1. But as this19* pin is also used for uart input as alternate function, the20* operational modes must be switched first:21* 1) disable uart using set_latch_u5()22* 2) turn off alternate function implicitly through23* gpio_direction_input()24* 3) read the GPIO's current value25* 4) undo step 2 by enabling alternate function (in this26* mode the GPIO direction is fixed, so no change needed)27* 5) turn on uart again28* The GPIO value occurs to be inverted, so pin high means29* button is not pressed.30*/31static bool rb532_button_pressed(void)32{33int val;3435set_latch_u5(0, LO_FOFF);36gpio_direction_input(GPIO_BTN_S1);3738val = gpio_get_value(GPIO_BTN_S1);3940rb532_gpio_set_func(GPIO_BTN_S1);41set_latch_u5(LO_FOFF, 0);4243return !val;44}4546static void rb532_button_poll(struct input_polled_dev *poll_dev)47{48input_report_key(poll_dev->input, RB532_BTN_KSYM,49rb532_button_pressed());50input_sync(poll_dev->input);51}5253static int __devinit rb532_button_probe(struct platform_device *pdev)54{55struct input_polled_dev *poll_dev;56int error;5758poll_dev = input_allocate_polled_device();59if (!poll_dev)60return -ENOMEM;6162poll_dev->poll = rb532_button_poll;63poll_dev->poll_interval = RB532_BTN_RATE;6465poll_dev->input->name = "rb532 button";66poll_dev->input->phys = "rb532/button0";67poll_dev->input->id.bustype = BUS_HOST;68poll_dev->input->dev.parent = &pdev->dev;6970dev_set_drvdata(&pdev->dev, poll_dev);7172input_set_capability(poll_dev->input, EV_KEY, RB532_BTN_KSYM);7374error = input_register_polled_device(poll_dev);75if (error) {76input_free_polled_device(poll_dev);77return error;78}7980return 0;81}8283static int __devexit rb532_button_remove(struct platform_device *pdev)84{85struct input_polled_dev *poll_dev = dev_get_drvdata(&pdev->dev);8687input_unregister_polled_device(poll_dev);88input_free_polled_device(poll_dev);89dev_set_drvdata(&pdev->dev, NULL);9091return 0;92}9394static struct platform_driver rb532_button_driver = {95.probe = rb532_button_probe,96.remove = __devexit_p(rb532_button_remove),97.driver = {98.name = DRV_NAME,99.owner = THIS_MODULE,100},101};102103static int __init rb532_button_init(void)104{105return platform_driver_register(&rb532_button_driver);106}107108static void __exit rb532_button_exit(void)109{110platform_driver_unregister(&rb532_button_driver);111}112113module_init(rb532_button_init);114module_exit(rb532_button_exit);115116MODULE_AUTHOR("Phil Sutter <[email protected]>");117MODULE_LICENSE("GPL");118MODULE_DESCRIPTION("Support for S1 button on Routerboard 532");119MODULE_ALIAS("platform:" DRV_NAME);120121122