linux/drivers/input/keyboard/iqs62x-keys.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Azoteq IQS620A/621/622/624/625 Keys and Switches
   4 *
   5 * Copyright (C) 2019 Jeff LaBundy <jeff@labundy.com>
   6 */
   7
   8#include <linux/device.h>
   9#include <linux/input.h>
  10#include <linux/kernel.h>
  11#include <linux/mfd/iqs62x.h>
  12#include <linux/module.h>
  13#include <linux/notifier.h>
  14#include <linux/platform_device.h>
  15#include <linux/property.h>
  16#include <linux/regmap.h>
  17#include <linux/slab.h>
  18
  19enum {
  20        IQS62X_SW_HALL_N,
  21        IQS62X_SW_HALL_S,
  22};
  23
  24static const char * const iqs62x_switch_names[] = {
  25        [IQS62X_SW_HALL_N] = "hall-switch-north",
  26        [IQS62X_SW_HALL_S] = "hall-switch-south",
  27};
  28
  29struct iqs62x_switch_desc {
  30        enum iqs62x_event_flag flag;
  31        unsigned int code;
  32        bool enabled;
  33};
  34
  35struct iqs62x_keys_private {
  36        struct iqs62x_core *iqs62x;
  37        struct input_dev *input;
  38        struct notifier_block notifier;
  39        struct iqs62x_switch_desc switches[ARRAY_SIZE(iqs62x_switch_names)];
  40        unsigned int keycode[IQS62X_NUM_KEYS];
  41        unsigned int keycodemax;
  42        u8 interval;
  43};
  44
  45static int iqs62x_keys_parse_prop(struct platform_device *pdev,
  46                                  struct iqs62x_keys_private *iqs62x_keys)
  47{
  48        struct fwnode_handle *child;
  49        unsigned int val;
  50        int ret, i;
  51
  52        ret = device_property_count_u32(&pdev->dev, "linux,keycodes");
  53        if (ret > IQS62X_NUM_KEYS) {
  54                dev_err(&pdev->dev, "Too many keycodes present\n");
  55                return -EINVAL;
  56        } else if (ret < 0) {
  57                dev_err(&pdev->dev, "Failed to count keycodes: %d\n", ret);
  58                return ret;
  59        }
  60        iqs62x_keys->keycodemax = ret;
  61
  62        ret = device_property_read_u32_array(&pdev->dev, "linux,keycodes",
  63                                             iqs62x_keys->keycode,
  64                                             iqs62x_keys->keycodemax);
  65        if (ret) {
  66                dev_err(&pdev->dev, "Failed to read keycodes: %d\n", ret);
  67                return ret;
  68        }
  69
  70        for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) {
  71                child = device_get_named_child_node(&pdev->dev,
  72                                                    iqs62x_switch_names[i]);
  73                if (!child)
  74                        continue;
  75
  76                ret = fwnode_property_read_u32(child, "linux,code", &val);
  77                if (ret) {
  78                        dev_err(&pdev->dev, "Failed to read switch code: %d\n",
  79                                ret);
  80                        return ret;
  81                }
  82                iqs62x_keys->switches[i].code = val;
  83                iqs62x_keys->switches[i].enabled = true;
  84
  85                if (fwnode_property_present(child, "azoteq,use-prox"))
  86                        iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ?
  87                                                         IQS62X_EVENT_HALL_N_P :
  88                                                         IQS62X_EVENT_HALL_S_P);
  89                else
  90                        iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ?
  91                                                         IQS62X_EVENT_HALL_N_T :
  92                                                         IQS62X_EVENT_HALL_S_T);
  93        }
  94
  95        return 0;
  96}
  97
  98static int iqs62x_keys_init(struct iqs62x_keys_private *iqs62x_keys)
  99{
 100        struct iqs62x_core *iqs62x = iqs62x_keys->iqs62x;
 101        enum iqs62x_event_flag flag;
 102        unsigned int event_reg, val;
 103        unsigned int event_mask = 0;
 104        int ret, i;
 105
 106        switch (iqs62x->dev_desc->prod_num) {
 107        case IQS620_PROD_NUM:
 108        case IQS621_PROD_NUM:
 109        case IQS622_PROD_NUM:
 110                event_reg = IQS620_GLBL_EVENT_MASK;
 111
 112                /*
 113                 * Discreet button, hysteresis and SAR UI flags represent keys
 114                 * and are unmasked if mapped to a valid keycode.
 115                 */
 116                for (i = 0; i < iqs62x_keys->keycodemax; i++) {
 117                        if (iqs62x_keys->keycode[i] == KEY_RESERVED)
 118                                continue;
 119
 120                        if (iqs62x_events[i].reg == IQS62X_EVENT_PROX)
 121                                event_mask |= iqs62x->dev_desc->prox_mask;
 122                        else if (iqs62x_events[i].reg == IQS62X_EVENT_HYST)
 123                                event_mask |= (iqs62x->dev_desc->hyst_mask |
 124                                               iqs62x->dev_desc->sar_mask);
 125                }
 126
 127                ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->hall_flags,
 128                                  &val);
 129                if (ret)
 130                        return ret;
 131
 132                /*
 133                 * Hall UI flags represent switches and are unmasked if their
 134                 * corresponding child nodes are present.
 135                 */
 136                for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) {
 137                        if (!(iqs62x_keys->switches[i].enabled))
 138                                continue;
 139
 140                        flag = iqs62x_keys->switches[i].flag;
 141
 142                        if (iqs62x_events[flag].reg != IQS62X_EVENT_HALL)
 143                                continue;
 144
 145                        event_mask |= iqs62x->dev_desc->hall_mask;
 146
 147                        input_report_switch(iqs62x_keys->input,
 148                                            iqs62x_keys->switches[i].code,
 149                                            (val & iqs62x_events[flag].mask) ==
 150                                            iqs62x_events[flag].val);
 151                }
 152
 153                input_sync(iqs62x_keys->input);
 154                break;
 155
 156        case IQS624_PROD_NUM:
 157                event_reg = IQS624_HALL_UI;
 158
 159                /*
 160                 * Interval change events represent keys and are unmasked if
 161                 * either wheel movement flag is mapped to a valid keycode.
 162                 */
 163                if (iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_UP] != KEY_RESERVED)
 164                        event_mask |= IQS624_HALL_UI_INT_EVENT;
 165
 166                if (iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_DN] != KEY_RESERVED)
 167                        event_mask |= IQS624_HALL_UI_INT_EVENT;
 168
 169                ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->interval,
 170                                  &val);
 171                if (ret)
 172                        return ret;
 173
 174                iqs62x_keys->interval = val;
 175                break;
 176
 177        default:
 178                return 0;
 179        }
 180
 181        return regmap_update_bits(iqs62x->regmap, event_reg, event_mask, 0);
 182}
 183
 184static int iqs62x_keys_notifier(struct notifier_block *notifier,
 185                                unsigned long event_flags, void *context)
 186{
 187        struct iqs62x_event_data *event_data = context;
 188        struct iqs62x_keys_private *iqs62x_keys;
 189        int ret, i;
 190
 191        iqs62x_keys = container_of(notifier, struct iqs62x_keys_private,
 192                                   notifier);
 193
 194        if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) {
 195                ret = iqs62x_keys_init(iqs62x_keys);
 196                if (ret) {
 197                        dev_err(iqs62x_keys->input->dev.parent,
 198                                "Failed to re-initialize device: %d\n", ret);
 199                        return NOTIFY_BAD;
 200                }
 201
 202                return NOTIFY_OK;
 203        }
 204
 205        for (i = 0; i < iqs62x_keys->keycodemax; i++) {
 206                if (iqs62x_events[i].reg == IQS62X_EVENT_WHEEL &&
 207                    event_data->interval == iqs62x_keys->interval)
 208                        continue;
 209
 210                input_report_key(iqs62x_keys->input, iqs62x_keys->keycode[i],
 211                                 event_flags & BIT(i));
 212        }
 213
 214        for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++)
 215                if (iqs62x_keys->switches[i].enabled)
 216                        input_report_switch(iqs62x_keys->input,
 217                                            iqs62x_keys->switches[i].code,
 218                                            event_flags &
 219                                            BIT(iqs62x_keys->switches[i].flag));
 220
 221        input_sync(iqs62x_keys->input);
 222
 223        if (event_data->interval == iqs62x_keys->interval)
 224                return NOTIFY_OK;
 225
 226        /*
 227         * Each frame contains at most one wheel event (up or down), in which
 228         * case a complementary release cycle is emulated.
 229         */
 230        if (event_flags & BIT(IQS62X_EVENT_WHEEL_UP)) {
 231                input_report_key(iqs62x_keys->input,
 232                                 iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_UP],
 233                                 0);
 234                input_sync(iqs62x_keys->input);
 235        } else if (event_flags & BIT(IQS62X_EVENT_WHEEL_DN)) {
 236                input_report_key(iqs62x_keys->input,
 237                                 iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_DN],
 238                                 0);
 239                input_sync(iqs62x_keys->input);
 240        }
 241
 242        iqs62x_keys->interval = event_data->interval;
 243
 244        return NOTIFY_OK;
 245}
 246
 247static int iqs62x_keys_probe(struct platform_device *pdev)
 248{
 249        struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent);
 250        struct iqs62x_keys_private *iqs62x_keys;
 251        struct input_dev *input;
 252        int ret, i;
 253
 254        iqs62x_keys = devm_kzalloc(&pdev->dev, sizeof(*iqs62x_keys),
 255                                   GFP_KERNEL);
 256        if (!iqs62x_keys)
 257                return -ENOMEM;
 258
 259        platform_set_drvdata(pdev, iqs62x_keys);
 260
 261        ret = iqs62x_keys_parse_prop(pdev, iqs62x_keys);
 262        if (ret)
 263                return ret;
 264
 265        input = devm_input_allocate_device(&pdev->dev);
 266        if (!input)
 267                return -ENOMEM;
 268
 269        input->keycodemax = iqs62x_keys->keycodemax;
 270        input->keycode = iqs62x_keys->keycode;
 271        input->keycodesize = sizeof(*iqs62x_keys->keycode);
 272
 273        input->name = iqs62x->dev_desc->dev_name;
 274        input->id.bustype = BUS_I2C;
 275
 276        for (i = 0; i < iqs62x_keys->keycodemax; i++)
 277                if (iqs62x_keys->keycode[i] != KEY_RESERVED)
 278                        input_set_capability(input, EV_KEY,
 279                                             iqs62x_keys->keycode[i]);
 280
 281        for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++)
 282                if (iqs62x_keys->switches[i].enabled)
 283                        input_set_capability(input, EV_SW,
 284                                             iqs62x_keys->switches[i].code);
 285
 286        iqs62x_keys->iqs62x = iqs62x;
 287        iqs62x_keys->input = input;
 288
 289        ret = iqs62x_keys_init(iqs62x_keys);
 290        if (ret) {
 291                dev_err(&pdev->dev, "Failed to initialize device: %d\n", ret);
 292                return ret;
 293        }
 294
 295        ret = input_register_device(iqs62x_keys->input);
 296        if (ret) {
 297                dev_err(&pdev->dev, "Failed to register device: %d\n", ret);
 298                return ret;
 299        }
 300
 301        iqs62x_keys->notifier.notifier_call = iqs62x_keys_notifier;
 302        ret = blocking_notifier_chain_register(&iqs62x_keys->iqs62x->nh,
 303                                               &iqs62x_keys->notifier);
 304        if (ret)
 305                dev_err(&pdev->dev, "Failed to register notifier: %d\n", ret);
 306
 307        return ret;
 308}
 309
 310static int iqs62x_keys_remove(struct platform_device *pdev)
 311{
 312        struct iqs62x_keys_private *iqs62x_keys = platform_get_drvdata(pdev);
 313        int ret;
 314
 315        ret = blocking_notifier_chain_unregister(&iqs62x_keys->iqs62x->nh,
 316                                                 &iqs62x_keys->notifier);
 317        if (ret)
 318                dev_err(&pdev->dev, "Failed to unregister notifier: %d\n", ret);
 319
 320        return ret;
 321}
 322
 323static struct platform_driver iqs62x_keys_platform_driver = {
 324        .driver = {
 325                .name = "iqs62x-keys",
 326        },
 327        .probe = iqs62x_keys_probe,
 328        .remove = iqs62x_keys_remove,
 329};
 330module_platform_driver(iqs62x_keys_platform_driver);
 331
 332MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
 333MODULE_DESCRIPTION("Azoteq IQS620A/621/622/624/625 Keys and Switches");
 334MODULE_LICENSE("GPL");
 335MODULE_ALIAS("platform:iqs62x-keys");
 336