1*6122813fSMike Frysinger /* 2*6122813fSMike Frysinger * Simulate a SPI port 3*6122813fSMike Frysinger * 4*6122813fSMike Frysinger * Copyright (c) 2011-2013 The Chromium OS Authors. 5*6122813fSMike Frysinger * See file CREDITS for list of people who contributed to this 6*6122813fSMike Frysinger * project. 7*6122813fSMike Frysinger * 8*6122813fSMike Frysinger * Licensed under the GPL-2 or later. 9*6122813fSMike Frysinger */ 10*6122813fSMike Frysinger 11*6122813fSMike Frysinger #include <common.h> 12*6122813fSMike Frysinger #include <malloc.h> 13*6122813fSMike Frysinger #include <spi.h> 14*6122813fSMike Frysinger #include <os.h> 15*6122813fSMike Frysinger 16*6122813fSMike Frysinger #include <asm/errno.h> 17*6122813fSMike Frysinger #include <asm/spi.h> 18*6122813fSMike Frysinger #include <asm/state.h> 19*6122813fSMike Frysinger 20*6122813fSMike Frysinger #ifndef CONFIG_SPI_IDLE_VAL 21*6122813fSMike Frysinger # define CONFIG_SPI_IDLE_VAL 0xFF 22*6122813fSMike Frysinger #endif 23*6122813fSMike Frysinger 24*6122813fSMike Frysinger struct sandbox_spi_slave { 25*6122813fSMike Frysinger struct spi_slave slave; 26*6122813fSMike Frysinger const struct sandbox_spi_emu_ops *ops; 27*6122813fSMike Frysinger void *priv; 28*6122813fSMike Frysinger }; 29*6122813fSMike Frysinger 30*6122813fSMike Frysinger #define to_sandbox_spi_slave(s) container_of(s, struct sandbox_spi_slave, slave) 31*6122813fSMike Frysinger 32*6122813fSMike Frysinger const char *sandbox_spi_parse_spec(const char *arg, unsigned long *bus, 33*6122813fSMike Frysinger unsigned long *cs) 34*6122813fSMike Frysinger { 35*6122813fSMike Frysinger char *endp; 36*6122813fSMike Frysinger 37*6122813fSMike Frysinger *bus = simple_strtoul(arg, &endp, 0); 38*6122813fSMike Frysinger if (*endp != ':' || *bus >= CONFIG_SANDBOX_SPI_MAX_BUS) 39*6122813fSMike Frysinger return NULL; 40*6122813fSMike Frysinger 41*6122813fSMike Frysinger *cs = simple_strtoul(endp + 1, &endp, 0); 42*6122813fSMike Frysinger if (*endp != ':' || *cs >= CONFIG_SANDBOX_SPI_MAX_CS) 43*6122813fSMike Frysinger return NULL; 44*6122813fSMike Frysinger 45*6122813fSMike Frysinger return endp + 1; 46*6122813fSMike Frysinger } 47*6122813fSMike Frysinger 48*6122813fSMike Frysinger int spi_cs_is_valid(unsigned int bus, unsigned int cs) 49*6122813fSMike Frysinger { 50*6122813fSMike Frysinger return bus < CONFIG_SANDBOX_SPI_MAX_BUS && 51*6122813fSMike Frysinger cs < CONFIG_SANDBOX_SPI_MAX_CS; 52*6122813fSMike Frysinger } 53*6122813fSMike Frysinger 54*6122813fSMike Frysinger void spi_cs_activate(struct spi_slave *slave) 55*6122813fSMike Frysinger { 56*6122813fSMike Frysinger struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave); 57*6122813fSMike Frysinger 58*6122813fSMike Frysinger debug("sandbox_spi: activating CS\n"); 59*6122813fSMike Frysinger if (sss->ops->cs_activate) 60*6122813fSMike Frysinger sss->ops->cs_activate(sss->priv); 61*6122813fSMike Frysinger } 62*6122813fSMike Frysinger 63*6122813fSMike Frysinger void spi_cs_deactivate(struct spi_slave *slave) 64*6122813fSMike Frysinger { 65*6122813fSMike Frysinger struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave); 66*6122813fSMike Frysinger 67*6122813fSMike Frysinger debug("sandbox_spi: deactivating CS\n"); 68*6122813fSMike Frysinger if (sss->ops->cs_deactivate) 69*6122813fSMike Frysinger sss->ops->cs_deactivate(sss->priv); 70*6122813fSMike Frysinger } 71*6122813fSMike Frysinger 72*6122813fSMike Frysinger void spi_init(void) 73*6122813fSMike Frysinger { 74*6122813fSMike Frysinger } 75*6122813fSMike Frysinger 76*6122813fSMike Frysinger void spi_set_speed(struct spi_slave *slave, uint hz) 77*6122813fSMike Frysinger { 78*6122813fSMike Frysinger } 79*6122813fSMike Frysinger 80*6122813fSMike Frysinger struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, 81*6122813fSMike Frysinger unsigned int max_hz, unsigned int mode) 82*6122813fSMike Frysinger { 83*6122813fSMike Frysinger struct sandbox_spi_slave *sss; 84*6122813fSMike Frysinger struct sandbox_state *state = state_get_current(); 85*6122813fSMike Frysinger const char *spec; 86*6122813fSMike Frysinger 87*6122813fSMike Frysinger if (!spi_cs_is_valid(bus, cs)) { 88*6122813fSMike Frysinger debug("sandbox_spi: Invalid SPI bus/cs\n"); 89*6122813fSMike Frysinger return NULL; 90*6122813fSMike Frysinger } 91*6122813fSMike Frysinger 92*6122813fSMike Frysinger sss = spi_alloc_slave(struct sandbox_spi_slave, bus, cs); 93*6122813fSMike Frysinger if (!sss) { 94*6122813fSMike Frysinger debug("sandbox_spi: Out of memory\n"); 95*6122813fSMike Frysinger return NULL; 96*6122813fSMike Frysinger } 97*6122813fSMike Frysinger 98*6122813fSMike Frysinger spec = state->spi[bus][cs].spec; 99*6122813fSMike Frysinger sss->ops = state->spi[bus][cs].ops; 100*6122813fSMike Frysinger if (!spec || !sss->ops || sss->ops->setup(&sss->priv, spec)) { 101*6122813fSMike Frysinger free(sss); 102*6122813fSMike Frysinger printf("sandbox_spi: unable to locate a slave client\n"); 103*6122813fSMike Frysinger return NULL; 104*6122813fSMike Frysinger } 105*6122813fSMike Frysinger 106*6122813fSMike Frysinger return &sss->slave; 107*6122813fSMike Frysinger } 108*6122813fSMike Frysinger 109*6122813fSMike Frysinger void spi_free_slave(struct spi_slave *slave) 110*6122813fSMike Frysinger { 111*6122813fSMike Frysinger struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave); 112*6122813fSMike Frysinger 113*6122813fSMike Frysinger debug("sandbox_spi: releasing slave\n"); 114*6122813fSMike Frysinger 115*6122813fSMike Frysinger if (sss->ops->free) 116*6122813fSMike Frysinger sss->ops->free(sss->priv); 117*6122813fSMike Frysinger 118*6122813fSMike Frysinger free(sss); 119*6122813fSMike Frysinger } 120*6122813fSMike Frysinger 121*6122813fSMike Frysinger static int spi_bus_claim_cnt[CONFIG_SANDBOX_SPI_MAX_BUS]; 122*6122813fSMike Frysinger 123*6122813fSMike Frysinger int spi_claim_bus(struct spi_slave *slave) 124*6122813fSMike Frysinger { 125*6122813fSMike Frysinger if (spi_bus_claim_cnt[slave->bus]++) { 126*6122813fSMike Frysinger printf("sandbox_spi: error: bus already claimed: %d!\n", 127*6122813fSMike Frysinger spi_bus_claim_cnt[slave->bus]); 128*6122813fSMike Frysinger } 129*6122813fSMike Frysinger 130*6122813fSMike Frysinger return 0; 131*6122813fSMike Frysinger } 132*6122813fSMike Frysinger 133*6122813fSMike Frysinger void spi_release_bus(struct spi_slave *slave) 134*6122813fSMike Frysinger { 135*6122813fSMike Frysinger if (--spi_bus_claim_cnt[slave->bus]) { 136*6122813fSMike Frysinger printf("sandbox_spi: error: bus freed too often: %d!\n", 137*6122813fSMike Frysinger spi_bus_claim_cnt[slave->bus]); 138*6122813fSMike Frysinger } 139*6122813fSMike Frysinger } 140*6122813fSMike Frysinger 141*6122813fSMike Frysinger int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, 142*6122813fSMike Frysinger void *din, unsigned long flags) 143*6122813fSMike Frysinger { 144*6122813fSMike Frysinger struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave); 145*6122813fSMike Frysinger uint bytes = bitlen / 8, i; 146*6122813fSMike Frysinger int ret = 0; 147*6122813fSMike Frysinger u8 *tx = (void *)dout, *rx = din; 148*6122813fSMike Frysinger 149*6122813fSMike Frysinger if (bitlen == 0) 150*6122813fSMike Frysinger goto done; 151*6122813fSMike Frysinger 152*6122813fSMike Frysinger /* we can only do 8 bit transfers */ 153*6122813fSMike Frysinger if (bitlen % 8) { 154*6122813fSMike Frysinger printf("sandbox_spi: xfer: invalid bitlen size %u; needs to be 8bit\n", 155*6122813fSMike Frysinger bitlen); 156*6122813fSMike Frysinger flags |= SPI_XFER_END; 157*6122813fSMike Frysinger goto done; 158*6122813fSMike Frysinger } 159*6122813fSMike Frysinger 160*6122813fSMike Frysinger if (flags & SPI_XFER_BEGIN) 161*6122813fSMike Frysinger spi_cs_activate(slave); 162*6122813fSMike Frysinger 163*6122813fSMike Frysinger /* make sure rx/tx buffers are full so clients can assume */ 164*6122813fSMike Frysinger if (!tx) { 165*6122813fSMike Frysinger debug("sandbox_spi: xfer: auto-allocating tx scratch buffer\n"); 166*6122813fSMike Frysinger tx = malloc(bytes); 167*6122813fSMike Frysinger if (!tx) { 168*6122813fSMike Frysinger debug("sandbox_spi: Out of memory\n"); 169*6122813fSMike Frysinger return -ENOMEM; 170*6122813fSMike Frysinger } 171*6122813fSMike Frysinger } 172*6122813fSMike Frysinger if (!rx) { 173*6122813fSMike Frysinger debug("sandbox_spi: xfer: auto-allocating rx scratch buffer\n"); 174*6122813fSMike Frysinger rx = malloc(bytes); 175*6122813fSMike Frysinger if (!rx) { 176*6122813fSMike Frysinger debug("sandbox_spi: Out of memory\n"); 177*6122813fSMike Frysinger return -ENOMEM; 178*6122813fSMike Frysinger } 179*6122813fSMike Frysinger } 180*6122813fSMike Frysinger 181*6122813fSMike Frysinger debug("sandbox_spi: xfer: bytes = %u\n tx:", bytes); 182*6122813fSMike Frysinger for (i = 0; i < bytes; ++i) 183*6122813fSMike Frysinger debug(" %u:%02x", i, tx[i]); 184*6122813fSMike Frysinger debug("\n"); 185*6122813fSMike Frysinger 186*6122813fSMike Frysinger ret = sss->ops->xfer(sss->priv, tx, rx, bytes); 187*6122813fSMike Frysinger 188*6122813fSMike Frysinger debug("sandbox_spi: xfer: got back %i (that's %s)\n rx:", 189*6122813fSMike Frysinger ret, ret ? "bad" : "good"); 190*6122813fSMike Frysinger for (i = 0; i < bytes; ++i) 191*6122813fSMike Frysinger debug(" %u:%02x", i, rx[i]); 192*6122813fSMike Frysinger debug("\n"); 193*6122813fSMike Frysinger 194*6122813fSMike Frysinger if (tx != dout) 195*6122813fSMike Frysinger free(tx); 196*6122813fSMike Frysinger if (rx != din) 197*6122813fSMike Frysinger free(rx); 198*6122813fSMike Frysinger 199*6122813fSMike Frysinger done: 200*6122813fSMike Frysinger if (flags & SPI_XFER_END) 201*6122813fSMike Frysinger spi_cs_deactivate(slave); 202*6122813fSMike Frysinger 203*6122813fSMike Frysinger return ret; 204*6122813fSMike Frysinger } 205