Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 118 additions & 34 deletions drivers/gpio/gpio_stellaris.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ struct gpio_stellaris_runtime {
#define GPIO_RW_ADDR(base, offset, p) \
(GPIO_REG_ADDR(base, offset) | (1 << (p + 2)))

#define GPIO_RW_MASK_ADDR(base, offset, mask) \
(GPIO_REG_ADDR(base, offset) | (mask << 2))

enum gpio_regs {
GPIO_DATA_OFFSET = 0x000,
GPIO_DIR_OFFSET = 0x400,
Expand Down Expand Up @@ -80,9 +83,12 @@ static int gpio_stellaris_configure(struct device *dev, int access_op,
u32_t base = cfg->base;
u32_t port_map = cfg->port_map;

/* Check for an invalid pin configuration */
if ((flags & GPIO_INT) && (flags & GPIO_DIR_OUT)) {
return -EINVAL;
if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0) {
return -ENOTSUP;
}

if ((flags & GPIO_SINGLE_ENDED) != 0) {
return -ENOTSUP;
}

/* Supports access by pin now,you can add access by port when needed */
Expand All @@ -95,42 +101,27 @@ static int gpio_stellaris_configure(struct device *dev, int access_op,
return -EINVAL;
}

/* Pin digital enable */
sys_set_bit(GPIO_REG_ADDR(base, GPIO_DEN_OFFSET), pin);
if ((flags & GPIO_OUTPUT) != 0) {
mm_reg_t mask_addr;

/* Input-0,output-1 */
if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) {
mask_addr = GPIO_RW_MASK_ADDR(base, GPIO_DATA_OFFSET, BIT(pin));
if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
sys_write32(BIT(pin), mask_addr);
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
sys_write32(0, mask_addr);
}
sys_set_bit(GPIO_REG_ADDR(base, GPIO_DIR_OFFSET), pin);
/* Pin digital enable */
sys_set_bit(GPIO_REG_ADDR(base, GPIO_DEN_OFFSET), pin);
} else if ((flags & GPIO_INPUT) != 0) {
sys_clear_bit(GPIO_REG_ADDR(base, GPIO_DIR_OFFSET), pin);
/* Pin digital enable */
sys_set_bit(GPIO_REG_ADDR(base, GPIO_DEN_OFFSET), pin);
} else {
sys_set_bit(GPIO_REG_ADDR(base, GPIO_DIR_OFFSET), pin);
/* Pin digital disable */
sys_clear_bit(GPIO_REG_ADDR(base, GPIO_DEN_OFFSET), pin);
}

/* Check if GPIO port needs interrupt support */
if (flags & GPIO_INT) {

/* GPIO interrupt edge trigger enable or level trigger enable */
if (flags & GPIO_INT_EDGE) {
sys_clear_bit(GPIO_REG_ADDR(base, GPIO_IS_OFFSET), pin);
} else {
sys_set_bit(GPIO_REG_ADDR(base, GPIO_IS_OFFSET), pin);
}

/* GPIO interrupt both edge sense */
if (flags & GPIO_INT_DOUBLE_EDGE) {
sys_set_bit(GPIO_REG_ADDR(base, GPIO_IBE_OFFSET), pin);
}

/*
* GPIO interrupt rising edge & high level enable or
* falling edge & low level enable
*/
if (flags & GPIO_INT_ACTIVE_HIGH) {
sys_set_bit(GPIO_REG_ADDR(base, GPIO_IEV_OFFSET), pin);
} else {
sys_clear_bit(GPIO_REG_ADDR(base,
GPIO_IEV_OFFSET), pin);
}
}
return 0;
}

Expand Down Expand Up @@ -172,6 +163,93 @@ static int gpio_stellaris_read(struct device *dev,
return 0;
}

static int gpio_stellaris_port_get_raw(struct device *dev, u32_t *value)
{
const struct gpio_stellaris_config *cfg = DEV_CFG(dev);
u32_t base = cfg->base;

*value = sys_read32(GPIO_RW_MASK_ADDR(base, GPIO_DATA_OFFSET, 0xff));

return 0;
}

static int gpio_stellaris_port_set_masked_raw(struct device *dev, u32_t mask,
u32_t value)
{
const struct gpio_stellaris_config *cfg = DEV_CFG(dev);
u32_t base = cfg->base;

sys_write32(value, GPIO_RW_MASK_ADDR(base, GPIO_DATA_OFFSET, mask));

return 0;
}

static int gpio_stellaris_port_set_bits_raw(struct device *dev, u32_t mask)
{
const struct gpio_stellaris_config *cfg = DEV_CFG(dev);
u32_t base = cfg->base;

sys_write32(mask, GPIO_RW_MASK_ADDR(base, GPIO_DATA_OFFSET, mask));

return 0;
}

static int gpio_stellaris_port_clear_bits_raw(struct device *dev, u32_t mask)
{
const struct gpio_stellaris_config *cfg = DEV_CFG(dev);
u32_t base = cfg->base;

sys_write32(0, GPIO_RW_MASK_ADDR(base, GPIO_DATA_OFFSET, mask));

return 0;
}

static int gpio_stellaris_port_toggle_bits(struct device *dev, u32_t mask)
{
const struct gpio_stellaris_config *cfg = DEV_CFG(dev);
u32_t base = cfg->base;
u32_t value;

value = sys_read32(GPIO_RW_MASK_ADDR(base, GPIO_DATA_OFFSET, 0xff));
value ^= mask;
sys_write32(value, GPIO_RW_MASK_ADDR(base, GPIO_DATA_OFFSET, 0xff));

return 0;
}

static int gpio_stellaris_pin_interrupt_configure(struct device *dev,
unsigned int pin, enum gpio_int_mode mode,
enum gpio_int_trig trig)
{
const struct gpio_stellaris_config *cfg = DEV_CFG(dev);
u32_t base = cfg->base;

/* Check if GPIO port needs interrupt support */
if (mode == GPIO_INT_MODE_DISABLED) {
/* Set the mask to disable the interrupt */
sys_set_bit(GPIO_REG_ADDR(base, GPIO_IM_OFFSET), pin);
} else {
if (mode == GPIO_INT_MODE_EDGE) {
sys_clear_bit(GPIO_REG_ADDR(base, GPIO_IS_OFFSET), pin);
} else {
sys_set_bit(GPIO_REG_ADDR(base, GPIO_IS_OFFSET), pin);
}

if (trig == GPIO_INT_TRIG_BOTH) {
sys_set_bit(GPIO_REG_ADDR(base, GPIO_IBE_OFFSET), pin);
} else if (trig == GPIO_INT_TRIG_HIGH) {
sys_set_bit(GPIO_REG_ADDR(base, GPIO_IEV_OFFSET), pin);
} else {
sys_clear_bit(GPIO_REG_ADDR(base,
GPIO_IEV_OFFSET), pin);
}
/* Clear the Mask to enable the interrupt */
sys_clear_bit(GPIO_REG_ADDR(base, GPIO_IM_OFFSET), pin);
}

return 0;
}

static int gpio_stellaris_init(struct device *dev)
{
const struct gpio_stellaris_config *cfg = DEV_CFG(dev);
Expand Down Expand Up @@ -225,6 +303,12 @@ static const struct gpio_driver_api gpio_stellaris_driver_api = {
.config = gpio_stellaris_configure,
.write = gpio_stellaris_write,
.read = gpio_stellaris_read,
.port_get_raw = gpio_stellaris_port_get_raw,
.port_set_masked_raw = gpio_stellaris_port_set_masked_raw,
.port_set_bits_raw = gpio_stellaris_port_set_bits_raw,
.port_clear_bits_raw = gpio_stellaris_port_clear_bits_raw,
.port_toggle_bits = gpio_stellaris_port_toggle_bits,
.pin_interrupt_configure = gpio_stellaris_pin_interrupt_configure,
.manage_callback = gpio_stellaris_manage_callback,
.enable_callback = gpio_stellaris_enable_callback,
.disable_callback = gpio_stellaris_disable_callback,
Expand Down