blob: c13165030db6e5edb71ef78491039977d3ef0ae0 [file] [log] [blame]
wdenke3093092002-10-01 01:07:28 +00001/*
2 * (C) Copyright 2002
3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
4 *
5 * Influenced by code from:
6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 */
26
27#include <common.h>
28#include <spi.h>
29
30#if defined(CONFIG_SOFT_SPI)
31
Haavard Skinnemoend255bb02008-05-16 11:10:31 +020032#include <malloc.h>
33
wdenke3093092002-10-01 01:07:28 +000034/*-----------------------------------------------------------------------
35 * Definitions
36 */
37
38#ifdef DEBUG_SPI
39#define PRINTD(fmt,args...) printf (fmt ,##args)
40#else
41#define PRINTD(fmt,args...)
42#endif
43
Haavard Skinnemoend255bb02008-05-16 11:10:31 +020044struct soft_spi_slave {
45 struct spi_slave slave;
46 unsigned int mode;
47};
48
49static inline struct soft_spi_slave *to_soft_spi(struct spi_slave *slave)
50{
51 return container_of(slave, struct soft_spi_slave, slave);
52}
wdenke3093092002-10-01 01:07:28 +000053
wdenke3093092002-10-01 01:07:28 +000054/*=====================================================================*/
55/* Public Functions */
56/*=====================================================================*/
57
58/*-----------------------------------------------------------------------
59 * Initialization
60 */
61void spi_init (void)
62{
63#ifdef SPI_INIT
64 volatile immap_t *immr = (immap_t *)CFG_IMMR;
65
66 SPI_INIT;
67#endif
68}
69
Haavard Skinnemoend255bb02008-05-16 11:10:31 +020070struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
71 unsigned int max_hz, unsigned int mode)
72{
73 struct soft_spi_slave *ss;
74
75 if (!spi_cs_is_valid(bus, cs))
76 return NULL;
77
78 ss = malloc(sizeof(struct soft_spi_slave));
79 if (!ss)
80 return NULL;
81
82 ss->slave.bus = bus;
83 ss->slave.cs = cs;
84 ss->mode = mode;
85
86 /* TODO: Use max_hz to limit the SCK rate */
87
88 return &ss->slave;
89}
90
91void spi_free_slave(struct spi_slave *slave)
92{
93 struct soft_spi_slave *ss = to_soft_spi(slave);
94
95 free(ss);
96}
97
98int spi_claim_bus(struct spi_slave *slave)
99{
100#ifdef CFG_IMMR
101 volatile immap_t *immr = (immap_t *)CFG_IMMR;
102#endif
103 struct soft_spi_slave *ss = to_soft_spi(slave);
104
105 /*
106 * Make sure the SPI clock is in idle state as defined for
107 * this slave.
108 */
109 if (ss->mode & SPI_CPOL)
110 SPI_SCL(1);
111 else
112 SPI_SCL(0);
113
114 return 0;
115}
116
117void spi_release_bus(struct spi_slave *slave)
118{
119 /* Nothing to do */
120}
wdenke3093092002-10-01 01:07:28 +0000121
122/*-----------------------------------------------------------------------
123 * SPI transfer
124 *
125 * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
126 * "bitlen" bits in the SPI MISO port. That's just the way SPI works.
127 *
128 * The source of the outgoing bits is the "dout" parameter and the
129 * destination of the input bits is the "din" parameter. Note that "dout"
130 * and "din" can point to the same memory location, in which case the
131 * input data overwrites the output data (since both are buffered by
132 * temporary variables, this is OK).
wdenke3093092002-10-01 01:07:28 +0000133 */
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200134int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
135 const void *dout, void *din, unsigned long flags)
wdenke3093092002-10-01 01:07:28 +0000136{
John Otkend4024bb2007-07-26 17:49:11 +0200137#ifdef CFG_IMMR
wdenke3093092002-10-01 01:07:28 +0000138 volatile immap_t *immr = (immap_t *)CFG_IMMR;
John Otkend4024bb2007-07-26 17:49:11 +0200139#endif
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200140 struct soft_spi_slave *ss = to_soft_spi(slave);
141 uchar tmpdin = 0;
142 uchar tmpdout = 0;
143 const u8 *txd = dout;
144 u8 *rxd = din;
145 int cpol = ss->mode & SPI_CPOL;
146 int cpha = ss->mode & SPI_CPHA;
147 unsigned int j;
wdenke3093092002-10-01 01:07:28 +0000148
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200149 PRINTD("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
150 slave->bus, slave->cs, *(uint *)txd, *(uint *)rxd, bitlen);
wdenke3093092002-10-01 01:07:28 +0000151
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200152 if (flags & SPI_XFER_BEGIN)
153 spi_cs_activate(slave);
wdenke3093092002-10-01 01:07:28 +0000154
155 for(j = 0; j < bitlen; j++) {
156 /*
157 * Check if it is time to work on a new byte.
158 */
159 if((j % 8) == 0) {
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200160 tmpdout = *txd++;
wdenke3093092002-10-01 01:07:28 +0000161 if(j != 0) {
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200162 *rxd++ = tmpdin;
wdenke3093092002-10-01 01:07:28 +0000163 }
164 tmpdin = 0;
165 }
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200166
167 if (!cpha)
168 SPI_SCL(!cpol);
wdenke3093092002-10-01 01:07:28 +0000169 SPI_SDA(tmpdout & 0x80);
170 SPI_DELAY;
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200171 if (cpha)
172 SPI_SCL(!cpol);
173 else
174 SPI_SCL(cpol);
175 tmpdin <<= 1;
176 tmpdin |= SPI_READ;
177 tmpdout <<= 1;
wdenke3093092002-10-01 01:07:28 +0000178 SPI_DELAY;
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200179 if (cpha)
180 SPI_SCL(cpol);
wdenke3093092002-10-01 01:07:28 +0000181 }
182 /*
183 * If the number of bits isn't a multiple of 8, shift the last
184 * bits over to left-justify them. Then store the last byte
185 * read in.
186 */
187 if((bitlen % 8) != 0)
188 tmpdin <<= 8 - (bitlen % 8);
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200189 *rxd++ = tmpdin;
wdenke3093092002-10-01 01:07:28 +0000190
Haavard Skinnemoend255bb02008-05-16 11:10:31 +0200191 if (flags & SPI_XFER_END)
192 spi_cs_deactivate(slave);
wdenke3093092002-10-01 01:07:28 +0000193
194 return(0);
195}
196
197#endif /* CONFIG_SOFT_SPI */