mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-01 12:52:26 +00:00
Use open drain reset signals, and clean up signals to 5VALW-powered devices
Open drain cleanup minimizes leakage and signal glitching on shared reset/signal lines, and is tidier than explicitly switching the signals between inputs/outputs. Touchscreen and lightbar are powered by +5VALW so their signals need to be dropped when +5VALW is off to avoid leakage, and so they see a clean reset signal when they're powered up. Moved +5VALW power-on to S5-S3 transition, to minimize power draw in S5. This also ensures that 5VALW-powered devices get reset when the device bounces through S5. (No effect on proto1, where 5VALW is not under EC control.) Signed-off-by: Randall Spangler <rspangler@chromium.org> BUG=chrome-os-partner:9172 TEST=boot and shutdown system; still works. Change-Id: Ia4bf0703292a189c324ce283d1e79a33776ee40f
This commit is contained in:
@@ -74,8 +74,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
|
||||
{"WRITE_PROTECT", LM4_GPIO_J, (1<<4), GPIO_INT_BOTH,
|
||||
power_button_interrupt},
|
||||
/* Outputs; all unasserted by default except for reset signals */
|
||||
/* CPU_PROCHOTn is high-Z unless we're driving it */
|
||||
{"CPU_PROCHOTn", LM4_GPIO_F, (1<<2), 0, NULL},
|
||||
{"CPU_PROCHOTn", LM4_GPIO_F, (1<<2), GPIO_HI_Z, NULL},
|
||||
{"ENABLE_1_5V_DDR", LM4_GPIO_H, (1<<5), GPIO_OUT_LOW, NULL},
|
||||
{"ENABLE_5VALW", LM4_GPIO_K, (1<<4), GPIO_OUT_LOW, NULL},
|
||||
{"ENABLE_BACKLIGHT", LM4_GPIO_H, (1<<4), GPIO_OUT_LOW, NULL},
|
||||
@@ -92,13 +91,11 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
|
||||
{"PCH_NMIn", LM4_GPIO_M, (1<<2), GPIO_OUT_HIGH, NULL},
|
||||
{"PCH_PWRBTNn", LM4_GPIO_G, (1<<7), GPIO_OUT_HIGH, NULL},
|
||||
{"PCH_PWROK", LM4_GPIO_F, (1<<5), GPIO_OUT_LOW, NULL},
|
||||
{"PCH_RCINn", LM4_GPIO_Q, (1<<7), GPIO_OUT_LOW, NULL},
|
||||
{"PCH_RCINn", LM4_GPIO_Q, (1<<7), GPIO_HI_Z, NULL},
|
||||
{"PCH_RSMRSTn", LM4_GPIO_F, (1<<1), GPIO_OUT_LOW, NULL},
|
||||
/* RTCRST# (and SRTCRST# below) are unasserted by default so we don't
|
||||
* clear the RTC wells in the PCH when the EC resets. */
|
||||
{"PCH_RTCRSTn", LM4_GPIO_F, (1<<6), GPIO_OUT_HIGH, NULL},
|
||||
{"PCH_RTCRSTn", LM4_GPIO_F, (1<<6), GPIO_HI_Z, NULL},
|
||||
{"PCH_SMIn", LM4_GPIO_F, (1<<4), GPIO_OUT_HIGH, NULL},
|
||||
{"PCH_SRTCRSTn", LM4_GPIO_C, (1<<7), GPIO_OUT_HIGH, NULL},
|
||||
{"PCH_SRTCRSTn", LM4_GPIO_C, (1<<7), GPIO_HI_Z, NULL},
|
||||
{"PCH_SUSACKn", LM4_GPIO_F, (1<<3), GPIO_OUT_HIGH, NULL},
|
||||
{"RADIO_ENABLE_WLAN", LM4_GPIO_D, (1<<0), GPIO_OUT_LOW, NULL},
|
||||
{"RADIO_ENABLE_BT", LM4_GPIO_D, (1<<1), GPIO_OUT_LOW, NULL},
|
||||
|
||||
@@ -184,14 +184,18 @@ int gpio_set_flags(enum gpio_signal signal, int flags)
|
||||
|
||||
if (flags & GPIO_OUTPUT) {
|
||||
/* Output */
|
||||
LM4_GPIO_DIR(g->port) |= g->mask;
|
||||
|
||||
/* Select open drain first, so that we don't glitch the signal
|
||||
* when changing the line to an output. */
|
||||
if (g->flags & GPIO_OPEN_DRAIN)
|
||||
LM4_GPIO_ODR(g->port) |= g->mask;
|
||||
else
|
||||
LM4_GPIO_ODR(g->port) &= ~g->mask;
|
||||
|
||||
LM4_GPIO_DIR(g->port) |= g->mask;
|
||||
} else {
|
||||
/* Input */
|
||||
LM4_GPIO_DIR(g->port) &= ~g->mask;
|
||||
|
||||
if (g->flags & GPIO_PULL) {
|
||||
/* With pull up/down */
|
||||
if (g->flags & GPIO_HIGH)
|
||||
|
||||
@@ -597,11 +597,16 @@ void lightbar_task(void)
|
||||
{
|
||||
uint32_t msg;
|
||||
|
||||
/* Keep the controllers out of reset. The reset pullup uses more power
|
||||
* than leaving them in standby. */
|
||||
gpio_set_level(GPIO_LIGHTBAR_RESETn, 1);
|
||||
usleep(100);
|
||||
|
||||
/* Reset lightbar to a known state */
|
||||
/* TODO: (crosbug.com/p/9561) only needed on proto1, since on EVT the
|
||||
* lightbar loses power when +5VALW goes away, and will come back on
|
||||
* with these default values anyway.
|
||||
*
|
||||
* Also note than on EVT, it costs more power to deassert lightbar
|
||||
* reset than it does to hold the lightbar in reset, because the
|
||||
* lightbar reset line is a leakage path from +3VALW. On proto1,
|
||||
* that's reversed, because the LED drivers consume more power held in
|
||||
* reset than out of reset. */
|
||||
lightbar_init_vals();
|
||||
lightbar_off();
|
||||
|
||||
|
||||
@@ -117,11 +117,10 @@ static void overheated_action(void)
|
||||
|
||||
if (overheated[THRESHOLD_WARNING]) {
|
||||
smi_overheated_warning();
|
||||
gpio_set_flags(GPIO_CPU_PROCHOTn, GPIO_OUTPUT);
|
||||
gpio_set_level(GPIO_CPU_PROCHOTn, 0);
|
||||
}
|
||||
else
|
||||
gpio_set_flags(GPIO_CPU_PROCHOTn, 0);
|
||||
gpio_set_flags(GPIO_CPU_PROCHOTn, 1);
|
||||
|
||||
if (fan_ctrl_on) {
|
||||
int i;
|
||||
|
||||
@@ -201,10 +201,6 @@ void x86_power_reset(int cold_reset)
|
||||
* assert INIT# to the CPU without dropping power or asserting
|
||||
* PLTRST# to reset the rest of the system. */
|
||||
|
||||
/* Ignore if RCINn is already low */
|
||||
if (gpio_get_level(GPIO_PCH_RCINn) == 0)
|
||||
return;
|
||||
|
||||
/* Pulse must be at least 16 PCI clocks long = 500 ns */
|
||||
gpio_set_level(GPIO_PCH_RCINn, 0);
|
||||
udelay(10);
|
||||
@@ -305,7 +301,6 @@ static int x86_power_init(void)
|
||||
CPUTS("[x86 forcing G3]\n");
|
||||
gpio_set_level(GPIO_PCH_PWROK, 0);
|
||||
gpio_set_level(GPIO_ENABLE_VCORE, 0);
|
||||
gpio_set_level(GPIO_PCH_RCINn, 0);
|
||||
gpio_set_level(GPIO_ENABLE_VS, 0);
|
||||
gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0);
|
||||
gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 0);
|
||||
@@ -407,12 +402,8 @@ void x86_power_task(void)
|
||||
break;
|
||||
|
||||
case X86_G3S5:
|
||||
/* Switch on +5V always-on */
|
||||
gpio_set_level(GPIO_ENABLE_5VALW, 1);
|
||||
/* Wait for the always-on rails to be good */
|
||||
wait_in_signals(IN_PGOOD_ALWAYS_ON);
|
||||
|
||||
/* Wait 10ms after +5VALW good */
|
||||
/* Wait 10ms after +3VALW good, since that powers
|
||||
* VccDSW and VccSUS. */
|
||||
usleep(10000);
|
||||
|
||||
/* Assert DPWROK, deassert RSMRST# */
|
||||
@@ -426,13 +417,23 @@ void x86_power_task(void)
|
||||
break;
|
||||
|
||||
case X86_S5S3:
|
||||
/* Switch on +5V always-on */
|
||||
gpio_set_level(GPIO_ENABLE_5VALW, 1);
|
||||
/* Wait for the always-on rails to be good */
|
||||
wait_in_signals(IN_PGOOD_ALWAYS_ON);
|
||||
|
||||
/* Take touchscreen and lightbar out of reset, now
|
||||
* that +5VALW is available and we won't leak +3VALW
|
||||
* through the reset line. */
|
||||
gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 1);
|
||||
gpio_set_level(GPIO_LIGHTBAR_RESETn, 1);
|
||||
|
||||
/* Turn on power to RAM */
|
||||
gpio_set_level(GPIO_ENABLE_1_5V_DDR, 1);
|
||||
|
||||
/* Enable touchpad power and take touchscreen out of
|
||||
* reset, so they can wake the system from suspend. */
|
||||
/* Enable touchpad power so it can wake the system from
|
||||
* suspend. */
|
||||
gpio_set_level(GPIO_ENABLE_TOUCHPAD, 1);
|
||||
gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 1);
|
||||
|
||||
/* Call hooks now that rails are up */
|
||||
hook_notify(HOOK_CHIPSET_STARTUP, 0);
|
||||
@@ -441,9 +442,6 @@ void x86_power_task(void)
|
||||
break;
|
||||
|
||||
case X86_S3S0:
|
||||
/* Deassert RCINn */
|
||||
gpio_set_level(GPIO_PCH_RCINn, 1);
|
||||
|
||||
/* Turn on power rails */
|
||||
gpio_set_level(GPIO_ENABLE_VS, 1);
|
||||
|
||||
@@ -484,9 +482,6 @@ void x86_power_task(void)
|
||||
/* Disable +CPU_CORE and +VGFX_CORE */
|
||||
gpio_set_level(GPIO_ENABLE_VCORE, 0);
|
||||
|
||||
/* Assert RCINn */
|
||||
gpio_set_level(GPIO_PCH_RCINn, 0);
|
||||
|
||||
/* Disable WLAN */
|
||||
gpio_set_level(GPIO_ENABLE_WLAN, 0);
|
||||
gpio_set_level(GPIO_RADIO_ENABLE_WLAN, 0);
|
||||
@@ -502,13 +497,20 @@ void x86_power_task(void)
|
||||
/* Call hooks before we remove power rails */
|
||||
hook_notify(HOOK_CHIPSET_SHUTDOWN, 0);
|
||||
|
||||
/* Disable touchpad power and reset touchscreen. */
|
||||
/* Disable touchpad power */
|
||||
gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0);
|
||||
gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 0);
|
||||
|
||||
/* Turn off power to RAM */
|
||||
gpio_set_level(GPIO_ENABLE_1_5V_DDR, 0);
|
||||
|
||||
/* Put touchscreen and lightbar in reset, so we won't
|
||||
* leak +3VALW through the reset line. */
|
||||
gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 0);
|
||||
gpio_set_level(GPIO_LIGHTBAR_RESETn, 0);
|
||||
|
||||
/* Switch off +5V always-on */
|
||||
gpio_set_level(GPIO_ENABLE_5VALW, 0);
|
||||
|
||||
state = X86_S5;
|
||||
break;
|
||||
|
||||
@@ -517,9 +519,6 @@ void x86_power_task(void)
|
||||
gpio_set_level(GPIO_PCH_DPWROK, 0);
|
||||
gpio_set_level(GPIO_PCH_RSMRSTn, 0);
|
||||
|
||||
/* Switch off +5V always-on */
|
||||
gpio_set_level(GPIO_ENABLE_5VALW, 0);
|
||||
|
||||
state = X86_G3;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user