aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/arm/mach-omap1/mcbsp.c16
-rw-r--r--arch/arm/mach-omap2/mcbsp.c20
-rw-r--r--arch/arm/plat-omap/include/plat/mcbsp.h3
-rw-r--r--arch/arm/plat-omap/mcbsp.c77
4 files changed, 84 insertions, 32 deletions
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index 6bddce104ee9..f9a5cf750b59 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -99,9 +99,11 @@ static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
99 }, 99 },
100}; 100};
101#define OMAP7XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap7xx_mcbsp_pdata) 101#define OMAP7XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap7xx_mcbsp_pdata)
102#define OMAP7XX_MCBSP_REG_NUM (OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
102#else 103#else
103#define omap7xx_mcbsp_pdata NULL 104#define omap7xx_mcbsp_pdata NULL
104#define OMAP7XX_MCBSP_PDATA_SZ 0 105#define OMAP7XX_MCBSP_PDATA_SZ 0
106#define OMAP7XX_MCBSP_REG_NUM 0
105#endif 107#endif
106 108
107#ifdef CONFIG_ARCH_OMAP15XX 109#ifdef CONFIG_ARCH_OMAP15XX
@@ -132,9 +134,11 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
132 }, 134 },
133}; 135};
134#define OMAP15XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap15xx_mcbsp_pdata) 136#define OMAP15XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap15xx_mcbsp_pdata)
137#define OMAP15XX_MCBSP_REG_NUM (OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
135#else 138#else
136#define omap15xx_mcbsp_pdata NULL 139#define omap15xx_mcbsp_pdata NULL
137#define OMAP15XX_MCBSP_PDATA_SZ 0 140#define OMAP15XX_MCBSP_PDATA_SZ 0
141#define OMAP15XX_MCBSP_REG_NUM 0
138#endif 142#endif
139 143
140#ifdef CONFIG_ARCH_OMAP16XX 144#ifdef CONFIG_ARCH_OMAP16XX
@@ -165,19 +169,25 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
165 }, 169 },
166}; 170};
167#define OMAP16XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap16xx_mcbsp_pdata) 171#define OMAP16XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap16xx_mcbsp_pdata)
172#define OMAP16XX_MCBSP_REG_NUM (OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
168#else 173#else
169#define omap16xx_mcbsp_pdata NULL 174#define omap16xx_mcbsp_pdata NULL
170#define OMAP16XX_MCBSP_PDATA_SZ 0 175#define OMAP16XX_MCBSP_PDATA_SZ 0
176#define OMAP16XX_MCBSP_REG_NUM 0
171#endif 177#endif
172 178
173int __init omap1_mcbsp_init(void) 179int __init omap1_mcbsp_init(void)
174{ 180{
175 if (cpu_is_omap7xx()) 181 if (cpu_is_omap7xx()) {
176 omap_mcbsp_count = OMAP7XX_MCBSP_PDATA_SZ; 182 omap_mcbsp_count = OMAP7XX_MCBSP_PDATA_SZ;
177 if (cpu_is_omap15xx()) 183 omap_mcbsp_cache_size = OMAP7XX_MCBSP_REG_NUM * sizeof(u16);
184 } else if (cpu_is_omap15xx()) {
178 omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ; 185 omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ;
179 if (cpu_is_omap16xx()) 186 omap_mcbsp_cache_size = OMAP15XX_MCBSP_REG_NUM * sizeof(u16);
187 } else if (cpu_is_omap16xx()) {
180 omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ; 188 omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ;
189 omap_mcbsp_cache_size = OMAP16XX_MCBSP_REG_NUM * sizeof(u16);
190 }
181 191
182 mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *), 192 mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
183 GFP_KERNEL); 193 GFP_KERNEL);
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 4b6e5157520f..d601f9405d11 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -65,9 +65,11 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
65 }, 65 },
66}; 66};
67#define OMAP2420_MCBSP_PDATA_SZ ARRAY_SIZE(omap2420_mcbsp_pdata) 67#define OMAP2420_MCBSP_PDATA_SZ ARRAY_SIZE(omap2420_mcbsp_pdata)
68#define OMAP2420_MCBSP_REG_NUM (OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
68#else 69#else
69#define omap2420_mcbsp_pdata NULL 70#define omap2420_mcbsp_pdata NULL
70#define OMAP2420_MCBSP_PDATA_SZ 0 71#define OMAP2420_MCBSP_PDATA_SZ 0
72#define OMAP2420_MCBSP_REG_NUM 0
71#endif 73#endif
72 74
73#ifdef CONFIG_ARCH_OMAP2430 75#ifdef CONFIG_ARCH_OMAP2430
@@ -114,9 +116,11 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
114 }, 116 },
115}; 117};
116#define OMAP2430_MCBSP_PDATA_SZ ARRAY_SIZE(omap2430_mcbsp_pdata) 118#define OMAP2430_MCBSP_PDATA_SZ ARRAY_SIZE(omap2430_mcbsp_pdata)
119#define OMAP2430_MCBSP_REG_NUM (OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
117#else 120#else
118#define omap2430_mcbsp_pdata NULL 121#define omap2430_mcbsp_pdata NULL
119#define OMAP2430_MCBSP_PDATA_SZ 0 122#define OMAP2430_MCBSP_PDATA_SZ 0
123#define OMAP2430_MCBSP_REG_NUM 0
120#endif 124#endif
121 125
122#ifdef CONFIG_ARCH_OMAP3 126#ifdef CONFIG_ARCH_OMAP3
@@ -168,9 +172,11 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
168 }, 172 },
169}; 173};
170#define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) 174#define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata)
175#define OMAP34XX_MCBSP_REG_NUM (OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
171#else 176#else
172#define omap34xx_mcbsp_pdata NULL 177#define omap34xx_mcbsp_pdata NULL
173#define OMAP34XX_MCBSP_PDATA_SZ 0 178#define OMAP34XX_MCBSP_PDATA_SZ 0
179#define OMAP34XX_MCBSP_REG_NUM 0
174#endif 180#endif
175 181
176static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = { 182static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = {
@@ -208,17 +214,23 @@ static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = {
208 }, 214 },
209}; 215};
210#define OMAP44XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap44xx_mcbsp_pdata) 216#define OMAP44XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap44xx_mcbsp_pdata)
217#define OMAP44XX_MCBSP_REG_NUM (OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
211 218
212static int __init omap2_mcbsp_init(void) 219static int __init omap2_mcbsp_init(void)
213{ 220{
214 if (cpu_is_omap2420()) 221 if (cpu_is_omap2420()) {
215 omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ; 222 omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
216 if (cpu_is_omap2430()) 223 omap_mcbsp_cache_size = OMAP2420_MCBSP_REG_NUM * sizeof(u16);
224 } else if (cpu_is_omap2430()) {
217 omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ; 225 omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ;
218 if (cpu_is_omap34xx()) 226 omap_mcbsp_cache_size = OMAP2430_MCBSP_REG_NUM * sizeof(u32);
227 } else if (cpu_is_omap34xx()) {
219 omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ; 228 omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
220 if (cpu_is_omap44xx()) 229 omap_mcbsp_cache_size = OMAP34XX_MCBSP_REG_NUM * sizeof(u32);
230 } else if (cpu_is_omap44xx()) {
221 omap_mcbsp_count = OMAP44XX_MCBSP_PDATA_SZ; 231 omap_mcbsp_count = OMAP44XX_MCBSP_PDATA_SZ;
232 omap_mcbsp_cache_size = OMAP44XX_MCBSP_REG_NUM * sizeof(u32);
233 }
222 234
223 mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *), 235 mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
224 GFP_KERNEL); 236 GFP_KERNEL);
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index d93fa44b1c9a..4df957b1d252 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -414,9 +414,10 @@ struct omap_mcbsp {
414 u16 max_tx_thres; 414 u16 max_tx_thres;
415 u16 max_rx_thres; 415 u16 max_rx_thres;
416#endif 416#endif
417 void *reg_cache;
417}; 418};
418extern struct omap_mcbsp **mcbsp_ptr; 419extern struct omap_mcbsp **mcbsp_ptr;
419extern int omap_mcbsp_count; 420extern int omap_mcbsp_count, omap_mcbsp_cache_size;
420 421
421int omap_mcbsp_init(void); 422int omap_mcbsp_init(void);
422void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, 423void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
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