Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: cros_ec: Switch to use the new cros-ec-chardev driver

With the purpose of remove the things that far extends the bounds of
what a MFD was designed to do, instantiate the new platform misc
cros-ec-chardev driver and get rid of all the unneeded code. After this
patch the misc chardev driver is a sub-device of the MFD, and all the
new file operations should be implemented there.

Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
Tested-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Enric Balletbo i Serra and committed by
Lee Jones
459aedb9 eda2e30c

+6 -216
+6 -214
drivers/mfd/cros_ec_dev.c
··· 5 5 * Copyright (C) 2014 Google, Inc. 6 6 */ 7 7 8 - #include <linux/fs.h> 9 8 #include <linux/mfd/core.h> 10 9 #include <linux/mfd/cros_ec.h> 11 10 #include <linux/mfd/cros_ec_commands.h> 12 11 #include <linux/module.h> 13 12 #include <linux/mod_devicetable.h> 14 - #include <linux/platform_data/cros_ec_chardev.h> 15 13 #include <linux/of_platform.h> 16 14 #include <linux/platform_device.h> 17 - #include <linux/pm.h> 15 + #include <linux/platform_data/cros_ec_chardev.h> 18 16 #include <linux/slab.h> 19 - #include <linux/uaccess.h> 20 - 21 17 22 18 #define DRV_NAME "cros-ec-dev" 23 - 24 - /* Device variables */ 25 - #define CROS_MAX_DEV 128 26 - static int ec_major; 27 19 28 20 static struct class cros_class = { 29 21 .owner = THIS_MODULE, 30 22 .name = "chromeos", 31 23 }; 32 - 33 - /* Basic communication */ 34 - static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen) 35 - { 36 - struct ec_response_get_version *resp; 37 - static const char * const current_image_name[] = { 38 - "unknown", "read-only", "read-write", "invalid", 39 - }; 40 - struct cros_ec_command *msg; 41 - int ret; 42 - 43 - msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL); 44 - if (!msg) 45 - return -ENOMEM; 46 - 47 - msg->version = 0; 48 - msg->command = EC_CMD_GET_VERSION + ec->cmd_offset; 49 - msg->insize = sizeof(*resp); 50 - msg->outsize = 0; 51 - 52 - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); 53 - if (ret < 0) 54 - goto exit; 55 - 56 - if (msg->result != EC_RES_SUCCESS) { 57 - snprintf(str, maxlen, 58 - "%s\nUnknown EC version: EC returned %d\n", 59 - CROS_EC_DEV_VERSION, msg->result); 60 - ret = -EINVAL; 61 - goto exit; 62 - } 63 - 64 - resp = (struct ec_response_get_version *)msg->data; 65 - if (resp->current_image >= ARRAY_SIZE(current_image_name)) 66 - resp->current_image = 3; /* invalid */ 67 - 68 - snprintf(str, maxlen, "%s\n%s\n%s\n%s\n", CROS_EC_DEV_VERSION, 69 - resp->version_string_ro, resp->version_string_rw, 70 - current_image_name[resp->current_image]); 71 - 72 - ret = 0; 73 - exit: 74 - kfree(msg); 75 - return ret; 76 - } 77 24 78 25 static int cros_ec_check_features(struct cros_ec_dev *ec, int feature) 79 26 { ··· 56 109 57 110 return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature); 58 111 } 59 - 60 - /* Device file ops */ 61 - static int ec_device_open(struct inode *inode, struct file *filp) 62 - { 63 - struct cros_ec_dev *ec = container_of(inode->i_cdev, 64 - struct cros_ec_dev, cdev); 65 - filp->private_data = ec; 66 - nonseekable_open(inode, filp); 67 - return 0; 68 - } 69 - 70 - static int ec_device_release(struct inode *inode, struct file *filp) 71 - { 72 - return 0; 73 - } 74 - 75 - static ssize_t ec_device_read(struct file *filp, char __user *buffer, 76 - size_t length, loff_t *offset) 77 - { 78 - struct cros_ec_dev *ec = filp->private_data; 79 - char msg[sizeof(struct ec_response_get_version) + 80 - sizeof(CROS_EC_DEV_VERSION)]; 81 - size_t count; 82 - int ret; 83 - 84 - if (*offset != 0) 85 - return 0; 86 - 87 - ret = ec_get_version(ec, msg, sizeof(msg)); 88 - if (ret) 89 - return ret; 90 - 91 - count = min(length, strlen(msg)); 92 - 93 - if (copy_to_user(buffer, msg, count)) 94 - return -EFAULT; 95 - 96 - *offset = count; 97 - return count; 98 - } 99 - 100 - /* Ioctls */ 101 - static long ec_device_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg) 102 - { 103 - long ret; 104 - struct cros_ec_command u_cmd; 105 - struct cros_ec_command *s_cmd; 106 - 107 - if (copy_from_user(&u_cmd, arg, sizeof(u_cmd))) 108 - return -EFAULT; 109 - 110 - if ((u_cmd.outsize > EC_MAX_MSG_BYTES) || 111 - (u_cmd.insize > EC_MAX_MSG_BYTES)) 112 - return -EINVAL; 113 - 114 - s_cmd = kmalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize), 115 - GFP_KERNEL); 116 - if (!s_cmd) 117 - return -ENOMEM; 118 - 119 - if (copy_from_user(s_cmd, arg, sizeof(*s_cmd) + u_cmd.outsize)) { 120 - ret = -EFAULT; 121 - goto exit; 122 - } 123 - 124 - if (u_cmd.outsize != s_cmd->outsize || 125 - u_cmd.insize != s_cmd->insize) { 126 - ret = -EINVAL; 127 - goto exit; 128 - } 129 - 130 - s_cmd->command += ec->cmd_offset; 131 - ret = cros_ec_cmd_xfer(ec->ec_dev, s_cmd); 132 - /* Only copy data to userland if data was received. */ 133 - if (ret < 0) 134 - goto exit; 135 - 136 - if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + s_cmd->insize)) 137 - ret = -EFAULT; 138 - exit: 139 - kfree(s_cmd); 140 - return ret; 141 - } 142 - 143 - static long ec_device_ioctl_readmem(struct cros_ec_dev *ec, void __user *arg) 144 - { 145 - struct cros_ec_device *ec_dev = ec->ec_dev; 146 - struct cros_ec_readmem s_mem = { }; 147 - long num; 148 - 149 - /* Not every platform supports direct reads */ 150 - if (!ec_dev->cmd_readmem) 151 - return -ENOTTY; 152 - 153 - if (copy_from_user(&s_mem, arg, sizeof(s_mem))) 154 - return -EFAULT; 155 - 156 - num = ec_dev->cmd_readmem(ec_dev, s_mem.offset, s_mem.bytes, 157 - s_mem.buffer); 158 - if (num <= 0) 159 - return num; 160 - 161 - if (copy_to_user((void __user *)arg, &s_mem, sizeof(s_mem))) 162 - return -EFAULT; 163 - 164 - return num; 165 - } 166 - 167 - static long ec_device_ioctl(struct file *filp, unsigned int cmd, 168 - unsigned long arg) 169 - { 170 - struct cros_ec_dev *ec = filp->private_data; 171 - 172 - if (_IOC_TYPE(cmd) != CROS_EC_DEV_IOC) 173 - return -ENOTTY; 174 - 175 - switch (cmd) { 176 - case CROS_EC_DEV_IOCXCMD: 177 - return ec_device_ioctl_xcmd(ec, (void __user *)arg); 178 - case CROS_EC_DEV_IOCRDMEM: 179 - return ec_device_ioctl_readmem(ec, (void __user *)arg); 180 - } 181 - 182 - return -ENOTTY; 183 - } 184 - 185 - /* Module initialization */ 186 - static const struct file_operations fops = { 187 - .open = ec_device_open, 188 - .release = ec_device_release, 189 - .read = ec_device_read, 190 - .unlocked_ioctl = ec_device_ioctl, 191 - #ifdef CONFIG_COMPAT 192 - .compat_ioctl = ec_device_ioctl, 193 - #endif 194 - }; 195 112 196 113 static void cros_ec_class_release(struct device *dev) 197 114 { ··· 264 453 }; 265 454 266 455 static const struct mfd_cell cros_ec_platform_cells[] = { 456 + { .name = "cros-ec-chardev" }, 267 457 { .name = "cros-ec-debugfs" }, 268 458 { .name = "cros-ec-lightbar" }, 269 459 { .name = "cros-ec-sysfs" }, ··· 292 480 ec->features[0] = -1U; /* Not cached yet */ 293 481 ec->features[1] = -1U; /* Not cached yet */ 294 482 device_initialize(&ec->class_dev); 295 - cdev_init(&ec->cdev, &fops); 296 483 297 484 /* Check whether this is actually a Fingerprint MCU rather than an EC */ 298 485 if (cros_ec_check_features(ec, EC_FEATURE_FINGERPRINT)) { ··· 338 527 339 528 /* 340 529 * Add the class device 341 - * Link to the character device for creating the /dev entry 342 - * in devtmpfs. 343 530 */ 344 - ec->class_dev.devt = MKDEV(ec_major, pdev->id); 345 531 ec->class_dev.class = &cros_class; 346 532 ec->class_dev.parent = dev; 347 533 ec->class_dev.release = cros_ec_class_release; ··· 348 540 dev_err(dev, "dev_set_name failed => %d\n", retval); 349 541 goto failed; 350 542 } 543 + 544 + retval = device_add(&ec->class_dev); 545 + if (retval) 546 + goto failed; 351 547 352 548 /* check whether this EC is a sensor hub. */ 353 549 if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) ··· 396 584 retval); 397 585 } 398 586 399 - /* We can now add the sysfs class, we know which parameter to show */ 400 - retval = cdev_device_add(&ec->cdev, &ec->class_dev); 401 - if (retval) { 402 - dev_err(dev, "cdev_device_add failed => %d\n", retval); 403 - goto failed; 404 - } 405 - 406 587 retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO, 407 588 cros_ec_platform_cells, 408 589 ARRAY_SIZE(cros_ec_platform_cells), ··· 429 624 struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev); 430 625 431 626 mfd_remove_devices(ec->dev); 432 - cdev_del(&ec->cdev); 433 627 device_unregister(&ec->class_dev); 434 628 return 0; 435 629 } ··· 451 647 static int __init cros_ec_dev_init(void) 452 648 { 453 649 int ret; 454 - dev_t dev = 0; 455 650 456 651 ret = class_register(&cros_class); 457 652 if (ret) { 458 653 pr_err(CROS_EC_DEV_NAME ": failed to register device class\n"); 459 654 return ret; 460 655 } 461 - 462 - /* Get a range of minor numbers (starting with 0) to work with */ 463 - ret = alloc_chrdev_region(&dev, 0, CROS_MAX_DEV, CROS_EC_DEV_NAME); 464 - if (ret < 0) { 465 - pr_err(CROS_EC_DEV_NAME ": alloc_chrdev_region() failed\n"); 466 - goto failed_chrdevreg; 467 - } 468 - ec_major = MAJOR(dev); 469 656 470 657 /* Register the driver */ 471 658 ret = platform_driver_register(&cros_ec_dev_driver); ··· 467 672 return 0; 468 673 469 674 failed_devreg: 470 - unregister_chrdev_region(MKDEV(ec_major, 0), CROS_MAX_DEV); 471 - failed_chrdevreg: 472 675 class_unregister(&cros_class); 473 676 return ret; 474 677 } ··· 474 681 static void __exit cros_ec_dev_exit(void) 475 682 { 476 683 platform_driver_unregister(&cros_ec_dev_driver); 477 - unregister_chrdev(ec_major, CROS_EC_DEV_NAME); 478 684 class_unregister(&cros_class); 479 685 } 480 686
-2
include/linux/mfd/cros_ec.h
··· 192 192 /** 193 193 * struct cros_ec_dev - ChromeOS EC device entry point. 194 194 * @class_dev: Device structure used in sysfs. 195 - * @cdev: Character device structure in /dev. 196 195 * @ec_dev: cros_ec_device structure to talk to the physical device. 197 196 * @dev: Pointer to the platform device. 198 197 * @debug_info: cros_ec_debugfs structure for debugging information. ··· 201 202 */ 202 203 struct cros_ec_dev { 203 204 struct device class_dev; 204 - struct cdev cdev; 205 205 struct cros_ec_device *ec_dev; 206 206 struct device *dev; 207 207 struct cros_ec_debugfs *debug_info;