Merge "soc: qcom: smp2p: Add proper retrigger detection"

This commit is contained in:
qctecmdr 2022-06-29 08:29:09 -07:00 committed by Gerrit - the friendly Code Review server
commit 5a1f4af368

View File

@ -2,6 +2,7 @@
/*
* Copyright (c) 2015, Sony Mobile Communications AB.
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/interrupt.h>
@ -101,6 +102,7 @@ struct smp2p_entry {
struct irq_domain *domain;
DECLARE_BITMAP(irq_enabled, 32);
DECLARE_BITMAP(irq_pending, 32);
DECLARE_BITMAP(irq_rising, 32);
DECLARE_BITMAP(irq_falling, 32);
@ -146,6 +148,7 @@ struct qcom_smp2p {
unsigned local_pid;
unsigned remote_pid;
int irq;
struct regmap *ipc_regmap;
int ipc_offset;
int ipc_bit;
@ -217,8 +220,8 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p)
{
struct smp2p_smem_item *in;
struct smp2p_entry *entry;
unsigned long status;
int irq_pin;
u32 status;
char buf[SMP2P_MAX_ENTRY_NAME];
u32 val;
int i;
@ -247,19 +250,18 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p)
status = val ^ entry->last_value;
entry->last_value = val;
status |= *entry->irq_pending;
/* No changes of this entry? */
if (!status)
continue;
for_each_set_bit(i, entry->irq_enabled, 32) {
if (!(status & BIT(i)))
continue;
for_each_set_bit(i, &status, 32) {
if ((val & BIT(i) && test_bit(i, entry->irq_rising)) ||
(!(val & BIT(i)) && test_bit(i, entry->irq_falling))) {
irq_pin = irq_find_mapping(entry->domain, i);
handle_nested_irq(irq_pin);
clear_bit(i, entry->irq_pending);
}
}
}
@ -348,11 +350,22 @@ static int smp2p_set_irq_type(struct irq_data *irqd, unsigned int type)
return 0;
}
static int smp2p_retrigger_irq(struct irq_data *irqd)
{
struct smp2p_entry *entry = irq_data_get_irq_chip_data(irqd);
irq_hw_number_t irq = irqd_to_hwirq(irqd);
set_bit(irq, entry->irq_pending);
return 0;
}
static struct irq_chip smp2p_irq_chip = {
.name = "smp2p",
.irq_mask = smp2p_mask_irq,
.irq_unmask = smp2p_unmask_irq,
.irq_set_type = smp2p_set_irq_type,
.irq_retrigger = smp2p_retrigger_irq,
};
static int smp2p_irq_map(struct irq_domain *d,
@ -365,6 +378,8 @@ static int smp2p_irq_map(struct irq_domain *d,
irq_set_chip_data(irq, entry);
irq_set_nested_thread(irq, 1);
irq_set_noprobe(irq);
irq_set_parent(irq, entry->smp2p->irq);
irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
return 0;
}
@ -609,6 +624,7 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
/* Kick the outgoing edge after allocating entries */
qcom_smp2p_kick(smp2p);
smp2p->irq = irq;
ret = devm_request_threaded_irq(&pdev->dev, irq,
NULL, qcom_smp2p_intr,
IRQF_ONESHOT,