Skip to content

Commit

Permalink
gpio/pl061: add get/set interrupt and mode control functions
Browse files Browse the repository at this point in the history
Signed-off-by: Victor Chong <victor.chong@linaro.org>
Reviewed-by: David Brown <david.brown@linaro.org>
Reviewed-by: Jerome Forissier <jerome.forissier@linaro.org>
  • Loading branch information
Victor Chong committed Jul 28, 2016
1 parent bbab0cd commit f1d7853
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 4 deletions.
81 changes: 77 additions & 4 deletions core/drivers/pl061_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,41 @@ static void pl061_set_value(unsigned int gpio_pin, enum gpio_level value)
write8(0, base_addr + BIT(offset + 2));
}

static enum gpio_interrupt pl061_get_interrupt(unsigned int gpio_pin)
{
vaddr_t base_addr;
uint8_t data;
unsigned int offset;

assert(gpio_pin < PLAT_PL061_MAX_GPIOS);

base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061];
offset = gpio_pin % GPIOS_PER_PL061;
data = read8(base_addr + GPIOIE);
if (data & BIT(offset))
return GPIO_INTERRUPT_ENABLE;
return GPIO_INTERRUPT_DISABLE;
}

static void pl061_set_interrupt(unsigned int gpio_pin,
enum gpio_interrupt ena_dis)
{
vaddr_t base_addr;
uint8_t data;
unsigned int offset;

assert(gpio_pin < PLAT_PL061_MAX_GPIOS);

base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061];
offset = gpio_pin % GPIOS_PER_PL061;
if (ena_dis == GPIO_INTERRUPT_ENABLE) {
data = read8(base_addr + GPIOIE) | BIT(offset);
write8(data, base_addr + GPIOIE);
} else {
data = read8(base_addr + GPIOIE) & ~BIT(offset);
write8(data, base_addr + GPIOIE);
}
}

/*
* Register the PL061 GPIO controller with a base address and the offset
Expand All @@ -152,10 +187,12 @@ void pl061_register(vaddr_t base_addr, unsigned int gpio_dev)
}

static const struct gpio_ops pl061_ops = {
.get_direction = pl061_get_direction,
.set_direction = pl061_set_direction,
.get_value = pl061_get_value,
.set_value = pl061_set_value,
.get_direction = pl061_get_direction,
.set_direction = pl061_set_direction,
.get_value = pl061_get_value,
.set_value = pl061_set_value,
.get_interrupt = pl061_get_interrupt,
.set_interrupt = pl061_set_interrupt,
};

/*
Expand All @@ -168,3 +205,39 @@ void pl061_init(struct pl061_data *pd)
assert(pd);
pd->chip.ops = &pl061_ops;
}

enum pl061_mode_control pl061_get_mode_control(unsigned int gpio_pin)
{
vaddr_t base_addr;
uint8_t data;
unsigned int offset;

assert(gpio_pin < PLAT_PL061_MAX_GPIOS);

base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061];
offset = gpio_pin % GPIOS_PER_PL061;
data = read8(base_addr + GPIOAFSEL);
if (data & BIT(offset))
return PL061_MC_HW;
return PL061_MC_SW;
}

void pl061_set_mode_control(unsigned int gpio_pin,
enum pl061_mode_control hw_sw)
{
vaddr_t base_addr;
uint8_t data;
unsigned int offset;

assert(gpio_pin < PLAT_PL061_MAX_GPIOS);

base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061];
offset = gpio_pin % GPIOS_PER_PL061;
if (hw_sw == PL061_MC_HW) {
data = read8(base_addr + GPIOAFSEL) | BIT(offset);
write8(data, base_addr + GPIOAFSEL);
} else {
data = read8(base_addr + GPIOAFSEL) & ~BIT(offset);
write8(data, base_addr + GPIOAFSEL);
}
}
8 changes: 8 additions & 0 deletions core/include/drivers/pl061_gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,19 @@

#define PL061_REG_SIZE 0x1000

enum pl061_mode_control {
PL061_MC_SW,
PL061_MC_HW
};

struct pl061_data {
struct gpio_chip chip;
};

void pl061_register(vaddr_t base_addr, unsigned int gpio_dev);
void pl061_init(struct pl061_data *pd);
enum pl061_mode_control pl061_get_mode_control(unsigned int gpio_pin);
void pl061_set_mode_control(unsigned int gpio_pin,
enum pl061_mode_control hw_sw);

#endif /* __PL061_GPIO_H__ */
8 changes: 8 additions & 0 deletions core/include/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ enum gpio_level {
GPIO_LEVEL_HIGH
};

enum gpio_interrupt {
GPIO_INTERRUPT_DISABLE,
GPIO_INTERRUPT_ENABLE
};

struct gpio_chip {
const struct gpio_ops *ops;
};
Expand All @@ -47,6 +52,9 @@ struct gpio_ops {
void (*set_direction)(unsigned int gpio_pin, enum gpio_dir direction);
enum gpio_level (*get_value)(unsigned int gpio_pin);
void (*set_value)(unsigned int gpio_pin, enum gpio_level value);
enum gpio_interrupt (*get_interrupt)(unsigned int gpio_pin);
void (*set_interrupt)(unsigned int gpio_pin,
enum gpio_interrupt ena_dis);
};

#endif /* __GPIO_H__ */

0 comments on commit f1d7853

Please sign in to comment.