Files
OpenCellular/board/cr50/power_button.c
Randall Spangler ccb151d013 cr50: Defragment code
For historical reasons, CCD, reset, and power button control were
scattered around several files.  Consolidate the code in more sensible
(in retrospect) places.

No functional changes, just moving code.

BUG=none
BRANCH=cr50
TEST=make buildall; boot cr50

Change-Id: Ic381a5a5d0627753cc771189aa377e88b81b155e
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/653766
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
2017-09-09 13:48:49 -07:00

119 lines
3.0 KiB
C

/* Copyright 2017 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "console.h"
#include "gpio.h"
#include "hooks.h"
#include "physical_presence.h"
#include "rbox.h"
#include "registers.h"
#include "system.h"
#include "system_chip.h"
#include "task.h"
#include "timer.h"
#define CPRINTS(format, args...) cprints(CC_RBOX, format, ## args)
#define CPRINTF(format, args...) cprintf(CC_RBOX, format, ## args)
/**
* Enable/disable power button interrupt.
*
* @param enable Enable (!=0) or disable (==0)
*/
static void power_button_enable_interrupt(int enable)
{
if (enable) {
/* Clear any leftover power button interrupts */
GWRITE_FIELD(RBOX, INT_STATE, INTR_PWRB_IN_FED, 1);
/* Enable power button interrupt */
GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_FED, 1);
task_enable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT);
} else {
GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_FED, 0);
task_disable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT);
}
}
static void power_button_handler(void)
{
CPRINTS("power button pressed");
if (physical_detect_press() != EC_SUCCESS) {
/* Not consumed by physical detect */
#ifdef CONFIG_U2F
/* Track last power button press for U2F */
power_button_record();
#endif
}
GWRITE_FIELD(RBOX, INT_STATE, INTR_PWRB_IN_FED, 1);
}
DECLARE_IRQ(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT, power_button_handler, 1);
#ifdef CONFIG_U2F
static void power_button_init(void)
{
/*
* Enable power button interrupts all the time for U2F.
*
* Ideally U2F should only enable physical presence after the start of
* a U2F request (using atomic operations for the PP enable mask so it
* plays nicely with CCD config), but that doesn't happen yet.
*/
power_button_enable_interrupt(1);
}
DECLARE_HOOK(HOOK_INIT, power_button_init, HOOK_PRIO_DEFAULT);
#endif /* CONFIG_U2F */
void board_physical_presence_enable(int enable)
{
#ifndef CONFIG_U2F
/* Enable/disable power button interrupts */
power_button_enable_interrupt(enable);
#endif
/* Stay awake while we're doing this, just in case. */
if (enable)
disable_sleep(SLEEP_MASK_PHYSICAL_PRESENCE);
else
enable_sleep(SLEEP_MASK_PHYSICAL_PRESENCE);
}
static int command_powerbtn(int argc, char **argv)
{
char *e;
int ms = 200;
if (argc > 1) {
if (!strcasecmp("pulse", argv[1])) {
if (argc == 3) {
ms = strtoi(argv[2], &e, 0);
if (*e)
return EC_ERROR_PARAM2;
}
ccprintf("Force %dms power button press\n", ms);
rbox_powerbtn_press();
msleep(ms);
rbox_powerbtn_release();
} else if (!strcasecmp("press", argv[1])) {
rbox_powerbtn_press();
} else if (!strcasecmp("release", argv[1])) {
rbox_powerbtn_release();
} else
return EC_ERROR_PARAM1;
}
ccprintf("powerbtn: %s\n",
rbox_powerbtn_override_is_enabled() ? "forced press" :
rbox_powerbtn_is_pressed() ? "pressed\n" : "released\n");
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(powerbtn, command_powerbtn,
"[pulse [ms] | press | release]",
"get/set the state of the power button");