summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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;
OpenPOWER on IntegriCloud