xref: /openbmc/u-boot/drivers/spi/davinci_spi.c (revision a4145534)
1 /*
2  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
3  *
4  * Driver for SPI controller on DaVinci. Based on atmel_spi.c
5  * by Atmel Corporation
6  *
7  * Copyright (C) 2007 Atmel Corporation
8  *
9  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  */
27 #include <common.h>
28 #include <spi.h>
29 #include <malloc.h>
30 #include <asm/io.h>
31 #include <asm/arch/hardware.h>
32 #include "davinci_spi.h"
33 
34 void spi_init()
35 {
36 	/* do nothing */
37 }
38 
39 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
40 			unsigned int max_hz, unsigned int mode)
41 {
42 	struct davinci_spi_slave	*ds;
43 
44 	if (!spi_cs_is_valid(bus, cs))
45 		return NULL;
46 
47 	ds = malloc(sizeof(*ds));
48 	if (!ds)
49 		return NULL;
50 
51 	ds->slave.bus = bus;
52 	ds->slave.cs = cs;
53 	ds->regs = (struct davinci_spi_regs *)CONFIG_SYS_SPI_BASE;
54 	ds->freq = max_hz;
55 
56 	return &ds->slave;
57 }
58 
59 void spi_free_slave(struct spi_slave *slave)
60 {
61 	struct davinci_spi_slave *ds = to_davinci_spi(slave);
62 
63 	free(ds);
64 }
65 
66 int spi_claim_bus(struct spi_slave *slave)
67 {
68 	struct davinci_spi_slave *ds = to_davinci_spi(slave);
69 	unsigned int scalar, data1_reg_val = 0;
70 
71 	/* Enable the SPI hardware */
72 	writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
73 	udelay(1000);
74 	writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
75 
76 	/* Set master mode, powered up and not activated */
77 	writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
78 
79 	/* CS, CLK, SIMO and SOMI are functional pins */
80 	writel((SPIPC0_EN0FUN_MASK | SPIPC0_CLKFUN_MASK |
81 		SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
82 
83 	/* setup format */
84 	scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
85 
86 	/*
87 	 * Use following format:
88 	 *   character length = 8,
89 	 *   clock signal delayed by half clk cycle,
90 	 *   clock low in idle state - Mode 0,
91 	 *   MSB shifted out first
92 	 */
93 	writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
94 		(1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
95 
96 	/* hold cs active at end of transfer until explicitly de-asserted */
97 	data1_reg_val = (1 << SPIDAT1_CSHOLD_SHIFT) |
98 			(slave->cs << SPIDAT1_CSNR_SHIFT);
99 	writel(data1_reg_val, &ds->regs->dat1);
100 
101 	/*
102 	 * Including a minor delay. No science here. Should be good even with
103 	 * no delay
104 	 */
105 	writel((50 << SPI_C2TDELAY_SHIFT) |
106 		(50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
107 
108 	/* default chip select register */
109 	writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
110 
111 	/* no interrupts */
112 	writel(0, &ds->regs->int0);
113 	writel(0, &ds->regs->lvl);
114 
115 	/* enable SPI */
116 	writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
117 
118 	return 0;
119 }
120 
121 void spi_release_bus(struct spi_slave *slave)
122 {
123 	struct davinci_spi_slave *ds = to_davinci_spi(slave);
124 
125 	/* Disable the SPI hardware */
126 	writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
127 }
128 
129 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
130 		const void *dout, void *din, unsigned long flags)
131 {
132 	struct davinci_spi_slave *ds = to_davinci_spi(slave);
133 	unsigned int	len, data1_reg_val = readl(&ds->regs->dat1);
134 	int		ret, i;
135 	const u8	*txp = dout; /* dout can be NULL for read operation */
136 	u8		*rxp = din;  /* din can be NULL for write operation */
137 
138 	ret = 0;
139 
140 	if (bitlen == 0)
141 		/* Finish any previously submitted transfers */
142 		goto out;
143 
144 	/*
145 	 * It's not clear how non-8-bit-aligned transfers are supposed to be
146 	 * represented as a stream of bytes...this is a limitation of
147 	 * the current SPI interface - here we terminate on receiving such a
148 	 * transfer request.
149 	 */
150 	if (bitlen % 8) {
151 		/* Errors always terminate an ongoing transfer */
152 		flags |= SPI_XFER_END;
153 		goto out;
154 	}
155 
156 	len = bitlen / 8;
157 
158 	/* do an empty read to clear the current contents */
159 	readl(&ds->regs->buf);
160 
161 	/* keep writing and reading 1 byte until done */
162 	for (i = 0; i < len; i++) {
163 		/* wait till TXFULL is asserted */
164 		while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK);
165 
166 		/* write the data */
167 		data1_reg_val &= ~0xFFFF;
168 		if (txp) {
169 			data1_reg_val |= *txp;
170 			txp++;
171 		}
172 
173 		/*
174 		 * Write to DAT1 is required to keep the serial transfer going.
175 		 * We just terminate when we reach the end.
176 		 */
177 		if ((i == (len - 1)) && (flags & SPI_XFER_END)) {
178 			/* clear CS hold */
179 			writel(data1_reg_val &
180 				~(1 << SPIDAT1_CSHOLD_SHIFT), &ds->regs->dat1);
181 		} else {
182 			/* enable CS hold */
183 			data1_reg_val |= ((1 << SPIDAT1_CSHOLD_SHIFT) |
184 					(slave->cs << SPIDAT1_CSNR_SHIFT));
185 			writel(data1_reg_val, &ds->regs->dat1);
186 		}
187 
188 		/* read the data - wait for data availability */
189 		while (readl(&ds->regs->buf) & SPIBUF_RXEMPTY_MASK);
190 
191 		if (rxp) {
192 			*rxp = readl(&ds->regs->buf) & 0xFF;
193 			rxp++;
194 		} else {
195 			/* simply drop the read character */
196 			readl(&ds->regs->buf);
197 		}
198 	}
199 	return 0;
200 
201 out:
202 	if (flags & SPI_XFER_END) {
203 		writel(data1_reg_val &
204 			~(1 << SPIDAT1_CSHOLD_SHIFT), &ds->regs->dat1);
205 	}
206 	return 0;
207 }
208 
209 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
210 {
211 	return bus == 0 && cs == 0;
212 }
213 
214 void spi_cs_activate(struct spi_slave *slave)
215 {
216 	/* do nothing */
217 }
218 
219 void spi_cs_deactivate(struct spi_slave *slave)
220 {
221 	/* do nothing */
222 }
223