Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
0004  * Copyright (C) 2018-2020 Linaro Ltd.
0005  */
0006 
0007 /* DOC: IPA Interrupts
0008  *
0009  * The IPA has an interrupt line distinct from the interrupt used by the GSI
0010  * code.  Whereas GSI interrupts are generally related to channel events (like
0011  * transfer completions), IPA interrupts are related to other events related
0012  * to the IPA.  Some of the IPA interrupts come from a microcontroller
0013  * embedded in the IPA.  Each IPA interrupt type can be both masked and
0014  * acknowledged independent of the others.
0015  *
0016  * Two of the IPA interrupts are initiated by the microcontroller.  A third
0017  * can be generated to signal the need for a wakeup/resume when an IPA
0018  * endpoint has been suspended.  There are other IPA events, but at this
0019  * time only these three are supported.
0020  */
0021 
0022 #include <linux/types.h>
0023 #include <linux/interrupt.h>
0024 #include <linux/pm_runtime.h>
0025 
0026 #include "ipa.h"
0027 #include "ipa_reg.h"
0028 #include "ipa_endpoint.h"
0029 #include "ipa_interrupt.h"
0030 
0031 /**
0032  * struct ipa_interrupt - IPA interrupt information
0033  * @ipa:        IPA pointer
0034  * @irq:        Linux IRQ number used for IPA interrupts
0035  * @enabled:        Mask indicating which interrupts are enabled
0036  * @handler:        Array of handlers indexed by IPA interrupt ID
0037  */
0038 struct ipa_interrupt {
0039     struct ipa *ipa;
0040     u32 irq;
0041     u32 enabled;
0042     ipa_irq_handler_t handler[IPA_IRQ_COUNT];
0043 };
0044 
0045 /* Returns true if the interrupt type is associated with the microcontroller */
0046 static bool ipa_interrupt_uc(struct ipa_interrupt *interrupt, u32 irq_id)
0047 {
0048     return irq_id == IPA_IRQ_UC_0 || irq_id == IPA_IRQ_UC_1;
0049 }
0050 
0051 /* Process a particular interrupt type that has been received */
0052 static void ipa_interrupt_process(struct ipa_interrupt *interrupt, u32 irq_id)
0053 {
0054     bool uc_irq = ipa_interrupt_uc(interrupt, irq_id);
0055     struct ipa *ipa = interrupt->ipa;
0056     u32 mask = BIT(irq_id);
0057     u32 offset;
0058 
0059     /* For microcontroller interrupts, clear the interrupt right away,
0060      * "to avoid clearing unhandled interrupts."
0061      */
0062     offset = ipa_reg_irq_clr_offset(ipa->version);
0063     if (uc_irq)
0064         iowrite32(mask, ipa->reg_virt + offset);
0065 
0066     if (irq_id < IPA_IRQ_COUNT && interrupt->handler[irq_id])
0067         interrupt->handler[irq_id](interrupt->ipa, irq_id);
0068 
0069     /* Clearing the SUSPEND_TX interrupt also clears the register
0070      * that tells us which suspended endpoint(s) caused the interrupt,
0071      * so defer clearing until after the handler has been called.
0072      */
0073     if (!uc_irq)
0074         iowrite32(mask, ipa->reg_virt + offset);
0075 }
0076 
0077 /* IPA IRQ handler is threaded */
0078 static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
0079 {
0080     struct ipa_interrupt *interrupt = dev_id;
0081     struct ipa *ipa = interrupt->ipa;
0082     u32 enabled = interrupt->enabled;
0083     struct device *dev;
0084     u32 pending;
0085     u32 offset;
0086     u32 mask;
0087     int ret;
0088 
0089     dev = &ipa->pdev->dev;
0090     ret = pm_runtime_get_sync(dev);
0091     if (WARN_ON(ret < 0))
0092         goto out_power_put;
0093 
0094     /* The status register indicates which conditions are present,
0095      * including conditions whose interrupt is not enabled.  Handle
0096      * only the enabled ones.
0097      */
0098     offset = ipa_reg_irq_stts_offset(ipa->version);
0099     pending = ioread32(ipa->reg_virt + offset);
0100     while ((mask = pending & enabled)) {
0101         do {
0102             u32 irq_id = __ffs(mask);
0103 
0104             mask ^= BIT(irq_id);
0105 
0106             ipa_interrupt_process(interrupt, irq_id);
0107         } while (mask);
0108         pending = ioread32(ipa->reg_virt + offset);
0109     }
0110 
0111     /* If any disabled interrupts are pending, clear them */
0112     if (pending) {
0113         dev_dbg(dev, "clearing disabled IPA interrupts 0x%08x\n",
0114             pending);
0115         offset = ipa_reg_irq_clr_offset(ipa->version);
0116         iowrite32(pending, ipa->reg_virt + offset);
0117     }
0118 out_power_put:
0119     pm_runtime_mark_last_busy(dev);
0120     (void)pm_runtime_put_autosuspend(dev);
0121 
0122     return IRQ_HANDLED;
0123 }
0124 
0125 /* Common function used to enable/disable TX_SUSPEND for an endpoint */
0126 static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
0127                       u32 endpoint_id, bool enable)
0128 {
0129     struct ipa *ipa = interrupt->ipa;
0130     u32 mask = BIT(endpoint_id);
0131     u32 offset;
0132     u32 val;
0133 
0134     WARN_ON(!(mask & ipa->available));
0135 
0136     /* IPA version 3.0 does not support TX_SUSPEND interrupt control */
0137     if (ipa->version == IPA_VERSION_3_0)
0138         return;
0139 
0140     offset = ipa_reg_irq_suspend_en_offset(ipa->version);
0141     val = ioread32(ipa->reg_virt + offset);
0142     if (enable)
0143         val |= mask;
0144     else
0145         val &= ~mask;
0146     iowrite32(val, ipa->reg_virt + offset);
0147 }
0148 
0149 /* Enable TX_SUSPEND for an endpoint */
0150 void
0151 ipa_interrupt_suspend_enable(struct ipa_interrupt *interrupt, u32 endpoint_id)
0152 {
0153     ipa_interrupt_suspend_control(interrupt, endpoint_id, true);
0154 }
0155 
0156 /* Disable TX_SUSPEND for an endpoint */
0157 void
0158 ipa_interrupt_suspend_disable(struct ipa_interrupt *interrupt, u32 endpoint_id)
0159 {
0160     ipa_interrupt_suspend_control(interrupt, endpoint_id, false);
0161 }
0162 
0163 /* Clear the suspend interrupt for all endpoints that signaled it */
0164 void ipa_interrupt_suspend_clear_all(struct ipa_interrupt *interrupt)
0165 {
0166     struct ipa *ipa = interrupt->ipa;
0167     u32 offset;
0168     u32 val;
0169 
0170     offset = ipa_reg_irq_suspend_info_offset(ipa->version);
0171     val = ioread32(ipa->reg_virt + offset);
0172 
0173     /* SUSPEND interrupt status isn't cleared on IPA version 3.0 */
0174     if (ipa->version == IPA_VERSION_3_0)
0175         return;
0176 
0177     offset = ipa_reg_irq_suspend_clr_offset(ipa->version);
0178     iowrite32(val, ipa->reg_virt + offset);
0179 }
0180 
0181 /* Simulate arrival of an IPA TX_SUSPEND interrupt */
0182 void ipa_interrupt_simulate_suspend(struct ipa_interrupt *interrupt)
0183 {
0184     ipa_interrupt_process(interrupt, IPA_IRQ_TX_SUSPEND);
0185 }
0186 
0187 /* Add a handler for an IPA interrupt */
0188 void ipa_interrupt_add(struct ipa_interrupt *interrupt,
0189                enum ipa_irq_id ipa_irq, ipa_irq_handler_t handler)
0190 {
0191     struct ipa *ipa = interrupt->ipa;
0192     u32 offset;
0193 
0194     if (WARN_ON(ipa_irq >= IPA_IRQ_COUNT))
0195         return;
0196 
0197     interrupt->handler[ipa_irq] = handler;
0198 
0199     /* Update the IPA interrupt mask to enable it */
0200     interrupt->enabled |= BIT(ipa_irq);
0201     offset = ipa_reg_irq_en_offset(ipa->version);
0202     iowrite32(interrupt->enabled, ipa->reg_virt + offset);
0203 }
0204 
0205 /* Remove the handler for an IPA interrupt type */
0206 void
0207 ipa_interrupt_remove(struct ipa_interrupt *interrupt, enum ipa_irq_id ipa_irq)
0208 {
0209     struct ipa *ipa = interrupt->ipa;
0210     u32 offset;
0211 
0212     if (WARN_ON(ipa_irq >= IPA_IRQ_COUNT))
0213         return;
0214 
0215     /* Update the IPA interrupt mask to disable it */
0216     interrupt->enabled &= ~BIT(ipa_irq);
0217     offset = ipa_reg_irq_en_offset(ipa->version);
0218     iowrite32(interrupt->enabled, ipa->reg_virt + offset);
0219 
0220     interrupt->handler[ipa_irq] = NULL;
0221 }
0222 
0223 /* Configure the IPA interrupt framework */
0224 struct ipa_interrupt *ipa_interrupt_config(struct ipa *ipa)
0225 {
0226     struct device *dev = &ipa->pdev->dev;
0227     struct ipa_interrupt *interrupt;
0228     unsigned int irq;
0229     u32 offset;
0230     int ret;
0231 
0232     ret = platform_get_irq_byname(ipa->pdev, "ipa");
0233     if (ret <= 0) {
0234         dev_err(dev, "DT error %d getting \"ipa\" IRQ property\n",
0235             ret);
0236         return ERR_PTR(ret ? : -EINVAL);
0237     }
0238     irq = ret;
0239 
0240     interrupt = kzalloc(sizeof(*interrupt), GFP_KERNEL);
0241     if (!interrupt)
0242         return ERR_PTR(-ENOMEM);
0243     interrupt->ipa = ipa;
0244     interrupt->irq = irq;
0245 
0246     /* Start with all IPA interrupts disabled */
0247     offset = ipa_reg_irq_en_offset(ipa->version);
0248     iowrite32(0, ipa->reg_virt + offset);
0249 
0250     ret = request_threaded_irq(irq, NULL, ipa_isr_thread, IRQF_ONESHOT,
0251                    "ipa", interrupt);
0252     if (ret) {
0253         dev_err(dev, "error %d requesting \"ipa\" IRQ\n", ret);
0254         goto err_kfree;
0255     }
0256 
0257     ret = enable_irq_wake(irq);
0258     if (ret) {
0259         dev_err(dev, "error %d enabling wakeup for \"ipa\" IRQ\n", ret);
0260         goto err_free_irq;
0261     }
0262 
0263     return interrupt;
0264 
0265 err_free_irq:
0266     free_irq(interrupt->irq, interrupt);
0267 err_kfree:
0268     kfree(interrupt);
0269 
0270     return ERR_PTR(ret);
0271 }
0272 
0273 /* Inverse of ipa_interrupt_config() */
0274 void ipa_interrupt_deconfig(struct ipa_interrupt *interrupt)
0275 {
0276     struct device *dev = &interrupt->ipa->pdev->dev;
0277     int ret;
0278 
0279     ret = disable_irq_wake(interrupt->irq);
0280     if (ret)
0281         dev_err(dev, "error %d disabling \"ipa\" IRQ wakeup\n", ret);
0282     free_irq(interrupt->irq, interrupt);
0283     kfree(interrupt);
0284 }