cros_ec_dev.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /*
  2. * cros_ec_dev - expose the Chrome OS Embedded Controller to user-space
  3. *
  4. * Copyright (C) 2014 Google, Inc.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <linux/fs.h>
  20. #include <linux/mfd/core.h>
  21. #include <linux/module.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/pm.h>
  24. #include <linux/slab.h>
  25. #include <linux/uaccess.h>
  26. #include "cros_ec_debugfs.h"
  27. #include "cros_ec_dev.h"
  28. /* Device variables */
  29. #define CROS_MAX_DEV 128
  30. static int ec_major;
  31. static const struct attribute_group *cros_ec_groups[] = {
  32. &cros_ec_attr_group,
  33. &cros_ec_lightbar_attr_group,
  34. &cros_ec_vbc_attr_group,
  35. NULL,
  36. };
  37. static struct class cros_class = {
  38. .owner = THIS_MODULE,
  39. .name = "chromeos",
  40. .dev_groups = cros_ec_groups,
  41. };
  42. /* Basic communication */
  43. static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
  44. {
  45. struct ec_response_get_version *resp;
  46. static const char * const current_image_name[] = {
  47. "unknown", "read-only", "read-write", "invalid",
  48. };
  49. struct cros_ec_command *msg;
  50. int ret;
  51. msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
  52. if (!msg)
  53. return -ENOMEM;
  54. msg->version = 0;
  55. msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
  56. msg->insize = sizeof(*resp);
  57. msg->outsize = 0;
  58. ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
  59. if (ret < 0)
  60. goto exit;
  61. if (msg->result != EC_RES_SUCCESS) {
  62. snprintf(str, maxlen,
  63. "%s\nUnknown EC version: EC returned %d\n",
  64. CROS_EC_DEV_VERSION, msg->result);
  65. ret = -EINVAL;
  66. goto exit;
  67. }
  68. resp = (struct ec_response_get_version *)msg->data;
  69. if (resp->current_image >= ARRAY_SIZE(current_image_name))
  70. resp->current_image = 3; /* invalid */
  71. snprintf(str, maxlen, "%s\n%s\n%s\n%s\n", CROS_EC_DEV_VERSION,
  72. resp->version_string_ro, resp->version_string_rw,
  73. current_image_name[resp->current_image]);
  74. ret = 0;
  75. exit:
  76. kfree(msg);
  77. return ret;
  78. }
  79. static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
  80. {
  81. struct cros_ec_command *msg;
  82. int ret;
  83. if (ec->features[0] == -1U && ec->features[1] == -1U) {
  84. /* features bitmap not read yet */
  85. msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
  86. if (!msg)
  87. return -ENOMEM;
  88. msg->version = 0;
  89. msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
  90. msg->insize = sizeof(ec->features);
  91. msg->outsize = 0;
  92. ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
  93. if (ret < 0 || msg->result != EC_RES_SUCCESS) {
  94. dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
  95. ret, msg->result);
  96. memset(ec->features, 0, sizeof(ec->features));
  97. }
  98. memcpy(ec->features, msg->data, sizeof(ec->features));
  99. dev_dbg(ec->dev, "EC features %08x %08x\n",
  100. ec->features[0], ec->features[1]);
  101. kfree(msg);
  102. }
  103. return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
  104. }
  105. /* Device file ops */
  106. static int ec_device_open(struct inode *inode, struct file *filp)
  107. {
  108. struct cros_ec_dev *ec = container_of(inode->i_cdev,
  109. struct cros_ec_dev, cdev);
  110. filp->private_data = ec;
  111. nonseekable_open(inode, filp);
  112. return 0;
  113. }
  114. static int ec_device_release(struct inode *inode, struct file *filp)
  115. {
  116. return 0;
  117. }
  118. static ssize_t ec_device_read(struct file *filp, char __user *buffer,
  119. size_t length, loff_t *offset)
  120. {
  121. struct cros_ec_dev *ec = filp->private_data;
  122. char msg[sizeof(struct ec_response_get_version) +
  123. sizeof(CROS_EC_DEV_VERSION)];
  124. size_t count;
  125. int ret;
  126. if (*offset != 0)
  127. return 0;
  128. ret = ec_get_version(ec, msg, sizeof(msg));
  129. if (ret)
  130. return ret;
  131. count = min(length, strlen(msg));
  132. if (copy_to_user(buffer, msg, count))
  133. return -EFAULT;
  134. *offset = count;
  135. return count;
  136. }
  137. /* Ioctls */
  138. static long ec_device_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
  139. {
  140. long ret;
  141. struct cros_ec_command u_cmd;
  142. struct cros_ec_command *s_cmd;
  143. if (copy_from_user(&u_cmd, arg, sizeof(u_cmd)))
  144. return -EFAULT;
  145. if ((u_cmd.outsize > EC_MAX_MSG_BYTES) ||
  146. (u_cmd.insize > EC_MAX_MSG_BYTES))
  147. return -EINVAL;
  148. s_cmd = kmalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
  149. GFP_KERNEL);
  150. if (!s_cmd)
  151. return -ENOMEM;
  152. if (copy_from_user(s_cmd, arg, sizeof(*s_cmd) + u_cmd.outsize)) {
  153. ret = -EFAULT;
  154. goto exit;
  155. }
  156. if (u_cmd.outsize != s_cmd->outsize ||
  157. u_cmd.insize != s_cmd->insize) {
  158. ret = -EINVAL;
  159. goto exit;
  160. }
  161. s_cmd->command += ec->cmd_offset;
  162. ret = cros_ec_cmd_xfer(ec->ec_dev, s_cmd);
  163. /* Only copy data to userland if data was received. */
  164. if (ret < 0)
  165. goto exit;
  166. if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + s_cmd->insize))
  167. ret = -EFAULT;
  168. exit:
  169. kfree(s_cmd);
  170. return ret;
  171. }
  172. static long ec_device_ioctl_readmem(struct cros_ec_dev *ec, void __user *arg)
  173. {
  174. struct cros_ec_device *ec_dev = ec->ec_dev;
  175. struct cros_ec_readmem s_mem = { };
  176. long num;
  177. /* Not every platform supports direct reads */
  178. if (!ec_dev->cmd_readmem)
  179. return -ENOTTY;
  180. if (copy_from_user(&s_mem, arg, sizeof(s_mem)))
  181. return -EFAULT;
  182. num = ec_dev->cmd_readmem(ec_dev, s_mem.offset, s_mem.bytes,
  183. s_mem.buffer);
  184. if (num <= 0)
  185. return num;
  186. if (copy_to_user((void __user *)arg, &s_mem, sizeof(s_mem)))
  187. return -EFAULT;
  188. return 0;
  189. }
  190. static long ec_device_ioctl(struct file *filp, unsigned int cmd,
  191. unsigned long arg)
  192. {
  193. struct cros_ec_dev *ec = filp->private_data;
  194. if (_IOC_TYPE(cmd) != CROS_EC_DEV_IOC)
  195. return -ENOTTY;
  196. switch (cmd) {
  197. case CROS_EC_DEV_IOCXCMD:
  198. return ec_device_ioctl_xcmd(ec, (void __user *)arg);
  199. case CROS_EC_DEV_IOCRDMEM:
  200. return ec_device_ioctl_readmem(ec, (void __user *)arg);
  201. }
  202. return -ENOTTY;
  203. }
  204. /* Module initialization */
  205. static const struct file_operations fops = {
  206. .open = ec_device_open,
  207. .release = ec_device_release,
  208. .read = ec_device_read,
  209. .unlocked_ioctl = ec_device_ioctl,
  210. #ifdef CONFIG_COMPAT
  211. .compat_ioctl = ec_device_ioctl,
  212. #endif
  213. };
  214. static void __remove(struct device *dev)
  215. {
  216. struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
  217. class_dev);
  218. kfree(ec);
  219. }
  220. static void cros_ec_sensors_register(struct cros_ec_dev *ec)
  221. {
  222. /*
  223. * Issue a command to get the number of sensor reported.
  224. * Build an array of sensors driver and register them all.
  225. */
  226. int ret, i, id, sensor_num;
  227. struct mfd_cell *sensor_cells;
  228. struct cros_ec_sensor_platform *sensor_platforms;
  229. int sensor_type[MOTIONSENSE_TYPE_MAX];
  230. struct ec_params_motion_sense *params;
  231. struct ec_response_motion_sense *resp;
  232. struct cros_ec_command *msg;
  233. msg = kzalloc(sizeof(struct cros_ec_command) +
  234. max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
  235. if (msg == NULL)
  236. return;
  237. msg->version = 2;
  238. msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
  239. msg->outsize = sizeof(*params);
  240. msg->insize = sizeof(*resp);
  241. params = (struct ec_params_motion_sense *)msg->data;
  242. params->cmd = MOTIONSENSE_CMD_DUMP;
  243. ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
  244. if (ret < 0 || msg->result != EC_RES_SUCCESS) {
  245. dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
  246. ret, msg->result);
  247. goto error;
  248. }
  249. resp = (struct ec_response_motion_sense *)msg->data;
  250. sensor_num = resp->dump.sensor_count;
  251. /* Allocate 2 extra sensors in case lid angle or FIFO are needed */
  252. sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
  253. GFP_KERNEL);
  254. if (sensor_cells == NULL)
  255. goto error;
  256. sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) *
  257. (sensor_num + 1), GFP_KERNEL);
  258. if (sensor_platforms == NULL)
  259. goto error_platforms;
  260. memset(sensor_type, 0, sizeof(sensor_type));
  261. id = 0;
  262. for (i = 0; i < sensor_num; i++) {
  263. params->cmd = MOTIONSENSE_CMD_INFO;
  264. params->info.sensor_num = i;
  265. ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
  266. if (ret < 0 || msg->result != EC_RES_SUCCESS) {
  267. dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
  268. i, ret, msg->result);
  269. continue;
  270. }
  271. switch (resp->info.type) {
  272. case MOTIONSENSE_TYPE_ACCEL:
  273. sensor_cells[id].name = "cros-ec-accel";
  274. break;
  275. case MOTIONSENSE_TYPE_BARO:
  276. sensor_cells[id].name = "cros-ec-baro";
  277. break;
  278. case MOTIONSENSE_TYPE_GYRO:
  279. sensor_cells[id].name = "cros-ec-gyro";
  280. break;
  281. case MOTIONSENSE_TYPE_MAG:
  282. sensor_cells[id].name = "cros-ec-mag";
  283. break;
  284. case MOTIONSENSE_TYPE_PROX:
  285. sensor_cells[id].name = "cros-ec-prox";
  286. break;
  287. case MOTIONSENSE_TYPE_LIGHT:
  288. sensor_cells[id].name = "cros-ec-light";
  289. break;
  290. case MOTIONSENSE_TYPE_ACTIVITY:
  291. sensor_cells[id].name = "cros-ec-activity";
  292. break;
  293. default:
  294. dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
  295. continue;
  296. }
  297. sensor_platforms[id].sensor_num = i;
  298. sensor_cells[id].id = sensor_type[resp->info.type];
  299. sensor_cells[id].platform_data = &sensor_platforms[id];
  300. sensor_cells[id].pdata_size =
  301. sizeof(struct cros_ec_sensor_platform);
  302. sensor_type[resp->info.type]++;
  303. id++;
  304. }
  305. if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
  306. sensor_platforms[id].sensor_num = sensor_num;
  307. sensor_cells[id].name = "cros-ec-angle";
  308. sensor_cells[id].id = 0;
  309. sensor_cells[id].platform_data = &sensor_platforms[id];
  310. sensor_cells[id].pdata_size =
  311. sizeof(struct cros_ec_sensor_platform);
  312. id++;
  313. }
  314. if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
  315. sensor_cells[id].name = "cros-ec-ring";
  316. id++;
  317. }
  318. ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
  319. NULL, 0, NULL);
  320. if (ret)
  321. dev_err(ec->dev, "failed to add EC sensors\n");
  322. kfree(sensor_platforms);
  323. error_platforms:
  324. kfree(sensor_cells);
  325. error:
  326. kfree(msg);
  327. }
  328. static int ec_device_probe(struct platform_device *pdev)
  329. {
  330. int retval = -ENOMEM;
  331. struct device *dev = &pdev->dev;
  332. struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
  333. struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
  334. if (!ec)
  335. return retval;
  336. dev_set_drvdata(dev, ec);
  337. ec->ec_dev = dev_get_drvdata(dev->parent);
  338. ec->dev = dev;
  339. ec->cmd_offset = ec_platform->cmd_offset;
  340. ec->features[0] = -1U; /* Not cached yet */
  341. ec->features[1] = -1U; /* Not cached yet */
  342. device_initialize(&ec->class_dev);
  343. cdev_init(&ec->cdev, &fops);
  344. /*
  345. * Add the class device
  346. * Link to the character device for creating the /dev entry
  347. * in devtmpfs.
  348. */
  349. ec->class_dev.devt = MKDEV(ec_major, pdev->id);
  350. ec->class_dev.class = &cros_class;
  351. ec->class_dev.parent = dev;
  352. ec->class_dev.release = __remove;
  353. retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
  354. if (retval) {
  355. dev_err(dev, "dev_set_name failed => %d\n", retval);
  356. goto failed;
  357. }
  358. retval = cdev_device_add(&ec->cdev, &ec->class_dev);
  359. if (retval) {
  360. dev_err(dev, "cdev_device_add failed => %d\n", retval);
  361. goto failed;
  362. }
  363. if (cros_ec_debugfs_init(ec))
  364. dev_warn(dev, "failed to create debugfs directory\n");
  365. /* check whether this EC is a sensor hub. */
  366. if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
  367. cros_ec_sensors_register(ec);
  368. /* Take control of the lightbar from the EC. */
  369. lb_manual_suspend_ctrl(ec, 1);
  370. return 0;
  371. failed:
  372. put_device(&ec->class_dev);
  373. return retval;
  374. }
  375. static int ec_device_remove(struct platform_device *pdev)
  376. {
  377. struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
  378. /* Let the EC take over the lightbar again. */
  379. lb_manual_suspend_ctrl(ec, 0);
  380. cros_ec_debugfs_remove(ec);
  381. cdev_del(&ec->cdev);
  382. device_unregister(&ec->class_dev);
  383. return 0;
  384. }
  385. static const struct platform_device_id cros_ec_id[] = {
  386. { "cros-ec-ctl", 0 },
  387. { /* sentinel */ },
  388. };
  389. MODULE_DEVICE_TABLE(platform, cros_ec_id);
  390. static __maybe_unused int ec_device_suspend(struct device *dev)
  391. {
  392. struct cros_ec_dev *ec = dev_get_drvdata(dev);
  393. lb_suspend(ec);
  394. return 0;
  395. }
  396. static __maybe_unused int ec_device_resume(struct device *dev)
  397. {
  398. struct cros_ec_dev *ec = dev_get_drvdata(dev);
  399. lb_resume(ec);
  400. return 0;
  401. }
  402. static const struct dev_pm_ops cros_ec_dev_pm_ops = {
  403. #ifdef CONFIG_PM_SLEEP
  404. .suspend = ec_device_suspend,
  405. .resume = ec_device_resume,
  406. #endif
  407. };
  408. static struct platform_driver cros_ec_dev_driver = {
  409. .driver = {
  410. .name = "cros-ec-ctl",
  411. .pm = &cros_ec_dev_pm_ops,
  412. },
  413. .probe = ec_device_probe,
  414. .remove = ec_device_remove,
  415. };
  416. static int __init cros_ec_dev_init(void)
  417. {
  418. int ret;
  419. dev_t dev = 0;
  420. ret = class_register(&cros_class);
  421. if (ret) {
  422. pr_err(CROS_EC_DEV_NAME ": failed to register device class\n");
  423. return ret;
  424. }
  425. /* Get a range of minor numbers (starting with 0) to work with */
  426. ret = alloc_chrdev_region(&dev, 0, CROS_MAX_DEV, CROS_EC_DEV_NAME);
  427. if (ret < 0) {
  428. pr_err(CROS_EC_DEV_NAME ": alloc_chrdev_region() failed\n");
  429. goto failed_chrdevreg;
  430. }
  431. ec_major = MAJOR(dev);
  432. /* Register the driver */
  433. ret = platform_driver_register(&cros_ec_dev_driver);
  434. if (ret < 0) {
  435. pr_warn(CROS_EC_DEV_NAME ": can't register driver: %d\n", ret);
  436. goto failed_devreg;
  437. }
  438. return 0;
  439. failed_devreg:
  440. unregister_chrdev_region(MKDEV(ec_major, 0), CROS_MAX_DEV);
  441. failed_chrdevreg:
  442. class_unregister(&cros_class);
  443. return ret;
  444. }
  445. static void __exit cros_ec_dev_exit(void)
  446. {
  447. platform_driver_unregister(&cros_ec_dev_driver);
  448. unregister_chrdev(ec_major, CROS_EC_DEV_NAME);
  449. class_unregister(&cros_class);
  450. }
  451. module_init(cros_ec_dev_init);
  452. module_exit(cros_ec_dev_exit);
  453. MODULE_AUTHOR("Bill Richardson <wfrichar@chromium.org>");
  454. MODULE_DESCRIPTION("Userspace interface to the Chrome OS Embedded Controller");
  455. MODULE_VERSION("1.0");
  456. MODULE_LICENSE("GPL");