summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/greybus/gpbridge.c7
-rw-r--r--drivers/staging/greybus/gpbridge.h4
-rw-r--r--drivers/staging/greybus/legacy.c1
-rw-r--r--drivers/staging/greybus/spi.c79
4 files changed, 62 insertions, 29 deletions
diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c
index d228e276f788..1dc6c8f85778 100644
--- a/drivers/staging/greybus/gpbridge.c
+++ b/drivers/staging/greybus/gpbridge.c
@@ -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();
diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h
index 3f1d19eb35f3..ab3900363ec8 100644
--- a/drivers/staging/greybus/gpbridge.h
+++ b/drivers/staging/greybus/gpbridge.h
@@ -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 */
diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c
index d94282d2dbe5..95d1eda98f72 100644
--- a/drivers/staging/greybus/legacy.c
+++ b/drivers/staging/greybus/legacy.c
@@ -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) },
{ }
};
diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c
index ce706ed218e2..dc811b142432 100644
--- a/drivers/staging/greybus/spi.c
+++ b/drivers/staging/greybus/spi.c
@@ -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);