diff options
author | Hauke Mehrtens <hauke@hauke-m.de> | 2012-11-20 22:24:30 +0000 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2012-11-21 21:55:52 +0100 |
commit | cf0936b06d8e98a157630e99f647e2ff6d29d7ad (patch) | |
tree | 651457e034e073d236e9b0e64e0008e4ed2e0150 /drivers/bcma/driver_gpio.c | |
parent | 3e8bb507edfb44dfb8b0e06574826e34a8f6291d (diff) |
bcma: add GPIO driver
Register a GPIO driver to access the GPIOs provided by the chip.
The GPIOs of the SoC should always start at 0 and the other GPIOs could
start at a random position. There is just one SoC in a system and when
they start at 0 the number is predictable.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Patchwork: http://patchwork.linux-mips.org/patch/4587
Acked-by: Florian Fainelli <florian@openwrt.org>
Diffstat (limited to 'drivers/bcma/driver_gpio.c')
-rw-r--r-- | drivers/bcma/driver_gpio.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c new file mode 100644 index 000000000000..9a6f585da2d9 --- /dev/null +++ b/drivers/bcma/driver_gpio.c @@ -0,0 +1,98 @@ +/* + * Broadcom specific AMBA + * GPIO driver + * + * Copyright 2011, Broadcom Corporation + * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include <linux/gpio.h> +#include <linux/export.h> +#include <linux/bcma/bcma.h> + +#include "bcma_private.h" + +static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip) +{ + return container_of(chip, struct bcma_drv_cc, gpio); +} + +static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio) +{ + struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); + + return !!bcma_chipco_gpio_in(cc, 1 << gpio); +} + +static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio, + int value) +{ + struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); + + bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0); +} + +static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +{ + struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); + + bcma_chipco_gpio_outen(cc, 1 << gpio, 0); + return 0; +} + +static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, + int value) +{ + struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); + + bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio); + bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0); + return 0; +} + +static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio) +{ + struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); + + bcma_chipco_gpio_control(cc, 1 << gpio, 0); + /* clear pulldown */ + bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0); + /* Set pullup */ + bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio); + + return 0; +} + +static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio) +{ + struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); + + /* clear pullup */ + bcma_chipco_gpio_pullup(cc, 1 << gpio, 0); +} + +int bcma_gpio_init(struct bcma_drv_cc *cc) +{ + struct gpio_chip *chip = &cc->gpio; + + chip->label = "bcma_gpio"; + chip->owner = THIS_MODULE; + chip->request = bcma_gpio_request; + chip->free = bcma_gpio_free; + chip->get = bcma_gpio_get_value; + chip->set = bcma_gpio_set_value; + chip->direction_input = bcma_gpio_direction_input; + chip->direction_output = bcma_gpio_direction_output; + chip->ngpio = 16; + /* There is just one SoC in one device and its GPIO addresses should be + * deterministic to address them more easily. The other buses could get + * a random base number. */ + if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC) + chip->base = 0; + else + chip->base = -1; + + return gpiochip_add(chip); +} |