adp5520-keys.c (4918B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Keypad driver for Analog Devices ADP5520 MFD PMICs 4 * 5 * Copyright 2009 Analog Devices Inc. 6 */ 7 8#include <linux/module.h> 9#include <linux/kernel.h> 10#include <linux/platform_device.h> 11#include <linux/input.h> 12#include <linux/mfd/adp5520.h> 13#include <linux/slab.h> 14#include <linux/device.h> 15 16struct adp5520_keys { 17 struct input_dev *input; 18 struct notifier_block notifier; 19 struct device *master; 20 unsigned short keycode[ADP5520_KEYMAPSIZE]; 21}; 22 23static void adp5520_keys_report_event(struct adp5520_keys *dev, 24 unsigned short keymask, int value) 25{ 26 int i; 27 28 for (i = 0; i < ADP5520_MAXKEYS; i++) 29 if (keymask & (1 << i)) 30 input_report_key(dev->input, dev->keycode[i], value); 31 32 input_sync(dev->input); 33} 34 35static int adp5520_keys_notifier(struct notifier_block *nb, 36 unsigned long event, void *data) 37{ 38 struct adp5520_keys *dev; 39 uint8_t reg_val_lo, reg_val_hi; 40 unsigned short keymask; 41 42 dev = container_of(nb, struct adp5520_keys, notifier); 43 44 if (event & ADP5520_KP_INT) { 45 adp5520_read(dev->master, ADP5520_KP_INT_STAT_1, ®_val_lo); 46 adp5520_read(dev->master, ADP5520_KP_INT_STAT_2, ®_val_hi); 47 48 keymask = (reg_val_hi << 8) | reg_val_lo; 49 /* Read twice to clear */ 50 adp5520_read(dev->master, ADP5520_KP_INT_STAT_1, ®_val_lo); 51 adp5520_read(dev->master, ADP5520_KP_INT_STAT_2, ®_val_hi); 52 keymask |= (reg_val_hi << 8) | reg_val_lo; 53 adp5520_keys_report_event(dev, keymask, 1); 54 } 55 56 if (event & ADP5520_KR_INT) { 57 adp5520_read(dev->master, ADP5520_KR_INT_STAT_1, ®_val_lo); 58 adp5520_read(dev->master, ADP5520_KR_INT_STAT_2, ®_val_hi); 59 60 keymask = (reg_val_hi << 8) | reg_val_lo; 61 /* Read twice to clear */ 62 adp5520_read(dev->master, ADP5520_KR_INT_STAT_1, ®_val_lo); 63 adp5520_read(dev->master, ADP5520_KR_INT_STAT_2, ®_val_hi); 64 keymask |= (reg_val_hi << 8) | reg_val_lo; 65 adp5520_keys_report_event(dev, keymask, 0); 66 } 67 68 return 0; 69} 70 71static int adp5520_keys_probe(struct platform_device *pdev) 72{ 73 struct adp5520_keys_platform_data *pdata = dev_get_platdata(&pdev->dev); 74 struct input_dev *input; 75 struct adp5520_keys *dev; 76 int ret, i; 77 unsigned char en_mask, ctl_mask = 0; 78 79 if (pdev->id != ID_ADP5520) { 80 dev_err(&pdev->dev, "only ADP5520 supports Keypad\n"); 81 return -EINVAL; 82 } 83 84 if (!pdata) { 85 dev_err(&pdev->dev, "missing platform data\n"); 86 return -EINVAL; 87 } 88 89 if (!(pdata->rows_en_mask && pdata->cols_en_mask)) 90 return -EINVAL; 91 92 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 93 if (!dev) { 94 dev_err(&pdev->dev, "failed to alloc memory\n"); 95 return -ENOMEM; 96 } 97 98 input = devm_input_allocate_device(&pdev->dev); 99 if (!input) 100 return -ENOMEM; 101 102 dev->master = pdev->dev.parent; 103 dev->input = input; 104 105 input->name = pdev->name; 106 input->phys = "adp5520-keys/input0"; 107 input->dev.parent = &pdev->dev; 108 109 input->id.bustype = BUS_I2C; 110 input->id.vendor = 0x0001; 111 input->id.product = 0x5520; 112 input->id.version = 0x0001; 113 114 input->keycodesize = sizeof(dev->keycode[0]); 115 input->keycodemax = pdata->keymapsize; 116 input->keycode = dev->keycode; 117 118 memcpy(dev->keycode, pdata->keymap, 119 pdata->keymapsize * input->keycodesize); 120 121 /* setup input device */ 122 __set_bit(EV_KEY, input->evbit); 123 124 if (pdata->repeat) 125 __set_bit(EV_REP, input->evbit); 126 127 for (i = 0; i < input->keycodemax; i++) 128 __set_bit(dev->keycode[i], input->keybit); 129 __clear_bit(KEY_RESERVED, input->keybit); 130 131 ret = input_register_device(input); 132 if (ret) { 133 dev_err(&pdev->dev, "unable to register input device\n"); 134 return ret; 135 } 136 137 en_mask = pdata->rows_en_mask | pdata->cols_en_mask; 138 139 ret = adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_1, en_mask); 140 141 if (en_mask & ADP5520_COL_C3) 142 ctl_mask |= ADP5520_C3_MODE; 143 144 if (en_mask & ADP5520_ROW_R3) 145 ctl_mask |= ADP5520_R3_MODE; 146 147 if (ctl_mask) 148 ret |= adp5520_set_bits(dev->master, ADP5520_LED_CONTROL, 149 ctl_mask); 150 151 ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP, 152 pdata->rows_en_mask); 153 154 if (ret) { 155 dev_err(&pdev->dev, "failed to write\n"); 156 return -EIO; 157 } 158 159 dev->notifier.notifier_call = adp5520_keys_notifier; 160 ret = adp5520_register_notifier(dev->master, &dev->notifier, 161 ADP5520_KP_IEN | ADP5520_KR_IEN); 162 if (ret) { 163 dev_err(&pdev->dev, "failed to register notifier\n"); 164 return ret; 165 } 166 167 platform_set_drvdata(pdev, dev); 168 return 0; 169} 170 171static int adp5520_keys_remove(struct platform_device *pdev) 172{ 173 struct adp5520_keys *dev = platform_get_drvdata(pdev); 174 175 adp5520_unregister_notifier(dev->master, &dev->notifier, 176 ADP5520_KP_IEN | ADP5520_KR_IEN); 177 178 return 0; 179} 180 181static struct platform_driver adp5520_keys_driver = { 182 .driver = { 183 .name = "adp5520-keys", 184 }, 185 .probe = adp5520_keys_probe, 186 .remove = adp5520_keys_remove, 187}; 188module_platform_driver(adp5520_keys_driver); 189 190MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 191MODULE_DESCRIPTION("Keys ADP5520 Driver"); 192MODULE_LICENSE("GPL"); 193MODULE_ALIAS("platform:adp5520-keys");