mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
Merge "soc: qcom: smp2p: Add proper retrigger detection"
This commit is contained in:
commit
5a1f4af368
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user