aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2012-11-05 10:10:31 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2012-11-11 17:35:03 -0500
commit76f93992e4c44f30be797d5c99d6f369ed001747 (patch)
treef4ece6f5b6cf7bcd06f3460640b01807fae6fc0a
parent7da0cbfc54c82eec793ff3d1b23b7a25406c6dba (diff)
mfd: Provide the STMPE driver with its own IRQ domain
The STMPE driver is yet another IRQ controller which requires its own IRQ domain. So, we provide it with one. Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/stmpe.c82
-rw-r--r--include/linux/mfd/stmpe.h2
2 files changed, 52 insertions, 32 deletions
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index ad13cb00a749..5c8d8f260df2 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -12,6 +12,7 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/interrupt.h> 13#include <linux/interrupt.h>
14#include <linux/irq.h> 14#include <linux/irq.h>
15#include <linux/irqdomain.h>
15#include <linux/pm.h> 16#include <linux/pm.h>
16#include <linux/slab.h> 17#include <linux/slab.h>
17#include <linux/mfd/core.h> 18#include <linux/mfd/core.h>
@@ -757,7 +758,9 @@ static irqreturn_t stmpe_irq(int irq, void *data)
757 int i; 758 int i;
758 759
759 if (variant->id_val == STMPE801_ID) { 760 if (variant->id_val == STMPE801_ID) {
760 handle_nested_irq(stmpe->irq_base); 761 int base = irq_create_mapping(stmpe->domain, 0);
762
763 handle_nested_irq(base);
761 return IRQ_HANDLED; 764 return IRQ_HANDLED;
762 } 765 }
763 766
@@ -778,8 +781,9 @@ static irqreturn_t stmpe_irq(int irq, void *data)
778 while (status) { 781 while (status) {
779 int bit = __ffs(status); 782 int bit = __ffs(status);
780 int line = bank * 8 + bit; 783 int line = bank * 8 + bit;
784 int nestedirq = irq_create_mapping(stmpe->domain, line);
781 785
782 handle_nested_irq(stmpe->irq_base + line); 786 handle_nested_irq(nestedirq);
783 status &= ~(1 << bit); 787 status &= ~(1 << bit);
784 } 788 }
785 789
@@ -820,7 +824,7 @@ static void stmpe_irq_sync_unlock(struct irq_data *data)
820static void stmpe_irq_mask(struct irq_data *data) 824static void stmpe_irq_mask(struct irq_data *data)
821{ 825{
822 struct stmpe *stmpe = irq_data_get_irq_chip_data(data); 826 struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
823 int offset = data->irq - stmpe->irq_base; 827 int offset = data->hwirq;
824 int regoffset = offset / 8; 828 int regoffset = offset / 8;
825 int mask = 1 << (offset % 8); 829 int mask = 1 << (offset % 8);
826 830
@@ -830,7 +834,7 @@ static void stmpe_irq_mask(struct irq_data *data)
830static void stmpe_irq_unmask(struct irq_data *data) 834static void stmpe_irq_unmask(struct irq_data *data)
831{ 835{
832 struct stmpe *stmpe = irq_data_get_irq_chip_data(data); 836 struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
833 int offset = data->irq - stmpe->irq_base; 837 int offset = data->hwirq;
834 int regoffset = offset / 8; 838 int regoffset = offset / 8;
835 int mask = 1 << (offset % 8); 839 int mask = 1 << (offset % 8);
836 840
@@ -845,43 +849,62 @@ static struct irq_chip stmpe_irq_chip = {
845 .irq_unmask = stmpe_irq_unmask, 849 .irq_unmask = stmpe_irq_unmask,
846}; 850};
847 851
848static int __devinit stmpe_irq_init(struct stmpe *stmpe) 852static int stmpe_irq_map(struct irq_domain *d, unsigned int virq,
853 irq_hw_number_t hwirq)
849{ 854{
855 struct stmpe *stmpe = d->host_data;
850 struct irq_chip *chip = NULL; 856 struct irq_chip *chip = NULL;
851 int num_irqs = stmpe->variant->num_irqs;
852 int base = stmpe->irq_base;
853 int irq;
854 857
855 if (stmpe->variant->id_val != STMPE801_ID) 858 if (stmpe->variant->id_val != STMPE801_ID)
856 chip = &stmpe_irq_chip; 859 chip = &stmpe_irq_chip;
857 860
858 for (irq = base; irq < base + num_irqs; irq++) { 861 irq_set_chip_data(virq, stmpe);
859 irq_set_chip_data(irq, stmpe); 862 irq_set_chip_and_handler(virq, chip, handle_edge_irq);
860 irq_set_chip_and_handler(irq, chip, handle_edge_irq); 863 irq_set_nested_thread(virq, 1);
861 irq_set_nested_thread(irq, 1);
862#ifdef CONFIG_ARM 864#ifdef CONFIG_ARM
863 set_irq_flags(irq, IRQF_VALID); 865 set_irq_flags(virq, IRQF_VALID);
864#else 866#else
865 irq_set_noprobe(irq); 867 irq_set_noprobe(virq);
866#endif 868#endif
867 }
868 869
869 return 0; 870 return 0;
870} 871}
871 872
872static void stmpe_irq_remove(struct stmpe *stmpe) 873static void stmpe_irq_unmap(struct irq_domain *d, unsigned int virq)
873{ 874{
874 int num_irqs = stmpe->variant->num_irqs;
875 int base = stmpe->irq_base;
876 int irq;
877
878 for (irq = base; irq < base + num_irqs; irq++) {
879#ifdef CONFIG_ARM 875#ifdef CONFIG_ARM
880 set_irq_flags(irq, 0); 876 set_irq_flags(virq, 0);
881#endif 877#endif
882 irq_set_chip_and_handler(irq, NULL, NULL); 878 irq_set_chip_and_handler(virq, NULL, NULL);
883 irq_set_chip_data(irq, NULL); 879 irq_set_chip_data(virq, NULL);
880}
881
882static struct irq_domain_ops stmpe_irq_ops = {
883 .map = stmpe_irq_map,
884 .unmap = stmpe_irq_unmap,
885 .xlate = irq_domain_xlate_twocell,
886};
887
888static int __devinit stmpe_irq_init(struct stmpe *stmpe)
889{
890 int base = stmpe->irq_base;
891 int num_irqs = stmpe->variant->num_irqs;
892
893 if (base) {
894 stmpe->domain = irq_domain_add_legacy(
895 NULL, num_irqs, base, 0, &stmpe_irq_ops, stmpe);
896 }
897 else {
898 stmpe->domain = irq_domain_add_linear(
899 NULL, num_irqs, &stmpe_irq_ops, stmpe);
900 }
901
902 if (!stmpe->domain) {
903 dev_err(stmpe->dev, "Failed to create irqdomain\n");
904 return -ENOSYS;
884 } 905 }
906
907 return 0;
885} 908}
886 909
887static int __devinit stmpe_chip_init(struct stmpe *stmpe) 910static int __devinit stmpe_chip_init(struct stmpe *stmpe)
@@ -954,7 +977,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe,
954 struct mfd_cell *cell) 977 struct mfd_cell *cell)
955{ 978{
956 return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, 979 return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
957 NULL, stmpe->irq_base, NULL); 980 NULL, stmpe->irq_base, stmpe->domain);
958} 981}
959 982
960static int __devinit stmpe_devices_init(struct stmpe *stmpe) 983static int __devinit stmpe_devices_init(struct stmpe *stmpe)
@@ -1067,7 +1090,7 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
1067 if (ret) { 1090 if (ret) {
1068 dev_err(stmpe->dev, "failed to request IRQ: %d\n", 1091 dev_err(stmpe->dev, "failed to request IRQ: %d\n",
1069 ret); 1092 ret);
1070 goto out_removeirq; 1093 goto free_gpio;
1071 } 1094 }
1072 } 1095 }
1073 1096
@@ -1083,9 +1106,6 @@ out_removedevs:
1083 mfd_remove_devices(stmpe->dev); 1106 mfd_remove_devices(stmpe->dev);
1084 if (stmpe->irq >= 0) 1107 if (stmpe->irq >= 0)
1085 free_irq(stmpe->irq, stmpe); 1108 free_irq(stmpe->irq, stmpe);
1086out_removeirq:
1087 if (stmpe->irq >= 0)
1088 stmpe_irq_remove(stmpe);
1089free_gpio: 1109free_gpio:
1090 if (pdata->irq_over_gpio) 1110 if (pdata->irq_over_gpio)
1091 gpio_free(pdata->irq_gpio); 1111 gpio_free(pdata->irq_gpio);
@@ -1098,10 +1118,8 @@ int stmpe_remove(struct stmpe *stmpe)
1098{ 1118{
1099 mfd_remove_devices(stmpe->dev); 1119 mfd_remove_devices(stmpe->dev);
1100 1120
1101 if (stmpe->irq >= 0) { 1121 if (stmpe->irq >= 0)
1102 free_irq(stmpe->irq, stmpe); 1122 free_irq(stmpe->irq, stmpe);
1103 stmpe_irq_remove(stmpe);
1104 }
1105 1123
1106 if (stmpe->pdata->irq_over_gpio) 1124 if (stmpe->pdata->irq_over_gpio)
1107 gpio_free(stmpe->pdata->irq_gpio); 1125 gpio_free(stmpe->pdata->irq_gpio);
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h
index f8d5b4d5843f..15dac790365f 100644
--- a/include/linux/mfd/stmpe.h
+++ b/include/linux/mfd/stmpe.h
@@ -62,6 +62,7 @@ struct stmpe_client_info;
62 * @lock: lock protecting I/O operations 62 * @lock: lock protecting I/O operations
63 * @irq_lock: IRQ bus lock 63 * @irq_lock: IRQ bus lock
64 * @dev: device, mostly for dev_dbg() 64 * @dev: device, mostly for dev_dbg()
65 * @irq_domain: IRQ domain
65 * @client: client - i2c or spi 66 * @client: client - i2c or spi
66 * @ci: client specific information 67 * @ci: client specific information
67 * @partnum: part number 68 * @partnum: part number
@@ -79,6 +80,7 @@ struct stmpe {
79 struct mutex lock; 80 struct mutex lock;
80 struct mutex irq_lock; 81 struct mutex irq_lock;
81 struct device *dev; 82 struct device *dev;
83 struct irq_domain *domain;
82 void *client; 84 void *client;
83 struct stmpe_client_info *ci; 85 struct stmpe_client_info *ci;
84 enum stmpe_partnum partnum; 86 enum stmpe_partnum partnum;