コード例 #1
0
ファイル: legacy.c プロジェクト: lmsantana/greybus
static int legacy_connection_create(struct legacy_connection *lc,
					struct gb_bundle *bundle,
					struct greybus_descriptor_cport *desc)
{
	struct gb_connection *connection;
	struct gb_protocol *protocol;
	gb_request_handler_t handler;
	u8 major, minor;
	int ret;

	/*
	 * The legacy protocols have always been looked up using a hard-coded
	 * version of 0.1, despite (or perhaps rather, due to) the fact that
	 * module version negotiation could not take place until after the
	 * protocol was bound.
	 */
	major = 0;
	minor = 1;

	protocol = gb_protocol_get(desc->protocol_id, major, minor);
	if (!protocol) {
		dev_err(&bundle->dev,
				"protocol 0x%02x version %u.%u not found\n",
				desc->protocol_id, major, minor);
		return -EPROTONOSUPPORT;
	}

	if (protocol->request_recv)
		handler = legacy_request_handler;
	else
		handler = NULL;

	connection = gb_connection_create(bundle, le16_to_cpu(desc->id),
						handler);
	if (IS_ERR(connection)) {
		ret = PTR_ERR(connection);
		goto err_protocol_put;
	}

	/*
	 * NOTE: We need to keep a pointer to the protocol in the actual
	 *       connection structure for now.
	 */
	connection->protocol = protocol;

	lc->connection = connection;
	lc->protocol = protocol;

	return 0;

err_protocol_put:
	gb_protocol_put(protocol);

	return ret;
}
コード例 #2
0
ファイル: vibrator.c プロジェクト: AshishNamdev/linux
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;
}
コード例 #3
0
ファイル: firmware.c プロジェクト: tharagopinath/greybus
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;
}
コード例 #4
0
ファイル: gpio.c プロジェクト: AshishNamdev/linux
static int gb_gpio_probe(struct gbphy_device *gbphy_dev,
			 const struct gbphy_device_id *id)
{
	struct gb_connection *connection;
	struct gb_gpio_controller *ggc;
	struct gpio_chip *gpio;
	struct irq_chip *irqc;
	int ret;

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

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

	ggc->connection = connection;
	gb_connection_set_data(connection, ggc);
	ggc->gbphy_dev = gbphy_dev;
	gb_gbphy_set_data(gbphy_dev, ggc);

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

	ret = gb_gpio_controller_setup(ggc);
	if (ret)
		goto exit_connection_disable;

	irqc = &ggc->irqc;
	irqc->irq_mask = gb_gpio_irq_mask;
	irqc->irq_unmask = gb_gpio_irq_unmask;
	irqc->irq_set_type = gb_gpio_irq_set_type;
	irqc->irq_bus_lock = gb_gpio_irq_bus_lock;
	irqc->irq_bus_sync_unlock = gb_gpio_irq_bus_sync_unlock;
	irqc->name = "greybus_gpio";

	mutex_init(&ggc->irq_lock);

	gpio = &ggc->chip;

	gpio->label = "greybus_gpio";
	gpio->parent = &gbphy_dev->dev;
	gpio->owner = THIS_MODULE;

	gpio->request = gb_gpio_request;
	gpio->free = gb_gpio_free;
	gpio->get_direction = gb_gpio_get_direction;
	gpio->direction_input = gb_gpio_direction_input;
	gpio->direction_output = gb_gpio_direction_output;
	gpio->get = gb_gpio_get;
	gpio->set = gb_gpio_set;
	gpio->set_config = gb_gpio_set_config;
	gpio->to_irq = gb_gpio_to_irq;
	gpio->base = -1;		/* Allocate base dynamically */
	gpio->ngpio = ggc->line_max + 1;
	gpio->can_sleep = true;

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

	ret = gb_gpio_irqchip_add(gpio, irqc, 0,
				   handle_level_irq, IRQ_TYPE_NONE);
	if (ret) {
		dev_err(&gbphy_dev->dev, "failed to add irq chip: %d\n", ret);
		goto exit_line_free;
	}

	ret = gpiochip_add(gpio);
	if (ret) {
		dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret);
		goto exit_gpio_irqchip_remove;
	}

	gbphy_runtime_put_autosuspend(gbphy_dev);
	return 0;

exit_gpio_irqchip_remove:
	gb_gpio_irqchip_remove(ggc);
exit_line_free:
	kfree(ggc->lines);
exit_connection_disable:
	gb_connection_disable(connection);
exit_connection_destroy:
	gb_connection_destroy(connection);
exit_ggc_free:
	kfree(ggc);
	return ret;
}
コード例 #5
0
ファイル: bootrom.c プロジェクト: 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;
}
コード例 #6
0
ファイル: light.c プロジェクト: gregkh/greybus
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;
}