spi_flash: Add spi_flash_probe_fdt() to locate SPI by FDT node

This allows us to put the SPI flash chip inside the SPI interface node,
with U-Boot finding the correct bus and chip select automatically.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c
index 202acf2..2fc9110 100644
--- a/drivers/misc/cros_ec_spi.c
+++ b/drivers/misc/cros_ec_spi.c
@@ -135,8 +135,7 @@
  */
 int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob)
 {
-	dev->spi = spi_setup_slave_fdt(blob, dev->parent_node,
-				       dev->cs, dev->max_frequency, 0);
+	dev->spi = spi_setup_slave_fdt(blob, dev->parent_node, dev->node);
 	if (!dev->spi) {
 		debug("%s: Could not setup SPI slave\n", __func__);
 		return -1;
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 5eb8ffe..ca12715 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -285,16 +285,13 @@
 }
 #endif /* CONFIG_OF_CONTROL */
 
-struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
-		unsigned int max_hz, unsigned int spi_mode)
+static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
 {
-	struct spi_slave *spi;
 	struct spi_flash *flash = NULL;
 	u8 idcode[5];
 	int ret;
 
 	/* Setup spi_slave */
-	spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
 	if (!spi) {
 		printf("SF: Failed to set up slave\n");
 		return NULL;
@@ -358,6 +355,26 @@
 	return NULL;
 }
 
+struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int spi_mode)
+{
+	struct spi_slave *spi;
+
+	spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
+	return spi_flash_probe_slave(spi);
+}
+
+#ifdef CONFIG_OF_SPI_FLASH
+struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
+				      int spi_node)
+{
+	struct spi_slave *spi;
+
+	spi = spi_setup_slave_fdt(blob, slave_node, spi_node);
+	return spi_flash_probe_slave(spi);
+}
+#endif
+
 void spi_flash_free(struct spi_flash *flash)
 {
 	spi_free_slave(flash->spi);
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index 699c57e..4d5def2 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -529,18 +529,18 @@
  * @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 node,
-		unsigned int cs, unsigned int max_hz, unsigned int mode)
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
+				      int spi_node)
 {
 	struct spi_bus *bus;
 	unsigned int i;
 
 	for (i = 0, bus = spi_bus; i < bus_count; i++, bus++) {
-		if (bus->node == node)
-			return spi_setup_slave(i, cs, max_hz, mode);
+		if (bus->node == spi_node)
+			return spi_base_setup_slave_fdt(blob, i, slave_node);
 	}
 
-	debug("%s: Failed to find bus node %d\n", __func__, node);
+	debug("%s: Failed to find bus node %d\n", __func__, spi_node);
 	return NULL;
 }
 
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b76a26c..7ddea9b 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <fdtdec.h>
 #include <malloc.h>
 #include <spi.h>
 
@@ -37,3 +38,21 @@
 
 	return ptr;
 }
+
+#ifdef CONFIG_OF_SPI
+struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum,
+					   int node)
+{
+	int cs, max_hz, mode = 0;
+
+	cs = fdtdec_get_int(blob, node, "reg", -1);
+	max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 100000);
+	if (fdtdec_get_bool(blob, node, "spi-cpol"))
+		mode |= SPI_CPOL;
+	if (fdtdec_get_bool(blob, node, "spi-cpha"))
+		mode |= SPI_CPHA;
+	if (fdtdec_get_bool(blob, node, "spi-cs-high"))
+		mode |= SPI_CS_HIGH;
+	return spi_setup_slave(busnum, cs, max_hz, mode);
+}
+#endif
diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h
index bdefee1..74ba2b6 100644
--- a/include/configs/exynos5250-dt.h
+++ b/include/configs/exynos5250-dt.h
@@ -276,6 +276,7 @@
 #define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
 #define CONFIG_SF_DEFAULT_SPEED		50000000
 #define EXYNOS5_SPI_NUM_CONTROLLERS	5
+#define CONFIG_OF_SPI
 #endif
 
 #ifdef CONFIG_ENV_IS_IN_SPI_FLASH
diff --git a/include/spi.h b/include/spi.h
index e2563c9..aba7922 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -259,13 +259,24 @@
  * spi_free_slave() to free it later.
  *
  * @param blob:		Device tree blob
- * @param node:		SPI peripheral node to use
- * @param cs:		Chip select to use
- * @param max_hz:	Maximum SCK rate in Hz (0 for default)
- * @param mode:		Clock polarity, clock phase and other parameters
+ * @param slave_node:	Slave node to use
+ * @param spi_node:	SPI peripheral node to use
  * @return pointer to new spi_slave structure
  */
-struct spi_slave *spi_setup_slave_fdt(const void *blob, int node,
-		unsigned int cs, unsigned int max_hz, unsigned int mode);
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
+				      int spi_node);
+
+/**
+ * spi_base_setup_slave_fdt() - helper function to set up a SPI slace
+ *
+ * This decodes SPI properties from the slave node to determine the
+ * chip select and SPI parameters.
+ *
+ * @blob:	Device tree blob
+ * @busnum:	Bus number to use
+ * @node:	Device tree node for the SPI bus
+ */
+struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum,
+					   int node);
 
 #endif	/* _SPI_H_ */
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 25ca8f1..afc3a58 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -67,6 +67,19 @@
 
 struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
 		unsigned int max_hz, unsigned int spi_mode);
+
+/**
+ * Set up a new SPI flash from an fdt node
+ *
+ * @param blob		Device tree blob
+ * @param slave_node	Pointer to this SPI slave node in the device tree
+ * @param spi_node	Cached pointer to the SPI interface this node belongs
+ *			to
+ * @return 0 if ok, -1 on error
+ */
+struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
+				      int spi_node);
+
 void spi_flash_free(struct spi_flash *flash);
 
 static inline int spi_flash_read(struct spi_flash *flash, u32 offset,