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

pinctrl: lpc18xx: add nxp,gpio-pin-interrupt property

Add support for setting up GPIO pin interrupts in the lpc18xx pinctrl
driver. The LPC18xx SCU contain two registers that sets up the signal
routing to the GPIO pin interrupt (PINT) block. The routing uses the
GPIO namespace and not the pin namespace so a lookup is preformed on
the pin.

Routing configuration is done in the device tree by using the new
nxp,gpio-pin-interrupt property. This property takes single parameter
which sets the PINT hwirq for the GPIO.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Joachim Eastwood and committed by
Linus Walleij
81825b11 b18537cd

+137 -6
+137 -6
drivers/pinctrl/pinctrl-lpc18xx.c
··· 49 49 50 50 #define LPC18XX_SCU_FUNC_PER_PIN 8 51 51 52 + /* LPC18XX SCU pin interrupt select registers */ 53 + #define LPC18XX_SCU_PINTSEL0 0xe00 54 + #define LPC18XX_SCU_PINTSEL1 0xe04 55 + #define LPC18XX_SCU_PINTSEL_VAL_MASK 0xff 56 + #define LPC18XX_SCU_PINTSEL_PORT_SHIFT 5 57 + #define LPC18XX_SCU_IRQ_PER_PINTSEL 4 58 + #define LPC18XX_GPIO_PINS_PER_PORT 32 59 + #define LPC18XX_GPIO_PIN_INT_MAX 8 60 + 61 + #define LPC18XX_SCU_PINTSEL_VAL(val, n) \ 62 + ((val) << (((n) % LPC18XX_SCU_IRQ_PER_PINTSEL) * 8)) 63 + 52 64 /* LPC18xx pin types */ 53 65 enum { 54 66 TYPE_ND, /* Normal-drive */ ··· 630 618 LPC18XX_PIN(i2c0_sda, PIN_I2C0_SDA), 631 619 }; 632 620 621 + /** 622 + * enum lpc18xx_pin_config_param - possible pin configuration parameters 623 + * @PIN_CONFIG_GPIO_PIN_INT: route gpio to the gpio pin interrupt 624 + * controller. 625 + */ 626 + enum lpc18xx_pin_config_param { 627 + PIN_CONFIG_GPIO_PIN_INT = PIN_CONFIG_END + 1, 628 + }; 629 + 630 + static const struct pinconf_generic_params lpc18xx_params[] = { 631 + {"nxp,gpio-pin-interrupt", PIN_CONFIG_GPIO_PIN_INT, 0}, 632 + }; 633 + 634 + #ifdef CONFIG_DEBUG_FS 635 + static const struct pin_config_item lpc18xx_conf_items[ARRAY_SIZE(lpc18xx_params)] = { 636 + PCONFDUMP(PIN_CONFIG_GPIO_PIN_INT, "gpio pin int", NULL, true), 637 + }; 638 + #endif 639 + 633 640 static int lpc18xx_pconf_get_usb1(enum pin_config_param param, int *arg, u32 reg) 634 641 { 635 642 switch (param) { ··· 724 693 return 0; 725 694 } 726 695 727 - static int lpc18xx_pconf_get_pin(enum pin_config_param param, int *arg, u32 reg, 696 + static int lpc18xx_pin_to_gpio(struct pinctrl_dev *pctldev, unsigned pin) 697 + { 698 + struct pinctrl_gpio_range *range; 699 + 700 + range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); 701 + if (!range) 702 + return -EINVAL; 703 + 704 + return pin - range->pin_base + range->base; 705 + } 706 + 707 + static int lpc18xx_get_pintsel(void __iomem *addr, u32 val, int *arg) 708 + { 709 + u32 reg_val; 710 + int i; 711 + 712 + reg_val = readl(addr); 713 + for (i = 0; i < LPC18XX_SCU_IRQ_PER_PINTSEL; i++) { 714 + if ((reg_val & LPC18XX_SCU_PINTSEL_VAL_MASK) == val) 715 + return 0; 716 + 717 + reg_val >>= BITS_PER_BYTE; 718 + *arg += 1; 719 + } 720 + 721 + return -EINVAL; 722 + } 723 + 724 + static u32 lpc18xx_gpio_to_pintsel_val(int gpio) 725 + { 726 + unsigned int gpio_port, gpio_pin; 727 + 728 + gpio_port = gpio / LPC18XX_GPIO_PINS_PER_PORT; 729 + gpio_pin = gpio % LPC18XX_GPIO_PINS_PER_PORT; 730 + 731 + return gpio_pin | (gpio_port << LPC18XX_SCU_PINTSEL_PORT_SHIFT); 732 + } 733 + 734 + static int lpc18xx_pconf_get_gpio_pin_int(struct pinctrl_dev *pctldev, 735 + int *arg, unsigned pin) 736 + { 737 + struct lpc18xx_scu_data *scu = pinctrl_dev_get_drvdata(pctldev); 738 + int gpio, ret; 739 + u32 val; 740 + 741 + gpio = lpc18xx_pin_to_gpio(pctldev, pin); 742 + if (gpio < 0) 743 + return -ENOTSUPP; 744 + 745 + val = lpc18xx_gpio_to_pintsel_val(gpio); 746 + 747 + /* 748 + * Check if this pin has been enabled as a interrupt in any of the two 749 + * PINTSEL registers. *arg indicates which interrupt number (0-7). 750 + */ 751 + *arg = 0; 752 + ret = lpc18xx_get_pintsel(scu->base + LPC18XX_SCU_PINTSEL0, val, arg); 753 + if (ret == 0) 754 + return ret; 755 + 756 + return lpc18xx_get_pintsel(scu->base + LPC18XX_SCU_PINTSEL1, val, arg); 757 + } 758 + 759 + static int lpc18xx_pconf_get_pin(struct pinctrl_dev *pctldev, unsigned param, 760 + int *arg, u32 reg, unsigned pin, 728 761 struct lpc18xx_pin_caps *pin_cap) 729 762 { 730 763 switch (param) { ··· 850 755 } 851 756 break; 852 757 758 + case PIN_CONFIG_GPIO_PIN_INT: 759 + return lpc18xx_pconf_get_gpio_pin_int(pctldev, arg, pin); 760 + 853 761 default: 854 762 return -ENOTSUPP; 855 763 } ··· 892 794 else if (pin_cap->type == TYPE_USB1) 893 795 ret = lpc18xx_pconf_get_usb1(param, &arg, reg); 894 796 else 895 - ret = lpc18xx_pconf_get_pin(param, &arg, reg, pin_cap); 797 + ret = lpc18xx_pconf_get_pin(pctldev, param, &arg, reg, pin, pin_cap); 896 798 897 799 if (ret < 0) 898 800 return ret; ··· 981 883 return 0; 982 884 } 983 885 984 - static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev, 985 - enum pin_config_param param, 986 - u16 param_val, u32 *reg, 886 + static int lpc18xx_pconf_set_gpio_pin_int(struct pinctrl_dev *pctldev, 887 + u16 param_val, unsigned pin) 888 + { 889 + struct lpc18xx_scu_data *scu = pinctrl_dev_get_drvdata(pctldev); 890 + u32 val, reg_val, reg_offset = LPC18XX_SCU_PINTSEL0; 891 + int gpio; 892 + 893 + if (param_val >= LPC18XX_GPIO_PIN_INT_MAX) 894 + return -EINVAL; 895 + 896 + gpio = lpc18xx_pin_to_gpio(pctldev, pin); 897 + if (gpio < 0) 898 + return -ENOTSUPP; 899 + 900 + val = lpc18xx_gpio_to_pintsel_val(gpio); 901 + 902 + reg_offset += (param_val / LPC18XX_SCU_IRQ_PER_PINTSEL) * sizeof(u32); 903 + 904 + reg_val = readl(scu->base + reg_offset); 905 + reg_val &= ~LPC18XX_SCU_PINTSEL_VAL(LPC18XX_SCU_PINTSEL_VAL_MASK, param_val); 906 + reg_val |= LPC18XX_SCU_PINTSEL_VAL(val, param_val); 907 + writel(reg_val, scu->base + reg_offset); 908 + 909 + return 0; 910 + } 911 + 912 + static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev, unsigned param, 913 + u16 param_val, u32 *reg, unsigned pin, 987 914 struct lpc18xx_pin_caps *pin_cap) 988 915 { 989 916 switch (param) { ··· 1071 948 *reg |= param_val << LPC18XX_SCU_PIN_EHD_POS; 1072 949 break; 1073 950 951 + case PIN_CONFIG_GPIO_PIN_INT: 952 + return lpc18xx_pconf_set_gpio_pin_int(pctldev, param_val, pin); 953 + 1074 954 default: 1075 955 dev_err(pctldev->dev, "Property not supported\n"); 1076 956 return -ENOTSUPP; ··· 1108 982 else if (pin_cap->type == TYPE_USB1) 1109 983 ret = lpc18xx_pconf_set_usb1(pctldev, param, param_val, &reg); 1110 984 else 1111 - ret = lpc18xx_pconf_set_pin(pctldev, param, param_val, &reg, pin_cap); 985 + ret = lpc18xx_pconf_set_pin(pctldev, param, param_val, &reg, pin, pin_cap); 1112 986 1113 987 if (ret) 1114 988 return ret; ··· 1262 1136 .pctlops = &lpc18xx_pctl_ops, 1263 1137 .pmxops = &lpc18xx_pmx_ops, 1264 1138 .confops = &lpc18xx_pconf_ops, 1139 + .num_custom_params = ARRAY_SIZE(lpc18xx_params), 1140 + .custom_params = lpc18xx_params, 1141 + #ifdef CONFIG_DEBUG_FS 1142 + .custom_conf_items = lpc18xx_conf_items, 1143 + #endif 1265 1144 .owner = THIS_MODULE, 1266 1145 }; 1267 1146