summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/greybus/Makefile4
-rw-r--r--drivers/staging/greybus/spilib.c (renamed from drivers/staging/greybus/spi.c)126
-rw-r--r--drivers/staging/greybus/spilib.h18
3 files changed, 93 insertions, 55 deletions
diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile
index 2680f7e..a9802da 100644
--- a/drivers/staging/greybus/Makefile
+++ b/drivers/staging/greybus/Makefile
@@ -33,7 +33,7 @@ gb-audio-manager-y += audio_manager.o
gb-audio-manager-y += audio_manager_module.o
gb-camera-y := camera.o
gb-firmware-y := fw-core.o fw-download.o
-gb-spi-y := spi.o
+gb-spilib-y := spilib.o
gb-sdio-y := sdio.o
gb-uart-y := uart.o
gb-pwm-y := pwm.o
@@ -62,7 +62,7 @@ obj-m += gb-audio-gb.o
obj-m += gb-audio-apbridgea.o
obj-m += gb-audio-manager.o
obj-m += gb-firmware.o
-obj-m += gb-spi.o
+obj-m += gb-spilib.o
obj-m += gb-sdio.o
obj-m += gb-uart.o
obj-m += gb-pwm.o
diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spilib.c
index 6cf18d1..c7fe878 100644
--- a/drivers/staging/greybus/spi.c
+++ b/drivers/staging/greybus/spilib.c
@@ -1,8 +1,8 @@
/*
- * SPI bridge driver for the Greybus "generic" SPI module.
+ * Greybus SPI library
*
- * Copyright 2014-2015 Google Inc.
- * Copyright 2014-2015 Linaro Ltd.
+ * Copyright 2014-2016 Google Inc.
+ * Copyright 2014-2016 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
@@ -15,10 +15,11 @@
#include "greybus.h"
#include "gpbridge.h"
+#include "spilib.h"
-struct gb_spi {
+struct gb_spilib {
struct gb_connection *connection;
- struct gpbridge_device *gpbdev;
+ struct device *parent;
struct spi_transfer *first_xfer;
struct spi_transfer *last_xfer;
u32 rx_xfer_offset;
@@ -42,7 +43,7 @@ struct gb_spi {
#define XFER_TIMEOUT_TOLERANCE 200
-static struct spi_master *get_master_from_spi(struct gb_spi *spi)
+static struct spi_master *get_master_from_spi(struct gb_spilib *spi)
{
return gb_connection_get_data(spi->connection);
}
@@ -92,7 +93,7 @@ static size_t calc_tx_xfer_size(u32 tx_size, u32 count, size_t len,
return len;
}
-static void clean_xfer_state(struct gb_spi *spi)
+static void clean_xfer_state(struct gb_spilib *spi)
{
spi->first_xfer = NULL;
spi->last_xfer = NULL;
@@ -102,7 +103,7 @@ static void clean_xfer_state(struct gb_spi *spi)
spi->op_timeout = 0;
}
-static int setup_next_xfer(struct gb_spi *spi, struct spi_message *msg)
+static int setup_next_xfer(struct gb_spilib *spi, struct spi_message *msg)
{
struct spi_transfer *last_xfer = spi->last_xfer;
@@ -149,9 +150,8 @@ static struct spi_transfer *get_next_xfer(struct spi_transfer *xfer,
}
/* Routines to transfer data */
-static struct gb_operation *
-gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection,
- struct spi_message *msg)
+static struct gb_operation *gb_spi_operation_create(struct gb_spilib *spi,
+ struct gb_connection *connection, struct spi_message *msg)
{
struct gb_spi_transfer_request *request;
struct spi_device *dev = msg->spi;
@@ -175,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(&spi->gpbdev->dev,
+ dev_err(spi->parent,
"bufferless transfer, length %u\n", xfer->len);
msg->state = GB_SPI_STATE_MSG_ERROR;
return NULL;
@@ -279,7 +279,8 @@ gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection,
return operation;
}
-static void gb_spi_decode_response(struct gb_spi *spi, struct spi_message *msg,
+static void gb_spi_decode_response(struct gb_spilib *spi,
+ struct spi_message *msg,
struct gb_spi_transfer_response *response)
{
struct spi_transfer *xfer = spi->first_xfer;
@@ -311,7 +312,7 @@ static void gb_spi_decode_response(struct gb_spi *spi, struct spi_message *msg,
static int gb_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg)
{
- struct gb_spi *spi = spi_master_get_devdata(master);
+ struct gb_spilib *spi = spi_master_get_devdata(master);
struct gb_connection *connection = spi->connection;
struct gb_spi_transfer_response *response;
struct gb_operation *operation;
@@ -343,7 +344,7 @@ static int gb_spi_transfer_one_message(struct spi_master *master,
if (response)
gb_spi_decode_response(spi, msg, response);
} else {
- dev_err(&spi->gpbdev->dev,
+ dev_err(spi->parent,
"transfer operation failed: %d\n", ret);
msg->state = GB_SPI_STATE_MSG_ERROR;
}
@@ -381,7 +382,7 @@ static void gb_spi_cleanup(struct spi_device *spi)
#define gb_spi_mode_map(mode) mode
#define gb_spi_flags_map(flags) flags
-static int gb_spi_get_master_config(struct gb_spi *spi)
+static int gb_spi_get_master_config(struct gb_spilib *spi)
{
struct gb_spi_master_config_response response;
u16 mode, flags;
@@ -407,7 +408,7 @@ static int gb_spi_get_master_config(struct gb_spi *spi)
return 0;
}
-static int gb_spi_setup_device(struct gb_spi *spi, u8 cs)
+static int gb_spi_setup_device(struct gb_spilib *spi, u8 cs)
{
struct spi_master *master = get_master_from_spi(spi);
struct gb_spi_device_config_request request;
@@ -451,48 +452,29 @@ static int gb_spi_setup_device(struct gb_spi *spi, u8 cs)
return 0;
}
-static int gb_spi_probe(struct gpbridge_device *gpbdev,
- const struct gpbridge_device_id *id)
+int gb_spilib_master_init(struct gb_connection *connection, struct device *dev)
{
- struct gb_connection *connection;
- struct gb_spi *spi;
+ struct gb_spilib *spi;
struct spi_master *master;
int ret;
u8 i;
/* Allocate master with space for data */
- master = spi_alloc_master(&gpbdev->dev, sizeof(*spi));
+ master = spi_alloc_master(dev, sizeof(*spi));
if (!master) {
- dev_err(&gpbdev->dev, "cannot alloc SPI master\n");
+ dev_err(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;
+ spi->parent = dev;
/* get master configuration */
ret = gb_spi_get_master_config(spi);
if (ret)
- goto exit_connection_disable;
+ goto exit_spi_put;
master->bus_num = -1; /* Allow spi-core to allocate it dynamically */
master->num_chipselect = spi->num_chipselect;
@@ -507,43 +489,81 @@ static int gb_spi_probe(struct gpbridge_device *gpbdev,
ret = spi_register_master(master);
if (ret < 0)
- goto exit_connection_disable;
+ goto exit_spi_put;
/* 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(&gpbdev->dev,
- "failed to allocate spi device %d: %d\n",
+ dev_err(dev, "failed to allocate spi device %d: %d\n",
i, ret);
goto exit_spi_unregister;
}
}
- return ret;
+ return 0;
exit_spi_unregister:
spi_unregister_master(master);
+exit_spi_put:
+ spi_master_put(master);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(gb_spilib_master_init);
+
+void gb_spilib_master_exit(struct gb_connection *connection)
+{
+ struct spi_master *master = gb_connection_get_data(connection);
+
+ spi_unregister_master(master);
+ spi_master_put(master);
+}
+EXPORT_SYMBOL_GPL(gb_spilib_master_exit);
+
+static int gb_spi_probe(struct gpbridge_device *gpbdev,
+ const struct gpbridge_device_id *id)
+{
+ struct gb_connection *connection;
+ int ret;
+
+ connection = gb_connection_create(gpbdev->bundle,
+ le16_to_cpu(gpbdev->cport_desc->id),
+ NULL);
+ if (IS_ERR(connection))
+ return PTR_ERR(connection);
+
+ ret = gb_connection_enable(connection);
+ if (ret)
+ goto exit_connection_destroy;
+
+ ret = gb_gpbridge_get_version(connection);
+ if (ret)
+ goto exit_connection_disable;
+
+ ret = gb_spilib_master_init(connection, &gpbdev->dev);
+ if (ret)
+ goto exit_connection_disable;
+
+ gb_gpbridge_set_data(gpbdev, connection);
+
+ return 0;
+
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_remove(struct gpbridge_device *gpbdev)
{
- struct spi_master *master = gb_gpbridge_get_data(gpbdev);
- struct gb_spi *spi = spi_master_get_devdata(master);
- struct gb_connection *connection = spi->connection;
+ struct gb_connection *connection = gb_gpbridge_get_data(gpbdev);
- spi_unregister_master(master);
+ gb_spilib_master_exit(connection);
gb_connection_disable(connection);
gb_connection_destroy(connection);
- spi_master_put(master);
}
static const struct gpbridge_device_id gb_spi_id_table[] = {
diff --git a/drivers/staging/greybus/spilib.h b/drivers/staging/greybus/spilib.h
new file mode 100644
index 0000000..9be1b31
--- /dev/null
+++ b/drivers/staging/greybus/spilib.h
@@ -0,0 +1,18 @@
+/*
+ * Greybus SPI library header
+ *
+ * copyright 2016 google inc.
+ * copyright 2016 linaro ltd.
+ *
+ * released under the gplv2 only.
+ */
+
+#ifndef __SPILIB_H
+#define __SPILIB_H
+
+struct gb_connection;
+
+int gb_spilib_master_init(struct gb_connection *connection, struct device *dev);
+void gb_spilib_master_exit(struct gb_connection *connection);
+
+#endif /* __SPILIB_H */
OpenPOWER on IntegriCloud