pcf50633-input.c (2818B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* NXP PCF50633 Input Driver 3 * 4 * (C) 2006-2008 by Openmoko, Inc. 5 * Author: Balaji Rao <balajirrao@openmoko.org> 6 * All rights reserved. 7 * 8 * Broken down from monstrous PCF50633 driver mainly by 9 * Harald Welte, Andy Green and Werner Almesberger 10 */ 11 12#include <linux/kernel.h> 13#include <linux/module.h> 14#include <linux/device.h> 15#include <linux/platform_device.h> 16#include <linux/input.h> 17#include <linux/slab.h> 18 19#include <linux/mfd/pcf50633/core.h> 20 21#define PCF50633_OOCSTAT_ONKEY 0x01 22#define PCF50633_REG_OOCSTAT 0x12 23#define PCF50633_REG_OOCMODE 0x10 24 25struct pcf50633_input { 26 struct pcf50633 *pcf; 27 struct input_dev *input_dev; 28}; 29 30static void 31pcf50633_input_irq(int irq, void *data) 32{ 33 struct pcf50633_input *input; 34 int onkey_released; 35 36 input = data; 37 38 /* We report only one event depending on the key press status */ 39 onkey_released = pcf50633_reg_read(input->pcf, PCF50633_REG_OOCSTAT) 40 & PCF50633_OOCSTAT_ONKEY; 41 42 if (irq == PCF50633_IRQ_ONKEYF && !onkey_released) 43 input_report_key(input->input_dev, KEY_POWER, 1); 44 else if (irq == PCF50633_IRQ_ONKEYR && onkey_released) 45 input_report_key(input->input_dev, KEY_POWER, 0); 46 47 input_sync(input->input_dev); 48} 49 50static int pcf50633_input_probe(struct platform_device *pdev) 51{ 52 struct pcf50633_input *input; 53 struct input_dev *input_dev; 54 int ret; 55 56 57 input = kzalloc(sizeof(*input), GFP_KERNEL); 58 if (!input) 59 return -ENOMEM; 60 61 input_dev = input_allocate_device(); 62 if (!input_dev) { 63 kfree(input); 64 return -ENOMEM; 65 } 66 67 platform_set_drvdata(pdev, input); 68 input->pcf = dev_to_pcf50633(pdev->dev.parent); 69 input->input_dev = input_dev; 70 71 input_dev->name = "PCF50633 PMU events"; 72 input_dev->id.bustype = BUS_I2C; 73 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR); 74 set_bit(KEY_POWER, input_dev->keybit); 75 76 ret = input_register_device(input_dev); 77 if (ret) { 78 input_free_device(input_dev); 79 kfree(input); 80 return ret; 81 } 82 pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR, 83 pcf50633_input_irq, input); 84 pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF, 85 pcf50633_input_irq, input); 86 87 return 0; 88} 89 90static int pcf50633_input_remove(struct platform_device *pdev) 91{ 92 struct pcf50633_input *input = platform_get_drvdata(pdev); 93 94 pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYR); 95 pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYF); 96 97 input_unregister_device(input->input_dev); 98 kfree(input); 99 100 return 0; 101} 102 103static struct platform_driver pcf50633_input_driver = { 104 .driver = { 105 .name = "pcf50633-input", 106 }, 107 .probe = pcf50633_input_probe, 108 .remove = pcf50633_input_remove, 109}; 110module_platform_driver(pcf50633_input_driver); 111 112MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>"); 113MODULE_DESCRIPTION("PCF50633 input driver"); 114MODULE_LICENSE("GPL"); 115MODULE_ALIAS("platform:pcf50633-input");