summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hovold <johan@hovoldconsulting.com>2016-03-29 18:56:08 -0400
committerGreg Kroah-Hartman <gregkh@google.com>2016-03-30 14:23:19 -0700
commit153ff7e76ddb2fd5ab3d790c0139154dfd5464f1 (patch)
tree222fe2929cb69033ca747c02b2496e21775071ef
parentaf1471e7a903c18e98adf49fc9e2e444915b48c8 (diff)
downloadop-kernel-dev-153ff7e76ddb2fd5ab3d790c0139154dfd5464f1.zip
op-kernel-dev-153ff7e76ddb2fd5ab3d790c0139154dfd5464f1.tar.gz
greybus: interface: read DME attributes at activation
Read the DDBL1 and Ara DME attributes when activating an interface. These values are currently provided by the SVC in the intf_hotplug request, which is about to go away. Note that there are currently no standard Ara VID and PID attributes and that Toshiba uses attributes from the reserved space in ES3. For now, we therefore refuse to enumerate any non-Toshiba bridges. Also note that the Ara serial number is currently not supported. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
-rw-r--r--drivers/staging/greybus/interface.c72
-rw-r--r--drivers/staging/greybus/interface.h1
-rw-r--r--drivers/staging/greybus/svc.c18
3 files changed, 78 insertions, 13 deletions
diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c
index 823debb..c7793a9 100644
--- a/drivers/staging/greybus/interface.c
+++ b/drivers/staging/greybus/interface.c
@@ -12,6 +12,74 @@
#define GB_INTERFACE_DEVICE_ID_BAD 0xff
+/* DME attributes */
+#define DME_DDBL1_MANUFACTURERID 0x5003
+#define DME_DDBL1_PRODUCTID 0x5004
+
+#define DME_TOSHIBA_ARA_VID 0x6000
+#define DME_TOSHIBA_ARA_PID 0x6001
+
+/* DDBL1 Manufacturer and Product ids */
+#define TOSHIBA_DMID 0x0126
+#define TOSHIBA_ES2_BRIDGE_DPID 0x1000
+#define TOSHIBA_ES3_APBRIDGE_DPID 0x1001
+#define TOSHIBA_ES3_GPBRIDGE_DPID 0x1002
+
+
+static int gb_interface_dme_attr_get(struct gb_interface *intf,
+ u16 attr, u32 *val)
+{
+ return gb_svc_dme_peer_get(intf->hd->svc, intf->interface_id,
+ attr, DME_ATTR_SELECTOR_INDEX_NULL,
+ val);
+}
+
+static int gb_interface_read_ara_dme(struct gb_interface *intf)
+{
+ int ret;
+
+ /*
+ * Unless this is a Toshiba bridge, bail out until we have defined
+ * standard Ara attributes.
+ */
+ if (intf->ddbl1_manufacturer_id != TOSHIBA_DMID) {
+ dev_err(&intf->dev, "unknown manufacturer %08x\n",
+ intf->ddbl1_manufacturer_id);
+ return -ENODEV;
+ }
+
+ ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_VID,
+ &intf->vendor_id);
+ if (ret)
+ return ret;
+
+ ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_PID,
+ &intf->product_id);
+ if (ret)
+ return ret;
+
+ /* FIXME: serial number not implemented */
+ intf->serial_number = 0;
+
+ return 0;
+}
+
+static int gb_interface_read_dme(struct gb_interface *intf)
+{
+ int ret;
+
+ ret = gb_interface_dme_attr_get(intf, DME_DDBL1_MANUFACTURERID,
+ &intf->ddbl1_manufacturer_id);
+ if (ret)
+ return ret;
+
+ ret = gb_interface_dme_attr_get(intf, DME_DDBL1_PRODUCTID,
+ &intf->ddbl1_product_id);
+ if (ret)
+ return ret;
+
+ return gb_interface_read_ara_dme(intf);
+}
static int gb_interface_route_create(struct gb_interface *intf)
{
@@ -279,6 +347,10 @@ int gb_interface_activate(struct gb_interface *intf)
{
int ret;
+ ret = gb_interface_read_dme(intf);
+ if (ret)
+ return ret;
+
ret = gb_interface_route_create(intf);
if (ret)
return ret;
diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h
index 8b6fcfe..1a6ce5c 100644
--- a/drivers/staging/greybus/interface.h
+++ b/drivers/staging/greybus/interface.h
@@ -27,7 +27,6 @@ struct gb_interface {
char *vendor_string;
char *product_string;
- /* Information taken from the hotplug event */
u32 ddbl1_manufacturer_id;
u32 ddbl1_product_id;
u32 vendor_id;
diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c
index 96d3d55..0659815 100644
--- a/drivers/staging/greybus/svc.c
+++ b/drivers/staging/greybus/svc.c
@@ -460,11 +460,12 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
return;
}
- intf->ddbl1_manufacturer_id = le32_to_cpu(request->data.ddbl1_mfr_id);
- intf->ddbl1_product_id = le32_to_cpu(request->data.ddbl1_prod_id);
- intf->vendor_id = le32_to_cpu(request->data.ara_vend_id);
- intf->product_id = le32_to_cpu(request->data.ara_prod_id);
- intf->serial_number = le64_to_cpu(request->data.serial_number);
+ ret = gb_interface_activate(intf);
+ if (ret) {
+ dev_err(&svc->dev, "failed to activate interface %u: %d\n",
+ intf_id, ret);
+ goto err_interface_add;
+ }
/*
* Use VID/PID specified at hotplug if:
@@ -480,13 +481,6 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
intf->product_id = product_id;
}
- ret = gb_interface_activate(intf);
- if (ret) {
- dev_err(&svc->dev, "failed to activate interface %u: %d\n",
- intf_id, ret);
- goto err_interface_add;
- }
-
ret = gb_interface_enable(intf);
if (ret) {
dev_err(&svc->dev, "failed to enable interface %u: %d\n",
OpenPOWER on IntegriCloud