greybus: SPI: convert to a gpbridge driver
authorGreg Kroah-Hartman <gregkh@google.com>
Thu, 5 May 2016 09:02:35 +0000 (14:32 +0530)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 5 May 2016 20:38:57 +0000 (13:38 -0700)
This converts the SPI 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/spi.c

index d228e276f788088ad9eb0dda2ba2df83dc37ca66..1dc6c8f857789d4e45da02d4cf9523d92a4a854e 100644 (file)
@@ -256,6 +256,7 @@ static const struct greybus_bundle_id gb_gpbridge_id_table[] = {
        { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) },
        { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) },
        { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) },
+       { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) },
        { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) },
        { },
 };
@@ -308,8 +309,8 @@ static int __init gpbridge_init(void)
                pr_err("error initializing i2c driver\n");
                goto error_i2c;
        }
-       if (gb_spi_protocol_init()) {
-               pr_err("error initializing spi protocol\n");
+       if (gb_spi_driver_init()) {
+               pr_err("error initializing spi driver\n");
                goto error_spi;
        }
 
@@ -338,7 +339,7 @@ module_init(gpbridge_init);
 
 static void __exit gpbridge_exit(void)
 {
-       gb_spi_protocol_exit();
+       gb_spi_driver_exit();
        gb_i2c_driver_exit();
        gb_usb_protocol_exit();
        gb_sdio_driver_exit();
index 3f1d19eb35f303d15eacddf2e17243820b126625..ab3900363ec841aae1c5ab096aed0cee976201c3 100644 (file)
@@ -84,8 +84,8 @@ extern void gb_usb_protocol_exit(void);
 extern int gb_i2c_driver_init(void);
 extern void gb_i2c_driver_exit(void);
 
-extern int gb_spi_protocol_init(void);
-extern void gb_spi_protocol_exit(void);
+extern int gb_spi_driver_init(void);
+extern void gb_spi_driver_exit(void);
 
 #endif /* __GPBRIDGE_H */
 
index d94282d2dbe5775ce50c2fc2fbe672ef8d6ea37c..95d1eda98f728d030658ed3179215170445d7178 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_SPI) },
        { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) },
        { }
 };
index ce706ed218e2e98c05360ece20faaefa23cda1d2..dc811b1424324700b57059f3ff4b8ccaa941cac3 100644 (file)
@@ -18,6 +18,7 @@
 
 struct gb_spi {
        struct gb_connection    *connection;
+       struct gpbridge_device  *gpbdev;
        struct spi_transfer     *first_xfer;
        struct spi_transfer     *last_xfer;
        u32                     rx_xfer_offset;
@@ -174,7 +175,7 @@ gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection,
                spi->last_xfer = xfer;
 
                if (!xfer->tx_buf && !xfer->rx_buf) {
-                       dev_err(&connection->bundle->dev,
+                       dev_err(&spi->gpbdev->dev,
                                "bufferless transfer, length %u\n", xfer->len);
                        msg->state = GB_SPI_STATE_MSG_ERROR;
                        return NULL;
@@ -342,7 +343,7 @@ static int gb_spi_transfer_one_message(struct spi_master *master,
                        if (response)
                                gb_spi_decode_response(spi, msg, response);
                } else {
-                       dev_err(&connection->bundle->dev,
+                       dev_err(&spi->gpbdev->dev,
                                "transfer operation failed: %d\n", ret);
                        msg->state = GB_SPI_STATE_MSG_ERROR;
                }
@@ -450,28 +451,48 @@ static int gb_spi_setup_device(struct gb_spi *spi, u8 cs)
        return 0;
 }
 
-static int gb_spi_connection_init(struct gb_connection *connection)
+static int gb_spi_probe(struct gpbridge_device *gpbdev,
+                       const struct gpbridge_device_id *id)
 {
+       struct gb_connection *connection;
        struct gb_spi *spi;
        struct spi_master *master;
        int ret;
        u8 i;
 
        /* Allocate master with space for data */
-       master = spi_alloc_master(&connection->bundle->dev, sizeof(*spi));
+       master = spi_alloc_master(&gpbdev->dev, sizeof(*spi));
        if (!master) {
-               dev_err(&connection->bundle->dev, "cannot alloc SPI master\n");
+               dev_err(&gpbdev->dev, "cannot alloc SPI master\n");
                return -ENOMEM;
        }
 
+       connection = gb_connection_create(gpbdev->bundle,
+                                         le16_to_cpu(gpbdev->cport_desc->id),
+                                         NULL);
+       if (IS_ERR(connection)) {
+               ret = PTR_ERR(connection);
+               goto exit_spi_put;
+       }
+
        spi = spi_master_get_devdata(master);
        spi->connection = connection;
        gb_connection_set_data(connection, master);
+       spi->gpbdev = gpbdev;
+       gb_gpbridge_set_data(gpbdev, master);
+
+       ret = gb_connection_enable(connection);
+       if (ret)
+               goto exit_connection_destroy;
+
+       ret = gb_gpbridge_get_version(connection);
+       if (ret)
+               goto exit_connection_disable;
 
        /* get master configuration */
        ret = gb_spi_get_master_config(spi);
        if (ret)
-               goto out_put_master;
+               goto exit_connection_disable;
 
        master->bus_num = -1; /* Allow spi-core to allocate it dynamically */
        master->num_chipselect = spi->num_chipselect;
@@ -486,42 +507,54 @@ static int gb_spi_connection_init(struct gb_connection *connection)
 
        ret = spi_register_master(master);
        if (ret < 0)
-               goto out_put_master;
+               goto exit_connection_disable;
 
        /* now, fetch the devices configuration */
        for (i = 0; i < spi->num_chipselect; i++) {
                ret = gb_spi_setup_device(spi, i);
                if (ret < 0) {
-                       dev_err(&connection->bundle->dev,
-                               "failed to allocated spi device: %d\n", ret);
-                       spi_unregister_master(master);
-                       break;
+                       dev_err(&gpbdev->dev,
+                               "failed to allocate spi device %d: %d\n",
+                               i, ret);
+                       goto exit_spi_unregister;
                }
        }
 
        return ret;
 
-out_put_master:
+exit_spi_unregister:
+       spi_unregister_master(master);
+exit_connection_disable:
+       gb_connection_disable(connection);
+exit_connection_destroy:
+       gb_connection_destroy(connection);
+exit_spi_put:
        spi_master_put(master);
 
        return ret;
 }
 
-static void gb_spi_connection_exit(struct gb_connection *connection)
+static void gb_spi_remove(struct gpbridge_device *gpbdev)
 {
-       struct spi_master *master = gb_connection_get_data(connection);
+       struct spi_master *master = gb_gpbridge_get_data(gpbdev);
+       struct gb_spi *spi = spi_master_get_devdata(master);
+       struct gb_connection *connection = spi->connection;
 
        spi_unregister_master(master);
+       gb_connection_disable(connection);
+       gb_connection_destroy(connection);
+       spi_master_put(master);
 }
 
-static struct gb_protocol spi_protocol = {
-       .name                   = "spi",
-       .id                     = GREYBUS_PROTOCOL_SPI,
-       .major                  = GB_SPI_VERSION_MAJOR,
-       .minor                  = GB_SPI_VERSION_MINOR,
-       .connection_init        = gb_spi_connection_init,
-       .connection_exit        = gb_spi_connection_exit,
-       .request_recv           = NULL,
+static const struct gpbridge_device_id gb_spi_id_table[] = {
+       { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SPI) },
+       { },
 };
 
-gb_builtin_protocol_driver(spi_protocol);
+static struct gpbridge_driver spi_driver = {
+       .name           = "spi",
+       .probe          = gb_spi_probe,
+       .remove         = gb_spi_remove,
+       .id_table       = gb_spi_id_table,
+};
+gb_gpbridge_builtin_driver(spi_driver);