0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/acpi.h>
0015 #include <linux/dmi.h>
0016 #include <linux/delay.h>
0017 #include <linux/io.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/module.h>
0020 #include <linux/platform_data/cros_ec_commands.h>
0021 #include <linux/platform_data/cros_ec_proto.h>
0022 #include <linux/platform_device.h>
0023 #include <linux/printk.h>
0024 #include <linux/suspend.h>
0025
0026 #include "cros_ec.h"
0027 #include "cros_ec_lpc_mec.h"
0028
0029 #define DRV_NAME "cros_ec_lpcs"
0030 #define ACPI_DRV_NAME "GOOG0004"
0031
0032
0033 static bool cros_ec_lpc_acpi_device_found;
0034
0035
0036
0037
0038
0039
0040
0041
0042 struct lpc_driver_ops {
0043 u8 (*read)(unsigned int offset, unsigned int length, u8 *dest);
0044 u8 (*write)(unsigned int offset, unsigned int length, const u8 *msg);
0045 };
0046
0047 static struct lpc_driver_ops cros_ec_lpc_ops = { };
0048
0049
0050
0051
0052
0053 static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
0054 u8 *dest)
0055 {
0056 int sum = 0;
0057 int i;
0058
0059 for (i = 0; i < length; ++i) {
0060 dest[i] = inb(offset + i);
0061 sum += dest[i];
0062 }
0063
0064
0065 return sum;
0066 }
0067
0068
0069
0070
0071
0072 static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
0073 const u8 *msg)
0074 {
0075 int sum = 0;
0076 int i;
0077
0078 for (i = 0; i < length; ++i) {
0079 outb(msg[i], offset + i);
0080 sum += msg[i];
0081 }
0082
0083
0084 return sum;
0085 }
0086
0087
0088
0089
0090
0091 static u8 cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
0092 u8 *dest)
0093 {
0094 int in_range = cros_ec_lpc_mec_in_range(offset, length);
0095
0096 if (in_range < 0)
0097 return 0;
0098
0099 return in_range ?
0100 cros_ec_lpc_io_bytes_mec(MEC_IO_READ,
0101 offset - EC_HOST_CMD_REGION0,
0102 length, dest) :
0103 cros_ec_lpc_read_bytes(offset, length, dest);
0104 }
0105
0106
0107
0108
0109
0110 static u8 cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length,
0111 const u8 *msg)
0112 {
0113 int in_range = cros_ec_lpc_mec_in_range(offset, length);
0114
0115 if (in_range < 0)
0116 return 0;
0117
0118 return in_range ?
0119 cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE,
0120 offset - EC_HOST_CMD_REGION0,
0121 length, (u8 *)msg) :
0122 cros_ec_lpc_write_bytes(offset, length, msg);
0123 }
0124
0125 static int ec_response_timed_out(void)
0126 {
0127 unsigned long one_second = jiffies + HZ;
0128 u8 data;
0129
0130 usleep_range(200, 300);
0131 do {
0132 if (!(cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data) &
0133 EC_LPC_STATUS_BUSY_MASK))
0134 return 0;
0135 usleep_range(100, 200);
0136 } while (time_before(jiffies, one_second));
0137
0138 return 1;
0139 }
0140
0141 static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
0142 struct cros_ec_command *msg)
0143 {
0144 struct ec_host_response response;
0145 u8 sum;
0146 int ret = 0;
0147 u8 *dout;
0148
0149 ret = cros_ec_prepare_tx(ec, msg);
0150 if (ret < 0)
0151 goto done;
0152
0153
0154 cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
0155
0156
0157 sum = EC_COMMAND_PROTOCOL_3;
0158 cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
0159
0160 if (ec_response_timed_out()) {
0161 dev_warn(ec->dev, "EC response timed out\n");
0162 ret = -EIO;
0163 goto done;
0164 }
0165
0166
0167 msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
0168 ret = cros_ec_check_result(ec, msg);
0169 if (ret)
0170 goto done;
0171
0172
0173 dout = (u8 *)&response;
0174 sum = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
0175 dout);
0176
0177 msg->result = response.result;
0178
0179 if (response.data_len > msg->insize) {
0180 dev_err(ec->dev,
0181 "packet too long (%d bytes, expected %d)",
0182 response.data_len, msg->insize);
0183 ret = -EMSGSIZE;
0184 goto done;
0185 }
0186
0187
0188 sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET +
0189 sizeof(response), response.data_len,
0190 msg->data);
0191
0192 if (sum) {
0193 dev_err(ec->dev,
0194 "bad packet checksum %02x\n",
0195 response.checksum);
0196 ret = -EBADMSG;
0197 goto done;
0198 }
0199
0200
0201 ret = response.data_len;
0202 done:
0203 return ret;
0204 }
0205
0206 static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
0207 struct cros_ec_command *msg)
0208 {
0209 struct ec_lpc_host_args args;
0210 u8 sum;
0211 int ret = 0;
0212
0213 if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
0214 msg->insize > EC_PROTO2_MAX_PARAM_SIZE) {
0215 dev_err(ec->dev,
0216 "invalid buffer sizes (out %d, in %d)\n",
0217 msg->outsize, msg->insize);
0218 return -EINVAL;
0219 }
0220
0221
0222 args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
0223 args.command_version = msg->version;
0224 args.data_size = msg->outsize;
0225
0226
0227 sum = msg->command + args.flags + args.command_version + args.data_size;
0228
0229
0230 sum += cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
0231 msg->data);
0232
0233
0234 args.checksum = sum;
0235 cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
0236 (u8 *)&args);
0237
0238
0239 sum = msg->command;
0240 cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
0241
0242 if (ec_response_timed_out()) {
0243 dev_warn(ec->dev, "EC response timed out\n");
0244 ret = -EIO;
0245 goto done;
0246 }
0247
0248
0249 msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
0250 ret = cros_ec_check_result(ec, msg);
0251 if (ret)
0252 goto done;
0253
0254
0255 cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args);
0256
0257 if (args.data_size > msg->insize) {
0258 dev_err(ec->dev,
0259 "packet too long (%d bytes, expected %d)",
0260 args.data_size, msg->insize);
0261 ret = -ENOSPC;
0262 goto done;
0263 }
0264
0265
0266 sum = msg->command + args.flags + args.command_version + args.data_size;
0267
0268
0269 sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size,
0270 msg->data);
0271
0272
0273 if (args.checksum != sum) {
0274 dev_err(ec->dev,
0275 "bad packet checksum, expected %02x, got %02x\n",
0276 args.checksum, sum);
0277 ret = -EBADMSG;
0278 goto done;
0279 }
0280
0281
0282 ret = args.data_size;
0283 done:
0284 return ret;
0285 }
0286
0287
0288 static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
0289 unsigned int bytes, void *dest)
0290 {
0291 int i = offset;
0292 char *s = dest;
0293 int cnt = 0;
0294
0295 if (offset >= EC_MEMMAP_SIZE - bytes)
0296 return -EINVAL;
0297
0298
0299 if (bytes) {
0300 cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + offset, bytes, s);
0301 return bytes;
0302 }
0303
0304
0305 for (; i < EC_MEMMAP_SIZE; i++, s++) {
0306 cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + i, 1, s);
0307 cnt++;
0308 if (!*s)
0309 break;
0310 }
0311
0312 return cnt;
0313 }
0314
0315 static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
0316 {
0317 struct cros_ec_device *ec_dev = data;
0318 bool ec_has_more_events;
0319 int ret;
0320
0321 ec_dev->last_event_time = cros_ec_get_time_ns();
0322
0323 if (ec_dev->mkbp_event_supported)
0324 do {
0325 ret = cros_ec_get_next_event(ec_dev, NULL,
0326 &ec_has_more_events);
0327 if (ret > 0)
0328 blocking_notifier_call_chain(
0329 &ec_dev->event_notifier, 0,
0330 ec_dev);
0331 } while (ec_has_more_events);
0332
0333 if (value == ACPI_NOTIFY_DEVICE_WAKE)
0334 pm_system_wakeup();
0335 }
0336
0337 static int cros_ec_lpc_probe(struct platform_device *pdev)
0338 {
0339 struct device *dev = &pdev->dev;
0340 struct acpi_device *adev;
0341 acpi_status status;
0342 struct cros_ec_device *ec_dev;
0343 u8 buf[2];
0344 int irq, ret;
0345
0346
0347
0348
0349
0350
0351 if (!devm_request_region(dev, EC_HOST_CMD_REGION0,
0352 EC_HOST_CMD_MEC_REGION_SIZE, dev_name(dev))) {
0353 dev_err(dev, "couldn't reserve MEC region\n");
0354 return -EBUSY;
0355 }
0356
0357
0358
0359
0360
0361
0362
0363 cros_ec_lpc_ops.read = cros_ec_lpc_mec_read_bytes;
0364 cros_ec_lpc_ops.write = cros_ec_lpc_mec_write_bytes;
0365 cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
0366 if (buf[0] != 'E' || buf[1] != 'C') {
0367 if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE,
0368 dev_name(dev))) {
0369 dev_err(dev, "couldn't reserve memmap region\n");
0370 return -EBUSY;
0371 }
0372
0373
0374 cros_ec_lpc_ops.read = cros_ec_lpc_read_bytes;
0375 cros_ec_lpc_ops.write = cros_ec_lpc_write_bytes;
0376 cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2,
0377 buf);
0378 if (buf[0] != 'E' || buf[1] != 'C') {
0379 dev_err(dev, "EC ID not detected\n");
0380 return -ENODEV;
0381 }
0382
0383
0384 if (!devm_request_region(dev, EC_HOST_CMD_REGION0 + EC_HOST_CMD_MEC_REGION_SIZE,
0385 EC_HOST_CMD_REGION_SIZE - EC_HOST_CMD_MEC_REGION_SIZE,
0386 dev_name(dev))) {
0387 dev_err(dev, "couldn't reserve remainder of region0\n");
0388 return -EBUSY;
0389 }
0390 if (!devm_request_region(dev, EC_HOST_CMD_REGION1,
0391 EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
0392 dev_err(dev, "couldn't reserve region1\n");
0393 return -EBUSY;
0394 }
0395 }
0396
0397 ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
0398 if (!ec_dev)
0399 return -ENOMEM;
0400
0401 platform_set_drvdata(pdev, ec_dev);
0402 ec_dev->dev = dev;
0403 ec_dev->phys_name = dev_name(dev);
0404 ec_dev->cmd_xfer = cros_ec_cmd_xfer_lpc;
0405 ec_dev->pkt_xfer = cros_ec_pkt_xfer_lpc;
0406 ec_dev->cmd_readmem = cros_ec_lpc_readmem;
0407 ec_dev->din_size = sizeof(struct ec_host_response) +
0408 sizeof(struct ec_response_get_protocol_info);
0409 ec_dev->dout_size = sizeof(struct ec_host_request);
0410
0411
0412
0413
0414
0415 irq = platform_get_irq_optional(pdev, 0);
0416 if (irq > 0)
0417 ec_dev->irq = irq;
0418 else if (irq != -ENXIO) {
0419 dev_err(dev, "couldn't retrieve IRQ number (%d)\n", irq);
0420 return irq;
0421 }
0422
0423 ret = cros_ec_register(ec_dev);
0424 if (ret) {
0425 dev_err(dev, "couldn't register ec_dev (%d)\n", ret);
0426 return ret;
0427 }
0428
0429
0430
0431
0432
0433 adev = ACPI_COMPANION(dev);
0434 if (adev) {
0435 status = acpi_install_notify_handler(adev->handle,
0436 ACPI_ALL_NOTIFY,
0437 cros_ec_lpc_acpi_notify,
0438 ec_dev);
0439 if (ACPI_FAILURE(status))
0440 dev_warn(dev, "Failed to register notifier %08x\n",
0441 status);
0442 }
0443
0444 return 0;
0445 }
0446
0447 static int cros_ec_lpc_remove(struct platform_device *pdev)
0448 {
0449 struct cros_ec_device *ec_dev = platform_get_drvdata(pdev);
0450 struct acpi_device *adev;
0451
0452 adev = ACPI_COMPANION(&pdev->dev);
0453 if (adev)
0454 acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
0455 cros_ec_lpc_acpi_notify);
0456
0457 cros_ec_unregister(ec_dev);
0458
0459 return 0;
0460 }
0461
0462 static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
0463 { ACPI_DRV_NAME, 0 },
0464 { }
0465 };
0466 MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids);
0467
0468 static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = {
0469 {
0470
0471
0472
0473
0474
0475 .matches = {
0476 DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
0477 DMI_MATCH(DMI_BIOS_VERSION, "Google_"),
0478 },
0479 },
0480 {
0481
0482
0483
0484
0485
0486
0487 .matches = {
0488 DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
0489 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
0490 },
0491 },
0492 {
0493
0494 .matches = {
0495 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
0496 DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
0497 },
0498 },
0499 {
0500
0501 .matches = {
0502 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
0503 DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
0504 },
0505 },
0506 {
0507
0508 .matches = {
0509 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
0510 DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
0511 },
0512 },
0513 {
0514
0515 .matches = {
0516 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
0517 DMI_MATCH(DMI_PRODUCT_NAME, "Glimmer"),
0518 },
0519 },
0520
0521 {
0522
0523 .matches = {
0524 DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
0525 DMI_MATCH(DMI_PRODUCT_NAME, "Laptop"),
0526 },
0527 },
0528 { }
0529 };
0530 MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
0531
0532 #ifdef CONFIG_PM_SLEEP
0533 static int cros_ec_lpc_suspend(struct device *dev)
0534 {
0535 struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
0536
0537 return cros_ec_suspend(ec_dev);
0538 }
0539
0540 static int cros_ec_lpc_resume(struct device *dev)
0541 {
0542 struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
0543
0544 return cros_ec_resume(ec_dev);
0545 }
0546 #endif
0547
0548 static const struct dev_pm_ops cros_ec_lpc_pm_ops = {
0549 SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_lpc_suspend, cros_ec_lpc_resume)
0550 };
0551
0552 static struct platform_driver cros_ec_lpc_driver = {
0553 .driver = {
0554 .name = DRV_NAME,
0555 .acpi_match_table = cros_ec_lpc_acpi_device_ids,
0556 .pm = &cros_ec_lpc_pm_ops,
0557 },
0558 .probe = cros_ec_lpc_probe,
0559 .remove = cros_ec_lpc_remove,
0560 };
0561
0562 static struct platform_device cros_ec_lpc_device = {
0563 .name = DRV_NAME
0564 };
0565
0566 static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level,
0567 void *context, void **retval)
0568 {
0569 *(bool *)context = true;
0570 return AE_CTRL_TERMINATE;
0571 }
0572
0573 static int __init cros_ec_lpc_init(void)
0574 {
0575 int ret;
0576 acpi_status status;
0577
0578 status = acpi_get_devices(ACPI_DRV_NAME, cros_ec_lpc_parse_device,
0579 &cros_ec_lpc_acpi_device_found, NULL);
0580 if (ACPI_FAILURE(status))
0581 pr_warn(DRV_NAME ": Looking for %s failed\n", ACPI_DRV_NAME);
0582
0583 if (!cros_ec_lpc_acpi_device_found &&
0584 !dmi_check_system(cros_ec_lpc_dmi_table)) {
0585 pr_err(DRV_NAME ": unsupported system.\n");
0586 return -ENODEV;
0587 }
0588
0589 cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0,
0590 EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE);
0591
0592
0593 ret = platform_driver_register(&cros_ec_lpc_driver);
0594 if (ret) {
0595 pr_err(DRV_NAME ": can't register driver: %d\n", ret);
0596 cros_ec_lpc_mec_destroy();
0597 return ret;
0598 }
0599
0600 if (!cros_ec_lpc_acpi_device_found) {
0601
0602 ret = platform_device_register(&cros_ec_lpc_device);
0603 if (ret) {
0604 pr_err(DRV_NAME ": can't register device: %d\n", ret);
0605 platform_driver_unregister(&cros_ec_lpc_driver);
0606 cros_ec_lpc_mec_destroy();
0607 }
0608 }
0609
0610 return ret;
0611 }
0612
0613 static void __exit cros_ec_lpc_exit(void)
0614 {
0615 if (!cros_ec_lpc_acpi_device_found)
0616 platform_device_unregister(&cros_ec_lpc_device);
0617 platform_driver_unregister(&cros_ec_lpc_driver);
0618 cros_ec_lpc_mec_destroy();
0619 }
0620
0621 module_init(cros_ec_lpc_init);
0622 module_exit(cros_ec_lpc_exit);
0623
0624 MODULE_LICENSE("GPL");
0625 MODULE_DESCRIPTION("ChromeOS EC LPC driver");