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>
This commit is contained in:
Simon Glass 2014-10-13 23:41:53 -06:00
parent d7af6a4851
commit c60e1f2547
4 changed files with 62 additions and 0 deletions

View File

@ -8,6 +8,7 @@
# There are many options which enable SPI, so make this library available
ifdef CONFIG_DM_SPI
obj-y += spi-uclass.o
obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o
else
obj-y += spi.o
endif

View File

@ -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",
};

View File

@ -18,6 +18,7 @@ enum uclass_id {
UCLASS_TEST,
UCLASS_TEST_FDT,
UCLASS_TEST_BUS,
UCLASS_SPI_EMUL, /* sandbox SPI device emulator */
/* U-Boot uclasses start here */
UCLASS_GPIO, /* Bank of general-purpose I/O pins */

View File

@ -456,6 +456,35 @@ struct dm_spi_ops {
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
*
@ -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);
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,
struct udevice *bus, struct udevice *slave,
struct udevice **emulp);
/* Access the serial operations for a device */
#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 /* _SPI_H_ */