From b5dcfef79f16fa37038ad68e1259159266c9ac1d Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Tue, 2 Jul 2013 11:51:39 -0500 Subject: [PATCH] haswell: fix RCIN_L leakage It's still unclear why the PL6 pin which is used for RCIN_L does not behave properly when configured as open drain. Work around the misbehavior by configuring the PL6 pin as an input. When it is required to be driven low the pin is reconfigured to an output and subsequently made an input again. This provides the open drain semantics that are required to eliminate leakage. BUG=chrome-os-partner:19811 BUG=chrome-os-partner:20054 BUG=chrome-os-partner:20173 BUG=chrome-os-partner:20175 BRANCH=None TEST=manual 'apreset warm' causes reset as expected. The pin is configured as an input by default without open drain or a pullup resistor: > rw 0x40062400 (GPIODIR) read 0x40062400 = 0x00000000 > rw 0x4006250c (GPIOODR) read 0x4006250c = 0x00000000 > rw 0x40062510 (GPIOPUR) read 0x40062510 = 0x00000000 Change-Id: Ia3ad6fa7fec06be1cbff6854d9341722d8617408 Signed-off-by: Aaron Durbin Reviewed-on: https://gerrit.chromium.org/gerrit/60780 Reviewed-by: Sameer Nanda --- board/falco/board.c | 8 +++++--- board/peppy/board.c | 8 +++++--- board/slippy/board.c | 8 +++++--- common/x86_power_haswell.c | 13 +++++++------ 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/board/falco/board.c b/board/falco/board.c index e516c93b99..b088bcf3c5 100644 --- a/board/falco/board.c +++ b/board/falco/board.c @@ -98,9 +98,11 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"PCH_NMI_L", LM4_GPIO_F, (1<<2), GPIO_OUT_HIGH, NULL}, {"PCH_PWRBTN_L", LM4_GPIO_H, (1<<0), GPIO_OUT_HIGH, NULL}, {"PCH_PWROK", LM4_GPIO_F, (1<<5), GPIO_OUT_LOW, NULL}, - /* FIXME: Why is PL6 act like it is inverted. Setting value to - * 0 makes the signal high, and setting it to 1 makes the signal low. */ - {"PCH_RCIN_L", LM4_GPIO_L, (1<<6), GPIO_ODR_LOW, NULL}, + /* FIXME: Why does PL6 not honor open drain semantics? Setting it to 1 + * drives the pin low while setting it to 0 drives the pin high. To + * work around this PCH_RCIN_L is set to an input. It will only + * be set to an output when it needs to be driven to 0. */ + {"PCH_RCIN_L", LM4_GPIO_L, (1<<6), GPIO_INPUT, NULL}, {"PCH_RSMRST_L", LM4_GPIO_F, (1<<1), GPIO_OUT_LOW, NULL}, {"PCH_SMI_L", LM4_GPIO_F, (1<<4), GPIO_ODR_HIGH, NULL}, {"TOUCHSCREEN_RESET_L", LM4_GPIO_N, (1<<7), GPIO_OUT_LOW, NULL}, diff --git a/board/peppy/board.c b/board/peppy/board.c index aa34db95d1..1f3afd49b5 100644 --- a/board/peppy/board.c +++ b/board/peppy/board.c @@ -98,9 +98,11 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"PCH_NMI_L", LM4_GPIO_F, (1<<2), GPIO_OUT_HIGH, NULL}, {"PCH_PWRBTN_L", LM4_GPIO_H, (1<<0), GPIO_OUT_HIGH, NULL}, {"PCH_PWROK", LM4_GPIO_F, (1<<5), GPIO_OUT_LOW, NULL}, - /* FIXME: Why is PL6 act like it is inverted. Setting value to - * 0 makes the signal high, and setting it to 1 makes the signal low. */ - {"PCH_RCIN_L", LM4_GPIO_L, (1<<6), GPIO_ODR_LOW, NULL}, + /* FIXME: Why does PL6 not honor open drain semantics? Setting it to 1 + * drives the pin low while setting it to 0 drives the pin high. To + * work around this PCH_RCIN_L is set to an input. It will only + * be set to an output when it needs to be driven to 0. */ + {"PCH_RCIN_L", LM4_GPIO_L, (1<<6), GPIO_INPUT, NULL}, {"PCH_RSMRST_L", LM4_GPIO_F, (1<<1), GPIO_OUT_LOW, NULL}, {"PCH_SMI_L", LM4_GPIO_F, (1<<4), GPIO_ODR_HIGH, NULL}, {"TOUCHSCREEN_RESET_L", LM4_GPIO_N, (1<<7), GPIO_OUT_LOW, NULL}, diff --git a/board/slippy/board.c b/board/slippy/board.c index c17f373c69..2fc24797ce 100644 --- a/board/slippy/board.c +++ b/board/slippy/board.c @@ -98,9 +98,11 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"PCH_NMI_L", LM4_GPIO_F, (1<<2), GPIO_OUT_HIGH, NULL}, {"PCH_PWRBTN_L", LM4_GPIO_H, (1<<0), GPIO_OUT_HIGH, NULL}, {"PCH_PWROK", LM4_GPIO_F, (1<<5), GPIO_OUT_LOW, NULL}, - /* FIXME: Why is PL6 act like it is inverted. Setting value to - * 0 makes the signal high, and setting it to 1 makes the signal low. */ - {"PCH_RCIN_L", LM4_GPIO_L, (1<<6), GPIO_ODR_LOW, NULL}, + /* FIXME: Why does PL6 not honor open drain semantics? Setting it to 1 + * drives the pin low while setting it to 0 drives the pin high. To + * work around this PCH_RCIN_L is set to an input. It will only + * be set to an output when it needs to be driven to 0. */ + {"PCH_RCIN_L", LM4_GPIO_L, (1<<6), GPIO_INPUT, NULL}, {"PCH_RSMRST_L", LM4_GPIO_F, (1<<1), GPIO_OUT_LOW, NULL}, {"PCH_SMI_L", LM4_GPIO_F, (1<<4), GPIO_ODR_HIGH, NULL}, {"TOUCHSCREEN_RESET_L", LM4_GPIO_N, (1<<7), GPIO_OUT_LOW, NULL}, diff --git a/common/x86_power_haswell.c b/common/x86_power_haswell.c index 06bce3f204..f47a2c6769 100644 --- a/common/x86_power_haswell.c +++ b/common/x86_power_haswell.c @@ -239,13 +239,14 @@ void chipset_reset(int cold_reset) /* * Pulse must be at least 16 PCI clocks long = 500 ns. The gpio - * pin used by the EC is configured as open drain. However, - * empirically it was deteremined the polarity of the pin is - * inverted. No idea why. Therefore, the driving RCIN# low - * needs to be set to level 1. FIXME: why? */ - gpio_set_level(GPIO_PCH_RCIN_L, 1); + * pin used by the EC (PL6) does not behave in the correct + * manner when configured as open drain. In order to mimic + * open drain, the pin is initially configured as an input. + * When it is needed to drive low, the flags are updated which + * changes the pin to an output and drives the pin low. */ + gpio_set_flags(GPIO_PCH_RCIN_L, GPIO_OUT_LOW); udelay(10); - gpio_set_level(GPIO_PCH_RCIN_L, 0); + gpio_set_flags(GPIO_PCH_RCIN_L, GPIO_INPUT); } }