18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2011 Google, Inc.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Author:
68c2ecf20Sopenharmony_ci *	Colin Cross <ccross@android.com>
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2010,2013, NVIDIA Corporation
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/cpu_pm.h>
128c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
138c2ecf20Sopenharmony_ci#include <linux/io.h>
148c2ecf20Sopenharmony_ci#include <linux/irqchip/arm-gic.h>
158c2ecf20Sopenharmony_ci#include <linux/irq.h>
168c2ecf20Sopenharmony_ci#include <linux/kernel.h>
178c2ecf20Sopenharmony_ci#include <linux/of_address.h>
188c2ecf20Sopenharmony_ci#include <linux/of.h>
198c2ecf20Sopenharmony_ci#include <linux/syscore_ops.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include <soc/tegra/irq.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include "board.h"
248c2ecf20Sopenharmony_ci#include "iomap.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define SGI_MASK 0xFFFF
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
298c2ecf20Sopenharmony_cistatic void __iomem *tegra_gic_cpu_base;
308c2ecf20Sopenharmony_ci#endif
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cibool tegra_pending_sgi(void)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	u32 pending_set;
358c2ecf20Sopenharmony_ci	void __iomem *distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE);
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	pending_set = readl_relaxed(distbase + GIC_DIST_PENDING_SET);
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	if (pending_set & SGI_MASK)
408c2ecf20Sopenharmony_ci		return true;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	return false;
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
468c2ecf20Sopenharmony_cistatic int tegra_gic_notifier(struct notifier_block *self,
478c2ecf20Sopenharmony_ci			      unsigned long cmd, void *v)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	switch (cmd) {
508c2ecf20Sopenharmony_ci	case CPU_PM_ENTER:
518c2ecf20Sopenharmony_ci		writel_relaxed(0x1E0, tegra_gic_cpu_base + GIC_CPU_CTRL);
528c2ecf20Sopenharmony_ci		break;
538c2ecf20Sopenharmony_ci	}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	return NOTIFY_OK;
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic struct notifier_block tegra_gic_notifier_block = {
598c2ecf20Sopenharmony_ci	.notifier_call = tegra_gic_notifier,
608c2ecf20Sopenharmony_ci};
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic const struct of_device_id tegra114_dt_gic_match[] __initconst = {
638c2ecf20Sopenharmony_ci	{ .compatible = "arm,cortex-a15-gic" },
648c2ecf20Sopenharmony_ci	{ }
658c2ecf20Sopenharmony_ci};
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic void __init tegra114_gic_cpu_pm_registration(void)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	struct device_node *dn;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	dn = of_find_matching_node(NULL, tegra114_dt_gic_match);
728c2ecf20Sopenharmony_ci	if (!dn)
738c2ecf20Sopenharmony_ci		return;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	tegra_gic_cpu_base = of_iomap(dn, 1);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	cpu_pm_register_notifier(&tegra_gic_notifier_block);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci#else
808c2ecf20Sopenharmony_cistatic void __init tegra114_gic_cpu_pm_registration(void) { }
818c2ecf20Sopenharmony_ci#endif
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cistatic const struct of_device_id tegra_ictlr_match[] __initconst = {
848c2ecf20Sopenharmony_ci	{ .compatible = "nvidia,tegra20-ictlr" },
858c2ecf20Sopenharmony_ci	{ .compatible = "nvidia,tegra30-ictlr" },
868c2ecf20Sopenharmony_ci	{ }
878c2ecf20Sopenharmony_ci};
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_civoid __init tegra_init_irq(void)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	if (WARN_ON(!of_find_matching_node(NULL, tegra_ictlr_match)))
928c2ecf20Sopenharmony_ci		pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	tegra114_gic_cpu_pm_registration();
958c2ecf20Sopenharmony_ci}
96