| .. | .. |
|---|
| 38 | 38 | u32 eint_con; |
|---|
| 39 | 39 | u32 eint_mask; |
|---|
| 40 | 40 | u32 eint_pend; |
|---|
| 41 | | - u32 eint_wake_mask_value; |
|---|
| 41 | + u32 *eint_wake_mask_value; |
|---|
| 42 | 42 | u32 eint_wake_mask_reg; |
|---|
| 43 | 43 | void (*set_eint_wakeup_mask)(struct samsung_pinctrl_drv_data *drvdata, |
|---|
| 44 | 44 | struct exynos_irq_chip *irq_chip); |
|---|
| .. | .. |
|---|
| 207 | 207 | /* |
|---|
| 208 | 208 | * irq_chip for gpio interrupts. |
|---|
| 209 | 209 | */ |
|---|
| 210 | | -static struct exynos_irq_chip exynos_gpio_irq_chip = { |
|---|
| 210 | +static const struct exynos_irq_chip exynos_gpio_irq_chip __initconst = { |
|---|
| 211 | 211 | .chip = { |
|---|
| 212 | 212 | .name = "exynos_gpio_irq_chip", |
|---|
| 213 | 213 | .irq_unmask = exynos_irq_unmask, |
|---|
| .. | .. |
|---|
| 274 | 274 | * exynos_eint_gpio_init() - setup handling of external gpio interrupts. |
|---|
| 275 | 275 | * @d: driver data of samsung pinctrl driver. |
|---|
| 276 | 276 | */ |
|---|
| 277 | | -int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) |
|---|
| 277 | +__init int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) |
|---|
| 278 | 278 | { |
|---|
| 279 | 279 | struct samsung_pin_bank *bank; |
|---|
| 280 | 280 | struct device *dev = d->dev; |
|---|
| .. | .. |
|---|
| 297 | 297 | for (i = 0; i < d->nr_banks; ++i, ++bank) { |
|---|
| 298 | 298 | if (bank->eint_type != EINT_TYPE_GPIO) |
|---|
| 299 | 299 | continue; |
|---|
| 300 | + |
|---|
| 301 | + bank->irq_chip = devm_kmemdup(dev, &exynos_gpio_irq_chip, |
|---|
| 302 | + sizeof(*bank->irq_chip), GFP_KERNEL); |
|---|
| 303 | + if (!bank->irq_chip) { |
|---|
| 304 | + ret = -ENOMEM; |
|---|
| 305 | + goto err_domains; |
|---|
| 306 | + } |
|---|
| 307 | + bank->irq_chip->chip.name = bank->name; |
|---|
| 308 | + |
|---|
| 300 | 309 | bank->irq_domain = irq_domain_add_linear(bank->of_node, |
|---|
| 301 | 310 | bank->nr_pins, &exynos_eint_irqd_ops, bank); |
|---|
| 302 | 311 | if (!bank->irq_domain) { |
|---|
| .. | .. |
|---|
| 313 | 322 | goto err_domains; |
|---|
| 314 | 323 | } |
|---|
| 315 | 324 | |
|---|
| 316 | | - bank->irq_chip = &exynos_gpio_irq_chip; |
|---|
| 317 | 325 | } |
|---|
| 318 | 326 | |
|---|
| 319 | 327 | return 0; |
|---|
| .. | .. |
|---|
| 328 | 336 | return ret; |
|---|
| 329 | 337 | } |
|---|
| 330 | 338 | |
|---|
| 331 | | -static u32 exynos_eint_wake_mask = 0xffffffff; |
|---|
| 332 | | - |
|---|
| 333 | | -u32 exynos_get_eint_wake_mask(void) |
|---|
| 334 | | -{ |
|---|
| 335 | | - return exynos_eint_wake_mask; |
|---|
| 336 | | -} |
|---|
| 337 | | - |
|---|
| 338 | 339 | static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on) |
|---|
| 339 | 340 | { |
|---|
| 340 | 341 | struct irq_chip *chip = irq_data_get_irq_chip(irqd); |
|---|
| .. | .. |
|---|
| 345 | 346 | pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq); |
|---|
| 346 | 347 | |
|---|
| 347 | 348 | if (!on) |
|---|
| 348 | | - exynos_eint_wake_mask |= bit; |
|---|
| 349 | + *our_chip->eint_wake_mask_value |= bit; |
|---|
| 349 | 350 | else |
|---|
| 350 | | - exynos_eint_wake_mask &= ~bit; |
|---|
| 351 | | - our_chip->eint_wake_mask_value = exynos_eint_wake_mask; |
|---|
| 351 | + *our_chip->eint_wake_mask_value &= ~bit; |
|---|
| 352 | 352 | |
|---|
| 353 | 353 | return 0; |
|---|
| 354 | 354 | } |
|---|
| .. | .. |
|---|
| 368 | 368 | pmu_regs = drvdata->retention_ctrl->priv; |
|---|
| 369 | 369 | dev_info(drvdata->dev, |
|---|
| 370 | 370 | "Setting external wakeup interrupt mask: 0x%x\n", |
|---|
| 371 | | - irq_chip->eint_wake_mask_value); |
|---|
| 371 | + *irq_chip->eint_wake_mask_value); |
|---|
| 372 | 372 | |
|---|
| 373 | 373 | regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg, |
|---|
| 374 | | - irq_chip->eint_wake_mask_value); |
|---|
| 374 | + *irq_chip->eint_wake_mask_value); |
|---|
| 375 | 375 | } |
|---|
| 376 | 376 | |
|---|
| 377 | 377 | static void |
|---|
| .. | .. |
|---|
| 390 | 390 | |
|---|
| 391 | 391 | clk_base = (void __iomem *) drvdata->retention_ctrl->priv; |
|---|
| 392 | 392 | |
|---|
| 393 | | - __raw_writel(irq_chip->eint_wake_mask_value, |
|---|
| 393 | + __raw_writel(*irq_chip->eint_wake_mask_value, |
|---|
| 394 | 394 | clk_base + irq_chip->eint_wake_mask_reg); |
|---|
| 395 | 395 | } |
|---|
| 396 | 396 | |
|---|
| 397 | +static u32 eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED; |
|---|
| 397 | 398 | /* |
|---|
| 398 | 399 | * irq_chip for wakeup interrupts |
|---|
| 399 | 400 | */ |
|---|
| .. | .. |
|---|
| 411 | 412 | .eint_con = EXYNOS_WKUP_ECON_OFFSET, |
|---|
| 412 | 413 | .eint_mask = EXYNOS_WKUP_EMASK_OFFSET, |
|---|
| 413 | 414 | .eint_pend = EXYNOS_WKUP_EPEND_OFFSET, |
|---|
| 414 | | - .eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED, |
|---|
| 415 | + .eint_wake_mask_value = &eint_wake_mask_value, |
|---|
| 415 | 416 | /* Only differences with exynos4210_wkup_irq_chip: */ |
|---|
| 416 | 417 | .eint_wake_mask_reg = S5PV210_EINT_WAKEUP_MASK, |
|---|
| 417 | 418 | .set_eint_wakeup_mask = s5pv210_pinctrl_set_eint_wakeup_mask, |
|---|
| .. | .. |
|---|
| 431 | 432 | .eint_con = EXYNOS_WKUP_ECON_OFFSET, |
|---|
| 432 | 433 | .eint_mask = EXYNOS_WKUP_EMASK_OFFSET, |
|---|
| 433 | 434 | .eint_pend = EXYNOS_WKUP_EPEND_OFFSET, |
|---|
| 434 | | - .eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED, |
|---|
| 435 | + .eint_wake_mask_value = &eint_wake_mask_value, |
|---|
| 435 | 436 | .eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK, |
|---|
| 436 | 437 | .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask, |
|---|
| 437 | 438 | }; |
|---|
| .. | .. |
|---|
| 450 | 451 | .eint_con = EXYNOS7_WKUP_ECON_OFFSET, |
|---|
| 451 | 452 | .eint_mask = EXYNOS7_WKUP_EMASK_OFFSET, |
|---|
| 452 | 453 | .eint_pend = EXYNOS7_WKUP_EPEND_OFFSET, |
|---|
| 453 | | - .eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED, |
|---|
| 454 | + .eint_wake_mask_value = &eint_wake_mask_value, |
|---|
| 454 | 455 | .eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK, |
|---|
| 455 | 456 | .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask, |
|---|
| 456 | 457 | }; |
|---|
| .. | .. |
|---|
| 521 | 522 | * exynos_eint_wkup_init() - setup handling of external wakeup interrupts. |
|---|
| 522 | 523 | * @d: driver data of samsung pinctrl driver. |
|---|
| 523 | 524 | */ |
|---|
| 524 | | -int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) |
|---|
| 525 | +__init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) |
|---|
| 525 | 526 | { |
|---|
| 526 | 527 | struct device *dev = d->dev; |
|---|
| 527 | 528 | struct device_node *wkup_np = NULL; |
|---|
| .. | .. |
|---|
| 529 | 530 | struct samsung_pin_bank *bank; |
|---|
| 530 | 531 | struct exynos_weint_data *weint_data; |
|---|
| 531 | 532 | struct exynos_muxed_weint_data *muxed_data; |
|---|
| 532 | | - struct exynos_irq_chip *irq_chip; |
|---|
| 533 | + const struct exynos_irq_chip *irq_chip; |
|---|
| 533 | 534 | unsigned int muxed_banks = 0; |
|---|
| 534 | 535 | unsigned int i; |
|---|
| 535 | 536 | int idx, irq; |
|---|
| .. | .. |
|---|
| 539 | 540 | |
|---|
| 540 | 541 | match = of_match_node(exynos_wkup_irq_ids, np); |
|---|
| 541 | 542 | if (match) { |
|---|
| 542 | | - irq_chip = kmemdup(match->data, |
|---|
| 543 | | - sizeof(*irq_chip), GFP_KERNEL); |
|---|
| 544 | | - if (!irq_chip) { |
|---|
| 545 | | - of_node_put(np); |
|---|
| 546 | | - return -ENOMEM; |
|---|
| 547 | | - } |
|---|
| 543 | + irq_chip = match->data; |
|---|
| 548 | 544 | wkup_np = np; |
|---|
| 549 | 545 | break; |
|---|
| 550 | 546 | } |
|---|
| .. | .. |
|---|
| 557 | 553 | if (bank->eint_type != EINT_TYPE_WKUP) |
|---|
| 558 | 554 | continue; |
|---|
| 559 | 555 | |
|---|
| 556 | + bank->irq_chip = devm_kmemdup(dev, irq_chip, sizeof(*irq_chip), |
|---|
| 557 | + GFP_KERNEL); |
|---|
| 558 | + if (!bank->irq_chip) { |
|---|
| 559 | + of_node_put(wkup_np); |
|---|
| 560 | + return -ENOMEM; |
|---|
| 561 | + } |
|---|
| 562 | + bank->irq_chip->chip.name = bank->name; |
|---|
| 563 | + |
|---|
| 560 | 564 | bank->irq_domain = irq_domain_add_linear(bank->of_node, |
|---|
| 561 | 565 | bank->nr_pins, &exynos_eint_irqd_ops, bank); |
|---|
| 562 | 566 | if (!bank->irq_domain) { |
|---|
| .. | .. |
|---|
| 564 | 568 | of_node_put(wkup_np); |
|---|
| 565 | 569 | return -ENXIO; |
|---|
| 566 | 570 | } |
|---|
| 567 | | - |
|---|
| 568 | | - bank->irq_chip = irq_chip; |
|---|
| 569 | 571 | |
|---|
| 570 | 572 | if (!of_find_property(bank->of_node, "interrupts", NULL)) { |
|---|
| 571 | 573 | bank->eint_type = EINT_TYPE_WKUP_MUX; |
|---|
| .. | .. |
|---|
| 665 | 667 | irq_chip = bank->irq_chip; |
|---|
| 666 | 668 | irq_chip->set_eint_wakeup_mask(drvdata, |
|---|
| 667 | 669 | irq_chip); |
|---|
| 668 | | - } else if (bank->irq_chip != irq_chip) { |
|---|
| 669 | | - dev_warn(drvdata->dev, |
|---|
| 670 | | - "More than one external wakeup interrupt chip configured (bank: %s). This is not supported by hardware nor by driver.\n", |
|---|
| 671 | | - bank->name); |
|---|
| 672 | 670 | } |
|---|
| 673 | 671 | } |
|---|
| 674 | 672 | } |
|---|