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