dm: sandbox: spi: Move to driver model

Adjust the sandbox SPI driver to support driver model and move sandbox over
to driver model for SPI.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index d17a82e..4e0981a 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -43,6 +43,7 @@
 struct sandbox_spi_info {
 	const char *spec;
 	const struct sandbox_spi_emu_ops *ops;
+	struct udevice *emul;
 };
 
 /* The complete state of the test system */
diff --git a/drivers/spi/sandbox_spi.c b/drivers/spi/sandbox_spi.c
index 12e9bda..e717424 100644
--- a/drivers/spi/sandbox_spi.c
+++ b/drivers/spi/sandbox_spi.c
@@ -9,26 +9,23 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
 #include <spi.h>
+#include <spi_flash.h>
 #include <os.h>
 
 #include <asm/errno.h>
 #include <asm/spi.h>
 #include <asm/state.h>
+#include <dm/device-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
 
 #ifndef CONFIG_SPI_IDLE_VAL
 # define CONFIG_SPI_IDLE_VAL 0xFF
 #endif
 
-struct sandbox_spi_slave {
-	struct spi_slave slave;
-	const struct sandbox_spi_emu_ops *ops;
-	void *priv;
-};
-
-#define to_sandbox_spi_slave(s) container_of(s, struct sandbox_spi_slave, slave)
-
 const char *sandbox_spi_parse_spec(const char *arg, unsigned long *bus,
 				   unsigned long *cs)
 {
@@ -45,120 +42,52 @@
 	return endp + 1;
 }
 
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+__weak int sandbox_spi_get_emul(struct sandbox_state *state,
+				struct udevice *bus, struct udevice *slave,
+				struct udevice **emulp)
 {
-	return bus < CONFIG_SANDBOX_SPI_MAX_BUS &&
-		cs < CONFIG_SANDBOX_SPI_MAX_CS;
+	return -ENOENT;
 }
 
-void spi_cs_activate(struct spi_slave *slave)
+static int sandbox_spi_xfer(struct udevice *slave, unsigned int bitlen,
+			    const void *dout, void *din, unsigned long flags)
 {
-	struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
-
-	debug("sandbox_spi: activating CS\n");
-	if (sss->ops->cs_activate)
-		sss->ops->cs_activate(sss->priv);
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
-	struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
-
-	debug("sandbox_spi: deactivating CS\n");
-	if (sss->ops->cs_deactivate)
-		sss->ops->cs_deactivate(sss->priv);
-}
-
-void spi_init(void)
-{
-}
-
-void spi_set_speed(struct spi_slave *slave, uint hz)
-{
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-		unsigned int max_hz, unsigned int mode)
-{
-	struct sandbox_spi_slave *sss;
+	struct udevice *bus = slave->parent;
 	struct sandbox_state *state = state_get_current();
-	const char *spec;
-
-	if (!spi_cs_is_valid(bus, cs)) {
-		debug("sandbox_spi: Invalid SPI bus/cs\n");
-		return NULL;
-	}
-
-	sss = spi_alloc_slave(struct sandbox_spi_slave, bus, cs);
-	if (!sss) {
-		debug("sandbox_spi: Out of memory\n");
-		return NULL;
-	}
-
-	spec = state->spi[bus][cs].spec;
-	sss->ops = state->spi[bus][cs].ops;
-	if (!spec || !sss->ops || sss->ops->setup(&sss->priv, spec)) {
-		free(sss);
-		printf("sandbox_spi: unable to locate a slave client\n");
-		return NULL;
-	}
-
-	return &sss->slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
-	struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
-
-	debug("sandbox_spi: releasing slave\n");
-
-	if (sss->ops->free)
-		sss->ops->free(sss->priv);
-
-	free(sss);
-}
-
-static int spi_bus_claim_cnt[CONFIG_SANDBOX_SPI_MAX_BUS];
-
-int spi_claim_bus(struct spi_slave *slave)
-{
-	if (spi_bus_claim_cnt[slave->bus]++) {
-		printf("sandbox_spi: error: bus already claimed: %d!\n",
-		       spi_bus_claim_cnt[slave->bus]);
-	}
-
-	return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
-	if (--spi_bus_claim_cnt[slave->bus]) {
-		printf("sandbox_spi: error: bus freed too often: %d!\n",
-		       spi_bus_claim_cnt[slave->bus]);
-	}
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-		void *din, unsigned long flags)
-{
-	struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
+	struct dm_spi_emul_ops *ops;
+	struct udevice *emul;
 	uint bytes = bitlen / 8, i;
-	int ret = 0;
+	int ret;
 	u8 *tx = (void *)dout, *rx = din;
+	uint busnum, cs;
 
 	if (bitlen == 0)
-		goto done;
+		return 0;
 
 	/* we can only do 8 bit transfers */
 	if (bitlen % 8) {
 		printf("sandbox_spi: xfer: invalid bitlen size %u; needs to be 8bit\n",
 		       bitlen);
-		flags |= SPI_XFER_END;
-		goto done;
+		return -EINVAL;
 	}
 
-	if (flags & SPI_XFER_BEGIN)
-		spi_cs_activate(slave);
+	busnum = bus->seq;
+	cs = spi_chip_select(slave);
+	if (busnum >= CONFIG_SANDBOX_SPI_MAX_BUS ||
+	    cs >= CONFIG_SANDBOX_SPI_MAX_CS) {
+		printf("%s: busnum=%u, cs=%u: out of range\n", __func__,
+		       busnum, cs);
+		return -ENOENT;
+	}
+	ret = sandbox_spi_get_emul(state, bus, slave, &emul);
+	if (ret) {
+		printf("%s: busnum=%u, cs=%u: no emulation available (err=%d)\n",
+		       __func__, busnum, cs, ret);
+		return -ENOENT;
+	}
+	ret = device_probe(emul);
+	if (ret)
+		return ret;
 
 	/* make sure rx/tx buffers are full so clients can assume */
 	if (!tx) {
@@ -178,12 +107,8 @@
 		}
 	}
 
-	debug("sandbox_spi: xfer: bytes = %u\n tx:", bytes);
-	for (i = 0; i < bytes; ++i)
-		debug(" %u:%02x", i, tx[i]);
-	debug("\n");
-
-	ret = sss->ops->xfer(sss->priv, tx, rx, bytes);
+	ops = spi_emul_get_ops(emul);
+	ret = ops->xfer(emul, bitlen, dout, din, flags);
 
 	debug("sandbox_spi: xfer: got back %i (that's %s)\n rx:",
 	      ret, ret ? "bad" : "good");
@@ -196,22 +121,45 @@
 	if (rx != din)
 		free(rx);
 
- done:
-	if (flags & SPI_XFER_END)
-		spi_cs_deactivate(slave);
-
 	return ret;
 }
 
-/**
- * Set up a new SPI slave for an fdt node
- *
- * @param blob		Device tree blob
- * @param node		SPI peripheral node to use
- * @return 0 if ok, -1 on error
- */
-struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
-				      int spi_node)
+static int sandbox_spi_set_speed(struct udevice *bus, uint speed)
 {
-	return NULL;
+	return 0;
 }
+
+static int sandbox_spi_set_mode(struct udevice *bus, uint mode)
+{
+	return 0;
+}
+
+static int sandbox_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	/* Always allow activity on CS 0 */
+	if (cs >= 1)
+		return -ENODEV;
+
+	return 0;
+}
+
+static const struct dm_spi_ops sandbox_spi_ops = {
+	.xfer		= sandbox_spi_xfer,
+	.set_speed	= sandbox_spi_set_speed,
+	.set_mode	= sandbox_spi_set_mode,
+	.cs_info	= sandbox_cs_info,
+};
+
+static const struct udevice_id sandbox_spi_ids[] = {
+	{ .compatible = "sandbox,spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(spi_sandbox) = {
+	.name	= "spi_sandbox",
+	.id	= UCLASS_SPI,
+	.of_match = sandbox_spi_ids,
+	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
+	.ops	= &sandbox_spi_ops,
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 022629f..8b74f49 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -97,8 +97,7 @@
 #define CONFIG_CMD_SF_TEST
 #define CONFIG_CMD_SPI
 #define CONFIG_SPI_FLASH
-#define CONFIG_OF_SPI
-#define CONFIG_OF_SPI_FLASH
+#define CONFIG_DM_SPI
 #define CONFIG_SPI_FLASH_ATMEL
 #define CONFIG_SPI_FLASH_EON
 #define CONFIG_SPI_FLASH_GIGADEVICE