aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorJavier Martinez Canillas <javier.martinez@collabora.co.uk>2013-06-28 11:27:02 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-07-20 12:57:27 -0400
commit0e970cec05635adbe7b686063e2548a8e4afb8f4 (patch)
tree3964060d8cbf5da9107e319b00afa65f2b709f7f /drivers/gpio
parentad81f0545ef01ea651886dddac4bef6cec930092 (diff)
gpio/omap: don't create an IRQ mapping for every GPIO on DT
When a GPIO is defined as an interrupt line using Device Tree, a call to irq_create_of_mapping() is made that calls irq_create_mapping(). So, is not necessary to do the mapping for all OMAP GPIO lines and explicitly call irq_create_mapping() on the driver probe() when booting with Device Tree. Add a custom IRQ domain .map function handler that will be called by irq_create_mapping() to map the GPIO lines used as IRQ. This also allows to execute needed setup code such as configuring a GPIO as input and enabling the GPIO bank. Changes since v3: - Use bank->chip.of_node instead of_have_populated_dt() to check DT or legacy boot as suggested by Jean-Christophe PLAGNIOL-VILLARD Changes since v2: - Unconditionally do the IRQ setup in the .map() function and only call irq_create_mapping() in the gpio chip init to avoid code duplication as suggested by Grant Likely. Changes since v1: - Split the addition of the .map function handler and the automatic gpio request in two different patches. - Add GPIO IRQ setup logic to the irq domain mapping function. - Only call irq_create_mapping for every GPIO on legacy boot. - Only setup a GPIO IRQ on the .map function for DeviceTree boot. Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Tested-by: Enric Balletbo i Serra <eballetbo@gmail.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-omap.c54
1 files changed, 40 insertions, 14 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index dfeb3a3a8f20..5e667ff91dc3 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -1068,24 +1068,50 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
1068 1068
1069 gpiochip_add(&bank->chip); 1069 gpiochip_add(&bank->chip);
1070 1070
1071 for (j = 0; j < bank->width; j++) { 1071 /*
1072 int irq = irq_create_mapping(bank->domain, j); 1072 * REVISIT these explicit calls to irq_create_mapping()
1073 irq_set_lockdep_class(irq, &gpio_lock_class); 1073 * to do the GPIO to IRQ domain mapping for each GPIO in
1074 irq_set_chip_data(irq, bank); 1074 * the bank can be removed once all OMAP platforms have
1075 if (bank->is_mpuio) { 1075 * been migrated to Device Tree boot only.
1076 omap_mpuio_alloc_gc(bank, irq, bank->width); 1076 * Since in DT boot irq_create_mapping() is called from
1077 } else { 1077 * irq_create_of_mapping() only for the GPIO lines that
1078 irq_set_chip_and_handler(irq, &gpio_irq_chip, 1078 * are used as interrupts.
1079 handle_simple_irq); 1079 */
1080 set_irq_flags(irq, IRQF_VALID); 1080 if (!bank->chip.of_node)
1081 } 1081 for (j = 0; j < bank->width; j++)
1082 } 1082 irq_create_mapping(bank->domain, j);
1083 irq_set_chained_handler(bank->irq, gpio_irq_handler); 1083 irq_set_chained_handler(bank->irq, gpio_irq_handler);
1084 irq_set_handler_data(bank->irq, bank); 1084 irq_set_handler_data(bank->irq, bank);
1085} 1085}
1086 1086
1087static const struct of_device_id omap_gpio_match[]; 1087static const struct of_device_id omap_gpio_match[];
1088 1088
1089static int omap_gpio_irq_map(struct irq_domain *d, unsigned int virq,
1090 irq_hw_number_t hwirq)
1091{
1092 struct gpio_bank *bank = d->host_data;
1093
1094 if (!bank)
1095 return -EINVAL;
1096
1097 irq_set_lockdep_class(virq, &gpio_lock_class);
1098 irq_set_chip_data(virq, bank);
1099 if (bank->is_mpuio) {
1100 omap_mpuio_alloc_gc(bank, virq, bank->width);
1101 } else {
1102 irq_set_chip_and_handler(virq, &gpio_irq_chip,
1103 handle_simple_irq);
1104 set_irq_flags(virq, IRQF_VALID);
1105 }
1106
1107 return 0;
1108}
1109
1110static struct irq_domain_ops omap_gpio_irq_ops = {
1111 .xlate = irq_domain_xlate_onetwocell,
1112 .map = omap_gpio_irq_map,
1113};
1114
1089static int omap_gpio_probe(struct platform_device *pdev) 1115static int omap_gpio_probe(struct platform_device *pdev)
1090{ 1116{
1091 struct device *dev = &pdev->dev; 1117 struct device *dev = &pdev->dev;
@@ -1151,10 +1177,10 @@ static int omap_gpio_probe(struct platform_device *pdev)
1151 } 1177 }
1152 1178
1153 bank->domain = irq_domain_add_legacy(node, bank->width, irq_base, 1179 bank->domain = irq_domain_add_legacy(node, bank->width, irq_base,
1154 0, &irq_domain_simple_ops, NULL); 1180 0, &omap_gpio_irq_ops, bank);
1155#else 1181#else
1156 bank->domain = irq_domain_add_linear(node, bank->width, 1182 bank->domain = irq_domain_add_linear(node, bank->width,
1157 &irq_domain_simple_ops, NULL); 1183 &omap_gpio_irq_ops, bank);
1158#endif 1184#endif
1159 if (!bank->domain) { 1185 if (!bank->domain) {
1160 dev_err(dev, "Couldn't register an IRQ domain\n"); 1186 dev_err(dev, "Couldn't register an IRQ domain\n");