diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 823debb40272..c7793a93c802 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 8b6fcfe90883..1a6ce5ce6e6c 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 96d3d55f54ed..0659815248f9 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",