Merge "mpm-of: Support multiple mpm pin mapping to same gic interrupt"
This commit is contained in:
commit
480bfd599a
1 changed files with 66 additions and 47 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -69,8 +69,8 @@ struct mpm_irqs {
|
||||||
char domain_name[MAX_DOMAIN_NAME];
|
char domain_name[MAX_DOMAIN_NAME];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAX_MPM_PIN_PER_IRQ 2
|
||||||
static struct mpm_irqs unlisted_irqs[MSM_MPM_NR_IRQ_DOMAINS];
|
static struct mpm_irqs unlisted_irqs[MSM_MPM_NR_IRQ_DOMAINS];
|
||||||
|
|
||||||
static int num_mpm_irqs = MSM_MPM_NR_MPM_IRQS;
|
static int num_mpm_irqs = MSM_MPM_NR_MPM_IRQS;
|
||||||
static struct hlist_head *irq_hash;
|
static struct hlist_head *irq_hash;
|
||||||
static unsigned int *msm_mpm_irqs_m2a;
|
static unsigned int *msm_mpm_irqs_m2a;
|
||||||
|
@ -244,9 +244,10 @@ static inline unsigned int msm_mpm_get_irq_m2a(unsigned int pin)
|
||||||
return msm_mpm_irqs_m2a[pin];
|
return msm_mpm_irqs_m2a[pin];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t msm_mpm_get_irq_a2m(struct irq_data *d)
|
static inline void msm_mpm_get_irq_a2m(struct irq_data *d, uint16_t *mpm_pins)
|
||||||
{
|
{
|
||||||
struct mpm_irqs_a2m *node = NULL;
|
struct mpm_irqs_a2m *node = NULL;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
hlist_for_each_entry(node, &irq_hash[hashfn(d->hwirq)], node) {
|
hlist_for_each_entry(node, &irq_hash[hashfn(d->hwirq)], node) {
|
||||||
if ((node->hwirq == d->hwirq)
|
if ((node->hwirq == d->hwirq)
|
||||||
|
@ -257,58 +258,71 @@ static inline uint16_t msm_mpm_get_irq_a2m(struct irq_data *d)
|
||||||
*/
|
*/
|
||||||
if (node->pin != 0xff)
|
if (node->pin != 0xff)
|
||||||
msm_mpm_irqs_m2a[node->pin] = d->irq;
|
msm_mpm_irqs_m2a[node->pin] = d->irq;
|
||||||
break;
|
if (count >= MAX_MPM_PIN_PER_IRQ) {
|
||||||
|
count--;
|
||||||
|
__WARN();
|
||||||
|
}
|
||||||
|
mpm_pins[count] = node->pin;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return node ? node->pin : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int msm_mpm_enable_irq_exclusive(
|
static int msm_mpm_enable_irq_exclusive(
|
||||||
struct irq_data *d, bool enable, bool wakeset)
|
struct irq_data *d, bool enable, bool wakeset)
|
||||||
{
|
{
|
||||||
uint16_t mpm_pin;
|
uint16_t num = 0;
|
||||||
|
uint16_t mpm_pins[MAX_MPM_PIN_PER_IRQ] = {0};
|
||||||
|
|
||||||
WARN_ON(!d);
|
WARN_ON(!d);
|
||||||
|
|
||||||
if (!d)
|
if (!d)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mpm_pin = msm_mpm_get_irq_a2m(d);
|
msm_mpm_get_irq_a2m(d, mpm_pins);
|
||||||
|
|
||||||
if (mpm_pin == 0xff)
|
for (num = 0; num < MAX_MPM_PIN_PER_IRQ; num++) {
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (mpm_pin) {
|
if (mpm_pins[num] == 0xff)
|
||||||
uint32_t *mpm_irq_masks = wakeset ?
|
break;
|
||||||
|
|
||||||
|
if (num && mpm_pins[num] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (mpm_pins[num]) {
|
||||||
|
uint32_t *mpm_irq_masks = wakeset ?
|
||||||
msm_mpm_wake_irq : msm_mpm_enabled_irq;
|
msm_mpm_wake_irq : msm_mpm_enabled_irq;
|
||||||
uint32_t index = MSM_MPM_IRQ_INDEX(mpm_pin);
|
uint32_t index = MSM_MPM_IRQ_INDEX(mpm_pins[num]);
|
||||||
uint32_t mask = MSM_MPM_IRQ_MASK(mpm_pin);
|
uint32_t mask = MSM_MPM_IRQ_MASK(mpm_pins[num]);
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
mpm_irq_masks[index] |= mask;
|
mpm_irq_masks[index] |= mask;
|
||||||
else
|
else
|
||||||
mpm_irq_masks[index] &= ~mask;
|
mpm_irq_masks[index] &= ~mask;
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
unsigned long *irq_apps;
|
unsigned long *irq_apps;
|
||||||
|
|
||||||
for (i = 0; i < MSM_MPM_NR_IRQ_DOMAINS; i++) {
|
for (i = 0; i < MSM_MPM_NR_IRQ_DOMAINS; i++) {
|
||||||
if (d->domain == unlisted_irqs[i].domain)
|
if (d->domain == unlisted_irqs[i].domain)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == MSM_MPM_NR_IRQ_DOMAINS)
|
if (i == MSM_MPM_NR_IRQ_DOMAINS)
|
||||||
return 0;
|
return 0;
|
||||||
irq_apps = wakeset ? unlisted_irqs[i].wakeup_irqs :
|
|
||||||
|
irq_apps = wakeset ? unlisted_irqs[i].wakeup_irqs :
|
||||||
unlisted_irqs[i].enabled_irqs;
|
unlisted_irqs[i].enabled_irqs;
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
__set_bit(d->hwirq, irq_apps);
|
__set_bit(d->hwirq, irq_apps);
|
||||||
else
|
else
|
||||||
__clear_bit(d->hwirq, irq_apps);
|
__clear_bit(d->hwirq, irq_apps);
|
||||||
|
|
||||||
if ((msm_mpm_initialized & MSM_MPM_DEVICE_PROBED)
|
if ((msm_mpm_initialized & MSM_MPM_DEVICE_PROBED)
|
||||||
&& !wakeset && !msm_mpm_in_suspend)
|
&& !wakeset && !msm_mpm_in_suspend)
|
||||||
complete(&wake_wq);
|
complete(&wake_wq);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -337,27 +351,32 @@ static void msm_mpm_set_edge_ctl(int pin, unsigned int flow_type)
|
||||||
static int msm_mpm_set_irq_type_exclusive(
|
static int msm_mpm_set_irq_type_exclusive(
|
||||||
struct irq_data *d, unsigned int flow_type)
|
struct irq_data *d, unsigned int flow_type)
|
||||||
{
|
{
|
||||||
uint32_t mpm_irq;
|
uint16_t num = 0;
|
||||||
|
uint16_t mpm_pins[MAX_MPM_PIN_PER_IRQ] = {0};
|
||||||
|
|
||||||
mpm_irq = msm_mpm_get_irq_a2m(d);
|
msm_mpm_get_irq_a2m(d, mpm_pins);
|
||||||
|
|
||||||
if (mpm_irq == 0xff)
|
for (num = 0; num < MAX_MPM_PIN_PER_IRQ; num++) {
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (mpm_irq) {
|
if (mpm_pins[num] == 0xff)
|
||||||
uint32_t index = MSM_MPM_IRQ_INDEX(mpm_irq);
|
break;
|
||||||
uint32_t mask = MSM_MPM_IRQ_MASK(mpm_irq);
|
|
||||||
|
|
||||||
if (index >= MSM_MPM_REG_WIDTH)
|
if (mpm_pins[num]) {
|
||||||
return -EFAULT;
|
uint32_t index = MSM_MPM_IRQ_INDEX(mpm_pins[num]);
|
||||||
|
uint32_t mask = MSM_MPM_IRQ_MASK(mpm_pins[num]);
|
||||||
|
|
||||||
msm_mpm_set_edge_ctl(mpm_irq, flow_type);
|
if (index >= MSM_MPM_REG_WIDTH)
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
if (flow_type & IRQ_TYPE_LEVEL_HIGH)
|
msm_mpm_set_edge_ctl(mpm_pins[num], flow_type);
|
||||||
msm_mpm_polarity[index] |= mask;
|
|
||||||
else
|
if (flow_type & IRQ_TYPE_LEVEL_HIGH)
|
||||||
msm_mpm_polarity[index] &= ~mask;
|
msm_mpm_polarity[index] |= mask;
|
||||||
|
else
|
||||||
|
msm_mpm_polarity[index] &= ~mask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue