From 91684d5e33396caccd4b91791e41c0a240764830 Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Tue, 29 Mar 2016 20:31:22 -0700 Subject: Cr50: Add stubs to support low-power idle This just adds the framework to use for implementing sleep and deep-sleep. This provides a custom idle task, and a new "idle" console command to control what that task should do (nothing, yet). BUG=chrome-os-partner:49955 BRANCH=none TEST=make buildall; test on Cr50 Other than the new idle command which does nothing, there is no visible change. This is just a stub. Change-Id: I8a9b82ca68dd6d1e3e7275f4f6753a23a7448f1d Signed-off-by: Bill Richardson Reviewed-on: https://chromium-review.googlesource.com/336420 Reviewed-by: Randall Spangler --- board/cr50/board.h | 2 ++ chip/g/build.mk | 2 ++ chip/g/idle.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 chip/g/idle.c diff --git a/board/cr50/board.h b/board/cr50/board.h index 90635323ae..d7cface787 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -21,6 +21,8 @@ /* TODO(crosbug.com/p/44745): For debugging only */ #define CONFIG_CMD_FLASH +/* Go to sleep when nothing else is happening */ +#define CONFIG_LOW_POWER_IDLE /* USB configuration */ #define CONFIG_USB diff --git a/chip/g/build.mk b/chip/g/build.mk index 0d8ae631b2..d6df5d228c 100644 --- a/chip/g/build.mk +++ b/chip/g/build.mk @@ -48,6 +48,8 @@ chip-$(CONFIG_USB_CONSOLE)+=usb_console.o chip-$(CONFIG_USB_HID)+=usb_hid.o chip-$(CONFIG_USB_BLOB)+=usb_blob.o +chip-$(CONFIG_LOW_POWER_IDLE)+=idle.o + chip-$(CONFIG_FLASH)+=flash.o dirs-y += chip/g/dcrypto diff --git a/chip/g/idle.c b/chip/g/idle.c new file mode 100644 index 0000000000..fc955e0b30 --- /dev/null +++ b/chip/g/idle.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2014 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 "common.h" +#include "console.h" +#include "util.h" + +/* This function is assumed to exist, but we don't use it */ +void clock_refresh_console_in_use(void) +{ +} + +/* What to do when we're just waiting */ +static enum { + IDLE_WFI, /* default */ + IDLE_SLEEP, + IDLE_DEEP_SLEEP, + NUM_CHOICES +} idle_action; + +static const char const *idle_name[] = { + "wfi", + "sleep", + "deep sleep", +}; +BUILD_ASSERT(ARRAY_SIZE(idle_name) == NUM_CHOICES); + +static int command_idle(int argc, char **argv) +{ + int c, i; + + if (argc > 1) { + c = tolower(argv[1][0]); + for (i = 0; i < ARRAY_SIZE(idle_name); i++) + if (idle_name[i][0] == c) { + idle_action = i; + break; + } + } + + ccprintf("idle action: %s\n", idle_name[idle_action]); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(idle, command_idle, + "[w|s|d]", + "Set or show the idle action: wfi, sleep, deep sleep", + NULL); + +/* Custom idle task, executed when no tasks are ready to be scheduled. */ +void __idle(void) +{ + while (1) { + + /* Don't even bother unless we've enabled it */ + if (idle_action == IDLE_WFI) + goto wfi; + + /* TODO(wfrichar): sleep/deep-sleep stuff goes here... */ + +wfi: + /* Wait for the next irq event. This stops the CPU clock and + * may trigger sleep or deep sleep if enabled. */ + asm("wfi"); + + /* + * TODO: Normal sleep resumes by handling the interrupt, but we + * need to clear PMU_LOW_POWER_DIS right away or we might sleep + * again by accident. We can't do that here because we don't + * get here until the next idle, so we'll have to do it in the + * interrupt handler or when task switching. Deep sleep resumes + * with a warm boot, which handles it differently. + */ + } +} -- cgit v1.2.1