aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorVitaly Wool <vwool@ru.mvista.com>2006-01-08 16:34:28 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-13 19:29:56 -0500
commit8275c642ccdce09a2146d0a9eb022e3698ee927e (patch)
treeea330810f665fcbdf36d31b0da1643db528ad83f /drivers/spi
parent2f9f762879015d738a5ec2ac8a16be94b3a4a06d (diff)
[PATCH] spi: use linked lists rather than an array
This makes the SPI core and its users access transfers in the SPI message structure as linked list not as an array, as discussed on LKML. From: David Brownell <dbrownell@users.sourceforge.net> Updates including doc, bugfixes to the list code, add spi_message_add_tail(). Plus, initialize things _before_ grabbing the locks in some cases (in case it grows more expensive). This also merges some bitbang updates of mine that didn't yet make it into the mm tree. Signed-off-by: Vitaly Wool <vwool@ru.mvista.com> Signed-off-by: Dmitry Pervushin <dpervushin@gmail.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi.c18
-rw-r--r--drivers/spi/spi_bitbang.c86
2 files changed, 60 insertions, 44 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 3ecedccdb96c..cdb242de901d 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -557,6 +557,17 @@ int spi_write_then_read(struct spi_device *spi,
557 if ((n_tx + n_rx) > SPI_BUFSIZ) 557 if ((n_tx + n_rx) > SPI_BUFSIZ)
558 return -EINVAL; 558 return -EINVAL;
559 559
560 spi_message_init(&message);
561 memset(x, 0, sizeof x);
562 if (n_tx) {
563 x[0].len = n_tx;
564 spi_message_add_tail(&x[0], &message);
565 }
566 if (n_rx) {
567 x[1].len = n_rx;
568 spi_message_add_tail(&x[1], &message);
569 }
570
560 /* ... unless someone else is using the pre-allocated buffer */ 571 /* ... unless someone else is using the pre-allocated buffer */
561 if (down_trylock(&lock)) { 572 if (down_trylock(&lock)) {
562 local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); 573 local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
@@ -565,18 +576,11 @@ int spi_write_then_read(struct spi_device *spi,
565 } else 576 } else
566 local_buf = buf; 577 local_buf = buf;
567 578
568 memset(x, 0, sizeof x);
569
570 memcpy(local_buf, txbuf, n_tx); 579 memcpy(local_buf, txbuf, n_tx);
571 x[0].tx_buf = local_buf; 580 x[0].tx_buf = local_buf;
572 x[0].len = n_tx;
573
574 x[1].rx_buf = local_buf + n_tx; 581 x[1].rx_buf = local_buf + n_tx;
575 x[1].len = n_rx;
576 582
577 /* do the i/o */ 583 /* do the i/o */
578 message.transfers = x;
579 message.n_transfer = ARRAY_SIZE(x);
580 status = spi_sync(spi, &message); 584 status = spi_sync(spi, &message);
581 if (status == 0) { 585 if (status == 0) {
582 memcpy(rxbuf, x[1].rx_buf, n_rx); 586 memcpy(rxbuf, x[1].rx_buf, n_rx);
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 44aff198eb96..f037e5593269 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -146,6 +146,9 @@ int spi_bitbang_setup(struct spi_device *spi)
146 struct spi_bitbang_cs *cs = spi->controller_state; 146 struct spi_bitbang_cs *cs = spi->controller_state;
147 struct spi_bitbang *bitbang; 147 struct spi_bitbang *bitbang;
148 148
149 if (!spi->max_speed_hz)
150 return -EINVAL;
151
149 if (!cs) { 152 if (!cs) {
150 cs = kzalloc(sizeof *cs, SLAB_KERNEL); 153 cs = kzalloc(sizeof *cs, SLAB_KERNEL);
151 if (!cs) 154 if (!cs)
@@ -172,13 +175,8 @@ int spi_bitbang_setup(struct spi_device *spi)
172 if (!cs->txrx_word) 175 if (!cs->txrx_word)
173 return -EINVAL; 176 return -EINVAL;
174 177
175 if (!spi->max_speed_hz) 178 /* nsecs = (clock period)/2 */
176 spi->max_speed_hz = 500 * 1000;
177
178 /* nsecs = max(50, (clock period)/2), be optimistic */
179 cs->nsecs = (1000000000/2) / (spi->max_speed_hz); 179 cs->nsecs = (1000000000/2) / (spi->max_speed_hz);
180 if (cs->nsecs < 50)
181 cs->nsecs = 50;
182 if (cs->nsecs > MAX_UDELAY_MS * 1000) 180 if (cs->nsecs > MAX_UDELAY_MS * 1000)
183 return -EINVAL; 181 return -EINVAL;
184 182
@@ -194,7 +192,7 @@ int spi_bitbang_setup(struct spi_device *spi)
194 /* deselect chip (low or high) */ 192 /* deselect chip (low or high) */
195 spin_lock(&bitbang->lock); 193 spin_lock(&bitbang->lock);
196 if (!bitbang->busy) { 194 if (!bitbang->busy) {
197 bitbang->chipselect(spi, 0); 195 bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
198 ndelay(cs->nsecs); 196 ndelay(cs->nsecs);
199 } 197 }
200 spin_unlock(&bitbang->lock); 198 spin_unlock(&bitbang->lock);
@@ -244,9 +242,9 @@ static void bitbang_work(void *_bitbang)
244 struct spi_message *m; 242 struct spi_message *m;
245 struct spi_device *spi; 243 struct spi_device *spi;
246 unsigned nsecs; 244 unsigned nsecs;
247 struct spi_transfer *t; 245 struct spi_transfer *t = NULL;
248 unsigned tmp; 246 unsigned tmp;
249 unsigned chipselect; 247 unsigned cs_change;
250 int status; 248 int status;
251 249
252 m = container_of(bitbang->queue.next, struct spi_message, 250 m = container_of(bitbang->queue.next, struct spi_message,
@@ -254,37 +252,49 @@ static void bitbang_work(void *_bitbang)
254 list_del_init(&m->queue); 252 list_del_init(&m->queue);
255 spin_unlock_irqrestore(&bitbang->lock, flags); 253 spin_unlock_irqrestore(&bitbang->lock, flags);
256 254
257// FIXME this is made-up 255 /* FIXME this is made-up ... the correct value is known to
258nsecs = 100; 256 * word-at-a-time bitbang code, and presumably chipselect()
257 * should enforce these requirements too?
258 */
259 nsecs = 100;
259 260
260 spi = m->spi; 261 spi = m->spi;
261 t = m->transfers;
262 tmp = 0; 262 tmp = 0;
263 chipselect = 0; 263 cs_change = 1;
264 status = 0; 264 status = 0;
265 265
266 for (;;t++) { 266 list_for_each_entry (t, &m->transfers, transfer_list) {
267 if (bitbang->shutdown) { 267 if (bitbang->shutdown) {
268 status = -ESHUTDOWN; 268 status = -ESHUTDOWN;
269 break; 269 break;
270 } 270 }
271 271
272 /* set up default clock polarity, and activate chip */ 272 /* set up default clock polarity, and activate chip;
273 if (!chipselect) { 273 * this implicitly updates clock and spi modes as
274 bitbang->chipselect(spi, 1); 274 * previously recorded for this device via setup().
275 * (and also deselects any other chip that might be
276 * selected ...)
277 */
278 if (cs_change) {
279 bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
275 ndelay(nsecs); 280 ndelay(nsecs);
276 } 281 }
282 cs_change = t->cs_change;
277 if (!t->tx_buf && !t->rx_buf && t->len) { 283 if (!t->tx_buf && !t->rx_buf && t->len) {
278 status = -EINVAL; 284 status = -EINVAL;
279 break; 285 break;
280 } 286 }
281 287
282 /* transfer data */ 288 /* transfer data. the lower level code handles any
289 * new dma mappings it needs. our caller always gave
290 * us dma-safe buffers.
291 */
283 if (t->len) { 292 if (t->len) {
284 /* FIXME if bitbang->use_dma, dma_map_single() 293 /* REVISIT dma API still needs a designated
285 * before the transfer, and dma_unmap_single() 294 * DMA_ADDR_INVALID; ~0 might be better.
286 * afterwards, for either or both buffers...
287 */ 295 */
296 if (!m->is_dma_mapped)
297 t->rx_dma = t->tx_dma = 0;
288 status = bitbang->txrx_bufs(spi, t); 298 status = bitbang->txrx_bufs(spi, t);
289 } 299 }
290 if (status != t->len) { 300 if (status != t->len) {
@@ -299,29 +309,31 @@ nsecs = 100;
299 if (t->delay_usecs) 309 if (t->delay_usecs)
300 udelay(t->delay_usecs); 310 udelay(t->delay_usecs);
301 311
302 tmp++; 312 if (!cs_change)
303 if (tmp >= m->n_transfer)
304 break;
305
306 chipselect = !t->cs_change;
307 if (chipselect);
308 continue; 313 continue;
314 if (t->transfer_list.next == &m->transfers)
315 break;
309 316
310 bitbang->chipselect(spi, 0); 317 /* sometimes a short mid-message deselect of the chip
311 318 * may be needed to terminate a mode or command
312 /* REVISIT do we want the udelay here instead? */ 319 */
313 msleep(1); 320 ndelay(nsecs);
321 bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
322 ndelay(nsecs);
314 } 323 }
315 324
316 tmp = m->n_transfer - 1;
317 tmp = m->transfers[tmp].cs_change;
318
319 m->status = status; 325 m->status = status;
320 m->complete(m->context); 326 m->complete(m->context);
321 327
322 ndelay(2 * nsecs); 328 /* normally deactivate chipselect ... unless no error and
323 bitbang->chipselect(spi, status == 0 && tmp); 329 * cs_change has hinted that the next message will probably
324 ndelay(nsecs); 330 * be for this chip too.
331 */
332 if (!(status == 0 && cs_change)) {
333 ndelay(nsecs);
334 bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
335 ndelay(nsecs);
336 }
325 337
326 spin_lock_irqsave(&bitbang->lock, flags); 338 spin_lock_irqsave(&bitbang->lock, flags);
327 } 339 }