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/dmi.h>
  25#include <linux/delay.h>
  26#include <linux/io.h>
  27#include <linux/mfd/cros_ec.h>
  28#include <linux/mfd/cros_ec_commands.h>
  29#include <linux/module.h>
  30#include <linux/platform_device.h>
  31#include <linux/printk.h>
  32
  33#define DRV_NAME "cros_ec_lpc"
  34
  35static int ec_response_timed_out(void)
  36{
  37        unsigned long one_second = jiffies + HZ;
  38
  39        usleep_range(200, 300);
  40        do {
  41                if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK))
  42                        return 0;
  43                usleep_range(100, 200);
  44        } while (time_before(jiffies, one_second));
  45
  46        return 1;
  47}
  48
  49static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
  50                                struct cros_ec_command *msg)
  51{
  52        struct ec_host_request *request;
  53        struct ec_host_response response;
  54        u8 sum = 0;
  55        int i;
  56        int ret = 0;
  57        u8 *dout;
  58
  59        ret = cros_ec_prepare_tx(ec, msg);
  60
  61        /* Write buffer */
  62        for (i = 0; i < ret; i++)
  63                outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i);
  64
  65        request = (struct ec_host_request *)ec->dout;
  66
  67        /* Here we go */
  68        outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
  69
  70        if (ec_response_timed_out()) {
  71                dev_warn(ec->dev, "EC responsed timed out\n");
  72                ret = -EIO;
  73                goto done;
  74        }
  75
  76        /* Check result */
  77        msg->result = inb(EC_LPC_ADDR_HOST_DATA);
  78        ret = cros_ec_check_result(ec, msg);
  79        if (ret)
  80                goto done;
  81
  82        /* Read back response */
  83        dout = (u8 *)&response;
  84        for (i = 0; i < sizeof(response); i++) {
  85                dout[i] = inb(EC_LPC_ADDR_HOST_PACKET + i);
  86                sum += dout[i];
  87        }
  88
  89        msg->result = response.result;
  90
  91        if (response.data_len > msg->insize) {
  92                dev_err(ec->dev,
  93                        "packet too long (%d bytes, expected %d)",
  94                        response.data_len, msg->insize);
  95                ret = -EMSGSIZE;
  96                goto done;
  97        }
  98
  99        /* Read response and process checksum */
 100        for (i = 0; i < response.data_len; i++) {
 101                msg->data[i] =
 102                        inb(EC_LPC_ADDR_HOST_PACKET + sizeof(response) + i);
 103                sum += msg->data[i];
 104        }
 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        int csum;
 125        int i;
 126        int ret = 0;
 127
 128        if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
 129            msg->insize > EC_PROTO2_MAX_PARAM_SIZE) {
 130                dev_err(ec->dev,
 131                        "invalid buffer sizes (out %d, in %d)\n",
 132                        msg->outsize, msg->insize);
 133                return -EINVAL;
 134        }
 135
 136        /* Now actually send the command to the EC and get the result */
 137        args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
 138        args.command_version = msg->version;
 139        args.data_size = msg->outsize;
 140
 141        /* Initialize checksum */
 142        csum = msg->command + args.flags +
 143                args.command_version + args.data_size;
 144
 145        /* Copy data and update checksum */
 146        for (i = 0; i < msg->outsize; i++) {
 147                outb(msg->data[i], EC_LPC_ADDR_HOST_PARAM + i);
 148                csum += msg->data[i];
 149        }
 150
 151        /* Finalize checksum and write args */
 152        args.checksum = csum & 0xFF;
 153        outb(args.flags, EC_LPC_ADDR_HOST_ARGS);
 154        outb(args.command_version, EC_LPC_ADDR_HOST_ARGS + 1);
 155        outb(args.data_size, EC_LPC_ADDR_HOST_ARGS + 2);
 156        outb(args.checksum, EC_LPC_ADDR_HOST_ARGS + 3);
 157
 158        /* Here we go */
 159        outb(msg->command, EC_LPC_ADDR_HOST_CMD);
 160
 161        if (ec_response_timed_out()) {
 162                dev_warn(ec->dev, "EC responsed timed out\n");
 163                ret = -EIO;
 164                goto done;
 165        }
 166
 167        /* Check result */
 168        msg->result = inb(EC_LPC_ADDR_HOST_DATA);
 169
 170        switch (msg->result) {
 171        case EC_RES_SUCCESS:
 172                break;
 173        case EC_RES_IN_PROGRESS:
 174                ret = -EAGAIN;
 175                dev_dbg(ec->dev, "command 0x%02x in progress\n",
 176                        msg->command);
 177                goto done;
 178        default:
 179                dev_dbg(ec->dev, "command 0x%02x returned %d\n",
 180                        msg->command, msg->result);
 181        }
 182
 183        /* Read back args */
 184        args.flags = inb(EC_LPC_ADDR_HOST_ARGS);
 185        args.command_version = inb(EC_LPC_ADDR_HOST_ARGS + 1);
 186        args.data_size = inb(EC_LPC_ADDR_HOST_ARGS + 2);
 187        args.checksum = inb(EC_LPC_ADDR_HOST_ARGS + 3);
 188
 189        if (args.data_size > msg->insize) {
 190                dev_err(ec->dev,
 191                        "packet too long (%d bytes, expected %d)",
 192                        args.data_size, msg->insize);
 193                ret = -ENOSPC;
 194                goto done;
 195        }
 196
 197        /* Start calculating response checksum */
 198        csum = msg->command + args.flags +
 199                args.command_version + args.data_size;
 200
 201        /* Read response and update checksum */
 202        for (i = 0; i < args.data_size; i++) {
 203                msg->data[i] = inb(EC_LPC_ADDR_HOST_PARAM + i);
 204                csum += msg->data[i];
 205        }
 206
 207        /* Verify checksum */
 208        if (args.checksum != (csum & 0xFF)) {
 209                dev_err(ec->dev,
 210                        "bad packet checksum, expected %02x, got %02x\n",
 211                        args.checksum, csum & 0xFF);
 212                ret = -EBADMSG;
 213                goto done;
 214        }
 215
 216        /* Return actual amount of data received */
 217        ret = args.data_size;
 218done:
 219        return ret;
 220}
 221
 222/* Returns num bytes read, or negative on error. Doesn't need locking. */
 223static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
 224                               unsigned int bytes, void *dest)
 225{
 226        int i = offset;
 227        char *s = dest;
 228        int cnt = 0;
 229
 230        if (offset >= EC_MEMMAP_SIZE - bytes)
 231                return -EINVAL;
 232
 233        /* fixed length */
 234        if (bytes) {
 235                for (; cnt < bytes; i++, s++, cnt++)
 236                        *s = inb(EC_LPC_ADDR_MEMMAP + i);
 237                return cnt;
 238        }
 239
 240        /* string */
 241        for (; i < EC_MEMMAP_SIZE; i++, s++) {
 242                *s = inb(EC_LPC_ADDR_MEMMAP + i);
 243                cnt++;
 244                if (!*s)
 245                        break;
 246        }
 247
 248        return cnt;
 249}
 250
 251static int cros_ec_lpc_probe(struct platform_device *pdev)
 252{
 253        struct device *dev = &pdev->dev;
 254        struct cros_ec_device *ec_dev;
 255        int ret;
 256
 257        if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE,
 258                                 dev_name(dev))) {
 259                dev_err(dev, "couldn't reserve memmap region\n");
 260                return -EBUSY;
 261        }
 262
 263        if ((inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) != 'E') ||
 264            (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1) != 'C')) {
 265                dev_err(dev, "EC ID not detected\n");
 266                return -ENODEV;
 267        }
 268
 269        if (!devm_request_region(dev, EC_HOST_CMD_REGION0,
 270                                 EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
 271                dev_err(dev, "couldn't reserve region0\n");
 272                return -EBUSY;
 273        }
 274        if (!devm_request_region(dev, EC_HOST_CMD_REGION1,
 275                                 EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
 276                dev_err(dev, "couldn't reserve region1\n");
 277                return -EBUSY;
 278        }
 279
 280        ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
 281        if (!ec_dev)
 282                return -ENOMEM;
 283
 284        platform_set_drvdata(pdev, ec_dev);
 285        ec_dev->dev = dev;
 286        ec_dev->phys_name = dev_name(dev);
 287        ec_dev->cmd_xfer = cros_ec_cmd_xfer_lpc;
 288        ec_dev->pkt_xfer = cros_ec_pkt_xfer_lpc;
 289        ec_dev->cmd_readmem = cros_ec_lpc_readmem;
 290        ec_dev->din_size = sizeof(struct ec_host_response) +
 291                           sizeof(struct ec_response_get_protocol_info);
 292        ec_dev->dout_size = sizeof(struct ec_host_request);
 293
 294        ret = cros_ec_register(ec_dev);
 295        if (ret) {
 296                dev_err(dev, "couldn't register ec_dev (%d)\n", ret);
 297                return ret;
 298        }
 299
 300        return 0;
 301}
 302
 303static int cros_ec_lpc_remove(struct platform_device *pdev)
 304{
 305        struct cros_ec_device *ec_dev;
 306
 307        ec_dev = platform_get_drvdata(pdev);
 308        cros_ec_remove(ec_dev);
 309
 310        return 0;
 311}
 312
 313static struct dmi_system_id cros_ec_lpc_dmi_table[] __initdata = {
 314        {
 315                /*
 316                 * Today all Chromebooks/boxes ship with Google_* as version and
 317                 * coreboot as bios vendor. No other systems with this
 318                 * combination are known to date.
 319                 */
 320                .matches = {
 321                        DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
 322                        DMI_MATCH(DMI_BIOS_VERSION, "Google_"),
 323                },
 324        },
 325        {
 326                /* x86-link, the Chromebook Pixel. */
 327                .matches = {
 328                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
 329                        DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
 330                },
 331        },
 332        {
 333                /* x86-peppy, the Acer C720 Chromebook. */
 334                .matches = {
 335                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 336                        DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
 337                },
 338        },
 339        { /* sentinel */ }
 340};
 341MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
 342
 343static struct platform_driver cros_ec_lpc_driver = {
 344        .driver = {
 345                .name = DRV_NAME,
 346        },
 347        .probe = cros_ec_lpc_probe,
 348        .remove = cros_ec_lpc_remove,
 349};
 350
 351static struct platform_device cros_ec_lpc_device = {
 352        .name = DRV_NAME
 353};
 354
 355static int __init cros_ec_lpc_init(void)
 356{
 357        int ret;
 358
 359        if (!dmi_check_system(cros_ec_lpc_dmi_table)) {
 360                pr_err(DRV_NAME ": unsupported system.\n");
 361                return -ENODEV;
 362        }
 363
 364        /* Register the driver */
 365        ret = platform_driver_register(&cros_ec_lpc_driver);
 366        if (ret) {
 367                pr_err(DRV_NAME ": can't register driver: %d\n", ret);
 368                return ret;
 369        }
 370
 371        /* Register the device, and it'll get hooked up automatically */
 372        ret = platform_device_register(&cros_ec_lpc_device);
 373        if (ret) {
 374                pr_err(DRV_NAME ": can't register device: %d\n", ret);
 375                platform_driver_unregister(&cros_ec_lpc_driver);
 376                return ret;
 377        }
 378
 379        return 0;
 380}
 381
 382static void __exit cros_ec_lpc_exit(void)
 383{
 384        platform_device_unregister(&cros_ec_lpc_device);
 385        platform_driver_unregister(&cros_ec_lpc_driver);
 386}
 387
 388module_init(cros_ec_lpc_init);
 389module_exit(cros_ec_lpc_exit);
 390
 391MODULE_LICENSE("GPL");
 392MODULE_DESCRIPTION("ChromeOS EC LPC driver");
 393