aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-orion.c
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2012-07-23 07:16:55 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-08-17 17:56:18 -0400
commitba59a807883382f6ce5ad884312d91d5748e90ee (patch)
tree561687a7aa98aed84d9ba5bd5ffc6e9523c2e381 /drivers/spi/spi-orion.c
parentd9875690d9b89a866022ff49e3fcea892345ad92 (diff)
spi: Refactor spi-orion to use SPI framework queue.
Replace the deprecated master->transfer with transfer_one_message() and allow the SPI subsystem handle all the queuing of messages. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Acked-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@googlemail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/spi/spi-orion.c')
-rw-r--r--drivers/spi/spi-orion.c209
1 files changed, 61 insertions, 148 deletions
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 9b0caddce503..b17c09cf0a05 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -36,12 +36,6 @@
36#define ORION_SPI_CLK_PRESCALE_MASK 0x1F 36#define ORION_SPI_CLK_PRESCALE_MASK 0x1F
37 37
38struct orion_spi { 38struct orion_spi {
39 struct work_struct work;
40
41 /* Lock access to transfer list. */
42 spinlock_t lock;
43
44 struct list_head msg_queue;
45 struct spi_master *master; 39 struct spi_master *master;
46 void __iomem *base; 40 void __iomem *base;
47 unsigned int max_speed; 41 unsigned int max_speed;
@@ -49,8 +43,6 @@ struct orion_spi {
49 struct clk *clk; 43 struct clk *clk;
50}; 44};
51 45
52static struct workqueue_struct *orion_spi_wq;
53
54static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg) 46static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
55{ 47{
56 return orion_spi->base + reg; 48 return orion_spi->base + reg;
@@ -277,73 +269,78 @@ out:
277} 269}
278 270
279 271
280static void orion_spi_work(struct work_struct *work) 272static int orion_spi_transfer_one_message(struct spi_master *master,
273 struct spi_message *m)
281{ 274{
282 struct orion_spi *orion_spi = 275 struct orion_spi *orion_spi = spi_master_get_devdata(master);
283 container_of(work, struct orion_spi, work); 276 struct spi_device *spi = m->spi;
284 277 struct spi_transfer *t = NULL;
285 spin_lock_irq(&orion_spi->lock); 278 int par_override = 0;
286 while (!list_empty(&orion_spi->msg_queue)) { 279 int status = 0;
287 struct spi_message *m; 280 int cs_active = 0;
288 struct spi_device *spi;
289 struct spi_transfer *t = NULL;
290 int par_override = 0;
291 int status = 0;
292 int cs_active = 0;
293
294 m = container_of(orion_spi->msg_queue.next, struct spi_message,
295 queue);
296 281
297 list_del_init(&m->queue); 282 /* Load defaults */
298 spin_unlock_irq(&orion_spi->lock); 283 status = orion_spi_setup_transfer(spi, NULL);
299 284
300 spi = m->spi; 285 if (status < 0)
286 goto msg_done;
301 287
302 /* Load defaults */ 288 list_for_each_entry(t, &m->transfers, transfer_list) {
303 status = orion_spi_setup_transfer(spi, NULL); 289 /* make sure buffer length is even when working in 16
290 * bit mode*/
291 if ((t->bits_per_word == 16) && (t->len & 1)) {
292 dev_err(&spi->dev,
293 "message rejected : "
294 "odd data length %d while in 16 bit mode\n",
295 t->len);
296 status = -EIO;
297 goto msg_done;
298 }
304 299
305 if (status < 0) 300 if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
301 dev_err(&spi->dev,
302 "message rejected : "
303 "device min speed (%d Hz) exceeds "
304 "required transfer speed (%d Hz)\n",
305 orion_spi->min_speed, t->speed_hz);
306 status = -EIO;
306 goto msg_done; 307 goto msg_done;
308 }
307 309
308 list_for_each_entry(t, &m->transfers, transfer_list) { 310 if (par_override || t->speed_hz || t->bits_per_word) {
309 if (par_override || t->speed_hz || t->bits_per_word) { 311 par_override = 1;
310 par_override = 1; 312 status = orion_spi_setup_transfer(spi, t);
311 status = orion_spi_setup_transfer(spi, t); 313 if (status < 0)
312 if (status < 0) 314 break;
313 break; 315 if (!t->speed_hz && !t->bits_per_word)
314 if (!t->speed_hz && !t->bits_per_word) 316 par_override = 0;
315 par_override = 0;
316 }
317
318 if (!cs_active) {
319 orion_spi_set_cs(orion_spi, 1);
320 cs_active = 1;
321 }
322
323 if (t->len)
324 m->actual_length +=
325 orion_spi_write_read(spi, t);
326
327 if (t->delay_usecs)
328 udelay(t->delay_usecs);
329
330 if (t->cs_change) {
331 orion_spi_set_cs(orion_spi, 0);
332 cs_active = 0;
333 }
334 } 317 }
335 318
336msg_done: 319 if (!cs_active) {
337 if (cs_active) 320 orion_spi_set_cs(orion_spi, 1);
338 orion_spi_set_cs(orion_spi, 0); 321 cs_active = 1;
322 }
339 323
340 m->status = status; 324 if (t->len)
341 m->complete(m->context); 325 m->actual_length += orion_spi_write_read(spi, t);
342 326
343 spin_lock_irq(&orion_spi->lock); 327 if (t->delay_usecs)
328 udelay(t->delay_usecs);
329
330 if (t->cs_change) {
331 orion_spi_set_cs(orion_spi, 0);
332 cs_active = 0;
333 }
344 } 334 }
345 335
346 spin_unlock_irq(&orion_spi->lock); 336msg_done:
337 if (cs_active)
338 orion_spi_set_cs(orion_spi, 0);
339
340 m->status = status;
341 spi_finalize_current_message(master);
342
343 return 0;
347} 344}
348 345
349static int __init orion_spi_reset(struct orion_spi *orion_spi) 346static int __init orion_spi_reset(struct orion_spi *orion_spi)
@@ -376,75 +373,6 @@ static int orion_spi_setup(struct spi_device *spi)
376 return 0; 373 return 0;
377} 374}
378 375
379static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
380{
381 struct orion_spi *orion_spi;
382 struct spi_transfer *t = NULL;
383 unsigned long flags;
384
385 m->actual_length = 0;
386 m->status = 0;
387
388 /* reject invalid messages and transfers */
389 if (list_empty(&m->transfers) || !m->complete)
390 return -EINVAL;
391
392 orion_spi = spi_master_get_devdata(spi->master);
393
394 list_for_each_entry(t, &m->transfers, transfer_list) {
395 unsigned int bits_per_word = spi->bits_per_word;
396
397 if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
398 dev_err(&spi->dev,
399 "message rejected : "
400 "invalid transfer data buffers\n");
401 goto msg_rejected;
402 }
403
404 if (t->bits_per_word)
405 bits_per_word = t->bits_per_word;
406
407 if ((bits_per_word != 8) && (bits_per_word != 16)) {
408 dev_err(&spi->dev,
409 "message rejected : "
410 "invalid transfer bits_per_word (%d bits)\n",
411 bits_per_word);
412 goto msg_rejected;
413 }
414 /*make sure buffer length is even when working in 16 bit mode*/
415 if ((t->bits_per_word == 16) && (t->len & 1)) {
416 dev_err(&spi->dev,
417 "message rejected : "
418 "odd data length (%d) while in 16 bit mode\n",
419 t->len);
420 goto msg_rejected;
421 }
422
423 if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
424 dev_err(&spi->dev,
425 "message rejected : "
426 "device min speed (%d Hz) exceeds "
427 "required transfer speed (%d Hz)\n",
428 orion_spi->min_speed, t->speed_hz);
429 goto msg_rejected;
430 }
431 }
432
433
434 spin_lock_irqsave(&orion_spi->lock, flags);
435 list_add_tail(&m->queue, &orion_spi->msg_queue);
436 queue_work(orion_spi_wq, &orion_spi->work);
437 spin_unlock_irqrestore(&orion_spi->lock, flags);
438
439 return 0;
440msg_rejected:
441 /* Message rejected and not queued */
442 m->status = -EINVAL;
443 if (m->complete)
444 m->complete(m->context);
445 return -EINVAL;
446}
447
448static int __init orion_spi_probe(struct platform_device *pdev) 376static int __init orion_spi_probe(struct platform_device *pdev)
449{ 377{
450 struct spi_master *master; 378 struct spi_master *master;
@@ -474,7 +402,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)
474 master->mode_bits = 0; 402 master->mode_bits = 0;
475 403
476 master->setup = orion_spi_setup; 404 master->setup = orion_spi_setup;
477 master->transfer = orion_spi_transfer; 405 master->transfer_one_message = orion_spi_transfer_one_message;
478 master->num_chipselect = ORION_NUM_CHIPSELECTS; 406 master->num_chipselect = ORION_NUM_CHIPSELECTS;
479 407
480 dev_set_drvdata(&pdev->dev, master); 408 dev_set_drvdata(&pdev->dev, master);
@@ -507,11 +435,6 @@ static int __init orion_spi_probe(struct platform_device *pdev)
507 } 435 }
508 spi->base = ioremap(r->start, SZ_1K); 436 spi->base = ioremap(r->start, SZ_1K);
509 437
510 INIT_WORK(&spi->work, orion_spi_work);
511
512 spin_lock_init(&spi->lock);
513 INIT_LIST_HEAD(&spi->msg_queue);
514
515 if (orion_spi_reset(spi) < 0) 438 if (orion_spi_reset(spi) < 0)
516 goto out_rel_mem; 439 goto out_rel_mem;
517 440
@@ -536,14 +459,12 @@ out:
536static int __exit orion_spi_remove(struct platform_device *pdev) 459static int __exit orion_spi_remove(struct platform_device *pdev)
537{ 460{
538 struct spi_master *master; 461 struct spi_master *master;
539 struct orion_spi *spi;
540 struct resource *r; 462 struct resource *r;
463 struct orion_spi *spi;
541 464
542 master = dev_get_drvdata(&pdev->dev); 465 master = dev_get_drvdata(&pdev->dev);
543 spi = spi_master_get_devdata(master); 466 spi = spi_master_get_devdata(master);
544 467
545 cancel_work_sync(&spi->work);
546
547 clk_disable_unprepare(spi->clk); 468 clk_disable_unprepare(spi->clk);
548 clk_put(spi->clk); 469 clk_put(spi->clk);
549 470
@@ -574,21 +495,13 @@ static struct platform_driver orion_spi_driver = {
574 495
575static int __init orion_spi_init(void) 496static int __init orion_spi_init(void)
576{ 497{
577 orion_spi_wq = create_singlethread_workqueue(
578 orion_spi_driver.driver.name);
579 if (orion_spi_wq == NULL)
580 return -ENOMEM;
581
582 return platform_driver_probe(&orion_spi_driver, orion_spi_probe); 498 return platform_driver_probe(&orion_spi_driver, orion_spi_probe);
583} 499}
584module_init(orion_spi_init); 500module_init(orion_spi_init);
585 501
586static void __exit orion_spi_exit(void) 502static void __exit orion_spi_exit(void)
587{ 503{
588 flush_workqueue(orion_spi_wq);
589 platform_driver_unregister(&orion_spi_driver); 504 platform_driver_unregister(&orion_spi_driver);
590
591 destroy_workqueue(orion_spi_wq);
592} 505}
593module_exit(orion_spi_exit); 506module_exit(orion_spi_exit);
594 507