summaryrefslogtreecommitdiff
path: root/chip/g
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2018-01-02 15:40:00 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-01-03 16:54:35 -0800
commit5789d6925777d82db30d80cd2eef62f57e5c9ca7 (patch)
tree34cf8440fd8b2b1ecaec83711bfae5097d95a76a /chip/g
parent27f92a378aad37bac9f2de1a311f78012eac574b (diff)
downloadchrome-ec-5789d6925777d82db30d80cd2eef62f57e5c9ca7.tar.gz
g: simulate open drain GPIO behavior
Some upcoming designs based on the g chip require GPIOs connected to open drain circuits. Even though the chip explicitly provides only two open drain GPIOs, the desired behavior of the rest of the pins when configured as 'open drain' could be simulated by software if when 'high' is required the output is disabled instead of driving the pin value. To make sure there is no fallout from RO driving the pins, also add an explicit 'disable output' initialization in case a GPIO is configured for open drain and the initial output value is 'high'. BRANCH=cr50 BUG=none TEST=verified that Cr50 booted successfully, also confirmed that on the test board that GPIOs defined as Open Drain allow we set output to 1 only if pulled up. Change-Id: Id2daa19b992bab7fb01148b6fa7b57fd0728b33d Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/848152 Reviewed-by: Randall Spangler <rspangler@chromium.org>
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) {