Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dcd2086a authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

greybus: SDIO: convert to a gpbridge driver



This converts the SDIO driver to be a gpbridge driver, moving it away
from the "legacy" interface.

Testing Done: Tested on gbsim.

Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
Signed-off-by: default avatarVaibhav Hiremath <vaibhav.hiremath@linaro.org>
[vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of
drivers. 2.Exit path fix. 3. Fixed review comments]
Reviewed-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Tested-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 315bea0e
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -255,6 +255,7 @@ static const struct greybus_bundle_id gb_gpbridge_id_table[] = {
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) },
	{ },
};
@@ -295,8 +296,8 @@ static int __init gpbridge_init(void)
		pr_err("error initializing uart driver\n");
		goto error_uart;
	}
	if (gb_sdio_protocol_init()) {
		pr_err("error initializing sdio protocol\n");
	if (gb_sdio_driver_init()) {
		pr_err("error initializing sdio driver\n");
		goto error_sdio;
	}
	if (gb_usb_protocol_init()) {
@@ -319,7 +320,7 @@ static int __init gpbridge_init(void)
error_i2c:
	gb_usb_protocol_exit();
error_usb:
	gb_sdio_protocol_exit();
	gb_sdio_driver_exit();
error_sdio:
	gb_uart_driver_exit();
error_uart:
@@ -340,7 +341,7 @@ static void __exit gpbridge_exit(void)
	gb_spi_protocol_exit();
	gb_i2c_driver_exit();
	gb_usb_protocol_exit();
	gb_sdio_protocol_exit();
	gb_sdio_driver_exit();
	gb_uart_driver_exit();
	gb_pwm_driver_exit();
	gb_gpio_driver_exit();
+2 −2
Original line number Diff line number Diff line
@@ -75,8 +75,8 @@ extern void gb_pwm_driver_exit(void);
extern int gb_uart_driver_init(void);
extern void gb_uart_driver_exit(void);

extern int gb_sdio_protocol_init(void);
extern void gb_sdio_protocol_exit(void);
extern int gb_sdio_driver_init(void);
extern void gb_sdio_driver_exit(void);

extern int gb_usb_protocol_init(void);
extern void gb_usb_protocol_exit(void);
+0 −1
Original line number Diff line number Diff line
@@ -237,7 +237,6 @@ static void legacy_disconnect(struct gb_bundle *bundle)

static const struct greybus_bundle_id legacy_id_table[] = {
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) },
	{ }
+57 −26
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

struct gb_sdio_host {
	struct gb_connection	*connection;
	struct gpbridge_device	*gpbdev;
	struct mmc_host		*mmc;
	struct mmc_request	*mrq;
	struct mutex		lock;	/* lock for this host */
@@ -199,11 +200,12 @@ static int _gb_sdio_process_events(struct gb_sdio_host *host, u8 event)
	return 0;
}

static int gb_sdio_event_recv(u8 type, struct gb_operation *op)
static int gb_sdio_request_handler(struct gb_operation *op)
{
	struct gb_sdio_host *host = gb_connection_get_data(op->connection);
	struct gb_message *request;
	struct gb_sdio_event_request *payload;
	u8 type = op->type;
	int ret =  0;
	u8 event;

@@ -706,27 +708,47 @@ static const struct mmc_host_ops gb_sdio_ops = {
	.get_cd		= gb_mmc_get_cd,
};

static int gb_sdio_connection_init(struct gb_connection *connection)
static int gb_sdio_probe(struct gpbridge_device *gpbdev,
			 const struct gpbridge_device_id *id)
{
	struct gb_connection *connection;
	struct mmc_host *mmc;
	struct gb_sdio_host *host;
	size_t max_buffer;
	int ret = 0;

	mmc = mmc_alloc_host(sizeof(*host), &connection->bundle->dev);
	mmc = mmc_alloc_host(sizeof(*host), &gpbdev->dev);
	if (!mmc)
		return -ENOMEM;

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

	host = mmc_priv(mmc);
	host->mmc = mmc;
	host->removed = true;

	host->connection = connection;
	gb_connection_set_data(connection, host);
	host->gpbdev = gpbdev;
	gb_gpbridge_set_data(gpbdev, host);

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

	ret = gb_gpbridge_get_version(connection);
	if (ret)
		goto exit_connection_disable;

	ret = gb_sdio_get_caps(host);
	if (ret < 0)
		goto free_mmc;
		goto exit_connection_disable;

	mmc->ops = &gb_sdio_ops;

@@ -740,45 +762,50 @@ static int gb_sdio_connection_init(struct gb_connection *connection)
	host->xfer_buffer = kzalloc(max_buffer, GFP_KERNEL);
	if (!host->xfer_buffer) {
		ret = -ENOMEM;
		goto free_mmc;
		goto exit_connection_disable;
	}
	mutex_init(&host->lock);
	spin_lock_init(&host->xfer);
	host->mrq_workqueue = alloc_workqueue("mmc-%s", 0, 1,
					      dev_name(&connection->bundle->dev));
					      dev_name(&gpbdev->dev));
	if (!host->mrq_workqueue) {
		ret = -ENOMEM;
		goto free_buffer;
		goto exit_buf_free;
	}
	INIT_WORK(&host->mrqwork, gb_sdio_mrq_work);

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

	ret = mmc_add_host(mmc);
	if (ret < 0)
		goto free_work;
		goto exit_wq_destroy;
	host->removed = false;
	ret = _gb_sdio_process_events(host, host->queued_events);
	host->queued_events = 0;

	return ret;

free_work:
exit_wq_destroy:
	destroy_workqueue(host->mrq_workqueue);
free_buffer:
exit_buf_free:
	kfree(host->xfer_buffer);
free_mmc:
	gb_connection_set_data(connection, NULL);
exit_connection_disable:
	gb_connection_disable(connection);
exit_connection_destroy:
	gb_connection_destroy(connection);
exit_mmc_free:
	mmc_free_host(mmc);

	return ret;
}

static void gb_sdio_connection_exit(struct gb_connection *connection)
static void gb_sdio_remove(struct gpbridge_device *gpbdev)
{
	struct gb_sdio_host *host = gb_gpbridge_get_data(gpbdev);
	struct gb_connection *connection = host->connection;
	struct mmc_host *mmc;
	struct gb_sdio_host *host = gb_connection_get_data(connection);

	if (!host)
		return;

	mutex_lock(&host->lock);
	host->removed = true;
@@ -788,19 +815,23 @@ static void gb_sdio_connection_exit(struct gb_connection *connection)

	flush_workqueue(host->mrq_workqueue);
	destroy_workqueue(host->mrq_workqueue);
	gb_connection_disable_rx(connection);
	mmc_remove_host(mmc);
	gb_connection_disable(connection);
	gb_connection_destroy(connection);
	kfree(host->xfer_buffer);
	mmc_free_host(mmc);
}

static struct gb_protocol sdio_protocol = {
	.name			= "sdio",
	.id			= GREYBUS_PROTOCOL_SDIO,
	.major			= GB_SDIO_VERSION_MAJOR,
	.minor			= GB_SDIO_VERSION_MINOR,
	.connection_init	= gb_sdio_connection_init,
	.connection_exit	= gb_sdio_connection_exit,
	.request_recv		= gb_sdio_event_recv,
static const struct gpbridge_device_id gb_sdio_id_table[] = {
	{ GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SDIO) },
	{ },
};

gb_builtin_protocol_driver(sdio_protocol);
static struct gpbridge_driver sdio_driver = {
	.name		= "sdio",
	.probe		= gb_sdio_probe,
	.remove		= gb_sdio_remove,
	.id_table	= gb_sdio_id_table,
};
gb_gpbridge_builtin_driver(sdio_driver);