add gpiolib support
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
This commit is contained in:
parent
f64bd3d932
commit
2f8fe26382
|
@ -17,3 +17,4 @@ obj-$(CONFIG_PWM) += pwm/
|
|||
obj-y += input/
|
||||
obj-y += dma/
|
||||
obj-y += watchdog/
|
||||
obj-y += gpio/
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
config GPIOLIB
|
||||
bool
|
|
@ -0,0 +1 @@
|
|||
obj-$(CONFIG_GPIOLIB) += gpio.o
|
|
@ -0,0 +1,134 @@
|
|||
#include <common.h>
|
||||
#include <gpio.h>
|
||||
#include <errno.h>
|
||||
|
||||
static LIST_HEAD(chip_list);
|
||||
|
||||
#define ARCH_NR_GPIOS 256
|
||||
|
||||
static struct gpio_chip *gpio_desc[ARCH_NR_GPIOS];
|
||||
|
||||
static int gpio_is_valid(unsigned gpio)
|
||||
{
|
||||
if (gpio < ARCH_NR_GPIOS)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpio_set_value(unsigned gpio, int value)
|
||||
{
|
||||
struct gpio_chip *chip = gpio_desc[gpio];
|
||||
|
||||
if (!gpio_is_valid(gpio))
|
||||
return;
|
||||
if (!chip)
|
||||
return;
|
||||
if (!chip->ops->set)
|
||||
return;
|
||||
chip->ops->set(chip, gpio - chip->base, value);
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_set_value);
|
||||
|
||||
int gpio_get_value(unsigned gpio)
|
||||
{
|
||||
struct gpio_chip *chip = gpio_desc[gpio];
|
||||
|
||||
if (!gpio_is_valid(gpio))
|
||||
return -EINVAL;
|
||||
if (!chip)
|
||||
return -ENODEV;
|
||||
if (!chip->ops->get)
|
||||
return -ENOSYS;
|
||||
return chip->ops->get(chip, gpio - chip->base);
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_get_value);
|
||||
|
||||
int gpio_direction_output(unsigned gpio, int value)
|
||||
{
|
||||
struct gpio_chip *chip = gpio_desc[gpio];
|
||||
|
||||
if (!gpio_is_valid(gpio))
|
||||
return -EINVAL;
|
||||
if (!chip)
|
||||
return -ENODEV;
|
||||
if (!chip->ops->direction_output)
|
||||
return -ENOSYS;
|
||||
return chip->ops->direction_output(chip, gpio - chip->base, value);
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_direction_output);
|
||||
|
||||
int gpio_direction_input(unsigned gpio)
|
||||
{
|
||||
struct gpio_chip *chip = gpio_desc[gpio];
|
||||
|
||||
if (!gpio_is_valid(gpio))
|
||||
return -EINVAL;
|
||||
if (!chip)
|
||||
return -ENODEV;
|
||||
if (!chip->ops->direction_input)
|
||||
return -ENOSYS;
|
||||
return chip->ops->direction_input(chip, gpio - chip->base);
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_direction_input);
|
||||
|
||||
static int gpiochip_find_base(int start, int ngpio)
|
||||
{
|
||||
int i;
|
||||
int spare = 0;
|
||||
int base = -ENOSPC;
|
||||
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
|
||||
for (i = start; i < ARCH_NR_GPIOS; i++) {
|
||||
struct gpio_chip *chip = gpio_desc[i];
|
||||
|
||||
if (!chip) {
|
||||
spare++;
|
||||
if (spare == ngpio) {
|
||||
base = i + 1 - ngpio;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
spare = 0;
|
||||
i += chip->ngpio - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpio_is_valid(base))
|
||||
debug("%s: found new base at %d\n", __func__, base);
|
||||
return base;
|
||||
}
|
||||
|
||||
int gpiochip_add(struct gpio_chip *chip)
|
||||
{
|
||||
int base, i;
|
||||
|
||||
base = gpiochip_find_base(chip->base, chip->ngpio);
|
||||
if (base < 0)
|
||||
return base;
|
||||
|
||||
if (chip->base >= 0 && chip->base != base)
|
||||
return -EBUSY;
|
||||
|
||||
chip->base = base;
|
||||
|
||||
list_add_tail(&chip->list, &chip_list);
|
||||
|
||||
for (i = chip->base; i < chip->base + chip->ngpio; i++)
|
||||
gpio_desc[i] = chip;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_get_num(struct device_d *dev, int gpio)
|
||||
{
|
||||
struct gpio_chip *chip;
|
||||
|
||||
list_for_each_entry(chip, &chip_list, list) {
|
||||
if (chip->dev == dev)
|
||||
return chip->base + gpio;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
|
@ -5,10 +5,35 @@
|
|||
|
||||
static inline int gpio_request(unsigned gpio, const char *label)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void gpio_free(unsigned gpio)
|
||||
{
|
||||
}
|
||||
|
||||
struct gpio_chip;
|
||||
|
||||
struct gpio_ops {
|
||||
int (*direction_input)(struct gpio_chip *chip, unsigned offset);
|
||||
int (*direction_output)(struct gpio_chip *chip, unsigned offset, int value);
|
||||
int (*get)(struct gpio_chip *chip, unsigned offset);
|
||||
void (*set)(struct gpio_chip *chip, unsigned offset, int value);
|
||||
};
|
||||
|
||||
struct gpio_chip {
|
||||
struct device_d *dev;
|
||||
|
||||
int base;
|
||||
int ngpio;
|
||||
|
||||
struct gpio_ops *ops;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
int gpiochip_add(struct gpio_chip *chip);
|
||||
|
||||
int gpio_get_num(struct device_d *dev, int gpio);
|
||||
|
||||
#endif /* __GPIO_H */
|
||||
|
|
Loading…
Reference in New Issue