xref: /rk3399_rockchip-uboot/drivers/spi/exynos_spi.c (revision e4eaef8910df805d511b1cb9b2caafa7d2827fdc)
11bf43b82SRajeshwari Shinde /*
21bf43b82SRajeshwari Shinde  * (C) Copyright 2012 SAMSUNG Electronics
31bf43b82SRajeshwari Shinde  * Padmavathi Venna <padma.v@samsung.com>
41bf43b82SRajeshwari Shinde  *
51bf43b82SRajeshwari Shinde  * This program is free software; you can redistribute it and/or modify
61bf43b82SRajeshwari Shinde  * it under the terms of the GNU General Public License as published by
71bf43b82SRajeshwari Shinde  * the Free Software Foundation; either version 2 of the License, or
81bf43b82SRajeshwari Shinde  * (at your option) any later version.
91bf43b82SRajeshwari Shinde  *
101bf43b82SRajeshwari Shinde  * This program is distributed in the hope that it will be useful,
111bf43b82SRajeshwari Shinde  * but WITHOUT ANY WARRANTY; without even the implied warranty of
121bf43b82SRajeshwari Shinde  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
131bf43b82SRajeshwari Shinde  * GNU General Public License for more details.
141bf43b82SRajeshwari Shinde  *
151bf43b82SRajeshwari Shinde  * You should have received a copy of the GNU General Public License
161bf43b82SRajeshwari Shinde  * along with this program; if not, write to the Free Software
171bf43b82SRajeshwari Shinde  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
181bf43b82SRajeshwari Shinde  */
191bf43b82SRajeshwari Shinde 
201bf43b82SRajeshwari Shinde #include <common.h>
211bf43b82SRajeshwari Shinde #include <malloc.h>
221bf43b82SRajeshwari Shinde #include <spi.h>
234d3acb9dSRajeshwari Shinde #include <fdtdec.h>
241bf43b82SRajeshwari Shinde #include <asm/arch/clk.h>
251bf43b82SRajeshwari Shinde #include <asm/arch/clock.h>
261bf43b82SRajeshwari Shinde #include <asm/arch/cpu.h>
271bf43b82SRajeshwari Shinde #include <asm/arch/gpio.h>
281bf43b82SRajeshwari Shinde #include <asm/arch/pinmux.h>
291bf43b82SRajeshwari Shinde #include <asm/arch-exynos/spi.h>
301bf43b82SRajeshwari Shinde #include <asm/io.h>
311bf43b82SRajeshwari Shinde 
324d3acb9dSRajeshwari Shinde DECLARE_GLOBAL_DATA_PTR;
334d3acb9dSRajeshwari Shinde 
341bf43b82SRajeshwari Shinde /* Information about each SPI controller */
351bf43b82SRajeshwari Shinde struct spi_bus {
361bf43b82SRajeshwari Shinde 	enum periph_id periph_id;
371bf43b82SRajeshwari Shinde 	s32 frequency;		/* Default clock frequency, -1 for none */
381bf43b82SRajeshwari Shinde 	struct exynos_spi *regs;
391bf43b82SRajeshwari Shinde 	int inited;		/* 1 if this bus is ready for use */
404d3acb9dSRajeshwari Shinde 	int node;
411bf43b82SRajeshwari Shinde };
421bf43b82SRajeshwari Shinde 
431bf43b82SRajeshwari Shinde /* A list of spi buses that we know about */
441bf43b82SRajeshwari Shinde static struct spi_bus spi_bus[EXYNOS5_SPI_NUM_CONTROLLERS];
454d3acb9dSRajeshwari Shinde static unsigned int bus_count;
461bf43b82SRajeshwari Shinde 
471bf43b82SRajeshwari Shinde struct exynos_spi_slave {
481bf43b82SRajeshwari Shinde 	struct spi_slave slave;
491bf43b82SRajeshwari Shinde 	struct exynos_spi *regs;
501bf43b82SRajeshwari Shinde 	unsigned int freq;		/* Default frequency */
511bf43b82SRajeshwari Shinde 	unsigned int mode;
521bf43b82SRajeshwari Shinde 	enum periph_id periph_id;	/* Peripheral ID for this device */
531bf43b82SRajeshwari Shinde 	unsigned int fifo_size;
54*e4eaef89SRajeshwari Shinde 	int skip_preamble;
551bf43b82SRajeshwari Shinde };
561bf43b82SRajeshwari Shinde 
571bf43b82SRajeshwari Shinde static struct spi_bus *spi_get_bus(unsigned dev_index)
581bf43b82SRajeshwari Shinde {
594d3acb9dSRajeshwari Shinde 	if (dev_index < bus_count)
601bf43b82SRajeshwari Shinde 		return &spi_bus[dev_index];
611bf43b82SRajeshwari Shinde 	debug("%s: invalid bus %d", __func__, dev_index);
621bf43b82SRajeshwari Shinde 
631bf43b82SRajeshwari Shinde 	return NULL;
641bf43b82SRajeshwari Shinde }
651bf43b82SRajeshwari Shinde 
661bf43b82SRajeshwari Shinde static inline struct exynos_spi_slave *to_exynos_spi(struct spi_slave *slave)
671bf43b82SRajeshwari Shinde {
681bf43b82SRajeshwari Shinde 	return container_of(slave, struct exynos_spi_slave, slave);
691bf43b82SRajeshwari Shinde }
701bf43b82SRajeshwari Shinde 
711bf43b82SRajeshwari Shinde /**
721bf43b82SRajeshwari Shinde  * Setup the driver private data
731bf43b82SRajeshwari Shinde  *
741bf43b82SRajeshwari Shinde  * @param bus		ID of the bus that the slave is attached to
751bf43b82SRajeshwari Shinde  * @param cs		ID of the chip select connected to the slave
761bf43b82SRajeshwari Shinde  * @param max_hz	Required spi frequency
771bf43b82SRajeshwari Shinde  * @param mode		Required spi mode (clk polarity, clk phase and
781bf43b82SRajeshwari Shinde  *			master or slave)
791bf43b82SRajeshwari Shinde  * @return new device or NULL
801bf43b82SRajeshwari Shinde  */
811bf43b82SRajeshwari Shinde struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
821bf43b82SRajeshwari Shinde 			unsigned int max_hz, unsigned int mode)
831bf43b82SRajeshwari Shinde {
841bf43b82SRajeshwari Shinde 	struct exynos_spi_slave *spi_slave;
851bf43b82SRajeshwari Shinde 	struct spi_bus *bus;
861bf43b82SRajeshwari Shinde 
871bf43b82SRajeshwari Shinde 	if (!spi_cs_is_valid(busnum, cs)) {
881bf43b82SRajeshwari Shinde 		debug("%s: Invalid bus/chip select %d, %d\n", __func__,
891bf43b82SRajeshwari Shinde 		      busnum, cs);
901bf43b82SRajeshwari Shinde 		return NULL;
911bf43b82SRajeshwari Shinde 	}
921bf43b82SRajeshwari Shinde 
93d3504feeSSimon Glass 	spi_slave = spi_alloc_slave(struct exynos_spi_slave, busnum, cs);
941bf43b82SRajeshwari Shinde 	if (!spi_slave) {
951bf43b82SRajeshwari Shinde 		debug("%s: Could not allocate spi_slave\n", __func__);
961bf43b82SRajeshwari Shinde 		return NULL;
971bf43b82SRajeshwari Shinde 	}
981bf43b82SRajeshwari Shinde 
991bf43b82SRajeshwari Shinde 	bus = &spi_bus[busnum];
1001bf43b82SRajeshwari Shinde 	spi_slave->regs = bus->regs;
1011bf43b82SRajeshwari Shinde 	spi_slave->mode = mode;
1021bf43b82SRajeshwari Shinde 	spi_slave->periph_id = bus->periph_id;
1031bf43b82SRajeshwari Shinde 	if (bus->periph_id == PERIPH_ID_SPI1 ||
1041bf43b82SRajeshwari Shinde 	    bus->periph_id == PERIPH_ID_SPI2)
1051bf43b82SRajeshwari Shinde 		spi_slave->fifo_size = 64;
1061bf43b82SRajeshwari Shinde 	else
1071bf43b82SRajeshwari Shinde 		spi_slave->fifo_size = 256;
1081bf43b82SRajeshwari Shinde 
109*e4eaef89SRajeshwari Shinde 	spi_slave->skip_preamble = 0;
110*e4eaef89SRajeshwari Shinde 
1111bf43b82SRajeshwari Shinde 	spi_slave->freq = bus->frequency;
1121bf43b82SRajeshwari Shinde 	if (max_hz)
1131bf43b82SRajeshwari Shinde 		spi_slave->freq = min(max_hz, spi_slave->freq);
1141bf43b82SRajeshwari Shinde 
1151bf43b82SRajeshwari Shinde 	return &spi_slave->slave;
1161bf43b82SRajeshwari Shinde }
1171bf43b82SRajeshwari Shinde 
1181bf43b82SRajeshwari Shinde /**
1191bf43b82SRajeshwari Shinde  * Free spi controller
1201bf43b82SRajeshwari Shinde  *
1211bf43b82SRajeshwari Shinde  * @param slave	Pointer to spi_slave to which controller has to
1221bf43b82SRajeshwari Shinde  *		communicate with
1231bf43b82SRajeshwari Shinde  */
1241bf43b82SRajeshwari Shinde void spi_free_slave(struct spi_slave *slave)
1251bf43b82SRajeshwari Shinde {
1261bf43b82SRajeshwari Shinde 	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
1271bf43b82SRajeshwari Shinde 
1281bf43b82SRajeshwari Shinde 	free(spi_slave);
1291bf43b82SRajeshwari Shinde }
1301bf43b82SRajeshwari Shinde 
1311bf43b82SRajeshwari Shinde /**
1321bf43b82SRajeshwari Shinde  * Flush spi tx, rx fifos and reset the SPI controller
1331bf43b82SRajeshwari Shinde  *
1341bf43b82SRajeshwari Shinde  * @param slave	Pointer to spi_slave to which controller has to
1351bf43b82SRajeshwari Shinde  *		communicate with
1361bf43b82SRajeshwari Shinde  */
1371bf43b82SRajeshwari Shinde static void spi_flush_fifo(struct spi_slave *slave)
1381bf43b82SRajeshwari Shinde {
1391bf43b82SRajeshwari Shinde 	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
1401bf43b82SRajeshwari Shinde 	struct exynos_spi *regs = spi_slave->regs;
1411bf43b82SRajeshwari Shinde 
1421bf43b82SRajeshwari Shinde 	clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
1431bf43b82SRajeshwari Shinde 	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
1441bf43b82SRajeshwari Shinde 	setbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
1451bf43b82SRajeshwari Shinde }
1461bf43b82SRajeshwari Shinde 
1471bf43b82SRajeshwari Shinde /**
1481bf43b82SRajeshwari Shinde  * Initialize the spi base registers, set the required clock frequency and
1491bf43b82SRajeshwari Shinde  * initialize the gpios
1501bf43b82SRajeshwari Shinde  *
1511bf43b82SRajeshwari Shinde  * @param slave	Pointer to spi_slave to which controller has to
1521bf43b82SRajeshwari Shinde  *		communicate with
1531bf43b82SRajeshwari Shinde  * @return zero on success else a negative value
1541bf43b82SRajeshwari Shinde  */
1551bf43b82SRajeshwari Shinde int spi_claim_bus(struct spi_slave *slave)
1561bf43b82SRajeshwari Shinde {
1571bf43b82SRajeshwari Shinde 	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
1581bf43b82SRajeshwari Shinde 	struct exynos_spi *regs = spi_slave->regs;
1591bf43b82SRajeshwari Shinde 	u32 reg = 0;
1601bf43b82SRajeshwari Shinde 	int ret;
1611bf43b82SRajeshwari Shinde 
1621bf43b82SRajeshwari Shinde 	ret = set_spi_clk(spi_slave->periph_id,
1631bf43b82SRajeshwari Shinde 					spi_slave->freq);
1641bf43b82SRajeshwari Shinde 	if (ret < 0) {
1651bf43b82SRajeshwari Shinde 		debug("%s: Failed to setup spi clock\n", __func__);
1661bf43b82SRajeshwari Shinde 		return ret;
1671bf43b82SRajeshwari Shinde 	}
1681bf43b82SRajeshwari Shinde 
1691bf43b82SRajeshwari Shinde 	exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE);
1701bf43b82SRajeshwari Shinde 
1711bf43b82SRajeshwari Shinde 	spi_flush_fifo(slave);
1721bf43b82SRajeshwari Shinde 
1731bf43b82SRajeshwari Shinde 	reg = readl(&regs->ch_cfg);
1741bf43b82SRajeshwari Shinde 	reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
1751bf43b82SRajeshwari Shinde 
1761bf43b82SRajeshwari Shinde 	if (spi_slave->mode & SPI_CPHA)
1771bf43b82SRajeshwari Shinde 		reg |= SPI_CH_CPHA_B;
1781bf43b82SRajeshwari Shinde 
1791bf43b82SRajeshwari Shinde 	if (spi_slave->mode & SPI_CPOL)
1801bf43b82SRajeshwari Shinde 		reg |= SPI_CH_CPOL_L;
1811bf43b82SRajeshwari Shinde 
1821bf43b82SRajeshwari Shinde 	writel(reg, &regs->ch_cfg);
1831bf43b82SRajeshwari Shinde 	writel(SPI_FB_DELAY_180, &regs->fb_clk);
1841bf43b82SRajeshwari Shinde 
1851bf43b82SRajeshwari Shinde 	return 0;
1861bf43b82SRajeshwari Shinde }
1871bf43b82SRajeshwari Shinde 
1881bf43b82SRajeshwari Shinde /**
1891bf43b82SRajeshwari Shinde  * Reset the spi H/W and flush the tx and rx fifos
1901bf43b82SRajeshwari Shinde  *
1911bf43b82SRajeshwari Shinde  * @param slave	Pointer to spi_slave to which controller has to
1921bf43b82SRajeshwari Shinde  *		communicate with
1931bf43b82SRajeshwari Shinde  */
1941bf43b82SRajeshwari Shinde void spi_release_bus(struct spi_slave *slave)
1951bf43b82SRajeshwari Shinde {
1961bf43b82SRajeshwari Shinde 	spi_flush_fifo(slave);
1971bf43b82SRajeshwari Shinde }
1981bf43b82SRajeshwari Shinde 
1991bf43b82SRajeshwari Shinde static void spi_get_fifo_levels(struct exynos_spi *regs,
2001bf43b82SRajeshwari Shinde 	int *rx_lvl, int *tx_lvl)
2011bf43b82SRajeshwari Shinde {
2021bf43b82SRajeshwari Shinde 	uint32_t spi_sts = readl(&regs->spi_sts);
2031bf43b82SRajeshwari Shinde 
2041bf43b82SRajeshwari Shinde 	*rx_lvl = (spi_sts >> SPI_RX_LVL_OFFSET) & SPI_FIFO_LVL_MASK;
2051bf43b82SRajeshwari Shinde 	*tx_lvl = (spi_sts >> SPI_TX_LVL_OFFSET) & SPI_FIFO_LVL_MASK;
2061bf43b82SRajeshwari Shinde }
2071bf43b82SRajeshwari Shinde 
2081bf43b82SRajeshwari Shinde /**
2091bf43b82SRajeshwari Shinde  * If there's something to transfer, do a software reset and set a
2101bf43b82SRajeshwari Shinde  * transaction size.
2111bf43b82SRajeshwari Shinde  *
2121bf43b82SRajeshwari Shinde  * @param regs	SPI peripheral registers
2131bf43b82SRajeshwari Shinde  * @param count	Number of bytes to transfer
2141bf43b82SRajeshwari Shinde  */
2151bf43b82SRajeshwari Shinde static void spi_request_bytes(struct exynos_spi *regs, int count)
2161bf43b82SRajeshwari Shinde {
2171bf43b82SRajeshwari Shinde 	assert(count && count < (1 << 16));
2181bf43b82SRajeshwari Shinde 	setbits_le32(&regs->ch_cfg, SPI_CH_RST);
2191bf43b82SRajeshwari Shinde 	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
2201bf43b82SRajeshwari Shinde 	writel(count | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
2211bf43b82SRajeshwari Shinde }
2221bf43b82SRajeshwari Shinde 
223*e4eaef89SRajeshwari Shinde static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
224*e4eaef89SRajeshwari Shinde 			void **dinp, void const **doutp, unsigned long flags)
2251bf43b82SRajeshwari Shinde {
2261bf43b82SRajeshwari Shinde 	struct exynos_spi *regs = spi_slave->regs;
2271bf43b82SRajeshwari Shinde 	uchar *rxp = *dinp;
2281bf43b82SRajeshwari Shinde 	const uchar *txp = *doutp;
2291bf43b82SRajeshwari Shinde 	int rx_lvl, tx_lvl;
2301bf43b82SRajeshwari Shinde 	uint out_bytes, in_bytes;
231*e4eaef89SRajeshwari Shinde 	int toread;
232*e4eaef89SRajeshwari Shinde 	unsigned start = get_timer(0);
233*e4eaef89SRajeshwari Shinde 	int stopping;
2341bf43b82SRajeshwari Shinde 
2351bf43b82SRajeshwari Shinde 	out_bytes = in_bytes = todo;
2361bf43b82SRajeshwari Shinde 
237*e4eaef89SRajeshwari Shinde 	stopping = spi_slave->skip_preamble && (flags & SPI_XFER_END) &&
238*e4eaef89SRajeshwari Shinde 					!(spi_slave->mode & SPI_SLAVE);
239*e4eaef89SRajeshwari Shinde 
2401bf43b82SRajeshwari Shinde 	/*
2411bf43b82SRajeshwari Shinde 	 * If there's something to send, do a software reset and set a
2421bf43b82SRajeshwari Shinde 	 * transaction size.
2431bf43b82SRajeshwari Shinde 	 */
2441bf43b82SRajeshwari Shinde 	spi_request_bytes(regs, todo);
2451bf43b82SRajeshwari Shinde 
2461bf43b82SRajeshwari Shinde 	/*
2471bf43b82SRajeshwari Shinde 	 * Bytes are transmitted/received in pairs. Wait to receive all the
2481bf43b82SRajeshwari Shinde 	 * data because then transmission will be done as well.
2491bf43b82SRajeshwari Shinde 	 */
250*e4eaef89SRajeshwari Shinde 	toread = in_bytes;
251*e4eaef89SRajeshwari Shinde 
2521bf43b82SRajeshwari Shinde 	while (in_bytes) {
2531bf43b82SRajeshwari Shinde 		int temp;
2541bf43b82SRajeshwari Shinde 
2551bf43b82SRajeshwari Shinde 		/* Keep the fifos full/empty. */
2561bf43b82SRajeshwari Shinde 		spi_get_fifo_levels(regs, &rx_lvl, &tx_lvl);
2571bf43b82SRajeshwari Shinde 		if (tx_lvl < spi_slave->fifo_size && out_bytes) {
2581bf43b82SRajeshwari Shinde 			temp = txp ? *txp++ : 0xff;
2591bf43b82SRajeshwari Shinde 			writel(temp, &regs->tx_data);
2601bf43b82SRajeshwari Shinde 			out_bytes--;
2611bf43b82SRajeshwari Shinde 		}
262*e4eaef89SRajeshwari Shinde 		if (rx_lvl > 0) {
2631bf43b82SRajeshwari Shinde 			temp = readl(&regs->rx_data);
264*e4eaef89SRajeshwari Shinde 			if (spi_slave->skip_preamble) {
265*e4eaef89SRajeshwari Shinde 				if (temp == SPI_PREAMBLE_END_BYTE) {
266*e4eaef89SRajeshwari Shinde 					spi_slave->skip_preamble = 0;
267*e4eaef89SRajeshwari Shinde 					stopping = 0;
268*e4eaef89SRajeshwari Shinde 				}
269*e4eaef89SRajeshwari Shinde 			} else {
270*e4eaef89SRajeshwari Shinde 				if (rxp || stopping)
2711bf43b82SRajeshwari Shinde 					*rxp++ = temp;
2721bf43b82SRajeshwari Shinde 				in_bytes--;
2731bf43b82SRajeshwari Shinde 			}
274*e4eaef89SRajeshwari Shinde 			toread--;
275*e4eaef89SRajeshwari Shinde 		} else if (!toread) {
276*e4eaef89SRajeshwari Shinde 			/*
277*e4eaef89SRajeshwari Shinde 			 * We have run out of input data, but haven't read
278*e4eaef89SRajeshwari Shinde 			 * enough bytes after the preamble yet. Read some more,
279*e4eaef89SRajeshwari Shinde 			 * and make sure that we transmit dummy bytes too, to
280*e4eaef89SRajeshwari Shinde 			 * keep things going.
281*e4eaef89SRajeshwari Shinde 			 */
282*e4eaef89SRajeshwari Shinde 			assert(!out_bytes);
283*e4eaef89SRajeshwari Shinde 			out_bytes = in_bytes;
284*e4eaef89SRajeshwari Shinde 			toread = in_bytes;
285*e4eaef89SRajeshwari Shinde 			txp = NULL;
286*e4eaef89SRajeshwari Shinde 			spi_request_bytes(regs, toread);
2871bf43b82SRajeshwari Shinde 		}
288*e4eaef89SRajeshwari Shinde 		if (spi_slave->skip_preamble && get_timer(start) > 100) {
289*e4eaef89SRajeshwari Shinde 			printf("SPI timeout: in_bytes=%d, out_bytes=%d, ",
290*e4eaef89SRajeshwari Shinde 			       in_bytes, out_bytes);
291*e4eaef89SRajeshwari Shinde 			return -1;
292*e4eaef89SRajeshwari Shinde 		}
293*e4eaef89SRajeshwari Shinde 	}
294*e4eaef89SRajeshwari Shinde 
2951bf43b82SRajeshwari Shinde 	*dinp = rxp;
2961bf43b82SRajeshwari Shinde 	*doutp = txp;
297*e4eaef89SRajeshwari Shinde 
298*e4eaef89SRajeshwari Shinde 	return 0;
2991bf43b82SRajeshwari Shinde }
3001bf43b82SRajeshwari Shinde 
3011bf43b82SRajeshwari Shinde /**
3021bf43b82SRajeshwari Shinde  * Transfer and receive data
3031bf43b82SRajeshwari Shinde  *
3041bf43b82SRajeshwari Shinde  * @param slave		Pointer to spi_slave to which controller has to
3051bf43b82SRajeshwari Shinde  *			communicate with
3061bf43b82SRajeshwari Shinde  * @param bitlen	No of bits to tranfer or receive
3071bf43b82SRajeshwari Shinde  * @param dout		Pointer to transfer buffer
3081bf43b82SRajeshwari Shinde  * @param din		Pointer to receive buffer
3091bf43b82SRajeshwari Shinde  * @param flags		Flags for transfer begin and end
3101bf43b82SRajeshwari Shinde  * @return zero on success else a negative value
3111bf43b82SRajeshwari Shinde  */
3121bf43b82SRajeshwari Shinde int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
3131bf43b82SRajeshwari Shinde 	     void *din, unsigned long flags)
3141bf43b82SRajeshwari Shinde {
3151bf43b82SRajeshwari Shinde 	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
3161bf43b82SRajeshwari Shinde 	int upto, todo;
3171bf43b82SRajeshwari Shinde 	int bytelen;
318*e4eaef89SRajeshwari Shinde 	int ret = 0;
3191bf43b82SRajeshwari Shinde 
3201bf43b82SRajeshwari Shinde 	/* spi core configured to do 8 bit transfers */
3211bf43b82SRajeshwari Shinde 	if (bitlen % 8) {
3221bf43b82SRajeshwari Shinde 		debug("Non byte aligned SPI transfer.\n");
3231bf43b82SRajeshwari Shinde 		return -1;
3241bf43b82SRajeshwari Shinde 	}
3251bf43b82SRajeshwari Shinde 
3261bf43b82SRajeshwari Shinde 	/* Start the transaction, if necessary. */
3271bf43b82SRajeshwari Shinde 	if ((flags & SPI_XFER_BEGIN))
3281bf43b82SRajeshwari Shinde 		spi_cs_activate(slave);
3291bf43b82SRajeshwari Shinde 
3301bf43b82SRajeshwari Shinde 	/* Exynos SPI limits each transfer to 65535 bytes */
3311bf43b82SRajeshwari Shinde 	bytelen =  bitlen / 8;
332*e4eaef89SRajeshwari Shinde 	for (upto = 0; !ret && upto < bytelen; upto += todo) {
3331bf43b82SRajeshwari Shinde 		todo = min(bytelen - upto, (1 << 16) - 1);
334*e4eaef89SRajeshwari Shinde 		ret = spi_rx_tx(spi_slave, todo, &din, &dout, flags);
335*e4eaef89SRajeshwari Shinde 		if (ret)
336*e4eaef89SRajeshwari Shinde 			break;
3371bf43b82SRajeshwari Shinde 	}
3381bf43b82SRajeshwari Shinde 
3391bf43b82SRajeshwari Shinde 	/* Stop the transaction, if necessary. */
340*e4eaef89SRajeshwari Shinde 	if ((flags & SPI_XFER_END) && !(spi_slave->mode & SPI_SLAVE)) {
3411bf43b82SRajeshwari Shinde 		spi_cs_deactivate(slave);
342*e4eaef89SRajeshwari Shinde 		if (spi_slave->skip_preamble) {
343*e4eaef89SRajeshwari Shinde 			assert(!spi_slave->skip_preamble);
344*e4eaef89SRajeshwari Shinde 			debug("Failed to complete premable transaction\n");
345*e4eaef89SRajeshwari Shinde 			ret = -1;
346*e4eaef89SRajeshwari Shinde 		}
347*e4eaef89SRajeshwari Shinde 	}
3481bf43b82SRajeshwari Shinde 
349*e4eaef89SRajeshwari Shinde 	return ret;
3501bf43b82SRajeshwari Shinde }
3511bf43b82SRajeshwari Shinde 
3521bf43b82SRajeshwari Shinde /**
3531bf43b82SRajeshwari Shinde  * Validates the bus and chip select numbers
3541bf43b82SRajeshwari Shinde  *
3551bf43b82SRajeshwari Shinde  * @param bus	ID of the bus that the slave is attached to
3561bf43b82SRajeshwari Shinde  * @param cs	ID of the chip select connected to the slave
3571bf43b82SRajeshwari Shinde  * @return one on success else zero
3581bf43b82SRajeshwari Shinde  */
3591bf43b82SRajeshwari Shinde int spi_cs_is_valid(unsigned int bus, unsigned int cs)
3601bf43b82SRajeshwari Shinde {
3611bf43b82SRajeshwari Shinde 	return spi_get_bus(bus) && cs == 0;
3621bf43b82SRajeshwari Shinde }
3631bf43b82SRajeshwari Shinde 
3641bf43b82SRajeshwari Shinde /**
3651bf43b82SRajeshwari Shinde  * Activate the CS by driving it LOW
3661bf43b82SRajeshwari Shinde  *
3671bf43b82SRajeshwari Shinde  * @param slave	Pointer to spi_slave to which controller has to
3681bf43b82SRajeshwari Shinde  *		communicate with
3691bf43b82SRajeshwari Shinde  */
3701bf43b82SRajeshwari Shinde void spi_cs_activate(struct spi_slave *slave)
3711bf43b82SRajeshwari Shinde {
3721bf43b82SRajeshwari Shinde 	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
3731bf43b82SRajeshwari Shinde 
3741bf43b82SRajeshwari Shinde 	clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
3751bf43b82SRajeshwari Shinde 	debug("Activate CS, bus %d\n", spi_slave->slave.bus);
376*e4eaef89SRajeshwari Shinde 	spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
3771bf43b82SRajeshwari Shinde }
3781bf43b82SRajeshwari Shinde 
3791bf43b82SRajeshwari Shinde /**
3801bf43b82SRajeshwari Shinde  * Deactivate the CS by driving it HIGH
3811bf43b82SRajeshwari Shinde  *
3821bf43b82SRajeshwari Shinde  * @param slave	Pointer to spi_slave to which controller has to
3831bf43b82SRajeshwari Shinde  *		communicate with
3841bf43b82SRajeshwari Shinde  */
3851bf43b82SRajeshwari Shinde void spi_cs_deactivate(struct spi_slave *slave)
3861bf43b82SRajeshwari Shinde {
3871bf43b82SRajeshwari Shinde 	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
3881bf43b82SRajeshwari Shinde 
3891bf43b82SRajeshwari Shinde 	setbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
3901bf43b82SRajeshwari Shinde 	debug("Deactivate CS, bus %d\n", spi_slave->slave.bus);
3911bf43b82SRajeshwari Shinde }
3921bf43b82SRajeshwari Shinde 
3931bf43b82SRajeshwari Shinde static inline struct exynos_spi *get_spi_base(int dev_index)
3941bf43b82SRajeshwari Shinde {
3951bf43b82SRajeshwari Shinde 	if (dev_index < 3)
3961bf43b82SRajeshwari Shinde 		return (struct exynos_spi *)samsung_get_base_spi() + dev_index;
3971bf43b82SRajeshwari Shinde 	else
3981bf43b82SRajeshwari Shinde 		return (struct exynos_spi *)samsung_get_base_spi_isp() +
3991bf43b82SRajeshwari Shinde 					(dev_index - 3);
4001bf43b82SRajeshwari Shinde }
4011bf43b82SRajeshwari Shinde 
4024d3acb9dSRajeshwari Shinde /*
4034d3acb9dSRajeshwari Shinde  * Read the SPI config from the device tree node.
4044d3acb9dSRajeshwari Shinde  *
4054d3acb9dSRajeshwari Shinde  * @param blob  FDT blob to read from
4064d3acb9dSRajeshwari Shinde  * @param node  Node offset to read from
4074d3acb9dSRajeshwari Shinde  * @param bus   SPI bus structure to fill with information
4084d3acb9dSRajeshwari Shinde  * @return 0 if ok, or -FDT_ERR_NOTFOUND if something was missing
4094d3acb9dSRajeshwari Shinde  */
4107d179584SVivek Gautam #ifdef CONFIG_OF_CONTROL
4114d3acb9dSRajeshwari Shinde static int spi_get_config(const void *blob, int node, struct spi_bus *bus)
4124d3acb9dSRajeshwari Shinde {
4134d3acb9dSRajeshwari Shinde 	bus->node = node;
4144d3acb9dSRajeshwari Shinde 	bus->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg");
4154d3acb9dSRajeshwari Shinde 	bus->periph_id = pinmux_decode_periph_id(blob, node);
4164d3acb9dSRajeshwari Shinde 
4174d3acb9dSRajeshwari Shinde 	if (bus->periph_id == PERIPH_ID_NONE) {
4184d3acb9dSRajeshwari Shinde 		debug("%s: Invalid peripheral ID %d\n", __func__,
4194d3acb9dSRajeshwari Shinde 			bus->periph_id);
4204d3acb9dSRajeshwari Shinde 		return -FDT_ERR_NOTFOUND;
4214d3acb9dSRajeshwari Shinde 	}
4224d3acb9dSRajeshwari Shinde 
4234d3acb9dSRajeshwari Shinde 	/* Use 500KHz as a suitable default */
4244d3acb9dSRajeshwari Shinde 	bus->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
4254d3acb9dSRajeshwari Shinde 					500000);
4264d3acb9dSRajeshwari Shinde 
4274d3acb9dSRajeshwari Shinde 	return 0;
4284d3acb9dSRajeshwari Shinde }
4294d3acb9dSRajeshwari Shinde 
4304d3acb9dSRajeshwari Shinde /*
4314d3acb9dSRajeshwari Shinde  * Process a list of nodes, adding them to our list of SPI ports.
4324d3acb9dSRajeshwari Shinde  *
4334d3acb9dSRajeshwari Shinde  * @param blob          fdt blob
4344d3acb9dSRajeshwari Shinde  * @param node_list     list of nodes to process (any <=0 are ignored)
4354d3acb9dSRajeshwari Shinde  * @param count         number of nodes to process
4364d3acb9dSRajeshwari Shinde  * @param is_dvc        1 if these are DVC ports, 0 if standard I2C
4374d3acb9dSRajeshwari Shinde  * @return 0 if ok, -1 on error
4384d3acb9dSRajeshwari Shinde  */
4394d3acb9dSRajeshwari Shinde static int process_nodes(const void *blob, int node_list[], int count)
4404d3acb9dSRajeshwari Shinde {
4414d3acb9dSRajeshwari Shinde 	int i;
4424d3acb9dSRajeshwari Shinde 
4434d3acb9dSRajeshwari Shinde 	/* build the i2c_controllers[] for each controller */
4444d3acb9dSRajeshwari Shinde 	for (i = 0; i < count; i++) {
4454d3acb9dSRajeshwari Shinde 		int node = node_list[i];
4464d3acb9dSRajeshwari Shinde 		struct spi_bus *bus;
4474d3acb9dSRajeshwari Shinde 
4484d3acb9dSRajeshwari Shinde 		if (node <= 0)
4494d3acb9dSRajeshwari Shinde 			continue;
4504d3acb9dSRajeshwari Shinde 
4514d3acb9dSRajeshwari Shinde 		bus = &spi_bus[i];
4524d3acb9dSRajeshwari Shinde 		if (spi_get_config(blob, node, bus)) {
4534d3acb9dSRajeshwari Shinde 			printf("exynos spi_init: failed to decode bus %d\n",
4544d3acb9dSRajeshwari Shinde 				i);
4554d3acb9dSRajeshwari Shinde 			return -1;
4564d3acb9dSRajeshwari Shinde 		}
4574d3acb9dSRajeshwari Shinde 
4584d3acb9dSRajeshwari Shinde 		debug("spi: controller bus %d at %p, periph_id %d\n",
4594d3acb9dSRajeshwari Shinde 		      i, bus->regs, bus->periph_id);
4604d3acb9dSRajeshwari Shinde 		bus->inited = 1;
4614d3acb9dSRajeshwari Shinde 		bus_count++;
4624d3acb9dSRajeshwari Shinde 	}
4634d3acb9dSRajeshwari Shinde 
4644d3acb9dSRajeshwari Shinde 	return 0;
4654d3acb9dSRajeshwari Shinde }
4667d179584SVivek Gautam #endif
4674d3acb9dSRajeshwari Shinde 
4681bf43b82SRajeshwari Shinde /* Sadly there is no error return from this function */
4691bf43b82SRajeshwari Shinde void spi_init(void)
4701bf43b82SRajeshwari Shinde {
4714d3acb9dSRajeshwari Shinde 	int count;
4724d3acb9dSRajeshwari Shinde 
4734d3acb9dSRajeshwari Shinde #ifdef CONFIG_OF_CONTROL
4744d3acb9dSRajeshwari Shinde 	int node_list[EXYNOS5_SPI_NUM_CONTROLLERS];
4754d3acb9dSRajeshwari Shinde 	const void *blob = gd->fdt_blob;
4764d3acb9dSRajeshwari Shinde 
4774d3acb9dSRajeshwari Shinde 	count = fdtdec_find_aliases_for_id(blob, "spi",
4784d3acb9dSRajeshwari Shinde 			COMPAT_SAMSUNG_EXYNOS_SPI, node_list,
4794d3acb9dSRajeshwari Shinde 			EXYNOS5_SPI_NUM_CONTROLLERS);
4804d3acb9dSRajeshwari Shinde 	if (process_nodes(blob, node_list, count))
4814d3acb9dSRajeshwari Shinde 		return;
4824d3acb9dSRajeshwari Shinde 
4834d3acb9dSRajeshwari Shinde #else
4841bf43b82SRajeshwari Shinde 	struct spi_bus *bus;
4851bf43b82SRajeshwari Shinde 
4864d3acb9dSRajeshwari Shinde 	for (count = 0; count < EXYNOS5_SPI_NUM_CONTROLLERS; count++) {
4874d3acb9dSRajeshwari Shinde 		bus = &spi_bus[count];
4884d3acb9dSRajeshwari Shinde 		bus->regs = get_spi_base(count);
4894d3acb9dSRajeshwari Shinde 		bus->periph_id = PERIPH_ID_SPI0 + count;
4901bf43b82SRajeshwari Shinde 
4911bf43b82SRajeshwari Shinde 		/* Although Exynos5 supports upto 50Mhz speed,
4921bf43b82SRajeshwari Shinde 		 * we are setting it to 10Mhz for safe side
4931bf43b82SRajeshwari Shinde 		 */
4941bf43b82SRajeshwari Shinde 		bus->frequency = 10000000;
4951bf43b82SRajeshwari Shinde 		bus->inited = 1;
4964d3acb9dSRajeshwari Shinde 		bus->node = 0;
4974d3acb9dSRajeshwari Shinde 		bus_count = EXYNOS5_SPI_NUM_CONTROLLERS;
4981bf43b82SRajeshwari Shinde 	}
4994d3acb9dSRajeshwari Shinde #endif
5001bf43b82SRajeshwari Shinde }
501