Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / drivers / mfd / cros_ec_dev.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * cros_ec_dev - expose the Chrome OS Embedded Controller to user-space
4  *
5  * Copyright (C) 2014 Google, Inc.
6  */
7
8 #include <linux/mfd/core.h>
9 #include <linux/mfd/cros_ec.h>
10 #include <linux/module.h>
11 #include <linux/mod_devicetable.h>
12 #include <linux/of_platform.h>
13 #include <linux/platform_device.h>
14 #include <linux/platform_data/cros_ec_chardev.h>
15 #include <linux/platform_data/cros_ec_commands.h>
16 #include <linux/platform_data/cros_ec_proto.h>
17 #include <linux/slab.h>
18
19 #define DRV_NAME "cros-ec-dev"
20
21 static struct class cros_class = {
22         .owner          = THIS_MODULE,
23         .name           = "chromeos",
24 };
25
26 /**
27  * cros_feature_to_name - CrOS feature id to name/short description.
28  * @id: The feature identifier.
29  * @name: Device name associated with the feature id.
30  * @desc: Short name that will be displayed.
31  */
32 struct cros_feature_to_name {
33         unsigned int id;
34         const char *name;
35         const char *desc;
36 };
37
38 /**
39  * cros_feature_to_cells - CrOS feature id to mfd cells association.
40  * @id: The feature identifier.
41  * @mfd_cells: Pointer to the array of mfd cells that needs to be added.
42  * @num_cells: Number of mfd cells into the array.
43  */
44 struct cros_feature_to_cells {
45         unsigned int id;
46         const struct mfd_cell *mfd_cells;
47         unsigned int num_cells;
48 };
49
50 static const struct cros_feature_to_name cros_mcu_devices[] = {
51         {
52                 .id     = EC_FEATURE_FINGERPRINT,
53                 .name   = CROS_EC_DEV_FP_NAME,
54                 .desc   = "Fingerprint",
55         },
56         {
57                 .id     = EC_FEATURE_ISH,
58                 .name   = CROS_EC_DEV_ISH_NAME,
59                 .desc   = "Integrated Sensor Hub",
60         },
61         {
62                 .id     = EC_FEATURE_SCP,
63                 .name   = CROS_EC_DEV_SCP_NAME,
64                 .desc   = "System Control Processor",
65         },
66         {
67                 .id     = EC_FEATURE_TOUCHPAD,
68                 .name   = CROS_EC_DEV_TP_NAME,
69                 .desc   = "Touchpad",
70         },
71 };
72
73 static const struct mfd_cell cros_ec_cec_cells[] = {
74         { .name = "cros-ec-cec", },
75 };
76
77 static const struct mfd_cell cros_ec_rtc_cells[] = {
78         { .name = "cros-ec-rtc", },
79 };
80
81 static const struct mfd_cell cros_usbpd_charger_cells[] = {
82         { .name = "cros-usbpd-charger", },
83         { .name = "cros-usbpd-logger", },
84 };
85
86 static const struct cros_feature_to_cells cros_subdevices[] = {
87         {
88                 .id             = EC_FEATURE_CEC,
89                 .mfd_cells      = cros_ec_cec_cells,
90                 .num_cells      = ARRAY_SIZE(cros_ec_cec_cells),
91         },
92         {
93                 .id             = EC_FEATURE_RTC,
94                 .mfd_cells      = cros_ec_rtc_cells,
95                 .num_cells      = ARRAY_SIZE(cros_ec_rtc_cells),
96         },
97         {
98                 .id             = EC_FEATURE_USB_PD,
99                 .mfd_cells      = cros_usbpd_charger_cells,
100                 .num_cells      = ARRAY_SIZE(cros_usbpd_charger_cells),
101         },
102 };
103
104 static const struct mfd_cell cros_ec_platform_cells[] = {
105         { .name = "cros-ec-chardev", },
106         { .name = "cros-ec-debugfs", },
107         { .name = "cros-ec-lightbar", },
108         { .name = "cros-ec-sysfs", },
109 };
110
111 static const struct mfd_cell cros_ec_vbc_cells[] = {
112         { .name = "cros-ec-vbc", }
113 };
114
115 static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
116 {
117         struct cros_ec_command *msg;
118         int ret;
119
120         if (ec->features[0] == -1U && ec->features[1] == -1U) {
121                 /* features bitmap not read yet */
122                 msg = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
123                 if (!msg)
124                         return -ENOMEM;
125
126                 msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
127                 msg->insize = sizeof(ec->features);
128
129                 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
130                 if (ret < 0) {
131                         dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
132                                  ret, msg->result);
133                         memset(ec->features, 0, sizeof(ec->features));
134                 } else {
135                         memcpy(ec->features, msg->data, sizeof(ec->features));
136                 }
137
138                 dev_dbg(ec->dev, "EC features %08x %08x\n",
139                         ec->features[0], ec->features[1]);
140
141                 kfree(msg);
142         }
143
144         return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
145 }
146
147 static void cros_ec_class_release(struct device *dev)
148 {
149         kfree(to_cros_ec_dev(dev));
150 }
151
152 static void cros_ec_sensors_register(struct cros_ec_dev *ec)
153 {
154         /*
155          * Issue a command to get the number of sensor reported.
156          * Build an array of sensors driver and register them all.
157          */
158         int ret, i, id, sensor_num;
159         struct mfd_cell *sensor_cells;
160         struct cros_ec_sensor_platform *sensor_platforms;
161         int sensor_type[MOTIONSENSE_TYPE_MAX];
162         struct ec_params_motion_sense *params;
163         struct ec_response_motion_sense *resp;
164         struct cros_ec_command *msg;
165
166         msg = kzalloc(sizeof(struct cros_ec_command) +
167                       max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
168         if (msg == NULL)
169                 return;
170
171         msg->version = 2;
172         msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
173         msg->outsize = sizeof(*params);
174         msg->insize = sizeof(*resp);
175
176         params = (struct ec_params_motion_sense *)msg->data;
177         params->cmd = MOTIONSENSE_CMD_DUMP;
178
179         ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
180         if (ret < 0) {
181                 dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
182                          ret, msg->result);
183                 goto error;
184         }
185
186         resp = (struct ec_response_motion_sense *)msg->data;
187         sensor_num = resp->dump.sensor_count;
188         /*
189          * Allocate 2 extra sensors if lid angle sensor and/or FIFO are needed.
190          */
191         sensor_cells = kcalloc(sensor_num + 2, sizeof(struct mfd_cell),
192                                GFP_KERNEL);
193         if (sensor_cells == NULL)
194                 goto error;
195
196         sensor_platforms = kcalloc(sensor_num,
197                                    sizeof(struct cros_ec_sensor_platform),
198                                    GFP_KERNEL);
199         if (sensor_platforms == NULL)
200                 goto error_platforms;
201
202         memset(sensor_type, 0, sizeof(sensor_type));
203         id = 0;
204         for (i = 0; i < sensor_num; i++) {
205                 params->cmd = MOTIONSENSE_CMD_INFO;
206                 params->info.sensor_num = i;
207                 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
208                 if (ret < 0) {
209                         dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
210                                  i, ret, msg->result);
211                         continue;
212                 }
213                 switch (resp->info.type) {
214                 case MOTIONSENSE_TYPE_ACCEL:
215                         sensor_cells[id].name = "cros-ec-accel";
216                         break;
217                 case MOTIONSENSE_TYPE_BARO:
218                         sensor_cells[id].name = "cros-ec-baro";
219                         break;
220                 case MOTIONSENSE_TYPE_GYRO:
221                         sensor_cells[id].name = "cros-ec-gyro";
222                         break;
223                 case MOTIONSENSE_TYPE_MAG:
224                         sensor_cells[id].name = "cros-ec-mag";
225                         break;
226                 case MOTIONSENSE_TYPE_PROX:
227                         sensor_cells[id].name = "cros-ec-prox";
228                         break;
229                 case MOTIONSENSE_TYPE_LIGHT:
230                         sensor_cells[id].name = "cros-ec-light";
231                         break;
232                 case MOTIONSENSE_TYPE_ACTIVITY:
233                         sensor_cells[id].name = "cros-ec-activity";
234                         break;
235                 default:
236                         dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
237                         continue;
238                 }
239                 sensor_platforms[id].sensor_num = i;
240                 sensor_cells[id].id = sensor_type[resp->info.type];
241                 sensor_cells[id].platform_data = &sensor_platforms[id];
242                 sensor_cells[id].pdata_size =
243                         sizeof(struct cros_ec_sensor_platform);
244
245                 sensor_type[resp->info.type]++;
246                 id++;
247         }
248
249         if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2)
250                 ec->has_kb_wake_angle = true;
251
252         if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
253                 sensor_cells[id].name = "cros-ec-ring";
254                 id++;
255         }
256         if (cros_ec_check_features(ec,
257                                 EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) {
258                 sensor_cells[id].name = "cros-ec-lid-angle";
259                 id++;
260         }
261
262         ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
263                               NULL, 0, NULL);
264         if (ret)
265                 dev_err(ec->dev, "failed to add EC sensors\n");
266
267         kfree(sensor_platforms);
268 error_platforms:
269         kfree(sensor_cells);
270 error:
271         kfree(msg);
272 }
273
274 static struct cros_ec_sensor_platform sensor_platforms[] = {
275         { .sensor_num = 0 },
276         { .sensor_num = 1 }
277 };
278
279 static const struct mfd_cell cros_ec_accel_legacy_cells[] = {
280         {
281                 .name = "cros-ec-accel-legacy",
282                 .platform_data = &sensor_platforms[0],
283                 .pdata_size = sizeof(struct cros_ec_sensor_platform),
284         },
285         {
286                 .name = "cros-ec-accel-legacy",
287                 .platform_data = &sensor_platforms[1],
288                 .pdata_size = sizeof(struct cros_ec_sensor_platform),
289         }
290 };
291
292 static void cros_ec_accel_legacy_register(struct cros_ec_dev *ec)
293 {
294         struct cros_ec_device *ec_dev = ec->ec_dev;
295         u8 status;
296         int ret;
297
298         /*
299          * ECs that need legacy support are the main EC, directly connected to
300          * the AP.
301          */
302         if (ec->cmd_offset != 0)
303                 return;
304
305         /*
306          * Check if EC supports direct memory reads and if EC has
307          * accelerometers.
308          */
309         if (ec_dev->cmd_readmem) {
310                 ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS, 1,
311                                           &status);
312                 if (ret < 0) {
313                         dev_warn(ec->dev, "EC direct read error.\n");
314                         return;
315                 }
316
317                 /* Check if EC has accelerometers. */
318                 if (!(status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) {
319                         dev_info(ec->dev, "EC does not have accelerometers.\n");
320                         return;
321                 }
322         }
323
324         /*
325          * The device may still support accelerometers:
326          * it would be an older ARM based device that do not suppor the
327          * EC_CMD_GET_FEATURES command.
328          *
329          * Register 2 accelerometers, we will fail in the IIO driver if there
330          * are no sensors.
331          */
332         ret = mfd_add_hotplug_devices(ec->dev, cros_ec_accel_legacy_cells,
333                                       ARRAY_SIZE(cros_ec_accel_legacy_cells));
334         if (ret)
335                 dev_err(ec_dev->dev, "failed to add EC sensors\n");
336 }
337
338 static int ec_device_probe(struct platform_device *pdev)
339 {
340         int retval = -ENOMEM;
341         struct device_node *node;
342         struct device *dev = &pdev->dev;
343         struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
344         struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
345         int i;
346
347         if (!ec)
348                 return retval;
349
350         dev_set_drvdata(dev, ec);
351         ec->ec_dev = dev_get_drvdata(dev->parent);
352         ec->dev = dev;
353         ec->cmd_offset = ec_platform->cmd_offset;
354         ec->features[0] = -1U; /* Not cached yet */
355         ec->features[1] = -1U; /* Not cached yet */
356         device_initialize(&ec->class_dev);
357
358         for (i = 0; i < ARRAY_SIZE(cros_mcu_devices); i++) {
359                 /*
360                  * Check whether this is actually a dedicated MCU rather
361                  * than an standard EC.
362                  */
363                 if (cros_ec_check_features(ec, cros_mcu_devices[i].id)) {
364                         dev_info(dev, "CrOS %s MCU detected\n",
365                                  cros_mcu_devices[i].desc);
366                         /*
367                          * Help userspace differentiating ECs from other MCU,
368                          * regardless of the probing order.
369                          */
370                         ec_platform->ec_name = cros_mcu_devices[i].name;
371                         break;
372                 }
373         }
374
375         /*
376          * Add the class device
377          */
378         ec->class_dev.class = &cros_class;
379         ec->class_dev.parent = dev;
380         ec->class_dev.release = cros_ec_class_release;
381
382         retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
383         if (retval) {
384                 dev_err(dev, "dev_set_name failed => %d\n", retval);
385                 goto failed;
386         }
387
388         retval = device_add(&ec->class_dev);
389         if (retval)
390                 goto failed;
391
392         /* check whether this EC is a sensor hub. */
393         if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
394                 cros_ec_sensors_register(ec);
395         else
396                 /* Workaroud for older EC firmware */
397                 cros_ec_accel_legacy_register(ec);
398
399         /*
400          * The following subdevices can be detected by sending the
401          * EC_FEATURE_GET_CMD Embedded Controller device.
402          */
403         for (i = 0; i < ARRAY_SIZE(cros_subdevices); i++) {
404                 if (cros_ec_check_features(ec, cros_subdevices[i].id)) {
405                         retval = mfd_add_hotplug_devices(ec->dev,
406                                                 cros_subdevices[i].mfd_cells,
407                                                 cros_subdevices[i].num_cells);
408                         if (retval)
409                                 dev_err(ec->dev,
410                                         "failed to add %s subdevice: %d\n",
411                                         cros_subdevices[i].mfd_cells->name,
412                                         retval);
413                 }
414         }
415
416         /*
417          * The following subdevices cannot be detected by sending the
418          * EC_FEATURE_GET_CMD to the Embedded Controller device.
419          */
420         retval = mfd_add_hotplug_devices(ec->dev, cros_ec_platform_cells,
421                                          ARRAY_SIZE(cros_ec_platform_cells));
422         if (retval)
423                 dev_warn(ec->dev,
424                          "failed to add cros-ec platform devices: %d\n",
425                          retval);
426
427         /* Check whether this EC instance has a VBC NVRAM */
428         node = ec->ec_dev->dev->of_node;
429         if (of_property_read_bool(node, "google,has-vbc-nvram")) {
430                 retval = mfd_add_hotplug_devices(ec->dev, cros_ec_vbc_cells,
431                                                 ARRAY_SIZE(cros_ec_vbc_cells));
432                 if (retval)
433                         dev_warn(ec->dev, "failed to add VBC devices: %d\n",
434                                  retval);
435         }
436
437         return 0;
438
439 failed:
440         put_device(&ec->class_dev);
441         return retval;
442 }
443
444 static int ec_device_remove(struct platform_device *pdev)
445 {
446         struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
447
448         mfd_remove_devices(ec->dev);
449         device_unregister(&ec->class_dev);
450         return 0;
451 }
452
453 static const struct platform_device_id cros_ec_id[] = {
454         { DRV_NAME, 0 },
455         { /* sentinel */ }
456 };
457 MODULE_DEVICE_TABLE(platform, cros_ec_id);
458
459 static struct platform_driver cros_ec_dev_driver = {
460         .driver = {
461                 .name = DRV_NAME,
462         },
463         .id_table = cros_ec_id,
464         .probe = ec_device_probe,
465         .remove = ec_device_remove,
466 };
467
468 static int __init cros_ec_dev_init(void)
469 {
470         int ret;
471
472         ret  = class_register(&cros_class);
473         if (ret) {
474                 pr_err(CROS_EC_DEV_NAME ": failed to register device class\n");
475                 return ret;
476         }
477
478         /* Register the driver */
479         ret = platform_driver_register(&cros_ec_dev_driver);
480         if (ret < 0) {
481                 pr_warn(CROS_EC_DEV_NAME ": can't register driver: %d\n", ret);
482                 goto failed_devreg;
483         }
484         return 0;
485
486 failed_devreg:
487         class_unregister(&cros_class);
488         return ret;
489 }
490
491 static void __exit cros_ec_dev_exit(void)
492 {
493         platform_driver_unregister(&cros_ec_dev_driver);
494         class_unregister(&cros_class);
495 }
496
497 module_init(cros_ec_dev_init);
498 module_exit(cros_ec_dev_exit);
499
500 MODULE_ALIAS("platform:" DRV_NAME);
501 MODULE_AUTHOR("Bill Richardson <wfrichar@chromium.org>");
502 MODULE_DESCRIPTION("Userspace interface to the Chrome OS Embedded Controller");
503 MODULE_VERSION("1.0");
504 MODULE_LICENSE("GPL");