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 27 const 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 50 static 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 125 static int sandbox_spi_set_speed(struct udevice *bus, uint speed) 126 { 127 return 0; 128 } 129 130 static int sandbox_spi_set_mode(struct udevice *bus, uint mode) 131 { 132 return 0; 133 } 134 135 static 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 145 static 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 152 static const struct udevice_id sandbox_spi_ids[] = { 153 { .compatible = "sandbox,spi" }, 154 { } 155 }; 156 157 U_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