aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-mxs.c
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2011-06-06 11:37:58 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-06-06 12:01:19 -0400
commit8d7cf8370d5fb75a3265408dceb1d6173eebfafd (patch)
treec14bbe3f058dc65e0f9e3dcd7dc0c8e66bbf8ce3 /drivers/gpio/gpio-mxs.c
parent7b2fa5702059a03c11f934224724b2f712a749ce (diff)
gpio/mxs: Change gpio-mxs into an upstanding gpio driver
The patch makes necessary changes on gpio-mxs as below to turn it into an upstanding gpio driver. * Clean up the gpio port definition stuff * Use readl/writel to replace mach-specific accessors __raw_readl/__raw_writel * Change mxs_gpio_init into mxs_gpio_probe function And it then migrates mach-mxs to the updated driver by adding corresponding platform devices. Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio/gpio-mxs.c')
-rw-r--r--drivers/gpio/gpio-mxs.c216
1 files changed, 124 insertions, 92 deletions
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index e26bf309b214..a28761428bb0 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -25,12 +25,12 @@
25#include <linux/io.h> 25#include <linux/io.h>
26#include <linux/irq.h> 26#include <linux/irq.h>
27#include <linux/gpio.h> 27#include <linux/gpio.h>
28#include <mach/mx23.h> 28#include <linux/platform_device.h>
29#include <mach/mx28.h> 29#include <linux/slab.h>
30#include <asm-generic/bug.h> 30#include <mach/mxs.h>
31 31
32static struct mxs_gpio_port *mxs_gpio_ports; 32#define MXS_SET 0x4
33static int gpio_table_size; 33#define MXS_CLR 0x8
34 34
35#define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10) 35#define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10)
36#define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10) 36#define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10)
@@ -61,36 +61,42 @@ struct mxs_gpio_port {
61 61
62static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index) 62static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index)
63{ 63{
64 __mxs_clrl(1 << index, port->base + PINCTRL_IRQSTAT(port->id)); 64 writel(1 << index, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
65} 65}
66 66
67static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index, 67static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index,
68 int enable) 68 int enable)
69{ 69{
70 if (enable) { 70 if (enable) {
71 __mxs_setl(1 << index, port->base + PINCTRL_IRQEN(port->id)); 71 writel(1 << index,
72 __mxs_setl(1 << index, port->base + PINCTRL_PIN2IRQ(port->id)); 72 port->base + PINCTRL_IRQEN(port->id) + MXS_SET);
73 writel(1 << index,
74 port->base + PINCTRL_PIN2IRQ(port->id) + MXS_SET);
73 } else { 75 } else {
74 __mxs_clrl(1 << index, port->base + PINCTRL_IRQEN(port->id)); 76 writel(1 << index,
77 port->base + PINCTRL_IRQEN(port->id) + MXS_CLR);
75 } 78 }
76} 79}
77 80
78static void mxs_gpio_ack_irq(struct irq_data *d) 81static void mxs_gpio_ack_irq(struct irq_data *d)
79{ 82{
83 struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);
80 u32 gpio = irq_to_gpio(d->irq); 84 u32 gpio = irq_to_gpio(d->irq);
81 clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f); 85 clear_gpio_irqstatus(port, gpio & 0x1f);
82} 86}
83 87
84static void mxs_gpio_mask_irq(struct irq_data *d) 88static void mxs_gpio_mask_irq(struct irq_data *d)
85{ 89{
90 struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);
86 u32 gpio = irq_to_gpio(d->irq); 91 u32 gpio = irq_to_gpio(d->irq);
87 set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0); 92 set_gpio_irqenable(port, gpio & 0x1f, 0);
88} 93}
89 94
90static void mxs_gpio_unmask_irq(struct irq_data *d) 95static void mxs_gpio_unmask_irq(struct irq_data *d)
91{ 96{
97 struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);
92 u32 gpio = irq_to_gpio(d->irq); 98 u32 gpio = irq_to_gpio(d->irq);
93 set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1); 99 set_gpio_irqenable(port, gpio & 0x1f, 1);
94} 100}
95 101
96static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset); 102static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset);
@@ -99,7 +105,7 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
99{ 105{
100 u32 gpio = irq_to_gpio(d->irq); 106 u32 gpio = irq_to_gpio(d->irq);
101 u32 pin_mask = 1 << (gpio & 31); 107 u32 pin_mask = 1 << (gpio & 31);
102 struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32]; 108 struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);
103 void __iomem *pin_addr; 109 void __iomem *pin_addr;
104 int edge; 110 int edge;
105 111
@@ -123,16 +129,16 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
123 /* set level or edge */ 129 /* set level or edge */
124 pin_addr = port->base + PINCTRL_IRQLEV(port->id); 130 pin_addr = port->base + PINCTRL_IRQLEV(port->id);
125 if (edge & GPIO_INT_LEV_MASK) 131 if (edge & GPIO_INT_LEV_MASK)
126 __mxs_setl(pin_mask, pin_addr); 132 writel(pin_mask, pin_addr + MXS_SET);
127 else 133 else
128 __mxs_clrl(pin_mask, pin_addr); 134 writel(pin_mask, pin_addr + MXS_CLR);
129 135
130 /* set polarity */ 136 /* set polarity */
131 pin_addr = port->base + PINCTRL_IRQPOL(port->id); 137 pin_addr = port->base + PINCTRL_IRQPOL(port->id);
132 if (edge & GPIO_INT_POL_MASK) 138 if (edge & GPIO_INT_POL_MASK)
133 __mxs_setl(pin_mask, pin_addr); 139 writel(pin_mask, pin_addr + MXS_SET);
134 else 140 else
135 __mxs_clrl(pin_mask, pin_addr); 141 writel(pin_mask, pin_addr + MXS_CLR);
136 142
137 clear_gpio_irqstatus(port, gpio & 0x1f); 143 clear_gpio_irqstatus(port, gpio & 0x1f);
138 144
@@ -143,13 +149,13 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
143static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) 149static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
144{ 150{
145 u32 irq_stat; 151 u32 irq_stat;
146 struct mxs_gpio_port *port = (struct mxs_gpio_port *)irq_get_handler_data(irq); 152 struct mxs_gpio_port *port = irq_get_handler_data(irq);
147 u32 gpio_irq_no_base = port->virtual_irq_start; 153 u32 gpio_irq_no_base = port->virtual_irq_start;
148 154
149 desc->irq_data.chip->irq_ack(&desc->irq_data); 155 desc->irq_data.chip->irq_ack(&desc->irq_data);
150 156
151 irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) & 157 irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) &
152 __raw_readl(port->base + PINCTRL_IRQEN(port->id)); 158 readl(port->base + PINCTRL_IRQEN(port->id));
153 159
154 while (irq_stat != 0) { 160 while (irq_stat != 0) {
155 int irqoffset = fls(irq_stat) - 1; 161 int irqoffset = fls(irq_stat) - 1;
@@ -171,7 +177,7 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
171{ 177{
172 u32 gpio = irq_to_gpio(d->irq); 178 u32 gpio = irq_to_gpio(d->irq);
173 u32 gpio_idx = gpio & 0x1f; 179 u32 gpio_idx = gpio & 0x1f;
174 struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32]; 180 struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);
175 181
176 if (enable) { 182 if (enable) {
177 if (port->irq_high && (gpio_idx >= 16)) 183 if (port->irq_high && (gpio_idx >= 16))
@@ -205,9 +211,9 @@ static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset,
205 void __iomem *pin_addr = port->base + PINCTRL_DOE(port->id); 211 void __iomem *pin_addr = port->base + PINCTRL_DOE(port->id);
206 212
207 if (dir) 213 if (dir)
208 __mxs_setl(1 << offset, pin_addr); 214 writel(1 << offset, pin_addr + MXS_SET);
209 else 215 else
210 __mxs_clrl(1 << offset, pin_addr); 216 writel(1 << offset, pin_addr + MXS_CLR);
211} 217}
212 218
213static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset) 219static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -215,7 +221,7 @@ static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset)
215 struct mxs_gpio_port *port = 221 struct mxs_gpio_port *port =
216 container_of(chip, struct mxs_gpio_port, chip); 222 container_of(chip, struct mxs_gpio_port, chip);
217 223
218 return (__raw_readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1; 224 return (readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1;
219} 225}
220 226
221static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 227static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -225,9 +231,9 @@ static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
225 void __iomem *pin_addr = port->base + PINCTRL_DOUT(port->id); 231 void __iomem *pin_addr = port->base + PINCTRL_DOUT(port->id);
226 232
227 if (value) 233 if (value)
228 __mxs_setl(1 << offset, pin_addr); 234 writel(1 << offset, pin_addr + MXS_SET);
229 else 235 else
230 __mxs_clrl(1 << offset, pin_addr); 236 writel(1 << offset, pin_addr + MXS_CLR);
231} 237}
232 238
233static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 239static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -252,87 +258,113 @@ static int mxs_gpio_direction_output(struct gpio_chip *chip,
252 return 0; 258 return 0;
253} 259}
254 260
255int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt) 261static int __devinit mxs_gpio_probe(struct platform_device *pdev)
256{ 262{
257 int i, j; 263 static void __iomem *base;
264 struct mxs_gpio_port *port;
265 struct resource *iores = NULL;
266 int err, i;
267
268 port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL);
269 if (!port)
270 return -ENOMEM;
271
272 port->id = pdev->id;
273 port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32;
274
275 /*
276 * map memory region only once, as all the gpio ports
277 * share the same one
278 */
279 if (!base) {
280 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
281 if (!iores) {
282 err = -ENODEV;
283 goto out_kfree;
284 }
258 285
259 /* save for local usage */ 286 if (!request_mem_region(iores->start, resource_size(iores),
260 mxs_gpio_ports = port; 287 pdev->name)) {
261 gpio_table_size = cnt; 288 err = -EBUSY;
289 goto out_kfree;
290 }
262 291
263 pr_info("MXS GPIO hardware\n"); 292 base = ioremap(iores->start, resource_size(iores));
293 if (!base) {
294 err = -ENOMEM;
295 goto out_release_mem;
296 }
297 }
298 port->base = base;
264 299
265 for (i = 0; i < cnt; i++) { 300 port->irq = platform_get_irq(pdev, 0);
266 /* disable the interrupt and clear the status */ 301 if (port->irq < 0) {
267 __raw_writel(0, port[i].base + PINCTRL_PIN2IRQ(i)); 302 err = -EINVAL;
268 __raw_writel(0, port[i].base + PINCTRL_IRQEN(i)); 303 goto out_iounmap;
304 }
269 305
270 /* clear address has to be used to clear IRQSTAT bits */ 306 /* disable the interrupt and clear the status */
271 __mxs_clrl(~0U, port[i].base + PINCTRL_IRQSTAT(i)); 307 writel(0, port->base + PINCTRL_PIN2IRQ(port->id));
308 writel(0, port->base + PINCTRL_IRQEN(port->id));
272 309
273 for (j = port[i].virtual_irq_start; 310 /* clear address has to be used to clear IRQSTAT bits */
274 j < port[i].virtual_irq_start + 32; j++) { 311 writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
275 irq_set_chip_and_handler(j, &gpio_irq_chip,
276 handle_level_irq);
277 set_irq_flags(j, IRQF_VALID);
278 }
279 312
280 /* setup one handler for each entry */ 313 for (i = port->virtual_irq_start;
281 irq_set_chained_handler(port[i].irq, mxs_gpio_irq_handler); 314 i < port->virtual_irq_start + 32; i++) {
282 irq_set_handler_data(port[i].irq, &port[i]); 315 irq_set_chip_and_handler(i, &gpio_irq_chip,
283 316 handle_level_irq);
284 /* register gpio chip */ 317 set_irq_flags(i, IRQF_VALID);
285 port[i].chip.direction_input = mxs_gpio_direction_input; 318 irq_set_chip_data(i, port);
286 port[i].chip.direction_output = mxs_gpio_direction_output;
287 port[i].chip.get = mxs_gpio_get;
288 port[i].chip.set = mxs_gpio_set;
289 port[i].chip.to_irq = mxs_gpio_to_irq;
290 port[i].chip.base = i * 32;
291 port[i].chip.ngpio = 32;
292
293 /* its a serious configuration bug when it fails */
294 BUG_ON(gpiochip_add(&port[i].chip) < 0);
295 } 319 }
296 320
297 return 0; 321 /* setup one handler for each entry */
298} 322 irq_set_chained_handler(port->irq, mxs_gpio_irq_handler);
323 irq_set_handler_data(port->irq, port);
299 324
300#define MX23_GPIO_BASE MX23_IO_ADDRESS(MX23_PINCTRL_BASE_ADDR) 325 /* register gpio chip */
301#define MX28_GPIO_BASE MX28_IO_ADDRESS(MX28_PINCTRL_BASE_ADDR) 326 port->chip.direction_input = mxs_gpio_direction_input;
327 port->chip.direction_output = mxs_gpio_direction_output;
328 port->chip.get = mxs_gpio_get;
329 port->chip.set = mxs_gpio_set;
330 port->chip.to_irq = mxs_gpio_to_irq;
331 port->chip.base = port->id * 32;
332 port->chip.ngpio = 32;
302 333
303#define DEFINE_MXS_GPIO_PORT(_base, _irq, _id) \ 334 err = gpiochip_add(&port->chip);
304 { \ 335 if (err)
305 .chip.label = "gpio-" #_id, \ 336 goto out_iounmap;
306 .id = _id, \
307 .irq = _irq, \
308 .base = _base, \
309 .virtual_irq_start = MXS_GPIO_IRQ_START + (_id) * 32, \
310 }
311 337
312#ifdef CONFIG_SOC_IMX23 338 return 0;
313static struct mxs_gpio_port mx23_gpio_ports[] = {
314 DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO0, 0),
315 DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO1, 1),
316 DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO2, 2),
317};
318 339
319int __init mx23_register_gpios(void) 340out_iounmap:
320{ 341 if (iores)
321 return mxs_gpio_init(mx23_gpio_ports, ARRAY_SIZE(mx23_gpio_ports)); 342 iounmap(port->base);
343out_release_mem:
344 if (iores)
345 release_mem_region(iores->start, resource_size(iores));
346out_kfree:
347 kfree(port);
348 dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
349 return err;
322} 350}
323#endif 351
324 352static struct platform_driver mxs_gpio_driver = {
325#ifdef CONFIG_SOC_IMX28 353 .driver = {
326static struct mxs_gpio_port mx28_gpio_ports[] = { 354 .name = "gpio-mxs",
327 DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO0, 0), 355 .owner = THIS_MODULE,
328 DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO1, 1), 356 },
329 DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO2, 2), 357 .probe = mxs_gpio_probe,
330 DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO3, 3),
331 DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO4, 4),
332}; 358};
333 359
334int __init mx28_register_gpios(void) 360static int __init mxs_gpio_init(void)
335{ 361{
336 return mxs_gpio_init(mx28_gpio_ports, ARRAY_SIZE(mx28_gpio_ports)); 362 return platform_driver_register(&mxs_gpio_driver);
337} 363}
338#endif 364postcore_initcall(mxs_gpio_init);
365
366MODULE_AUTHOR("Freescale Semiconductor, "
367 "Daniel Mack <danielncaiaq.de>, "
368 "Juergen Beisert <kernel@pengutronix.de>");
369MODULE_DESCRIPTION("Freescale MXS GPIO");
370MODULE_LICENSE("GPL");