summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r--drivers/spi/spi.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 7756304f19..d9311d4af5 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -19,6 +19,7 @@
*/
#include <common.h>
+#include <linux/spi/spi-mem.h>
#include <spi/spi.h>
#include <xfuncs.h>
#include <malloc.h>
@@ -58,6 +59,7 @@ struct spi_device *spi_new_device(struct spi_controller *ctrl,
struct spi_board_info *chip)
{
struct spi_device *proxy;
+ struct spi_mem *mem;
int status;
/* Chipselects are numbered 0..max; validate. */
@@ -84,6 +86,15 @@ struct spi_device *spi_new_device(struct spi_controller *ctrl,
proxy->dev.parent = ctrl->dev;
proxy->master = proxy->controller = ctrl;
+ mem = xzalloc(sizeof *mem);
+ mem->spi = proxy;
+
+ if (ctrl->mem_ops && ctrl->mem_ops->get_name)
+ mem->name = ctrl->mem_ops->get_name(mem);
+ else
+ mem->name = dev_name(&proxy->dev);
+ proxy->mem = mem;
+
/* drivers may modify this initial i/o setup */
status = ctrl->setup(proxy);
if (status < 0) {
@@ -194,6 +205,26 @@ static void scan_boardinfo(struct spi_controller *ctrl)
static LIST_HEAD(spi_controller_list);
+static int spi_controller_check_ops(struct spi_controller *ctlr)
+{
+ /*
+ * The controller may implement only the high-level SPI-memory like
+ * operations if it does not support regular SPI transfers, and this is
+ * valid use case.
+ * If ->mem_ops is NULL, we request that at least one of the
+ * ->transfer_xxx() method be implemented.
+ */
+ if (ctlr->mem_ops) {
+ if (!ctlr->mem_ops->exec_op)
+ return -EINVAL;
+ } else if (!ctlr->transfer) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
/**
* spi_register_ctrl - register SPI ctrl controller
* @ctrl: initialized ctrl, originally from spi_alloc_ctrl()
@@ -221,6 +252,14 @@ int spi_register_controller(struct spi_controller *ctrl)
debug("%s: %s:%d\n", __func__, ctrl->dev->name, ctrl->dev->id);
+ /*
+ * Make sure all necessary hooks are implemented before registering
+ * the SPI controller.
+ */
+ status = spi_controller_check_ops(ctrl);
+ if (status)
+ return status;
+
/* even if it's just one always-selected device, there must
* be at least one chipselect
*/