uboot/drivers/spi/sandbox_spi.c
<<
>>
Prefs
   1/*
   2 * Simulate a SPI port
   3 *
   4 * Copyright (c) 2011-2013 The Chromium OS Authors.
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * Licensed under the GPL-2 or later.
   9 */
  10
  11#include <common.h>
  12#include <dm.h>
  13#include <malloc.h>
  14#include <spi.h>
  15#include <spi_flash.h>
  16#include <os.h>
  17
  18#include <linux/errno.h>
  19#include <asm/spi.h>
  20#include <asm/state.h>
  21#include <dm/device-internal.h>
  22
  23#ifndef CONFIG_SPI_IDLE_VAL
  24# define CONFIG_SPI_IDLE_VAL 0xFF
  25#endif
  26
  27const char *sandbox_spi_parse_spec(const char *arg, unsigned long *bus,
  28                                   unsigned long *cs)
  29{
  30        char *endp;
  31
  32        *bus = simple_strtoul(arg, &endp, 0);
  33        if (*endp != ':' || *bus >= CONFIG_SANDBOX_SPI_MAX_BUS)
  34                return NULL;
  35
  36        *cs = simple_strtoul(endp + 1, &endp, 0);
  37        if (*endp != ':' || *cs >= CONFIG_SANDBOX_SPI_MAX_CS)
  38                return NULL;
  39
  40        return endp + 1;
  41}
  42
  43__weak int sandbox_spi_get_emul(struct sandbox_state *state,
  44                                struct udevice *bus, struct udevice *slave,
  45                                struct udevice **emulp)
  46{
  47        return -ENOENT;
  48}
  49
  50static int sandbox_spi_xfer(struct udevice *slave, unsigned int bitlen,
  51                            const void *dout, void *din, unsigned long flags)
  52{
  53        struct udevice *bus = slave->parent;
  54        struct sandbox_state *state = state_get_current();
  55        struct dm_spi_emul_ops *ops;
  56        struct udevice *emul;
  57        uint bytes = bitlen / 8, i;
  58        int ret;
  59        u8 *tx = (void *)dout, *rx = din;
  60        uint busnum, cs;
  61
  62        if (bitlen == 0)
  63                return 0;
  64
  65        /* we can only do 8 bit transfers */
  66        if (bitlen % 8) {
  67                printf("sandbox_spi: xfer: invalid bitlen size %u; needs to be 8bit\n",
  68                       bitlen);
  69                return -EINVAL;
  70        }
  71
  72        busnum = bus->seq;
  73        cs = spi_chip_select(slave);
  74        if (busnum >= CONFIG_SANDBOX_SPI_MAX_BUS ||
  75            cs >= CONFIG_SANDBOX_SPI_MAX_CS) {
  76                printf("%s: busnum=%u, cs=%u: out of range\n", __func__,
  77                       busnum, cs);
  78                return -ENOENT;
  79        }
  80        ret = sandbox_spi_get_emul(state, bus, slave, &emul);
  81        if (ret) {
  82                printf("%s: busnum=%u, cs=%u: no emulation available (err=%d)\n",
  83                       __func__, busnum, cs, ret);
  84                return -ENOENT;
  85        }
  86        ret = device_probe(emul);
  87        if (ret)
  88                return ret;
  89
  90        /* make sure rx/tx buffers are full so clients can assume */
  91        if (!tx) {
  92                debug("sandbox_spi: xfer: auto-allocating tx scratch buffer\n");
  93                tx = malloc(bytes);
  94                if (!tx) {
  95                        debug("sandbox_spi: Out of memory\n");
  96                        return -ENOMEM;
  97                }
  98        }
  99        if (!rx) {
 100                debug("sandbox_spi: xfer: auto-allocating rx scratch buffer\n");
 101                rx = malloc(bytes);
 102                if (!rx) {
 103                        debug("sandbox_spi: Out of memory\n");
 104                        return -ENOMEM;
 105                }
 106        }
 107
 108        ops = spi_emul_get_ops(emul);
 109        ret = ops->xfer(emul, bitlen, dout, din, flags);
 110
 111        debug("sandbox_spi: xfer: got back %i (that's %s)\n rx:",
 112              ret, ret ? "bad" : "good");
 113        for (i = 0; i < bytes; ++i)
 114                debug(" %u:%02x", i, rx[i]);
 115        debug("\n");
 116
 117        if (tx != dout)
 118                free(tx);
 119        if (rx != din)
 120                free(rx);
 121
 122        return ret;
 123}
 124
 125static int sandbox_spi_set_speed(struct udevice *bus, uint speed)
 126{
 127        return 0;
 128}
 129
 130static int sandbox_spi_set_mode(struct udevice *bus, uint mode)
 131{
 132        return 0;
 133}
 134
 135static int sandbox_cs_info(struct udevice *bus, uint cs,
 136                           struct spi_cs_info *info)
 137{
 138        /* Always allow activity on CS 0 */
 139        if (cs >= 1)
 140                return -ENODEV;
 141
 142        return 0;
 143}
 144
 145static const struct dm_spi_ops sandbox_spi_ops = {
 146        .xfer           = sandbox_spi_xfer,
 147        .set_speed      = sandbox_spi_set_speed,
 148        .set_mode       = sandbox_spi_set_mode,
 149        .cs_info        = sandbox_cs_info,
 150};
 151
 152static const struct udevice_id sandbox_spi_ids[] = {
 153        { .compatible = "sandbox,spi" },
 154        { }
 155};
 156
 157U_BOOT_DRIVER(spi_sandbox) = {
 158        .name   = "spi_sandbox",
 159        .id     = UCLASS_SPI,
 160        .of_match = sandbox_spi_ids,
 161        .ops    = &sandbox_spi_ops,
 162};
 163