/* * Generic PXA GPIO handling * * Author: Nicolas Pitre * Created: Jun 15, 2001 * Copyright: MontaVista Software Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include int pxa_last_gpio; struct pxa_gpio_chip { void __iomem *regbase; }; static struct pxa_gpio_chip *pxa_gpio_chips; #define for_each_gpio_chip(i, c) \ for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) static int __init pxa_init_gpio_chip(int gpio_end) { int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; struct pxa_gpio_chip *chips; chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL); if (chips == NULL) { pr_err("%s: failed to allocate GPIO chips\n", __func__); return -ENOMEM; } for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) chips[i].regbase = (void __iomem *)GPIO_BANK(i); pxa_gpio_chips = chips; return 0; } int __init pxa_init_gpio(int start, int end) { struct pxa_gpio_chip *c; int err, gpio; pxa_last_gpio = end; /* Initialize GPIO chips */ err = pxa_init_gpio_chip(end); if (err) return err; for_each_gpio_chip(gpio, c) { /* clear all GPIO edge detects */ __raw_writel(0, c->regbase + GFER_OFFSET); __raw_writel(0, c->regbase + GRER_OFFSET); __raw_writel(~0, c->regbase + GEDR_OFFSET); } return 0; } int gpio_get_value(unsigned gpio) { return GPLR(gpio) & GPIO_bit(gpio); } void gpio_set_value(unsigned gpio, int value) { if (value) GPSR(gpio) = GPIO_bit(gpio); else GPCR(gpio) = GPIO_bit(gpio); } int gpio_direction_input(unsigned gpio) { if (__gpio_is_inverted(gpio)) GPDR(gpio) |= GPIO_bit(gpio); else GPDR(gpio) &= ~GPIO_bit(gpio); return 0; } int gpio_direction_output(unsigned gpio, int value) { gpio_set_value(gpio, value); if (__gpio_is_inverted(gpio)) GPDR(gpio) &= ~GPIO_bit(gpio); else GPDR(gpio) |= GPIO_bit(gpio); return 0; }