1 // SPDX-License-Identifier: GPL-2.0 2 3 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. 4 * Copyright (C) 2019-2024 Linaro Ltd. 5 */ 6 7 #include <linux/types.h> 8 #include <linux/platform_device.h> 9 #include <linux/interrupt.h> 10 #include <linux/notifier.h> 11 #include <linux/panic_notifier.h> 12 #include <linux/pm_runtime.h> 13 #include <linux/soc/qcom/smem_state.h> 14 15 #include "ipa_smp2p.h" 16 #include "ipa.h" 17 #include "ipa_uc.h" 18 19 /** 20 * DOC: IPA SMP2P communication with the modem 21 * 22 * SMP2P is a primitive communication mechanism available between the AP and 23 * the modem. The IPA driver uses this for two purposes: to enable the modem 24 * to state that the GSI hardware is ready to use; and to communicate the 25 * state of IPA power in the event of a crash. 26 * 27 * GSI needs to have early initialization completed before it can be used. 28 * This initialization is done either by Trust Zone or by the modem. In the 29 * latter case, the modem uses an SMP2P interrupt to tell the AP IPA driver 30 * when the GSI is ready to use. 31 * 32 * The modem is also able to inquire about the current state of IPA 33 * power by trigging another SMP2P interrupt to the AP. We communicate 34 * whether power is enabled using two SMP2P state bits--one to indicate 35 * the power state (on or off), and a second to indicate the power state 36 * bit is valid. The modem will poll the valid bit until it is set, and 37 * at that time records whether the AP has IPA power enabled. 38 * 39 * Finally, if the AP kernel panics, we update the SMP2P state bits even if 40 * we never receive an interrupt from the modem requesting this. 41 */ 42 43 /** 44 * struct ipa_smp2p - IPA SMP2P information 45 * @ipa: IPA pointer 46 * @valid_state: SMEM state indicating enabled state is valid 47 * @enabled_state: SMEM state to indicate power is enabled 48 * @valid_bit: Valid bit in 32-bit SMEM state mask 49 * @enabled_bit: Enabled bit in 32-bit SMEM state mask 50 * @enabled_bit: Enabled bit in 32-bit SMEM state mask 51 * @clock_query_irq: IPA interrupt triggered by modem for power query 52 * @setup_ready_irq: IPA interrupt triggered by modem to signal GSI ready 53 * @power_on: Whether IPA power is on 54 * @notified: Whether modem has been notified of power state 55 * @setup_disabled: Whether setup ready interrupt handler is disabled 56 * @mutex: Mutex protecting ready-interrupt/shutdown interlock 57 * @panic_notifier: Panic notifier structure 58 */ 59 struct ipa_smp2p { 60 struct ipa *ipa; 61 struct qcom_smem_state *valid_state; 62 struct qcom_smem_state *enabled_state; 63 u32 valid_bit; 64 u32 enabled_bit; 65 u32 clock_query_irq; 66 u32 setup_ready_irq; 67 bool power_on; 68 bool notified; 69 bool setup_disabled; 70 struct mutex mutex; 71 struct notifier_block panic_notifier; 72 }; 73 74 /** 75 * ipa_smp2p_notify() - use SMP2P to tell modem about IPA power state 76 * @smp2p: SMP2P information 77 * 78 * This is called either when the modem has requested it (by triggering 79 * the modem power query IPA interrupt) or whenever the AP is shutting down 80 * (via a panic notifier). It sets the two SMP2P state bits--one saying 81 * whether the IPA power is on, and the other indicating the first bit 82 * is valid. 83 */ 84 static void ipa_smp2p_notify(struct ipa_smp2p *smp2p) 85 { 86 u32 value; 87 u32 mask; 88 89 if (smp2p->notified) 90 return; 91 92 smp2p->power_on = pm_runtime_get_if_active(smp2p->ipa->dev) > 0; 93 94 /* Signal whether the IPA power is enabled */ 95 mask = BIT(smp2p->enabled_bit); 96 value = smp2p->power_on ? mask : 0; 97 qcom_smem_state_update_bits(smp2p->enabled_state, mask, value); 98 99 /* Now indicate that the enabled flag is valid */ 100 mask = BIT(smp2p->valid_bit); 101 value = mask; 102 qcom_smem_state_update_bits(smp2p->valid_state, mask, value); 103 104 smp2p->notified = true; 105 } 106 107 /* Threaded IRQ handler for modem "ipa-clock-query" SMP2P interrupt */ 108 static irqreturn_t ipa_smp2p_modem_clk_query_isr(int irq, void *dev_id) 109 { 110 struct ipa_smp2p *smp2p = dev_id; 111 112 ipa_smp2p_notify(smp2p); 113 114 return IRQ_HANDLED; 115 } 116 117 static int ipa_smp2p_panic_notifier(struct notifier_block *nb, 118 unsigned long action, void *data) 119 { 120 struct ipa_smp2p *smp2p; 121 122 smp2p = container_of(nb, struct ipa_smp2p, panic_notifier); 123 124 ipa_smp2p_notify(smp2p); 125 126 if (smp2p->power_on) 127 ipa_uc_panic_notifier(smp2p->ipa); 128 129 return NOTIFY_DONE; 130 } 131 132 static int ipa_smp2p_panic_notifier_register(struct ipa_smp2p *smp2p) 133 { 134 /* IPA panic handler needs to run before modem shuts down */ 135 smp2p->panic_notifier.notifier_call = ipa_smp2p_panic_notifier; 136 smp2p->panic_notifier.priority = INT_MAX; /* Do it early */ 137 138 return atomic_notifier_chain_register(&panic_notifier_list, 139 &smp2p->panic_notifier); 140 } 141 142 static void ipa_smp2p_panic_notifier_unregister(struct ipa_smp2p *smp2p) 143 { 144 atomic_notifier_chain_unregister(&panic_notifier_list, 145 &smp2p->panic_notifier); 146 } 147 148 /* Threaded IRQ handler for modem "ipa-setup-ready" SMP2P interrupt */ 149 static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id) 150 { 151 struct ipa_smp2p *smp2p = dev_id; 152 struct ipa *ipa = smp2p->ipa; 153 struct device *dev; 154 int ret; 155 156 /* Ignore any (spurious) interrupts received after the first */ 157 if (ipa->setup_complete) 158 return IRQ_HANDLED; 159 160 /* Power needs to be active for setup */ 161 dev = ipa->dev; 162 ret = pm_runtime_get_sync(dev); 163 if (ret < 0) { 164 dev_err(dev, "error %d getting power for setup\n", ret); 165 goto out_power_put; 166 } 167 168 /* An error here won't cause driver shutdown, so warn if one occurs */ 169 ret = ipa_setup(ipa); 170 WARN(ret != 0, "error %d from ipa_setup()\n", ret); 171 172 out_power_put: 173 pm_runtime_mark_last_busy(dev); 174 (void)pm_runtime_put_autosuspend(dev); 175 176 return IRQ_HANDLED; 177 } 178 179 /* Initialize SMP2P interrupts */ 180 static int ipa_smp2p_irq_init(struct ipa_smp2p *smp2p, 181 struct platform_device *pdev, 182 const char *name, irq_handler_t handler) 183 { 184 struct device *dev = &pdev->dev; 185 unsigned int irq; 186 int ret; 187 188 ret = platform_get_irq_byname(pdev, name); 189 if (ret <= 0) 190 return ret ? : -EINVAL; 191 irq = ret; 192 193 ret = request_threaded_irq(irq, NULL, handler, 0, name, smp2p); 194 if (ret) { 195 dev_err(dev, "error %d requesting \"%s\" IRQ\n", ret, name); 196 return ret; 197 } 198 199 return irq; 200 } 201 202 static void ipa_smp2p_irq_exit(struct ipa_smp2p *smp2p, u32 irq) 203 { 204 free_irq(irq, smp2p); 205 } 206 207 /* Drop the power reference if it was taken in ipa_smp2p_notify() */ 208 static void ipa_smp2p_power_release(struct ipa *ipa) 209 { 210 struct device *dev = ipa->dev; 211 212 if (!ipa->smp2p->power_on) 213 return; 214 215 pm_runtime_mark_last_busy(dev); 216 (void)pm_runtime_put_autosuspend(dev); 217 ipa->smp2p->power_on = false; 218 } 219 220 /* Initialize the IPA SMP2P subsystem */ 221 int 222 ipa_smp2p_init(struct ipa *ipa, struct platform_device *pdev, bool modem_init) 223 { 224 struct qcom_smem_state *enabled_state; 225 struct device *dev = &pdev->dev; 226 struct qcom_smem_state *valid_state; 227 struct ipa_smp2p *smp2p; 228 u32 enabled_bit; 229 u32 valid_bit; 230 int ret; 231 232 valid_state = qcom_smem_state_get(dev, "ipa-clock-enabled-valid", 233 &valid_bit); 234 if (IS_ERR(valid_state)) 235 return PTR_ERR(valid_state); 236 if (valid_bit >= 32) /* BITS_PER_U32 */ 237 return -EINVAL; 238 239 enabled_state = qcom_smem_state_get(dev, "ipa-clock-enabled", 240 &enabled_bit); 241 if (IS_ERR(enabled_state)) 242 return PTR_ERR(enabled_state); 243 if (enabled_bit >= 32) /* BITS_PER_U32 */ 244 return -EINVAL; 245 246 smp2p = kzalloc(sizeof(*smp2p), GFP_KERNEL); 247 if (!smp2p) 248 return -ENOMEM; 249 250 smp2p->ipa = ipa; 251 252 /* These fields are needed by the power query interrupt 253 * handler, so initialize them now. 254 */ 255 mutex_init(&smp2p->mutex); 256 smp2p->valid_state = valid_state; 257 smp2p->valid_bit = valid_bit; 258 smp2p->enabled_state = enabled_state; 259 smp2p->enabled_bit = enabled_bit; 260 261 /* We have enough information saved to handle notifications */ 262 ipa->smp2p = smp2p; 263 264 ret = ipa_smp2p_irq_init(smp2p, pdev, "ipa-clock-query", 265 ipa_smp2p_modem_clk_query_isr); 266 if (ret < 0) 267 goto err_null_smp2p; 268 smp2p->clock_query_irq = ret; 269 270 ret = ipa_smp2p_panic_notifier_register(smp2p); 271 if (ret) 272 goto err_irq_exit; 273 274 if (modem_init) { 275 /* Result will be non-zero (negative for error) */ 276 ret = ipa_smp2p_irq_init(smp2p, pdev, "ipa-setup-ready", 277 ipa_smp2p_modem_setup_ready_isr); 278 if (ret < 0) 279 goto err_notifier_unregister; 280 smp2p->setup_ready_irq = ret; 281 } 282 283 return 0; 284 285 err_notifier_unregister: 286 ipa_smp2p_panic_notifier_unregister(smp2p); 287 err_irq_exit: 288 ipa_smp2p_irq_exit(smp2p, smp2p->clock_query_irq); 289 err_null_smp2p: 290 ipa->smp2p = NULL; 291 mutex_destroy(&smp2p->mutex); 292 kfree(smp2p); 293 294 return ret; 295 } 296 297 void ipa_smp2p_exit(struct ipa *ipa) 298 { 299 struct ipa_smp2p *smp2p = ipa->smp2p; 300 301 if (smp2p->setup_ready_irq) 302 ipa_smp2p_irq_exit(smp2p, smp2p->setup_ready_irq); 303 ipa_smp2p_panic_notifier_unregister(smp2p); 304 ipa_smp2p_irq_exit(smp2p, smp2p->clock_query_irq); 305 /* We won't get notified any more; drop power reference (if any) */ 306 ipa_smp2p_power_release(ipa); 307 ipa->smp2p = NULL; 308 mutex_destroy(&smp2p->mutex); 309 kfree(smp2p); 310 } 311 312 void ipa_smp2p_irq_disable_setup(struct ipa *ipa) 313 { 314 struct ipa_smp2p *smp2p = ipa->smp2p; 315 316 if (!smp2p->setup_ready_irq) 317 return; 318 319 mutex_lock(&smp2p->mutex); 320 321 if (!smp2p->setup_disabled) { 322 disable_irq(smp2p->setup_ready_irq); 323 smp2p->setup_disabled = true; 324 } 325 326 mutex_unlock(&smp2p->mutex); 327 } 328 329 /* Reset state tracking whether we have notified the modem */ 330 void ipa_smp2p_notify_reset(struct ipa *ipa) 331 { 332 struct ipa_smp2p *smp2p = ipa->smp2p; 333 u32 mask; 334 335 if (!smp2p->notified) 336 return; 337 338 ipa_smp2p_power_release(ipa); 339 340 /* Reset the power enabled valid flag */ 341 mask = BIT(smp2p->valid_bit); 342 qcom_smem_state_update_bits(smp2p->valid_state, mask, 0); 343 344 /* Mark the power disabled for good measure... */ 345 mask = BIT(smp2p->enabled_bit); 346 qcom_smem_state_update_bits(smp2p->enabled_state, mask, 0); 347 348 smp2p->notified = false; 349 } 350