Commit f1e941a6 authored by Viresh Kumar's avatar Viresh Kumar Committed by Greg Kroah-Hartman
Browse files

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: default avatarViresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 32945d6e
Loading
Loading
Loading
Loading
+50 −1
Original line number Diff line number Diff line
@@ -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
+7 −0
Original line number Diff line number Diff line
@@ -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 */