aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/sdio.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@google.com>2016-05-05 14:32:34 +0530
committerGreg Kroah-Hartman <gregkh@google.com>2016-05-05 13:38:57 -0700
commitdcd2086aa87e274e2f2f96eae449a27548637dd9 (patch)
treebe0bd54b33bbecab93c7dc06ffe3d5e7103d9170 /drivers/staging/greybus/sdio.c
parentgreybus: GPIO: convert to a gpbridge driver (diff)
downloadlinux-dev-dcd2086aa87e274e2f2f96eae449a27548637dd9.tar.xz
linux-dev-dcd2086aa87e274e2f2f96eae449a27548637dd9.zip
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: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Vaibhav 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: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/sdio.c')
-rw-r--r--drivers/staging/greybus/sdio.c83
1 files changed, 57 insertions, 26 deletions
diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c
index d4cbcb972e94..8ee4d4c5e73d 100644
--- a/drivers/staging/greybus/sdio.c
+++ b/drivers/staging/greybus/sdio.c
@@ -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);