u-boot/arch/arm/mach-tegra/pmc.c
Harald Seiler 35b65dd8ef reset: Remove addr parameter from reset_cpu()
Historically, the reset_cpu() function had an `addr` parameter which was
meant to pass in an address of the reset vector location, where the CPU
should reset to.  This feature is no longer used anywhere in U-Boot as
all reset_cpu() implementations now ignore the passed value.  Generic
code has been added which always calls reset_cpu() with `0` which means
this feature can no longer be used easily anyway.

Over time, many implementations seem to have "misunderstood" the
existence of this parameter as a way to customize/parameterize the reset
(e.g.  COLD vs WARM resets).  As this is not properly supported, the
code will almost always not do what it is intended to (because all
call-sites just call reset_cpu() with 0).

To avoid confusion and to clean up the codebase from unused left-overs
of the past, remove the `addr` parameter entirely.  Code which intends
to support different kinds of resets should be rewritten as a sysreset
driver instead.

This transformation was done with the following coccinelle patch:

    @@
    expression argvalue;
    @@
    - reset_cpu(argvalue)
    + reset_cpu()

    @@
    identifier argname;
    type argtype;
    @@
    - reset_cpu(argtype argname)
    + reset_cpu(void)
    { ... }

Signed-off-by: Harald Seiler <hws@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
2021-03-02 14:03:02 -05:00

95 lines
2 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
*/
#include <common.h>
#include <cpu_func.h>
#include <log.h>
#include <asm/global_data.h>
#include <linux/arm-smccc.h>
#include <asm/io.h>
#include <asm/arch-tegra/pmc.h>
DECLARE_GLOBAL_DATA_PTR;
#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE)
static bool tegra_pmc_detect_tz_only(void)
{
static bool initialized = false;
static bool is_tz_only = false;
u32 value, saved;
if (!initialized) {
saved = readl(NV_PA_PMC_BASE + PMC_SCRATCH0);
value = saved ^ 0xffffffff;
if (value == 0xffffffff)
value = 0xdeadbeef;
/* write pattern and read it back */
writel(value, NV_PA_PMC_BASE + PMC_SCRATCH0);
value = readl(NV_PA_PMC_BASE + PMC_SCRATCH0);
/* if we read all-zeroes, access is restricted to TZ only */
if (value == 0) {
debug("access to PMC is restricted to TZ\n");
is_tz_only = true;
} else {
/* restore original value */
writel(saved, NV_PA_PMC_BASE + PMC_SCRATCH0);
}
initialized = true;
}
return is_tz_only;
}
#endif
uint32_t tegra_pmc_readl(unsigned long offset)
{
#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE)
if (tegra_pmc_detect_tz_only()) {
struct arm_smccc_res res;
arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_READ, offset, 0, 0,
0, 0, 0, &res);
if (res.a0)
printf("%s(): SMC failed: %lu\n", __func__, res.a0);
return res.a1;
}
#endif
return readl(NV_PA_PMC_BASE + offset);
}
void tegra_pmc_writel(u32 value, unsigned long offset)
{
#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE)
if (tegra_pmc_detect_tz_only()) {
struct arm_smccc_res res;
arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_WRITE, offset,
value, 0, 0, 0, 0, &res);
if (res.a0)
printf("%s(): SMC failed: %lu\n", __func__, res.a0);
return;
}
#endif
writel(value, NV_PA_PMC_BASE + offset);
}
void reset_cpu(void)
{
u32 value;
value = tegra_pmc_readl(PMC_CNTRL);
value |= PMC_CNTRL_MAIN_RST;
tegra_pmc_writel(value, PMC_CNTRL);
}