aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-s5p/irq-gpioint.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-s5p/irq-gpioint.c')
-rw-r--r--arch/arm/plat-s5p/irq-gpioint.c116
1 files changed, 27 insertions, 89 deletions
diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c
index cd6d67c8382..135abda31c9 100644
--- a/arch/arm/plat-s5p/irq-gpioint.c
+++ b/arch/arm/plat-s5p/irq-gpioint.c
@@ -41,72 +41,11 @@ struct s5p_gpioint_bank {
41 41
42LIST_HEAD(banks); 42LIST_HEAD(banks);
43 43
44static int s5p_gpioint_get_offset(struct irq_data *data) 44static int s5p_gpioint_set_type(struct irq_data *d, unsigned int type)
45{ 45{
46 struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data); 46 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
47 return data->irq - chip->irq_base; 47 struct irq_chip_type *ct = gc->chip_types;
48} 48 unsigned int shift = (d->irq - gc->irq_base) << 2;
49
50static void s5p_gpioint_ack(struct irq_data *data)
51{
52 struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
53 int group, offset, pend_offset;
54 unsigned int value;
55
56 group = chip->group;
57 offset = s5p_gpioint_get_offset(data);
58 pend_offset = REG_OFFSET(group);
59
60 value = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
61 value |= BIT(offset);
62 __raw_writel(value, GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
63}
64
65static void s5p_gpioint_mask(struct irq_data *data)
66{
67 struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
68 int group, offset, mask_offset;
69 unsigned int value;
70
71 group = chip->group;
72 offset = s5p_gpioint_get_offset(data);
73 mask_offset = REG_OFFSET(group);
74
75 value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
76 value |= BIT(offset);
77 __raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
78}
79
80static void s5p_gpioint_unmask(struct irq_data *data)
81{
82 struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
83 int group, offset, mask_offset;
84 unsigned int value;
85
86 group = chip->group;
87 offset = s5p_gpioint_get_offset(data);
88 mask_offset = REG_OFFSET(group);
89
90 value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
91 value &= ~BIT(offset);
92 __raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
93}
94
95static void s5p_gpioint_mask_ack(struct irq_data *data)
96{
97 s5p_gpioint_mask(data);
98 s5p_gpioint_ack(data);
99}
100
101static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
102{
103 struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
104 int group, offset, con_offset;
105 unsigned int value;
106
107 group = chip->group;
108 offset = s5p_gpioint_get_offset(data);
109 con_offset = REG_OFFSET(group);
110 49
111 switch (type) { 50 switch (type) {
112 case IRQ_TYPE_EDGE_RISING: 51 case IRQ_TYPE_EDGE_RISING:
@@ -130,23 +69,12 @@ static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
130 return -EINVAL; 69 return -EINVAL;
131 } 70 }
132 71
133 value = __raw_readl(GPIO_BASE(chip) + CON_OFFSET + con_offset); 72 gc->type_cache &= ~(0x7 << shift);
134 value &= ~(0x7 << (offset * 0x4)); 73 gc->type_cache |= type << shift;
135 value |= (type << (offset * 0x4)); 74 writel(gc->type_cache, gc->reg_base + ct->regs.type);
136 __raw_writel(value, GPIO_BASE(chip) + CON_OFFSET + con_offset);
137
138 return 0; 75 return 0;
139} 76}
140 77
141static struct irq_chip s5p_gpioint = {
142 .name = "s5p_gpioint",
143 .irq_ack = s5p_gpioint_ack,
144 .irq_mask = s5p_gpioint_mask,
145 .irq_mask_ack = s5p_gpioint_mask_ack,
146 .irq_unmask = s5p_gpioint_unmask,
147 .irq_set_type = s5p_gpioint_set_type,
148};
149
150static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc) 78static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
151{ 79{
152 struct s5p_gpioint_bank *bank = irq_get_handler_data(irq); 80 struct s5p_gpioint_bank *bank = irq_get_handler_data(irq);
@@ -179,9 +107,10 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
179static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip) 107static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
180{ 108{
181 static int used_gpioint_groups = 0; 109 static int used_gpioint_groups = 0;
182 int irq, group = chip->group; 110 int group = chip->group;
183 int i;
184 struct s5p_gpioint_bank *bank = NULL; 111 struct s5p_gpioint_bank *bank = NULL;
112 struct irq_chip_generic *gc;
113 struct irq_chip_type *ct;
185 114
186 if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT) 115 if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT)
187 return -ENOMEM; 116 return -ENOMEM;
@@ -211,19 +140,28 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
211 * chained GPIO irq has been successfully registered, allocate new gpio 140 * chained GPIO irq has been successfully registered, allocate new gpio
212 * int group and assign irq nubmers 141 * int group and assign irq nubmers
213 */ 142 */
214
215 chip->irq_base = S5P_GPIOINT_BASE + 143 chip->irq_base = S5P_GPIOINT_BASE +
216 used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE; 144 used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE;
217 used_gpioint_groups++; 145 used_gpioint_groups++;
218 146
219 bank->chips[group - bank->start] = chip; 147 bank->chips[group - bank->start] = chip;
220 for (i = 0; i < chip->chip.ngpio; i++) { 148
221 irq = chip->irq_base + i; 149 gc = irq_alloc_generic_chip("s5p_gpioint", 1, chip->irq_base,
222 irq_set_chip(irq, &s5p_gpioint); 150 (void __iomem *)GPIO_BASE(chip),
223 irq_set_handler_data(irq, chip); 151 handle_level_irq);
224 irq_set_handler(irq, handle_level_irq); 152 if (!gc)
225 set_irq_flags(irq, IRQF_VALID); 153 return -ENOMEM;
226 } 154 ct = gc->chip_types;
155 ct->chip.irq_ack = irq_gc_ack;
156 ct->chip.irq_mask = irq_gc_mask_set_bit;
157 ct->chip.irq_unmask = irq_gc_mask_clr_bit;
158 ct->chip.irq_set_type = s5p_gpioint_set_type,
159 ct->regs.ack = PEND_OFFSET + REG_OFFSET(chip->group);
160 ct->regs.mask = MASK_OFFSET + REG_OFFSET(chip->group);
161 ct->regs.type = CON_OFFSET + REG_OFFSET(chip->group);
162 irq_setup_generic_chip(gc, IRQ_MSK(chip->chip.ngpio),
163 IRQ_GC_INIT_MASK_CACHE,
164 IRQ_NOREQUEST | IRQ_NOPROBE, 0);
227 return 0; 165 return 0;
228} 166}
229 167