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

Merge tag 'samsung-pinctrl-4.19' of https://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung into devel

Samsung pinctrl drivers changes for v4.19

1. Add handling of external wakeup interrupts mask inside the pin
controller driver.

Existing solution is spread between the driver and machine code. The
machine code writes the mask but its value is taken from pin
controller driver.

This moves everything into pin controller driver allowing later to
remove the cross-subsystem interaction. Also this is a necessary
step for implementing later Suspend to RAM on ARMv8 Exynos5433.

2. Bring necessary suspend/resume callbacks for Exynos542x and
Exynos5260.

3. Document hidden requirement about one external wakeup interrupts
device node.

4. Minor documentation cleanups.

+113 -10
+9 -2
Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
··· 145 145 146 146 B. External Wakeup Interrupts: For supporting external wakeup interrupts, a 147 147 child node representing the external wakeup interrupt controller should be 148 - included in the pin-controller device node. This child node should include 149 - the following properties. 148 + included in the pin-controller device node. 149 + 150 + Only one pin-controller device node can include external wakeup interrupts 151 + child node (in other words, only one External Wakeup Interrupts 152 + pin-controller is supported). 153 + 154 + This child node should include following properties: 150 155 151 156 - compatible: identifies the type of the external wakeup interrupt controller 152 157 The possible values are: ··· 161 156 found on Samsung S3C2412 and S3C2413 SoCs, 162 157 - samsung,s3c64xx-wakeup-eint: represents wakeup interrupt controller 163 158 found on Samsung S3C64xx SoCs, 159 + - samsung,s5pv210-wakeup-eint: represents wakeup interrupt controller 160 + found on Samsung S5Pv210 SoCs, 164 161 - samsung,exynos4210-wakeup-eint: represents wakeup interrupt controller 165 162 found on Samsung Exynos4210 and S5PC110/S5PV210 SoCs. 166 163 - samsung,exynos7-wakeup-eint: represents wakeup interrupt controller
+1 -1
arch/arm/mach-exynos/suspend.c
··· 272 272 static void exynos_pm_set_wakeup_mask(void) 273 273 { 274 274 /* Set wake-up mask registers */ 275 - pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK); 275 + pmu_raw_writel(exynos_get_eint_wake_mask(), EXYNOS_EINT_WAKEUP_MASK); 276 276 pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK); 277 277 } 278 278
+16
drivers/pinctrl/samsung/pinctrl-exynos-arm.c
··· 616 616 .nr_banks = ARRAY_SIZE(exynos5260_pin_banks0), 617 617 .eint_gpio_init = exynos_eint_gpio_init, 618 618 .eint_wkup_init = exynos_eint_wkup_init, 619 + .suspend = exynos_pinctrl_suspend, 620 + .resume = exynos_pinctrl_resume, 619 621 }, { 620 622 /* pin-controller instance 1 data */ 621 623 .pin_banks = exynos5260_pin_banks1, 622 624 .nr_banks = ARRAY_SIZE(exynos5260_pin_banks1), 623 625 .eint_gpio_init = exynos_eint_gpio_init, 626 + .suspend = exynos_pinctrl_suspend, 627 + .resume = exynos_pinctrl_resume, 624 628 }, { 625 629 /* pin-controller instance 2 data */ 626 630 .pin_banks = exynos5260_pin_banks2, 627 631 .nr_banks = ARRAY_SIZE(exynos5260_pin_banks2), 628 632 .eint_gpio_init = exynos_eint_gpio_init, 633 + .suspend = exynos_pinctrl_suspend, 634 + .resume = exynos_pinctrl_resume, 629 635 }, 630 636 }; 631 637 ··· 848 842 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks0), 849 843 .eint_gpio_init = exynos_eint_gpio_init, 850 844 .eint_wkup_init = exynos_eint_wkup_init, 845 + .suspend = exynos_pinctrl_suspend, 846 + .resume = exynos_pinctrl_resume, 851 847 .retention_data = &exynos5420_retention_data, 852 848 }, { 853 849 /* pin-controller instance 1 data */ 854 850 .pin_banks = exynos5420_pin_banks1, 855 851 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks1), 856 852 .eint_gpio_init = exynos_eint_gpio_init, 853 + .suspend = exynos_pinctrl_suspend, 854 + .resume = exynos_pinctrl_resume, 857 855 .retention_data = &exynos5420_retention_data, 858 856 }, { 859 857 /* pin-controller instance 2 data */ 860 858 .pin_banks = exynos5420_pin_banks2, 861 859 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks2), 862 860 .eint_gpio_init = exynos_eint_gpio_init, 861 + .suspend = exynos_pinctrl_suspend, 862 + .resume = exynos_pinctrl_resume, 863 863 .retention_data = &exynos5420_retention_data, 864 864 }, { 865 865 /* pin-controller instance 3 data */ 866 866 .pin_banks = exynos5420_pin_banks3, 867 867 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks3), 868 868 .eint_gpio_init = exynos_eint_gpio_init, 869 + .suspend = exynos_pinctrl_suspend, 870 + .resume = exynos_pinctrl_resume, 869 871 .retention_data = &exynos5420_retention_data, 870 872 }, { 871 873 /* pin-controller instance 4 data */ 872 874 .pin_banks = exynos5420_pin_banks4, 873 875 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks4), 874 876 .eint_gpio_init = exynos_eint_gpio_init, 877 + .suspend = exynos_pinctrl_suspend, 878 + .resume = exynos_pinctrl_resume, 875 879 .retention_data = &exynos4_audio_retention_data, 876 880 }, 877 881 };
+67 -1
drivers/pinctrl/samsung/pinctrl-exynos.c
··· 25 25 #include <linux/regmap.h> 26 26 #include <linux/err.h> 27 27 #include <linux/soc/samsung/exynos-pmu.h> 28 + #include <linux/soc/samsung/exynos-regs-pmu.h> 28 29 29 30 #include <dt-bindings/pinctrl/samsung.h> 30 31 ··· 38 37 u32 eint_con; 39 38 u32 eint_mask; 40 39 u32 eint_pend; 40 + u32 eint_wake_mask_value; 41 + u32 eint_wake_mask_reg; 41 42 }; 42 43 43 44 static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip) ··· 218 215 .eint_con = EXYNOS_GPIO_ECON_OFFSET, 219 216 .eint_mask = EXYNOS_GPIO_EMASK_OFFSET, 220 217 .eint_pend = EXYNOS_GPIO_EPEND_OFFSET, 218 + /* eint_wake_mask_value not used */ 221 219 }; 222 220 223 221 static int exynos_eint_irq_map(struct irq_domain *h, unsigned int virq, ··· 334 330 335 331 static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on) 336 332 { 333 + struct irq_chip *chip = irq_data_get_irq_chip(irqd); 334 + struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); 337 335 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); 338 336 unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq); 339 337 ··· 345 339 exynos_eint_wake_mask |= bit; 346 340 else 347 341 exynos_eint_wake_mask &= ~bit; 342 + our_chip->eint_wake_mask_value = exynos_eint_wake_mask; 348 343 349 344 return 0; 350 345 } ··· 353 346 /* 354 347 * irq_chip for wakeup interrupts 355 348 */ 349 + static const struct exynos_irq_chip s5pv210_wkup_irq_chip __initconst = { 350 + .chip = { 351 + .name = "s5pv210_wkup_irq_chip", 352 + .irq_unmask = exynos_irq_unmask, 353 + .irq_mask = exynos_irq_mask, 354 + .irq_ack = exynos_irq_ack, 355 + .irq_set_type = exynos_irq_set_type, 356 + .irq_set_wake = exynos_wkup_irq_set_wake, 357 + .irq_request_resources = exynos_irq_request_resources, 358 + .irq_release_resources = exynos_irq_release_resources, 359 + }, 360 + .eint_con = EXYNOS_WKUP_ECON_OFFSET, 361 + .eint_mask = EXYNOS_WKUP_EMASK_OFFSET, 362 + .eint_pend = EXYNOS_WKUP_EPEND_OFFSET, 363 + .eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED, 364 + /* Only difference with exynos4210_wkup_irq_chip: */ 365 + .eint_wake_mask_reg = S5PV210_EINT_WAKEUP_MASK, 366 + }; 367 + 356 368 static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = { 357 369 .chip = { 358 370 .name = "exynos4210_wkup_irq_chip", ··· 386 360 .eint_con = EXYNOS_WKUP_ECON_OFFSET, 387 361 .eint_mask = EXYNOS_WKUP_EMASK_OFFSET, 388 362 .eint_pend = EXYNOS_WKUP_EPEND_OFFSET, 363 + .eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED, 364 + .eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK, 389 365 }; 390 366 391 367 static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = { ··· 404 376 .eint_con = EXYNOS7_WKUP_ECON_OFFSET, 405 377 .eint_mask = EXYNOS7_WKUP_EMASK_OFFSET, 406 378 .eint_pend = EXYNOS7_WKUP_EPEND_OFFSET, 379 + .eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED, 380 + .eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK, 407 381 }; 408 382 409 383 /* list of external wakeup controllers supported */ 410 384 static const struct of_device_id exynos_wkup_irq_ids[] = { 385 + { .compatible = "samsung,s5pv210-wakeup-eint", 386 + .data = &s5pv210_wkup_irq_chip }, 411 387 { .compatible = "samsung,exynos4210-wakeup-eint", 412 388 .data = &exynos4210_wkup_irq_chip }, 413 389 { .compatible = "samsung,exynos7-wakeup-eint", ··· 574 542 return 0; 575 543 } 576 544 545 + static void 546 + exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata, 547 + struct exynos_irq_chip *irq_chip) 548 + { 549 + struct regmap *pmu_regs; 550 + 551 + if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) { 552 + dev_warn(drvdata->dev, 553 + "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n"); 554 + return; 555 + } 556 + 557 + pmu_regs = drvdata->retention_ctrl->priv; 558 + dev_info(drvdata->dev, 559 + "Setting external wakeup interrupt wakeup mask: 0x%x\n", 560 + irq_chip->eint_wake_mask_value); 561 + 562 + regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg, 563 + irq_chip->eint_wake_mask_value); 564 + } 565 + 577 566 static void exynos_pinctrl_suspend_bank( 578 567 struct samsung_pinctrl_drv_data *drvdata, 579 568 struct samsung_pin_bank *bank) ··· 617 564 void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata) 618 565 { 619 566 struct samsung_pin_bank *bank = drvdata->pin_banks; 567 + struct exynos_irq_chip *irq_chip = NULL; 620 568 int i; 621 569 622 - for (i = 0; i < drvdata->nr_banks; ++i, ++bank) 570 + for (i = 0; i < drvdata->nr_banks; ++i, ++bank) { 623 571 if (bank->eint_type == EINT_TYPE_GPIO) 624 572 exynos_pinctrl_suspend_bank(drvdata, bank); 573 + else if (bank->eint_type == EINT_TYPE_WKUP) { 574 + if (!irq_chip) { 575 + irq_chip = bank->irq_chip; 576 + exynos_pinctrl_set_eint_wakeup_mask(drvdata, 577 + irq_chip); 578 + } else if (bank->irq_chip != irq_chip) { 579 + dev_warn(drvdata->dev, 580 + "More than one external wakeup interrupt chip configured (bank: %s). This is not supported by hardware nor by driver.\n", 581 + bank->name); 582 + } 583 + } 584 + } 625 585 } 626 586 627 587 static void exynos_pinctrl_resume_bank(
+11
drivers/pinctrl/samsung/pinctrl-samsung.h
··· 223 223 * interrupts for the controller. 224 224 * @eint_wkup_init: platform specific callback to setup the external wakeup 225 225 * interrupts for the controller. 226 + * @suspend: platform specific suspend callback, executed during pin controller 227 + * device suspend, see samsung_pinctrl_suspend() 228 + * @resume: platform specific resume callback, executed during pin controller 229 + * device suspend, see samsung_pinctrl_resume() 230 + * 231 + * External wakeup interrupts must define at least eint_wkup_init, 232 + * retention_data and suspend in order for proper suspend/resume to work. 226 233 */ 227 234 struct samsung_pin_ctrl { 228 235 const struct samsung_pin_bank_data *pin_banks; ··· 262 255 * @pin_base: starting system wide pin number. 263 256 * @nr_pins: number of pins supported by the controller. 264 257 * @retention_ctrl: retention control runtime data. 258 + * @suspend: platform specific suspend callback, executed during pin controller 259 + * device suspend, see samsung_pinctrl_suspend() 260 + * @resume: platform specific resume callback, executed during pin controller 261 + * device suspend, see samsung_pinctrl_resume() 265 262 */ 266 263 struct samsung_pinctrl_drv_data { 267 264 struct list_head node;
+2 -5
include/dt-bindings/pinctrl/samsung.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 1 2 /* 2 3 * Samsung's Exynos pinctrl bindings 3 4 * 4 5 * Copyright (c) 2016 Samsung Electronics Co., Ltd. 5 6 * http://www.samsung.com 6 7 * Author: Krzysztof Kozlowski <krzk@kernel.org> 7 - * 8 - * This program is free software; you can redistribute it and/or modify 9 - * it under the terms of the GNU General Public License version 2 as 10 - * published by the Free Software Foundation. 11 - */ 8 + */ 12 9 13 10 #ifndef __DT_BINDINGS_PINCTRL_SAMSUNG_H__ 14 11 #define __DT_BINDINGS_PINCTRL_SAMSUNG_H__
+7 -1
include/linux/soc/samsung/exynos-regs-pmu.h
··· 42 42 #define EXYNOS_SWRESET 0x0400 43 43 44 44 #define S5P_WAKEUP_STAT 0x0600 45 - #define S5P_EINT_WAKEUP_MASK 0x0604 45 + /* Value for EXYNOS_EINT_WAKEUP_MASK disabling all external wakeup interrupts */ 46 + #define EXYNOS_EINT_WAKEUP_MASK_DISABLED 0xffffffff 47 + #define EXYNOS_EINT_WAKEUP_MASK 0x0604 46 48 #define S5P_WAKEUP_MASK 0x0608 47 49 #define S5P_WAKEUP_MASK2 0x0614 48 50 ··· 181 179 #define S5P_CORE_LOCAL_PWR_EN 0x3 182 180 #define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3 << 8) 183 181 #define S5P_CORE_AUTOWAKEUP_EN (1 << 31) 182 + 183 + /* Only for S5Pv210 */ 184 + #define S5PV210_EINT_WAKEUP_MASK 0xC004 184 185 185 186 /* Only for EXYNOS4210 */ 186 187 #define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154 ··· 646 641 | EXYNOS5420_KFC_USE_STANDBY_WFI3) 647 642 648 643 /* For EXYNOS5433 */ 644 + #define EXYNOS5433_EINT_WAKEUP_MASK (0x060C) 649 645 #define EXYNOS5433_USBHOST30_PHY_CONTROL (0x0728) 650 646 #define EXYNOS5433_PAD_RETENTION_AUD_OPTION (0x3028) 651 647 #define EXYNOS5433_PAD_RETENTION_MMC2_OPTION (0x30C8)