Lines Matching +full:ipa +full:- +full:reg
1 // SPDX-License-Identifier: GPL-2.0
3 /* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2018-2022 Linaro Ltd.
7 /* DOC: IPA Interrupts
9 * The IPA has an interrupt line distinct from the interrupt used by the GSI
11 * transfer completions), IPA interrupts are related to other events related
12 * to the IPA. Some of the IPA interrupts come from a microcontroller
13 * embedded in the IPA. Each IPA interrupt type can be both masked and
16 * Two of the IPA interrupts are initiated by the microcontroller. A third
17 * can be generated to signal the need for a wakeup/resume when an IPA
18 * endpoint has been suspended. There are other IPA events, but at this
27 #include "ipa.h"
35 * struct ipa_interrupt - IPA interrupt information
36 * @ipa: IPA pointer
37 * @irq: Linux IRQ number used for IPA interrupts
41 struct ipa *ipa; member
49 struct ipa *ipa = interrupt->ipa; in ipa_interrupt_process() local
50 const struct reg *reg; in ipa_interrupt_process() local
54 reg = ipa_reg(ipa, IPA_IRQ_CLR); in ipa_interrupt_process()
55 offset = reg_offset(reg); in ipa_interrupt_process()
63 iowrite32(mask, ipa->reg_virt + offset); in ipa_interrupt_process()
64 ipa_uc_interrupt_handler(ipa, irq_id); in ipa_interrupt_process()
73 ipa_power_suspend_handler(ipa, irq_id); in ipa_interrupt_process()
77 iowrite32(mask, ipa->reg_virt + offset); in ipa_interrupt_process()
82 /* IPA IRQ handler is threaded */
86 struct ipa *ipa = interrupt->ipa; in ipa_isr_thread() local
87 u32 enabled = interrupt->enabled; in ipa_isr_thread()
88 const struct reg *reg; in ipa_isr_thread() local
95 dev = &ipa->pdev->dev; in ipa_isr_thread()
104 reg = ipa_reg(ipa, IPA_IRQ_STTS); in ipa_isr_thread()
105 offset = reg_offset(reg); in ipa_isr_thread()
106 pending = ioread32(ipa->reg_virt + offset); in ipa_isr_thread()
115 pending = ioread32(ipa->reg_virt + offset); in ipa_isr_thread()
120 dev_dbg(dev, "clearing disabled IPA interrupts 0x%08x\n", in ipa_isr_thread()
122 reg = ipa_reg(ipa, IPA_IRQ_CLR); in ipa_isr_thread()
123 iowrite32(pending, ipa->reg_virt + reg_offset(reg)); in ipa_isr_thread()
132 static void ipa_interrupt_enabled_update(struct ipa *ipa) in ipa_interrupt_enabled_update() argument
134 const struct reg *reg = ipa_reg(ipa, IPA_IRQ_EN); in ipa_interrupt_enabled_update() local
136 iowrite32(ipa->interrupt->enabled, ipa->reg_virt + reg_offset(reg)); in ipa_interrupt_enabled_update()
139 /* Enable an IPA interrupt type */
140 void ipa_interrupt_enable(struct ipa *ipa, enum ipa_irq_id ipa_irq) in ipa_interrupt_enable() argument
142 /* Update the IPA interrupt mask to enable it */ in ipa_interrupt_enable()
143 ipa->interrupt->enabled |= BIT(ipa_irq); in ipa_interrupt_enable()
144 ipa_interrupt_enabled_update(ipa); in ipa_interrupt_enable()
147 /* Disable an IPA interrupt type */
148 void ipa_interrupt_disable(struct ipa *ipa, enum ipa_irq_id ipa_irq) in ipa_interrupt_disable() argument
150 /* Update the IPA interrupt mask to disable it */ in ipa_interrupt_disable()
151 ipa->interrupt->enabled &= ~BIT(ipa_irq); in ipa_interrupt_disable()
152 ipa_interrupt_enabled_update(ipa); in ipa_interrupt_disable()
155 void ipa_interrupt_irq_disable(struct ipa *ipa) in ipa_interrupt_irq_disable() argument
157 disable_irq(ipa->interrupt->irq); in ipa_interrupt_irq_disable()
160 void ipa_interrupt_irq_enable(struct ipa *ipa) in ipa_interrupt_irq_enable() argument
162 enable_irq(ipa->interrupt->irq); in ipa_interrupt_irq_enable()
169 struct ipa *ipa = interrupt->ipa; in ipa_interrupt_suspend_control() local
172 const struct reg *reg; in ipa_interrupt_suspend_control() local
176 WARN_ON(!test_bit(endpoint_id, ipa->available)); in ipa_interrupt_suspend_control()
178 /* IPA version 3.0 does not support TX_SUSPEND interrupt control */ in ipa_interrupt_suspend_control()
179 if (ipa->version == IPA_VERSION_3_0) in ipa_interrupt_suspend_control()
182 reg = ipa_reg(ipa, IRQ_SUSPEND_EN); in ipa_interrupt_suspend_control()
183 offset = reg_n_offset(reg, unit); in ipa_interrupt_suspend_control()
184 val = ioread32(ipa->reg_virt + offset); in ipa_interrupt_suspend_control()
191 iowrite32(val, ipa->reg_virt + offset); in ipa_interrupt_suspend_control()
211 struct ipa *ipa = interrupt->ipa; in ipa_interrupt_suspend_clear_all() local
215 unit_count = DIV_ROUND_UP(ipa->endpoint_count, 32); in ipa_interrupt_suspend_clear_all()
217 const struct reg *reg; in ipa_interrupt_suspend_clear_all() local
220 reg = ipa_reg(ipa, IRQ_SUSPEND_INFO); in ipa_interrupt_suspend_clear_all()
221 val = ioread32(ipa->reg_virt + reg_n_offset(reg, unit)); in ipa_interrupt_suspend_clear_all()
223 /* SUSPEND interrupt status isn't cleared on IPA version 3.0 */ in ipa_interrupt_suspend_clear_all()
224 if (ipa->version == IPA_VERSION_3_0) in ipa_interrupt_suspend_clear_all()
227 reg = ipa_reg(ipa, IRQ_SUSPEND_CLR); in ipa_interrupt_suspend_clear_all()
228 iowrite32(val, ipa->reg_virt + reg_n_offset(reg, unit)); in ipa_interrupt_suspend_clear_all()
232 /* Simulate arrival of an IPA TX_SUSPEND interrupt */
238 /* Configure the IPA interrupt framework */
239 struct ipa_interrupt *ipa_interrupt_config(struct ipa *ipa) in ipa_interrupt_config() argument
241 struct device *dev = &ipa->pdev->dev; in ipa_interrupt_config()
243 const struct reg *reg; in ipa_interrupt_config() local
247 ret = platform_get_irq_byname(ipa->pdev, "ipa"); in ipa_interrupt_config()
249 dev_err(dev, "DT error %d getting \"ipa\" IRQ property\n", in ipa_interrupt_config()
251 return ERR_PTR(ret ? : -EINVAL); in ipa_interrupt_config()
257 return ERR_PTR(-ENOMEM); in ipa_interrupt_config()
258 interrupt->ipa = ipa; in ipa_interrupt_config()
259 interrupt->irq = irq; in ipa_interrupt_config()
261 /* Start with all IPA interrupts disabled */ in ipa_interrupt_config()
262 reg = ipa_reg(ipa, IPA_IRQ_EN); in ipa_interrupt_config()
263 iowrite32(0, ipa->reg_virt + reg_offset(reg)); in ipa_interrupt_config()
266 "ipa", interrupt); in ipa_interrupt_config()
268 dev_err(dev, "error %d requesting \"ipa\" IRQ\n", ret); in ipa_interrupt_config()
274 dev_err(dev, "error %d registering \"ipa\" IRQ as wakeirq\n", ret); in ipa_interrupt_config()
281 free_irq(interrupt->irq, interrupt); in ipa_interrupt_config()
291 struct device *dev = &interrupt->ipa->pdev->dev; in ipa_interrupt_deconfig()
294 free_irq(interrupt->irq, interrupt); in ipa_interrupt_deconfig()