diff options
Diffstat (limited to 'drivers/platform/chrome/cros_ec_vbc.c')
| -rw-r--r-- | drivers/platform/chrome/cros_ec_vbc.c | 122 |
1 files changed, 71 insertions, 51 deletions
diff --git a/drivers/platform/chrome/cros_ec_vbc.c b/drivers/platform/chrome/cros_ec_vbc.c index 5356f26bc022..5ee8adaa6564 100644 --- a/drivers/platform/chrome/cros_ec_vbc.c +++ b/drivers/platform/chrome/cros_ec_vbc.c @@ -1,40 +1,34 @@ -/* - * cros_ec_vbc - Expose the vboot context nvram to userspace - * - * Copyright (C) 2015 Collabora Ltd. - * - * based on vendor driver, - * - * Copyright (C) 2012 The Chromium OS Authors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ +// SPDX-License-Identifier: GPL-2.0+ +// Expose the vboot context nvram to userspace +// +// Copyright (C) 2012 Google, Inc. +// Copyright (C) 2015 Collabora Ltd. #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/mfd/cros_ec.h> -#include <linux/mfd/cros_ec_commands.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/platform_data/cros_ec_commands.h> +#include <linux/platform_data/cros_ec_proto.h> #include <linux/slab.h> +#define DRV_NAME "cros-ec-vbc" + static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *att, char *buf, + const struct bin_attribute *att, char *buf, loff_t pos, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct cros_ec_dev *ec = to_cros_ec_dev(dev); struct cros_ec_device *ecdev = ec->ec_dev; - struct ec_params_vbnvcontext *params; struct cros_ec_command *msg; + /* + * This should be a pointer to the same type as op field in + * struct ec_params_vbnvcontext. + */ + uint32_t *params_op; int err; - const size_t para_sz = sizeof(params->op); + const size_t para_sz = sizeof(*params_op); const size_t resp_sz = sizeof(struct ec_response_vbnvcontext); const size_t payload = max(para_sz, resp_sz); @@ -43,15 +37,15 @@ static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj, return -ENOMEM; /* NB: we only kmalloc()ated enough space for the op field */ - params = (struct ec_params_vbnvcontext *)msg->data; - params->op = EC_VBNV_CONTEXT_OP_READ; + params_op = (uint32_t *)msg->data; + *params_op = EC_VBNV_CONTEXT_OP_READ; msg->version = EC_VER_VBNV_CONTEXT; msg->command = EC_CMD_VBNV_CONTEXT; msg->outsize = para_sz; msg->insize = resp_sz; - err = cros_ec_cmd_xfer(ecdev, msg); + err = cros_ec_cmd_xfer_status(ecdev, msg); if (err < 0) { dev_err(dev, "Error sending read request: %d\n", err); kfree(msg); @@ -65,10 +59,10 @@ static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj, } static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, + const struct bin_attribute *attr, char *buf, loff_t pos, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct cros_ec_dev *ec = to_cros_ec_dev(dev); struct cros_ec_device *ecdev = ec->ec_dev; struct ec_params_vbnvcontext *params; @@ -94,7 +88,7 @@ static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj, msg->outsize = para_sz; msg->insize = 0; - err = cros_ec_cmd_xfer(ecdev, msg); + err = cros_ec_cmd_xfer_status(ecdev, msg); if (err < 0) { dev_err(dev, "Error sending write request: %d\n", err); kfree(msg); @@ -105,31 +99,57 @@ static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj, return data_sz; } -static umode_t cros_ec_vbc_is_visible(struct kobject *kobj, - struct bin_attribute *a, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct cros_ec_dev *ec = to_cros_ec_dev(dev); - struct device_node *np = ec->ec_dev->dev->of_node; - - if (IS_ENABLED(CONFIG_OF) && np) { - if (of_property_read_bool(np, "google,has-vbc-nvram")) - return a->attr.mode; - } - - return 0; -} - -static BIN_ATTR_RW(vboot_context, 16); +static const BIN_ATTR_RW(vboot_context, 16); -static struct bin_attribute *cros_ec_vbc_bin_attrs[] = { +static const struct bin_attribute *const cros_ec_vbc_bin_attrs[] = { &bin_attr_vboot_context, NULL }; -struct attribute_group cros_ec_vbc_attr_group = { +static const struct attribute_group cros_ec_vbc_attr_group = { .name = "vbc", .bin_attrs = cros_ec_vbc_bin_attrs, - .is_bin_visible = cros_ec_vbc_is_visible, }; -EXPORT_SYMBOL(cros_ec_vbc_attr_group); + +static int cros_ec_vbc_probe(struct platform_device *pd) +{ + struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent); + struct device *dev = &pd->dev; + int ret; + + ret = sysfs_create_group(&ec_dev->class_dev.kobj, + &cros_ec_vbc_attr_group); + if (ret < 0) + dev_err(dev, "failed to create %s attributes. err=%d\n", + cros_ec_vbc_attr_group.name, ret); + + return ret; +} + +static void cros_ec_vbc_remove(struct platform_device *pd) +{ + struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent); + + sysfs_remove_group(&ec_dev->class_dev.kobj, + &cros_ec_vbc_attr_group); +} + +static const struct platform_device_id cros_ec_vbc_id[] = { + { DRV_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(platform, cros_ec_vbc_id); + +static struct platform_driver cros_ec_vbc_driver = { + .driver = { + .name = DRV_NAME, + }, + .probe = cros_ec_vbc_probe, + .remove = cros_ec_vbc_remove, + .id_table = cros_ec_vbc_id, +}; + +module_platform_driver(cros_ec_vbc_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Expose the vboot context nvram to userspace"); |
