aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm/smd.c
diff options
context:
space:
mode:
authorBrian Swetland <swetland@google.com>2009-07-01 21:30:47 -0400
committerDaniel Walker <dwalker@codeaurora.org>2010-05-12 12:15:11 -0400
commit37521a3181123dc4a9584cc4b8572c08ea0a8274 (patch)
tree1e5571657f48baa7e2a8b5763fc33da583be878c /arch/arm/mach-msm/smd.c
parent03e00cd350c6636b5f2a9854609fea93a5c7b677 (diff)
[ARM] msm: smd: add support for DSP SMD channels
- QSD8250 has a DSP that speaks SMD, in addition to the modem - handle a separate list of modem vs dsp channels - install dsp smd irq handler as necessary Signed-off-by: Brian Swetland <swetland@google.com> Signed-off-by: Daniel Walker <dwalker@codeaurora.org>
Diffstat (limited to 'arch/arm/mach-msm/smd.c')
-rw-r--r--arch/arm/mach-msm/smd.c114
1 files changed, 68 insertions, 46 deletions
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 1aaee4d70863..a88a8fc05f86 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -35,6 +35,10 @@
35#include "smd_private.h" 35#include "smd_private.h"
36#include "proc_comm.h" 36#include "proc_comm.h"
37 37
38#if defined(CONFIG_ARCH_QSD8X50)
39#define CONFIG_QDSP6 1
40#endif
41
38void (*msm_hw_reset_hook)(void); 42void (*msm_hw_reset_hook)(void);
39 43
40#define MODULE_NAME "msm_smd" 44#define MODULE_NAME "msm_smd"
@@ -70,6 +74,9 @@ static unsigned last_heap_free = 0xffffffff;
70static inline void notify_other_smsm(void) 74static inline void notify_other_smsm(void)
71{ 75{
72 writel(1, MSM_A2M_INT(5)); 76 writel(1, MSM_A2M_INT(5));
77#ifdef CONFIG_QDSP6
78 writel(1, MSM_A2M_INT(8));
79#endif
73} 80}
74 81
75static inline void notify_modem_smd(void) 82static inline void notify_modem_smd(void)
@@ -140,7 +147,8 @@ static DEFINE_MUTEX(smd_creation_mutex);
140static int smd_initialized; 147static int smd_initialized;
141 148
142LIST_HEAD(smd_ch_closed_list); 149LIST_HEAD(smd_ch_closed_list);
143LIST_HEAD(smd_ch_list); /* todo: per-target lists */ 150LIST_HEAD(smd_ch_list_modem);
151LIST_HEAD(smd_ch_list_dsp);
144 152
145static unsigned char smd_ch_allocated[64]; 153static unsigned char smd_ch_allocated[64];
146static struct work_struct probe_work; 154static struct work_struct probe_work;
@@ -150,6 +158,7 @@ static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type);
150static void smd_channel_probe_worker(struct work_struct *work) 158static void smd_channel_probe_worker(struct work_struct *work)
151{ 159{
152 struct smd_alloc_elm *shared; 160 struct smd_alloc_elm *shared;
161 unsigned ctype;
153 unsigned type; 162 unsigned type;
154 unsigned n; 163 unsigned n;
155 164
@@ -165,12 +174,19 @@ static void smd_channel_probe_worker(struct work_struct *work)
165 continue; 174 continue;
166 if (!shared[n].name[0]) 175 if (!shared[n].name[0])
167 continue; 176 continue;
177 ctype = shared[n].ctype;
178 type = ctype & SMD_TYPE_MASK;
179
180 /* DAL channels are stream but neither the modem,
181 * nor the DSP correctly indicate this. Fixup manually.
182 */
183 if (!memcmp(shared[n].name, "DAL", 3))
184 ctype = (ctype & (~SMD_KIND_MASK)) | SMD_KIND_STREAM;
185
168 type = shared[n].ctype & SMD_TYPE_MASK; 186 type = shared[n].ctype & SMD_TYPE_MASK;
169 if ((type == SMD_TYPE_APPS_MODEM) || 187 if ((type == SMD_TYPE_APPS_MODEM) ||
170 (type == SMD_TYPE_APPS_DSP)) 188 (type == SMD_TYPE_APPS_DSP))
171 smd_alloc_channel(shared[n].name, 189 smd_alloc_channel(shared[n].name, shared[n].cid, ctype);
172 shared[n].cid,
173 shared[n].ctype);
174 smd_ch_allocated[n] = 1; 190 smd_ch_allocated[n] = 1;
175 } 191 }
176} 192}
@@ -403,67 +419,59 @@ static void handle_smd_irq(struct list_head *list, void (*notify)(void))
403 do_smd_probe(); 419 do_smd_probe();
404} 420}
405 421
406static irqreturn_t smd_irq_handler(int irq, void *data) 422static irqreturn_t smd_modem_irq_handler(int irq, void *data)
423{
424 handle_smd_irq(&smd_ch_list_modem, notify_modem_smd);
425 return IRQ_HANDLED;
426}
427
428static irqreturn_t smd_dsp_irq_handler(int irq, void *data)
407{ 429{
408 handle_smd_irq(&smd_ch_list, notify_modem_smd); 430 handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
409 return IRQ_HANDLED; 431 return IRQ_HANDLED;
410} 432}
411 433
412static void smd_fake_irq_handler(unsigned long arg) 434static void smd_fake_irq_handler(unsigned long arg)
413{ 435{
414 smd_irq_handler(0, NULL); 436 handle_smd_irq(&smd_ch_list_modem, notify_modem_smd);
437 handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
415} 438}
416 439
417static DECLARE_TASKLET(smd_fake_irq_tasklet, smd_fake_irq_handler, 0); 440static DECLARE_TASKLET(smd_fake_irq_tasklet, smd_fake_irq_handler, 0);
418 441
442static inline int smd_need_int(struct smd_channel *ch)
443{
444 if (ch_is_open(ch)) {
445 if (ch->recv->fHEAD || ch->recv->fTAIL || ch->recv->fSTATE)
446 return 1;
447 if (ch->recv->state != ch->last_state)
448 return 1;
449 }
450 return 0;
451}
452
419void smd_sleep_exit(void) 453void smd_sleep_exit(void)
420{ 454{
421 unsigned long flags; 455 unsigned long flags;
422 struct smd_channel *ch; 456 struct smd_channel *ch;
423 unsigned tmp;
424 int need_int = 0; 457 int need_int = 0;
425 458
426 spin_lock_irqsave(&smd_lock, flags); 459 spin_lock_irqsave(&smd_lock, flags);
427 list_for_each_entry(ch, &smd_ch_list, ch_list) { 460 list_for_each_entry(ch, &smd_ch_list_modem, ch_list) {
428 if (ch_is_open(ch)) { 461 if (smd_need_int(ch)) {
429 if (ch->recv->fHEAD) { 462 need_int = 1;
430 if (msm_smd_debug_mask & MSM_SMD_DEBUG) 463 break;
431 pr_info("smd_sleep_exit ch %d fHEAD " 464 }
432 "%x %x %x\n", 465 }
433 ch->n, ch->recv->fHEAD, 466 list_for_each_entry(ch, &smd_ch_list_dsp, ch_list) {
434 ch->recv->head, ch->recv->tail); 467 if (smd_need_int(ch)) {
435 need_int = 1; 468 need_int = 1;
436 break; 469 break;
437 }
438 if (ch->recv->fTAIL) {
439 if (msm_smd_debug_mask & MSM_SMD_DEBUG)
440 pr_info("smd_sleep_exit ch %d fTAIL "
441 "%x %x %x\n",
442 ch->n, ch->recv->fTAIL,
443 ch->send->head, ch->send->tail);
444 need_int = 1;
445 break;
446 }
447 if (ch->recv->fSTATE) {
448 if (msm_smd_debug_mask & MSM_SMD_DEBUG)
449 pr_info("smd_sleep_exit ch %d fSTATE %x"
450 "\n", ch->n, ch->recv->fSTATE);
451 need_int = 1;
452 break;
453 }
454 tmp = ch->recv->state;
455 if (tmp != ch->last_state) {
456 if (msm_smd_debug_mask & MSM_SMD_DEBUG)
457 pr_info("smd_sleep_exit ch %d "
458 "state %x != %x\n",
459 ch->n, tmp, ch->last_state);
460 need_int = 1;
461 break;
462 }
463 } 470 }
464 } 471 }
465 spin_unlock_irqrestore(&smd_lock, flags); 472 spin_unlock_irqrestore(&smd_lock, flags);
466 do_smd_probe(); 473 do_smd_probe();
474
467 if (need_int) { 475 if (need_int) {
468 if (msm_smd_debug_mask & MSM_SMD_DEBUG) 476 if (msm_smd_debug_mask & MSM_SMD_DEBUG)
469 pr_info("smd_sleep_exit need interrupt\n"); 477 pr_info("smd_sleep_exit need interrupt\n");
@@ -737,7 +745,11 @@ int smd_open(const char *name, smd_channel_t **_ch,
737 *_ch = ch; 745 *_ch = ch;
738 746
739 spin_lock_irqsave(&smd_lock, flags); 747 spin_lock_irqsave(&smd_lock, flags);
740 list_add(&ch->ch_list, &smd_ch_list); 748
749 if ((ch->type & SMD_TYPE_MASK) == SMD_TYPE_APPS_MODEM)
750 list_add(&ch->ch_list, &smd_ch_list_modem);
751 else
752 list_add(&ch->ch_list, &smd_ch_list_dsp);
741 753
742 /* If the remote side is CLOSING, we need to get it to 754 /* If the remote side is CLOSING, we need to get it to
743 * move to OPENING (which we'll do by moving from CLOSED to 755 * move to OPENING (which we'll do by moving from CLOSED to
@@ -982,7 +994,7 @@ int smd_core_init(void)
982 994
983 smd_info.ready = 1; 995 smd_info.ready = 1;
984 996
985 r = request_irq(INT_A9_M2A_0, smd_irq_handler, 997 r = request_irq(INT_A9_M2A_0, smd_modem_irq_handler,
986 IRQF_TRIGGER_RISING, "smd_dev", 0); 998 IRQF_TRIGGER_RISING, "smd_dev", 0);
987 if (r < 0) 999 if (r < 0)
988 return r; 1000 return r;
@@ -1000,6 +1012,16 @@ int smd_core_init(void)
1000 if (r < 0) 1012 if (r < 0)
1001 pr_err("smd_core_init: enable_irq_wake failed for A9_M2A_5\n"); 1013 pr_err("smd_core_init: enable_irq_wake failed for A9_M2A_5\n");
1002 1014
1015#if defined(CONFIG_QDSP6)
1016 r = request_irq(INT_ADSP_A11, smd_dsp_irq_handler,
1017 IRQF_TRIGGER_RISING, "smd_dsp", 0);
1018 if (r < 0) {
1019 free_irq(INT_A9_M2A_0, 0);
1020 free_irq(INT_A9_M2A_5, 0);
1021 return r;
1022 }
1023#endif
1024
1003 /* check for any SMD channels that may already exist */ 1025 /* check for any SMD channels that may already exist */
1004 do_smd_probe(); 1026 do_smd_probe();
1005 1027