]>
git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/spi/davinci_spi.c
2 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
4 * Driver for SPI controller on DaVinci. Based on atmel_spi.c
7 * Copyright (C) 2007 Atmel Corporation
9 * See file CREDITS for list of people who contributed to this
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.
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.
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,
31 #include <asm/arch/hardware.h>
32 #include "davinci_spi.h"
39 struct spi_slave
*spi_setup_slave(unsigned int bus
, unsigned int cs
,
40 unsigned int max_hz
, unsigned int mode
)
42 struct davinci_spi_slave
*ds
;
44 if (!spi_cs_is_valid(bus
, cs
))
47 ds
= malloc(sizeof(*ds
));
53 ds
->regs
= (struct davinci_spi_regs
*)CONFIG_SYS_SPI_BASE
;
59 void spi_free_slave(struct spi_slave
*slave
)
61 struct davinci_spi_slave
*ds
= to_davinci_spi(slave
);
66 int spi_claim_bus(struct spi_slave
*slave
)
68 struct davinci_spi_slave
*ds
= to_davinci_spi(slave
);
69 unsigned int scalar
, data1_reg_val
= 0;
71 /* Enable the SPI hardware */
72 writel(SPIGCR0_SPIRST_MASK
, &ds
->regs
->gcr0
);
74 writel(SPIGCR0_SPIENA_MASK
, &ds
->regs
->gcr0
);
76 /* Set master mode, powered up and not activated */
77 writel(SPIGCR1_MASTER_MASK
| SPIGCR1_CLKMOD_MASK
, &ds
->regs
->gcr1
);
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
);
84 scalar
= ((CONFIG_SYS_SPI_CLK
/ ds
->freq
) - 1) & 0xFF;
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
93 writel(8 | (scalar
<< SPIFMT_PRESCALE_SHIFT
) |
94 (1 << SPIFMT_PHASE_SHIFT
), &ds
->regs
->fmt0
);
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
);
102 * Including a minor delay. No science here. Should be good even with
105 writel((50 << SPI_C2TDELAY_SHIFT
) |
106 (50 << SPI_T2CDELAY_SHIFT
), &ds
->regs
->delay
);
108 /* default chip select register */
109 writel(SPIDEF_CSDEF0_MASK
, &ds
->regs
->def
);
112 writel(0, &ds
->regs
->int0
);
113 writel(0, &ds
->regs
->lvl
);
116 writel((readl(&ds
->regs
->gcr1
) | SPIGCR1_SPIENA_MASK
), &ds
->regs
->gcr1
);
121 void spi_release_bus(struct spi_slave
*slave
)
123 struct davinci_spi_slave
*ds
= to_davinci_spi(slave
);
125 /* Disable the SPI hardware */
126 writel(SPIGCR0_SPIRST_MASK
, &ds
->regs
->gcr0
);
129 int spi_xfer(struct spi_slave
*slave
, unsigned int bitlen
,
130 const void *dout
, void *din
, unsigned long flags
)
132 struct davinci_spi_slave
*ds
= to_davinci_spi(slave
);
133 unsigned int len
, data1_reg_val
= readl(&ds
->regs
->dat1
);
135 const u8
*txp
= dout
; /* dout can be NULL for read operation */
136 u8
*rxp
= din
; /* din can be NULL for write operation */
141 /* Finish any previously submitted transfers */
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
151 /* Errors always terminate an ongoing transfer */
152 flags
|= SPI_XFER_END
;
158 /* do an empty read to clear the current contents */
159 readl(&ds
->regs
->buf
);
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
);
167 data1_reg_val
&= ~0xFFFF;
169 data1_reg_val
|= *txp
;
174 * Write to DAT1 is required to keep the serial transfer going.
175 * We just terminate when we reach the end.
177 if ((i
== (len
- 1)) && (flags
& SPI_XFER_END
)) {
179 writel(data1_reg_val
&
180 ~(1 << SPIDAT1_CSHOLD_SHIFT
), &ds
->regs
->dat1
);
183 data1_reg_val
|= ((1 << SPIDAT1_CSHOLD_SHIFT
) |
184 (slave
->cs
<< SPIDAT1_CSNR_SHIFT
));
185 writel(data1_reg_val
, &ds
->regs
->dat1
);
188 /* read the data - wait for data availability */
189 while (readl(&ds
->regs
->buf
) & SPIBUF_RXEMPTY_MASK
);
192 *rxp
= readl(&ds
->regs
->buf
) & 0xFF;
195 /* simply drop the read character */
196 readl(&ds
->regs
->buf
);
202 if (flags
& SPI_XFER_END
) {
203 writel(data1_reg_val
&
204 ~(1 << SPIDAT1_CSHOLD_SHIFT
), &ds
->regs
->dat1
);
209 int spi_cs_is_valid(unsigned int bus
, unsigned int cs
)
211 return bus
== 0 && cs
== 0;
214 void spi_cs_activate(struct spi_slave
*slave
)
219 void spi_cs_deactivate(struct spi_slave
*slave
)