mirror of https://gitee.com/openkylin/linux.git
[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>
This commit is contained in:
parent
03e00cd350
commit
37521a3181
|
@ -35,6 +35,10 @@
|
||||||
#include "smd_private.h"
|
#include "smd_private.h"
|
||||||
#include "proc_comm.h"
|
#include "proc_comm.h"
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_QSD8X50)
|
||||||
|
#define CONFIG_QDSP6 1
|
||||||
|
#endif
|
||||||
|
|
||||||
void (*msm_hw_reset_hook)(void);
|
void (*msm_hw_reset_hook)(void);
|
||||||
|
|
||||||
#define MODULE_NAME "msm_smd"
|
#define MODULE_NAME "msm_smd"
|
||||||
|
@ -70,6 +74,9 @@ static unsigned last_heap_free = 0xffffffff;
|
||||||
static inline void notify_other_smsm(void)
|
static inline void notify_other_smsm(void)
|
||||||
{
|
{
|
||||||
writel(1, MSM_A2M_INT(5));
|
writel(1, MSM_A2M_INT(5));
|
||||||
|
#ifdef CONFIG_QDSP6
|
||||||
|
writel(1, MSM_A2M_INT(8));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void notify_modem_smd(void)
|
static inline void notify_modem_smd(void)
|
||||||
|
@ -140,7 +147,8 @@ static DEFINE_MUTEX(smd_creation_mutex);
|
||||||
static int smd_initialized;
|
static int smd_initialized;
|
||||||
|
|
||||||
LIST_HEAD(smd_ch_closed_list);
|
LIST_HEAD(smd_ch_closed_list);
|
||||||
LIST_HEAD(smd_ch_list); /* todo: per-target lists */
|
LIST_HEAD(smd_ch_list_modem);
|
||||||
|
LIST_HEAD(smd_ch_list_dsp);
|
||||||
|
|
||||||
static unsigned char smd_ch_allocated[64];
|
static unsigned char smd_ch_allocated[64];
|
||||||
static struct work_struct probe_work;
|
static struct work_struct probe_work;
|
||||||
|
@ -150,6 +158,7 @@ static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type);
|
||||||
static void smd_channel_probe_worker(struct work_struct *work)
|
static void smd_channel_probe_worker(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct smd_alloc_elm *shared;
|
struct smd_alloc_elm *shared;
|
||||||
|
unsigned ctype;
|
||||||
unsigned type;
|
unsigned type;
|
||||||
unsigned n;
|
unsigned n;
|
||||||
|
|
||||||
|
@ -165,12 +174,19 @@ static void smd_channel_probe_worker(struct work_struct *work)
|
||||||
continue;
|
continue;
|
||||||
if (!shared[n].name[0])
|
if (!shared[n].name[0])
|
||||||
continue;
|
continue;
|
||||||
|
ctype = shared[n].ctype;
|
||||||
|
type = ctype & SMD_TYPE_MASK;
|
||||||
|
|
||||||
|
/* DAL channels are stream but neither the modem,
|
||||||
|
* nor the DSP correctly indicate this. Fixup manually.
|
||||||
|
*/
|
||||||
|
if (!memcmp(shared[n].name, "DAL", 3))
|
||||||
|
ctype = (ctype & (~SMD_KIND_MASK)) | SMD_KIND_STREAM;
|
||||||
|
|
||||||
type = shared[n].ctype & SMD_TYPE_MASK;
|
type = shared[n].ctype & SMD_TYPE_MASK;
|
||||||
if ((type == SMD_TYPE_APPS_MODEM) ||
|
if ((type == SMD_TYPE_APPS_MODEM) ||
|
||||||
(type == SMD_TYPE_APPS_DSP))
|
(type == SMD_TYPE_APPS_DSP))
|
||||||
smd_alloc_channel(shared[n].name,
|
smd_alloc_channel(shared[n].name, shared[n].cid, ctype);
|
||||||
shared[n].cid,
|
|
||||||
shared[n].ctype);
|
|
||||||
smd_ch_allocated[n] = 1;
|
smd_ch_allocated[n] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -403,67 +419,59 @@ static void handle_smd_irq(struct list_head *list, void (*notify)(void))
|
||||||
do_smd_probe();
|
do_smd_probe();
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t smd_irq_handler(int irq, void *data)
|
static irqreturn_t smd_modem_irq_handler(int irq, void *data)
|
||||||
{
|
{
|
||||||
handle_smd_irq(&smd_ch_list, notify_modem_smd);
|
handle_smd_irq(&smd_ch_list_modem, notify_modem_smd);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t smd_dsp_irq_handler(int irq, void *data)
|
||||||
|
{
|
||||||
|
handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void smd_fake_irq_handler(unsigned long arg)
|
static void smd_fake_irq_handler(unsigned long arg)
|
||||||
{
|
{
|
||||||
smd_irq_handler(0, NULL);
|
handle_smd_irq(&smd_ch_list_modem, notify_modem_smd);
|
||||||
|
handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DECLARE_TASKLET(smd_fake_irq_tasklet, smd_fake_irq_handler, 0);
|
static DECLARE_TASKLET(smd_fake_irq_tasklet, smd_fake_irq_handler, 0);
|
||||||
|
|
||||||
|
static inline int smd_need_int(struct smd_channel *ch)
|
||||||
|
{
|
||||||
|
if (ch_is_open(ch)) {
|
||||||
|
if (ch->recv->fHEAD || ch->recv->fTAIL || ch->recv->fSTATE)
|
||||||
|
return 1;
|
||||||
|
if (ch->recv->state != ch->last_state)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void smd_sleep_exit(void)
|
void smd_sleep_exit(void)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct smd_channel *ch;
|
struct smd_channel *ch;
|
||||||
unsigned tmp;
|
|
||||||
int need_int = 0;
|
int need_int = 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&smd_lock, flags);
|
spin_lock_irqsave(&smd_lock, flags);
|
||||||
list_for_each_entry(ch, &smd_ch_list, ch_list) {
|
list_for_each_entry(ch, &smd_ch_list_modem, ch_list) {
|
||||||
if (ch_is_open(ch)) {
|
if (smd_need_int(ch)) {
|
||||||
if (ch->recv->fHEAD) {
|
|
||||||
if (msm_smd_debug_mask & MSM_SMD_DEBUG)
|
|
||||||
pr_info("smd_sleep_exit ch %d fHEAD "
|
|
||||||
"%x %x %x\n",
|
|
||||||
ch->n, ch->recv->fHEAD,
|
|
||||||
ch->recv->head, ch->recv->tail);
|
|
||||||
need_int = 1;
|
need_int = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ch->recv->fTAIL) {
|
}
|
||||||
if (msm_smd_debug_mask & MSM_SMD_DEBUG)
|
list_for_each_entry(ch, &smd_ch_list_dsp, ch_list) {
|
||||||
pr_info("smd_sleep_exit ch %d fTAIL "
|
if (smd_need_int(ch)) {
|
||||||
"%x %x %x\n",
|
|
||||||
ch->n, ch->recv->fTAIL,
|
|
||||||
ch->send->head, ch->send->tail);
|
|
||||||
need_int = 1;
|
need_int = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ch->recv->fSTATE) {
|
|
||||||
if (msm_smd_debug_mask & MSM_SMD_DEBUG)
|
|
||||||
pr_info("smd_sleep_exit ch %d fSTATE %x"
|
|
||||||
"\n", ch->n, ch->recv->fSTATE);
|
|
||||||
need_int = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmp = ch->recv->state;
|
|
||||||
if (tmp != ch->last_state) {
|
|
||||||
if (msm_smd_debug_mask & MSM_SMD_DEBUG)
|
|
||||||
pr_info("smd_sleep_exit ch %d "
|
|
||||||
"state %x != %x\n",
|
|
||||||
ch->n, tmp, ch->last_state);
|
|
||||||
need_int = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&smd_lock, flags);
|
spin_unlock_irqrestore(&smd_lock, flags);
|
||||||
do_smd_probe();
|
do_smd_probe();
|
||||||
|
|
||||||
if (need_int) {
|
if (need_int) {
|
||||||
if (msm_smd_debug_mask & MSM_SMD_DEBUG)
|
if (msm_smd_debug_mask & MSM_SMD_DEBUG)
|
||||||
pr_info("smd_sleep_exit need interrupt\n");
|
pr_info("smd_sleep_exit need interrupt\n");
|
||||||
|
@ -737,7 +745,11 @@ int smd_open(const char *name, smd_channel_t **_ch,
|
||||||
*_ch = ch;
|
*_ch = ch;
|
||||||
|
|
||||||
spin_lock_irqsave(&smd_lock, flags);
|
spin_lock_irqsave(&smd_lock, flags);
|
||||||
list_add(&ch->ch_list, &smd_ch_list);
|
|
||||||
|
if ((ch->type & SMD_TYPE_MASK) == SMD_TYPE_APPS_MODEM)
|
||||||
|
list_add(&ch->ch_list, &smd_ch_list_modem);
|
||||||
|
else
|
||||||
|
list_add(&ch->ch_list, &smd_ch_list_dsp);
|
||||||
|
|
||||||
/* If the remote side is CLOSING, we need to get it to
|
/* If the remote side is CLOSING, we need to get it to
|
||||||
* move to OPENING (which we'll do by moving from CLOSED to
|
* move to OPENING (which we'll do by moving from CLOSED to
|
||||||
|
@ -982,7 +994,7 @@ int smd_core_init(void)
|
||||||
|
|
||||||
smd_info.ready = 1;
|
smd_info.ready = 1;
|
||||||
|
|
||||||
r = request_irq(INT_A9_M2A_0, smd_irq_handler,
|
r = request_irq(INT_A9_M2A_0, smd_modem_irq_handler,
|
||||||
IRQF_TRIGGER_RISING, "smd_dev", 0);
|
IRQF_TRIGGER_RISING, "smd_dev", 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -1000,6 +1012,16 @@ int smd_core_init(void)
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
pr_err("smd_core_init: enable_irq_wake failed for A9_M2A_5\n");
|
pr_err("smd_core_init: enable_irq_wake failed for A9_M2A_5\n");
|
||||||
|
|
||||||
|
#if defined(CONFIG_QDSP6)
|
||||||
|
r = request_irq(INT_ADSP_A11, smd_dsp_irq_handler,
|
||||||
|
IRQF_TRIGGER_RISING, "smd_dsp", 0);
|
||||||
|
if (r < 0) {
|
||||||
|
free_irq(INT_A9_M2A_0, 0);
|
||||||
|
free_irq(INT_A9_M2A_5, 0);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* check for any SMD channels that may already exist */
|
/* check for any SMD channels that may already exist */
|
||||||
do_smd_probe();
|
do_smd_probe();
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ static int dump_ch(char *buf, int max, struct smd_channel *ch)
|
||||||
buf, max,
|
buf, max,
|
||||||
"ch%02d:"
|
"ch%02d:"
|
||||||
" %8s(%05d/%05d) %c%c%c%c%c%c%c <->"
|
" %8s(%05d/%05d) %c%c%c%c%c%c%c <->"
|
||||||
" %8s(%05d/%05d) %c%c%c%c%c%c%c\n", ch->n,
|
" %8s(%05d/%05d) %c%c%c%c%c%c%c '%s'\n", ch->n,
|
||||||
chstate(s->state), s->tail, s->head,
|
chstate(s->state), s->tail, s->head,
|
||||||
s->fDSR ? 'D' : 'd',
|
s->fDSR ? 'D' : 'd',
|
||||||
s->fCTS ? 'C' : 'c',
|
s->fCTS ? 'C' : 'c',
|
||||||
|
@ -71,7 +71,8 @@ static int dump_ch(char *buf, int max, struct smd_channel *ch)
|
||||||
r->fRI ? 'I' : 'i',
|
r->fRI ? 'I' : 'i',
|
||||||
r->fHEAD ? 'W' : 'w',
|
r->fHEAD ? 'W' : 'w',
|
||||||
r->fTAIL ? 'R' : 'r',
|
r->fTAIL ? 'R' : 'r',
|
||||||
r->fSTATE ? 'S' : 's'
|
r->fSTATE ? 'S' : 's',
|
||||||
|
ch->name
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +136,9 @@ static int debug_read_ch(char *buf, int max)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&smd_lock, flags);
|
spin_lock_irqsave(&smd_lock, flags);
|
||||||
list_for_each_entry(ch, &smd_ch_list, ch_list)
|
list_for_each_entry(ch, &smd_ch_list_dsp, ch_list)
|
||||||
|
i += dump_ch(buf + i, max - i, ch);
|
||||||
|
list_for_each_entry(ch, &smd_ch_list_modem, ch_list)
|
||||||
i += dump_ch(buf + i, max - i, ch);
|
i += dump_ch(buf + i, max - i, ch);
|
||||||
list_for_each_entry(ch, &smd_ch_closed_list, ch_list)
|
list_for_each_entry(ch, &smd_ch_closed_list, ch_list)
|
||||||
i += dump_ch(buf + i, max - i, ch);
|
i += dump_ch(buf + i, max - i, ch);
|
||||||
|
|
|
@ -324,7 +324,8 @@ struct smd_channel {
|
||||||
#define SMD_KIND_PACKET 0x200
|
#define SMD_KIND_PACKET 0x200
|
||||||
|
|
||||||
extern struct list_head smd_ch_closed_list;
|
extern struct list_head smd_ch_closed_list;
|
||||||
extern struct list_head smd_ch_list;
|
extern struct list_head smd_ch_list_modem;
|
||||||
|
extern struct list_head smd_ch_list_dsp;
|
||||||
|
|
||||||
extern spinlock_t smd_lock;
|
extern spinlock_t smd_lock;
|
||||||
extern spinlock_t smem_lock;
|
extern spinlock_t smem_lock;
|
||||||
|
|
Loading…
Reference in New Issue