From 0efc02499f9131bd7e1689ebb8d626ef12387de4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 3 Dec 2013 16:43:24 -0700 Subject: [PATCH] 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 --- drivers/misc/cros_ec_spi.c | 3 +-- drivers/mtd/spi/sf_probe.c | 25 +++++++++++++++++++++---- drivers/spi/exynos_spi.c | 10 +++++----- drivers/spi/spi.c | 19 +++++++++++++++++++ include/configs/exynos5250-dt.h | 1 + include/spi.h | 23 +++++++++++++++++------ include/spi_flash.h | 13 +++++++++++++ 7 files changed, 77 insertions(+), 17 deletions(-) diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c index 202acf258b..2fc911025e 100644 --- a/drivers/misc/cros_ec_spi.c +++ b/drivers/misc/cros_ec_spi.c @@ -135,8 +135,7 @@ int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob) */ 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 5eb8ffe843..ca127155b5 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -285,16 +285,13 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) } #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 @@ err_claim_bus: 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 699c57eb6d..4d5def2d31 100644 --- a/drivers/spi/exynos_spi.c +++ b/drivers/spi/exynos_spi.c @@ -529,18 +529,18 @@ static int process_nodes(const void *blob, int node_list[], int count) * @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 b76a26cef0..7ddea9b026 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -37,3 +38,21 @@ void *spi_do_alloc_slave(int offset, int size, unsigned int bus, 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 bdefee108d..74ba2b64c4 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 e2563c99f2..aba792244a 100644 --- a/include/spi.h +++ b/include/spi.h @@ -259,13 +259,24 @@ static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte) * 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 25ca8f177b..afc3a5809e 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -67,6 +67,19 @@ struct spi_flash { 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, -- 2.39.2