From f3e6c0971af62c81d0a9f0b408ae0e97248e2976 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 22 Jan 2016 16:16:08 +0530 Subject: [PATCH] greybus: svc: Expose and retain VID/PID received from bootrom for ES2 ES2 chips doesn't have efuses for storing module's vendor_id and product_id and so we have hacked bootrom earlier using firmware protocol, so that VID/PID can be received for fetching firmware packages. Another requirement is to expose them to sysfs, so that modules can be identified properly. That can be easily solved by updating interface's VID/PID, when fetched using firmware protocol and later reusing them while the module switches its identity from bootrom to firmware. Do that only if the module is ES2 and the VID/PID sent during hotplug are both 0. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/firmware.c | 22 ++++++++++++---------- drivers/staging/greybus/svc.c | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index ee239a913e0c..37895107e427 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -14,8 +14,6 @@ struct gb_firmware { struct gb_connection *connection; const struct firmware *fw; - u32 vendor_id; - u32 product_id; }; static void free_firmware(struct gb_firmware *firmware) @@ -31,7 +29,7 @@ static void free_firmware(struct gb_firmware *firmware) * This fetches VID/PID (over firmware protocol) for es2 chip only, when VID/PID * already sent during hotplug are 0. * - * Otherwise, we keep firmware->vendor_id/product_id same as what's passed + * Otherwise, we keep intf->vendor_id/product_id same as what's passed * during hotplug. */ static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) @@ -59,11 +57,18 @@ static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) return; } - firmware->vendor_id = le32_to_cpu(response.vendor_id); - firmware->product_id = le32_to_cpu(response.product_id); + /* + * NOTE: This is hacked, so that the same values of VID/PID can be used + * by next firmware level as well. The uevent for bootrom will still + * have VID/PID as 0, though after this point the sysfs files will start + * showing the updated values. But yeah, that's a bit racy as the same + * sysfs files would be showing 0 before this point. + */ + intf->vendor_id = le32_to_cpu(response.vendor_id); + intf->product_id = le32_to_cpu(response.product_id); dev_dbg(&connection->bundle->dev, "Firmware got vid (0x%x)/pid (0x%x)\n", - firmware->vendor_id, firmware->product_id); + intf->vendor_id, intf->product_id); } /* This returns path of the firmware blob on the disk */ @@ -86,7 +91,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) snprintf(firmware_name, sizeof(firmware_name), "ara_%08x_%08x_%08x_%08x_%02x.tftf", intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, - firmware->vendor_id, firmware->product_id, stage); + intf->vendor_id, intf->product_id, stage); // FIXME: // Turn to dev_dbg later after everyone has valid bootloaders with good @@ -246,9 +251,6 @@ static int gb_firmware_connection_init(struct gb_connection *connection) firmware->connection = connection; connection->private = firmware; - firmware->vendor_id = connection->intf->vendor_id; - firmware->product_id = connection->intf->product_id; - firmware_es2_fixup_vid_pid(firmware); /* Tell bootrom we're ready. */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index feadb624cfd4..85eb7eaae737 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -464,6 +464,8 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) struct gb_host_device *hd = connection->hd; struct gb_interface *intf; u8 intf_id, device_id; + u32 vendor_id = 0; + u32 product_id = 0; int ret; /* The request message size has already been verified. */ @@ -474,6 +476,14 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf = gb_interface_find(hd, intf_id); if (intf) { + /* + * For ES2, we need to maintain the same vendor/product ids we + * got from bootrom, otherwise userspace can't distinguish + * between modules. + */ + vendor_id = intf->vendor_id; + product_id = intf->product_id; + /* * We have received a hotplug request for an interface that * already exists. @@ -506,6 +516,20 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf->product_id = le32_to_cpu(request->data.ara_prod_id); intf->serial_number = le64_to_cpu(request->data.serial_number); + /* + * Use VID/PID specified at hotplug if: + * - Bridge ASIC chip isn't ES2 + * - Received non-zero Vendor/Product ids + * + * Otherwise, use the ids we received from bootrom. + */ + if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && + intf->ddbl1_product_id == ES2_DDBL1_PROD_ID && + intf->vendor_id == 0 && intf->product_id == 0) { + intf->vendor_id = vendor_id; + intf->product_id = product_id; + } + ret = gb_svc_read_and_clear_module_boot_status(intf); if (ret) { dev_err(&svc->dev, "failed to clear boot status of interface %u: %d\n", -- 2.39.5