1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * cros_ec_dev - expose the Chrome OS Embedded Controller to user-space
5 * Copyright (C) 2014 Google, Inc.
9 #include <linux/mfd/core.h>
10 #include <linux/module.h>
11 #include <linux/mod_devicetable.h>
12 #include <linux/of_platform.h>
13 #include <linux/platform_device.h>
15 #include <linux/slab.h>
16 #include <linux/uaccess.h>
18 #include "cros_ec_dev.h"
20 #define DRV_NAME "cros-ec-dev"
22 /* Device variables */
23 #define CROS_MAX_DEV 128
26 static struct class cros_class
= {
31 /* Basic communication */
32 static int ec_get_version(struct cros_ec_dev
*ec
, char *str
, int maxlen
)
34 struct ec_response_get_version
*resp
;
35 static const char * const current_image_name
[] = {
36 "unknown", "read-only", "read-write", "invalid",
38 struct cros_ec_command
*msg
;
41 msg
= kmalloc(sizeof(*msg
) + sizeof(*resp
), GFP_KERNEL
);
46 msg
->command
= EC_CMD_GET_VERSION
+ ec
->cmd_offset
;
47 msg
->insize
= sizeof(*resp
);
50 ret
= cros_ec_cmd_xfer(ec
->ec_dev
, msg
);
54 if (msg
->result
!= EC_RES_SUCCESS
) {
56 "%s\nUnknown EC version: EC returned %d\n",
57 CROS_EC_DEV_VERSION
, msg
->result
);
62 resp
= (struct ec_response_get_version
*)msg
->data
;
63 if (resp
->current_image
>= ARRAY_SIZE(current_image_name
))
64 resp
->current_image
= 3; /* invalid */
66 snprintf(str
, maxlen
, "%s\n%s\n%s\n%s\n", CROS_EC_DEV_VERSION
,
67 resp
->version_string_ro
, resp
->version_string_rw
,
68 current_image_name
[resp
->current_image
]);
76 static int cros_ec_check_features(struct cros_ec_dev
*ec
, int feature
)
78 struct cros_ec_command
*msg
;
81 if (ec
->features
[0] == -1U && ec
->features
[1] == -1U) {
82 /* features bitmap not read yet */
84 msg
= kmalloc(sizeof(*msg
) + sizeof(ec
->features
), GFP_KERNEL
);
89 msg
->command
= EC_CMD_GET_FEATURES
+ ec
->cmd_offset
;
90 msg
->insize
= sizeof(ec
->features
);
93 ret
= cros_ec_cmd_xfer(ec
->ec_dev
, msg
);
94 if (ret
< 0 || msg
->result
!= EC_RES_SUCCESS
) {
95 dev_warn(ec
->dev
, "cannot get EC features: %d/%d\n",
97 memset(ec
->features
, 0, sizeof(ec
->features
));
99 memcpy(ec
->features
, msg
->data
, sizeof(ec
->features
));
102 dev_dbg(ec
->dev
, "EC features %08x %08x\n",
103 ec
->features
[0], ec
->features
[1]);
108 return ec
->features
[feature
/ 32] & EC_FEATURE_MASK_0(feature
);
111 /* Device file ops */
112 static int ec_device_open(struct inode
*inode
, struct file
*filp
)
114 struct cros_ec_dev
*ec
= container_of(inode
->i_cdev
,
115 struct cros_ec_dev
, cdev
);
116 filp
->private_data
= ec
;
117 nonseekable_open(inode
, filp
);
121 static int ec_device_release(struct inode
*inode
, struct file
*filp
)
126 static ssize_t
ec_device_read(struct file
*filp
, char __user
*buffer
,
127 size_t length
, loff_t
*offset
)
129 struct cros_ec_dev
*ec
= filp
->private_data
;
130 char msg
[sizeof(struct ec_response_get_version
) +
131 sizeof(CROS_EC_DEV_VERSION
)];
138 ret
= ec_get_version(ec
, msg
, sizeof(msg
));
142 count
= min(length
, strlen(msg
));
144 if (copy_to_user(buffer
, msg
, count
))
152 static long ec_device_ioctl_xcmd(struct cros_ec_dev
*ec
, void __user
*arg
)
155 struct cros_ec_command u_cmd
;
156 struct cros_ec_command
*s_cmd
;
158 if (copy_from_user(&u_cmd
, arg
, sizeof(u_cmd
)))
161 if ((u_cmd
.outsize
> EC_MAX_MSG_BYTES
) ||
162 (u_cmd
.insize
> EC_MAX_MSG_BYTES
))
165 s_cmd
= kmalloc(sizeof(*s_cmd
) + max(u_cmd
.outsize
, u_cmd
.insize
),
170 if (copy_from_user(s_cmd
, arg
, sizeof(*s_cmd
) + u_cmd
.outsize
)) {
175 if (u_cmd
.outsize
!= s_cmd
->outsize
||
176 u_cmd
.insize
!= s_cmd
->insize
) {
181 s_cmd
->command
+= ec
->cmd_offset
;
182 ret
= cros_ec_cmd_xfer(ec
->ec_dev
, s_cmd
);
183 /* Only copy data to userland if data was received. */
187 if (copy_to_user(arg
, s_cmd
, sizeof(*s_cmd
) + s_cmd
->insize
))
194 static long ec_device_ioctl_readmem(struct cros_ec_dev
*ec
, void __user
*arg
)
196 struct cros_ec_device
*ec_dev
= ec
->ec_dev
;
197 struct cros_ec_readmem s_mem
= { };
200 /* Not every platform supports direct reads */
201 if (!ec_dev
->cmd_readmem
)
204 if (copy_from_user(&s_mem
, arg
, sizeof(s_mem
)))
207 num
= ec_dev
->cmd_readmem(ec_dev
, s_mem
.offset
, s_mem
.bytes
,
212 if (copy_to_user((void __user
*)arg
, &s_mem
, sizeof(s_mem
)))
218 static long ec_device_ioctl(struct file
*filp
, unsigned int cmd
,
221 struct cros_ec_dev
*ec
= filp
->private_data
;
223 if (_IOC_TYPE(cmd
) != CROS_EC_DEV_IOC
)
227 case CROS_EC_DEV_IOCXCMD
:
228 return ec_device_ioctl_xcmd(ec
, (void __user
*)arg
);
229 case CROS_EC_DEV_IOCRDMEM
:
230 return ec_device_ioctl_readmem(ec
, (void __user
*)arg
);
236 /* Module initialization */
237 static const struct file_operations fops
= {
238 .open
= ec_device_open
,
239 .release
= ec_device_release
,
240 .read
= ec_device_read
,
241 .unlocked_ioctl
= ec_device_ioctl
,
243 .compat_ioctl
= ec_device_ioctl
,
247 static void cros_ec_class_release(struct device
*dev
)
249 kfree(to_cros_ec_dev(dev
));
252 static void cros_ec_sensors_register(struct cros_ec_dev
*ec
)
255 * Issue a command to get the number of sensor reported.
256 * Build an array of sensors driver and register them all.
258 int ret
, i
, id
, sensor_num
;
259 struct mfd_cell
*sensor_cells
;
260 struct cros_ec_sensor_platform
*sensor_platforms
;
261 int sensor_type
[MOTIONSENSE_TYPE_MAX
];
262 struct ec_params_motion_sense
*params
;
263 struct ec_response_motion_sense
*resp
;
264 struct cros_ec_command
*msg
;
266 msg
= kzalloc(sizeof(struct cros_ec_command
) +
267 max(sizeof(*params
), sizeof(*resp
)), GFP_KERNEL
);
272 msg
->command
= EC_CMD_MOTION_SENSE_CMD
+ ec
->cmd_offset
;
273 msg
->outsize
= sizeof(*params
);
274 msg
->insize
= sizeof(*resp
);
276 params
= (struct ec_params_motion_sense
*)msg
->data
;
277 params
->cmd
= MOTIONSENSE_CMD_DUMP
;
279 ret
= cros_ec_cmd_xfer(ec
->ec_dev
, msg
);
280 if (ret
< 0 || msg
->result
!= EC_RES_SUCCESS
) {
281 dev_warn(ec
->dev
, "cannot get EC sensor information: %d/%d\n",
286 resp
= (struct ec_response_motion_sense
*)msg
->data
;
287 sensor_num
= resp
->dump
.sensor_count
;
288 /* Allocate 1 extra sensors in FIFO are needed */
289 sensor_cells
= kcalloc(sensor_num
+ 1, sizeof(struct mfd_cell
),
291 if (sensor_cells
== NULL
)
294 sensor_platforms
= kcalloc(sensor_num
+ 1,
295 sizeof(struct cros_ec_sensor_platform
),
297 if (sensor_platforms
== NULL
)
298 goto error_platforms
;
300 memset(sensor_type
, 0, sizeof(sensor_type
));
302 for (i
= 0; i
< sensor_num
; i
++) {
303 params
->cmd
= MOTIONSENSE_CMD_INFO
;
304 params
->info
.sensor_num
= i
;
305 ret
= cros_ec_cmd_xfer(ec
->ec_dev
, msg
);
306 if (ret
< 0 || msg
->result
!= EC_RES_SUCCESS
) {
307 dev_warn(ec
->dev
, "no info for EC sensor %d : %d/%d\n",
308 i
, ret
, msg
->result
);
311 switch (resp
->info
.type
) {
312 case MOTIONSENSE_TYPE_ACCEL
:
313 sensor_cells
[id
].name
= "cros-ec-accel";
315 case MOTIONSENSE_TYPE_BARO
:
316 sensor_cells
[id
].name
= "cros-ec-baro";
318 case MOTIONSENSE_TYPE_GYRO
:
319 sensor_cells
[id
].name
= "cros-ec-gyro";
321 case MOTIONSENSE_TYPE_MAG
:
322 sensor_cells
[id
].name
= "cros-ec-mag";
324 case MOTIONSENSE_TYPE_PROX
:
325 sensor_cells
[id
].name
= "cros-ec-prox";
327 case MOTIONSENSE_TYPE_LIGHT
:
328 sensor_cells
[id
].name
= "cros-ec-light";
330 case MOTIONSENSE_TYPE_ACTIVITY
:
331 sensor_cells
[id
].name
= "cros-ec-activity";
334 dev_warn(ec
->dev
, "unknown type %d\n", resp
->info
.type
);
337 sensor_platforms
[id
].sensor_num
= i
;
338 sensor_cells
[id
].id
= sensor_type
[resp
->info
.type
];
339 sensor_cells
[id
].platform_data
= &sensor_platforms
[id
];
340 sensor_cells
[id
].pdata_size
=
341 sizeof(struct cros_ec_sensor_platform
);
343 sensor_type
[resp
->info
.type
]++;
347 if (sensor_type
[MOTIONSENSE_TYPE_ACCEL
] >= 2)
348 ec
->has_kb_wake_angle
= true;
350 if (cros_ec_check_features(ec
, EC_FEATURE_MOTION_SENSE_FIFO
)) {
351 sensor_cells
[id
].name
= "cros-ec-ring";
355 ret
= mfd_add_devices(ec
->dev
, 0, sensor_cells
, id
,
358 dev_err(ec
->dev
, "failed to add EC sensors\n");
360 kfree(sensor_platforms
);
367 static const struct mfd_cell cros_ec_cec_cells
[] = {
368 { .name
= "cros-ec-cec" }
371 static const struct mfd_cell cros_ec_rtc_cells
[] = {
372 { .name
= "cros-ec-rtc" }
375 static const struct mfd_cell cros_usbpd_charger_cells
[] = {
376 { .name
= "cros-usbpd-charger" },
377 { .name
= "cros-usbpd-logger" },
380 static const struct mfd_cell cros_ec_platform_cells
[] = {
381 { .name
= "cros-ec-debugfs" },
382 { .name
= "cros-ec-lightbar" },
383 { .name
= "cros-ec-sysfs" },
386 static const struct mfd_cell cros_ec_vbc_cells
[] = {
387 { .name
= "cros-ec-vbc" }
390 static int ec_device_probe(struct platform_device
*pdev
)
392 int retval
= -ENOMEM
;
393 struct device_node
*node
;
394 struct device
*dev
= &pdev
->dev
;
395 struct cros_ec_platform
*ec_platform
= dev_get_platdata(dev
);
396 struct cros_ec_dev
*ec
= kzalloc(sizeof(*ec
), GFP_KERNEL
);
401 dev_set_drvdata(dev
, ec
);
402 ec
->ec_dev
= dev_get_drvdata(dev
->parent
);
404 ec
->cmd_offset
= ec_platform
->cmd_offset
;
405 ec
->features
[0] = -1U; /* Not cached yet */
406 ec
->features
[1] = -1U; /* Not cached yet */
407 device_initialize(&ec
->class_dev
);
408 cdev_init(&ec
->cdev
, &fops
);
410 /* Check whether this is actually a Fingerprint MCU rather than an EC */
411 if (cros_ec_check_features(ec
, EC_FEATURE_FINGERPRINT
)) {
412 dev_info(dev
, "CrOS Fingerprint MCU detected.\n");
414 * Help userspace differentiating ECs from FP MCU,
415 * regardless of the probing order.
417 ec_platform
->ec_name
= CROS_EC_DEV_FP_NAME
;
421 * Check whether this is actually an Integrated Sensor Hub (ISH)
424 if (cros_ec_check_features(ec
, EC_FEATURE_ISH
)) {
425 dev_info(dev
, "CrOS ISH MCU detected.\n");
427 * Help userspace differentiating ECs from ISH MCU,
428 * regardless of the probing order.
430 ec_platform
->ec_name
= CROS_EC_DEV_ISH_NAME
;
433 /* Check whether this is actually a Touchpad MCU rather than an EC */
434 if (cros_ec_check_features(ec
, EC_FEATURE_TOUCHPAD
)) {
435 dev_info(dev
, "CrOS Touchpad MCU detected.\n");
437 * Help userspace differentiating ECs from TP MCU,
438 * regardless of the probing order.
440 ec_platform
->ec_name
= CROS_EC_DEV_TP_NAME
;
444 * Add the class device
445 * Link to the character device for creating the /dev entry
448 ec
->class_dev
.devt
= MKDEV(ec_major
, pdev
->id
);
449 ec
->class_dev
.class = &cros_class
;
450 ec
->class_dev
.parent
= dev
;
451 ec
->class_dev
.release
= cros_ec_class_release
;
453 retval
= dev_set_name(&ec
->class_dev
, "%s", ec_platform
->ec_name
);
455 dev_err(dev
, "dev_set_name failed => %d\n", retval
);
459 /* check whether this EC is a sensor hub. */
460 if (cros_ec_check_features(ec
, EC_FEATURE_MOTION_SENSE
))
461 cros_ec_sensors_register(ec
);
463 /* Check whether this EC instance has CEC host command support */
464 if (cros_ec_check_features(ec
, EC_FEATURE_CEC
)) {
465 retval
= mfd_add_devices(ec
->dev
, PLATFORM_DEVID_AUTO
,
467 ARRAY_SIZE(cros_ec_cec_cells
),
471 "failed to add cros-ec-cec device: %d\n",
475 /* Check whether this EC instance has RTC host command support */
476 if (cros_ec_check_features(ec
, EC_FEATURE_RTC
)) {
477 retval
= mfd_add_devices(ec
->dev
, PLATFORM_DEVID_AUTO
,
479 ARRAY_SIZE(cros_ec_rtc_cells
),
483 "failed to add cros-ec-rtc device: %d\n",
487 /* Check whether this EC instance has the PD charge manager */
488 if (cros_ec_check_features(ec
, EC_FEATURE_USB_PD
)) {
489 retval
= mfd_add_devices(ec
->dev
, PLATFORM_DEVID_AUTO
,
490 cros_usbpd_charger_cells
,
491 ARRAY_SIZE(cros_usbpd_charger_cells
),
495 "failed to add cros-usbpd-charger device: %d\n",
499 /* We can now add the sysfs class, we know which parameter to show */
500 retval
= cdev_device_add(&ec
->cdev
, &ec
->class_dev
);
502 dev_err(dev
, "cdev_device_add failed => %d\n", retval
);
506 retval
= mfd_add_devices(ec
->dev
, PLATFORM_DEVID_AUTO
,
507 cros_ec_platform_cells
,
508 ARRAY_SIZE(cros_ec_platform_cells
),
512 "failed to add cros-ec platform devices: %d\n",
515 /* Check whether this EC instance has a VBC NVRAM */
516 node
= ec
->ec_dev
->dev
->of_node
;
517 if (of_property_read_bool(node
, "google,has-vbc-nvram")) {
518 retval
= mfd_add_devices(ec
->dev
, PLATFORM_DEVID_AUTO
,
520 ARRAY_SIZE(cros_ec_vbc_cells
),
523 dev_warn(ec
->dev
, "failed to add VBC devices: %d\n",
530 put_device(&ec
->class_dev
);
534 static int ec_device_remove(struct platform_device
*pdev
)
536 struct cros_ec_dev
*ec
= dev_get_drvdata(&pdev
->dev
);
538 mfd_remove_devices(ec
->dev
);
540 device_unregister(&ec
->class_dev
);
544 static const struct platform_device_id cros_ec_id
[] = {
548 MODULE_DEVICE_TABLE(platform
, cros_ec_id
);
550 static struct platform_driver cros_ec_dev_driver
= {
554 .id_table
= cros_ec_id
,
555 .probe
= ec_device_probe
,
556 .remove
= ec_device_remove
,
559 static int __init
cros_ec_dev_init(void)
564 ret
= class_register(&cros_class
);
566 pr_err(CROS_EC_DEV_NAME
": failed to register device class\n");
570 /* Get a range of minor numbers (starting with 0) to work with */
571 ret
= alloc_chrdev_region(&dev
, 0, CROS_MAX_DEV
, CROS_EC_DEV_NAME
);
573 pr_err(CROS_EC_DEV_NAME
": alloc_chrdev_region() failed\n");
574 goto failed_chrdevreg
;
576 ec_major
= MAJOR(dev
);
578 /* Register the driver */
579 ret
= platform_driver_register(&cros_ec_dev_driver
);
581 pr_warn(CROS_EC_DEV_NAME
": can't register driver: %d\n", ret
);
587 unregister_chrdev_region(MKDEV(ec_major
, 0), CROS_MAX_DEV
);
589 class_unregister(&cros_class
);
593 static void __exit
cros_ec_dev_exit(void)
595 platform_driver_unregister(&cros_ec_dev_driver
);
596 unregister_chrdev(ec_major
, CROS_EC_DEV_NAME
);
597 class_unregister(&cros_class
);
600 module_init(cros_ec_dev_init
);
601 module_exit(cros_ec_dev_exit
);
603 MODULE_ALIAS("platform:" DRV_NAME
);
604 MODULE_AUTHOR("Bill Richardson <wfrichar@chromium.org>");
605 MODULE_DESCRIPTION("Userspace interface to the Chrome OS Embedded Controller");
606 MODULE_VERSION("1.0");
607 MODULE_LICENSE("GPL");