Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
0004  * Copyright (C) 2019-2020 Linaro Ltd.
0005  */
0006 
0007 #include <linux/types.h>
0008 #include <linux/device.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/notifier.h>
0011 #include <linux/panic_notifier.h>
0012 #include <linux/pm_runtime.h>
0013 #include <linux/soc/qcom/smem.h>
0014 #include <linux/soc/qcom/smem_state.h>
0015 
0016 #include "ipa_smp2p.h"
0017 #include "ipa.h"
0018 #include "ipa_uc.h"
0019 
0020 /**
0021  * DOC: IPA SMP2P communication with the modem
0022  *
0023  * SMP2P is a primitive communication mechanism available between the AP and
0024  * the modem.  The IPA driver uses this for two purposes:  to enable the modem
0025  * to state that the GSI hardware is ready to use; and to communicate the
0026  * state of IPA power in the event of a crash.
0027  *
0028  * GSI needs to have early initialization completed before it can be used.
0029  * This initialization is done either by Trust Zone or by the modem.  In the
0030  * latter case, the modem uses an SMP2P interrupt to tell the AP IPA driver
0031  * when the GSI is ready to use.
0032  *
0033  * The modem is also able to inquire about the current state of IPA
0034  * power by trigging another SMP2P interrupt to the AP.  We communicate
0035  * whether power is enabled using two SMP2P state bits--one to indicate
0036  * the power state (on or off), and a second to indicate the power state
0037  * bit is valid.  The modem will poll the valid bit until it is set, and
0038  * at that time records whether the AP has IPA power enabled.
0039  *
0040  * Finally, if the AP kernel panics, we update the SMP2P state bits even if
0041  * we never receive an interrupt from the modem requesting this.
0042  */
0043 
0044 /**
0045  * struct ipa_smp2p - IPA SMP2P information
0046  * @ipa:        IPA pointer
0047  * @valid_state:    SMEM state indicating enabled state is valid
0048  * @enabled_state:  SMEM state to indicate power is enabled
0049  * @valid_bit:      Valid bit in 32-bit SMEM state mask
0050  * @enabled_bit:    Enabled bit in 32-bit SMEM state mask
0051  * @enabled_bit:    Enabled bit in 32-bit SMEM state mask
0052  * @clock_query_irq:    IPA interrupt triggered by modem for power query
0053  * @setup_ready_irq:    IPA interrupt triggered by modem to signal GSI ready
0054  * @power_on:       Whether IPA power is on
0055  * @notified:       Whether modem has been notified of power state
0056  * @setup_disabled: Whether setup ready interrupt handler is disabled
0057  * @mutex:      Mutex protecting ready-interrupt/shutdown interlock
0058  * @panic_notifier: Panic notifier structure
0059 */
0060 struct ipa_smp2p {
0061     struct ipa *ipa;
0062     struct qcom_smem_state *valid_state;
0063     struct qcom_smem_state *enabled_state;
0064     u32 valid_bit;
0065     u32 enabled_bit;
0066     u32 clock_query_irq;
0067     u32 setup_ready_irq;
0068     bool power_on;
0069     bool notified;
0070     bool setup_disabled;
0071     struct mutex mutex;
0072     struct notifier_block panic_notifier;
0073 };
0074 
0075 /**
0076  * ipa_smp2p_notify() - use SMP2P to tell modem about IPA power state
0077  * @smp2p:  SMP2P information
0078  *
0079  * This is called either when the modem has requested it (by triggering
0080  * the modem power query IPA interrupt) or whenever the AP is shutting down
0081  * (via a panic notifier).  It sets the two SMP2P state bits--one saying
0082  * whether the IPA power is on, and the other indicating the first bit
0083  * is valid.
0084  */
0085 static void ipa_smp2p_notify(struct ipa_smp2p *smp2p)
0086 {
0087     struct device *dev;
0088     u32 value;
0089     u32 mask;
0090 
0091     if (smp2p->notified)
0092         return;
0093 
0094     dev = &smp2p->ipa->pdev->dev;
0095     smp2p->power_on = pm_runtime_get_if_active(dev, true) > 0;
0096 
0097     /* Signal whether the IPA power is enabled */
0098     mask = BIT(smp2p->enabled_bit);
0099     value = smp2p->power_on ? mask : 0;
0100     qcom_smem_state_update_bits(smp2p->enabled_state, mask, value);
0101 
0102     /* Now indicate that the enabled flag is valid */
0103     mask = BIT(smp2p->valid_bit);
0104     value = mask;
0105     qcom_smem_state_update_bits(smp2p->valid_state, mask, value);
0106 
0107     smp2p->notified = true;
0108 }
0109 
0110 /* Threaded IRQ handler for modem "ipa-clock-query" SMP2P interrupt */
0111 static irqreturn_t ipa_smp2p_modem_clk_query_isr(int irq, void *dev_id)
0112 {
0113     struct ipa_smp2p *smp2p = dev_id;
0114 
0115     ipa_smp2p_notify(smp2p);
0116 
0117     return IRQ_HANDLED;
0118 }
0119 
0120 static int ipa_smp2p_panic_notifier(struct notifier_block *nb,
0121                     unsigned long action, void *data)
0122 {
0123     struct ipa_smp2p *smp2p;
0124 
0125     smp2p = container_of(nb, struct ipa_smp2p, panic_notifier);
0126 
0127     ipa_smp2p_notify(smp2p);
0128 
0129     if (smp2p->power_on)
0130         ipa_uc_panic_notifier(smp2p->ipa);
0131 
0132     return NOTIFY_DONE;
0133 }
0134 
0135 static int ipa_smp2p_panic_notifier_register(struct ipa_smp2p *smp2p)
0136 {
0137     /* IPA panic handler needs to run before modem shuts down */
0138     smp2p->panic_notifier.notifier_call = ipa_smp2p_panic_notifier;
0139     smp2p->panic_notifier.priority = INT_MAX;   /* Do it early */
0140 
0141     return atomic_notifier_chain_register(&panic_notifier_list,
0142                           &smp2p->panic_notifier);
0143 }
0144 
0145 static void ipa_smp2p_panic_notifier_unregister(struct ipa_smp2p *smp2p)
0146 {
0147     atomic_notifier_chain_unregister(&panic_notifier_list,
0148                      &smp2p->panic_notifier);
0149 }
0150 
0151 /* Threaded IRQ handler for modem "ipa-setup-ready" SMP2P interrupt */
0152 static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id)
0153 {
0154     struct ipa_smp2p *smp2p = dev_id;
0155     struct device *dev;
0156     int ret;
0157 
0158     /* Ignore any (spurious) interrupts received after the first */
0159     if (smp2p->ipa->setup_complete)
0160         return IRQ_HANDLED;
0161 
0162     /* Power needs to be active for setup */
0163     dev = &smp2p->ipa->pdev->dev;
0164     ret = pm_runtime_get_sync(dev);
0165     if (ret < 0) {
0166         dev_err(dev, "error %d getting power for setup\n", ret);
0167         goto out_power_put;
0168     }
0169 
0170     /* An error here won't cause driver shutdown, so warn if one occurs */
0171     ret = ipa_setup(smp2p->ipa);
0172     WARN(ret != 0, "error %d from ipa_setup()\n", ret);
0173 
0174 out_power_put:
0175     pm_runtime_mark_last_busy(dev);
0176     (void)pm_runtime_put_autosuspend(dev);
0177 
0178     return IRQ_HANDLED;
0179 }
0180 
0181 /* Initialize SMP2P interrupts */
0182 static int ipa_smp2p_irq_init(struct ipa_smp2p *smp2p, const char *name,
0183                   irq_handler_t handler)
0184 {
0185     struct device *dev = &smp2p->ipa->pdev->dev;
0186     unsigned int irq;
0187     int ret;
0188 
0189     ret = platform_get_irq_byname(smp2p->ipa->pdev, name);
0190     if (ret <= 0)
0191         return ret ? : -EINVAL;
0192     irq = ret;
0193 
0194     ret = request_threaded_irq(irq, NULL, handler, 0, name, smp2p);
0195     if (ret) {
0196         dev_err(dev, "error %d requesting \"%s\" IRQ\n", ret, name);
0197         return ret;
0198     }
0199 
0200     return irq;
0201 }
0202 
0203 static void ipa_smp2p_irq_exit(struct ipa_smp2p *smp2p, u32 irq)
0204 {
0205     free_irq(irq, smp2p);
0206 }
0207 
0208 /* Drop the power reference if it was taken in ipa_smp2p_notify() */
0209 static void ipa_smp2p_power_release(struct ipa *ipa)
0210 {
0211     struct device *dev = &ipa->pdev->dev;
0212 
0213     if (!ipa->smp2p->power_on)
0214         return;
0215 
0216     pm_runtime_mark_last_busy(dev);
0217     (void)pm_runtime_put_autosuspend(dev);
0218     ipa->smp2p->power_on = false;
0219 }
0220 
0221 /* Initialize the IPA SMP2P subsystem */
0222 int ipa_smp2p_init(struct ipa *ipa, bool modem_init)
0223 {
0224     struct qcom_smem_state *enabled_state;
0225     struct device *dev = &ipa->pdev->dev;
0226     struct qcom_smem_state *valid_state;
0227     struct ipa_smp2p *smp2p;
0228     u32 enabled_bit;
0229     u32 valid_bit;
0230     int ret;
0231 
0232     valid_state = qcom_smem_state_get(dev, "ipa-clock-enabled-valid",
0233                       &valid_bit);
0234     if (IS_ERR(valid_state))
0235         return PTR_ERR(valid_state);
0236     if (valid_bit >= 32)        /* BITS_PER_U32 */
0237         return -EINVAL;
0238 
0239     enabled_state = qcom_smem_state_get(dev, "ipa-clock-enabled",
0240                         &enabled_bit);
0241     if (IS_ERR(enabled_state))
0242         return PTR_ERR(enabled_state);
0243     if (enabled_bit >= 32)      /* BITS_PER_U32 */
0244         return -EINVAL;
0245 
0246     smp2p = kzalloc(sizeof(*smp2p), GFP_KERNEL);
0247     if (!smp2p)
0248         return -ENOMEM;
0249 
0250     smp2p->ipa = ipa;
0251 
0252     /* These fields are needed by the power query interrupt
0253      * handler, so initialize them now.
0254      */
0255     mutex_init(&smp2p->mutex);
0256     smp2p->valid_state = valid_state;
0257     smp2p->valid_bit = valid_bit;
0258     smp2p->enabled_state = enabled_state;
0259     smp2p->enabled_bit = enabled_bit;
0260 
0261     /* We have enough information saved to handle notifications */
0262     ipa->smp2p = smp2p;
0263 
0264     ret = ipa_smp2p_irq_init(smp2p, "ipa-clock-query",
0265                  ipa_smp2p_modem_clk_query_isr);
0266     if (ret < 0)
0267         goto err_null_smp2p;
0268     smp2p->clock_query_irq = ret;
0269 
0270     ret = ipa_smp2p_panic_notifier_register(smp2p);
0271     if (ret)
0272         goto err_irq_exit;
0273 
0274     if (modem_init) {
0275         /* Result will be non-zero (negative for error) */
0276         ret = ipa_smp2p_irq_init(smp2p, "ipa-setup-ready",
0277                      ipa_smp2p_modem_setup_ready_isr);
0278         if (ret < 0)
0279             goto err_notifier_unregister;
0280         smp2p->setup_ready_irq = ret;
0281     }
0282 
0283     return 0;
0284 
0285 err_notifier_unregister:
0286     ipa_smp2p_panic_notifier_unregister(smp2p);
0287 err_irq_exit:
0288     ipa_smp2p_irq_exit(smp2p, smp2p->clock_query_irq);
0289 err_null_smp2p:
0290     ipa->smp2p = NULL;
0291     mutex_destroy(&smp2p->mutex);
0292     kfree(smp2p);
0293 
0294     return ret;
0295 }
0296 
0297 void ipa_smp2p_exit(struct ipa *ipa)
0298 {
0299     struct ipa_smp2p *smp2p = ipa->smp2p;
0300 
0301     if (smp2p->setup_ready_irq)
0302         ipa_smp2p_irq_exit(smp2p, smp2p->setup_ready_irq);
0303     ipa_smp2p_panic_notifier_unregister(smp2p);
0304     ipa_smp2p_irq_exit(smp2p, smp2p->clock_query_irq);
0305     /* We won't get notified any more; drop power reference (if any) */
0306     ipa_smp2p_power_release(ipa);
0307     ipa->smp2p = NULL;
0308     mutex_destroy(&smp2p->mutex);
0309     kfree(smp2p);
0310 }
0311 
0312 void ipa_smp2p_irq_disable_setup(struct ipa *ipa)
0313 {
0314     struct ipa_smp2p *smp2p = ipa->smp2p;
0315 
0316     if (!smp2p->setup_ready_irq)
0317         return;
0318 
0319     mutex_lock(&smp2p->mutex);
0320 
0321     if (!smp2p->setup_disabled) {
0322         disable_irq(smp2p->setup_ready_irq);
0323         smp2p->setup_disabled = true;
0324     }
0325 
0326     mutex_unlock(&smp2p->mutex);
0327 }
0328 
0329 /* Reset state tracking whether we have notified the modem */
0330 void ipa_smp2p_notify_reset(struct ipa *ipa)
0331 {
0332     struct ipa_smp2p *smp2p = ipa->smp2p;
0333     u32 mask;
0334 
0335     if (!smp2p->notified)
0336         return;
0337 
0338     ipa_smp2p_power_release(ipa);
0339 
0340     /* Reset the power enabled valid flag */
0341     mask = BIT(smp2p->valid_bit);
0342     qcom_smem_state_update_bits(smp2p->valid_state, mask, 0);
0343 
0344     /* Mark the power disabled for good measure... */
0345     mask = BIT(smp2p->enabled_bit);
0346     qcom_smem_state_update_bits(smp2p->enabled_state, mask, 0);
0347 
0348     smp2p->notified = false;
0349 }