summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@google.com>2015-04-07 18:26:53 (GMT)
committerGreg Kroah-Hartman <gregkh@google.com>2015-04-09 20:50:09 (GMT)
commit0f035acdedcb4f016c2b7cc23758d9191713d951 (patch)
tree4d649229a91c19b8f86ed122b6ad224a22836dcf
parent764e824e2fa5cca0d7c671ae58e65cd06aed0fce (diff)
downloadlinux-0f035acdedcb4f016c2b7cc23758d9191713d951.tar.xz
greybus: endo: add endo structures and logic
This adds endo.c and endo.h and provides functions to create an endo and the initial 0x0555 set of modules. But, it doesn't hook this logic up into the running code yet, that comes next. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Reviewed-by: Alex Elder <elder@linaro.org>
-rw-r--r--drivers/staging/greybus/Makefile1
-rw-r--r--drivers/staging/greybus/core.c8
-rw-r--r--drivers/staging/greybus/endo.c164
-rw-r--r--drivers/staging/greybus/endo.h32
-rw-r--r--drivers/staging/greybus/greybus.h7
5 files changed, 212 insertions, 0 deletions
diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile
index f6ad19a..9945cb8 100644
--- a/drivers/staging/greybus/Makefile
+++ b/drivers/staging/greybus/Makefile
@@ -2,6 +2,7 @@ greybus-y := core.o \
debugfs.o \
ap.o \
manifest.o \
+ endo.o \
module.o \
interface.o \
bundle.o \
diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c
index da62c54..7c701f3 100644
--- a/drivers/staging/greybus/core.c
+++ b/drivers/staging/greybus/core.c
@@ -51,6 +51,14 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
struct gb_bundle *bundle = NULL;
struct gb_connection *connection = NULL;
+ if (is_gb_endo(dev)) {
+ /*
+ * Not much to do for an endo, just fall through, as the
+ * "default" attributes are good enough for us.
+ */
+ return 0;
+ }
+
if (is_gb_module(dev)) {
module = to_gb_module(dev);
} else if (is_gb_interface(dev)) {
diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c
new file mode 100644
index 0000000..e3bb25f
--- /dev/null
+++ b/drivers/staging/greybus/endo.c
@@ -0,0 +1,164 @@
+/*
+ * Greybus endo code
+ *
+ * Copyright 2015 Google Inc.
+ * Copyright 2014 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#include "greybus.h"
+
+/* endo sysfs attributes */
+static ssize_t serial_number_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gb_endo *endo = to_gb_endo(dev);
+
+ return sprintf(buf, "%s", &endo->svc.serial_number[0]);
+}
+static DEVICE_ATTR_RO(serial_number);
+
+static ssize_t version_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct gb_endo *endo = to_gb_endo(dev);
+
+ return sprintf(buf, "%s", &endo->svc.version[0]);
+}
+static DEVICE_ATTR_RO(version);
+
+static struct attribute *endo_attrs[] = {
+ &dev_attr_serial_number.attr,
+ &dev_attr_version.attr,
+ NULL,
+};
+static const struct attribute_group endo_group = {
+ .attrs = endo_attrs,
+ .name = "SVC",
+};
+static const struct attribute_group *endo_groups[] = {
+ &endo_group,
+ NULL,
+};
+
+static void greybus_endo_release(struct device *dev)
+{
+ struct gb_endo *endo = to_gb_endo(dev);
+
+ kfree(endo);
+}
+
+struct device_type greybus_endo_type = {
+ .name = "greybus_endo",
+ .release = greybus_endo_release,
+};
+
+
+/*
+ * Endo "types" have different module locations, these are tables based on those
+ * types that list the module ids for the different locations.
+ *
+ * List must end with 0x00 in order to properly terminate the list.
+ */
+static u8 endo_0555[] = {
+ 0x01,
+ 0x03,
+ 0x05,
+ 0x07,
+ 0x08,
+ 0x0a,
+ 0x0c,
+ 0x00,
+};
+
+
+static int create_modules(struct gb_endo *endo)
+{
+ struct gb_module *module;
+ u8 *endo_modules;
+ int i;
+
+ /* Depending on the endo type, create a bunch of different modules */
+ switch (endo->type) {
+ case 0x0555:
+ endo_modules = &endo_0555[0];
+ break;
+ default:
+ dev_err(&endo->dev, "Unknown endo type 0x%04x, aborting!",
+ endo->type);
+ return -EINVAL;
+ }
+
+ for (i = 0; endo_modules[i] != 0x00; ++i) {
+// module = gb_module_create(&endo->dev, endo_modules[i]);
+ if (!module)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void remove_modules(struct gb_endo *endo)
+{
+ /*
+ * We really don't care how many modules have been created, or what the
+ * configuration of them are, let's just enumerate over everything in
+ * the system and delete all found modules.
+ */
+
+}
+
+struct gb_endo *gb_endo_create(struct greybus_host_device *hd)
+{
+ struct gb_endo *endo;
+ int retval;
+
+ endo = kzalloc(sizeof(*endo), GFP_KERNEL);
+ if (!endo)
+ return NULL;
+
+ endo->dev.parent = hd->parent;
+ endo->dev.bus = &greybus_bus_type;
+ endo->dev.type = &greybus_endo_type;
+ endo->dev.groups = endo_groups;
+ endo->dev.dma_mask = hd->parent->dma_mask;
+ device_initialize(&endo->dev);
+
+ // FIXME - determine endo "type" from the SVC
+ // Also get the version and serial number from the SVC, right now we are
+ // using "fake" numbers.
+ strcpy(&endo->svc.serial_number[0], "042");
+ strcpy(&endo->svc.version[0], "0.0");
+ endo->type = 0x0555;
+
+ dev_set_name(&endo->dev, "endo-0x%04x", endo->type);
+ retval = device_add(&endo->dev);
+ if (retval) {
+ dev_err(hd->parent, "failed to add endo device of type 0x%04x\n",
+ endo->type);
+ put_device(&endo->dev);
+ kfree(endo);
+ return NULL;
+ }
+
+ retval = create_modules(endo);
+ if (retval) {
+ gb_endo_remove(endo);
+ return NULL;
+ }
+
+ return endo;
+}
+
+void gb_endo_remove(struct gb_endo *endo)
+{
+ if (!endo)
+ return;
+
+ /* remove all modules first */
+ remove_modules(endo);
+
+ device_unregister(&endo->dev);
+}
+
diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h
new file mode 100644
index 0000000..649093e
--- /dev/null
+++ b/drivers/staging/greybus/endo.h
@@ -0,0 +1,32 @@
+/*
+ * Greybus endo code
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#ifndef __ENDO_H
+#define __ENDO_H
+
+/* Greybus "public" definitions" */
+struct gb_svc {
+ u8 serial_number[10];
+ u8 version[10];
+};
+
+struct gb_endo {
+ struct device dev;
+ struct gb_svc svc;
+ u16 type;
+};
+#define to_gb_endo(d) container_of(d, struct gb_endo, dev)
+
+
+/* Greybus "private" definitions */
+struct greybus_host_device;
+
+struct gb_endo *gb_endo_create(struct greybus_host_device *hd);
+void gb_endo_remove(struct gb_endo *endo);
+
+#endif /* __ENDO_H */
diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h
index 8d4bde3..e0aae42 100644
--- a/drivers/staging/greybus/greybus.h
+++ b/drivers/staging/greybus/greybus.h
@@ -24,6 +24,7 @@
#include "greybus_id.h"
#include "greybus_manifest.h"
#include "manifest.h"
+#include "endo.h"
#include "module.h"
#include "interface.h"
#include "bundle.h"
@@ -158,11 +159,17 @@ void gb_uart_device_exit(struct gb_connection *connection);
int svc_set_route_send(struct gb_bundle *bundle,
struct greybus_host_device *hd);
+extern struct device_type greybus_endo_type;
extern struct device_type greybus_module_type;
extern struct device_type greybus_interface_type;
extern struct device_type greybus_bundle_type;
extern struct device_type greybus_connection_type;
+static inline int is_gb_endo(const struct device *dev)
+{
+ return dev->type == &greybus_endo_type;
+}
+
static inline int is_gb_module(const struct device *dev)
{
return dev->type == &greybus_module_type;