diff options
Diffstat (limited to 'roms/u-boot/drivers/spi/sandbox_spi.c')
-rw-r--r-- | roms/u-boot/drivers/spi/sandbox_spi.c | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/spi/sandbox_spi.c b/roms/u-boot/drivers/spi/sandbox_spi.c new file mode 100644 index 000000000..0564d8b55 --- /dev/null +++ b/roms/u-boot/drivers/spi/sandbox_spi.c @@ -0,0 +1,179 @@ +/* + * Simulate a SPI port + * + * Copyright (c) 2011-2013 The Chromium OS Authors. + * See file CREDITS for list of people who contributed to this + * project. + * + * Licensed under the GPL-2 or later. + */ + +#define LOG_CATEGORY UCLASS_SPI + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <malloc.h> +#include <spi.h> +#include <spi_flash.h> +#include <os.h> + +#include <linux/errno.h> +#include <asm/spi.h> +#include <asm/state.h> +#include <dm/acpi.h> +#include <dm/device-internal.h> + +#ifndef CONFIG_SPI_IDLE_VAL +# define CONFIG_SPI_IDLE_VAL 0xFF +#endif + +/** + * struct sandbox_spi_priv - Sandbox SPI private data + * + * Helper struct to keep track of the sandbox SPI bus internal state. It is + * used in unit tests to verify that dm spi functions update the bus + * speed/mode properly (for instance, when jumping back and forth between spi + * slaves claiming the bus, we need to make sure that the bus speed is updated + * accordingly for each slave). + * + * @speed: Current bus speed. + * @mode: Current bus mode. + */ +struct sandbox_spi_priv { + uint speed; + uint mode; +}; + +__weak int sandbox_spi_get_emul(struct sandbox_state *state, + struct udevice *bus, struct udevice *slave, + struct udevice **emulp) +{ + return -ENOENT; +} + +uint sandbox_spi_get_speed(struct udevice *dev) +{ + struct sandbox_spi_priv *priv = dev_get_priv(dev); + + return priv->speed; +} + +uint sandbox_spi_get_mode(struct udevice *dev) +{ + struct sandbox_spi_priv *priv = dev_get_priv(dev); + + return priv->mode; +} + +static int sandbox_spi_xfer(struct udevice *slave, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct udevice *bus = slave->parent; + struct sandbox_state *state = state_get_current(); + struct dm_spi_emul_ops *ops; + struct udevice *emul; + uint bytes = bitlen / 8, i; + int ret; + uint busnum, cs; + + if (bitlen == 0) + return 0; + + /* we can only do 8 bit transfers */ + if (bitlen % 8) { + printf("sandbox_spi: xfer: invalid bitlen size %u; needs to be 8bit\n", + bitlen); + return -EINVAL; + } + + busnum = dev_seq(bus); + cs = spi_chip_select(slave); + if (busnum >= CONFIG_SANDBOX_SPI_MAX_BUS || + cs >= CONFIG_SANDBOX_SPI_MAX_CS) { + printf("%s: busnum=%u, cs=%u: out of range\n", __func__, + busnum, cs); + return -ENOENT; + } + ret = sandbox_spi_get_emul(state, bus, slave, &emul); + if (ret) { + printf("%s: busnum=%u, cs=%u: no emulation available (err=%d)\n", + __func__, busnum, cs, ret); + return -ENOENT; + } + ret = device_probe(emul); + if (ret) + return ret; + + ops = spi_emul_get_ops(emul); + ret = ops->xfer(emul, bitlen, dout, din, flags); + + log_content("sandbox_spi: xfer: got back %i (that's %s)\n rx:", + ret, ret ? "bad" : "good"); + if (din) { + for (i = 0; i < bytes; ++i) + log_content(" %u:%02x", i, ((u8 *)din)[i]); + } + log_content("\n"); + + return ret; +} + +static int sandbox_spi_set_speed(struct udevice *bus, uint speed) +{ + struct sandbox_spi_priv *priv = dev_get_priv(bus); + + priv->speed = speed; + + return 0; +} + +static int sandbox_spi_set_mode(struct udevice *bus, uint mode) +{ + struct sandbox_spi_priv *priv = dev_get_priv(bus); + + priv->mode = mode; + + return 0; +} + +static int sandbox_cs_info(struct udevice *bus, uint cs, + struct spi_cs_info *info) +{ + /* Always allow activity on CS 0, CS 1 */ + if (cs >= 2) + return -EINVAL; + + return 0; +} + +static int sandbox_spi_get_mmap(struct udevice *dev, ulong *map_basep, + uint *map_sizep, uint *offsetp) +{ + *map_basep = 0x1000; + *map_sizep = 0x2000; + *offsetp = 0x100; + + return 0; +} + +static const struct dm_spi_ops sandbox_spi_ops = { + .xfer = sandbox_spi_xfer, + .set_speed = sandbox_spi_set_speed, + .set_mode = sandbox_spi_set_mode, + .cs_info = sandbox_cs_info, + .get_mmap = sandbox_spi_get_mmap, +}; + +static const struct udevice_id sandbox_spi_ids[] = { + { .compatible = "sandbox,spi" }, + { } +}; + +U_BOOT_DRIVER(sandbox_spi) = { + .name = "sandbox_spi", + .id = UCLASS_SPI, + .of_match = sandbox_spi_ids, + .ops = &sandbox_spi_ops, + .priv_auto = sizeof(struct sandbox_spi_priv), +}; |