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>
This commit is contained in:
		
							parent
							
								
									7b3efc6699
								
							
						
					
					
						commit
						0efc02499f
					
				| 
						 | 
					@ -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)
 | 
					int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	dev->spi = spi_setup_slave_fdt(blob, dev->parent_node,
 | 
						dev->spi = spi_setup_slave_fdt(blob, dev->parent_node, dev->node);
 | 
				
			||||||
				       dev->cs, dev->max_frequency, 0);
 | 
					 | 
				
			||||||
	if (!dev->spi) {
 | 
						if (!dev->spi) {
 | 
				
			||||||
		debug("%s: Could not setup SPI slave\n", __func__);
 | 
							debug("%s: Could not setup SPI slave\n", __func__);
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,16 +285,13 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* CONFIG_OF_CONTROL */
 | 
					#endif /* CONFIG_OF_CONTROL */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
 | 
					static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
 | 
				
			||||||
		unsigned int max_hz, unsigned int spi_mode)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct spi_slave *spi;
 | 
					 | 
				
			||||||
	struct spi_flash *flash = NULL;
 | 
						struct spi_flash *flash = NULL;
 | 
				
			||||||
	u8 idcode[5];
 | 
						u8 idcode[5];
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Setup spi_slave */
 | 
						/* Setup spi_slave */
 | 
				
			||||||
	spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
 | 
					 | 
				
			||||||
	if (!spi) {
 | 
						if (!spi) {
 | 
				
			||||||
		printf("SF: Failed to set up slave\n");
 | 
							printf("SF: Failed to set up slave\n");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
| 
						 | 
					@ -358,6 +355,26 @@ err_claim_bus:
 | 
				
			||||||
	return NULL;
 | 
						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)
 | 
					void spi_flash_free(struct spi_flash *flash)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	spi_free_slave(flash->spi);
 | 
						spi_free_slave(flash->spi);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -529,18 +529,18 @@ static int process_nodes(const void *blob, int node_list[], int count)
 | 
				
			||||||
 * @param node		SPI peripheral node to use
 | 
					 * @param node		SPI peripheral node to use
 | 
				
			||||||
 * @return 0 if ok, -1 on error
 | 
					 * @return 0 if ok, -1 on error
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct spi_slave *spi_setup_slave_fdt(const void *blob, int node,
 | 
					struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
 | 
				
			||||||
		unsigned int cs, unsigned int max_hz, unsigned int mode)
 | 
									      int spi_node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct spi_bus *bus;
 | 
						struct spi_bus *bus;
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0, bus = spi_bus; i < bus_count; i++, bus++) {
 | 
						for (i = 0, bus = spi_bus; i < bus_count; i++, bus++) {
 | 
				
			||||||
		if (bus->node == node)
 | 
							if (bus->node == spi_node)
 | 
				
			||||||
			return spi_setup_slave(i, cs, max_hz, mode);
 | 
								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;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <common.h>
 | 
					#include <common.h>
 | 
				
			||||||
 | 
					#include <fdtdec.h>
 | 
				
			||||||
#include <malloc.h>
 | 
					#include <malloc.h>
 | 
				
			||||||
#include <spi.h>
 | 
					#include <spi.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,3 +38,21 @@ void *spi_do_alloc_slave(int offset, int size, unsigned int bus,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ptr;
 | 
						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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -276,6 +276,7 @@
 | 
				
			||||||
#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
 | 
					#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
 | 
				
			||||||
#define CONFIG_SF_DEFAULT_SPEED		50000000
 | 
					#define CONFIG_SF_DEFAULT_SPEED		50000000
 | 
				
			||||||
#define EXYNOS5_SPI_NUM_CONTROLLERS	5
 | 
					#define EXYNOS5_SPI_NUM_CONTROLLERS	5
 | 
				
			||||||
 | 
					#define CONFIG_OF_SPI
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
 | 
					#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -259,13 +259,24 @@ static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte)
 | 
				
			||||||
 * spi_free_slave() to free it later.
 | 
					 * spi_free_slave() to free it later.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param blob:		Device tree blob
 | 
					 * @param blob:		Device tree blob
 | 
				
			||||||
 * @param node:		SPI peripheral node to use
 | 
					 * @param slave_node:	Slave node to use
 | 
				
			||||||
 * @param cs:		Chip select to use
 | 
					 * @param spi_node:	SPI peripheral node to use
 | 
				
			||||||
 * @param max_hz:	Maximum SCK rate in Hz (0 for default)
 | 
					 | 
				
			||||||
 * @param mode:		Clock polarity, clock phase and other parameters
 | 
					 | 
				
			||||||
 * @return pointer to new spi_slave structure
 | 
					 * @return pointer to new spi_slave structure
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct spi_slave *spi_setup_slave_fdt(const void *blob, int node,
 | 
					struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
 | 
				
			||||||
		unsigned int cs, unsigned int max_hz, unsigned int mode);
 | 
									      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_ */
 | 
					#endif	/* _SPI_H_ */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,6 +67,19 @@ struct spi_flash {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
 | 
					struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
 | 
				
			||||||
		unsigned int max_hz, unsigned int spi_mode);
 | 
							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);
 | 
					void spi_flash_free(struct spi_flash *flash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
 | 
					static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue