linux/drivers/platform/chrome/cros_ec_lpc.c
<<
>>
Prefs
   1/*
   2 * cros_ec_lpc - LPC access to the Chrome OS Embedded Controller
   3 *
   4 * Copyright (C) 2012-2015 Google, Inc
   5 *
   6 * This software is licensed under the terms of the GNU General Public
   7 * License version 2, as published by the Free Software Foundation, and
   8 * may be copied, distributed, and modified under those terms.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * This driver uses the Chrome OS EC byte-level message-based protocol for
  16 * communicating the keyboard state (which keys are pressed) from a keyboard EC
  17 * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
  18 * but everything else (including deghosting) is done here.  The main
  19 * motivation for this is to keep the EC firmware as simple as possible, since
  20 * it cannot be easily upgraded and EC flash/IRAM space is relatively
  21 * expensive.
  22 */
  23
  24#include <linux/acpi.h>
  25#include <linux/dmi.h>
  26#include <linux/delay.h>
  27#include <linux/io.h>
  28#include <linux/mfd/cros_ec.h>
  29#include <linux/mfd/cros_ec_commands.h>
  30#include <linux/mfd/cros_ec_lpc_reg.h>
  31#include <linux/module.h>
  32#include <linux/platform_device.h>
  33#include <linux/printk.h>
  34
  35#define DRV_NAME "cros_ec_lpcs"
  36#define ACPI_DRV_NAME "GOOG0004"
  37
  38static int ec_response_timed_out(void)
  39{
  40        unsigned long one_second = jiffies + HZ;
  41        u8 data;
  42
  43        usleep_range(200, 300);
  44        do {
  45                if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, &data) &
  46                    EC_LPC_STATUS_BUSY_MASK))
  47                        return 0;
  48                usleep_range(100, 200);
  49        } while (time_before(jiffies, one_second));
  50
  51        return 1;
  52}
  53
  54static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
  55                                struct cros_ec_command *msg)
  56{
  57        struct ec_host_request *request;
  58        struct ec_host_response response;
  59        u8 sum;
  60        int ret = 0;
  61        u8 *dout;
  62
  63        ret = cros_ec_prepare_tx(ec, msg);
  64
  65        /* Write buffer */
  66        cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
  67
  68        request = (struct ec_host_request *)ec->dout;
  69
  70        /* Here we go */
  71        sum = EC_COMMAND_PROTOCOL_3;
  72        cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum);
  73
  74        if (ec_response_timed_out()) {
  75                dev_warn(ec->dev, "EC responsed timed out\n");
  76                ret = -EIO;
  77                goto done;
  78        }
  79
  80        /* Check result */
  81        msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum);
  82        ret = cros_ec_check_result(ec, msg);
  83        if (ret)
  84                goto done;
  85
  86        /* Read back response */
  87        dout = (u8 *)&response;
  88        sum = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
  89                                     dout);
  90
  91        msg->result = response.result;
  92
  93        if (response.data_len > msg->insize) {
  94                dev_err(ec->dev,
  95                        "packet too long (%d bytes, expected %d)",
  96                        response.data_len, msg->insize);
  97                ret = -EMSGSIZE;
  98                goto done;
  99        }
 100
 101        /* Read response and process checksum */
 102        sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET +
 103                                      sizeof(response), response.data_len,
 104                                      msg->data);
 105
 106        if (sum) {
 107                dev_err(ec->dev,
 108                        "bad packet checksum %02x\n",
 109                        response.checksum);
 110                ret = -EBADMSG;
 111                goto done;
 112        }
 113
 114        /* Return actual amount of data received */
 115        ret = response.data_len;
 116done:
 117        return ret;
 118}
 119
 120static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
 121                                struct cros_ec_command *msg)
 122{
 123        struct ec_lpc_host_args args;
 124        u8 sum;
 125        int ret = 0;
 126
 127        if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
 128            msg->insize > EC_PROTO2_MAX_PARAM_SIZE) {
 129                dev_err(ec->dev,
 130                        "invalid buffer sizes (out %d, in %d)\n",
 131                        msg->outsize, msg->insize);
 132                return -EINVAL;
 133        }
 134
 135        /* Now actually send the command to the EC and get the result */
 136        args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
 137        args.command_version = msg->version;
 138        args.data_size = msg->outsize;
 139
 140        /* Initialize checksum */
 141        sum = msg->command + args.flags + args.command_version + args.data_size;
 142
 143        /* Copy data and update checksum */
 144        sum += cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
 145                                       msg->data);
 146
 147        /* Finalize checksum and write args */
 148        args.checksum = sum;
 149        cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
 150                                (u8 *)&args);
 151
 152        /* Here we go */
 153        sum = msg->command;
 154        cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum);
 155
 156        if (ec_response_timed_out()) {
 157                dev_warn(ec->dev, "EC responsed timed out\n");
 158                ret = -EIO;
 159                goto done;
 160        }
 161
 162        /* Check result */
 163        msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum);
 164        ret = cros_ec_check_result(ec, msg);
 165        if (ret)
 166                goto done;
 167
 168        /* Read back args */
 169        cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
 170                               (u8 *)&args);
 171
 172        if (args.data_size > msg->insize) {
 173                dev_err(ec->dev,
 174                        "packet too long (%d bytes, expected %d)",
 175                        args.data_size, msg->insize);
 176                ret = -ENOSPC;
 177                goto done;
 178        }
 179
 180        /* Start calculating response checksum */
 181        sum = msg->command + args.flags + args.command_version + args.data_size;
 182
 183        /* Read response and update checksum */
 184        sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PARAM, args.data_size,
 185                                      msg->data);
 186
 187        /* Verify checksum */
 188        if (args.checksum != sum) {
 189                dev_err(ec->dev,
 190                        "bad packet checksum, expected %02x, got %02x\n",
 191                        args.checksum, sum);
 192                ret = -EBADMSG;
 193                goto done;
 194        }
 195
 196        /* Return actual amount of data received */
 197        ret = args.data_size;
 198done:
 199        return ret;
 200}
 201
 202/* Returns num bytes read, or negative on error. Doesn't need locking. */
 203static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
 204                               unsigned int bytes, void *dest)
 205{
 206        int i = offset;
 207        char *s = dest;
 208        int cnt = 0;
 209
 210        if (offset >= EC_MEMMAP_SIZE - bytes)
 211                return -EINVAL;
 212
 213        /* fixed length */
 214        if (bytes) {
 215                cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + offset, bytes, s);
 216                return bytes;
 217        }
 218
 219        /* string */
 220        for (; i < EC_MEMMAP_SIZE; i++, s++) {
 221                cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + i, 1, s);
 222                cnt++;
 223                if (!*s)
 224                        break;
 225        }
 226
 227        return cnt;
 228}
 229
 230static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
 231{
 232        struct cros_ec_device *ec_dev = data;
 233
 234        if (ec_dev->mkbp_event_supported &&
 235            cros_ec_get_next_event(ec_dev, NULL) > 0)
 236                blocking_notifier_call_chain(&ec_dev->event_notifier, 0,
 237                                             ec_dev);
 238}
 239
 240static int cros_ec_lpc_probe(struct platform_device *pdev)
 241{
 242        struct device *dev = &pdev->dev;
 243        struct acpi_device *adev;
 244        acpi_status status;
 245        struct cros_ec_device *ec_dev;
 246        u8 buf[2];
 247        int ret;
 248
 249        if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE,
 250                                 dev_name(dev))) {
 251                dev_err(dev, "couldn't reserve memmap region\n");
 252                return -EBUSY;
 253        }
 254
 255        cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
 256        if (buf[0] != 'E' || buf[1] != 'C') {
 257                dev_err(dev, "EC ID not detected\n");
 258                return -ENODEV;
 259        }
 260
 261        if (!devm_request_region(dev, EC_HOST_CMD_REGION0,
 262                                 EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
 263                dev_err(dev, "couldn't reserve region0\n");
 264                return -EBUSY;
 265        }
 266        if (!devm_request_region(dev, EC_HOST_CMD_REGION1,
 267                                 EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
 268                dev_err(dev, "couldn't reserve region1\n");
 269                return -EBUSY;
 270        }
 271
 272        ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
 273        if (!ec_dev)
 274                return -ENOMEM;
 275
 276        platform_set_drvdata(pdev, ec_dev);
 277        ec_dev->dev = dev;
 278        ec_dev->phys_name = dev_name(dev);
 279        ec_dev->cmd_xfer = cros_ec_cmd_xfer_lpc;
 280        ec_dev->pkt_xfer = cros_ec_pkt_xfer_lpc;
 281        ec_dev->cmd_readmem = cros_ec_lpc_readmem;
 282        ec_dev->din_size = sizeof(struct ec_host_response) +
 283                           sizeof(struct ec_response_get_protocol_info);
 284        ec_dev->dout_size = sizeof(struct ec_host_request);
 285
 286        ret = cros_ec_register(ec_dev);
 287        if (ret) {
 288                dev_err(dev, "couldn't register ec_dev (%d)\n", ret);
 289                return ret;
 290        }
 291
 292        /*
 293         * Connect a notify handler to process MKBP messages if we have a
 294         * companion ACPI device.
 295         */
 296        adev = ACPI_COMPANION(dev);
 297        if (adev) {
 298                status = acpi_install_notify_handler(adev->handle,
 299                                                     ACPI_ALL_NOTIFY,
 300                                                     cros_ec_lpc_acpi_notify,
 301                                                     ec_dev);
 302                if (ACPI_FAILURE(status))
 303                        dev_warn(dev, "Failed to register notifier %08x\n",
 304                                 status);
 305        }
 306
 307        return 0;
 308}
 309
 310static int cros_ec_lpc_remove(struct platform_device *pdev)
 311{
 312        struct cros_ec_device *ec_dev;
 313        struct acpi_device *adev;
 314
 315        adev = ACPI_COMPANION(&pdev->dev);
 316        if (adev)
 317                acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
 318                                           cros_ec_lpc_acpi_notify);
 319
 320        ec_dev = platform_get_drvdata(pdev);
 321        cros_ec_remove(ec_dev);
 322
 323        return 0;
 324}
 325
 326static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
 327        { ACPI_DRV_NAME, 0 },
 328        { }
 329};
 330MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids);
 331
 332static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = {
 333        {
 334                /*
 335                 * Today all Chromebooks/boxes ship with Google_* as version and
 336                 * coreboot as bios vendor. No other systems with this
 337                 * combination are known to date.
 338                 */
 339                .matches = {
 340                        DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
 341                        DMI_MATCH(DMI_BIOS_VERSION, "Google_"),
 342                },
 343        },
 344        {
 345                /* x86-link, the Chromebook Pixel. */
 346                .matches = {
 347                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
 348                        DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
 349                },
 350        },
 351        {
 352                /* x86-samus, the Chromebook Pixel 2. */
 353                .matches = {
 354                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
 355                        DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
 356                },
 357        },
 358        {
 359                /* x86-peppy, the Acer C720 Chromebook. */
 360                .matches = {
 361                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 362                        DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
 363                },
 364        },
 365        { /* sentinel */ }
 366};
 367MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
 368
 369#ifdef CONFIG_PM_SLEEP
 370static int cros_ec_lpc_suspend(struct device *dev)
 371{
 372        struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
 373
 374        return cros_ec_suspend(ec_dev);
 375}
 376
 377static int cros_ec_lpc_resume(struct device *dev)
 378{
 379        struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
 380
 381        return cros_ec_resume(ec_dev);
 382}
 383#endif
 384
 385const struct dev_pm_ops cros_ec_lpc_pm_ops = {
 386        SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_lpc_suspend, cros_ec_lpc_resume)
 387};
 388
 389static struct platform_driver cros_ec_lpc_driver = {
 390        .driver = {
 391                .name = DRV_NAME,
 392                .acpi_match_table = cros_ec_lpc_acpi_device_ids,
 393                .pm = &cros_ec_lpc_pm_ops,
 394        },
 395        .probe = cros_ec_lpc_probe,
 396        .remove = cros_ec_lpc_remove,
 397};
 398
 399static int __init cros_ec_lpc_init(void)
 400{
 401        int ret;
 402
 403        if (!dmi_check_system(cros_ec_lpc_dmi_table)) {
 404                pr_err(DRV_NAME ": unsupported system.\n");
 405                return -ENODEV;
 406        }
 407
 408        cros_ec_lpc_reg_init();
 409
 410        /* Register the driver */
 411        ret = platform_driver_register(&cros_ec_lpc_driver);
 412        if (ret) {
 413                pr_err(DRV_NAME ": can't register driver: %d\n", ret);
 414                cros_ec_lpc_reg_destroy();
 415                return ret;
 416        }
 417
 418        return 0;
 419}
 420
 421static void __exit cros_ec_lpc_exit(void)
 422{
 423        platform_driver_unregister(&cros_ec_lpc_driver);
 424        cros_ec_lpc_reg_destroy();
 425}
 426
 427module_init(cros_ec_lpc_init);
 428module_exit(cros_ec_lpc_exit);
 429
 430MODULE_LICENSE("GPL");
 431MODULE_DESCRIPTION("ChromeOS EC LPC driver");
 432