code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2013 Linaro Ltd.
 * Copyright (c) 2013 HiSilicon Limited.
 */

#include <linux/cpu.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include "core.h"

/* Sysctrl registers in Hi3620 SoC */
#define SCISOEN				0xc0
#define SCISODIS			0xc4
#define SCPERPWREN			0xd0
#define SCPERPWRDIS			0xd4
#define SCCPUCOREEN			0xf4
#define SCCPUCOREDIS			0xf8
#define SCPERCTRL0			0x200
#define SCCPURSTEN			0x410
#define SCCPURSTDIS			0x414

/*
 * bit definition in SCISOEN/SCPERPWREN/...
 *
 * CPU2_ISO_CTRL	(1 << 5)
 * CPU3_ISO_CTRL	(1 << 6)
 * ...
 */
#define CPU2_ISO_CTRL			(1 << 5)

/*
 * bit definition in SCPERCTRL0
 *
 * CPU0_WFI_MASK_CFG	(1 << 28)
 * CPU1_WFI_MASK_CFG	(1 << 29)
 * ...
 */
#define CPU0_WFI_MASK_CFG		(1 << 28)

/*
 * bit definition in SCCPURSTEN/...
 *
 * CPU0_SRST_REQ_EN	(1 << 0)
 * CPU1_SRST_REQ_EN	(1 << 1)
 * ...
 */
#define CPU0_HPM_SRST_REQ_EN		(1 << 22)
#define CPU0_DBG_SRST_REQ_EN		(1 << 12)
#define CPU0_NEON_SRST_REQ_EN		(1 << 4)
#define CPU0_SRST_REQ_EN		(1 << 0)

#define HIX5HD2_PERI_CRG20		0x50
#define CRG20_CPU1_RESET		(1 << 17)

#define HIX5HD2_PERI_PMC0		0x1000
#define PMC0_CPU1_WAIT_MTCOMS_ACK	(1 << 8)
#define PMC0_CPU1_PMC_ENABLE		(1 << 7)
#define PMC0_CPU1_POWERDOWN		(1 << 3)

#define HIP01_PERI9                    0x50
#define PERI9_CPU1_RESET               (1 << 1)

enum {
	HI3620_CTRL,
	ERROR_CTRL,
};

static void __iomem *ctrl_base;
static int id;

static void set_cpu_hi3620(int cpu, bool enable)
{
	u32 val = 0;

	if (enable) {
		/* MTCMOS set */
		if ((cpu == 2) || (cpu == 3))
			writel_relaxed(CPU2_ISO_CTRL << (cpu - 2),
				       ctrl_base + SCPERPWREN);
		udelay(100);

		/* Enable core */
		writel_relaxed(0x01 << cpu, ctrl_base + SCCPUCOREEN);

		/* unreset */
		val = CPU0_DBG_SRST_REQ_EN | CPU0_NEON_SRST_REQ_EN
			| CPU0_SRST_REQ_EN;
		writel_relaxed(val << cpu, ctrl_base + SCCPURSTDIS);
		/* reset */
		val |= CPU0_HPM_SRST_REQ_EN;
		writel_relaxed(val << cpu, ctrl_base + SCCPURSTEN);

		/* ISO disable */
		if ((cpu == 2) || (cpu == 3))
			writel_relaxed(CPU2_ISO_CTRL << (cpu - 2),
				       ctrl_base + SCISODIS);
		udelay(1);

		/* WFI Mask */
		val = readl_relaxed(ctrl_base + SCPERCTRL0);
		val &= ~(CPU0_WFI_MASK_CFG << cpu);
		writel_relaxed(val, ctrl_base + SCPERCTRL0);

		/* Unreset */
		val = CPU0_DBG_SRST_REQ_EN | CPU0_NEON_SRST_REQ_EN
			| CPU0_SRST_REQ_EN | CPU0_HPM_SRST_REQ_EN;
		writel_relaxed(val << cpu, ctrl_base + SCCPURSTDIS);
	} else {
		/* wfi mask */
		val = readl_relaxed(ctrl_base + SCPERCTRL0);
		val |= (CPU0_WFI_MASK_CFG << cpu);
		writel_relaxed(val, ctrl_base + SCPERCTRL0);

		/* disable core*/
		writel_relaxed(0x01 << cpu, ctrl_base + SCCPUCOREDIS);

		if ((cpu == 2) || (cpu == 3)) {
			/* iso enable */
			writel_relaxed(CPU2_ISO_CTRL << (cpu - 2),
				       ctrl_base + SCISOEN);
			udelay(1);
		}

		/* reset */
		val = CPU0_DBG_SRST_REQ_EN | CPU0_NEON_SRST_REQ_EN
			| CPU0_SRST_REQ_EN | CPU0_HPM_SRST_REQ_EN;
		writel_relaxed(val << cpu, ctrl_base + SCCPURSTEN);

		if ((cpu == 2) || (cpu == 3)) {
			/* MTCMOS unset */
			writel_relaxed(CPU2_ISO_CTRL << (cpu - 2),
				       ctrl_base + SCPERPWRDIS);
			udelay(100);
		}
	}
}

static int hi3xxx_hotplug_init(void)
{
	struct device_node *node;

	node = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
	if (!node) {
		id = ERROR_CTRL;
		return -ENOENT;
	}

	ctrl_base = of_iomap(node, 0);
	of_node_put(node);
	if (!ctrl_base) {
		id = ERROR_CTRL;
		return -ENOMEM;
	}

	id = HI3620_CTRL;
	return 0;
}

void hi3xxx_set_cpu(int cpu, bool enable)
{
	if (!ctrl_base) {
		if (hi3xxx_hotplug_init() < 0)
			return;
	}

	if (id == HI3620_CTRL)
		set_cpu_hi3620(cpu, enable);
}

static bool hix5hd2_hotplug_init(void)
{
	struct device_node *np;

	np = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl");
	if (!np)
		return false;

	ctrl_base = of_iomap(np, 0);
	of_node_put(np);
	if (!ctrl_base)
		return false;

	return true;
}

void hix5hd2_set_cpu(int cpu, bool enable)
{
	u32 val = 0;

	if (!ctrl_base)
		if (!hix5hd2_hotplug_init())
			BUG();

	if (enable) {
		/* power on cpu1 */
		val = readl_relaxed(ctrl_base + HIX5HD2_PERI_PMC0);
		val &= ~(PMC0_CPU1_WAIT_MTCOMS_ACK | PMC0_CPU1_POWERDOWN);
		val |= PMC0_CPU1_PMC_ENABLE;
		writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
		/* unreset */
		val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
		val &= ~CRG20_CPU1_RESET;
		writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
	} else {
		/* power down cpu1 */
		val = readl_relaxed(ctrl_base + HIX5HD2_PERI_PMC0);
		val |= PMC0_CPU1_PMC_ENABLE | PMC0_CPU1_POWERDOWN;
		val &= ~PMC0_CPU1_WAIT_MTCOMS_ACK;
		writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);

		/* reset */
		val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
		val |= CRG20_CPU1_RESET;
		writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
	}
}

void hip01_set_cpu(int cpu, bool enable)
{
	unsigned int temp;
	struct device_node *np;

	if (!ctrl_base) {
		np = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
		BUG_ON(!np);
		ctrl_base = of_iomap(np, 0);
		of_node_put(np);
		BUG_ON(!ctrl_base);
	}

	if (enable) {
		/* reset on CPU1  */
		temp = readl_relaxed(ctrl_base + HIP01_PERI9);
		temp |= PERI9_CPU1_RESET;
		writel_relaxed(temp, ctrl_base + HIP01_PERI9);

		udelay(50);

		/* unreset on CPU1 */
		temp = readl_relaxed(ctrl_base + HIP01_PERI9);
		temp &= ~PERI9_CPU1_RESET;
		writel_relaxed(temp, ctrl_base + HIP01_PERI9);
	}
}

static inline void cpu_enter_lowpower(void)
{
	unsigned int v;

	flush_cache_all();

	/*
	 * Turn off coherency and L1 D-cache
	 */
	asm volatile(
	"	mrc	p15, 0, %0, c1, c0, 1\n"
	"	bic	%0, %0, #0x40\n"
	"	mcr	p15, 0, %0, c1, c0, 1\n"
	"	mrc	p15, 0, %0, c1, c0, 0\n"
	"	bic	%0, %0, #0x04\n"
	"	mcr	p15, 0, %0, c1, c0, 0\n"
	  : "=&r" (v)
	  : "r" (0)
	  : "cc");
}

#ifdef CONFIG_HOTPLUG_CPU
void hi3xxx_cpu_die(unsigned int cpu)
{
	cpu_enter_lowpower();
	hi3xxx_set_cpu_jump(cpu, phys_to_virt(0));
	cpu_do_idle();

	/* We should have never returned from idle */
	panic("cpu %d unexpectedly exit from shutdown\n", cpu);
}

int hi3xxx_cpu_kill(unsigned int cpu)
{
	unsigned long timeout = jiffies + msecs_to_jiffies(50);

	while (hi3xxx_get_cpu_jump(cpu))
		if (time_after(jiffies, timeout))
			return 0;
	hi3xxx_set_cpu(cpu, false);
	return 1;
}

void hix5hd2_cpu_die(unsigned int cpu)
{
	flush_cache_all();
	hix5hd2_set_cpu(cpu, false);
}
#endif


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2013-2014 Linaro Ltd.
 * Copyright (c) 2013-2014 HiSilicon Limited.
 */
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/memblock.h>
#include <linux/of_address.h>

#include <asm/cputype.h>
#include <asm/cp15.h>
#include <asm/cacheflush.h>
#include <asm/smp.h>
#include <asm/smp_plat.h>

#include "core.h"

/* bits definition in SC_CPU_RESET_REQ[x]/SC_CPU_RESET_DREQ[x]
 * 1 -- unreset; 0 -- reset
 */
#define CORE_RESET_BIT(x)		(1 << x)
#define NEON_RESET_BIT(x)		(1 << (x + 4))
#define CORE_DEBUG_RESET_BIT(x)		(1 << (x + 9))
#define CLUSTER_L2_RESET_BIT		(1 << 8)
#define CLUSTER_DEBUG_RESET_BIT		(1 << 13)

/*
 * bits definition in SC_CPU_RESET_STATUS[x]
 * 1 -- reset status; 0 -- unreset status
 */
#define CORE_RESET_STATUS(x)		(1 << x)
#define NEON_RESET_STATUS(x)		(1 << (x + 4))
#define CORE_DEBUG_RESET_STATUS(x)	(1 << (x + 9))
#define CLUSTER_L2_RESET_STATUS		(1 << 8)
#define CLUSTER_DEBUG_RESET_STATUS	(1 << 13)
#define CORE_WFI_STATUS(x)		(1 << (x + 16))
#define CORE_WFE_STATUS(x)		(1 << (x + 20))
#define CORE_DEBUG_ACK(x)		(1 << (x + 24))

#define SC_CPU_RESET_REQ(x)		(0x520 + (x << 3))	/* reset */
#define SC_CPU_RESET_DREQ(x)		(0x524 + (x << 3))	/* unreset */
#define SC_CPU_RESET_STATUS(x)		(0x1520 + (x << 3))

#define FAB_SF_MODE			0x0c
#define FAB_SF_INVLD			0x10

/* bits definition in FB_SF_INVLD */
#define FB_SF_INVLD_START		(1 << 8)

#define HIP04_MAX_CLUSTERS		4
#define HIP04_MAX_CPUS_PER_CLUSTER	4

#define POLL_MSEC	10
#define TIMEOUT_MSEC	1000

static void __iomem *sysctrl, *fabric;
static int hip04_cpu_table[HIP04_MAX_CLUSTERS][HIP04_MAX_CPUS_PER_CLUSTER];
static DEFINE_SPINLOCK(boot_lock);
static u32 fabric_phys_addr;
/*
 * [0]: bootwrapper physical address
 * [1]: bootwrapper size
 * [2]: relocation address
 * [3]: relocation size
 */
static u32 hip04_boot_method[4];

static bool hip04_cluster_is_down(unsigned int cluster)
{
	int i;

	for (i = 0; i < HIP04_MAX_CPUS_PER_CLUSTER; i++)
		if (hip04_cpu_table[cluster][i])
			return false;
	return true;
}

static void hip04_set_snoop_filter(unsigned int cluster, unsigned int on)
{
	unsigned long data;

	if (!fabric)
		BUG();
	data = readl_relaxed(fabric + FAB_SF_MODE);
	if (on)
		data |= 1 << cluster;
	else
		data &= ~(1 << cluster);
	writel_relaxed(data, fabric + FAB_SF_MODE);
	do {
		cpu_relax();
	} while (data != readl_relaxed(fabric + FAB_SF_MODE));
}

static int hip04_boot_secondary(unsigned int l_cpu, struct task_struct *idle)
{
	unsigned int mpidr, cpu, cluster;
	unsigned long data;
	void __iomem *sys_dreq, *sys_status;

	mpidr = cpu_logical_map(l_cpu);
	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);

	if (!sysctrl)
		return -ENODEV;
	if (cluster >= HIP04_MAX_CLUSTERS || cpu >= HIP04_MAX_CPUS_PER_CLUSTER)
		return -EINVAL;

	spin_lock_irq(&boot_lock);

	if (hip04_cpu_table[cluster][cpu])
		goto out;

	sys_dreq = sysctrl + SC_CPU_RESET_DREQ(cluster);
	sys_status = sysctrl + SC_CPU_RESET_STATUS(cluster);
	if (hip04_cluster_is_down(cluster)) {
		data = CLUSTER_DEBUG_RESET_BIT;
		writel_relaxed(data, sys_dreq);
		do {
			cpu_relax();
			data = readl_relaxed(sys_status);
		} while (data & CLUSTER_DEBUG_RESET_STATUS);
		hip04_set_snoop_filter(cluster, 1);
	}

	data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
	       CORE_DEBUG_RESET_BIT(cpu);
	writel_relaxed(data, sys_dreq);
	do {
		cpu_relax();
	} while (data == readl_relaxed(sys_status));

	/*
	 * We may fail to power up core again without this delay.
	 * It's not mentioned in document. It's found by test.
	 */
	udelay(20);

	arch_send_wakeup_ipi_mask(cpumask_of(l_cpu));

out:
	hip04_cpu_table[cluster][cpu]++;
	spin_unlock_irq(&boot_lock);

	return 0;
}

#ifdef CONFIG_HOTPLUG_CPU
static void hip04_cpu_die(unsigned int l_cpu)
{
	unsigned int mpidr, cpu, cluster;
	bool last_man;

	mpidr = cpu_logical_map(l_cpu);
	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);

	spin_lock(&boot_lock);
	hip04_cpu_table[cluster][cpu]--;
	if (hip04_cpu_table[cluster][cpu] == 1) {
		/* A power_up request went ahead of us. */
		spin_unlock(&boot_lock);
		return;
	} else if (hip04_cpu_table[cluster][cpu] > 1) {
		pr_err("Cluster %d CPU%d boots multiple times\n", cluster, cpu);
		BUG();
	}

	last_man = hip04_cluster_is_down(cluster);
	spin_unlock(&boot_lock);
	if (last_man) {
		/* Since it's Cortex A15, disable L2 prefetching. */
		asm volatile(
		"mcr	p15, 1, %0, c15, c0, 3 \n\t"
		"isb	\n\t"
		"dsb	"
		: : "r" (0x400) );
		v7_exit_coherency_flush(all);
	} else {
		v7_exit_coherency_flush(louis);
	}

	for (;;)
		wfi();
}

static int hip04_cpu_kill(unsigned int l_cpu)
{
	unsigned int mpidr, cpu, cluster;
	unsigned int data, tries, count;

	mpidr = cpu_logical_map(l_cpu);
	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
	BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
	       cpu >= HIP04_MAX_CPUS_PER_CLUSTER);

	count = TIMEOUT_MSEC / POLL_MSEC;
	spin_lock_irq(&boot_lock);
	for (tries = 0; tries < count; tries++) {
		if (hip04_cpu_table[cluster][cpu])
			goto err;
		cpu_relax();
		data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
		if (data & CORE_WFI_STATUS(cpu))
			break;
		spin_unlock_irq(&boot_lock);
		/* Wait for clean L2 when the whole cluster is down. */
		msleep(POLL_MSEC);
		spin_lock_irq(&boot_lock);
	}
	if (tries >= count)
		goto err;
	data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
	       CORE_DEBUG_RESET_BIT(cpu);
	writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
	for (tries = 0; tries < count; tries++) {
		cpu_relax();
		data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
		if (data & CORE_RESET_STATUS(cpu))
			break;
	}
	if (tries >= count)
		goto err;
	if (hip04_cluster_is_down(cluster))
		hip04_set_snoop_filter(cluster, 0);
	spin_unlock_irq(&boot_lock);
	return 1;
err:
	spin_unlock_irq(&boot_lock);
	return 0;
}
#endif

static const struct smp_operations hip04_smp_ops __initconst = {
	.smp_boot_secondary	= hip04_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
	.cpu_die		= hip04_cpu_die,
	.cpu_kill		= hip04_cpu_kill,
#endif
};

static bool __init hip04_cpu_table_init(void)
{
	unsigned int mpidr, cpu, cluster;

	mpidr = read_cpuid_mpidr();
	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);

	if (cluster >= HIP04_MAX_CLUSTERS ||
	    cpu >= HIP04_MAX_CPUS_PER_CLUSTER) {
		pr_err("%s: boot CPU is out of bound!\n", __func__);
		return false;
	}
	hip04_set_snoop_filter(cluster, 1);
	hip04_cpu_table[cluster][cpu] = 1;
	return true;
}

static int __init hip04_smp_init(void)
{
	struct device_node *np, *np_sctl, *np_fab;
	struct resource fab_res;
	void __iomem *relocation;
	int ret = -ENODEV;

	np = of_find_compatible_node(NULL, NULL, "hisilicon,hip04-bootwrapper");
	if (!np)
		goto err;
	ret = of_property_read_u32_array(np, "boot-method",
					 &hip04_boot_method[0], 4);
	if (ret)
		goto err;

	ret = -ENODEV;
	np_sctl = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
	if (!np_sctl)
		goto err;
	np_fab = of_find_compatible_node(NULL, NULL, "hisilicon,hip04-fabric");
	if (!np_fab)
		goto err;

	ret = memblock_reserve(hip04_boot_method[0], hip04_boot_method[1]);
	if (ret)
		goto err;

	relocation = ioremap(hip04_boot_method[2], hip04_boot_method[3]);
	if (!relocation) {
		pr_err("failed to map relocation space\n");
		ret = -ENOMEM;
		goto err_reloc;
	}
	sysctrl = of_iomap(np_sctl, 0);
	if (!sysctrl) {
		pr_err("failed to get sysctrl base\n");
		ret = -ENOMEM;
		goto err_sysctrl;
	}
	ret = of_address_to_resource(np_fab, 0, &fab_res);
	if (ret) {
		pr_err("failed to get fabric base phys\n");
		goto err_fabric;
	}
	fabric_phys_addr = fab_res.start;
	sync_cache_w(&fabric_phys_addr);
	fabric = of_iomap(np_fab, 0);
	if (!fabric) {
		pr_err("failed to get fabric base\n");
		ret = -ENOMEM;
		goto err_fabric;
	}

	if (!hip04_cpu_table_init()) {
		ret = -EINVAL;
		goto err_table;
	}

	/*
	 * Fill the instruction address that is used after secondary core
	 * out of reset.
	 */
	writel_relaxed(hip04_boot_method[0], relocation);
	writel_relaxed(0xa5a5a5a5, relocation + 4);	/* magic number */
	writel_relaxed(__pa_symbol(secondary_startup), relocation + 8);
	writel_relaxed(0, relocation + 12);
	iounmap(relocation);

	smp_set_ops(&hip04_smp_ops);
	return ret;
err_table:
	iounmap(fabric);
err_fabric:
	iounmap(sysctrl);
err_sysctrl:
	iounmap(relocation);
err_reloc:
	memblock_phys_free(hip04_boot_method[0], hip04_boot_method[1]);
err:
	return ret;
}
early_initcall(hip04_smp_init);

repo_name: angery/linux


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2013 Linaro Ltd.
 * Copyright (c) 2013 HiSilicon Limited.
 * Based on arch/arm/mach-vexpress/platsmp.c, Copyright (C) 2002 ARM Ltd.
 */
#include <linux/smp.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/delay.h>

#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/mach/map.h>

#include "core.h"

#define HIX5HD2_BOOT_ADDRESS		0xffff0000

static void __iomem *ctrl_base;

void hi3xxx_set_cpu_jump(int cpu, void *jump_addr)
{
	cpu = cpu_logical_map(cpu);
	if (!cpu || !ctrl_base)
		return;
	writel_relaxed(__pa_symbol(jump_addr), ctrl_base + ((cpu - 1) << 2));
}

int hi3xxx_get_cpu_jump(int cpu)
{
	cpu = cpu_logical_map(cpu);
	if (!cpu || !ctrl_base)
		return 0;
	return readl_relaxed(ctrl_base + ((cpu - 1) << 2));
}

static void __init hisi_enable_scu_a9(void)
{
	unsigned long base = 0;
	void __iomem *scu_base = NULL;

	if (scu_a9_has_base()) {
		base = scu_a9_get_base();
		scu_base = ioremap(base, SZ_4K);
		if (!scu_base) {
			pr_err("ioremap(scu_base) failed\n");
			return;
		}
		scu_enable(scu_base);
		iounmap(scu_base);
	}
}

static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
{
	struct device_node *np = NULL;
	u32 offset = 0;

	hisi_enable_scu_a9();
	if (!ctrl_base) {
		np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
		if (!np) {
			pr_err("failed to find hisilicon,sysctrl node\n");
			return;
		}
		ctrl_base = of_iomap(np, 0);
		if (!ctrl_base) {
			of_node_put(np);
			pr_err("failed to map address\n");
			return;
		}
		if (of_property_read_u32(np, "smp-offset", &offset) < 0) {
			of_node_put(np);
			pr_err("failed to find smp-offset property\n");
			return;
		}
		ctrl_base += offset;
		of_node_put(np);
	}
}

static int hi3xxx_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	hi3xxx_set_cpu(cpu, true);
	hi3xxx_set_cpu_jump(cpu, secondary_startup);
	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
	return 0;
}

static const struct smp_operations hi3xxx_smp_ops __initconst = {
	.smp_prepare_cpus	= hi3xxx_smp_prepare_cpus,
	.smp_boot_secondary	= hi3xxx_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
	.cpu_die		= hi3xxx_cpu_die,
	.cpu_kill		= hi3xxx_cpu_kill,
#endif
};

static void __init hisi_common_smp_prepare_cpus(unsigned int max_cpus)
{
	hisi_enable_scu_a9();
}

static void hix5hd2_set_scu_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
{
	void __iomem *virt;

	virt = ioremap(start_addr, PAGE_SIZE);

	writel_relaxed(0xe51ff004, virt);	/* ldr pc, [pc, #-4] */
	writel_relaxed(jump_addr, virt + 4);	/* pc jump phy address */
	iounmap(virt);
}

static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	phys_addr_t jumpaddr;

	jumpaddr = __pa_symbol(secondary_startup);
	hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr);
	hix5hd2_set_cpu(cpu, true);
	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
	return 0;
}

static const struct smp_operations hix5hd2_smp_ops __initconst = {
	.smp_prepare_cpus	= hisi_common_smp_prepare_cpus,
	.smp_boot_secondary	= hix5hd2_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
	.cpu_die		= hix5hd2_cpu_die,
#endif
};

#define SC_SCTL_REMAP_CLR      0x00000100
#define HIP01_BOOT_ADDRESS     0x80000000
#define REG_SC_CTRL            0x000

static void hip01_set_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
{
	void __iomem *virt;

	virt = phys_to_virt(start_addr);

	writel_relaxed(0xe51ff004, virt);
	writel_relaxed(jump_addr, virt + 4);
}

static int hip01_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	phys_addr_t jumpaddr;
	unsigned int remap_reg_value = 0;
	struct device_node *node;

	jumpaddr = __pa_symbol(secondary_startup);
	hip01_set_boot_addr(HIP01_BOOT_ADDRESS, jumpaddr);

	node = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
	if (WARN_ON(!node))
		return -1;
	ctrl_base = of_iomap(node, 0);
	of_node_put(node);

	/* set the secondary core boot from DDR */
	remap_reg_value = readl_relaxed(ctrl_base + REG_SC_CTRL);
	barrier();
	remap_reg_value |= SC_SCTL_REMAP_CLR;
	barrier();
	writel_relaxed(remap_reg_value, ctrl_base + REG_SC_CTRL);

	hip01_set_cpu(cpu, true);

	return 0;
}

static const struct smp_operations hip01_smp_ops __initconst = {
	.smp_prepare_cpus       = hisi_common_smp_prepare_cpus,
	.smp_boot_secondary     = hip01_boot_secondary,
};

CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops);
CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops);
CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", &hip01_smp_ops);


code:
menuconfig ARCH_HPE
	bool "HPE SoC support"
	depends on ARCH_MULTI_V7
	help
	  This enables support for HPE ARM based BMC chips.
if ARCH_HPE

config ARCH_HPE_GXP
	bool "HPE GXP SoC"
	depends on ARCH_MULTI_V7
	select ARM_VIC
	select GENERIC_IRQ_CHIP
	select CLKSRC_MMIO
	help
	  HPE GXP is the name of the HPE Soc. This SoC is used to implement many
	  BMC features at HPE. It supports ARMv7 architecture based on the Cortex
	  A9 core. It is capable of using an AXI bus to which a memory controller
	  is attached. It has multiple SPI interfaces to connect boot flash and
	  BIOS flash. It uses a 10/100/1000 MAC for network connectivity. It
	  has multiple i2c engines to drive connectivity with a host
	  infrastructure.

endif

path: arch/arm/mach-hpe/Kconfig


code: obj-$(CONFIG_ARCH_HPE_GXP) += gxp.o

path: arch/arm/mach-hpe/Makefile


code:
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2022 Hewlett-Packard Enterprise Development Company, L.P. */

#include <linux/of_platform.h>
#include <asm/mach/arch.h>

static const char * const gxp_board_dt_compat[] = {
	"hpe,gxp",
	NULL,
};

DT_MACHINE_START(GXP_DT, "HPE GXP")
	.dt_compat	= gxp_board_dt_compat,
	.l2c_aux_val = 0,
	.l2c_aux_mask = ~0,
MACHINE_END


code:
# SPDX-License-Identifier: GPL-2.0-only
menuconfig ARCH_MXC
	bool "Freescale i.MX family"
	depends on ((ARCH_MULTI_V4T || ARCH_MULTI_V5) && CPU_LITTLE_ENDIAN) || \
		ARCH_MULTI_V6_V7 || ARM_SINGLE_ARMV7M
	select CLKSRC_IMX_GPT
	select GENERIC_IRQ_CHIP
	select GPIOLIB
	select PINCTRL
	select PM_OPP if PM
	select SOC_BUS
	select SRAM
	help
	  Support for Freescale MXC/iMX-based family of processors

if ARCH_MXC

config MXC_TZIC
	bool

config MXC_AVIC
	bool

config HAVE_IMX_ANATOP
	bool

config HAVE_IMX_GPC
	bool
	select PM_GENERIC_DOMAINS if PM

config HAVE_IMX_MMDC
	bool

config HAVE_IMX_SRC
	def_bool y if SMP
	select ARCH_HAS_RESET_CONTROLLER

if ARCH_MULTI_V6

comment "ARM1136 platforms"

config SOC_IMX31
	bool "i.MX31 support"
	select CPU_V6
	select MXC_AVIC
	help
	  This enables support for Freescale i.MX31 processor

config SOC_IMX35
	bool "i.MX35 support"
	select MXC_AVIC
	select PINCTRL_IMX35
	help
	  This enables support for Freescale i.MX35 processor

endif

if ARCH_MULTI_V4T

config SOC_IMX1
	bool "i.MX1 support"
	select CPU_ARM920T
	select MXC_AVIC
	select PINCTRL_IMX1
	help
	  This enables support for Freescale i.MX1 processor

endif

if ARCH_MULTI_V5

config SOC_IMX25
	bool "i.MX25 support"
	select CPU_ARM926T
	select MXC_AVIC
	select PINCTRL_IMX25
	help
	  This enables support for Freescale i.MX25 processor

config SOC_IMX27
	bool "i.MX27 support"
	select CPU_ARM926T
	select MXC_AVIC
	select PINCTRL_IMX27
	help
	  This enables support for Freescale i.MX27 processor

endif

if ARCH_MULTI_V7

comment "Cortex-A platforms"

config SOC_IMX5
	bool
	select HAVE_IMX_SRC
	select MXC_TZIC

config SOC_IMX50
	bool "i.MX50 support"
	select PINCTRL_IMX50
	select SOC_IMX5

	help
	  This enables support for Freescale i.MX50 processor.

config SOC_IMX51
	bool "i.MX51 support"
	select PINCTRL_IMX51
	select SOC_IMX5
	help
	  This enables support for Freescale i.MX51 processor

config SOC_IMX53
	bool "i.MX53 support"
	select PINCTRL_IMX53
	select SOC_IMX5

	help
	  This enables support for Freescale i.MX53 processor.

config SOC_IMX6
	bool
	select ARM_CPU_SUSPEND if (PM || CPU_IDLE)
	select ARM_GIC
	select HAVE_IMX_ANATOP
	select HAVE_IMX_GPC
	select HAVE_IMX_MMDC
	select HAVE_IMX_SRC
	select MFD_SYSCON
	select PL310_ERRATA_769419 if CACHE_L2X0

config SOC_IMX6Q
	bool "i.MX6 Quad/DualLite support"
	select ARM_ERRATA_764369 if SMP
	select ARM_ERRATA_754322
	select ARM_ERRATA_775420
	select HAVE_ARM_SCU if SMP
	select HAVE_ARM_TWD
	select PINCTRL_IMX6Q
	select SOC_IMX6

	help
	  This enables support for Freescale i.MX6 Quad processor.

config SOC_IMX6SL
	bool "i.MX6 SoloLite support"
	select ARM_ERRATA_754322
	select ARM_ERRATA_775420
	select PINCTRL_IMX6SL
	select SOC_IMX6

	help
	  This enables support for Freescale i.MX6 SoloLite processor.

config SOC_IMX6SLL
	bool "i.MX6 SoloLiteLite support"
	select ARM_ERRATA_754322
	select ARM_ERRATA_775420
	select PINCTRL_IMX6SLL
	select SOC_IMX6

	help
	  This enables support for Freescale i.MX6 SoloLiteLite processor.

config SOC_IMX6SX
	bool "i.MX6 SoloX support"
	select ARM_ERRATA_754322
	select ARM_ERRATA_775420
	select PINCTRL_IMX6SX
	select SOC_IMX6

	help
	  This enables support for Freescale i.MX6 SoloX processor.

config SOC_IMX6UL
	bool "i.MX6 UltraLite support"
	select PINCTRL_IMX6UL
	select SOC_IMX6
	select ARM_ERRATA_814220

	help
	  This enables support for Freescale i.MX6 UltraLite processor.

config SOC_LS1021A
	bool "Freescale LS1021A support"
	select ARM_GIC
	select HAVE_ARM_ARCH_TIMER
	select ZONE_DMA if ARM_LPAE
	help
	  This enables support for Freescale LS1021A processor.

endif

if ARCH_MULTI_V7 || ARM_SINGLE_ARMV7M

comment "Cortex-A/Cortex-M asymmetric multiprocessing platforms"

config SOC_IMX7D_CA7
	bool
	select ARM_GIC
	select HAVE_ARM_ARCH_TIMER
	select HAVE_IMX_ANATOP
	select HAVE_IMX_MMDC
	select HAVE_IMX_SRC
	select IMX_GPCV2

config SOC_IMX7D_CM4
	bool
	select ARMV7M_SYSTICK

config SOC_IMX7D
	bool "i.MX7 Dual support"
	select PINCTRL_IMX7D
	select SOC_IMX7D_CA7 if ARCH_MULTI_V7
	select SOC_IMX7D_CM4 if ARM_SINGLE_ARMV7M
	select ARM_ERRATA_814220 if ARCH_MULTI_V7
	help
	  This enables support for Freescale i.MX7 Dual processor.

config SOC_IMX7ULP
	bool "i.MX7ULP support"
	select CLKSRC_IMX_TPM
	select PINCTRL_IMX7ULP
	select SOC_IMX7D_CA7 if ARCH_MULTI_V7
	select SOC_IMX7D_CM4 if ARM_SINGLE_ARMV7M
	help
	  This enables support for Freescale i.MX7 Ultra Low Power processor.

config SOC_IMXRT
	bool "i.MXRT support"
	depends on ARM_SINGLE_ARMV7M
	select ARMV7M_SYSTICK if ARM_SINGLE_ARMV7M
	help
	  This enables support for Freescale i.MXRT Crossover processor.

config SOC_VF610
	bool "Vybrid Family VF610 support"
	select ARM_GIC if ARCH_MULTI_V7
	select PINCTRL_VF610

	help
	  This enables support for Freescale Vybrid VF610 processor.

choice
	prompt "Clocksource for scheduler clock"
	depends on SOC_VF610
	default VF_USE_ARM_GLOBAL_TIMER

	config VF_USE_ARM_GLOBAL_TIMER
		bool "Use ARM Global Timer"
		depends on ARCH_MULTI_V7
		select ARM_GLOBAL_TIMER
		select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
		help
		  Use the ARM Global Timer as clocksource

	config VF_USE_PIT_TIMER
		bool "Use PIT timer"
		select VF_PIT_TIMER
		help
		  Use SoC Periodic Interrupt Timer (PIT) as clocksource

endchoice

endif

endif

path: arch/arm/mach-imx/Kconfig


code:
# SPDX-License-Identifier: GPL-2.0
obj-y := cpu.o system.o irq-common.o

obj-$(CONFIG_SOC_IMX25) += cpu-imx25.o mach-imx25.o pm-imx25.o

obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o mach-imx27.o

obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o mach-imx31.o
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o mach-imx35.o

imx5-pm-$(CONFIG_PM) += pm-imx5.o
obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o $(imx5-pm-y)

obj-$(CONFIG_MXC_TZIC) += tzic.o
obj-$(CONFIG_MXC_AVIC) += avic.o

ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
obj-$(CONFIG_SOC_IMX6SLL) += cpuidle-imx6sx.o
obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o
obj-$(CONFIG_SOC_IMX6UL) += cpuidle-imx6sx.o
obj-$(CONFIG_SOC_IMX7ULP) += cpuidle-imx7ulp.o
endif

ifdef CONFIG_SND_SOC_IMX_PCM_FIQ
obj-y += ssi-fiq.o
obj-y += ssi-fiq-ksym.o
endif

obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_IMX7D_CA7)$(CONFIG_SOC_LS1021A),)
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
endif
obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o
obj-$(CONFIG_SOC_IMX6SLL) += mach-imx6sl.o
obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o
obj-$(CONFIG_SOC_IMX6UL) += mach-imx6ul.o
obj-$(CONFIG_SOC_IMX7D_CA7) += mach-imx7d.o
obj-$(CONFIG_SOC_IMX7D_CM4) += mach-imx7d-cm4.o
obj-$(CONFIG_SOC_IMX7ULP) += mach-imx7ulp.o pm-imx7ulp.o

ifeq ($(CONFIG_SUSPEND),y)
obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o
endif
ifeq ($(CONFIG_ARM_CPU_SUSPEND),y)
obj-$(CONFIG_SOC_IMX6) += resume-imx6.o
endif
obj-$(CONFIG_SOC_IMX6) += pm-imx6.o

obj-$(CONFIG_SOC_IMX1) += mach-imx1.o
obj-$(CONFIG_SOC_IMX50) += mach-imx50.o
obj-$(CONFIG_SOC_IMX51) += mach-imx51.o
obj-$(CONFIG_SOC_IMX53) += mach-imx53.o

obj-$(CONFIG_SOC_IMXRT) += mach-imxrt.o

obj-$(CONFIG_SOC_VF610) += mach-vf610.o

obj-$(CONFIG_SOC_LS1021A) += mach-ls1021a.o

path: arch/arm/mach-imx/Makefile


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
 * Copyright 2017-2018 NXP.
 */

#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "common.h"
#include "hardware.h"

#define REG_SET		0x4
#define REG_CLR		0x8

#define ANADIG_REG_2P5		0x130
#define ANADIG_REG_CORE		0x140
#define ANADIG_ANA_MISC0	0x150
#define ANADIG_DIGPROG		0x260
#define ANADIG_DIGPROG_IMX6SL	0x280
#define ANADIG_DIGPROG_IMX7D	0x800

#define SRC_SBMR2		0x1c

#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG	0x40000
#define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN	0x8
#define BM_ANADIG_REG_CORE_FET_ODRIVE		0x20000000
#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG	0x1000
/* Below MISC0_DISCON_HIGH_SNVS is only for i.MX6SL */
#define BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS	0x2000

static struct regmap *anatop;

static void imx_anatop_enable_weak2p5(bool enable)
{
	u32 reg, val;

	regmap_read(anatop, ANADIG_ANA_MISC0, &val);

	/* can only be enabled when stop_mode_config is clear. */
	reg = ANADIG_REG_2P5;
	reg += (enable && (val & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) ?
		REG_SET : REG_CLR;
	regmap_write(anatop, reg, BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG);
}

static void imx_anatop_enable_fet_odrive(bool enable)
{
	regmap_write(anatop, ANADIG_REG_CORE + (enable ? REG_SET : REG_CLR),
		BM_ANADIG_REG_CORE_FET_ODRIVE);
}

static inline void imx_anatop_enable_2p5_pulldown(bool enable)
{
	regmap_write(anatop, ANADIG_REG_2P5 + (enable ? REG_SET : REG_CLR),
		BM_ANADIG_REG_2P5_ENABLE_PULLDOWN);
}

static inline void imx_anatop_disconnect_high_snvs(bool enable)
{
	regmap_write(anatop, ANADIG_ANA_MISC0 + (enable ? REG_SET : REG_CLR),
		BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS);
}

void imx_anatop_pre_suspend(void)
{
	if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
		imx_anatop_enable_2p5_pulldown(true);
	else
		imx_anatop_enable_weak2p5(true);

	imx_anatop_enable_fet_odrive(true);

	if (cpu_is_imx6sl())
		imx_anatop_disconnect_high_snvs(true);
}

void imx_anatop_post_resume(void)
{
	if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
		imx_anatop_enable_2p5_pulldown(false);
	else
		imx_anatop_enable_weak2p5(false);

	imx_anatop_enable_fet_odrive(false);

	if (cpu_is_imx6sl())
		imx_anatop_disconnect_high_snvs(false);
}

void __init imx_init_revision_from_anatop(void)
{
	struct device_node *np, *src_np;
	void __iomem *anatop_base;
	unsigned int revision;
	u32 digprog;
	u16 offset = ANADIG_DIGPROG;
	u8 major_part, minor_part;

	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
	anatop_base = of_iomap(np, 0);
	WARN_ON(!anatop_base);
	if (of_device_is_compatible(np, "fsl,imx6sl-anatop"))
		offset = ANADIG_DIGPROG_IMX6SL;
	if (of_device_is_compatible(np, "fsl,imx7d-anatop"))
		offset = ANADIG_DIGPROG_IMX7D;
	digprog = readl_relaxed(anatop_base + offset);
	iounmap(anatop_base);

	/*
	 * On i.MX7D digprog value match linux version format, so
	 * it needn't map again and we can use register value directly.
	 */
	if (of_device_is_compatible(np, "fsl,imx7d-anatop")) {
		revision = digprog & 0xff;
	} else {
		/*
		 * MAJOR: [15:8], the major silicon revison;
		 * MINOR: [7: 0], the minor silicon revison;
		 *
		 * please refer to the i.MX RM for the detailed
		 * silicon revison bit define.
		 * format the major part and minor part to match the
		 * linux kernel soc version format.
		 */
		major_part = (digprog >> 8) & 0xf;
		minor_part = digprog & 0xf;
		revision = ((major_part + 1) << 4) | minor_part;

		if ((digprog >> 16) == MXC_CPU_IMX6ULL) {
			void __iomem *src_base;
			u32 sbmr2;

			src_np = of_find_compatible_node(NULL, NULL,
						     "fsl,imx6ul-src");
			src_base = of_iomap(src_np, 0);
			of_node_put(src_np);
			WARN_ON(!src_base);
			sbmr2 = readl_relaxed(src_base + SRC_SBMR2);
			iounmap(src_base);

			/* src_sbmr2 bit 6 is to identify if it is i.MX6ULZ */
			if (sbmr2 & (1 << 6)) {
				digprog &= ~(0xff << 16);
				digprog |= (MXC_CPU_IMX6ULZ << 16);
			}
		}
	}
	of_node_put(np);

	mxc_set_cpu_type(digprog >> 16 & 0xff);
	imx_set_soc_revision(revision);
}

void __init imx_anatop_init(void)
{
	anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop");
	if (IS_ERR(anatop))
		pr_err("%s: failed to find imx6q-anatop regmap!\n", __func__);
}


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
 */

#include <linux/module.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/irqchip.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <asm/mach/irq.h>
#include <asm/exception.h>

#include "common.h"
#include "hardware.h"
#include "irq-common.h"

#define AVIC_INTCNTL		0x00	/* int control reg */
#define AVIC_NIMASK		0x04	/* int mask reg */
#define AVIC_INTENNUM		0x08	/* int enable number reg */
#define AVIC_INTDISNUM		0x0C	/* int disable number reg */
#define AVIC_INTENABLEH		0x10	/* int enable reg high */
#define AVIC_INTENABLEL		0x14	/* int enable reg low */
#define AVIC_INTTYPEH		0x18	/* int type reg high */
#define AVIC_INTTYPEL		0x1C	/* int type reg low */
#define AVIC_NIPRIORITY(x)	(0x20 + 4 * (7 - (x))) /* int priority */
#define AVIC_NIVECSR		0x40	/* norm int vector/status */
#define AVIC_FIVECSR		0x44	/* fast int vector/status */
#define AVIC_INTSRCH		0x48	/* int source reg high */
#define AVIC_INTSRCL		0x4C	/* int source reg low */
#define AVIC_INTFRCH		0x50	/* int force reg high */
#define AVIC_INTFRCL		0x54	/* int force reg low */
#define AVIC_NIPNDH		0x58	/* norm int pending high */
#define AVIC_NIPNDL		0x5C	/* norm int pending low */
#define AVIC_FIPNDH		0x60	/* fast int pending high */
#define AVIC_FIPNDL		0x64	/* fast int pending low */

#define AVIC_NUM_IRQS 64

/* low power interrupt mask registers */
#define MX25_CCM_LPIMR0	0x68
#define MX25_CCM_LPIMR1	0x6C

static void __iomem *avic_base;
static void __iomem *mx25_ccm_base;
static struct irq_domain *domain;

#ifdef CONFIG_FIQ
static int avic_set_irq_fiq(unsigned int hwirq, unsigned int type)
{
	unsigned int irqt;

	if (hwirq >= AVIC_NUM_IRQS)
		return -EINVAL;

	if (hwirq < AVIC_NUM_IRQS / 2) {
		irqt = imx_readl(avic_base + AVIC_INTTYPEL) & ~(1 << hwirq);
		imx_writel(irqt | (!!type << hwirq), avic_base + AVIC_INTTYPEL);
	} else {
		hwirq -= AVIC_NUM_IRQS / 2;
		irqt = imx_readl(avic_base + AVIC_INTTYPEH) & ~(1 << hwirq);
		imx_writel(irqt | (!!type << hwirq), avic_base + AVIC_INTTYPEH);
	}

	return 0;
}
#endif /* CONFIG_FIQ */

static struct mxc_extra_irq avic_extra_irq = {
#ifdef CONFIG_FIQ
	.set_irq_fiq = avic_set_irq_fiq,
#endif
};

#ifdef CONFIG_PM
static u32 avic_saved_mask_reg[2];

static void avic_irq_suspend(struct irq_data *d)
{
	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
	struct irq_chip_type *ct = gc->chip_types;
	int idx = d->hwirq >> 5;

	avic_saved_mask_reg[idx] = imx_readl(avic_base + ct->regs.mask);
	imx_writel(gc->wake_active, avic_base + ct->regs.mask);

	if (mx25_ccm_base) {
		u8 offs = d->hwirq < AVIC_NUM_IRQS / 2 ?
			MX25_CCM_LPIMR0 : MX25_CCM_LPIMR1;
		/*
		 * The interrupts which are still enabled will be used as wakeup
		 * sources. Allow those interrupts in low-power mode.
		 * The LPIMR registers use 0 to allow an interrupt, the AVIC
		 * registers use 1.
		 */
		imx_writel(~gc->wake_active, mx25_ccm_base + offs);
	}
}

static void avic_irq_resume(struct irq_data *d)
{
	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
	struct irq_chip_type *ct = gc->chip_types;
	int idx = d->hwirq >> 5;

	imx_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);

	if (mx25_ccm_base) {
		u8 offs = d->hwirq < AVIC_NUM_IRQS / 2 ?
			MX25_CCM_LPIMR0 : MX25_CCM_LPIMR1;

		imx_writel(0xffffffff, mx25_ccm_base + offs);
	}
}

#else
#define avic_irq_suspend NULL
#define avic_irq_resume NULL
#endif

static __init void avic_init_gc(int idx, unsigned int irq_start)
{
	struct irq_chip_generic *gc;
	struct irq_chip_type *ct;

	gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
				    handle_level_irq);
	gc->private = &avic_extra_irq;
	gc->wake_enabled = IRQ_MSK(32);

	ct = gc->chip_types;
	ct->chip.irq_mask = irq_gc_mask_clr_bit;
	ct->chip.irq_unmask = irq_gc_mask_set_bit;
	ct->chip.irq_ack = irq_gc_mask_clr_bit;
	ct->chip.irq_set_wake = irq_gc_set_wake;
	ct->chip.irq_suspend = avic_irq_suspend;
	ct->chip.irq_resume = avic_irq_resume;
	ct->regs.mask = !idx ? AVIC_INTENABLEL : AVIC_INTENABLEH;
	ct->regs.ack = ct->regs.mask;

	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
}

static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
{
	u32 nivector;

	do {
		nivector = imx_readl(avic_base + AVIC_NIVECSR) >> 16;
		if (nivector == 0xffff)
			break;

		generic_handle_domain_irq(domain, nivector);
	} while (1);
}

/*
 * This function initializes the AVIC hardware and disables all the
 * interrupts. It registers the interrupt enable and disable functions
 * to the kernel for each interrupt source.
 */
static void __init mxc_init_irq(void __iomem *irqbase)
{
	struct device_node *np;
	int irq_base;
	int i;

	avic_base = irqbase;

	np = of_find_compatible_node(NULL, NULL, "fsl,imx25-ccm");
	mx25_ccm_base = of_iomap(np, 0);

	if (mx25_ccm_base) {
		/*
		 * By default, we mask all interrupts. We set the actual mask
		 * before we go into low-power mode.
		 */
		imx_writel(0xffffffff, mx25_ccm_base + MX25_CCM_LPIMR0);
		imx_writel(0xffffffff, mx25_ccm_base + MX25_CCM_LPIMR1);
	}

	/* put the AVIC into the reset value with
	 * all interrupts disabled
	 */
	imx_writel(0, avic_base + AVIC_INTCNTL);
	imx_writel(0x1f, avic_base + AVIC_NIMASK);

	/* disable all interrupts */
	imx_writel(0, avic_base + AVIC_INTENABLEH);
	imx_writel(0, avic_base + AVIC_INTENABLEL);

	/* all IRQ no FIQ */
	imx_writel(0, avic_base + AVIC_INTTYPEH);
	imx_writel(0, avic_base + AVIC_INTTYPEL);

	irq_base = irq_alloc_descs(-1, 0, AVIC_NUM_IRQS, numa_node_id());
	WARN_ON(irq_base < 0);

	np = of_find_compatible_node(NULL, NULL, "fsl,avic");
	domain = irq_domain_add_legacy(np, AVIC_NUM_IRQS, irq_base, 0,
				       &irq_domain_simple_ops, NULL);
	WARN_ON(!domain);

	for (i = 0; i < AVIC_NUM_IRQS / 32; i++, irq_base += 32)
		avic_init_gc(i, irq_base);

	/* Set default priority value (0) for all IRQ's */
	for (i = 0; i < 8; i++)
		imx_writel(0, avic_base + AVIC_NIPRIORITY(i));

	set_handle_irq(avic_handle_irq);

#ifdef CONFIG_FIQ
	/* Initialize FIQ */
	init_FIQ(FIQ_START);
#endif

	printk(KERN_INFO "MXC IRQ initialized\n");
}

static int __init imx_avic_init(struct device_node *node,
			       struct device_node *parent)
{
	void __iomem *avic_base;

	avic_base = of_iomap(node, 0);
	BUG_ON(!avic_base);
	mxc_init_irq(avic_base);
	return 0;
}

IRQCHIP_DECLARE(imx_avic, "fsl,avic", imx_avic_init);


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
 */

#ifndef __ASM_ARCH_MXC_COMMON_H__
#define __ASM_ARCH_MXC_COMMON_H__

#include <linux/reboot.h>

struct irq_data;
struct platform_device;
struct pt_regs;
struct clk;
struct device_node;
enum mxc_cpu_pwr_mode;
struct of_device_id;

void mx31_map_io(void);
void mx35_map_io(void);
void imx21_init_early(void);
void imx31_init_early(void);
void imx35_init_early(void);
void mx31_init_irq(void);
void mx35_init_irq(void);
void mxc_set_cpu_type(unsigned int type);
void mxc_restart(enum reboot_mode, const char *);
void mxc_arch_reset_init(void __iomem *);
void imx1_reset_init(void __iomem *);
void imx_set_aips(void __iomem *);
void imx_aips_allow_unprivileged_access(const char *compat);
int mxc_device_init(void);
void imx_set_soc_revision(unsigned int rev);
void imx_init_revision_from_anatop(void);
void imx6_enable_rbc(bool enable);
void imx_gpc_check_dt(void);
void imx_gpc_set_arm_power_in_lpm(bool power_off);
void imx_gpc_set_l2_mem_power_in_lpm(bool power_off);
void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw);
void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw);
void imx25_pm_init(void);
void imx27_pm_init(void);
void imx5_pmu_init(void);

enum mxc_cpu_pwr_mode {
	WAIT_CLOCKED,		/* wfi only */
	WAIT_UNCLOCKED,		/* WAIT */
	WAIT_UNCLOCKED_POWER_OFF,	/* WAIT + SRPG */
	STOP_POWER_ON,		/* just STOP */
	STOP_POWER_OFF,		/* STOP + SRPG */
};

enum ulp_cpu_pwr_mode {
	ULP_PM_HSRUN,    /* High speed run mode */
	ULP_PM_RUN,      /* Run mode */
	ULP_PM_WAIT,     /* Wait mode */
	ULP_PM_STOP,     /* Stop mode */
	ULP_PM_VLPS,     /* Very low power stop mode */
	ULP_PM_VLLS,     /* very low leakage stop mode */
};

void imx_enable_cpu(int cpu, bool enable);
void imx_set_cpu_jump(int cpu, void *jump_addr);
u32 imx_get_cpu_arg(int cpu);
void imx_set_cpu_arg(int cpu, u32 arg);
#ifdef CONFIG_SMP
void v7_secondary_startup(void);
void imx_scu_map_io(void);
void imx_smp_prepare(void);
#else
static inline void imx_scu_map_io(void) {}
static inline void imx_smp_prepare(void) {}
#endif
void imx_src_init(void);
void imx7_src_init(void);
void imx_gpc_pre_suspend(bool arm_power_off);
void imx_gpc_post_resume(void);
void imx_gpc_mask_all(void);
void imx_gpc_restore_all(void);
void imx_gpc_hwirq_mask(unsigned int hwirq);
void imx_gpc_hwirq_unmask(unsigned int hwirq);
void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn);
void imx_anatop_init(void);
void imx_anatop_pre_suspend(void);
void imx_anatop_post_resume(void);
int imx6_set_lpm(enum mxc_cpu_pwr_mode mode);
void imx6_set_int_mem_clk_lpm(bool enable);
int imx_mmdc_get_ddr_type(void);
int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode);

void imx_cpu_die(unsigned int cpu);
int imx_cpu_kill(unsigned int cpu);

#ifdef CONFIG_SUSPEND
void imx53_suspend(void __iomem *ocram_vbase);
extern const u32 imx53_suspend_sz;
void imx6_suspend(void __iomem *ocram_vbase);
#else
static inline void imx53_suspend(void __iomem *ocram_vbase) {}
static const u32 imx53_suspend_sz;
static inline void imx6_suspend(void __iomem *ocram_vbase) {}
#endif

void v7_cpu_resume(void);

void imx6_pm_ccm_init(const char *ccm_compat);
void imx6q_pm_init(void);
void imx6dl_pm_init(void);
void imx6sl_pm_init(void);
void imx6sx_pm_init(void);
void imx6ul_pm_init(void);
void imx7ulp_pm_init(void);

#ifdef CONFIG_PM
void imx51_pm_init(void);
void imx53_pm_init(void);
#else
static inline void imx51_pm_init(void) {}
static inline void imx53_pm_init(void) {}
#endif

#ifdef CONFIG_NEON
int mx51_neon_fixup(void);
#else
static inline int mx51_neon_fixup(void) { return 0; }
#endif

#ifdef CONFIG_CACHE_L2X0
void imx_init_l2cache(void);
#else
static inline void imx_init_l2cache(void) {}
#endif

extern const struct smp_operations imx_smp_ops;
extern const struct smp_operations imx7_smp_ops;
extern const struct smp_operations ls1021a_smp_ops;

#endif


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * MX25 CPU type detection
 *
 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
 * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved
 */
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>

#include "iim.h"
#include "hardware.h"

static int mx25_cpu_rev = -1;

static int mx25_read_cpu_rev(void)
{
	u32 rev;
	void __iomem *iim_base;
	struct device_node *np;

	np = of_find_compatible_node(NULL, NULL, "fsl,imx25-iim");
	iim_base = of_iomap(np, 0);
	BUG_ON(!iim_base);
	rev = readl(iim_base + MXC_IIMSREV);
	iounmap(iim_base);

	switch (rev) {
	case 0x00:
		return IMX_CHIP_REVISION_1_0;
	case 0x01:
		return IMX_CHIP_REVISION_1_1;
	case 0x02:
		return IMX_CHIP_REVISION_1_2;
	default:
		return IMX_CHIP_REVISION_UNKNOWN;
	}
}

int mx25_revision(void)
{
	if (mx25_cpu_rev == -1)
		mx25_cpu_rev = mx25_read_cpu_rev();

	return mx25_cpu_rev;
}
EXPORT_SYMBOL(mx25_revision);


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
 */

/*
 * i.MX27 specific CPU detection code
 */

#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/module.h>

#include "hardware.h"

static int mx27_cpu_rev = -1;
static int mx27_cpu_partnumber;

#define SYS_CHIP_ID             0x00    /* The offset of CHIP ID register */
#define SYSCTRL_OFFSET		0x800	/* Offset from CCM base address */

static int mx27_read_cpu_rev(void)
{
	void __iomem *ccm_base;
	struct device_node *np;
	u32 val;

	np = of_find_compatible_node(NULL, NULL, "fsl,imx27-ccm");
	ccm_base = of_iomap(np, 0);
	BUG_ON(!ccm_base);
	/*
	 * now we have access to the IO registers. As we need
	 * the silicon revision very early we read it here to
	 * avoid any further hooks
	*/
	val = imx_readl(ccm_base + SYSCTRL_OFFSET + SYS_CHIP_ID);

	mx27_cpu_partnumber = (int)((val >> 12) & 0xFFFF);

	switch (val >> 28) {
	case 0:
		return IMX_CHIP_REVISION_1_0;
	case 1:
		return IMX_CHIP_REVISION_2_0;
	case 2:
		return IMX_CHIP_REVISION_2_1;
	default:
		return IMX_CHIP_REVISION_UNKNOWN;
	}
}

/*
 * Returns:
 *	the silicon revision of the cpu
 *	-EINVAL - not a mx27
 */
int mx27_revision(void)
{
	if (mx27_cpu_rev == -1)
		mx27_cpu_rev = mx27_read_cpu_rev();

	if (mx27_cpu_partnumber != 0x8821)
		return -EINVAL;

	return mx27_cpu_rev;
}
EXPORT_SYMBOL(mx27_revision);


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * MX31 CPU type detection
 *
 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
 */

#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/io.h>

#include "common.h"
#include "hardware.h"
#include "iim.h"

static int mx31_cpu_rev = -1;

static struct {
	u8 srev;
	const char *name;
	unsigned int rev;
} mx31_cpu_type[] = {
	{ .srev = 0x00, .name = "i.MX31(L)", .rev = IMX_CHIP_REVISION_1_0 },
	{ .srev = 0x10, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_1 },
	{ .srev = 0x11, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_1 },
	{ .srev = 0x12, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_1 },
	{ .srev = 0x13, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_1 },
	{ .srev = 0x14, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_2 },
	{ .srev = 0x15, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_2 },
	{ .srev = 0x28, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_2_0 },
	{ .srev = 0x29, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_2_0 },
};

static int mx31_read_cpu_rev(void)
{
	void __iomem *iim_base;
	struct device_node *np;
	u32 i, srev;

	np = of_find_compatible_node(NULL, NULL, "fsl,imx31-iim");
	iim_base = of_iomap(np, 0);
	BUG_ON(!iim_base);

	/* read SREV register from IIM module */
	srev = imx_readl(iim_base + MXC_IIMSREV);
	srev &= 0xff;

	for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
		if (srev == mx31_cpu_type[i].srev) {
			imx_print_silicon_rev(mx31_cpu_type[i].name,
						mx31_cpu_type[i].rev);
			return mx31_cpu_type[i].rev;
		}

	imx_print_silicon_rev("i.MX31", IMX_CHIP_REVISION_UNKNOWN);
	return IMX_CHIP_REVISION_UNKNOWN;
}

int mx31_revision(void)
{
	if (mx31_cpu_rev == -1)
		mx31_cpu_rev = mx31_read_cpu_rev();

	return mx31_cpu_rev;
}
EXPORT_SYMBOL(mx31_revision);


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * MX35 CPU type detection
 *
 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
 */
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/io.h>

#include "hardware.h"
#include "iim.h"

static int mx35_cpu_rev = -1;

static int mx35_read_cpu_rev(void)
{
	void __iomem *iim_base;
	struct device_node *np;
	u32 rev;

	np = of_find_compatible_node(NULL, NULL, "fsl,imx35-iim");
	iim_base = of_iomap(np, 0);
	BUG_ON(!iim_base);

	rev = imx_readl(iim_base + MXC_IIMSREV);
	switch (rev) {
	case 0x00:
		return IMX_CHIP_REVISION_1_0;
	case 0x10:
		return IMX_CHIP_REVISION_2_0;
	case 0x11:
		return IMX_CHIP_REVISION_2_1;
	default:
		return IMX_CHIP_REVISION_UNKNOWN;
	}
}

int mx35_revision(void)
{
	if (mx35_cpu_rev == -1)
		mx35_cpu_rev = mx35_read_cpu_rev();

	return mx35_cpu_rev;
}
EXPORT_SYMBOL(mx35_revision);


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * This file contains the CPU initialization code.
 */

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>

#include "hardware.h"
#include "common.h"

static int mx5_cpu_rev = -1;

#define IIM_SREV 0x24

static u32 imx5_read_srev_reg(const char *compat)
{
	void __iomem *iim_base;
	struct device_node *np;
	u32 srev;

	np = of_find_compatible_node(NULL, NULL, compat);
	iim_base = of_iomap(np, 0);
	WARN_ON(!iim_base);

	srev = readl(iim_base + IIM_SREV) & 0xff;

	iounmap(iim_base);

	return srev;
}

static int get_mx51_srev(void)
{
	u32 rev = imx5_read_srev_reg("fsl,imx51-iim");

	switch (rev) {
	case 0x0:
		return IMX_CHIP_REVISION_2_0;
	case 0x10:
		return IMX_CHIP_REVISION_3_0;
	default:
		return IMX_CHIP_REVISION_UNKNOWN;
	}
}

/*
 * Returns:
 *	the silicon revision of the cpu
 */
int mx51_revision(void)
{
	if (mx5_cpu_rev == -1)
		mx5_cpu_rev = get_mx51_srev();

	return mx5_cpu_rev;
}
EXPORT_SYMBOL(mx51_revision);

#ifdef CONFIG_NEON

/*
 * All versions of the silicon before Rev. 3 have broken NEON implementations.
 * Dependent on link order - so the assumption is that vfp_init is called
 * before us.
 */
int __init mx51_neon_fixup(void)
{
	if (mx51_revision() < IMX_CHIP_REVISION_3_0 &&
			(elf_hwcap & HWCAP_NEON)) {
		elf_hwcap &= ~HWCAP_NEON;
		pr_info("Turning off NEON support, detected broken NEON implementation\n");
	}
	return 0;
}

#endif

static int get_mx53_srev(void)
{
	u32 rev = imx5_read_srev_reg("fsl,imx53-iim");

	switch (rev) {
	case 0x0:
		return IMX_CHIP_REVISION_1_0;
	case 0x2:
		return IMX_CHIP_REVISION_2_0;
	case 0x3:
		return IMX_CHIP_REVISION_2_1;
	default:
		return IMX_CHIP_REVISION_UNKNOWN;
	}
}

/*
 * Returns:
 *	the silicon revision of the cpu
 */
int mx53_revision(void)
{
	if (mx5_cpu_rev == -1)
		mx5_cpu_rev = get_mx53_srev();

	return mx5_cpu_rev;
}
EXPORT_SYMBOL(mx53_revision);

#define ARM_GPC		0x4
#define DBGEN		BIT(16)

/*
 * This enables the DBGEN bit in ARM_GPC register, which is
 * required for accessing some performance counter features.
 * Technically it is only required while perf is used, but to
 * keep the source code simple we just enable it all the time
 * when the kernel configuration allows using the feature.
 */
void __init imx5_pmu_init(void)
{
	void __iomem *tigerp_base;
	struct device_node *np;
	u32 gpc;

	if (!IS_ENABLED(CONFIG_ARM_PMU))
		return;

	np = of_find_compatible_node(NULL, NULL, "arm,cortex-a8-pmu");
	if (!np)
		return;

	if (!of_property_read_bool(np, "secure-reg-access"))
		goto exit;

	of_node_put(np);

	np = of_find_compatible_node(NULL, NULL, "fsl,imx51-tigerp");
	if (!np)
		return;

	tigerp_base = of_iomap(np, 0);
	if (!tigerp_base)
		goto exit;

	gpc = readl_relaxed(tigerp_base + ARM_GPC);
	gpc |= DBGEN;
	writel_relaxed(gpc, tigerp_base + ARM_GPC);
	iounmap(tigerp_base);
exit:
	of_node_put(np);

}


code:
// SPDX-License-Identifier: GPL-2.0
#include <linux/err.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>

#include "hardware.h"
#include "common.h"

unsigned int __mxc_cpu_type;
static unsigned int imx_soc_revision;

void mxc_set_cpu_type(unsigned int type)
{
	__mxc_cpu_type = type;
}

void imx_set_soc_revision(unsigned int rev)
{
	imx_soc_revision = rev;
}

unsigned int imx_get_soc_revision(void)
{
	return imx_soc_revision;
}

void imx_print_silicon_rev(const char *cpu, int srev)
{
	if (srev == IMX_CHIP_REVISION_UNKNOWN)
		pr_info("CPU identified as %s, unknown revision\n", cpu);
	else
		pr_info("CPU identified as %s, silicon rev %d.%d\n",
				cpu, (srev >> 4) & 0xf, srev & 0xf);
}

void __init imx_set_aips(void __iomem *base)
{
	unsigned int reg;
/*
 * Set all MPROTx to be non-bufferable, trusted for R/W,
 * not forced to user-mode.
 */
	imx_writel(0x77777777, base + 0x0);
	imx_writel(0x77777777, base + 0x4);

/*
 * Set all OPACRx to be non-bufferable, to not require
 * supervisor privilege level for access, allow for
 * write access and untrusted master access.
 */
	imx_writel(0x0, base + 0x40);
	imx_writel(0x0, base + 0x44);
	imx_writel(0x0, base + 0x48);
	imx_writel(0x0, base + 0x4C);
	reg = imx_readl(base + 0x50) & 0x00FFFFFF;
	imx_writel(reg, base + 0x50);
}

void __init imx_aips_allow_unprivileged_access(
		const char *compat)
{
	void __iomem *aips_base_addr;
	struct device_node *np;

	for_each_compatible_node(np, NULL, compat) {
		aips_base_addr = of_iomap(np, 0);
		WARN_ON(!aips_base_addr);
		imx_set_aips(aips_base_addr);
	}
}


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2012 Freescale Semiconductor, Inc.
 */

#include <linux/cpuidle.h>
#include <linux/module.h>
#include <asm/system_misc.h>
#include "cpuidle.h"

static int imx5_cpuidle_enter(struct cpuidle_device *dev,
			      struct cpuidle_driver *drv, int index)
{
	arm_pm_idle();
	return index;
}

static struct cpuidle_driver imx5_cpuidle_driver = {
	.name             = "imx5_cpuidle",
	.owner            = THIS_MODULE,
	.states[0] = {
		.enter            = imx5_cpuidle_enter,
		.exit_latency     = 2,
		.target_residency = 1,
		.name             = "IMX5 SRPG",
		.desc             = "CPU state retained,powered off",
	},
	.state_count = 1,
};

int __init imx5_cpuidle_init(void)
{
	return cpuidle_register(&imx5_cpuidle_driver, NULL);
}


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2012 Freescale Semiconductor, Inc.
 */

#include <linux/context_tracking.h>
#include <linux/cpuidle.h>
#include <linux/module.h>
#include <asm/cpuidle.h>

#include <soc/imx/cpuidle.h>

#include "common.h"
#include "cpuidle.h"
#include "hardware.h"

static int num_idle_cpus = 0;
static DEFINE_RAW_SPINLOCK(cpuidle_lock);

static int imx6q_enter_wait(struct cpuidle_device *dev,
			    struct cpuidle_driver *drv, int index)
{
	raw_spin_lock(&cpuidle_lock);
	if (++num_idle_cpus == num_online_cpus())
		imx6_set_lpm(WAIT_UNCLOCKED);
	raw_spin_unlock(&cpuidle_lock);

	ct_idle_enter();
	cpu_do_idle();
	ct_idle_exit();

	raw_spin_lock(&cpuidle_lock);
	if (num_idle_cpus-- == num_online_cpus())
		imx6_set_lpm(WAIT_CLOCKED);
	raw_spin_unlock(&cpuidle_lock);

	return index;
}

static struct cpuidle_driver imx6q_cpuidle_driver = {
	.name = "imx6q_cpuidle",
	.owner = THIS_MODULE,
	.states = {
		/* WFI */
		ARM_CPUIDLE_WFI_STATE,
		/* WAIT */
		{
			.exit_latency = 50,
			.target_residency = 75,
			.flags = CPUIDLE_FLAG_TIMER_STOP | CPUIDLE_FLAG_RCU_IDLE,
			.enter = imx6q_enter_wait,
			.name = "WAIT",
			.desc = "Clock off",
		},
	},
	.state_count = 2,
	.safe_state_index = 0,
};

/*
 * i.MX6 Q/DL has an erratum (ERR006687) that prevents the FEC from waking the
 * CPUs when they are in wait(unclocked) state. As the hardware workaround isn't
 * applicable to all boards, disable the deeper idle state when the workaround
 * isn't present and the FEC is in use.
 */
void imx6q_cpuidle_fec_irqs_used(void)
{
	cpuidle_driver_state_disabled(&imx6q_cpuidle_driver, 1, true);
}
EXPORT_SYMBOL_GPL(imx6q_cpuidle_fec_irqs_used);

void imx6q_cpuidle_fec_irqs_unused(void)
{
	cpuidle_driver_state_disabled(&imx6q_cpuidle_driver, 1, false);
}
EXPORT_SYMBOL_GPL(imx6q_cpuidle_fec_irqs_unused);

int __init imx6q_cpuidle_init(void)
{
	/* Set INT_MEM_CLK_LPM bit to get a reliable WAIT mode support */
	imx6_set_int_mem_clk_lpm(true);

	return cpuidle_register(&imx6q_cpuidle_driver, NULL);
}


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2014 Freescale Semiconductor, Inc.
 */

#include <linux/clk/imx.h>
#include <linux/cpuidle.h>
#include <linux/module.h>
#include <asm/cpuidle.h>

#include "common.h"
#include "cpuidle.h"

static int imx6sl_enter_wait(struct cpuidle_device *dev,
			    struct cpuidle_driver *drv, int index)
{
	imx6_set_lpm(WAIT_UNCLOCKED);
	/*
	 * Software workaround for ERR005311, see function
	 * description for details.
	 */
	imx6sl_set_wait_clk(true);
	cpu_do_idle();
	imx6sl_set_wait_clk(false);
	imx6_set_lpm(WAIT_CLOCKED);

	return index;
}

static struct cpuidle_driver imx6sl_cpuidle_driver = {
	.name = "imx6sl_cpuidle",
	.owner = THIS_MODULE,
	.states = {
		/* WFI */
		ARM_CPUIDLE_WFI_STATE,
		/* WAIT */
		{
			.exit_latency = 50,
			.target_residency = 75,
			.flags = CPUIDLE_FLAG_TIMER_STOP,
			.enter = imx6sl_enter_wait,
			.name = "WAIT",
			.desc = "Clock off",
		},
	},
	.state_count = 2,
	.safe_state_index = 0,
};

int __init imx6sl_cpuidle_init(void)
{
	return cpuidle_register(&imx6sl_cpuidle_driver, NULL);
}


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2014 Freescale Semiconductor, Inc.
 */

#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
#include <linux/module.h>
#include <asm/cacheflush.h>
#include <asm/cpuidle.h>
#include <asm/suspend.h>

#include "common.h"
#include "cpuidle.h"
#include "hardware.h"

static int imx6sx_idle_finish(unsigned long val)
{
	/*
	 * for Cortex-A7 which has an internal L2
	 * cache, need to flush it before powering
	 * down ARM platform, since flushing L1 cache
	 * here again has very small overhead, compared
	 * to adding conditional code for L2 cache type,
	 * just call flush_cache_all() is fine.
	 */
	flush_cache_all();
	cpu_do_idle();

	return 0;
}

static int imx6sx_enter_wait(struct cpuidle_device *dev,
			    struct cpuidle_driver *drv, int index)
{
	imx6_set_lpm(WAIT_UNCLOCKED);

	switch (index) {
	case 1:
		cpu_do_idle();
		break;
	case 2:
		imx6_enable_rbc(true);
		imx_gpc_set_arm_power_in_lpm(true);
		imx_set_cpu_jump(0, v7_cpu_resume);
		/* Need to notify there is a cpu pm operation. */
		cpu_pm_enter();
		cpu_cluster_pm_enter();

		cpu_suspend(0, imx6sx_idle_finish);

		cpu_cluster_pm_exit();
		cpu_pm_exit();
		imx_gpc_set_arm_power_in_lpm(false);
		imx6_enable_rbc(false);
		break;
	default:
		break;
	}

	imx6_set_lpm(WAIT_CLOCKED);

	return index;
}

static struct cpuidle_driver imx6sx_cpuidle_driver = {
	.name = "imx6sx_cpuidle",
	.owner = THIS_MODULE,
	.states = {
		/* WFI */
		ARM_CPUIDLE_WFI_STATE,
		/* WAIT */
		{
			.exit_latency = 50,
			.target_residency = 75,
			.flags = CPUIDLE_FLAG_TIMER_STOP,
			.enter = imx6sx_enter_wait,
			.name = "WAIT",
			.desc = "Clock off",
		},
		/* WAIT + ARM power off  */
		{
			/*
			 * ARM gating 31us * 5 + RBC clear 65us
			 * and some margin for SW execution, here set it
			 * to 300us.
			 */
			.exit_latency = 300,
			.target_residency = 500,
			.flags = CPUIDLE_FLAG_TIMER_STOP,
			.enter = imx6sx_enter_wait,
			.name = "LOW-POWER-IDLE",
			.desc = "ARM power off",
		},
	},
	.state_count = 3,
	.safe_state_index = 0,
};

int __init imx6sx_cpuidle_init(void)
{
	imx6_set_int_mem_clk_lpm(true);
	imx6_enable_rbc(false);
	imx_gpc_set_l2_mem_power_in_lpm(false);
	/*
	 * set ARM power up/down timing to the fastest,
	 * sw2iso and sw can be set to one 32K cycle = 31us
	 * except for power up sw2iso which need to be
	 * larger than LDO ramp up time.
	 */
	imx_gpc_set_arm_power_up_timing(cpu_is_imx6sx() ? 0xf : 0x2, 1);
	imx_gpc_set_arm_power_down_timing(1, 1);

	return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
}


code:
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2016 Freescale Semiconductor, Inc.
 * Copyright 2017-2018 NXP
 *   Anson Huang <Anson.Huang@nxp.com>
 */

#include <linux/cpuidle.h>
#include <linux/module.h>
#include <asm/cpuidle.h>

#include "common.h"
#include "cpuidle.h"

static int imx7ulp_enter_wait(struct cpuidle_device *dev,
			    struct cpuidle_driver *drv, int index)
{
	if (index == 1)
		imx7ulp_set_lpm(ULP_PM_WAIT);
	else
		imx7ulp_set_lpm(ULP_PM_STOP);

	cpu_do_idle();

	imx7ulp_set_lpm(ULP_PM_RUN);

	return index;
}

static struct cpuidle_driver imx7ulp_cpuidle_driver = {
	.name = "imx7ulp_cpuidle",
	.owner = THIS_MODULE,
	.states = {
		/* WFI */
		ARM_CPUIDLE_WFI_STATE,
		/* WAIT */
		{
			.exit_latency = 50,
			.target_residency = 75,
			.enter = imx7ulp_enter_wait,
			.name = "WAIT",
			.desc = "PSTOP2",
		},
		/* STOP */
		{
			.exit_latency = 100,
			.target_residency = 150,
			.enter = imx7ulp_enter_wait,
			.name = "STOP",
			.desc = "PSTOP1",
		},
	},
	.state_count = 3,
	.safe_state_index = 0,
};

int __init imx7ulp_cpuidle_init(void)
{
	return cpuidle_register(&imx7ulp_cpuidle_driver, NULL);
}


code:
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright 2012 Freescale Semiconductor, Inc.
 * Copyright 2012 Linaro Ltd.
 */

#ifdef CONFIG_CPU_IDLE
extern int imx5_cpuidle_init(void);
extern int imx6q_cpuidle_init(void);
extern int imx6sl_cpuidle_init(void);
extern int imx6sx_cpuidle_init(void);
extern int imx7ulp_cpuidle_init(void);
#else
static inline int imx5_cpuidle_init(void)
{
	return 0;
}
static inline int imx6q_cpuidle_init(void)
{
	return 0;
}
static inline int imx6sl_cpuidle_init(void)
{
	return 0;
}
static inline int imx6sx_cpuidle_init(void)
{
	return 0;
}
static inline int imx7ulp_cpuidle_init(void)
{
	return 0;
}
#endif


code:
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
 */

#ifndef __ARCH_ARM_MACH_MX3_CRM_REGS_H__
#define __ARCH_ARM_MACH_MX3_CRM_REGS_H__

#define CKIH_CLK_FREQ           26000000
#define CKIH_CLK_FREQ_27MHZ     27000000
#define CKIL_CLK_FREQ           32768

extern void __iomem *mx3_ccm_base;

/* Register addresses */
#define MXC_CCM_CCMR		0x00
#define MXC_CCM_PDR0		0x04
#define MXC_CCM_PDR1		0x08
#define MX35_CCM_PDR2		0x0C
#define MXC_CCM_RCSR		0x0C
#define MX35_CCM_PDR3		0x10
#define MXC_CCM_MPCTL		0x10
#define MX35_CCM_PDR4		0x14
#define MXC_CCM_UPCTL		0x14
#define MX35_CCM_RCSR		0x18
#define MXC_CCM_SRPCTL		0x18
#define MX35_CCM_MPCTL		0x1C
#define MXC_CCM_COSR		0x1C
#define MX35_CCM_PPCTL		0x20
#define MXC_CCM_CGR0		0x20
#define MX35_CCM_ACMR		0x24
#define MXC_CCM_CGR1		0x24
#define MX35_CCM_COSR		0x28
#define MXC_CCM_CGR2		0x28
#define MX35_CCM_CGR0		0x2C
#define MXC_CCM_WIMR		0x2C
#define MX35_CCM_CGR1		0x30
#define MXC_CCM_LDC		0x30
#define MX35_CCM_CGR2		0x34
#define MXC_CCM_DCVR0		0x34
#define MX35_CCM_CGR3		0x38
#define MXC_CCM_DCVR1		0x38
#define MXC_CCM_DCVR2		0x3C
#define MXC_CCM_DCVR3		0x40
#define MXC_CCM_LTR0		0x44
#define MXC_CCM_LTR1		0x48
#define MXC_CCM_LTR2		0x4C
#define MXC_CCM_LTR3		0x50
#define MXC_CCM_LTBR0		0x54
#define MXC_CCM_LTBR1		0x58
#define MXC_CCM_PMCR0		0x5C
#define MXC_CCM_PMCR1		0x60
#define MXC_CCM_PDR2		0x64

/* Register bit definitions */
#define MXC_CCM_CCMR_WBEN                       (1 << 27)
#define MXC_CCM_CCMR_CSCS                       (1 << 25)
#define MXC_CCM_CCMR_PERCS                      (1 << 24)
#define MXC_CCM_CCMR_SSI1S_OFFSET               18
#define MXC_CCM_CCMR_SSI1S_MASK                 (0x3 << 18)
#define MXC_CCM_CCMR_SSI2S_OFFSET               21
#define MXC_CCM_CCMR_SSI2S_MASK                 (0x3 << 21)
#define MXC_CCM_CCMR_LPM_OFFSET                 14
#define MXC_CCM_CCMR_LPM_MASK                   (0x3 << 14)
#define MXC_CCM_CCMR_LPM_WAIT_MX35		(0x1 << 14)
#define MXC_CCM_CCMR_FIRS_OFFSET                11
#define MXC_CCM_CCMR_FIRS_MASK                  (0x3 << 11)
#define MXC_CCM_CCMR_UPE                        (1 << 9)
#define MXC_CCM_CCMR_SPE                        (1 << 8)
#define MXC_CCM_CCMR_MDS                        (1 << 7)
#define MXC_CCM_CCMR_SBYCS                      (1 << 4)
#define MXC_CCM_CCMR_MPE                        (1 << 3)
#define MXC_CCM_CCMR_PRCS_OFFSET                1
#define MXC_CCM_CCMR_PRCS_MASK                  (0x3 << 1)

#define MXC_CCM_PDR0_CSI_PODF_OFFSET            26
#define MXC_CCM_PDR0_CSI_PODF_MASK              (0x3F << 26)
#define MXC_CCM_PDR0_CSI_PRDF_OFFSET            23
#define MXC_CCM_PDR0_CSI_PRDF_MASK              (0x7 << 23)
#define MXC_CCM_PDR0_PER_PODF_OFFSET            16
#define MXC_CCM_PDR0_PER_PODF_MASK              (0x1F << 16)
#define MXC_CCM_PDR0_HSP_PODF_OFFSET            11
#define MXC_CCM_PDR0_HSP_PODF_MASK              (0x7 << 11)
#define MXC_CCM_PDR0_NFC_PODF_OFFSET            8
#define MXC_CCM_PDR0_NFC_PODF_MASK              (0x7 << 8)
#define MXC_CCM_PDR0_IPG_PODF_OFFSET            6
#define MXC_CCM_PDR0_IPG_PODF_MASK              (0x3 << 6)
#define MXC_CCM_PDR0_MAX_PODF_OFFSET            3
#define MXC_CCM_PDR0_MAX_PODF_MASK              (0x7 << 3)
#define MXC_CCM_PDR0_MCU_PODF_OFFSET            0
#define MXC_CCM_PDR0_MCU_PODF_MASK              0x7

#define MXC_CCM_PDR1_USB_PRDF_OFFSET            30
#define MXC_CCM_PDR1_USB_PRDF_MASK              (0x3 << 30)
#define MXC_CCM_PDR1_USB_PODF_OFFSET            27
#define MXC_CCM_PDR1_USB_PODF_MASK              (0x7 << 27)
#define MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET       24
#define MXC_CCM_PDR1_FIRI_PRE_PODF_MASK         (0x7 << 24)
#define MXC_CCM_PDR1_FIRI_PODF_OFFSET           18
#define MXC_CCM_PDR1_FIRI_PODF_MASK             (0x3F << 18)
#define MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET       15
#define MXC_CCM_PDR1_SSI2_PRE_PODF_MASK         (0x7 << 15)
#define MXC_CCM_PDR1_SSI2_PODF_OFFSET           9
#define MXC_CCM_PDR1_SSI2_PODF_MASK             (0x3F << 9)
#define MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET       6
#define MXC_CCM_PDR1_SSI1_PRE_PODF_MASK         (0x7 << 6)
#define MXC_CCM_PDR1_SSI1_PODF_OFFSET           0
#define MXC_CCM_PDR1_SSI1_PODF_MASK             0x3F

/* Bit definitions for RCSR */
#define MXC_CCM_RCSR_NF16B			0x80000000

/*
 * LTR0 register offsets
 */
#define MXC_CCM_LTR0_DIV3CK_OFFSET              1
#define MXC_CCM_LTR0_DIV3CK_MASK                (0x3 << 1)
#define MXC_CCM_LTR0_DNTHR_OFFSET               16
#define MXC_CCM_LTR0_DNTHR_MASK                 (0x3F << 16)
#define MXC_CCM_LTR0_UPTHR_OFFSET               22
#define MXC_CCM_LTR0_UPTHR_MASK                 (0x3F << 22)

/*
 * LTR1 register offsets
 */
#define MXC_CCM_LTR1_PNCTHR_OFFSET              0
#define MXC_CCM_LTR1_PNCTHR_MASK                0x3F
#define MXC_CCM_LTR1_UPCNT_OFFSET               6
#define MXC_CCM_LTR1_UPCNT_MASK                 (0xFF << 6)
#define MXC_CCM_LTR1_DNCNT_OFFSET               14
#define MXC_CCM_LTR1_DNCNT_MASK                 (0xFF << 14)
#define MXC_CCM_LTR1_LTBRSR_MASK                0x400000
#define MXC_CCM_LTR1_LTBRSR_OFFSET              22
#define MXC_CCM_LTR1_LTBRSR                     0x400000
#define MXC_CCM_LTR1_LTBRSH                     0x800000

/*
 * LTR2 bit definitions. x ranges from 0 for WSW9 to 6 for WSW15
 */
#define MXC_CCM_LTR2_WSW_OFFSET(x)              (11 + (x) * 3)
#define MXC_CCM_LTR2_WSW_MASK(x)                (0x7 << \
					MXC_CCM_LTR2_WSW_OFFSET((x)))
#define MXC_CCM_LTR2_EMAC_OFFSET                0
#define MXC_CCM_LTR2_EMAC_MASK                  0x1FF

/*
 * LTR3 bit definitions. x ranges from 0 for WSW0 to 8 for WSW8
 */
#define MXC_CCM_LTR3_WSW_OFFSET(x)              (5 + (x) * 3)
#define MXC_CCM_LTR3_WSW_MASK(x)                (0x7 << \
					MXC_CCM_LTR3_WSW_OFFSET((x)))

#define MXC_CCM_PMCR0_DFSUP1                    0x80000000
#define MXC_CCM_PMCR0_DFSUP1_SPLL               (0 << 31)
#define MXC_CCM_PMCR0_DFSUP1_MPLL               (1 << 31)
#define MXC_CCM_PMCR0_DFSUP0                    0x40000000
#define MXC_CCM_PMCR0_DFSUP0_PLL                (0 << 30)
#define MXC_CCM_PMCR0_DFSUP0_PDR                (1 << 30)
#define MXC_CCM_PMCR0_DFSUP_MASK                (0x3 << 30)

#define DVSUP_TURBO				0
#define DVSUP_HIGH				1
#define DVSUP_MEDIUM				2
#define DVSUP_LOW				3
#define MXC_CCM_PMCR0_DVSUP_TURBO               (DVSUP_TURBO << 28)
#define MXC_CCM_PMCR0_DVSUP_HIGH                (DVSUP_HIGH << 28)
#define MXC_CCM_PMCR0_DVSUP_MEDIUM              (DVSUP_MEDIUM << 28)
#define MXC_CCM_PMCR0_DVSUP_LOW                 (DVSUP_LOW << 28)
#define MXC_CCM_PMCR0_DVSUP_OFFSET              28
#define MXC_CCM_PMCR0_DVSUP_MASK                (0x3 << 28)
#define MXC_CCM_PMCR0_UDSC                      0x08000000
#define MXC_CCM_PMCR0_UDSC_MASK                 (1 << 27)
#define MXC_CCM_PMCR0_UDSC_UP                   (1 << 27)
#define MXC_CCM_PMCR0_UDSC_DOWN                 (0 << 27)

#define MXC_CCM_PMCR0_VSCNT_1                   (0x0 << 24)
#define MXC_CCM_PMCR0_VSCNT_2                   (0x1 << 24)
#define MXC_CCM_PMCR0_VSCNT_3                   (0x2 << 24)
#define MXC_CCM_PMCR0_VSCNT_4                   (0x3 << 24)
#define MXC_CCM_PMCR0_VSCNT_5                   (0x4 << 24)
#define MXC_CCM_PMCR0_VSCNT_6                   (0x5 << 24)
#define MXC_CCM_PMCR0_VSCNT_7                   (0x6 << 24)
#define MXC_CCM_PMCR0_VSCNT_8                   (0x7 << 24)
#define MXC_CCM_PMCR0_VSCNT_OFFSET              24
#define MXC_CCM_PMCR0_VSCNT_MASK                (0x7 << 24)
#define MXC_CCM_PMCR0_DVFEV                     0x00800000
#define MXC_CCM_PMCR0_DVFIS                     0x00400000
#define MXC_CCM_PMCR0_LBMI                      0x00200000
#define MXC_CCM_PMCR0_LBFL                      0x00100000
#define MXC_CCM_PMCR0_LBCF_4                    (0x0 << 18)
#define MXC_CCM_PMCR0_LBCF_8                    (0x1 << 18)
#define MXC_CCM_PMCR0_LBCF_12                   (0x2 << 18)
#define MXC_CCM_PMCR0_LBCF_16                   (0x3 << 18)
#define MXC_CCM_PMCR0_LBCF_OFFSET               18
#define MXC_CCM_PMCR0_LBCF_MASK                 (0x3 << 18)
#define MXC_CCM_PMCR0_PTVIS                     0x00020000
#define MXC_CCM_PMCR0_UPDTEN                    0x00010000
#define MXC_CCM_PMCR0_UPDTEN_MASK               (0x1 << 16)
#define MXC_CCM_PMCR0_FSVAIM                    0x00008000
#define MXC_CCM_PMCR0_FSVAI_OFFSET              13
#define MXC_CCM_PMCR0_FSVAI_MASK                (0x3 << 13)
#define MXC_CCM_PMCR0_DPVCR                     0x00001000
#define MXC_CCM_PMCR0_DPVV                      0x00000800
#define MXC_CCM_PMCR0_WFIM                      0x00000400
#define MXC_CCM_PMCR0_DRCE3                     0x00000200
#define MXC_CCM_PMCR0_DRCE2                     0x00000100
#define MXC_CCM_PMCR0_DRCE1                     0x00000080
#define MXC_CCM_PMCR0_DRCE0                     0x00000040
#define MXC_CCM_PMCR0_DCR                       0x00000020
#define MXC_CCM_PMCR0_DVFEN                     0x00000010
#define MXC_CCM_PMCR0_PTVAIM                    0x00000008
#define MXC_CCM_PMCR0_PTVAI_OFFSET              1
#define MXC_CCM_PMCR0_PTVAI_MASK                (0x3 << 1)
#define MXC_CCM_PMCR0_DPTEN                     0x00000001

#define MXC_CCM_PMCR1_DVGP_OFFSET               0
#define MXC_CCM_PMCR1_DVGP_MASK                 (0xF)

#define MXC_CCM_PMCR1_PLLRDIS                      (0x1 << 7)
#define MXC_CCM_PMCR1_EMIRQ_EN                      (0x1 << 8)

#define MXC_CCM_DCVR_ULV_MASK                   (0x3FF << 22)
#define MXC_CCM_DCVR_ULV_OFFSET                 22
#define MXC_CCM_DCVR_LLV_MASK                   (0x3FF << 12)
#define MXC_CCM_DCVR_LLV_OFFSET                 12
#define MXC_CCM_DCVR_ELV_MASK                   (0x3FF << 2)
#define MXC_CCM_DCVR_ELV_OFFSET                 2

#define MXC_CCM_PDR2_MST2_PDF_MASK              (0x3F << 7)
#define MXC_CCM_PDR2_MST2_PDF_OFFSET            7
#define MXC_CCM_PDR2_MST1_PDF_MASK              0x3F
#define MXC_CCM_PDR2_MST1_PDF_OFFSET            0

#define MXC_CCM_COSR_CLKOSEL_MASK               0x0F
#define MXC_CCM_COSR_CLKOSEL_OFFSET             0
#define MXC_CCM_COSR_CLKOUTDIV_MASK             (0x07 << 6)
#define MXC_CCM_COSR_CLKOUTDIV_OFFSET           6
#define MXC_CCM_COSR_CLKOEN                     (1 << 9)

/*
 * PMCR0 register offsets
 */
#define MXC_CCM_PMCR0_LBFL_OFFSET   20
#define MXC_CCM_PMCR0_DFSUP0_OFFSET 30
#define MXC_CCM_PMCR0_DFSUP1_OFFSET 31

#endif				/* __ARCH_ARM_MACH_MX3_CRM_REGS_H__ */


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2011-2013 Freescale Semiconductor, Inc.
 * Copyright 2011 Linaro Ltd.
 */

#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>

#include "common.h"
#include "hardware.h"

#define GPC_CNTR		0x0
#define GPC_IMR1		0x008
#define GPC_PGC_CPU_PDN		0x2a0
#define GPC_PGC_CPU_PUPSCR	0x2a4
#define GPC_PGC_CPU_PDNSCR	0x2a8
#define GPC_PGC_SW2ISO_SHIFT	0x8
#define GPC_PGC_SW_SHIFT	0x0

#define GPC_CNTR_L2_PGE_SHIFT	22

#define IMR_NUM			4
#define GPC_MAX_IRQS		(IMR_NUM * 32)

static void __iomem *gpc_base;
static u32 gpc_wake_irqs[IMR_NUM];
static u32 gpc_saved_imrs[IMR_NUM];

void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw)
{
	writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) |
		(sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR);
}

void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw)
{
	writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) |
		(sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PDNSCR);
}

void imx_gpc_set_arm_power_in_lpm(bool power_off)
{
	writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN);
}

void imx_gpc_set_l2_mem_power_in_lpm(bool power_off)
{
	u32 val;

	val = readl_relaxed(gpc_base + GPC_CNTR);
	val &= ~(1 << GPC_CNTR_L2_PGE_SHIFT);
	if (power_off)
		val |= 1 << GPC_CNTR_L2_PGE_SHIFT;
	writel_relaxed(val, gpc_base + GPC_CNTR);
}

void imx_gpc_pre_suspend(bool arm_power_off)
{
	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
	int i;

	/* Tell GPC to power off ARM core when suspend */
	if (arm_power_off)
		imx_gpc_set_arm_power_in_lpm(arm_power_off);

	for (i = 0; i < IMR_NUM; i++) {
		gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
		writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4);
	}
}

void imx_gpc_post_resume(void)
{
	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
	int i;

	/* Keep ARM core powered on for other low-power modes */
	imx_gpc_set_arm_power_in_lpm(false);

	for (i = 0; i < IMR_NUM; i++)
		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
}

static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
{
	unsigned int idx = d->hwirq / 32;
	u32 mask;

	mask = 1 << d->hwirq % 32;
	gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
				  gpc_wake_irqs[idx] & ~mask;

	/*
	 * Do *not* call into the parent, as the GIC doesn't have any
	 * wake-up facility...
	 */
	return 0;
}

void imx_gpc_mask_all(void)
{
	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
	int i;

	for (i = 0; i < IMR_NUM; i++) {
		gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
		writel_relaxed(~0, reg_imr1 + i * 4);
	}
}

void imx_gpc_restore_all(void)
{
	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
	int i;

	for (i = 0; i < IMR_NUM; i++)
		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
}

void imx_gpc_hwirq_unmask(unsigned int hwirq)
{
	void __iomem *reg;
	u32 val;

	reg = gpc_base + GPC_IMR1 + hwirq / 32 * 4;
	val = readl_relaxed(reg);
	val &= ~(1 << hwirq % 32);
	writel_relaxed(val, reg);
}

void imx_gpc_hwirq_mask(unsigned int hwirq)
{
	void __iomem *reg;
	u32 val;

	reg = gpc_base + GPC_IMR1 + hwirq / 32 * 4;
	val = readl_relaxed(reg);
	val |= 1 << (hwirq % 32);
	writel_relaxed(val, reg);
}

static void imx_gpc_irq_unmask(struct irq_data *d)
{
	imx_gpc_hwirq_unmask(d->hwirq);
	irq_chip_unmask_parent(d);
}

static void imx_gpc_irq_mask(struct irq_data *d)
{
	imx_gpc_hwirq_mask(d->hwirq);
	irq_chip_mask_parent(d);
}

static struct irq_chip imx_gpc_chip = {
	.name			= "GPC",
	.irq_eoi		= irq_chip_eoi_parent,
	.irq_mask		= imx_gpc_irq_mask,
	.irq_unmask		= imx_gpc_irq_unmask,
	.irq_retrigger		= irq_chip_retrigger_hierarchy,
	.irq_set_wake		= imx_gpc_irq_set_wake,
	.irq_set_type           = irq_chip_set_type_parent,
#ifdef CONFIG_SMP
	.irq_set_affinity	= irq_chip_set_affinity_parent,
#endif
};

static int imx_gpc_domain_translate(struct irq_domain *d,
				    struct irq_fwspec *fwspec,
				    unsigned long *hwirq,
				    unsigned int *type)
{
	if (is_of_node(fwspec->fwnode)) {
		if (fwspec->param_count != 3)
			return -EINVAL;

		/* No PPI should point to this domain */
		if (fwspec->param[0] != 0)
			return -EINVAL;

		*hwirq = fwspec->param[1];
		*type = fwspec->param[2];
		return 0;
	}

	return -EINVAL;
}

static int imx_gpc_domain_alloc(struct irq_domain *domain,
				  unsigned int irq,
				  unsigned int nr_irqs, void *data)
{
	struct irq_fwspec *fwspec = data;
	struct irq_fwspec parent_fwspec;
	irq_hw_number_t hwirq;
	int i;

	if (fwspec->param_count != 3)
		return -EINVAL;	/* Not GIC compliant */
	if (fwspec->param[0] != 0)
		return -EINVAL;	/* No PPI should point to this domain */

	hwirq = fwspec->param[1];
	if (hwirq >= GPC_MAX_IRQS)
		return -EINVAL;	/* Can't deal with this */

	for (i = 0; i < nr_irqs; i++)
		irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
					      &imx_gpc_chip, NULL);

	parent_fwspec = *fwspec;
	parent_fwspec.fwnode = domain->parent->fwnode;
	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
					    &parent_fwspec);
}

static const struct irq_domain_ops imx_gpc_domain_ops = {
	.translate	= imx_gpc_domain_translate,
	.alloc		= imx_gpc_domain_alloc,
	.free		= irq_domain_free_irqs_common,
};

static int __init imx_gpc_init(struct device_node *node,
			       struct device_node *parent)
{
	struct irq_domain *parent_domain, *domain;
	int i;

	if (!parent) {
		pr_err("%pOF: no parent, giving up\n", node);
		return -ENODEV;
	}

	parent_domain = irq_find_host(parent);
	if (!parent_domain) {
		pr_err("%pOF: unable to obtain parent domain\n", node);
		return -ENXIO;
	}

	gpc_base = of_iomap(node, 0);
	if (WARN_ON(!gpc_base))
	        return -ENOMEM;

	domain = irq_domain_add_hierarchy(parent_domain, 0, GPC_MAX_IRQS,
					  node, &imx_gpc_domain_ops,
					  NULL);
	if (!domain) {
		iounmap(gpc_base);
		return -ENOMEM;
	}

	/* Initially mask all interrupts */
	for (i = 0; i < IMR_NUM; i++)
		writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);

	/*
	 * Clear the OF_POPULATED flag set in of_irq_init so that
	 * later the GPC power domain driver will not be skipped.
	 */
	of_node_clear_flag(node, OF_POPULATED);

	return 0;
}
IRQCHIP_DECLARE(imx_gpc, "fsl,imx6q-gpc", imx_gpc_init);

void __init imx_gpc_check_dt(void)
{
	struct device_node *np;

	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
	if (WARN_ON(!np))
		return;

	if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) {
		pr_warn("Outdated DT detected, suspend/resume will NOT work\n");

		/* map GPC, so that at least CPUidle and WARs keep working */
		gpc_base = of_iomap(np, 0);
	}
	of_node_put(np);
}


code:
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright 2004-2007, 2014 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
 */

#ifndef __ASM_ARCH_MXC_HARDWARE_H__
#define __ASM_ARCH_MXC_HARDWARE_H__

#ifndef __ASSEMBLY__
#include <asm/io.h>
#include <soc/imx/revision.h>
#endif
#include <linux/sizes.h>

#define addr_in_module(addr, mod) \
	((unsigned long)(addr) - mod ## _BASE_ADDR < mod ## _SIZE)

#define IMX_IO_P2V_MODULE(addr, module)					\
	(((addr) - module ## _BASE_ADDR) < module ## _SIZE ?		\
	 (addr) - (module ## _BASE_ADDR) + (module ## _BASE_ADDR_VIRT) : 0)

/*
 * This is rather complicated for humans and ugly to verify, but for a machine
 * it's OK.  Still more as it is usually only applied to constants.  The upsides
 * on using this approach are:
 *
 *  - same mapping on all i.MX machines
 *  - works for assembler, too
 *  - no need to nurture #defines for virtual addresses
 *
 * The downside it, it's hard to verify (but I have a script for that).
 *
 * Obviously this needs to be injective for each SoC.  In general it maps the
 * whole address space to [0xf4000000, 0xf5ffffff].  So [0xf6000000,0xfeffffff]
 * is free for per-machine use (e.g. KZM_ARM11_01 uses 64MiB there).
 *
 * It applies the following mappings for the different SoCs:
 *
 * mx1:
 *	IO	0x00200000+0x100000	->	0xf4000000+0x100000
 * mx21:
 *	AIPI	0x10000000+0x100000	->	0xf4400000+0x100000
 *	SAHB1	0x80000000+0x100000	->	0xf5000000+0x100000
 *	X_MEMC	0xdf000000+0x004000	->	0xf5f00000+0x004000
 * mx25:
 *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
 *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
 *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
 * mx27:
 *	AIPI	0x10000000+0x100000	->	0xf4400000+0x100000
 *	SAHB1	0x80000000+0x100000	->	0xf5000000+0x100000
 *	X_MEMC	0xd8000000+0x100000	->	0xf5c00000+0x100000
 * mx31:
 *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
 *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
 *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
 *	X_MEMC	0xb8000000+0x010000	->	0xf5c00000+0x010000
 *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
 * mx35:
 *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
 *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
 *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
 *	X_MEMC	0xb8000000+0x010000	->	0xf5c00000+0x010000
 *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
 * mx51:
 *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
 *	IRAM	0x1ffe0000+0x020000	->	0xf4fe0000+0x020000
 *	DEBUG	0x60000000+0x100000	->	0xf5000000+0x100000
 *	SPBA0	0x70000000+0x100000	->	0xf5400000+0x100000
 *	AIPS1	0x73f00000+0x100000	->	0xf5700000+0x100000
 *	AIPS2	0x83f00000+0x100000	->	0xf5300000+0x100000
 * mx53:
 *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
 *	DEBUG	0x40000000+0x100000	->	0xf5000000+0x100000
 *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
 *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
 *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
 * mx6q:
 *	SCU	0x00a00000+0x004000	->	0xf4000000+0x004000
 *	CCM	0x020c4000+0x004000	->	0xf42c4000+0x004000
 *	ANATOP	0x020c8000+0x004000	->	0xf42c8000+0x004000
 *	UART4	0x021f0000+0x004000	->	0xf42f0000+0x004000
 */
#define IMX_IO_P2V(x)	(						\
			(((x) & 0x80000000) >> 7) |			\
			(0xf4000000 +					\
			(((x) & 0x50000000) >> 6) +			\
			(((x) & 0x0b000000) >> 4) +			\
			(((x) & 0x000fffff))))

#define IMX_IO_ADDRESS(x)	IOMEM(IMX_IO_P2V(x))

#include "mxc.h"

#include "mx3x.h"
#include "mx31.h"
#include "mx35.h"
#include "mx2x.h"
#include "mx27.h"

#define imx_map_entry(soc, name, _type)	{				\
	.virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR),	\
	.pfn = __phys_to_pfn(soc ## _ ## name ## _BASE_ADDR),		\
	.length = soc ## _ ## name ## _SIZE,				\
	.type = _type,							\
}

#endif /* __ASM_ARCH_MXC_HARDWARE_H__ */


code:
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright 2011 Freescale Semiconductor, Inc.
 * Copyright 2011 Linaro Ltd.
 */

#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>

.arch armv7-a

diag_reg_offset:
	.word	g_diag_reg - .

	.macro	set_diag_reg
	adr	r0, diag_reg_offset
	ldr	r1, [r0]
	add	r1, r1, r0		@ r1 = physical &g_diag_reg
	ldr	r0, [r1]
	mcr	p15, 0, r0, c15, c0, 1	@ write diagnostic register
	.endm

ENTRY(v7_secondary_startup)
ARM_BE8(setend be)			@ go BE8 if entered LE
	mrc	p15, 0, r0, c0, c0, 0
	lsl	r0, r0, #16
	lsr	r0, r0, #20
	/* 0xc07 is cortex A7's ID */
	mov	r1, #0xc00
	orr	r1, #0x7
	cmp	r0, r1
	beq	secondary_startup

	set_diag_reg
	b	secondary_startup
ENDPROC(v7_secondary_startup)


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2011 Freescale Semiconductor, Inc.
 * Copyright 2011 Linaro Ltd.
 */

#include <linux/errno.h>
#include <linux/jiffies.h>
#include <asm/cacheflush.h>
#include <asm/cp15.h>
#include <asm/proc-fns.h>

#include "common.h"
#include "hardware.h"

/*
 * platform-specific code to shutdown a CPU
 *
 * Called with IRQs disabled
 */
void imx_cpu_die(unsigned int cpu)
{
	v7_exit_coherency_flush(louis);
	/*
	 * We use the cpu jumping argument register to sync with
	 * imx_cpu_kill() which is running on cpu0 and waiting for
	 * the register being cleared to kill the cpu.
	 */
	imx_set_cpu_arg(cpu, ~0);

	while (1)
		cpu_do_idle();
}

int imx_cpu_kill(unsigned int cpu)
{
	unsigned long timeout = jiffies + msecs_to_jiffies(50);

	while (imx_get_cpu_arg(cpu) == 0)
		if (time_after(jiffies, timeout))
			return 0;
	imx_enable_cpu(cpu, false);
	imx_set_cpu_arg(cpu, 0);
	if (cpu_is_imx7d())
		imx_gpcv2_set_core1_pdn_pup_by_software(true);
	return 1;
}


code:
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
 */

#ifndef __ASM_ARCH_MXC_IIM_H__
#define __ASM_ARCH_MXC_IIM_H__

/* Register offsets */
#define MXC_IIMSTAT             0x0000
#define MXC_IIMSTATM            0x0004
#define MXC_IIMERR              0x0008
#define MXC_IIMEMASK            0x000C
#define MXC_IIMFCTL             0x0010
#define MXC_IIMUA               0x0014
#define MXC_IIMLA               0x0018
#define MXC_IIMSDAT             0x001C
#define MXC_IIMPREV             0x0020
#define MXC_IIMSREV             0x0024
#define MXC_IIMPRG_P            0x0028
#define MXC_IIMSCS0             0x002C
#define MXC_IIMSCS1             0x0030
#define MXC_IIMSCS2             0x0034
#define MXC_IIMSCS3             0x0038
#define MXC_IIMFBAC0            0x0800
#define MXC_IIMJAC              0x0804
#define MXC_IIMHWV1             0x0808
#define MXC_IIMHWV2             0x080C
#define MXC_IIMHAB0             0x0810
#define MXC_IIMHAB1             0x0814
/* Definitions for i.MX27 TO2 */
#define MXC_IIMMAC              0x0814
#define MXC_IIMPREV_FUSE        0x0818
#define MXC_IIMSREV_FUSE        0x081C
#define MXC_IIMSJC_CHALL_0      0x0820
#define MXC_IIMSJC_CHALL_7      0x083C
#define MXC_IIMFB0UC17          0x0840
#define MXC_IIMFB0UC255         0x0BFC
#define MXC_IIMFBAC1            0x0C00
/* Definitions for i.MX27 TO2 */
#define MXC_IIMSUID             0x0C04
#define MXC_IIMKEY0             0x0C04
#define MXC_IIMKEY20            0x0C54
#define MXC_IIMSJC_RESP_0       0x0C58
#define MXC_IIMSJC_RESP_7       0x0C74
#define MXC_IIMFB1UC30          0x0C78
#define MXC_IIMFB1UC255         0x0FFC

/* Bit definitions */

#define MXC_IIMHWV1_WLOCK               (0x1 << 7)
#define MXC_IIMHWV1_MCU_ENDIAN          (0x1 << 6)
#define MXC_IIMHWV1_DSP_ENDIAN          (0x1 << 5)
#define MXC_IIMHWV1_BOOT_INT            (0x1 << 4)
#define MXC_IIMHWV1_SCC_DISABLE         (0x1 << 3)
#define MXC_IIMHWV1_HANTRO_DISABLE      (0x1 << 2)
#define MXC_IIMHWV1_MEMSTICK_DIS        (0x1 << 1)

#define MXC_IIMHWV2_WLOCK               (0x1 << 7)
#define MXC_IIMHWV2_BP_SDMA             (0x1 << 6)
#define MXC_IIMHWV2_SCM_DCM             (0x1 << 5)

#endif /* __ASM_ARCH_MXC_IIM_H__ */


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) BitBox Ltd 2010
 */

#include <linux/module.h>
#include <linux/irq.h>
#include <linux/platform_data/asoc-imx-ssi.h>

#include "irq-common.h"

int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
{
	struct irq_chip_generic *gc;
	struct mxc_extra_irq *exirq;
	int ret;

	ret = -ENOSYS;

	gc = irq_get_chip_data(irq);
	if (gc && gc->private) {
		exirq = gc->private;
		if (exirq->set_irq_fiq) {
			struct irq_data *d = irq_get_irq_data(irq);
			ret = exirq->set_irq_fiq(irqd_to_hwirq(d), type);
		}
	}

	return ret;
}
EXPORT_SYMBOL(mxc_set_irq_fiq);


code:
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) BitBox Ltd 2010
 */

#ifndef __PLAT_MXC_IRQ_COMMON_H__
#define __PLAT_MXC_IRQ_COMMON_H__

/* all normal IRQs can be FIQs */
#define FIQ_START	0

struct mxc_extra_irq
{
	int (*set_irq_fiq)(unsigned int irq, unsigned int type);
};

#endif


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
 */

#include <linux/of_platform.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>

#include "common.h"
#include "hardware.h"

#define MX1_AVIC_ADDR	0x00223000

static void __init imx1_init_early(void)
{
	mxc_set_cpu_type(MXC_CPU_MX1);
}

static const char * const imx1_dt_board_compat[] __initconst = {
	"fsl,imx1",
	NULL
};

DT_MACHINE_START(IMX1_DT, "Freescale i.MX1 (Device Tree Support)")
	.init_early	= imx1_init_early,
	.dt_compat	= imx1_dt_board_compat,
	.restart	= mxc_restart,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2012 Sascha Hauer, Pengutronix
 */

#include <linux/irq.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include "common.h"
#include "hardware.h"

static void __init imx25_init_early(void)
{
	mxc_set_cpu_type(MXC_CPU_MX25);
}

static void __init imx25_dt_init(void)
{
	imx_aips_allow_unprivileged_access("fsl,imx25-aips");
}

static const char * const imx25_dt_board_compat[] __initconst = {
	"fsl,imx25",
	NULL
};

DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
	.init_early	= imx25_init_early,
	.init_machine	= imx25_dt_init,
	.init_late      = imx25_pm_init,
	.dt_compat	= imx25_dt_board_compat,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2012 Sascha Hauer, Pengutronix
 */

#include <linux/init.h>
#include <linux/irq.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/mm.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>

#include "common.h"
#include "hardware.h"
#include "mx27.h"

/* MX27 memory map definition */
static struct map_desc imx27_io_desc[] __initdata = {
	/*
	 * this fixed mapping covers:
	 * - AIPI1
	 * - AIPI2
	 * - AITC
	 * - ROM Patch
	 * - and some reserved space
	 */
	imx_map_entry(MX27, AIPI, MT_DEVICE),
	/*
	 * this fixed mapping covers:
	 * - CSI
	 * - ATA
	 */
	imx_map_entry(MX27, SAHB1, MT_DEVICE),
	/*
	 * this fixed mapping covers:
	 * - EMI
	 */
	imx_map_entry(MX27, X_MEMC, MT_DEVICE),
};

/*
 * Initialize the memory map. It is called during the
 * system startup to create static physical to virtual
 * memory map for the IO modules.
 */
static void __init mx27_map_io(void)
{
	iotable_init(imx27_io_desc, ARRAY_SIZE(imx27_io_desc));
}

static void __init imx27_init_early(void)
{
	mxc_set_cpu_type(MXC_CPU_MX27);
}

static const char * const imx27_dt_board_compat[] __initconst = {
	"fsl,imx27",
	NULL
};

DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)")
	.map_io		= mx27_map_io,
	.init_early	= imx27_init_early,
	.init_late	= imx27_pm_init,
	.dt_compat	= imx27_dt_board_compat,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2012 Sascha Hauer, Pengutronix
 */

#include <asm/mach/arch.h>
#include "common.h"

static const char * const imx31_dt_board_compat[] __initconst = {
	"fsl,imx31",
	NULL
};

DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)")
	.map_io		= mx31_map_io,
	.init_early	= imx31_init_early,
	.dt_compat	= imx31_dt_board_compat,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2012 Steffen Trumtrar, Pengutronix
 *
 * based on imx27-dt.c
 */

#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/hardware/cache-l2x0.h>
#include "common.h"
#include "mx35.h"

static const char * const imx35_dt_board_compat[] __initconst = {
	"fsl,imx35",
	NULL
};

DT_MACHINE_START(IMX35_DT, "Freescale i.MX35 (Device Tree Support)")
	.l2c_aux_val 	= 0,
	.l2c_aux_mask	= ~0,
	.map_io		= mx35_map_io,
	.init_early	= imx35_init_early,
	.dt_compat	= imx35_dt_board_compat,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2013 Greg Ungerer <gerg@uclinux.org>
 * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright 2011 Linaro Ltd.
 */

#include <linux/of_platform.h>
#include <asm/mach/arch.h>

#include "common.h"
#include "hardware.h"

static void __init imx50_init_early(void)
{
	mxc_set_cpu_type(MXC_CPU_MX50);
}

static const char * const imx50_dt_board_compat[] __initconst = {
	"fsl,imx50",
	NULL
};

DT_MACHINE_START(IMX50_DT, "Freescale i.MX50 (Device Tree Support)")
	.init_early	= imx50_init_early,
	.dt_compat	= imx50_dt_board_compat,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright 2011 Linaro Ltd.
 */

#include <linux/io.h>
#include <linux/irq.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>

#include "common.h"
#include "hardware.h"

static void __init imx51_init_early(void)
{
	mxc_set_cpu_type(MXC_CPU_MX51);
}

/*
 * The MIPI HSC unit has been removed from the i.MX51 Reference Manual by
 * the Freescale marketing division. However this did not remove the
 * hardware from the chip which still needs to be configured for proper
 * IPU support.
 */
#define MX51_MIPI_HSC_BASE 0x83fdc000
static void __init imx51_ipu_mipi_setup(void)
{
	void __iomem *hsc_addr;

	hsc_addr = ioremap(MX51_MIPI_HSC_BASE, SZ_16K);
	WARN_ON(!hsc_addr);

	/* setup MIPI module to legacy mode */
	imx_writel(0xf00, hsc_addr);

	/* CSI mode: reserved; DI control mode: legacy (from Freescale BSP) */
	imx_writel(imx_readl(hsc_addr + 0x800) | 0x30ff, hsc_addr + 0x800);

	iounmap(hsc_addr);
}

static void __init imx51_m4if_setup(void)
{
	void __iomem *m4if_base;
	struct device_node *np;

	np = of_find_compatible_node(NULL, NULL, "fsl,imx51-m4if");
	if (!np)
		return;

	m4if_base = of_iomap(np, 0);
	of_node_put(np);
	if (!m4if_base) {
		pr_err("Unable to map M4IF registers\n");
		return;
	}

	/*
	 * Configure VPU and IPU with higher priorities
	 * in order to avoid artifacts during video playback
	 */
	writel_relaxed(0x00000203, m4if_base + 0x40);
	writel_relaxed(0x00000000, m4if_base + 0x44);
	writel_relaxed(0x00120125, m4if_base + 0x9c);
	writel_relaxed(0x001901A3, m4if_base + 0x48);
	iounmap(m4if_base);
}

static void __init imx51_dt_init(void)
{
	imx51_ipu_mipi_setup();
	imx_src_init();
	imx51_m4if_setup();
	imx5_pmu_init();
	imx_aips_allow_unprivileged_access("fsl,imx51-aipstz");
}

static void __init imx51_init_late(void)
{
	mx51_neon_fixup();
	imx51_pm_init();
}

static const char * const imx51_dt_board_compat[] __initconst = {
	"fsl,imx51",
	NULL
};

DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
	.init_early	= imx51_init_early,
	.init_machine	= imx51_dt_init,
	.init_late	= imx51_init_late,
	.dt_compat	= imx51_dt_board_compat,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright 2011 Linaro Ltd.
 */

#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>

#include "common.h"
#include "hardware.h"

static void __init imx53_init_early(void)
{
	mxc_set_cpu_type(MXC_CPU_MX53);
}

static void __init imx53_dt_init(void)
{
	imx_src_init();
	imx5_pmu_init();
	imx_aips_allow_unprivileged_access("fsl,imx53-aipstz");
}

static void __init imx53_init_late(void)
{
	imx53_pm_init();
}

static const char * const imx53_dt_board_compat[] __initconst = {
	"fsl,imx53",
	NULL
};

DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
	.init_early	= imx53_init_early,
	.init_machine	= imx53_dt_init,
	.init_late	= imx53_init_late,
	.dt_compat	= imx53_dt_board_compat,
MACHINE_END