greybus: firmware: Fetch es2 VID/PID to distinguish module vendors

The es2 chip doesn't have VID/PID programmed into the hardware and we
need to hack that up to distinguish different modules and their firmware
packages.

This fetches VID/PID (over firmware protocol) for es2 chip only, when
VID/PID already sent during hotplug are 0.

Since only the bootrom contains a firmware protocol cport, this only
affects bootrom's working and not nuttx.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Viresh Kumar 2015-11-26 15:33:46 +05:30 коммит произвёл Greg Kroah-Hartman
Родитель 32945d6ecc
Коммит f1e941a6e4
2 изменённых файлов: 57 добавлений и 1 удалений

Просмотреть файл

@ -11,9 +11,14 @@
#include "greybus.h"
#define ES2_UNIPRO_MFG_ID 0x00000126
#define ES2_UNIPRO_PROD_ID 0x00001000
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)
@ -22,6 +27,45 @@ static void free_firmware(struct gb_firmware *firmware)
firmware->fw = NULL;
}
/*
* The es2 chip doesn't have VID/PID programmed into the hardware and we need to
* hack that up to distinguish different modules and their firmware blobs.
*
* 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
* during hotplug.
*/
static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware)
{
struct gb_firmware_get_vid_pid_response response;
struct gb_connection *connection = firmware->connection;
struct gb_interface *intf = connection->bundle->intf;
int ret;
/*
* Use VID/PID specified at hotplug if:
* - Bridge ASIC chip isn't ES2
* - Received non-zero Vendor/Product ids
*/
if (intf->unipro_mfg_id != ES2_UNIPRO_MFG_ID ||
intf->unipro_prod_id != ES2_UNIPRO_PROD_ID ||
intf->vendor_id != 0 || intf->product_id != 0)
return;
ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_GET_VID_PID,
NULL, 0, &response, sizeof(response));
if (ret) {
dev_err(&connection->bundle->dev,
"Firmware get vid/pid operation failed (%d)\n", ret);
return;
}
firmware->vendor_id = le32_to_cpu(response.vendor_id);
firmware->product_id = le32_to_cpu(response.product_id);
}
/* This returns path of the firmware blob on the disk */
static int download_firmware(struct gb_firmware *firmware, u8 stage)
{
@ -41,7 +85,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->unipro_mfg_id, intf->unipro_prod_id,
intf->vendor_id, intf->product_id, stage);
firmware->vendor_id, firmware->product_id, stage);
return request_firmware(&firmware->fw, firmware_name,
&connection->bundle->dev);
@ -183,6 +227,11 @@ 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);
/*
* Module's Bootrom needs a way to know (currently), when to start
* sending requests to the AP. The version request is sent before this

Просмотреть файл

@ -158,6 +158,7 @@ struct gb_control_disconnected_request {
#define GB_FIRMWARE_TYPE_GET_FIRMWARE 0x03
#define GB_FIRMWARE_TYPE_READY_TO_BOOT 0x04
#define GB_FIRMWARE_TYPE_AP_READY 0x05 /* Request with no-payload */
#define GB_FIRMWARE_TYPE_GET_VID_PID 0x06 /* Request with no-payload */
/* Greybus firmware boot stages */
#define GB_FIRMWARE_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */
@ -197,6 +198,12 @@ struct gb_firmware_ready_to_boot_request {
} __packed;
/* Firmware protocol Ready to boot response has no payload */
/* Firmware protocol get VID/PID request has no payload */
struct gb_firmware_get_vid_pid_response {
__le32 vendor_id;
__le32 product_id;
} __packed;
/* Power Supply */