Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

irqchip/stm32-exti: Split MCU and MPU code

Keep only the code for ARMv7m STM32 MCUs in in stm32-exti.c and split out
the code for ARMv7a & ARMv8a STM32MPxxx MPUs into stm32mp-exti.c

Signed-off-by: Antonio Borneo <antonio.borneo@foss.st.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240620083115.204362-5-antonio.borneo@foss.st.com

authored by

Antonio Borneo and committed by
Thomas Gleixner
350755e2 00f07f97

+751 -667
+2 -1
drivers/irqchip/Kconfig
··· 406 406 407 407 config STM32MP_EXTI 408 408 bool 409 - select STM32_EXTI 409 + select IRQ_DOMAIN 410 + select GENERIC_IRQ_CHIP 410 411 411 412 config STM32_EXTI 412 413 bool
+1
drivers/irqchip/Makefile
··· 84 84 obj-$(CONFIG_LS_EXTIRQ) += irq-ls-extirq.o 85 85 obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o 86 86 obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o irq-aspeed-scu-ic.o 87 + obj-$(CONFIG_STM32MP_EXTI) += irq-stm32mp-exti.o 87 88 obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o 88 89 obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o 89 90 obj-$(CONFIG_IRQ_UNIPHIER_AIDET) += irq-uniphier-aidet.o
+4 -666
drivers/irqchip/irq-stm32-exti.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 3 * Copyright (C) Maxime Coquelin 2015 4 - * Copyright (C) STMicroelectronics 2017 4 + * Copyright (C) STMicroelectronics 2017-2024 5 5 * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com> 6 6 */ 7 7 8 8 #include <linux/bitops.h> 9 - #include <linux/delay.h> 10 - #include <linux/hwspinlock.h> 11 9 #include <linux/interrupt.h> 12 10 #include <linux/io.h> 13 11 #include <linux/irq.h> 14 12 #include <linux/irqchip.h> 15 13 #include <linux/irqchip/chained_irq.h> 16 14 #include <linux/irqdomain.h> 17 - #include <linux/mod_devicetable.h> 18 - #include <linux/module.h> 19 15 #include <linux/of_address.h> 20 16 #include <linux/of_irq.h> 21 - #include <linux/platform_device.h> 22 - #include <linux/pm.h> 23 - 24 - #include <dt-bindings/interrupt-controller/arm-gic.h> 25 17 26 18 #define IRQS_PER_BANK 32 27 - 28 - #define HWSPNLCK_TIMEOUT 1000 /* usec */ 29 - 30 - #define EXTI_EnCIDCFGR(n) (0x180 + (n) * 4) 31 - #define EXTI_HWCFGR1 0x3f0 32 - 33 - /* Register: EXTI_EnCIDCFGR(n) */ 34 - #define EXTI_CIDCFGR_CFEN_MASK BIT(0) 35 - #define EXTI_CIDCFGR_CID_MASK GENMASK(6, 4) 36 - #define EXTI_CIDCFGR_CID_SHIFT 4 37 - 38 - /* Register: EXTI_HWCFGR1 */ 39 - #define EXTI_HWCFGR1_CIDWIDTH_MASK GENMASK(27, 24) 40 - 41 - #define EXTI_CID1 1 42 19 43 20 struct stm32_exti_bank { 44 21 u32 imr_ofst; ··· 24 47 u32 ftsr_ofst; 25 48 u32 swier_ofst; 26 49 u32 rpr_ofst; 27 - u32 fpr_ofst; 28 - u32 trg_ofst; 29 - u32 seccfgr_ofst; 30 50 }; 31 - 32 - #define UNDEF_REG ~0 33 51 34 52 struct stm32_exti_drv_data { 35 53 const struct stm32_exti_bank **exti_banks; ··· 35 63 struct stm32_exti_chip_data { 36 64 struct stm32_exti_host_data *host_data; 37 65 const struct stm32_exti_bank *reg_bank; 38 - struct raw_spinlock rlock; 39 66 u32 wake_active; 40 67 u32 mask_cache; 41 68 u32 rtsr_cache; ··· 47 76 struct device *dev; 48 77 struct stm32_exti_chip_data *chips_data; 49 78 const struct stm32_exti_drv_data *drv_data; 50 - struct hwspinlock *hwlock; 51 - bool dt_has_irqs_desc; /* skip internal desc_irqs array and get it from DT */ 52 79 }; 53 80 54 81 static const struct stm32_exti_bank stm32f4xx_exti_b1 = { ··· 56 87 .ftsr_ofst = 0x0C, 57 88 .swier_ofst = 0x10, 58 89 .rpr_ofst = 0x14, 59 - .fpr_ofst = UNDEF_REG, 60 - .trg_ofst = UNDEF_REG, 61 - .seccfgr_ofst = UNDEF_REG, 62 90 }; 63 91 64 92 static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = { ··· 74 108 .ftsr_ofst = 0x04, 75 109 .swier_ofst = 0x08, 76 110 .rpr_ofst = 0x88, 77 - .fpr_ofst = UNDEF_REG, 78 - .trg_ofst = UNDEF_REG, 79 - .seccfgr_ofst = UNDEF_REG, 80 111 }; 81 112 82 113 static const struct stm32_exti_bank stm32h7xx_exti_b2 = { ··· 83 120 .ftsr_ofst = 0x24, 84 121 .swier_ofst = 0x28, 85 122 .rpr_ofst = 0x98, 86 - .fpr_ofst = UNDEF_REG, 87 - .trg_ofst = UNDEF_REG, 88 - .seccfgr_ofst = UNDEF_REG, 89 123 }; 90 124 91 125 static const struct stm32_exti_bank stm32h7xx_exti_b3 = { ··· 92 132 .ftsr_ofst = 0x44, 93 133 .swier_ofst = 0x48, 94 134 .rpr_ofst = 0xA8, 95 - .fpr_ofst = UNDEF_REG, 96 - .trg_ofst = UNDEF_REG, 97 - .seccfgr_ofst = UNDEF_REG, 98 135 }; 99 136 100 137 static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = { ··· 105 148 .bank_nr = ARRAY_SIZE(stm32h7xx_exti_banks), 106 149 }; 107 150 108 - static const struct stm32_exti_bank stm32mp1_exti_b1 = { 109 - .imr_ofst = 0x80, 110 - .emr_ofst = UNDEF_REG, 111 - .rtsr_ofst = 0x00, 112 - .ftsr_ofst = 0x04, 113 - .swier_ofst = 0x08, 114 - .rpr_ofst = 0x0C, 115 - .fpr_ofst = 0x10, 116 - .trg_ofst = 0x3EC, 117 - .seccfgr_ofst = 0x14, 118 - }; 119 - 120 - static const struct stm32_exti_bank stm32mp1_exti_b2 = { 121 - .imr_ofst = 0x90, 122 - .emr_ofst = UNDEF_REG, 123 - .rtsr_ofst = 0x20, 124 - .ftsr_ofst = 0x24, 125 - .swier_ofst = 0x28, 126 - .rpr_ofst = 0x2C, 127 - .fpr_ofst = 0x30, 128 - .trg_ofst = 0x3E8, 129 - .seccfgr_ofst = 0x34, 130 - }; 131 - 132 - static const struct stm32_exti_bank stm32mp1_exti_b3 = { 133 - .imr_ofst = 0xA0, 134 - .emr_ofst = UNDEF_REG, 135 - .rtsr_ofst = 0x40, 136 - .ftsr_ofst = 0x44, 137 - .swier_ofst = 0x48, 138 - .rpr_ofst = 0x4C, 139 - .fpr_ofst = 0x50, 140 - .trg_ofst = 0x3E4, 141 - .seccfgr_ofst = 0x54, 142 - }; 143 - 144 - static const struct stm32_exti_bank *stm32mp1_exti_banks[] = { 145 - &stm32mp1_exti_b1, 146 - &stm32mp1_exti_b2, 147 - &stm32mp1_exti_b3, 148 - }; 149 - 150 - static struct irq_chip stm32_exti_h_chip; 151 - static struct irq_chip stm32_exti_h_chip_direct; 152 - 153 - #define EXTI_INVALID_IRQ U8_MAX 154 - #define STM32MP1_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp1_exti_banks) * IRQS_PER_BANK) 155 - 156 - /* 157 - * Use some intentionally tricky logic here to initialize the whole array to 158 - * EXTI_INVALID_IRQ, but then override certain fields, requiring us to indicate 159 - * that we "know" that there are overrides in this structure, and we'll need to 160 - * disable that warning from W=1 builds. 161 - */ 162 - __diag_push(); 163 - __diag_ignore_all("-Woverride-init", 164 - "logic to initialize all and then override some is OK"); 165 - 166 - static const u8 stm32mp1_desc_irq[] = { 167 - /* default value */ 168 - [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ, 169 - 170 - [0] = 6, 171 - [1] = 7, 172 - [2] = 8, 173 - [3] = 9, 174 - [4] = 10, 175 - [5] = 23, 176 - [6] = 64, 177 - [7] = 65, 178 - [8] = 66, 179 - [9] = 67, 180 - [10] = 40, 181 - [11] = 42, 182 - [12] = 76, 183 - [13] = 77, 184 - [14] = 121, 185 - [15] = 127, 186 - [16] = 1, 187 - [19] = 3, 188 - [21] = 31, 189 - [22] = 33, 190 - [23] = 72, 191 - [24] = 95, 192 - [25] = 107, 193 - [26] = 37, 194 - [27] = 38, 195 - [28] = 39, 196 - [29] = 71, 197 - [30] = 52, 198 - [31] = 53, 199 - [32] = 82, 200 - [33] = 83, 201 - [46] = 151, 202 - [47] = 93, 203 - [48] = 138, 204 - [50] = 139, 205 - [52] = 140, 206 - [53] = 141, 207 - [54] = 135, 208 - [61] = 100, 209 - [65] = 144, 210 - [68] = 143, 211 - [70] = 62, 212 - [73] = 129, 213 - }; 214 - 215 - static const u8 stm32mp13_desc_irq[] = { 216 - /* default value */ 217 - [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ, 218 - 219 - [0] = 6, 220 - [1] = 7, 221 - [2] = 8, 222 - [3] = 9, 223 - [4] = 10, 224 - [5] = 24, 225 - [6] = 65, 226 - [7] = 66, 227 - [8] = 67, 228 - [9] = 68, 229 - [10] = 41, 230 - [11] = 43, 231 - [12] = 77, 232 - [13] = 78, 233 - [14] = 106, 234 - [15] = 109, 235 - [16] = 1, 236 - [19] = 3, 237 - [21] = 32, 238 - [22] = 34, 239 - [23] = 73, 240 - [24] = 93, 241 - [25] = 114, 242 - [26] = 38, 243 - [27] = 39, 244 - [28] = 40, 245 - [29] = 72, 246 - [30] = 53, 247 - [31] = 54, 248 - [32] = 83, 249 - [33] = 84, 250 - [44] = 96, 251 - [47] = 92, 252 - [48] = 116, 253 - [50] = 117, 254 - [52] = 118, 255 - [53] = 119, 256 - [68] = 63, 257 - [70] = 98, 258 - }; 259 - 260 - __diag_pop(); 261 - 262 - static const struct stm32_exti_drv_data stm32mp1_drv_data = { 263 - .exti_banks = stm32mp1_exti_banks, 264 - .bank_nr = ARRAY_SIZE(stm32mp1_exti_banks), 265 - .desc_irqs = stm32mp1_desc_irq, 266 - }; 267 - 268 - static const struct stm32_exti_drv_data stm32mp13_drv_data = { 269 - .exti_banks = stm32mp1_exti_banks, 270 - .bank_nr = ARRAY_SIZE(stm32mp1_exti_banks), 271 - .desc_irqs = stm32mp13_desc_irq, 272 - }; 273 - 274 151 static unsigned long stm32_exti_pending(struct irq_chip_generic *gc) 275 152 { 276 153 struct stm32_exti_chip_data *chip_data = gc->private; 277 154 const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 278 - unsigned long pending; 279 155 280 - pending = irq_reg_readl(gc, stm32_bank->rpr_ofst); 281 - if (stm32_bank->fpr_ofst != UNDEF_REG) 282 - pending |= irq_reg_readl(gc, stm32_bank->fpr_ofst); 283 - 284 - return pending; 156 + return irq_reg_readl(gc, stm32_bank->rpr_ofst); 285 157 } 286 158 287 159 static void stm32_irq_handler(struct irq_desc *desc) ··· 166 380 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 167 381 struct stm32_exti_chip_data *chip_data = gc->private; 168 382 const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 169 - struct hwspinlock *hwlock = chip_data->host_data->hwlock; 170 383 u32 rtsr, ftsr; 171 384 int err; 172 385 173 386 irq_gc_lock(gc); 174 - 175 - if (hwlock) { 176 - err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT); 177 - if (err) { 178 - pr_err("%s can't get hwspinlock (%d)\n", __func__, err); 179 - goto unlock; 180 - } 181 - } 182 387 183 388 rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst); 184 389 ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst); 185 390 186 391 err = stm32_exti_set_type(d, type, &rtsr, &ftsr); 187 392 if (err) 188 - goto unspinlock; 393 + goto unlock; 189 394 190 395 irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst); 191 396 irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst); 192 397 193 - unspinlock: 194 - if (hwlock) 195 - hwspin_unlock_in_atomic(hwlock); 196 398 unlock: 197 399 irq_gc_unlock(gc); 198 400 ··· 268 494 irq_gc_lock(gc); 269 495 270 496 irq_reg_writel(gc, d->mask, stm32_bank->rpr_ofst); 271 - if (stm32_bank->fpr_ofst != UNDEF_REG) 272 - irq_reg_writel(gc, d->mask, stm32_bank->fpr_ofst); 273 497 274 498 irq_gc_unlock(gc); 275 - } 276 - 277 - /* directly set the target bit without reading first. */ 278 - static inline void stm32_exti_write_bit(struct irq_data *d, u32 reg) 279 - { 280 - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 281 - void __iomem *base = chip_data->host_data->base; 282 - u32 val = BIT(d->hwirq % IRQS_PER_BANK); 283 - 284 - writel_relaxed(val, base + reg); 285 - } 286 - 287 - static inline u32 stm32_exti_set_bit(struct irq_data *d, u32 reg) 288 - { 289 - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 290 - void __iomem *base = chip_data->host_data->base; 291 - u32 val; 292 - 293 - val = readl_relaxed(base + reg); 294 - val |= BIT(d->hwirq % IRQS_PER_BANK); 295 - writel_relaxed(val, base + reg); 296 - 297 - return val; 298 - } 299 - 300 - static inline u32 stm32_exti_clr_bit(struct irq_data *d, u32 reg) 301 - { 302 - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 303 - void __iomem *base = chip_data->host_data->base; 304 - u32 val; 305 - 306 - val = readl_relaxed(base + reg); 307 - val &= ~BIT(d->hwirq % IRQS_PER_BANK); 308 - writel_relaxed(val, base + reg); 309 - 310 - return val; 311 - } 312 - 313 - static void stm32_exti_h_eoi(struct irq_data *d) 314 - { 315 - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 316 - const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 317 - 318 - raw_spin_lock(&chip_data->rlock); 319 - 320 - stm32_exti_write_bit(d, stm32_bank->rpr_ofst); 321 - if (stm32_bank->fpr_ofst != UNDEF_REG) 322 - stm32_exti_write_bit(d, stm32_bank->fpr_ofst); 323 - 324 - raw_spin_unlock(&chip_data->rlock); 325 - 326 - if (d->parent_data->chip) 327 - irq_chip_eoi_parent(d); 328 - } 329 - 330 - static void stm32_exti_h_mask(struct irq_data *d) 331 - { 332 - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 333 - const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 334 - 335 - raw_spin_lock(&chip_data->rlock); 336 - chip_data->mask_cache = stm32_exti_clr_bit(d, stm32_bank->imr_ofst); 337 - raw_spin_unlock(&chip_data->rlock); 338 - 339 - if (d->parent_data->chip) 340 - irq_chip_mask_parent(d); 341 - } 342 - 343 - static void stm32_exti_h_unmask(struct irq_data *d) 344 - { 345 - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 346 - const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 347 - 348 - raw_spin_lock(&chip_data->rlock); 349 - chip_data->mask_cache = stm32_exti_set_bit(d, stm32_bank->imr_ofst); 350 - raw_spin_unlock(&chip_data->rlock); 351 - 352 - if (d->parent_data->chip) 353 - irq_chip_unmask_parent(d); 354 - } 355 - 356 - static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) 357 - { 358 - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 359 - const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 360 - struct hwspinlock *hwlock = chip_data->host_data->hwlock; 361 - void __iomem *base = chip_data->host_data->base; 362 - u32 rtsr, ftsr; 363 - int err; 364 - 365 - raw_spin_lock(&chip_data->rlock); 366 - 367 - if (hwlock) { 368 - err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT); 369 - if (err) { 370 - pr_err("%s can't get hwspinlock (%d)\n", __func__, err); 371 - goto unlock; 372 - } 373 - } 374 - 375 - rtsr = readl_relaxed(base + stm32_bank->rtsr_ofst); 376 - ftsr = readl_relaxed(base + stm32_bank->ftsr_ofst); 377 - 378 - err = stm32_exti_set_type(d, type, &rtsr, &ftsr); 379 - if (err) 380 - goto unspinlock; 381 - 382 - writel_relaxed(rtsr, base + stm32_bank->rtsr_ofst); 383 - writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst); 384 - 385 - unspinlock: 386 - if (hwlock) 387 - hwspin_unlock_in_atomic(hwlock); 388 - unlock: 389 - raw_spin_unlock(&chip_data->rlock); 390 - 391 - return err; 392 - } 393 - 394 - static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on) 395 - { 396 - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 397 - u32 mask = BIT(d->hwirq % IRQS_PER_BANK); 398 - 399 - raw_spin_lock(&chip_data->rlock); 400 - 401 - if (on) 402 - chip_data->wake_active |= mask; 403 - else 404 - chip_data->wake_active &= ~mask; 405 - 406 - raw_spin_unlock(&chip_data->rlock); 407 - 408 - return 0; 409 - } 410 - 411 - static int stm32_exti_h_set_affinity(struct irq_data *d, 412 - const struct cpumask *dest, bool force) 413 - { 414 - if (d->parent_data->chip) 415 - return irq_chip_set_affinity_parent(d, dest, force); 416 - 417 - return IRQ_SET_MASK_OK_DONE; 418 - } 419 - 420 - static int stm32_exti_h_suspend(struct device *dev) 421 - { 422 - struct stm32_exti_host_data *host_data = dev_get_drvdata(dev); 423 - struct stm32_exti_chip_data *chip_data; 424 - int i; 425 - 426 - for (i = 0; i < host_data->drv_data->bank_nr; i++) { 427 - chip_data = &host_data->chips_data[i]; 428 - stm32_chip_suspend(chip_data, chip_data->wake_active); 429 - } 430 - 431 - return 0; 432 - } 433 - 434 - static int stm32_exti_h_resume(struct device *dev) 435 - { 436 - struct stm32_exti_host_data *host_data = dev_get_drvdata(dev); 437 - struct stm32_exti_chip_data *chip_data; 438 - int i; 439 - 440 - for (i = 0; i < host_data->drv_data->bank_nr; i++) { 441 - chip_data = &host_data->chips_data[i]; 442 - stm32_chip_resume(chip_data, chip_data->mask_cache); 443 - } 444 - 445 - return 0; 446 - } 447 - 448 - static int stm32_exti_h_retrigger(struct irq_data *d) 449 - { 450 - struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 451 - const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 452 - void __iomem *base = chip_data->host_data->base; 453 - u32 mask = BIT(d->hwirq % IRQS_PER_BANK); 454 - 455 - writel_relaxed(mask, base + stm32_bank->swier_ofst); 456 - 457 - return 0; 458 - } 459 - 460 - static struct irq_chip stm32_exti_h_chip = { 461 - .name = "stm32-exti-h", 462 - .irq_eoi = stm32_exti_h_eoi, 463 - .irq_mask = stm32_exti_h_mask, 464 - .irq_unmask = stm32_exti_h_unmask, 465 - .irq_retrigger = stm32_exti_h_retrigger, 466 - .irq_set_type = stm32_exti_h_set_type, 467 - .irq_set_wake = stm32_exti_h_set_wake, 468 - .flags = IRQCHIP_MASK_ON_SUSPEND, 469 - .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? stm32_exti_h_set_affinity : NULL, 470 - }; 471 - 472 - static struct irq_chip stm32_exti_h_chip_direct = { 473 - .name = "stm32-exti-h-direct", 474 - .irq_eoi = irq_chip_eoi_parent, 475 - .irq_ack = irq_chip_ack_parent, 476 - .irq_mask = stm32_exti_h_mask, 477 - .irq_unmask = stm32_exti_h_unmask, 478 - .irq_retrigger = irq_chip_retrigger_hierarchy, 479 - .irq_set_type = irq_chip_set_type_parent, 480 - .irq_set_wake = stm32_exti_h_set_wake, 481 - .flags = IRQCHIP_MASK_ON_SUSPEND, 482 - .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent : NULL, 483 - }; 484 - 485 - static int stm32_exti_h_domain_alloc(struct irq_domain *dm, 486 - unsigned int virq, 487 - unsigned int nr_irqs, void *data) 488 - { 489 - struct stm32_exti_host_data *host_data = dm->host_data; 490 - struct stm32_exti_chip_data *chip_data; 491 - u8 desc_irq; 492 - struct irq_fwspec *fwspec = data; 493 - struct irq_fwspec p_fwspec; 494 - irq_hw_number_t hwirq; 495 - int bank; 496 - u32 event_trg; 497 - struct irq_chip *chip; 498 - 499 - hwirq = fwspec->param[0]; 500 - if (hwirq >= host_data->drv_data->bank_nr * IRQS_PER_BANK) 501 - return -EINVAL; 502 - 503 - bank = hwirq / IRQS_PER_BANK; 504 - chip_data = &host_data->chips_data[bank]; 505 - 506 - /* Check if event is reserved (Secure) */ 507 - if (chip_data->event_reserved & BIT(hwirq % IRQS_PER_BANK)) { 508 - dev_err(host_data->dev, "event %lu is reserved, secure\n", hwirq); 509 - return -EPERM; 510 - } 511 - 512 - event_trg = readl_relaxed(host_data->base + chip_data->reg_bank->trg_ofst); 513 - chip = (event_trg & BIT(hwirq % IRQS_PER_BANK)) ? 514 - &stm32_exti_h_chip : &stm32_exti_h_chip_direct; 515 - 516 - irq_domain_set_hwirq_and_chip(dm, virq, hwirq, chip, chip_data); 517 - 518 - if (host_data->dt_has_irqs_desc) { 519 - struct of_phandle_args out_irq; 520 - int ret; 521 - 522 - ret = of_irq_parse_one(host_data->dev->of_node, hwirq, &out_irq); 523 - if (ret) 524 - return ret; 525 - /* we only support one parent, so far */ 526 - if (of_node_to_fwnode(out_irq.np) != dm->parent->fwnode) 527 - return -EINVAL; 528 - 529 - of_phandle_args_to_fwspec(out_irq.np, out_irq.args, 530 - out_irq.args_count, &p_fwspec); 531 - 532 - return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); 533 - } 534 - 535 - if (!host_data->drv_data->desc_irqs) 536 - return -EINVAL; 537 - 538 - desc_irq = host_data->drv_data->desc_irqs[hwirq]; 539 - if (desc_irq != EXTI_INVALID_IRQ) { 540 - p_fwspec.fwnode = dm->parent->fwnode; 541 - p_fwspec.param_count = 3; 542 - p_fwspec.param[0] = GIC_SPI; 543 - p_fwspec.param[1] = desc_irq; 544 - p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; 545 - 546 - return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); 547 - } 548 - 549 - return 0; 550 499 } 551 500 552 501 static struct ··· 319 822 chip_data->host_data = h_data; 320 823 chip_data->reg_bank = stm32_bank; 321 824 322 - raw_spin_lock_init(&chip_data->rlock); 323 - 324 825 /* 325 826 * This IP has no reset, so after hot reboot we should 326 827 * clear registers to avoid residue 327 828 */ 328 829 writel_relaxed(0, base + stm32_bank->imr_ofst); 329 - if (stm32_bank->emr_ofst != UNDEF_REG) 330 - writel_relaxed(0, base + stm32_bank->emr_ofst); 331 - 332 - /* reserve Secure events */ 333 - if (stm32_bank->seccfgr_ofst != UNDEF_REG) 334 - chip_data->event_reserved = readl_relaxed(base + stm32_bank->seccfgr_ofst); 830 + writel_relaxed(0, base + stm32_bank->emr_ofst); 335 831 336 832 pr_info("%pOF: bank%d\n", node, bank_idx); 337 833 ··· 404 914 return ret; 405 915 } 406 916 407 - static const struct irq_domain_ops stm32_exti_h_domain_ops = { 408 - .alloc = stm32_exti_h_domain_alloc, 409 - .free = irq_domain_free_irqs_common, 410 - .xlate = irq_domain_xlate_twocell, 411 - }; 412 - 413 - static void stm32_exti_check_rif(struct stm32_exti_host_data *host_data) 414 - { 415 - unsigned int bank, i, event; 416 - u32 cid, cidcfgr, hwcfgr1; 417 - 418 - /* quit on CID not supported */ 419 - hwcfgr1 = readl_relaxed(host_data->base + EXTI_HWCFGR1); 420 - if ((hwcfgr1 & EXTI_HWCFGR1_CIDWIDTH_MASK) == 0) 421 - return; 422 - 423 - for (bank = 0; bank < host_data->drv_data->bank_nr; bank++) { 424 - for (i = 0; i < IRQS_PER_BANK; i++) { 425 - event = bank * IRQS_PER_BANK + i; 426 - cidcfgr = readl_relaxed(host_data->base + EXTI_EnCIDCFGR(event)); 427 - cid = (cidcfgr & EXTI_CIDCFGR_CID_MASK) >> EXTI_CIDCFGR_CID_SHIFT; 428 - if ((cidcfgr & EXTI_CIDCFGR_CFEN_MASK) && cid != EXTI_CID1) 429 - host_data->chips_data[bank].event_reserved |= BIT(i); 430 - } 431 - } 432 - } 433 - 434 - static void stm32_exti_remove_irq(void *data) 435 - { 436 - struct irq_domain *domain = data; 437 - 438 - irq_domain_remove(domain); 439 - } 440 - 441 - static int stm32_exti_probe(struct platform_device *pdev) 442 - { 443 - int ret, i; 444 - struct device *dev = &pdev->dev; 445 - struct device_node *np = dev->of_node; 446 - struct irq_domain *parent_domain, *domain; 447 - struct stm32_exti_host_data *host_data; 448 - const struct stm32_exti_drv_data *drv_data; 449 - 450 - host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL); 451 - if (!host_data) 452 - return -ENOMEM; 453 - 454 - dev_set_drvdata(dev, host_data); 455 - host_data->dev = dev; 456 - 457 - /* check for optional hwspinlock which may be not available yet */ 458 - ret = of_hwspin_lock_get_id(np, 0); 459 - if (ret == -EPROBE_DEFER) 460 - /* hwspinlock framework not yet ready */ 461 - return ret; 462 - 463 - if (ret >= 0) { 464 - host_data->hwlock = devm_hwspin_lock_request_specific(dev, ret); 465 - if (!host_data->hwlock) { 466 - dev_err(dev, "Failed to request hwspinlock\n"); 467 - return -EINVAL; 468 - } 469 - } else if (ret != -ENOENT) { 470 - /* note: ENOENT is a valid case (means 'no hwspinlock') */ 471 - dev_err(dev, "Failed to get hwspinlock\n"); 472 - return ret; 473 - } 474 - 475 - /* initialize host_data */ 476 - drv_data = of_device_get_match_data(dev); 477 - if (!drv_data) { 478 - dev_err(dev, "no of match data\n"); 479 - return -ENODEV; 480 - } 481 - host_data->drv_data = drv_data; 482 - 483 - host_data->chips_data = devm_kcalloc(dev, drv_data->bank_nr, 484 - sizeof(*host_data->chips_data), 485 - GFP_KERNEL); 486 - if (!host_data->chips_data) 487 - return -ENOMEM; 488 - 489 - host_data->base = devm_platform_ioremap_resource(pdev, 0); 490 - if (IS_ERR(host_data->base)) 491 - return PTR_ERR(host_data->base); 492 - 493 - for (i = 0; i < drv_data->bank_nr; i++) 494 - stm32_exti_chip_init(host_data, i, np); 495 - 496 - stm32_exti_check_rif(host_data); 497 - 498 - parent_domain = irq_find_host(of_irq_find_parent(np)); 499 - if (!parent_domain) { 500 - dev_err(dev, "GIC interrupt-parent not found\n"); 501 - return -EINVAL; 502 - } 503 - 504 - domain = irq_domain_add_hierarchy(parent_domain, 0, 505 - drv_data->bank_nr * IRQS_PER_BANK, 506 - np, &stm32_exti_h_domain_ops, 507 - host_data); 508 - 509 - if (!domain) { 510 - dev_err(dev, "Could not register exti domain\n"); 511 - return -ENOMEM; 512 - } 513 - 514 - ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, domain); 515 - if (ret) 516 - return ret; 517 - 518 - if (of_property_read_bool(np, "interrupts-extended")) 519 - host_data->dt_has_irqs_desc = true; 520 - 521 - return 0; 522 - } 523 - 524 - /* platform driver only for MP1 */ 525 - static const struct of_device_id stm32_exti_ids[] = { 526 - { .compatible = "st,stm32mp1-exti", .data = &stm32mp1_drv_data}, 527 - { .compatible = "st,stm32mp13-exti", .data = &stm32mp13_drv_data}, 528 - {}, 529 - }; 530 - MODULE_DEVICE_TABLE(of, stm32_exti_ids); 531 - 532 - static const struct dev_pm_ops stm32_exti_dev_pm_ops = { 533 - NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_exti_h_suspend, stm32_exti_h_resume) 534 - }; 535 - 536 - static struct platform_driver stm32_exti_driver = { 537 - .probe = stm32_exti_probe, 538 - .driver = { 539 - .name = "stm32_exti", 540 - .of_match_table = stm32_exti_ids, 541 - .pm = &stm32_exti_dev_pm_ops, 542 - }, 543 - }; 544 - 545 - static int __init stm32_exti_arch_init(void) 546 - { 547 - return platform_driver_register(&stm32_exti_driver); 548 - } 549 - 550 - static void __exit stm32_exti_arch_exit(void) 551 - { 552 - return platform_driver_unregister(&stm32_exti_driver); 553 - } 554 - 555 - arch_initcall(stm32_exti_arch_init); 556 - module_exit(stm32_exti_arch_exit); 557 - 558 - /* no platform driver for F4 and H7 */ 559 917 static int __init stm32f4_exti_of_init(struct device_node *np, 560 918 struct device_node *parent) 561 919 {
+744
drivers/irqchip/irq-stm32mp-exti.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) Maxime Coquelin 2015 4 + * Copyright (C) STMicroelectronics 2017-2024 5 + * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com> 6 + */ 7 + 8 + #include <linux/bitops.h> 9 + #include <linux/hwspinlock.h> 10 + #include <linux/interrupt.h> 11 + #include <linux/io.h> 12 + #include <linux/irq.h> 13 + #include <linux/irqchip.h> 14 + #include <linux/irqdomain.h> 15 + #include <linux/mod_devicetable.h> 16 + #include <linux/module.h> 17 + #include <linux/of_address.h> 18 + #include <linux/of_irq.h> 19 + #include <linux/platform_device.h> 20 + #include <linux/pm.h> 21 + 22 + #include <dt-bindings/interrupt-controller/arm-gic.h> 23 + 24 + #define IRQS_PER_BANK 32 25 + 26 + #define HWSPNLCK_TIMEOUT 1000 /* usec */ 27 + 28 + #define EXTI_EnCIDCFGR(n) (0x180 + (n) * 4) 29 + #define EXTI_HWCFGR1 0x3f0 30 + 31 + /* Register: EXTI_EnCIDCFGR(n) */ 32 + #define EXTI_CIDCFGR_CFEN_MASK BIT(0) 33 + #define EXTI_CIDCFGR_CID_MASK GENMASK(6, 4) 34 + #define EXTI_CIDCFGR_CID_SHIFT 4 35 + 36 + /* Register: EXTI_HWCFGR1 */ 37 + #define EXTI_HWCFGR1_CIDWIDTH_MASK GENMASK(27, 24) 38 + 39 + #define EXTI_CID1 1 40 + 41 + struct stm32_exti_bank { 42 + u32 imr_ofst; 43 + u32 rtsr_ofst; 44 + u32 ftsr_ofst; 45 + u32 swier_ofst; 46 + u32 rpr_ofst; 47 + u32 fpr_ofst; 48 + u32 trg_ofst; 49 + u32 seccfgr_ofst; 50 + }; 51 + 52 + struct stm32_exti_drv_data { 53 + const struct stm32_exti_bank **exti_banks; 54 + const u8 *desc_irqs; 55 + u32 bank_nr; 56 + }; 57 + 58 + struct stm32_exti_chip_data { 59 + struct stm32_exti_host_data *host_data; 60 + const struct stm32_exti_bank *reg_bank; 61 + struct raw_spinlock rlock; 62 + u32 wake_active; 63 + u32 mask_cache; 64 + u32 rtsr_cache; 65 + u32 ftsr_cache; 66 + u32 event_reserved; 67 + }; 68 + 69 + struct stm32_exti_host_data { 70 + void __iomem *base; 71 + struct device *dev; 72 + struct stm32_exti_chip_data *chips_data; 73 + const struct stm32_exti_drv_data *drv_data; 74 + struct hwspinlock *hwlock; 75 + bool dt_has_irqs_desc; /* skip internal desc_irqs array and get it from DT */ 76 + }; 77 + 78 + static const struct stm32_exti_bank stm32mp1_exti_b1 = { 79 + .imr_ofst = 0x80, 80 + .rtsr_ofst = 0x00, 81 + .ftsr_ofst = 0x04, 82 + .swier_ofst = 0x08, 83 + .rpr_ofst = 0x0C, 84 + .fpr_ofst = 0x10, 85 + .trg_ofst = 0x3EC, 86 + .seccfgr_ofst = 0x14, 87 + }; 88 + 89 + static const struct stm32_exti_bank stm32mp1_exti_b2 = { 90 + .imr_ofst = 0x90, 91 + .rtsr_ofst = 0x20, 92 + .ftsr_ofst = 0x24, 93 + .swier_ofst = 0x28, 94 + .rpr_ofst = 0x2C, 95 + .fpr_ofst = 0x30, 96 + .trg_ofst = 0x3E8, 97 + .seccfgr_ofst = 0x34, 98 + }; 99 + 100 + static const struct stm32_exti_bank stm32mp1_exti_b3 = { 101 + .imr_ofst = 0xA0, 102 + .rtsr_ofst = 0x40, 103 + .ftsr_ofst = 0x44, 104 + .swier_ofst = 0x48, 105 + .rpr_ofst = 0x4C, 106 + .fpr_ofst = 0x50, 107 + .trg_ofst = 0x3E4, 108 + .seccfgr_ofst = 0x54, 109 + }; 110 + 111 + static const struct stm32_exti_bank *stm32mp1_exti_banks[] = { 112 + &stm32mp1_exti_b1, 113 + &stm32mp1_exti_b2, 114 + &stm32mp1_exti_b3, 115 + }; 116 + 117 + static struct irq_chip stm32_exti_h_chip; 118 + static struct irq_chip stm32_exti_h_chip_direct; 119 + 120 + #define EXTI_INVALID_IRQ U8_MAX 121 + #define STM32MP1_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp1_exti_banks) * IRQS_PER_BANK) 122 + 123 + /* 124 + * Use some intentionally tricky logic here to initialize the whole array to 125 + * EXTI_INVALID_IRQ, but then override certain fields, requiring us to indicate 126 + * that we "know" that there are overrides in this structure, and we'll need to 127 + * disable that warning from W=1 builds. 128 + */ 129 + __diag_push(); 130 + __diag_ignore_all("-Woverride-init", 131 + "logic to initialize all and then override some is OK"); 132 + 133 + static const u8 stm32mp1_desc_irq[] = { 134 + /* default value */ 135 + [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ, 136 + 137 + [0] = 6, 138 + [1] = 7, 139 + [2] = 8, 140 + [3] = 9, 141 + [4] = 10, 142 + [5] = 23, 143 + [6] = 64, 144 + [7] = 65, 145 + [8] = 66, 146 + [9] = 67, 147 + [10] = 40, 148 + [11] = 42, 149 + [12] = 76, 150 + [13] = 77, 151 + [14] = 121, 152 + [15] = 127, 153 + [16] = 1, 154 + [19] = 3, 155 + [21] = 31, 156 + [22] = 33, 157 + [23] = 72, 158 + [24] = 95, 159 + [25] = 107, 160 + [26] = 37, 161 + [27] = 38, 162 + [28] = 39, 163 + [29] = 71, 164 + [30] = 52, 165 + [31] = 53, 166 + [32] = 82, 167 + [33] = 83, 168 + [46] = 151, 169 + [47] = 93, 170 + [48] = 138, 171 + [50] = 139, 172 + [52] = 140, 173 + [53] = 141, 174 + [54] = 135, 175 + [61] = 100, 176 + [65] = 144, 177 + [68] = 143, 178 + [70] = 62, 179 + [73] = 129, 180 + }; 181 + 182 + static const u8 stm32mp13_desc_irq[] = { 183 + /* default value */ 184 + [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ, 185 + 186 + [0] = 6, 187 + [1] = 7, 188 + [2] = 8, 189 + [3] = 9, 190 + [4] = 10, 191 + [5] = 24, 192 + [6] = 65, 193 + [7] = 66, 194 + [8] = 67, 195 + [9] = 68, 196 + [10] = 41, 197 + [11] = 43, 198 + [12] = 77, 199 + [13] = 78, 200 + [14] = 106, 201 + [15] = 109, 202 + [16] = 1, 203 + [19] = 3, 204 + [21] = 32, 205 + [22] = 34, 206 + [23] = 73, 207 + [24] = 93, 208 + [25] = 114, 209 + [26] = 38, 210 + [27] = 39, 211 + [28] = 40, 212 + [29] = 72, 213 + [30] = 53, 214 + [31] = 54, 215 + [32] = 83, 216 + [33] = 84, 217 + [44] = 96, 218 + [47] = 92, 219 + [48] = 116, 220 + [50] = 117, 221 + [52] = 118, 222 + [53] = 119, 223 + [68] = 63, 224 + [70] = 98, 225 + }; 226 + 227 + __diag_pop(); 228 + 229 + static const struct stm32_exti_drv_data stm32mp1_drv_data = { 230 + .exti_banks = stm32mp1_exti_banks, 231 + .bank_nr = ARRAY_SIZE(stm32mp1_exti_banks), 232 + .desc_irqs = stm32mp1_desc_irq, 233 + }; 234 + 235 + static const struct stm32_exti_drv_data stm32mp13_drv_data = { 236 + .exti_banks = stm32mp1_exti_banks, 237 + .bank_nr = ARRAY_SIZE(stm32mp1_exti_banks), 238 + .desc_irqs = stm32mp13_desc_irq, 239 + }; 240 + 241 + static int stm32_exti_set_type(struct irq_data *d, 242 + unsigned int type, u32 *rtsr, u32 *ftsr) 243 + { 244 + u32 mask = BIT(d->hwirq % IRQS_PER_BANK); 245 + 246 + switch (type) { 247 + case IRQ_TYPE_EDGE_RISING: 248 + *rtsr |= mask; 249 + *ftsr &= ~mask; 250 + break; 251 + case IRQ_TYPE_EDGE_FALLING: 252 + *rtsr &= ~mask; 253 + *ftsr |= mask; 254 + break; 255 + case IRQ_TYPE_EDGE_BOTH: 256 + *rtsr |= mask; 257 + *ftsr |= mask; 258 + break; 259 + default: 260 + return -EINVAL; 261 + } 262 + 263 + return 0; 264 + } 265 + 266 + static void stm32_chip_suspend(struct stm32_exti_chip_data *chip_data, 267 + u32 wake_active) 268 + { 269 + const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 270 + void __iomem *base = chip_data->host_data->base; 271 + 272 + /* save rtsr, ftsr registers */ 273 + chip_data->rtsr_cache = readl_relaxed(base + stm32_bank->rtsr_ofst); 274 + chip_data->ftsr_cache = readl_relaxed(base + stm32_bank->ftsr_ofst); 275 + 276 + writel_relaxed(wake_active, base + stm32_bank->imr_ofst); 277 + } 278 + 279 + static void stm32_chip_resume(struct stm32_exti_chip_data *chip_data, 280 + u32 mask_cache) 281 + { 282 + const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 283 + void __iomem *base = chip_data->host_data->base; 284 + 285 + /* restore rtsr, ftsr, registers */ 286 + writel_relaxed(chip_data->rtsr_cache, base + stm32_bank->rtsr_ofst); 287 + writel_relaxed(chip_data->ftsr_cache, base + stm32_bank->ftsr_ofst); 288 + 289 + writel_relaxed(mask_cache, base + stm32_bank->imr_ofst); 290 + } 291 + 292 + /* directly set the target bit without reading first. */ 293 + static inline void stm32_exti_write_bit(struct irq_data *d, u32 reg) 294 + { 295 + struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 296 + void __iomem *base = chip_data->host_data->base; 297 + u32 val = BIT(d->hwirq % IRQS_PER_BANK); 298 + 299 + writel_relaxed(val, base + reg); 300 + } 301 + 302 + static inline u32 stm32_exti_set_bit(struct irq_data *d, u32 reg) 303 + { 304 + struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 305 + void __iomem *base = chip_data->host_data->base; 306 + u32 val; 307 + 308 + val = readl_relaxed(base + reg); 309 + val |= BIT(d->hwirq % IRQS_PER_BANK); 310 + writel_relaxed(val, base + reg); 311 + 312 + return val; 313 + } 314 + 315 + static inline u32 stm32_exti_clr_bit(struct irq_data *d, u32 reg) 316 + { 317 + struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 318 + void __iomem *base = chip_data->host_data->base; 319 + u32 val; 320 + 321 + val = readl_relaxed(base + reg); 322 + val &= ~BIT(d->hwirq % IRQS_PER_BANK); 323 + writel_relaxed(val, base + reg); 324 + 325 + return val; 326 + } 327 + 328 + static void stm32_exti_h_eoi(struct irq_data *d) 329 + { 330 + struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 331 + const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 332 + 333 + raw_spin_lock(&chip_data->rlock); 334 + 335 + stm32_exti_write_bit(d, stm32_bank->rpr_ofst); 336 + stm32_exti_write_bit(d, stm32_bank->fpr_ofst); 337 + 338 + raw_spin_unlock(&chip_data->rlock); 339 + 340 + if (d->parent_data->chip) 341 + irq_chip_eoi_parent(d); 342 + } 343 + 344 + static void stm32_exti_h_mask(struct irq_data *d) 345 + { 346 + struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 347 + const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 348 + 349 + raw_spin_lock(&chip_data->rlock); 350 + chip_data->mask_cache = stm32_exti_clr_bit(d, stm32_bank->imr_ofst); 351 + raw_spin_unlock(&chip_data->rlock); 352 + 353 + if (d->parent_data->chip) 354 + irq_chip_mask_parent(d); 355 + } 356 + 357 + static void stm32_exti_h_unmask(struct irq_data *d) 358 + { 359 + struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 360 + const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 361 + 362 + raw_spin_lock(&chip_data->rlock); 363 + chip_data->mask_cache = stm32_exti_set_bit(d, stm32_bank->imr_ofst); 364 + raw_spin_unlock(&chip_data->rlock); 365 + 366 + if (d->parent_data->chip) 367 + irq_chip_unmask_parent(d); 368 + } 369 + 370 + static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) 371 + { 372 + struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 373 + const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 374 + struct hwspinlock *hwlock = chip_data->host_data->hwlock; 375 + void __iomem *base = chip_data->host_data->base; 376 + u32 rtsr, ftsr; 377 + int err; 378 + 379 + raw_spin_lock(&chip_data->rlock); 380 + 381 + if (hwlock) { 382 + err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT); 383 + if (err) { 384 + pr_err("%s can't get hwspinlock (%d)\n", __func__, err); 385 + goto unlock; 386 + } 387 + } 388 + 389 + rtsr = readl_relaxed(base + stm32_bank->rtsr_ofst); 390 + ftsr = readl_relaxed(base + stm32_bank->ftsr_ofst); 391 + 392 + err = stm32_exti_set_type(d, type, &rtsr, &ftsr); 393 + if (err) 394 + goto unspinlock; 395 + 396 + writel_relaxed(rtsr, base + stm32_bank->rtsr_ofst); 397 + writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst); 398 + 399 + unspinlock: 400 + if (hwlock) 401 + hwspin_unlock_in_atomic(hwlock); 402 + unlock: 403 + raw_spin_unlock(&chip_data->rlock); 404 + 405 + return err; 406 + } 407 + 408 + static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on) 409 + { 410 + struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 411 + u32 mask = BIT(d->hwirq % IRQS_PER_BANK); 412 + 413 + raw_spin_lock(&chip_data->rlock); 414 + 415 + if (on) 416 + chip_data->wake_active |= mask; 417 + else 418 + chip_data->wake_active &= ~mask; 419 + 420 + raw_spin_unlock(&chip_data->rlock); 421 + 422 + return 0; 423 + } 424 + 425 + static int stm32_exti_h_set_affinity(struct irq_data *d, 426 + const struct cpumask *dest, bool force) 427 + { 428 + if (d->parent_data->chip) 429 + return irq_chip_set_affinity_parent(d, dest, force); 430 + 431 + return IRQ_SET_MASK_OK_DONE; 432 + } 433 + 434 + static int stm32_exti_h_suspend(struct device *dev) 435 + { 436 + struct stm32_exti_host_data *host_data = dev_get_drvdata(dev); 437 + struct stm32_exti_chip_data *chip_data; 438 + int i; 439 + 440 + for (i = 0; i < host_data->drv_data->bank_nr; i++) { 441 + chip_data = &host_data->chips_data[i]; 442 + stm32_chip_suspend(chip_data, chip_data->wake_active); 443 + } 444 + 445 + return 0; 446 + } 447 + 448 + static int stm32_exti_h_resume(struct device *dev) 449 + { 450 + struct stm32_exti_host_data *host_data = dev_get_drvdata(dev); 451 + struct stm32_exti_chip_data *chip_data; 452 + int i; 453 + 454 + for (i = 0; i < host_data->drv_data->bank_nr; i++) { 455 + chip_data = &host_data->chips_data[i]; 456 + stm32_chip_resume(chip_data, chip_data->mask_cache); 457 + } 458 + 459 + return 0; 460 + } 461 + 462 + static int stm32_exti_h_retrigger(struct irq_data *d) 463 + { 464 + struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); 465 + const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; 466 + void __iomem *base = chip_data->host_data->base; 467 + u32 mask = BIT(d->hwirq % IRQS_PER_BANK); 468 + 469 + writel_relaxed(mask, base + stm32_bank->swier_ofst); 470 + 471 + return 0; 472 + } 473 + 474 + static struct irq_chip stm32_exti_h_chip = { 475 + .name = "stm32-exti-h", 476 + .irq_eoi = stm32_exti_h_eoi, 477 + .irq_mask = stm32_exti_h_mask, 478 + .irq_unmask = stm32_exti_h_unmask, 479 + .irq_retrigger = stm32_exti_h_retrigger, 480 + .irq_set_type = stm32_exti_h_set_type, 481 + .irq_set_wake = stm32_exti_h_set_wake, 482 + .flags = IRQCHIP_MASK_ON_SUSPEND, 483 + .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? stm32_exti_h_set_affinity : NULL, 484 + }; 485 + 486 + static struct irq_chip stm32_exti_h_chip_direct = { 487 + .name = "stm32-exti-h-direct", 488 + .irq_eoi = irq_chip_eoi_parent, 489 + .irq_ack = irq_chip_ack_parent, 490 + .irq_mask = stm32_exti_h_mask, 491 + .irq_unmask = stm32_exti_h_unmask, 492 + .irq_retrigger = irq_chip_retrigger_hierarchy, 493 + .irq_set_type = irq_chip_set_type_parent, 494 + .irq_set_wake = stm32_exti_h_set_wake, 495 + .flags = IRQCHIP_MASK_ON_SUSPEND, 496 + .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent : NULL, 497 + }; 498 + 499 + static int stm32_exti_h_domain_alloc(struct irq_domain *dm, 500 + unsigned int virq, 501 + unsigned int nr_irqs, void *data) 502 + { 503 + struct stm32_exti_host_data *host_data = dm->host_data; 504 + struct stm32_exti_chip_data *chip_data; 505 + u8 desc_irq; 506 + struct irq_fwspec *fwspec = data; 507 + struct irq_fwspec p_fwspec; 508 + irq_hw_number_t hwirq; 509 + int bank; 510 + u32 event_trg; 511 + struct irq_chip *chip; 512 + 513 + hwirq = fwspec->param[0]; 514 + if (hwirq >= host_data->drv_data->bank_nr * IRQS_PER_BANK) 515 + return -EINVAL; 516 + 517 + bank = hwirq / IRQS_PER_BANK; 518 + chip_data = &host_data->chips_data[bank]; 519 + 520 + /* Check if event is reserved (Secure) */ 521 + if (chip_data->event_reserved & BIT(hwirq % IRQS_PER_BANK)) { 522 + dev_err(host_data->dev, "event %lu is reserved, secure\n", hwirq); 523 + return -EPERM; 524 + } 525 + 526 + event_trg = readl_relaxed(host_data->base + chip_data->reg_bank->trg_ofst); 527 + chip = (event_trg & BIT(hwirq % IRQS_PER_BANK)) ? 528 + &stm32_exti_h_chip : &stm32_exti_h_chip_direct; 529 + 530 + irq_domain_set_hwirq_and_chip(dm, virq, hwirq, chip, chip_data); 531 + 532 + if (host_data->dt_has_irqs_desc) { 533 + struct of_phandle_args out_irq; 534 + int ret; 535 + 536 + ret = of_irq_parse_one(host_data->dev->of_node, hwirq, &out_irq); 537 + if (ret) 538 + return ret; 539 + /* we only support one parent, so far */ 540 + if (of_node_to_fwnode(out_irq.np) != dm->parent->fwnode) 541 + return -EINVAL; 542 + 543 + of_phandle_args_to_fwspec(out_irq.np, out_irq.args, 544 + out_irq.args_count, &p_fwspec); 545 + 546 + return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); 547 + } 548 + 549 + if (!host_data->drv_data->desc_irqs) 550 + return -EINVAL; 551 + 552 + desc_irq = host_data->drv_data->desc_irqs[hwirq]; 553 + if (desc_irq != EXTI_INVALID_IRQ) { 554 + p_fwspec.fwnode = dm->parent->fwnode; 555 + p_fwspec.param_count = 3; 556 + p_fwspec.param[0] = GIC_SPI; 557 + p_fwspec.param[1] = desc_irq; 558 + p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; 559 + 560 + return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); 561 + } 562 + 563 + return 0; 564 + } 565 + 566 + static struct 567 + stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data, 568 + u32 bank_idx, 569 + struct device_node *node) 570 + { 571 + const struct stm32_exti_bank *stm32_bank; 572 + struct stm32_exti_chip_data *chip_data; 573 + void __iomem *base = h_data->base; 574 + 575 + stm32_bank = h_data->drv_data->exti_banks[bank_idx]; 576 + chip_data = &h_data->chips_data[bank_idx]; 577 + chip_data->host_data = h_data; 578 + chip_data->reg_bank = stm32_bank; 579 + 580 + raw_spin_lock_init(&chip_data->rlock); 581 + 582 + /* 583 + * This IP has no reset, so after hot reboot we should 584 + * clear registers to avoid residue 585 + */ 586 + writel_relaxed(0, base + stm32_bank->imr_ofst); 587 + 588 + /* reserve Secure events */ 589 + chip_data->event_reserved = readl_relaxed(base + stm32_bank->seccfgr_ofst); 590 + 591 + pr_info("%pOF: bank%d\n", node, bank_idx); 592 + 593 + return chip_data; 594 + } 595 + 596 + static const struct irq_domain_ops stm32_exti_h_domain_ops = { 597 + .alloc = stm32_exti_h_domain_alloc, 598 + .free = irq_domain_free_irqs_common, 599 + .xlate = irq_domain_xlate_twocell, 600 + }; 601 + 602 + static void stm32_exti_check_rif(struct stm32_exti_host_data *host_data) 603 + { 604 + unsigned int bank, i, event; 605 + u32 cid, cidcfgr, hwcfgr1; 606 + 607 + /* quit on CID not supported */ 608 + hwcfgr1 = readl_relaxed(host_data->base + EXTI_HWCFGR1); 609 + if ((hwcfgr1 & EXTI_HWCFGR1_CIDWIDTH_MASK) == 0) 610 + return; 611 + 612 + for (bank = 0; bank < host_data->drv_data->bank_nr; bank++) { 613 + for (i = 0; i < IRQS_PER_BANK; i++) { 614 + event = bank * IRQS_PER_BANK + i; 615 + cidcfgr = readl_relaxed(host_data->base + EXTI_EnCIDCFGR(event)); 616 + cid = (cidcfgr & EXTI_CIDCFGR_CID_MASK) >> EXTI_CIDCFGR_CID_SHIFT; 617 + if ((cidcfgr & EXTI_CIDCFGR_CFEN_MASK) && cid != EXTI_CID1) 618 + host_data->chips_data[bank].event_reserved |= BIT(i); 619 + } 620 + } 621 + } 622 + 623 + static void stm32_exti_remove_irq(void *data) 624 + { 625 + struct irq_domain *domain = data; 626 + 627 + irq_domain_remove(domain); 628 + } 629 + 630 + static int stm32_exti_probe(struct platform_device *pdev) 631 + { 632 + int ret, i; 633 + struct device *dev = &pdev->dev; 634 + struct device_node *np = dev->of_node; 635 + struct irq_domain *parent_domain, *domain; 636 + struct stm32_exti_host_data *host_data; 637 + const struct stm32_exti_drv_data *drv_data; 638 + 639 + host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL); 640 + if (!host_data) 641 + return -ENOMEM; 642 + 643 + dev_set_drvdata(dev, host_data); 644 + host_data->dev = dev; 645 + 646 + /* check for optional hwspinlock which may be not available yet */ 647 + ret = of_hwspin_lock_get_id(np, 0); 648 + if (ret == -EPROBE_DEFER) 649 + /* hwspinlock framework not yet ready */ 650 + return ret; 651 + 652 + if (ret >= 0) { 653 + host_data->hwlock = devm_hwspin_lock_request_specific(dev, ret); 654 + if (!host_data->hwlock) { 655 + dev_err(dev, "Failed to request hwspinlock\n"); 656 + return -EINVAL; 657 + } 658 + } else if (ret != -ENOENT) { 659 + /* note: ENOENT is a valid case (means 'no hwspinlock') */ 660 + dev_err(dev, "Failed to get hwspinlock\n"); 661 + return ret; 662 + } 663 + 664 + /* initialize host_data */ 665 + drv_data = of_device_get_match_data(dev); 666 + if (!drv_data) { 667 + dev_err(dev, "no of match data\n"); 668 + return -ENODEV; 669 + } 670 + host_data->drv_data = drv_data; 671 + 672 + host_data->chips_data = devm_kcalloc(dev, drv_data->bank_nr, 673 + sizeof(*host_data->chips_data), 674 + GFP_KERNEL); 675 + if (!host_data->chips_data) 676 + return -ENOMEM; 677 + 678 + host_data->base = devm_platform_ioremap_resource(pdev, 0); 679 + if (IS_ERR(host_data->base)) 680 + return PTR_ERR(host_data->base); 681 + 682 + for (i = 0; i < drv_data->bank_nr; i++) 683 + stm32_exti_chip_init(host_data, i, np); 684 + 685 + stm32_exti_check_rif(host_data); 686 + 687 + parent_domain = irq_find_host(of_irq_find_parent(np)); 688 + if (!parent_domain) { 689 + dev_err(dev, "GIC interrupt-parent not found\n"); 690 + return -EINVAL; 691 + } 692 + 693 + domain = irq_domain_add_hierarchy(parent_domain, 0, 694 + drv_data->bank_nr * IRQS_PER_BANK, 695 + np, &stm32_exti_h_domain_ops, 696 + host_data); 697 + 698 + if (!domain) { 699 + dev_err(dev, "Could not register exti domain\n"); 700 + return -ENOMEM; 701 + } 702 + 703 + ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, domain); 704 + if (ret) 705 + return ret; 706 + 707 + if (of_property_read_bool(np, "interrupts-extended")) 708 + host_data->dt_has_irqs_desc = true; 709 + 710 + return 0; 711 + } 712 + 713 + static const struct of_device_id stm32_exti_ids[] = { 714 + { .compatible = "st,stm32mp1-exti", .data = &stm32mp1_drv_data}, 715 + { .compatible = "st,stm32mp13-exti", .data = &stm32mp13_drv_data}, 716 + {}, 717 + }; 718 + MODULE_DEVICE_TABLE(of, stm32_exti_ids); 719 + 720 + static const struct dev_pm_ops stm32_exti_dev_pm_ops = { 721 + NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_exti_h_suspend, stm32_exti_h_resume) 722 + }; 723 + 724 + static struct platform_driver stm32_exti_driver = { 725 + .probe = stm32_exti_probe, 726 + .driver = { 727 + .name = "stm32_exti", 728 + .of_match_table = stm32_exti_ids, 729 + .pm = &stm32_exti_dev_pm_ops, 730 + }, 731 + }; 732 + 733 + static int __init stm32_exti_arch_init(void) 734 + { 735 + return platform_driver_register(&stm32_exti_driver); 736 + } 737 + 738 + static void __exit stm32_exti_arch_exit(void) 739 + { 740 + return platform_driver_unregister(&stm32_exti_driver); 741 + } 742 + 743 + arch_initcall(stm32_exti_arch_init); 744 + module_exit(stm32_exti_arch_exit);