Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new gpio from pulp #186

Merged
merged 14 commits into from
Jan 20, 2023
Prev Previous commit
Next Next commit
update gpio driver
  • Loading branch information
davideschiavone committed Dec 15, 2022
commit 9539f90d391a0a58fb521f7261e360e3a63ec48e
200 changes: 66 additions & 134 deletions sw/device/lib/drivers/gpio/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,49 +16,6 @@
*/
static uint32_t index_to_mask(uint32_t index) { return 1u << index; }

/**
* Perform a masked write to a single bit of a GPIO register. (For the new GPIO)
*
* The GPIO device provides masked bit-level atomic writes to its DIRECT_OUT
* and DIRECT_OE registers. This allows software to modify half of the bits
* at a time without requiring a read-modify-write. This function is guaranteed
* to perform only one write since it never needs to access both halves of a
* register.
*
* See also `gpio_masked_write()`.
*
* @param gpio GPIO instance.
* @param reg_lower_offset Offset of the masked access register that corresponds
* to the lower half of the actual register.
* @param reg_upper_offset Offset of the masked access register that corresponds
* to the upper half of the actual register.
* @param index Zero-based index of the bit to write to.
* @param val Value to write.
*/
static gpio_result_t gpio_masked_bit_write(const gpio_t *gpio,
ptrdiff_t reg_offset,
uint32_t index, bool val) {
if (gpio == NULL) {
return kGpioBadArg;
}
uint32_t temp = mmio_region_read32(gpio->params.base_addr, reg_offset);
if (val == true){
uint32_t mask = index_to_mask(index);
uint32_t mask_val = mask | temp;
mmio_region_write32(gpio->params.base_addr, reg_offset,
mask_val);

}else{
uint32_t mask = index_to_mask(index);
mask = ~mask;
uint32_t mask_val = mask & temp;
mmio_region_write32(gpio->params.base_addr, reg_offset,
mask_val);
}

return kGpioOk;
}

gpio_result_t gpio_init(gpio_params_t params, gpio_t *gpio) {
if (gpio == NULL) {
return kGpioBadArg;
Expand All @@ -74,32 +31,21 @@ gpio_result_t gpio_reset(const gpio_t *gpio) {
return kGpioBadArg;
}

// We don't need to write to `GPIO_MASKED_OE_*` and `GPIO_MASKED_OUT_*`
// since we directly reset `GPIO_DIRECT_OE` and `GPIO_DIRECT_OUT` below.
mmio_region_write32(gpio->params.base_addr, GPIO_GPIO_EN_OFFSET, 0);
mmio_region_write32(gpio->params.base_addr, GPIO_DATA_IN_REG_OFFSET, 0);
mmio_region_write32(gpio->params.base_addr, GPIO_DIRECT_OUT_REG_OFFSET, 0);
// Clear all the interrupt enable
mmio_region_write32(gpio->params.base_addr,
GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, 0);
mmio_region_write32(gpio->params.base_addr,
GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, 0);
mmio_region_write32(gpio->params.base_addr,
GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET, 0);
GPIO_CFG_REG_OFFSET, 0);
mmio_region_write32(gpio->params.base_addr,
GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, 0);
// Also clear all the interrupt
GPIO_GPIO_MODE_0_REG_OFFSET, 0);
mmio_region_write32(gpio->params.base_addr,
GPIO_INTRPT_RISE_STATUS_OFFSET, 0);
GPIO_GPIO_MODE_0_REG_OFFSET, 0);
mmio_region_write32(gpio->params.base_addr,
GPIO_INTRPT_FALL_STATUS_OFFSET, 0);
GPIO_GPIO_EN_REG_OFFSET, 0);
mmio_region_write32(gpio->params.base_addr,
GPIO_INTRPT_LVL_HIGH_STATUS_OFFSET, 0);
GPIO_GPIO_CLEAR_REG_OFFSET, 0);
mmio_region_write32(gpio->params.base_addr,
GPIO_INTRPT_LVL_LOW_STATUS_OFFSET, 0);
GPIO_GPIO_SET_REG_OFFSET, 0);
// Also clear all pending interrupts
mmio_region_write32(gpio->params.base_addr, GPIO_INTRPT_STATUS_OFFSET,
0xFFFFFFFFu);
mmio_region_write32(gpio->params.base_addr,
GPIO_INTRPT_STATUS_REG_OFFSET, 0);

return kGpioOk;
}
Expand All @@ -112,7 +58,7 @@ gpio_result_t gpio_irq_is_pending(const gpio_t *gpio,
}

*is_pending = mmio_region_get_bit32(gpio->params.base_addr,
GPIO_INTRPT_STATUS_OFFSET, pin);
GPIO_INTRPT_STATUS_REG_OFFSET, pin);

return kGpioOk;
}
Expand All @@ -124,7 +70,7 @@ gpio_result_t gpio_irq_is_pending_all(const gpio_t *gpio,
}

*is_pending =
mmio_region_read32(gpio->params.base_addr, GPIO_INTRPT_STATUS_OFFSET);
mmio_region_read32(gpio->params.base_addr, GPIO_INTRPT_STATUS_REG_OFFSET);

return kGpioOk;
}
Expand All @@ -135,12 +81,26 @@ gpio_result_t gpio_irq_acknowledge(const gpio_t *gpio,
return kGpioBadArg;
}

mmio_region_write32(gpio->params.base_addr, GPIO_INTRPT_STATUS_OFFSET,
mmio_region_write32(gpio->params.base_addr, GPIO_INTRPT_STATUS_REG_OFFSET,
index_to_mask(pin));

return kGpioOk;
}

gpio_result_t gpio_irq_get_enabled(const gpio_t *gpio,
gpio_pin_t pin,
gpio_toggle_t *state) {
if (gpio == NULL || state == NULL) {
return kGpioBadArg;
}

bool is_enabled = mmio_region_get_bit32(gpio->params.base_addr,
GPIO_INTRPT_LVL_HIGH_EN_REG_OFFSET, pin);
*state = is_enabled ? kGpioToggleEnabled : kGpioToggleDisabled;

return kGpioOk;
}

gpio_result_t gpio_irq_set_trigger(const gpio_t *gpio,
gpio_mask_t mask,
gpio_irq_trigger_t trigger) {
Expand All @@ -150,53 +110,54 @@ gpio_result_t gpio_irq_set_trigger(const gpio_t *gpio,

// Disable all interrupt triggers for the given mask.
mmio_region_nonatomic_clear_mask32(
gpio->params.base_addr, GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, mask, 0);
gpio->params.base_addr, GPIO_INTRPT_RISE_EN_REG_OFFSET, mask, 0);
mmio_region_nonatomic_clear_mask32(
gpio->params.base_addr, GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET, mask, 0);
gpio->params.base_addr, GPIO_INTRPT_FALL_EN_REG_OFFSET, mask, 0);
mmio_region_nonatomic_clear_mask32(
gpio->params.base_addr, GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET, mask, 0);
gpio->params.base_addr, GPIO_INTRPT_LVL_HIGH_EN_REG_OFFSET, mask, 0);
mmio_region_nonatomic_clear_mask32(
gpio->params.base_addr, GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, mask, 0);
gpio->params.base_addr, GPIO_INTRPT_LVL_LOW_EN_REG_OFFSET, mask, 0);

switch (trigger) {
case kGpioIrqTriggerEdgeRising:
mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, mask, 0);
gpio->params.base_addr, GPIO_INTRPT_RISE_EN_REG_OFFSET, mask, 0);
break;
case kGpioIrqTriggerEdgeFalling:
mmio_region_nonatomic_set_mask32(gpio->params.base_addr,
GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET,
GPIO_INTRPT_FALL_EN_REG_OFFSET,
mask, 0);
break;
case kGpioIrqTriggerLevelLow:
mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, mask, 0);
gpio->params.base_addr, GPIO_INTRPT_LVL_LOW_EN_REG_OFFSET, mask, 0);
break;
case kGpioIrqTriggerLevelHigh:
mmio_region_nonatomic_set_mask32(gpio->params.base_addr,
GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET,
GPIO_INTRPT_LVL_HIGH_EN_REG_OFFSET,
mask, 0);
break;
case kGpioIrqTriggerEdgeRisingFalling:
mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, mask, 0);
gpio->params.base_addr, GPIO_INTRPT_RISE_EN_REG_OFFSET, mask, 0);
mmio_region_nonatomic_set_mask32(gpio->params.base_addr,
GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET,
GPIO_INTRPT_FALL_EN_REG_OFFSET,
mask, 0);
break;
case kGpioIrqTriggerEdgeRisingLevelLow:
mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_INTR_CTRL_EN_RISING_REG_OFFSET, mask, 0);
gpio->params.base_addr, GPIO_INTRPT_RISE_EN_REG_OFFSET, mask, 0);
mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_INTR_CTRL_EN_LVLLOW_REG_OFFSET, mask, 0);
gpio->params.base_addr, GPIO_INTRPT_LVL_LOW_EN_REG_OFFSET, mask, 0);
break;
case kGpioIrqTriggerEdgeFallingLevelHigh:
mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_INTRPT_RISE_EN_REG_OFFSET, mask, 0);
mmio_region_nonatomic_set_mask32(gpio->params.base_addr,
GPIO_INTR_CTRL_EN_FALLING_REG_OFFSET,
mask, 0);
mmio_region_nonatomic_set_mask32(gpio->params.base_addr,
GPIO_INTR_CTRL_EN_LVLHIGH_REG_OFFSET,
GPIO_INTRPT_FALL_EN_REG_OFFSET,
mask, 0);
mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_INTRPT_LVL_LOW_EN_REG_OFFSET, mask, 0);
break;
default:
return kGpioError;
Expand All @@ -211,7 +172,7 @@ gpio_result_t gpio_read_all(const gpio_t *gpio,
return kGpioBadArg;
}

*state = mmio_region_read32(gpio->params.base_addr, GPIO_DATA_IN_REG_OFFSET);
*state = mmio_region_read32(gpio->params.base_addr, GPIO_GPIO_IN_REG_OFFSET);

return kGpioOk;
}
Expand All @@ -223,7 +184,7 @@ gpio_result_t gpio_read(const gpio_t *gpio, gpio_pin_t pin,
}

*state = mmio_region_get_bit32(gpio->params.base_addr,
GPIO_DATA_IN_REG_OFFSET, pin);
GPIO_GPIO_IN_REG_OFFSET, pin);

return kGpioOk;
}
Expand All @@ -234,95 +195,66 @@ gpio_result_t gpio_write_all(const gpio_t *gpio,
return kGpioBadArg;
}

mmio_region_write32(gpio->params.base_addr, GPIO_DIRECT_OUT_REG_OFFSET,
mmio_region_write32(gpio->params.base_addr, GPIO_GPIO_OUT_REG_OFFSET,
state);

return kGpioOk;
}

gpio_result_t gpio_write(const gpio_t *gpio, gpio_pin_t pin,
bool state) {
if (state == true){
return gpio_masked_bit_write(gpio, GPIO_GPIO_SET_OFFSET,
pin, state);
}else{
return gpio_masked_bit_write(gpio, GPIO_GPIO_CLEAR_OFFSET,
pin, state);
}
}
gpio_result_t gpio_input_set_enabled_all(const gpio_t *gpio,
gpio_state_t state) {
if (gpio == NULL) {
return kGpioBadArg;
}

mmio_region_write32(gpio->params.base_addr, GPIO_GPIO_EN_OFFSET, state);

return kGpioOk;
}

gpio_result_t gpio_input_set_enabled(const gpio_t *gpio,
gpio_pin_t pin,
gpio_state_t state) {
if (gpio == NULL) {
return kGpioBadArg;
}
gpio_masked_bit_write(gpio, GPIO_GPIO_EN_OFFSET,
pin, state);

mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_GPIO_OUT_REG_OFFSET, index_to_mask(pin), state);

return kGpioOk;
}

gpio_result_t gpio_set(const gpio_t *gpio, gpio_state_t state) {
gpio_result_t gpio_write_masked(const gpio_t *gpio,
gpio_mask_t mask,
gpio_state_t state) {
if (gpio == NULL) {
return kGpioBadArg;
}

mmio_region_write32(gpio->params.base_addr, GPIO_GPIO_SET_OFFSET,
state);
mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_GPIO_OUT_REG_OFFSET, mask, state);

return kGpioOk;
}

gpio_result_t gpio_clear(const gpio_t *gpio, gpio_state_t state) {
gpio_result_t gpio_output_set_enabled_all(const gpio_t *gpio,
gpio_state_t state) {
if (gpio == NULL) {
return kGpioBadArg;
}

mmio_region_write32(gpio->params.base_addr, GPIO_GPIO_CLEAR_OFFSET,
state);
mmio_region_write32(gpio->params.base_addr, GPIO_GPIO_EN_REG_OFFSET, state);

return kGpioOk;
}

gpio_result_t gpio_toggle(const gpio_t *gpio, gpio_state_t state) {
gpio_result_t gpio_output_set_enabled(const gpio_t *gpio,
gpio_pin_t pin,
gpio_toggle_t state) {
if (gpio == NULL) {
return kGpioBadArg;
}

mmio_region_write32(gpio->params.base_addr, GPIO_GPIO_TOGGLE_OFFSET,
state);
mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_GPIO_EN_REG_OFFSET, index_to_mask(pin), state);

return kGpioOk;
}

gpio_result_t gpio_output_set_enabled_masked(const gpio_t *gpio,
gpio_mask_t mask,
gpio_state_t state) {
mmio_region_nonatomic_set_mask32(
gpio->params.base_addr, GPIO_GPIO_EN_REG_OFFSET, mask, state);

gpio_result_t gpio_set_mode(const gpio_t *gpio, gpio_pin_t pin,
bool state1, bool state2) {
if(pin < 16){
gpio_masked_bit_write(gpio, GPIO_GPIO_MODE_0_OFFSET, 2*pin, state2);
return gpio_masked_bit_write(gpio, GPIO_GPIO_MODE_0_OFFSET, 2*pin+1, state1);
}else{
gpio_masked_bit_write(gpio, GPIO_GPIO_MODE_1_OFFSET, 2*(pin-16), state2);
return gpio_masked_bit_write(gpio, GPIO_GPIO_MODE_1_OFFSET, 2*(pin-16)+1, state1);
}
}
gpio_result_t gpio_set_mode_all(const gpio_t *gpio,
bool state1, bool state2) {
mmio_region_write32(gpio->params.base_addr, GPIO_GPIO_MODE_1_OFFSET,
state1);
mmio_region_write32(gpio->params.base_addr, GPIO_GPIO_MODE_0_OFFSET,
state2);
return kGpioOk;

}