1 // SPDX-License-Identifier: GPL-2.0 2 3 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. 4 * Copyright (C) 2019-2020 Linaro Ltd. 5 */ 6 7 #include <linux/types.h> 8 #include <linux/device.h> 9 #include <linux/interrupt.h> 10 #include <linux/notifier.h> 11 #include <linux/soc/qcom/smem.h> 12 #include <linux/soc/qcom/smem_state.h> 13 14 #include "ipa_smp2p.h" 15 #include "ipa.h" 16 #include "ipa_uc.h" 17 #include "ipa_clock.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 the IPA clock 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 the IPA 33 * clock by trigging another SMP2P interrupt to the AP. We communicate 34 * whether the clock is enabled using two SMP2P state bits--one to 35 * indicate the clock state (on or off), and a second to indicate the 36 * clock state bit is valid. The modem will poll the valid bit until it 37 * is set, and at that time records whether the AP has the IPA clock 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 clock 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 clock query 52 * @setup_ready_irq: IPA interrupt triggered by modem to signal GSI ready 53 * @clock_on: Whether IPA clock is on 54 * @notified: Whether modem has been notified of clock state 55 * @disabled: Whether setup ready interrupt handling 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 clock_on; 68 bool notified; 69 bool 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 clock state 76 * @smp2p: SMP2P information 77 * 78 * This is called either when the modem has requested it (by triggering 79 * the modem clock 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 clock is running, 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->clock_on = ipa_clock_get_additional(smp2p->ipa); 93 94 /* Signal whether the clock is enabled */ 95 mask = BIT(smp2p->enabled_bit); 96 value = smp2p->clock_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->clock_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 153 mutex_lock(&smp2p->mutex); 154 155 if (!smp2p->disabled) { 156 int ret; 157 158 ret = ipa_setup(smp2p->ipa); 159 if (ret) 160 dev_err(&smp2p->ipa->pdev->dev, 161 "error %d from ipa_setup()\n", ret); 162 smp2p->disabled = true; 163 } 164 165 mutex_unlock(&smp2p->mutex); 166 167 return IRQ_HANDLED; 168 } 169 170 /* Initialize SMP2P interrupts */ 171 static int ipa_smp2p_irq_init(struct ipa_smp2p *smp2p, const char *name, 172 irq_handler_t handler) 173 { 174 struct device *dev = &smp2p->ipa->pdev->dev; 175 unsigned int irq; 176 int ret; 177 178 ret = platform_get_irq_byname(smp2p->ipa->pdev, name); 179 if (ret <= 0) { 180 dev_err(dev, "DT error %d getting \"%s\" IRQ property\n", 181 ret, name); 182 return ret ? : -EINVAL; 183 } 184 irq = ret; 185 186 ret = request_threaded_irq(irq, NULL, handler, 0, name, smp2p); 187 if (ret) { 188 dev_err(dev, "error %d requesting \"%s\" IRQ\n", ret, name); 189 return ret; 190 } 191 192 return irq; 193 } 194 195 static void ipa_smp2p_irq_exit(struct ipa_smp2p *smp2p, u32 irq) 196 { 197 free_irq(irq, smp2p); 198 } 199 200 /* Drop the clock reference if it was taken in ipa_smp2p_notify() */ 201 static void ipa_smp2p_clock_release(struct ipa *ipa) 202 { 203 if (!ipa->smp2p->clock_on) 204 return; 205 206 ipa_clock_put(ipa); 207 ipa->smp2p->clock_on = false; 208 } 209 210 /* Initialize the IPA SMP2P subsystem */ 211 int ipa_smp2p_init(struct ipa *ipa, bool modem_init) 212 { 213 struct qcom_smem_state *enabled_state; 214 struct device *dev = &ipa->pdev->dev; 215 struct qcom_smem_state *valid_state; 216 struct ipa_smp2p *smp2p; 217 u32 enabled_bit; 218 u32 valid_bit; 219 int ret; 220 221 valid_state = qcom_smem_state_get(dev, "ipa-clock-enabled-valid", 222 &valid_bit); 223 if (IS_ERR(valid_state)) 224 return PTR_ERR(valid_state); 225 if (valid_bit >= 32) /* BITS_PER_U32 */ 226 return -EINVAL; 227 228 enabled_state = qcom_smem_state_get(dev, "ipa-clock-enabled", 229 &enabled_bit); 230 if (IS_ERR(enabled_state)) 231 return PTR_ERR(enabled_state); 232 if (enabled_bit >= 32) /* BITS_PER_U32 */ 233 return -EINVAL; 234 235 smp2p = kzalloc(sizeof(*smp2p), GFP_KERNEL); 236 if (!smp2p) 237 return -ENOMEM; 238 239 smp2p->ipa = ipa; 240 241 /* These fields are needed by the clock query interrupt 242 * handler, so initialize them now. 243 */ 244 mutex_init(&smp2p->mutex); 245 smp2p->valid_state = valid_state; 246 smp2p->valid_bit = valid_bit; 247 smp2p->enabled_state = enabled_state; 248 smp2p->enabled_bit = enabled_bit; 249 250 /* We have enough information saved to handle notifications */ 251 ipa->smp2p = smp2p; 252 253 ret = ipa_smp2p_irq_init(smp2p, "ipa-clock-query", 254 ipa_smp2p_modem_clk_query_isr); 255 if (ret < 0) 256 goto err_null_smp2p; 257 smp2p->clock_query_irq = ret; 258 259 ret = ipa_smp2p_panic_notifier_register(smp2p); 260 if (ret) 261 goto err_irq_exit; 262 263 if (modem_init) { 264 /* Result will be non-zero (negative for error) */ 265 ret = ipa_smp2p_irq_init(smp2p, "ipa-setup-ready", 266 ipa_smp2p_modem_setup_ready_isr); 267 if (ret < 0) 268 goto err_notifier_unregister; 269 smp2p->setup_ready_irq = ret; 270 } 271 272 return 0; 273 274 err_notifier_unregister: 275 ipa_smp2p_panic_notifier_unregister(smp2p); 276 err_irq_exit: 277 ipa_smp2p_irq_exit(smp2p, smp2p->clock_query_irq); 278 err_null_smp2p: 279 ipa->smp2p = NULL; 280 mutex_destroy(&smp2p->mutex); 281 kfree(smp2p); 282 283 return ret; 284 } 285 286 void ipa_smp2p_exit(struct ipa *ipa) 287 { 288 struct ipa_smp2p *smp2p = ipa->smp2p; 289 290 if (smp2p->setup_ready_irq) 291 ipa_smp2p_irq_exit(smp2p, smp2p->setup_ready_irq); 292 ipa_smp2p_panic_notifier_unregister(smp2p); 293 ipa_smp2p_irq_exit(smp2p, smp2p->clock_query_irq); 294 /* We won't get notified any more; drop clock reference (if any) */ 295 ipa_smp2p_clock_release(ipa); 296 ipa->smp2p = NULL; 297 mutex_destroy(&smp2p->mutex); 298 kfree(smp2p); 299 } 300 301 void ipa_smp2p_disable(struct ipa *ipa) 302 { 303 struct ipa_smp2p *smp2p = ipa->smp2p; 304 305 if (!smp2p->setup_ready_irq) 306 return; 307 308 mutex_lock(&smp2p->mutex); 309 310 smp2p->disabled = true; 311 312 mutex_unlock(&smp2p->mutex); 313 } 314 315 /* Reset state tracking whether we have notified the modem */ 316 void ipa_smp2p_notify_reset(struct ipa *ipa) 317 { 318 struct ipa_smp2p *smp2p = ipa->smp2p; 319 u32 mask; 320 321 if (!smp2p->notified) 322 return; 323 324 ipa_smp2p_clock_release(ipa); 325 326 /* Reset the clock enabled valid flag */ 327 mask = BIT(smp2p->valid_bit); 328 qcom_smem_state_update_bits(smp2p->valid_state, mask, 0); 329 330 /* Mark the clock disabled for good measure... */ 331 mask = BIT(smp2p->enabled_bit); 332 qcom_smem_state_update_bits(smp2p->enabled_state, mask, 0); 333 334 smp2p->notified = false; 335 } 336