diff options
author | Gwendal Grignou <gwendal@chromium.org> | 2018-03-23 13:42:47 -0400 |
---|---|---|
committer | Benson Leung <bleung@chromium.org> | 2018-04-11 01:25:07 -0400 |
commit | c1d1e91aff3d1183d6b16a282c2575e3e006cee4 (patch) | |
tree | c28563a8b73ebda8598b47f059ab328df9cc65e9 /drivers | |
parent | b082b2e1454c3e0217d7cf70f2211966c3d54301 (diff) |
platform/chrome: mfd/cros_ec_dev: Add sysfs entry to set keyboard wake lid angle
This adds a sysfs attribute (/sys/class/chromeos/cros_ec/kb_wake_angle)
used to set and get the keyboard wake lid angle. This attribute is
present only if 2 accelerometers are controlled by the EC.
This patch also moves the cros_ec features check before the device is
added so the features map obtained from the EC is ready on time.
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Benson Leung <bleung@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mfd/cros_ec_dev.c | 31 | ||||
-rw-r--r-- | drivers/platform/chrome/cros_ec_sysfs.c | 81 |
2 files changed, 94 insertions, 18 deletions
diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index e4fafdd96e5e..eafd06f62a3a 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c | |||
@@ -305,8 +305,8 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec) | |||
305 | 305 | ||
306 | resp = (struct ec_response_motion_sense *)msg->data; | 306 | resp = (struct ec_response_motion_sense *)msg->data; |
307 | sensor_num = resp->dump.sensor_count; | 307 | sensor_num = resp->dump.sensor_count; |
308 | /* Allocate 2 extra sensors in case lid angle or FIFO are needed */ | 308 | /* Allocate 1 extra sensors in FIFO are needed */ |
309 | sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2), | 309 | sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 1), |
310 | GFP_KERNEL); | 310 | GFP_KERNEL); |
311 | if (sensor_cells == NULL) | 311 | if (sensor_cells == NULL) |
312 | goto error; | 312 | goto error; |
@@ -362,16 +362,10 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec) | |||
362 | sensor_type[resp->info.type]++; | 362 | sensor_type[resp->info.type]++; |
363 | id++; | 363 | id++; |
364 | } | 364 | } |
365 | if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) { | ||
366 | sensor_platforms[id].sensor_num = sensor_num; | ||
367 | 365 | ||
368 | sensor_cells[id].name = "cros-ec-angle"; | 366 | if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) |
369 | sensor_cells[id].id = 0; | 367 | ec->has_kb_wake_angle = true; |
370 | sensor_cells[id].platform_data = &sensor_platforms[id]; | 368 | |
371 | sensor_cells[id].pdata_size = | ||
372 | sizeof(struct cros_ec_sensor_platform); | ||
373 | id++; | ||
374 | } | ||
375 | if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) { | 369 | if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) { |
376 | sensor_cells[id].name = "cros-ec-ring"; | 370 | sensor_cells[id].name = "cros-ec-ring"; |
377 | id++; | 371 | id++; |
@@ -424,6 +418,14 @@ static int ec_device_probe(struct platform_device *pdev) | |||
424 | goto failed; | 418 | goto failed; |
425 | } | 419 | } |
426 | 420 | ||
421 | /* check whether this EC is a sensor hub. */ | ||
422 | if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) | ||
423 | cros_ec_sensors_register(ec); | ||
424 | |||
425 | /* Take control of the lightbar from the EC. */ | ||
426 | lb_manual_suspend_ctrl(ec, 1); | ||
427 | |||
428 | /* We can now add the sysfs class, we know which parameter to show */ | ||
427 | retval = cdev_device_add(&ec->cdev, &ec->class_dev); | 429 | retval = cdev_device_add(&ec->cdev, &ec->class_dev); |
428 | if (retval) { | 430 | if (retval) { |
429 | dev_err(dev, "cdev_device_add failed => %d\n", retval); | 431 | dev_err(dev, "cdev_device_add failed => %d\n", retval); |
@@ -433,13 +435,6 @@ static int ec_device_probe(struct platform_device *pdev) | |||
433 | if (cros_ec_debugfs_init(ec)) | 435 | if (cros_ec_debugfs_init(ec)) |
434 | dev_warn(dev, "failed to create debugfs directory\n"); | 436 | dev_warn(dev, "failed to create debugfs directory\n"); |
435 | 437 | ||
436 | /* check whether this EC is a sensor hub. */ | ||
437 | if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) | ||
438 | cros_ec_sensors_register(ec); | ||
439 | |||
440 | /* Take control of the lightbar from the EC. */ | ||
441 | lb_manual_suspend_ctrl(ec, 1); | ||
442 | |||
443 | return 0; | 438 | return 0; |
444 | 439 | ||
445 | failed: | 440 | failed: |
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index 78ae0d3760e4..5a6db3fe213a 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c | |||
@@ -258,21 +258,102 @@ exit: | |||
258 | return ret; | 258 | return ret; |
259 | } | 259 | } |
260 | 260 | ||
261 | /* Keyboard wake angle control */ | ||
262 | static ssize_t kb_wake_angle_show(struct device *dev, | ||
263 | struct device_attribute *attr, char *buf) | ||
264 | { | ||
265 | struct cros_ec_dev *ec = to_cros_ec_dev(dev); | ||
266 | struct ec_response_motion_sense *resp; | ||
267 | struct ec_params_motion_sense *param; | ||
268 | struct cros_ec_command *msg; | ||
269 | int ret; | ||
270 | |||
271 | msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL); | ||
272 | if (!msg) | ||
273 | return -ENOMEM; | ||
274 | |||
275 | param = (struct ec_params_motion_sense *)msg->data; | ||
276 | msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; | ||
277 | msg->version = 2; | ||
278 | param->cmd = MOTIONSENSE_CMD_KB_WAKE_ANGLE; | ||
279 | param->kb_wake_angle.data = EC_MOTION_SENSE_NO_VALUE; | ||
280 | msg->outsize = sizeof(*param); | ||
281 | msg->insize = sizeof(*resp); | ||
282 | |||
283 | ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); | ||
284 | if (ret < 0) | ||
285 | goto exit; | ||
286 | |||
287 | resp = (struct ec_response_motion_sense *)msg->data; | ||
288 | ret = scnprintf(buf, PAGE_SIZE, "%d\n", resp->kb_wake_angle.ret); | ||
289 | exit: | ||
290 | kfree(msg); | ||
291 | return ret; | ||
292 | } | ||
293 | |||
294 | static ssize_t kb_wake_angle_store(struct device *dev, | ||
295 | struct device_attribute *attr, | ||
296 | const char *buf, size_t count) | ||
297 | { | ||
298 | struct cros_ec_dev *ec = to_cros_ec_dev(dev); | ||
299 | struct ec_params_motion_sense *param; | ||
300 | struct cros_ec_command *msg; | ||
301 | u16 angle; | ||
302 | int ret; | ||
303 | |||
304 | ret = kstrtou16(buf, 0, &angle); | ||
305 | if (ret) | ||
306 | return ret; | ||
307 | |||
308 | msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL); | ||
309 | if (!msg) | ||
310 | return -ENOMEM; | ||
311 | |||
312 | param = (struct ec_params_motion_sense *)msg->data; | ||
313 | msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; | ||
314 | msg->version = 2; | ||
315 | param->cmd = MOTIONSENSE_CMD_KB_WAKE_ANGLE; | ||
316 | param->kb_wake_angle.data = angle; | ||
317 | msg->outsize = sizeof(*param); | ||
318 | msg->insize = sizeof(struct ec_response_motion_sense); | ||
319 | |||
320 | ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); | ||
321 | kfree(msg); | ||
322 | if (ret < 0) | ||
323 | return ret; | ||
324 | return count; | ||
325 | } | ||
326 | |||
261 | /* Module initialization */ | 327 | /* Module initialization */ |
262 | 328 | ||
263 | static DEVICE_ATTR_RW(reboot); | 329 | static DEVICE_ATTR_RW(reboot); |
264 | static DEVICE_ATTR_RO(version); | 330 | static DEVICE_ATTR_RO(version); |
265 | static DEVICE_ATTR_RO(flashinfo); | 331 | static DEVICE_ATTR_RO(flashinfo); |
332 | static DEVICE_ATTR_RW(kb_wake_angle); | ||
266 | 333 | ||
267 | static struct attribute *__ec_attrs[] = { | 334 | static struct attribute *__ec_attrs[] = { |
335 | &dev_attr_kb_wake_angle.attr, | ||
268 | &dev_attr_reboot.attr, | 336 | &dev_attr_reboot.attr, |
269 | &dev_attr_version.attr, | 337 | &dev_attr_version.attr, |
270 | &dev_attr_flashinfo.attr, | 338 | &dev_attr_flashinfo.attr, |
271 | NULL, | 339 | NULL, |
272 | }; | 340 | }; |
273 | 341 | ||
342 | static umode_t cros_ec_ctrl_visible(struct kobject *kobj, | ||
343 | struct attribute *a, int n) | ||
344 | { | ||
345 | struct device *dev = container_of(kobj, struct device, kobj); | ||
346 | struct cros_ec_dev *ec = to_cros_ec_dev(dev); | ||
347 | |||
348 | if (a == &dev_attr_kb_wake_angle.attr && !ec->has_kb_wake_angle) | ||
349 | return 0; | ||
350 | |||
351 | return a->mode; | ||
352 | } | ||
353 | |||
274 | struct attribute_group cros_ec_attr_group = { | 354 | struct attribute_group cros_ec_attr_group = { |
275 | .attrs = __ec_attrs, | 355 | .attrs = __ec_attrs, |
356 | .is_visible = cros_ec_ctrl_visible, | ||
276 | }; | 357 | }; |
277 | EXPORT_SYMBOL(cros_ec_attr_group); | 358 | EXPORT_SYMBOL(cros_ec_attr_group); |
278 | 359 | ||