xref: /openbmc/u-boot/drivers/spi/sandbox_spi.c (revision 6e16d90a)
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