aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2011-06-07 10:00:54 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-06-07 11:00:57 -0400
commit498c17cf6a935335c8652165cae5dc196340b3e9 (patch)
tree8a2c1d9c50dbafd556850c44152ee0db23fec0dd /drivers/gpio
parent6161715e3f1adecae9e7c160930add4040fa10e9 (diff)
gpio/mxs: convert gpio-mxs to use generic irq chip
The patch converts gpio-mxs driver to use generic irq chip. Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig1
-rw-r--r--drivers/gpio/gpio-mxs.c95
2 files changed, 35 insertions, 61 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 531bfb6c874..b84666a69af 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -102,6 +102,7 @@ config GPIO_MXS
102 def_bool y 102 def_bool y
103 depends on ARCH_MXS 103 depends on ARCH_MXS
104 select GPIO_GENERIC 104 select GPIO_GENERIC
105 select GENERIC_IRQ_CHIP
105 106
106config GPIO_PLAT_SAMSUNG 107config GPIO_PLAT_SAMSUNG
107 def_bool y 108 def_bool y
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index ddde0f44ba7..d8cafba8c82 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -59,51 +59,12 @@ struct mxs_gpio_port {
59 59
60/* Note: This driver assumes 32 GPIOs are handled in one register */ 60/* Note: This driver assumes 32 GPIOs are handled in one register */
61 61
62static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index)
63{
64 writel(1 << index, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
65}
66
67static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index,
68 int enable)
69{
70 if (enable) {
71 writel(1 << index,
72 port->base + PINCTRL_IRQEN(port->id) + MXS_SET);
73 writel(1 << index,
74 port->base + PINCTRL_PIN2IRQ(port->id) + MXS_SET);
75 } else {
76 writel(1 << index,
77 port->base + PINCTRL_IRQEN(port->id) + MXS_CLR);
78 }
79}
80
81static void mxs_gpio_ack_irq(struct irq_data *d)
82{
83 struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);
84 u32 gpio = irq_to_gpio(d->irq);
85 clear_gpio_irqstatus(port, gpio & 0x1f);
86}
87
88static void mxs_gpio_mask_irq(struct irq_data *d)
89{
90 struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);
91 u32 gpio = irq_to_gpio(d->irq);
92 set_gpio_irqenable(port, gpio & 0x1f, 0);
93}
94
95static void mxs_gpio_unmask_irq(struct irq_data *d)
96{
97 struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);
98 u32 gpio = irq_to_gpio(d->irq);
99 set_gpio_irqenable(port, gpio & 0x1f, 1);
100}
101
102static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) 62static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
103{ 63{
104 u32 gpio = irq_to_gpio(d->irq); 64 u32 gpio = irq_to_gpio(d->irq);
105 u32 pin_mask = 1 << (gpio & 31); 65 u32 pin_mask = 1 << (gpio & 31);
106 struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); 66 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
67 struct mxs_gpio_port *port = gc->private;
107 void __iomem *pin_addr; 68 void __iomem *pin_addr;
108 int edge; 69 int edge;
109 70
@@ -138,7 +99,8 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
138 else 99 else
139 writel(pin_mask, pin_addr + MXS_CLR); 100 writel(pin_mask, pin_addr + MXS_CLR);
140 101
141 clear_gpio_irqstatus(port, gpio & 0x1f); 102 writel(1 << (gpio & 0x1f),
103 port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
142 104
143 return 0; 105 return 0;
144} 106}
@@ -173,7 +135,8 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
173 */ 135 */
174static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable) 136static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
175{ 137{
176 struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d); 138 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
139 struct mxs_gpio_port *port = gc->private;
177 140
178 if (enable) 141 if (enable)
179 enable_irq_wake(port->irq); 142 enable_irq_wake(port->irq);
@@ -183,14 +146,26 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
183 return 0; 146 return 0;
184} 147}
185 148
186static struct irq_chip gpio_irq_chip = { 149static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port)
187 .name = "mxs gpio", 150{
188 .irq_ack = mxs_gpio_ack_irq, 151 struct irq_chip_generic *gc;
189 .irq_mask = mxs_gpio_mask_irq, 152 struct irq_chip_type *ct;
190 .irq_unmask = mxs_gpio_unmask_irq, 153
191 .irq_set_type = mxs_gpio_set_irq_type, 154 gc = irq_alloc_generic_chip("gpio-mxs", 1, port->virtual_irq_start,
192 .irq_set_wake = mxs_gpio_set_wake_irq, 155 port->base, handle_level_irq);
193}; 156 gc->private = port;
157
158 ct = gc->chip_types;
159 ct->chip.irq_ack = irq_gc_ack,
160 ct->chip.irq_mask = irq_gc_mask_clr_bit;
161 ct->chip.irq_unmask = irq_gc_mask_set_bit;
162 ct->chip.irq_set_type = mxs_gpio_set_irq_type;
163 ct->chip.irq_set_wake = mxs_gpio_set_wake_irq,
164 ct->regs.ack = PINCTRL_IRQSTAT(port->id) + MXS_CLR;
165 ct->regs.mask = PINCTRL_IRQEN(port->id);
166
167 irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
168}
194 169
195static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) 170static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
196{ 171{
@@ -206,7 +181,7 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev)
206 static void __iomem *base; 181 static void __iomem *base;
207 struct mxs_gpio_port *port; 182 struct mxs_gpio_port *port;
208 struct resource *iores = NULL; 183 struct resource *iores = NULL;
209 int err, i; 184 int err;
210 185
211 port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL); 186 port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL);
212 if (!port) 187 if (!port)
@@ -246,20 +221,18 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev)
246 goto out_iounmap; 221 goto out_iounmap;
247 } 222 }
248 223
249 /* disable the interrupt and clear the status */ 224 /*
250 writel(0, port->base + PINCTRL_PIN2IRQ(port->id)); 225 * select the pin interrupt functionality but initially
226 * disable the interrupts
227 */
228 writel(~0U, port->base + PINCTRL_PIN2IRQ(port->id));
251 writel(0, port->base + PINCTRL_IRQEN(port->id)); 229 writel(0, port->base + PINCTRL_IRQEN(port->id));
252 230
253 /* clear address has to be used to clear IRQSTAT bits */ 231 /* clear address has to be used to clear IRQSTAT bits */
254 writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); 232 writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
255 233
256 for (i = port->virtual_irq_start; 234 /* gpio-mxs can be a generic irq chip */
257 i < port->virtual_irq_start + 32; i++) { 235 mxs_gpio_init_gc(port);
258 irq_set_chip_and_handler(i, &gpio_irq_chip,
259 handle_level_irq);
260 set_irq_flags(i, IRQF_VALID);
261 irq_set_chip_data(i, port);
262 }
263 236
264 /* setup one handler for each entry */ 237 /* setup one handler for each entry */
265 irq_set_chained_handler(port->irq, mxs_gpio_irq_handler); 238 irq_set_chained_handler(port->irq, mxs_gpio_irq_handler);