summaryrefslogtreecommitdiff
path: root/chip/g
diff options
context:
space:
mode:
Diffstat (limited to 'chip/g')
-rw-r--r--chip/g/gpio.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/chip/g/gpio.c b/chip/g/gpio.c
index c8399f01ce..432608beea 100644
--- a/chip/g/gpio.c
+++ b/chip/g/gpio.c
@@ -38,6 +38,16 @@ static void set_one_gpio_bit(uint32_t port, uint16_t mask, int value)
void gpio_set_level(enum gpio_signal signal, int value)
{
const struct gpio_info *g = gpio_list + signal;
+
+ if (g->flags & GPIO_OPEN_DRAIN) {
+ if (value) {
+ GR_GPIO_CLRDOUTEN(g->port) = g->mask;
+ /* Don't ever set ODR output to HIGH. */
+ return;
+ }
+ GR_GPIO_SETDOUTEN(g->port) = g->mask;
+ }
+
set_one_gpio_bit(g->port, g->mask, value);
}
@@ -68,17 +78,30 @@ int gpio_get_flags_by_mask(uint32_t port, uint32_t mask)
void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags)
{
- /* Only matters for outputs */
- if (flags & GPIO_LOW)
- set_one_gpio_bit(port, mask, 0);
- else if (flags & GPIO_HIGH)
- set_one_gpio_bit(port, mask, 1);
-
- /* Output must be enabled; input is always enabled */
- if (flags & GPIO_OUTPUT)
- GR_GPIO_SETDOUTEN(port) = mask;
- else
+ /* Output must be enabled when needed, input is always enabled */
+ if (flags & GPIO_OUTPUT) {
+
+ if (flags & GPIO_LOW)
+ set_one_gpio_bit(port, mask, 0);
+ else if ((flags & GPIO_HIGH) && !(flags & GPIO_OPEN_DRAIN))
+ /* Set to HIGH only if not open drain. */
+ set_one_gpio_bit(port, mask, 1);
+
+ if (!(flags & GPIO_OPEN_DRAIN) || (flags & GPIO_LOW))
+ /*
+ * Enable output for push-pull (high or low), or
+ * open-drain low.
+ */
+ GR_GPIO_SETDOUTEN(port) = mask;
+ else if (flags & GPIO_OPEN_DRAIN)
+ /*
+ * Disable output for other open-drain cases to get a
+ * high-Z pin.
+ */
+ GR_GPIO_CLRDOUTEN(port) = mask;
+ } else {
GR_GPIO_CLRDOUTEN(port) = mask;
+ }
/* Interrupt types */
if (flags & GPIO_INT_F_LOW) {