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