greybus: SDIO: convert to a gpbridge driver
authorGreg Kroah-Hartman <gregkh@google.com>
Thu, 5 May 2016 09:02:34 +0000 (14:32 +0530)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 5 May 2016 20:38:57 +0000 (13:38 -0700)
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>
drivers/staging/greybus/gpbridge.c
drivers/staging/greybus/gpbridge.h
drivers/staging/greybus/legacy.c
drivers/staging/greybus/sdio.c

index a65ab1609127206243cc35d085c4b8c4679a592a..d228e276f788088ad9eb0dda2ba2df83dc37ca66 100644 (file)
@@ -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 @@ error_spi:
 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();
index f5161c56cc9889cdc48b62be59bc43cc36947e57..3f1d19eb35f303d15eacddf2e17243820b126625 100644 (file)
@@ -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);
index ee122ad2334a48d4e82ba974e92b9a310787e61f..d94282d2dbe5775ce50c2fc2fbe672ef8d6ea37c 100644 (file)
@@ -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) },
        { }
index d4cbcb972e94c7e875237fa689704a77b14f1389..8ee4d4c5e73dae64a3bfe7c1eb3ef8ad6b9dfaa8 100644 (file)
@@ -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);