Beispiel #1
0
static int legacy_probe(struct gb_bundle *bundle,
			const struct greybus_bundle_id *id)
{
	struct greybus_descriptor_cport *cport_desc;
	struct legacy_data *data;
	struct legacy_connection *lc;
	int i;
	int ret;

	dev_dbg(&bundle->dev,
			"%s - bundle class = 0x%02x, num_cports = %zu\n",
			__func__, bundle->class, bundle->num_cports);

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

	data->num_cports = bundle->num_cports;
	data->connections = kcalloc(data->num_cports,
						sizeof(*data->connections),
						GFP_KERNEL);
	if (!data->connections) {
		ret = -ENOMEM;
		goto err_free_data;
	}

	for (i = 0; i < data->num_cports; ++i) {
		cport_desc = &bundle->cport_desc[i];
		lc = &data->connections[i];

		ret = legacy_connection_create(lc, bundle, cport_desc);
		if (ret)
			goto err_connections_destroy;
	}

	greybus_set_drvdata(bundle, data);

	for (i = 0; i < data->num_cports; ++i) {
		lc = &data->connections[i];

		ret = legacy_connection_init(lc);
		if (ret)
			goto err_connections_disable;
	}

	return 0;

err_connections_disable:
	for (--i; i >= 0; --i)
		legacy_connection_exit(&data->connections[i]);
err_connections_destroy:
	for (i = 0; i < data->num_cports; ++i)
		legacy_connection_destroy(&data->connections[i]);
	kfree(data->connections);
err_free_data:
	kfree(data);

	return ret;
}
Beispiel #2
0
static int gb_vibrator_probe(struct gb_bundle *bundle,
					const struct greybus_bundle_id *id)
{
	struct greybus_descriptor_cport *cport_desc;
	struct gb_connection *connection;
	struct gb_vibrator_device *vib;
	struct device *dev;
	int retval;

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

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

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

	connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
						NULL);
	if (IS_ERR(connection)) {
		retval = PTR_ERR(connection);
		goto err_free_vib;
	}
	gb_connection_set_data(connection, vib);

	vib->connection = connection;

	greybus_set_drvdata(bundle, vib);

	retval = gb_connection_enable(connection);
	if (retval)
		goto err_connection_destroy;

	/*
	 * For now we create a device in sysfs for the vibrator, but odds are
	 * there is a "real" device somewhere in the kernel for this, but I
	 * can't find it at the moment...
	 */
	vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL);
	if (vib->minor < 0) {
		retval = vib->minor;
		goto err_connection_disable;
	}
	dev = device_create(&vibrator_class, &bundle->dev,
			    MKDEV(0, 0), vib, "vibrator%d", vib->minor);
	if (IS_ERR(dev)) {
		retval = -EINVAL;
		goto err_ida_remove;
	}
	vib->dev = dev;

	INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker);

	gb_pm_runtime_put_autosuspend(bundle);

	return 0;

err_ida_remove:
	ida_simple_remove(&minors, vib->minor);
err_connection_disable:
	gb_connection_disable(connection);
err_connection_destroy:
	gb_connection_destroy(connection);
err_free_vib:
	kfree(vib);

	return retval;
}
Beispiel #3
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
static int gb_lights_probe(struct gb_bundle *bundle,
			   const struct greybus_bundle_id *id)
{
	struct greybus_descriptor_cport *cport_desc;
	struct gb_connection *connection;
	struct gb_lights *glights;
	int ret;

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

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

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

	mutex_init(&glights->lights_lock);

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

	glights->connection = connection;
	gb_connection_set_data(connection, glights);

	greybus_set_drvdata(bundle, glights);

	/* We aren't ready to receive an incoming request yet */
	ret = gb_connection_enable_tx(connection);
	if (ret)
		goto error_connection_destroy;

	/*
	 * Setup all the lights devices over this connection, if anything goes
	 * wrong tear down all lights
	 */
	ret = gb_lights_create_all(glights);
	if (ret < 0)
		goto error_connection_disable;

	/* We are ready to receive an incoming request now, enable RX as well */
	ret = gb_connection_enable(connection);
	if (ret)
		goto error_connection_disable;

	/* Enable & register lights */
	ret = gb_lights_register_all(glights);
	if (ret < 0)
		goto error_connection_disable;

	gb_pm_runtime_put_autosuspend(bundle);

	return 0;

error_connection_disable:
	gb_connection_disable(connection);
error_connection_destroy:
	gb_connection_destroy(connection);
out:
	gb_lights_release(glights);
	return ret;
}