msm: smd: add support for RPM based edges
RPM SMD edges only support word size accesses, so modify internal SMD
structures to reflect that constraint. Also abstract away the differences
to preserve common code so that SMD edge processing code works on all edges.
Change-Id: Ica3e751ea660965ff777d40084ca2b66dcc7302a
Signed-off-by: Jeffrey Hugo <jhugo@codeaurora.org>
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 3ef61f4..f14f1ea 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -87,7 +87,7 @@
ifdef CONFIG_DEBUG_FS
obj-$(CONFIG_MSM_IPC_LOGGING) += ipc_logging_debug.o
endif
-obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o
+obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o smd_private.o
obj-y += socinfo.o
ifndef CONFIG_ARCH_MSM9615
ifndef CONFIG_ARCH_APQ8064
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 839f932..19b3ea6 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -138,6 +138,7 @@
static irqreturn_t smsm_dsps_irq_handler(int irq, void *data);
static irqreturn_t smd_wcnss_irq_handler(int irq, void *data);
static irqreturn_t smsm_wcnss_irq_handler(int irq, void *data);
+static irqreturn_t smd_rpm_irq_handler(int irq, void *data);
static irqreturn_t smsm_irq_handler(int irq, void *data);
static struct interrupt_config private_intr_config[NUM_SMD_SUBSYSTEMS] = {
@@ -157,6 +158,10 @@
.smd.irq_handler = smd_wcnss_irq_handler,
.smsm.irq_handler = smsm_wcnss_irq_handler,
},
+ [SMD_RPM] = {
+ .smd.irq_handler = smd_rpm_irq_handler,
+ .smsm.irq_handler = NULL, /* does not support smsm */
+ },
};
struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
@@ -430,6 +435,18 @@
}
}
+static inline void notify_rpm_smd(void)
+{
+ static const struct interrupt_config_item *intr
+ = &private_intr_config[SMD_RPM].smd;
+
+ if (intr->out_base) {
+ ++interrupt_stats[SMD_RPM].smd_out_config_count;
+ smd_write_intr(intr->out_bit_pos,
+ intr->out_base + intr->out_offset);
+ }
+}
+
static inline void notify_modem_smsm(void)
{
static const struct interrupt_config_item *intr
@@ -608,9 +625,14 @@
struct smd_half_channel ch1;
};
+struct smd_shared_v2_word_access {
+ struct smd_half_channel_word_access ch0;
+ struct smd_half_channel_word_access ch1;
+};
+
struct smd_channel {
- volatile struct smd_half_channel *send;
- volatile struct smd_half_channel *recv;
+ volatile void *send; /* some variant of smd_half_channel */
+ volatile void *recv; /* some variant of smd_half_channel */
unsigned char *send_data;
unsigned char *recv_data;
unsigned fifo_size;
@@ -641,6 +663,12 @@
int pending_pkt_sz;
char is_pkt_ch;
+
+ /*
+ * private internal functions to access *send and *recv.
+ * never to be exported outside of smd
+ */
+ struct smd_half_channel_access *half_ch;
};
struct edge_to_pid {
@@ -668,6 +696,10 @@
[SMD_QDSP_Q6FW] = {SMD_Q6, SMD_MODEM_Q6_FW},
[SMD_DSPS_Q6FW] = {SMD_DSPS, SMD_MODEM_Q6_FW},
[SMD_WCNSS_Q6FW] = {SMD_WCNSS, SMD_MODEM_Q6_FW},
+ [SMD_APPS_RPM] = {SMD_APPS, SMD_RPM},
+ [SMD_MODEM_RPM] = {SMD_MODEM, SMD_RPM},
+ [SMD_QDSP_RPM] = {SMD_Q6, SMD_RPM},
+ [SMD_WCNSS_RPM] = {SMD_WCNSS, SMD_RPM},
};
struct restart_notifier_block {
@@ -686,6 +718,7 @@
static LIST_HEAD(smd_ch_list_dsp);
static LIST_HEAD(smd_ch_list_dsps);
static LIST_HEAD(smd_ch_list_wcnss);
+static LIST_HEAD(smd_ch_list_rpm);
static unsigned char smd_ch_allocated[64];
static struct work_struct probe_work;
@@ -721,8 +754,8 @@
/* channel should be allocated only if APPS
processor is involved */
type = SMD_CHANNEL_TYPE(shared[n].type);
- if ((type != SMD_APPS_MODEM) && (type != SMD_APPS_QDSP) &&
- (type != SMD_APPS_DSPS) && (type != SMD_APPS_WCNSS))
+ if (type >= ARRAY_SIZE(edge_to_pids) ||
+ edge_to_pids[type].local_pid != SMD_APPS)
continue;
if (!shared[n].ref_count)
continue;
@@ -941,14 +974,15 @@
/* how many bytes are available for reading */
static int smd_stream_read_avail(struct smd_channel *ch)
{
- return (ch->recv->head - ch->recv->tail) & ch->fifo_mask;
+ return (ch->half_ch->get_head(ch->recv) -
+ ch->half_ch->get_tail(ch->recv)) & ch->fifo_mask;
}
/* how many bytes we are free to write */
static int smd_stream_write_avail(struct smd_channel *ch)
{
- return ch->fifo_mask -
- ((ch->send->head - ch->send->tail) & ch->fifo_mask);
+ return ch->fifo_mask - ((ch->half_ch->get_head(ch->send) -
+ ch->half_ch->get_tail(ch->send)) & ch->fifo_mask);
}
static int smd_packet_read_avail(struct smd_channel *ch)
@@ -971,16 +1005,16 @@
static int ch_is_open(struct smd_channel *ch)
{
- return (ch->recv->state == SMD_SS_OPENED ||
- ch->recv->state == SMD_SS_FLUSHING)
- && (ch->send->state == SMD_SS_OPENED);
+ return (ch->half_ch->get_state(ch->recv) == SMD_SS_OPENED ||
+ ch->half_ch->get_state(ch->recv) == SMD_SS_FLUSHING)
+ && (ch->half_ch->get_state(ch->send) == SMD_SS_OPENED);
}
/* provide a pointer and length to readable data in the fifo */
static unsigned ch_read_buffer(struct smd_channel *ch, void **ptr)
{
- unsigned head = ch->recv->head;
- unsigned tail = ch->recv->tail;
+ unsigned head = ch->half_ch->get_head(ch->recv);
+ unsigned tail = ch->half_ch->get_tail(ch->recv);
*ptr = (void *) (ch->recv_data + tail);
if (tail <= head)
@@ -991,16 +1025,17 @@
static int read_intr_blocked(struct smd_channel *ch)
{
- return ch->recv->fBLOCKREADINTR;
+ return ch->half_ch->get_fBLOCKREADINTR(ch->recv);
}
/* advance the fifo read pointer after data from ch_read_buffer is consumed */
static void ch_read_done(struct smd_channel *ch, unsigned count)
{
BUG_ON(count > smd_stream_read_avail(ch));
- ch->recv->tail = (ch->recv->tail + count) & ch->fifo_mask;
+ ch->half_ch->set_tail(ch->recv,
+ (ch->half_ch->get_tail(ch->recv) + count) & ch->fifo_mask);
wmb();
- ch->send->fTAIL = 1;
+ ch->half_ch->set_fTAIL(ch->send, 1);
}
/* basic read interface to ch_read_{buffer,done} used
@@ -1072,8 +1107,8 @@
/* provide a pointer and length to next free space in the fifo */
static unsigned ch_write_buffer(struct smd_channel *ch, void **ptr)
{
- unsigned head = ch->send->head;
- unsigned tail = ch->send->tail;
+ unsigned head = ch->half_ch->get_head(ch->send);
+ unsigned tail = ch->half_ch->get_tail(ch->send);
*ptr = (void *) (ch->send_data + head);
if (head < tail) {
@@ -1092,24 +1127,25 @@
static void ch_write_done(struct smd_channel *ch, unsigned count)
{
BUG_ON(count > smd_stream_write_avail(ch));
- ch->send->head = (ch->send->head + count) & ch->fifo_mask;
+ ch->half_ch->set_head(ch->send,
+ (ch->half_ch->get_head(ch->send) + count) & ch->fifo_mask);
wmb();
- ch->send->fHEAD = 1;
+ ch->half_ch->set_fHEAD(ch->send, 1);
}
static void ch_set_state(struct smd_channel *ch, unsigned n)
{
if (n == SMD_SS_OPENED) {
- ch->send->fDSR = 1;
- ch->send->fCTS = 1;
- ch->send->fCD = 1;
+ ch->half_ch->set_fDSR(ch->send, 1);
+ ch->half_ch->set_fCTS(ch->send, 1);
+ ch->half_ch->set_fCD(ch->send, 1);
} else {
- ch->send->fDSR = 0;
- ch->send->fCTS = 0;
- ch->send->fCD = 0;
+ ch->half_ch->set_fDSR(ch->send, 0);
+ ch->half_ch->set_fCTS(ch->send, 0);
+ ch->half_ch->set_fCD(ch->send, 0);
}
- ch->send->state = n;
- ch->send->fSTATE = 1;
+ ch->half_ch->set_state(ch->send, n);
+ ch->half_ch->set_fSTATE(ch->send, 1);
ch->notify_other_cpu();
}
@@ -1131,16 +1167,16 @@
switch (next) {
case SMD_SS_OPENING:
- if (ch->send->state == SMD_SS_CLOSING ||
- ch->send->state == SMD_SS_CLOSED) {
- ch->recv->tail = 0;
- ch->send->head = 0;
- ch->send->fBLOCKREADINTR = 0;
+ if (ch->half_ch->get_state(ch->send) == SMD_SS_CLOSING ||
+ ch->half_ch->get_state(ch->send) == SMD_SS_CLOSED) {
+ ch->half_ch->set_tail(ch->recv, 0);
+ ch->half_ch->set_head(ch->send, 0);
+ ch->half_ch->set_fBLOCKREADINTR(ch->send, 0);
ch_set_state(ch, SMD_SS_OPENING);
}
break;
case SMD_SS_OPENED:
- if (ch->send->state == SMD_SS_OPENING) {
+ if (ch->half_ch->get_state(ch->send) == SMD_SS_OPENING) {
ch_set_state(ch, SMD_SS_OPENED);
ch->notify(ch->priv, SMD_EVENT_OPEN);
}
@@ -1150,7 +1186,7 @@
/* we should force them to close? */
break;
case SMD_SS_CLOSED:
- if (ch->send->state == SMD_SS_OPENED) {
+ if (ch->half_ch->get_state(ch->send) == SMD_SS_OPENED) {
ch_set_state(ch, SMD_SS_CLOSING);
ch->current_packet = 0;
ch->pending_pkt_sz = 0;
@@ -1158,7 +1194,7 @@
}
break;
case SMD_SS_CLOSING:
- if (ch->send->state == SMD_SS_CLOSED) {
+ if (ch->half_ch->get_state(ch->send) == SMD_SS_CLOSED) {
list_move(&ch->ch_list,
&smd_ch_to_close_list);
queue_work(channel_close_wq,
@@ -1177,9 +1213,9 @@
spin_lock_irqsave(&smd_lock, flags);
list_for_each_entry_safe(ch, index, &smd_ch_closing_list, ch_list) {
- if (ch->recv->fSTATE)
- ch->recv->fSTATE = 0;
- tmp = ch->recv->state;
+ if (ch->half_ch->get_fSTATE(ch->recv))
+ ch->half_ch->set_fSTATE(ch->recv, 0);
+ tmp = ch->half_ch->get_state(ch->recv);
if (tmp != ch->last_state)
smd_state_change(ch, ch->last_state, tmp);
}
@@ -1199,20 +1235,20 @@
state_change = 0;
ch_flags = 0;
if (ch_is_open(ch)) {
- if (ch->recv->fHEAD) {
- ch->recv->fHEAD = 0;
+ if (ch->half_ch->get_fHEAD(ch->recv)) {
+ ch->half_ch->set_fHEAD(ch->recv, 0);
ch_flags |= 1;
}
- if (ch->recv->fTAIL) {
- ch->recv->fTAIL = 0;
+ if (ch->half_ch->get_fTAIL(ch->recv)) {
+ ch->half_ch->set_fTAIL(ch->recv, 0);
ch_flags |= 2;
}
- if (ch->recv->fSTATE) {
- ch->recv->fSTATE = 0;
+ if (ch->half_ch->get_fSTATE(ch->recv)) {
+ ch->half_ch->set_fSTATE(ch->recv, 0);
ch_flags |= 4;
}
}
- tmp = ch->recv->state;
+ tmp = ch->half_ch->get_state(ch->recv);
if (tmp != ch->last_state) {
SMx_POWER_INFO("SMD ch%d '%s' State change %d->%d\n",
ch->n, ch->name, ch->last_state, tmp);
@@ -1273,12 +1309,22 @@
return IRQ_HANDLED;
}
+static irqreturn_t smd_rpm_irq_handler(int irq, void *data)
+{
+ SMx_POWER_INFO("SMD Int RPM->Apps\n");
+ ++interrupt_stats[SMD_RPM].smd_in_count;
+ handle_smd_irq(&smd_ch_list_rpm, notify_rpm_smd);
+ handle_smd_irq_closing_list();
+ return IRQ_HANDLED;
+}
+
static void smd_fake_irq_handler(unsigned long arg)
{
handle_smd_irq(&smd_ch_list_modem, notify_modem_smd);
handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
handle_smd_irq(&smd_ch_list_dsps, notify_dsps_smd);
handle_smd_irq(&smd_ch_list_wcnss, notify_wcnss_smd);
+ handle_smd_irq(&smd_ch_list_rpm, notify_rpm_smd);
handle_smd_irq_closing_list();
}
@@ -1287,9 +1333,11 @@
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)
+ if (ch->half_ch->get_fHEAD(ch->recv) ||
+ ch->half_ch->get_fTAIL(ch->recv) ||
+ ch->half_ch->get_fSTATE(ch->recv))
return 1;
- if (ch->recv->state != ch->last_state)
+ if (ch->half_ch->get_state(ch->recv) != ch->last_state)
return 1;
}
return 0;
@@ -1504,15 +1552,32 @@
#if (defined(CONFIG_MSM_SMD_PKG4) || defined(CONFIG_MSM_SMD_PKG3))
static int smd_alloc_v2(struct smd_channel *ch)
{
- struct smd_shared_v2 *shared2;
void *buffer;
unsigned buffer_sz;
- shared2 = smem_alloc(SMEM_SMD_BASE_ID + ch->n, sizeof(*shared2));
- if (!shared2) {
- SMD_INFO("smem_alloc failed ch=%d\n", ch->n);
- return -EINVAL;
+ if (is_word_access_ch(ch->type)) {
+ struct smd_shared_v2_word_access *shared2;
+ shared2 = smem_alloc(SMEM_SMD_BASE_ID + ch->n,
+ sizeof(*shared2));
+ if (!shared2) {
+ SMD_INFO("smem_alloc failed ch=%d\n", ch->n);
+ return -EINVAL;
+ }
+ ch->send = &shared2->ch0;
+ ch->recv = &shared2->ch1;
+ } else {
+ struct smd_shared_v2 *shared2;
+ shared2 = smem_alloc(SMEM_SMD_BASE_ID + ch->n,
+ sizeof(*shared2));
+ if (!shared2) {
+ SMD_INFO("smem_alloc failed ch=%d\n", ch->n);
+ return -EINVAL;
+ }
+ ch->send = &shared2->ch0;
+ ch->recv = &shared2->ch1;
}
+ ch->half_ch = get_half_ch_funcs(ch->type);
+
buffer = smem_get_entry(SMEM_SMD_FIFO_BASE_ID + ch->n, &buffer_sz);
if (!buffer) {
SMD_INFO("smem_get_entry failed\n");
@@ -1525,11 +1590,10 @@
return -EINVAL;
}
buffer_sz /= 2;
- ch->send = &shared2->ch0;
- ch->recv = &shared2->ch1;
ch->send_data = buffer;
ch->recv_data = buffer + buffer_sz;
ch->fifo_size = buffer_sz;
+
return 0;
}
@@ -1557,6 +1621,7 @@
ch->send_data = shared1->data0;
ch->recv_data = shared1->data1;
ch->fifo_size = SMD_BUF_SIZE;
+ ch->half_ch = get_half_ch_funcs(ch->type);
return 0;
}
@@ -1572,6 +1637,7 @@
return -1;
}
ch->n = alloc_elm->cid;
+ ch->type = SMD_CHANNEL_TYPE(alloc_elm->type);
if (smd_alloc_v2(ch) && smd_alloc_v1(ch)) {
kfree(ch);
@@ -1579,16 +1645,18 @@
}
ch->fifo_mask = ch->fifo_size - 1;
- ch->type = SMD_CHANNEL_TYPE(alloc_elm->type);
+ /* probe_worker guarentees ch->type will be a valid type */
if (ch->type == SMD_APPS_MODEM)
ch->notify_other_cpu = notify_modem_smd;
else if (ch->type == SMD_APPS_QDSP)
ch->notify_other_cpu = notify_dsp_smd;
else if (ch->type == SMD_APPS_DSPS)
ch->notify_other_cpu = notify_dsps_smd;
- else
+ else if (ch->type == SMD_APPS_WCNSS)
ch->notify_other_cpu = notify_wcnss_smd;
+ else if (ch->type == SMD_APPS_RPM)
+ ch->notify_other_cpu = notify_rpm_smd;
if (smd_is_packet(alloc_elm)) {
ch->read = smd_packet_read;
@@ -1783,10 +1851,10 @@
if (edge == SMD_LOOPBACK_TYPE) {
ch->last_state = SMD_SS_OPENED;
- ch->send->state = SMD_SS_OPENED;
- ch->send->fDSR = 1;
- ch->send->fCTS = 1;
- ch->send->fCD = 1;
+ ch->half_ch->set_state(ch->send, SMD_SS_OPENED);
+ ch->half_ch->set_fDSR(ch->send, 1);
+ ch->half_ch->set_fCTS(ch->send, 1);
+ ch->half_ch->set_fCD(ch->send, 1);
}
*_ch = ch;
@@ -1802,6 +1870,8 @@
list_add(&ch->ch_list, &smd_ch_list_dsps);
else if (SMD_CHANNEL_TYPE(ch->type) == SMD_APPS_WCNSS)
list_add(&ch->ch_list, &smd_ch_list_wcnss);
+ else if (SMD_CHANNEL_TYPE(ch->type) == SMD_APPS_RPM)
+ list_add(&ch->ch_list, &smd_ch_list_rpm);
else
list_add(&ch->ch_list, &smd_ch_list_loopback);
@@ -1837,14 +1907,14 @@
spin_lock_irqsave(&smd_lock, flags);
list_del(&ch->ch_list);
if (ch->n == SMD_LOOPBACK_CID) {
- ch->send->fDSR = 0;
- ch->send->fCTS = 0;
- ch->send->fCD = 0;
- ch->send->state = SMD_SS_CLOSED;
+ ch->half_ch->set_fDSR(ch->send, 0);
+ ch->half_ch->set_fCTS(ch->send, 0);
+ ch->half_ch->set_fCD(ch->send, 0);
+ ch->half_ch->set_state(ch->send, SMD_SS_CLOSED);
} else
ch_set_state(ch, SMD_SS_CLOSED);
- if (ch->recv->state == SMD_SS_OPENED) {
+ if (ch->half_ch->get_state(ch->recv) == SMD_SS_OPENED) {
list_add(&ch->ch_list, &smd_ch_closing_list);
spin_unlock_irqrestore(&smd_lock, flags);
} else {
@@ -2031,14 +2101,14 @@
void smd_enable_read_intr(smd_channel_t *ch)
{
if (ch)
- ch->send->fBLOCKREADINTR = 0;
+ ch->half_ch->set_fBLOCKREADINTR(ch->send, 0);
}
EXPORT_SYMBOL(smd_enable_read_intr);
void smd_disable_read_intr(smd_channel_t *ch)
{
if (ch)
- ch->send->fBLOCKREADINTR = 1;
+ ch->half_ch->set_fBLOCKREADINTR(ch->send, 1);
}
EXPORT_SYMBOL(smd_disable_read_intr);
@@ -2070,12 +2140,12 @@
return -ENODEV;
}
- return (ch->recv->fDSR ? TIOCM_DSR : 0) |
- (ch->recv->fCTS ? TIOCM_CTS : 0) |
- (ch->recv->fCD ? TIOCM_CD : 0) |
- (ch->recv->fRI ? TIOCM_RI : 0) |
- (ch->send->fCTS ? TIOCM_RTS : 0) |
- (ch->send->fDSR ? TIOCM_DTR : 0);
+ return (ch->half_ch->get_fDSR(ch->recv) ? TIOCM_DSR : 0) |
+ (ch->half_ch->get_fCTS(ch->recv) ? TIOCM_CTS : 0) |
+ (ch->half_ch->get_fCD(ch->recv) ? TIOCM_CD : 0) |
+ (ch->half_ch->get_fRI(ch->recv) ? TIOCM_RI : 0) |
+ (ch->half_ch->get_fCTS(ch->send) ? TIOCM_RTS : 0) |
+ (ch->half_ch->get_fDSR(ch->send) ? TIOCM_DTR : 0);
}
EXPORT_SYMBOL(smd_tiocmget);
@@ -2089,18 +2159,18 @@
}
if (set & TIOCM_DTR)
- ch->send->fDSR = 1;
+ ch->half_ch->set_fDSR(ch->send, 1);
if (set & TIOCM_RTS)
- ch->send->fCTS = 1;
+ ch->half_ch->set_fCTS(ch->send, 1);
if (clear & TIOCM_DTR)
- ch->send->fDSR = 0;
+ ch->half_ch->set_fDSR(ch->send, 0);
if (clear & TIOCM_RTS)
- ch->send->fCTS = 0;
+ ch->half_ch->set_fCTS(ch->send, 0);
- ch->send->fSTATE = 1;
+ ch->half_ch->set_fSTATE(ch->send, 1);
barrier();
ch->notify_other_cpu();
@@ -3148,11 +3218,13 @@
break;
}
- ret = intr_init(
- &private_intr_config[cfg->irq_config_id].smsm,
- &cfg->smsm_int,
- pdev
- );
+ /* only init smsm structs if this edge supports smsm */
+ if (cfg->smsm_int.irq_id)
+ ret = intr_init(
+ &private_intr_config[cfg->irq_config_id].smsm,
+ &cfg->smsm_int,
+ pdev
+ );
if (ret < 0) {
err_ret = ret;
@@ -3161,7 +3233,8 @@
break;
}
- strncpy(edge_to_pids[cfg->edge].subsys_name,
+ if (cfg->subsys_name)
+ strlcpy(edge_to_pids[cfg->edge].subsys_name,
cfg->subsys_name, SMD_MAX_CH_NAME_LEN);
}
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
index 764102d..5dce1ac 100644
--- a/arch/arm/mach-msm/smd_debug.c
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -248,8 +248,9 @@
}
static int dump_ch(char *buf, int max, int n,
- struct smd_half_channel *s,
- struct smd_half_channel *r,
+ void *half_ch_s,
+ void *half_ch_r,
+ struct smd_half_channel_access *half_ch_funcs,
unsigned size)
{
return scnprintf(
@@ -257,24 +258,28 @@
"ch%02d:"
" %8s(%04d/%04d) %c%c%c%c%c%c%c%c <->"
" %8s(%04d/%04d) %c%c%c%c%c%c%c%c : %5x\n", n,
- chstate(s->state), s->tail, s->head,
- s->fDSR ? 'D' : 'd',
- s->fCTS ? 'C' : 'c',
- s->fCD ? 'C' : 'c',
- s->fRI ? 'I' : 'i',
- s->fHEAD ? 'W' : 'w',
- s->fTAIL ? 'R' : 'r',
- s->fSTATE ? 'S' : 's',
- s->fBLOCKREADINTR ? 'B' : 'b',
- chstate(r->state), r->tail, r->head,
- r->fDSR ? 'D' : 'd',
- r->fCTS ? 'R' : 'r',
- r->fCD ? 'C' : 'c',
- r->fRI ? 'I' : 'i',
- r->fHEAD ? 'W' : 'w',
- r->fTAIL ? 'R' : 'r',
- r->fSTATE ? 'S' : 's',
- r->fBLOCKREADINTR ? 'B' : 'b',
+ chstate(half_ch_funcs->get_state(half_ch_s)),
+ half_ch_funcs->get_tail(half_ch_s),
+ half_ch_funcs->get_head(half_ch_s),
+ half_ch_funcs->get_fDSR(half_ch_s) ? 'D' : 'd',
+ half_ch_funcs->get_fCTS(half_ch_s) ? 'C' : 'c',
+ half_ch_funcs->get_fCD(half_ch_s) ? 'C' : 'c',
+ half_ch_funcs->get_fRI(half_ch_s) ? 'I' : 'i',
+ half_ch_funcs->get_fHEAD(half_ch_s) ? 'W' : 'w',
+ half_ch_funcs->get_fTAIL(half_ch_s) ? 'R' : 'r',
+ half_ch_funcs->get_fSTATE(half_ch_s) ? 'S' : 's',
+ half_ch_funcs->get_fBLOCKREADINTR(half_ch_s) ? 'B' : 'b',
+ chstate(half_ch_funcs->get_state(half_ch_r)),
+ half_ch_funcs->get_tail(half_ch_r),
+ half_ch_funcs->get_head(half_ch_r),
+ half_ch_funcs->get_fDSR(half_ch_r) ? 'D' : 'd',
+ half_ch_funcs->get_fCTS(half_ch_r) ? 'C' : 'c',
+ half_ch_funcs->get_fCD(half_ch_r) ? 'C' : 'c',
+ half_ch_funcs->get_fRI(half_ch_r) ? 'I' : 'i',
+ half_ch_funcs->get_fHEAD(half_ch_r) ? 'W' : 'w',
+ half_ch_funcs->get_fTAIL(half_ch_r) ? 'R' : 'r',
+ half_ch_funcs->get_fSTATE(half_ch_r) ? 'S' : 's',
+ half_ch_funcs->get_fBLOCKREADINTR(half_ch_r) ? 'B' : 'b',
size
);
}
@@ -542,19 +547,33 @@
{
void *shared;
int n, i = 0;
+ struct smd_alloc_elm *ch_tbl;
+ unsigned ch_type;
+ unsigned shared_size;
+
+ ch_tbl = smem_find(ID_CH_ALLOC_TBL, sizeof(*ch_tbl) * 64);
+ if (!ch_tbl)
+ goto fail;
for (n = 0; n < SMD_CHANNELS; n++) {
+ ch_type = SMD_CHANNEL_TYPE(ch_tbl[n].type);
+ if (is_word_access_ch(ch_type))
+ shared_size =
+ sizeof(struct smd_half_channel_word_access);
+ else
+ shared_size = sizeof(struct smd_half_channel);
shared = smem_find(ID_SMD_CHANNELS + n,
- 2 * (sizeof(struct smd_half_channel) +
- SMD_BUF_SIZE));
+ 2 * shared_size + SMD_BUF_SIZE);
if (shared == 0)
continue;
i += dump_ch(buf + i, max - i, n, shared,
- (shared + sizeof(struct smd_half_channel) +
- SMD_BUF_SIZE), SMD_BUF_SIZE);
+ (shared + shared_size +
+ SMD_BUF_SIZE), get_half_ch_funcs(ch_type),
+ SMD_BUF_SIZE);
}
+fail:
return i;
}
#else
@@ -563,10 +582,23 @@
void *shared, *buffer;
unsigned buffer_sz;
int n, i = 0;
+ struct smd_alloc_elm *ch_tbl;
+ unsigned ch_type;
+ unsigned shared_size;
+
+ ch_tbl = smem_find(ID_CH_ALLOC_TBL, sizeof(*ch_tbl) * 64);
+ if (!ch_tbl)
+ goto fail;
for (n = 0; n < SMD_CHANNELS; n++) {
- shared = smem_find(ID_SMD_CHANNELS + n,
- 2 * sizeof(struct smd_half_channel));
+ ch_type = SMD_CHANNEL_TYPE(ch_tbl[n].type);
+ if (is_word_access_ch(ch_type))
+ shared_size =
+ sizeof(struct smd_half_channel_word_access);
+ else
+ shared_size = sizeof(struct smd_half_channel);
+
+ shared = smem_find(ID_SMD_CHANNELS + n, 2 * shared_size);
if (shared == 0)
continue;
@@ -577,10 +609,12 @@
continue;
i += dump_ch(buf + i, max - i, n, shared,
- (shared + sizeof(struct smd_half_channel)),
+ (shared + shared_size),
+ get_half_ch_funcs(ch_type),
buffer_sz / 2);
}
+fail:
return i;
}
#endif
diff --git a/arch/arm/mach-msm/smd_private.c b/arch/arm/mach-msm/smd_private.c
new file mode 100644
index 0000000..5a78b6f
--- /dev/null
+++ b/arch/arm/mach-msm/smd_private.c
@@ -0,0 +1,303 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "smd_private.h"
+
+void set_state(volatile void *half_channel, unsigned data)
+{
+ ((struct smd_half_channel *)(half_channel))->state = data;
+}
+
+unsigned get_state(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->state;
+}
+
+void set_fDSR(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel *)(half_channel))->fDSR = data;
+}
+
+unsigned get_fDSR(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->fDSR;
+}
+
+void set_fCTS(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel *)(half_channel))->fCTS = data;
+}
+
+unsigned get_fCTS(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->fCTS;
+}
+
+void set_fCD(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel *)(half_channel))->fCD = data;
+}
+
+unsigned get_fCD(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->fCD;
+}
+
+void set_fRI(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel *)(half_channel))->fRI = data;
+}
+
+unsigned get_fRI(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->fRI;
+}
+
+void set_fHEAD(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel *)(half_channel))->fHEAD = data;
+}
+
+unsigned get_fHEAD(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->fHEAD;
+}
+
+void set_fTAIL(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel *)(half_channel))->fTAIL = data;
+}
+
+unsigned get_fTAIL(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->fTAIL;
+}
+
+void set_fSTATE(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel *)(half_channel))->fSTATE = data;
+}
+
+unsigned get_fSTATE(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->fSTATE;
+}
+
+void set_fBLOCKREADINTR(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel *)(half_channel))->fBLOCKREADINTR = data;
+}
+
+unsigned get_fBLOCKREADINTR(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->fBLOCKREADINTR;
+}
+
+void set_tail(volatile void *half_channel, unsigned data)
+{
+ ((struct smd_half_channel *)(half_channel))->tail = data;
+}
+
+unsigned get_tail(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->tail;
+}
+
+void set_head(volatile void *half_channel, unsigned data)
+{
+ ((struct smd_half_channel *)(half_channel))->head = data;
+}
+
+unsigned get_head(volatile void *half_channel)
+{
+ return ((struct smd_half_channel *)(half_channel))->head;
+}
+
+void set_state_word_access(volatile void *half_channel, unsigned data)
+{
+ ((struct smd_half_channel_word_access *)(half_channel))->state = data;
+}
+
+unsigned get_state_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)(half_channel))->state;
+}
+
+void set_fDSR_word_access(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel_word_access *)(half_channel))->fDSR = data;
+}
+
+unsigned get_fDSR_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)(half_channel))->fDSR;
+}
+
+void set_fCTS_word_access(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel_word_access *)(half_channel))->fCTS = data;
+}
+
+unsigned get_fCTS_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)(half_channel))->fCTS;
+}
+
+void set_fCD_word_access(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel_word_access *)(half_channel))->fCD = data;
+}
+
+unsigned get_fCD_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)(half_channel))->fCD;
+}
+
+void set_fRI_word_access(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel_word_access *)(half_channel))->fRI = data;
+}
+
+unsigned get_fRI_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)(half_channel))->fRI;
+}
+
+void set_fHEAD_word_access(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel_word_access *)(half_channel))->fHEAD = data;
+}
+
+unsigned get_fHEAD_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)(half_channel))->fHEAD;
+}
+
+void set_fTAIL_word_access(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel_word_access *)(half_channel))->fTAIL = data;
+}
+
+unsigned get_fTAIL_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)(half_channel))->fTAIL;
+}
+
+void set_fSTATE_word_access(volatile void *half_channel, unsigned char data)
+{
+ ((struct smd_half_channel_word_access *)(half_channel))->fSTATE = data;
+}
+
+unsigned get_fSTATE_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)(half_channel))->fSTATE;
+}
+
+void set_fBLOCKREADINTR_word_access(volatile void *half_channel,
+ unsigned char data)
+{
+ ((struct smd_half_channel_word_access *)
+ (half_channel))->fBLOCKREADINTR = data;
+}
+
+unsigned get_fBLOCKREADINTR_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)
+ (half_channel))->fBLOCKREADINTR;
+}
+
+void set_tail_word_access(volatile void *half_channel, unsigned data)
+{
+ ((struct smd_half_channel_word_access *)(half_channel))->tail = data;
+}
+
+unsigned get_tail_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)(half_channel))->tail;
+}
+
+void set_head_word_access(volatile void *half_channel, unsigned data)
+{
+ ((struct smd_half_channel_word_access *)(half_channel))->head = data;
+}
+
+unsigned get_head_word_access(volatile void *half_channel)
+{
+ return ((struct smd_half_channel_word_access *)(half_channel))->head;
+}
+
+int is_word_access_ch(unsigned ch_type)
+{
+ if (ch_type == SMD_APPS_RPM || ch_type == SMD_MODEM_RPM ||
+ ch_type == SMD_QDSP_RPM || ch_type == SMD_WCNSS_RPM)
+ return 1;
+ else
+ return 0;
+}
+
+struct smd_half_channel_access *get_half_ch_funcs(unsigned ch_type)
+{
+ static struct smd_half_channel_access byte_access = {
+ .set_state = set_state,
+ .get_state = get_state,
+ .set_fDSR = set_fDSR,
+ .get_fDSR = get_fDSR,
+ .set_fCTS = set_fCTS,
+ .get_fCTS = get_fCTS,
+ .set_fCD = set_fCD,
+ .get_fCD = get_fCD,
+ .set_fRI = set_fRI,
+ .get_fRI = get_fRI,
+ .set_fHEAD = set_fHEAD,
+ .get_fHEAD = get_fHEAD,
+ .set_fTAIL = set_fTAIL,
+ .get_fTAIL = get_fTAIL,
+ .set_fSTATE = set_fSTATE,
+ .get_fSTATE = get_fSTATE,
+ .set_fBLOCKREADINTR = set_fBLOCKREADINTR,
+ .get_fBLOCKREADINTR = get_fBLOCKREADINTR,
+ .set_tail = set_tail,
+ .get_tail = get_tail,
+ .set_head = set_head,
+ .get_head = get_head,
+ };
+ static struct smd_half_channel_access word_access = {
+ .set_state = set_state_word_access,
+ .get_state = get_state_word_access,
+ .set_fDSR = set_fDSR_word_access,
+ .get_fDSR = get_fDSR_word_access,
+ .set_fCTS = set_fCTS_word_access,
+ .get_fCTS = get_fCTS_word_access,
+ .set_fCD = set_fCD_word_access,
+ .get_fCD = get_fCD_word_access,
+ .set_fRI = set_fRI_word_access,
+ .get_fRI = get_fRI_word_access,
+ .set_fHEAD = set_fHEAD_word_access,
+ .get_fHEAD = get_fHEAD_word_access,
+ .set_fTAIL = set_fTAIL_word_access,
+ .get_fTAIL = get_fTAIL_word_access,
+ .set_fSTATE = set_fSTATE_word_access,
+ .get_fSTATE = get_fSTATE_word_access,
+ .set_fBLOCKREADINTR = set_fBLOCKREADINTR_word_access,
+ .get_fBLOCKREADINTR = get_fBLOCKREADINTR_word_access,
+ .set_tail = set_tail_word_access,
+ .get_tail = get_tail_word_access,
+ .set_head = set_head_word_access,
+ .get_head = get_head_word_access,
+ };
+
+ if (is_word_access_ch(ch_type))
+ return &word_access;
+ else
+ return &byte_access;
+}
+
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index e39c57b..3464140 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -134,6 +134,50 @@
unsigned head;
};
+struct smd_half_channel_word_access {
+ unsigned state;
+ unsigned fDSR;
+ unsigned fCTS;
+ unsigned fCD;
+ unsigned fRI;
+ unsigned fHEAD;
+ unsigned fTAIL;
+ unsigned fSTATE;
+ unsigned fBLOCKREADINTR;
+ unsigned tail;
+ unsigned head;
+};
+
+struct smd_half_channel_access {
+ void (*set_state)(volatile void *half_channel, unsigned data);
+ unsigned (*get_state)(volatile void *half_channel);
+ void (*set_fDSR)(volatile void *half_channel, unsigned char data);
+ unsigned (*get_fDSR)(volatile void *half_channel);
+ void (*set_fCTS)(volatile void *half_channel, unsigned char data);
+ unsigned (*get_fCTS)(volatile void *half_channel);
+ void (*set_fCD)(volatile void *half_channel, unsigned char data);
+ unsigned (*get_fCD)(volatile void *half_channel);
+ void (*set_fRI)(volatile void *half_channel, unsigned char data);
+ unsigned (*get_fRI)(volatile void *half_channel);
+ void (*set_fHEAD)(volatile void *half_channel, unsigned char data);
+ unsigned (*get_fHEAD)(volatile void *half_channel);
+ void (*set_fTAIL)(volatile void *half_channel, unsigned char data);
+ unsigned (*get_fTAIL)(volatile void *half_channel);
+ void (*set_fSTATE)(volatile void *half_channel, unsigned char data);
+ unsigned (*get_fSTATE)(volatile void *half_channel);
+ void (*set_fBLOCKREADINTR)(volatile void *half_channel,
+ unsigned char data);
+ unsigned (*get_fBLOCKREADINTR)(volatile void *half_channel);
+ void (*set_tail)(volatile void *half_channel, unsigned data);
+ unsigned (*get_tail)(volatile void *half_channel);
+ void (*set_head)(volatile void *half_channel, unsigned data);
+ unsigned (*get_head)(volatile void *half_channel);
+};
+
+int is_word_access_ch(unsigned ch_type);
+
+struct smd_half_channel_access *get_half_ch_funcs(unsigned ch_type);
+
struct smem_ram_ptn {
char name[16];
unsigned start;