xref: /openbmc/u-boot/drivers/spi/davinci_spi.c (revision 15855700)
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) |
117 		SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
118 
119 	return 0;
120 }
121 
122 void spi_release_bus(struct spi_slave *slave)
123 {
124 	struct davinci_spi_slave *ds = to_davinci_spi(slave);
125 
126 	/* Disable the SPI hardware */
127 	writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
128 }
129 
130 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
131 		const void *dout, void *din, unsigned long flags)
132 {
133 	struct davinci_spi_slave *ds = to_davinci_spi(slave);
134 	unsigned int	len, data1_reg_val = readl(&ds->regs->dat1);
135 	unsigned int	i_cnt = 0, o_cnt = 0, buf_reg_val;
136 	const u8	*txp = dout; /* dout can be NULL for read operation */
137 	u8		*rxp = din;  /* din can be NULL for write operation */
138 
139 	if (bitlen == 0)
140 		/* Finish any previously submitted transfers */
141 		goto out;
142 
143 	/*
144 	 * It's not clear how non-8-bit-aligned transfers are supposed to be
145 	 * represented as a stream of bytes...this is a limitation of
146 	 * the current SPI interface - here we terminate on receiving such a
147 	 * transfer request.
148 	 */
149 	if (bitlen % 8) {
150 		/* Errors always terminate an ongoing transfer */
151 		flags |= SPI_XFER_END;
152 		goto out;
153 	}
154 
155 	len = bitlen / 8;
156 
157 	/* do an empty read to clear the current contents */
158 	readl(&ds->regs->buf);
159 
160 	/* keep writing and reading 1 byte until done */
161 	while ((i_cnt < len) || (o_cnt < len)) {
162 		/* read RX buffer and flags */
163 		buf_reg_val = readl(&ds->regs->buf);
164 
165 		/* if data is available */
166 		if ((i_cnt < len) &&
167 			(buf_reg_val & SPIBUF_RXEMPTY_MASK) == 0) {
168 			/*
169 			 * If there is no read buffer simply
170 			 * ignore the read character
171 			 */
172 			if (rxp)
173 				*rxp++ = buf_reg_val & 0xFF;
174 			/* increment read words count */
175 			i_cnt++;
176 		}
177 
178 		/*
179 		 * if the tx buffer is empty and there
180 		 * is still data to transmit
181 		 */
182 		if ((o_cnt < len) &&
183 			((buf_reg_val & SPIBUF_TXFULL_MASK) == 0)) {
184 			/* write the data */
185 			data1_reg_val &= ~0xFFFF;
186 			if (txp)
187 				data1_reg_val |= *txp++;
188 			/*
189 			 * Write to DAT1 is required to keep
190 			 * the serial transfer going.
191 			 * We just terminate when we reach the end.
192 			 */
193 			if ((o_cnt == (len - 1)) && (flags & SPI_XFER_END)) {
194 				/* clear CS hold */
195 				writel(data1_reg_val &
196 						~(1 << SPIDAT1_CSHOLD_SHIFT),
197 						&ds->regs->dat1);
198 			} else {
199 				/* enable CS hold and write TX register */
200 				data1_reg_val |= ((1 << SPIDAT1_CSHOLD_SHIFT) |
201 					(slave->cs << SPIDAT1_CSNR_SHIFT));
202 				writel(data1_reg_val, &ds->regs->dat1);
203 			}
204 			/* increment written words count */
205 			o_cnt++;
206 		}
207 	}
208 	return 0;
209 
210 out:
211 	if (flags & SPI_XFER_END) {
212 		writel(data1_reg_val &
213 			~(1 << SPIDAT1_CSHOLD_SHIFT), &ds->regs->dat1);
214 	}
215 	return 0;
216 }
217 
218 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
219 {
220 	return bus == 0 && cs == 0;
221 }
222 
223 void spi_cs_activate(struct spi_slave *slave)
224 {
225 	/* do nothing */
226 }
227 
228 void spi_cs_deactivate(struct spi_slave *slave)
229 {
230 	/* do nothing */
231 }
232