dm: sandbox: Add a SPI emulation uclass
U-Boot includes a SPI emulation driver already but it is not explicit, and is hidden in the SPI flash code. Conceptually with sandbox's SPI implementation we have a layer which creates SPI bus transitions and a layer which interprets them, currently only for SPI flash. The latter is actually an emulation, and it should be possible to add more than one emulation - not just SPI flash. Add a SPI emulation uclass so that other emulations can be plugged in to support different types of emulated devices on difference buses/chip selects. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>utp
parent
d7af6a4851
commit
c60e1f2547
|
@ -8,6 +8,7 @@
|
||||||
# There are many options which enable SPI, so make this library available
|
# There are many options which enable SPI, so make this library available
|
||||||
ifdef CONFIG_DM_SPI
|
ifdef CONFIG_DM_SPI
|
||||||
obj-y += spi-uclass.o
|
obj-y += spi-uclass.o
|
||||||
|
obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o
|
||||||
else
|
else
|
||||||
obj-y += spi.o
|
obj-y += spi.o
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014 Google, Inc
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <spi.h>
|
||||||
|
#include <spi_flash.h>
|
||||||
|
|
||||||
|
UCLASS_DRIVER(spi_emul) = {
|
||||||
|
.id = UCLASS_SPI_EMUL,
|
||||||
|
.name = "spi_emul",
|
||||||
|
};
|
|
@ -18,6 +18,7 @@ enum uclass_id {
|
||||||
UCLASS_TEST,
|
UCLASS_TEST,
|
||||||
UCLASS_TEST_FDT,
|
UCLASS_TEST_FDT,
|
||||||
UCLASS_TEST_BUS,
|
UCLASS_TEST_BUS,
|
||||||
|
UCLASS_SPI_EMUL, /* sandbox SPI device emulator */
|
||||||
|
|
||||||
/* U-Boot uclasses start here */
|
/* U-Boot uclasses start here */
|
||||||
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
|
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
|
||||||
|
|
|
@ -456,6 +456,35 @@ struct dm_spi_ops {
|
||||||
int (*cs_info)(struct udevice *bus, uint cs, struct spi_cs_info *info);
|
int (*cs_info)(struct udevice *bus, uint cs, struct spi_cs_info *info);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dm_spi_emul_ops {
|
||||||
|
/**
|
||||||
|
* SPI transfer
|
||||||
|
*
|
||||||
|
* This writes "bitlen" bits out the SPI MOSI port and simultaneously
|
||||||
|
* clocks "bitlen" bits in the SPI MISO port. That's just the way SPI
|
||||||
|
* works. Here the device is a slave.
|
||||||
|
*
|
||||||
|
* The source of the outgoing bits is the "dout" parameter and the
|
||||||
|
* destination of the input bits is the "din" parameter. Note that
|
||||||
|
* "dout" and "din" can point to the same memory location, in which
|
||||||
|
* case the input data overwrites the output data (since both are
|
||||||
|
* buffered by temporary variables, this is OK).
|
||||||
|
*
|
||||||
|
* spi_xfer() interface:
|
||||||
|
* @slave: The SPI slave which will be sending/receiving the data.
|
||||||
|
* @bitlen: How many bits to write and read.
|
||||||
|
* @dout: Pointer to a string of bits sent to the device. The
|
||||||
|
* bits are held in a byte array and are sent MSB first.
|
||||||
|
* @din: Pointer to a string of bits that will be sent back to
|
||||||
|
* the master.
|
||||||
|
* @flags: A bitwise combination of SPI_XFER_* flags.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, not -1 on failure
|
||||||
|
*/
|
||||||
|
int (*xfer)(struct udevice *slave, unsigned int bitlen,
|
||||||
|
const void *dout, void *din, unsigned long flags);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* spi_find_bus_and_cs() - Find bus and slave devices by number
|
* spi_find_bus_and_cs() - Find bus and slave devices by number
|
||||||
*
|
*
|
||||||
|
@ -545,12 +574,28 @@ int spi_ofdata_to_platdata(const void *blob, int node, struct spi_slave *spi);
|
||||||
int spi_cs_info(struct udevice *bus, uint cs, struct spi_cs_info *info);
|
int spi_cs_info(struct udevice *bus, uint cs, struct spi_cs_info *info);
|
||||||
|
|
||||||
struct sandbox_state;
|
struct sandbox_state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sandbox_spi_get_emul() - get an emulator for a SPI slave
|
||||||
|
*
|
||||||
|
* This provides a way to attach an emulated SPI device to a particular SPI
|
||||||
|
* slave, so that xfer() operations on the slave will be handled by the
|
||||||
|
* emulator. If a emulator already exists on that chip select it is returned.
|
||||||
|
* Otherwise one is created.
|
||||||
|
*
|
||||||
|
* @state: Sandbox state
|
||||||
|
* @bus: SPI bus requesting the emulator
|
||||||
|
* @slave: SPI slave device requesting the emulator
|
||||||
|
* @emuip: Returns pointer to emulator
|
||||||
|
* @return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
int sandbox_spi_get_emul(struct sandbox_state *state,
|
int sandbox_spi_get_emul(struct sandbox_state *state,
|
||||||
struct udevice *bus, struct udevice *slave,
|
struct udevice *bus, struct udevice *slave,
|
||||||
struct udevice **emulp);
|
struct udevice **emulp);
|
||||||
|
|
||||||
/* Access the serial operations for a device */
|
/* Access the serial operations for a device */
|
||||||
#define spi_get_ops(dev) ((struct dm_spi_ops *)(dev)->driver->ops)
|
#define spi_get_ops(dev) ((struct dm_spi_ops *)(dev)->driver->ops)
|
||||||
|
#define spi_emul_get_ops(dev) ((struct dm_spi_emul_ops *)(dev)->driver->ops)
|
||||||
#endif /* CONFIG_DM_SPI */
|
#endif /* CONFIG_DM_SPI */
|
||||||
|
|
||||||
#endif /* _SPI_H_ */
|
#endif /* _SPI_H_ */
|
||||||
|
|
Loading…
Reference in New Issue