diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2014-03-25 05:44:09 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-03-26 05:31:33 -0400 |
commit | e0bc34a3dada03a48ff5501381ff7fdef885ed25 (patch) | |
tree | 646ef286908d6635f28bb994e19f5fe1f83fc50e /drivers/pinctrl | |
parent | 8d5b24bd30c23930e666813ea0adc4672ea58c62 (diff) |
pinctrl: nomadik: convert driver to use gpiolib irqchip
This converts the Nomadik pin control driver to register its
chained irq handler and irqchip using the helpers in the
gpiolib core.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/Kconfig | 3 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-nomadik.c | 123 |
2 files changed, 36 insertions, 90 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 1e4e69384baa..a05087bd1955 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig | |||
@@ -235,6 +235,9 @@ config PINCTRL_NOMADIK | |||
235 | depends on ARCH_U8500 || ARCH_NOMADIK | 235 | depends on ARCH_U8500 || ARCH_NOMADIK |
236 | select PINMUX | 236 | select PINMUX |
237 | select PINCONF | 237 | select PINCONF |
238 | select GPIOLIB | ||
239 | select OF_GPIO | ||
240 | select GPIOLIB_IRQCHIP | ||
238 | 241 | ||
239 | config PINCTRL_STN8815 | 242 | config PINCTRL_STN8815 |
240 | bool "STN8815 pin controller driver" | 243 | bool "STN8815 pin controller driver" |
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 98a36a0969f9..db0cc30c82de 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c | |||
@@ -21,9 +21,6 @@ | |||
21 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
22 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/irq.h> | ||
25 | #include <linux/irqdomain.h> | ||
26 | #include <linux/irqchip/chained_irq.h> | ||
27 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
28 | #include <linux/of_device.h> | 25 | #include <linux/of_device.h> |
29 | #include <linux/of_address.h> | 26 | #include <linux/of_address.h> |
@@ -248,7 +245,6 @@ enum nmk_gpio_slpm { | |||
248 | 245 | ||
249 | struct nmk_gpio_chip { | 246 | struct nmk_gpio_chip { |
250 | struct gpio_chip chip; | 247 | struct gpio_chip chip; |
251 | struct irq_domain *domain; | ||
252 | void __iomem *addr; | 248 | void __iomem *addr; |
253 | struct clk *clk; | 249 | struct clk *clk; |
254 | unsigned int bank; | 250 | unsigned int bank; |
@@ -419,7 +415,7 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset) | |||
419 | u32 falling = nmk_chip->fimsc & BIT(offset); | 415 | u32 falling = nmk_chip->fimsc & BIT(offset); |
420 | u32 rising = nmk_chip->rimsc & BIT(offset); | 416 | u32 rising = nmk_chip->rimsc & BIT(offset); |
421 | int gpio = nmk_chip->chip.base + offset; | 417 | int gpio = nmk_chip->chip.base + offset; |
422 | int irq = irq_find_mapping(nmk_chip->domain, offset); | 418 | int irq = irq_find_mapping(nmk_chip->chip.irqdomain, offset); |
423 | struct irq_data *d = irq_get_irq_data(irq); | 419 | struct irq_data *d = irq_get_irq_data(irq); |
424 | 420 | ||
425 | if (!rising && !falling) | 421 | if (!rising && !falling) |
@@ -647,11 +643,8 @@ static inline int nmk_gpio_get_bitmask(int gpio) | |||
647 | 643 | ||
648 | static void nmk_gpio_irq_ack(struct irq_data *d) | 644 | static void nmk_gpio_irq_ack(struct irq_data *d) |
649 | { | 645 | { |
650 | struct nmk_gpio_chip *nmk_chip; | 646 | struct gpio_chip *chip = irq_data_get_irq_chip_data(d); |
651 | 647 | struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); | |
652 | nmk_chip = irq_data_get_irq_chip_data(d); | ||
653 | if (!nmk_chip) | ||
654 | return; | ||
655 | 648 | ||
656 | clk_enable(nmk_chip->clk); | 649 | clk_enable(nmk_chip->clk); |
657 | writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC); | 650 | writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC); |
@@ -848,26 +841,6 @@ static void nmk_gpio_irq_shutdown(struct irq_data *d) | |||
848 | clk_disable(nmk_chip->clk); | 841 | clk_disable(nmk_chip->clk); |
849 | } | 842 | } |
850 | 843 | ||
851 | static int nmk_gpio_irq_reqres(struct irq_data *d) | ||
852 | { | ||
853 | struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); | ||
854 | |||
855 | if (gpio_lock_as_irq(&nmk_chip->chip, d->hwirq)) { | ||
856 | dev_err(nmk_chip->chip.dev, | ||
857 | "unable to lock HW IRQ %lu for IRQ\n", | ||
858 | d->hwirq); | ||
859 | return -EINVAL; | ||
860 | } | ||
861 | return 0; | ||
862 | } | ||
863 | |||
864 | static void nmk_gpio_irq_relres(struct irq_data *d) | ||
865 | { | ||
866 | struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); | ||
867 | |||
868 | gpio_unlock_as_irq(&nmk_chip->chip, d->hwirq); | ||
869 | } | ||
870 | |||
871 | static struct irq_chip nmk_gpio_irq_chip = { | 844 | static struct irq_chip nmk_gpio_irq_chip = { |
872 | .name = "Nomadik-GPIO", | 845 | .name = "Nomadik-GPIO", |
873 | .irq_ack = nmk_gpio_irq_ack, | 846 | .irq_ack = nmk_gpio_irq_ack, |
@@ -877,24 +850,21 @@ static struct irq_chip nmk_gpio_irq_chip = { | |||
877 | .irq_set_wake = nmk_gpio_irq_set_wake, | 850 | .irq_set_wake = nmk_gpio_irq_set_wake, |
878 | .irq_startup = nmk_gpio_irq_startup, | 851 | .irq_startup = nmk_gpio_irq_startup, |
879 | .irq_shutdown = nmk_gpio_irq_shutdown, | 852 | .irq_shutdown = nmk_gpio_irq_shutdown, |
880 | .irq_request_resources = nmk_gpio_irq_reqres, | ||
881 | .irq_release_resources = nmk_gpio_irq_relres, | ||
882 | .flags = IRQCHIP_MASK_ON_SUSPEND, | 853 | .flags = IRQCHIP_MASK_ON_SUSPEND, |
883 | }; | 854 | }; |
884 | 855 | ||
885 | static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, | 856 | static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, |
886 | u32 status) | 857 | u32 status) |
887 | { | 858 | { |
888 | struct nmk_gpio_chip *nmk_chip; | ||
889 | struct irq_chip *host_chip = irq_get_chip(irq); | 859 | struct irq_chip *host_chip = irq_get_chip(irq); |
860 | struct gpio_chip *chip = irq_desc_get_handler_data(desc); | ||
890 | 861 | ||
891 | chained_irq_enter(host_chip, desc); | 862 | chained_irq_enter(host_chip, desc); |
892 | 863 | ||
893 | nmk_chip = irq_get_handler_data(irq); | ||
894 | while (status) { | 864 | while (status) { |
895 | int bit = __ffs(status); | 865 | int bit = __ffs(status); |
896 | 866 | ||
897 | generic_handle_irq(irq_find_mapping(nmk_chip->domain, bit)); | 867 | generic_handle_irq(irq_find_mapping(chip->irqdomain, bit)); |
898 | status &= ~BIT(bit); | 868 | status &= ~BIT(bit); |
899 | } | 869 | } |
900 | 870 | ||
@@ -903,9 +873,11 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, | |||
903 | 873 | ||
904 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 874 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) |
905 | { | 875 | { |
906 | struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq); | 876 | struct gpio_chip *chip = irq_desc_get_handler_data(desc); |
877 | struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); | ||
907 | u32 status; | 878 | u32 status; |
908 | 879 | ||
880 | pr_err("PLONK IRQ %d\n", irq); | ||
909 | clk_enable(nmk_chip->clk); | 881 | clk_enable(nmk_chip->clk); |
910 | status = readl(nmk_chip->addr + NMK_GPIO_IS); | 882 | status = readl(nmk_chip->addr + NMK_GPIO_IS); |
911 | clk_disable(nmk_chip->clk); | 883 | clk_disable(nmk_chip->clk); |
@@ -916,26 +888,13 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
916 | static void nmk_gpio_latent_irq_handler(unsigned int irq, | 888 | static void nmk_gpio_latent_irq_handler(unsigned int irq, |
917 | struct irq_desc *desc) | 889 | struct irq_desc *desc) |
918 | { | 890 | { |
919 | struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq); | 891 | struct gpio_chip *chip = irq_desc_get_handler_data(desc); |
892 | struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); | ||
920 | u32 status = nmk_chip->get_latent_status(nmk_chip->bank); | 893 | u32 status = nmk_chip->get_latent_status(nmk_chip->bank); |
921 | 894 | ||
922 | __nmk_gpio_irq_handler(irq, desc, status); | 895 | __nmk_gpio_irq_handler(irq, desc, status); |
923 | } | 896 | } |
924 | 897 | ||
925 | static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) | ||
926 | { | ||
927 | irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); | ||
928 | irq_set_handler_data(nmk_chip->parent_irq, nmk_chip); | ||
929 | |||
930 | if (nmk_chip->latent_parent_irq >= 0) { | ||
931 | irq_set_chained_handler(nmk_chip->latent_parent_irq, | ||
932 | nmk_gpio_latent_irq_handler); | ||
933 | irq_set_handler_data(nmk_chip->latent_parent_irq, nmk_chip); | ||
934 | } | ||
935 | |||
936 | return 0; | ||
937 | } | ||
938 | |||
939 | /* I/O Functions */ | 898 | /* I/O Functions */ |
940 | 899 | ||
941 | static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset) | 900 | static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset) |
@@ -1014,14 +973,6 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, | |||
1014 | return 0; | 973 | return 0; |
1015 | } | 974 | } |
1016 | 975 | ||
1017 | static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
1018 | { | ||
1019 | struct nmk_gpio_chip *nmk_chip = | ||
1020 | container_of(chip, struct nmk_gpio_chip, chip); | ||
1021 | |||
1022 | return irq_create_mapping(nmk_chip->domain, offset); | ||
1023 | } | ||
1024 | |||
1025 | #ifdef CONFIG_DEBUG_FS | 976 | #ifdef CONFIG_DEBUG_FS |
1026 | 977 | ||
1027 | #include <linux/seq_file.h> | 978 | #include <linux/seq_file.h> |
@@ -1120,7 +1071,6 @@ static struct gpio_chip nmk_gpio_template = { | |||
1120 | .get = nmk_gpio_get_input, | 1071 | .get = nmk_gpio_get_input, |
1121 | .direction_output = nmk_gpio_make_output, | 1072 | .direction_output = nmk_gpio_make_output, |
1122 | .set = nmk_gpio_set_output, | 1073 | .set = nmk_gpio_set_output, |
1123 | .to_irq = nmk_gpio_to_irq, | ||
1124 | .dbg_show = nmk_gpio_dbg_show, | 1074 | .dbg_show = nmk_gpio_dbg_show, |
1125 | .can_sleep = false, | 1075 | .can_sleep = false, |
1126 | }; | 1076 | }; |
@@ -1221,27 +1171,6 @@ void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up) | |||
1221 | } | 1171 | } |
1222 | } | 1172 | } |
1223 | 1173 | ||
1224 | static int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq, | ||
1225 | irq_hw_number_t hwirq) | ||
1226 | { | ||
1227 | struct nmk_gpio_chip *nmk_chip = d->host_data; | ||
1228 | |||
1229 | if (!nmk_chip) | ||
1230 | return -EINVAL; | ||
1231 | |||
1232 | irq_set_chip_and_handler(irq, &nmk_gpio_irq_chip, handle_edge_irq); | ||
1233 | set_irq_flags(irq, IRQF_VALID); | ||
1234 | irq_set_chip_data(irq, nmk_chip); | ||
1235 | irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); | ||
1236 | |||
1237 | return 0; | ||
1238 | } | ||
1239 | |||
1240 | static const struct irq_domain_ops nmk_gpio_irq_simple_ops = { | ||
1241 | .map = nmk_gpio_irq_map, | ||
1242 | .xlate = irq_domain_xlate_twocell, | ||
1243 | }; | ||
1244 | |||
1245 | static int nmk_gpio_probe(struct platform_device *dev) | 1174 | static int nmk_gpio_probe(struct platform_device *dev) |
1246 | { | 1175 | { |
1247 | struct device_node *np = dev->dev.of_node; | 1176 | struct device_node *np = dev->dev.of_node; |
@@ -1321,17 +1250,31 @@ static int nmk_gpio_probe(struct platform_device *dev) | |||
1321 | 1250 | ||
1322 | platform_set_drvdata(dev, nmk_chip); | 1251 | platform_set_drvdata(dev, nmk_chip); |
1323 | 1252 | ||
1324 | nmk_chip->domain = irq_domain_add_simple(np, | 1253 | /* |
1325 | NMK_GPIO_PER_CHIP, 0, | 1254 | * Let the generic code handle this edge IRQ, the the chained |
1326 | &nmk_gpio_irq_simple_ops, nmk_chip); | 1255 | * handler will perform the actual work of handling the parent |
1327 | if (!nmk_chip->domain) { | 1256 | * interrupt. |
1328 | dev_err(&dev->dev, "failed to create irqdomain\n"); | 1257 | */ |
1329 | /* Just do this, no matter if it fails */ | 1258 | ret = gpiochip_irqchip_add(&nmk_chip->chip, |
1259 | &nmk_gpio_irq_chip, | ||
1260 | 0, | ||
1261 | handle_edge_irq, | ||
1262 | IRQ_TYPE_EDGE_FALLING); | ||
1263 | if (ret) { | ||
1264 | dev_err(&dev->dev, "could not add irqchip\n"); | ||
1330 | ret = gpiochip_remove(&nmk_chip->chip); | 1265 | ret = gpiochip_remove(&nmk_chip->chip); |
1331 | return -ENOSYS; | 1266 | return -ENODEV; |
1332 | } | 1267 | } |
1333 | 1268 | /* Then register the chain on the parent IRQ */ | |
1334 | nmk_gpio_init_irq(nmk_chip); | 1269 | gpiochip_set_chained_irqchip(&nmk_chip->chip, |
1270 | &nmk_gpio_irq_chip, | ||
1271 | nmk_chip->parent_irq, | ||
1272 | nmk_gpio_irq_handler); | ||
1273 | if (nmk_chip->latent_parent_irq > 0) | ||
1274 | gpiochip_set_chained_irqchip(&nmk_chip->chip, | ||
1275 | &nmk_gpio_irq_chip, | ||
1276 | nmk_chip->latent_parent_irq, | ||
1277 | nmk_gpio_latent_irq_handler); | ||
1335 | 1278 | ||
1336 | dev_info(&dev->dev, "at address %p\n", nmk_chip->addr); | 1279 | dev_info(&dev->dev, "at address %p\n", nmk_chip->addr); |
1337 | 1280 | ||