Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfc8bab4 authored by Maulik Shah's avatar Maulik Shah
Browse files

mpm-of: Support multiple mpm pin mapping to same gic interrupt



Currently one gic interrupt is mapped to one mpm pin.
Support multiple mpm pins to get enabled with single irq
with client drivers using enable_irq_wake API.

Change-Id: Iea575079c24ed0986b74fb6e86c7b8100474f19e
Signed-off-by: default avatarMaulik Shah <mkshah@codeaurora.org>
parent b2b64139
Loading
Loading
Loading
Loading
+64 −48
Original line number Diff line number Diff line
/* 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
 * 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];
};

#define MAX_MPM_PIN_PER_IRQ 2
static struct mpm_irqs unlisted_irqs[MSM_MPM_NR_IRQ_DOMAINS];

static int num_mpm_irqs = MSM_MPM_NR_MPM_IRQS;
static struct hlist_head *irq_hash;
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];
}

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;
	int count = 0;

	hlist_for_each_entry(node, &irq_hash[hashfn(d->hwirq)], node) {
		if ((node->hwirq == d->hwirq)
@@ -257,31 +258,39 @@ static inline uint16_t msm_mpm_get_irq_a2m(struct irq_data *d)
			 */
			if (node->pin != 0xff)
				msm_mpm_irqs_m2a[node->pin] = d->irq;
			break;
			BUG_ON(count >= MAX_MPM_PIN_PER_IRQ);
			mpm_pins[count] = node->pin;
			count++;
		}
	}
	return node ? node->pin : 0;
}

static int msm_mpm_enable_irq_exclusive(
	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);

	if (!d)
		return 0;

	mpm_pin = msm_mpm_get_irq_a2m(d);
	msm_mpm_get_irq_a2m(d, mpm_pins);

	if (mpm_pin == 0xff)
		return 0;
	for (num = 0; num < MAX_MPM_PIN_PER_IRQ; num++) {

		if (mpm_pins[num] == 0xff)
			break;

		if (num && mpm_pins[num] == 0)
			break;

	if (mpm_pin) {
		if (mpm_pins[num]) {
			uint32_t *mpm_irq_masks = wakeset ?
				msm_mpm_wake_irq : msm_mpm_enabled_irq;
		uint32_t index = MSM_MPM_IRQ_INDEX(mpm_pin);
		uint32_t mask = MSM_MPM_IRQ_MASK(mpm_pin);
			uint32_t index = MSM_MPM_IRQ_INDEX(mpm_pins[num]);
			uint32_t mask = MSM_MPM_IRQ_MASK(mpm_pins[num]);

			if (enable)
				mpm_irq_masks[index] |= mask;
@@ -298,6 +307,7 @@ static int msm_mpm_enable_irq_exclusive(

			if (i == MSM_MPM_NR_IRQ_DOMAINS)
				return 0;

			irq_apps = wakeset ? unlisted_irqs[i].wakeup_irqs :
					unlisted_irqs[i].enabled_irqs;

@@ -310,6 +320,7 @@ static int msm_mpm_enable_irq_exclusive(
				&& !wakeset && !msm_mpm_in_suspend)
				complete(&wake_wq);
		}
	}

	return 0;
}
@@ -337,27 +348,32 @@ static void msm_mpm_set_edge_ctl(int pin, unsigned int flow_type)
static int msm_mpm_set_irq_type_exclusive(
	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)
		return 0;
	for (num = 0; num < MAX_MPM_PIN_PER_IRQ; num++) {

	if (mpm_irq) {
		uint32_t index = MSM_MPM_IRQ_INDEX(mpm_irq);
		uint32_t mask = MSM_MPM_IRQ_MASK(mpm_irq);
		if (mpm_pins[num] == 0xff)
			break;

		if (mpm_pins[num]) {
			uint32_t index = MSM_MPM_IRQ_INDEX(mpm_pins[num]);
			uint32_t mask = MSM_MPM_IRQ_MASK(mpm_pins[num]);

			if (index >= MSM_MPM_REG_WIDTH)
				return -EFAULT;

		msm_mpm_set_edge_ctl(mpm_irq, flow_type);
			msm_mpm_set_edge_ctl(mpm_pins[num], flow_type);

			if (flow_type &  IRQ_TYPE_LEVEL_HIGH)
				msm_mpm_polarity[index] |= mask;
			else
				msm_mpm_polarity[index] &= ~mask;
		}
	}

	return 0;
}