|
@@ -1,6 +1,6 @@
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
/*
|
|
|
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
|
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
|
|
*/
|
|
|
|
|
@@ -415,6 +415,7 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr,
|
|
|
int start_idx;
|
|
|
int end_idx;
|
|
|
u32 irq_status;
|
|
|
+ u32 enable_mask;
|
|
|
unsigned long irq_flags;
|
|
|
|
|
|
if (!intr)
|
|
@@ -427,8 +428,6 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr,
|
|
|
*/
|
|
|
spin_lock_irqsave(&intr->irq_lock, irq_flags);
|
|
|
for (reg_idx = 0; reg_idx < intr->sde_irq_size; reg_idx++) {
|
|
|
- irq_status = intr->save_irq_status[reg_idx];
|
|
|
-
|
|
|
/*
|
|
|
* Each Interrupt register has dynamic range of indexes,
|
|
|
* initialized during hw_intr_init when sde_irq_tbl is created.
|
|
@@ -440,6 +439,20 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr,
|
|
|
end_idx > intr->sde_irq_map_size)
|
|
|
continue;
|
|
|
|
|
|
+ /* Read interrupt status */
|
|
|
+ irq_status = SDE_REG_READ(&intr->hw, intr->sde_irq_tbl[reg_idx].status_off);
|
|
|
+
|
|
|
+ /* Read enable mask */
|
|
|
+ enable_mask = SDE_REG_READ(&intr->hw, intr->sde_irq_tbl[reg_idx].en_off);
|
|
|
+
|
|
|
+ /* and clear the interrupt */
|
|
|
+ if (irq_status)
|
|
|
+ SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[reg_idx].clr_off,
|
|
|
+ irq_status);
|
|
|
+
|
|
|
+ /* Finally update IRQ status based on enable mask */
|
|
|
+ irq_status &= enable_mask;
|
|
|
+
|
|
|
/*
|
|
|
* Search through matching intr status from irq map.
|
|
|
* start_idx and end_idx defined the search range in
|
|
@@ -474,6 +487,10 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr,
|
|
|
~intr->sde_irq_map[irq_idx].irq_mask;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /* ensure register writes go through */
|
|
|
+ wmb();
|
|
|
+
|
|
|
spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
|
|
|
}
|
|
|
|
|
@@ -620,40 +637,6 @@ static int sde_hw_intr_get_interrupt_sources(struct sde_hw_intr *intr,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void sde_hw_intr_get_interrupt_statuses(struct sde_hw_intr *intr)
|
|
|
-{
|
|
|
- int i;
|
|
|
- u32 enable_mask;
|
|
|
- unsigned long irq_flags;
|
|
|
-
|
|
|
- if (!intr)
|
|
|
- return;
|
|
|
-
|
|
|
- spin_lock_irqsave(&intr->irq_lock, irq_flags);
|
|
|
- for (i = 0; i < intr->sde_irq_size; i++) {
|
|
|
- /* Read interrupt status */
|
|
|
- intr->save_irq_status[i] = SDE_REG_READ(&intr->hw,
|
|
|
- intr->sde_irq_tbl[i].status_off);
|
|
|
-
|
|
|
- /* Read enable mask */
|
|
|
- enable_mask = SDE_REG_READ(&intr->hw,
|
|
|
- intr->sde_irq_tbl[i].en_off);
|
|
|
-
|
|
|
- /* and clear the interrupt */
|
|
|
- if (intr->save_irq_status[i])
|
|
|
- SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[i].clr_off,
|
|
|
- intr->save_irq_status[i]);
|
|
|
-
|
|
|
- /* Finally update IRQ status based on enable mask */
|
|
|
- intr->save_irq_status[i] &= enable_mask;
|
|
|
- }
|
|
|
-
|
|
|
- /* ensure register writes go through */
|
|
|
- wmb();
|
|
|
-
|
|
|
- spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
|
|
|
-}
|
|
|
-
|
|
|
static void sde_hw_intr_clear_intr_status_nolock(struct sde_hw_intr *intr,
|
|
|
int irq_idx)
|
|
|
{
|
|
@@ -856,7 +839,6 @@ static void __setup_intr_ops(struct sde_hw_intr_ops *ops)
|
|
|
ops->clear_all_irqs = sde_hw_intr_clear_irqs;
|
|
|
ops->disable_all_irqs = sde_hw_intr_disable_irqs;
|
|
|
ops->get_interrupt_sources = sde_hw_intr_get_interrupt_sources;
|
|
|
- ops->get_interrupt_statuses = sde_hw_intr_get_interrupt_statuses;
|
|
|
ops->clear_interrupt_status = sde_hw_intr_clear_interrupt_status;
|
|
|
ops->clear_intr_status_nolock = sde_hw_intr_clear_intr_status_nolock;
|
|
|
ops->get_interrupt_status = sde_hw_intr_get_interrupt_status;
|
|
@@ -881,7 +863,6 @@ void sde_hw_intr_destroy(struct sde_hw_intr *intr)
|
|
|
kfree(intr->sde_irq_tbl);
|
|
|
kfree(intr->sde_irq_map);
|
|
|
kfree(intr->cache_irq_mask);
|
|
|
- kfree(intr->save_irq_status);
|
|
|
kfree(intr);
|
|
|
}
|
|
|
}
|
|
@@ -1151,13 +1132,6 @@ struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr,
|
|
|
goto exit;
|
|
|
}
|
|
|
|
|
|
- intr->save_irq_status = kcalloc(intr->sde_irq_size,
|
|
|
- sizeof(*intr->save_irq_status), GFP_KERNEL);
|
|
|
- if (intr->save_irq_status == NULL) {
|
|
|
- ret = -ENOMEM;
|
|
|
- goto exit;
|
|
|
- }
|
|
|
-
|
|
|
spin_lock_init(&intr->irq_lock);
|
|
|
|
|
|
exit:
|