platform/chrome: wilco_ec: Add property helper library
authorNick Crews <ncrews@chromium.org>
Wed, 24 Apr 2019 16:56:50 +0000 (10:56 -0600)
committerEnric Balletbo i Serra <enric.balletbo@collabora.com>
Mon, 20 May 2019 08:18:09 +0000 (10:18 +0200)
A Property is typically a data item that is stored to NVRAM
by the EC. Each of these data items has an index associated
with it, known as the Property ID (PID). Properties may have
variable lengths, up to a max of WILCO_EC_PROPERTY_MAX_SIZE
bytes. Properties can be simple integers, or they may be more
complex binary data.

This patch adds support for getting and setting properties.
This will be useful for setting the charge algorithm and charge
schedules, which all use properties.

Signed-off-by: Nick Crews <ncrews@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
drivers/platform/chrome/wilco_ec/Makefile
drivers/platform/chrome/wilco_ec/properties.c [new file with mode: 0644]
include/linux/platform_data/wilco-ec.h

index 063e7fb4ea17df0ea35574e919e56f6040915831..29b734137786e23fb0ceb48385c8833354c46492 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
-wilco_ec-objs                          := core.o mailbox.o
+wilco_ec-objs                          := core.o mailbox.o properties.o
 obj-$(CONFIG_WILCO_EC)                 += wilco_ec.o
 wilco_ec_debugfs-objs                  := debugfs.o
 obj-$(CONFIG_WILCO_EC_DEBUGFS)         += wilco_ec_debugfs.o
diff --git a/drivers/platform/chrome/wilco_ec/properties.c b/drivers/platform/chrome/wilco_ec/properties.c
new file mode 100644 (file)
index 0000000..e69682c
--- /dev/null
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <linux/platform_data/wilco-ec.h>
+#include <linux/string.h>
+#include <linux/unaligned/le_memmove.h>
+
+/* Operation code; what the EC should do with the property */
+enum ec_property_op {
+       EC_OP_GET = 0,
+       EC_OP_SET = 1,
+};
+
+struct ec_property_request {
+       u8 op; /* One of enum ec_property_op */
+       u8 property_id[4]; /* The 32 bit PID is stored Little Endian */
+       u8 length;
+       u8 data[WILCO_EC_PROPERTY_MAX_SIZE];
+} __packed;
+
+struct ec_property_response {
+       u8 reserved[2];
+       u8 op; /* One of enum ec_property_op */
+       u8 property_id[4]; /* The 32 bit PID is stored Little Endian */
+       u8 length;
+       u8 data[WILCO_EC_PROPERTY_MAX_SIZE];
+} __packed;
+
+static int send_property_msg(struct wilco_ec_device *ec,
+                            struct ec_property_request *rq,
+                            struct ec_property_response *rs)
+{
+       struct wilco_ec_message ec_msg;
+       int ret;
+
+       memset(&ec_msg, 0, sizeof(ec_msg));
+       ec_msg.type = WILCO_EC_MSG_PROPERTY;
+       ec_msg.request_data = rq;
+       ec_msg.request_size = sizeof(*rq);
+       ec_msg.response_data = rs;
+       ec_msg.response_size = sizeof(*rs);
+
+       ret = wilco_ec_mailbox(ec, &ec_msg);
+       if (ret < 0)
+               return ret;
+       if (rs->op != rq->op)
+               return -EBADMSG;
+       if (memcmp(rq->property_id, rs->property_id, sizeof(rs->property_id)))
+               return -EBADMSG;
+
+       return 0;
+}
+
+int wilco_ec_get_property(struct wilco_ec_device *ec,
+                         struct wilco_ec_property_msg *prop_msg)
+{
+       struct ec_property_request rq;
+       struct ec_property_response rs;
+       int ret;
+
+       memset(&rq, 0, sizeof(rq));
+       rq.op = EC_OP_GET;
+       put_unaligned_le32(prop_msg->property_id, rq.property_id);
+
+       ret = send_property_msg(ec, &rq, &rs);
+       if (ret < 0)
+               return ret;
+
+       prop_msg->length = rs.length;
+       memcpy(prop_msg->data, rs.data, rs.length);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wilco_ec_get_property);
+
+int wilco_ec_set_property(struct wilco_ec_device *ec,
+                         struct wilco_ec_property_msg *prop_msg)
+{
+       struct ec_property_request rq;
+       struct ec_property_response rs;
+       int ret;
+
+       memset(&rq, 0, sizeof(rq));
+       rq.op = EC_OP_SET;
+       put_unaligned_le32(prop_msg->property_id, rq.property_id);
+       rq.length = prop_msg->length;
+       memcpy(rq.data, prop_msg->data, prop_msg->length);
+
+       ret = send_property_msg(ec, &rq, &rs);
+       if (ret < 0)
+               return ret;
+       if (rs.length != prop_msg->length)
+               return -EBADMSG;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wilco_ec_set_property);
+
+int wilco_ec_get_byte_property(struct wilco_ec_device *ec, u32 property_id,
+                              u8 *val)
+{
+       struct wilco_ec_property_msg msg;
+       int ret;
+
+       msg.property_id = property_id;
+
+       ret = wilco_ec_get_property(ec, &msg);
+       if (ret < 0)
+               return ret;
+       if (msg.length != 1)
+               return -EBADMSG;
+
+       *val = msg.data[0];
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wilco_ec_get_byte_property);
+
+int wilco_ec_set_byte_property(struct wilco_ec_device *ec, u32 property_id,
+                              u8 val)
+{
+       struct wilco_ec_property_msg msg;
+
+       msg.property_id = property_id;
+       msg.data[0] = val;
+       msg.length = 1;
+
+       return wilco_ec_set_property(ec, &msg);
+}
+EXPORT_SYMBOL_GPL(wilco_ec_set_byte_property);
index 1ff224793c99f9778f803b3fed1d1e4eed70227e..50a21bd5fd44eaa34f452e6ee648fbec747727c0 100644 (file)
@@ -123,4 +123,75 @@ struct wilco_ec_message {
  */
 int wilco_ec_mailbox(struct wilco_ec_device *ec, struct wilco_ec_message *msg);
 
+/*
+ * A Property is typically a data item that is stored to NVRAM
+ * by the EC. Each of these data items has an index associated
+ * with it, known as the Property ID (PID). Properties may have
+ * variable lengths, up to a max of WILCO_EC_PROPERTY_MAX_SIZE
+ * bytes. Properties can be simple integers, or they may be more
+ * complex binary data.
+ */
+
+#define WILCO_EC_PROPERTY_MAX_SIZE     4
+
+/**
+ * struct ec_property_set_msg - Message to get or set a property.
+ * @property_id: Which property to get or set.
+ * @length: Number of bytes of |data| that are used.
+ * @data: Actual property data.
+ */
+struct wilco_ec_property_msg {
+       u32 property_id;
+       int length;
+       u8 data[WILCO_EC_PROPERTY_MAX_SIZE];
+};
+
+/**
+ * wilco_ec_get_property() - Retrieve a property from the EC.
+ * @ec: Embedded Controller device.
+ * @prop_msg: Message for request and response.
+ *
+ * The property_id field of |prop_msg| should be filled before calling this
+ * function. The result will be stored in the data and length fields.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int wilco_ec_get_property(struct wilco_ec_device *ec,
+                         struct wilco_ec_property_msg *prop_msg);
+
+/**
+ * wilco_ec_set_property() - Store a property on the EC.
+ * @ec: Embedded Controller device.
+ * @prop_msg: Message for request and response.
+ *
+ * The property_id, length, and data fields of |prop_msg| should be
+ * filled before calling this function.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int wilco_ec_set_property(struct wilco_ec_device *ec,
+                         struct wilco_ec_property_msg *prop_msg);
+
+/**
+ * wilco_ec_get_byte_property() - Retrieve a byte-size property from the EC.
+ * @ec: Embedded Controller device.
+ * @property_id: Which property to retrieve.
+ * @val: The result value, will be filled by this function.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int wilco_ec_get_byte_property(struct wilco_ec_device *ec, u32 property_id,
+                              u8 *val);
+
+/**
+ * wilco_ec_get_byte_property() - Store a byte-size property on the EC.
+ * @ec: Embedded Controller device.
+ * @property_id: Which property to store.
+ * @val: Value to store.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int wilco_ec_set_byte_property(struct wilco_ec_device *ec, u32 property_id,
+                              u8 val);
+
 #endif /* WILCO_EC_H */