162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Copyright (C) 1999,2000 Arm Limited
462306a36Sopenharmony_ci *  Copyright (C) 2000 Deep Blue Solutions Ltd
562306a36Sopenharmony_ci *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
662306a36Sopenharmony_ci *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
762306a36Sopenharmony_ci *    - add MX31 specific definitions
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/mm.h>
1162306a36Sopenharmony_ci#include <linux/init.h>
1262306a36Sopenharmony_ci#include <linux/err.h>
1362306a36Sopenharmony_ci#include <linux/io.h>
1462306a36Sopenharmony_ci#include <linux/of_address.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <asm/system_misc.h>
1762306a36Sopenharmony_ci#include <asm/hardware/cache-l2x0.h>
1862306a36Sopenharmony_ci#include <asm/mach/map.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include "common.h"
2162306a36Sopenharmony_ci#include "crmregs-imx3.h"
2262306a36Sopenharmony_ci#include "hardware.h"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_civoid __iomem *mx3_ccm_base;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic void imx3_idle(void)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	unsigned long reg = 0;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	__asm__ __volatile__(
3162306a36Sopenharmony_ci		/* disable I and D cache */
3262306a36Sopenharmony_ci		"mrc p15, 0, %0, c1, c0, 0\n"
3362306a36Sopenharmony_ci		"bic %0, %0, #0x00001000\n"
3462306a36Sopenharmony_ci		"bic %0, %0, #0x00000004\n"
3562306a36Sopenharmony_ci		"mcr p15, 0, %0, c1, c0, 0\n"
3662306a36Sopenharmony_ci		/* invalidate I cache */
3762306a36Sopenharmony_ci		"mov %0, #0\n"
3862306a36Sopenharmony_ci		"mcr p15, 0, %0, c7, c5, 0\n"
3962306a36Sopenharmony_ci		/* clear and invalidate D cache */
4062306a36Sopenharmony_ci		"mov %0, #0\n"
4162306a36Sopenharmony_ci		"mcr p15, 0, %0, c7, c14, 0\n"
4262306a36Sopenharmony_ci		/* WFI */
4362306a36Sopenharmony_ci		"mov %0, #0\n"
4462306a36Sopenharmony_ci		"mcr p15, 0, %0, c7, c0, 4\n"
4562306a36Sopenharmony_ci		"nop\n" "nop\n" "nop\n" "nop\n"
4662306a36Sopenharmony_ci		"nop\n" "nop\n" "nop\n"
4762306a36Sopenharmony_ci		/* enable I and D cache */
4862306a36Sopenharmony_ci		"mrc p15, 0, %0, c1, c0, 0\n"
4962306a36Sopenharmony_ci		"orr %0, %0, #0x00001000\n"
5062306a36Sopenharmony_ci		"orr %0, %0, #0x00000004\n"
5162306a36Sopenharmony_ci		"mcr p15, 0, %0, c1, c0, 0\n"
5262306a36Sopenharmony_ci		: "=r" (reg));
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic void __iomem *imx3_ioremap_caller(phys_addr_t phys_addr, size_t size,
5662306a36Sopenharmony_ci					 unsigned int mtype, void *caller)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	if (mtype == MT_DEVICE) {
5962306a36Sopenharmony_ci		/*
6062306a36Sopenharmony_ci		 * Access all peripherals below 0x80000000 as nonshared device
6162306a36Sopenharmony_ci		 * on mx3, but leave l2cc alone.  Otherwise cache corruptions
6262306a36Sopenharmony_ci		 * can occur.
6362306a36Sopenharmony_ci		 */
6462306a36Sopenharmony_ci		if (phys_addr < 0x80000000 &&
6562306a36Sopenharmony_ci				!addr_in_module(phys_addr, MX3x_L2CC))
6662306a36Sopenharmony_ci			mtype = MT_DEVICE_NONSHARED;
6762306a36Sopenharmony_ci	}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	return __arm_ioremap_caller(phys_addr, size, mtype, caller);
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#ifdef CONFIG_SOC_IMX31
7362306a36Sopenharmony_cistatic struct map_desc mx31_io_desc[] __initdata = {
7462306a36Sopenharmony_ci	imx_map_entry(MX31, X_MEMC, MT_DEVICE),
7562306a36Sopenharmony_ci	imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
7662306a36Sopenharmony_ci	imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
7762306a36Sopenharmony_ci	imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
7862306a36Sopenharmony_ci	imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci/*
8262306a36Sopenharmony_ci * This function initializes the memory map. It is called during the
8362306a36Sopenharmony_ci * system startup to create static physical to virtual memory mappings
8462306a36Sopenharmony_ci * for the IO modules.
8562306a36Sopenharmony_ci */
8662306a36Sopenharmony_civoid __init mx31_map_io(void)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistatic void imx31_idle(void)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	int reg = imx_readl(mx3_ccm_base + MXC_CCM_CCMR);
9462306a36Sopenharmony_ci	reg &= ~MXC_CCM_CCMR_LPM_MASK;
9562306a36Sopenharmony_ci	imx_writel(reg, mx3_ccm_base + MXC_CCM_CCMR);
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	imx3_idle();
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_civoid __init imx31_init_early(void)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	struct device_node *np;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	mxc_set_cpu_type(MXC_CPU_MX31);
10562306a36Sopenharmony_ci	arch_ioremap_caller = imx3_ioremap_caller;
10662306a36Sopenharmony_ci	arm_pm_idle = imx31_idle;
10762306a36Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm");
10862306a36Sopenharmony_ci	mx3_ccm_base = of_iomap(np, 0);
10962306a36Sopenharmony_ci	BUG_ON(!mx3_ccm_base);
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci#endif /* ifdef CONFIG_SOC_IMX31 */
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci#ifdef CONFIG_SOC_IMX35
11462306a36Sopenharmony_cistatic struct map_desc mx35_io_desc[] __initdata = {
11562306a36Sopenharmony_ci	imx_map_entry(MX35, X_MEMC, MT_DEVICE),
11662306a36Sopenharmony_ci	imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
11762306a36Sopenharmony_ci	imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
11862306a36Sopenharmony_ci	imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
11962306a36Sopenharmony_ci	imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
12062306a36Sopenharmony_ci};
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_civoid __init mx35_map_io(void)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic void imx35_idle(void)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	int reg = imx_readl(mx3_ccm_base + MXC_CCM_CCMR);
13062306a36Sopenharmony_ci	reg &= ~MXC_CCM_CCMR_LPM_MASK;
13162306a36Sopenharmony_ci	reg |= MXC_CCM_CCMR_LPM_WAIT_MX35;
13262306a36Sopenharmony_ci	imx_writel(reg, mx3_ccm_base + MXC_CCM_CCMR);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	imx3_idle();
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_civoid __init imx35_init_early(void)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	struct device_node *np;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	mxc_set_cpu_type(MXC_CPU_MX35);
14262306a36Sopenharmony_ci	arm_pm_idle = imx35_idle;
14362306a36Sopenharmony_ci	arch_ioremap_caller = imx3_ioremap_caller;
14462306a36Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "fsl,imx35-ccm");
14562306a36Sopenharmony_ci	mx3_ccm_base = of_iomap(np, 0);
14662306a36Sopenharmony_ci	BUG_ON(!mx3_ccm_base);
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci#endif /* ifdef CONFIG_SOC_IMX35 */
149