Files
system76-coreboot/src/soc/nvidia/tegra124/power.c
Yen Lin 5840626cec T124: perform ram_repair when CPU rail is powered on in coldboot
This patch is to perform software triggered RAM re-repair in
the cold boot path.

"RAM" actually refers to the CPU cache here (yeah, I know, but that's
how the manuals call it). This is some magic hardware thing that must be
done every time after applying power to the main CPU cores or their
cache may have random failures in some very rare cases.

BUG=chrome-os-partner:30430
BRANCH=nyan
TEST=run cold reboot test on nyan.

Original-Signed-off-by: Yen Lin <yelin@nvidia.com>
Original-Change-Id: I87869431e80e7bc66948a7f67f35e5b907993765
Original-Reviewed-on: https://chromium-review.googlesource.com/207362
Original-Tested-by: Yen Lin <yelin@nvidia.com>
Original-Reviewed-by: Tom Warren <twarren@nvidia.com>
Original-Reviewed-by: Julius Werner <jwerner@chromium.org>
Original-Commit-Queue: Yen Lin <yelin@nvidia.com>
(cherry picked from commit d999f5ecc31d90c8dce1dd91533bc34ffd3c03f2)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>

Change-Id: Iaee1d7f9fa8856f26d7ead70eaeeff9d80dbb181
Reviewed-on: http://review.coreboot.org/8415
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2015-02-17 01:16:47 +01:00

111 lines
3.1 KiB
C

/*
* This file is part of the coreboot project.
*
* Copyright 2013 Google Inc.
* Copyright (c) 2013, 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 <console/console.h>
#include <soc/addressmap.h>
#include <soc/clock.h>
#include "pmc.h"
#include "power.h"
#include "flow.h"
static struct tegra_pmc_regs * const pmc = (void *)TEGRA_PMC_BASE;
static struct flow_ctlr * const flow = (void *)TEGRA_FLOW_BASE;
static int partition_powered(int id)
{
return read32(&pmc->pwrgate_status) & (0x1 << id);
}
static int partition_clamp_on(int id)
{
return read32(&pmc->clamp_status) & (0x1 << id);
}
static void power_ungate_partition(uint32_t id)
{
printk(BIOS_INFO, "Ungating power partition %d.\n", id);
if (!partition_powered(id)) {
uint32_t pwrgate_toggle = read32(&pmc->pwrgate_toggle);
pwrgate_toggle &= ~(PMC_PWRGATE_TOGGLE_PARTID_MASK);
pwrgate_toggle |= (id << PMC_PWRGATE_TOGGLE_PARTID_SHIFT);
pwrgate_toggle |= PMC_PWRGATE_TOGGLE_START;
write32(pwrgate_toggle, &pmc->pwrgate_toggle);
// Wait for the request to be accepted.
while (read32(&pmc->pwrgate_toggle) & PMC_PWRGATE_TOGGLE_START)
;
printk(BIOS_DEBUG, "Power gate toggle request accepted.\n");
// Wait for the partition to be powered.
while (!partition_powered(id))
;
// Wait for clamp off.
while (partition_clamp_on(id))
;
}
printk(BIOS_INFO, "Ungated power partition %d.\n", id);
}
void power_enable_and_ungate_cpu(void)
{
/*
* Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (150MHz),
* set it for 5ms as per SysEng (5ms * PCLK_KHZ * 1000 / 1s).
*/
write32((TEGRA_PCLK_KHZ * 5), &pmc->cpupwrgood_timer);
uint32_t cntrl = read32(&pmc->cntrl);
cntrl &= ~PMC_CNTRL_CPUPWRREQ_POLARITY;
cntrl |= PMC_CNTRL_CPUPWRREQ_OE;
write32(cntrl, &pmc->cntrl);
power_ungate_partition(POWER_PARTID_CRAIL);
// Ungate power to the non-core parts of the fast cluster.
power_ungate_partition(POWER_PARTID_C0NC);
// Ungate power to CPU0 in the fast cluster.
power_ungate_partition(POWER_PARTID_CE0);
}
int power_reset_status(void)
{
return read32(&pmc->rst_status) & 0x7;
}
void ram_repair(void)
{
// Request RAM repair for cluster 0
setbits_le32(&flow->ram_repair, RAM_REPAIR_REQ);
// Poll for completion
while (!(read32(&flow->ram_repair) & RAM_REPAIR_STS))
;
// Request RAM repair for cluster 1
setbits_le32(&flow->ram_repair_cluster1, RAM_REPAIR_REQ);
// Poll for completion
while (!(read32(&flow->ram_repair_cluster1) & RAM_REPAIR_STS))
;
}