aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/mcbsp.c
diff options
context:
space:
mode:
authorJanusz Krzysztofik <jkrzyszt@tis.icnet.pl>2010-02-15 13:03:33 -0500
committerTony Lindgren <tony@atomide.com>2010-02-15 13:03:33 -0500
commitc8c99699bd25d8b238ba75d2530d1be90e3c39ea (patch)
tree50d4b5fa730c3f1a77c96ebb4abd7593c0fcb7e0 /arch/arm/plat-omap/mcbsp.c
parent8ea3200f1de1c3d8f3c884a704107fb1e7449547 (diff)
omap: McBSP: Introduce caching in register write operations
Determine cache size required per McBSP port at init time, based on processor type running on. Allocate space for storing cached copies of McBSP register values at port request. Modify omap_msbcp_write() function to update the cache with every register write operation. Modify omap_mcbsp_read() to support reading from cache or hardware. Update MCBSP_READ() macro for modified omap_mcbsp_read() function API. Introduce a new macro that reads from the cache. Tested on OMAP1510 based Amstrad Delta using linux-omap for-next, commit fb7380d70e041e4b3892f6b19dff7efb609d15a4 (2.6.33-rc3+ dated 2010-01-11). Compile-tested with: omap_perseus2_730_defconfig, omap_generic_1610_defconfig, omap_generic_2420_defconfig, omap_2430sdp_defconfig, omap_3430sdp_defconfig, omap_4430sdp_defconfig with CONFIG_OMAP_MCBSP=y selected. Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Acked-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Acked-by: Jarkko Nikula <jhnikula@gmail.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/plat-omap/mcbsp.c')
-rw-r--r--arch/arm/plat-omap/mcbsp.c77
1 files changed, 53 insertions, 24 deletions
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index f8245f25825b..61e440a0f7cd 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -28,28 +28,42 @@
28#include <plat/mcbsp.h> 28#include <plat/mcbsp.h>
29 29
30struct omap_mcbsp **mcbsp_ptr; 30struct omap_mcbsp **mcbsp_ptr;
31int omap_mcbsp_count; 31int omap_mcbsp_count, omap_mcbsp_cache_size;
32 32
33void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) 33void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
34{ 34{
35 if (cpu_class_is_omap1() || cpu_is_omap2420()) 35 if (cpu_class_is_omap1()) {
36 ((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)] = (u16)val;
36 __raw_writew((u16)val, mcbsp->io_base + reg); 37 __raw_writew((u16)val, mcbsp->io_base + reg);
37 else 38 } else if (cpu_is_omap2420()) {
39 ((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)] = (u16)val;
40 __raw_writew((u16)val, mcbsp->io_base + reg);
41 } else {
42 ((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)] = val;
38 __raw_writel(val, mcbsp->io_base + reg); 43 __raw_writel(val, mcbsp->io_base + reg);
44 }
39} 45}
40 46
41int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg) 47int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
42{ 48{
43 if (cpu_class_is_omap1() || cpu_is_omap2420()) 49 if (cpu_class_is_omap1()) {
44 return __raw_readw(mcbsp->io_base + reg); 50 return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
45 else 51 ((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)];
46 return __raw_readl(mcbsp->io_base + reg); 52 } else if (cpu_is_omap2420()) {
53 return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
54 ((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)];
55 } else {
56 return !from_cache ? __raw_readl(mcbsp->io_base + reg) :
57 ((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)];
58 }
47} 59}
48 60
49#define MCBSP_READ(mcbsp, reg) \ 61#define MCBSP_READ(mcbsp, reg) \
50 omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg) 62 omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0)
51#define MCBSP_WRITE(mcbsp, reg, val) \ 63#define MCBSP_WRITE(mcbsp, reg, val) \
52 omap_mcbsp_write(mcbsp, OMAP_MCBSP_REG_##reg, val) 64 omap_mcbsp_write(mcbsp, OMAP_MCBSP_REG_##reg, val)
65#define MCBSP_READ_CACHE(mcbsp, reg) \
66 omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1)
53 67
54#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count) 68#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count)
55#define id_to_mcbsp_ptr(id) mcbsp_ptr[id]; 69#define id_to_mcbsp_ptr(id) mcbsp_ptr[id];
@@ -383,6 +397,7 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type);
383int omap_mcbsp_request(unsigned int id) 397int omap_mcbsp_request(unsigned int id)
384{ 398{
385 struct omap_mcbsp *mcbsp; 399 struct omap_mcbsp *mcbsp;
400 void *reg_cache;
386 int err; 401 int err;
387 402
388 if (!omap_mcbsp_check_valid_id(id)) { 403 if (!omap_mcbsp_check_valid_id(id)) {
@@ -391,15 +406,21 @@ int omap_mcbsp_request(unsigned int id)
391 } 406 }
392 mcbsp = id_to_mcbsp_ptr(id); 407 mcbsp = id_to_mcbsp_ptr(id);
393 408
409 reg_cache = kzalloc(omap_mcbsp_cache_size, GFP_KERNEL);
410 if (!reg_cache) {
411 return -ENOMEM;
412 }
413
394 spin_lock(&mcbsp->lock); 414 spin_lock(&mcbsp->lock);
395 if (!mcbsp->free) { 415 if (!mcbsp->free) {
396 dev_err(mcbsp->dev, "McBSP%d is currently in use\n", 416 dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
397 mcbsp->id); 417 mcbsp->id);
398 spin_unlock(&mcbsp->lock); 418 err = -EBUSY;
399 return -EBUSY; 419 goto err_kfree;
400 } 420 }
401 421
402 mcbsp->free = 0; 422 mcbsp->free = 0;
423 mcbsp->reg_cache = reg_cache;
403 spin_unlock(&mcbsp->lock); 424 spin_unlock(&mcbsp->lock);
404 425
405 if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) 426 if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
@@ -427,7 +448,7 @@ int omap_mcbsp_request(unsigned int id)
427 dev_err(mcbsp->dev, "Unable to request TX IRQ %d " 448 dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
428 "for McBSP%d\n", mcbsp->tx_irq, 449 "for McBSP%d\n", mcbsp->tx_irq,
429 mcbsp->id); 450 mcbsp->id);
430 goto error; 451 goto err_clk_disable;
431 } 452 }
432 453
433 init_completion(&mcbsp->rx_irq_completion); 454 init_completion(&mcbsp->rx_irq_completion);
@@ -437,16 +458,16 @@ int omap_mcbsp_request(unsigned int id)
437 dev_err(mcbsp->dev, "Unable to request RX IRQ %d " 458 dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
438 "for McBSP%d\n", mcbsp->rx_irq, 459 "for McBSP%d\n", mcbsp->rx_irq,
439 mcbsp->id); 460 mcbsp->id);
440 goto tx_irq; 461 goto err_free_irq;
441 } 462 }
442 } 463 }
443 464
444 return 0; 465 return 0;
445tx_irq: 466err_free_irq:
446 free_irq(mcbsp->tx_irq, (void *)mcbsp); 467 free_irq(mcbsp->tx_irq, (void *)mcbsp);
447error: 468err_clk_disable:
448 if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) 469 if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
449 mcbsp->pdata->ops->free(id); 470 mcbsp->pdata->ops->free(id);
450 471
451 /* Do procedure specific to omap34xx arch, if applicable */ 472 /* Do procedure specific to omap34xx arch, if applicable */
452 omap34xx_mcbsp_free(mcbsp); 473 omap34xx_mcbsp_free(mcbsp);
@@ -454,7 +475,12 @@ error:
454 clk_disable(mcbsp->fclk); 475 clk_disable(mcbsp->fclk);
455 clk_disable(mcbsp->iclk); 476 clk_disable(mcbsp->iclk);
456 477
478 spin_lock(&mcbsp->lock);
457 mcbsp->free = 1; 479 mcbsp->free = 1;
480 mcbsp->reg_cache = NULL;
481err_kfree:
482 spin_unlock(&mcbsp->lock);
483 kfree(reg_cache);
458 484
459 return err; 485 return err;
460} 486}
@@ -463,6 +489,7 @@ EXPORT_SYMBOL(omap_mcbsp_request);
463void omap_mcbsp_free(unsigned int id) 489void omap_mcbsp_free(unsigned int id)
464{ 490{
465 struct omap_mcbsp *mcbsp; 491 struct omap_mcbsp *mcbsp;
492 void *reg_cache;
466 493
467 if (!omap_mcbsp_check_valid_id(id)) { 494 if (!omap_mcbsp_check_valid_id(id)) {
468 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); 495 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
@@ -485,16 +512,18 @@ void omap_mcbsp_free(unsigned int id)
485 free_irq(mcbsp->tx_irq, (void *)mcbsp); 512 free_irq(mcbsp->tx_irq, (void *)mcbsp);
486 } 513 }
487 514
488 spin_lock(&mcbsp->lock); 515 reg_cache = mcbsp->reg_cache;
489 if (mcbsp->free) {
490 dev_err(mcbsp->dev, "McBSP%d was not reserved\n",
491 mcbsp->id);
492 spin_unlock(&mcbsp->lock);
493 return;
494 }
495 516
496 mcbsp->free = 1; 517 spin_lock(&mcbsp->lock);
518 if (mcbsp->free)
519 dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id);
520 else
521 mcbsp->free = 1;
522 mcbsp->reg_cache = NULL;
497 spin_unlock(&mcbsp->lock); 523 spin_unlock(&mcbsp->lock);
524
525 if (reg_cache)
526 kfree(reg_cache);
498} 527}
499EXPORT_SYMBOL(omap_mcbsp_free); 528EXPORT_SYMBOL(omap_mcbsp_free);
500 529