aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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