Commit 94b847c7 authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'tegra-for-5.16-soc' of...

Merge tag 'tegra-for-5.16-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into arm/drivers

soc/tegra: Changes for v5.16-rc1

This set consists of stub additions to enable compile testing for more
drivers, exposes the PMC's USB regmap on all SoC generations, removes a
state synchronization workaround that is no longer needed and adds an
error reporting driver that can help troubleshoot crashes.

To top it all off, an error handling path in the powergating code is
fixed and the devm_platform_ioremap_resource() function is used to
remove some boilerplate code.

* tag 'tegra-for-5.16-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  soc/tegra: pmc: Use devm_platform_ioremap_resource()
  soc/tegra: Add Tegra186 ARI driver
  soc/tegra: Fix an error handling path in tegra_powergate_power_up()
  soc/tegra: pmc: Expose USB regmap to all SoCs
  soc/tegra: pmc: Disable PMC state syncing
  soc/tegra: pm: Make stubs usable for compile testing
  soc/tegra: irq: Add stubs needed for compile testing
  soc/tegra: fuse: Add stubs needed for compile testing

Link: https://lore.kernel.org/r/20211008201132.1678814-4-thierry.reding@gmail.comSigned-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents e4fb7b44 76d89474
......@@ -7,3 +7,4 @@ obj-$(CONFIG_SOC_TEGRA_PMC) += pmc.o
obj-$(CONFIG_SOC_TEGRA_POWERGATE_BPMP) += powergate-bpmp.o
obj-$(CONFIG_SOC_TEGRA20_VOLTAGE_COUPLER) += regulators-tegra20.o
obj-$(CONFIG_SOC_TEGRA30_VOLTAGE_COUPLER) += regulators-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_186_SOC) += ari-tegra186.o
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/arm-smccc.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/panic_notifier.h>
#define SMC_SIP_INVOKE_MCE 0xc2ffff00
#define MCE_SMC_READ_MCA 12
#define MCA_ARI_CMD_RD_SERR 1
#define MCA_ARI_RW_SUBIDX_STAT 1
#define SERR_STATUS_VAL BIT_ULL(63)
#define MCA_ARI_RW_SUBIDX_ADDR 2
#define MCA_ARI_RW_SUBIDX_MSC1 3
#define MCA_ARI_RW_SUBIDX_MSC2 4
static const char * const bank_names[] = {
"SYS:DPMU", "ROC:IOB", "ROC:MCB", "ROC:CCE", "ROC:CQX", "ROC:CTU",
};
static void read_uncore_mca(u8 cmd, u8 idx, u8 subidx, u8 inst, u64 *data)
{
struct arm_smccc_res res;
arm_smccc_smc(SMC_SIP_INVOKE_MCE | MCE_SMC_READ_MCA,
((u64)inst << 24) | ((u64)idx << 16) |
((u64)subidx << 8) | ((u64)cmd << 0),
0, 0, 0, 0, 0, 0, &res);
*data = res.a2;
}
static int tegra186_ari_panic_handler(struct notifier_block *nb,
unsigned long code, void *unused)
{
u64 status;
int i;
for (i = 0; i < ARRAY_SIZE(bank_names); i++) {
read_uncore_mca(MCA_ARI_CMD_RD_SERR, i, MCA_ARI_RW_SUBIDX_STAT,
0, &status);
if (status & SERR_STATUS_VAL) {
u64 addr, misc1, misc2;
read_uncore_mca(MCA_ARI_CMD_RD_SERR, i,
MCA_ARI_RW_SUBIDX_ADDR, 0, &addr);
read_uncore_mca(MCA_ARI_CMD_RD_SERR, i,
MCA_ARI_RW_SUBIDX_MSC1, 0, &misc1);
read_uncore_mca(MCA_ARI_CMD_RD_SERR, i,
MCA_ARI_RW_SUBIDX_MSC2, 0, &misc2);
pr_crit("Machine Check Error in %s\n"
" status=0x%llx addr=0x%llx\n"
" msc1=0x%llx msc2=0x%llx\n",
bank_names[i], status, addr, misc1, misc2);
}
}
return NOTIFY_DONE;
}
static struct notifier_block tegra186_ari_panic_nb = {
.notifier_call = tegra186_ari_panic_handler,
};
static int __init tegra186_ari_init(void)
{
if (of_machine_is_compatible("nvidia,tegra186"))
atomic_notifier_chain_register(&panic_notifier_list, &tegra186_ari_panic_nb);
return 0;
}
early_initcall(tegra186_ari_init);
......@@ -360,6 +360,7 @@ struct tegra_pmc_soc {
unsigned int num_pmc_clks;
bool has_blink_output;
bool has_usb_sleepwalk;
bool supports_core_domain;
};
/**
......@@ -782,7 +783,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg,
err = reset_control_deassert(pg->reset);
if (err)
goto powergate_off;
goto disable_clks;
usleep_range(10, 20);
......@@ -2815,8 +2816,7 @@ static int tegra_pmc_probe(struct platform_device *pdev)
return err;
/* take over the memory region from the early initialization */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
......@@ -3041,6 +3041,7 @@ static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
}
static const struct tegra_pmc_soc tegra20_pmc_soc = {
.supports_core_domain = false,
.num_powergates = ARRAY_SIZE(tegra20_powergates),
.powergates = tegra20_powergates,
.num_cpu_powergates = 0,
......@@ -3065,7 +3066,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
.pmc_clks_data = NULL,
.num_pmc_clks = 0,
.has_blink_output = true,
.has_usb_sleepwalk = false,
.has_usb_sleepwalk = true,
};
static const char * const tegra30_powergates[] = {
......@@ -3101,6 +3102,7 @@ static const char * const tegra30_reset_sources[] = {
};
static const struct tegra_pmc_soc tegra30_pmc_soc = {
.supports_core_domain = false,
.num_powergates = ARRAY_SIZE(tegra30_powergates),
.powergates = tegra30_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
......@@ -3125,7 +3127,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
.pmc_clks_data = tegra_pmc_clks_data,
.num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
.has_blink_output = true,
.has_usb_sleepwalk = false,
.has_usb_sleepwalk = true,
};
static const char * const tegra114_powergates[] = {
......@@ -3157,6 +3159,7 @@ static const u8 tegra114_cpu_powergates[] = {
};
static const struct tegra_pmc_soc tegra114_pmc_soc = {
.supports_core_domain = false,
.num_powergates = ARRAY_SIZE(tegra114_powergates),
.powergates = tegra114_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
......@@ -3181,7 +3184,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
.pmc_clks_data = tegra_pmc_clks_data,
.num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
.has_blink_output = true,
.has_usb_sleepwalk = false,
.has_usb_sleepwalk = true,
};
static const char * const tegra124_powergates[] = {
......@@ -3273,6 +3276,7 @@ static const struct pinctrl_pin_desc tegra124_pin_descs[] = {
};
static const struct tegra_pmc_soc tegra124_pmc_soc = {
.supports_core_domain = false,
.num_powergates = ARRAY_SIZE(tegra124_powergates),
.powergates = tegra124_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
......@@ -3398,6 +3402,7 @@ static const struct tegra_wake_event tegra210_wake_events[] = {
};
static const struct tegra_pmc_soc tegra210_pmc_soc = {
.supports_core_domain = false,
.num_powergates = ARRAY_SIZE(tegra210_powergates),
.powergates = tegra210_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra210_cpu_powergates),
......@@ -3555,6 +3560,7 @@ static const struct tegra_wake_event tegra186_wake_events[] = {
};
static const struct tegra_pmc_soc tegra186_pmc_soc = {
.supports_core_domain = false,
.num_powergates = 0,
.powergates = NULL,
.num_cpu_powergates = 0,
......@@ -3689,6 +3695,7 @@ static const struct tegra_wake_event tegra194_wake_events[] = {
};
static const struct tegra_pmc_soc tegra194_pmc_soc = {
.supports_core_domain = false,
.num_powergates = 0,
.powergates = NULL,
.num_cpu_powergates = 0,
......@@ -3757,6 +3764,7 @@ static const char * const tegra234_reset_sources[] = {
};
static const struct tegra_pmc_soc tegra234_pmc_soc = {
.supports_core_domain = false,
.num_powergates = 0,
.powergates = NULL,
.num_cpu_powergates = 0,
......@@ -3803,6 +3811,14 @@ static void tegra_pmc_sync_state(struct device *dev)
{
int err;
/*
* Newer device-trees have power domains, but we need to prepare all
* device drivers with runtime PM and OPP support first, otherwise
* state syncing is unsafe.
*/
if (!pmc->soc->supports_core_domain)
return;
/*
* Older device-trees don't have core PD, and thus, there are
* no dependencies that will block the state syncing. We shouldn't
......
......@@ -6,6 +6,8 @@
#ifndef __SOC_TEGRA_FUSE_H__
#define __SOC_TEGRA_FUSE_H__
#include <linux/types.h>
#define TEGRA20 0x20
#define TEGRA30 0x30
#define TEGRA114 0x35
......@@ -22,11 +24,6 @@
#ifndef __ASSEMBLY__
u32 tegra_read_chipid(void);
u8 tegra_get_chip_id(void);
u8 tegra_get_platform(void);
bool tegra_is_silicon(void);
enum tegra_revision {
TEGRA_REVISION_UNKNOWN = 0,
TEGRA_REVISION_A01,
......@@ -57,6 +54,10 @@ extern struct tegra_sku_info tegra_sku_info;
u32 tegra_read_straps(void);
u32 tegra_read_ram_code(void);
int tegra_fuse_readl(unsigned long offset, u32 *value);
u32 tegra_read_chipid(void);
u8 tegra_get_chip_id(void);
u8 tegra_get_platform(void);
bool tegra_is_silicon(void);
#else
static struct tegra_sku_info tegra_sku_info __maybe_unused;
......@@ -74,6 +75,26 @@ static inline int tegra_fuse_readl(unsigned long offset, u32 *value)
{
return -ENODEV;
}
static inline u32 tegra_read_chipid(void)
{
return 0;
}
static inline u8 tegra_get_chip_id(void)
{
return 0;
}
static inline u8 tegra_get_platform(void)
{
return 0;
}
static inline bool tegra_is_silicon(void)
{
return false;
}
#endif
struct device *tegra_soc_device_register(void);
......
......@@ -6,8 +6,15 @@
#ifndef __SOC_TEGRA_IRQ_H
#define __SOC_TEGRA_IRQ_H
#if defined(CONFIG_ARM)
#include <linux/types.h>
#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_TEGRA)
bool tegra_pending_sgi(void);
#else
static inline bool tegra_pending_sgi(void)
{
return false;
}
#endif
#endif /* __SOC_TEGRA_IRQ_H */
......@@ -17,7 +17,7 @@ enum tegra_suspend_mode {
TEGRA_SUSPEND_NOT_READY,
};
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) && defined(CONFIG_ARCH_TEGRA)
enum tegra_suspend_mode
tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment