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 <adurbin@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/60780
Reviewed-by: Sameer Nanda <snanda@chromium.org>
This commit is contained in:
Aaron Durbin
2013-07-02 11:51:39 -05:00
committed by ChromeBot
parent 09329a5f4b
commit b5dcfef79f
4 changed files with 22 additions and 15 deletions

View File

@@ -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},

View File

@@ -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},

View File

@@ -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},

View File

@@ -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);
}
}