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        ret = cros_ec_check_result(ec, msg);
 170        if (ret)
 171                goto done;
 172
 173        /* Read back args */
 174        args.flags = inb(EC_LPC_ADDR_HOST_ARGS);
 175        args.command_version = inb(EC_LPC_ADDR_HOST_ARGS + 1);
 176        args.data_size = inb(EC_LPC_ADDR_HOST_ARGS + 2);
 177        args.checksum = inb(EC_LPC_ADDR_HOST_ARGS + 3);
 178
 179        if (args.data_size > msg->insize) {
 180                dev_err(ec->dev,
 181                        "packet too long (%d bytes, expected %d)",
 182                        args.data_size, msg->insize);
 183                ret = -ENOSPC;
 184                goto done;
 185        }
 186
 187        /* Start calculating response checksum */
 188        csum = msg->command + args.flags +
 189                args.command_version + args.data_size;
 190
 191        /* Read response and update checksum */
 192        for (i = 0; i < args.data_size; i++) {
 193                msg->data[i] = inb(EC_LPC_ADDR_HOST_PARAM + i);
 194                csum += msg->data[i];
 195        }
 196
 197        /* Verify checksum */
 198        if (args.checksum != (csum & 0xFF)) {
 199                dev_err(ec->dev,
 200                        "bad packet checksum, expected %02x, got %02x\n",
 201                        args.checksum, csum & 0xFF);
 202                ret = -EBADMSG;
 203                goto done;
 204        }
 205
 206        /* Return actual amount of data received */
 207        ret = args.data_size;
 208done:
 209        return ret;
 210}
 211
 212/* Returns num bytes read, or negative on error. Doesn't need locking. */
 213static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
 214                               unsigned int bytes, void *dest)
 215{
 216        int i = offset;
 217        char *s = dest;
 218        int cnt = 0;
 219
 220        if (offset >= EC_MEMMAP_SIZE - bytes)
 221                return -EINVAL;
 222
 223        /* fixed length */
 224        if (bytes) {
 225                for (; cnt < bytes; i++, s++, cnt++)
 226                        *s = inb(EC_LPC_ADDR_MEMMAP + i);
 227                return cnt;
 228        }
 229
 230        /* string */
 231        for (; i < EC_MEMMAP_SIZE; i++, s++) {
 232                *s = inb(EC_LPC_ADDR_MEMMAP + i);
 233                cnt++;
 234                if (!*s)
 235                        break;
 236        }
 237
 238        return cnt;
 239}
 240
 241static int cros_ec_lpc_probe(struct platform_device *pdev)
 242{
 243        struct device *dev = &pdev->dev;
 244        struct cros_ec_device *ec_dev;
 245        int ret;
 246
 247        if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE,
 248                                 dev_name(dev))) {
 249                dev_err(dev, "couldn't reserve memmap region\n");
 250                return -EBUSY;
 251        }
 252
 253        if ((inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) != 'E') ||
 254            (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1) != 'C')) {
 255                dev_err(dev, "EC ID not detected\n");
 256                return -ENODEV;
 257        }
 258
 259        if (!devm_request_region(dev, EC_HOST_CMD_REGION0,
 260                                 EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
 261                dev_err(dev, "couldn't reserve region0\n");
 262                return -EBUSY;
 263        }
 264        if (!devm_request_region(dev, EC_HOST_CMD_REGION1,
 265                                 EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
 266                dev_err(dev, "couldn't reserve region1\n");
 267                return -EBUSY;
 268        }
 269
 270        ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
 271        if (!ec_dev)
 272                return -ENOMEM;
 273
 274        platform_set_drvdata(pdev, ec_dev);
 275        ec_dev->dev = dev;
 276        ec_dev->phys_name = dev_name(dev);
 277        ec_dev->cmd_xfer = cros_ec_cmd_xfer_lpc;
 278        ec_dev->pkt_xfer = cros_ec_pkt_xfer_lpc;
 279        ec_dev->cmd_readmem = cros_ec_lpc_readmem;
 280        ec_dev->din_size = sizeof(struct ec_host_response) +
 281                           sizeof(struct ec_response_get_protocol_info);
 282        ec_dev->dout_size = sizeof(struct ec_host_request);
 283
 284        ret = cros_ec_register(ec_dev);
 285        if (ret) {
 286                dev_err(dev, "couldn't register ec_dev (%d)\n", ret);
 287                return ret;
 288        }
 289
 290        return 0;
 291}
 292
 293static int cros_ec_lpc_remove(struct platform_device *pdev)
 294{
 295        struct cros_ec_device *ec_dev;
 296
 297        ec_dev = platform_get_drvdata(pdev);
 298        cros_ec_remove(ec_dev);
 299
 300        return 0;
 301}
 302
 303static struct dmi_system_id cros_ec_lpc_dmi_table[] __initdata = {
 304        {
 305                /*
 306                 * Today all Chromebooks/boxes ship with Google_* as version and
 307                 * coreboot as bios vendor. No other systems with this
 308                 * combination are known to date.
 309                 */
 310                .matches = {
 311                        DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
 312                        DMI_MATCH(DMI_BIOS_VERSION, "Google_"),
 313                },
 314        },
 315        {
 316                /* x86-link, the Chromebook Pixel. */
 317                .matches = {
 318                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
 319                        DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
 320                },
 321        },
 322        {
 323                /* x86-samus, the Chromebook Pixel 2. */
 324                .matches = {
 325                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
 326                        DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
 327                },
 328        },
 329        {
 330                /* x86-peppy, the Acer C720 Chromebook. */
 331                .matches = {
 332                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 333                        DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
 334                },
 335        },
 336        { /* sentinel */ }
 337};
 338MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
 339
 340static struct platform_driver cros_ec_lpc_driver = {
 341        .driver = {
 342                .name = DRV_NAME,
 343        },
 344        .probe = cros_ec_lpc_probe,
 345        .remove = cros_ec_lpc_remove,
 346};
 347
 348static struct platform_device cros_ec_lpc_device = {
 349        .name = DRV_NAME
 350};
 351
 352static int __init cros_ec_lpc_init(void)
 353{
 354        int ret;
 355
 356        if (!dmi_check_system(cros_ec_lpc_dmi_table)) {
 357                pr_err(DRV_NAME ": unsupported system.\n");
 358                return -ENODEV;
 359        }
 360
 361        /* Register the driver */
 362        ret = platform_driver_register(&cros_ec_lpc_driver);
 363        if (ret) {
 364                pr_err(DRV_NAME ": can't register driver: %d\n", ret);
 365                return ret;
 366        }
 367
 368        /* Register the device, and it'll get hooked up automatically */
 369        ret = platform_device_register(&cros_ec_lpc_device);
 370        if (ret) {
 371                pr_err(DRV_NAME ": can't register device: %d\n", ret);
 372                platform_driver_unregister(&cros_ec_lpc_driver);
 373                return ret;
 374        }
 375
 376        return 0;
 377}
 378
 379static void __exit cros_ec_lpc_exit(void)
 380{
 381        platform_device_unregister(&cros_ec_lpc_device);
 382        platform_driver_unregister(&cros_ec_lpc_driver);
 383}
 384
 385module_init(cros_ec_lpc_init);
 386module_exit(cros_ec_lpc_exit);
 387
 388MODULE_LICENSE("GPL");
 389MODULE_DESCRIPTION("ChromeOS EC LPC driver");
 390