16122813fSMike Frysinger /* 26122813fSMike Frysinger * Simulate a SPI port 36122813fSMike Frysinger * 46122813fSMike Frysinger * Copyright (c) 2011-2013 The Chromium OS Authors. 56122813fSMike Frysinger * See file CREDITS for list of people who contributed to this 66122813fSMike Frysinger * project. 76122813fSMike Frysinger * 86122813fSMike Frysinger * Licensed under the GPL-2 or later. 96122813fSMike Frysinger */ 106122813fSMike Frysinger 116122813fSMike Frysinger #include <common.h> 126122813fSMike Frysinger #include <malloc.h> 136122813fSMike Frysinger #include <spi.h> 146122813fSMike Frysinger #include <os.h> 156122813fSMike Frysinger 166122813fSMike Frysinger #include <asm/errno.h> 176122813fSMike Frysinger #include <asm/spi.h> 186122813fSMike Frysinger #include <asm/state.h> 196122813fSMike Frysinger 206122813fSMike Frysinger #ifndef CONFIG_SPI_IDLE_VAL 216122813fSMike Frysinger # define CONFIG_SPI_IDLE_VAL 0xFF 226122813fSMike Frysinger #endif 236122813fSMike Frysinger 246122813fSMike Frysinger struct sandbox_spi_slave { 256122813fSMike Frysinger struct spi_slave slave; 266122813fSMike Frysinger const struct sandbox_spi_emu_ops *ops; 276122813fSMike Frysinger void *priv; 286122813fSMike Frysinger }; 296122813fSMike Frysinger 306122813fSMike Frysinger #define to_sandbox_spi_slave(s) container_of(s, struct sandbox_spi_slave, slave) 316122813fSMike Frysinger 326122813fSMike Frysinger const char *sandbox_spi_parse_spec(const char *arg, unsigned long *bus, 336122813fSMike Frysinger unsigned long *cs) 346122813fSMike Frysinger { 356122813fSMike Frysinger char *endp; 366122813fSMike Frysinger 376122813fSMike Frysinger *bus = simple_strtoul(arg, &endp, 0); 386122813fSMike Frysinger if (*endp != ':' || *bus >= CONFIG_SANDBOX_SPI_MAX_BUS) 396122813fSMike Frysinger return NULL; 406122813fSMike Frysinger 416122813fSMike Frysinger *cs = simple_strtoul(endp + 1, &endp, 0); 426122813fSMike Frysinger if (*endp != ':' || *cs >= CONFIG_SANDBOX_SPI_MAX_CS) 436122813fSMike Frysinger return NULL; 446122813fSMike Frysinger 456122813fSMike Frysinger return endp + 1; 466122813fSMike Frysinger } 476122813fSMike Frysinger 486122813fSMike Frysinger int spi_cs_is_valid(unsigned int bus, unsigned int cs) 496122813fSMike Frysinger { 506122813fSMike Frysinger return bus < CONFIG_SANDBOX_SPI_MAX_BUS && 516122813fSMike Frysinger cs < CONFIG_SANDBOX_SPI_MAX_CS; 526122813fSMike Frysinger } 536122813fSMike Frysinger 546122813fSMike Frysinger void spi_cs_activate(struct spi_slave *slave) 556122813fSMike Frysinger { 566122813fSMike Frysinger struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave); 576122813fSMike Frysinger 586122813fSMike Frysinger debug("sandbox_spi: activating CS\n"); 596122813fSMike Frysinger if (sss->ops->cs_activate) 606122813fSMike Frysinger sss->ops->cs_activate(sss->priv); 616122813fSMike Frysinger } 626122813fSMike Frysinger 636122813fSMike Frysinger void spi_cs_deactivate(struct spi_slave *slave) 646122813fSMike Frysinger { 656122813fSMike Frysinger struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave); 666122813fSMike Frysinger 676122813fSMike Frysinger debug("sandbox_spi: deactivating CS\n"); 686122813fSMike Frysinger if (sss->ops->cs_deactivate) 696122813fSMike Frysinger sss->ops->cs_deactivate(sss->priv); 706122813fSMike Frysinger } 716122813fSMike Frysinger 726122813fSMike Frysinger void spi_init(void) 736122813fSMike Frysinger { 746122813fSMike Frysinger } 756122813fSMike Frysinger 766122813fSMike Frysinger void spi_set_speed(struct spi_slave *slave, uint hz) 776122813fSMike Frysinger { 786122813fSMike Frysinger } 796122813fSMike Frysinger 806122813fSMike Frysinger struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, 816122813fSMike Frysinger unsigned int max_hz, unsigned int mode) 826122813fSMike Frysinger { 836122813fSMike Frysinger struct sandbox_spi_slave *sss; 846122813fSMike Frysinger struct sandbox_state *state = state_get_current(); 856122813fSMike Frysinger const char *spec; 866122813fSMike Frysinger 876122813fSMike Frysinger if (!spi_cs_is_valid(bus, cs)) { 886122813fSMike Frysinger debug("sandbox_spi: Invalid SPI bus/cs\n"); 896122813fSMike Frysinger return NULL; 906122813fSMike Frysinger } 916122813fSMike Frysinger 926122813fSMike Frysinger sss = spi_alloc_slave(struct sandbox_spi_slave, bus, cs); 936122813fSMike Frysinger if (!sss) { 946122813fSMike Frysinger debug("sandbox_spi: Out of memory\n"); 956122813fSMike Frysinger return NULL; 966122813fSMike Frysinger } 976122813fSMike Frysinger 986122813fSMike Frysinger spec = state->spi[bus][cs].spec; 996122813fSMike Frysinger sss->ops = state->spi[bus][cs].ops; 1006122813fSMike Frysinger if (!spec || !sss->ops || sss->ops->setup(&sss->priv, spec)) { 1016122813fSMike Frysinger free(sss); 1026122813fSMike Frysinger printf("sandbox_spi: unable to locate a slave client\n"); 1036122813fSMike Frysinger return NULL; 1046122813fSMike Frysinger } 1056122813fSMike Frysinger 1066122813fSMike Frysinger return &sss->slave; 1076122813fSMike Frysinger } 1086122813fSMike Frysinger 1096122813fSMike Frysinger void spi_free_slave(struct spi_slave *slave) 1106122813fSMike Frysinger { 1116122813fSMike Frysinger struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave); 1126122813fSMike Frysinger 1136122813fSMike Frysinger debug("sandbox_spi: releasing slave\n"); 1146122813fSMike Frysinger 1156122813fSMike Frysinger if (sss->ops->free) 1166122813fSMike Frysinger sss->ops->free(sss->priv); 1176122813fSMike Frysinger 1186122813fSMike Frysinger free(sss); 1196122813fSMike Frysinger } 1206122813fSMike Frysinger 1216122813fSMike Frysinger static int spi_bus_claim_cnt[CONFIG_SANDBOX_SPI_MAX_BUS]; 1226122813fSMike Frysinger 1236122813fSMike Frysinger int spi_claim_bus(struct spi_slave *slave) 1246122813fSMike Frysinger { 1256122813fSMike Frysinger if (spi_bus_claim_cnt[slave->bus]++) { 1266122813fSMike Frysinger printf("sandbox_spi: error: bus already claimed: %d!\n", 1276122813fSMike Frysinger spi_bus_claim_cnt[slave->bus]); 1286122813fSMike Frysinger } 1296122813fSMike Frysinger 1306122813fSMike Frysinger return 0; 1316122813fSMike Frysinger } 1326122813fSMike Frysinger 1336122813fSMike Frysinger void spi_release_bus(struct spi_slave *slave) 1346122813fSMike Frysinger { 1356122813fSMike Frysinger if (--spi_bus_claim_cnt[slave->bus]) { 1366122813fSMike Frysinger printf("sandbox_spi: error: bus freed too often: %d!\n", 1376122813fSMike Frysinger spi_bus_claim_cnt[slave->bus]); 1386122813fSMike Frysinger } 1396122813fSMike Frysinger } 1406122813fSMike Frysinger 1416122813fSMike Frysinger int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, 1426122813fSMike Frysinger void *din, unsigned long flags) 1436122813fSMike Frysinger { 1446122813fSMike Frysinger struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave); 1456122813fSMike Frysinger uint bytes = bitlen / 8, i; 1466122813fSMike Frysinger int ret = 0; 1476122813fSMike Frysinger u8 *tx = (void *)dout, *rx = din; 1486122813fSMike Frysinger 1496122813fSMike Frysinger if (bitlen == 0) 1506122813fSMike Frysinger goto done; 1516122813fSMike Frysinger 1526122813fSMike Frysinger /* we can only do 8 bit transfers */ 1536122813fSMike Frysinger if (bitlen % 8) { 1546122813fSMike Frysinger printf("sandbox_spi: xfer: invalid bitlen size %u; needs to be 8bit\n", 1556122813fSMike Frysinger bitlen); 1566122813fSMike Frysinger flags |= SPI_XFER_END; 1576122813fSMike Frysinger goto done; 1586122813fSMike Frysinger } 1596122813fSMike Frysinger 1606122813fSMike Frysinger if (flags & SPI_XFER_BEGIN) 1616122813fSMike Frysinger spi_cs_activate(slave); 1626122813fSMike Frysinger 1636122813fSMike Frysinger /* make sure rx/tx buffers are full so clients can assume */ 1646122813fSMike Frysinger if (!tx) { 1656122813fSMike Frysinger debug("sandbox_spi: xfer: auto-allocating tx scratch buffer\n"); 1666122813fSMike Frysinger tx = malloc(bytes); 1676122813fSMike Frysinger if (!tx) { 1686122813fSMike Frysinger debug("sandbox_spi: Out of memory\n"); 1696122813fSMike Frysinger return -ENOMEM; 1706122813fSMike Frysinger } 1716122813fSMike Frysinger } 1726122813fSMike Frysinger if (!rx) { 1736122813fSMike Frysinger debug("sandbox_spi: xfer: auto-allocating rx scratch buffer\n"); 1746122813fSMike Frysinger rx = malloc(bytes); 1756122813fSMike Frysinger if (!rx) { 1766122813fSMike Frysinger debug("sandbox_spi: Out of memory\n"); 1776122813fSMike Frysinger return -ENOMEM; 1786122813fSMike Frysinger } 1796122813fSMike Frysinger } 1806122813fSMike Frysinger 1816122813fSMike Frysinger debug("sandbox_spi: xfer: bytes = %u\n tx:", bytes); 1826122813fSMike Frysinger for (i = 0; i < bytes; ++i) 1836122813fSMike Frysinger debug(" %u:%02x", i, tx[i]); 1846122813fSMike Frysinger debug("\n"); 1856122813fSMike Frysinger 1866122813fSMike Frysinger ret = sss->ops->xfer(sss->priv, tx, rx, bytes); 1876122813fSMike Frysinger 1886122813fSMike Frysinger debug("sandbox_spi: xfer: got back %i (that's %s)\n rx:", 1896122813fSMike Frysinger ret, ret ? "bad" : "good"); 1906122813fSMike Frysinger for (i = 0; i < bytes; ++i) 1916122813fSMike Frysinger debug(" %u:%02x", i, rx[i]); 1926122813fSMike Frysinger debug("\n"); 1936122813fSMike Frysinger 1946122813fSMike Frysinger if (tx != dout) 1956122813fSMike Frysinger free(tx); 1966122813fSMike Frysinger if (rx != din) 1976122813fSMike Frysinger free(rx); 1986122813fSMike Frysinger 1996122813fSMike Frysinger done: 2006122813fSMike Frysinger if (flags & SPI_XFER_END) 2016122813fSMike Frysinger spi_cs_deactivate(slave); 2026122813fSMike Frysinger 2036122813fSMike Frysinger return ret; 2046122813fSMike Frysinger } 205*6e16d90aSSimon Glass 206*6e16d90aSSimon Glass /** 207*6e16d90aSSimon Glass * Set up a new SPI slave for an fdt node 208*6e16d90aSSimon Glass * 209*6e16d90aSSimon Glass * @param blob Device tree blob 210*6e16d90aSSimon Glass * @param node SPI peripheral node to use 211*6e16d90aSSimon Glass * @return 0 if ok, -1 on error 212*6e16d90aSSimon Glass */ 213*6e16d90aSSimon Glass struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node, 214*6e16d90aSSimon Glass int spi_node) 215*6e16d90aSSimon Glass { 216*6e16d90aSSimon Glass return NULL; 217*6e16d90aSSimon Glass } 218