max77650-onkey.c (3171B)
1// SPDX-License-Identifier: GPL-2.0 2// 3// Copyright (C) 2018 BayLibre SAS 4// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> 5// 6// ONKEY driver for MAXIM 77650/77651 charger/power-supply. 7 8#include <linux/i2c.h> 9#include <linux/input.h> 10#include <linux/interrupt.h> 11#include <linux/mfd/max77650.h> 12#include <linux/module.h> 13#include <linux/platform_device.h> 14#include <linux/regmap.h> 15 16#define MAX77650_ONKEY_MODE_MASK BIT(3) 17#define MAX77650_ONKEY_MODE_PUSH 0x00 18#define MAX77650_ONKEY_MODE_SLIDE BIT(3) 19 20struct max77650_onkey { 21 struct input_dev *input; 22 unsigned int code; 23}; 24 25static irqreturn_t max77650_onkey_falling(int irq, void *data) 26{ 27 struct max77650_onkey *onkey = data; 28 29 input_report_key(onkey->input, onkey->code, 0); 30 input_sync(onkey->input); 31 32 return IRQ_HANDLED; 33} 34 35static irqreturn_t max77650_onkey_rising(int irq, void *data) 36{ 37 struct max77650_onkey *onkey = data; 38 39 input_report_key(onkey->input, onkey->code, 1); 40 input_sync(onkey->input); 41 42 return IRQ_HANDLED; 43} 44 45static int max77650_onkey_probe(struct platform_device *pdev) 46{ 47 int irq_r, irq_f, error, mode; 48 struct max77650_onkey *onkey; 49 struct device *dev, *parent; 50 struct regmap *map; 51 unsigned int type; 52 53 dev = &pdev->dev; 54 parent = dev->parent; 55 56 map = dev_get_regmap(parent, NULL); 57 if (!map) 58 return -ENODEV; 59 60 onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL); 61 if (!onkey) 62 return -ENOMEM; 63 64 error = device_property_read_u32(dev, "linux,code", &onkey->code); 65 if (error) 66 onkey->code = KEY_POWER; 67 68 if (device_property_read_bool(dev, "maxim,onkey-slide")) { 69 mode = MAX77650_ONKEY_MODE_SLIDE; 70 type = EV_SW; 71 } else { 72 mode = MAX77650_ONKEY_MODE_PUSH; 73 type = EV_KEY; 74 } 75 76 error = regmap_update_bits(map, MAX77650_REG_CNFG_GLBL, 77 MAX77650_ONKEY_MODE_MASK, mode); 78 if (error) 79 return error; 80 81 irq_f = platform_get_irq_byname(pdev, "nEN_F"); 82 if (irq_f < 0) 83 return irq_f; 84 85 irq_r = platform_get_irq_byname(pdev, "nEN_R"); 86 if (irq_r < 0) 87 return irq_r; 88 89 onkey->input = devm_input_allocate_device(dev); 90 if (!onkey->input) 91 return -ENOMEM; 92 93 onkey->input->name = "max77650_onkey"; 94 onkey->input->phys = "max77650_onkey/input0"; 95 onkey->input->id.bustype = BUS_I2C; 96 input_set_capability(onkey->input, type, onkey->code); 97 98 error = devm_request_any_context_irq(dev, irq_f, max77650_onkey_falling, 99 IRQF_ONESHOT, "onkey-down", onkey); 100 if (error < 0) 101 return error; 102 103 error = devm_request_any_context_irq(dev, irq_r, max77650_onkey_rising, 104 IRQF_ONESHOT, "onkey-up", onkey); 105 if (error < 0) 106 return error; 107 108 return input_register_device(onkey->input); 109} 110 111static const struct of_device_id max77650_onkey_of_match[] = { 112 { .compatible = "maxim,max77650-onkey" }, 113 { } 114}; 115MODULE_DEVICE_TABLE(of, max77650_onkey_of_match); 116 117static struct platform_driver max77650_onkey_driver = { 118 .driver = { 119 .name = "max77650-onkey", 120 .of_match_table = max77650_onkey_of_match, 121 }, 122 .probe = max77650_onkey_probe, 123}; 124module_platform_driver(max77650_onkey_driver); 125 126MODULE_DESCRIPTION("MAXIM 77650/77651 ONKEY driver"); 127MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); 128MODULE_LICENSE("GPL v2"); 129MODULE_ALIAS("platform:max77650-onkey");