linux/drivers/input/keyboard/st-keyscan.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * STMicroelectronics Key Scanning driver
   4 *
   5 * Copyright (c) 2014 STMicroelectonics Ltd.
   6 * Author: Stuart Menefy <stuart.menefy@st.com>
   7 *
   8 * Based on sh_keysc.c, copyright 2008 Magnus Damm
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/interrupt.h>
  13#include <linux/platform_device.h>
  14#include <linux/clk.h>
  15#include <linux/io.h>
  16#include <linux/input/matrix_keypad.h>
  17
  18#define ST_KEYSCAN_MAXKEYS 16
  19
  20#define KEYSCAN_CONFIG_OFF              0x0
  21#define KEYSCAN_CONFIG_ENABLE           0x1
  22#define KEYSCAN_DEBOUNCE_TIME_OFF       0x4
  23#define KEYSCAN_MATRIX_STATE_OFF        0x8
  24#define KEYSCAN_MATRIX_DIM_OFF          0xc
  25#define KEYSCAN_MATRIX_DIM_X_SHIFT      0x0
  26#define KEYSCAN_MATRIX_DIM_Y_SHIFT      0x2
  27
  28struct st_keyscan {
  29        void __iomem *base;
  30        int irq;
  31        struct clk *clk;
  32        struct input_dev *input_dev;
  33        unsigned long last_state;
  34        unsigned int n_rows;
  35        unsigned int n_cols;
  36        unsigned int debounce_us;
  37};
  38
  39static irqreturn_t keyscan_isr(int irq, void *dev_id)
  40{
  41        struct st_keyscan *keypad = dev_id;
  42        unsigned short *keycode = keypad->input_dev->keycode;
  43        unsigned long state, change;
  44        int bit_nr;
  45
  46        state = readl(keypad->base + KEYSCAN_MATRIX_STATE_OFF) & 0xffff;
  47        change = keypad->last_state ^ state;
  48        keypad->last_state = state;
  49
  50        for_each_set_bit(bit_nr, &change, BITS_PER_LONG)
  51                input_report_key(keypad->input_dev,
  52                                 keycode[bit_nr], state & BIT(bit_nr));
  53
  54        input_sync(keypad->input_dev);
  55
  56        return IRQ_HANDLED;
  57}
  58
  59static int keyscan_start(struct st_keyscan *keypad)
  60{
  61        int error;
  62
  63        error = clk_enable(keypad->clk);
  64        if (error)
  65                return error;
  66
  67        writel(keypad->debounce_us * (clk_get_rate(keypad->clk) / 1000000),
  68               keypad->base + KEYSCAN_DEBOUNCE_TIME_OFF);
  69
  70        writel(((keypad->n_cols - 1) << KEYSCAN_MATRIX_DIM_X_SHIFT) |
  71               ((keypad->n_rows - 1) << KEYSCAN_MATRIX_DIM_Y_SHIFT),
  72               keypad->base + KEYSCAN_MATRIX_DIM_OFF);
  73
  74        writel(KEYSCAN_CONFIG_ENABLE, keypad->base + KEYSCAN_CONFIG_OFF);
  75
  76        return 0;
  77}
  78
  79static void keyscan_stop(struct st_keyscan *keypad)
  80{
  81        writel(0, keypad->base + KEYSCAN_CONFIG_OFF);
  82
  83        clk_disable(keypad->clk);
  84}
  85
  86static int keyscan_open(struct input_dev *dev)
  87{
  88        struct st_keyscan *keypad = input_get_drvdata(dev);
  89
  90        return keyscan_start(keypad);
  91}
  92
  93static void keyscan_close(struct input_dev *dev)
  94{
  95        struct st_keyscan *keypad = input_get_drvdata(dev);
  96
  97        keyscan_stop(keypad);
  98}
  99
 100static int keypad_matrix_key_parse_dt(struct st_keyscan *keypad_data)
 101{
 102        struct device *dev = keypad_data->input_dev->dev.parent;
 103        struct device_node *np = dev->of_node;
 104        int error;
 105
 106        error = matrix_keypad_parse_properties(dev, &keypad_data->n_rows,
 107                                               &keypad_data->n_cols);
 108        if (error) {
 109                dev_err(dev, "failed to parse keypad params\n");
 110                return error;
 111        }
 112
 113        of_property_read_u32(np, "st,debounce-us", &keypad_data->debounce_us);
 114
 115        dev_dbg(dev, "n_rows=%d n_col=%d debounce=%d\n",
 116                keypad_data->n_rows, keypad_data->n_cols,
 117                keypad_data->debounce_us);
 118
 119        return 0;
 120}
 121
 122static int keyscan_probe(struct platform_device *pdev)
 123{
 124        struct st_keyscan *keypad_data;
 125        struct input_dev *input_dev;
 126        struct resource *res;
 127        int error;
 128
 129        if (!pdev->dev.of_node) {
 130                dev_err(&pdev->dev, "no DT data present\n");
 131                return -EINVAL;
 132        }
 133
 134        keypad_data = devm_kzalloc(&pdev->dev, sizeof(*keypad_data),
 135                                   GFP_KERNEL);
 136        if (!keypad_data)
 137                return -ENOMEM;
 138
 139        input_dev = devm_input_allocate_device(&pdev->dev);
 140        if (!input_dev) {
 141                dev_err(&pdev->dev, "failed to allocate the input device\n");
 142                return -ENOMEM;
 143        }
 144
 145        input_dev->name = pdev->name;
 146        input_dev->phys = "keyscan-keys/input0";
 147        input_dev->dev.parent = &pdev->dev;
 148        input_dev->open = keyscan_open;
 149        input_dev->close = keyscan_close;
 150
 151        input_dev->id.bustype = BUS_HOST;
 152
 153        keypad_data->input_dev = input_dev;
 154
 155        error = keypad_matrix_key_parse_dt(keypad_data);
 156        if (error)
 157                return error;
 158
 159        error = matrix_keypad_build_keymap(NULL, NULL,
 160                                           keypad_data->n_rows,
 161                                           keypad_data->n_cols,
 162                                           NULL, input_dev);
 163        if (error) {
 164                dev_err(&pdev->dev, "failed to build keymap\n");
 165                return error;
 166        }
 167
 168        input_set_drvdata(input_dev, keypad_data);
 169
 170        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 171        keypad_data->base = devm_ioremap_resource(&pdev->dev, res);
 172        if (IS_ERR(keypad_data->base))
 173                return PTR_ERR(keypad_data->base);
 174
 175        keypad_data->clk = devm_clk_get(&pdev->dev, NULL);
 176        if (IS_ERR(keypad_data->clk)) {
 177                dev_err(&pdev->dev, "cannot get clock\n");
 178                return PTR_ERR(keypad_data->clk);
 179        }
 180
 181        error = clk_enable(keypad_data->clk);
 182        if (error) {
 183                dev_err(&pdev->dev, "failed to enable clock\n");
 184                return error;
 185        }
 186
 187        keyscan_stop(keypad_data);
 188
 189        keypad_data->irq = platform_get_irq(pdev, 0);
 190        if (keypad_data->irq < 0)
 191                return -EINVAL;
 192
 193        error = devm_request_irq(&pdev->dev, keypad_data->irq, keyscan_isr, 0,
 194                                 pdev->name, keypad_data);
 195        if (error) {
 196                dev_err(&pdev->dev, "failed to request IRQ\n");
 197                return error;
 198        }
 199
 200        error = input_register_device(input_dev);
 201        if (error) {
 202                dev_err(&pdev->dev, "failed to register input device\n");
 203                return error;
 204        }
 205
 206        platform_set_drvdata(pdev, keypad_data);
 207
 208        device_set_wakeup_capable(&pdev->dev, 1);
 209
 210        return 0;
 211}
 212
 213#ifdef CONFIG_PM_SLEEP
 214static int keyscan_suspend(struct device *dev)
 215{
 216        struct platform_device *pdev = to_platform_device(dev);
 217        struct st_keyscan *keypad = platform_get_drvdata(pdev);
 218        struct input_dev *input = keypad->input_dev;
 219
 220        mutex_lock(&input->mutex);
 221
 222        if (device_may_wakeup(dev))
 223                enable_irq_wake(keypad->irq);
 224        else if (input->users)
 225                keyscan_stop(keypad);
 226
 227        mutex_unlock(&input->mutex);
 228        return 0;
 229}
 230
 231static int keyscan_resume(struct device *dev)
 232{
 233        struct platform_device *pdev = to_platform_device(dev);
 234        struct st_keyscan *keypad = platform_get_drvdata(pdev);
 235        struct input_dev *input = keypad->input_dev;
 236        int retval = 0;
 237
 238        mutex_lock(&input->mutex);
 239
 240        if (device_may_wakeup(dev))
 241                disable_irq_wake(keypad->irq);
 242        else if (input->users)
 243                retval = keyscan_start(keypad);
 244
 245        mutex_unlock(&input->mutex);
 246        return retval;
 247}
 248#endif
 249
 250static SIMPLE_DEV_PM_OPS(keyscan_dev_pm_ops, keyscan_suspend, keyscan_resume);
 251
 252static const struct of_device_id keyscan_of_match[] = {
 253        { .compatible = "st,sti-keyscan" },
 254        { },
 255};
 256MODULE_DEVICE_TABLE(of, keyscan_of_match);
 257
 258static struct platform_driver keyscan_device_driver = {
 259        .probe          = keyscan_probe,
 260        .driver         = {
 261                .name   = "st-keyscan",
 262                .pm     = &keyscan_dev_pm_ops,
 263                .of_match_table = of_match_ptr(keyscan_of_match),
 264        }
 265};
 266
 267module_platform_driver(keyscan_device_driver);
 268
 269MODULE_AUTHOR("Stuart Menefy <stuart.menefy@st.com>");
 270MODULE_DESCRIPTION("STMicroelectronics keyscan device driver");
 271MODULE_LICENSE("GPL");
 272