[coreboot-gerrit] Patch set updated for coreboot: 92ee859 tegra132: psci: add cpu_on/off support

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Fri Apr 10 15:00:36 CEST 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9542

-gerrit

commit 92ee859f080874f0e6734525ce4f9b034f484a9c
Author: Joseph Lo <josephl at nvidia.com>
Date:   Fri Nov 21 08:54:15 2014 +0800

    tegra132: psci: add cpu_on/off support
    
    The CPU on/off functions are the method for the Kernel to support CPU
    hot-plug function in PSCI. To support this, we still need flow controller
    support to capture the WFI from the CPU and inform PMC to power gate the
    CPU core. On the other path, we turn on the CPU by toggling the PMC and
    use flow controller to let go when the power is steady.
    
    BUG=chrome-os-partner:32136
    BRANCH=None
    TEST=built the kernel with PSCI enabled,
         check both of the CPUs are coming up,
         test the CPU hot-plug is working on Ryu
    
    Change-Id: If2c529b6719c5747d5aea95fb5049b2d7353ff17
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: 0f078e89daad1c4d8b342a395f36b3e922af66f5
    Original-Change-Id: Ie49940adb2966dcc9967d2fcc9b1e0dcd6d98743
    Original-Signed-off-by: Joseph Lo <josephl at nvidia.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/231267
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
---
 src/soc/nvidia/tegra132/Makefile.inc            |  2 +
 src/soc/nvidia/tegra132/flow_ctrl.c             | 96 +++++++++++++++++++++++++
 src/soc/nvidia/tegra132/include/soc/flow_ctrl.h | 26 +++++++
 src/soc/nvidia/tegra132/psci.c                  | 75 ++++++++++++++++++-
 4 files changed, 197 insertions(+), 2 deletions(-)

diff --git a/src/soc/nvidia/tegra132/Makefile.inc b/src/soc/nvidia/tegra132/Makefile.inc
index a46a2e5..fc22b2a 100644
--- a/src/soc/nvidia/tegra132/Makefile.inc
+++ b/src/soc/nvidia/tegra132/Makefile.inc
@@ -97,6 +97,8 @@ ramstage-$(CONFIG_ARCH_USE_SECURE_MONITOR) += secmon.c
 secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += 32bit_reset.S
 secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += cpu.c
 secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += cpu_lib.S
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += flow_ctrl.c
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += power.c
 secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += psci.c
 secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += uart.c
 
diff --git a/src/soc/nvidia/tegra132/flow_ctrl.c b/src/soc/nvidia/tegra132/flow_ctrl.c
new file mode 100644
index 0000000..4da54b1
--- /dev/null
+++ b/src/soc/nvidia/tegra132/flow_ctrl.c
@@ -0,0 +1,96 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <soc/addressmap.h>
+#include <soc/flow_ctrl.h>
+
+#define FLOW_CTRL_HALT_CPU0_EVENTS	0x0
+#define FLOW_CTRL_WAITEVENT		(2 << 29)
+#define FLOW_CTRL_WAIT_FOR_INTERRUPT	(4 << 29)
+#define FLOW_CTRL_HALT_LIC_IRQ		(1 << 11)
+#define FLOW_CTRL_HALT_LIC_FIQ		(1 << 10)
+#define FLOW_CTRL_CPU0_CSR		0x8
+#define FLOW_CTRL_CSR_INTR_FLAG		(1 << 15)
+#define FLOW_CTRL_CSR_EVENT_FLAG	(1 << 14)
+#define FLOW_CTRL_CSR_WFI_CPU0		(1 << 8)
+#define FLOW_CTRL_CSR_WFI_BITMAP	(0xF << 8)
+#define FLOW_CTRL_CSR_WFE_BITMAP	(0xF << 4)
+#define FLOW_CTRL_CSR_ENABLE		(1 << 0)
+#define FLOW_CTRL_HALT_CPU1_EVENTS	0x14
+#define FLOW_CTRL_CPU1_CSR		0x18
+
+#define HALT_REG_CORE0 (\
+	FLOW_CTRL_WAIT_FOR_INTERRUPT | \
+	FLOW_CTRL_HALT_LIC_IRQ | \
+	FLOW_CTRL_HALT_LIC_FIQ)
+
+#define HALT_REG_CORE1 FLOW_CTRL_WAITEVENT
+
+static void *tegra_flowctrl_base = (void*)TEGRA_FLOW_BASE;
+
+static const uint8_t flowctrl_offset_halt_cpu[] = {
+	FLOW_CTRL_HALT_CPU0_EVENTS,
+	FLOW_CTRL_HALT_CPU1_EVENTS
+};
+
+static const uint8_t flowctrl_offset_cpu_csr[] = {
+	FLOW_CTRL_CPU0_CSR,
+	FLOW_CTRL_CPU1_CSR
+};
+
+static uint32_t flowctrl_read_cpu_csr(int cpu)
+{
+	return read32(tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu]);
+}
+
+static void flowctrl_write_cpu_csr(int cpu, uint32_t val)
+{
+	write32(val, tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu]);
+	val = readl(tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu]);
+}
+
+void flowctrl_write_cpu_halt(int cpu, uint32_t val)
+{
+	writel(val, tegra_flowctrl_base + flowctrl_offset_halt_cpu[cpu]);
+	val = readl(tegra_flowctrl_base + flowctrl_offset_halt_cpu[cpu]);
+}
+
+static void flowctrl_prepare_cpu_off(int cpu)
+{
+	uint32_t reg;
+
+	reg = flowctrl_read_cpu_csr(cpu);
+	reg &= ~FLOW_CTRL_CSR_WFE_BITMAP;	/* clear wfe bitmap */
+	reg &= ~FLOW_CTRL_CSR_WFI_BITMAP;	/* clear wfi bitmap */
+	reg |= FLOW_CTRL_CSR_INTR_FLAG;		/* clear intr flag */
+	reg |= FLOW_CTRL_CSR_EVENT_FLAG;	/* clear event flag */
+	reg |= FLOW_CTRL_CSR_WFI_CPU0 << cpu;	/* power gating on wfi */
+	reg |= FLOW_CTRL_CSR_ENABLE;		/* enable power gating */
+	flowctrl_write_cpu_csr(cpu, reg);
+}
+
+void flowctrl_cpu_off(int cpu)
+{
+	uint32_t reg;
+
+	reg = cpu ? HALT_REG_CORE1 : HALT_REG_CORE0;
+	flowctrl_prepare_cpu_off(cpu);
+	flowctrl_write_cpu_halt(cpu, reg);
+}
diff --git a/src/soc/nvidia/tegra132/include/soc/flow_ctrl.h b/src/soc/nvidia/tegra132/include/soc/flow_ctrl.h
new file mode 100644
index 0000000..28fe846
--- /dev/null
+++ b/src/soc/nvidia/tegra132/include/soc/flow_ctrl.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _TEGRA132_FLOW_CTRL_H_
+#define _TEGRA132_FLOW_CTRL_H_
+
+void flowctrl_cpu_off(int cpu);
+void flowctrl_write_cpu_halt(int cpu, uint32_t val);
+
+#endif
diff --git a/src/soc/nvidia/tegra132/psci.c b/src/soc/nvidia/tegra132/psci.c
index b075ffc..4525f98 100644
--- a/src/soc/nvidia/tegra132/psci.c
+++ b/src/soc/nvidia/tegra132/psci.c
@@ -17,8 +17,16 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
  */
 
+#include <arch/cpu.h>
+#include <arch/io.h>
 #include <arch/psci.h>
+#include <soc/addressmap.h>
+#include <soc/clk_rst.h>
 #include <soc/cpu.h>
+#include <soc/flow_ctrl.h>
+#include <soc/power.h>
+
+#include <console/console.h>
 
 static void *cpu_on_entry_point;
 
@@ -57,14 +65,77 @@ static size_t children_at_level(int parent_level, uint64_t mpidr)
 	}
 }
 
+#define TEGRA132_PM_CORE_C7	0x3
+
+static inline void tegra132_enter_sleep(unsigned long pmstate)
+{
+	asm volatile(
+	"       isb\n"
+	"       msr actlr_el1, %0\n"
+	"       wfi\n"
+	:
+	: "r" (pmstate));
+}
+
+static void prepare_cpu_on(int cpu)
+{
+	uint32_t partid;
+
+	partid = cpu ? POWER_PARTID_CE1 : POWER_PARTID_CE0;
+
+	power_ungate_partition(partid);
+	flowctrl_write_cpu_halt(cpu, 0);
+}
+
 static int cmd_prepare(struct psci_cmd *cmd)
 {
-	return PSCI_RET_NOT_SUPPORTED;
+	int ret;
+
+	switch (cmd->type) {
+	case PSCI_CMD_ON:
+		prepare_cpu_on(cmd->target->cpu_state.ci->id);
+		ret = PSCI_RET_SUCCESS;
+		break;
+	case PSCI_CMD_OFF:
+		if (cmd->state_id != -1) {
+			ret = PSCI_RET_INVALID_PARAMETERS;
+			break;
+		}
+		cmd->state_id = TEGRA132_PM_CORE_C7;
+		ret = PSCI_RET_SUCCESS;
+		break;
+	default:
+		ret = PSCI_RET_NOT_SUPPORTED;
+		break;
+	}
+	return ret;
 }
 
 static int cmd_commit(struct psci_cmd *cmd)
 {
-	return PSCI_RET_NOT_SUPPORTED;
+	int ret;
+	struct cpu_info *ci;
+
+	ci = cmd->target->cpu_state.ci;
+
+	switch (cmd->type) {
+	case PSCI_CMD_ON:
+		/* Take CPU out of reset */
+		start_cpu_silent(ci->id, cpu_on_entry_point);
+		ret = PSCI_RET_SUCCESS;
+		break;
+	case PSCI_CMD_OFF:
+		flowctrl_cpu_off(ci->id);
+		tegra132_enter_sleep(cmd->state_id);
+		/* Never reach here */
+		ret = PSCI_RET_NOT_SUPPORTED;
+		printk(BIOS_ERR, "t132 CPU%d PSCI_CMD_OFF fail\n", ci->id);
+		break;
+	default:
+		ret = PSCI_RET_NOT_SUPPORTED;
+		break;
+	}
+	return ret;
 }
 
 struct psci_soc_ops soc_psci_ops = {



More information about the coreboot-gerrit mailing list