greybus: firmware: Add firmware management bundle driver
authorViresh Kumar <viresh.kumar@linaro.org>
Tue, 26 Apr 2016 04:50:49 +0000 (10:20 +0530)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 27 Apr 2016 18:10:44 +0000 (11:10 -0700)
All firmware packages on the Modules or Interfaces are now managed by a
special Firmware Management Protocol. The Interface Manifest shall
at least contain the Firmware Management Bundle and a Firmware
Management Protocol CPort within it.

The bundle may contain additional CPorts based on the extra
functionality required to manage firmware packages.

For example, this is how the Firmware Management Bundle of the Interface
Manifest may look like:

; Firmware Management Bundle (Bundle 1):
[bundle-descriptor 1]
class = 0x16

; (Mandatory) Firmware Management Protocol on CPort 1
[cport-descriptor 1]
bundle = 1
protocol = 0x18

; (Optional) Firmware Download Protocol on CPort 2
[cport-descriptor 2]
bundle = 1
protocol = 0x17

; (Optional) SPI protocol on CPort 3
[cport-descriptor 3]
bundle = 1
protocol = 0x0b

; (Optional) Component Authentication Protocol (CAP) on CPort 4
[cport-descriptor 4]
bundle = 1
protocol = 0xXX //TBD

This patch adds the basic firmware-management bundle driver, which just
creates a firmware-management connection. Support for individual
protocols will be added separately.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/Makefile
drivers/staging/greybus/fw-core.c [new file with mode: 0644]
drivers/staging/greybus/greybus_manifest.h

index 5bdccccbe17132577dcfbd5d6dab3e747f7a0b23..1a120d9284853b63572cff9053c22b89645f6467 100644 (file)
@@ -39,6 +39,7 @@ gb-audio-apbridgea-y := audio_apbridgea.o
 gb-audio-manager-y += audio_manager.o
 gb-audio-manager-y += audio_manager_module.o
 gb-camera-y := camera.o
+gb-firmware-y := fw-core.o
 
 obj-m += greybus.o
 obj-m += gb-phy.o
@@ -60,6 +61,7 @@ endif
 obj-m += gb-audio-gb.o
 obj-m += gb-audio-apbridgea.o
 obj-m += gb-audio-manager.o
+obj-m += gb-firmware.o
 
 KERNELVER              ?= $(shell uname -r)
 KERNELDIR              ?= /lib/modules/$(KERNELVER)/build
diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c
new file mode 100644 (file)
index 0000000..4720d59
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Greybus Firmware Core Bundle Driver.
+ *
+ * Copyright 2016 Google Inc.
+ * Copyright 2016 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/firmware.h>
+#include "greybus.h"
+
+struct gb_fw_core {
+       struct gb_connection    *mgmt_connection;
+};
+
+static int gb_fw_core_probe(struct gb_bundle *bundle,
+                           const struct greybus_bundle_id *id)
+{
+       struct greybus_descriptor_cport *cport_desc;
+       struct gb_connection *connection;
+       struct gb_fw_core *fw_core;
+       int ret, i;
+       u16 cport_id;
+       u8 protocol_id;
+
+       fw_core = kzalloc(sizeof(*fw_core), GFP_KERNEL);
+       if (!fw_core)
+               return -ENOMEM;
+
+       /* Parse CPorts and create connections */
+       for (i = 0; i < bundle->num_cports; i++) {
+               cport_desc = &bundle->cport_desc[i];
+               cport_id = le16_to_cpu(cport_desc->id);
+               protocol_id = cport_desc->protocol_id;
+
+               switch (protocol_id) {
+               case GREYBUS_PROTOCOL_FW_MANAGEMENT:
+                       /* Disallow multiple Firmware Management CPorts */
+                       if (fw_core->mgmt_connection) {
+                               dev_err(&bundle->dev,
+                                       "multiple management CPorts found\n");
+                               ret = -EINVAL;
+                               goto err_destroy_connections;
+                       }
+
+                       connection = gb_connection_create(bundle, cport_id,
+                                                         NULL);
+                       if (IS_ERR(connection)) {
+                               ret = PTR_ERR(connection);
+                               dev_err(&bundle->dev,
+                                       "failed to create management connection (%d)\n",
+                                       ret);
+                               goto err_free_fw_core;
+                       }
+
+                       fw_core->mgmt_connection = connection;
+                       break;
+               default:
+                       dev_err(&bundle->dev, "invalid protocol id (0x%02x)\n",
+                               protocol_id);
+                       ret = -EINVAL;
+                       goto err_free_fw_core;
+               }
+       }
+
+       /* Firmware Management connection is mandatory */
+       if (!fw_core->mgmt_connection) {
+               dev_err(&bundle->dev, "missing management connection\n");
+               ret = -ENODEV;
+               goto err_free_fw_core;
+       }
+
+       greybus_set_drvdata(bundle, fw_core);
+
+       return 0;
+
+err_destroy_connections:
+       gb_connection_destroy(fw_core->mgmt_connection);
+err_free_fw_core:
+       kfree(fw_core);
+
+       return ret;
+}
+
+static void gb_fw_core_disconnect(struct gb_bundle *bundle)
+{
+       struct gb_fw_core *fw_core = greybus_get_drvdata(bundle);
+
+       gb_connection_destroy(fw_core->mgmt_connection);
+
+       kfree(fw_core);
+}
+
+static const struct greybus_bundle_id gb_fw_core_id_table[] = {
+       { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FW_MANAGEMENT) },
+       { }
+};
+
+static struct greybus_driver gb_fw_core_driver = {
+       .name           = "gb-firmware",
+       .probe          = gb_fw_core_probe,
+       .disconnect     = gb_fw_core_disconnect,
+       .id_table       = gb_fw_core_id_table,
+};
+
+static int fw_core_init(void)
+{
+       return greybus_register(&gb_fw_core_driver);
+}
+module_init(fw_core_init);
+
+static void __exit fw_core_exit(void)
+{
+       greybus_deregister(&gb_fw_core_driver);
+}
+module_exit(fw_core_exit);
+
+MODULE_ALIAS("greybus:firmware");
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
+MODULE_DESCRIPTION("Greybus Firmware Bundle Driver");
+MODULE_LICENSE("GPL v2");
index 460fced979a42c5e4bb00a1f7c94b2ca170d440c..5d00f7de504171ca5c9909a20eaeb381d1791e97 100644 (file)
@@ -45,6 +45,8 @@ enum greybus_protocol {
        GREYBUS_PROTOCOL_SVC            = 0x14,
        GREYBUS_PROTOCOL_BOOTROM        = 0x15,
        GREYBUS_PROTOCOL_CAMERA_DATA    = 0x16,
+       GREYBUS_PROTOCOL_FW_DOWNLOAD    = 0x17,
+       GREYBUS_PROTOCOL_FW_MANAGEMENT  = 0x18,
                /* ... */
        GREYBUS_PROTOCOL_RAW            = 0xfe,
        GREYBUS_PROTOCOL_VENDOR         = 0xff,
@@ -73,6 +75,7 @@ enum greybus_class_type {
        /* 0x13 is unused */
        /* 0x14 is unused */
        GREYBUS_CLASS_BOOTROM           = 0x15,
+       GREYBUS_CLASS_FW_MANAGEMENT     = 0x16,
                /* ... */
        GREYBUS_CLASS_RAW               = 0xfe,
        GREYBUS_CLASS_VENDOR            = 0xff,