Esempio n. 1
0
/*
 * 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 bootrom protocol) for es2 chip only, when VID/PID
 * already sent during hotplug are 0.
 *
 * Otherwise, we keep intf->vendor_id/product_id same as what's passed
 * during hotplug.
 */
static void bootrom_es2_fixup_vid_pid(struct gb_bootrom *bootrom)
{
	struct gb_bootrom_get_vid_pid_response response;
	struct gb_connection *connection = bootrom->connection;
	struct gb_interface *intf = connection->bundle->intf;
	int ret;

	if (!(intf->quirks & GB_INTERFACE_QUIRK_NO_GMP_IDS))
		return;

	ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_GET_VID_PID,
				NULL, 0, &response, sizeof(response));
	if (ret) {
		dev_err(&connection->bundle->dev,
			"Bootrom get vid/pid operation failed (%d)\n", ret);
		return;
	}

	/*
	 * 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, "Bootrom got vid (0x%x)/pid (0x%x)\n",
		intf->vendor_id, intf->product_id);
}
Esempio n. 2
0
int gb_i2s_mgmt_get_supported_configurations(
	struct gb_connection *connection,
	struct gb_i2s_mgmt_get_supported_configurations_response *get_cfg,
	size_t size)
{
	return gb_operation_sync(connection,
				 GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS,
				 NULL, 0, get_cfg, size);
}
Esempio n. 3
0
static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc)
{
	struct gb_gpio_line_count_response response;
	int ret;

	ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_LINE_COUNT,
				NULL, 0, &response, sizeof(response));
	if (!ret)
		ggc->line_max = response.count;
	return ret;
}
Esempio n. 4
0
int gb_i2s_mgmt_deactivate_cport(struct gb_connection *connection,
					uint16_t cport)
{
	struct gb_i2s_mgmt_deactivate_cport_request request;

	memset(&request, 0, sizeof(request));
	request.cport = cpu_to_le16(cport);

	return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT,
				 &request, sizeof(request), NULL, 0);
}
Esempio n. 5
0
static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which)
{
	struct gb_gpio_activate_request request;
	int ret;

	request.which = which;
	ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE,
				 &request, sizeof(request), NULL, 0);
	if (!ret)
		ggc->lines[which].active = true;
	return ret;
}
Esempio n. 6
0
static int turn_off(struct gb_vibrator_device *vib)
{
	struct gb_bundle *bundle = vib->connection->bundle;
	int ret;

	ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF,
			NULL, 0, NULL, 0);

	gb_pm_runtime_put_autosuspend(bundle);

	return ret;
}
Esempio n. 7
0
static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on,
			unsigned long *delay_off)
{
	struct gb_channel *channel = get_channel_from_cdev(cdev);
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	struct gb_lights_blink_request req;
	bool old_active;
	int ret;

	if (channel->releasing)
		return -ESHUTDOWN;

	mutex_lock(&channel->lock);
	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		goto out_unlock;

	old_active = channel->active;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;
	req.time_on_ms = cpu_to_le16(*delay_on);
	req.time_off_ms = cpu_to_le16(*delay_off);

	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req,
				sizeof(req), NULL, 0);
	if (ret < 0)
		goto out_pm_put;

	if (delay_on)
		channel->active = true;
	else
		channel->active = false;

	/* we need to keep module alive when turning to active state */
	if (!old_active && channel->active)
		goto out_unlock;

	/*
	 * on the other hand if going to inactive we still hold a reference and
	 * need to put it, so we could go to suspend.
	 */
	if (old_active && !channel->active)
		gb_pm_runtime_put_autosuspend(bundle);

out_pm_put:
	gb_pm_runtime_put_autosuspend(bundle);
out_unlock:
	mutex_unlock(&channel->lock);

	return ret;
}
Esempio n. 8
0
static int gb_gpio_direction_in_operation(struct gb_gpio_controller *ggc,
					u8 which)
{
	struct gb_gpio_direction_in_request request;
	int ret;

	request.which = which;
	ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_IN,
				&request, sizeof(request), NULL, 0);
	if (!ret)
		ggc->lines[which].direction = 1;
	return ret;
}
Esempio n. 9
0
static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq)
{
	struct device *dev = &ggc->gbphy_dev->dev;
	struct gb_gpio_irq_unmask_request request;
	int ret;

	request.which = hwirq;
	ret = gb_operation_sync(ggc->connection,
				GB_GPIO_TYPE_IRQ_UNMASK,
				&request, sizeof(request), NULL, 0);
	if (ret)
		dev_err(dev, "failed to unmask irq: %d\n", ret);
}
Esempio n. 10
0
int gb_i2s_mgmt_set_samples_per_message(
				struct gb_connection *connection,
				uint16_t samples_per_message)
{
	struct gb_i2s_mgmt_set_samples_per_message_request request;

	memset(&request, 0, sizeof(request));
	request.samples_per_message = cpu_to_le16(samples_per_message);

	return gb_operation_sync(connection,
				 GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE,
				 &request, sizeof(request), NULL, 0);
}
Esempio n. 11
0
static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc,
					u8 which, bool value_high)
{
	struct gb_gpio_direction_out_request request;
	int ret;

	request.which = which;
	request.value = value_high ? 1 : 0;
	ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_OUT,
				&request, sizeof(request), NULL, 0);
	if (!ret)
		ggc->lines[which].direction = 0;
	return ret;
}
Esempio n. 12
0
static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc,
					u8 which, u16 debounce_usec)
{
	struct gb_gpio_set_debounce_request request;
	int ret;

	request.which = which;
	request.usec = cpu_to_le16(debounce_usec);
	ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_DEBOUNCE,
				&request, sizeof(request), NULL, 0);
	if (!ret)
		ggc->lines[which].debounce_usec = debounce_usec;
	return ret;
}
Esempio n. 13
0
static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc,
					u8 hwirq, u8 type)
{
	struct device *dev = &ggc->gbphy_dev->dev;
	struct gb_gpio_irq_type_request request;
	int ret;

	request.which = hwirq;
	request.type = type;

	ret = gb_operation_sync(ggc->connection,
				GB_GPIO_TYPE_IRQ_TYPE,
				&request, sizeof(request), NULL, 0);
	if (ret)
		dev_err(dev, "failed to set irq type: %d\n", ret);
}
Esempio n. 14
0
static int __gb_lights_led_brightness_set(struct gb_channel *channel)
{
	struct gb_lights_set_brightness_request req;
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	bool old_active;
	int ret;

	mutex_lock(&channel->lock);
	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		goto out_unlock;

	old_active = channel->active;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;
	req.brightness = (u8)channel->led->brightness;

	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS,
				&req, sizeof(req), NULL, 0);
	if (ret < 0)
		goto out_pm_put;

	if (channel->led->brightness)
		channel->active = true;
	else
		channel->active = false;

	/* we need to keep module alive when turning to active state */
	if (!old_active && channel->active)
		goto out_unlock;

	/*
	 * on the other hand if going to inactive we still hold a reference and
	 * need to put it, so we could go to suspend.
	 */
	if (old_active && !channel->active)
		gb_pm_runtime_put_autosuspend(bundle);

out_pm_put:
	gb_pm_runtime_put_autosuspend(bundle);
out_unlock:
	mutex_unlock(&channel->lock);

	return ret;
}
Esempio n. 15
0
static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc,
					u8 which)
{
	struct device *dev = &ggc->connection->bundle->dev;
	struct gb_gpio_deactivate_request request;
	int ret;

	request.which = which;
	ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE,
				 &request, sizeof(request), NULL, 0);
	if (ret) {
		dev_err(dev, "failed to deactivate gpio %u\n", which);
		return;
	}

	ggc->lines[which].active = false;
}
Esempio n. 16
0
static int gb_lights_get_count(struct gb_lights *glights)
{
	struct gb_lights_get_lights_response resp;
	int ret;

	ret = gb_operation_sync(glights->connection, GB_LIGHTS_TYPE_GET_LIGHTS,
				NULL, 0, &resp, sizeof(resp));
	if (ret < 0)
		return ret;

	if (!resp.lights_count)
		return -EINVAL;

	glights->lights_count = resp.lights_count;

	return 0;
}
Esempio n. 17
0
static int gb_lights_light_config(struct gb_lights *glights, u8 id)
{
	struct gb_light *light = &glights->lights[id];
	struct gb_lights_get_light_config_request req;
	struct gb_lights_get_light_config_response conf;
	int ret;
	int i;

	light->glights = glights;
	light->id = id;

	req.id = id;

	ret = gb_operation_sync(glights->connection,
				GB_LIGHTS_TYPE_GET_LIGHT_CONFIG,
				&req, sizeof(req), &conf, sizeof(conf));
	if (ret < 0)
		return ret;

	if (!conf.channel_count)
		return -EINVAL;
	if (!strlen(conf.name))
		return -EINVAL;

	light->channels_count = conf.channel_count;
	light->name = kstrndup(conf.name, NAMES_MAX, GFP_KERNEL);

	light->channels = kzalloc(light->channels_count *
				  sizeof(struct gb_channel), GFP_KERNEL);
	if (!light->channels)
		return -ENOMEM;

	/* First we collect all the configurations for all channels */
	for (i = 0; i < light->channels_count; i++) {
		light->channels[i].id = i;
		ret = gb_lights_channel_config(light, &light->channels[i]);
		if (ret < 0)
			return ret;
	}

	return 0;
}
Esempio n. 18
0
static int gb_lights_channel_flash_config(struct gb_channel *channel)
{
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_lights_get_channel_flash_config_request req;
	struct gb_lights_get_channel_flash_config_response conf;
	struct led_flash_setting *fset;
	int ret;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;

	ret = gb_operation_sync(connection,
				GB_LIGHTS_TYPE_GET_CHANNEL_FLASH_CONFIG,
				&req, sizeof(req), &conf, sizeof(conf));
	if (ret < 0)
		return ret;

	/*
	 * Intensity constraints for flash related modes: flash, torch,
	 * indicator.  They will be needed for v4l2 registration.
	 */
	fset = &channel->intensity_uA;
	fset->min = le32_to_cpu(conf.intensity_min_uA);
	fset->max = le32_to_cpu(conf.intensity_max_uA);
	fset->step = le32_to_cpu(conf.intensity_step_uA);

	/*
	 * On flash type, max brightness is set as the number of intensity steps
	 * available.
	 */
	channel->led->max_brightness = (fset->max - fset->min) / fset->step;

	/* Only the flash mode have the timeout constraints settings */
	if (channel->mode & GB_CHANNEL_MODE_FLASH) {
		fset = &channel->timeout_us;
		fset->min = le32_to_cpu(conf.timeout_min_us);
		fset->max = le32_to_cpu(conf.timeout_max_us);
		fset->step = le32_to_cpu(conf.timeout_step_us);
	}

	return 0;
}
Esempio n. 19
0
static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc,
					u8 which)
{
	struct gbphy_device *gbphy_dev = ggc->gbphy_dev;
	struct device *dev = &gbphy_dev->dev;
	struct gb_gpio_deactivate_request request;
	int ret;

	request.which = which;
	ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE,
				 &request, sizeof(request), NULL, 0);
	if (ret) {
		dev_err(dev, "failed to deactivate gpio %u\n", which);
		goto out_pm_put;
	}

	ggc->lines[which].active = false;

out_pm_put:
	gbphy_runtime_put_autosuspend(gbphy_dev);
}
Esempio n. 20
0
static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which)
{
	struct gb_gpio_activate_request request;
	struct gbphy_device *gbphy_dev = ggc->gbphy_dev;
	int ret;

	ret = gbphy_runtime_get_sync(gbphy_dev);
	if (ret)
		return ret;

	request.which = which;
	ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE,
				 &request, sizeof(request), NULL, 0);
	if (ret) {
		gbphy_runtime_put_autosuspend(gbphy_dev);
		return ret;
	}

	ggc->lines[which].active = true;

	return 0;
}
Esempio n. 21
0
int gb_i2s_send_data(struct gb_connection *connection,
					void *req_buf, void *source_addr,
					size_t len, int sample_num)
{
	struct gb_i2s_send_data_request *gb_req;
	int ret;

	gb_req = req_buf;
	gb_req->sample_number = cpu_to_le32(sample_num);

	memcpy((void *)&gb_req->data[0], source_addr, len);

	if (len < MAX_SEND_DATA_LEN)
		for (; len < MAX_SEND_DATA_LEN; len++)
			gb_req->data[len] = gb_req->data[len - SAMPLE_SIZE];

	gb_req->size = cpu_to_le32(len);

	ret = gb_operation_sync(connection, GB_I2S_DATA_TYPE_SEND_DATA,
				(void *) gb_req, SEND_DATA_BUF_LEN, NULL, 0);
	return ret;
}
Esempio n. 22
0
/*
 * 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 intf->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->ddbl1_manufacturer_id != ES2_DDBL1_MFR_ID ||
	    intf->ddbl1_product_id != ES2_DDBL1_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;
	}

	/*
	 * 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",
		intf->vendor_id, intf->product_id);
}
Esempio n. 23
0
static int gb_lights_color_set(struct gb_channel *channel, u32 color)
{
	struct gb_connection *connection = get_conn_from_channel(channel);
	struct gb_bundle *bundle = connection->bundle;
	struct gb_lights_set_color_request req;
	int ret;

	if (channel->releasing)
		return -ESHUTDOWN;

	ret = gb_pm_runtime_get_sync(bundle);
	if (ret < 0)
		return ret;

	req.light_id = channel->light->id;
	req.channel_id = channel->id;
	req.color = cpu_to_le32(color);
	ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR,
				&req, sizeof(req), NULL, 0);

	gb_pm_runtime_put_autosuspend(bundle);

	return ret;
}
Esempio n. 24
0
static int gb_firmware_get_version(struct gb_firmware *firmware)
{
	struct gb_bundle *bundle = firmware->connection->bundle;
	struct gb_firmware_version_request request;
	struct gb_firmware_version_response response;
	int ret;

	request.major = GB_FIRMWARE_VERSION_MAJOR;
	request.minor = GB_FIRMWARE_VERSION_MINOR;

	ret = gb_operation_sync(firmware->connection,
				GB_FIRMWARE_TYPE_VERSION,
				&request, sizeof(request), &response,
				sizeof(response));
	if (ret) {
		dev_err(&bundle->dev,
				"failed to get protocol version: %d\n",
				ret);
		return ret;
	}

	if (response.major > request.major) {
		dev_err(&bundle->dev,
				"unsupported major protocol version (%u > %u)\n",
				response.major, request.major);
		return -ENOTSUPP;
	}

	firmware->protocol_major = response.major;
	firmware->protocol_minor = response.minor;

	dev_dbg(&bundle->dev, "%s - %u.%u\n", __func__, response.major,
			response.minor);

	return 0;
}
Esempio n. 25
0
static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc,
					u8 which, bool value_high)
{
	struct device *dev = &ggc->gbphy_dev->dev;
	struct gb_gpio_set_value_request request;
	int ret;

	if (ggc->lines[which].direction == 1) {
		dev_warn(dev, "refusing to set value of input gpio %u\n",
			 which);
		return;
	}

	request.which = which;
	request.value = value_high ? 1 : 0;
	ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE,
				&request, sizeof(request), NULL, 0);
	if (ret) {
		dev_err(dev, "failed to set value of gpio %u\n", which);
		return;
	}

	ggc->lines[which].value = request.value;
}
Esempio n. 26
0
static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms)
{
	struct gb_bundle *bundle = vib->connection->bundle;
	int ret;

	ret = gb_pm_runtime_get_sync(bundle);
	if (ret)
		return ret;

	/* Vibrator was switched ON earlier */
	if (cancel_delayed_work_sync(&vib->delayed_work))
		turn_off(vib);

	ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON,
			NULL, 0, NULL, 0);
	if (ret) {
		gb_pm_runtime_put_autosuspend(bundle);
		return ret;
	}

	schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms));

	return 0;
}
Esempio n. 27
0
static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc,
					u8 which)
{
	struct device *dev = &ggc->gbphy_dev->dev;
	struct gb_gpio_get_direction_request request;
	struct gb_gpio_get_direction_response response;
	int ret;
	u8 direction;

	request.which = which;
	ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_DIRECTION,
				&request, sizeof(request),
				&response, sizeof(response));
	if (ret)
		return ret;

	direction = response.direction;
	if (direction && direction != 1) {
		dev_warn(dev, "gpio %u direction was %u (should be 0 or 1)\n",
			 which, direction);
	}
	ggc->lines[which].direction = direction ? 1 : 0;
	return 0;
}
Esempio n. 28
0
File: bootrom.c Progetto: mhei/linux
static int gb_bootrom_probe(struct gb_bundle *bundle,
                            const struct greybus_bundle_id *id)
{
    struct greybus_descriptor_cport *cport_desc;
    struct gb_connection *connection;
    struct gb_bootrom *bootrom;
    int ret;

    if (bundle->num_cports != 1)
        return -ENODEV;

    cport_desc = &bundle->cport_desc[0];
    if (cport_desc->protocol_id != GREYBUS_PROTOCOL_BOOTROM)
        return -ENODEV;

    bootrom = kzalloc(sizeof(*bootrom), GFP_KERNEL);
    if (!bootrom)
        return -ENOMEM;

    connection = gb_connection_create(bundle,
                                      le16_to_cpu(cport_desc->id),
                                      gb_bootrom_request_handler);
    if (IS_ERR(connection)) {
        ret = PTR_ERR(connection);
        goto err_free_bootrom;
    }

    gb_connection_set_data(connection, bootrom);

    bootrom->connection = connection;

    mutex_init(&bootrom->mutex);
    INIT_DELAYED_WORK(&bootrom->dwork, gb_bootrom_timedout);
    greybus_set_drvdata(bundle, bootrom);

    ret = gb_connection_enable_tx(connection);
    if (ret)
        goto err_connection_destroy;

    ret = gb_bootrom_get_version(bootrom);
    if (ret)
        goto err_connection_disable;

    bootrom_es2_fixup_vid_pid(bootrom);

    ret = gb_connection_enable(connection);
    if (ret)
        goto err_connection_disable;

    /* Refresh timeout */
    gb_bootrom_set_timeout(bootrom, NEXT_REQ_FIRMWARE_SIZE,
                           NEXT_REQ_TIMEOUT_MS);

    /* Tell bootrom we're ready. */
    ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_AP_READY, NULL, 0,
                            NULL, 0);
    if (ret) {
        dev_err(&connection->bundle->dev,
                "failed to send AP READY: %d\n", ret);
        goto err_cancel_timeout;
    }

    dev_dbg(&bundle->dev, "AP_READY sent\n");

    return 0;

err_cancel_timeout:
    gb_bootrom_cancel_timeout(bootrom);
err_connection_disable:
    gb_connection_disable(connection);
err_connection_destroy:
    gb_connection_destroy(connection);
err_free_bootrom:
    kfree(bootrom);

    return ret;
}
Esempio n. 29
0
int gb_i2s_mgmt_set_configuration(struct gb_connection *connection,
			struct gb_i2s_mgmt_set_configuration_request *set_cfg)
{
	return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_SET_CONFIGURATION,
				 set_cfg, sizeof(*set_cfg), NULL, 0);
}
Esempio n. 30
0
static int gb_firmware_probe(struct gb_bundle *bundle,
					const struct greybus_bundle_id *id)
{
	struct greybus_descriptor_cport *cport_desc;
	struct gb_connection *connection;
	struct gb_firmware *firmware;
	int ret;

	if (bundle->num_cports != 1)
		return -ENODEV;

	cport_desc = &bundle->cport_desc[0];
	if (cport_desc->protocol_id != GREYBUS_PROTOCOL_FIRMWARE)
		return -ENODEV;

	firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
	if (!firmware)
		return -ENOMEM;

	connection = gb_connection_create(bundle,
						le16_to_cpu(cport_desc->id),
						gb_firmware_request_handler);
	if (IS_ERR(connection)) {
		ret = PTR_ERR(connection);
		goto err_free_firmware;
	}

	gb_connection_set_data(connection, firmware);

	firmware->connection = connection;

	greybus_set_drvdata(bundle, firmware);

	ret = gb_connection_enable_tx(connection);
	if (ret)
		goto err_connection_destroy;

	ret = gb_firmware_get_version(firmware);
	if (ret)
		goto err_connection_disable;

	firmware_es2_fixup_vid_pid(firmware);

	ret = gb_connection_enable(connection);
	if (ret)
		goto err_connection_disable;

	/* Tell bootrom we're ready. */
	ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_AP_READY, NULL, 0,
				NULL, 0);
	if (ret) {
		dev_err(&connection->bundle->dev,
				"failed to send AP READY: %d\n", ret);
		goto err_connection_disable;
	}

	dev_dbg(&bundle->dev, "AP_READY sent\n");

	return 0;

err_connection_disable:
	gb_connection_disable(connection);
err_connection_destroy:
	gb_connection_destroy(connection);
err_free_firmware:
	kfree(firmware);

	return ret;
}