linux/drivers/input/keyboard/cros_ec_keyb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// ChromeOS EC keyboard driver
   3//
   4// Copyright (C) 2012 Google, Inc.
   5//
   6// This driver uses the ChromeOS EC byte-level message-based protocol for
   7// communicating the keyboard state (which keys are pressed) from a keyboard EC
   8// to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
   9// but everything else (including deghosting) is done here.  The main
  10// motivation for this is to keep the EC firmware as simple as possible, since
  11// it cannot be easily upgraded and EC flash/IRAM space is relatively
  12// expensive.
  13
  14#include <linux/module.h>
  15#include <linux/bitops.h>
  16#include <linux/i2c.h>
  17#include <linux/input.h>
  18#include <linux/interrupt.h>
  19#include <linux/kernel.h>
  20#include <linux/notifier.h>
  21#include <linux/platform_device.h>
  22#include <linux/slab.h>
  23#include <linux/sysrq.h>
  24#include <linux/input/matrix_keypad.h>
  25#include <linux/mfd/cros_ec.h>
  26#include <linux/mfd/cros_ec_commands.h>
  27
  28#include <asm/unaligned.h>
  29
  30/*
  31 * @rows: Number of rows in the keypad
  32 * @cols: Number of columns in the keypad
  33 * @row_shift: log2 or number of rows, rounded up
  34 * @keymap_data: Matrix keymap data used to convert to keyscan values
  35 * @ghost_filter: true to enable the matrix key-ghosting filter
  36 * @valid_keys: bitmap of existing keys for each matrix column
  37 * @old_kb_state: bitmap of keys pressed last scan
  38 * @dev: Device pointer
  39 * @ec: Top level ChromeOS device to use to talk to EC
  40 * @idev: The input device for the matrix keys.
  41 * @bs_idev: The input device for non-matrix buttons and switches (or NULL).
  42 * @notifier: interrupt event notifier for transport devices
  43 */
  44struct cros_ec_keyb {
  45        unsigned int rows;
  46        unsigned int cols;
  47        int row_shift;
  48        const struct matrix_keymap_data *keymap_data;
  49        bool ghost_filter;
  50        uint8_t *valid_keys;
  51        uint8_t *old_kb_state;
  52
  53        struct device *dev;
  54        struct cros_ec_device *ec;
  55
  56        struct input_dev *idev;
  57        struct input_dev *bs_idev;
  58        struct notifier_block notifier;
  59};
  60
  61
  62/**
  63 * cros_ec_bs_map - Struct mapping Linux keycodes to EC button/switch bitmap
  64 * #defines
  65 *
  66 * @ev_type: The type of the input event to generate (e.g., EV_KEY).
  67 * @code: A linux keycode
  68 * @bit: A #define like EC_MKBP_POWER_BUTTON or EC_MKBP_LID_OPEN
  69 * @inverted: If the #define and EV_SW have opposite meanings, this is true.
  70 *            Only applicable to switches.
  71 */
  72struct cros_ec_bs_map {
  73        unsigned int ev_type;
  74        unsigned int code;
  75        u8 bit;
  76        bool inverted;
  77};
  78
  79/* cros_ec_keyb_bs - Map EC button/switch #defines into kernel ones */
  80static const struct cros_ec_bs_map cros_ec_keyb_bs[] = {
  81        /* Buttons */
  82        {
  83                .ev_type        = EV_KEY,
  84                .code           = KEY_POWER,
  85                .bit            = EC_MKBP_POWER_BUTTON,
  86        },
  87        {
  88                .ev_type        = EV_KEY,
  89                .code           = KEY_VOLUMEUP,
  90                .bit            = EC_MKBP_VOL_UP,
  91        },
  92        {
  93                .ev_type        = EV_KEY,
  94                .code           = KEY_VOLUMEDOWN,
  95                .bit            = EC_MKBP_VOL_DOWN,
  96        },
  97
  98        /* Switches */
  99        {
 100                .ev_type        = EV_SW,
 101                .code           = SW_LID,
 102                .bit            = EC_MKBP_LID_OPEN,
 103                .inverted       = true,
 104        },
 105        {
 106                .ev_type        = EV_SW,
 107                .code           = SW_TABLET_MODE,
 108                .bit            = EC_MKBP_TABLET_MODE,
 109        },
 110};
 111
 112/*
 113 * Returns true when there is at least one combination of pressed keys that
 114 * results in ghosting.
 115 */
 116static bool cros_ec_keyb_has_ghosting(struct cros_ec_keyb *ckdev, uint8_t *buf)
 117{
 118        int col1, col2, buf1, buf2;
 119        struct device *dev = ckdev->dev;
 120        uint8_t *valid_keys = ckdev->valid_keys;
 121
 122        /*
 123         * Ghosting happens if for any pressed key X there are other keys
 124         * pressed both in the same row and column of X as, for instance,
 125         * in the following diagram:
 126         *
 127         * . . Y . g .
 128         * . . . . . .
 129         * . . . . . .
 130         * . . X . Z .
 131         *
 132         * In this case only X, Y, and Z are pressed, but g appears to be
 133         * pressed too (see Wikipedia).
 134         */
 135        for (col1 = 0; col1 < ckdev->cols; col1++) {
 136                buf1 = buf[col1] & valid_keys[col1];
 137                for (col2 = col1 + 1; col2 < ckdev->cols; col2++) {
 138                        buf2 = buf[col2] & valid_keys[col2];
 139                        if (hweight8(buf1 & buf2) > 1) {
 140                                dev_dbg(dev, "ghost found at: B[%02d]:0x%02x & B[%02d]:0x%02x",
 141                                        col1, buf1, col2, buf2);
 142                                return true;
 143                        }
 144                }
 145        }
 146
 147        return false;
 148}
 149
 150
 151/*
 152 * Compares the new keyboard state to the old one and produces key
 153 * press/release events accordingly.  The keyboard state is 13 bytes (one byte
 154 * per column)
 155 */
 156static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
 157                         uint8_t *kb_state, int len)
 158{
 159        struct input_dev *idev = ckdev->idev;
 160        int col, row;
 161        int new_state;
 162        int old_state;
 163
 164        if (ckdev->ghost_filter && cros_ec_keyb_has_ghosting(ckdev, kb_state)) {
 165                /*
 166                 * Simple-minded solution: ignore this state. The obvious
 167                 * improvement is to only ignore changes to keys involved in
 168                 * the ghosting, but process the other changes.
 169                 */
 170                dev_dbg(ckdev->dev, "ghosting found\n");
 171                return;
 172        }
 173
 174        for (col = 0; col < ckdev->cols; col++) {
 175                for (row = 0; row < ckdev->rows; row++) {
 176                        int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
 177                        const unsigned short *keycodes = idev->keycode;
 178
 179                        new_state = kb_state[col] & (1 << row);
 180                        old_state = ckdev->old_kb_state[col] & (1 << row);
 181                        if (new_state != old_state) {
 182                                dev_dbg(ckdev->dev,
 183                                        "changed: [r%d c%d]: byte %02x\n",
 184                                        row, col, new_state);
 185
 186                                input_report_key(idev, keycodes[pos],
 187                                                 new_state);
 188                        }
 189                }
 190                ckdev->old_kb_state[col] = kb_state[col];
 191        }
 192        input_sync(ckdev->idev);
 193}
 194
 195/**
 196 * cros_ec_keyb_report_bs - Report non-matrixed buttons or switches
 197 *
 198 * This takes a bitmap of buttons or switches from the EC and reports events,
 199 * syncing at the end.
 200 *
 201 * @ckdev: The keyboard device.
 202 * @ev_type: The input event type (e.g., EV_KEY).
 203 * @mask: A bitmap of buttons from the EC.
 204 */
 205static void cros_ec_keyb_report_bs(struct cros_ec_keyb *ckdev,
 206                                   unsigned int ev_type, u32 mask)
 207
 208{
 209        struct input_dev *idev = ckdev->bs_idev;
 210        int i;
 211
 212        for (i = 0; i < ARRAY_SIZE(cros_ec_keyb_bs); i++) {
 213                const struct cros_ec_bs_map *map = &cros_ec_keyb_bs[i];
 214
 215                if (map->ev_type != ev_type)
 216                        continue;
 217
 218                input_event(idev, ev_type, map->code,
 219                            !!(mask & BIT(map->bit)) ^ map->inverted);
 220        }
 221        input_sync(idev);
 222}
 223
 224static int cros_ec_keyb_work(struct notifier_block *nb,
 225                             unsigned long queued_during_suspend, void *_notify)
 226{
 227        struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
 228                                                  notifier);
 229        u32 val;
 230        unsigned int ev_type;
 231
 232        /*
 233         * If not wake enabled, discard key state changes during
 234         * suspend. Switches will be re-checked in
 235         * cros_ec_keyb_resume() to be sure nothing is lost.
 236         */
 237        if (queued_during_suspend && !device_may_wakeup(ckdev->dev))
 238                return NOTIFY_OK;
 239
 240        switch (ckdev->ec->event_data.event_type) {
 241        case EC_MKBP_EVENT_KEY_MATRIX:
 242                pm_wakeup_event(ckdev->dev, 0);
 243
 244                if (ckdev->ec->event_size != ckdev->cols) {
 245                        dev_err(ckdev->dev,
 246                                "Discarded incomplete key matrix event.\n");
 247                        return NOTIFY_OK;
 248                }
 249
 250                cros_ec_keyb_process(ckdev,
 251                                     ckdev->ec->event_data.data.key_matrix,
 252                                     ckdev->ec->event_size);
 253                break;
 254
 255        case EC_MKBP_EVENT_SYSRQ:
 256                pm_wakeup_event(ckdev->dev, 0);
 257
 258                val = get_unaligned_le32(&ckdev->ec->event_data.data.sysrq);
 259                dev_dbg(ckdev->dev, "sysrq code from EC: %#x\n", val);
 260                handle_sysrq(val);
 261                break;
 262
 263        case EC_MKBP_EVENT_BUTTON:
 264        case EC_MKBP_EVENT_SWITCH:
 265                pm_wakeup_event(ckdev->dev, 0);
 266
 267                if (ckdev->ec->event_data.event_type == EC_MKBP_EVENT_BUTTON) {
 268                        val = get_unaligned_le32(
 269                                        &ckdev->ec->event_data.data.buttons);
 270                        ev_type = EV_KEY;
 271                } else {
 272                        val = get_unaligned_le32(
 273                                        &ckdev->ec->event_data.data.switches);
 274                        ev_type = EV_SW;
 275                }
 276                cros_ec_keyb_report_bs(ckdev, ev_type, val);
 277                break;
 278
 279        default:
 280                return NOTIFY_DONE;
 281        }
 282
 283        return NOTIFY_OK;
 284}
 285
 286/*
 287 * Walks keycodes flipping bit in buffer COLUMNS deep where bit is ROW.  Used by
 288 * ghosting logic to ignore NULL or virtual keys.
 289 */
 290static void cros_ec_keyb_compute_valid_keys(struct cros_ec_keyb *ckdev)
 291{
 292        int row, col;
 293        int row_shift = ckdev->row_shift;
 294        unsigned short *keymap = ckdev->idev->keycode;
 295        unsigned short code;
 296
 297        BUG_ON(ckdev->idev->keycodesize != sizeof(*keymap));
 298
 299        for (col = 0; col < ckdev->cols; col++) {
 300                for (row = 0; row < ckdev->rows; row++) {
 301                        code = keymap[MATRIX_SCAN_CODE(row, col, row_shift)];
 302                        if (code && (code != KEY_BATTERY))
 303                                ckdev->valid_keys[col] |= 1 << row;
 304                }
 305                dev_dbg(ckdev->dev, "valid_keys[%02d] = 0x%02x\n",
 306                        col, ckdev->valid_keys[col]);
 307        }
 308}
 309
 310/**
 311 * cros_ec_keyb_info - Wrap the EC command EC_CMD_MKBP_INFO
 312 *
 313 * This wraps the EC_CMD_MKBP_INFO, abstracting out all of the marshalling and
 314 * unmarshalling and different version nonsense into something simple.
 315 *
 316 * @ec_dev: The EC device
 317 * @info_type: Either EC_MKBP_INFO_SUPPORTED or EC_MKBP_INFO_CURRENT.
 318 * @event_type: Either EC_MKBP_EVENT_BUTTON or EC_MKBP_EVENT_SWITCH.  Actually
 319 *              in some cases this could be EC_MKBP_EVENT_KEY_MATRIX or
 320 *              EC_MKBP_EVENT_HOST_EVENT too but we don't use in this driver.
 321 * @result: Where we'll store the result; a union
 322 * @result_size: The size of the result.  Expected to be the size of one of
 323 *               the elements in the union.
 324 *
 325 * Returns 0 if no error or -error upon error.
 326 */
 327static int cros_ec_keyb_info(struct cros_ec_device *ec_dev,
 328                             enum ec_mkbp_info_type info_type,
 329                             enum ec_mkbp_event event_type,
 330                             union ec_response_get_next_data *result,
 331                             size_t result_size)
 332{
 333        struct ec_params_mkbp_info *params;
 334        struct cros_ec_command *msg;
 335        int ret;
 336
 337        msg = kzalloc(sizeof(*msg) + max_t(size_t, result_size,
 338                                           sizeof(*params)), GFP_KERNEL);
 339        if (!msg)
 340                return -ENOMEM;
 341
 342        msg->command = EC_CMD_MKBP_INFO;
 343        msg->version = 1;
 344        msg->outsize = sizeof(*params);
 345        msg->insize = result_size;
 346        params = (struct ec_params_mkbp_info *)msg->data;
 347        params->info_type = info_type;
 348        params->event_type = event_type;
 349
 350        ret = cros_ec_cmd_xfer(ec_dev, msg);
 351        if (ret < 0) {
 352                dev_warn(ec_dev->dev, "Transfer error %d/%d: %d\n",
 353                         (int)info_type, (int)event_type, ret);
 354        } else if (msg->result == EC_RES_INVALID_VERSION) {
 355                /* With older ECs we just return 0 for everything */
 356                memset(result, 0, result_size);
 357                ret = 0;
 358        } else if (msg->result != EC_RES_SUCCESS) {
 359                dev_warn(ec_dev->dev, "Error getting info %d/%d: %d\n",
 360                         (int)info_type, (int)event_type, msg->result);
 361                ret = -EPROTO;
 362        } else if (ret != result_size) {
 363                dev_warn(ec_dev->dev, "Wrong size %d/%d: %d != %zu\n",
 364                         (int)info_type, (int)event_type,
 365                         ret, result_size);
 366                ret = -EPROTO;
 367        } else {
 368                memcpy(result, msg->data, result_size);
 369                ret = 0;
 370        }
 371
 372        kfree(msg);
 373
 374        return ret;
 375}
 376
 377/**
 378 * cros_ec_keyb_query_switches - Query the state of switches and report
 379 *
 380 * This will ask the EC about the current state of switches and report to the
 381 * kernel.  Note that we don't query for buttons because they are more
 382 * transitory and we'll get an update on the next release / press.
 383 *
 384 * @ckdev: The keyboard device
 385 *
 386 * Returns 0 if no error or -error upon error.
 387 */
 388static int cros_ec_keyb_query_switches(struct cros_ec_keyb *ckdev)
 389{
 390        struct cros_ec_device *ec_dev = ckdev->ec;
 391        union ec_response_get_next_data event_data = {};
 392        int ret;
 393
 394        ret = cros_ec_keyb_info(ec_dev, EC_MKBP_INFO_CURRENT,
 395                                EC_MKBP_EVENT_SWITCH, &event_data,
 396                                sizeof(event_data.switches));
 397        if (ret)
 398                return ret;
 399
 400        cros_ec_keyb_report_bs(ckdev, EV_SW,
 401                               get_unaligned_le32(&event_data.switches));
 402
 403        return 0;
 404}
 405
 406/**
 407 * cros_ec_keyb_resume - Resume the keyboard
 408 *
 409 * We use the resume notification as a chance to query the EC for switches.
 410 *
 411 * @dev: The keyboard device
 412 *
 413 * Returns 0 if no error or -error upon error.
 414 */
 415static __maybe_unused int cros_ec_keyb_resume(struct device *dev)
 416{
 417        struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
 418
 419        if (ckdev->bs_idev)
 420                return cros_ec_keyb_query_switches(ckdev);
 421
 422        return 0;
 423}
 424
 425/**
 426 * cros_ec_keyb_register_bs - Register non-matrix buttons/switches
 427 *
 428 * Handles all the bits of the keyboard driver related to non-matrix buttons
 429 * and switches, including asking the EC about which are present and telling
 430 * the kernel to expect them.
 431 *
 432 * If this device has no support for buttons and switches we'll return no error
 433 * but the ckdev->bs_idev will remain NULL when this function exits.
 434 *
 435 * @ckdev: The keyboard device
 436 *
 437 * Returns 0 if no error or -error upon error.
 438 */
 439static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev)
 440{
 441        struct cros_ec_device *ec_dev = ckdev->ec;
 442        struct device *dev = ckdev->dev;
 443        struct input_dev *idev;
 444        union ec_response_get_next_data event_data = {};
 445        const char *phys;
 446        u32 buttons;
 447        u32 switches;
 448        int ret;
 449        int i;
 450
 451        ret = cros_ec_keyb_info(ec_dev, EC_MKBP_INFO_SUPPORTED,
 452                                EC_MKBP_EVENT_BUTTON, &event_data,
 453                                sizeof(event_data.buttons));
 454        if (ret)
 455                return ret;
 456        buttons = get_unaligned_le32(&event_data.buttons);
 457
 458        ret = cros_ec_keyb_info(ec_dev, EC_MKBP_INFO_SUPPORTED,
 459                                EC_MKBP_EVENT_SWITCH, &event_data,
 460                                sizeof(event_data.switches));
 461        if (ret)
 462                return ret;
 463        switches = get_unaligned_le32(&event_data.switches);
 464
 465        if (!buttons && !switches)
 466                return 0;
 467
 468        /*
 469         * We call the non-matrix buttons/switches 'input1', if present.
 470         * Allocate phys before input dev, to ensure correct tear-down
 471         * ordering.
 472         */
 473        phys = devm_kasprintf(dev, GFP_KERNEL, "%s/input1", ec_dev->phys_name);
 474        if (!phys)
 475                return -ENOMEM;
 476
 477        idev = devm_input_allocate_device(dev);
 478        if (!idev)
 479                return -ENOMEM;
 480
 481        idev->name = "cros_ec_buttons";
 482        idev->phys = phys;
 483        __set_bit(EV_REP, idev->evbit);
 484
 485        idev->id.bustype = BUS_VIRTUAL;
 486        idev->id.version = 1;
 487        idev->id.product = 0;
 488        idev->dev.parent = dev;
 489
 490        input_set_drvdata(idev, ckdev);
 491        ckdev->bs_idev = idev;
 492
 493        for (i = 0; i < ARRAY_SIZE(cros_ec_keyb_bs); i++) {
 494                const struct cros_ec_bs_map *map = &cros_ec_keyb_bs[i];
 495
 496                if (buttons & BIT(map->bit))
 497                        input_set_capability(idev, map->ev_type, map->code);
 498        }
 499
 500        ret = cros_ec_keyb_query_switches(ckdev);
 501        if (ret) {
 502                dev_err(dev, "cannot query switches\n");
 503                return ret;
 504        }
 505
 506        ret = input_register_device(ckdev->bs_idev);
 507        if (ret) {
 508                dev_err(dev, "cannot register input device\n");
 509                return ret;
 510        }
 511
 512        return 0;
 513}
 514
 515/**
 516 * cros_ec_keyb_register_bs - Register matrix keys
 517 *
 518 * Handles all the bits of the keyboard driver related to matrix keys.
 519 *
 520 * @ckdev: The keyboard device
 521 *
 522 * Returns 0 if no error or -error upon error.
 523 */
 524static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
 525{
 526        struct cros_ec_device *ec_dev = ckdev->ec;
 527        struct device *dev = ckdev->dev;
 528        struct input_dev *idev;
 529        const char *phys;
 530        int err;
 531
 532        err = matrix_keypad_parse_properties(dev, &ckdev->rows, &ckdev->cols);
 533        if (err)
 534                return err;
 535
 536        ckdev->valid_keys = devm_kzalloc(dev, ckdev->cols, GFP_KERNEL);
 537        if (!ckdev->valid_keys)
 538                return -ENOMEM;
 539
 540        ckdev->old_kb_state = devm_kzalloc(dev, ckdev->cols, GFP_KERNEL);
 541        if (!ckdev->old_kb_state)
 542                return -ENOMEM;
 543
 544        /*
 545         * We call the keyboard matrix 'input0'. Allocate phys before input
 546         * dev, to ensure correct tear-down ordering.
 547         */
 548        phys = devm_kasprintf(dev, GFP_KERNEL, "%s/input0", ec_dev->phys_name);
 549        if (!phys)
 550                return -ENOMEM;
 551
 552        idev = devm_input_allocate_device(dev);
 553        if (!idev)
 554                return -ENOMEM;
 555
 556        idev->name = CROS_EC_DEV_NAME;
 557        idev->phys = phys;
 558        __set_bit(EV_REP, idev->evbit);
 559
 560        idev->id.bustype = BUS_VIRTUAL;
 561        idev->id.version = 1;
 562        idev->id.product = 0;
 563        idev->dev.parent = dev;
 564
 565        ckdev->ghost_filter = of_property_read_bool(dev->of_node,
 566                                        "google,needs-ghost-filter");
 567
 568        err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols,
 569                                         NULL, idev);
 570        if (err) {
 571                dev_err(dev, "cannot build key matrix\n");
 572                return err;
 573        }
 574
 575        ckdev->row_shift = get_count_order(ckdev->cols);
 576
 577        input_set_capability(idev, EV_MSC, MSC_SCAN);
 578        input_set_drvdata(idev, ckdev);
 579        ckdev->idev = idev;
 580        cros_ec_keyb_compute_valid_keys(ckdev);
 581
 582        err = input_register_device(ckdev->idev);
 583        if (err) {
 584                dev_err(dev, "cannot register input device\n");
 585                return err;
 586        }
 587
 588        return 0;
 589}
 590
 591static int cros_ec_keyb_probe(struct platform_device *pdev)
 592{
 593        struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
 594        struct device *dev = &pdev->dev;
 595        struct cros_ec_keyb *ckdev;
 596        int err;
 597
 598        if (!dev->of_node)
 599                return -ENODEV;
 600
 601        ckdev = devm_kzalloc(dev, sizeof(*ckdev), GFP_KERNEL);
 602        if (!ckdev)
 603                return -ENOMEM;
 604
 605        ckdev->ec = ec;
 606        ckdev->dev = dev;
 607        dev_set_drvdata(dev, ckdev);
 608
 609        err = cros_ec_keyb_register_matrix(ckdev);
 610        if (err) {
 611                dev_err(dev, "cannot register matrix inputs: %d\n", err);
 612                return err;
 613        }
 614
 615        err = cros_ec_keyb_register_bs(ckdev);
 616        if (err) {
 617                dev_err(dev, "cannot register non-matrix inputs: %d\n", err);
 618                return err;
 619        }
 620
 621        ckdev->notifier.notifier_call = cros_ec_keyb_work;
 622        err = blocking_notifier_chain_register(&ckdev->ec->event_notifier,
 623                                               &ckdev->notifier);
 624        if (err) {
 625                dev_err(dev, "cannot register notifier: %d\n", err);
 626                return err;
 627        }
 628
 629        device_init_wakeup(ckdev->dev, true);
 630        return 0;
 631}
 632
 633static int cros_ec_keyb_remove(struct platform_device *pdev)
 634{
 635        struct cros_ec_keyb *ckdev = dev_get_drvdata(&pdev->dev);
 636
 637        blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
 638                                           &ckdev->notifier);
 639
 640        return 0;
 641}
 642
 643#ifdef CONFIG_OF
 644static const struct of_device_id cros_ec_keyb_of_match[] = {
 645        { .compatible = "google,cros-ec-keyb" },
 646        {},
 647};
 648MODULE_DEVICE_TABLE(of, cros_ec_keyb_of_match);
 649#endif
 650
 651static SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume);
 652
 653static struct platform_driver cros_ec_keyb_driver = {
 654        .probe = cros_ec_keyb_probe,
 655        .remove = cros_ec_keyb_remove,
 656        .driver = {
 657                .name = "cros-ec-keyb",
 658                .of_match_table = of_match_ptr(cros_ec_keyb_of_match),
 659                .pm = &cros_ec_keyb_pm_ops,
 660        },
 661};
 662
 663module_platform_driver(cros_ec_keyb_driver);
 664
 665MODULE_LICENSE("GPL v2");
 666MODULE_DESCRIPTION("ChromeOS EC keyboard driver");
 667MODULE_ALIAS("platform:cros-ec-keyb");
 668