forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 072de836f53be56a70cecf70b43ae43b7ce17376
kernel/drivers/platform/chrome/cros_ec_lightbar.c
....@@ -1,37 +1,23 @@
1
-/*
2
- * cros_ec_lightbar - expose the Chromebook Pixel lightbar to userspace
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
-
20
-#define pr_fmt(fmt) "cros_ec_lightbar: " fmt
1
+// SPDX-License-Identifier: GPL-2.0+
2
+// Expose the Chromebook Pixel lightbar to userspace
3
+//
4
+// Copyright (C) 2014 Google, Inc.
215
226 #include <linux/ctype.h>
237 #include <linux/delay.h>
248 #include <linux/device.h>
259 #include <linux/fs.h>
2610 #include <linux/kobject.h>
27
-#include <linux/mfd/cros_ec.h>
28
-#include <linux/mfd/cros_ec_commands.h>
2911 #include <linux/module.h>
12
+#include <linux/platform_data/cros_ec_commands.h>
13
+#include <linux/platform_data/cros_ec_proto.h>
3014 #include <linux/platform_device.h>
3115 #include <linux/sched.h>
3216 #include <linux/types.h>
3317 #include <linux/uaccess.h>
3418 #include <linux/slab.h>
19
+
20
+#define DRV_NAME "cros-ec-lightbar"
3521
3622 /* Rate-limit the lightbar interface to prevent DoS. */
3723 static unsigned long lb_interval_jiffies = 50 * HZ / 1000;
....@@ -41,7 +27,6 @@
4127 * If this is true, we won't do anything during suspend/resume.
4228 */
4329 static bool userspace_control;
44
-static struct cros_ec_dev *ec_with_lightbar;
4530
4631 static ssize_t interval_msec_show(struct device *dev,
4732 struct device_attribute *attr, char *buf)
....@@ -131,8 +116,10 @@
131116
132117 param = (struct ec_params_lightbar *)msg->data;
133118 param->cmd = LIGHTBAR_CMD_VERSION;
134
- ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
135
- if (ret < 0) {
119
+ msg->outsize = sizeof(param->cmd);
120
+ msg->result = sizeof(resp->version);
121
+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
122
+ if (ret < 0 && ret != -EINVAL) {
136123 ret = 0;
137124 goto exit;
138125 }
....@@ -208,14 +195,9 @@
208195 if (ret)
209196 goto exit;
210197
211
- ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
198
+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
212199 if (ret < 0)
213200 goto exit;
214
-
215
- if (msg->result != EC_RES_SUCCESS) {
216
- ret = -EINVAL;
217
- goto exit;
218
- }
219201
220202 ret = count;
221203 exit:
....@@ -273,11 +255,8 @@
273255 goto exit;
274256 }
275257
276
- ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
258
+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
277259 if (ret < 0)
278
- goto exit;
279
-
280
- if (msg->result != EC_RES_SUCCESS)
281260 goto exit;
282261
283262 i = 0;
....@@ -320,13 +299,10 @@
320299 if (ret)
321300 goto exit;
322301
323
- ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
324
- if (ret < 0)
325
- goto exit;
326
-
327
- if (msg->result != EC_RES_SUCCESS) {
328
- ret = scnprintf(buf, PAGE_SIZE,
329
- "ERROR: EC returned %d\n", msg->result);
302
+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
303
+ if (ret < 0) {
304
+ ret = scnprintf(buf, PAGE_SIZE, "XFER / EC ERROR %d / %d\n",
305
+ ret, msg->result);
330306 goto exit;
331307 }
332308
....@@ -359,13 +335,10 @@
359335 if (ret)
360336 goto error;
361337
362
- ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
338
+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
363339 if (ret < 0)
364340 goto error;
365
- if (msg->result != EC_RES_SUCCESS) {
366
- ret = -EINVAL;
367
- goto error;
368
- }
341
+
369342 ret = 0;
370343 error:
371344 kfree(msg);
....@@ -373,14 +346,11 @@
373346 return ret;
374347 }
375348
376
-int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable)
349
+static int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable)
377350 {
378351 struct ec_params_lightbar *param;
379352 struct cros_ec_command *msg;
380353 int ret;
381
-
382
- if (ec != ec_with_lightbar)
383
- return 0;
384354
385355 msg = alloc_lightbar_cmd_msg(ec);
386356 if (!msg)
....@@ -395,38 +365,16 @@
395365 if (ret)
396366 goto error;
397367
398
- ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
368
+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
399369 if (ret < 0)
400370 goto error;
401
- if (msg->result != EC_RES_SUCCESS) {
402
- ret = -EINVAL;
403
- goto error;
404
- }
371
+
405372 ret = 0;
406373 error:
407374 kfree(msg);
408375
409376 return ret;
410377 }
411
-EXPORT_SYMBOL(lb_manual_suspend_ctrl);
412
-
413
-int lb_suspend(struct cros_ec_dev *ec)
414
-{
415
- if (userspace_control || ec != ec_with_lightbar)
416
- return 0;
417
-
418
- return lb_send_empty_cmd(ec, LIGHTBAR_CMD_SUSPEND);
419
-}
420
-EXPORT_SYMBOL(lb_suspend);
421
-
422
-int lb_resume(struct cros_ec_dev *ec)
423
-{
424
- if (userspace_control || ec != ec_with_lightbar)
425
- return 0;
426
-
427
- return lb_send_empty_cmd(ec, LIGHTBAR_CMD_RESUME);
428
-}
429
-EXPORT_SYMBOL(lb_resume);
430378
431379 static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
432380 const char *buf, size_t count)
....@@ -462,14 +410,9 @@
462410 if (ret)
463411 goto exit;
464412
465
- ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
413
+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
466414 if (ret < 0)
467415 goto exit;
468
-
469
- if (msg->result != EC_RES_SUCCESS) {
470
- ret = -EINVAL;
471
- goto exit;
472
- }
473416
474417 ret = count;
475418 exit:
....@@ -524,13 +467,9 @@
524467 */
525468 msg->outsize = count + extra_bytes;
526469
527
- ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
470
+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
528471 if (ret < 0)
529472 goto exit;
530
- if (msg->result != EC_RES_SUCCESS) {
531
- ret = -EINVAL;
532
- goto exit;
533
- }
534473
535474 ret = count;
536475 exit:
....@@ -584,36 +523,91 @@
584523 NULL,
585524 };
586525
587
-bool ec_has_lightbar(struct cros_ec_dev *ec)
526
+static struct attribute_group cros_ec_lightbar_attr_group = {
527
+ .name = "lightbar",
528
+ .attrs = __lb_cmds_attrs,
529
+};
530
+
531
+static int cros_ec_lightbar_probe(struct platform_device *pd)
588532 {
589
- return !!get_lightbar_version(ec, NULL, NULL);
533
+ struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
534
+ struct cros_ec_platform *pdata = dev_get_platdata(ec_dev->dev);
535
+ struct device *dev = &pd->dev;
536
+ int ret;
537
+
538
+ /*
539
+ * Only instantiate the lightbar if the EC name is 'cros_ec'. Other EC
540
+ * devices like 'cros_pd' doesn't have a lightbar.
541
+ */
542
+ if (strcmp(pdata->ec_name, CROS_EC_DEV_NAME) != 0)
543
+ return -ENODEV;
544
+
545
+ /*
546
+ * Ask then for the lightbar version, if it's 0 then the 'cros_ec'
547
+ * doesn't have a lightbar.
548
+ */
549
+ if (!get_lightbar_version(ec_dev, NULL, NULL))
550
+ return -ENODEV;
551
+
552
+ /* Take control of the lightbar from the EC. */
553
+ lb_manual_suspend_ctrl(ec_dev, 1);
554
+
555
+ ret = sysfs_create_group(&ec_dev->class_dev.kobj,
556
+ &cros_ec_lightbar_attr_group);
557
+ if (ret < 0)
558
+ dev_err(dev, "failed to create %s attributes. err=%d\n",
559
+ cros_ec_lightbar_attr_group.name, ret);
560
+
561
+ return ret;
590562 }
591563
592
-static umode_t cros_ec_lightbar_attrs_are_visible(struct kobject *kobj,
593
- struct attribute *a, int n)
564
+static int cros_ec_lightbar_remove(struct platform_device *pd)
594565 {
595
- struct device *dev = container_of(kobj, struct device, kobj);
596
- struct cros_ec_dev *ec = to_cros_ec_dev(dev);
597
- struct platform_device *pdev = to_platform_device(ec->dev);
598
- struct cros_ec_platform *pdata = pdev->dev.platform_data;
599
- int is_cros_ec;
566
+ struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
600567
601
- is_cros_ec = strcmp(pdata->ec_name, CROS_EC_DEV_NAME);
568
+ sysfs_remove_group(&ec_dev->class_dev.kobj,
569
+ &cros_ec_lightbar_attr_group);
602570
603
- if (is_cros_ec != 0)
604
- return 0;
571
+ /* Let the EC take over the lightbar again. */
572
+ lb_manual_suspend_ctrl(ec_dev, 0);
605573
606
- /* Only instantiate this stuff if the EC has a lightbar */
607
- if (ec_has_lightbar(ec)) {
608
- ec_with_lightbar = ec;
609
- return a->mode;
610
- }
611574 return 0;
612575 }
613576
614
-struct attribute_group cros_ec_lightbar_attr_group = {
615
- .name = "lightbar",
616
- .attrs = __lb_cmds_attrs,
617
- .is_visible = cros_ec_lightbar_attrs_are_visible,
577
+static int __maybe_unused cros_ec_lightbar_resume(struct device *dev)
578
+{
579
+ struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
580
+
581
+ if (userspace_control)
582
+ return 0;
583
+
584
+ return lb_send_empty_cmd(ec_dev, LIGHTBAR_CMD_RESUME);
585
+}
586
+
587
+static int __maybe_unused cros_ec_lightbar_suspend(struct device *dev)
588
+{
589
+ struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
590
+
591
+ if (userspace_control)
592
+ return 0;
593
+
594
+ return lb_send_empty_cmd(ec_dev, LIGHTBAR_CMD_SUSPEND);
595
+}
596
+
597
+static SIMPLE_DEV_PM_OPS(cros_ec_lightbar_pm_ops,
598
+ cros_ec_lightbar_suspend, cros_ec_lightbar_resume);
599
+
600
+static struct platform_driver cros_ec_lightbar_driver = {
601
+ .driver = {
602
+ .name = DRV_NAME,
603
+ .pm = &cros_ec_lightbar_pm_ops,
604
+ },
605
+ .probe = cros_ec_lightbar_probe,
606
+ .remove = cros_ec_lightbar_remove,
618607 };
619
-EXPORT_SYMBOL(cros_ec_lightbar_attr_group);
608
+
609
+module_platform_driver(cros_ec_lightbar_driver);
610
+
611
+MODULE_LICENSE("GPL");
612
+MODULE_DESCRIPTION("Expose the Chromebook Pixel's lightbar to userspace");
613
+MODULE_ALIAS("platform:" DRV_NAME);