aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2018-03-23 13:42:47 -0400
committerBenson Leung <bleung@chromium.org>2018-04-11 01:25:07 -0400
commitc1d1e91aff3d1183d6b16a282c2575e3e006cee4 (patch)
treec28563a8b73ebda8598b47f059ab328df9cc65e9 /drivers
parentb082b2e1454c3e0217d7cf70f2211966c3d54301 (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.c31
-rw-r--r--drivers/platform/chrome/cros_ec_sysfs.c81
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
445failed: 440failed:
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 */
262static 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);
289exit:
290 kfree(msg);
291 return ret;
292}
293
294static 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
263static DEVICE_ATTR_RW(reboot); 329static DEVICE_ATTR_RW(reboot);
264static DEVICE_ATTR_RO(version); 330static DEVICE_ATTR_RO(version);
265static DEVICE_ATTR_RO(flashinfo); 331static DEVICE_ATTR_RO(flashinfo);
332static DEVICE_ATTR_RW(kb_wake_angle);
266 333
267static struct attribute *__ec_attrs[] = { 334static 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
342static 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
274struct attribute_group cros_ec_attr_group = { 354struct attribute_group cros_ec_attr_group = {
275 .attrs = __ec_attrs, 355 .attrs = __ec_attrs,
356 .is_visible = cros_ec_ctrl_visible,
276}; 357};
277EXPORT_SYMBOL(cros_ec_attr_group); 358EXPORT_SYMBOL(cros_ec_attr_group);
278 359