summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2013-12-06 08:22:48 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2013-12-06 08:22:48 +0100
commit2789ccd18ffe32371a41b126d5ac02f9885a015c (patch)
treeea6a27ed4ee176c4cf7788aee4f19848bec5de8b
parentcac8f8deb4fd1cdfb64397301830a62a1649ff40 (diff)
parentbcf08772662c47ff69b253c44ac2415507fb9a93 (diff)
downloadbarebox-2789ccd18ffe32371a41b126d5ac02f9885a015c.tar.gz
barebox-2789ccd18ffe32371a41b126d5ac02f9885a015c.tar.xz
Merge branch 'for-next/gpio'
-rw-r--r--drivers/gpio/gpio-dw.c9
-rw-r--r--drivers/gpio/gpiolib.c90
-rw-r--r--drivers/led/led-gpio.c4
-rw-r--r--include/gpio.h43
4 files changed, 142 insertions, 4 deletions
diff --git a/drivers/gpio/gpio-dw.c b/drivers/gpio/gpio-dw.c
index 791488a19d..e46cc8e129 100644
--- a/drivers/gpio/gpio-dw.c
+++ b/drivers/gpio/gpio-dw.c
@@ -90,9 +90,18 @@ static int dw_gpio_direction_output(struct gpio_chip *gc,
return 0;
}
+static int dw_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
+{
+ struct dw_gpio_instance *chip = to_dw_gpio(gc);
+
+ return (readl(chip->regs + DW_GPIO_DDR) & (1 << offset)) ?
+ GPIOF_DIR_OUT : GPIOF_DIR_IN;
+}
+
static struct gpio_ops imx_gpio_ops = {
.direction_input = dw_gpio_direction_input,
.direction_output = dw_gpio_direction_output,
+ .get_direction = dw_gpio_get_direction,
.get = dw_gpio_get,
.set = dw_gpio_set,
};
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index ca6e8adab4..cafef907ef 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -85,6 +85,72 @@ void gpio_free(unsigned gpio)
free(gi->label);
}
+/**
+ * gpio_request_one - request a single GPIO with initial configuration
+ * @gpio: the GPIO number
+ * @flags: GPIO configuration as specified by GPIOF_*
+ * @label: a literal description string of this GPIO
+ */
+int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
+{
+ int err;
+
+ err = gpio_request(gpio, label);
+ if (err)
+ return err;
+
+ if (flags & GPIOF_DIR_IN)
+ err = gpio_direction_input(gpio);
+ else
+ err = gpio_direction_output(gpio,
+ (flags & GPIOF_INIT_HIGH) ? 1 : 0);
+
+ if (err)
+ goto free_gpio;
+
+ return 0;
+
+ free_gpio:
+ gpio_free(gpio);
+ return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_one);
+
+/**
+ * gpio_request_array - request multiple GPIOs in a single call
+ * @array: array of the 'struct gpio'
+ * @num: how many GPIOs in the array
+ */
+int gpio_request_array(const struct gpio *array, size_t num)
+{
+ int i, err;
+
+ for (i = 0; i < num; i++, array++) {
+ err = gpio_request_one(array->gpio, array->flags, array->label);
+ if (err)
+ goto err_free;
+ }
+ return 0;
+
+err_free:
+ while (i--)
+ gpio_free((--array)->gpio);
+ return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_array);
+
+/**
+ * gpio_free_array - release multiple GPIOs in a single call
+ * @array: array of the 'struct gpio'
+ * @num: how many GPIOs in the array
+ */
+void gpio_free_array(const struct gpio *array, size_t num)
+{
+ while (num--)
+ gpio_free((array++)->gpio);
+}
+EXPORT_SYMBOL_GPL(gpio_free_array);
+
void gpio_set_value(unsigned gpio, int value)
{
struct gpio_info *gi = gpio_to_desc(gpio);
@@ -228,16 +294,34 @@ static int do_gpiolib(int argc, char *argv[])
int i;
printf("gpiolib: gpio lists\n");
- printf("%*crequested label\n", 11, ' ');
for (i = 0; i < ARCH_NR_GPIOS; i++) {
struct gpio_info *gi = &gpio_desc[i];
+ int val = -1, dir = -1;
if (!gi->chip)
continue;
- printf("gpio %*d: %*s %s\n", 4,
- i, 9, gi->requested ? "true" : "false",
+ /* print chip information and header on first gpio */
+ if (gi->chip->base == i) {
+ printf("\ngpios %u-%u, chip %s:\n",
+ gi->chip->base,
+ gi->chip->base + gi->chip->ngpio - 1,
+ gi->chip->dev->name);
+ printf("%*cdir val requested label\n", 13, ' ');
+ }
+
+ if (gi->chip->ops->get_direction)
+ dir = gi->chip->ops->get_direction(gi->chip,
+ i - gi->chip->base);
+ if (gi->chip->ops->get)
+ val = gi->chip->ops->get(gi->chip,
+ i - gi->chip->base);
+
+ printf(" gpio %*d: %*s %*s %*s %s\n", 4, i,
+ 3, (dir < 0) ? "unk" : ((dir == GPIOF_DIR_IN) ? "in" : "out"),
+ 3, (val < 0) ? "unk" : ((val == 0) ? "lo" : "hi"),
+ 9, gi->requested ? "true" : "false",
gi->label ? gi->label : "");
}
diff --git a/drivers/led/led-gpio.c b/drivers/led/led-gpio.c
index 69db70fab8..7a5ef473e6 100644
--- a/drivers/led/led-gpio.c
+++ b/drivers/led/led-gpio.c
@@ -225,6 +225,8 @@ static void led_of_parse_trigger(struct led *led, struct device_node *np)
for (i = 0; i < ARRAY_SIZE(triggers); i++) {
struct led_trg *trg = &triggers[i];
if (!strcmp(trg->str, trigger)) {
+ /* disable LED before installing trigger */
+ led_set(led, 0);
led_set_trigger(trg->trg, led);
return;
}
@@ -252,8 +254,8 @@ static int led_gpio_of_probe(struct device_d *dev)
dev_dbg(dev, "register led %s on gpio%d, active_low = %d\n",
gled->led.name, gled->gpio, gled->active_low);
- led_of_parse_trigger(&gled->led, child);
led_gpio_register(gled);
+ led_of_parse_trigger(&gled->led, child);
}
return 0;
diff --git a/include/gpio.h b/include/gpio.h
index 140d53c83e..4a97521aee 100644
--- a/include/gpio.h
+++ b/include/gpio.h
@@ -3,6 +3,28 @@
#include <asm/gpio.h>
+#define GPIOF_DIR_OUT (0 << 0)
+#define GPIOF_DIR_IN (1 << 0)
+
+#define GPIOF_INIT_LOW (0 << 1)
+#define GPIOF_INIT_HIGH (1 << 1)
+
+#define GPIOF_IN (GPIOF_DIR_IN)
+#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
+#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
+
+/**
+ * struct gpio - a structure describing a GPIO with configuration
+ * @gpio: the GPIO number
+ * @flags: GPIO configuration as specified by GPIOF_*
+ * @label: a literal description string of this GPIO
+ */
+struct gpio {
+ unsigned gpio;
+ unsigned long flags;
+ const char *label;
+};
+
#ifndef CONFIG_GPIOLIB
static inline int gpio_request(unsigned gpio, const char *label)
{
@@ -12,9 +34,29 @@ static inline int gpio_request(unsigned gpio, const char *label)
static inline void gpio_free(unsigned gpio)
{
}
+
+static inline int gpio_request_one(unsigned gpio,
+ unsigned long flags, const char *label)
+{
+ return -ENOSYS;
+}
+
+static inline int gpio_request_array(const struct gpio *array, size_t num)
+{
+ return -ENOSYS;
+}
+
+static inline void gpio_free_array(const struct gpio *array, size_t num)
+{
+ /* GPIO can never have been requested */
+ WARN_ON(1);
+}
#else
int gpio_request(unsigned gpio, const char *label);
void gpio_free(unsigned gpio);
+int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
+int gpio_request_array(const struct gpio *array, size_t num);
+void gpio_free_array(const struct gpio *array, size_t num);
#endif
struct gpio_chip;
@@ -24,6 +66,7 @@ struct gpio_ops {
void (*free)(struct gpio_chip *chip, unsigned offset);
int (*direction_input)(struct gpio_chip *chip, unsigned offset);
int (*direction_output)(struct gpio_chip *chip, unsigned offset, int value);
+ int (*get_direction)(struct gpio_chip *chip, unsigned offset);
int (*get)(struct gpio_chip *chip, unsigned offset);
void (*set)(struct gpio_chip *chip, unsigned offset, int value);
};