diff options
author | Shawn Guo <shawn.guo@linaro.org> | 2011-06-07 10:00:54 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-06-07 11:00:57 -0400 |
commit | 498c17cf6a935335c8652165cae5dc196340b3e9 (patch) | |
tree | 8a2c1d9c50dbafd556850c44152ee0db23fec0dd /drivers/gpio/gpio-mxs.c | |
parent | 6161715e3f1adecae9e7c160930add4040fa10e9 (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/gpio-mxs.c')
-rw-r--r-- | drivers/gpio/gpio-mxs.c | 95 |
1 files changed, 34 insertions, 61 deletions
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index ddde0f44ba70..d8cafba8c829 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 | ||
62 | static 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 | |||
67 | static 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 | |||
81 | static 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 | |||
88 | static 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 | |||
95 | static 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 | |||
102 | static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) | 62 | static 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 | */ |
174 | static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable) | 136 | static 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 | ||
186 | static struct irq_chip gpio_irq_chip = { | 149 | static 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 | ||
195 | static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | 170 | static 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); |